eclair snapshot
diff --git a/README.txt b/README.txt
index 6955945..2969180 100644
--- a/README.txt
+++ b/README.txt
@@ -1,5 +1,5 @@
-This directory contains the Dalvik virtual machine and associated
-class library.
+This directory contains the Dalvik virtual machine and core class library,
+as well as related tools, libraries, and tests.
 
 A note about the licenses and header comments
 ---------------------------------------------
@@ -50,3 +50,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
+
+Native SH call bridge
+---------------------
+
+Native SH call bridge is written by
+Shin-ichiro KAWASAKI <shinichiro.kawasaki.mg@hitachi.com>
+and Contributed to Android by Hitachi, Ltd. and Renesas Solutions Corp.
diff --git a/dalvikvm/Main.c b/dalvikvm/Main.c
index 70cc61f..a6439fb 100644
--- a/dalvikvm/Main.c
+++ b/dalvikvm/Main.c
@@ -115,7 +115,7 @@
     }
     getModifiersId = (*env)->GetMethodID(env, methodClass,
                         "getModifiers", "()I");
-    if (methodClass == NULL) {
+    if (getModifiersId == NULL) {
         fprintf(stderr, "Dalvik VM unable to find reflect.Method.getModifiers\n");
         goto bail;
     }
diff --git a/dexdump/DexDump.c b/dexdump/DexDump.c
index c5714ea..6fed7aa 100644
--- a/dexdump/DexDump.c
+++ b/dexdump/DexDump.c
@@ -60,10 +60,12 @@
 
 /* command-line options */
 struct {
+    bool checksumOnly;
     bool disassemble;
     bool showFileHeaders;
     bool showSectionHeaders;
     bool ignoreBadChecksum;
+    bool dumpRegisterMaps;
     OutputFormat outputFormat;
     const char* tempFileName;
     bool exportsOnly;
@@ -86,6 +88,14 @@
 }   
 
 /*
+ * Get 4 little-endian bytes. 
+ */ 
+static inline u4 get4LE(unsigned char const* pSrc)
+{
+    return pSrc[0] | (pSrc[1] << 8) | (pSrc[2] << 16) | (pSrc[3] << 24);
+}   
+
+/*
  * Converts a single-character primitive type into its human-readable
  * equivalent.
  */
@@ -589,10 +599,6 @@
 void dumpInstruction(DexFile* pDexFile, const DexCode* pCode, int insnIdx,
     int insnWidth, const DecodedInstruction* pDecInsn)
 {
-    static const float gSpecialTab[16] = {
-        -2.0f, -1.0f, -0.5f, -0.25f, -0.1f, 0.1f, 0.25f, 0.5f,
-        1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 10.0f, 100.0f, 1000.0f
-    };
     const u2* insns = pCode->insns;
     int i;
 
@@ -1197,6 +1203,8 @@
 /*
  * Dump the class.
  *
+ * Note "idx" is a DexClassDef index, not a DexTypeId index.
+ *
  * If "*pLastPackage" is NULL or does not match the current class' package,
  * the value will be replaced with a newly-allocated string.
  */
@@ -1369,6 +1377,208 @@
     free(accessStr);
 }
 
+
+/*
+ * Advance "ptr" to ensure 32-bit alignment.
+ */
+static inline const u1* align32(const u1* ptr)
+{
+    return (u1*) (((int) ptr + 3) & ~0x03);
+}
+
+
+/*
+ * Dump a map in the "differential" format.
+ *
+ * TODO: show a hex dump of the compressed data.  (We can show the
+ * uncompressed data if we move the compression code to libdex; otherwise
+ * it's too complex to merit a fast & fragile implementation here.)
+ */
+void dumpDifferentialCompressedMap(const u1** pData)
+{
+    const u1* data = *pData;
+    const u1* dataStart = data -1;      // format byte already removed
+    u1 regWidth;
+    u2 numEntries;
+
+    /* standard header */
+    regWidth = *data++;
+    numEntries = *data++;
+    numEntries |= (*data++) << 8;
+
+    /* compressed data begins with the compressed data length */
+    int compressedLen = readUnsignedLeb128(&data);
+    int addrWidth = 1;
+    if ((*data & 0x80) != 0)
+        addrWidth++;
+
+    int origLen = 4 + (addrWidth + regWidth) * numEntries;
+    int compLen = (data - dataStart) + compressedLen;
+
+    printf("        (differential compression %d -> %d [%d -> %d])\n",
+        origLen, compLen,
+        (addrWidth + regWidth) * numEntries, compressedLen);
+
+    /* skip past end of entry */
+    data += compressedLen;
+
+    *pData = data;
+}
+
+/*
+ * Dump register map contents of the current method.
+ *
+ * "*pData" should point to the start of the register map data.  Advances
+ * "*pData" to the start of the next map.
+ */
+void dumpMethodMap(DexFile* pDexFile, const DexMethod* pDexMethod, int idx,
+    const u1** pData)
+{
+    const u1* data = *pData;
+    const DexMethodId* pMethodId;
+    const char* name;
+    int offset = data - (u1*) pDexFile->pOptHeader;
+
+    pMethodId = dexGetMethodId(pDexFile, pDexMethod->methodIdx);
+    name = dexStringById(pDexFile, pMethodId->nameIdx);
+    printf("      #%d: 0x%08x %s\n", idx, offset, name);
+
+    u1 format;
+    int addrWidth;
+
+    format = *data++;
+    if (format == 1) {              /* kRegMapFormatNone */
+        /* no map */
+        printf("        (no map)\n");
+        addrWidth = 0;
+    } else if (format == 2) {       /* kRegMapFormatCompact8 */
+        addrWidth = 1;
+    } else if (format == 3) {       /* kRegMapFormatCompact16 */
+        addrWidth = 2;
+    } else if (format == 4) {       /* kRegMapFormatDifferential */
+        dumpDifferentialCompressedMap(&data);
+        goto bail;
+    } else {
+        printf("        (unknown format %d!)\n", format);
+        /* don't know how to skip data; failure will cascade to end of class */
+        goto bail;
+    }
+
+    if (addrWidth > 0) {
+        u1 regWidth;
+        u2 numEntries;
+        int idx, addr, byte;
+
+        regWidth = *data++;
+        numEntries = *data++;
+        numEntries |= (*data++) << 8;
+
+        for (idx = 0; idx < numEntries; idx++) {
+            addr = *data++;
+            if (addrWidth > 1)
+                addr |= (*data++) << 8;
+
+            printf("        %4x:", addr);
+            for (byte = 0; byte < regWidth; byte++) {
+                printf(" %02x", *data++);
+            }
+            printf("\n");
+        }
+    }
+
+bail:
+    //if (addrWidth >= 0)
+    //    *pData = align32(data);
+    *pData = data;
+}
+
+/*
+ * Dump the contents of the register map area.
+ *
+ * These are only present in optimized DEX files, and the structure is
+ * not really exposed to other parts of the VM itself.  We're going to
+ * dig through them here, but this is pretty fragile.  DO NOT rely on
+ * this or derive other code from it.
+ */
+void dumpRegisterMaps(DexFile* pDexFile)
+{
+    const u1* pClassPool = pDexFile->pRegisterMapPool;
+    const u4* classOffsets;
+    const u1* ptr;
+    u4 numClasses;
+    int baseFileOffset = (u1*) pClassPool - (u1*) pDexFile->pOptHeader;
+    int idx;
+
+    if (pClassPool == NULL) {
+        printf("No register maps found\n");
+        return;
+    }
+
+    ptr = pClassPool;
+    numClasses = get4LE(ptr);
+    ptr += sizeof(u4);
+    classOffsets = (const u4*) ptr;
+
+    printf("RMAP begins at offset 0x%07x\n", baseFileOffset);
+    printf("Maps for %d classes\n", numClasses);
+    for (idx = 0; idx < (int) numClasses; idx++) {
+        const DexClassDef* pClassDef;
+        const char* classDescriptor;
+
+        pClassDef = dexGetClassDef(pDexFile, idx);
+        classDescriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx);
+
+        printf("%4d: +%d (0x%08x) %s\n", idx, classOffsets[idx],
+            baseFileOffset + classOffsets[idx], classDescriptor);
+
+        if (classOffsets[idx] == 0)
+            continue;
+
+        /*
+         * What follows is a series of RegisterMap entries, one for every
+         * direct method, then one for every virtual method.
+         */
+        DexClassData* pClassData;
+        const u1* pEncodedData;
+        const u1* data = (u1*) pClassPool + classOffsets[idx];
+        u2 methodCount;
+        int i;
+
+        pEncodedData = dexGetClassData(pDexFile, pClassDef);
+        pClassData = dexReadAndVerifyClassData(&pEncodedData, NULL);
+        if (pClassData == NULL) {
+            fprintf(stderr, "Trouble reading class data\n");
+            continue;
+        }
+
+        methodCount = *data++;
+        methodCount |= (*data++) << 8;
+        data += 2;      /* two pad bytes follow methodCount */
+        if (methodCount != pClassData->header.directMethodsSize
+                            + pClassData->header.virtualMethodsSize)
+        {
+            printf("NOTE: method count discrepancy (%d != %d + %d)\n",
+                methodCount, pClassData->header.directMethodsSize,
+                pClassData->header.virtualMethodsSize);
+            /* this is bad, but keep going anyway */
+        }
+
+        printf("    direct methods: %d\n",
+            pClassData->header.directMethodsSize);
+        for (i = 0; i < (int) pClassData->header.directMethodsSize; i++) {
+            dumpMethodMap(pDexFile, &pClassData->directMethods[i], i, &data);
+        }
+
+        printf("    virtual methods: %d\n",
+            pClassData->header.virtualMethodsSize);
+        for (i = 0; i < (int) pClassData->header.virtualMethodsSize; i++) {
+            dumpMethodMap(pDexFile, &pClassData->virtualMethods[i], i, &data);
+        }
+
+        free(pClassData);
+    }
+}
+
 /*
  * Dump the requested sections of the file.
  */
@@ -1382,6 +1592,11 @@
             pDexFile->pHeader->magic +4);
     }
 
+    if (gOptions.dumpRegisterMaps) {
+        dumpRegisterMaps(pDexFile);
+        return;
+    }
+
     if (gOptions.showFileHeaders)
         dumpFileHeader(pDexFile);
 
@@ -1433,7 +1648,11 @@
         goto bail;
     }
 
-    processDexFile(fileName, pDexFile);
+    if (gOptions.checksumOnly) {
+        printf("Checksum verified\n");
+    } else {
+        processDexFile(fileName, pDexFile);
+    }
 
     result = 0;
 
@@ -1453,14 +1672,16 @@
 {
     fprintf(stderr, "Copyright (C) 2007 The Android Open Source Project\n\n");
     fprintf(stderr,
-        "%s: [-d] [-f] [-h] [-i] [-l layout] [-t tempfile] dexfile...\n",
+        "%s: [-c] [-d] [-f] [-h] [-i] [-l layout] [-m] [-t tempfile] dexfile...\n",
         gProgName);
     fprintf(stderr, "\n");
+    fprintf(stderr, " -c : verify checksum and exit\n");
     fprintf(stderr, " -d : disassemble code sections\n");
     fprintf(stderr, " -f : display summary information from file header\n");
     fprintf(stderr, " -h : display file header details\n");
     fprintf(stderr, " -i : ignore checksum failures\n");
     fprintf(stderr, " -l : output layout, either 'plain' or 'xml'\n");
+    fprintf(stderr, " -m : dump register maps (and nothing else)\n");
     fprintf(stderr, " -t : temp file name (defaults to /sdcard/dex-temp-*)\n");
 }
 
@@ -1478,11 +1699,14 @@
     gOptions.verbose = true;
 
     while (1) {
-        ic = getopt(argc, argv, "dfhil:t:");
+        ic = getopt(argc, argv, "cdfhil:mt:");
         if (ic < 0)
             break;
 
         switch (ic) {
+        case 'c':       // verify the checksum then exit
+            gOptions.checksumOnly = true;
+            break;
         case 'd':       // disassemble Dalvik instructions
             gOptions.disassemble = true;
             break;
@@ -1506,6 +1730,9 @@
                 wantUsage = true;
             }
             break;
+        case 'm':       // dump register maps only
+            gOptions.dumpRegisterMaps = true;
+            break;
         case 't':       // temp file, used when opening compressed Jar
             gOptions.tempFileName = optarg;
             break;
@@ -1520,6 +1747,11 @@
         wantUsage = true;
     }
 
+    if (gOptions.checksumOnly && gOptions.ignoreBadChecksum) {
+        fprintf(stderr, "Can't specify both -c and -i\n");
+        wantUsage = true;
+    }
+
     /* initialize some VM tables */
     gInstrWidth = dexCreateInstrWidthTable();
     gInstrFormat = dexCreateInstrFormatTable();
@@ -1529,12 +1761,14 @@
         return 2;
     }
 
-    while (optind < argc)
-        process(argv[optind++]);
+    int result = 0;
+    while (optind < argc) {
+        result |= process(argv[optind++]);
+    }
 
     free(gInstrWidth);
     free(gInstrFormat);
 
-    return 0;
+    return (result != 0);
 }
 
diff --git a/dexopt/OptMain.c b/dexopt/OptMain.c
index ef339cd..953db0b 100644
--- a/dexopt/OptMain.c
+++ b/dexopt/OptMain.c
@@ -337,7 +337,7 @@
      */
     GET_ARG(vmBuildVersion, strtol, "bad vm build");
     if (vmBuildVersion != DALVIK_VM_BUILD) {
-        LOGE("Inconsistent build rev: %d vs %d\n",
+        LOGE("DexOpt: build rev does not match VM: %d vs %d\n",
             vmBuildVersion, DALVIK_VM_BUILD);
         goto bail;
     }
diff --git a/docs/debugger.html b/docs/debugger.html
index 6e23f0d..523c712 100644
--- a/docs/debugger.html
+++ b/docs/debugger.html
@@ -41,11 +41,11 @@
 communication, such as notifying the debugger when the VM has stopped at
 a breakpoint, are sent from the affected thread.
 </p><p>
-When the VM is embedded in the Android framework,
-debugging is enabled in the VM unless the system property
-<code>ro.secure</code> is set to </code>1</code>.  On these
-"secure" devices, debugging is only enabled in app processes whose
-manifest contains <code>android:debuggable="true"</code> in the
+When the VM is started from the Android app framework, debugging is enabled
+for all applications when the system property <code>ro.debuggable</code>
+is set to </code>1</code> (use <code>adb shell getprop ro.debuggable</code>
+to check it).  If it's zero, debugging can be enabled via the application's
+manifest, which must include <code>android:debuggable="true"</code> in the
 <code>&lt;application&gt;</code> element.
 
 </p><p>
@@ -194,7 +194,9 @@
 integrated at present.  The VM currently guarantees that any object the
 debugger is aware of will not be garbage collected until after the
 debugger disconnects.  This can result in a build-up over time while the
-debugger is connected.
+debugger is connected.  For example, if the debugger sees a running
+thread, the associated Thread object will not be collected, even after
+the thread terminates.
 </p><p>
 The situation is exacerbated by a flaw in the exception processing code,
 which results in nearly all exceptions being added to the "do not discard"
@@ -202,6 +204,43 @@
 to a program that throws lots of exceptions can result in out-of-memory
 errors.  This will be fixed in a future release.
 </p><p>
+The only way to "unlock" the references is to detach and reattach the
+debugger.
+</p><p>
+&nbsp;
+</p><p>
+The translation from Java bytecode to Dalvik bytecode may result in
+identical sequences of instructions being combined.  This can make it
+look like the wrong bit of code is being executed.  For example:
+<pre>    int test(int i) {
+        if (i == 1) {
+            return 0;
+        }
+        return 1;
+    }</pre>
+The Dalvik bytecode uses a common <code>return</code> instruction for both
+<code>return</code> statements, so when <code>i</code> is 1 the debugger
+will single-step through <code>return 0</code> and then <code>return 1</code>.
+</p><p>
+&nbsp;
+</p><p>
+Dalvik handles synchronized methods differently from other VMs.
+Instead of marking a method as <code>synchronized</code> and expecting
+the VM to handle the locks, <code>dx</code> inserts a "lock"
+instruction at the top of the method and an "unlock" instruction in a
+synthetic <code>finally</code> block.  As a result, when single-stepping
+a <code>return</code> statement, the "current line" cursor may jump to
+the last line in the method.
+</p><p>
+This can also affect the way the debugger processes exceptions.  The
+debugger may decide to break on an
+exception based on whether that exception is "caught" or "uncaught".  To
+be considered uncaught, there must be no matching <code>catch</code> block
+or <code>finally</code> clause between the current point of execution and
+the top of the thread.  An exception thrown within or below a synchronized
+method will always be considered "caught", so the debugger won't stop
+until the exception is re-thrown from the synthetic <code>finally</code> block.
+</p><p>
 
 
 <address>Copyright &copy; 2009 The Android Open Source Project</address>
diff --git a/docs/dex-format.html b/docs/dex-format.html
index 88a7fb0..bc69dd0 100644
--- a/docs/dex-format.html
+++ b/docs/dex-format.html
@@ -2499,12 +2499,12 @@
   <td>count of fields annotated by this item</td>
 </tr>
 <tr>
-  <td>annotated_methods_off</td>
+  <td>annotated_methods_size</td>
   <td>uint</td>
   <td>count of methods annotated by this item</td>
 </tr>
 <tr>
-  <td>annotated_parameters_off</td>
+  <td>annotated_parameters_size</td>
   <td>uint</td>
   <td>count of method parameter lists annotated by this item</td>
 </tr>
diff --git a/docs/embedded-vm-control.html b/docs/embedded-vm-control.html
index f90f0e5..0b279e8 100644
--- a/docs/embedded-vm-control.html
+++ b/docs/embedded-vm-control.html
@@ -15,6 +15,7 @@
     <li><a href="#execmode">Execution Mode</a>
     <li><a href="#dp">Deadlock Prediction</a>
     <li><a href="#stackdump">Stack Dumps</a>
+    <li><a href="#dexcheck">DEX File Checksums</a>
 </ul>
 
 <h2><a name="overview">Overview</a></h2>
@@ -35,12 +36,22 @@
 settings are processed in the "zygote" process, which starts early and stays
 around "forever".
 
-<p>You could also add a line to <code>/data/local.prop</code> that looks like:
+<p>You may not be able to set this as an unprivileged user.  You can use
+<code>adb root</code> or run the <code>su</code> command from the device
+shell on "userdebug" builds to become root first.  When in doubt,
+<pre>adb shell getprop &lt;name&gt;</pre>
+will tell you if the <code>setprop</code> took.
+
+<p>If you don't want the property to evaporate when the device reboots,
+add a line to <code>/data/local.prop</code> that looks like:
 <pre>&lt;name&gt; = &lt;value&gt;</pre>
 
-<p>Such changes will survive reboots, but will be removed by anything
-that wipes the data partition.  (Hint: create a <code>local.prop</code>
-on your workstation, then <code>adb push local.prop /data</code> .)
+<p>Such changes will survive reboots, but will be lost if the data
+partition is wiped.  (Hint: create a <code>local.prop</code>
+on your workstation, then <code>adb push local.prop /data</code> .  Or,
+use one-liners like
+<code>adb shell "echo name = value &gt;&gt; /data/local.prop"</code> -- note
+the quotes are important.)
 
 
 <h2><a name="checkjni">Extended JNI Checks</a></h2>
@@ -72,7 +83,8 @@
 
 <p>You can also pass JNI-checking options into the VM through a system
 property.  The value set for <code>dalvik.vm.jniopts</code> will
-be passed in as the <code>-Xjniopts</code> argument.
+be passed in as the <code>-Xjniopts</code> argument.  For example:
+<pre>adb shell setprop dalvik.vm.jniopts forcecopy</pre>
 
 <p>For more information about JNI checks, see
 <a href="jni-tips.html">JNI Tips</a>.
@@ -158,7 +170,12 @@
 run on a broad range of platforms.  The "debug" interpreter is a variant
 of "portable" that includes support for profiling and single-stepping.
 
-<p>The VM allows you to choose between "fast" and "portable" with an
+<p>The VM may also support just-in-time compilation.  While not strictly
+a different interpreter, the JIT compiler may be enabled or disabled
+with the same flag.  (Check the output of <code>dalvikvm -help</code> to
+see if JIT compilation is enabled in your VM.)
+
+<p>The VM allows you to choose between "fast", "portable", and "jit" with an
 extended form of the <code>-Xint</code> argument.  The value of this
 argument can be set through the <code>dalvik.vm.execution-mode</code>
 system property.
@@ -235,6 +252,35 @@
 <p>If the property is not defined, the VM will write the stack traces to
 the Android log when the signal arrives.
 
+
+<h2><a name="dexcheck">DEX File Checksums</a></h2>
+
+<p>For performance reasons, the checksum on "optimized" DEX files is
+ignored.  This is usually safe, because the files are generated on the
+device, and have access permissions that prevent modification.
+
+<p>If the storage on a device becomes unreliable, however, data corruption
+can occur.  This usually manifests itself as a repeatable virtual machine
+crash.  To speed diagnosis of such failures, the VM provides the
+<code>-Xcheckdexsum</code> argument.  When set, the checksums on all DEX
+files are verified before the contents are used.
+
+<p>The application framework will provide this argument during VM
+creation if the <code>dalvik.vm.check-dex-sum</code> property is enabled.
+
+<p>To enable extended DEX checksum verification:
+<pre>adb shell setprop dalvik.vm.check-dex-sum true</pre>
+
+<p>Incorrect checksums will prevent the DEX data from being used, and will
+cause errors to be written to the log file.  If a device has a history of
+problems it may be useful to add the property to
+<code>/data/local.prop</code>.
+
+<p>Note also that the
+<code>dexdump</code> tool always verifies DEX checksums, and can be used
+to check for corruption in a large set of files.
+
+
 <address>Copyright &copy; 2008 The Android Open Source Project</address>
 
 </body></html>
diff --git a/docs/heap-profiling.html b/docs/heap-profiling.html
new file mode 100644
index 0000000..e36b606
--- /dev/null
+++ b/docs/heap-profiling.html
@@ -0,0 +1,178 @@
+<html>
+<head>
+    <title>Dalvik Heap Profiling</title>
+</head>
+
+<body>
+<h1>Dalvik Heap Profiling</h1>
+
+<p>
+The Dalvik virtual machine can produce a complete dump of the contents
+of the virtual heap.  This is very useful for debugging memory usage
+and looking for memory leaks.  Getting at the information can be tricky,
+but has become easier in recent releases.
+
+
+<h2>Getting the data</h2>
+<p>
+The first step is to cause the VM to dump its status, and then pull the hprof
+data off.  The exact manner for doing so has changed over time.
+</p><p>
+There is a <code>runhat</code> shell function, added by
+<code>build/envsetup.sh</code>, that partially automates these steps.  The
+function changes in each release to accommodate newer behavior, so you have
+to be careful that you don't use the wrong version.
+</p><p>
+
+<h3>Early releases (1.0/1.1)</h3>
+<p>
+You can only generate heap data on the emulator or a device with root
+access, because of the way the dump is initiated and where the output
+files go.
+</p><p>
+Get a command shell on the device:
+<blockquote><pre>
+$ adb shell
+</pre></blockquote>
+</p><p>
+You can verify that you're running as root with the <code>id</code> command.
+The response should look like <code>uid=0(root) gid=0(root)</code>.  If not,
+type <code>su</code> and try again.  If <code>su</code> fails, you're out
+of luck.
+
+</p><p>
+Next, ensure the target directory exists:
+<blockquote><pre>
+# mkdir /data/misc
+# chmod 777 /data/misc
+</pre></blockquote>
+
+</p><p>
+Use <code>ps</code> or DDMS to determine the process ID of your application,
+then send a <code>SIGUSR1</code> to the target process:
+
+<blockquote><pre>
+# kill -10 &lt;pid&gt;
+</pre></blockquote>
+
+</p><p>
+The signal causes a GC, followed by the heap dump (to be completely
+accurate, they actually happen concurrently, but the results in the heap
+dump reflect the post-GC state).  This can take a couple of seconds,
+so you have to watch for the GC log message to know when it's complete.
+</p><p>
+Next:
+
+<blockquote><pre>
+# ls /data/misc/heap-dump*
+# exit
+</pre></blockquote>
+
+</p><p>
+Use <code>ls</code> to check the file names, then <code>exit</code> to quit
+the device command shell.
+
+</p><p>
+You should see two output files, named
+<code>/data/misc/heap-dump-BLAH-BLAH.hprof</code> and
+<code>.hprof-head</code>, where BLAH is a runtime-generated value
+that ensures the filename is unique.  Pull them off of the device and
+remove the device-side copy:
+
+<blockquote><pre>
+$ adb pull /data/misc/heap-dump-BLAH-BLAH.hprof tail.hprof
+$ adb pull /data/misc/heap-dump-BLAH-BLAH.hprof-head head.hprof
+$ adb shell rm /data/misc/heap-dump-BLAH-BLAH.hprof /data/misc/heap-dump-BLAH-BLAH.hprof-head
+</pre></blockquote>
+
+</p><p>
+Merge them together and remove the intermediates:
+
+<blockquote><pre>
+$ cat head.hprof tail.hprof &gt; dump.hprof
+$ rm head.hprof tail.hprof
+</pre></blockquote>
+
+</p><p>
+You now have the hprof dump in <code>dump.hprof</code>.
+</p><p>
+
+
+<h3>Android 1.5 ("Cupcake")</h3>
+<p>
+Some steps were taken to make this simpler.  Notably, the two output
+files are now combined for you, and a new API call was added that allows
+a program to write the dump at will to a specific file.  If you're not
+using the API call, you still need to be on an emulator or running as root.
+(For some builds, you can use <code>adb root</code> to restart the adb
+daemon as root.)
+</p><p>
+The basic procedure is the same as for 1.0/1.1, but only one file will
+appear in <code>/data/misc</code> (no <code>-head</code>), and upon
+completion you will see a log message that says "hprof: heap dump completed".
+It looks like this in the log:
+
+<blockquote><pre>
+I/dalvikvm(  289): threadid=7: reacting to signal 10
+I/dalvikvm(  289): SIGUSR1 forcing GC and HPROF dump
+I/dalvikvm(  289): hprof: dumping VM heap to "/data/misc/heap-dump-tm1240861355-pid289.hprof-hptemp".
+I/dalvikvm(  289): hprof: dumping heap strings to "/data/misc/heap-dump-tm1240861355-pid289.hprof".
+I/dalvikvm(  289): hprof: heap dump completed, temp file removed
+</pre></blockquote>
+
+</p><p>
+Summary: as above, use <code>mkdir</code> and <code>chmod</code>
+to ensure the directory exists and is writable by your application.
+Send the <code>SIGUSR1</code> or use the API call to initiate a dump.
+Use <code>adb pull &lt;dump-file&gt;</code> and <code>adb shell rm
+&lt;dump-file&gt;</code> to retrieve the file and remove it from the
+device.  The concatenation step is not needed.
+
+</p><p>
+The new API is in the <code>android.os.Debug</code> class:
+<blockquote><pre>
+public static void dumpHprofData(String fileName) throws IOException
+</pre></blockquote>
+When called, the VM will go through the same series of steps (GC and
+generate a .hprof file), but the output will be written to a file of
+your choice, e.g. <code>/sdcard/myapp.hprof</code>.  Because you're
+initiating the action from within the app, and can write the file to
+removable storage or the app's private data area, you can do this on a
+device without root access.
+
+
+
+<h3>Android 1.6 ("Donut")</h3>
+<p>
+In 1.6, features were added that allow DDMS to request a heap dump on
+demand, and automatically pull the result across.  Select your application
+and click the "dump HPROF file" button.
+</p><p>
+However, 1.6 also introduced the <code>WRITE_EXTERNAL_STORAGE</code>
+permission, which is required to write data to the SD card.  To use
+the DDMS feature, which always writes files to the SD card,
+you must have a card inserted and the permission enabled in your application.
+</p><p>
+Otherwise, things are the same as they were in 1.5.
+
+
+<h2>Examining the data</h2>
+<p>
+The data file format was augmented slightly from the common hprof format,
+and due to licensing restrictions the modified <code>hat</code> tool cannot
+be distributed.  A conversion tool, <code>hprof-conv</code>, can be used
+to strip the Android-specific portions from the output.  This tool was
+first included in 1.5, but will work with older versions of Android.
+</p><p>
+The converted output should work with any hprof data analyzer, including
+<code>jhat</code>, which is available for free in the Sun JDK, and
+Eclipse MAT.
+
+<!-- say something about how to track down common problems, interesting
+     things to look for, ...? -->
+
+</p><p>
+<address>Copyright &copy; 2009 The Android Open Source Project</address>
+
+</body>
+</html>
diff --git a/docs/hello-world.html b/docs/hello-world.html
new file mode 100644
index 0000000..dbbaea6
--- /dev/null
+++ b/docs/hello-world.html
@@ -0,0 +1,216 @@
+<html>
+<head>
+    <title>Basic Dalvik VM Invocation</title>
+</head>
+
+<body>
+<h1>Basic Dalvik VM Invocation</h1>
+
+<p>
+On an Android device, the Dalvik virtual machine usually executes embedded
+in the Android application framework.  It's also possible to run it directly,
+just as you would a virtual machine on your desktop system.
+</p><p>
+After compiling your Java language sources, convert and combine the .class
+files into a DEX file, and push that to the device.  Here's a simple example:
+
+</p><p><code>
+% <font color="green">echo 'class Foo {'\</font><br>
+&gt; <font color="green">'public static void main(String[] args) {'\</font><br>
+&gt; <font color="green">'System.out.println("Hello, world"); }}' &gt; Foo.java</font><br>
+% <font color="green">javac Foo.java</font><br>
+% <font color="green">dx --dex --output=foo.jar Foo.class</font><br>
+% <font color="green">adb push foo.jar /sdcard</font><br>
+% <font color="green">adb shell dalvikvm -cp /sdcard/foo.jar Foo</font><br>
+Hello, world 
+</code>
+</p><p>
+The <code>-cp</code> option sets the classpath.  The initial directory
+for <code>adb shell</code> may not be what you expect it to be, so it's
+usually best to specify absolute pathnames.
+
+</p><p>
+The <code>dx</code> command accepts lists of individual class files,
+directories, or Jar archives.  When the <code>--output</code> filename
+ends with <code>.jar</code>, <code>.zip</code>, or <code>.apk</code>,
+a file called <code>classes.dex</code> is created and stored inside the
+archive.
+</p><p>
+Run <code>adb shell dalvikvm -help</code> to see a list of command-line
+options.
+</p><p>
+
+
+
+<h2>Using a debugger</h2>
+
+<p>
+You can debug stand-alone applications with any JDWP-compliant debugger.
+There are two basic approaches.
+</p><p>
+The first way is to connect directly through TCP.  Add, to the "dalvikvm"
+invocation line above, an argument like:
+</p><p>
+<code>&nbsp;&nbsp;-agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=y</code>
+</p><p>
+This tells the VM to wait for a debugger to connect to it on TCP port 8000.
+You need to tell adb to forward local port 8000 to device port 8000:
+</p><p>
+<code>% <font color="green">adb forward tcp:8000 tcp:8000</font></code>
+</p><p>
+and then connect to it with your favorite debugger (using <code>jdb</code>
+as an example here):
+</p><p>
+<code>% <font color="green">jdb -attach localhost:8000</font></code>
+</p><p>
+When the debugger attaches, the VM will be in a suspended state.  You can
+set breakpoints and then tell it to continue.
+
+
+</p><p>
+You can also connect through DDMS, like you would for an Android application.
+Add, to the "dalvikvm" command line:
+</p><p>
+<code>&nbsp;&nbsp;-agentlib:jdwp=transport=dt_android_adb,suspend=y,server=y</code>
+</p><p>
+Note the <code>transport</code> has changed, and you no longer need to
+specify a TCP port number.  When your application starts, it will appear
+in DDMS, with "?" as the application name.  Select it in DDMS, and connect
+to it as usual, e.g.:
+</p><p>
+<code>% <font color="green">jdb -attach localhost:8700</font></code>
+</p><p>
+Because command-line applications don't include the client-side
+DDM setup, features like thread monitoring and allocation tracking will not
+be available in DDMS.  It's strictly a debugger pass-through in this mode.
+</p><p>
+See <a href="debugger.html">Dalvik Debugger Support</a> for more information
+about using debuggers with Dalvik.
+
+
+
+<h2>Working with the desktop build</h2>
+
+<!-- largely lifted from
+http://groups.google.com/group/android-porting/browse_thread/thread/ab553116dbc960da/29167c58b3b49051#29167c58b3b49051
+-->
+
+<p>
+The Dalvik VM can also be used directly on the desktop.  This is somewhat
+more complicated however, because you won't have certain things set up in
+your environment, and several native code libraries are required to support
+the core Dalvik libs.
+</p><p>
+Start with:
+
+<pre>
+  . build/envsetup.sh
+  lunch sim-eng
+</pre>
+
+You should see something like:
+
+<pre>
+  ============================================
+  TARGET_PRODUCT=sim
+  TARGET_BUILD_VARIANT=eng
+  TARGET_SIMULATOR=true
+  TARGET_BUILD_TYPE=debug
+  TARGET_ARCH=x86
+  HOST_ARCH=x86
+  HOST_OS=linux
+  HOST_BUILD_TYPE=release
+  BUILD_ID=
+  ============================================
+</pre>
+
+</p></p>
+This configures you to build for the desktop, linking against glibc.
+This mode is NOT recommended for anything but experimental use.  It
+may go away in the future.
+</p></p>
+You may see <code>TARGET_BUILD_TYPE=release</code> or <code>=debug</code>
+or possibly nothing there at all.  You may want to replace the
+<code>lunch</code> command with
+<code>choosecombo Simulator debug sim eng</code>.
+</p></p>
+Build the world (add a <code>-j4</code> if you have multiple cores):
+
+<pre>
+  make
+</pre>
+
+</p></p>
+When that completes, you have a working dalvikm on your desktop
+machine:
+
+<pre>
+  % dalvikvm
+  E/dalvikvm(19521): ERROR: must specify non-'.' bootclasspath
+  W/dalvikvm(19521): JNI_CreateJavaVM failed
+  Dalvik VM init failed (check log file)
+</pre>
+
+</p></p>
+To actually do something, you need to specify the bootstrap class path
+and give it a place to put DEX data that it uncompresses from jar
+files.  You can do that with a script like this:
+
+<blockquote><pre>
+#!/bin/sh
+
+# base directory, at top of source tree; replace with absolute path
+base=`pwd`
+
+# configure root dir of interesting stuff
+root=$base/out/debug/host/linux-x86/product/sim/system
+export ANDROID_ROOT=$root
+
+# configure bootclasspath
+bootpath=$root/framework
+export BOOTCLASSPATH=$bootpath/core.jar:$bootpath/ext.jar:$bootpath/framework.jar:$bootpath/android.policy.jar:$bootpath/services.jar
+
+# this is where we create the dalvik-cache directory; make sure it exists
+export ANDROID_DATA=/tmp/dalvik_$USER
+mkdir -p $ANDROID_DATA/dalvik-cache
+
+exec dalvikvm $@
+</pre></blockquote>
+
+</p></p>
+The preparation with <code>dx</code> is the same as before:
+
+<pre>
+  % cat &gt; Foo.java
+  class Foo { public static void main(String[] args) {
+    System.out.println("Hello, world");
+  } }
+  (ctrl-D)
+  % javac Foo.java
+  % dx --dex --output=foo.jar Foo.class
+  % ./rund -cp foo.jar Foo
+  Hello, world
+</pre>
+
+As above, you can get some info about valid arguments like this:
+
+<pre>
+  % ./rund -help
+</pre>
+
+</p></p>
+This also shows what options the VM was configured with.  The sim "debug"
+build has all sorts of additional assertions and checks enabled,
+which slows the VM down, but since this is just for experiments it
+doesn't matter.
+
+</p></p>
+All of the above applies to x86 Linux.  Anything else will likely
+require a porting effort.  If libffi supports your system, the amount of
+work required should be minor.
+
+</p></p>
+<address>Copyright &copy; 2009 The Android Open Source Project</address>
+
+</body>
+</html>
diff --git a/docs/jni-tips.html b/docs/jni-tips.html
index e2c3b85..e85434b 100644
--- a/docs/jni-tips.html
+++ b/docs/jni-tips.html
@@ -14,7 +14,7 @@
 <li> <a href="#JavaVM_and_JNIEnv">JavaVM and JNIEnv</a>
 
 </li>
-<li> <a href="#jclassID_jmethodID_and_jfieldID">jclassID, jmethodID, and jfieldID</a>
+<li> <a href="#jclass_jmethodID_and_jfieldID">jclass, jmethodID, and jfieldID</a>
 </li>
 <li> <a href="#local_vs_global_references">Local vs. Global References</a>
 </li>
@@ -79,7 +79,7 @@
 that header refers to JNIEnv.)
 </p><p>
 </p><p>
-</p><h2><a name="jclassID_jmethodID_and_jfieldID"> jclassID, jmethodID, and jfieldID </a></h2>
+</p><h2><a name="jclass_jmethodID_and_jfieldID"> jclass, jmethodID, and jfieldID </a></h2>
 <p>
 If you want to access an object's field from native code, you would do the following:
 </p><p>
@@ -104,7 +104,8 @@
 </p><p>
 The class references, field IDs, and method IDs are guaranteed valid until the class is unloaded.  Classes
 are only unloaded if all classes associated with a ClassLoader can be garbage collected,
-which is rare but will not be impossible in our system.  The jclassID
+which is rare but will not be impossible in our system.  Note however that
+the <code>jclass</code>
 is a class reference and <strong>must be protected</strong> with a call
 to <code>NewGlobalRef</code> (see the next section).
 </p><p>
@@ -145,23 +146,40 @@
 Every object that JNI returns is a "local reference".  This means that it's valid for the
 duration of the current native method in the current thread.
 <strong>Even if the object itself continues to live on after the native method returns, the reference is not valid.</strong>
-This applies to all sub-classes of jobject, including jclass and jarray.
-(Dalvik VM will warn you about this when -Xcheck:jni is enabled.)
+This applies to all sub-classes of <code>jobject</code>, including
+<code>jclass</code>, <code>jstring</code>, and <code>jarray</code>.
+(Dalvik VM will warn you about most reference mis-uses when extended JNI
+checks are enabled.)
 </p><p>
 
-If you want to hold on to a reference for a longer period, you must use a "global" reference.
-The <code>NewGlobalRef</code> function takes the local reference as
-an argument and returns a global one:
-
-<p><pre>jobject* localRef = [...];
-jobject* globalRef;
-globalRef = env-&gt;NewGlobalRef(localRef);
-</pre>
-
+If you want to hold on to a reference for a longer period, you must use
+a "global" reference.  The <code>NewGlobalRef</code> function takes the
+local reference as an argument and returns a global one.
 The global reference is guaranteed to be valid until you call
 <code>DeleteGlobalRef</code>.
+
+</p><p>
+This pattern is commonly used when caching copies of class objects obtained
+from <code>FindClass</code>, e.g.:
+<p><pre>jclass* localClass = env-&gt;FindClass("MyClass");
+jclass* globalClass = (jclass*) env-&gt;NewGlobalRef(localClass);
+</pre>
+
 </p><p>
 All JNI methods accept both local and global references as arguments.
+It's possible for references to the same object to have different values;
+for example, the return values from consecutive calls to
+<code>NewGlobalRef</code> on the same object may be different.
+<strong>To see if two references refer to the same object,
+you must use the <code>IsSameObject</code> function.</strong>  Never compare
+references with "==" in native code.
+</p><p>
+One consequence of this is that you
+<strong>must not assume object references are constant or unique</strong>
+in native code.  The 32-bit value representing an object may be different
+from one invocation of a method to the next, and it's possible that two
+different objects could have the same 32-bit value on consecutive calls.  Do
+not use <code>jobject</code> values as keys.
 </p><p>
 Programmers are required to "not excessively allocate" local references.  In practical terms this means
 that if you're creating large numbers of local references, perhaps while running through an array of
@@ -179,8 +197,8 @@
 One unusual case deserves separate mention.  If you attach a native
 thread to the VM with AttachCurrentThread, the code you are running will
 never "return" to the VM until the thread detaches from the VM.  Any local
-references you create will have to be deleted manually unless the thread
-is about to exit or detach.
+references you create will have to be deleted manually unless you're going
+to detach the thread soon.
 </p><p>
 </p><p>
 </p><p>
@@ -201,9 +219,10 @@
 the string pointer.
 
 </p><p>
-<strong>Don't forget to Release the strings you Get</strong>.  The string functions return <code>jchar*</code> or <code>jbyte*</code>, which
-are pointers to primitive types rather than local references.  They are
-guaranteed valid until Release is called, which means they are not
+<strong>Don't forget to Release the strings you Get</strong>.  The
+string functions return <code>jchar*</code> or <code>jbyte*</code>, which
+are C-style pointers to primitive data rather than local references.  They
+are guaranteed valid until Release is called, which means they are not
 released when the native method returns.
 </p><p>
 </p><p>
@@ -305,10 +324,10 @@
 </p><p>
 This accomplishes the same thing, with several advantages:
 <ul>
-    <li>Requires one JNI call instead of 3, reducing overhead.
+    <li>Requires one JNI call instead of 2, reducing overhead.
     <li>Doesn't require pinning or extra data copies.
-    <li>Reduces the risk of programmer error -- no need to match up
-    <code>Get</code> and <code>Release</code> calls.
+    <li>Reduces the risk of programmer error -- no risk of forgetting
+    to call <code>Release</code> after something fails.
 </ul>
 </p><p>
 Similarly, you can use the <code>Set&lt;Type&gt;ArrayRegion</code> call
@@ -366,7 +385,7 @@
 </p><p>
 </p><h2><a name="Extended_checking"> Extended Checking </a></h2>
 <p>
-JNI does very little error checking.  Calling <code>SetFieldInt</code>
+JNI does very little error checking.  Calling <code>SetIntField</code>
 on an Object field will succeed, even if the field is marked
 <code>private</code> and <code>final</code>.  The
 goal is to minimize the overhead on the assumption that, if you've written it in native code,
@@ -377,7 +396,7 @@
 an extended series of checks before calling the standard implementation.
 
 </p><p>
-Some things that may be verified:
+Some things that may be checked:
 </p><p>
 </p>
 <ul>
@@ -420,6 +439,7 @@
 are over-allocated and surrounded with a guard pattern to help identify
 code writing outside the buffer, and the contents are erased before the
 storage is freed to trip up code that uses the data after calling Release.
+This will have a noticeable performance impact on some applications.
 <dt>warnonly
 <dd>By default, JNI "warnings" cause the VM to abort.  With this flag
 it continues on.
@@ -434,7 +454,10 @@
 preferred way to get at your native code is:
 </p><p>
 </p><ul>
-<li> Call <code>System.loadLibrary()</code> from a static class initializer.  (See the earlier example, where one is used to call nativeClassInit().)  The argument is the "undecorated" library name, e.g. to load "libfubar.so" you would pass in "fubar".
+<li> Call <code>System.loadLibrary()</code> from a static class
+initializer.  (See the earlier example, where one is used to call
+<code>nativeClassInit()</code>.)  The argument is the "undecorated"
+library name, e.g. to load "libfubar.so" you would pass in "fubar".
 
 </li>
 <li> Provide a native function: <code><strong>jint JNI_OnLoad(JavaVM* vm, void* reserved)</strong></code>
@@ -462,17 +485,27 @@
 </pre></blockquote>
 </p><p>
 You can also call <code>System.load()</code> with the full path name of the
-shared library.  For Android apps, you can get the full path to the
-application's private data storage area from the context object.
+shared library.  For Android apps, you may find it useful to get the full
+path to the application's private data storage area from the context object.
 </p><p>
-Dalvik does support "discovery" of native methods that are named in a
+This is the recommended approach, but not the only approach.  The VM does
+not require explicit registration, nor that you provide a
+<code>JNI_OnLoad</code> function.
+You can instead use "discovery" of native methods that are named in a
 specific way (see <a href="http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/design.html#wp615">
-    the JNI spec</a> for details), but this is a less desirable
-approach.  It requires more space in the shared object symbol table,
+    the JNI spec</a> for details), though this is less desirable.
+It requires more space in the shared object symbol table,
 loading is slower because it requires string searches through all of the
 loaded shared libraries, and if a method signature is wrong you won't know
 about it until the first time the method is actually used.
 </p><p>
+One other note about <code>JNI_OnLoad</code>: any <code>FindClass</code>
+calls you make from there will happen in the context of the class loader
+that was used to load the shared library.  Normally <code>FindClass</code>
+uses the loader associated with the method at the top of the interpreted
+stack, or if there isn't one (because the thread was just attached to
+the VM) it uses the "system" class loader.
+</p><p>
 
 
 </p><h2><a name="64bit"> 64-bit Considerations </a></h2>
diff --git a/docs/opcodes/opcode-04-move-wide.html b/docs/opcodes/opcode-04-move-wide.html
index 42202be..e043be9 100644
--- a/docs/opcodes/opcode-04-move-wide.html
+++ b/docs/opcodes/opcode-04-move-wide.html
@@ -9,7 +9,7 @@
 
 <body>
 
-<h1>move</h1>
+<h1>move-wide</h1>
 
 <h2>Purpose</h2>
 
diff --git a/docs/porting-guide.html b/docs/porting-guide.html
new file mode 100644
index 0000000..b5ac387
--- /dev/null
+++ b/docs/porting-guide.html
@@ -0,0 +1,356 @@
+<html>
+<head>
+    <title>Dalvik Porting Guide</title>
+</head>
+
+<body>
+<h1>Dalvik Porting Guide</h1>
+
+<p>
+The Dalvik virtual machine is intended to run on a variety of platforms.
+The baseline system is expected to be a variant of UNIX (Linux, BSD, Mac
+OS X) running the GNU C compiler.  Little-endian CPUs have been exercised
+the most heavily, but big-endian systems are explicitly supported.
+</p><p>
+There are two general categories of work: porting to a Linux system
+with a previously unseen CPU architecture, and porting to a different
+operating system.  This document covers the former.
+</p><p>
+Basic familiarity with the Android platform, source code structure, and
+build system is assumed.
+</p>
+
+
+<h2>Core Libraries</h2>
+
+<p>
+The native code in the core libraries (chiefly <code>dalvik/libcore</code>,
+but also <code>dalvik/vm/native</code>) is written in C/C++ and is expected
+to work without modification in a Linux environment.  Much of the code
+comes directly from the Apache Harmony project.
+</p><p>
+The core libraries pull in code from many other projects, including
+OpenSSL, zlib, and ICU.  These will also need to be ported before the VM
+can be used.
+</p>
+
+
+<h2>JNI Call Bridge</h2>
+
+<p>
+Most of the Dalvik VM runtime is written in portable C.  The one
+non-portable component of the runtime is the JNI call bridge.  Simply put,
+this converts an array of integers into function arguments of various
+types, and calls a function.  This must be done according to the C calling
+conventions for the platform.  The task could be as simple as pushing all
+of the arguments onto the stack, or involve complex rules for register
+assignment and stack alignment.
+</p><p>
+To ease porting to new platforms, the <a href="http://sourceware.org/libffi/">
+open-source FFI library</a> (Foreign Function Interface) is used when a
+custom bridge is unavailable.  FFI is not as fast as a native implementation,
+and the optional performance improvements it does offer are not used, so
+writing a replacement is a good first step.
+</p><p>
+The code lives in <code>dalvik/vm/arch/*</code>, with the FFI-based version
+in the "generic" directory.  There are two source files for each architecture.
+One defines the call bridge itself:
+</p><p><blockquote>
+<code>void dvmPlatformInvoke(void* pEnv, ClassObject* clazz, int argInfo,
+int argc, const u4* argv, const char* signature, void* func,
+JValue* pReturn)</code>
+</blockquote></p><p>
+This will invoke a C/C++ function declared:
+</p><p><blockquote>
+    <code>return_type func(JNIEnv* pEnv, Object* this [, <i>args</i>])<br></code>
+</blockquote>or (for a "static" method):<blockquote>
+    <code>return_type func(JNIEnv* pEnv, ClassObject* clazz [, <i>args</i>])</code>
+</blockquote></p><p>
+The role of <code>dvmPlatformInvoke</code> is to convert the values in
+<code>argv</code> into C-style calling conventions, call the method, and
+then place the return type into <code>pReturn</code> (a union that holds
+all of the basic JNI types).  The code may use the method signature
+(a DEX "shorty" signature, with one character for the return type and one
+per argument) to determine how to handle the values.
+</p><p>
+The other source file involved here defines a 32-bit "hint".  The hint
+is computed when the method's class is loaded, and passed in as the
+"argInfo" argument.  The hint can be used to avoid scanning the ASCII
+method signature for things like the return value, total argument size,
+or inter-argument 64-bit alignment restrictions.
+
+
+<h2>Interpreter</h2>
+
+<p>
+The Dalvik runtime includes two interpreters, labeled "portable" and "fast".
+The portable interpreter is largely contained within a single C function,
+and should compile on any system that supports gcc.  (If you don't have gcc,
+you may need to disable the "threaded" execution model, which relies on
+gcc's "goto table" implementation; look for the THREADED_INTERP define.)
+</p><p>
+The fast interpreter uses hand-coded assembly fragments.  If none are
+available for the current architecture, the build system will create an
+interpreter out of C "stubs".  The resulting "all stubs" interpreter is
+quite a bit slower than the portable interpreter, making "fast" something
+of a misnomer.
+</p><p>
+The fast interpreter is enabled by default.  On platforms without native
+support, you may want to switch to the portable interpreter.  This can
+be controlled with the <code>dalvik.vm.execution-mode</code> system
+property.  For example, if you:
+</p><p><blockquote>
+<code>adb shell "echo dalvik.vm.execution-mode = int:portable >> /data/local.prop"</code>
+</blockquote></p><p>
+and reboot, the Android app framework will start the VM with the portable
+interpreter enabled.
+</p>
+
+
+<h3>Mterp Interpreter Structure</h3>
+
+<p>
+There may be significant performance advantages to rewriting the
+interpreter core in assembly language, using architecture-specific
+optimizations.  In Dalvik this can be done one instruction at a time.
+</p><p>
+The simplest way to implement an interpreter is to have a large "switch"
+statement.  After each instruction is handled, the interpreter returns to
+the top of the loop, fetches the next instruction, and jumps to the
+appropriate label.
+</p><p>
+An improvement on this is called "threaded" execution.  The instruction
+fetch and dispatch are included at the end of every instruction handler.
+This makes the interpreter a little larger overall, but you get to avoid
+the (potentially expensive) branch back to the top of the switch statement.
+</p><p>
+Dalvik mterp goes one step further, using a computed goto instead of a goto
+table.  Instead of looking up the address in a table, which requires an
+extra memory fetch on every instruction, mterp multiplies the opcode number
+by a fixed value.  By default, each handler is allowed 64 bytes of space.
+</p><p>
+Not all handlers fit in 64 bytes.  Those that don't can have subroutines
+or simply continue on to additional code outside the basic space.  Some of
+this is handled automatically by Dalvik, but there's no portable way to detect
+overflow of a 64-byte handler until the VM starts executing.
+</p><p>
+The choice of 64 bytes is somewhat arbitrary, but has worked out well for
+ARM and x86.
+</p><p>
+In the course of development it's useful to have C and assembly
+implementations of each handler, and be able to flip back and forth
+between them when hunting problems down.  In mterp this is relatively
+straightforward.  You can always see the files being fed to the compiler
+and assembler for your platform by looking in the
+<code>dalvik/vm/mterp/out</code> directory.
+</p><p>
+The interpreter sources live in <code>dalvik/vm/mterp</code>.  If you
+haven't yet, you should read <code>dalvik/vm/mterp/README.txt</code> now.
+</p>
+
+
+<h3>Getting Started With Mterp</h3>
+
+</p><p>
+Getting started:
+<ol>
+<li>Decide on the name of your architecture.  For the sake of discussion,
+let's call it <code>myarch</code>.
+<li>Make a copy of <code>dalvik/vm/mterp/config-allstubs</code> to
+<code>dalvik/vm/mterp/config-myarch</code>.
+<li>Create a <code>dalvik/vm/mterp/myarch</code> directory to hold your
+source files.
+<li>Add <code>myarch</code> to the list in
+<code>dalvik/vm/mterp/rebuild.sh</code>.
+<li>Make sure <code>dalvik/vm/Android.mk</code> will find the files for
+your architecture.  If <code>$(TARGET_ARCH)</code> is configured this
+will happen automatically.
+</ol>
+</p><p>
+You now have the basic framework in place.  Whenever you make a change, you
+need to perform two steps: regenerate the mterp output, and build the
+core VM library.  (It's two steps because we didn't want the build system
+to require Python 2.5.  Which, incidentally, you need to have.)
+<ol>
+<li>In the <code>dalvik/vm/mterp</code> directory, regenerate the contents
+of the files in <code>dalvik/vm/mterp/out</code> by executing
+<code>./rebuild.sh</code>.  Note there are two files, one in C and one
+in assembly.
+<li>In the <code>dalvik</code> directory, regenerate the
+<code>libdvm.so</code> library with <code>mm</code>.  You can also use
+<code>make libdvm</code> from the top of the tree.
+</ol>
+</p><p>
+This will leave you with an updated libdvm.so, which can be pushed out to
+a device with <code>adb sync</code> or <code>adb push</code>.  If you're
+using the emulator, you need to add <code>make snod</code> (System image,
+NO Dependency check) to rebuild the system image file.  You should not
+need to do a top-level "make" and rebuild the dependent binaries.
+</p><p>
+At this point you have an "all stubs" interpreter.  You can see how it
+works by examining <code>dalvik/vm/mterp/cstubs/entry.c</code>.  The
+code runs in a loop, pulling out the next opcode, and invoking the
+handler through a function pointer.  Each handler takes a "glue" argument
+that contains all of the useful state.
+</p><p>
+Your goal is to replace the entry method, exit method, and each individual
+instruction with custom implementations.  The first thing you need to do
+is create an entry function that calls the handler for the first instruction.
+After that, the instructions chain together, so you don't need a loop.
+(Look at the ARM or x86 implementation to see how they work.)
+</p><p>
+Once you have that, you need something to jump to.  You can't branch
+directly to the C stub because it's expecting to be called with a "glue"
+argument and then return.  We need a C stub "wrapper" that does the
+setup and jumps directly to the next handler.  We write this in assembly
+and then add it to the config file definition.
+</p><p>
+To see how this works, create a file called
+<code>dalvik/vm/mterp/myarch/stub.S</code> that contains one line:
+<pre>
+/* stub for ${opcode} */
+</pre>
+Then, in <code>dalvik/vm/mterp/config-myarch</code>, add this below the
+<code>handler-size</code> directive:
+<pre>
+# source for the instruction table stub
+asm-stub myarch/stub.S
+</pre>
+</p><p>
+Regenerate the sources with <code>./rebuild.sh</code>, and take a look
+inside <code>dalvik/vm/mterp/out/InterpAsm-myarch.S</code>.  You should
+see 256 copies of the stub function in a single large block after the
+<code>dvmAsmInstructionStart</code> label.  The <code>stub.S</code>
+code will be used anywhere you don't provide an assembly implementation.
+</p><p>
+Note that each block begins with a <code>.balign 64</code> directive.
+This is what pads each handler out to 64 bytes.  Note also that the
+<code>${opcode}</code> text changed into an opcode name, which should
+be used to call the C implementation (<code>dvmMterp_${opcode}</code>).
+</p><p>
+The actual contents of <code>stub.S</code> are up to you to define.
+See <code>entry.S</code> and <code>stub.S</code> in the <code>armv5te</code>
+or <code>x86</code> directories for working examples.
+</p><p>
+If you're working on a variation of an existing architecture, you may be
+able to use most of the existing code and just provide replacements for
+a few instructions.  Look at the <code>armv4t</code> implementation as
+an example.
+</p>
+
+
+<h3>Replacing Stubs</h3>
+
+<p>
+There are roughly 230 Dalvik opcodes, including some that are inserted by
+<a href="dexopt.html">dexopt</a> and aren't described in the
+<a href="dalvik-bytecode.html">Dalvik bytecode</a> documentation.  Each
+one must perform the appropriate actions, fetch the next opcode, and
+branch to the next handler.  The actions performed by the assembly version
+must exactly match those performed by the C version (in
+<code>dalvik/vm/mterp/c/OP_*</code>).
+</p><p>
+It is possible to customize the set of "optimized" instructions for your
+platform.  This is possible because optimized DEX files are not expected
+to work on multiple devices.  Adding, removing, or redefining instructions
+is beyond the scope of this document, and for simplicity it's best to stick
+with the basic set defined by the portable interpreter.
+</p><p>
+Once you have written a handler that looks like it should work, add
+it to the config file.  For example, suppose we have a working version
+of <code>OP_NOP</code>.  For demonstration purposes, fake it for now by
+putting this into <code>dalvik/vm/mterp/myarch/OP_NOP.S</code>:
+<pre>
+/* This is my NOP handler */
+</pre>
+</p><p>
+Then, in the <code>op-start</code> section of <code>config-myarch</code>, add:
+<pre>
+    op OP_NOP myarch
+</pre>
+</p><p>
+This tells the generation script to use the assembly version from the
+<code>myarch</code> directory instead of the C version from the <code>c</code>
+directory.
+</p><p>
+Execute <code>./rebuild.sh</code>.  Look at <code>InterpAsm-myarch.S</code>
+and <code>InterpC-myarch.c</code> in the <code>out</code> directory.  You
+will see that the <code>OP_NOP</code> stub wrapper has been replaced with our
+new code in the assembly file, and the C stub implementation is no longer
+included.
+</p><p>
+As you implement instructions, the C version and corresponding stub wrapper
+will disappear from the output files.  Eventually you will have a 100%
+assembly interpreter.  You may find it saves a little time to examine
+the output of your compiler for some of the operations.  The
+<a href="porting-proto.c.txt">porting-proto.c</a> sample code can be
+helpful here.
+</p>
+
+
+<h3>Interpreter Switching</h3>
+
+<p>
+The Dalvik VM actually includes a third interpreter implementation: the debug
+interpreter.  This is a variation of the portable interpreter that includes
+support for debugging and profiling.
+</p><p>
+When a debugger attaches, or a profiling feature is enabled, the VM
+will switch interpreters at a convenient point.  This is done at the
+same time as the GC safe point check: on a backward branch, a method
+return, or an exception throw.  Similarly, when the debugger detaches
+or profiling is discontinued, execution transfers back to the "fast" or
+"portable" interpreter.
+</p><p>
+Your entry function needs to test the "entryPoint" value in the "glue"
+pointer to determine where execution should begin.  Your exit function
+will need to return a boolean that indicates whether the interpreter is
+exiting (because we reached the "bottom" of a thread stack) or wants to
+switch to the other implementation.
+</p><p>
+See the <code>entry.S</code> file in <code>x86</code> or <code>armv5te</code>
+for examples.
+</p>
+
+
+<h3>Testing</h3>
+
+<p>
+A number of VM tests can be found in <code>dalvik/tests</code>.  The most
+useful during interpreter development is <code>003-omnibus-opcodes</code>,
+which tests many different instructions.
+</p><p>
+The basic invocation is:
+<pre>
+$ cd dalvik/tests
+$ ./run-test 003
+</pre>
+</p><p>
+This will run test 003 on an attached device or emulator.  You can run
+the test against your desktop VM by specifying <code>--reference</code>
+if you suspect the test may be faulty.  You can also use
+<code>--portable</code> and <code>--fast</code> to explictly specify
+one Dalvik interpreter or the other.
+</p><p>
+Some instructions are replaced by <code>dexopt</code>, notably when
+"quickening" field accesses and method invocations.  To ensure
+that you are testing the basic form of the instruction, add the
+<code>--no-optimize</code> option.
+</p><p>
+There is no in-built instruction tracing mechanism.  If you want
+to know for sure that your implementation of an opcode handler
+is being used, the easiest approach is to insert a "printf"
+call.  For an example, look at <code>common_squeak</code> in
+<code>dalvik/vm/mterp/armv5te/footer.S</code>.
+</p><p>
+At some point you need to ensure that debuggers and profiling work with
+your interpreter.  The easiest way to do this is to simply connect a
+debugger or toggle profiling.  (A future test suite may include some
+tests for this.)
+</p>
+
+<p>
+<address>Copyright &copy; 2009 The Android Open Source Project</address>
+
+</body>
+</html>
diff --git a/docs/porting-proto.c.txt b/docs/porting-proto.c.txt
new file mode 100644
index 0000000..2f72bac
--- /dev/null
+++ b/docs/porting-proto.c.txt
@@ -0,0 +1,245 @@
+/*
+ * 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.
+ */
+
+/*
+ * Dalvik instruction fragments, useful when porting mterp.
+ *
+ * Compile this and examine the output to see what your compiler generates.
+ * This can give you a head start on some of the more complicated operations.
+ *
+ * Example:
+ *   % gcc -c -O2 -save-temps -fverbose-asm porting-proto.c
+ *   % less porting-proto.s
+ */
+#include <stdint.h>
+
+typedef int8_t s1;
+typedef uint8_t u1;
+typedef int16_t s2;
+typedef uint16_t u2;
+typedef int32_t s4;
+typedef uint32_t u4;
+typedef int64_t s8;
+typedef uint64_t u8;
+
+s4 iadd32(s4 x, s4 y) { return x + y; }
+s8 iadd64(s8 x, s8 y) { return x + y; }
+float fadd32(float x, float y) { return x + y; }
+double fadd64(double x, double y) { return x + y; }
+
+s4 isub32(s4 x, s4 y) { return x - y; }
+s8 isub64(s8 x, s8 y) { return x - y; }
+float fsub32(float x, float y) { return x - y; }
+double fsub64(double x, double y) { return x - y; }
+
+s4 irsub32lit8(s4 x) { return 25 - x; }
+
+s4 imul32(s4 x, s4 y) { return x * y; }
+s8 imul64(s8 x, s8 y) { return x * y; }
+float fmul32(float x, float y) { return x * y; }
+double fmul64(double x, double y) { return x * y; }
+
+s4 idiv32(s4 x, s4 y) { return x / y; }
+s8 idiv64(s8 x, s8 y) { return x / y; }
+float fdiv32(float x, float y) { return x / y; }
+double fdiv64(double x, double y) { return x / y; }
+
+s4 irem32(s4 x, s4 y) { return x % y; }
+s8 irem64(s8 x, s8 y) { return x % y; }
+
+s4 iand32(s4 x, s4 y) { return x & y; }
+s8 iand64(s8 x, s8 y) { return x & y; }
+
+s4 ior32(s4 x, s4 y) { return x | y; }
+s8 ior64(s8 x, s8 y) { return x | y; }
+
+s4 ixor32(s4 x, s4 y) { return x ^ y; }
+s8 ixor64(s8 x, s8 y) { return x ^ y; }
+
+s4 iasl32(s4 x, s4 count) { return x << (count & 0x1f); }
+s8 iasl64(s8 x, s4 count) { return x << (count & 0x3f); }
+
+s4 iasr32(s4 x, s4 count) { return x >> (count & 0x1f); }
+s8 iasr64(s8 x, s4 count) { return x >> (count & 0x3f); }
+
+s4 ilsr32(s4 x, s4 count) { return ((u4)x) >> (count & 0x1f); } // unsigned
+s8 ilsr64(s8 x, s4 count) { return ((u8)x) >> (count & 0x3f); } // unsigned
+
+s4 ineg32(s4 x) { return -x; }
+s8 ineg64(s8 x) { return -x; }
+float fneg32(float x) { return -x; }
+double fneg64(double x) { return -x; }
+
+s4 inot32(s4 x) { return x ^ -1; }
+s8 inot64(s8 x) { return x ^ -1LL; }
+
+s4 float2int(float x) { return (s4) x; }
+double float2double(float x) { return (double) x; }
+s4 double2int(double x) { return (s4) x; }
+float double2float(double x) { return (float) x; }
+
+/*
+ * ARM lib doesn't clamp large values or NaN the way we want on these two.
+ * If the simple version isn't correct, use the long version.  (You can use
+ * dalvik/tests/041-narrowing to verify.)
+ */
+s8 float2long(float x) { return (s8) x; }
+s8 float2long_clamp(float x)
+{
+    static const float kMaxLong = (float)0x7fffffffffffffffULL;
+    static const float kMinLong = (float)0x8000000000000000ULL;
+
+    if (x >= kMaxLong) {
+        return 0x7fffffffffffffffULL;
+    } else if (x <= kMinLong) {
+        return 0x8000000000000000ULL;
+    } else if (x != x) {
+        return 0;
+    } else {
+        return (s8) x;
+    }
+}
+s8 double2long(double x) { return (s8) x; }
+s8 double2long_clamp(double x)
+{
+    static const double kMaxLong = (double)0x7fffffffffffffffULL;
+    static const double kMinLong = (double)0x8000000000000000ULL;
+
+    if (x >= kMaxLong) {
+        return 0x7fffffffffffffffULL;
+    } else if (x <= kMinLong) {
+        return 0x8000000000000000ULL;
+    } else if (x != x) {
+        return 0;
+    } else {
+        return (s8) x;
+    }
+}
+
+s1 int2byte(s4 x) { return (s1) x; }
+s2 int2short(s4 x) { return (s2) x; }
+u2 int2char(s4 x) { return (u2) x; }
+s8 int2long(s4 x) { return (s8) x; }
+float int2float(s4 x) { return (float) x; }
+double int2double(s4 x) { return (double) x; }
+
+s4 long2int(s8 x) { return (s4) x; }
+float long2float(s8 x) { return (float) x; }
+double long2double(s8 x) { return (double) x; }
+
+int cmpl_float(float x, float y)
+{
+    int result;
+
+    if (x == y)
+        result = 0;
+    else if (x > y)
+        result = 1;
+    else /* (x < y) or NaN */
+        result = -1;
+    return result;
+}
+
+int cmpg_float(float x, float y)
+{
+    int result;
+
+    if (x == y)
+        result = 0;
+    else if (x < y)
+        result = -1;
+    else /* (x > y) or NaN */
+        result = 1;
+    return result;
+}
+
+int cmpl_double(double x, double y)
+{
+    int result;
+
+    if (x == y)
+        result = 0;
+    else if (x > y)
+        result = 1;
+    else /* (x < y) or NaN */
+        result = -1;
+    return result;
+}
+
+int cmpg_double(double x, double y)
+{
+    int result;
+
+    if (x == y)
+        result = 0;
+    else if (x < y)
+        result = -1;
+    else /* (x > y) or NaN */
+        result = 1;
+    return result;
+}
+
+int cmp_long(s8 x, s8 y)
+{
+    int result;
+
+    if (x == y)
+        result = 0;
+    else if (x < y)
+        result = -1;
+    else /* (x > y) */
+        result = 1;
+    return result;
+}
+
+/* instruction decoding fragments */
+u1 unsignedAA(u2 x) { return x >> 8; }
+s1 signedAA(u2 x) { return (s4)(x << 16) >> 24; }
+s2 signedBB(u2 x) { return (s2) x; }
+u1 unsignedA(u2 x) { return (x >> 8) & 0x0f; }
+u1 unsignedB(u2 x) { return x >> 12; }
+
+/* some handy immediate constants when working with float/double */
+u4 const_43e00000(u4 highword) { return 0x43e00000; }
+u4 const_c3e00000(u4 highword) { return 0xc3e00000; }
+u4 const_ffc00000(u4 highword) { return 0xffc00000; }
+u4 const_41dfffff(u4 highword) { return 0x41dfffff; }
+u4 const_c1e00000(u4 highword) { return 0xc1e00000; }
+
+/*
+ * Test for some gcc-defined symbols.  If you're frequently switching
+ * between different cross-compiler architectures or CPU feature sets,
+ * this can help you keep track of which one you're compiling for.
+ */
+#ifdef __arm__
+# warning "found __arm__"
+#endif
+#ifdef __ARM_EABI__
+# warning "found __ARM_EABI__"
+#endif
+#ifdef __VFP_FP__
+# warning "found __VFP_FP__"    /* VFP-format doubles used; may not have VFP */
+#endif
+#if defined(__VFP_FP__) && !defined(__SOFTFP__)
+# warning "VFP in use"
+#endif
+#ifdef __ARM_ARCH_5TE__
+# warning "found __ARM_ARCH_5TE__"
+#endif
+#ifdef __ARM_ARCH_7A__
+# warning "found __ARM_ARCH_7A__"
+#endif
+
diff --git a/docs/verifier.html b/docs/verifier.html
index 656b832..022923b 100644
--- a/docs/verifier.html
+++ b/docs/verifier.html
@@ -33,10 +33,9 @@
     error cases because the verifier guarantees that they are impossible.
     Also, we can optimize the DEX file more aggressively if we start
     with a stronger set of assumptions about the bytecode.
-    <li>"Exact" GC.  The work peformed during verification has significant
-    overlap with the work required to compute register use maps for exact
-    GC.  Improper register use, caught by the verifier, could lead to
-    subtle problems with an "exact" GC.
+    <li>"Precise" GC.  The work peformed during verification has significant
+    overlap with the work required to compute register use maps for
+    type-precise GC.
     <li>Intra-application security.  If an app wants to download bits
     of interpreted code over the network and execute them, it can safely
     do so using well-established security mechanisms.
@@ -85,6 +84,12 @@
 </ul>
 
 <p>
+The VM is permitted but not required to enforce "structured locking"
+constraints, which are designed to ensure that, when a method returns, all
+monitors locked by the method have been unlocked an equal number of times.
+This is not currently implemented.
+
+<p>
 The Dalvik verifier is more restrictive than other VMs in one area:
 type safety on sub-32-bit integer widths.  These additional restrictions
 should make it impossible to, say, pass a value outside the range
@@ -94,24 +99,31 @@
 <h2>Verification Failures</h2>
 
 <p>
-When the verifier rejects a class, it always throws a VerifyError.
-This is different in some cases from other implementations.  For example,
-if a class attempts to perform an illegal access on a field, the expected
-behavior is to receive an IllegalAccessError at runtime the first time
-the field is actually accessed.  The Dalvik verifier will reject the
-entire class immediately.
+The verifier may reject a class immediately, or it may defer throwing
+an exception until the code is actually used.  For example, if a class
+attempts to perform an illegal access on a field, the VM should throw
+an IllegalAccessError the first time the instruction is encountered.
+On the other hand, if a class contains an invalid bytecode, it should be
+rejected immediately with a VerifyError.
 
 <p>
-It's difficult to throw the error on first use in Dalvik.  Possible ways
-to implement this behavior include:
+Immediate VerifyErrors are accompanied by detailed, if somewhat cryptic,
+information in the log file.  From this it's possible to determine the
+exact instruction that failed, and the reason for the failure.
+
+<p>
+It's a bit tricky to implement deferred verification errors in Dalvik.
+A few approaches were considered:
 
 <ol>
 <li>We could replace the invalid field access instruction with a special
 instruction that generates an illegal access error, and allow class
 verification to complete successfully.  This type of verification must
-often be deferred to first class load, rather than be performed ahead of time
-during DEX optimization, which means the bytecode instructions will be
-mapped read-only during verification.  So this won't work.
+be deferred to first class load, rather than be performed ahead of time
+during DEX optimization, because some failures will depend on the current
+execution environment (e.g. not all classes are available at dexopt time).
+At that point the bytecode instructions are mapped read-only during
+verification, so rewriting them isn't possible.
 </li>
 
 <li>We can perform the access checks when the field/method/class is
@@ -120,7 +132,7 @@
 files combine multiple classfiles together, merging the field/method/class
 resolution results into a single large table.  Once one class successfully
 resolves the field, every other class in the same DEX file would be able
-to access the field.  This is bad.
+to access the field.  This is incorrect.
 </li>
 
 <li>Perform the access checks on every field/method/class access.
@@ -134,25 +146,29 @@
 </ol>
 
 <p>
-Other implementations are possible, but they all involve allocating
-some amount of additional memory or spending additional cycles
-on non-DEX-optimized instructions.  We don't want to throw an
-IllegalAccessError at verification time, since that would indicate that
-access to the class being verified was illegal.
+In early versions of Dalvik (as found in Android 1.6 and earlier), the verifier
+simply regarded all problems as immediately fatal.  This generally worked,
+but in some cases the VM was rejecting classes because of bits of code
+that were never used.  The VerifyError itself was sometimes difficult to
+decipher, because it was thrown during verification rather than at the
+point where the problem was first noticed during execution.
 <p>
-One approach that might be worth pursuing: for situations like illegal
-accesses, the verifier makes an in-RAM private copy of the method, and
-alters the instructions there.  The class object is altered to point at
-the new copy of the instructions.  This requires minimal memory overhead
-and provides a better experience for developers.
+The current version uses a variation of approach #1.  The dexopt
+command works the way it did before, leaving the code untouched and
+flagging fully-correct classes as "pre-verified".  When the VM loads a
+class that didn't pass pre-verification, the verifier is invoked.  If a
+"deferrable" problem is detected, a modifiable copy of the instructions
+in the problematic method is made.  In that copy, the troubled instruction
+is replaced with an "always throw" opcode, and verification continues.
 
 <p>
-The VerifyError is accompanied by detailed, if somewhat cryptic,
-information in the log file.  From this it's possible to determine the
-exact instruction that failed, and the reason for the failure.  We can
-also constructor the VerifyError with an IllegalAccessError passed in as
-the cause.
+In the example used earlier, an attempt to read from an inaccessible
+field would result in the "field get" instruction being replaced by
+"always throw IllegalAccessError on field X".  Creating copies of method
+bodies requires additional heap space, but since this affects very few
+methods overall the memory impact should be minor.
 
+<p>
 <address>Copyright &copy; 2008 The Android Open Source Project</address>
 
 </body>
diff --git a/dx/README.txt b/dx/README.txt
index 5421e7b..6a20c82 100644
--- a/dx/README.txt
+++ b/dx/README.txt
@@ -1,2 +1,3 @@
 Home of Dalvik eXchange, the thing that takes in class files and
-reformulates them for consumption in the VM.
+reformulates them for consumption in the VM. It also does a few other
+things; use "dx --help" to see a modicum of self-documentation.
diff --git a/dx/etc/dx b/dx/etc/dx
index dae5874..f773495 100644
--- a/dx/etc/dx
+++ b/dx/etc/dx
@@ -36,42 +36,50 @@
 
 jarfile=dx.jar
 libdir="$progdir"
-if [ ! -r "$libdir/$jarfile" ]
-then
+if [ ! -r "$libdir/$jarfile" ]; then
     libdir=`dirname "$progdir"`/tools/lib
 fi
-if [ ! -r "$libdir/$jarfile" ]
-then
+
+if [ ! -r "$libdir/$jarfile" ]; then
     libdir=`dirname "$progdir"`/framework
 fi
-if [ ! -r "$libdir/$jarfile" ]
-then
+
+if [ ! -r "$libdir/$jarfile" ]; then
     echo `basename "$prog"`": can't find $jarfile"
     exit 1
 fi
 
+# By default, give dx a max heap size of 1 gig. This can be overridden
+# by using a "-J" option (see below).
+defaultMx="-Xmx1024M"
+
+# The following will extract any initial parameters of the form
+# "-J<stuff>" from the command line and pass them to the Java
+# invocation (instead of to dx). This makes it possible for you to add
+# a command-line parameter such as "-JXmx256M" in your scripts, for
+# example. "java" (with no args) and "java -X" give a summary of
+# available options.
+
 javaOpts=""
 
-# If you want DX to have more memory when executing, uncomment the following
-# line and adjust the value accordingly. Use "java -X" for a list of options
-# you can pass here.
-# 
-# javaOpts="-Xmx256M"
-
-# Alternatively, this will extract any parameter "-Jxxx" from the command line
-# and pass them to Java (instead of to dx). This makes it possible for you to
-# add a command-line parameter such as "-JXmx256M" in your ant scripts, for
-# example.
 while expr "x$1" : 'x-J' >/dev/null; do
-    opt=`expr "$1" : '-J\(.*\)'`
+    opt=`expr "x$1" : 'x-J\(.*\)'`
     javaOpts="${javaOpts} -${opt}"
+    if expr "x${opt}" : "xXmx[0-9]" >/dev/null; then
+        defaultMx="no"
+    fi
     shift
 done
 
-if [ "$OSTYPE" = "cygwin" ] ; then
-	jarpath=`cygpath -w  "$libdir/$jarfile"`
+if [ "${defaultMx}" != "no" ]; then
+    javaOpts="${javaOpts} ${defaultMx}"
+fi
+
+if [ "$OSTYPE" = "cygwin" ]; then
+    # For Cygwin, convert the jarfile path into native Windows style.
+    jarpath=`cygpath -w "$libdir/$jarfile"`
 else
-	jarpath="$libdir/$jarfile"
+    jarpath="$libdir/$jarfile"
 fi
 
 exec java $javaOpts -jar "$jarpath" "$@"
diff --git a/dx/etc/dx.bat b/dx/etc/dx.bat
index 2686d6a..1361bb6 100755
--- a/dx/etc/dx.bat
+++ b/dx/etc/dx.bat
@@ -40,12 +40,47 @@
 set jarpath=%frameworkdir%%jarfile%
 
 set javaOpts=
+set args=
 
-REM If you want DX to have more memory when executing, uncomment the
-REM following line and adjust the value accordingly. Use "java -X" for
-REM a list of options you can pass here.
-REM 
-REM set javaOpts=-Xmx256M
+REM By default, give dx a max heap size of 1 gig. This can be overridden
+REM by using a "-JXmx..." option (see below).
+set defaultMx=-Xmx1024M
 
-call java %javaOpts% -Djava.ext.dirs=%frameworkdir% -jar %jarpath% %*
+REM capture all arguments to process them below
+set params=%*
+
+:nextArg
+if "%params%"=="" goto endArgs
+    REM Note: advanced substitions don't work on %1..%N. We need to assign to
+    REM a variable first.
+    REM We also can't use %1..%N directly because an option such as --output=name
+    REM gets automagically converted into %1=--output and %2=name (yes, really!)
+    REM Instead we manually extract the first token from the params variable.
+    for /F "tokens=1*" %%a in ("%params%") do call :getArg "%%a" "%%b"
+
+    if "%defaultMx%"=="" goto notXmx
+    if "%A:~0,5%" NEQ "-JXmx" goto notXmx
+        set defaultMx=
+    :notXmx
+
+    if "%A:~0,2%" NEQ "-J" goto notJ
+        set javaOpts=%javaOpts% -%A:~2%
+        goto nextArg
+
+    :notJ
+        set args=%args% %A%
+        goto nextArg
+
+:getArg
+    REM this subroutine is called by the for /F with the first argument of params
+    REM and the rest of the line. The "goto :eof" actually exits the subroutine.
+    set A=%~1
+    set params=%~2
+    goto :eof
+
+:endArgs
+
+set javaOpts=%javaOpts% %defaultMx%
+
+call java %javaOpts% -Djava.ext.dirs=%frameworkdir% -jar %jarpath% %args%
 
diff --git a/dx/src/com/android/dx/Version.java b/dx/src/com/android/dx/Version.java
index 02dc7b2..4950d39 100644
--- a/dx/src/com/android/dx/Version.java
+++ b/dx/src/com/android/dx/Version.java
@@ -20,6 +20,6 @@
  * Version number for dx.
  */
 public class Version {
-    /** non-null; version string */
-    public static final String VERSION = "1.2";
+    /** {@code non-null;} version string */
+    public static final String VERSION = "1.3";
 }
diff --git a/dx/src/com/android/dx/cf/attrib/AttAnnotationDefault.java b/dx/src/com/android/dx/cf/attrib/AttAnnotationDefault.java
index 12e1f74..acf5a9e 100644
--- a/dx/src/com/android/dx/cf/attrib/AttAnnotationDefault.java
+++ b/dx/src/com/android/dx/cf/attrib/AttAnnotationDefault.java
@@ -19,24 +19,24 @@
 import com.android.dx.rop.cst.Constant;
 
 /**
- * Attribute class for <code>AnnotationDefault</code> attributes.
+ * Attribute class for {@code AnnotationDefault} attributes.
  */
 public final class AttAnnotationDefault extends BaseAttribute {
-    /** non-null; attribute name for attributes of this type */
+    /** {@code non-null;} attribute name for attributes of this type */
     public static final String ATTRIBUTE_NAME = "AnnotationDefault";
 
-    /** non-null; the annotation default value */
+    /** {@code non-null;} the annotation default value */
     private final Constant value;
 
-    /** &gt;= 0; attribute data length in the original classfile (not
+    /** {@code >= 0;} attribute data length in the original classfile (not
      * including the attribute header) */
     private final int byteLength;
 
     /**
      * Constructs an instance.
      * 
-     * @param value non-null; the annotation default value
-     * @param byteLength &gt;= 0; attribute data length in the original
+     * @param value {@code non-null;} the annotation default value
+     * @param byteLength {@code >= 0;} attribute data length in the original
      * classfile (not including the attribute header)
      */
     public AttAnnotationDefault(Constant value, int byteLength) {
@@ -59,7 +59,7 @@
     /**
      * Gets the annotation default value.
      * 
-     * @return non-null; the value
+     * @return {@code non-null;} the value
      */
     public Constant getValue() {
         return value;
diff --git a/dx/src/com/android/dx/cf/attrib/AttCode.java b/dx/src/com/android/dx/cf/attrib/AttCode.java
index f00da2f..89ba895 100644
--- a/dx/src/com/android/dx/cf/attrib/AttCode.java
+++ b/dx/src/com/android/dx/cf/attrib/AttCode.java
@@ -22,35 +22,35 @@
 import com.android.dx.util.MutabilityException;
 
 /**
- * Attribute class for standard <code>Code</code> attributes.
+ * Attribute class for standard {@code Code} attributes.
  */
 public final class AttCode extends BaseAttribute {
-    /** non-null; attribute name for attributes of this type */
+    /** {@code non-null;} attribute name for attributes of this type */
     public static final String ATTRIBUTE_NAME = "Code";
 
-    /** &gt;= 0; the stack size */
+    /** {@code >= 0;} the stack size */
     private final int maxStack;
 
-    /** &gt;= 0; the number of locals */
+    /** {@code >= 0;} the number of locals */
     private final int maxLocals;
 
-    /** non-null; array containing the bytecode per se */
+    /** {@code non-null;} array containing the bytecode per se */
     private final BytecodeArray code;
 
-    /** non-null; the exception table */
+    /** {@code non-null;} the exception table */
     private final ByteCatchList catches;
 
-    /** non-null; the associated list of attributes */
+    /** {@code non-null;} the associated list of attributes */
     private final AttributeList attributes;
 
     /**
      * Constructs an instance.
      * 
-     * @param maxStack &gt;= 0; the stack size
-     * @param maxLocals &gt;= 0; the number of locals
-     * @param code non-null; array containing the bytecode per se
-     * @param catches non-null; the exception table
-     * @param attributes non-null; the associated list of attributes
+     * @param maxStack {@code >= 0;} the stack size
+     * @param maxLocals {@code >= 0;} the number of locals
+     * @param code {@code non-null;} array containing the bytecode per se
+     * @param catches {@code non-null;} the exception table
+     * @param attributes {@code non-null;} the associated list of attributes
      */
     public AttCode(int maxStack, int maxLocals, BytecodeArray code,
                    ByteCatchList catches, AttributeList attributes) {
@@ -101,7 +101,7 @@
     /**
      * Gets the maximum stack size.
      * 
-     * @return &gt;= 0; the maximum stack size
+     * @return {@code >= 0;} the maximum stack size
      */
     public int getMaxStack() {
         return maxStack;
@@ -110,7 +110,7 @@
     /**
      * Gets the number of locals.
      * 
-     * @return &gt;= 0; the number of locals
+     * @return {@code >= 0;} the number of locals
      */
     public int getMaxLocals() {
         return maxLocals;
@@ -119,7 +119,7 @@
     /**
      * Gets the bytecode array.
      * 
-     * @return non-null; the bytecode array
+     * @return {@code non-null;} the bytecode array
      */
     public BytecodeArray getCode() {
         return code;
@@ -128,7 +128,7 @@
     /**
      * Gets the exception table.
      * 
-     * @return non-null; the exception table
+     * @return {@code non-null;} the exception table
      */
     public ByteCatchList getCatches() {
         return catches;
@@ -137,7 +137,7 @@
     /**
      * Gets the associated attribute list.
      * 
-     * @return non-null; the attribute list
+     * @return {@code non-null;} the attribute list
      */
     public AttributeList getAttributes() {
         return attributes;
diff --git a/dx/src/com/android/dx/cf/attrib/AttConstantValue.java b/dx/src/com/android/dx/cf/attrib/AttConstantValue.java
index a84da43..a7436f3 100644
--- a/dx/src/com/android/dx/cf/attrib/AttConstantValue.java
+++ b/dx/src/com/android/dx/cf/attrib/AttConstantValue.java
@@ -24,22 +24,22 @@
 import com.android.dx.rop.cst.TypedConstant;
 
 /**
- * Attribute class for standard <code>ConstantValue</code> attributes.
+ * Attribute class for standard {@code ConstantValue} attributes.
  */
 public final class AttConstantValue extends BaseAttribute {
-    /** non-null; attribute name for attributes of this type */
+    /** {@code non-null;} attribute name for attributes of this type */
     public static final String ATTRIBUTE_NAME = "ConstantValue";
 
-    /** non-null; the constant value */
+    /** {@code non-null;} the constant value */
     private final TypedConstant constantValue;
 
     /**
      * Constructs an instance.
      * 
-     * @param constantValue non-null; the constant value, which must
-     * be an instance of one of: <code>CstString</code>,
-     * <code>CstInteger</code>, <code>CstLong</code>,
-     * <code>CstFloat</code>, or <code>CstDouble</code>
+     * @param constantValue {@code non-null;} the constant value, which must
+     * be an instance of one of: {@code CstString},
+     * {@code CstInteger}, {@code CstLong},
+     * {@code CstFloat}, or {@code CstDouble}
      */
     public AttConstantValue(TypedConstant constantValue) {
         super(ATTRIBUTE_NAME);
@@ -65,11 +65,11 @@
 
     /**
      * Gets the constant value of this instance. The returned value
-     * is an instance of one of: <code>CstString</code>,
-     * <code>CstInteger</code>, <code>CstLong</code>,
-     * <code>CstFloat</code>, or <code>CstDouble</code>.
+     * is an instance of one of: {@code CstString},
+     * {@code CstInteger}, {@code CstLong},
+     * {@code CstFloat}, or {@code CstDouble}.
      * 
-     * @return non-null; the constant value
+     * @return {@code non-null;} the constant value
      */
     public TypedConstant getConstantValue() {
         return constantValue;
diff --git a/dx/src/com/android/dx/cf/attrib/AttDeprecated.java b/dx/src/com/android/dx/cf/attrib/AttDeprecated.java
index cd1dd24..d440aae 100644
--- a/dx/src/com/android/dx/cf/attrib/AttDeprecated.java
+++ b/dx/src/com/android/dx/cf/attrib/AttDeprecated.java
@@ -17,10 +17,10 @@
 package com.android.dx.cf.attrib;
 
 /**
- * Attribute class for standard <code>Deprecated</code> attributes.
+ * Attribute class for standard {@code Deprecated} attributes.
  */
 public final class AttDeprecated extends BaseAttribute {
-    /** non-null; attribute name for attributes of this type */
+    /** {@code non-null;} attribute name for attributes of this type */
     public static final String ATTRIBUTE_NAME = "Deprecated";
 
     /**
diff --git a/dx/src/com/android/dx/cf/attrib/AttEnclosingMethod.java b/dx/src/com/android/dx/cf/attrib/AttEnclosingMethod.java
index 7cccad7..68a24d9 100644
--- a/dx/src/com/android/dx/cf/attrib/AttEnclosingMethod.java
+++ b/dx/src/com/android/dx/cf/attrib/AttEnclosingMethod.java
@@ -20,24 +20,24 @@
 import com.android.dx.rop.cst.CstType;
 
 /**
- * Attribute class for standards-track <code>EnclosingMethod</code>
+ * Attribute class for standards-track {@code EnclosingMethod}
  * attributes.
  */
 public final class AttEnclosingMethod extends BaseAttribute {
-    /** non-null; attribute name for attributes of this type */
+    /** {@code non-null;} attribute name for attributes of this type */
     public static final String ATTRIBUTE_NAME = "EnclosingMethod";
 
-    /** non-null; the innermost enclosing class */
+    /** {@code non-null;} the innermost enclosing class */
     private final CstType type;
 
-    /** null-ok; the name-and-type of the innermost enclosing method, if any */
+    /** {@code null-ok;} the name-and-type of the innermost enclosing method, if any */
     private final CstNat method;
 
     /**
      * Constructs an instance.
      * 
-     * @param type non-null; the innermost enclosing class
-     * @param method null-ok; the name-and-type of the innermost enclosing
+     * @param type {@code non-null;} the innermost enclosing class
+     * @param method {@code null-ok;} the name-and-type of the innermost enclosing
      * method, if any
      */
     public AttEnclosingMethod(CstType type, CstNat method) {
@@ -59,7 +59,7 @@
     /**
      * Gets the innermost enclosing class.
      * 
-     * @return non-null; the innermost enclosing class
+     * @return {@code non-null;} the innermost enclosing class
      */
     public CstType getEnclosingClass() {
         return type;
@@ -69,7 +69,7 @@
      * Gets the name-and-type of the innermost enclosing method, if
      * any.
      * 
-     * @return null-ok; the name-and-type of the innermost enclosing
+     * @return {@code null-ok;} the name-and-type of the innermost enclosing
      * method, if any
      */
     public CstNat getMethod() {
diff --git a/dx/src/com/android/dx/cf/attrib/AttExceptions.java b/dx/src/com/android/dx/cf/attrib/AttExceptions.java
index 59e624e..c592047 100644
--- a/dx/src/com/android/dx/cf/attrib/AttExceptions.java
+++ b/dx/src/com/android/dx/cf/attrib/AttExceptions.java
@@ -20,20 +20,20 @@
 import com.android.dx.util.MutabilityException;
 
 /**
- * Attribute class for standard <code>Exceptions</code> attributes.
+ * Attribute class for standard {@code Exceptions} attributes.
  */
 public final class AttExceptions extends BaseAttribute {
-    /** non-null; attribute name for attributes of this type */
+    /** {@code non-null;} attribute name for attributes of this type */
     public static final String ATTRIBUTE_NAME = "Exceptions";
 
-    /** non-null; list of exception classes */
+    /** {@code non-null;} list of exception classes */
     private final TypeList exceptions;
 
     /**
      * Constructs an instance.
      * 
-     * @param exceptions non-null; list of classes, presumed but not
-     * verified to be subclasses of <code>Throwable</code>
+     * @param exceptions {@code non-null;} list of classes, presumed but not
+     * verified to be subclasses of {@code Throwable}
      */
     public AttExceptions(TypeList exceptions) {
         super(ATTRIBUTE_NAME);
@@ -58,9 +58,9 @@
     /**
      * Gets the list of classes associated with this instance. In
      * general, these classes are not pre-verified to be subclasses of
-     * <code>Throwable</code>.
+     * {@code Throwable}.
      * 
-     * @return non-null; the list of classes
+     * @return {@code non-null;} the list of classes
      */
     public TypeList getExceptions() {
         return exceptions;
diff --git a/dx/src/com/android/dx/cf/attrib/AttInnerClasses.java b/dx/src/com/android/dx/cf/attrib/AttInnerClasses.java
index df30539..bd6c7cd 100644
--- a/dx/src/com/android/dx/cf/attrib/AttInnerClasses.java
+++ b/dx/src/com/android/dx/cf/attrib/AttInnerClasses.java
@@ -19,19 +19,19 @@
 import com.android.dx.util.MutabilityException;
 
 /**
- * Attribute class for standard <code>InnerClasses</code> attributes.
+ * Attribute class for standard {@code InnerClasses} attributes.
  */
 public final class AttInnerClasses extends BaseAttribute {
-    /** non-null; attribute name for attributes of this type */
+    /** {@code non-null;} attribute name for attributes of this type */
     public static final String ATTRIBUTE_NAME = "InnerClasses";
 
-    /** non-null; list of inner class entries */
+    /** {@code non-null;} list of inner class entries */
     private final InnerClassList innerClasses;
 
     /**
      * Constructs an instance.
      * 
-     * @param innerClasses non-null; list of inner class entries
+     * @param innerClasses {@code non-null;} list of inner class entries
      */
     public AttInnerClasses(InnerClassList innerClasses) {
         super(ATTRIBUTE_NAME);
@@ -56,7 +56,7 @@
     /**
      * Gets the list of "inner class" entries associated with this instance.
      * 
-     * @return non-null; the list
+     * @return {@code non-null;} the list
      */
     public InnerClassList getInnerClasses() {
         return innerClasses;
diff --git a/dx/src/com/android/dx/cf/attrib/AttLineNumberTable.java b/dx/src/com/android/dx/cf/attrib/AttLineNumberTable.java
index c5e65e8..38980be 100644
--- a/dx/src/com/android/dx/cf/attrib/AttLineNumberTable.java
+++ b/dx/src/com/android/dx/cf/attrib/AttLineNumberTable.java
@@ -20,19 +20,19 @@
 import com.android.dx.util.MutabilityException;
 
 /**
- * Attribute class for standard <code>LineNumberTable</code> attributes.
+ * Attribute class for standard {@code LineNumberTable} attributes.
  */
 public final class AttLineNumberTable extends BaseAttribute {
-    /** non-null; attribute name for attributes of this type */
+    /** {@code non-null;} attribute name for attributes of this type */
     public static final String ATTRIBUTE_NAME = "LineNumberTable";
 
-    /** non-null; list of line number entries */
+    /** {@code non-null;} list of line number entries */
     private final LineNumberList lineNumbers;
 
     /**
      * Constructs an instance.
      * 
-     * @param lineNumbers non-null; list of line number entries
+     * @param lineNumbers {@code non-null;} list of line number entries
      */
     public AttLineNumberTable(LineNumberList lineNumbers) {
         super(ATTRIBUTE_NAME);
@@ -57,7 +57,7 @@
     /**
      * Gets the list of "line number" entries associated with this instance.
      * 
-     * @return non-null; the list
+     * @return {@code non-null;} the list
      */
     public LineNumberList getLineNumbers() {
         return lineNumbers;
diff --git a/dx/src/com/android/dx/cf/attrib/AttLocalVariableTable.java b/dx/src/com/android/dx/cf/attrib/AttLocalVariableTable.java
index 893f254..53ba64f 100644
--- a/dx/src/com/android/dx/cf/attrib/AttLocalVariableTable.java
+++ b/dx/src/com/android/dx/cf/attrib/AttLocalVariableTable.java
@@ -19,16 +19,16 @@
 import com.android.dx.cf.code.LocalVariableList;
 
 /**
- * Attribute class for standard <code>LocalVariableTable</code> attributes.
+ * Attribute class for standard {@code LocalVariableTable} attributes.
  */
 public final class AttLocalVariableTable extends BaseLocalVariables {
-    /** non-null; attribute name for attributes of this type */
+    /** {@code non-null;} attribute name for attributes of this type */
     public static final String ATTRIBUTE_NAME = "LocalVariableTable";
 
     /**
      * Constructs an instance.
      * 
-     * @param localVariables non-null; list of local variable entries
+     * @param localVariables {@code non-null;} list of local variable entries
      */
     public AttLocalVariableTable(LocalVariableList localVariables) {
         super(ATTRIBUTE_NAME, localVariables);
diff --git a/dx/src/com/android/dx/cf/attrib/AttLocalVariableTypeTable.java b/dx/src/com/android/dx/cf/attrib/AttLocalVariableTypeTable.java
index 7037b74..49cdb0c 100644
--- a/dx/src/com/android/dx/cf/attrib/AttLocalVariableTypeTable.java
+++ b/dx/src/com/android/dx/cf/attrib/AttLocalVariableTypeTable.java
@@ -19,16 +19,16 @@
 import com.android.dx.cf.code.LocalVariableList;
 
 /**
- * Attribute class for standard <code>LocalVariableTypeTable</code> attributes.
+ * Attribute class for standard {@code LocalVariableTypeTable} attributes.
  */
 public final class AttLocalVariableTypeTable extends BaseLocalVariables {
-    /** non-null; attribute name for attributes of this type */
+    /** {@code non-null;} attribute name for attributes of this type */
     public static final String ATTRIBUTE_NAME = "LocalVariableTypeTable";
 
     /**
      * Constructs an instance.
      * 
-     * @param localVariables non-null; list of local variable entries
+     * @param localVariables {@code non-null;} list of local variable entries
      */
     public AttLocalVariableTypeTable(LocalVariableList localVariables) {
         super(ATTRIBUTE_NAME, localVariables);
diff --git a/dx/src/com/android/dx/cf/attrib/AttRuntimeInvisibleAnnotations.java b/dx/src/com/android/dx/cf/attrib/AttRuntimeInvisibleAnnotations.java
index 583ab17..e83b76f 100644
--- a/dx/src/com/android/dx/cf/attrib/AttRuntimeInvisibleAnnotations.java
+++ b/dx/src/com/android/dx/cf/attrib/AttRuntimeInvisibleAnnotations.java
@@ -19,18 +19,18 @@
 import com.android.dx.rop.annotation.Annotations;
 
 /**
- * Attribute class for standard <code>RuntimeInvisibleAnnotations</code>
+ * Attribute class for standard {@code RuntimeInvisibleAnnotations}
  * attributes.
  */
 public final class AttRuntimeInvisibleAnnotations extends BaseAnnotations {
-    /** non-null; attribute name for attributes of this type */
+    /** {@code non-null;} attribute name for attributes of this type */
     public static final String ATTRIBUTE_NAME = "RuntimeInvisibleAnnotations";
 
     /**
      * Constructs an instance.
      * 
-     * @param annotations non-null; the list of annotations
-     * @param byteLength &gt;= 0; attribute data length in the original
+     * @param annotations {@code non-null;} the list of annotations
+     * @param byteLength {@code >= 0;} attribute data length in the original
      * classfile (not including the attribute header)
      */
     public AttRuntimeInvisibleAnnotations(Annotations annotations,
diff --git a/dx/src/com/android/dx/cf/attrib/AttRuntimeInvisibleParameterAnnotations.java b/dx/src/com/android/dx/cf/attrib/AttRuntimeInvisibleParameterAnnotations.java
index 08865e1..7dfe206 100644
--- a/dx/src/com/android/dx/cf/attrib/AttRuntimeInvisibleParameterAnnotations.java
+++ b/dx/src/com/android/dx/cf/attrib/AttRuntimeInvisibleParameterAnnotations.java
@@ -20,19 +20,19 @@
 
 /**
  * Attribute class for standard
- * <code>RuntimeInvisibleParameterAnnotations</code> attributes.
+ * {@code RuntimeInvisibleParameterAnnotations} attributes.
  */
 public final class AttRuntimeInvisibleParameterAnnotations
         extends BaseParameterAnnotations {
-    /** non-null; attribute name for attributes of this type */
+    /** {@code non-null;} attribute name for attributes of this type */
     public static final String ATTRIBUTE_NAME =
         "RuntimeInvisibleParameterAnnotations";
 
     /**
      * Constructs an instance.
      * 
-     * @param parameterAnnotations non-null; the parameter annotations
-     * @param byteLength &gt;= 0; attribute data length in the original
+     * @param parameterAnnotations {@code non-null;} the parameter annotations
+     * @param byteLength {@code >= 0;} attribute data length in the original
      * classfile (not including the attribute header)
      */
     public AttRuntimeInvisibleParameterAnnotations(
diff --git a/dx/src/com/android/dx/cf/attrib/AttRuntimeVisibleAnnotations.java b/dx/src/com/android/dx/cf/attrib/AttRuntimeVisibleAnnotations.java
index c61acb5..9de0588 100644
--- a/dx/src/com/android/dx/cf/attrib/AttRuntimeVisibleAnnotations.java
+++ b/dx/src/com/android/dx/cf/attrib/AttRuntimeVisibleAnnotations.java
@@ -19,18 +19,18 @@
 import com.android.dx.rop.annotation.Annotations;
 
 /**
- * Attribute class for standard <code>RuntimeVisibleAnnotations</code>
+ * Attribute class for standard {@code RuntimeVisibleAnnotations}
  * attributes.
  */
 public final class AttRuntimeVisibleAnnotations extends BaseAnnotations {
-    /** non-null; attribute name for attributes of this type */
+    /** {@code non-null;} attribute name for attributes of this type */
     public static final String ATTRIBUTE_NAME = "RuntimeVisibleAnnotations";
 
     /**
      * Constructs an instance.
      * 
-     * @param annotations non-null; the list of annotations
-     * @param byteLength &gt;= 0; attribute data length in the original
+     * @param annotations {@code non-null;} the list of annotations
+     * @param byteLength {@code >= 0;} attribute data length in the original
      * classfile (not including the attribute header)
      */
     public AttRuntimeVisibleAnnotations(Annotations annotations,
diff --git a/dx/src/com/android/dx/cf/attrib/AttRuntimeVisibleParameterAnnotations.java b/dx/src/com/android/dx/cf/attrib/AttRuntimeVisibleParameterAnnotations.java
index dfe57b2..76607c0 100644
--- a/dx/src/com/android/dx/cf/attrib/AttRuntimeVisibleParameterAnnotations.java
+++ b/dx/src/com/android/dx/cf/attrib/AttRuntimeVisibleParameterAnnotations.java
@@ -19,20 +19,20 @@
 import com.android.dx.rop.annotation.AnnotationsList;
 
 /**
- * Attribute class for standard <code>RuntimeVisibleParameterAnnotations</code>
+ * Attribute class for standard {@code RuntimeVisibleParameterAnnotations}
  * attributes.
  */
 public final class AttRuntimeVisibleParameterAnnotations
         extends BaseParameterAnnotations {
-    /** non-null; attribute name for attributes of this type */
+    /** {@code non-null;} attribute name for attributes of this type */
     public static final String ATTRIBUTE_NAME =
         "RuntimeVisibleParameterAnnotations";
 
     /**
      * Constructs an instance.
      * 
-     * @param annotations non-null; the parameter annotations
-     * @param byteLength &gt;= 0; attribute data length in the original
+     * @param annotations {@code non-null;} the parameter annotations
+     * @param byteLength {@code >= 0;} attribute data length in the original
      * classfile (not including the attribute header)
      */
     public AttRuntimeVisibleParameterAnnotations(
diff --git a/dx/src/com/android/dx/cf/attrib/AttSignature.java b/dx/src/com/android/dx/cf/attrib/AttSignature.java
index 97edbbd..b9cb97d 100644
--- a/dx/src/com/android/dx/cf/attrib/AttSignature.java
+++ b/dx/src/com/android/dx/cf/attrib/AttSignature.java
@@ -19,19 +19,19 @@
 import com.android.dx.rop.cst.CstUtf8;
 
 /**
- * Attribute class for standards-track <code>Signature</code> attributes.
+ * Attribute class for standards-track {@code Signature} attributes.
  */
 public final class AttSignature extends BaseAttribute {
-    /** non-null; attribute name for attributes of this type */
+    /** {@code non-null;} attribute name for attributes of this type */
     public static final String ATTRIBUTE_NAME = "Signature";
 
-    /** non-null; the signature string */
+    /** {@code non-null;} the signature string */
     private final CstUtf8 signature;
 
     /**
      * Constructs an instance.
      * 
-     * @param signature non-null; the signature string
+     * @param signature {@code non-null;} the signature string
      */
     public AttSignature(CstUtf8 signature) {
         super(ATTRIBUTE_NAME);
@@ -51,7 +51,7 @@
     /**
      * Gets the signature string.
      * 
-     * @return non-null; the signature string
+     * @return {@code non-null;} the signature string
      */
     public CstUtf8 getSignature() {
         return signature;
diff --git a/dx/src/com/android/dx/cf/attrib/AttSourceFile.java b/dx/src/com/android/dx/cf/attrib/AttSourceFile.java
index f087217..941a2b0 100644
--- a/dx/src/com/android/dx/cf/attrib/AttSourceFile.java
+++ b/dx/src/com/android/dx/cf/attrib/AttSourceFile.java
@@ -19,19 +19,19 @@
 import com.android.dx.rop.cst.CstUtf8;
 
 /**
- * Attribute class for standard <code>SourceFile</code> attributes.
+ * Attribute class for standard {@code SourceFile} attributes.
  */
 public final class AttSourceFile extends BaseAttribute {
-    /** non-null; attribute name for attributes of this type */
+    /** {@code non-null;} attribute name for attributes of this type */
     public static final String ATTRIBUTE_NAME = "SourceFile";
 
-    /** non-null; name of the source file */
+    /** {@code non-null;} name of the source file */
     private final CstUtf8 sourceFile;
 
     /**
      * Constructs an instance.
      * 
-     * @param sourceFile non-null; the name of the source file
+     * @param sourceFile {@code non-null;} the name of the source file
      */
     public AttSourceFile(CstUtf8 sourceFile) {
         super(ATTRIBUTE_NAME);
@@ -51,7 +51,7 @@
     /**
      * Gets the source file name of this instance.
      * 
-     * @return non-null; the source file
+     * @return {@code non-null;} the source file
      */
     public CstUtf8 getSourceFile() {
         return sourceFile;
diff --git a/dx/src/com/android/dx/cf/attrib/AttSynthetic.java b/dx/src/com/android/dx/cf/attrib/AttSynthetic.java
index daa9b0c..e3841eb 100644
--- a/dx/src/com/android/dx/cf/attrib/AttSynthetic.java
+++ b/dx/src/com/android/dx/cf/attrib/AttSynthetic.java
@@ -17,10 +17,10 @@
 package com.android.dx.cf.attrib;
 
 /**
- * Attribute class for standard <code>Synthetic</code> attributes.
+ * Attribute class for standard {@code Synthetic} attributes.
  */
 public final class AttSynthetic extends BaseAttribute {
-    /** non-null; attribute name for attributes of this type */
+    /** {@code non-null;} attribute name for attributes of this type */
     public static final String ATTRIBUTE_NAME = "Synthetic";
 
     /**
diff --git a/dx/src/com/android/dx/cf/attrib/BaseAnnotations.java b/dx/src/com/android/dx/cf/attrib/BaseAnnotations.java
index 0163e2c..4d9201e 100644
--- a/dx/src/com/android/dx/cf/attrib/BaseAnnotations.java
+++ b/dx/src/com/android/dx/cf/attrib/BaseAnnotations.java
@@ -23,19 +23,19 @@
  * Base class for annotations attributes.
  */
 public abstract class BaseAnnotations extends BaseAttribute {
-    /** non-null; list of annotations */
+    /** {@code non-null;} list of annotations */
     private final Annotations annotations;
 
-    /** &gt;= 0; attribute data length in the original classfile (not
+    /** {@code >= 0;} attribute data length in the original classfile (not
      * including the attribute header) */
     private final int byteLength;
 
     /**
      * Constructs an instance.
      * 
-     * @param attributeName non-null; the name of the attribute
-     * @param annotations non-null; the list of annotations
-     * @param byteLength &gt;= 0; attribute data length in the original
+     * @param attributeName {@code non-null;} the name of the attribute
+     * @param annotations {@code non-null;} the list of annotations
+     * @param byteLength {@code >= 0;} attribute data length in the original
      * classfile (not including the attribute header)
      */
     public BaseAnnotations(String attributeName, Annotations annotations,
@@ -64,7 +64,7 @@
     /**
      * Gets the list of annotations associated with this instance.
      * 
-     * @return non-null; the list
+     * @return {@code non-null;} the list
      */
     public final Annotations getAnnotations() {
         return annotations;
diff --git a/dx/src/com/android/dx/cf/attrib/BaseAttribute.java b/dx/src/com/android/dx/cf/attrib/BaseAttribute.java
index ef1c6ac..c9c1b33 100644
--- a/dx/src/com/android/dx/cf/attrib/BaseAttribute.java
+++ b/dx/src/com/android/dx/cf/attrib/BaseAttribute.java
@@ -23,13 +23,13 @@
  * the attribute name but leaves the rest up to subclasses.
  */
 public abstract class BaseAttribute implements Attribute {
-    /** non-null; attribute name */
+    /** {@code non-null;} attribute name */
     private final String name;
 
     /**
      * Constructs an instance.
      * 
-     * @param name non-null; attribute name
+     * @param name {@code non-null;} attribute name
      */
     public BaseAttribute(String name) {
         if (name == null) {
diff --git a/dx/src/com/android/dx/cf/attrib/BaseLocalVariables.java b/dx/src/com/android/dx/cf/attrib/BaseLocalVariables.java
index a39e724..5ba5889 100644
--- a/dx/src/com/android/dx/cf/attrib/BaseLocalVariables.java
+++ b/dx/src/com/android/dx/cf/attrib/BaseLocalVariables.java
@@ -20,18 +20,18 @@
 import com.android.dx.util.MutabilityException;
 
 /**
- * Base attribute class for standard <code>LocalVariableTable</code>
- * and <code>LocalVariableTypeTable</code> attributes.
+ * Base attribute class for standard {@code LocalVariableTable}
+ * and {@code LocalVariableTypeTable} attributes.
  */
 public abstract class BaseLocalVariables extends BaseAttribute {
-    /** non-null; list of local variable entries */
+    /** {@code non-null;} list of local variable entries */
     private final LocalVariableList localVariables;
 
     /**
      * Constructs an instance.
      * 
-     * @param name non-null; attribute name
-     * @param localVariables non-null; list of local variable entries
+     * @param name {@code non-null;} attribute name
+     * @param localVariables {@code non-null;} list of local variable entries
      */
     public BaseLocalVariables(String name,
             LocalVariableList localVariables) {
@@ -57,7 +57,7 @@
     /**
      * Gets the list of "local variable" entries associated with this instance.
      * 
-     * @return non-null; the list
+     * @return {@code non-null;} the list
      */
     public final LocalVariableList getLocalVariables() {
         return localVariables;
diff --git a/dx/src/com/android/dx/cf/attrib/BaseParameterAnnotations.java b/dx/src/com/android/dx/cf/attrib/BaseParameterAnnotations.java
index a927e3d..1b204b3 100644
--- a/dx/src/com/android/dx/cf/attrib/BaseParameterAnnotations.java
+++ b/dx/src/com/android/dx/cf/attrib/BaseParameterAnnotations.java
@@ -23,19 +23,19 @@
  * Base class for parameter annotation list attributes.
  */
 public abstract class BaseParameterAnnotations extends BaseAttribute {
-    /** non-null; list of annotations */
+    /** {@code non-null;} list of annotations */
     private final AnnotationsList parameterAnnotations;
 
-    /** &gt;= 0; attribute data length in the original classfile (not
+    /** {@code >= 0;} attribute data length in the original classfile (not
      * including the attribute header) */
     private final int byteLength;
 
     /**
      * Constructs an instance.
      * 
-     * @param attributeName non-null; the name of the attribute
-     * @param parameterAnnotations non-null; the annotations
-     * @param byteLength &gt;= 0; attribute data length in the original
+     * @param attributeName {@code non-null;} the name of the attribute
+     * @param parameterAnnotations {@code non-null;} the annotations
+     * @param byteLength {@code >= 0;} attribute data length in the original
      * classfile (not including the attribute header)
      */
     public BaseParameterAnnotations(String attributeName,
@@ -65,7 +65,7 @@
     /**
      * Gets the list of annotation lists associated with this instance.
      * 
-     * @return non-null; the list
+     * @return {@code non-null;} the list
      */
     public final AnnotationsList getParameterAnnotations() {
         return parameterAnnotations;
diff --git a/dx/src/com/android/dx/cf/attrib/InnerClassList.java b/dx/src/com/android/dx/cf/attrib/InnerClassList.java
index 3585f1d..96e1b60 100644
--- a/dx/src/com/android/dx/cf/attrib/InnerClassList.java
+++ b/dx/src/com/android/dx/cf/attrib/InnerClassList.java
@@ -22,7 +22,7 @@
 
 /**
  * List of "inner class" entries, which are the contents of
- * <code>InnerClasses</code> attributes.
+ * {@code InnerClasses} attributes.
  */
 public final class InnerClassList extends FixedSizeList {
     /**
@@ -37,8 +37,8 @@
     /**
      * Gets the indicated item.
      *
-     * @param n &gt;= 0; which item
-     * @return null-ok; the indicated item
+     * @param n {@code >= 0;} which item
+     * @return {@code null-ok;} the indicated item
      */
     public Item get(int n) {
         return (Item) get0(n);
@@ -47,11 +47,11 @@
     /**
      * Sets the item at the given index.
      *
-     * @param n &gt;= 0, &lt; size(); which class
-     * @param innerClass non-null; class this item refers to
-     * @param outerClass null-ok; outer class that this class is a
+     * @param n {@code >= 0, < size();} which class
+     * @param innerClass {@code non-null;} class this item refers to
+     * @param outerClass {@code null-ok;} outer class that this class is a
      * member of, if any
-     * @param innerName null-ok; original simple name of this class,
+     * @param innerName {@code null-ok;} original simple name of this class,
      * if not anonymous
      * @param accessFlags original declared access flags
      */
@@ -64,13 +64,13 @@
      * Item in an inner classes list.
      */
     public static class Item {
-        /** non-null; class this item refers to */
+        /** {@code non-null;} class this item refers to */
         private final CstType innerClass;
 
-        /** null-ok; outer class that this class is a member of, if any */
+        /** {@code null-ok;} outer class that this class is a member of, if any */
         private final CstType outerClass;
 
-        /** null-ok; original simple name of this class, if not anonymous */
+        /** {@code null-ok;} original simple name of this class, if not anonymous */
         private final CstUtf8 innerName;
 
         /** original declared access flags */
@@ -79,10 +79,10 @@
         /**
          * Constructs an instance.
          *
-         * @param innerClass non-null; class this item refers to
-         * @param outerClass null-ok; outer class that this class is a
+         * @param innerClass {@code non-null;} class this item refers to
+         * @param outerClass {@code null-ok;} outer class that this class is a
          * member of, if any
-         * @param innerName null-ok; original simple name of this
+         * @param innerName {@code null-ok;} original simple name of this
          * class, if not anonymous
          * @param accessFlags original declared access flags
          */
@@ -101,7 +101,7 @@
         /**
          * Gets the class this item refers to.
          *
-         * @return non-null; the class
+         * @return {@code non-null;} the class
          */
         public CstType getInnerClass() {
             return innerClass;
@@ -110,7 +110,7 @@
         /**
          * Gets the outer class that this item's class is a member of, if any.
          *
-         * @return null-ok; the class
+         * @return {@code null-ok;} the class
          */
         public CstType getOuterClass() {
             return outerClass;
@@ -119,7 +119,7 @@
         /**
          * Gets the original name of this item's class, if not anonymous.
          *
-         * @return null-ok; the name
+         * @return {@code null-ok;} the name
          */
         public CstUtf8 getInnerName() {
             return innerName;
diff --git a/dx/src/com/android/dx/cf/attrib/RawAttribute.java b/dx/src/com/android/dx/cf/attrib/RawAttribute.java
index b89926d..585e5c5 100644
--- a/dx/src/com/android/dx/cf/attrib/RawAttribute.java
+++ b/dx/src/com/android/dx/cf/attrib/RawAttribute.java
@@ -23,11 +23,11 @@
  * Raw attribute, for holding onto attributes that are unrecognized.
  */
 public final class RawAttribute extends BaseAttribute {
-    /** non-null; attribute data */
+    /** {@code non-null;} attribute data */
     private final ByteArray data;
 
     /**
-     * null-ok; constant pool to use for resolution of cpis in {@link
+     * {@code null-ok;} constant pool to use for resolution of cpis in {@link
      * #data} 
      */
     private final ConstantPool pool;
@@ -35,9 +35,9 @@
     /**
      * Constructs an instance.
      * 
-     * @param name non-null; attribute name
-     * @param data non-null; attribute data
-     * @param pool null-ok; constant pool to use for cpi resolution
+     * @param name {@code non-null;} attribute name
+     * @param data {@code non-null;} attribute data
+     * @param pool {@code null-ok;} constant pool to use for cpi resolution
      */
     public RawAttribute(String name, ByteArray data, ConstantPool pool) {
         super(name);
@@ -53,11 +53,11 @@
     /**
      * Constructs an instance from a sub-array of a {@link ByteArray}.
      * 
-     * @param name non-null; attribute name
-     * @param data non-null; array containing the attribute data
-     * @param offset offset in <code>data</code> to the attribute data
+     * @param name {@code non-null;} attribute name
+     * @param data {@code non-null;} array containing the attribute data
+     * @param offset offset in {@code data} to the attribute data
      * @param length length of the attribute data, in bytes
-     * @param pool null-ok; constant pool to use for cpi resolution
+     * @param pool {@code null-ok;} constant pool to use for cpi resolution
      */
     public RawAttribute(String name, ByteArray data, int offset,
                         int length, ConstantPool pool) {
@@ -67,7 +67,7 @@
     /**
      * Get the raw data of the attribute.
      * 
-     * @return non-null; the data
+     * @return {@code non-null;} the data
      */
     public ByteArray getData() {
         return data;
@@ -83,7 +83,7 @@
      * presumably came from the class file that this attribute came
      * from.
      * 
-     * @return null-ok; the constant pool
+     * @return {@code null-ok;} the constant pool
      */
     public ConstantPool getPool() {
         return pool;
diff --git a/dx/src/com/android/dx/cf/code/BaseMachine.java b/dx/src/com/android/dx/cf/code/BaseMachine.java
index 430e48b..b7e700d 100644
--- a/dx/src/com/android/dx/cf/code/BaseMachine.java
+++ b/dx/src/com/android/dx/cf/code/BaseMachine.java
@@ -33,44 +33,44 @@
  * TypeBearer}.</p>
  */
 public abstract class BaseMachine implements Machine {
-    /* non-null; the prototype for the associated method */
+    /* {@code non-null;} the prototype for the associated method */
     private final Prototype prototype;
     
-    /** non-null; primary arguments */
+    /** {@code non-null;} primary arguments */
     private TypeBearer[] args;
 
-    /** &gt;= 0; number of primary arguments */
+    /** {@code >= 0;} number of primary arguments */
     private int argCount;
 
-    /** null-ok; type of the operation, if salient */
+    /** {@code null-ok;} type of the operation, if salient */
     private Type auxType;
 
-    /** auxiliary <code>int</code> argument */
+    /** auxiliary {@code int} argument */
     private int auxInt;
 
-    /** null-ok; auxiliary constant argument */
+    /** {@code null-ok;} auxiliary constant argument */
     private Constant auxCst;
 
     /** auxiliary branch target argument */
     private int auxTarget;
 
-    /** null-ok; auxiliary switch cases argument */
+    /** {@code null-ok;} auxiliary switch cases argument */
     private SwitchList auxCases;
 
-    /** null-ok; auxiliary initial value list for newarray */
+    /** {@code null-ok;} auxiliary initial value list for newarray */
     private ArrayList<Constant> auxInitValues;
 
-    /** &gt;= -1; last local accessed */
+    /** {@code >= -1;} last local accessed */
     private int localIndex;
 
-    /** null-ok; local target spec, if salient and calculated */
+    /** {@code null-ok;} local target spec, if salient and calculated */
     private RegisterSpec localTarget;
 
-    /** non-null; results */
+    /** {@code non-null;} results */
     private TypeBearer[] results;
 
     /**
-     * &gt;= -1; count of the results, or <code>-1</code> if no results
+     * {@code >= -1;} count of the results, or {@code -1} if no results
      * have been set
      */
     private int resultCount;
@@ -78,7 +78,7 @@
     /**
      * Constructs an instance.
      * 
-     * @param prototype non-null; the prototype for the associated method
+     * @param prototype {@code non-null;} the prototype for the associated method
      */
     public BaseMachine(Prototype prototype) {
         if (prototype == null) {
@@ -254,7 +254,7 @@
     /**
      * Gets the number of primary arguments.
      * 
-     * @return &gt;= 0; the number of primary arguments
+     * @return {@code >= 0;} the number of primary arguments
      */
     protected final int argCount() {
         return argCount;
@@ -264,7 +264,7 @@
      * Gets the width of the arguments (where a category-2 value counts as
      * two).
      * 
-     * @return &gt;= 0; the argument width
+     * @return {@code >= 0;} the argument width
      */
     protected final int argWidth() {
         int result = 0;
@@ -277,10 +277,10 @@
     }
 
     /**
-     * Gets the <code>n</code>th primary argument.
+     * Gets the {@code n}th primary argument.
      * 
-     * @param n &gt;= 0, &lt; argCount(); which argument
-     * @return non-null; the indicated argument
+     * @param n {@code >= 0, < argCount();} which argument
+     * @return {@code non-null;} the indicated argument
      */
     protected final TypeBearer arg(int n) {
         if (n >= argCount) {
@@ -298,14 +298,14 @@
     /**
      * Gets the type auxiliary argument.
      * 
-     * @return null-ok; the salient type
+     * @return {@code null-ok;} the salient type
      */
     protected final Type getAuxType() {
         return auxType;
     }
 
     /**
-     * Gets the <code>int</code> auxiliary argument.
+     * Gets the {@code int} auxiliary argument.
      * 
      * @return the argument value
      */
@@ -316,7 +316,7 @@
     /**
      * Gets the constant auxiliary argument.
      * 
-     * @return null-ok; the argument value
+     * @return {@code null-ok;} the argument value
      */
     protected final Constant getAuxCst() {
         return auxCst;
@@ -334,7 +334,7 @@
     /**
      * Gets the switch cases auxiliary argument.
      * 
-     * @return null-ok; the argument value
+     * @return {@code null-ok;} the argument value
      */
     protected final SwitchList getAuxCases() {
         return auxCases;
@@ -343,7 +343,7 @@
     /**
      * Gets the init values auxiliary argument.
      *
-     * @return null-ok; the argument value
+     * @return {@code null-ok;} the argument value
      */
     protected final ArrayList<Constant> getInitValues() {
         return auxInitValues;
@@ -351,7 +351,7 @@
     /**
      * Gets the last local index accessed.
      * 
-     * @return &gt;= -1; the salient local index or <code>-1</code> if none
+     * @return {@code >= -1;} the salient local index or {@code -1} if none
      * was set since the last time {@link #clearArgs} was called
      */
     protected final int getLocalIndex() {
@@ -365,7 +365,7 @@
      * should be the sole result set by a call to {@link #setResult} (or
      * the combination {@link #clearResult} then {@link #addResult}.
      * 
-     * @return null-ok; the salient register spec or <code>null</code> if no
+     * @return {@code null-ok;} the salient register spec or {@code null} if no
      * local target was set since the last time {@link #clearArgs} was
      * called
      */
@@ -417,7 +417,7 @@
      * <p><b>Note:</b> If there is more than one result value, the
      * others may be added by using {@link #addResult}.</p>
      * 
-     * @param result non-null; result value
+     * @param result {@code non-null;} result value
      */
     protected final void setResult(TypeBearer result) {
         if (result == null) {
@@ -433,7 +433,7 @@
      * 
      * @see #setResult
      * 
-     * @param result non-null; result value
+     * @param result {@code non-null;} result value
      */
     protected final void addResult(TypeBearer result) {
         if (result == null) {
@@ -448,7 +448,7 @@
      * Gets the count of results. This throws an exception if results were
      * never set. (Explicitly clearing the results counts as setting them.)
      * 
-     * @return &gt;= 0; the count
+     * @return {@code >= 0;} the count
      */
     protected final int resultCount() {
         if (resultCount < 0) {
@@ -462,7 +462,7 @@
      * Gets the width of the results (where a category-2 value counts as
      * two).
      * 
-     * @return &gt;= 0; the result width
+     * @return {@code >= 0;} the result width
      */
     protected final int resultWidth() {
         int width = 0;
@@ -475,10 +475,10 @@
     }
 
     /**
-     * Gets the <code>n</code>th result value.
+     * Gets the {@code n}th result value.
      * 
-     * @param n &gt;= 0, &lt; resultCount(); which result
-     * @return non-null; the indicated result value
+     * @param n {@code >= 0, < resultCount();} which result
+     * @return {@code non-null;} the indicated result value
      */
     protected final TypeBearer result(int n) {
         if (n >= resultCount) {
@@ -499,7 +499,7 @@
      * result is stored to that target; otherwise any results are pushed
      * onto the stack.
      * 
-     * @param frame non-null; frame to operate on
+     * @param frame {@code non-null;} frame to operate on
      */
     protected final void storeResults(Frame frame) {
         if (resultCount < 0) {
@@ -529,8 +529,8 @@
      * Throws an exception that indicates a mismatch in local variable
      * types.
      * 
-     * @param found non-null; the encountered type
-     * @param local non-null; the local variable's claimed type
+     * @param found {@code non-null;} the encountered type
+     * @param local {@code non-null;} the local variable's claimed type
      */
     public static void throwLocalMismatch(TypeBearer found,
             TypeBearer local) {
diff --git a/dx/src/com/android/dx/cf/code/BasicBlocker.java b/dx/src/com/android/dx/cf/code/BasicBlocker.java
index 82e4a08..d67e525 100644
--- a/dx/src/com/android/dx/cf/code/BasicBlocker.java
+++ b/dx/src/com/android/dx/cf/code/BasicBlocker.java
@@ -29,33 +29,37 @@
  * Utility that identifies basic blocks in bytecode.
  */
 public final class BasicBlocker implements BytecodeArray.Visitor {
-    /** non-null; method being converted */
+    /** {@code non-null;} method being converted */
     private final ConcreteMethod method;
 
-    /** non-null; work set; bits indicate offsets in need of examination */
+    /**
+     * {@code non-null;} work set; bits indicate offsets in need of
+     * examination
+     */
     private final int[] workSet;
 
     /**
-     * non-null; live set; bits indicate potentially-live opcodes; contrawise,
-     * a bit that isn't on is either in the middle of an instruction or is
-     * a definitely-dead opcode 
+     * {@code non-null;} live set; bits indicate potentially-live
+     * opcodes; contrawise, a bit that isn't on is either in the
+     * middle of an instruction or is a definitely-dead opcode
      */
     private final int[] liveSet;
 
     /**
-     * non-null; block start set; bits indicate the starts of basic blocks,
-     * including the opcodes that start blocks of definitely-dead code 
+     * {@code non-null;} block start set; bits indicate the starts of
+     * basic blocks, including the opcodes that start blocks of
+     * definitely-dead code
      */
     private final int[] blockSet;
 
     /**
-     * non-null, sparse; for each instruction offset to a branch of
+     * {@code non-null, sparse;} for each instruction offset to a branch of
      * some sort, the list of targets for that instruction 
      */
     private final IntList[] targetLists;
 
     /**
-     * non-null, sparse; for each instruction offset to a throwing
+     * {@code non-null, sparse;} for each instruction offset to a throwing
      * instruction, the list of exception handlers for that instruction 
      */
     private final ByteCatchList[] catchLists;
@@ -68,8 +72,8 @@
      * returning a list of them. The returned list notably omits any
      * definitely-dead code that is identified in the process.
      * 
-     * @param method non-null; method to convert
-     * @return non-null; list of basic blocks
+     * @param method {@code non-null;} method to convert
+     * @return {@code non-null;} list of basic blocks
      */
     public static ByteBlockList identifyBlocks(ConcreteMethod method) {
         BasicBlocker bb = new BasicBlocker(method);
@@ -82,7 +86,7 @@
      * Constructs an instance. This class is not publicly instantiable; use
      * {@link #identifyBlocks}.
      * 
-     * @param method non-null; method to convert
+     * @param method {@code non-null;} method to convert
      */
     private BasicBlocker(ConcreteMethod method) {
         if (method == null) {
@@ -262,10 +266,9 @@
     /**
      * Extracts the list of basic blocks from the bit sets.
      * 
-     * @return non-null; the list of basic blocks
+     * @return {@code non-null;} the list of basic blocks
      */
     private ByteBlockList getBlockList() {
-        ByteCatchList catches = method.getCatches();
         BytecodeArray bytes = method.getCode();
         ByteBlock[] bbs = new ByteBlock[bytes.size()];
         int count = 0;
@@ -366,7 +369,7 @@
      * isn't yet known to be possibly-live.
      * 
      * @param offset offset to the instruction in question
-     * @param blockStart <code>true</code> iff this instruction starts a
+     * @param blockStart {@code true} iff this instruction starts a
      * basic block
      */
     private void addWorkIfNecessary(int offset, boolean blockStart) {
@@ -384,7 +387,7 @@
      * 
      * @param offset offset to the instruction
      * @param length length of the instruction, in bytes
-     * @param nextIsLive <code>true</code> iff the instruction after
+     * @param nextIsLive {@code true} iff the instruction after
      * the indicated one is possibly-live (because this one isn't an
      * unconditional branch, a return, or a switch)
      */
@@ -417,7 +420,7 @@
      * 
      * @param offset offset to the instruction
      * @param length length of the instruction, in bytes
-     * @param nextIsLive <code>true</code> iff the instruction after
+     * @param nextIsLive {@code true} iff the instruction after
      * the indicated one is possibly-live (because this one isn't an
      * unconditional throw)
      */
diff --git a/dx/src/com/android/dx/cf/code/ByteBlock.java b/dx/src/com/android/dx/cf/code/ByteBlock.java
index 065c522..40b91c3 100644
--- a/dx/src/com/android/dx/cf/code/ByteBlock.java
+++ b/dx/src/com/android/dx/cf/code/ByteBlock.java
@@ -24,32 +24,32 @@
  * Representation of a basic block in a bytecode array.
  */
 public final class ByteBlock implements LabeledItem {
-    /** &gt;= 0; label for this block */
+    /** {@code >= 0;} label for this block */
     private final int label;
 
-    /** &gt;= 0; bytecode offset (inclusive) of the start of the block */
+    /** {@code >= 0;} bytecode offset (inclusive) of the start of the block */
     private final int start;
 
-    /** &gt; start; bytecode offset (exclusive) of the end of the block */
+    /** {@code > start;} bytecode offset (exclusive) of the end of the block */
     private final int end;
 
-    /** non-null; list of successors that this block may branch to */
+    /** {@code non-null;} list of successors that this block may branch to */
     private final IntList successors;
 
-    /** non-null; list of exceptions caught and their handler targets */
+    /** {@code non-null;} list of exceptions caught and their handler targets */
     private final ByteCatchList catches;
 
     /**
      * Constructs an instance. 
      * 
-     * @param label &gt;= 0; target label for this block
-     * @param start &gt;= 0; bytecode offset (inclusive) of the start
+     * @param label {@code >= 0;} target label for this block
+     * @param start {@code >= 0;} bytecode offset (inclusive) of the start
      * of the block
-     * @param end &gt; start; bytecode offset (exclusive) of the end
+     * @param end {@code > start;} bytecode offset (exclusive) of the end
      * of the block
-     * @param successors non-null; list of successors that this block may
+     * @param successors {@code non-null;} list of successors that this block may
      * branch to
-     * @param catches non-null; list of exceptions caught and their
+     * @param catches {@code non-null;} list of exceptions caught and their
      * handler targets
      */
     public ByteBlock(int label, int start, int end, IntList successors,
@@ -100,7 +100,7 @@
     /**
      * Gets the label of this block.
      * 
-     * @return &gt;= 0; the label
+     * @return {@code >= 0;} the label
      */
     public int getLabel() {
         return label;
@@ -109,7 +109,7 @@
     /**
      * Gets the bytecode offset (inclusive) of the start of this block.
      * 
-     * @return &gt;= 0; the start offset
+     * @return {@code >= 0;} the start offset
      */
     public int getStart() {
         return start;
@@ -118,7 +118,7 @@
     /**
      * Gets the bytecode offset (exclusive) of the end of this block.
      * 
-     * @return &gt; getStart(); the end offset
+     * @return {@code > getStart();} the end offset
      */
     public int getEnd() {
         return end;
@@ -128,7 +128,7 @@
      * Gets the list of successors that this block may branch to 
      * non-exceptionally.
      * 
-     * @return non-null; the successor list
+     * @return {@code non-null;} the successor list
      */
     public IntList getSuccessors() {
         return successors;
@@ -137,7 +137,7 @@
     /**
      * Gets the list of exceptions caught and their handler targets.
      * 
-     * @return non-null; the catch list
+     * @return {@code non-null;} the catch list
      */
     public ByteCatchList getCatches() {
         return catches;
diff --git a/dx/src/com/android/dx/cf/code/ByteBlockList.java b/dx/src/com/android/dx/cf/code/ByteBlockList.java
index 9d27b7f..412dfc3 100644
--- a/dx/src/com/android/dx/cf/code/ByteBlockList.java
+++ b/dx/src/com/android/dx/cf/code/ByteBlockList.java
@@ -28,7 +28,7 @@
     /**
      * Constructs an instance.
      *
-     * @param size &gt;= 0; the number of elements to be in the list
+     * @param size {@code >= 0;} the number of elements to be in the list
      */
     public ByteBlockList(int size) {
         super(size);
@@ -37,10 +37,10 @@
     /**
      * Gets the indicated element. It is an error to call this with the
      * index for an element which was never set; if you do that, this
-     * will throw <code>NullPointerException</code>.
+     * will throw {@code NullPointerException}.
      *
-     * @param n &gt;= 0, &lt; size(); which element
-     * @return non-null; the indicated element
+     * @param n {@code >= 0, < size();} which element
+     * @return {@code non-null;} the indicated element
      */
     public ByteBlock get(int n) {
         return (ByteBlock) get0(n);
@@ -50,7 +50,7 @@
      * Gets the block with the given label.
      *
      * @param label the label to look for
-     * @return non-null; the block with the given label
+     * @return {@code non-null;} the block with the given label
      */
     public ByteBlock labelToBlock(int label) {
         int idx = indexOfLabel(label);
@@ -66,8 +66,8 @@
     /**
      * Sets the element at the given index.
      *
-     * @param n &gt;= 0, &lt; size(); which element
-     * @param bb null-ok; the value to store
+     * @param n {@code >= 0, < size();} which element
+     * @param bb {@code null-ok;} the value to store
      */
     public void set(int n, ByteBlock bb) {
         super.set(n, bb);
diff --git a/dx/src/com/android/dx/cf/code/ByteCatchList.java b/dx/src/com/android/dx/cf/code/ByteCatchList.java
index 375831e..aab2087 100644
--- a/dx/src/com/android/dx/cf/code/ByteCatchList.java
+++ b/dx/src/com/android/dx/cf/code/ByteCatchList.java
@@ -24,10 +24,10 @@
 
 /**
  * List of catch entries, that is, the elements of an "exception table,"
- * which is part of a standard <code>Code</code> attribute.
+ * which is part of a standard {@code Code} attribute.
  */
 public final class ByteCatchList extends FixedSizeList {
-    /** non-null; convenient zero-entry instance */
+    /** {@code non-null;} convenient zero-entry instance */
     public static final ByteCatchList EMPTY = new ByteCatchList(0);
 
     /**
@@ -41,10 +41,10 @@
 
     /**
      * Gets the total length of this structure in bytes, when included in
-     * a <code>Code</code> attribute. The returned value includes the
-     * two bytes for <code>exception_table_length</code>.
+     * a {@code Code} attribute. The returned value includes the
+     * two bytes for {@code exception_table_length}.
      *
-     * @return &gt;= 2; the total length, in bytes
+     * @return {@code >= 2;} the total length, in bytes
      */
     public int byteLength() {
         return 2 + size() * 8;
@@ -53,8 +53,8 @@
     /**
      * Gets the indicated item.
      *
-     * @param n &gt;= 0; which item
-     * @return null-ok; the indicated item
+     * @param n {@code >= 0;} which item
+     * @return {@code null-ok;} the indicated item
      */
     public Item get(int n) {
         return (Item) get0(n);
@@ -63,8 +63,8 @@
     /**
      * Sets the item at the given index.
      *
-     * @param n &gt;= 0, &lt; size(); which entry to set
-     * @param item non-null; the item
+     * @param n {@code >= 0, < size();} which entry to set
+     * @param item {@code non-null;} the item
      */
     public void set(int n, Item item) {
         if (item == null) {
@@ -77,13 +77,13 @@
     /**
      * Sets the item at the given index.
      *
-     * @param n &gt;= 0, &lt; size(); which entry to set
-     * @param startPc &gt;= 0; the start pc (inclusive) of the handler's range
-     * @param endPc &gt;= startPc; the end pc (exclusive) of the
+     * @param n {@code >= 0, < size();} which entry to set
+     * @param startPc {@code >= 0;} the start pc (inclusive) of the handler's range
+     * @param endPc {@code >= startPc;} the end pc (exclusive) of the
      * handler's range
-     * @param handlerPc &gt;= 0; the pc of the exception handler
-     * @param exceptionClass null-ok; the exception class or
-     * <code>null</code> to catch all exceptions with this handler
+     * @param handlerPc {@code >= 0;} the pc of the exception handler
+     * @param exceptionClass {@code null-ok;} the exception class or
+     * {@code null} to catch all exceptions with this handler
      */
     public void set(int n, int startPc, int endPc, int handlerPc,
             CstType exceptionClass) {
@@ -95,8 +95,8 @@
      * automatically made immutable.
      *
      * @param pc which address
-     * @return non-null; list of exception handlers active at
-     * <code>pc</code>
+     * @return {@code non-null;} list of exception handlers active at
+     * {@code pc}
      */
     public ByteCatchList listFor(int pc) {
         int sz = size();
@@ -128,12 +128,12 @@
      * Helper method for {@link #listFor}, which tells whether a match
      * is <i>not</i> found for the exception type of the given item in
      * the given array. A match is considered to be either an exact type
-     * match or the class <code>Object</code> which represents a catch-all.
+     * match or the class {@code Object} which represents a catch-all.
      * 
-     * @param item non-null; item with the exception type to look for
-     * @param arr non-null; array to search in
-     * @param count non-null; maximum number of elements in the array to check
-     * @return <code>true</code> iff the exception type is <i>not</i> found
+     * @param item {@code non-null;} item with the exception type to look for
+     * @param arr {@code non-null;} array to search in
+     * @param count {@code non-null;} maximum number of elements in the array to check
+     * @return {@code true} iff the exception type is <i>not</i> found
      */
     private static boolean typeNotFound(Item item, Item[] arr, int count) {
         CstType type = item.getExceptionClass();
@@ -151,13 +151,13 @@
     /**
      * Returns a target list corresponding to this instance. The result
      * is a list of all the exception handler addresses, with the given
-     * <code>noException</code> address appended if appropriate. The
+     * {@code noException} address appended if appropriate. The
      * result is automatically made immutable.
      * 
-     * @param noException &gt;= -1; the no-exception address to append, or
-     * <code>-1</code> not to append anything
-     * @return non-null; list of exception targets, with
-     * <code>noException</code> appended if necessary
+     * @param noException {@code >= -1;} the no-exception address to append, or
+     * {@code -1} not to append anything
+     * @return {@code non-null;} list of exception targets, with
+     * {@code noException} appended if necessary
      */
     public IntList toTargetList(int noException) {
         if (noException < -1) {
@@ -199,7 +199,7 @@
     /**
      * Returns a rop-style catches list equivalent to this one.
      *
-     * @return non-null; the converted instance
+     * @return {@code non-null;} the converted instance
      */
     public TypeList toRopCatchList() {
         int sz = size();
@@ -221,29 +221,29 @@
      * Item in an exception handler list.
      */
     public static class Item {
-        /** &gt;= 0; the start pc (inclusive) of the handler's range */
+        /** {@code >= 0;} the start pc (inclusive) of the handler's range */
         private final int startPc;
 
-        /** &gt;= startPc; the end pc (exclusive) of the handler's range */
+        /** {@code >= startPc;} the end pc (exclusive) of the handler's range */
         private final int endPc;
 
-        /** &gt;= 0; the pc of the exception handler */
+        /** {@code >= 0;} the pc of the exception handler */
         private final int handlerPc;
 
-        /** null-ok; the exception class or <code>null</code> to catch all
+        /** {@code null-ok;} the exception class or {@code null} to catch all
          * exceptions with this handler */
         private final CstType exceptionClass;
 
         /**
          * Constructs an instance.
          *
-         * @param startPc &gt;= 0; the start pc (inclusive) of the
+         * @param startPc {@code >= 0;} the start pc (inclusive) of the
          * handler's range
-         * @param endPc &gt;= startPc; the end pc (exclusive) of the
+         * @param endPc {@code >= startPc;} the end pc (exclusive) of the
          * handler's range
-         * @param handlerPc &gt;= 0; the pc of the exception handler
-         * @param exceptionClass null-ok; the exception class or
-         * <code>null</code> to catch all exceptions with this handler
+         * @param handlerPc {@code >= 0;} the pc of the exception handler
+         * @param exceptionClass {@code null-ok;} the exception class or
+         * {@code null} to catch all exceptions with this handler
          */
         public Item(int startPc, int endPc, int handlerPc,
                 CstType exceptionClass) {
@@ -268,7 +268,7 @@
         /**
          * Gets the start pc (inclusive) of the handler's range.
          *
-         * @return &gt;= 0; the start pc (inclusive) of the handler's range.
+         * @return {@code >= 0;} the start pc (inclusive) of the handler's range.
          */
         public int getStartPc() {
             return startPc;
@@ -277,7 +277,7 @@
         /**
          * Gets the end pc (exclusive) of the handler's range.
          *
-         * @return &gt;= startPc; the end pc (exclusive) of the
+         * @return {@code >= startPc;} the end pc (exclusive) of the
          * handler's range.
          */
         public int getEndPc() {
@@ -287,7 +287,7 @@
         /**
          * Gets the pc of the exception handler.
          *
-         * @return &gt;= 0; the pc of the exception handler
+         * @return {@code >= 0;} the pc of the exception handler
          */
         public int getHandlerPc() {
             return handlerPc;
@@ -296,7 +296,7 @@
         /**
          * Gets the class of exception handled.
          *
-         * @return non-null; the exception class; {@link CstType#OBJECT}
+         * @return {@code non-null;} the exception class; {@link CstType#OBJECT}
          * if this entry handles all possible exceptions
          */
         public CstType getExceptionClass() {
@@ -308,7 +308,7 @@
          * Returns whether the given address is in the range of this item.
          *
          * @param pc the address
-         * @return <code>true</code> iff this item covers <code>pc</code>
+         * @return {@code true} iff this item covers {@code pc}
          */
         public boolean covers(int pc) {
             return (pc >= startPc) && (pc < endPc);
diff --git a/dx/src/com/android/dx/cf/code/ByteOps.java b/dx/src/com/android/dx/cf/code/ByteOps.java
index 4c420f6..ea7b514 100644
--- a/dx/src/com/android/dx/cf/code/ByteOps.java
+++ b/dx/src/com/android/dx/cf/code/ByteOps.java
@@ -242,114 +242,114 @@
     /** invalid */
     public static final int FMT_INVALID = 0;
 
-    /** "-": <code>op</code> */
+    /** "-": {@code op} */
     public static final int FMT_NO_ARGS = 1;
 
-    /** "0": <code>op</code>; implies <code>max_locals &gt;= 1</code> */
+    /** "0": {@code op}; implies {@code max_locals >= 1} */
     public static final int FMT_NO_ARGS_LOCALS_1 = 2;
 
-    /** "1": <code>op</code>; implies <code>max_locals &gt;= 2</code> */
+    /** "1": {@code op}; implies {@code max_locals >= 2} */
     public static final int FMT_NO_ARGS_LOCALS_2 = 3;
 
-    /** "2": <code>op</code>; implies <code>max_locals &gt;= 3</code> */
+    /** "2": {@code op}; implies {@code max_locals >= 3} */
     public static final int FMT_NO_ARGS_LOCALS_3 = 4;
 
-    /** "3": <code>op</code>; implies <code>max_locals &gt;= 4</code> */
+    /** "3": {@code op}; implies {@code max_locals >= 4} */
     public static final int FMT_NO_ARGS_LOCALS_4 = 5;
 
-    /** "4": <code>op</code>; implies <code>max_locals &gt;= 5</code> */
+    /** "4": {@code op}; implies {@code max_locals >= 5} */
     public static final int FMT_NO_ARGS_LOCALS_5 = 6;
 
-    /** "b": <code>op target target</code> */
+    /** "b": {@code op target target} */
     public static final int FMT_BRANCH = 7;
 
-    /** "c": <code>op target target target target</code> */
+    /** "c": {@code op target target target target} */
     public static final int FMT_WIDE_BRANCH = 8;
 
-    /** "p": <code>op #cpi #cpi</code>; constant restricted as specified */
+    /** "p": {@code op #cpi #cpi}; constant restricted as specified */
     public static final int FMT_CPI = 9;
 
     /**
-     * "l": <code>op local</code>; category-1 local; implies
-     * <code>max_locals</code> is at least two more than the given
+     * "l": {@code op local}; category-1 local; implies
+     * {@code max_locals} is at least two more than the given
      * local number 
      */
     public static final int FMT_LOCAL_1 = 10;
 
     /**
-     * "m": <code>op local</code>; category-2 local; implies
-     * <code>max_locals</code> is at least two more than the given
+     * "m": {@code op local}; category-2 local; implies
+     * {@code max_locals} is at least two more than the given
      * local number 
      */
     public static final int FMT_LOCAL_2 = 11;
 
     /**
-     * "y": <code>op #byte</code> (<code>bipush</code> and
-     * <code>newarray</code>) 
+     * "y": {@code op #byte} ({@code bipush} and
+     * {@code newarray}) 
      */
     public static final int FMT_LITERAL_BYTE = 12;
 
-    /** "I": <code>invokeinterface cpi cpi count 0</code> */
+    /** "I": {@code invokeinterface cpi cpi count 0} */
     public static final int FMT_INVOKEINTERFACE = 13;
 
-    /** "L": <code>ldc #cpi</code>; constant restricted as specified */
+    /** "L": {@code ldc #cpi}; constant restricted as specified */
     public static final int FMT_LDC = 14;
 
-    /** "S": <code>sipush #byte #byte</code> */
+    /** "S": {@code sipush #byte #byte} */
     public static final int FMT_SIPUSH = 15;
 
-    /** "T": <code>tableswitch ...</code> */
+    /** "T": {@code tableswitch ...} */
     public static final int FMT_TABLESWITCH = 16;
 
-    /** "U": <code>lookupswitch ...</code> */
+    /** "U": {@code lookupswitch ...} */
     public static final int FMT_LOOKUPSWITCH = 17;
 
-    /** "M": <code>multianewarray cpi cpi dims</code> */
+    /** "M": {@code multianewarray cpi cpi dims} */
     public static final int FMT_MULTIANEWARRAY = 18;
 
-    /** "W": <code>wide ...</code> */
+    /** "W": {@code wide ...} */
     public static final int FMT_WIDE = 19;
 
     /** mask for the bits representing the opcode format */
     public static final int FMT_MASK = 0x1f;
 
-    /** "I": flag bit for valid cp type for <code>Integer</code> */
+    /** "I": flag bit for valid cp type for {@code Integer} */
     public static final int CPOK_Integer = 0x20;
 
-    /** "F": flag bit for valid cp type for <code>Float</code> */
+    /** "F": flag bit for valid cp type for {@code Float} */
     public static final int CPOK_Float = 0x40;
 
-    /** "J": flag bit for valid cp type for <code>Long</code> */
+    /** "J": flag bit for valid cp type for {@code Long} */
     public static final int CPOK_Long = 0x80;
 
-    /** "D": flag bit for valid cp type for <code>Double</code> */
+    /** "D": flag bit for valid cp type for {@code Double} */
     public static final int CPOK_Double = 0x100;
 
-    /** "c": flag bit for valid cp type for <code>Class</code> */
+    /** "c": flag bit for valid cp type for {@code Class} */
     public static final int CPOK_Class = 0x200;
 
-    /** "s": flag bit for valid cp type for <code>String</code> */
+    /** "s": flag bit for valid cp type for {@code String} */
     public static final int CPOK_String = 0x400;
 
-    /** "f": flag bit for valid cp type for <code>Fieldref</code> */
+    /** "f": flag bit for valid cp type for {@code Fieldref} */
     public static final int CPOK_Fieldref = 0x800;
 
-    /** "m": flag bit for valid cp type for <code>Methodref</code> */
+    /** "m": flag bit for valid cp type for {@code Methodref} */
     public static final int CPOK_Methodref = 0x1000;
 
-    /** "i": flag bit for valid cp type for <code>InterfaceMethodref</code> */
+    /** "i": flag bit for valid cp type for {@code InterfaceMethodref} */
     public static final int CPOK_InterfaceMethodref = 0x2000;
 
     /**
-     * non-null; map from opcodes to format or'ed with allowed constant
+     * {@code non-null;} map from opcodes to format or'ed with allowed constant
      * pool types 
      */
     private static final int[] OPCODE_INFO = new int[256];
 
-    /** non-null; map from opcodes to their names */
+    /** {@code non-null;} map from opcodes to their names */
     private static final String[] OPCODE_NAMES = new String[256];
 
-    /** non-null; bigass string describing all the opcodes */
+    /** {@code non-null;} bigass string describing all the opcodes */
     private static final String OPCODE_DETAILS =
         "00 - nop;" +
         "01 - aconst_null;" +
@@ -623,8 +623,8 @@
     /**
      * Gets the name of the given opcode.
      * 
-     * @param opcode &gt;= 0, &lt;= 255; the opcode
-     * @return non-null; its name
+     * @param opcode {@code >= 0, <= 255;} the opcode
+     * @return {@code non-null;} its name
      */
     public static String opName(int opcode) {
         String result = OPCODE_NAMES[opcode];
@@ -640,7 +640,7 @@
     /**
      * Gets the format and allowed cp types of the given opcode.
      * 
-     * @param opcode &gt;= 0, &lt;= 255; the opcode
+     * @param opcode {@code >= 0, <= 255;} the opcode
      * @return its format and allowed cp types
      */
     public static int opInfo(int opcode) {
diff --git a/dx/src/com/android/dx/cf/code/BytecodeArray.java b/dx/src/com/android/dx/cf/code/BytecodeArray.java
index 71ba029..60f0cee 100644
--- a/dx/src/com/android/dx/cf/code/BytecodeArray.java
+++ b/dx/src/com/android/dx/cf/code/BytecodeArray.java
@@ -32,23 +32,23 @@
 import java.util.ArrayList;
 
 /**
- * Bytecode array, which is part of a standard <code>Code</code> attribute.
+ * Bytecode array, which is part of a standard {@code Code} attribute.
  */
 public final class BytecodeArray {
     /** convenient no-op implementation of {@link Visitor} */
     public static final Visitor EMPTY_VISITOR = new BaseVisitor();
 
-    /** non-null; underlying bytes */
+    /** {@code non-null;} underlying bytes */
     private final ByteArray bytes;
 
-    /** non-null; constant pool to use when resolving constant pool indices */
+    /** {@code non-null;} constant pool to use when resolving constant pool indices */
     private final ConstantPool pool;
 
     /**
      * Constructs an instance.
      * 
-     * @param bytes non-null; underlying bytes
-     * @param pool non-null; constant pool to use when resolving constant
+     * @param bytes {@code non-null;} underlying bytes
+     * @param pool {@code non-null;} constant pool to use when resolving constant
      * pool indices
      */
     public BytecodeArray(ByteArray bytes, ConstantPool pool) {
@@ -67,7 +67,7 @@
     /**
      * Gets the underlying byte array.
      * 
-     * @return non-null; the byte array
+     * @return {@code non-null;} the byte array
      */
     public ByteArray getBytes() {
         return bytes;
@@ -76,7 +76,7 @@
     /**
      * Gets the size of the bytecode array, per se.
      * 
-     * @return &gt;= 0; the length of the bytecode array
+     * @return {@code >= 0;} the length of the bytecode array
      */
     public int size() {
         return bytes.size();
@@ -84,10 +84,10 @@
 
     /**
      * Gets the total length of this structure in bytes, when included in
-     * a <code>Code</code> attribute. The returned value includes the
-     * array size plus four bytes for <code>code_length</code>.
+     * a {@code Code} attribute. The returned value includes the
+     * array size plus four bytes for {@code code_length}.
      * 
-     * @return &gt;= 4; the total length, in bytes
+     * @return {@code >= 4;} the total length, in bytes
      */
     public int byteLength() {
         return 4 + bytes.size();
@@ -96,7 +96,7 @@
     /**
      * Parses each instruction in the array, in order.
      * 
-     * @param visitor null-ok; visitor to call back to for each instruction
+     * @param visitor {@code null-ok;} visitor to call back to for each instruction
      */
     public void forEach(Visitor visitor) {
         int sz = bytes.size();
@@ -116,7 +116,7 @@
      * result is a bit set with the offset of each opcode-per-se flipped on.
      * 
      * @see Bits
-     * @return non-null; appropriately constructed bit set
+     * @return {@code non-null;} appropriately constructed bit set
      */
     public int[] getInstructionOffsets() {
         int sz = bytes.size();
@@ -139,8 +139,8 @@
      * work set is empty. It is expected that the visitor will regularly
      * set new bits in the work set during the process.
      * 
-     * @param workSet non-null; the work set to process
-     * @param visitor non-null; visitor to call back to for each instruction
+     * @param workSet {@code non-null;} the work set to process
+     * @param visitor {@code non-null;} visitor to call back to for each instruction
      */
     public void processWorkSet(int[] workSet, Visitor visitor) {
         if (visitor == null) {
@@ -170,42 +170,42 @@
      * 
      * <ul>
      * <li>The opcodes to push literal constants of primitive types all become
-     *   <code>ldc</code>.
-     *   E.g., <code>fconst_0</code>, <code>sipush</code>, and 
-     *   <code>lconst_0</code> qualify for this treatment.</li>
-     * <li><code>aconst_null</code> becomes <code>ldc</code> of a
+     *   {@code ldc}.
+     *   E.g., {@code fconst_0}, {@code sipush}, and 
+     *   {@code lconst_0} qualify for this treatment.</li>
+     * <li>{@code aconst_null} becomes {@code ldc} of a
      *   "known null."</li>
      * <li>Shorthand local variable accessors become the corresponding
-     *   longhand. E.g. <code>aload_2</code> becomes <code>aload</code>.</li>
-     * <li><code>goto_w</code> and <code>jsr_w</code> become <code>goto</code>
-     *   and <code>jsr</code> (respectively).</li>
-     * <li><code>ldc_w</code> becomes <code>ldc</code>.</li>
-     * <li><code>tableswitch</code> becomes <code>lookupswitch</code>.
+     *   longhand. E.g. {@code aload_2} becomes {@code aload}.</li>
+     * <li>{@code goto_w} and {@code jsr_w} become {@code goto}
+     *   and {@code jsr} (respectively).</li>
+     * <li>{@code ldc_w} becomes {@code ldc}.</li>
+     * <li>{@code tableswitch} becomes {@code lookupswitch}.
      * <li>Arithmetic, array, and value-returning ops are collapsed
-     *   to the <code>int</code> variant opcode, with the <code>type</code>
+     *   to the {@code int} variant opcode, with the {@code type}
      *   argument set to indicate the actual type. E.g.,
-     *   <code>fadd</code> becomes <code>iadd</code>, but
-     *   <code>type</code> is passed as <code>Type.FLOAT</code> in that
-     *   case. Similarly, <code>areturn</code> becomes
-     *   <code>ireturn</code>. (However, <code>return</code> remains
+     *   {@code fadd} becomes {@code iadd}, but
+     *   {@code type} is passed as {@code Type.FLOAT} in that
+     *   case. Similarly, {@code areturn} becomes
+     *   {@code ireturn}. (However, {@code return} remains
      *   unchanged.</li>
-     * <li>Local variable access ops are collapsed to the <code>int</code>
-     *   variant opcode, with the <code>type</code> argument set to indicate
-     *   the actual type. E.g., <code>aload</code> becomes <code>iload</code>,
-     *   but <code>type</code> is passed as <code>Type.OBJECT</code> in
+     * <li>Local variable access ops are collapsed to the {@code int}
+     *   variant opcode, with the {@code type} argument set to indicate
+     *   the actual type. E.g., {@code aload} becomes {@code iload},
+     *   but {@code type} is passed as {@code Type.OBJECT} in
      *   that case.</li>
-     * <li>Numeric conversion ops (<code>i2l</code>, etc.) are left alone
-     *   to avoid too much confustion, but their <code>type</code> is
-     *   the pushed type. E.g., <code>i2b</code> gets type
-     *   <code>Type.INT</code>, and <code>f2d</code> gets type
-     *   <code>Type.DOUBLE</code>. Other unaltered opcodes also get
-     *   their pushed type. E.g., <code>arraylength</code> gets type
-     *   <code>Type.INT</code>.</li>
+     * <li>Numeric conversion ops ({@code i2l}, etc.) are left alone
+     *   to avoid too much confustion, but their {@code type} is
+     *   the pushed type. E.g., {@code i2b} gets type
+     *   {@code Type.INT}, and {@code f2d} gets type
+     *   {@code Type.DOUBLE}. Other unaltered opcodes also get
+     *   their pushed type. E.g., {@code arraylength} gets type
+     *   {@code Type.INT}.</li>
      * </ul>
      * 
-     * @param offset &gt;= 0, &lt; bytes.size(); offset to the start of the
+     * @param offset {@code >= 0, < bytes.size();} offset to the start of the
      * instruction
-     * @param visitor null-ok; visitor to call back to
+     * @param visitor {@code null-ok;} visitor to call back to
      * @return the length of the instruction, in bytes
      */
     public int parseInstruction(int offset, Visitor visitor) {
@@ -797,10 +797,10 @@
     }
 
     /**
-     * Helper to deal with <code>tableswitch</code>.
+     * Helper to deal with {@code tableswitch}.
      * 
-     * @param offset the offset to the <code>tableswitch</code> opcode itself
-     * @param visitor non-null; visitor to use
+     * @param offset the offset to the {@code tableswitch} opcode itself
+     * @param visitor {@code non-null;} visitor to use
      * @return instruction length, in bytes
      */
     private int parseTableswitch(int offset, Visitor visitor) {
@@ -840,10 +840,10 @@
     }
 
     /**
-     * Helper to deal with <code>lookupswitch</code>.
+     * Helper to deal with {@code lookupswitch}.
      * 
-     * @param offset the offset to the <code>lookupswitch</code> opcode itself
-     * @param visitor non-null; visitor to use
+     * @param offset the offset to the {@code lookupswitch} opcode itself
+     * @param visitor {@code non-null;} visitor to use
      * @return instruction length, in bytes
      */
     private int parseLookupswitch(int offset, Visitor visitor) {
@@ -878,10 +878,10 @@
     }
 
     /**
-     * Helper to deal with <code>newarray</code>.
+     * Helper to deal with {@code newarray}.
      *
-     * @param offset the offset to the <code>newarray</code> opcode itself
-     * @param visitor non-null; visitor to use
+     * @param offset the offset to the {@code newarray} opcode itself
+     * @param visitor {@code non-null;} visitor to use
      * @return instruction length, in bytes
      */
     private int parseNewarray(int offset, Visitor visitor) {
@@ -1061,10 +1061,10 @@
 
     
     /**
-     * Helper to deal with <code>wide</code>.
+     * Helper to deal with {@code wide}.
      * 
-     * @param offset the offset to the <code>wide</code> opcode itself
-     * @param visitor non-null; visitor to use
+     * @param offset the offset to the {@code wide} opcode itself
+     * @param visitor {@code non-null;} visitor to use
      * @return instruction length, in bytes
      */
     private int parseWide(int offset, Visitor visitor) {
@@ -1159,7 +1159,7 @@
          * @param opcode the opcode
          * @param offset offset to the instruction
          * @param length length of the instruction, in bytes
-         * @param type non-null; type the instruction operates on
+         * @param type {@code non-null;} type the instruction operates on
          */
         public void visitNoArgs(int opcode, int offset, int length,
                 Type type);
@@ -1171,9 +1171,9 @@
          * @param offset offset to the instruction
          * @param length length of the instruction, in bytes
          * @param idx the local variable index
-         * @param type non-null; the type of the accessed value
+         * @param type {@code non-null;} the type of the accessed value
          * @param value additional literal integer argument, if salient (i.e.,
-         * for <code>iinc</code>)
+         * for {@code iinc})
          */
         public void visitLocal(int opcode, int offset, int length,
                 int idx, Type type, int value);
@@ -1182,23 +1182,23 @@
          * Visits an instruction which has a (possibly synthetic)
          * constant argument, and possibly also an
          * additional literal integer argument. In the case of
-         * <code>multianewarray</code>, the argument is the count of
-         * dimensions. In the case of <code>invokeinterface</code>,
+         * {@code multianewarray}, the argument is the count of
+         * dimensions. In the case of {@code invokeinterface},
          * the argument is the parameter count or'ed with the
          * should-be-zero value left-shifted by 8. In the case of entries
-         * of type <code>int</code>, the <code>value</code> field always
+         * of type {@code int}, the {@code value} field always
          * holds the raw value (for convenience of clients).
          * 
          * <p><b>Note:</b> In order to avoid giving it a barely-useful
-         * visitor all its own, <code>newarray</code> also uses this
-         * form, passing <code>value</code> as the array type code and
-         * <code>cst</code> as a {@link CstType} instance
+         * visitor all its own, {@code newarray} also uses this
+         * form, passing {@code value} as the array type code and
+         * {@code cst} as a {@link CstType} instance
          * corresponding to the array type.</p>
          * 
          * @param opcode the opcode
          * @param offset offset to the instruction
          * @param length length of the instruction, in bytes
-         * @param cst non-null; the constant
+         * @param cst {@code non-null;} the constant
          * @param value additional literal integer argument, if salient
          * (ignore if not)
          */
@@ -1222,7 +1222,7 @@
          * @param opcode the opcode
          * @param offset offset to the instruction
          * @param length length of the instruction, in bytes
-         * @param cases non-null; list of (value, target) pairs, plus the
+         * @param cases {@code non-null;} list of (value, target) pairs, plus the
          * default target
          * @param padding the bytes found in the padding area (if any),
          * packed
@@ -1235,8 +1235,8 @@
          *
          * @param offset   offset to the instruction
          * @param length   length of the instruction, in bytes
-         * @param cst non-null; the type of the array
-         * @param initVals non-null; list of bytecode offsets for init values
+         * @param cst {@code non-null;} the type of the array
+         * @param initVals {@code non-null;} list of bytecode offsets for init values
          */
         public void visitNewarray(int offset, int length, CstType type,
                 ArrayList<Constant> initVals);
diff --git a/dx/src/com/android/dx/cf/code/ConcreteMethod.java b/dx/src/com/android/dx/cf/code/ConcreteMethod.java
index 47f698d..70b6b45 100644
--- a/dx/src/com/android/dx/cf/code/ConcreteMethod.java
+++ b/dx/src/com/android/dx/cf/code/ConcreteMethod.java
@@ -35,38 +35,38 @@
  * Container for all the giblets that make up a concrete Java bytecode method.
  * It implements {@link Method}, so it provides all the original access
  * (by delegation), but it also constructs and keeps useful versions of
- * stuff extracted from the method's <code>Code</code> attribute.
+ * stuff extracted from the method's {@code Code} attribute.
  */
 public final class ConcreteMethod implements Method {
-    /** non-null; method being wrapped */
+    /** {@code non-null;} method being wrapped */
     private final Method method;
 
     /**
-     * null-ok; the class's <code>SourceFile</code> attribute value,
+     * {@code null-ok;} the class's {@code SourceFile} attribute value,
      * if any 
      */
     private final CstUtf8 sourceFile;
 
     /**
      * whether the class that this method is part of is defined with
-     * <code>ACC_SUPER</code> 
+     * {@code ACC_SUPER} 
      */
     private final boolean accSuper;
 
-    /** non-null; the code attribute */
+    /** {@code non-null;} the code attribute */
     private final AttCode attCode;
 
-    /** non-null; line number list */
+    /** {@code non-null;} line number list */
     private final LineNumberList lineNumbers;
 
-    /** non-null; local variable list */
+    /** {@code non-null;} local variable list */
     private final LocalVariableList localVariables;
 
     /**
      * Constructs an instance.
      * 
-     * @param method non-null; the method to be based on
-     * @param cf non-null; the class file that contains this method
+     * @param method {@code non-null;} the method to be based on
+     * @param cf {@code non-null;} the class file that contains this method
      * @param keepLines whether to keep the line number information
      * (if any)
      * @param keepLocals whether to keep the local variable
@@ -178,9 +178,9 @@
 
     /**
      * Gets whether the class that this method is part of is defined with
-     * <code>ACC_SUPER</code>.
+     * {@code ACC_SUPER}.
      * 
-     * @return the <code>ACC_SUPER</code> value
+     * @return the {@code ACC_SUPER} value
      */
     public boolean getAccSuper() {
         return accSuper;
@@ -189,7 +189,7 @@
     /**
      * Gets the maximum stack size.
      * 
-     * @return &gt;= 0; the maximum stack size
+     * @return {@code >= 0;} the maximum stack size
      */
     public int getMaxStack() {
         return attCode.getMaxStack();
@@ -198,7 +198,7 @@
     /**
      * Gets the number of locals.
      * 
-     * @return &gt;= 0; the number of locals
+     * @return {@code >= 0;} the number of locals
      */
     public int getMaxLocals() {
         return attCode.getMaxLocals();
@@ -207,7 +207,7 @@
     /**
      * Gets the bytecode array.
      * 
-     * @return non-null; the bytecode array
+     * @return {@code non-null;} the bytecode array
      */
     public BytecodeArray getCode() {
         return attCode.getCode();
@@ -216,7 +216,7 @@
     /**
      * Gets the exception table.
      * 
-     * @return non-null; the exception table
+     * @return {@code non-null;} the exception table
      */
     public ByteCatchList getCatches() {
         return attCode.getCatches();
@@ -225,7 +225,7 @@
     /**
      * Gets the line number list.
      * 
-     * @return non-null; the line number list
+     * @return {@code non-null;} the line number list
      */
     public LineNumberList getLineNumbers() {
         return lineNumbers;
@@ -234,7 +234,7 @@
     /**
      * Gets the local variable list.
      * 
-     * @return non-null; the local variable list
+     * @return {@code non-null;} the local variable list
      */
     public LocalVariableList getLocalVariables() {
         return localVariables;
@@ -244,8 +244,8 @@
      * Returns a {@link SourcePosition} instance corresponding to the
      * given bytecode offset.
      * 
-     * @param offset &gt;= 0; the bytecode offset
-     * @return non-null; an appropriate instance
+     * @param offset {@code >= 0;} the bytecode offset
+     * @return {@code non-null;} an appropriate instance
      */
     public SourcePosition makeSourcePosistion(int offset) {
         return new SourcePosition(sourceFile, offset,
diff --git a/dx/src/com/android/dx/cf/code/ExecutionStack.java b/dx/src/com/android/dx/cf/code/ExecutionStack.java
index 1a2b565..15a9e6c 100644
--- a/dx/src/com/android/dx/cf/code/ExecutionStack.java
+++ b/dx/src/com/android/dx/cf/code/ExecutionStack.java
@@ -30,11 +30,11 @@
  * TypeBearer}.</p>
  */
 public final class ExecutionStack extends MutabilityControl {
-    /** non-null; array of stack contents */
+    /** {@code non-null;} array of stack contents */
     private final TypeBearer[] stack;
 
     /**
-     * &gt;= 0; stack pointer (points one past the end) / current stack
+     * {@code >= 0;} stack pointer (points one past the end) / current stack
      * size 
      */
     private int stackPtr;
@@ -42,7 +42,7 @@
     /**
      * Constructs an instance. 
      * 
-     * @param maxStack &gt;= 0; the maximum size of the stack for this
+     * @param maxStack {@code >= 0;} the maximum size of the stack for this
      * instance
      */
     public ExecutionStack(int maxStack) {
@@ -54,7 +54,7 @@
     /**
      * Makes and returns a mutable copy of this instance.
      * 
-     * @return non-null; the copy
+     * @return {@code non-null;} the copy
      */
     public ExecutionStack copy() {
         ExecutionStack result = new ExecutionStack(stack.length);
@@ -69,7 +69,7 @@
      * Annotates (adds context to) the given exception with information
      * about this instance.
      * 
-     * @param ex non-null; the exception to annotate
+     * @param ex {@code non-null;} the exception to annotate
      */
     public void annotate(ExceptionWithContext ex) {
         int limit = stackPtr - 1;
@@ -86,7 +86,7 @@
      * Replaces all the occurrences of the given uninitialized type in
      * this stack with its initialized equivalent.
      * 
-     * @param type non-null; type to replace
+     * @param type {@code non-null;} type to replace
      */
     public void makeInitialized(Type type) {
         if (stackPtr == 0) {
@@ -108,7 +108,7 @@
     /**
      * Gets the maximum stack size for this instance.
      * 
-     * @return &gt;= 0; the max stack size
+     * @return {@code >= 0;} the max stack size
      */
     public int getMaxStack() {
         return stack.length;
@@ -117,7 +117,7 @@
     /**
      * Gets the current stack size.
      * 
-     * @return &gt;= 0, &lt; getMaxStack(); the current stack size
+     * @return {@code >= 0, < getMaxStack();} the current stack size
      */
     public int size() {
         return stackPtr;
@@ -139,7 +139,7 @@
     /**
      * Pushes a value of the given type onto the stack.
      * 
-     * @param type non-null; type of the value
+     * @param type {@code non-null;} type of the value
      * @throws SimException thrown if there is insufficient room on the
      * stack for the value
      */
@@ -171,14 +171,14 @@
     }
 
     /**
-     * Peeks at the <code>n</code>th element down from the top of the stack.
-     * <code>n == 0</code> means to peek at the top of the stack. Note that
-     * this will return <code>null</code> if the indicated element is the
+     * Peeks at the {@code n}th element down from the top of the stack.
+     * {@code n == 0} means to peek at the top of the stack. Note that
+     * this will return {@code null} if the indicated element is the
      * deeper half of a category-2 value.
      * 
-     * @param n &gt;= 0; which element to peek at
-     * @return null-ok; the type of value stored at that element
-     * @throws SimException thrown if <code>n &gt;= size()</code> 
+     * @param n {@code >= 0;} which element to peek at
+     * @return {@code null-ok;} the type of value stored at that element
+     * @throws SimException thrown if {@code n >= size()} 
      */
     public TypeBearer peek(int n) {
         if (n < 0) {
@@ -193,10 +193,10 @@
     }
 
     /**
-     * Peeks at the <code>n</code>th element down from the top of the
+     * Peeks at the {@code n}th element down from the top of the
      * stack, returning the type per se, as opposed to the
      * <i>type-bearer</i>.  This method is just a convenient shorthand
-     * for <code>peek(n).getType()</code>.
+     * for {@code peek(n).getType()}.
      * 
      * @see #peek
      */
@@ -207,7 +207,7 @@
     /**
      * Pops the top element off of the stack.
      * 
-     * @return non-null; the type formerly on the top of the stack
+     * @return {@code non-null;} the type formerly on the top of the stack
      * @throws SimException thrown if the stack is empty
      */
     public TypeBearer pop() {
@@ -227,10 +227,10 @@
      * the following restriction on its behavior: You may only replace
      * values with other values of the same category.
      * 
-     * @param n &gt;= 0; which element to change, where <code>0</code> is
+     * @param n {@code >= 0;} which element to change, where {@code 0} is
      * the top element of the stack
-     * @param type non-null; type of the new value
-     * @throws SimException thrown if <code>n &gt;= size()</code> or
+     * @param type {@code non-null;} type of the new value
+     * @throws SimException thrown if {@code n >= size()} or
      * the action is otherwise prohibited
      */
     public void change(int n, TypeBearer type) {
@@ -262,8 +262,8 @@
      * returned.  See {@link Merger#mergeStack(ExecutionStack,ExecutionStack)
      * Merger.mergeStack()}
      *
-     * @param other non-null; a stack to merge with
-     * @return non-null; the result of the merge
+     * @param other {@code non-null;} a stack to merge with
+     * @return {@code non-null;} the result of the merge
      */
     public ExecutionStack merge(ExecutionStack other) {
         try {
@@ -279,11 +279,11 @@
 
     /**
      * Gets the string form for a stack element. This is the same as
-     * <code>toString()</code> except that <code>null</code> is converted
-     * to <code>"&lt;invalid&gt;"</code>.
+     * {@code toString()} except that {@code null} is converted
+     * to {@code "<invalid>"}.
      * 
-     * @param type null-ok; the stack element
-     * @return non-null; the string form
+     * @param type {@code null-ok;} the stack element
+     * @return {@code non-null;} the string form
      */
     private static String stackElementString(TypeBearer type) {
         if (type == null) {
@@ -296,7 +296,7 @@
     /**
      * Throws a properly-formatted exception.
      * 
-     * @param msg non-null; useful message
+     * @param msg {@code non-null;} useful message
      * @return never (keeps compiler happy)
      */
     private static TypeBearer throwSimException(String msg) {
diff --git a/dx/src/com/android/dx/cf/code/Frame.java b/dx/src/com/android/dx/cf/code/Frame.java
index a74d142..f345335 100644
--- a/dx/src/com/android/dx/cf/code/Frame.java
+++ b/dx/src/com/android/dx/cf/code/Frame.java
@@ -29,20 +29,20 @@
  * results" area.
  */
 public final class Frame {
-    /** non-null; the locals */
+    /** {@code non-null;} the locals */
     private final LocalsArray locals;
 
-    /** non-null; the stack */
+    /** {@code non-null;} the stack */
     private final ExecutionStack stack;
 
-    /** null-ok; stack of labels of subroutines that this block is nested in */
+    /** {@code null-ok;} stack of labels of subroutines that this block is nested in */
     private final IntList subroutines;
 
     /**
      * Constructs an instance.
      *
-     * @param locals non-null; the locals array to use
-     * @param stack non-null; the execution stack to use
+     * @param locals {@code non-null;} the locals array to use
+     * @param stack {@code non-null;} the execution stack to use
      */
     private Frame(LocalsArray locals, ExecutionStack stack) {
         this(locals, stack, IntList.EMPTY);
@@ -51,9 +51,9 @@
     /**
      * Constructs an instance.
      *
-     * @param locals non-null; the locals array to use
-     * @param stack non-null; the execution stack to use
-     * @param subroutines non-null; list of subroutine start labels for
+     * @param locals {@code non-null;} the locals array to use
+     * @param stack {@code non-null;} the execution stack to use
+     * @param subroutines {@code non-null;} list of subroutine start labels for
      * subroutines this frame is nested in
      */
     private Frame(LocalsArray locals,
@@ -75,12 +75,12 @@
 
     /**
      * Constructs an instance. The locals array initially consists of
-     * all-uninitialized values (represented as <code>null</code>s) and
+     * all-uninitialized values (represented as {@code null}s) and
      * the stack starts out empty.
      *
-     * @param maxLocals &gt;= 0; the maximum number of locals this instance
+     * @param maxLocals {@code >= 0;} the maximum number of locals this instance
      * can refer to
-     * @param maxStack &gt;= 0; the maximum size of the stack for this
+     * @param maxStack {@code >= 0;} the maximum size of the stack for this
      * instance
      */
     public Frame(int maxLocals, int maxStack) {
@@ -92,7 +92,7 @@
      * contains copies of the locals and stack (that is, it doesn't
      * share them with the original).
      *
-     * @return non-null; the copy
+     * @return {@code non-null;} the copy
      */
     public Frame copy() {
         return new Frame(locals.copy(), stack.copy(), subroutines);
@@ -111,7 +111,7 @@
      * Replaces all the occurrences of the given uninitialized type in
      * this frame with its initialized equivalent.
      *
-     * @param type non-null; type to replace
+     * @param type {@code non-null;} type to replace
      */
     public void makeInitialized(Type type) {
         locals.makeInitialized(type);
@@ -121,7 +121,7 @@
     /**
      * Gets the locals array for this instance.
      *
-     * @return non-null; the locals array
+     * @return {@code non-null;} the locals array
      */
     public LocalsArray getLocals() {
         return locals;
@@ -130,7 +130,7 @@
     /**
      * Gets the execution stack for this instance.
      *
-     * @return non-null; the execution stack
+     * @return {@code non-null;} the execution stack
      */
     public ExecutionStack getStack() {
         return stack;
@@ -143,7 +143,7 @@
      * list is ordered such that the deepest nesting (the actual subroutine
      * this block is in) is the last label in the list.
      *
-     * @return non-null; list as noted above
+     * @return {@code non-null;} list as noted above
      */
     public IntList getSubroutines() {
         return subroutines;
@@ -171,10 +171,10 @@
      * be used when returning from a subroutine. The stack state of all
      * subroutine invocations is identical, but the locals state may differ.
      *
-     * @param startLabel &gt;=0; The label of the returning subroutine's
+     * @param startLabel {@code >=0;} The label of the returning subroutine's
      * start block
-     * @param subLabel &gt;=0; A calling label of a subroutine
-     * @return null-ok; an appropriatly-constructed instance, or null
+     * @param subLabel {@code >=0;} A calling label of a subroutine
+     * @return {@code null-ok;} an appropriatly-constructed instance, or null
      * if label is not in the set
      */
     public Frame subFrameForLabel(int startLabel, int subLabel) {
@@ -206,8 +206,8 @@
      * Merges two frames. If the merged result is the same as this frame,
      * then this instance is returned.
      *
-     * @param other non-null; another frame
-     * @return non-null; the result of merging the two frames
+     * @param other {@code non-null;} another frame
+     * @return {@code non-null;} the result of merging the two frames
      */
     public Frame mergeWith(Frame other) {
         LocalsArray resultLocals;
@@ -237,7 +237,7 @@
      * 
      * @param otherSubroutines label list of subroutine start blocks, from
      * least-nested to most-nested.
-     * @return non-null; merged subroutine nest list as described above
+     * @return {@code non-null;} merged subroutine nest list as described above
      */
     private IntList mergeSubroutineLists(IntList otherSubroutines) {
         if (subroutines.equals(otherSubroutines)) {
@@ -265,10 +265,10 @@
      * need to be trimmed of all OneLocalsArray elements that relevent to
      * the subroutine that is returning.
      *
-     * @param locals non-null; LocalsArray from before a merge
-     * @param subroutines non-null; a label list of subroutine start blocks
+     * @param locals {@code non-null;} LocalsArray from before a merge
+     * @param subroutines {@code non-null;} a label list of subroutine start blocks
      * representing the subroutine nesting of the block being merged into.
-     * @return non-null; locals set appropriate for merge
+     * @return {@code non-null;} locals set appropriate for merge
      */
     private static LocalsArray adjustLocalsForSubroutines(
             LocalsArray locals, IntList subroutines) {
@@ -301,13 +301,13 @@
 
     /**
      * Merges this frame with the frame of a subroutine caller at
-     * <code>predLabel</code>. Only called on the frame at the first
+     * {@code predLabel}. Only called on the frame at the first
      * block of a subroutine.
      *
-     * @param other non-null; another frame
+     * @param other {@code non-null;} another frame
      * @param subLabel label of subroutine start block
      * @param predLabel label of calling block
-     * @return non-null; the result of merging the two frames
+     * @return {@code non-null;} the result of merging the two frames
      */
     public Frame mergeWithSubroutineCaller(Frame other, int subLabel,
             int predLabel) {
@@ -374,7 +374,7 @@
      * subroutine calls return.
      *
      * @param subLabel label of subroutine start block
-     * @param callerLabel &gt;=0 label of the caller block where this frame
+     * @param callerLabel {@code >=0;} label of the caller block where this frame
      * came from.
      * @return a new instance to begin a called subroutine.
      */
@@ -406,7 +406,7 @@
      * Annotates (adds context to) the given exception with information
      * about this frame.
      *
-     * @param ex non-null; the exception to annotate
+     * @param ex {@code non-null;} the exception to annotate
      */
     public void annotate(ExceptionWithContext ex) {
         locals.annotate(ex);
diff --git a/dx/src/com/android/dx/cf/code/LineNumberList.java b/dx/src/com/android/dx/cf/code/LineNumberList.java
index 35875b0..7af3f4e 100644
--- a/dx/src/com/android/dx/cf/code/LineNumberList.java
+++ b/dx/src/com/android/dx/cf/code/LineNumberList.java
@@ -20,19 +20,19 @@
 
 /**
  * List of "line number" entries, which are the contents of
- * <code>LineNumberTable</code> attributes.
+ * {@code LineNumberTable} attributes.
  */
 public final class LineNumberList extends FixedSizeList {
-    /** non-null; zero-size instance */
+    /** {@code non-null;} zero-size instance */
     public static final LineNumberList EMPTY = new LineNumberList(0);
 
     /**
      * Returns an instance which is the concatenation of the two given
      * instances.
      * 
-     * @param list1 non-null; first instance
-     * @param list2 non-null; second instance
-     * @return non-null; combined instance
+     * @param list1 {@code non-null;} first instance
+     * @param list2 {@code non-null;} second instance
+     * @return {@code non-null;} combined instance
      */
     public static LineNumberList concat(LineNumberList list1,
                                         LineNumberList list2) {
@@ -68,8 +68,8 @@
     /**
      * Gets the indicated item.
      * 
-     * @param n &gt;= 0; which item
-     * @return null-ok; the indicated item
+     * @param n {@code >= 0;} which item
+     * @return {@code null-ok;} the indicated item
      */
     public Item get(int n) {
         return (Item) get0(n);
@@ -78,8 +78,8 @@
     /**
      * Sets the item at the given index.
      * 
-     * @param n &gt;= 0, &lt; size(); which element
-     * @param item non-null; the item
+     * @param n {@code >= 0, < size();} which element
+     * @param item {@code non-null;} the item
      */
     public void set(int n, Item item) {
         if (item == null) {
@@ -92,9 +92,9 @@
     /**
      * Sets the item at the given index.
      * 
-     * @param n &gt;= 0, &lt; size(); which element
-     * @param startPc &gt;= 0; start pc of this item
-     * @param lineNumber &gt;= 0; corresponding line number
+     * @param n {@code >= 0, < size();} which element
+     * @param startPc {@code >= 0;} start pc of this item
+     * @param lineNumber {@code >= 0;} corresponding line number
      */
     public void set(int n, int startPc, int lineNumber) {
         set0(n, new Item(startPc, lineNumber));
@@ -103,8 +103,8 @@
     /**
      * Gets the line number associated with the given address.
      * 
-     * @param pc &gt;= 0; the address to look up
-     * @return &gt;= -1; the associated line number, or <code>-1</code> if
+     * @param pc {@code >= 0;} the address to look up
+     * @return {@code >= -1;} the associated line number, or {@code -1} if
      * none is known
      */
     public int pcToLine(int pc) {
@@ -138,17 +138,17 @@
      * Item in a line number table.
      */
     public static class Item {
-        /** &gt;= 0; start pc of this item */
+        /** {@code >= 0;} start pc of this item */
         private final int startPc;
 
-        /** &gt;= 0; corresponding line number */
+        /** {@code >= 0;} corresponding line number */
         private final int lineNumber;
 
         /**
          * Constructs an instance.
          * 
-         * @param startPc &gt;= 0; start pc of this item
-         * @param lineNumber &gt;= 0; corresponding line number
+         * @param startPc {@code >= 0;} start pc of this item
+         * @param lineNumber {@code >= 0;} corresponding line number
          */
         public Item(int startPc, int lineNumber) {
             if (startPc < 0) {
diff --git a/dx/src/com/android/dx/cf/code/LocalVariableList.java b/dx/src/com/android/dx/cf/code/LocalVariableList.java
index 1087603..8f49a33 100644
--- a/dx/src/com/android/dx/cf/code/LocalVariableList.java
+++ b/dx/src/com/android/dx/cf/code/LocalVariableList.java
@@ -23,20 +23,20 @@
 
 /**
  * List of "local variable" entries, which are the contents of
- * <code>LocalVariableTable</code> and <code>LocalVariableTypeTable</code>
+ * {@code LocalVariableTable} and {@code LocalVariableTypeTable}
  * attributes, as well as combinations of the two.
  */
 public final class LocalVariableList extends FixedSizeList {
-    /** non-null; zero-size instance */
+    /** {@code non-null;} zero-size instance */
     public static final LocalVariableList EMPTY = new LocalVariableList(0);
 
     /**
      * Returns an instance which is the concatenation of the two given
      * instances. The result is immutable.
      * 
-     * @param list1 non-null; first instance
-     * @param list2 non-null; second instance
-     * @return non-null; combined instance
+     * @param list1 {@code non-null;} first instance
+     * @param list2 {@code non-null;} second instance
+     * @return {@code non-null;} combined instance
      */
     public static LocalVariableList concat(LocalVariableList list1,
                                            LocalVariableList list2) {
@@ -70,14 +70,13 @@
      * element in the signature list gets augmented with the
      * corresponding signature. The result is immutable.
      * 
-     * @param descriptorList non-null; list with descriptors
-     * @param signatureList non-null; list with signatures
-     * @return non-null; the merged result
+     * @param descriptorList {@code non-null;} list with descriptors
+     * @param signatureList {@code non-null;} list with signatures
+     * @return {@code non-null;} the merged result
      */
     public static LocalVariableList mergeDescriptorsAndSignatures(
             LocalVariableList descriptorList,
             LocalVariableList signatureList) {
-        int signatureSize = signatureList.size();
         int descriptorSize = descriptorList.size();
         LocalVariableList result = new LocalVariableList(descriptorSize);
 
@@ -107,8 +106,8 @@
     /**
      * Gets the indicated item.
      * 
-     * @param n &gt;= 0; which item
-     * @return null-ok; the indicated item
+     * @param n {@code >= 0;} which item
+     * @return {@code null-ok;} the indicated item
      */
     public Item get(int n) {
         return (Item) get0(n);
@@ -117,8 +116,8 @@
     /**
      * Sets the item at the given index.
      * 
-     * @param n &gt;= 0, &lt; size(); which element
-     * @param item non-null; the item
+     * @param n {@code >= 0, < size();} which element
+     * @param item {@code non-null;} the item
      */
     public void set(int n, Item item) {
         if (item == null) {
@@ -131,17 +130,17 @@
     /**
      * Sets the item at the given index.
      * 
-     * <p><b>Note:</b> At least one of <code>descriptor</code> or
-     * <code>signature</code> must be passed as non-null.</p>
+     * <p><b>Note:</b> At least one of {@code descriptor} or
+     * {@code signature} must be passed as non-null.</p>
      * 
-     * @param n &gt;= 0, &lt; size(); which element
-     * @param startPc &gt;= 0; the start pc of this variable's scope
-     * @param length &gt;= 0; the length (in bytecodes) of this variable's
+     * @param n {@code >= 0, < size();} which element
+     * @param startPc {@code >= 0;} the start pc of this variable's scope
+     * @param length {@code >= 0;} the length (in bytecodes) of this variable's
      * scope
-     * @param name non-null; the variable's name
-     * @param descriptor null-ok; the variable's type descriptor
-     * @param signature null-ok; the variable's type signature
-     * @param index &gt;= 0; the variable's local index
+     * @param name {@code non-null;} the variable's name
+     * @param descriptor {@code null-ok;} the variable's type descriptor
+     * @param signature {@code null-ok;} the variable's type signature
+     * @param index {@code >= 0;} the variable's local index
      */
     public void set(int n, int startPc, int length, CstUtf8 name,
             CstUtf8 descriptor, CstUtf8 signature, int index) {
@@ -153,9 +152,9 @@
      * the given {@link com.android.dx.cf.code.LocalVariableList.Item}
      * in all respects but the type descriptor and signature, if any.
      * 
-     * @param item non-null; local variable information to match
-     * @return null-ok; the corresponding local variable information stored
-     * in this instance, or <code>null</code> if there is no matching
+     * @param item {@code non-null;} local variable information to match
+     * @return {@code null-ok;} the corresponding local variable information stored
+     * in this instance, or {@code null} if there is no matching
      * information
      */
     public Item itemToLocal(Item item) {
@@ -178,10 +177,10 @@
      * variable's start point is listed as the address of the instruction
      * <i>just past</i> the one that sets the variable.
      * 
-     * @param pc &gt;= 0; the address to look up
-     * @param index &gt;= 0; the local variable index
-     * @return null-ok; the associated local variable information, or
-     * <code>null</code> if none is known
+     * @param pc {@code >= 0;} the address to look up
+     * @param index {@code >= 0;} the local variable index
+     * @return {@code null-ok;} the associated local variable information, or
+     * {@code null} if none is known
      */
     public Item pcAndIndexToLocal(int pc, int index) {
         int sz = size();
@@ -201,37 +200,37 @@
      * Item in a local variable table.
      */
     public static class Item {
-        /** &gt;= 0; the start pc of this variable's scope */
+        /** {@code >= 0;} the start pc of this variable's scope */
         private final int startPc;
 
-        /** &gt;= 0; the length (in bytecodes) of this variable's scope */
+        /** {@code >= 0;} the length (in bytecodes) of this variable's scope */
         private final int length;
 
-        /** non-null; the variable's name */
+        /** {@code non-null;} the variable's name */
         private final CstUtf8 name;
 
-        /** null-ok; the variable's type descriptor */
+        /** {@code null-ok;} the variable's type descriptor */
         private final CstUtf8 descriptor;
 
-        /** null-ok; the variable's type signature */
+        /** {@code null-ok;} the variable's type signature */
         private final CstUtf8 signature;
 
-        /** &gt;= 0; the variable's local index */
+        /** {@code >= 0;} the variable's local index */
         private final int index;
 
         /**
          * Constructs an instance.
          * 
-         * <p><b>Note:</b> At least one of <code>descriptor</code> or
-         * <code>signature</code> must be passed as non-null.</p>
+         * <p><b>Note:</b> At least one of {@code descriptor} or
+         * {@code signature} must be passed as non-null.</p>
          * 
-         * @param startPc &gt;= 0; the start pc of this variable's scope
-         * @param length &gt;= 0; the length (in bytecodes) of this variable's
+         * @param startPc {@code >= 0;} the start pc of this variable's scope
+         * @param length {@code >= 0;} the length (in bytecodes) of this variable's
          * scope
-         * @param name non-null; the variable's name
-         * @param descriptor null-ok; the variable's type descriptor
-         * @param signature null-ok; the variable's type signature
-         * @param index &gt;= 0; the variable's local index
+         * @param name {@code non-null;} the variable's name
+         * @param descriptor {@code null-ok;} the variable's type descriptor
+         * @param signature {@code null-ok;} the variable's type signature
+         * @param index {@code >= 0;} the variable's local index
          */
         public Item(int startPc, int length, CstUtf8 name,
                 CstUtf8 descriptor, CstUtf8 signature, int index) {
@@ -267,7 +266,7 @@
         /**
          * Gets the start pc of this variable's scope.
          * 
-         * @return &gt;= 0; the start pc of this variable's scope
+         * @return {@code >= 0;} the start pc of this variable's scope
          */
         public int getStartPc() {
             return startPc;
@@ -276,7 +275,7 @@
         /**
          * Gets the length (in bytecodes) of this variable's scope.
          * 
-         * @return &gt;= 0; the length (in bytecodes) of this variable's scope
+         * @return {@code >= 0;} the length (in bytecodes) of this variable's scope
          */
         public int getLength() {
             return length;
@@ -285,7 +284,7 @@
         /**
          * Gets the variable's type descriptor.
          *
-         * @return null-ok; the variable's type descriptor
+         * @return {@code null-ok;} the variable's type descriptor
          */
         public CstUtf8 getDescriptor() {
             return descriptor;
@@ -294,7 +293,7 @@
         /**
          * Gets the variable's LocalItem, a (name, signature) tuple
          *
-         * @return null-ok; the variable's type descriptor
+         * @return {@code null-ok;} the variable's type descriptor
          */
         public LocalItem getLocalItem() {
             return LocalItem.make(name, signature);
@@ -304,7 +303,7 @@
          * Gets the variable's type signature. Private because if you need this,
          * you want getLocalItem() instead.
          *
-         * @return null-ok; the variable's type signature
+         * @return {@code null-ok;} the variable's type signature
          */
         private CstUtf8 getSignature() {
             return signature;
@@ -313,7 +312,7 @@
         /**
          * Gets the variable's local index.
          * 
-         * @return &gt;= 0; the variable's local index
+         * @return {@code >= 0;} the variable's local index
          */
         public int getIndex() {
             return index;
@@ -321,9 +320,9 @@
 
         /**
          * Gets the variable's type descriptor. This is a convenient shorthand
-         * for <code>Type.intern(getDescriptor().getString())</code>.
+         * for {@code Type.intern(getDescriptor().getString())}.
          * 
-         * @return non-null; the variable's type
+         * @return {@code non-null;} the variable's type
          */
         public Type getType() {
             return Type.intern(descriptor.getString());
@@ -333,8 +332,8 @@
          * Constructs and returns an instance which is identical to this
          * one, except that the signature is changed to the given value.
          * 
-         * @param newSignature non-null; the new signature
-         * @return non-null; an appropriately-constructed instance
+         * @param newSignature {@code non-null;} the new signature
+         * @return {@code non-null;} an appropriately-constructed instance
          */
         public Item withSignature(CstUtf8 newSignature) {
             return new Item(startPc, length, name, descriptor, newSignature,
@@ -345,10 +344,10 @@
          * Gets whether this instance matches (describes) the given
          * address and index.
          * 
-         * @param pc &gt;= 0; the address in question
-         * @param index &gt;= 0; the local variable index in question
-         * @return <code>true</code> iff this instance matches <code>pc</code>
-         * and <code>index</code>
+         * @param pc {@code >= 0;} the address in question
+         * @param index {@code >= 0;} the local variable index in question
+         * @return {@code true} iff this instance matches {@code pc}
+         * and {@code index}
          */
         public boolean matchesPcAndIndex(int pc, int index) {
             return (index == this.index) &&
@@ -361,8 +360,8 @@
          * other instance exactly in all fields except type descriptor and
          * type signature.
          * 
-         * @param other non-null; the instance to compare to
-         * @return <code>true</code> iff this instance matches
+         * @param other {@code non-null;} the instance to compare to
+         * @return {@code true} iff this instance matches
          */
         public boolean matchesAllButType(Item other) {
             return (startPc == other.startPc)
diff --git a/dx/src/com/android/dx/cf/code/LocalsArray.java b/dx/src/com/android/dx/cf/code/LocalsArray.java
index 1c324ca..b2c2689 100644
--- a/dx/src/com/android/dx/cf/code/LocalsArray.java
+++ b/dx/src/com/android/dx/cf/code/LocalsArray.java
@@ -36,7 +36,7 @@
     /**
      * Constructs an instance, explicitly indicating the mutability.
      *
-     * @param mutable <code>true</code> if this instance is mutable
+     * @param mutable {@code true} if this instance is mutable
      */   
     protected LocalsArray(boolean mutable) {
         super(mutable);
@@ -45,7 +45,7 @@
     /**
      * Makes and returns a mutable copy of this instance.
      * 
-     * @return non-null; the copy
+     * @return {@code non-null;} the copy
      */
     public abstract LocalsArray copy();
 
@@ -53,7 +53,7 @@
      * Annotates (adds context to) the given exception with information
      * about this instance.
      * 
-     * @param ex non-null; the exception to annotate
+     * @param ex {@code non-null;} the exception to annotate
      */
     public abstract void annotate(ExceptionWithContext ex);
 
@@ -61,7 +61,7 @@
      * Replaces all the occurrences of the given uninitialized type in
      * this array with its initialized equivalent.
      * 
-     * @param type non-null; type to replace
+     * @param type {@code non-null;} type to replace
      */
     public abstract void makeInitialized(Type type);
 
@@ -71,16 +71,17 @@
      * @return the max locals
      */
     public abstract int getMaxLocals();
+
     /**
      * Sets the type stored at the given local index. If the given type
      * is category-2, then (a) the index must be at least two less than
-     * <code>getMaxLocals()</code> and (b) the next index gets invalidated
+     * {@link #getMaxLocals} and (b) the next index gets invalidated
      * by the operation. In case of either category, if the <i>previous</i>
      * local contains a category-2 value, then it too is invalidated by
      * this operation.
      * 
-     * @param idx &gt;= 0, &lt; getMaxLocals(); which local
-     * @param type non-null; new type for the local at <code>idx</code>
+     * @param idx {@code >= 0, < getMaxLocals();} which local
+     * @param type {@code non-null;} new type for the local at {@code idx}
      */
     public abstract void set(int idx, TypeBearer type);
 
@@ -88,25 +89,25 @@
      * Sets the type for the local indicated by the given register spec
      * to that register spec (which includes type and optional name
      * information). This is identical to calling
-     * <code>set(spec.getReg(), spec)</code>.
+     * {@code set(spec.getReg(), spec)}.
      * 
-     * @param spec non-null; register spec to use as the basis for the update
+     * @param spec {@code non-null;} register spec to use as the basis for the update
      */
     public abstract void set(RegisterSpec spec);
 
     /**
      * Invalidates the local at the given index.
      * 
-     * @param idx &gt;= 0, &lt; getMaxLocals(); which local
+     * @param idx {@code >= 0, < getMaxLocals();} which local
      */
     public abstract void invalidate(int idx);
 
     /**
-     * Gets the type stored at the given local index, or <code>null</code>
+     * Gets the type stored at the given local index, or {@code null}
      * if the given local is uninitialized / invalid.
      * 
-     * @param idx &gt;= 0, &lt; getMaxLocals(); which local
-     * @return null-ok; the type of value stored in that local
+     * @param idx {@code >= 0, < getMaxLocals();} which local
+     * @return {@code null-ok;} the type of value stored in that local
      */
     public abstract TypeBearer getOrNull(int idx);
 
@@ -115,9 +116,9 @@
      * the given local contains a valid type (though it is allowed to
      * be an uninitialized instance).
      * 
-     * @param idx &gt;= 0, &lt; getMaxLocals(); which local
-     * @return non-null; the type of value stored in that local
-     * @throws SimException thrown if <code>idx</code> is valid, but
+     * @param idx {@code >= 0, < getMaxLocals();} which local
+     * @return {@code non-null;} the type of value stored in that local
+     * @throws SimException thrown if {@code idx} is valid, but
      * the contents are invalid
      */
     public abstract TypeBearer get(int idx);
@@ -126,9 +127,9 @@
      * Gets the type stored at the given local index, which is expected
      * to be an initialized category-1 value.
      * 
-     * @param idx &gt;= 0, &lt; getMaxLocals(); which local
-     * @return non-null; the type of value stored in that local
-     * @throws SimException thrown if <code>idx</code> is valid, but
+     * @param idx {@code >= 0, < getMaxLocals();} which local
+     * @return {@code non-null;} the type of value stored in that local
+     * @throws SimException thrown if {@code idx} is valid, but
      * one of the following holds: (a) the local is invalid; (b) the local
      * contains an uninitialized instance; (c) the local contains a
      * category-2 value
@@ -139,39 +140,39 @@
      * Gets the type stored at the given local index, which is expected
      * to be a category-2 value.
      * 
-     * @param idx &gt;= 0, &lt; getMaxLocals(); which local
-     * @return non-null; the type of value stored in that local
-     * @throws SimException thrown if <code>idx</code> is valid, but
+     * @param idx {@code >= 0, < getMaxLocals();} which local
+     * @return {@code non-null;} the type of value stored in that local
+     * @throws SimException thrown if {@code idx} is valid, but
      * one of the following holds: (a) the local is invalid; (b) the local
      * contains a category-1 value
      */
     public abstract TypeBearer getCategory2(int idx);
 
     /**
-     * Merges this instance with <code>other</code>. If the merged result is
+     * Merges this instance with {@code other}. If the merged result is
      * the same as this instance, then this is returned (not a copy).
      *
-     * @param other non-null; another LocalsArray
-     * @return non-null; the merge result, a new instance or this
+     * @param other {@code non-null;} another LocalsArray
+     * @return {@code non-null;} the merge result, a new instance or this
      */
     public abstract LocalsArray merge(LocalsArray other);
 
     /**
-     * Merges this instance with a <code>LocalsSet</code> from a subroutine
+     * Merges this instance with a {@code LocalsSet} from a subroutine
      * caller. To be used when merging in the first block of a subroutine.
      *
-     * @param other other non-null; another LocalsArray. The final locals
+     * @param other {@code other non-null;} another LocalsArray. The final locals
      * state of a subroutine caller.
      * @param predLabel the label of the subroutine caller block.
-     * @return non-null; the merge result, a new instance or this
+     * @return {@code non-null;} the merge result, a new instance or this
      */
     public abstract LocalsArraySet mergeWithSubroutineCaller
             (LocalsArray other, int predLabel);
 
     /**
      * Gets the locals set appropriate for the current execution context.
-     * That is, if this is a <code>OneLocalsArray</code> instance, then return
-     * <code>this</code>, otherwise return <code>LocalsArraySet</code>'s
+     * That is, if this is a {@code OneLocalsArray} instance, then return
+     * {@code this}, otherwise return {@code LocalsArraySet}'s
      * primary.
      *
      * @return locals for this execution context.
diff --git a/dx/src/com/android/dx/cf/code/LocalsArraySet.java b/dx/src/com/android/dx/cf/code/LocalsArraySet.java
index 9e24da9..fa2acbe 100644
--- a/dx/src/com/android/dx/cf/code/LocalsArraySet.java
+++ b/dx/src/com/android/dx/cf/code/LocalsArraySet.java
@@ -51,9 +51,9 @@
 
     /**
      * Constructs an instance. The locals array initially consists of
-     * all-uninitialized values (represented as <code>null</code>s).
+     * all-uninitialized values (represented as {@code null}s).
      *
-     * @param maxLocals &gt;= 0; the maximum number of locals this instance
+     * @param maxLocals {@code >= 0;} the maximum number of locals this instance
      * can refer to
      */
     public LocalsArraySet(int maxLocals) {
@@ -65,8 +65,8 @@
     /**
      * Constructs an instance with the specified primary and secondaries set.
      *
-     * @param primary non-null; primary locals to use
-     * @param secondaries non-null; secondaries set, indexed by subroutine
+     * @param primary {@code non-null;} primary locals to use
+     * @param secondaries {@code non-null;} secondaries set, indexed by subroutine
      * caller label.
      */
     public LocalsArraySet(OneLocalsArray primary,
@@ -80,7 +80,7 @@
     /**
      * Constructs an instance which is a copy of another.
      *
-     * @param toCopy non-null; instance to copy.
+     * @param toCopy {@code non-null;} instance to copy.
      */
     private LocalsArraySet(LocalsArraySet toCopy) {
         super(toCopy.getMaxLocals() > 0);
@@ -89,7 +89,7 @@
         secondaries = new ArrayList(toCopy.secondaries.size());
 
         int sz = toCopy.secondaries.size();
-        for(int i = 0; i < sz; i++) {
+        for (int i = 0; i < sz; i++) {
             LocalsArray la = toCopy.secondaries.get(i);
 
             if (la == null) {
@@ -106,7 +106,7 @@
     public void setImmutable() {
         primary.setImmutable();
 
-        for (LocalsArray la: secondaries) {
+        for (LocalsArray la : secondaries) {
             if (la != null) {
                 la.setImmutable();
             }
@@ -127,7 +127,7 @@
         primary.annotate(ex);
 
         int sz = secondaries.size();
-        for(int label = 0; label < sz; label++) {
+        for (int label = 0; label < sz; label++) {
             LocalsArray la = secondaries.get(label);
 
             if (la != null) {
@@ -149,7 +149,7 @@
         sb.append('\n');
 
         int sz = secondaries.size();
-        for(int label = 0; label < sz; label++) {
+        for (int label = 0; label < sz; label++) {
             LocalsArray la = secondaries.get(label);
 
             if (la != null) {
@@ -178,7 +178,7 @@
 
         primary.makeInitialized(type);
 
-        for (LocalsArray la: secondaries) {
+        for (LocalsArray la : secondaries) {
             if (la != null) {
                 la.makeInitialized(type);
             }
@@ -198,7 +198,7 @@
 
         primary.set(idx, type);
 
-        for (LocalsArray la: secondaries) {
+        for (LocalsArray la : secondaries) {
             if (la != null) {
                 la.set(idx, type);
             }
@@ -218,7 +218,7 @@
 
         primary.invalidate(idx);
 
-        for (LocalsArray la: secondaries) {
+        for (LocalsArray la : secondaries) {
             if (la != null) {
                 la.invalidate(idx);
             }
@@ -250,10 +250,10 @@
     }
 
     /**
-     * Merges this set with another <code>LocalsArraySet</code> instance.
+     * Merges this set with another {@code LocalsArraySet} instance.
      *
-     * @param other non-null; to merge
-     * @return non-null; this instance if merge was a no-op, or
+     * @param other {@code non-null;} to merge
+     * @return {@code non-null;} this instance if merge was a no-op, or
      * new merged instance.
      */
     private LocalsArraySet mergeWithSet(LocalsArraySet other) {
@@ -301,10 +301,10 @@
     }
 
     /**
-     * Merges this set with a <code>OneLocalsArray</code> instance.
+     * Merges this set with a {@code OneLocalsArray} instance.
      *
-     * @param other non-null; to merge
-     * @return non-null; this instance if merge was a no-op, or
+     * @param other {@code non-null;} to merge
+     * @return {@code non-null;} this instance if merge was a no-op, or
      * new merged instance.
      */
     private LocalsArraySet mergeWithOne(OneLocalsArray other) {
@@ -365,11 +365,11 @@
     }
 
     /**
-     * Gets the <code>LocalsArray</code> instance for a specified subroutine
+     * Gets the {@code LocalsArray} instance for a specified subroutine
      * caller label, or null if label has no locals associated with it.
      *
-     * @param label &gt;=0 subroutine caller label
-     * @return null-ok; locals if available.
+     * @param label {@code >= 0;} subroutine caller label
+     * @return {@code null-ok;} locals if available.
      */
     private LocalsArray getSecondaryForLabel(int label) {
         if (label >= secondaries.size()) {
@@ -445,8 +445,8 @@
      * Returns a LocalsArray instance representing the locals state that should
      * be used when returning to a subroutine caller.
      *
-     * @param subLabel &gt;= 0; A calling label of a subroutine
-     * @return null-ok; an instance for this subroutine, or null if subroutine
+     * @param subLabel {@code >= 0;} A calling label of a subroutine
+     * @return {@code null-ok;} an instance for this subroutine, or null if subroutine
      * is not in this set.
      */
     public LocalsArray subArrayForLabel(int subLabel) {
diff --git a/dx/src/com/android/dx/cf/code/Machine.java b/dx/src/com/android/dx/cf/code/Machine.java
index 517a10d..aff50b2 100644
--- a/dx/src/com/android/dx/cf/code/Machine.java
+++ b/dx/src/com/android/dx/cf/code/Machine.java
@@ -32,9 +32,9 @@
     /**
      * Gets the effective prototype of the method that this instance is
      * being used for. The <i>effective</i> prototype includes an initial
-     * <code>this</code> argument for instance methods.
+     * {@code this} argument for instance methods.
      * 
-     * @return non-null; the method prototype
+     * @return {@code non-null;} the method prototype
      */
     public Prototype getPrototype();
     
@@ -48,21 +48,21 @@
      * and store them in the arguments area, indicating that there are now
      * that many arguments. Also, clear the auxiliary arguments.
      *
-     * @param frame non-null; frame to operate on
-     * @param count &gt;= 0; number of values to pop
+     * @param frame {@code non-null;} frame to operate on
+     * @param count {@code >= 0;} number of values to pop
      */
     public void popArgs(Frame frame, int count);
 
     /**
      * Pops values from the stack of the types indicated by the given
-     * <code>Prototype</code> (popped in reverse of the argument
+     * {@code Prototype} (popped in reverse of the argument
      * order, so the first prototype argument type is for the deepest
      * element of the stack), and store them in the arguments area,
      * indicating that there are now that many arguments. Also, clear
      * the auxiliary arguments.
      *
-     * @param frame non-null; frame to operate on
-     * @param prototype non-null; prototype indicating arguments to pop
+     * @param frame {@code non-null;} frame to operate on
+     * @param prototype {@code non-null;} prototype indicating arguments to pop
      */
     public void popArgs(Frame frame, Prototype prototype);
 
@@ -71,8 +71,8 @@
      * in the arguments area, indicating that there are now that many
      * arguments. Also, clear the auxiliary arguments.
      *
-     * @param frame non-null; frame to operate on
-     * @param type non-null; type of the argument
+     * @param frame {@code non-null;} frame to operate on
+     * @param type {@code non-null;} type of the argument
      */
     public void popArgs(Frame frame, Type type);
 
@@ -83,9 +83,9 @@
      * area, indicating that there are now that many arguments. Also,
      * clear the auxiliary arguments.
      *
-     * @param frame non-null; frame to operate on
-     * @param type1 non-null; type of the first argument
-     * @param type2 non-null; type of the second argument
+     * @param frame {@code non-null;} frame to operate on
+     * @param type1 {@code non-null;} type of the first argument
+     * @param type2 {@code non-null;} type of the second argument
      */
     public void popArgs(Frame frame, Type type1, Type type2);
 
@@ -96,10 +96,10 @@
      * area, indicating that there are now that many arguments. Also,
      * clear the auxiliary arguments.
      *
-     * @param frame non-null; frame to operate on
-     * @param type1 non-null; type of the first argument
-     * @param type2 non-null; type of the second argument
-     * @param type3 non-null; type of the third argument
+     * @param frame {@code non-null;} frame to operate on
+     * @param type1 {@code non-null;} type of the first argument
+     * @param type2 {@code non-null;} type of the second argument
+     * @param type3 {@code non-null;} type of the third argument
      */
     public void popArgs(Frame frame, Type type1, Type type2, Type type3);
 
@@ -107,8 +107,8 @@
      * Loads the local variable with the given index as the sole argument in
      * the arguments area. Also, clear the auxiliary arguments.
      *
-     * @param frame non-null; frame to operate on
-     * @param idx &gt;= 0; the local variable index
+     * @param frame {@code non-null;} frame to operate on
+     * @param idx {@code >= 0;} the local variable index
      */
     public void localArg(Frame frame, int idx);
 
@@ -116,28 +116,28 @@
      * Indicates that the salient type of this operation is as
      * given. This differentiates between, for example, the various
      * arithmetic opcodes, which, by the time they hit a
-     * <code>Machine</code> are collapsed to the <code>int</code>
+     * {@code Machine} are collapsed to the {@code int}
      * variant. (See {@link BytecodeArray#parseInstruction} for
      * details.)
      *
-     * @param type non-null; the salient type of the upcoming operation
+     * @param type {@code non-null;} the salient type of the upcoming operation
      */
     public void auxType(Type type);
 
     /**
      * Indicates that there is an auxiliary (inline, not stack)
-     * argument of type <code>int</code>, with the given value.
+     * argument of type {@code int}, with the given value.
      *
      * <p><b>Note:</b> Perhaps unintuitively, the stack manipulation
-     * ops (e.g., <code>dup</code> and <code>swap</code>) use this to
+     * ops (e.g., {@code dup} and {@code swap}) use this to
      * indicate the result stack pattern with a straightforward hex
      * encoding of the push order starting with least-significant
      * nibbles getting pushed first). For example, an all-category-1
-     * <code>dup2_x1</code> sets this to <code>0x12312</code>, and the
+     * {@code dup2_x1} sets this to {@code 0x12312}, and the
      * other form of that op sets this to
-     * <code>0x121</code>.</p>
+     * {@code 0x121}.</p>
      *
-     * <p><b>Also Note:</b> For <code>switch*</code> instructions, this is
+     * <p><b>Also Note:</b> For {@code switch*} instructions, this is
      * used to indicate the padding value (which is only useful for
      * verification).</p>
      *
@@ -149,10 +149,10 @@
      * Indicates that there is an auxiliary (inline, not stack) object
      * argument, with the value based on the given constant.
      *
-     * <p><b>Note:</b> Some opcodes use both <code>int</code> and
+     * <p><b>Note:</b> Some opcodes use both {@code int} and
      * constant auxiliary arguments.</p>
      *
-     * @param cst non-null; the constant containing / referencing
+     * @param cst {@code non-null;} the constant containing / referencing
      * the value
      */
     public void auxCstArg(Constant cst);
@@ -167,12 +167,12 @@
 
     /**
      * Indicates that there is an auxiliary (inline, not stack) argument
-     * consisting of a <code>switch*</code> table.
+     * consisting of a {@code switch*} table.
      *
      * <p><b>Note:</b> This is generally used in conjunction with
      * {@link #auxIntArg} (which holds the padding).</p>
      *
-     * @param cases non-null; the list of key-target pairs, plus the default
+     * @param cases {@code non-null;} the list of key-target pairs, plus the default
      * target
      */
     public void auxSwitchArg(SwitchList cases);
@@ -181,7 +181,7 @@
      * Indicates that there is an auxiliary (inline, not stack) argument
      * consisting of a list of initial values for a newly created array.
      *
-     * @param initValues non-null; the list of constant values to initialize
+     * @param initValues {@code non-null;} the list of constant values to initialize
      * the array
      */
     public void auxInitValues(ArrayList<Constant> initValues);
@@ -189,9 +189,9 @@
     /**
      * Indicates that the target of this operation is the given local.
      *
-     * @param idx &gt;= 0; the local variable index
-     * @param type non-null; the type of the local
-     * @param local null-ok; the name and signature of the local, if known
+     * @param idx {@code >= 0;} the local variable index
+     * @param type {@code non-null;} the type of the local
+     * @param local {@code null-ok;} the name and signature of the local, if known
      */
     public void localTarget(int idx, Type type, LocalItem local);
 
@@ -199,10 +199,10 @@
      * "Runs" the indicated opcode in an appropriate way, using the arguments
      * area as appropriate, and modifying the given frame in response.
      *
-     * @param frame non-null; frame to operate on
-     * @param offset &gt;= 0; byte offset in the method to the opcode being
+     * @param frame {@code non-null;} frame to operate on
+     * @param offset {@code >= 0;} byte offset in the method to the opcode being
      * run
-     * @param opcode &gt;= 0; the opcode to run
+     * @param opcode {@code >= 0;} the opcode to run
      */
     public void run(Frame frame, int offset, int opcode);
 }
diff --git a/dx/src/com/android/dx/cf/code/Merger.java b/dx/src/com/android/dx/cf/code/Merger.java
index adeaab2..8da9a18 100644
--- a/dx/src/com/android/dx/cf/code/Merger.java
+++ b/dx/src/com/android/dx/cf/code/Merger.java
@@ -35,9 +35,9 @@
      * Merges two locals arrays. If the merged result is the same as the first
      * argument, then return the first argument (not a copy).
      * 
-     * @param locals1 non-null; a locals array
-     * @param locals2 non-null; another locals array
-     * @return non-null; the result of merging the two locals arrays
+     * @param locals1 {@code non-null;} a locals array
+     * @param locals2 {@code non-null;} another locals array
+     * @return {@code non-null;} the result of merging the two locals arrays
      */
     public static OneLocalsArray mergeLocals(OneLocalsArray locals1,
                                           OneLocalsArray locals2) {
@@ -87,9 +87,9 @@
      * Merges two stacks. If the merged result is the same as the first
      * argument, then return the first argument (not a copy).
      * 
-     * @param stack1 non-null; a stack
-     * @param stack2 non-null; another stack
-     * @return non-null; the result of merging the two stacks
+     * @param stack1 {@code non-null;} a stack
+     * @param stack2 {@code non-null;} another stack
+     * @return {@code non-null;} the result of merging the two stacks
      */
     public static ExecutionStack mergeStack(ExecutionStack stack1,
                                             ExecutionStack stack2) {
@@ -144,9 +144,9 @@
     /**
      * Merges two frame types.
      * 
-     * @param ft1 non-null; a frame type
-     * @param ft2 non-null; another frame type
-     * @return non-null; the result of merging the two types
+     * @param ft1 {@code non-null;} a frame type
+     * @param ft2 {@code non-null;} another frame type
+     * @return {@code non-null;} the result of merging the two types
      */
     public static TypeBearer mergeType(TypeBearer ft1, TypeBearer ft2) {
         if ((ft1 == null) || ft1.equals(ft2)) {
@@ -209,12 +209,12 @@
      * the given subtype. This takes into account primitiveness,
      * int-likeness, known-nullness, and array dimensions, but does
      * not assume anything about class hierarchy other than that the
-     * type <code>Object</code> is the supertype of all reference
+     * type {@code Object} is the supertype of all reference
      * types and all arrays are assignable to
-     * <code>Serializable</code> and <code>Cloneable</code>.
+     * {@code Serializable} and {@code Cloneable}.
      * 
-     * @param supertypeBearer non-null; the supertype
-     * @param subtypeBearer non-null; the subtype
+     * @param supertypeBearer {@code non-null;} the supertype
+     * @param subtypeBearer {@code non-null;} the subtype
      */
     public static boolean isPossiblyAssignableFrom(TypeBearer supertypeBearer,
             TypeBearer subtypeBearer) {
diff --git a/dx/src/com/android/dx/cf/code/OneLocalsArray.java b/dx/src/com/android/dx/cf/code/OneLocalsArray.java
index 3a590a1..cafd177 100644
--- a/dx/src/com/android/dx/cf/code/OneLocalsArray.java
+++ b/dx/src/com/android/dx/cf/code/OneLocalsArray.java
@@ -31,14 +31,14 @@
  * com.android.dx.rop.type.TypeBearer}.</p>
  */
 public class OneLocalsArray extends LocalsArray {
-    /** non-null; actual array */
+    /** {@code non-null;} actual array */
     private final TypeBearer[] locals;
 
     /**
      * Constructs an instance. The locals array initially consists of
-     * all-uninitialized values (represented as <code>null</code>s).
+     * all-uninitialized values (represented as {@code null}s).
      *
-     * @param maxLocals &gt;= 0; the maximum number of locals this instance
+     * @param maxLocals {@code >= 0;} the maximum number of locals this instance
      * can refer to
      */
     public OneLocalsArray(int maxLocals) {
@@ -237,7 +237,7 @@
      * Throws a properly-formatted exception.
      *
      * @param idx the salient local index
-     * @param msg non-null; useful message
+     * @param msg {@code non-null;} useful message
      * @return never (keeps compiler happy)
      */
     private static TypeBearer throwSimException(int idx, String msg) {
diff --git a/dx/src/com/android/dx/cf/code/ReturnAddress.java b/dx/src/com/android/dx/cf/code/ReturnAddress.java
index c69253c..47c6071 100644
--- a/dx/src/com/android/dx/cf/code/ReturnAddress.java
+++ b/dx/src/com/android/dx/cf/code/ReturnAddress.java
@@ -28,13 +28,13 @@
  * what instances of this class hang onto.
  */
 public final class ReturnAddress implements TypeBearer {
-    /** &gt;= 0; the start address of the subroutine being returned from */
+    /** {@code >= 0;} the start address of the subroutine being returned from */
     private final int subroutineAddress;
 
     /**
      * Constructs an instance.
      * 
-     * @param subroutineAddress &gt;= 0; the start address of the
+     * @param subroutineAddress {@code >= 0;} the start address of the
      * subroutine being returned from
      */
     public ReturnAddress(int subroutineAddress) {
@@ -100,7 +100,7 @@
     /**
      * Gets the subroutine address.
      * 
-     * @return &gt;= 0; the subroutine address
+     * @return {@code >= 0;} the subroutine address
      */
     public int getSubroutineAddress() {
         return subroutineAddress;
diff --git a/dx/src/com/android/dx/cf/code/Ropper.java b/dx/src/com/android/dx/cf/code/Ropper.java
index f3eecab..6e8c328 100644
--- a/dx/src/com/android/dx/cf/code/Ropper.java
+++ b/dx/src/com/android/dx/cf/code/Ropper.java
@@ -66,10 +66,10 @@
     /** number of special label offsets */
     private static final int SPECIAL_LABEL_COUNT = 7;
 
-    /** non-null; method being converted */
+    /** {@code non-null;} method being converted */
     private final ConcreteMethod method;
 
-    /** non-null; original block list */
+    /** {@code non-null;} original block list */
     private final ByteBlockList blocks;
 
     /** max locals of the method */
@@ -78,30 +78,30 @@
     /** max label (exclusive) of any original bytecode block */
     private final int maxLabel;
 
-    /** non-null; simulation machine to use */
+    /** {@code non-null;} simulation machine to use */
     private final RopperMachine machine;
 
-    /** non-null; simulator to use */
+    /** {@code non-null;} simulator to use */
     private final Simulator sim;
 
     /**
-     * non-null; sparse array mapping block labels to initial frame contents,
+     * {@code non-null;} sparse array mapping block labels to initial frame contents,
      * if known 
      */
     private final Frame[] startFrames;
 
-    /** non-null; output block list in-progress */
+    /** {@code non-null;} output block list in-progress */
     private final ArrayList<BasicBlock> result;
 
     /**
-     * non-null; list of subroutine-nest labels
+     * {@code non-null;} list of subroutine-nest labels
      * (See {@link Frame#getSubroutines} associated with each result block.
      * Parallel to {@link Ropper#result}. 
      */
     private final ArrayList<IntList> resultSubroutines;
 
     /**
-     * non-null; for each block (by label) that is used as an exception
+     * {@code non-null;} for each block (by label) that is used as an exception
      * handler, the type of exception it catches 
      */
     private final Type[] catchTypes;
@@ -112,10 +112,10 @@
      */
     private boolean synchNeedsExceptionHandler;
 
-    /** non-null; list of subroutines indexed by label of start address */
+    /** {@code non-null;} list of subroutines indexed by label of start address */
     private final Subroutine subroutines[];
 
-    /** true if <code>subroutines</code> is non-empty */
+    /** true if {@code subroutines} is non-empty */
     private boolean hasSubroutines;
 
     /**
@@ -155,7 +155,7 @@
         }
 
         /**
-         * @return &gt;= 0; the label of the subroutine's start block.
+         * @return {@code >= 0;} the label of the subroutine's start block.
          */
         int getStartBlock() {
             return startBlock;
@@ -194,13 +194,13 @@
             IntList successors = new IntList(callerBlocks.size());
 
             /*
-             * For each subroutine caller, get it's target. If the target is us,
-             * add the ret target (subroutine successor) to our list
+             * For each subroutine caller, get it's target. If the
+             * target is us, add the ret target (subroutine successor)
+             * to our list
              */
 
-            for(int label = callerBlocks.nextSetBit(0); label >= 0 
-                    ; label = callerBlocks.nextSetBit(label+1)) {
-
+            for (int label = callerBlocks.nextSetBit(0); label >= 0;
+                 label = callerBlocks.nextSetBit(label+1)) {
                 BasicBlock subCaller = labelToBlock(label);
                 successors.add(subCaller.getSuccessors().get(0));
             }
@@ -212,18 +212,15 @@
 
         /**
          * Merges the specified frame into this subroutine's successors,
-         * setting <code>workSet</code> as appropriate. To be called with
+         * setting {@code workSet} as appropriate. To be called with
          * the frame of a subroutine ret block.
          *
-         * @param frame non-null; frame from ret block to merge
-         * @param workSet non-null; workset to update
+         * @param frame {@code non-null;} frame from ret block to merge
+         * @param workSet {@code non-null;} workset to update
          */
         void mergeToSuccessors(Frame frame, int[] workSet) {
-            int sz = callerBlocks.size();
-
-            for(int label = callerBlocks.nextSetBit(0); label >= 0
-                    ; label = callerBlocks.nextSetBit(label+1)) {
-
+            for (int label = callerBlocks.nextSetBit(0); label >= 0;
+                 label = callerBlocks.nextSetBit(label+1)) {
                 BasicBlock subCaller = labelToBlock(label);
                 int succLabel = subCaller.getSuccessors().get(0);
 
@@ -242,9 +239,9 @@
     /**
      * Converts a {@link ConcreteMethod} to a {@link RopMethod}.
      * 
-     * @param method non-null; method to convert
-     * @param advice non-null; translation advice to use
-     * @return non-null; the converted instance
+     * @param method {@code non-null;} method to convert
+     * @param advice {@code non-null;} translation advice to use
+     * @return {@code non-null;} the converted instance
      */
     public static RopMethod convert(ConcreteMethod method,
             TranslationAdvice advice) {
@@ -263,8 +260,8 @@
      * Constructs an instance. This class is not publicly instantiable; use
      * {@link #convert}.
      * 
-     * @param method non-null; method to convert
-     * @param advice non-null; translation advice to use
+     * @param method {@code non-null;} method to convert
+     * @param advice {@code non-null;} translation advice to use
      */
     private Ropper(ConcreteMethod method, TranslationAdvice advice) {
         if (method == null) {
@@ -307,7 +304,7 @@
      * Gets the first (lowest) register number to use as the temporary
      * area when unwinding stack manipulation ops.
      * 
-     * @return &gt;= 0; the first register to use
+     * @return {@code >= 0;} the first register to use
      */
     /*package*/ int getFirstTempStackReg() {
         /*
@@ -326,8 +323,8 @@
      * Gets the label for the exception handler setup block corresponding
      * to the given label.
      * 
-     * @param label &gt;= 0; the original label
-     * @return &gt;= 0; the corresponding exception handler setup label
+     * @param label {@code >= 0;} the original label
+     * @return {@code >= 0;} the corresponding exception handler setup label
      */
     private int getExceptionSetupLabel(int label) {
         return maxLabel + label;
@@ -337,8 +334,8 @@
      * Gets the label for the given special-purpose block. The given label
      * should be one of the static constants defined by this class.
      * 
-     * @param label &lt; 0; the special label constant
-     * @return &gt;= 0; the actual label value to use
+     * @param label {@code < 0;} the special label constant
+     * @return {@code >= 0;} the actual label value to use
      */
     private int getSpecialLabel(int label) {
         /*
@@ -356,7 +353,7 @@
     /**
      * Gets the minimum label for unreserved use.
      * 
-     * @return &gt;= 0; the minimum label
+     * @return {@code >= 0;} the minimum label
      */
     private int getMinimumUnreservedLabel() {
         /*
@@ -370,7 +367,7 @@
     /**
      * Gets an arbitrary unreserved and available label.
      * 
-     * @return &gt;= 0; the label
+     * @return {@code >= 0;} the label
      */
     private int getAvailableLabel() {
         int candidate = getMinimumUnreservedLabel();
@@ -409,7 +406,7 @@
      * Gets the total number of registers used for "normal" purposes (i.e.,
      * for the straightforward translation from the original Java).
      * 
-     * @return &gt;= 0; the total number of registers used
+     * @return {@code >= 0;} the total number of registers used
      */
     private int getNormalRegCount() {
         return maxLocals + method.getMaxStack();
@@ -419,7 +416,7 @@
      * Gets the register spec to use to hold the object to synchronize on,
      * for a synchronized method.
      * 
-     * @return non-null; the register spec
+     * @return {@code non-null;} the register spec
      */
     private RegisterSpec getSynchReg() {
         /*
@@ -433,11 +430,11 @@
 
     /**
      * Searches {@link #result} for a block with the given label. Return its
-     * index if found, or return <code>-1</code> if there is no such block.
+     * index if found, or return {@code -1} if there is no such block.
      * 
      * @param label the label to look for
-     * @return &gt;= -1; the index for the block with the given label or
-     * <code>-1</code> if there is no such block
+     * @return {@code >= -1;} the index for the block with the given label or
+     * {@code -1} if there is no such block
      */
     private int labelToResultIndex(int label) {
         int sz = result.size();
@@ -456,7 +453,7 @@
      * found, or throw an exception if there is no such block.
      * 
      * @param label the label to look for
-     * @return non-null; the block with the given label
+     * @return {@code non-null;} the block with the given label
      */
     private BasicBlock labelToBlock(int label) {
         int idx = labelToResultIndex(label);
@@ -472,8 +469,8 @@
     /**
      * Adds a block to the output result.
      * 
-     * @param block non-null; the block to add
-     * @param subroutines non-null; subroutine label list as described in
+     * @param block {@code non-null;} the block to add
+     * @param subroutines {@code non-null;} subroutine label list as described in
      * {@link Frame#getSubroutines}
      */
     private void addBlock(BasicBlock block, IntList subroutines) {
@@ -491,11 +488,11 @@
      * replacement, then any extra blocks that got added with the
      * original get removed as a result of calling this method.
      * 
-     * @param block non-null; the block to add or replace
-     * @param subroutines non-null; subroutine label list as described in
+     * @param block {@code non-null;} the block to add or replace
+     * @param subroutines {@code non-null;} subroutine label list as described in
      * {@link Frame#getSubroutines}
-     * @return <code>true</code> if the block was replaced or
-     * <code>false</code> if it was added for the first time
+     * @return {@code true} if the block was replaced or
+     * {@code false} if it was added for the first time
      */
     private boolean addOrReplaceBlock(BasicBlock block, IntList subroutines) {
         if (block == null) {
@@ -529,11 +526,11 @@
      * Adds or replaces a block in the output result. Do not delete
      * any successors.
      *
-     * @param block non-null; the block to add or replace
-     * @param subroutines non-null; subroutine label list as described in
+     * @param block {@code non-null;} the block to add or replace
+     * @param subroutines {@code non-null;} subroutine label list as described in
      * {@link Frame#getSubroutines}
-     * @return <code>true</code> if the block was replaced or
-     * <code>false</code> if it was added for the first time
+     * @return {@code true} if the block was replaced or
+     * {@code false} if it was added for the first time
      */
     private boolean addOrReplaceBlockNoDelete(BasicBlock block,
             IntList subroutines) {
@@ -564,7 +561,7 @@
      * successors of it whose labels indicate that they are not in the
      * normally-translated range.
      * 
-     * @param idx non-null; block to remove (etc.)
+     * @param idx {@code non-null;} block to remove (etc.)
      */
     private void removeBlockAndSpecialSuccessors(int idx) {
         int minLabel = getMinimumUnreservedLabel();
@@ -591,7 +588,7 @@
     /**
      * Extracts the resulting {@link RopMethod} from the instance.
      * 
-     * @return non-null; the method object
+     * @return {@code non-null;} the method object
      */
     private RopMethod getRopMethod() {
 
@@ -663,9 +660,9 @@
     /**
      * Processes the given block.
      * 
-     * @param block non-null; block to process
-     * @param frame non-null; start frame for the block
-     * @param workSet non-null; bits representing work to do, which this
+     * @param block {@code non-null;} block to process
+     * @param frame {@code non-null;} start frame for the block
+     * @param workSet {@code non-null;} bits representing work to do, which this
      * method may add to
      */
     private void processBlock(ByteBlock block, Frame frame, int[] workSet) {
@@ -950,14 +947,14 @@
      * Helper for {@link #processBlock}, which merges frames and
      * adds to the work set, as necessary.
      * 
-     * @param label &gt;= 0; label to work on
-     * @param pred  predecessor label. Must be &gt;= 0 when
-     * <code>label</code> is a subroutine start block and calledSubroutine
+     * @param label {@code >= 0;} label to work on
+     * @param pred  predecessor label; must be {@code >= 0} when
+     * {@code label} is a subroutine start block and calledSubroutine
      * is non-null. Otherwise, may be -1.
-     * @param calledSubroutine null-ok; a Subroutine instance if
-     * <code>label</code> is the first block in a subroutine.
-     * @param frame non-null; new frame for the labelled block
-     * @param workSet non-null; bits representing work to do, which this
+     * @param calledSubroutine {@code null-ok;} a Subroutine instance if
+     * {@code label} is the first block in a subroutine.
+     * @param frame {@code non-null;} new frame for the labelled block
+     * @param workSet {@code non-null;} bits representing work to do, which this
      * method may add to
      */
     private void mergeAndWorkAsNecessary(int label, int pred,
@@ -1078,7 +1075,7 @@
 
     /**
      * Constructs and adds the return block, if necessary. The return
-     * block merely contains an appropriate <code>return</code>
+     * block merely contains an appropriate {@code return}
      * instruction.
      */
     private void addReturnBlock() {
@@ -1217,7 +1214,7 @@
     /**
      * Checks to see if the basic block is a subroutine caller block.
      *
-     * @param bb non-null; the basic block in question
+     * @param bb {@code non-null;} the basic block in question
      * @return true if this block calls a subroutine
      */
     private boolean isSubroutineCaller(BasicBlock bb) {
@@ -1340,7 +1337,7 @@
 
     /**
      * Inlines a subroutine. Start by calling
-     * <code>inlineSubroutineCalledFrom</code>.
+     * {@code inlineSubroutineCalledFrom}.
      */
     private class SubroutineInliner {
         /**
@@ -1399,9 +1396,8 @@
              */
             int newSubStartLabel = mapOrAllocateLabel(subroutineStart);
 
-            for(int label = workList.nextSetBit(0); label >= 0
-                    ; label = workList.nextSetBit(0)) {
-
+            for (int label = workList.nextSetBit(0); label >= 0;
+                 label = workList.nextSetBit(0)) {
                 workList.clear(label);
                 int newLabel = origLabelToCopiedLabel.get(label);
 
@@ -1421,7 +1417,8 @@
             addOrReplaceBlockNoDelete(
                 new BasicBlock(b.getLabel(), b.getInsns(),
                     IntList.makeImmutable (newSubStartLabel),
-                            newSubStartLabel), labelToSubroutines.get(b.getLabel()));
+                            newSubStartLabel),
+                labelToSubroutines.get(b.getLabel()));
        }
 
         /**
@@ -1502,8 +1499,8 @@
          * Checks to see if a specified label is involved in a specified
          * subroutine.
          *
-         * @param label &gt;=0 a basic block label
-         * @param subroutineStart &gt;=0 a subroutine as identified by the
+         * @param label {@code >= 0;} a basic block label
+         * @param subroutineStart {@code >= 0;} a subroutine as identified by the
          * label of its start block.
          * @return true if the block is dominated by the subroutine call.
          */
@@ -1554,10 +1551,10 @@
     }
 
     /**
-     * Finds a <code>Subroutine<code> that is returned from by a ret in
+     * Finds a {@code Subroutine} that is returned from by a ret in
      * a given block.
      * @param label A block that originally contained a ret instruction
-     * @return null-ok; Subroutine or null if none was found.
+     * @return {@code null-ok;} Subroutine or null if none was found.
      */
     private Subroutine subroutineFromRetBlock(int label) {
         for (int i = subroutines.length - 1 ; i >= 0 ; i--) {
diff --git a/dx/src/com/android/dx/cf/code/RopperMachine.java b/dx/src/com/android/dx/cf/code/RopperMachine.java
index 6d05b38..dd7fcd4 100644
--- a/dx/src/com/android/dx/cf/code/RopperMachine.java
+++ b/dx/src/com/android/dx/cf/code/RopperMachine.java
@@ -47,13 +47,13 @@
  * Machine implementation for use by {@link Ropper}.
  */
 /*package*/ final class RopperMachine extends ValueAwareMachine {
-    /** non-null; array reflection class */
+    /** {@code non-null;} array reflection class */
     private static final CstType ARRAY_REFLECT_TYPE =
         new CstType(Type.internClassName("java/lang/reflect/Array"));
 
     /**
-     * non-null; method constant for use in converting
-     * <code>multianewarray</code> instructions 
+     * {@code non-null;} method constant for use in converting
+     * {@code multianewarray} instructions 
      */
     private static final CstMethodRef MULTIANEWARRAY_METHOD =
         new CstMethodRef(ARRAY_REFLECT_TYPE,
@@ -61,34 +61,34 @@
                                     new CstUtf8("(Ljava/lang/Class;[I)" +
                                                 "Ljava/lang/Object;")));
 
-    /** non-null; {@link Ropper} controlling this instance */
+    /** {@code non-null;} {@link Ropper} controlling this instance */
     private final Ropper ropper;
 
-    /** non-null; method being converted */
+    /** {@code non-null;} method being converted */
     private final ConcreteMethod method;
 
-    /** non-null; translation advice */
+    /** {@code non-null;} translation advice */
     private final TranslationAdvice advice;
 
     /** max locals of the method */
     private final int maxLocals;
 
-    /** non-null; instructions for the rop basic block in-progress */
+    /** {@code non-null;} instructions for the rop basic block in-progress */
     private final ArrayList<Insn> insns;
 
-    /** non-null; catches for the block currently being processed */
+    /** {@code non-null;} catches for the block currently being processed */
     private TypeList catches;
 
     /** whether the catches have been used in an instruction */
     private boolean catchesUsed;
 
-    /** whether the block contains a <code>return</code> */
+    /** whether the block contains a {@code return} */
     private boolean returns;
 
     /** primary successor index */
     private int primarySuccessorIndex;
 
-    /** &gt;= 0; number of extra basic blocks required */
+    /** {@code >= 0;} number of extra basic blocks required */
     private int extraBlockCount;
 
     /** true if last processed block ends with a jsr or jsr_W*/
@@ -105,13 +105,13 @@
     private ReturnAddress returnAddress;
 
     /**
-     * null-ok; the appropriate <code>return</code> op or <code>null</code>
+     * {@code null-ok;} the appropriate {@code return} op or {@code null}
      * if it is not yet known 
      */
     private Rop returnOp;
 
     /**
-     * null-ok; the source position for the return block or <code>null</code>
+     * {@code null-ok;} the source position for the return block or {@code null}
      * if it is not yet known 
      */
     private SourcePosition returnPosition;
@@ -119,9 +119,9 @@
     /**
      * Constructs an instance.
      * 
-     * @param ropper non-null; ropper controlling this instance
-     * @param method non-null; method being converted
-     * @param advice non-null; translation advice to use
+     * @param ropper {@code non-null;} ropper controlling this instance
+     * @param method {@code non-null;} method being converted
+     * @param advice {@code non-null;} translation advice to use
      */
     public RopperMachine(Ropper ropper, ConcreteMethod method,
             TranslationAdvice advice) {
@@ -154,7 +154,7 @@
      * Gets the instructions array. It is shared and gets modified by
      * subsequent calls to this instance.
      * 
-     * @return non-null; the instructions array
+     * @return {@code non-null;} the instructions array
      */
     public ArrayList<Insn> getInsns() {
         return insns;
@@ -163,7 +163,7 @@
     /**
      * Gets the return opcode encountered, if any.
      * 
-     * @return null-ok; the return opcode
+     * @return {@code null-ok;} the return opcode
      */
     public Rop getReturnOp() {
         return returnOp;
@@ -172,7 +172,7 @@
     /**
      * Gets the return position, if known.
      * 
-     * @return null-ok; the return position
+     * @return {@code null-ok;} the return position
      */
     public SourcePosition getReturnPosition() {
         return returnPosition;
@@ -182,7 +182,7 @@
      * Gets ready to start working on a new block. This will clear the
      * {@link #insns} list, set {@link #catches}, reset whether it has
      * been used, reset whether the block contains a
-     * <code>return</code>, and reset {@link #primarySuccessorIndex}.
+     * {@code return}, and reset {@link #primarySuccessorIndex}.
      */
     public void startBlock(TypeList catches) {
         this.catches = catches;
@@ -201,7 +201,7 @@
      * Gets whether {@link #catches} was used. This indicates that the
      * last instruction in the block is one of the ones that can throw.
      * 
-     * @return whether <code>catches</code> has been used
+     * @return whether {@code catches} has been used
      */
     public boolean wereCatchesUsed() {
         return catchesUsed;
@@ -209,7 +209,7 @@
 
     /**
      * Gets whether the block just processed ended with a
-     * <code>return</code>.
+     * {@code return}.
      * 
      * @return whether the block returns
      */
@@ -220,12 +220,12 @@
     /**
      * Gets the primary successor index. This is the index into the
      * successors list where the primary may be found or
-     * <code>-1</code> if there are successors but no primary
+     * {@code -1} if there are successors but no primary
      * successor. This may return something other than
-     * <code>-1</code> in the case of an instruction with no
+     * {@code -1} in the case of an instruction with no
      * successors at all (primary or otherwise).
      * 
-     * @return &gt;= -1; the primary successor index
+     * @return {@code >= -1;} the primary successor index
      */
     public int getPrimarySuccessorIndex() {
         return primarySuccessorIndex;
@@ -236,7 +236,7 @@
      * block currently being translated. Each extra block should consist
      * of one instruction from the end of the original block.
      * 
-     * @return &gt;= 0; the number of extra blocks needed
+     * @return {@code >= 0;} the number of extra blocks needed
      */
     public int getExtraBlockCount() {
         return extraBlockCount;
@@ -259,16 +259,17 @@
     }
 
     /**
-     * @return true if a RET has ben encountered since the last call to 
-     * startBlock()
+     * @return {@code true} if a {@code ret} has ben encountered since
+     * the last call to {@code startBlock()}
      */
     public boolean hasRet() {
         return returnAddress != null;
     }
 
     /**
-     * @return null-ok; return address of a ret instruction if encountered
-     * since last call to startBlock(). null if no ret instruction encountered.
+     * @return {@code null-ok;} return address of a {@code ret}
+     * instruction if encountered since last call to startBlock().
+     * {@code null} if no ret instruction encountered.
      */
     public ReturnAddress getReturnAddress() {
         return returnAddress;
@@ -444,7 +445,7 @@
                     catches, MULTIANEWARRAY_METHOD);
             insns.add(insn);
 
-            // Add a move-result
+            // Add a move-result.
             rop = Rops.opMoveResult(MULTIANEWARRAY_METHOD.getPrototype()
                     .getReturnType());
             insn = new PlainInsn(rop, pos, objectReg, RegisterSpecList.EMPTY);
@@ -457,7 +458,6 @@
 
             opcode = ByteOps.CHECKCAST;
             sources = RegisterSpecList.make(objectReg);
-
         } else if (opcode == ByteOps.JSR) {
             // JSR has no Rop instruction
             hasJsr = true;
@@ -474,12 +474,14 @@
         }
 
         ropOpcode = jopToRopOpcode(opcode, cst);
-
         rop = Rops.ropFor(ropOpcode, destType, sources, cst);
 
         Insn moveResult = null;
         if (dest != null && rop.isCallLike()) {
-            // We're going to want to have a move-result in the next basic block
+            /*
+             * We're going to want to have a move-result in the next
+             * basic block.
+             */
             extraBlockCount++;
 
             moveResult = new PlainInsn(
@@ -488,8 +490,10 @@
 
             dest = null;
         } else if (dest != null && rop.canThrow()) {
-            // We're going to want to have a move-result-pseudo
-            // in the next basic block
+            /*
+             * We're going to want to have a move-result-pseudo in the
+             * next basic block.
+             */
             extraBlockCount++;
 
             moveResult = new PlainInsn(
@@ -599,11 +603,12 @@
         }
 
         /*
-         * If initValues is non-null, it means that the parser has seen a group
-         * of compatible constant initialization bytecodes that are applied to
-         * the current newarray. The action we take here is to convert these
-         * initialization bytecodes into a single fill-array-data ROP which lays
-         * out all the constant values in a table.
+         * If initValues is non-null, it means that the parser has
+         * seen a group of compatible constant initialization
+         * bytecodes that are applied to the current newarray. The
+         * action we take here is to convert these initialization
+         * bytecodes into a single fill-array-data ROP which lays out
+         * all the constant values in a table.
          */ 
         if (initValues != null) {
             extraBlockCount++;
@@ -619,9 +624,9 @@
      * instruction.
      * 
      * @param opcode the opcode being translated
-     * @param stackPointer &gt;= 0; the stack pointer after the instruction's
-     * arguments have been popped
-     * @return non-null; the sources
+     * @param stackPointer {@code >= 0;} the stack pointer after the
+     * instruction's arguments have been popped
+     * @return {@code non-null;} the sources
      */
     private RegisterSpecList getSources(int opcode, int stackPointer) {
         int count = argCount();
@@ -692,8 +697,8 @@
     /**
      * Sets or updates the information about the return block.
      * 
-     * @param op non-null; the opcode to use
-     * @param pos non-null; the position to use
+     * @param op {@code non-null;} the opcode to use
+     * @param pos {@code non-null;} the position to use
      */
     private void updateReturnOp(Rop op, SourcePosition pos) {
         if (op == null) {
@@ -723,9 +728,9 @@
     /**
      * Gets the register opcode for the given Java opcode.
      * 
-     * @param jop &gt;= 0; the Java opcode
-     * @param cst null-ok; the constant argument, if any
-     * @return &gt;= 0; the corresponding register opcode
+     * @param jop {@code >= 0;} the Java opcode
+     * @param cst {@code null-ok;} the constant argument, if any
+     * @return {@code >= 0;} the corresponding register opcode
      */
     private int jopToRopOpcode(int jop, Constant cst) {
         switch (jop) {
diff --git a/dx/src/com/android/dx/cf/code/Simulator.java b/dx/src/com/android/dx/cf/code/Simulator.java
index 3c90ee5..408e126 100644
--- a/dx/src/com/android/dx/cf/code/Simulator.java
+++ b/dx/src/com/android/dx/cf/code/Simulator.java
@@ -35,34 +35,37 @@
 
 /**
  * Class which knows how to simulate the effects of executing bytecode.
- * 
+ *
  * <p><b>Note:</b> This class is not thread-safe. If multiple threads
  * need to use a single instance, they must synchronize access explicitly
  * between themselves.</p>
  */
 public class Simulator {
-    /** non-null; canned error message for local variable table mismatches */
-    private static final String LOCAL_MISMATCH_ERROR = 
+    /**
+     * {@code non-null;} canned error message for local variable
+     * table mismatches
+     */
+    private static final String LOCAL_MISMATCH_ERROR =
         "This is symptomatic of .class transformation tools that ignore " +
         "local variable information.";
     
-    /** non-null; machine to use when simulating */
+    /** {@code non-null;} machine to use when simulating */
     private final Machine machine;
 
-    /** non-null; array of bytecode */
+    /** {@code non-null;} array of bytecode */
     private final BytecodeArray code;
 
-    /** non-null; local variable information */
+    /** {@code non-null;} local variable information */
     private final LocalVariableList localVariables;
 
-    /** non-null; visitor instance to use */
+    /** {@code non-null;} visitor instance to use */
     private final SimVisitor visitor;
 
     /**
      * Constructs an instance.
      * 
-     * @param machine non-null; machine to use when simulating
-     * @param method non-null; method data to use
+     * @param machine {@code non-null;} machine to use when simulating
+     * @param method {@code non-null;} method data to use
      */
     public Simulator(Machine machine, ConcreteMethod method) {
         if (machine == null) {
@@ -83,8 +86,8 @@
      * Simulates the effect of executing the given basic block. This modifies
      * the passed-in frame to represent the end result.
      * 
-     * @param bb non-null; the basic block
-     * @param frame non-null; frame to operate on
+     * @param bb {@code non-null;} the basic block
+     * @param frame {@code non-null;} frame to operate on
      */
     public void simulate(ByteBlock bb, Frame frame) {
         int end = bb.getEnd();
@@ -107,8 +110,8 @@
      * Simulates the effect of the instruction at the given offset, by
      * making appropriate calls on the given frame.
      * 
-     * @param offset &gt;= 0; offset of the instruction to simulate
-     * @param frame non-null; frame to operate on
+     * @param offset {@code >= 0;} offset of the instruction to simulate
+     * @param frame {@code non-null;} frame to operate on
      * @return the length of the instruction, in bytes
      */
     public int simulate(int offset, Frame frame) {
@@ -130,13 +133,13 @@
      */
     private class SimVisitor implements BytecodeArray.Visitor {
         /**
-         * non-null; machine instance to use (just to avoid excessive
-         * cross-object field access) 
+         * {@code non-null;} machine instance to use (just to avoid excessive
+         * cross-object field access)
          */
         private final Machine machine;
 
         /**
-         * null-ok; frame to use; set with each call to 
+         * {@code null-ok;} frame to use; set with each call to 
          * {@link Simulator#simulate}
          */
         private Frame frame;
@@ -155,7 +158,7 @@
         /**
          * Sets the frame to act on.
          * 
-         * @param frame non-null; the frame
+         * @param frame {@code non-null;} the frame
          */
         public void setFrame(Frame frame) {
             if (frame == null) {
@@ -255,25 +258,21 @@
                     /*
                      * Change the type (which is to be pushed) to
                      * reflect the actual component type of the array
-                     * being popped.
+                     * being popped, unless it turns out to be a
+                     * known-null, in which case we just use the type
+                     * implied by the original instruction.
                      */
-                    Type requireType = type.getArrayType();
-                    type = frame.getStack().peekType(1);
-                    if (type == Type.KNOWN_NULL) {
-                        /*
-                         * The type is a known-null: Just treat the
-                         * popped type as whatever is expected. In
-                         * reality, unless this frame is revisited
-                         * (due to a branch merge), execution will
-                         * result in the throwing of a
-                         * NullPointerException, but claiming the
-                         * expected type at here should be good enough
-                         * for the purposes at this level.
-                         */
-                        type = requireType;
+                    Type foundArrayType = frame.getStack().peekType(1);
+                    Type requireArrayType;
+
+                    if (foundArrayType != Type.KNOWN_NULL) {
+                        requireArrayType = foundArrayType;
+                        type = foundArrayType.getComponentType();
+                    } else {
+                        requireArrayType = type.getArrayType();
                     }
-                    type = type.getComponentType();
-                    machine.popArgs(frame, requireType, Type.INT);
+
+                    machine.popArgs(frame, requireArrayType, Type.INT);
                     break;
                 }
                 case ByteOps.IADD:
@@ -292,7 +291,7 @@
                 case ByteOps.IUSHR: {
                     machine.popArgs(frame, type, Type.INT);
                     break;
-                }                    
+                }
                 case ByteOps.LCMP: {
                     machine.popArgs(frame, Type.LONG, Type.LONG);
                     break;
@@ -308,8 +307,28 @@
                     break;
                 }
                 case ByteOps.IASTORE: {
-                    Type arrayType = type.getArrayType();
-                    machine.popArgs(frame, arrayType, Type.INT, type);
+                    /*
+                     * Change the type (which is the type of the
+                     * element) to reflect the actual component type
+                     * of the array being popped, unless it turns out
+                     * to be a known-null, in which case we just use
+                     * the type implied by the original instruction.
+                     * The category 1 vs. 2 thing here is that, if the
+                     * element type is category 2, we have to skip over
+                     * one extra stack slot to find the array.
+                     */
+                    Type foundArrayType =
+                        frame.getStack().peekType(type.isCategory1() ? 2 : 3);
+                    Type requireArrayType;
+
+                    if (foundArrayType != Type.KNOWN_NULL) {
+                        requireArrayType = foundArrayType;
+                        type = foundArrayType.getComponentType();
+                    } else {
+                        requireArrayType = type.getArrayType();
+                    }
+
+                    machine.popArgs(frame, requireArrayType, Type.INT, type);
                     break;
                 }
                 case ByteOps.POP2:
@@ -456,7 +475,7 @@
          * Checks whether the prototype is compatible with returning the
          * given type, and throws if not.
          * 
-         * @param encountered non-null; the encountered return type
+         * @param encountered {@code non-null;} the encountered return type
          */
         private void checkReturnType(Type encountered) {
             Type returnType = machine.getPrototype().getReturnType();
diff --git a/dx/src/com/android/dx/cf/code/SwitchList.java b/dx/src/com/android/dx/cf/code/SwitchList.java
index dc04137..fdd1596 100644
--- a/dx/src/com/android/dx/cf/code/SwitchList.java
+++ b/dx/src/com/android/dx/cf/code/SwitchList.java
@@ -21,15 +21,15 @@
 
 /**
  * List of (value, target) mappings representing the choices of a
- * <code>tableswitch</code> or <code>lookupswitch</code> instruction. It
+ * {@code tableswitch} or {@code lookupswitch} instruction. It
  * also holds the default target for the switch.
  */
 public final class SwitchList extends MutabilityControl {
-    /** non-null; list of test values */
+    /** {@code non-null;} list of test values */
     private final IntList values;
 
     /**
-     * non-null; list of targets corresponding to the test values; there
+     * {@code non-null;} list of targets corresponding to the test values; there
      * is always one extra element in the target list, to hold the
      * default target 
      */
@@ -41,7 +41,7 @@
     /**
      * Constructs an instance.
      * 
-     * @param size &gt;= 0; the number of elements to be in the table
+     * @param size {@code >= 0;} the number of elements to be in the table
      */
     public SwitchList(int size) {
         super(true);
@@ -61,7 +61,7 @@
     /**
      * Gets the size of the list.
      * 
-     * @return &gt;= 0; the list size
+     * @return {@code >= 0;} the list size
      */
     public int size() {
         return size;
@@ -70,7 +70,7 @@
     /**
      * Gets the indicated test value.
      * 
-     * @param n &gt;= 0;, &lt; size(); which index
+     * @param n {@code >= 0;}, &lt; size(); which index
      * @return the test value 
      */
     public int getValue(int n) {
@@ -78,11 +78,11 @@
     }
 
     /**
-     * Gets the indicated target. Asking for the target at <code>size()</code>
+     * Gets the indicated target. Asking for the target at {@code size()}
      * returns the default target.
      * 
-     * @param n &gt;= 0, &lt;= size(); which index
-     * @return &gt;= 0; the target
+     * @param n {@code >= 0, <= size();} which index
+     * @return {@code >= 0;} the target
      */
     public int getTarget(int n) {
         return targets.get(n);
@@ -90,9 +90,9 @@
 
     /**
      * Gets the default target. This is just a shorthand for
-     * <code>getTarget(size())</code>.
+     * {@code getTarget(size())}.
      * 
-     * @return &gt;= 0; the default target
+     * @return {@code >= 0;} the default target
      */
     public int getDefaultTarget() {
         return targets.get(size);
@@ -102,7 +102,7 @@
      * Gets the list of all targets. This includes one extra element at the
      * end of the list, which holds the default target.
      * 
-     * @return non-null; the target list
+     * @return {@code non-null;} the target list
      */
     public IntList getTargets() {
         return targets;
@@ -111,7 +111,7 @@
     /**
      * Gets the list of all case values.
      * 
-     * @return non-null; the case value list
+     * @return {@code non-null;} the case value list
      */
     public IntList getValues() {
         return values;
@@ -121,7 +121,7 @@
      * Sets the default target. It is only valid to call this method
      * when all the non-default elements have been set.
      * 
-     * @param target &gt;= 0; the absolute (not relative) default target
+     * @param target {@code >= 0;} the absolute (not relative) default target
      * address
      */
     public void setDefaultTarget(int target) {
@@ -142,7 +142,7 @@
      * Adds the given item.
      * 
      * @param value the test value
-     * @param target &gt;= 0; the absolute (not relative) target address
+     * @param target {@code >= 0;} the absolute (not relative) target address
      */
     public void add(int value, int target) {
         throwIfImmutable();
diff --git a/dx/src/com/android/dx/cf/code/ValueAwareMachine.java b/dx/src/com/android/dx/cf/code/ValueAwareMachine.java
index 4062c3b..43aab8a 100644
--- a/dx/src/com/android/dx/cf/code/ValueAwareMachine.java
+++ b/dx/src/com/android/dx/cf/code/ValueAwareMachine.java
@@ -30,7 +30,8 @@
     /**
      * Constructs an instance.
      * 
-     * @param prototype non-null; the prototype for the associated method
+     * @param prototype {@code non-null;} the prototype for the associated
+     * method
      */
     public ValueAwareMachine(Prototype prototype) {
         super(prototype);
diff --git a/dx/src/com/android/dx/cf/cst/ConstantPoolParser.java b/dx/src/com/android/dx/cf/cst/ConstantPoolParser.java
index 953981c..7cd9c9b 100644
--- a/dx/src/com/android/dx/cf/cst/ConstantPoolParser.java
+++ b/dx/src/com/android/dx/cf/cst/ConstantPoolParser.java
@@ -41,29 +41,29 @@
  * Parser for a constant pool embedded in a class file.
  */
 public final class ConstantPoolParser {
-    /** non-null; the bytes of the constant pool */
+    /** {@code non-null;} the bytes of the constant pool */
     private final ByteArray bytes;
 
-    /** non-null; actual parsed constant pool contents */
+    /** {@code non-null;} actual parsed constant pool contents */
     private final StdConstantPool pool;
 
-    /** non-null; byte offsets to each cst */
+    /** {@code non-null;} byte offsets to each cst */
     private final int[] offsets;
 
     /**
      * -1 || &gt;= 10; the end offset of this constant pool in the
-     * <code>byte[]</code> which it came from or <code>-1</code> if not
+     * {@code byte[]} which it came from or {@code -1} if not
      * yet parsed 
      */
     private int endOffset;
 
-    /** null-ok; parse observer, if any */
+    /** {@code null-ok;} parse observer, if any */
     private ParseObserver observer;
 
     /**
      * Constructs an instance.
      * 
-     * @param bytes non-null; the bytes of the file
+     * @param bytes {@code non-null;} the bytes of the file
      */
     public ConstantPoolParser(ByteArray bytes) {
         int size = bytes.getUnsignedShort(8); // constant_pool_count
@@ -77,17 +77,17 @@
     /**
      * Sets the parse observer for this instance.
      * 
-     * @param observer null-ok; the observer
+     * @param observer {@code null-ok;} the observer
      */
     public void setObserver(ParseObserver observer) {
         this.observer = observer;
     }
 
     /**
-     * Gets the end offset of this constant pool in the <code>byte[]</code>
+     * Gets the end offset of this constant pool in the {@code byte[]}
      * which it came from.
      * 
-     * @return &gt;= 10; the end offset
+     * @return {@code >= 10;} the end offset
      */
     public int getEndOffset() {
         parseIfNecessary();
@@ -97,7 +97,7 @@
     /**
      * Gets the actual constant pool.
      * 
-     * @return non-null; the constant pool
+     * @return {@code non-null;} the constant pool
      */
     public StdConstantPool getPool() {
         parseIfNecessary();
@@ -215,7 +215,7 @@
      * depends on.
      * 
      * @param idx which constant
-     * @return non-null; the parsed constant
+     * @return {@code non-null;} the parsed constant
      */
     private Constant parse0(int idx) {
         Constant cst = pool.getOrNull(idx);
@@ -316,7 +316,7 @@
      * Parses a utf8 constant.
      * 
      * @param at offset to the start of the constant (where the tag byte is)
-     * @return non-null; the parsed value
+     * @return {@code non-null;} the parsed value
      */
     private CstUtf8 parseUtf8(int at) {
         int length = bytes.getUnsignedShort(at + 1);
diff --git a/dx/src/com/android/dx/cf/cst/ConstantTags.java b/dx/src/com/android/dx/cf/cst/ConstantTags.java
index 64bc8d8..9febbdf 100644
--- a/dx/src/com/android/dx/cf/cst/ConstantTags.java
+++ b/dx/src/com/android/dx/cf/cst/ConstantTags.java
@@ -20,36 +20,36 @@
  * Tags for constant pool constants.
  */
 public interface ConstantTags {
-    /** tag for a <code>CONSTANT_Utf8_info</code> */
+    /** tag for a {@code CONSTANT_Utf8_info} */
     int CONSTANT_Utf8 = 1;
 
-    /** tag for a <code>CONSTANT_Integer_info</code> */
+    /** tag for a {@code CONSTANT_Integer_info} */
     int CONSTANT_Integer = 3;
 
-    /** tag for a <code>CONSTANT_Float_info</code> */
+    /** tag for a {@code CONSTANT_Float_info} */
     int CONSTANT_Float = 4;
 
-    /** tag for a <code>CONSTANT_Long_info</code> */
+    /** tag for a {@code CONSTANT_Long_info} */
     int CONSTANT_Long = 5;
 
-    /** tag for a <code>CONSTANT_Double_info</code> */
+    /** tag for a {@code CONSTANT_Double_info} */
     int CONSTANT_Double = 6;
 
-    /** tag for a <code>CONSTANT_Class_info</code> */
+    /** tag for a {@code CONSTANT_Class_info} */
     int CONSTANT_Class = 7;
 
-    /** tag for a <code>CONSTANT_String_info</code> */
+    /** tag for a {@code CONSTANT_String_info} */
     int CONSTANT_String = 8;
 
-    /** tag for a <code>CONSTANT_Fieldref_info</code> */
+    /** tag for a {@code CONSTANT_Fieldref_info} */
     int CONSTANT_Fieldref = 9;
 
-    /** tag for a <code>CONSTANT_Methodref_info</code> */
+    /** tag for a {@code CONSTANT_Methodref_info} */
     int CONSTANT_Methodref = 10;
 
-    /** tag for a <code>CONSTANT_InterfaceMethodref_info</code> */
+    /** tag for a {@code CONSTANT_InterfaceMethodref_info} */
     int CONSTANT_InterfaceMethodref = 11;
 
-    /** tag for a <code>CONSTANT_NameAndType_info</code> */
+    /** tag for a {@code CONSTANT_NameAndType_info} */
     int CONSTANT_NameAndType = 12;
 }
diff --git a/dx/src/com/android/dx/cf/direct/AnnotationParser.java b/dx/src/com/android/dx/cf/direct/AnnotationParser.java
index 5d80086..88e4cd2 100644
--- a/dx/src/com/android/dx/cf/direct/AnnotationParser.java
+++ b/dx/src/com/android/dx/cf/direct/AnnotationParser.java
@@ -51,23 +51,23 @@
  * Parser for annotations.
  */
 public final class AnnotationParser {
-    /** non-null; class file being parsed */
+    /** {@code non-null;} class file being parsed */
     private final DirectClassFile cf;
 
-    /** non-null; constant pool to use */
+    /** {@code non-null;} constant pool to use */
     private final ConstantPool pool;
 
-    /** non-null; bytes of the attribute data */
+    /** {@code non-null;} bytes of the attribute data */
     private final ByteArray bytes;
 
-    /** null-ok; parse observer, if any */
+    /** {@code null-ok;} parse observer, if any */
     private final ParseObserver observer;
 
-    /** non-null; input stream to parse from */
+    /** {@code non-null;} input stream to parse from */
     private final ByteArray.MyDataInputStream input;
 
     /**
-     * non-null; cursor for use when informing the observer of what
+     * {@code non-null;} cursor for use when informing the observer of what
      * was parsed
      */
     private int parseCursor;
@@ -75,10 +75,10 @@
     /**
      * Constructs an instance.
      * 
-     * @param cf non-null; class file to parse from
-     * @param offset &gt;= 0; offset into the class file data to parse at
-     * @param length &gt;= 0; number of bytes left in the attribute data
-     * @param observer null-ok; parse observer to notify, if any
+     * @param cf {@code non-null;} class file to parse from
+     * @param offset {@code >= 0;} offset into the class file data to parse at
+     * @param length {@code >= 0;} number of bytes left in the attribute data
+     * @param observer {@code null-ok;} parse observer to notify, if any
      */
     public AnnotationParser(DirectClassFile cf, int offset, int length,
             ParseObserver observer) {
@@ -95,9 +95,9 @@
     }
     
     /**
-     * Parses an annotation value (<code>element_value</code>) attribute.
+     * Parses an annotation value ({@code element_value}) attribute.
      * 
-     * @return non-null; the parsed constant value
+     * @return {@code non-null;} the parsed constant value
      */
     public Constant parseValueAttribute() {
         Constant result;
@@ -119,8 +119,8 @@
     /**
      * Parses a parameter annotation attribute.
      * 
-     * @param visibility non-null; visibility of the parsed annotations
-     * @return non-null; the parsed list of lists of annotations
+     * @param visibility {@code non-null;} visibility of the parsed annotations
+     * @return {@code non-null;} the parsed list of lists of annotations
      */
     public AnnotationsList parseParameterAttribute(
             AnnotationVisibility visibility) {
@@ -143,8 +143,8 @@
     /**
      * Parses an annotation attribute, per se.
      * 
-     * @param visibility non-null; visibility of the parsed annotations
-     * @return non-null; the list of annotations read from the attribute
+     * @param visibility {@code non-null;} visibility of the parsed annotations
+     * @return {@code non-null;} the list of annotations read from the attribute
      * data
      */
     public Annotations parseAnnotationAttribute(
@@ -168,8 +168,8 @@
     /**
      * Parses a list of annotation lists.
      * 
-     * @param visibility non-null; visibility of the parsed annotations
-     * @return non-null; the list of annotation lists read from the attribute
+     * @param visibility {@code non-null;} visibility of the parsed annotations
+     * @return {@code non-null;} the list of annotation lists read from the attribute
      * data
      */
     private AnnotationsList parseAnnotationsList(
@@ -203,8 +203,8 @@
     /**
      * Parses an annotation list.
      * 
-     * @param visibility non-null; visibility of the parsed annotations
-     * @return non-null; the list of annotations read from the attribute
+     * @param visibility {@code non-null;} visibility of the parsed annotations
+     * @return {@code non-null;} the list of annotations read from the attribute
      * data
      */
     private Annotations parseAnnotations(AnnotationVisibility visibility)
@@ -238,8 +238,8 @@
     /**
      * Parses a single annotation.
      * 
-     * @param visibility non-null; visibility of the parsed annotation
-     * @return non-null; the parsed annotation
+     * @param visibility {@code non-null;} visibility of the parsed annotation
+     * @return {@code non-null;} the parsed annotation
      */
     private Annotation parseAnnotation(AnnotationVisibility visibility)
             throws IOException {
@@ -278,7 +278,7 @@
     /**
      * Parses a {@link NameValuePair}.
      * 
-     * @return non-null; the parsed element
+     * @return {@code non-null;} the parsed element
      */
     private NameValuePair parseElement() throws IOException {
         requireLength(5);
@@ -304,7 +304,7 @@
     /**
      * Parses an annotation value.
      * 
-     * @return non-null; the parsed value
+     * @return {@code non-null;} the parsed value
      */
     private Constant parseValue() throws IOException {
         int tag = input.readUnsignedByte();
@@ -421,7 +421,7 @@
      * Helper for {@link #parseValue}, which parses a constant reference
      * and returns the referred-to constant value.
      * 
-     * @return non-null; the parsed value
+     * @return {@code non-null;} the parsed value
      */
     private Constant parseConstant() throws IOException {
         int constValueIndex = input.readUnsignedShort();
@@ -454,8 +454,8 @@
      * only be used (for efficiency sake) if the parse is known to be
      * observed.
      * 
-     * @param length &gt;= 0; number of bytes parsed
-     * @param message non-null; associated message
+     * @param length {@code >= 0;} number of bytes parsed
+     * @param message {@code non-null;} associated message
      */
     private void parsed(int length, String message) {
         observer.parsed(bytes, parseCursor, length, message);
@@ -464,7 +464,7 @@
 
     /**
      * Convenience wrapper that simply calls through to
-     * <code>observer.changeIndent()</code>.
+     * {@code observer.changeIndent()}.
      * 
      * @param indent the amount to change the indent by
      */
diff --git a/dx/src/com/android/dx/cf/direct/AttributeFactory.java b/dx/src/com/android/dx/cf/direct/AttributeFactory.java
index 420d741..d00a859 100644
--- a/dx/src/com/android/dx/cf/direct/AttributeFactory.java
+++ b/dx/src/com/android/dx/cf/direct/AttributeFactory.java
@@ -58,13 +58,13 @@
      * the name, and then does all the setup to call on to {@link #parse0},
      * which does the actual construction.
      * 
-     * @param cf non-null; class file to parse from
-     * @param context context to parse in; one of the <code>CTX_*</code>
+     * @param cf {@code non-null;} class file to parse from
+     * @param context context to parse in; one of the {@code CTX_*}
      * constants
-     * @param offset offset into <code>dcf</code>'s <code>bytes</code>
+     * @param offset offset into {@code dcf}'s {@code bytes}
      * to start parsing at
-     * @param observer null-ok; parse observer to report to, if any
-     * @return non-null; an appropriately-constructed {@link Attribute}
+     * @param observer {@code null-ok;} parse observer to report to, if any
+     * @return {@code non-null;} an appropriately-constructed {@link Attribute}
      */
     public final Attribute parse(DirectClassFile cf, int context, int offset,
                                  ParseObserver observer) {
@@ -108,15 +108,15 @@
      * an instance of {@link RawAttribute}. Subclasses are expected to
      * override this to do something better in most cases.
      * 
-     * @param cf non-null; class file to parse from
-     * @param context context to parse in; one of the <code>CTX_*</code>
+     * @param cf {@code non-null;} class file to parse from
+     * @param context context to parse in; one of the {@code CTX_*}
      * constants
-     * @param name non-null; the attribute name
-     * @param offset offset into <code>bytes</code> to start parsing at; this
+     * @param name {@code non-null;} the attribute name
+     * @param offset offset into {@code bytes} to start parsing at; this
      * is the offset to the start of attribute data, not to the header
      * @param length the length of the attribute data
-     * @param observer null-ok; parse observer to report to, if any
-     * @return non-null; an appropriately-constructed {@link Attribute}
+     * @param observer {@code null-ok;} parse observer to report to, if any
+     * @return {@code non-null;} an appropriately-constructed {@link Attribute}
      */
     protected Attribute parse0(DirectClassFile cf, int context, String name,
                                int offset, int length,
diff --git a/dx/src/com/android/dx/cf/direct/AttributeListParser.java b/dx/src/com/android/dx/cf/direct/AttributeListParser.java
index 7652265..2715e6a 100644
--- a/dx/src/com/android/dx/cf/direct/AttributeListParser.java
+++ b/dx/src/com/android/dx/cf/direct/AttributeListParser.java
@@ -27,7 +27,7 @@
  * Parser for lists of attributes.
  */
 final /*package*/ class AttributeListParser {
-    /** non-null; the class file to parse from */
+    /** {@code non-null;} the class file to parse from */
     private final DirectClassFile cf;
 
     /** attribute parsing context */
@@ -36,26 +36,26 @@
     /** offset in the byte array of the classfile to the start of the list */
     private final int offset;
 
-    /** non-null; attribute factory to use */
+    /** {@code non-null;} attribute factory to use */
     private final AttributeFactory attributeFactory;
 
-    /** non-null; list of parsed attributes */
+    /** {@code non-null;} list of parsed attributes */
     private final StdAttributeList list;
 
-    /** &gt;= -1; the end offset of this list in the byte array of the
-     * classfile, or <code>-1</code> if not yet parsed */
+    /** {@code >= -1;} the end offset of this list in the byte array of the
+     * classfile, or {@code -1} if not yet parsed */
     private int endOffset;
 
-    /** null-ok; parse observer, if any */
+    /** {@code null-ok;} parse observer, if any */
     private ParseObserver observer;
 
     /**
      * Constructs an instance.
      *
-     * @param cf non-null; class file to parse from
+     * @param cf {@code non-null;} class file to parse from
      * @param context attribute parsing context (see {@link AttributeFactory})
-     * @param offset offset in <code>bytes</code> to the start of the list
-     * @param attributeFactory non-null; attribute factory to use
+     * @param offset offset in {@code bytes} to the start of the list
+     * @param attributeFactory {@code non-null;} attribute factory to use
      */
     public AttributeListParser(DirectClassFile cf, int context, int offset,
                                AttributeFactory attributeFactory) {
@@ -80,17 +80,17 @@
     /**
      * Sets the parse observer for this instance.
      *
-     * @param observer null-ok; the observer
+     * @param observer {@code null-ok;} the observer
      */
     public void setObserver(ParseObserver observer) {
         this.observer = observer;
     }
 
     /**
-     * Gets the end offset of this constant pool in the <code>byte[]</code>
+     * Gets the end offset of this constant pool in the {@code byte[]}
      * which it came from.
      *
-     * @return &gt;= 0; the end offset
+     * @return {@code >= 0;} the end offset
      */
     public int getEndOffset() {
         parseIfNecessary();
@@ -100,7 +100,7 @@
     /**
      * Gets the parsed list.
      *
-     * @return non-null; the list
+     * @return {@code non-null;} the list
      */
     public StdAttributeList getList() {
         parseIfNecessary();
diff --git a/dx/src/com/android/dx/cf/direct/ClassPathOpener.java b/dx/src/com/android/dx/cf/direct/ClassPathOpener.java
index d302349..927e9bd 100644
--- a/dx/src/com/android/dx/cf/direct/ClassPathOpener.java
+++ b/dx/src/com/android/dx/cf/direct/ClassPathOpener.java
@@ -36,9 +36,9 @@
  */
 public class ClassPathOpener {
 
-    /** non-null; pathname to start with */
+    /** {@code non-null;} pathname to start with */
     private final String pathname;
-    /** non-null; callback interface */
+    /** {@code non-null;} callback interface */
     private final Consumer consumer;
     /**
      * If true, sort such that classes appear before their inner
@@ -48,20 +48,20 @@
     private final boolean sort;
 
     /**
-     * Callback interface for <code>ClassOpener</code>.
+     * Callback interface for {@code ClassOpener}.
      */
     public interface Consumer {
 
         /**
          * Provides the file name and byte array for a class path element.
          *
-         * @param name non-null; filename of element. May not be a valid
+         * @param name {@code non-null;} filename of element. May not be a valid
          * filesystem path.
          *
-         * @param bytes non-null; file data
+         * @param bytes {@code non-null;} file data
          * @return true on success. Result is or'd with all other results
-         * from <code>processFileBytes</code> and returned to the caller
-         * of <code>process()</code>.
+         * from {@code processFileBytes} and returned to the caller
+         * of {@code process()}.
          */
         boolean processFileBytes(String name, byte[] bytes);
 
@@ -69,14 +69,14 @@
          * Informs consumer that an exception occurred while processing
          * this path element. Processing will continue if possible.
          *
-         * @param ex non-null; exception
+         * @param ex {@code non-null;} exception
          */
         void onException(Exception ex);
 
         /**
          * Informs consumer that processing of an archive file has begun.
          *
-         * @param file non-null; archive file being processed
+         * @param file {@code non-null;} archive file being processed
          */
         void onProcessArchiveStart(File file);
     }
@@ -84,11 +84,11 @@
     /**
      * Constructs an instance.
      *
-     * @param pathname non-null; path element to process
+     * @param pathname {@code non-null;} path element to process
      * @param sort if true, sort such that classes appear before their inner
      * classes and "package-info" occurs before all other classes in that
      * package.
-     * @param consumer non-null; callback interface
+     * @param consumer {@code non-null;} callback interface
      */
     public ClassPathOpener(String pathname, boolean sort, Consumer consumer) {
         this.pathname = pathname;
@@ -100,7 +100,7 @@
      * Processes a path element.
      *
      * @return the OR of all return values
-     * from <code>Consumer.processFileBytes()</code>.
+     * from {@code Consumer.processFileBytes()}.
      */
     public boolean process() {
         File file = new File(pathname);
@@ -111,7 +111,7 @@
     /**
      * Processes one file.
      *
-     * @param file non-null; the file to process
+     * @param file {@code non-null;} the file to process
      * @param topLevel whether this is a top-level file (that is,
      * specified directly on the commandline)
      * @return whether any processing actually happened
@@ -142,9 +142,9 @@
      * Sorts java class names such that outer classes preceed their inner
      * classes and "package-info" preceeds all other classes in its package.
      *
-     * @param a non-null; first class name
-     * @param b non-null; second class name
-     * @return <code>compareTo()</code>-style result
+     * @param a {@code non-null;} first class name
+     * @param b {@code non-null;} second class name
+     * @return {@code compareTo()}-style result
      */
     private static int compareClassNames(String a, String b) {
         // Ensure inner classes sort second
@@ -164,7 +164,7 @@
     /**
      * Processes a directory recursively.
      *
-     * @param dir non-null; file representing the directory
+     * @param dir {@code non-null;} file representing the directory
      * @param topLevel whether this is a top-level directory (that is,
      * specified directly on the commandline)
      * @return whether any processing actually happened
@@ -194,10 +194,10 @@
     }
 
     /**
-     * Processes the contents of an archive (<code>.zip</code>,
-     * <code>.jar</code>, or <code>.apk</code>).
+     * Processes the contents of an archive ({@code .zip},
+     * {@code .jar}, or {@code .apk}).
      *
-     * @param file non-null; archive file to process
+     * @param file {@code non-null;} archive file to process
      * @return whether any processing actually happened
      * @throws IOException on i/o problem
      */
@@ -220,8 +220,7 @@
 
         consumer.onProcessArchiveStart(file);
 
-        for (ZipEntry one: entriesList) {
-
+        for (ZipEntry one : entriesList) {
             if (one.isDirectory()) {
                 continue;
             }
diff --git a/dx/src/com/android/dx/cf/direct/CodeObserver.java b/dx/src/com/android/dx/cf/direct/CodeObserver.java
index 950147f..952f1bc 100644
--- a/dx/src/com/android/dx/cf/direct/CodeObserver.java
+++ b/dx/src/com/android/dx/cf/direct/CodeObserver.java
@@ -39,17 +39,17 @@
  * Bytecode visitor to use when "observing" bytecode getting parsed.
  */
 public class CodeObserver implements BytecodeArray.Visitor {
-    /** non-null; actual array of bytecode */
+    /** {@code non-null;} actual array of bytecode */
     private final ByteArray bytes;
 
-    /** non-null; observer to inform of parsing */
+    /** {@code non-null;} observer to inform of parsing */
     private final ParseObserver observer;
 
     /**
      * Constructs an instance.
      * 
-     * @param bytes non-null; actual array of bytecode
-     * @param observer non-null; observer to inform of parsing
+     * @param bytes {@code non-null;} actual array of bytecode
+     * @param observer {@code non-null;} observer to inform of parsing
      */
     public CodeObserver(ByteArray bytes, ParseObserver observer) {
         if (bytes == null) {
@@ -218,8 +218,8 @@
     }
 
     /**
-     * Helper for {code #visitConstant} where the constant is an
-     * <code>int</code>.
+     * Helper for {@link #visitConstant} where the constant is an
+     * {@code int}.
      * 
      * @param opcode the opcode
      * @param offset offset to the instruction
@@ -245,8 +245,8 @@
     }
 
     /**
-     * Helper for {code #visitConstant} where the constant is a
-     * <code>long</code>.
+     * Helper for {@link #visitConstant} where the constant is a
+     * {@code long}.
      * 
      * @param opcode the opcode
      * @param offset offset to the instruction
@@ -269,8 +269,8 @@
     }
 
     /**
-     * Helper for {code #visitConstant} where the constant is a
-     * <code>float</code>.
+     * Helper for {@link #visitConstant} where the constant is a
+     * {@code float}.
      * 
      * @param opcode the opcode
      * @param offset offset to the instruction
@@ -287,8 +287,8 @@
     }
 
     /**
-     * Helper for {code #visitConstant} where the constant is a
-     * <code>double</code>.
+     * Helper for {@link #visitConstant} where the constant is a
+     * {@code double}.
      * 
      * @param opcode the opcode
      * @param offset offset to the instruction
diff --git a/dx/src/com/android/dx/cf/direct/DirectClassFile.java b/dx/src/com/android/dx/cf/direct/DirectClassFile.java
index e4751a4..ac227fa 100644
--- a/dx/src/com/android/dx/cf/direct/DirectClassFile.java
+++ b/dx/src/com/android/dx/cf/direct/DirectClassFile.java
@@ -38,14 +38,14 @@
 import com.android.dx.util.Hex;
 
 /**
- * Class file with info taken from a <code>byte[]</code> or slice thereof.
+ * Class file with info taken from a {@code byte[]} or slice thereof.
  */
 public class DirectClassFile implements ClassFile {
     /** the expected value of the ClassFile.magic field */
     private static final int CLASS_FILE_MAGIC = 0xcafebabe;
 
     /**
-     * minimum <code>.class</code> file major version
+     * minimum {@code .class} file major version
      * 
      * The class file definition (vmspec/2nd-edition) says:
      * 
@@ -64,92 +64,92 @@
      */
     private static final int CLASS_FILE_MIN_MAJOR_VERSION = 45;
 
-    /** maximum <code>.class</code> file major version */
+    /** maximum {@code .class} file major version */
     private static final int CLASS_FILE_MAX_MAJOR_VERSION = 50;
 
-    /** maximum <code>.class</code> file minor version */
+    /** maximum {@code .class} file minor version */
     private static final int CLASS_FILE_MAX_MINOR_VERSION = 0;
 
     /**
-     * non-null; the file path for the class, excluding any base directory
+     * {@code non-null;} the file path for the class, excluding any base directory
      * specification 
      */
     private final String filePath;
 
-    /** non-null; the bytes of the file */
+    /** {@code non-null;} the bytes of the file */
     private final ByteArray bytes;
 
     /**
      * whether to be strict about parsing; if
-     * <code>false</code>, this avoids doing checks that only exist
+     * {@code false}, this avoids doing checks that only exist
      * for purposes of verification (such as magic number matching and
      * path-package consistency checking) 
      */
     private final boolean strictParse;
 
     /**
-     * null-ok; the constant pool; only ever <code>null</code>
+     * {@code null-ok;} the constant pool; only ever {@code null}
      * before the constant pool is successfully parsed 
      */
     private StdConstantPool pool;
 
     /**
-     * the class file field <code>access_flags</code>; will be <code>-1</code>
+     * the class file field {@code access_flags}; will be {@code -1}
      * before the file is successfully parsed 
      */
     private int accessFlags;
 
     /**
-     * null-ok; the class file field <code>this_class</code>,
-     * interpreted as a type constant; only ever <code>null</code>
+     * {@code null-ok;} the class file field {@code this_class},
+     * interpreted as a type constant; only ever {@code null}
      * before the file is successfully parsed
      */
     private CstType thisClass;
 
     /**
-     * null-ok; the class file field <code>super_class</code>, interpreted
+     * {@code null-ok;} the class file field {@code super_class}, interpreted
      * as a type constant if non-zero 
      */
     private CstType superClass;
 
     /**
-     * null-ok; the class file field <code>interfaces</code>; only
-     * ever <code>null</code> before the file is successfully
+     * {@code null-ok;} the class file field {@code interfaces}; only
+     * ever {@code null} before the file is successfully
      * parsed 
      */
     private TypeList interfaces;
 
     /**
-     * null-ok; the class file field <code>fields</code>; only ever
-     * <code>null</code> before the file is successfully parsed 
+     * {@code null-ok;} the class file field {@code fields}; only ever
+     * {@code null} before the file is successfully parsed 
      */
     private FieldList fields;
 
     /**
-     * null-ok; the class file field <code>methods</code>; only ever
-     * <code>null</code> before the file is successfully parsed 
+     * {@code null-ok;} the class file field {@code methods}; only ever
+     * {@code null} before the file is successfully parsed 
      */
     private MethodList methods;
 
     /**
-     * null-ok; the class file field <code>attributes</code>; only
-     * ever <code>null</code> before the file is successfully
+     * {@code null-ok;} the class file field {@code attributes}; only
+     * ever {@code null} before the file is successfully
      * parsed 
      */
     private StdAttributeList attributes;
 
-    /** null-ok; attribute factory, if any */
+    /** {@code null-ok;} attribute factory, if any */
     private AttributeFactory attributeFactory;
 
-    /** null-ok; parse observer, if any */
+    /** {@code null-ok;} parse observer, if any */
     private ParseObserver observer;
 
     /**
-     * Returns the string form of an object or <code>"(none)"</code>
-     * (rather than <code>"null"</code>) for <code>null</code>.
+     * Returns the string form of an object or {@code "(none)"}
+     * (rather than {@code "null"}) for {@code null}.
      * 
-     * @param obj null-ok; the object to stringify
-     * @return non-null; the appropriate string form
+     * @param obj {@code null-ok;} the object to stringify
+     * @return {@code non-null;} the appropriate string form
      */
     public static String stringOrNone(Object obj) {
         if (obj == null) {
@@ -162,11 +162,11 @@
     /**
      * Constructs an instance.
      * 
-     * @param bytes non-null; the bytes of the file
-     * @param filePath non-null; the file path for the class,
+     * @param bytes {@code non-null;} the bytes of the file
+     * @param filePath {@code non-null;} the file path for the class,
      * excluding any base directory specification
      * @param strictParse whether to be strict about parsing; if
-     * <code>false</code>, this avoids doing checks that only exist
+     * {@code false}, this avoids doing checks that only exist
      * for purposes of verification (such as magic number matching and
      * path-package consistency checking)
      */
@@ -189,11 +189,11 @@
     /**
      * Constructs an instance.
      * 
-     * @param bytes non-null; the bytes of the file
-     * @param filePath non-null; the file path for the class,
+     * @param bytes {@code non-null;} the bytes of the file
+     * @param filePath {@code non-null;} the file path for the class,
      * excluding any base directory specification
      * @param strictParse whether to be strict about parsing; if
-     * <code>false</code>, this avoids doing checks that only exist
+     * {@code false}, this avoids doing checks that only exist
      * for purposes of verification (such as magic number matching and
      * path-package consistency checking)
      */
@@ -205,7 +205,7 @@
     /**
      * Sets the parse observer for this instance.
      * 
-     * @param observer null-ok; the observer
+     * @param observer {@code null-ok;} the observer
      */
     public void setObserver(ParseObserver observer) {
         this.observer = observer;
@@ -214,7 +214,7 @@
     /**
      * Sets the attribute factory to use.
      * 
-     * @param attributeFactory non-null; the attribute factory
+     * @param attributeFactory {@code non-null;} the attribute factory
      */
     public void setAttributeFactory(AttributeFactory attributeFactory) {
         if (attributeFactory == null) {
@@ -227,7 +227,7 @@
     /**
      * Gets the {@link ByteArray} that this instance's data comes from.
      * 
-     * @return non-null; the bytes
+     * @return {@code non-null;} the bytes
      */
     public ByteArray getBytes() {
         return bytes;
@@ -317,12 +317,12 @@
      * list of constant pool indices for classes, which are in turn
      * translated to type constants. Instance construction will fail
      * if any of the (alleged) indices turn out not to refer to
-     * constant pool entries of type <code>Class</code>.
+     * constant pool entries of type {@code Class}.
      * 
      * @param offset offset into {@link #bytes} for the start of the
      * data
      * @param size number of elements in the list (not number of bytes)
-     * @return non-null; an appropriately-constructed class list
+     * @return {@code non-null;} an appropriately-constructed class list
      */
     public TypeList makeTypeList(int offset, int size) {
         if (size == 0) {
@@ -337,7 +337,7 @@
     }
 
     /**
-     * Gets the class file field <code>magic</code>, but without doing any
+     * Gets the class file field {@code magic}, but without doing any
      * checks or parsing first.
      * 
      * @return the magic value
@@ -347,7 +347,7 @@
     }
 
     /**
-     * Gets the class file field <code>minor_version</code>, but
+     * Gets the class file field {@code minor_version}, but
      * without doing any checks or parsing first.
      * 
      * @return the minor version
@@ -357,7 +357,7 @@
     }
 
     /**
-     * Gets the class file field <code>major_version</code>, but
+     * Gets the class file field {@code major_version}, but
      * without doing any checks or parsing first.
      * 
      * @return the major version
@@ -554,27 +554,27 @@
      * which are in turn returned as type constants. Instance
      * construction will fail if any of the (alleged) indices turn out
      * not to refer to constant pool entries of type
-     * <code>Class</code>.
+     * {@code Class}.
      */
     private static class DcfTypeList implements TypeList {
-        /** non-null; array containing the data */
+        /** {@code non-null;} array containing the data */
         private final ByteArray bytes;
         
         /** number of elements in the list (not number of bytes) */
         private final int size;
 
-        /** non-null; the constant pool */
+        /** {@code non-null;} the constant pool */
         private final StdConstantPool pool;
 
         /**
          * Constructs an instance.
          * 
-         * @param bytes non-null; original classfile's bytes
+         * @param bytes {@code non-null;} original classfile's bytes
          * @param offset offset into {@link #bytes} for the start of the
          * data
          * @param size number of elements in the list (not number of bytes)
-         * @param pool non-null; the constant pool to use
-         * @param observer null-ok; parse observer to use, if any
+         * @param pool {@code non-null;} the constant pool to use
+         * @param observer {@code null-ok;} parse observer to use, if any
          */
         public DcfTypeList(ByteArray bytes, int offset, int size,
                 StdConstantPool pool, ParseObserver observer) {
diff --git a/dx/src/com/android/dx/cf/direct/FieldListParser.java b/dx/src/com/android/dx/cf/direct/FieldListParser.java
index 06dcc41..24ba7e0 100644
--- a/dx/src/com/android/dx/cf/direct/FieldListParser.java
+++ b/dx/src/com/android/dx/cf/direct/FieldListParser.java
@@ -28,16 +28,16 @@
  * Parser for lists of fields in a class file.
  */
 final /*package*/ class FieldListParser extends MemberListParser {
-    /** non-null; list in progress */
+    /** {@code non-null;} list in progress */
     private final StdFieldList fields;
 
     /**
      * Constructs an instance.
      * 
-     * @param cf non-null; the class file to parse from
-     * @param definer non-null; class being defined
-     * @param offset offset in <code>bytes</code> to the start of the list
-     * @param attributeFactory non-null; attribute factory to use
+     * @param cf {@code non-null;} the class file to parse from
+     * @param definer {@code non-null;} class being defined
+     * @param offset offset in {@code bytes} to the start of the list
+     * @param attributeFactory {@code non-null;} attribute factory to use
      */
     public FieldListParser(DirectClassFile cf, CstType definer, int offset,
             AttributeFactory attributeFactory) {
@@ -48,7 +48,7 @@
     /**
      * Gets the parsed list.
      * 
-     * @return non-null; the parsed list
+     * @return {@code non-null;} the parsed list
      */
     public StdFieldList getList() {
         parseIfNecessary();
diff --git a/dx/src/com/android/dx/cf/direct/MemberListParser.java b/dx/src/com/android/dx/cf/direct/MemberListParser.java
index 3c0bfa8..a0023c6 100644
--- a/dx/src/com/android/dx/cf/direct/MemberListParser.java
+++ b/dx/src/com/android/dx/cf/direct/MemberListParser.java
@@ -32,32 +32,32 @@
  * Parser for lists of class file members (that is, fields and methods).
  */
 abstract /*package*/ class MemberListParser {
-    /** non-null; the class file to parse from */
+    /** {@code non-null;} the class file to parse from */
     private final DirectClassFile cf;
 
-    /** non-null; class being defined */
+    /** {@code non-null;} class being defined */
     private final CstType definer;
 
     /** offset in the byte array of the classfile to the start of the list */
     private final int offset;
 
-    /** non-null; attribute factory to use */
+    /** {@code non-null;} attribute factory to use */
     private final AttributeFactory attributeFactory;
 
-    /** &gt;= -1; the end offset of this list in the byte array of the
-     * classfile, or <code>-1</code> if not yet parsed */
+    /** {@code >= -1;} the end offset of this list in the byte array of the
+     * classfile, or {@code -1} if not yet parsed */
     private int endOffset;
 
-    /** null-ok; parse observer, if any */
+    /** {@code null-ok;} parse observer, if any */
     private ParseObserver observer;
 
     /**
      * Constructs an instance.
      *
-     * @param cf non-null; the class file to parse from
-     * @param definer non-null; class being defined
-     * @param offset offset in <code>bytes</code> to the start of the list
-     * @param attributeFactory non-null; attribute factory to use
+     * @param cf {@code non-null;} the class file to parse from
+     * @param definer {@code non-null;} class being defined
+     * @param offset offset in {@code bytes} to the start of the list
+     * @param attributeFactory {@code non-null;} attribute factory to use
      */
     public MemberListParser(DirectClassFile cf, CstType definer,
             int offset, AttributeFactory attributeFactory) {
@@ -81,10 +81,10 @@
     }
 
     /**
-     * Gets the end offset of this constant pool in the <code>byte[]</code>
+     * Gets the end offset of this constant pool in the {@code byte[]}
      * which it came from.
      *
-     * @return &gt;= 0; the end offset
+     * @return {@code >= 0;} the end offset
      */
     public int getEndOffset() {
         parseIfNecessary();
@@ -94,7 +94,7 @@
     /**
      * Sets the parse observer for this instance.
      *
-     * @param observer null-ok; the observer
+     * @param observer {@code null-ok;} the observer
      */
     public final void setObserver(ParseObserver observer) {
         this.observer = observer;
@@ -122,7 +122,7 @@
     /**
      * Gets the class file being defined.
      *
-     * @return non-null; the class
+     * @return {@code non-null;} the class
      */
     protected final CstType getDefiner() {
         return definer;
@@ -132,7 +132,7 @@
      * Gets the human-oriented name for what this instance is parsing.
      * Subclasses must override this method.
      * 
-     * @return non-null; the human oriented name
+     * @return {@code non-null;} the human oriented name
      */
     protected abstract String humanName();
 
@@ -141,15 +141,15 @@
      * Subclasses must override this method.
      *
      * @param accessFlags the flags
-     * @return non-null; the string form
+     * @return {@code non-null;} the string form
      */
     protected abstract String humanAccessFlags(int accessFlags);
 
     /**
-     * Gets the <code>CTX_*</code> constant to use when parsing attributes.
+     * Gets the {@code CTX_*} constant to use when parsing attributes.
      * Subclasses must override this method.
      * 
-     * @return non-null; the human oriented name
+     * @return {@code non-null;} the human oriented name
      */
     protected abstract int getAttributeContext();
 
@@ -157,11 +157,11 @@
      * Sets an element in the list. Subclasses must override this method.
      *
      * @param n which element
-     * @param accessFlags the <code>access_flags</code>
+     * @param accessFlags the {@code access_flags}
      * @param nat the interpreted name and type (based on the two
-     * <code>*_index</code> fields)
+     * {@code *_index} fields)
      * @param attributes list of parsed attributes
-     * @return non-null; the constructed member
+     * @return {@code non-null;} the constructed member
      */
     protected abstract Member set(int n, int accessFlags, CstNat nat,
             AttributeList attributes);
diff --git a/dx/src/com/android/dx/cf/direct/MethodListParser.java b/dx/src/com/android/dx/cf/direct/MethodListParser.java
index 9ca8ba6..6ab1aba 100644
--- a/dx/src/com/android/dx/cf/direct/MethodListParser.java
+++ b/dx/src/com/android/dx/cf/direct/MethodListParser.java
@@ -28,16 +28,16 @@
  * Parser for lists of methods in a class file.
  */
 final /*package*/ class MethodListParser extends MemberListParser {
-    /** non-null; list in progress */
+    /** {@code non-null;} list in progress */
     final private StdMethodList methods;
 
     /**
      * Constructs an instance.
      * 
-     * @param cf non-null; the class file to parse from
-     * @param definer non-null; class being defined
-     * @param offset offset in <code>bytes</code> to the start of the list
-     * @param attributeFactory non-null; attribute factory to use
+     * @param cf {@code non-null;} the class file to parse from
+     * @param definer {@code non-null;} class being defined
+     * @param offset offset in {@code bytes} to the start of the list
+     * @param attributeFactory {@code non-null;} attribute factory to use
      */
     public MethodListParser(DirectClassFile cf, CstType definer,
             int offset, AttributeFactory attributeFactory) {
@@ -48,7 +48,7 @@
     /**
      * Gets the parsed list.
      * 
-     * @return non-null; the parsed list
+     * @return {@code non-null;} the parsed list
      */
     public StdMethodList getList() {
         parseIfNecessary();
diff --git a/dx/src/com/android/dx/cf/direct/StdAttributeFactory.java b/dx/src/com/android/dx/cf/direct/StdAttributeFactory.java
index ab0e2f7..da12a4e 100644
--- a/dx/src/com/android/dx/cf/direct/StdAttributeFactory.java
+++ b/dx/src/com/android/dx/cf/direct/StdAttributeFactory.java
@@ -65,7 +65,7 @@
  */
 public class StdAttributeFactory
     extends AttributeFactory {
-    /** non-null; shared instance of this class */
+    /** {@code non-null;} shared instance of this class */
     public static final StdAttributeFactory THE_ONE =
         new StdAttributeFactory();
 
@@ -191,7 +191,7 @@
     }
 
     /**
-     * Parses an <code>AnnotationDefault</code> attribute.
+     * Parses an {@code AnnotationDefault} attribute.
      */
     private Attribute annotationDefault(DirectClassFile cf,
             int offset, int length, ParseObserver observer) {
@@ -207,7 +207,7 @@
     }
 
     /**
-     * Parses a <code>Code</code> attribute.
+     * Parses a {@code Code} attribute.
      */
     private Attribute code(DirectClassFile cf, int offset, int length,
             ParseObserver observer) {
@@ -311,7 +311,7 @@
     }
 
     /**
-     * Parses a <code>ConstantValue</code> attribute.
+     * Parses a {@code ConstantValue} attribute.
      */
     private Attribute constantValue(DirectClassFile cf, int offset, int length,
             ParseObserver observer) {
@@ -333,7 +333,7 @@
     }
 
     /**
-     * Parses a <code>Deprecated</code> attribute.
+     * Parses a {@code Deprecated} attribute.
      */
     private Attribute deprecated(DirectClassFile cf, int offset, int length,
             ParseObserver observer) {
@@ -345,7 +345,7 @@
     }
 
     /**
-     * Parses an <code>EnclosingMethod</code> attribute.
+     * Parses an {@code EnclosingMethod} attribute.
      */
     private Attribute enclosingMethod(DirectClassFile cf, int offset,
             int length, ParseObserver observer) {
@@ -374,7 +374,7 @@
     }
 
     /**
-     * Parses an <code>Exceptions</code> attribute.
+     * Parses an {@code Exceptions} attribute.
      */
     private Attribute exceptions(DirectClassFile cf, int offset, int length,
             ParseObserver observer) {
@@ -402,7 +402,7 @@
     }
 
     /**
-     * Parses an <code>InnerClasses</code> attribute.
+     * Parses an {@code InnerClasses} attribute.
      */
     private Attribute innerClasses(DirectClassFile cf, int offset, int length,
             ParseObserver observer) {
@@ -459,7 +459,7 @@
     }
 
     /**
-     * Parses a <code>LineNumberTable</code> attribute.
+     * Parses a {@code LineNumberTable} attribute.
      */
     private Attribute lineNumberTable(DirectClassFile cf, int offset,
             int length, ParseObserver observer) {
@@ -500,7 +500,7 @@
     }
 
     /**
-     * Parses a <code>LocalVariableTable</code> attribute.
+     * Parses a {@code LocalVariableTable} attribute.
      */
     private Attribute localVariableTable(DirectClassFile cf, int offset,
             int length, ParseObserver observer) {
@@ -523,7 +523,7 @@
     }
 
     /**
-     * Parses a <code>LocalVariableTypeTable</code> attribute.
+     * Parses a {@code LocalVariableTypeTable} attribute.
      */
     private Attribute localVariableTypeTable(DirectClassFile cf, int offset,
             int length, ParseObserver observer) {
@@ -546,15 +546,15 @@
     }
 
     /**
-     * Parse the table part of either a <code>LocalVariableTable</code>
-     * or a <code>LocalVariableTypeTable</code>.
+     * Parse the table part of either a {@code LocalVariableTable}
+     * or a {@code LocalVariableTypeTable}.
      * 
-     * @param bytes non-null; bytes to parse, which should <i>only</i>
+     * @param bytes {@code non-null;} bytes to parse, which should <i>only</i>
      * contain the table data (no header)
-     * @param pool non-null; constant pool to use
-     * @param count &gt;= 0; the number of entries
-     * @param typeTable <code>true</code> iff this is for a type table
-     * @return non-null; the constructed list
+     * @param pool {@code non-null;} constant pool to use
+     * @param count {@code >= 0;} the number of entries
+     * @param typeTable {@code true} iff this is for a type table
+     * @return {@code non-null;} the constructed list
      */
     private LocalVariableList parseLocalVariables(ByteArray bytes,
             ConstantPool pool, ParseObserver observer, int count,
@@ -604,7 +604,7 @@
     }
 
     /**
-     * Parses a <code>RuntimeInvisibleAnnotations</code> attribute.
+     * Parses a {@code RuntimeInvisibleAnnotations} attribute.
      */
     private Attribute runtimeInvisibleAnnotations(DirectClassFile cf,
             int offset, int length, ParseObserver observer) {
@@ -621,7 +621,7 @@
     }
 
     /**
-     * Parses a <code>RuntimeVisibleAnnotations</code> attribute.
+     * Parses a {@code RuntimeVisibleAnnotations} attribute.
      */
     private Attribute runtimeVisibleAnnotations(DirectClassFile cf,
             int offset, int length, ParseObserver observer) {
@@ -638,7 +638,7 @@
     }
 
     /**
-     * Parses a <code>RuntimeInvisibleParameterAnnotations</code> attribute.
+     * Parses a {@code RuntimeInvisibleParameterAnnotations} attribute.
      */
     private Attribute runtimeInvisibleParameterAnnotations(DirectClassFile cf,
             int offset, int length, ParseObserver observer) {
@@ -655,7 +655,7 @@
     }
 
     /**
-     * Parses a <code>RuntimeVisibleParameterAnnotations</code> attribute.
+     * Parses a {@code RuntimeVisibleParameterAnnotations} attribute.
      */
     private Attribute runtimeVisibleParameterAnnotations(DirectClassFile cf,
             int offset, int length, ParseObserver observer) {
@@ -672,7 +672,7 @@
     }
 
     /**
-     * Parses a <code>Signature</code> attribute.
+     * Parses a {@code Signature} attribute.
      */
     private Attribute signature(DirectClassFile cf, int offset, int length,
             ParseObserver observer) {
@@ -694,7 +694,7 @@
     }
 
     /**
-     * Parses a <code>SourceFile</code> attribute.
+     * Parses a {@code SourceFile} attribute.
      */
     private Attribute sourceFile(DirectClassFile cf, int offset, int length,
             ParseObserver observer) {
@@ -716,7 +716,7 @@
     }
 
     /**
-     * Parses a <code>Synthetic</code> attribute.
+     * Parses a {@code Synthetic} attribute.
      */
     private Attribute synthetic(DirectClassFile cf, int offset, int length,
             ParseObserver observer) {
diff --git a/dx/src/com/android/dx/cf/iface/Attribute.java b/dx/src/com/android/dx/cf/iface/Attribute.java
index f28f51e..b075251 100644
--- a/dx/src/com/android/dx/cf/iface/Attribute.java
+++ b/dx/src/com/android/dx/cf/iface/Attribute.java
@@ -23,16 +23,16 @@
     /**
      * Get the name of the attribute.
      *
-     * @return non-null; the name
+     * @return {@code non-null;} the name
      */
     public String getName();
 
     /**
      * Get the total length of the attribute in bytes, including the
      * header. Since the header is always six bytes, the result of
-     * this method is always at least <code>6</code>.
+     * this method is always at least {@code 6}.
      *
-     * @return &gt;= 6; the total length, in bytes
+     * @return {@code >= 6;} the total length, in bytes
      */
     public int byteLength();
 }
diff --git a/dx/src/com/android/dx/cf/iface/AttributeList.java b/dx/src/com/android/dx/cf/iface/AttributeList.java
index a72965a..f7a1d27 100644
--- a/dx/src/com/android/dx/cf/iface/AttributeList.java
+++ b/dx/src/com/android/dx/cf/iface/AttributeList.java
@@ -22,11 +22,11 @@
 public interface AttributeList {
     /**
      * Get whether this instance is mutable. Note that the
-     * <code>AttributeList</code> interface itself doesn't provide any means
+     * {@code AttributeList} interface itself doesn't provide any means
      * of mutation, but that doesn't mean that there isn't a non-interface
      * way of mutating an instance.
      *
-     * @return <code>true</code> iff this instance is somehow mutable
+     * @return {@code true} iff this instance is somehow mutable
      */
     public boolean isMutable();
 
@@ -38,28 +38,28 @@
     public int size();
 
     /**
-     * Get the <code>n</code>th attribute.
+     * Get the {@code n}th attribute.
      *
-     * @param n <code>n &gt;= 0, n &lt; size()</code>; which attribute
-     * @return non-null; the attribute in question
+     * @param n {@code n >= 0, n < size();} which attribute
+     * @return {@code non-null;} the attribute in question
      */
     public Attribute get(int n);
 
     /**
      * Get the total length of this list in bytes, when part of a
      * class file. The returned value includes the two bytes for the
-     * <code>attributes_count</code> length indicator.
+     * {@code attributes_count} length indicator.
      *
-     * @return &gt;= 2; the total length, in bytes
+     * @return {@code >= 2;} the total length, in bytes
      */
     public int byteLength();
 
     /**
      * Get the first attribute in the list with the given name, if any.
      *
-     * @param name non-null; attribute name
-     * @return null-ok; first attribute in the list with the given name,
-     * or <code>null</code> if there is none
+     * @param name {@code non-null;} attribute name
+     * @return {@code null-ok;} first attribute in the list with the given name,
+     * or {@code null} if there is none
      */
     public Attribute findFirst(String name);
 
@@ -67,9 +67,9 @@
      * Get the next attribute in the list after the given one, with the same
      * name, if any.
      *
-     * @param attrib non-null; attribute to start looking after
-     * @return null-ok; next attribute after <code>attrib</code> with the
-     * same name as <code>attrib</code>
+     * @param attrib {@code non-null;} attribute to start looking after
+     * @return {@code null-ok;} next attribute after {@code attrib} with the
+     * same name as {@code attrib}
      */
     public Attribute findNext(Attribute attrib);
 }
diff --git a/dx/src/com/android/dx/cf/iface/ClassFile.java b/dx/src/com/android/dx/cf/iface/ClassFile.java
index 36a5f74..e37fec0 100644
--- a/dx/src/com/android/dx/cf/iface/ClassFile.java
+++ b/dx/src/com/android/dx/cf/iface/ClassFile.java
@@ -26,98 +26,98 @@
  * facsimiles thereof.
  *
  * <p><b>Note:</b> The fields referred to in this documentation are of the
- * <code>ClassFile</code> structure defined in vmspec-2 sec4.1.
+ * {@code ClassFile} structure defined in vmspec-2 sec4.1.
  */
 public interface ClassFile {
     /**
-     * Gets the field <code>magic</code>.
+     * Gets the field {@code magic}.
      *
      * @return the value in question
      */
     public int getMagic();
 
     /**
-     * Gets the field <code>minor_version</code>.
+     * Gets the field {@code minor_version}.
      *
      * @return the value in question
      */
     public int getMinorVersion();
 
     /**
-     * Gets the field <code>major_version</code>.
+     * Gets the field {@code major_version}.
      *
      * @return the value in question
      */
     public int getMajorVersion();
 
     /**
-     * Gets the field <code>access_flags</code>.
+     * Gets the field {@code access_flags}.
      *
      * @return the value in question
      */
     public int getAccessFlags();
 
     /**
-     * Gets the field <code>this_class</code>, interpreted as a type constant.
+     * Gets the field {@code this_class}, interpreted as a type constant.
      *
-     * @return non-null; the value in question
+     * @return {@code non-null;} the value in question
      */
     public CstType getThisClass();
 
     /**
-     * Gets the field <code>super_class</code>, interpreted as a type constant
+     * Gets the field {@code super_class}, interpreted as a type constant
      * if non-zero.
      *
-     * @return null-ok; the value in question
+     * @return {@code null-ok;} the value in question
      */
     public CstType getSuperclass();
 
     /**
-     * Gets the field <code>constant_pool</code> (along with
-     * <code>constant_pool_count</code>).
+     * Gets the field {@code constant_pool} (along with
+     * {@code constant_pool_count}).
      *
-     * @return non-null; the constant pool
+     * @return {@code non-null;} the constant pool
      */
     public ConstantPool getConstantPool();
 
     /**
-     * Gets the field <code>interfaces<code> (along with 
-     * interfaces_count</code>).
+     * Gets the field {@code interfaces} (along with 
+     * {@code interfaces_count}).
      *
-     * @return non-null; the list of interfaces
+     * @return {@code non-null;} the list of interfaces
      */
     public TypeList getInterfaces();
 
     /**
-     * Gets the field <code>fields</code> (along with
-     * <code>fields_count</code>).
+     * Gets the field {@code fields} (along with
+     * {@code fields_count}).
      *
-     * @return non-null; the list of fields
+     * @return {@code non-null;} the list of fields
      */
     public FieldList getFields();
 
     /**
-     * Gets the field <code>methods</code> (along with
-     * <code>methods_count</code>).
+     * Gets the field {@code methods} (along with
+     * {@code methods_count}).
      *
-     * @return non-null; the list of fields
+     * @return {@code non-null;} the list of fields
      */
     public MethodList getMethods();
 
     /**
-     * Gets the field <code>attributes</code> (along with
-     * <code>attributes_count</code>).
+     * Gets the field {@code attributes} (along with
+     * {@code attributes_count}).
      *
-     * @return non-null; the list of attributes
+     * @return {@code non-null;} the list of attributes
      */
     public AttributeList getAttributes();
 
     /**
-     * Gets the name out of the <code>SourceFile</code> attribute of this
+     * Gets the name out of the {@code SourceFile} attribute of this
      * file, if any. This is a convenient shorthand for scrounging around
      * the class's attributes.
      *
-     * @return non-null; the constant pool
+     * @return {@code non-null;} the constant pool
      */
     public CstUtf8 getSourceFile();
 }
diff --git a/dx/src/com/android/dx/cf/iface/Field.java b/dx/src/com/android/dx/cf/iface/Field.java
index d1694fc..e3002bc 100644
--- a/dx/src/com/android/dx/cf/iface/Field.java
+++ b/dx/src/com/android/dx/cf/iface/Field.java
@@ -25,10 +25,10 @@
         extends Member {
     /**
      * Get the constant value for this field, if any. This only returns
-     * non-<code>null</code> for a <code>static final</code> field which
-     * includes a <code>ConstantValue</code> attribute.
+     * non-{@code null} for a {@code static final} field which
+     * includes a {@code ConstantValue} attribute.
      *
-     * @return null-ok; the constant value, or <code>null</code> if this
+     * @return {@code null-ok;} the constant value, or {@code null} if this
      * field isn't a constant
      */
     public TypedConstant getConstantValue();
diff --git a/dx/src/com/android/dx/cf/iface/FieldList.java b/dx/src/com/android/dx/cf/iface/FieldList.java
index 80a794f..9cd27a3 100644
--- a/dx/src/com/android/dx/cf/iface/FieldList.java
+++ b/dx/src/com/android/dx/cf/iface/FieldList.java
@@ -23,11 +23,11 @@
 {
     /**
      * Get whether this instance is mutable. Note that the
-     * <code>FieldList</code> interface itself doesn't provide any means
+     * {@code FieldList} interface itself doesn't provide any means
      * of mutation, but that doesn't mean that there isn't a non-interface
      * way of mutating an instance.
      *
-     * @return <code>true</code> iff this instance is somehow mutable
+     * @return {@code true} iff this instance is somehow mutable
      */
     public boolean isMutable();
 
@@ -39,10 +39,10 @@
     public int size();
 
     /**
-     * Get the <code>n</code>th field.
+     * Get the {@code n}th field.
      *
-     * @param n <code>n &gt;= 0, n &lt; size()</code>; which field
-     * @return non-null; the field in question
+     * @param n {@code n >= 0, n < size();} which field
+     * @return {@code non-null;} the field in question
      */
     public Field get(int n);
 }
diff --git a/dx/src/com/android/dx/cf/iface/Member.java b/dx/src/com/android/dx/cf/iface/Member.java
index b305e09..0453a6f 100644
--- a/dx/src/com/android/dx/cf/iface/Member.java
+++ b/dx/src/com/android/dx/cf/iface/Member.java
@@ -27,48 +27,48 @@
     /**
      * Get the defining class.
      *
-     * @return non-null; the defining class
+     * @return {@code non-null;} the defining class
      */
     public CstType getDefiningClass();
 
     /**
-     * Get the field <code>access_flags</code>.
+     * Get the field {@code access_flags}.
      *
      * @return the access flags
      */
     public int getAccessFlags();
 
     /**
-     * Get the field <code>name_index</code> of the member. This is
-     * just a convenient shorthand for <code>getNat().getName()</code>.
+     * Get the field {@code name_index} of the member. This is
+     * just a convenient shorthand for {@code getNat().getName()}.
      *
-     * @return non-null; the name
+     * @return {@code non-null;} the name
      */
     public CstUtf8 getName();
 
     /**
-     * Get the field <code>descriptor_index</code> of the member. This is
-     * just a convenient shorthand for <code>getNat().getDescriptor()</code>.
+     * Get the field {@code descriptor_index} of the member. This is
+     * just a convenient shorthand for {@code getNat().getDescriptor()}.
      *
-     * @return non-null; the descriptor
+     * @return {@code non-null;} the descriptor
      */
     public CstUtf8 getDescriptor();
 
     /**
      * Get the name and type associated with this member. This is a
-     * combination of the fields <code>name_index</code> and
-     * <code>descriptor_index</code> in the original classfile, interpreted
+     * combination of the fields {@code name_index} and
+     * {@code descriptor_index} in the original classfile, interpreted
      * via the constant pool.
      *
-     * @return non-null; the name and type
+     * @return {@code non-null;} the name and type
      */
     public CstNat getNat();
 
     /**
-     * Get the field <code>attributes</code> (along with
-     * <code>attributes_count</code>).
+     * Get the field {@code attributes} (along with
+     * {@code attributes_count}).
      *
-     * @return non-null; the constant pool
+     * @return {@code non-null;} the constant pool
      */
     public AttributeList getAttributes();
 }
diff --git a/dx/src/com/android/dx/cf/iface/Method.java b/dx/src/com/android/dx/cf/iface/Method.java
index 424400a..18b9af6 100644
--- a/dx/src/com/android/dx/cf/iface/Method.java
+++ b/dx/src/com/android/dx/cf/iface/Method.java
@@ -26,9 +26,9 @@
 {
     /**
      * Get the <i>effective</i> method descriptor, which includes, if
-     * necessary, a first <code>this</code> parameter.
+     * necessary, a first {@code this} parameter.
      *
-     * @return non-null; the effective method descriptor
+     * @return {@code non-null;} the effective method descriptor
      */
     public Prototype getEffectiveDescriptor();
 }
diff --git a/dx/src/com/android/dx/cf/iface/MethodList.java b/dx/src/com/android/dx/cf/iface/MethodList.java
index a7a395c..dfa6528 100644
--- a/dx/src/com/android/dx/cf/iface/MethodList.java
+++ b/dx/src/com/android/dx/cf/iface/MethodList.java
@@ -22,11 +22,11 @@
 public interface MethodList {
     /**
      * Get whether this instance is mutable. Note that the
-     * <code>MethodList</code> interface itself doesn't provide any means
+     * {@code MethodList} interface itself doesn't provide any means
      * of mutation, but that doesn't mean that there isn't a non-interface
      * way of mutating an instance.
      *
-     * @return <code>true</code> iff this instance is somehow mutable
+     * @return {@code true} iff this instance is somehow mutable
      */
     public boolean isMutable();
 
@@ -38,10 +38,10 @@
     public int size();
 
     /**
-     * Get the <code>n</code>th method.
+     * Get the {@code n}th method.
      *
-     * @param n <code>n &gt;= 0, n &lt; size()</code>; which method
-     * @return non-null; the method in question
+     * @param n {@code n >= 0, n < size();} which method
+     * @return {@code non-null;} the method in question
      */
     public Method get(int n);
 }
diff --git a/dx/src/com/android/dx/cf/iface/ParseObserver.java b/dx/src/com/android/dx/cf/iface/ParseObserver.java
index 2ad3493..98d5a75 100644
--- a/dx/src/com/android/dx/cf/iface/ParseObserver.java
+++ b/dx/src/com/android/dx/cf/iface/ParseObserver.java
@@ -34,11 +34,11 @@
     /**
      * Indicate that a particular member is now being parsed.
      *
-     * @param bytes non-null; the source that is being parsed
-     * @param offset offset into <code>bytes</code> for the start of the
+     * @param bytes {@code non-null;} the source that is being parsed
+     * @param offset offset into {@code bytes} for the start of the
      * member
-     * @param name non-null; name of the member
-     * @param descriptor non-null; descriptor of the member
+     * @param name {@code non-null;} name of the member
+     * @param descriptor {@code non-null;} descriptor of the member
      */
     public void startParsingMember(ByteArray bytes, int offset, String name,
                                    String descriptor);
@@ -46,12 +46,12 @@
     /**
      * Indicate that a particular member is no longer being parsed.
      *
-     * @param bytes non-null; the source that was parsed
-     * @param offset offset into <code>bytes</code> for the end of the
+     * @param bytes {@code non-null;} the source that was parsed
+     * @param offset offset into {@code bytes} for the end of the
      * member
-     * @param name non-null; name of the member
-     * @param descriptor non-null; descriptor of the member
-     * @param member non-null; the actual member that was parsed
+     * @param name {@code non-null;} name of the member
+     * @param descriptor {@code non-null;} descriptor of the member
+     * @param member {@code non-null;} the actual member that was parsed
      */
     public void endParsingMember(ByteArray bytes, int offset, String name,
                                  String descriptor, Member member);
@@ -59,10 +59,10 @@
     /**
      * Indicate that some parsing happened.
      *
-     * @param bytes non-null; the source that was parsed
-     * @param offset offset into <code>bytes</code> for what was parsed
+     * @param bytes {@code non-null;} the source that was parsed
+     * @param offset offset into {@code bytes} for what was parsed
      * @param len number of bytes parsed
-     * @param human non-null; human form for what was parsed
+     * @param human {@code non-null;} human form for what was parsed
      */
     public void parsed(ByteArray bytes, int offset, int len, String human);
 }
diff --git a/dx/src/com/android/dx/cf/iface/StdAttributeList.java b/dx/src/com/android/dx/cf/iface/StdAttributeList.java
index c29bb08..dd5dfd7 100644
--- a/dx/src/com/android/dx/cf/iface/StdAttributeList.java
+++ b/dx/src/com/android/dx/cf/iface/StdAttributeList.java
@@ -25,7 +25,7 @@
 public final class StdAttributeList extends FixedSizeList
         implements AttributeList {
     /**
-     * Constructs an instance. All indices initially contain <code>null</code>.
+     * Constructs an instance. All indices initially contain {@code null}.
      * 
      * @param size the size of the list
      */
@@ -95,8 +95,8 @@
     /**
      * Sets the attribute at the given index.
      * 
-     * @param n &gt;= 0, &lt; size(); which attribute
-     * @param attribute null-ok; the attribute object
+     * @param n {@code >= 0, < size();} which attribute
+     * @param attribute {@code null-ok;} the attribute object
      */
     public void set(int n, Attribute attribute) {
         set0(n, attribute);
diff --git a/dx/src/com/android/dx/cf/iface/StdField.java b/dx/src/com/android/dx/cf/iface/StdField.java
index 3551aee..c3a4da6 100644
--- a/dx/src/com/android/dx/cf/iface/StdField.java
+++ b/dx/src/com/android/dx/cf/iface/StdField.java
@@ -29,10 +29,10 @@
     /**
      * Constructs an instance.
      * 
-     * @param definingClass non-null; the defining class
+     * @param definingClass {@code non-null;} the defining class
      * @param accessFlags access flags
-     * @param nat non-null; member name and type (descriptor)
-     * @param attributes non-null; list of associated attributes
+     * @param nat {@code non-null;} member name and type (descriptor)
+     * @param attributes {@code non-null;} list of associated attributes
      */
     public StdField(CstType definingClass, int accessFlags, CstNat nat,
                     AttributeList attributes) {
diff --git a/dx/src/com/android/dx/cf/iface/StdFieldList.java b/dx/src/com/android/dx/cf/iface/StdFieldList.java
index 0f8654b..044d6b7 100644
--- a/dx/src/com/android/dx/cf/iface/StdFieldList.java
+++ b/dx/src/com/android/dx/cf/iface/StdFieldList.java
@@ -24,7 +24,7 @@
  */
 public final class StdFieldList extends FixedSizeList implements FieldList {
     /**
-     * Constructs an instance. All indices initially contain <code>null</code>.
+     * Constructs an instance. All indices initially contain {@code null}.
      * 
      * @param size the size of the list
      */
@@ -40,8 +40,8 @@
     /**
      * Sets the field at the given index.
      * 
-     * @param n &gt;= 0, &lt; size(); which field
-     * @param field null-ok; the field object
+     * @param n {@code >= 0, < size();} which field
+     * @param field {@code null-ok;} the field object
      */
     public void set(int n, Field field) {
         set0(n, field);
diff --git a/dx/src/com/android/dx/cf/iface/StdMember.java b/dx/src/com/android/dx/cf/iface/StdMember.java
index eaf949e..dfe45c3 100644
--- a/dx/src/com/android/dx/cf/iface/StdMember.java
+++ b/dx/src/com/android/dx/cf/iface/StdMember.java
@@ -25,25 +25,25 @@
  * all the associated data.
  */
 public abstract class StdMember implements Member {
-    /** non-null; the defining class */
+    /** {@code non-null;} the defining class */
     private final CstType definingClass;
 
     /** access flags */
     private final int accessFlags;
 
-    /** non-null; member name and type */
+    /** {@code non-null;} member name and type */
     private final CstNat nat;
 
-    /** non-null; list of associated attributes */
+    /** {@code non-null;} list of associated attributes */
     private final AttributeList attributes;
 
     /**
      * Constructs an instance.
      * 
-     * @param definingClass non-null; the defining class
+     * @param definingClass {@code non-null;} the defining class
      * @param accessFlags access flags
-     * @param nat non-null; member name and type (descriptor)
-     * @param attributes non-null; list of associated attributes
+     * @param nat {@code non-null;} member name and type (descriptor)
+     * @param attributes {@code non-null;} list of associated attributes
      */
     public StdMember(CstType definingClass, int accessFlags, CstNat nat,
                      AttributeList attributes) {
diff --git a/dx/src/com/android/dx/cf/iface/StdMethod.java b/dx/src/com/android/dx/cf/iface/StdMethod.java
index a4acbaa..15fd6e1 100644
--- a/dx/src/com/android/dx/cf/iface/StdMethod.java
+++ b/dx/src/com/android/dx/cf/iface/StdMethod.java
@@ -26,16 +26,16 @@
  * all the associated data.
  */
 public final class StdMethod extends StdMember implements Method {
-    /** non-null; the effective method descriptor */
+    /** {@code non-null;} the effective method descriptor */
     private final Prototype effectiveDescriptor;
 
     /**
      * Constructs an instance.
      * 
-     * @param definingClass non-null; the defining class
+     * @param definingClass {@code non-null;} the defining class
      * @param accessFlags access flags
-     * @param nat non-null; member name and type (descriptor)
-     * @param attributes non-null; list of associated attributes
+     * @param nat {@code non-null;} member name and type (descriptor)
+     * @param attributes {@code non-null;} list of associated attributes
      */
     public StdMethod(CstType definingClass, int accessFlags, CstNat nat,
             AttributeList attributes) {
diff --git a/dx/src/com/android/dx/cf/iface/StdMethodList.java b/dx/src/com/android/dx/cf/iface/StdMethodList.java
index ef0ff31..521021e 100644
--- a/dx/src/com/android/dx/cf/iface/StdMethodList.java
+++ b/dx/src/com/android/dx/cf/iface/StdMethodList.java
@@ -24,7 +24,7 @@
  */
 public final class StdMethodList extends FixedSizeList implements MethodList {
     /**
-     * Constructs an instance. All indices initially contain <code>null</code>.
+     * Constructs an instance. All indices initially contain {@code null}.
      * 
      * @param size the size of the list
      */
@@ -40,8 +40,8 @@
     /**
      * Sets the method at the given index.
      * 
-     * @param n &gt;= 0, &lt; size(); which method
-     * @param method null-ok; the method object
+     * @param n {@code >= 0, < size();} which method
+     * @param method {@code null-ok;} the method object
      */
     public void set(int n, Method method) {
         set0(n, method);
diff --git a/dx/src/com/android/dx/command/DxConsole.java b/dx/src/com/android/dx/command/DxConsole.java
index 982e659..9ce9836 100644
--- a/dx/src/com/android/dx/command/DxConsole.java
+++ b/dx/src/com/android/dx/command/DxConsole.java
@@ -20,18 +20,18 @@
 
 /**
  * Provides standard and error PrintStream object to output information.<br>
- * By default the PrintStream objects link to <code>System.out</code> and
- * <code>System.err</code> but they can be changed to link to other
+ * By default the PrintStream objects link to {@code System.out} and
+ * {@code System.err} but they can be changed to link to other
  * PrintStream.
  */
 public class DxConsole {
     /**
-     * Standard output stream. Links to <code>System.out</code> by default.
+     * Standard output stream. Links to {@code System.out} by default.
      */
     public static PrintStream out = System.out;
 
     /**
-     * Error output stream. Links to <code>System.err</code> by default.
+     * Error output stream. Links to {@code System.err} by default.
      */
     public static PrintStream err = System.err;
 }
diff --git a/dx/src/com/android/dx/command/Main.java b/dx/src/com/android/dx/command/Main.java
index 17f5db3..281a83e 100644
--- a/dx/src/com/android/dx/command/Main.java
+++ b/dx/src/com/android/dx/command/Main.java
@@ -43,10 +43,12 @@
         "    options: none, important, lines.\n" +
         "  dx --annotool --annotation=<class> [--element=<element types>]\n" +
         "  [--print=<print types>]\n" +
-        "  dx --dump [--debug] [--strict] [--bytes] [--basic-blocks | " +
-        "--rop-blocks]\n" +
+        "  dx --dump [--debug] [--strict] [--bytes] [--optimize]\n" +
+        "  [--basic-blocks | --rop-blocks | --ssa-blocks | --dot] " +
+        "[--ssa-step=<step>]\n" +
         "  [--width=<n>] [<file>.class | <file>.txt] ...\n" +
-        "    Dump classfiles in a human-oriented format.\n" +
+        "    Dump classfiles, or transformations thereof, in a " +
+        "human-oriented format.\n" +
         "  dx --junit [-wait] <TestClass>\n" +
         "    Run the indicated unit test.\n" + 
         "  dx -J<option> ... <arguments, in one of the above " +
@@ -156,9 +158,9 @@
      * Returns a copy of the given args array, but without the indicated
      * element.
      *
-     * @param orig non-null; original array
+     * @param orig {@code non-null;} original array
      * @param n which element to omit
-     * @return non-null; new array
+     * @return {@code non-null;} new array
      */
     private static String[] without(String[] orig, int n) {
         int len = orig.length - 1;
diff --git a/dx/src/com/android/dx/command/annotool/AnnotationLister.java b/dx/src/com/android/dx/command/annotool/AnnotationLister.java
index 78f5d64..d3fb27c 100644
--- a/dx/src/com/android/dx/command/annotool/AnnotationLister.java
+++ b/dx/src/com/android/dx/command/annotool/AnnotationLister.java
@@ -34,10 +34,9 @@
 /**
  * Greps annotations on a set of class files and prints matching elements
  * to stdout. What counts as a match and what should be printed is controlled
- * by the <code>Main.Arguments</code> instance.
+ * by the {@code Main.Arguments} instance.
  */
 class AnnotationLister {
-
     /**
      * The string name of the pseudo-class that
      * contains package-wide annotations
@@ -59,7 +58,7 @@
 
     /** Processes based on configuration specified in constructor. */
     void process() {
-        for (String path: args.files) {
+        for (String path : args.files) {
             ClassPathOpener opener;
 
             opener = new ClassPathOpener(path, true,
@@ -137,8 +136,8 @@
     /**
      * Inspects a class annotation.
      *
-     * @param cf non-null; class file
-     * @param ann non-null; annotation
+     * @param cf {@code non-null;} class file
+     * @param ann {@code non-null;} annotation
      */
     private void visitClassAnnotation(DirectClassFile cf,
             BaseAnnotations ann) {
@@ -147,7 +146,7 @@
             return;
         }
 
-        for (Annotation anAnn: ann.getAnnotations().getAnnotations()) {
+        for (Annotation anAnn : ann.getAnnotations().getAnnotations()) {
             String annClassName
                     = anAnn.getType().getClassType().getClassName();
             if (args.aclass.equals(annClassName)) {
@@ -159,8 +158,8 @@
     /**
      * Inspects a package annotation
      *
-     * @param cf non-null; class file of "package-info" pseudo-class
-     * @param ann non-null; annotation
+     * @param cf {@code non-null;} class file of "package-info" pseudo-class
+     * @param ann {@code non-null;} annotation
      */
     private void visitPackageAnnotation(
             DirectClassFile cf, BaseAnnotations ann) {
@@ -181,7 +180,7 @@
         }
 
 
-        for (Annotation anAnn: ann.getAnnotations().getAnnotations()) {
+        for (Annotation anAnn : ann.getAnnotations().getAnnotations()) {
             String annClassName
                     = anAnn.getType().getClassType().getClassName();
             if (args.aclass.equals(annClassName)) {
@@ -195,10 +194,10 @@
      * Prints, or schedules for printing, elements related to a
      * matching package.
      *
-     * @param packageName non-null; name of package
+     * @param packageName {@code non-null;} name of package
      */
     private void printMatchPackage(String packageName) {
-        for(Main.PrintType pt: args.printTypes) {
+        for (Main.PrintType pt : args.printTypes) {
             switch (pt) {
                 case CLASS:
                 case INNERCLASS:
@@ -216,14 +215,15 @@
      * Prints, or schedules for printing, elements related to a matching
      * class.
      *
-     * @param cf non-null; matching class
+     * @param cf {@code non-null;} matching class
      */
     private void printMatch(DirectClassFile cf) {
-        for(Main.PrintType pt: args.printTypes) {
+        for (Main.PrintType pt : args.printTypes) {
             switch (pt) {
                 case CLASS:
                     String classname;
-                    classname = cf.getThisClass().getClassType().getClassName();
+                    classname =
+                        cf.getThisClass().getClassType().getClassName();
                     classname = classname.replace('/','.');
                     System.out.println(classname);
                     break;
@@ -244,7 +244,7 @@
      * Checks to see if a specified class name should be considered a match
      * due to previous matches.
      *
-     * @param s non-null; class name
+     * @param s {@code non-null;} class name
      * @return true if this class should be considered a match
      */
     private boolean isMatchingInnerClass(String s) {
@@ -264,7 +264,7 @@
      * Checks to see if a specified package should be considered a match due
      * to previous matches.
      *
-     * @param s non-null; package name
+     * @param s {@code non-null;} package name
      * @return true if this package should be considered a match
      */
     private boolean isMatchingPackage(String s) {
diff --git a/dx/src/com/android/dx/command/annotool/Main.java b/dx/src/com/android/dx/command/annotool/Main.java
index 4f1d9a4..9fd1ac5 100644
--- a/dx/src/com/android/dx/command/annotool/Main.java
+++ b/dx/src/com/android/dx/command/annotool/Main.java
@@ -87,17 +87,18 @@
                     String argParam = arg.substring(arg.indexOf('=') + 1);
 
                     try {
-                        for (String p: argParam.split(",")) {
+                        for (String p : argParam.split(",")) {
                             eTypes.add(ElementType.valueOf(p.toUpperCase()));
                         }
                     } catch (IllegalArgumentException ex) {
-                        throw new InvalidArgumentException("invalid --element");
+                        throw new InvalidArgumentException(
+                                "invalid --element");
                     }
                 } else if (arg.startsWith("--print=")) {
                     String argParam = arg.substring(arg.indexOf('=') + 1);
 
                     try {
-                        for (String p: argParam.split(",")) {
+                        for (String p : argParam.split(",")) {
                             printTypes.add(PrintType.valueOf(p.toUpperCase()));
                         }
                     } catch (IllegalArgumentException ex) {
diff --git a/dx/src/com/android/dx/command/dexer/Main.java b/dx/src/com/android/dx/command/dexer/Main.java
index 19f67b4..5a9f417 100644
--- a/dx/src/com/android/dx/command/dexer/Main.java
+++ b/dx/src/com/android/dx/command/dexer/Main.java
@@ -55,26 +55,26 @@
  */
 public class Main {
     /**
-     * non-null; name for the <code>.dex</code> file that goes into
-     * <code>.jar</code> files
+     * {@code non-null;} name for the {@code .dex} file that goes into
+     * {@code .jar} files
      */
     private static final String DEX_IN_JAR_NAME = "classes.dex";
 
     /**
-     * non-null; name of the standard manifest file in <code>.jar</code>
+     * {@code non-null;} name of the standard manifest file in {@code .jar}
      * files
      */
     private static final String MANIFEST_NAME = "META-INF/MANIFEST.MF";
 
     /**
-     * non-null; attribute name for the (quasi-standard?)
-     * <code>Created-By</code> attribute
+     * {@code non-null;} attribute name for the (quasi-standard?)
+     * {@code Created-By} attribute
      */
     private static final Attributes.Name CREATED_BY =
         new Attributes.Name("Created-By");
 
     /**
-     * non-null; list of <code>javax</code> subpackages that are considered
+     * {@code non-null;} list of {@code javax} subpackages that are considered
      * to be "core". <b>Note:</b>: This list must be sorted, since it
      * is binary-searched.
      */
@@ -90,15 +90,15 @@
     /** number of errors during processing */
     private static int errors = 0;
 
-    /** non-null; parsed command-line arguments */
+    /** {@code non-null;} parsed command-line arguments */
     private static Arguments args;
 
-    /** non-null; output file in-progress */
+    /** {@code non-null;} output file in-progress */
     private static DexFile outputDex;
 
     /**
-     * null-ok; map of resources to include in the output, or
-     * <code>null</code> if resources are being ignored
+     * {@code null-ok;} map of resources to include in the output, or
+     * {@code null} if resources are being ignored
      */
     private static TreeMap<String, byte[]> outputResources;
 
@@ -215,8 +215,9 @@
     /**
      * Processes one pathname element.
      *
-     * @param pathname non-null; the pathname to process. May be the path of
-     * a class file, a jar file, or a directory containing class files.
+     * @param pathname {@code non-null;} the pathname to process. May
+     * be the path of a class file, a jar file, or a directory
+     * containing class files.
      * @return whether any processing actually happened
      */
     private static boolean processOne(String pathname) {
@@ -237,7 +238,8 @@
             }
             public void onProcessArchiveStart(File file) {
                 if (args.verbose) {
-                    DxConsole.out.println("processing archive " + file + "...");
+                    DxConsole.out.println("processing archive " + file +
+                            "...");
                 }
             }
         });
@@ -248,8 +250,8 @@
     /**
      * Processes one file, which may be either a class or a resource.
      *
-     * @param name non-null; name of the file
-     * @param bytes non-null; contents of the file
+     * @param name {@code non-null;} name of the file
+     * @param bytes {@code non-null;} contents of the file
      * @return whether processing was successful
      */
     private static boolean processFileBytes(String name, byte[] bytes) {
@@ -283,9 +285,9 @@
     /**
      * Processes one classfile.
      *
-     * @param name non-null; name of the file, clipped such that it
+     * @param name {@code non-null;} name of the file, clipped such that it
      * <i>should</i> correspond to the name of the class it contains
-     * @param bytes non-null; contents of the file
+     * @param bytes {@code non-null;} contents of the file
      * @return whether processing was successful
      */
     private static boolean processClass(String name, byte[] bytes) {
@@ -316,7 +318,8 @@
      * class. If there is a problem, this updates the error count and
      * throws an exception to stop processing.
      * 
-     * @param name non-null; the fully-qualified internal-form class name
+     * @param name {@code non-null;} the fully-qualified internal-form
+     * class name
      */
     private static void checkClassName(String name) {
         boolean bogus = false;
@@ -346,35 +349,60 @@
 
         DxConsole.err.println("\ntrouble processing \"" + name + "\":");
         DxConsole.err.println("\n" + 
-                "Attempt to include a core VM class in something other " +
-                "than a core library.\n" +
-                "It is likely that you have attempted to include the " +
-                "core library from a desktop\n" +
-                "virtual machine into an application, which will most " +
-                "assuredly not work. If\n" +
-                "you really intend to build a core library -- which is "+
-                "only appropriate as\n" +
-                "part of creating a full virtual machine binary, as " +
-                "opposed to compiling an\n" +
-                "application -- then use the \"--core-library\" option " +
-                "to suppress this error\n" +
-                "message. If you go ahead and use \"--core-library\" " +
-                "but are in fact building\n" +
-                "an application, then please be aware that your build " +
-                "will still fail at some\n" +
-                "point; you will simply be denied the pleasure of " +
-                "reading this helpful error\n" +
-                "message.");
+                "Attempt to include a core class (java.* or javax.*) in " +
+                "something other\n" +
+                "than a core library. It is likely that you have " +
+                "attempted to include\n" +
+                "in an application the core library (or a part thereof) " +
+                "from a desktop\n" +
+                "virtual machine. This will most assuredly not work. " +
+                "At a minimum, it\n" +
+                "jeopardizes the compatibility of your app with future " +
+                "versions of the\n" +
+                "platform. It is also often of questionable legality.\n" +
+                "\n" +
+                "If you really intend to build a core library -- which is " +
+                "only\n" +
+                "appropriate as part of creating a full virtual machine " +
+                "distribution,\n" +
+                "as opposed to compiling an application -- then use the\n" +
+                "\"--core-library\" option to suppress this error message.\n" +
+                "\n" +
+                "If you go ahead and use \"--core-library\" but are in " +
+                "fact building an\n" +
+                "application, then be forewarned that your application " +
+                "will still fail\n" +
+                "to build or run, at some point. Please be prepared for " +
+                "angry customers\n" +
+                "who find, for example, that your application ceases to " +
+                "function once\n" +
+                "they upgrade their operating system. You will be to " +
+                "blame for this\n" +
+                "problem.\n" +
+                "\n" +
+                "If you are legitimately using some code that happens to " +
+                "be in a core\n" +
+                "package, then the easiest safe alternative you have is " +
+                "to repackage\n" +
+                "that code. That is, move the classes in question into " +
+                "your own package\n" +
+                "namespace. This means that they will never be in " +
+                "conflict with core\n" +
+                "system classes. If you find that you cannot do this, " +
+                "then that is an\n" +
+                "indication that the path you are on will ultimately lead " +
+                "to pain,\n" +
+                "suffering, grief, and lamentation.\n");
         errors++;
         throw new StopProcessing();
     }
 
     /**
-     * Converts {@link #outputDex} into a <code>byte[]</code>, write
+     * Converts {@link #outputDex} into a {@code byte[]}, write
      * it out to the proper file (if any), and also do whatever human-oriented
      * dumping is required.
      *
-     * @return null-ok; the converted <code>byte[]</code> or <code>null</code>
+     * @return {@code null-ok;} the converted {@code byte[]} or {@code null}
      * if there was a problem
      */
     private static byte[] writeDex() {
@@ -438,8 +466,9 @@
     /**
      * Creates a jar file from the resources and given dex file array.
      *
-     * @param fileName non-null; name of the file
-     * @param dexArray non-null; array containing the dex file to include
+     * @param fileName {@code non-null;} name of the file
+     * @param dexArray {@code non-null;} array containing the dex file
+     * to include
      * @return whether the creation was successful
      */
     private static boolean createJar(String fileName, byte[] dexArray) {
@@ -496,7 +525,7 @@
      * Creates and returns the manifest to use for the output. This may
      * modify {@link #outputResources} (removing the pre-existing manifest).
      *
-     * @return non-null; the manifest
+     * @return {@code non-null;} the manifest
      */
     private static Manifest makeManifest() throws IOException {
         byte[] manifestBytes = outputResources.get(MANIFEST_NAME);
@@ -531,8 +560,8 @@
     /**
      * Opens and returns the named file for writing, treating "-" specially.
      *
-     * @param name non-null; the file name
-     * @return non-null; the opened file
+     * @param name {@code non-null;} the file name
+     * @return {@code non-null;} the opened file
      */
     private static OutputStream openOutput(String name) throws IOException {
         if (name.equals("-") ||
@@ -547,9 +576,9 @@
      * Flushes and closes the given output stream, except if it happens to be
      * {@link System#out} in which case this method does the flush but not
      * the close. This method will also silently do nothing if given a
-     * <code>null</code> argument.
+     * {@code null} argument.
      *
-     * @param stream null-ok; what to close
+     * @param stream {@code null-ok;} what to close
      */
     private static void closeOutput(OutputStream stream) throws IOException {
         if (stream == null) {
@@ -565,18 +594,18 @@
 
     /**
      * Returns the "fixed" version of a given file path, suitable for
-     * use as a path within a <code>.jar</code> file and for checking
+     * use as a path within a {@code .jar} file and for checking
      * against a classfile-internal "this class" name. This looks for
-     * the last instance of the substring <code>"/./"</code> within
+     * the last instance of the substring {@code "/./"} within
      * the path, and if it finds it, it takes the portion after to be
      * the fixed path. If that isn't found but the path starts with
-     * <code>"./"</code>, then that prefix is removed and the rest is
+     * {@code "./"}, then that prefix is removed and the rest is
      * return. If neither of these is the case, this method returns
      * its argument.
      *
-     * @param path non-null; the path to "fix"
-     * @return non-null; the fixed version (which might be the same as
-     * the given <code>path</code>)
+     * @param path {@code non-null;} the path to "fix"
+     * @return {@code non-null;} the fixed version (which might be the same as
+     * the given {@code path})
      */
     private static String fixPath(String path) {
         /*
@@ -603,9 +632,10 @@
     /**
      * Dumps any method with the given name in the given file.
      *
-     * @param dex non-null; the dex file
-     * @param fqName non-null; the fully-qualified name of the method(s)
-     * @param out non-null; where to dump to
+     * @param dex {@code non-null;} the dex file
+     * @param fqName {@code non-null;} the fully-qualified name of the
+     * method(s)
+     * @param out {@code non-null;} where to dump to
      */
     private static void dumpMethod(DexFile dex, String fqName,
             OutputStreamWriter out) {
@@ -719,36 +749,36 @@
         /** whether we are constructing a core library */
         public boolean coreLibrary = false;
 
-        /** null-ok; particular method to dump */
+        /** {@code null-ok;} particular method to dump */
         public String methodToDump = null;
 
         /** max width for columnar output */
         public int dumpWidth = 0;
 
-        /** null-ok; output file name for binary file */
+        /** {@code null-ok;} output file name for binary file */
         public String outName = null;
 
-        /** null-ok; output file name for human-oriented dump */
+        /** {@code null-ok;} output file name for human-oriented dump */
         public String humanOutName = null;
 
         /** whether strict file-name-vs-class-name checking should be done */
         public boolean strictNameCheck = true;
 
         /**
-         * whether it is okay for there to be no <code>.class</code> files
+         * whether it is okay for there to be no {@code .class} files
          * to process
          */
         public boolean emptyOk = false;
 
         /**
-         * whether the binary output is to be a <code>.jar</code> file
-         * instead of a plain <code>.dex</code>
+         * whether the binary output is to be a {@code .jar} file
+         * instead of a plain {@code .dex}
          */
         public boolean jarOutput = false;
 
         /**
-         * when writing a <code>.jar</code> file, whether to still
-         * keep the <code>.class</code> files
+         * when writing a {@code .jar} file, whether to still
+         * keep the {@code .class} files
          */
         public boolean keepClassesInJar = false;
 
@@ -758,7 +788,7 @@
         /** whether to keep local variable information */
         public boolean localInfo = true;
 
-        /** non-null after {@link #parse}; file name arguments */
+        /** {@code non-null after {@link #parse};} file name arguments */
         public String[] fileNames;
 
         /** whether to do SSA/register optimization */
@@ -779,7 +809,7 @@
         /**
          * Parses the given command-line arguments.
          *
-         * @param args non-null; the arguments
+         * @param args {@code non-null;} the arguments
          */
         public void parse(String[] args) {
             int at = 0;
@@ -866,8 +896,6 @@
             }
 
             int fileCount = args.length - at;
-            fileNames = new String[fileCount];
-            System.arraycopy(args, at, fileNames, 0, fileCount);
 
             if (fileCount == 0) {
                 if (!emptyOk) {
@@ -876,9 +904,13 @@
                 }
             } else if (emptyOk) {
                 System.out.println("ignoring input files");
-                at = args.length;
+                at = 0;
+                fileCount = 0;
             }
 
+            fileNames = new String[fileCount];
+            System.arraycopy(args, at, fileNames, 0, fileCount);
+
             if ((humanOutName == null) && (methodToDump != null)) {
                 humanOutName = "-";
             }
diff --git a/dx/src/com/android/dx/command/dump/BaseDumper.java b/dx/src/com/android/dx/command/dump/BaseDumper.java
index f4a8dee..d2c1e13 100644
--- a/dx/src/com/android/dx/command/dump/BaseDumper.java
+++ b/dx/src/com/android/dx/command/dump/BaseDumper.java
@@ -34,21 +34,21 @@
  */
 public abstract class BaseDumper
         implements ParseObserver {
-    /** non-null; array of data being dumped */
+    /** {@code non-null;} array of data being dumped */
     private final byte[] bytes;
 
     /** whether or not to include the raw bytes (in a column on the left) */
     private final boolean rawBytes;
 
-    /** non-null; where to dump to */
+    /** {@code non-null;} where to dump to */
     private final PrintStream out;
 
     /** width of the output in columns */
     private final int width;
 
     /**
-     * non-null; the file path for the class, excluding any base directory
-     * specification 
+     * {@code non-null;} the file path for the class, excluding any base
+     * directory specification 
      */
     private final String filePath;
 
@@ -61,7 +61,7 @@
     /** the current level of indentation */
     private int indent;
 
-    /** non-null; the current column separator string */
+    /** {@code non-null;} the current column separator string */
     private String separator;
 
     /** the offset of the next byte to dump */
@@ -73,10 +73,9 @@
     /**
      * Constructs an instance.
      * 
-     * @param bytes non-null; bytes of the (alleged) class file
+     * @param bytes {@code non-null;} bytes of the (alleged) class file
      * on the left)
-     * @param out non-null; where to dump to
-     * passed in as &lt;= 0
+     * @param out {@code non-null;} where to dump to
      * @param filePath the file path for the class, excluding any base
      * directory specification
      */
@@ -109,7 +108,8 @@
      * @return width in register-units
      */
     static int computeParamWidth(ConcreteMethod meth, boolean isStatic) {
-        return meth.getEffectiveDescriptor().getParameterTypes().getWordCount();
+        return meth.getEffectiveDescriptor().getParameterTypes().
+            getWordCount();
     }
 
     /** {@inheritDoc} */
@@ -158,7 +158,7 @@
      * Gets the current dump cursor (that is, the offset of the expected
      * next byte to dump).
      * 
-     * @return &gt;= 0; the dump cursor
+     * @return {@code >= 0;} the dump cursor
      */
     protected final int getAt() {
         return at;
@@ -167,17 +167,17 @@
     /**
      * Sets the dump cursor to the indicated offset in the given array.
      * 
-     * @param arr non-null; array in question
-     * @param offset &gt;= 0; offset into the array
+     * @param arr {@code non-null;} array in question
+     * @param offset {@code >= 0;} offset into the array
      */
     protected final void setAt(ByteArray arr, int offset) {
         at = arr.underlyingOffset(offset, bytes);
     }
 
     /**
-     * Gets the array of <code>byte</code>s to process.
+     * Gets the array of {@code byte}s to process.
      * 
-     * @return non-null; the bytes
+     * @return {@code non-null;} the bytes
      */
     protected final byte[] getBytes() {
         return bytes;
@@ -186,7 +186,7 @@
     /**
      * Gets the filesystem/jar path of the file being dumped.
      * 
-     * @return non-null; the path
+     * @return {@code non-null;} the path
      */
     protected final String getFilePath() {
         return filePath;
@@ -204,7 +204,7 @@
     /**
      * Prints the given string to this instance's output stream.
      * 
-     * @param s null-ok; string to print
+     * @param s {@code null-ok;} string to print
      */
     protected final void print(String s) {
         out.print(s);
@@ -214,7 +214,7 @@
      * Prints the given string to this instance's output stream, followed
      * by a newline.
      * 
-     * @param s null-ok; string to print
+     * @param s {@code null-ok;} string to print
      */
     protected final void println(String s) {
         out.println(s);
@@ -230,10 +230,10 @@
     }
 
     /**
-     * Gets the width of the first column of output. This is <code>0</code>
+     * Gets the width of the first column of output. This is {@code 0}
      * unless raw bytes are being included in the output.
      * 
-     * @return &gt;= 0; the width of the first column
+     * @return {@code >= 0;} the width of the first column
      */
     protected final int getWidth1() {
         if (rawBytes) {
@@ -246,7 +246,7 @@
     /**
      * Gets the width of the second column of output.
      * 
-     * @return &gt;= 0; the width of the second column
+     * @return {@code >= 0;} the width of the second column
      */
     protected final int getWidth2() {
         int w1 = rawBytes ? (getWidth1() + 1) : 0;
@@ -258,7 +258,7 @@
      * 
      * @param offset offset to start dumping at
      * @param len length to dump
-     * @return non-null; the dump
+     * @return {@code non-null;} the dump
      */
     protected final String hexDump(int offset, int len) {
         return Hex.dump(bytes, offset, len, offset, hexCols, 4);
@@ -268,9 +268,9 @@
      * Combines a pair of strings as two columns, or if this is one-column
      * output, format the otherwise-second column.
      * 
-     * @param s1 non-null; the first column's string
-     * @param s2 non-null; the second column's string
-     * @return non-null; the combined output
+     * @param s1 {@code non-null;} the first column's string
+     * @param s2 {@code non-null;} the second column's string
+     * @return {@code non-null;} the combined output
      */
     protected final String twoColumns(String s1, String s2) {
         int w1 = getWidth1();
diff --git a/dx/src/com/android/dx/command/dump/BlockDumper.java b/dx/src/com/android/dx/command/dump/BlockDumper.java
index 0be2fb4..0858eab 100644
--- a/dx/src/com/android/dx/command/dump/BlockDumper.java
+++ b/dx/src/com/android/dx/command/dump/BlockDumper.java
@@ -54,14 +54,11 @@
     private boolean rop;
 
     /**
-     * null-ok; the class file object being constructed; becomes non-null
-     * during {@link #dump} 
+     * {@code null-ok;} the class file object being constructed;
+     * becomes non-null during {@link #dump} 
      */
     protected DirectClassFile classFile;
 
-    /** null-ok; most recently parsed code attribute */
-    private AttCode codeAtt;
-
     /** whether or not to suppress dumping */
     protected boolean suppressDump;
 
@@ -75,9 +72,8 @@
      * Dumps the given array, interpreting it as a class file and dumping
      * methods with indications of block-level stuff.
      * 
-     * @param bytes non-null; bytes of the (alleged) class file
-     * @param out non-null; where to dump to
-     * passed in as &lt;= 0
+     * @param bytes {@code non-null;} bytes of the (alleged) class file
+     * @param out {@code non-null;} where to dump to
      * @param filePath the file path for the class, excluding any base
      * directory specification
      * @param rop whether or not to registerize (make rop blocks)
@@ -102,7 +98,6 @@
 
         this.rop = rop;
         this.classFile = null;
-        this.codeAtt = null;
         this.suppressDump = true;
         this.first = true;
         this.optimize = args.optimize;
@@ -208,7 +203,7 @@
     /**
      * Does a regular basic block dump.
      * 
-     * @param meth non-null; method data to dump
+     * @param meth {@code non-null;} method data to dump
      */
     private void regularDump(ConcreteMethod meth) {
         BytecodeArray code = meth.getCode();
@@ -283,7 +278,7 @@
     /**
      * Does a registerizing dump.
      * 
-     * @param meth non-null; method data to dump
+     * @param meth {@code non-null;} method data to dump
      */
     private void ropDump(ConcreteMethod meth) {
         BytecodeArray code = meth.getCode();
diff --git a/dx/src/com/android/dx/command/dump/ClassDumper.java b/dx/src/com/android/dx/command/dump/ClassDumper.java
index 10dacf3..e98b6d6 100644
--- a/dx/src/com/android/dx/command/dump/ClassDumper.java
+++ b/dx/src/com/android/dx/command/dump/ClassDumper.java
@@ -30,8 +30,8 @@
     /**
      * Dumps the given array, interpreting it as a class file.
      *
-     * @param bytes non-null; bytes of the (alleged) class file
-     * @param out non-null; where to dump to
+     * @param bytes {@code non-null;} bytes of the (alleged) class file
+     * @param out {@code non-null;} where to dump to
      * passed in as &lt;= 0
      * @param filePath the file path for the class, excluding any base
      * directory specification
diff --git a/dx/src/com/android/dx/command/dump/DotDumper.java b/dx/src/com/android/dx/command/dump/DotDumper.java
index 87c5298..9de48fc 100644
--- a/dx/src/com/android/dx/command/dump/DotDumper.java
+++ b/dx/src/com/android/dx/command/dump/DotDumper.java
@@ -39,16 +39,15 @@
  * with the popular graph utility "dot".
  */
 public class DotDumper implements ParseObserver {
+    private DirectClassFile classFile;
 
-    DirectClassFile classFile;
+    private final byte[] bytes;
+    private final String filePath;
+    private final boolean strictParse;
+    private final boolean optimize;
+    private final Args args;
 
-    byte[] bytes;
-    String filePath;
-    boolean strictParse;
-    boolean optimize;
-    Args args;
-
-    static void dump (byte[] bytes, String filePath, Args args) {
+    static void dump(byte[] bytes, String filePath, Args args) {
         new DotDumper(bytes, filePath, args).run();
     }
 
@@ -60,7 +59,6 @@
         this.args = args;
     }
 
-
     private void run() {
         ByteArray ba = new ByteArray(bytes);
 
@@ -89,17 +87,17 @@
     }
 
     public void changeIndent(int indentDelta) {
-
+        // This space intentionally left blank.
     }
 
     public void parsed(ByteArray bytes, int offset, int len, String human) {
-        
+        // This space intentionally left blank.
     }
 
     /** {@inheritDoc} */
     public void startParsingMember(ByteArray bytes, int offset, String name,
                                    String descriptor) {
-
+        // This space intentionally left blank.
     }
 
     public void endParsingMember(ByteArray bytes, int offset, String name,
@@ -165,6 +163,5 @@
         }
 
         System.out.println("}");
-
     }
 }
diff --git a/dx/src/com/android/dx/command/dump/Main.java b/dx/src/com/android/dx/command/dump/Main.java
index 1ea26bc..d6ba374 100644
--- a/dx/src/com/android/dx/command/dump/Main.java
+++ b/dx/src/com/android/dx/command/dump/Main.java
@@ -110,8 +110,8 @@
     /**
      * Processes one file.
      *
-     * @param name non-null; name of the file
-     * @param bytes non-null; contents of the file
+     * @param name {@code non-null;} name of the file
+     * @param bytes {@code non-null;} contents of the file
      */
     private static void processOne(String name, byte[] bytes) {
         if (parsedArgs.dotDump) {
diff --git a/dx/src/com/android/dx/command/dump/SsaDumper.java b/dx/src/com/android/dx/command/dump/SsaDumper.java
index 95442a1..e5e9d97 100644
--- a/dx/src/com/android/dx/command/dump/SsaDumper.java
+++ b/dx/src/com/android/dx/command/dump/SsaDumper.java
@@ -40,29 +40,48 @@
 import com.android.dx.util.IntList;
 
 import java.io.PrintStream;
+import java.util.ArrayList;
 import java.util.BitSet;
+import java.util.Collections;
 import java.util.EnumSet;
 
+/**
+ * Dumper for the SSA-translated blocks of a method.
+ */
 public class SsaDumper extends BlockDumper {
-
+    /**
+     * Does the dump.
+     * 
+     * @param bytes {@code non-null;} bytes of the original class file
+     * @param out {@code non-null;} where to dump to
+     * @param filePath the file path for the class, excluding any base
+     * directory specification
+     * @param args commandline parsedArgs
+     */
     public static void dump(byte[] bytes, PrintStream out,
             String filePath, Args args) {
-
-        SsaDumper sd =
-            new SsaDumper(bytes, out, filePath, args);
+        SsaDumper sd = new SsaDumper(bytes, out, filePath, args);
         sd.dump();
     }
 
-    SsaDumper(byte[] bytes, PrintStream out, String filePath, Args args) {
-
+    /**
+     * Constructs an instance.
+     * 
+     * @param bytes {@code non-null;} bytes of the original class file
+     * @param out {@code non-null;} where to dump to
+     * @param filePath the file path for the class, excluding any base
+     * directory specification
+     * @param args commandline parsedArgs
+     */
+    private SsaDumper(byte[] bytes, PrintStream out, String filePath,
+            Args args) {
         super(bytes, out, filePath, true, args);
-
     }
 
     /** {@inheritDoc} */
     @Override
     public void endParsingMember(ByteArray bytes, int offset, String name,
-                                 String descriptor, Member member) {
+            String descriptor, Member member) {
         if (!(member instanceof Method)) {
             return;
         }
@@ -71,17 +90,14 @@
             return;
         }
 
-        ConcreteMethod meth = new ConcreteMethod((Method) member, classFile,
-                                                 true, true);
-
+        ConcreteMethod meth =
+            new ConcreteMethod((Method) member, classFile, true, true);
         TranslationAdvice advice = DexTranslationAdvice.THE_ONE;
-
         RopMethod rmeth = Ropper.convert(meth, advice);
-
         SsaMethod ssaMeth = null;
-
         boolean isStatic = AccessFlags.isStatic(meth.getAccessFlags());
         int paramWidth = computeParamWidth(meth, isStatic);
+
         if (args.ssaStep == null) {
             ssaMeth = Optimizer.debugNoRegisterAllocation(rmeth,
                     paramWidth, isStatic, true, advice,
@@ -106,30 +122,36 @@
         sb.append(Hex.u2(
                 ssaMeth.blockIndexToRopLabel(ssaMeth.getEntryBlockIndex())));
         sb.append('\n');
+
+        ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks();
+        ArrayList<SsaBasicBlock> sortedBlocks = 
+            (ArrayList<SsaBasicBlock>) blocks.clone();
+        Collections.sort(sortedBlocks, SsaBasicBlock.LABEL_COMPARATOR);
         
-        for (SsaBasicBlock block : ssaMeth.getBlocks()) {
+        for (SsaBasicBlock block : sortedBlocks) {
             sb.append("block ")
                     .append(Hex.u2(block.getRopLabel())).append('\n');
 
             BitSet preds = block.getPredecessors();
 
-            for(int i=preds.nextSetBit(0); i>=0; i=preds.nextSetBit(i+1)) {
-                sb.append ("  pred ");
-                sb.append (Hex.u2(ssaMeth.blockIndexToRopLabel(i)));
+            for (int i = preds.nextSetBit(0); i >= 0;
+                 i = preds.nextSetBit(i+1)) {
+                sb.append("  pred ");
+                sb.append(Hex.u2(ssaMeth.blockIndexToRopLabel(i)));
                 sb.append('\n');
             }
 
-            sb.append ("  live in:" + block.getLiveInRegs());
-            sb.append ("\n");
+            sb.append("  live in:" + block.getLiveInRegs());
+            sb.append("\n");
 
-            for (SsaInsn insn: block.getInsns()) {
+            for (SsaInsn insn : block.getInsns()) {
                 sb.append("  ");
                 sb.append(insn.toHuman());
                 sb.append('\n');
             }
 
             if (block.getSuccessors().cardinality() == 0) {
-                sb.append ("  returns\n");
+                sb.append("  returns\n");
             } else {
                 int primary = block.getPrimarySuccessorRopLabel();
 
@@ -138,18 +160,18 @@
                 int szSuccLabels = succLabelList.size();
 
                 for (int i = 0; i < szSuccLabels; i++) {
-                    sb.append ("  next ");
-                    sb.append (Hex.u2(succLabelList.get(i)));
+                    sb.append("  next ");
+                    sb.append(Hex.u2(succLabelList.get(i)));
 
                     if (szSuccLabels != 1 && primary == succLabelList.get(i)) {
-                        sb.append (" *");                        
+                        sb.append(" *");                        
                     }
                     sb.append('\n');
                 }
             }
 
-            sb.append ("  live out:" + block.getLiveOutRegs());
-            sb.append ("\n");
+            sb.append("  live out:" + block.getLiveOutRegs());
+            sb.append("\n");
         }
 
         suppressDump = false;
diff --git a/dx/src/com/android/dx/dex/cf/AttributeTranslator.java b/dx/src/com/android/dx/dex/cf/AttributeTranslator.java
index dab15c9..cdd29d7 100644
--- a/dx/src/com/android/dx/dex/cf/AttributeTranslator.java
+++ b/dx/src/com/android/dx/dex/cf/AttributeTranslator.java
@@ -51,7 +51,7 @@
 
 /**
  * Utility methods that translate various classfile attributes
- * into forms suitable for use in creating <code>dex</code> files.
+ * into forms suitable for use in creating {@code dex} files.
  */
 /*package*/ class AttributeTranslator {
     /**
@@ -64,8 +64,8 @@
     /**
      * Gets the list of thrown exceptions for a given method.
      *
-     * @param method non-null; the method in question
-     * @return non-null; the list of thrown exceptions
+     * @param method {@code non-null;} the method in question
+     * @return {@code non-null;} the list of thrown exceptions
      */
     public static TypeList getExceptions(Method method) {
         AttributeList attribs = method.getAttributes();
@@ -83,10 +83,10 @@
      * Gets the annotations out of a given {@link AttributeList}. This
      * combines both visible and invisible annotations into a single
      * result set and also adds in a system annotation for the
-     * <code>Signature</code> attribute if present.
+     * {@code Signature} attribute if present.
      * 
-     * @param attribs non-null; the attributes list to search in
-     * @return non-null; the set of annotations, which may be empty
+     * @param attribs {@code non-null;} the attributes list to search in
+     * @return {@code non-null;} the set of annotations, which may be empty
      */
     public static Annotations getAnnotations(AttributeList attribs) {
         Annotations result = getAnnotations0(attribs);
@@ -102,15 +102,15 @@
     /**
      * Gets the annotations out of a given class, similar to {@link
      * #getAnnotations}, also including annotations for translations
-     * of class-level attributes <code>EnclosingMethod</code> and
-     * <code>InnerClasses</code>, if present. Additionally, if the
+     * of class-level attributes {@code EnclosingMethod} and
+     * {@code InnerClasses}, if present. Additionally, if the
      * class is an annotation class, then this also includes a
-     * representation of all the <code>AnnotationDefault</code>
+     * representation of all the {@code AnnotationDefault}
      * values.
      * 
-     * @param cf non-null; the class in question
-     * @param args non-null; the high-level options
-     * @return non-null; the set of annotations, which may be empty
+     * @param cf {@code non-null;} the class in question
+     * @param args {@code non-null;} the high-level options
+     * @return {@code non-null;} the set of annotations, which may be empty
      */
     public static Annotations getClassAnnotations(DirectClassFile cf,
             CfOptions args) {
@@ -148,10 +148,10 @@
     /**
      * Gets the annotations out of a given method, similar to {@link
      * #getAnnotations}, also including an annotation for the translation
-     * of the method-specific attribute <code>Exceptions</code>.
+     * of the method-specific attribute {@code Exceptions}.
      * 
-     * @param method non-null; the method in question
-     * @return non-null; the set of annotations, which may be empty
+     * @param method {@code non-null;} the method in question
+     * @return {@code non-null;} the set of annotations, which may be empty
      */
     public static Annotations getMethodAnnotations(Method method) {
         Annotations result = getAnnotations(method.getAttributes());
@@ -170,8 +170,8 @@
      * Helper method for {@link #getAnnotations} which just gets the
      * existing annotations, per se.
      * 
-     * @param attribs non-null; the attributes list to search in
-     * @return non-null; the set of annotations, which may be empty
+     * @param attribs {@code non-null;} the attributes list to search in
+     * @return {@code non-null;} the set of annotations, which may be empty
      */
     private static Annotations getAnnotations0(AttributeList attribs) {
         AttRuntimeVisibleAnnotations visible =
@@ -199,11 +199,11 @@
     }
 
     /**
-     * Gets the <code>Signature</code> attribute out of a given
+     * Gets the {@code Signature} attribute out of a given
      * {@link AttributeList}, if any, translating it to an annotation.
      * 
-     * @param attribs non-null; the attributes list to search in
-     * @return null-ok; the converted <code>Signature</code> annotation,
+     * @param attribs {@code non-null;} the attributes list to search in
+     * @return {@code null-ok;} the converted {@code Signature} annotation,
      * if there was an attribute to translate
      */
     private static Annotation getSignature(AttributeList attribs) {
@@ -218,15 +218,15 @@
     }
 
     /**
-     * Gets the <code>EnclosingMethod</code> attribute out of a given
+     * Gets the {@code EnclosingMethod} attribute out of a given
      * {@link AttributeList}, if any, translating it to an annotation.
      * If the class really has an enclosing method, this returns an
-     * <code>EnclosingMethod</code> annotation; if not, this returns
-     * an <code>EnclosingClass</code> annotation.
+     * {@code EnclosingMethod} annotation; if not, this returns
+     * an {@code EnclosingClass} annotation.
      * 
-     * @param attribs non-null; the attributes list to search in
-     * @return null-ok; the converted <code>EnclosingMethod</code> or
-     * <code>EnclosingClass</code> annotation, if there was an
+     * @param attribs {@code non-null;} the attributes list to search in
+     * @return {@code null-ok;} the converted {@code EnclosingMethod} or
+     * {@code EnclosingClass} annotation, if there was an
      * attribute to translate
      */
     private static Annotation translateEnclosingMethod(AttributeList attribs) {
@@ -256,16 +256,16 @@
     }
 
     /**
-     * Gets the <code>InnerClasses</code> attribute out of a given
+     * Gets the {@code InnerClasses} attribute out of a given
      * {@link AttributeList}, if any, translating it to one or more of an
-     * <code>InnerClass</code>, <code>EnclosingClass</code>, or
-     * <code>MemberClasses</code> annotation.
+     * {@code InnerClass}, {@code EnclosingClass}, or
+     * {@code MemberClasses} annotation.
      * 
-     * @param thisClass non-null; type representing the class being processed
-     * @param attribs non-null; the attributes list to search in
+     * @param thisClass {@code non-null;} type representing the class being processed
+     * @param attribs {@code non-null;} the attributes list to search in
      * @param needEnclosingClass whether to include an
-     * <code>EnclosingClass</code> annotation
-     * @return null-ok; the converted list of annotations, if there
+     * {@code EnclosingClass} annotation
+     * @return {@code null-ok;} the converted list of annotations, if there
      * was an attribute to translate
      */
     private static Annotations translateInnerClasses(CstType thisClass,
@@ -342,8 +342,8 @@
      * combines both visible and invisible annotations into a single
      * result set.
      * 
-     * @param method non-null; the method in question
-     * @return non-null; the list of annotation sets, which may be empty
+     * @param method {@code non-null;} the method in question
+     * @return {@code non-null;} the list of annotation sets, which may be empty
      */
     public static AnnotationsList getParameterAnnotations(Method method) {
         AttributeList attribs = method.getAttributes();
@@ -374,14 +374,14 @@
     }
 
     /**
-     * Gets the <code>AnnotationDefault</code> attributes out of a
+     * Gets the {@code AnnotationDefault} attributes out of a
      * given class, if any, reforming them as an
-     * <code>AnnotationDefault</code> annotation.
+     * {@code AnnotationDefault} annotation.
      * 
-     * @param cf non-null; the class in question
-     * @return null-ok; an appropriately-constructed
-     * <code>AnnotationDefault</code> annotation, if there were any
-     * annotation defaults in the class, or <code>null<code> if not
+     * @param cf {@code non-null;} the class in question
+     * @return {@code null-ok;} an appropriately-constructed
+     * {@code AnnotationDefault} annotation, if there were any
+     * annotation defaults in the class, or {@code null} if not
      */
     private static Annotation translateAnnotationDefaults(DirectClassFile cf) {
         CstType thisClass = cf.getThisClass();
diff --git a/dx/src/com/android/dx/dex/cf/CfTranslator.java b/dx/src/com/android/dx/dex/cf/CfTranslator.java
index c48be53..8210e90 100644
--- a/dx/src/com/android/dx/dex/cf/CfTranslator.java
+++ b/dx/src/com/android/dx/dex/cf/CfTranslator.java
@@ -55,11 +55,11 @@
 import com.android.dx.util.ExceptionWithContext;
 
 /**
- * Static method that turns <code>byte[]</code>s containing Java
+ * Static method that turns {@code byte[]}s containing Java
  * classfiles into {@link ClassDefItem} instances.
  */
 public class CfTranslator {
-    /** set to <code>true</code> to enable development-time debugging code */
+    /** set to {@code true} to enable development-time debugging code */
     private static final boolean DEBUG = false;
 
     /**
@@ -70,14 +70,14 @@
     }
 
     /**
-     * Takes a <code>byte[]</code>, interprets it as a Java classfile, and
+     * Takes a {@code byte[]}, interprets it as a Java classfile, and
      * translates it into a {@link ClassDefItem}.
      *
-     * @param filePath non-null; the file path for the class,
+     * @param filePath {@code non-null;} the file path for the class,
      * excluding any base directory specification
-     * @param bytes non-null; contents of the file
+     * @param bytes {@code non-null;} contents of the file
      * @param args command-line arguments
-     * @return non-null; the translated class
+     * @return {@code non-null;} the translated class
      */
     public static ClassDefItem translate(String filePath, byte[] bytes,
             CfOptions args) {
@@ -94,11 +94,11 @@
      * from {@link #translate} just to keep things a bit simpler in
      * terms of exception handling.
      *
-     * @param filePath non-null; the file path for the class,
+     * @param filePath {@code non-null;} the file path for the class,
      * excluding any base directory specification
-     * @param bytes non-null; contents of the file
+     * @param bytes {@code non-null;} contents of the file
      * @param args command-line arguments
-     * @return non-null; the translated class
+     * @return {@code non-null;} the translated class
      */
     private static ClassDefItem translate0(String filePath, byte[] bytes,
             CfOptions args) {
@@ -136,8 +136,8 @@
     /**
      * Processes the fields of the given class.
      *
-     * @param cf non-null; class being translated
-     * @param out non-null; output class
+     * @param cf {@code non-null;} class being translated
+     * @param out {@code non-null;} output class
      */
     private static void processFields(DirectClassFile cf, ClassDefItem out) {
         CstType thisClass = cf.getThisClass();
@@ -179,8 +179,8 @@
      * Helper for {@link #processFields}, which translates constants into
      * more specific types if necessary.
      * 
-     * @param constant non-null; the constant in question
-     * @param type non-null; the desired type
+     * @param constant {@code non-null;} the constant in question
+     * @param type {@code non-null;} the desired type
      */
     private static TypedConstant coerceConstant(TypedConstant constant,
             Type type) {
@@ -213,9 +213,9 @@
     /**
      * Processes the methods of the given class.
      *
-     * @param cf non-null; class being translated
-     * @param args non-null; command-line args
-     * @param out non-null; output class
+     * @param cf {@code non-null;} class being translated
+     * @param args {@code non-null;} command-line args
+     * @param out {@code non-null;} output class
      */
     private static void processMethods(DirectClassFile cf,
             CfOptions args, ClassDefItem out) {
diff --git a/dx/src/com/android/dx/dex/cf/CodeStatistics.java b/dx/src/com/android/dx/dex/cf/CodeStatistics.java
index fa83100..b692d77 100644
--- a/dx/src/com/android/dx/dex/cf/CodeStatistics.java
+++ b/dx/src/com/android/dx/dex/cf/CodeStatistics.java
@@ -26,7 +26,7 @@
  * code.
  */
 public final class CodeStatistics {
-    /** set to <code>true</code> to enable development-time debugging code */
+    /** set to {@code true} to enable development-time debugging code */
     private static final boolean DEBUG = false;
 
     /**
@@ -76,7 +76,7 @@
     /**
      * Updates the number of original bytecode bytes processed.
      * 
-     * @param count &gt;= 0; the number of bytes to add
+     * @param count {@code >= 0;} the number of bytes to add
      */
     public static void updateOriginalByteCount(int count) {
         runningOriginalBytes += count;
@@ -146,7 +146,7 @@
     /**
      * Prints out the collected statistics.
      * 
-     * @param out non-null; where to output to
+     * @param out {@code non-null;} where to output to
      */
     public static void dumpStatistics(PrintStream out) {
         out.printf("Optimizer Delta Rop Insns: %d total: %d "
diff --git a/dx/src/com/android/dx/dex/cf/OptimizerOptions.java b/dx/src/com/android/dx/dex/cf/OptimizerOptions.java
index 1dc3f76..fa606e3 100644
--- a/dx/src/com/android/dx/dex/cf/OptimizerOptions.java
+++ b/dx/src/com/android/dx/dex/cf/OptimizerOptions.java
@@ -31,13 +31,14 @@
  */
 public class OptimizerOptions {
     /**
-     * null-ok; hash set of class name + method names that should be optimized.
-     * null if this constraint was not specified on the command line
+     * {@code null-ok;} hash set of class name + method names that
+     * should be optimized. {@code null} if this constraint was not
+     * specified on the command line
      */
     private static HashSet<String> optimizeList;
 
     /**
-     * null-ok; hash set of class name + method names that should NOT
+     * {@code null-ok;} hash set of class name + method names that should NOT
      * be optimized.  null if this constraint was not specified on the
      * command line
      */
@@ -97,7 +98,6 @@
 
         try {
             FileReader fr = new FileReader(filename);
-
             BufferedReader bfr = new BufferedReader(fr);
 
             String line;
@@ -105,6 +105,8 @@
             while (null != (line = bfr.readLine())) {
                 result.add(line);
             }
+
+            fr.close();
         } catch (IOException ex) {
             // Let the exception percolate up as a RuntimeException.
             throw new RuntimeException("Error with optimize list: " +
@@ -118,12 +120,12 @@
      * Compares the output of the optimizer run normally with a run skipping
      * some optional steps. Results are printed to stderr.
      *
-     * @param nonOptRmeth non-null; origional rop method
-     * @param paramSize &gt;= 0 parameter size of method
+     * @param nonOptRmeth {@code non-null;} origional rop method
+     * @param paramSize {@code >= 0;} parameter size of method
      * @param isStatic true if this method has no 'this' pointer argument.
-     * @param args non-null; translator arguments
-     * @param advice non-null; translation advice
-     * @param rmeth non-null; method with all optimization steps run.
+     * @param args {@code non-null;} translator arguments
+     * @param advice {@code non-null;} translation advice
+     * @param rmeth {@code non-null;} method with all optimization steps run.
      */
     public static void compareOptimizerStep(RopMethod nonOptRmeth,
             int paramSize, boolean isStatic, CfOptions args,
diff --git a/dx/src/com/android/dx/dex/code/ArrayData.java b/dx/src/com/android/dx/dex/code/ArrayData.java
index 8476a03..7698de1 100644
--- a/dx/src/com/android/dx/dex/code/ArrayData.java
+++ b/dx/src/com/android/dx/dex/code/ArrayData.java
@@ -29,12 +29,12 @@
  */
 public final class ArrayData extends VariableSizeInsn {
     /**
-     * non-null; address representing the instruction that uses this
+     * {@code non-null;} address representing the instruction that uses this
      * instance 
      */
     private final CodeAddress user;
 
-    /** non-null; initial values to be filled into an array */
+    /** {@code non-null;} initial values to be filled into an array */
     private final ArrayList<Constant> values;
 
     /** non-null: type of constant that initializes the array */
@@ -48,12 +48,12 @@
 
     /**
      * Constructs an instance. The output address of this instance is initially
-     * unknown (<code>-1</code>).
+     * unknown ({@code -1}).
      * 
-     * @param position non-null; source position
-     * @param user non-null; address representing the instruction that
+     * @param position {@code non-null;} source position
+     * @param user {@code non-null;} address representing the instruction that
      * uses this instance
-     * @param values non-null; initial values to be filled into an array
+     * @param values {@code non-null;} initial values to be filled into an array
      */
     public ArrayData(SourcePosition position, CodeAddress user,
                      ArrayList<Constant> values,
@@ -107,7 +107,6 @@
     /** {@inheritDoc} */
     @Override
     public void writeTo(AnnotatedOutput out) {
-        int baseAddress = user.getAddress();
         int sz = values.size();
 
         out.writeShort(0x300 | DalvOps.NOP);
diff --git a/dx/src/com/android/dx/dex/code/BlockAddresses.java b/dx/src/com/android/dx/dex/code/BlockAddresses.java
index 9fea66c..e55f893 100644
--- a/dx/src/com/android/dx/dex/code/BlockAddresses.java
+++ b/dx/src/com/android/dx/dex/code/BlockAddresses.java
@@ -28,15 +28,15 @@
  * start address, end address, and last instruction address.
  */
 public final class BlockAddresses {
-    /** non-null; array containing addresses for the start of each basic
+    /** {@code non-null;} array containing addresses for the start of each basic
      * block (indexed by basic block label) */
     private final CodeAddress[] starts;
 
-    /** non-null; array containing addresses for the final instruction
+    /** {@code non-null;} array containing addresses for the final instruction
      * of each basic block (indexed by basic block label) */
     private final CodeAddress[] lasts;
 
-    /** non-null; array containing addresses for the end (just past the
+    /** {@code non-null;} array containing addresses for the end (just past the
      * final instruction) of each basic block (indexed by basic block
      * label) */
     private final CodeAddress[] ends;
@@ -44,7 +44,7 @@
     /**
      * Constructs an instance.
      *
-     * @param method non-null; the method to have block addresses for
+     * @param method {@code non-null;} the method to have block addresses for
      */
     public BlockAddresses(RopMethod method) {
         BasicBlockList blocks = method.getBlocks();
@@ -60,8 +60,8 @@
     /**
      * Gets the instance for the start of the given block.
      * 
-     * @param block non-null; the block in question
-     * @return non-null; the appropriate instance
+     * @param block {@code non-null;} the block in question
+     * @return {@code non-null;} the appropriate instance
      */
     public CodeAddress getStart(BasicBlock block) {
         return starts[block.getLabel()];
@@ -70,8 +70,8 @@
     /**
      * Gets the instance for the start of the block with the given label.
      * 
-     * @param label non-null; the label of the block in question
-     * @return non-null; the appropriate instance
+     * @param label {@code non-null;} the label of the block in question
+     * @return {@code non-null;} the appropriate instance
      */
     public CodeAddress getStart(int label) {
         return starts[label];
@@ -80,8 +80,8 @@
     /**
      * Gets the instance for the final instruction of the given block.
      * 
-     * @param block non-null; the block in question
-     * @return non-null; the appropriate instance
+     * @param block {@code non-null;} the block in question
+     * @return {@code non-null;} the appropriate instance
      */
     public CodeAddress getLast(BasicBlock block) {
         return lasts[block.getLabel()];
@@ -91,8 +91,8 @@
      * Gets the instance for the final instruction of the block with
      * the given label.
      * 
-     * @param label non-null; the label of the block in question
-     * @return non-null; the appropriate instance
+     * @param label {@code non-null;} the label of the block in question
+     * @return {@code non-null;} the appropriate instance
      */
     public CodeAddress getLast(int label) {
         return lasts[label];
@@ -102,8 +102,8 @@
      * Gets the instance for the end (address after the final instruction)
      * of the given block.
      * 
-     * @param block non-null; the block in question
-     * @return non-null; the appropriate instance
+     * @param block {@code non-null;} the block in question
+     * @return {@code non-null;} the appropriate instance
      */
     public CodeAddress getEnd(BasicBlock block) {
         return ends[block.getLabel()];
@@ -113,8 +113,8 @@
      * Gets the instance for the end (address after the final instruction)
      * of the block with the given label.
      * 
-     * @param label non-null; the label of the block in question
-     * @return non-null; the appropriate instance
+     * @param label {@code non-null;} the label of the block in question
+     * @return {@code non-null;} the appropriate instance
      */
     public CodeAddress getEnd(int label) {
         return ends[label];
diff --git a/dx/src/com/android/dx/dex/code/CatchBuilder.java b/dx/src/com/android/dx/dex/code/CatchBuilder.java
index 8bc963b..d2ec3d7 100644
--- a/dx/src/com/android/dx/dex/code/CatchBuilder.java
+++ b/dx/src/com/android/dx/dex/code/CatchBuilder.java
@@ -27,7 +27,7 @@
     /**
      * Builds and returns the catch table for this instance.
      * 
-     * @return non-null; the constructed table
+     * @return {@code non-null;} the constructed table
      */
     public CatchTable build();
 
@@ -42,7 +42,7 @@
     /**
      * Gets the set of catch types associated with this instance.
      * 
-     * @return non-null; the set of catch types
+     * @return {@code non-null;} the set of catch types
      */
     public HashSet<Type> getCatchTypes();
 }
diff --git a/dx/src/com/android/dx/dex/code/CatchHandlerList.java b/dx/src/com/android/dx/dex/code/CatchHandlerList.java
index 862586c..a8a97be 100644
--- a/dx/src/com/android/dx/dex/code/CatchHandlerList.java
+++ b/dx/src/com/android/dx/dex/code/CatchHandlerList.java
@@ -25,13 +25,13 @@
  */
 public final class CatchHandlerList extends FixedSizeList
         implements Comparable<CatchHandlerList> {
-    /** non-null; empty instance */
+    /** {@code non-null;} empty instance */
     public static final CatchHandlerList EMPTY = new CatchHandlerList(0);
 
     /**
-     * Constructs an instance. All indices initially contain <code>null</code>.
+     * Constructs an instance. All indices initially contain {@code null}.
      *
-     * @param size &gt;= 0; the size of the list
+     * @param size {@code >= 0;} the size of the list
      */
     public CatchHandlerList(int size) {
         super(size);
@@ -40,10 +40,10 @@
     /**
      * Gets the element at the given index. It is an error to call
      * this with the index for an element which was never set; if you
-     * do that, this will throw <code>NullPointerException</code>.
+     * do that, this will throw {@code NullPointerException}.
      *
-     * @param n &gt;= 0, &lt; size(); which index
-     * @return non-null; element at that index
+     * @param n {@code >= 0, < size();} which index
+     * @return {@code non-null;} element at that index
      */
     public Entry get(int n) {
         return (Entry) get0(n);
@@ -58,10 +58,10 @@
      * Get the human form of this instance, prefixed on each line
      * with the string.
      * 
-     * @param prefix non-null; the prefix for every line
-     * @param header non-null; the header for the first line (after the
+     * @param prefix {@code non-null;} the prefix for every line
+     * @param header {@code non-null;} the header for the first line (after the
      * first prefix)
-     * @return non-null; the human form
+     * @return {@code non-null;} the human form
      */
     public String toHuman(String prefix, String header) {
         StringBuilder sb = new StringBuilder(100);
@@ -97,8 +97,8 @@
      * Returns whether or not this instance ends with a "catch-all"
      * handler.
      * 
-     * @return <code>true</code> if this instance ends with a "catch-all"
-     * handler or <code>false</code> if not
+     * @return {@code true} if this instance ends with a "catch-all"
+     * handler or {@code false} if not
      */
     public boolean catchesAll() {
         int size = size();
@@ -114,9 +114,9 @@
     /**
      * Sets the entry at the given index.
      *
-     * @param n &gt;= 0, &lt; size(); which index
-     * @param exceptionType non-null; type of exception handled
-     * @param handler &gt;= 0; exception handler address
+     * @param n {@code >= 0, < size();} which index
+     * @param exceptionType {@code non-null;} type of exception handled
+     * @param handler {@code >= 0;} exception handler address
      */
     public void set(int n, CstType exceptionType, int handler) {
         set0(n, new Entry(exceptionType, handler));
@@ -125,8 +125,8 @@
     /**
      * Sets the entry at the given index.
      *
-     * @param n &gt;= 0, &lt; size(); which index
-     * @param entry non-null; the entry to set at <code>n</code>
+     * @param n {@code >= 0, < size();} which index
+     * @param entry {@code non-null;} the entry to set at {@code n}
      */
     public void set(int n, Entry entry) {
         set0(n, entry);
@@ -165,17 +165,17 @@
      * Entry in the list.
      */
     public static class Entry implements Comparable<Entry> {
-        /** non-null; type of exception handled */
+        /** {@code non-null;} type of exception handled */
         private final CstType exceptionType;
 
-        /** &gt;= 0; exception handler address */
+        /** {@code >= 0;} exception handler address */
         private final int handler;
 
         /**
          * Constructs an instance.
          *
-         * @param exceptionType non-null; type of exception handled
-         * @param handler &gt;= 0; exception handler address
+         * @param exceptionType {@code non-null;} type of exception handled
+         * @param handler {@code >= 0;} exception handler address
          */
         public Entry(CstType exceptionType, int handler) {
             if (handler < 0) {
@@ -220,7 +220,7 @@
         /**
          * Gets the exception type handled.
          * 
-         * @return non-null; the exception type
+         * @return {@code non-null;} the exception type
          */
         public CstType getExceptionType() {
             return exceptionType;
@@ -229,7 +229,7 @@
         /**
          * Gets the handler address.
          * 
-         * @return &gt;= 0; the handler address
+         * @return {@code >= 0;} the handler address
          */
         public int getHandler() {
             return handler;
diff --git a/dx/src/com/android/dx/dex/code/CatchTable.java b/dx/src/com/android/dx/dex/code/CatchTable.java
index 86f9c58..fd8e3a7 100644
--- a/dx/src/com/android/dx/dex/code/CatchTable.java
+++ b/dx/src/com/android/dx/dex/code/CatchTable.java
@@ -26,13 +26,13 @@
  */
 public final class CatchTable extends FixedSizeList
         implements Comparable<CatchTable> {
-    /** non-null; empty instance */
+    /** {@code non-null;} empty instance */
     public static final CatchTable EMPTY = new CatchTable(0);
 
     /**
-     * Constructs an instance. All indices initially contain <code>null</code>.
+     * Constructs an instance. All indices initially contain {@code null}.
      *
-     * @param size &gt;= 0; the size of the table
+     * @param size {@code >= 0;} the size of the table
      */
     public CatchTable(int size) {
         super(size);
@@ -41,10 +41,10 @@
     /**
      * Gets the element at the given index. It is an error to call
      * this with the index for an element which was never set; if you
-     * do that, this will throw <code>NullPointerException</code>.
+     * do that, this will throw {@code NullPointerException}.
      *
-     * @param n &gt;= 0, &lt; size(); which index
-     * @return non-null; element at that index
+     * @param n {@code >= 0, < size();} which index
+     * @return {@code non-null;} element at that index
      */
     public Entry get(int n) {
         return (Entry) get0(n);
@@ -53,8 +53,8 @@
     /**
      * Sets the entry at the given index.
      *
-     * @param n &gt;= 0, &lt; size(); which index
-     * @param entry non-null; the entry to set at <code>n</code>
+     * @param n {@code >= 0, < size();} which index
+     * @param entry {@code non-null;} the entry to set at {@code n}
      */
     public void set(int n, Entry entry) {
         set0(n, entry);
@@ -93,21 +93,21 @@
      * Entry in a catch list.
      */
     public static class Entry implements Comparable<Entry> {
-        /** &gt;= 0; start address */
+        /** {@code >= 0;} start address */
         private final int start;
 
-        /** &gt; start; end address (exclusive) */
+        /** {@code > start;} end address (exclusive) */
         private final int end;
 
-        /** non-null; list of catch handlers */
+        /** {@code non-null;} list of catch handlers */
         private final CatchHandlerList handlers;
 
         /**
          * Constructs an instance.
          *
-         * @param start &gt;= 0; start address 
-         * @param end &gt; start; end address (exclusive)
-         * @param handlers non-null; list of catch handlers
+         * @param start {@code >= 0;} start address 
+         * @param end {@code > start;} end address (exclusive)
+         * @param handlers {@code non-null;} list of catch handlers
          */
         public Entry(int start, int end, CatchHandlerList handlers) {
             if (start < 0) {
@@ -165,7 +165,7 @@
         /**
          * Gets the start address.
          * 
-         * @return &gt;= 0; the start address
+         * @return {@code >= 0;} the start address
          */
         public int getStart() {
             return start;
@@ -174,7 +174,7 @@
         /**
          * Gets the end address (exclusive).
          * 
-         * @return &gt; start; the end address (exclusive)
+         * @return {@code > start;} the end address (exclusive)
          */
         public int getEnd() {
             return end;
@@ -183,7 +183,7 @@
         /**
          * Gets the handlers.
          * 
-         * @return non-null; the handlers
+         * @return {@code non-null;} the handlers
          */
         public CatchHandlerList getHandlers() {
             return handlers;
diff --git a/dx/src/com/android/dx/dex/code/CodeAddress.java b/dx/src/com/android/dx/dex/code/CodeAddress.java
index 9730913..f25718e 100644
--- a/dx/src/com/android/dx/dex/code/CodeAddress.java
+++ b/dx/src/com/android/dx/dex/code/CodeAddress.java
@@ -29,9 +29,9 @@
 public final class CodeAddress extends ZeroSizeInsn {
     /**
      * Constructs an instance. The output address of this instance is initially
-     * unknown (<code>-1</code>).
+     * unknown ({@code -1}).
      * 
-     * @param position non-null; source position
+     * @param position {@code non-null;} source position
      */
     public CodeAddress(SourcePosition position) {
         super(position);
diff --git a/dx/src/com/android/dx/dex/code/CstInsn.java b/dx/src/com/android/dx/dex/code/CstInsn.java
index 1bc9021..a579c5e 100644
--- a/dx/src/com/android/dx/dex/code/CstInsn.java
+++ b/dx/src/com/android/dx/dex/code/CstInsn.java
@@ -25,31 +25,31 @@
  * to all the normal instruction information.
  */
 public final class CstInsn extends FixedSizeInsn {
-    /** non-null; the constant argument for this instruction */
+    /** {@code non-null;} the constant argument for this instruction */
     private final Constant constant;
 
     /**
-     * &gt;= -1; the constant pool index for {@link #constant}, or
-     * <code>-1</code> if not yet set 
+     * {@code >= -1;} the constant pool index for {@link #constant}, or
+     * {@code -1} if not yet set 
      */
     private int index;
 
     /**
-     * &gt;= -1; the constant pool index for the class reference in
-     * {@link #constant} if any, or <code>-1</code> if not yet set 
+     * {@code >= -1;} the constant pool index for the class reference in
+     * {@link #constant} if any, or {@code -1} if not yet set 
      */
     private int classIndex;
 
     /**
      * Constructs an instance. The output address of this instance is
-     * initially unknown (<code>-1</code>) as is the constant pool index.
+     * initially unknown ({@code -1}) as is the constant pool index.
      * 
      * @param opcode the opcode; one of the constants from {@link Dops}
-     * @param position non-null; source position
-     * @param registers non-null; register list, including a
+     * @param position {@code non-null;} source position
+     * @param registers {@code non-null;} register list, including a
      * result register if appropriate (that is, registers may be either
      * ins or outs)
-     * @param constant non-null; constant argument
+     * @param constant {@code non-null;} constant argument
      */
     public CstInsn(Dop opcode, SourcePosition position,
                    RegisterSpecList registers, Constant constant) {
@@ -101,7 +101,7 @@
     /**
      * Gets the constant argument.
      * 
-     * @return non-null; the constant argument
+     * @return {@code non-null;} the constant argument
      */
     public Constant getConstant() {
         return constant;
@@ -111,7 +111,7 @@
      * Gets the constant's index. It is only valid to call this after
      * {@link #setIndex} has been called.
      * 
-     * @return &gt;= 0; the constant pool index
+     * @return {@code >= 0;} the constant pool index
      */
     public int getIndex() {
         if (index < 0) {
@@ -126,7 +126,7 @@
      * 
      * @see #setIndex
      * 
-     * @return <code>true</code> iff the index has been set
+     * @return {@code true} iff the index has been set
      */
     public boolean hasIndex() {
         return (index >= 0);
@@ -136,7 +136,7 @@
      * Sets the constant's index. It is only valid to call this method once
      * per instance.
      * 
-     * @param index &gt;= 0; the constant pool index
+     * @param index {@code >= 0;} the constant pool index
      */
     public void setIndex(int index) {
         if (index < 0) {
@@ -154,7 +154,7 @@
      * Gets the constant's class index. It is only valid to call this after
      * {@link #setClassIndex} has been called.
      * 
-     * @return &gt;= 0; the constant's class's constant pool index
+     * @return {@code >= 0;} the constant's class's constant pool index
      */
     public int getClassIndex() {
         if (classIndex < 0) {
@@ -170,7 +170,7 @@
      * 
      * @see #setClassIndex
      * 
-     * @return <code>true</code> iff the index has been set
+     * @return {@code true} iff the index has been set
      */
     public boolean hasClassIndex() {
         return (classIndex >= 0);
@@ -183,7 +183,7 @@
      * with reference constants that this method should ever be
      * called. It is only valid to call this method once per instance.
      * 
-     * @param index &gt;= 0; the constant's class's constant pool index
+     * @param index {@code >= 0;} the constant's class's constant pool index
      */
     public void setClassIndex(int index) {
         if (index < 0) {
diff --git a/dx/src/com/android/dx/dex/code/DalvCode.java b/dx/src/com/android/dx/dex/code/DalvCode.java
index cf6af09..f911912 100644
--- a/dx/src/com/android/dx/dex/code/DalvCode.java
+++ b/dx/src/com/android/dx/dex/code/DalvCode.java
@@ -23,7 +23,7 @@
 
 /**
  * Container for all the pieces of a concrete method. Each instance
- * corresponds to a <code>code</code> structure in a <code>.dex</code> file.
+ * corresponds to a {@code code} structure in a {@code .dex} file.
  */
 public final class DalvCode {
     /**
@@ -33,37 +33,37 @@
     private final int positionInfo;
 
     /**
-     * null-ok; the instruction list, ready for final processing;
+     * {@code null-ok;} the instruction list, ready for final processing;
      * nulled out in {@link #finishProcessingIfNecessary}
      */
     private OutputFinisher unprocessedInsns;
 
     /**
-     * non-null; unprocessed catch table;
+     * {@code non-null;} unprocessed catch table;
      * nulled out in {@link #finishProcessingIfNecessary}
      */
     private CatchBuilder unprocessedCatches;
 
     /**
-     * null-ok; catch table; set in
+     * {@code null-ok;} catch table; set in
      * {@link #finishProcessingIfNecessary} 
      */
     private CatchTable catches;
 
     /**
-     * null-ok; source positions list; set in
+     * {@code null-ok;} source positions list; set in
      * {@link #finishProcessingIfNecessary} 
      */
     private PositionList positions;
 
     /**
-     * null-ok; local variable list; set in
+     * {@code null-ok;} local variable list; set in
      * {@link #finishProcessingIfNecessary}
      */
     private LocalList locals;
 
     /**
-     * null-ok; the processed instruction list; set in
+     * {@code null-ok;} the processed instruction list; set in
      * {@link #finishProcessingIfNecessary}
      */
     private DalvInsnList insns;
@@ -73,9 +73,9 @@
      *
      * @param positionInfo how much position info to preserve; one of the
      * static constants in {@link PositionList}
-     * @param unprocessedInsns non-null; the instruction list, ready
+     * @param unprocessedInsns {@code non-null;} the instruction list, ready
      * for final processing
-     * @param unprocessedCatches non-null; unprocessed catch
+     * @param unprocessedCatches {@code non-null;} unprocessed catch
      * (exception handler) table
      */
     public DalvCode(int positionInfo, OutputFinisher unprocessedInsns,
@@ -120,7 +120,7 @@
      * given callback to perform lookups. This must be called before
      * {@link #getInsns}.
      * 
-     * @param callback non-null; callback object
+     * @param callback {@code non-null;} callback object
      */
     public void assignIndices(AssignIndicesCallback callback) {
         unprocessedInsns.assignIndices(callback);
@@ -129,7 +129,7 @@
     /**
      * Gets whether this instance has any position data to represent.
      * 
-     * @return <code>true</code> iff this instance has any position
+     * @return {@code true} iff this instance has any position
      * data to represent
      */
     public boolean hasPositions() {
@@ -140,7 +140,7 @@
     /**
      * Gets whether this instance has any local variable data to represent.
      * 
-     * @return <code>true</code> iff this instance has any local variable
+     * @return {@code true} iff this instance has any local variable
      * data to represent
      */
     public boolean hasLocals() {
@@ -160,7 +160,7 @@
     /**
      * Gets the set of catch types handled anywhere in the code.
      * 
-     * @return non-null; the set of catch types
+     * @return {@code non-null;} the set of catch types
      */
     public HashSet<Type> getCatchTypes() {
         return unprocessedCatches.getCatchTypes();
@@ -170,7 +170,7 @@
      * Gets the set of all constants referred to by instructions in
      * the code.
      * 
-     * @return non-null; the set of constants
+     * @return {@code non-null;} the set of constants
      */
     public HashSet<Constant> getInsnConstants() {
         return unprocessedInsns.getAllConstants();
@@ -179,7 +179,7 @@
     /**
      * Gets the list of instructions.
      * 
-     * @return non-null; the instruction list
+     * @return {@code non-null;} the instruction list
      */
     public DalvInsnList getInsns() {
         finishProcessingIfNecessary();
@@ -189,7 +189,7 @@
     /**
      * Gets the catch (exception handler) table.
      * 
-     * @return non-null; the catch table
+     * @return {@code non-null;} the catch table
      */
     public CatchTable getCatches() {
         finishProcessingIfNecessary();
@@ -199,7 +199,7 @@
     /**
      * Gets the source positions list.
      * 
-     * @return non-null; the source positions list
+     * @return {@code non-null;} the source positions list
      */
     public PositionList getPositions() {
         finishProcessingIfNecessary();
@@ -209,7 +209,7 @@
     /**
      * Gets the source positions list.
      * 
-     * @return non-null; the source positions list
+     * @return {@code non-null;} the source positions list
      */
     public LocalList getLocals() {
         finishProcessingIfNecessary();
@@ -223,8 +223,8 @@
         /**
          * Gets the index for the given constant.
          * 
-         * @param cst non-null; the constant
-         * @return &gt;= -1; the index or <code>-1</code> if the constant
+         * @param cst {@code non-null;} the constant
+         * @return {@code >= -1;} the index or {@code -1} if the constant
          * shouldn't actually be reified with an index
          */
         public int getIndex(Constant cst);
diff --git a/dx/src/com/android/dx/dex/code/DalvInsn.java b/dx/src/com/android/dx/dex/code/DalvInsn.java
index d922193..11ee55d 100644
--- a/dx/src/com/android/dx/dex/code/DalvInsn.java
+++ b/dx/src/com/android/dx/dex/code/DalvInsn.java
@@ -29,26 +29,26 @@
 public abstract class DalvInsn {
     /**
      * the actual output address of this instance, if known, or
-     * <code>-1</code> if not 
+     * {@code -1} if not 
      */
     private int address;
 
     /** the opcode; one of the constants from {@link Dops} */
     private final Dop opcode;
 
-    /** non-null; source position */
+    /** {@code non-null;} source position */
     private final SourcePosition position;
 
-    /** non-null; list of register arguments */
+    /** {@code non-null;} list of register arguments */
     private final RegisterSpecList registers;
 
     /**
      * Makes a move instruction, appropriate and ideal for the given arguments.
      * 
-     * @param position non-null; source position information
-     * @param dest non-null; destination register
-     * @param src non-null; source register
-     * @return non-null; an appropriately-constructed instance
+     * @param position {@code non-null;} source position information
+     * @param dest {@code non-null;} destination register
+     * @param src {@code non-null;} source register
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public static SimpleInsn makeMove(SourcePosition position,
             RegisterSpec dest, RegisterSpec src) {
@@ -75,17 +75,17 @@
 
     /**
      * Constructs an instance. The output address of this instance is initially
-     * unknown (<code>-1</code>).
+     * unknown ({@code -1}).
      * 
      * <p><b>Note:</b> In the unlikely event that an instruction takes
-     * absolutely no registers (e.g., a <code>nop</code> or a
+     * absolutely no registers (e.g., a {@code nop} or a
      * no-argument no-result static method call), then the given
      * register list may be passed as {@link
      * RegisterSpecList#EMPTY}.</p>
      * 
      * @param opcode the opcode; one of the constants from {@link Dops}
-     * @param position non-null; source position
-     * @param registers non-null; register list, including a
+     * @param position {@code non-null;} source position
+     * @param registers {@code non-null;} register list, including a
      * result register if appropriate (that is, registers may be either
      * ins and outs)
      */
@@ -151,11 +151,11 @@
 
     /**
      * Gets the output address of this instruction, if it is known. This throws
-     * a <code>RuntimeException</code> if it has not yet been set.
+     * a {@code RuntimeException} if it has not yet been set.
      * 
      * @see #setAddress
      * 
-     * @return &gt;= 0; the output address
+     * @return {@code >= 0;} the output address
      */
     public final int getAddress() {
         if (address < 0) {
@@ -168,7 +168,7 @@
     /**
      * Gets the opcode.
      * 
-     * @return non-null; the opcode
+     * @return {@code non-null;} the opcode
      */
     public final Dop getOpcode() {
         return opcode;
@@ -177,7 +177,7 @@
     /**
      * Gets the source position.
      * 
-     * @return non-null; the source position
+     * @return {@code non-null;} the source position
      */
     public final SourcePosition getPosition() {
         return position;
@@ -186,7 +186,7 @@
     /**
      * Gets the register list for this instruction.
      * 
-     * @return non-null; the registers
+     * @return {@code non-null;} the registers
      */
     public final RegisterSpecList getRegisters() {
         return registers;
@@ -195,9 +195,9 @@
     /**
      * Returns whether this instance's opcode uses a result register.
      * This method is a convenient shorthand for
-     * <code>getOpcode().hasResult()</code>.
+     * {@code getOpcode().hasResult()}.
      * 
-     * @return <code>true</code> iff this opcode uses a result register
+     * @return {@code true} iff this opcode uses a result register
      */
     public final boolean hasResult() {
         return opcode.hasResult();
@@ -210,7 +210,7 @@
      * (to be explicit here) category-2 values take up two consecutive
      * registers.
      * 
-     * @return &gt;= 0; the minimum distinct register requirement
+     * @return {@code >= 0;} the minimum distinct register requirement
      */
     public final int getMinimumRegisterRequirement() {
         boolean hasResult = hasResult();
@@ -231,7 +231,7 @@
      * 
      * @see #hrVersion
      * 
-     * @return null-ok; the prefix, if any
+     * @return {@code null-ok;} the prefix, if any
      */
     public DalvInsn hrPrefix() {
         RegisterSpecList regs = registers;
@@ -255,7 +255,7 @@
      * 
      * @see #hrVersion
      * 
-     * @return null-ok; the suffix, if any
+     * @return {@code null-ok;} the suffix, if any
      */
     public DalvInsn hrSuffix() {
         if (hasResult()) {
@@ -268,8 +268,8 @@
 
     /**
      * Gets the instruction that is equivalent to this one, except that
-     * uses sequential registers starting at <code>0</code> (storing
-     * the result, if any, in register <code>0</code> as well). The
+     * uses sequential registers starting at {@code 0} (storing
+     * the result, if any, in register {@code 0} as well). The
      * sequence of instructions from {@link #hrPrefix} and {@link
      * #hrSuffix} (if non-null) surrounding the result of a call to
      * this method are the high register transformation of this
@@ -277,7 +277,7 @@
      * used will be the number returned by {@link
      * #getMinimumRegisterRequirement}.
      * 
-     * @return non-null; the replacement
+     * @return {@code non-null;} the replacement
      */
     public DalvInsn hrVersion() {
         RegisterSpecList regs = 
@@ -289,7 +289,7 @@
      * Gets the short identifier for this instruction. This is its
      * address, if assigned, or its identity hashcode if not.
      * 
-     * @return non-null; the identifier
+     * @return {@code non-null;} the identifier
      */
     public final String identifierString() {
         if (address != -1) {
@@ -301,16 +301,16 @@
 
     /**
      * Returns the string form of this instance suitable for inclusion in
-     * a human-oriented listing dump. This method will return <code>null</code>
+     * a human-oriented listing dump. This method will return {@code null}
      * if this instance should not appear in a listing.
      * 
-     * @param prefix non-null; prefix before the address; each follow-on
+     * @param prefix {@code non-null;} prefix before the address; each follow-on
      * line will be indented to match as well
-     * @param width &gt;= 0; the width of the output or <code>0</code> for
+     * @param width {@code >= 0;} the width of the output or {@code 0} for
      * unlimited width
      * @param noteIndices whether to include an explicit notation of
      * constant pool indices
-     * @return null-ok; the string form or <code>null</code> if this
+     * @return {@code null-ok;} the string form or {@code null} if this
      * instance should not appear in a listing
      */
     public final String listingString(String prefix, int width,
@@ -331,7 +331,7 @@
     /**
      * Sets the output address.
      * 
-     * @param address &gt;= 0; the output address
+     * @param address {@code >= 0;} the output address
      */
     public final void setAddress(int address) {
         if (address < 0) {
@@ -347,7 +347,7 @@
      * to the address plus the length of the instruction format of this
      * instance's opcode.
      * 
-     * @return &gt;= 0; the next address
+     * @return {@code >= 0;} the next address
      */
     public final int getNextAddress() {
         return getAddress() + codeSize();
@@ -356,7 +356,7 @@
     /**
      * Gets the size of this instruction, in 16-bit code units.
      * 
-     * @return &gt;= 0; the code size of this instruction
+     * @return {@code >= 0;} the code size of this instruction
      */
     public abstract int codeSize();
 
@@ -364,7 +364,7 @@
      * Writes this instance to the given output. This method should
      * never annotate the output.
      * 
-     * @param out non-null; where to write to
+     * @param out {@code non-null;} where to write to
      */
     public abstract void writeTo(AnnotatedOutput out);
 
@@ -372,8 +372,8 @@
      * Returns an instance that is just like this one, except that its
      * opcode is replaced by the one given, and its address is reset.
      * 
-     * @param opcode non-null; the new opcode
-     * @return non-null; an appropriately-constructed instance
+     * @param opcode {@code non-null;} the new opcode
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public abstract DalvInsn withOpcode(Dop opcode);
 
@@ -383,7 +383,7 @@
      * address is reset.
      * 
      * @param delta the amount to offset register references by
-     * @return non-null; an appropriately-constructed instance
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public abstract DalvInsn withRegisterOffset(int delta);
 
@@ -392,8 +392,8 @@
      * register list is replaced by the given one, and its address is
      * reset.
      * 
-     * @param registers non-null; new register list
-     * @return non-null; an appropriately-constructed instance
+     * @param registers {@code non-null;} new register list
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public abstract DalvInsn withRegisters(RegisterSpecList registers);
 
@@ -401,8 +401,8 @@
      * Gets the string form for any arguments to this instance. Subclasses
      * must override this.
      * 
-     * @return null-ok; the string version of any arguments or
-     * <code>null</code> if there are none
+     * @return {@code null-ok;} the string version of any arguments or
+     * {@code null} if there are none
      */
     protected abstract String argString();
 
@@ -411,12 +411,12 @@
      * form of this instance suitable for inclusion in a
      * human-oriented listing dump, not including the instruction
      * address and without respect for any output formatting. This
-     * method should return <code>null</code> if this instance should
+     * method should return {@code null} if this instance should
      * not appear in a listing.
      * 
      * @param noteIndices whether to include an explicit notation of
      * constant pool indices
-     * @return null-ok; the listing string
+     * @return {@code null-ok;} the listing string
      */
     protected abstract String listingString0(boolean noteIndices);
 }
diff --git a/dx/src/com/android/dx/dex/code/DalvInsnList.java b/dx/src/com/android/dx/dex/code/DalvInsnList.java
index 2cd15c6..5cf22f2 100644
--- a/dx/src/com/android/dx/dex/code/DalvInsnList.java
+++ b/dx/src/com/android/dx/dex/code/DalvInsnList.java
@@ -46,10 +46,10 @@
      * Constructs and returns an immutable instance whose elements are
      * identical to the ones in the given list, in the same order.
      * 
-     * @param list non-null; the list to use for elements
+     * @param list {@code non-null;} the list to use for elements
      * @param regCount count, in register-units, of the number of registers
      * this code block requires.
-     * @return non-null; an appropriately-constructed instance of this
+     * @return {@code non-null;} an appropriately-constructed instance of this
      * class
      */
     public static DalvInsnList makeImmutable(ArrayList<DalvInsn> list,
@@ -66,7 +66,7 @@
     }
     
     /**
-     * Constructs an instance. All indices initially contain <code>null</code>.
+     * Constructs an instance. All indices initially contain {@code null}.
      * 
      * @param size the size of the list
      */
@@ -78,10 +78,10 @@
     /**
      * Gets the element at the given index. It is an error to call
      * this with the index for an element which was never set; if you
-     * do that, this will throw <code>NullPointerException</code>.
+     * do that, this will throw {@code NullPointerException}.
      * 
-     * @param n &gt;= 0, &lt; size(); which index
-     * @return non-null; element at that index
+     * @param n {@code >= 0, < size();} which index
+     * @return {@code non-null;} element at that index
      */
     public DalvInsn get(int n) {
         return (DalvInsn) get0(n);
@@ -90,8 +90,8 @@
     /**
      * Sets the instruction at the given index.
      * 
-     * @param n &gt;= 0, &lt; size(); which index
-     * @param insn non-null; the instruction to set at <code>n</code>
+     * @param n {@code >= 0, < size();} which index
+     * @param insn {@code non-null;} the instruction to set at {@code n}
      */
     public void set(int n, DalvInsn insn) {
         set0(n, insn);
@@ -102,7 +102,7 @@
      * return a meaningful result if the instructions in this instance all
      * have valid addresses.
      * 
-     * @return &gt;= 0; the size
+     * @return {@code >= 0;} the size
      */
     public int codeSize() {
         int sz = size();
@@ -119,7 +119,7 @@
      * Writes all the instructions in this instance to the given output
      * destination.
      * 
-     * @param out non-null; where to write to
+     * @param out {@code non-null;} where to write to
      */
     public void writeTo(AnnotatedOutput out) {
         int startCursor = out.getCursor();
@@ -170,7 +170,7 @@
      * Gets the minimum required register count implied by this
      * instance.  This includes any unused parameters that could
      * potentially be at the top of the register space.
-     * @return &gt;= 0; the required registers size
+     * @return {@code >= 0;} the required registers size
      */
     public int getRegistersSize() {
         return regCount;
@@ -181,7 +181,7 @@
      * method. This is equal to the largest argument word count of any
      * method referred to by this instance.
      * 
-     * @return &gt;= 0; the required outgoing arguments size
+     * @return {@code >= 0;} the required outgoing arguments size
      */
     public int getOutsSize() {
         int sz = size();
@@ -216,8 +216,8 @@
     /**
      * Does a human-friendly dump of this instance.
      * 
-     * @param out non-null; where to dump
-     * @param prefix non-null; prefix to attach to each line of output
+     * @param out {@code non-null;} where to dump
+     * @param prefix {@code non-null;} prefix to attach to each line of output
      * @param verbose whether to be verbose; verbose output includes
      * lines for zero-size instructions and explicit constant pool indices
      */
@@ -250,8 +250,8 @@
     /**
      * Does a human-friendly dump of this instance.
      * 
-     * @param out non-null; where to dump
-     * @param prefix non-null; prefix to attach to each line of output
+     * @param out {@code non-null;} where to dump
+     * @param prefix {@code non-null;} prefix to attach to each line of output
      * @param verbose whether to be verbose; verbose output includes
      * lines for zero-size instructions
      */
diff --git a/dx/src/com/android/dx/dex/code/Dop.java b/dx/src/com/android/dx/dex/code/Dop.java
index 6914fca..d1f92bf 100644
--- a/dx/src/com/android/dx/dex/code/Dop.java
+++ b/dx/src/com/android/dx/dex/code/Dop.java
@@ -26,25 +26,25 @@
     /** DalvOps.MIN_VALUE..DalvOps.MAX_VALUE; the opcode family */
     private final int family;
 
-    /** non-null; the instruction format */
+    /** {@code non-null;} the instruction format */
     private final InsnFormat format;
 
     /** whether this opcode uses a result register */
     private final boolean hasResult;
 
-    /** non-null; the name */
+    /** {@code non-null;} the name */
     private final String name;
 
     /**
      * Constructs an instance.
      * 
-     * @param opcode DalvOps.MIN_VALUE..DalvOps.MAX_VALUE; the opcode
+     * @param opcode {@code DalvOps.MIN_VALUE..DalvOps.MAX_VALUE;} the opcode
      * value itself
-     * @param family DalvOps.MIN_VALUE..DalvOps.MAX_VALUE; the opcode family
-     * @param format non-null; the instruction format
+     * @param family {@code DalvOps.MIN_VALUE..DalvOps.MAX_VALUE;} the opcode family
+     * @param format {@code non-null;} the instruction format
      * @param hasResult whether the opcode has a result register; if so it
      * is always the first register
-     * @param name non-null; the name
+     * @param name {@code non-null;} the name
      */
     public Dop(int opcode, int family, InsnFormat format,
                boolean hasResult, String name) {
@@ -80,7 +80,7 @@
     /**
      * Gets the opcode value.
      * 
-     * @return DalvOps.MIN_VALUE..DalvOps.MAX_VALUE; the opcode value
+     * @return {@code DalvOps.MIN_VALUE..DalvOps.MAX_VALUE;} the opcode value
      */
     public int getOpcode() {
         return opcode;
@@ -90,7 +90,7 @@
      * Gets the opcode family. The opcode family is the unmarked (no
      * "/...") opcode that has equivalent semantics to this one.
      * 
-     * @return DalvOps.MIN_VALUE..DalvOps.MAX_VALUE; the opcode family
+     * @return {@code DalvOps.MIN_VALUE..DalvOps.MAX_VALUE;} the opcode family
      */
     public int getFamily() {
         return family;
@@ -99,7 +99,7 @@
     /**
      * Gets the instruction format.
      * 
-     * @return non-null; the instruction format
+     * @return {@code non-null;} the instruction format
      */
     public InsnFormat getFormat() {
         return format;
@@ -108,7 +108,7 @@
     /**
      * Returns whether this opcode uses a result register.
      * 
-     * @return <code>true</code> iff this opcode uses a result register
+     * @return {@code true} iff this opcode uses a result register
      */
     public boolean hasResult() {
         return hasResult;
@@ -117,7 +117,7 @@
     /**
      * Gets the opcode name.
      * 
-     * @return non-null; the opcode name
+     * @return {@code non-null;} the opcode name
      */
     public String getName() {
         return name;
@@ -127,7 +127,7 @@
      * Gets the opcode for the opposite test of this instance. This is only
      * valid for opcodes which are in fact tests.
      * 
-     * @return non-null; the opposite test
+     * @return {@code non-null;} the opposite test
      */
     public Dop getOppositeTest() {
         switch (opcode) {
diff --git a/dx/src/com/android/dx/dex/code/Dops.java b/dx/src/com/android/dx/dex/code/Dops.java
index 8923c59..dfdaa73 100644
--- a/dx/src/com/android/dx/dex/code/Dops.java
+++ b/dx/src/com/android/dx/dex/code/Dops.java
@@ -47,7 +47,7 @@
  * them.
  */
 public final class Dops {
-    /** non-null; array containing all the standard instances */
+    /** {@code non-null;} array containing all the standard instances */
     private static final Dop[] DOPS;
 
     /**
@@ -1172,8 +1172,8 @@
     /**
      * Gets the {@link Dop} for the given opcode value.
      * 
-     * @param opcode DalvOps.MIN_VALUE..DalvOps.MAX_VALUE; the opcode value
-     * @return non-null; the associated opcode instance
+     * @param opcode {@code DalvOps.MIN_VALUE..DalvOps.MAX_VALUE;} the opcode value
+     * @return {@code non-null;} the associated opcode instance
      */
     public static Dop get(int opcode) {
         int idx = opcode - DalvOps.MIN_VALUE;
@@ -1194,9 +1194,9 @@
      * Gets the {@link Dop} with the given family/format combination, if
      * any.
      * 
-     * @param family DalvOps.MIN_VALUE..DalvOps.MAX_VALUE; the opcode family
-     * @param format non-null; the opcode's instruction format
-     * @return null-ok; the corresponding opcode, or <code>null</code> if
+     * @param family {@code DalvOps.MIN_VALUE..DalvOps.MAX_VALUE;} the opcode family
+     * @param format {@code non-null;} the opcode's instruction format
+     * @return {@code null-ok;} the corresponding opcode, or {@code null} if
      * there is none
      */
     public static Dop getOrNull(int family, InsnFormat format) {
@@ -1222,7 +1222,7 @@
     /**
      * Puts the given opcode into the table of all ops.
      * 
-     * @param opcode non-null; the opcode
+     * @param opcode {@code non-null;} the opcode
      */
     private static void set(Dop opcode) {
         int idx = opcode.getOpcode() - DalvOps.MIN_VALUE;
diff --git a/dx/src/com/android/dx/dex/code/FixedSizeInsn.java b/dx/src/com/android/dx/dex/code/FixedSizeInsn.java
index 63c9d24..147937f 100644
--- a/dx/src/com/android/dx/dex/code/FixedSizeInsn.java
+++ b/dx/src/com/android/dx/dex/code/FixedSizeInsn.java
@@ -28,17 +28,17 @@
 public abstract class FixedSizeInsn extends DalvInsn {
     /**
      * Constructs an instance. The output address of this instance is initially
-     * unknown (<code>-1</code>).
+     * unknown ({@code -1}).
      * 
      * <p><b>Note:</b> In the unlikely event that an instruction takes
-     * absolutely no registers (e.g., a <code>nop</code> or a
+     * absolutely no registers (e.g., a {@code nop} or a
      * no-argument no-result * static method call), then the given
      * register list may be passed as {@link
      * RegisterSpecList#EMPTY}.</p>
      * 
      * @param opcode the opcode; one of the constants from {@link Dops}
-     * @param position non-null; source position
-     * @param registers non-null; register list, including a
+     * @param position {@code non-null;} source position
+     * @param registers {@code non-null;} register list, including a
      * result register if appropriate (that is, registers may be either
      * ins or outs)
      */
diff --git a/dx/src/com/android/dx/dex/code/HighRegisterPrefix.java b/dx/src/com/android/dx/dex/code/HighRegisterPrefix.java
index 458bc89..9155367 100644
--- a/dx/src/com/android/dx/dex/code/HighRegisterPrefix.java
+++ b/dx/src/com/android/dx/dex/code/HighRegisterPrefix.java
@@ -24,21 +24,21 @@
 
 /**
  * Combination instruction which turns into a variable number of
- * <code>move*</code> instructions to move a set of registers into
- * registers starting at <code>0</code> sequentially. This is used
+ * {@code move*} instructions to move a set of registers into
+ * registers starting at {@code 0} sequentially. This is used
  * in translating an instruction whose register requirements cannot
  * be met using a straightforward choice of a single opcode.
  */
 public final class HighRegisterPrefix extends VariableSizeInsn {
-    /** null-ok; cached instructions, if constructed */
+    /** {@code null-ok;} cached instructions, if constructed */
     private SimpleInsn[] insns;
     
     /**
      * Constructs an instance. The output address of this instance is initially
-     * unknown (<code>-1</code>).
+     * unknown ({@code -1}).
      * 
-     * @param position non-null; source position
-     * @param registers non-null; source registers
+     * @param position {@code non-null;} source position
+     * @param registers {@code non-null;} source registers
      */
     public HighRegisterPrefix(SourcePosition position,
                               RegisterSpecList registers) {
@@ -135,9 +135,9 @@
      * Returns the proper move instruction for the given source spec
      * and destination index.
      *
-     * @param src non-null; the source register spec
-     * @param destIndex &gt;= 0; the destination register index
-     * @return non-null; the appropriate move instruction
+     * @param src {@code non-null;} the source register spec
+     * @param destIndex {@code >= 0;} the destination register index
+     * @return {@code non-null;} the appropriate move instruction
      */
     private static SimpleInsn moveInsnFor(RegisterSpec src, int destIndex) {
         return DalvInsn.makeMove(SourcePosition.NO_INFO,
diff --git a/dx/src/com/android/dx/dex/code/InsnFormat.java b/dx/src/com/android/dx/dex/code/InsnFormat.java
index ed4137b..ca6688b 100644
--- a/dx/src/com/android/dx/dex/code/InsnFormat.java
+++ b/dx/src/com/android/dx/dex/code/InsnFormat.java
@@ -37,10 +37,10 @@
      * dump, of the given instruction. The instruction must be of this
      * instance's format for proper operation.
      *
-     * @param insn non-null; the instruction
+     * @param insn {@code non-null;} the instruction
      * @param noteIndices whether to include an explicit notation of
      * constant pool indices
-     * @return non-null; the string form
+     * @return {@code non-null;} the string form
      */
     public final String listingString(DalvInsn insn, boolean noteIndices) {
         String op = insn.getOpcode().getName();
@@ -66,28 +66,28 @@
     /**
      * Returns the string form of the arguments to the given instruction.
      * The instruction must be of this instance's format. If the instruction
-     * has no arguments, then the result should be <code>""</code>, not
-     * <code>null</code>.
+     * has no arguments, then the result should be {@code ""}, not
+     * {@code null}.
      *
      * <p>Subclasses must override this method.</p>
      *
-     * @param insn non-null; the instruction
-     * @return non-null; the string form
+     * @param insn {@code non-null;} the instruction
+     * @return {@code non-null;} the string form
      */
     public abstract String insnArgString(DalvInsn insn);
 
     /**
      * Returns the associated comment for the given instruction, if any.
      * The instruction must be of this instance's format. If the instruction
-     * has no comment, then the result should be <code>""</code>, not
-     * <code>null</code>.
+     * has no comment, then the result should be {@code ""}, not
+     * {@code null}.
      *
      * <p>Subclasses must override this method.</p>
      *
-     * @param insn non-null; the instruction
+     * @param insn {@code non-null;} the instruction
      * @param noteIndices whether to include an explicit notation of
      * constant pool indices
-     * @return non-null; the string form
+     * @return {@code non-null;} the string form
      */
     public abstract String insnCommentString(DalvInsn insn,
             boolean noteIndices);
@@ -97,7 +97,7 @@
      * size is a number of 16-bit code units, not bytes. This should
      * throw an exception if this format is of variable size.
      *
-     * @return &gt;= 0; the instruction length in 16-bit code units
+     * @return {@code >= 0;} the instruction length in 16-bit code units
      */
     public abstract int codeSize();
 
@@ -112,24 +112,24 @@
      *
      * <p>Subclasses must override this method.</p>
      *
-     * @param insn non-null; the instruction to check
-     * @return <code>true</code> iff the instruction's arguments are
-     * appropriate for this instance, or <code>false</code> if not
+     * @param insn {@code non-null;} the instruction to check
+     * @return {@code true} iff the instruction's arguments are
+     * appropriate for this instance, or {@code false} if not
      */
     public abstract boolean isCompatible(DalvInsn insn);
 
     /**
      * Returns whether or not the given instruction's branch offset will
-     * fit in this instance's format. This always returns <code>false</code>
+     * fit in this instance's format. This always returns {@code false}
      * for formats that don't include a branch offset.
      *
      * <p>The default implementation of this method always returns
-     * <code>false</code>. Subclasses must override this method if they
+     * {@code false}. Subclasses must override this method if they
      * include branch offsets.</p>
      *
-     * @param insn non-null; the instruction to check
-     * @return <code>true</code> iff the instruction's branch offset is
-     * appropriate for this instance, or <code>false</code> if not
+     * @param insn {@code non-null;} the instruction to check
+     * @return {@code true} iff the instruction's branch offset is
+     * appropriate for this instance, or {@code false} if not
      */
     public boolean branchFits(TargetInsn insn) {
         return false;
@@ -141,7 +141,7 @@
      *
      * <p>Subclasses must override this method.</p>
      *
-     * @return null-ok; the next format to try, or <code>null</code> if
+     * @return {@code null-ok;} the next format to try, or {@code null} if
      * there are no suitable alternatives
      */
     public abstract InsnFormat nextUp();
@@ -152,16 +152,16 @@
      *
      * <p>Subclasses must override this method.</p>
      *
-     * @param out non-null; the output destination to write to
-     * @param insn non-null; the instruction to write
+     * @param out {@code non-null;} the output destination to write to
+     * @param insn {@code non-null;} the instruction to write
      */
     public abstract void writeTo(AnnotatedOutput out, DalvInsn insn);
 
     /**
      * Helper method to return a register list string.
      *
-     * @param list non-null; the list of registers
-     * @return non-null; the string form
+     * @param list {@code non-null;} the list of registers
+     * @return {@code non-null;} the string form
      */
     protected static String regListString(RegisterSpecList list) {
         int sz = list.size();
@@ -185,7 +185,7 @@
      * Helper method to return a literal bits argument string.
      *
      * @param value the value
-     * @return non-null; the string form
+     * @return {@code non-null;} the string form
      */
     protected static String literalBitsString(CstLiteralBits value) {
         StringBuffer sb = new StringBuffer(100);
@@ -208,8 +208,8 @@
      *
      * @param value the value
      * @param width the width of the constant, in bits (used for displaying
-     * the uninterpreted bits; one of: <code>4 8 16 32 64</code>
-     * @return non-null; the comment
+     * the uninterpreted bits; one of: {@code 4 8 16 32 64}
+     * @return {@code non-null;} the comment
      */
     protected static String literalBitsComment(CstLiteralBits value,
             int width) {
@@ -242,8 +242,8 @@
     /**
      * Helper method to return a branch address string.
      *
-     * @param insn non-null; the instruction in question
-     * @return non-null; the string form of the instruction's branch target
+     * @param insn {@code non-null;} the instruction in question
+     * @return {@code non-null;} the string form of the instruction's branch target
      */
     protected static String branchString(DalvInsn insn) {
         TargetInsn ti = (TargetInsn) insn;
@@ -255,8 +255,8 @@
     /**
      * Helper method to return the comment for a branch.
      *
-     * @param insn non-null; the instruction in question
-     * @return non-null; the comment
+     * @param insn {@code non-null;} the instruction in question
+     * @return {@code non-null;} the comment
      */
     protected static String branchComment(DalvInsn insn) {
         TargetInsn ti = (TargetInsn) insn;
@@ -268,8 +268,8 @@
     /**
      * Helper method to return a constant string.
      *
-     * @param insn non-null; a constant-bearing instruction
-     * @return non-null; the string form of the contained constant
+     * @param insn {@code non-null;} a constant-bearing instruction
+     * @return {@code non-null;} the string form of the contained constant
      */
     protected static String cstString(DalvInsn insn) {
         CstInsn ci = (CstInsn) insn;
@@ -281,8 +281,8 @@
     /**
      * Helper method to return an instruction comment for a constant.
      *
-     * @param insn non-null; a constant-bearing instruction
-     * @return non-null; comment string representing the constant
+     * @param insn {@code non-null;} a constant-bearing instruction
+     * @return {@code non-null;} comment string representing the constant
      */
     protected static String cstComment(DalvInsn insn) {
         CstInsn ci = (CstInsn) insn;
@@ -310,7 +310,7 @@
      * Helper method to determine if a signed int value fits in a nibble.
      *
      * @param value the value in question
-     * @return <code>true</code> iff it's in the range -8..+7
+     * @return {@code true} iff it's in the range -8..+7
      */
     protected static boolean signedFitsInNibble(int value) {
         return (value >= -8) && (value <= 7);
@@ -320,7 +320,7 @@
      * Helper method to determine if an unsigned int value fits in a nibble.
      *
      * @param value the value in question
-     * @return <code>true</code> iff it's in the range 0..0xf
+     * @return {@code true} iff it's in the range 0..0xf
      */
     protected static boolean unsignedFitsInNibble(int value) {
         return value == (value & 0xf);
@@ -330,7 +330,7 @@
      * Helper method to determine if a signed int value fits in a byte.
      *
      * @param value the value in question
-     * @return <code>true</code> iff it's in the range -0x80..+0x7f
+     * @return {@code true} iff it's in the range -0x80..+0x7f
      */
     protected static boolean signedFitsInByte(int value) {
         return (byte) value == value;
@@ -340,7 +340,7 @@
      * Helper method to determine if an unsigned int value fits in a byte.
      *
      * @param value the value in question
-     * @return <code>true</code> iff it's in the range 0..0xff
+     * @return {@code true} iff it's in the range 0..0xff
      */
     protected static boolean unsignedFitsInByte(int value) {
         return value == (value & 0xff);
@@ -350,7 +350,7 @@
      * Helper method to determine if a signed int value fits in a short.
      *
      * @param value the value in question
-     * @return <code>true</code> iff it's in the range -0x8000..+0x7fff
+     * @return {@code true} iff it's in the range -0x8000..+0x7fff
      */
     protected static boolean signedFitsInShort(int value) {
         return (short) value == value;
@@ -360,7 +360,7 @@
      * Helper method to determine if an unsigned int value fits in a short.
      *
      * @param value the value in question
-     * @return <code>true</code> iff it's in the range 0..0xffff
+     * @return {@code true} iff it's in the range 0..0xffff
      */
     protected static boolean unsignedFitsInShort(int value) {
         return value == (value & 0xffff);
@@ -370,7 +370,7 @@
      * Helper method to determine if a signed int value fits in three bytes.
      *
      * @param value the value in question
-     * @return <code>true</code> iff it's in the range -0x800000..+0x7fffff
+     * @return {@code true} iff it's in the range -0x800000..+0x7fffff
      */
     protected static boolean signedFitsIn3Bytes(int value) {
         return value == ((value << 8) >> 8);
@@ -380,8 +380,8 @@
      * Helper method to extract the callout-argument index from an
      * appropriate instruction.
      *
-     * @param insn non-null; the instruction
-     * @return &gt;= 0; the callout argument index
+     * @param insn {@code non-null;} the instruction
+     * @return {@code >= 0;} the callout argument index
      */
     protected static int argIndex(DalvInsn insn) {
         int arg = ((CstInteger) ((CstInsn) insn).getConstant()).getValue();
@@ -397,8 +397,8 @@
      * Helper method to combine an opcode and a second byte of data into
      * the appropriate form for emitting into a code buffer.
      *
-     * @param insn non-null; the instruction containing the opcode
-     * @param arg 0..255; arbitrary other byte value
+     * @param insn {@code non-null;} the instruction containing the opcode
+     * @param arg {@code 0..255;} arbitrary other byte value
      * @return combined value
      */
     protected static short opcodeUnit(DalvInsn insn, int arg) {
@@ -418,8 +418,8 @@
     /**
      * Helper method to combine two bytes into a code unit.
      *
-     * @param low 0..255; low byte
-     * @param high 0..255; high byte
+     * @param low {@code 0..255;} low byte
+     * @param high {@code 0..255;} high byte
      * @return combined value
      */
     protected static short codeUnit(int low, int high) {
@@ -437,10 +437,10 @@
     /**
      * Helper method to combine four nibbles into a code unit.
      *
-     * @param n0 0..15; low nibble
-     * @param n1 0..15; medium-low nibble
-     * @param n2 0..15; medium-high nibble
-     * @param n3 0..15; high nibble
+     * @param n0 {@code 0..15;} low nibble
+     * @param n1 {@code 0..15;} medium-low nibble
+     * @param n2 {@code 0..15;} medium-high nibble
+     * @param n3 {@code 0..15;} high nibble
      * @return combined value
      */
     protected static short codeUnit(int n0, int n1, int n2, int n3) {
@@ -466,9 +466,9 @@
     /**
      * Helper method to combine two nibbles into a byte.
      *
-     * @param low 0..15; low nibble
-     * @param high 0..15; high nibble
-     * @return 0..255; combined value
+     * @param low {@code 0..15;} low nibble
+     * @param high {@code 0..15;} high nibble
+     * @return {@code 0..255;} combined value
      */
     protected static int makeByte(int low, int high) {
         if ((low & 0xf) != low) {
@@ -485,7 +485,7 @@
     /**
      * Writes one code unit to the given output destination.
      * 
-     * @param out non-null; where to write to
+     * @param out {@code non-null;} where to write to
      * @param c0 code unit to write
      */
     protected static void write(AnnotatedOutput out, short c0) {
@@ -495,7 +495,7 @@
     /**
      * Writes two code units to the given output destination.
      * 
-     * @param out non-null; where to write to
+     * @param out {@code non-null;} where to write to
      * @param c0 code unit to write
      * @param c1 code unit to write
      */
@@ -507,7 +507,7 @@
     /**
      * Writes three code units to the given output destination.
      * 
-     * @param out non-null; where to write to
+     * @param out {@code non-null;} where to write to
      * @param c0 code unit to write
      * @param c1 code unit to write
      * @param c2 code unit to write
@@ -522,7 +522,7 @@
     /**
      * Writes four code units to the given output destination.
      * 
-     * @param out non-null; where to write to
+     * @param out {@code non-null;} where to write to
      * @param c0 code unit to write
      * @param c1 code unit to write
      * @param c2 code unit to write
@@ -539,7 +539,7 @@
     /**
      * Writes five code units to the given output destination.
      * 
-     * @param out non-null; where to write to
+     * @param out {@code non-null;} where to write to
      * @param c0 code unit to write
      * @param c1 code unit to write
      * @param c2 code unit to write
@@ -558,7 +558,7 @@
     /**
      * Writes six code units to the given output destination.
      * 
-     * @param out non-null; where to write to
+     * @param out {@code non-null;} where to write to
      * @param c0 code unit to write
      * @param c1 code unit to write
      * @param c2 code unit to write
diff --git a/dx/src/com/android/dx/dex/code/LocalEnd.java b/dx/src/com/android/dx/dex/code/LocalEnd.java
index c19a8dc..360a55c 100644
--- a/dx/src/com/android/dx/dex/code/LocalEnd.java
+++ b/dx/src/com/android/dx/dex/code/LocalEnd.java
@@ -28,7 +28,7 @@
  */
 public final class LocalEnd extends ZeroSizeInsn {
     /**
-     * non-null; register spec representing the local variable ended
+     * {@code non-null;} register spec representing the local variable ended
      * by this instance. <b>Note:</b> Technically, only the register
      * number needs to be recorded here as the rest of the information
      * is implicit in the ambient local variable state, but other code
@@ -38,10 +38,10 @@
 
     /**
      * Constructs an instance. The output address of this instance is initially
-     * unknown (<code>-1</code>).
+     * unknown ({@code -1}).
      * 
-     * @param position non-null; source position
-     * @param local non-null; register spec representing the local
+     * @param position {@code non-null;} source position
+     * @param local {@code non-null;} register spec representing the local
      * variable introduced by this instance
      */
     public LocalEnd(SourcePosition position, RegisterSpec local) {
@@ -70,7 +70,7 @@
      * Gets the register spec representing the local variable ended
      * by this instance.
      * 
-     * @return non-null; the register spec
+     * @return {@code non-null;} the register spec
      */
     public RegisterSpec getLocal() {
         return local;
diff --git a/dx/src/com/android/dx/dex/code/LocalList.java b/dx/src/com/android/dx/dex/code/LocalList.java
index 4614fc4..93e7c3f 100644
--- a/dx/src/com/android/dx/dex/code/LocalList.java
+++ b/dx/src/com/android/dx/dex/code/LocalList.java
@@ -33,16 +33,16 @@
  * and a type.
  */
 public final class LocalList extends FixedSizeList {
-    /** non-null; empty instance */
+    /** {@code non-null;} empty instance */
     public static final LocalList EMPTY = new LocalList(0);
 
     /** whether to run the self-check code */
     private static final boolean DEBUG = false;
-    
+
     /**
-     * Constructs an instance. All indices initially contain <code>null</code>.
-     * 
-     * @param size &gt;= 0; the size of the list
+     * Constructs an instance. All indices initially contain {@code null}.
+     *
+     * @param size {@code >= 0;} the size of the list
      */
     public LocalList(int size) {
         super(size);
@@ -51,10 +51,10 @@
     /**
      * Gets the element at the given index. It is an error to call
      * this with the index for an element which was never set; if you
-     * do that, this will throw <code>NullPointerException</code>.
-     * 
-     * @param n &gt;= 0, &lt; size(); which index
-     * @return non-null; element at that index
+     * do that, this will throw {@code NullPointerException}.
+     *
+     * @param n {@code >= 0, < size();} which index
+     * @return {@code non-null;} element at that index
      */
     public Entry get(int n) {
         return (Entry) get0(n);
@@ -62,9 +62,9 @@
 
     /**
      * Sets the entry at the given index.
-     * 
-     * @param n &gt;= 0, &lt; size(); which index
-     * @param entry non-null; the entry to set at <code>n</code>
+     *
+     * @param n {@code >= 0, < size();} which index
+     * @param entry {@code non-null;} the entry to set at {@code n}
      */
     public void set(int n, Entry entry) {
         set0(n, entry);
@@ -72,9 +72,9 @@
 
     /**
      * Does a human-friendly dump of this instance.
-     * 
-     * @param out non-null; where to dump
-     * @param prefix non-null; prefix to attach to each line of output
+     *
+     * @param out {@code non-null;} where to dump
+     * @param prefix {@code non-null;} prefix to attach to each line of output
      */
     public void debugPrint(PrintStream out, String prefix) {
         int sz = size();
@@ -90,7 +90,7 @@
      */
     public static enum Disposition {
         /** local started (introduced) */
-        START, 
+        START,
 
         /** local ended without being replaced */
         END_SIMPLY,
@@ -118,24 +118,25 @@
      * Entry in a local list.
      */
     public static class Entry implements Comparable<Entry> {
-        /** &gt;= 0; address */
+        /** {@code >= 0;} address */
         private final int address;
 
-        /** non-null; disposition of the local */
+        /** {@code non-null;} disposition of the local */
         private final Disposition disposition;
 
-        /** non-null; register spec representing the variable */
+        /** {@code non-null;} register spec representing the variable */
         private final RegisterSpec spec;
 
-        /** non-null; variable type (derived from {@code spec}) */
+        /** {@code non-null;} variable type (derived from {@code spec}) */
         private final CstType type;
-        
+
         /**
          * Constructs an instance.
-         * 
-         * @param address &gt;= 0; address 
-         * @param disposition non-null; disposition of the local
-         * @param spec non-null; register spec representing the variable
+         *
+         * @param address {@code >= 0;} address
+         * @param disposition {@code non-null;} disposition of the local
+         * @param spec {@code non-null;} register spec representing
+         * the variable
          */
         public Entry(int address, Disposition disposition, RegisterSpec spec) {
             if (address < 0) {
@@ -181,9 +182,9 @@
          * Compares by (in priority order) address, end then start
          * disposition (variants of end are all consistered
          * equivalent), and spec.
-         * 
-         * @param other non-null; entry to compare to
-         * @return {@code -1..1}; standard result of comparison
+         *
+         * @param other {@code non-null;} entry to compare to
+         * @return {@code -1..1;} standard result of comparison
          */
         public int compareTo(Entry other) {
             if (address < other.address) {
@@ -194,7 +195,7 @@
 
             boolean thisIsStart = isStart();
             boolean otherIsStart = other.isStart();
-            
+
             if (thisIsStart != otherIsStart) {
                 return thisIsStart ? 1 : -1;
             }
@@ -204,8 +205,8 @@
 
         /**
          * Gets the address.
-         * 
-         * @return &gt;= 0; the address
+         *
+         * @return {@code >= 0;} the address
          */
         public int getAddress() {
             return address;
@@ -213,8 +214,8 @@
 
         /**
          * Gets the disposition.
-         * 
-         * @return non-null; the disposition
+         *
+         * @return {@code non-null;} the disposition
          */
         public Disposition getDisposition() {
             return disposition;
@@ -223,7 +224,7 @@
         /**
          * Gets whether this is a local start. This is just shorthand for
          * {@code getDisposition() == Disposition.START}.
-         * 
+         *
          * @return {@code true} iff this is a start
          */
         public boolean isStart() {
@@ -232,8 +233,8 @@
 
         /**
          * Gets the variable name.
-         * 
-         * @return null-ok; the variable name
+         *
+         * @return {@code null-ok;} the variable name
          */
         public CstUtf8 getName() {
             return spec.getLocalItem().getName();
@@ -242,7 +243,7 @@
         /**
          * Gets the variable signature.
          *
-         * @return null-ok; the variable signature
+         * @return {@code null-ok;} the variable signature
          */
         public CstUtf8 getSignature() {
             return spec.getLocalItem().getSignature();
@@ -250,8 +251,8 @@
 
         /**
          * Gets the variable's type.
-         * 
-         * @return non-null; the type
+         *
+         * @return {@code non-null;} the type
          */
         public CstType getType() {
             return type;
@@ -259,8 +260,9 @@
 
         /**
          * Gets the number of the register holding the variable.
-         * 
-         * @return &gt;= 0; the number fo the register holding the variable
+         *
+         * @return {@code >= 0;} the number of the register holding
+         * the variable
          */
         public int getRegister() {
             return spec.getReg();
@@ -269,7 +271,7 @@
         /**
          * Gets the RegisterSpec of the register holding the variable.
          *
-         * @return non-null; RegisterSpec of the holding register.
+         * @return {@code non-null;} RegisterSpec of the holding register.
          */
         public RegisterSpec getRegisterSpec() {
             return spec;
@@ -277,10 +279,10 @@
 
         /**
          * Returns whether or not this instance matches the given spec.
-         * 
-         * @param spec non-null; the spec in question
-         * @return <code>true</code> iff this instance matches
-         * <code>spec</code>
+         *
+         * @param spec {@code non-null;} the spec in question
+         * @return {@code true} iff this instance matches
+         * {@code spec}
          */
         public boolean matches(RegisterSpec otherSpec) {
             return spec.equalsUsingSimpleType(otherSpec);
@@ -290,9 +292,9 @@
          * Returns whether or not this instance matches the spec in
          * the given instance.
          *
-         * @param other non-null; another entry
-         * @return <code>true</code> iff this instance's spec matches
-         * <code>other</code>
+         * @param other {@code non-null;} another entry
+         * @return {@code true} iff this instance's spec matches
+         * {@code other}
          */
         public boolean matches(Entry other) {
             return matches(other.spec);
@@ -300,26 +302,26 @@
 
         /**
          * Returns an instance just like this one but with the disposition
-         * set as given
-         * 
-         * @param disposition non-null; the new disposition
-         * @return non-null; an appropriately-constructed instance
+         * set as given.
+         *
+         * @param disposition {@code non-null;} the new disposition
+         * @return {@code non-null;} an appropriately-constructed instance
          */
         public Entry withDisposition(Disposition disposition) {
             if (disposition == this.disposition) {
                 return this;
             }
-            
+
             return new Entry(address, disposition, spec);
         }
     }
-    
+
     /**
      * Constructs an instance for the given method, based on the given
      * block order and intermediate local information.
-     * 
-     * @param insns non-null; instructions to convert
-     * @return non-null; the constructed list 
+     *
+     * @param insns {@code non-null;} instructions to convert
+     * @return {@code non-null;} the constructed list
      */
     public static LocalList make(DalvInsnList insns) {
         int sz = insns.size();
@@ -330,8 +332,8 @@
          * into separate per-variable starts, adding explicit ends
          * wherever a variable is replaced or moved, and collecting
          * these and all the other local variable "activity"
-         * together into an output list (without the other insns). 
-         * 
+         * together into an output list (without the other insns).
+         *
          * Note: As of this writing, this method won't be handed any
          * insn lists that contain local ends, but I (danfuzz) expect
          * that to change at some point, when we start feeding that
@@ -382,9 +384,9 @@
             }
             throw ex;
         }
-            
+
     }
-    
+
     /**
      * Helper for {@link #debugVerify} which does most of the work.
      */
@@ -411,7 +413,7 @@
                     throw new RuntimeException("redundant end at " +
                             Integer.toHexString(e.getAddress()));
                 }
-                
+
                 int addr = e.getAddress();
                 boolean foundStart = false;
 
@@ -433,7 +435,7 @@
                             throw new RuntimeException(
                                     "redundant end at " +
                                     Integer.toHexString(addr));
-                        }                            
+                        }
                     }
                 }
 
@@ -443,7 +445,7 @@
                             "improper end replacement claim at " +
                             Integer.toHexString(addr));
                 }
-                    
+
                 active[reg] = null;
             }
         }
@@ -453,31 +455,25 @@
      * Intermediate state when constructing a local list.
      */
     public static class MakeState {
-        /** non-null; result being collected */
+        /** {@code non-null;} result being collected */
         private final ArrayList<Entry> result;
 
         /**
-         * &gt;= 0; running count of nulled result entries, to help with
+         * {@code >= 0;} running count of nulled result entries, to help with
          * sizing the final list
          */
         private int nullResultCount;
 
-        /** null-ok; current register mappings */
+        /** {@code null-ok;} current register mappings */
         private RegisterSpecSet regs;
 
-        /** null-ok; result indices where local ends are stored */
+        /** {@code null-ok;} result indices where local ends are stored */
         private int[] endIndices;
 
-        /** &gt;= 0; last address seen */
+        /** {@code >= 0;} last address seen */
         private int lastAddress;
 
         /**
-         * &gt;= 0; result index where the first element for the most
-         * recent address is stored
-         */
-        private int startIndexForAddress;
-
-        /**
          * Constructs an instance.
          */
         public MakeState(int initialSize) {
@@ -486,19 +482,18 @@
             regs = null;
             endIndices = null;
             lastAddress = 0;
-            startIndexForAddress = 0;
         }
 
         /**
          * Checks the address and other vitals as a prerequisite to
          * further processing.
          *
-         * @param address &gt;= 0; address about to be processed
-         * @param reg &gt;= 0; register number about to be processed
+         * @param address {@code >= 0;} address about to be processed
+         * @param reg {@code >= 0;} register number about to be processed
          */
         private void aboutToProcess(int address, int reg) {
             boolean first = (endIndices == null);
-            
+
             if ((address == lastAddress) && !first) {
                 return;
             }
@@ -534,11 +529,15 @@
          * Sets the local state at the given address to the given snapshot.
          * The first call on this instance must be to this method, so that
          * the register state can be properly sized.
-         * 
-         * @param address &gt;= 0; the address
-         * @param specs non-null; spec set representing the locals
+         *
+         * @param address {@code >= 0;} the address
+         * @param specs {@code non-null;} spec set representing the locals
          */
         public void snapshot(int address, RegisterSpecSet specs) {
+            if (DEBUG) {
+                System.err.printf("%04x snapshot %s\n", address, specs);
+            }
+
             int sz = specs.getMaxSize();
             aboutToProcess(address, sz - 1);
 
@@ -557,15 +556,24 @@
                     startLocal(address, newSpec);
                 }
             }
+
+            if (DEBUG) {
+                System.err.printf("%04x snapshot done\n", address);
+            }
         }
-        
+
         /**
          * Starts a local at the given address.
-         * 
-         * @param address &gt;= 0; the address
-         * @param startedLocal non-null; spec representing the started local
+         *
+         * @param address {@code >= 0;} the address
+         * @param startedLocal {@code non-null;} spec representing the
+         * started local
          */
         public void startLocal(int address, RegisterSpec startedLocal) {
+            if (DEBUG) {
+                System.err.printf("%04x start %s\n", address, startedLocal);
+            }
+
             int regNum = startedLocal.getReg();
 
             startedLocal = filterSpec(startedLocal);
@@ -588,7 +596,7 @@
             }
 
             int endAt = endIndices[regNum];
-            
+
             if (existingLocal != null) {
                 /*
                  * There is an existing (but non-matching) local.
@@ -633,8 +641,8 @@
                     }
                 }
             }
-                                
-            /* 
+
+            /*
              * The code above didn't find and remove an unnecessary
              * local end, so we now have to add one or more entries to
              * the output to capture the transition.
@@ -672,17 +680,36 @@
              * if any (that is, if the local migrates from vX to vY,
              * we should note that as a local end in vX).
              */
-            
+
             add(address, Disposition.START, startedLocal);
         }
 
         /**
+         * Ends a local at the given address, using the disposition
+         * {@code END_SIMPLY}.
+         *
+         * @param address {@code >= 0;} the address
+         * @param endedLocal {@code non-null;} spec representing the
+         * local being ended
+         */
+        public void endLocal(int address, RegisterSpec endedLocal) {
+            endLocal(address, endedLocal, Disposition.END_SIMPLY);
+        }
+
+        /**
          * Ends a local at the given address.
          *
-         * @param address &gt;= 0; the address
-         * @param endedLocal non-null; spec representing the local being ended
+         * @param address {@code >= 0;} the address
+         * @param endedLocal {@code non-null;} spec representing the
+         * local being ended
+         * @param disposition reason for the end
          */
-        public void endLocal(int address, RegisterSpec endedLocal) {
+        public void endLocal(int address, RegisterSpec endedLocal,
+                Disposition disposition) {
+            if (DEBUG) {
+                System.err.printf("%04x end %s\n", address, endedLocal);
+            }
+
             int regNum = endedLocal.getReg();
 
             endedLocal = filterSpec(endedLocal);
@@ -703,7 +730,7 @@
                 return;
             }
 
-            add(address, Disposition.END_SIMPLY, endedLocal);
+            add(address, disposition, endedLocal);
         }
 
         /**
@@ -714,9 +741,10 @@
          * active), update the {@link #endIndices} to be accurate, and
          * if needed update the newly-active end to reflect an altered
          * disposition.
-         * 
-         * @param address &gt;= 0; the address
-         * @param endedLocal non-null; spec representing the local being ended
+         *
+         * @param address {@code >= 0;} the address
+         * @param endedLocal {@code non-null;} spec representing the
+         * local being ended
          * @return {@code true} iff this method found the case in question
          * and adjusted things accordingly
          */
@@ -747,7 +775,7 @@
              * In fact, we found that the endedLocal had started at the
              * same address, so do all the requisite cleanup.
              */
-            
+
             regs.remove(endedLocal);
             result.set(at, null);
             nullResultCount++;
@@ -773,7 +801,7 @@
             if (found) {
                 // We found an end for the same register.
                 endIndices[regNum] = at;
-                   
+
                 if (entry.getAddress() == address) {
                     /*
                      * It's still the same address, so update the
@@ -793,13 +821,13 @@
          * null" type into simply {@code Object}. This method needs to
          * be called for any spec that is on its way into a locals
          * list.
-         * 
+         *
          * <p>This isn't necessarily the cleanest way to achieve the
          * goal of not representing known nulls in a locals list, but
          * it gets the job done.</p>
-         * 
-         * @param orig null-ok; the original spec
-         * @return null-ok; an appropriately modified spec, or the
+         *
+         * @param orig {@code null-ok;} the original spec
+         * @return {@code null-ok;} an appropriately modified spec, or the
          * original if nothing needs to be done
          */
         private static RegisterSpec filterSpec(RegisterSpec orig) {
@@ -814,9 +842,9 @@
          * Adds an entry to the result, updating the adjunct tables
          * accordingly.
          *
-         * @param address &gt;= 0; the address
-         * @param disposition non-null; the disposition
-         * @param spec non-null; spec representing the local
+         * @param address {@code >= 0;} the address
+         * @param disposition {@code non-null;} the disposition
+         * @param spec {@code non-null;} spec representing the local
          */
         private void add(int address, Disposition disposition,
                 RegisterSpec spec) {
@@ -834,11 +862,13 @@
         }
 
         /**
-         * Adds or updates an end local (changing its disposition).
-         * 
-         * @param address &gt;= 0; the address
-         * @param disposition non-null; the disposition
-         * @param spec non-null; spec representing the local
+         * Adds or updates an end local (changing its disposition). If
+         * this would cause an empty range for a local, this instead
+         * removes the local entirely.
+         *
+         * @param address {@code >= 0;} the address
+         * @param disposition {@code non-null;} the disposition
+         * @param spec {@code non-null;} spec representing the local
          */
         private void addOrUpdateEnd(int address, Disposition disposition,
                 RegisterSpec spec) {
@@ -850,29 +880,34 @@
             int endAt = endIndices[regNum];
 
             if (endAt >= 0) {
+                // There is a previous end.
                 Entry endEntry = result.get(endAt);
                 if ((endEntry.getAddress() == address) &&
                         endEntry.getRegisterSpec().equals(spec)) {
+                    /*
+                     * The end is for the right address and variable, so
+                     * update it.
+                     */
                     result.set(endAt, endEntry.withDisposition(disposition));
-                    regs.remove(spec);
+                    regs.remove(spec); // TODO: Is this line superfluous?
                     return;
                 }
             }
-                
-            add(address, disposition, spec);
+
+            endLocal(address, spec, disposition);
         }
 
         /**
          * Finishes processing altogether and gets the result.
-         * 
-         * @return non-null; the result list
+         *
+         * @return {@code non-null;} the result list
          */
         public LocalList finish() {
             aboutToProcess(Integer.MAX_VALUE, 0);
 
             int resultSz = result.size();
             int finalSz = resultSz - nullResultCount;
-            
+
             if (finalSz == 0) {
                 return EMPTY;
             }
@@ -909,5 +944,5 @@
             resultList.setImmutable();
             return resultList;
         }
-    }    
+    }
 }
diff --git a/dx/src/com/android/dx/dex/code/LocalSnapshot.java b/dx/src/com/android/dx/dex/code/LocalSnapshot.java
index 19a9baa..409ad15 100644
--- a/dx/src/com/android/dx/dex/code/LocalSnapshot.java
+++ b/dx/src/com/android/dx/dex/code/LocalSnapshot.java
@@ -27,15 +27,15 @@
  * the instance in an instruction array.
  */
 public final class LocalSnapshot extends ZeroSizeInsn {
-    /** non-null; local state associated with this instance */
+    /** {@code non-null;} local state associated with this instance */
     private final RegisterSpecSet locals;
 
     /**
      * Constructs an instance. The output address of this instance is initially
-     * unknown (<code>-1</code>).
+     * unknown ({@code -1}).
      * 
-     * @param position non-null; source position
-     * @param locals non-null; associated local variable state
+     * @param position {@code non-null;} source position
+     * @param locals {@code non-null;} associated local variable state
      */
     public LocalSnapshot(SourcePosition position, RegisterSpecSet locals) {
         super(position);
@@ -62,7 +62,7 @@
     /**
      * Gets the local state associated with this instance.
      * 
-     * @return non-null; the state
+     * @return {@code non-null;} the state
      */
     public RegisterSpecSet getLocals() {
         return locals;
diff --git a/dx/src/com/android/dx/dex/code/LocalStart.java b/dx/src/com/android/dx/dex/code/LocalStart.java
index 22e20f8..ec70e30 100644
--- a/dx/src/com/android/dx/dex/code/LocalStart.java
+++ b/dx/src/com/android/dx/dex/code/LocalStart.java
@@ -28,7 +28,7 @@
  */
 public final class LocalStart extends ZeroSizeInsn {
     /**
-     * non-null; register spec representing the local variable introduced
+     * {@code non-null;} register spec representing the local variable introduced
      * by this instance 
      */
     private final RegisterSpec local;
@@ -36,8 +36,8 @@
     /**
      * Returns the local variable listing string for a single register spec.
      * 
-     * @param spec non-null; the spec to convert
-     * @return non-null; the string form
+     * @param spec {@code non-null;} the spec to convert
+     * @return {@code non-null;} the string form
      */
     public static String localString(RegisterSpec spec) {
         return spec.regString() + ' ' + spec.getLocalItem().toString() + ": " +
@@ -46,10 +46,10 @@
 
     /**
      * Constructs an instance. The output address of this instance is initially
-     * unknown (<code>-1</code>).
+     * unknown ({@code -1}).
      * 
-     * @param position non-null; source position
-     * @param local non-null; register spec representing the local
+     * @param position {@code non-null;} source position
+     * @param local {@code non-null;} register spec representing the local
      * variable introduced by this instance
      */
     public LocalStart(SourcePosition position, RegisterSpec local) {
@@ -78,7 +78,7 @@
      * Gets the register spec representing the local variable introduced
      * by this instance.
      * 
-     * @return non-null; the register spec
+     * @return {@code non-null;} the register spec
      */
     public RegisterSpec getLocal() {
         return local;
diff --git a/dx/src/com/android/dx/dex/code/OddSpacer.java b/dx/src/com/android/dx/dex/code/OddSpacer.java
index f99df36..727def0 100644
--- a/dx/src/com/android/dx/dex/code/OddSpacer.java
+++ b/dx/src/com/android/dx/dex/code/OddSpacer.java
@@ -21,7 +21,7 @@
 import com.android.dx.util.AnnotatedOutput;
 
 /**
- * Pseudo-instruction which either turns into a <code>nop</code> or
+ * Pseudo-instruction which either turns into a {@code nop} or
  * nothingness, in order to make the subsequent instruction have an
  * even address. This is used to align (subsequent) instructions that
  * require it.
@@ -29,9 +29,9 @@
 public final class OddSpacer extends VariableSizeInsn {
     /**
      * Constructs an instance. The output address of this instance is initially
-     * unknown (<code>-1</code>).
+     * unknown ({@code -1}).
      * 
-     * @param position non-null; source position
+     * @param position {@code non-null;} source position
      */
     public OddSpacer(SourcePosition position) {
         super(position, RegisterSpecList.EMPTY);
diff --git a/dx/src/com/android/dx/dex/code/OutputCollector.java b/dx/src/com/android/dx/dex/code/OutputCollector.java
index 98d8a9c..2643373 100644
--- a/dx/src/com/android/dx/dex/code/OutputCollector.java
+++ b/dx/src/com/android/dx/dex/code/OutputCollector.java
@@ -28,13 +28,13 @@
  */
 public final class OutputCollector {
     /**
-     * non-null; the associated finisher (which holds the instruction
+     * {@code non-null;} the associated finisher (which holds the instruction
      * list in-progress)
      */
     private final OutputFinisher finisher;
 
     /**
-     * null-ok; suffix for the output, or <code>null</code> if the suffix
+     * {@code null-ok;} suffix for the output, or {@code null} if the suffix
      * has been appended to the main output (by {@link #appendSuffixToOutput})
      */
     private ArrayList<DalvInsn> suffix;
@@ -42,10 +42,10 @@
     /**
      * Constructs an instance.
      * 
-     * @param initialCapacity &gt;= 0; initial capacity of the output list
-     * @param suffixInitialCapacity &gt;= 0; initial capacity of the output
+     * @param initialCapacity {@code >= 0;} initial capacity of the output list
+     * @param suffixInitialCapacity {@code >= 0;} initial capacity of the output
      * suffix
-     * @param regCount &gt;= 0; register count for the method
+     * @param regCount {@code >= 0;} register count for the method
      */
     public OutputCollector(int initialCapacity, int suffixInitialCapacity,
             int regCount) {
@@ -56,7 +56,7 @@
     /**
      * Adds an instruction to the output.
      * 
-     * @param insn non-null; the instruction to add 
+     * @param insn {@code non-null;} the instruction to add 
      */
     public void add(DalvInsn insn) {
         finisher.add(insn);
@@ -68,9 +68,9 @@
      * indicated instruction really is a reversible branch.
      * 
      * @param which how many instructions back to find the branch;
-     * <code>0</code> is the most recently added instruction,
-     * <code>1</code> is the instruction before that, etc.
-     * @param newTarget non-null; the new target for the reversed branch
+     * {@code 0} is the most recently added instruction,
+     * {@code 1} is the instruction before that, etc.
+     * @param newTarget {@code non-null;} the new target for the reversed branch
      */
     public void reverseBranch(int which, CodeAddress newTarget) {
         finisher.reverseBranch(which, newTarget);
@@ -79,7 +79,7 @@
     /**
      * Adds an instruction to the output suffix.
      * 
-     * @param insn non-null; the instruction to add 
+     * @param insn {@code non-null;} the instruction to add 
      */
     public void addSuffix(DalvInsn insn) {
         suffix.add(insn);
@@ -89,7 +89,7 @@
      * Gets the results of all the calls on this instance, in the form of
      * an {@link OutputFinisher}.
      *
-     * @return non-null; the output finisher
+     * @return {@code non-null;} the output finisher
      * @throws UnsupportedOperationException if this method has
      * already been called
      */
diff --git a/dx/src/com/android/dx/dex/code/OutputFinisher.java b/dx/src/com/android/dx/dex/code/OutputFinisher.java
index 73eecf8..5b1d533 100644
--- a/dx/src/com/android/dx/dex/code/OutputFinisher.java
+++ b/dx/src/com/android/dx/dex/code/OutputFinisher.java
@@ -37,12 +37,12 @@
  */
 public final class OutputFinisher {
     /**
-     * &gt;= 0; register count for the method, not including any extra
+     * {@code >= 0;} register count for the method, not including any extra
      * "reserved" registers needed to translate "difficult" instructions
      */
     private final int unreservedRegCount;
 
-    /** non-null; the list of instructions, per se */
+    /** {@code non-null;} the list of instructions, per se */
     private ArrayList<DalvInsn> insns;
 
     /** whether any instruction has position info */
@@ -52,7 +52,7 @@
     private boolean hasAnyLocalInfo;
 
     /**
-     * &gt;= 0; the count of reserved registers (low-numbered
+     * {@code >= 0;} the count of reserved registers (low-numbered
      * registers used when expanding instructions that can't be
      * represented simply); becomes valid after a call to {@link
      * #massageInstructions}
@@ -62,8 +62,8 @@
     /**
      * Constructs an instance. It initially contains no instructions.
      * 
-     * @param regCount &gt;= 0; register count for the method
-     * @param initialCapacity &gt;= 0; initial capacity of the instructions
+     * @param regCount {@code >= 0;} register count for the method
+     * @param initialCapacity {@code >= 0;} initial capacity of the instructions
      * list
      */
     public OutputFinisher(int initialCapacity, int regCount) {
@@ -98,8 +98,8 @@
      * Helper for {@link #add} which scrutinizes a single
      * instruction for local variable information.
      * 
-     * @param insn non-null; instruction to scrutinize
-     * @return <code>true</code> iff the instruction refers to any
+     * @param insn {@code non-null;} instruction to scrutinize
+     * @return {@code true} iff the instruction refers to any
      * named locals
      */
     private static boolean hasLocalInfo(DalvInsn insn) {
@@ -125,8 +125,8 @@
      * Helper for {@link #hasAnyLocalInfo} which scrutinizes a single
      * register spec.
      * 
-     * @param spec non-null; spec to scrutinize
-     * @return <code>true</code> iff the spec refers to any
+     * @param spec {@code non-null;} spec to scrutinize
+     * @return {@code true} iff the spec refers to any
      * named locals
      */
     private static boolean hasLocalInfo(RegisterSpec spec) {
@@ -138,7 +138,7 @@
      * Returns the set of all constants referred to by instructions added
      * to this instance.
      * 
-     * @return non-null; the set of constants
+     * @return {@code non-null;} the set of constants
      */
     public HashSet<Constant> getAllConstants() {
         HashSet<Constant> result = new HashSet<Constant>(20);
@@ -154,8 +154,8 @@
      * Helper for {@link #getAllConstants} which adds all the info for
      * a single instruction.
      * 
-     * @param result non-null; result set to add to
-     * @param insn non-null; instruction to scrutinize
+     * @param result {@code non-null;} result set to add to
+     * @param insn {@code non-null;} instruction to scrutinize
      */
     private static void addConstants(HashSet<Constant> result,
             DalvInsn insn) {
@@ -176,10 +176,10 @@
 
     /**
      * Helper for {@link #getAllConstants} which adds all the info for
-     * a single <code>RegisterSpec</code>.
+     * a single {@code RegisterSpec}.
      *
-     * @param result non-null; result set to add to
-     * @param spec null-ok; register spec to add
+     * @param result {@code non-null;} result set to add to
+     * @param spec {@code null-ok;} register spec to add
      */
     private static void addConstants(HashSet<Constant> result,
             RegisterSpec spec) {
@@ -208,7 +208,7 @@
     /**
      * Adds an instruction to the output.
      * 
-     * @param insn non-null; the instruction to add 
+     * @param insn {@code non-null;} the instruction to add 
      */
     public void add(DalvInsn insn) {
         insns.add(insn);
@@ -218,8 +218,8 @@
     /**
      * Inserts an instruction in the output at the given offset.
      * 
-     * @param at &gt;= 0; what index to insert at
-     * @param insn non-null; the instruction to insert
+     * @param at {@code >= 0;} what index to insert at
+     * @param insn {@code non-null;} the instruction to insert
      */
     public void insert(int at, DalvInsn insn) {
         insns.add(at, insn);
@@ -230,7 +230,7 @@
      * Helper for {@link #add} and {@link #insert},
      * which updates the position and local info flags.
      * 
-     * @param insn non-null; an instruction that was just introduced
+     * @param insn {@code non-null;} an instruction that was just introduced
      */
     private void updateInfo(DalvInsn insn) {
         if (! hasAnyPositionInfo) {
@@ -253,9 +253,9 @@
      * indicated instruction really is a reversible branch.
      * 
      * @param which how many instructions back to find the branch;
-     * <code>0</code> is the most recently added instruction,
-     * <code>1</code> is the instruction before that, etc.
-     * @param newTarget non-null; the new target for the reversed branch
+     * {@code 0} is the most recently added instruction,
+     * {@code 1} is the instruction before that, etc.
+     * @param newTarget {@code non-null;} the new target for the reversed branch
      */
     public void reverseBranch(int which, CodeAddress newTarget) {
         int size = insns.size();
@@ -284,7 +284,7 @@
      * given callback to perform lookups. This should be called before
      * calling {@link #finishProcessingAndGetList}.
      * 
-     * @param callback non-null; callback object
+     * @param callback {@code non-null;} callback object
      */
     public void assignIndices(DalvCode.AssignIndicesCallback callback) {
         for (DalvInsn insn : insns) {
@@ -298,8 +298,8 @@
      * Helper for {@link #assignIndices} which does assignment for one
      * instruction.
      * 
-     * @param insn non-null; the instruction
-     * @param callback non-null; the callback
+     * @param insn {@code non-null;} the instruction
+     * @param callback {@code non-null;} the callback
      */
     private static void assignIndices(CstInsn insn,
             DalvCode.AssignIndicesCallback callback) {
@@ -336,7 +336,7 @@
      * <p><b>Note:</b> This method may only be called once per instance
      * of this class.</p>
      *
-     * @return non-null; the output list
+     * @return {@code non-null;} the output list
      * @throws UnsupportedOperationException if this method has
      * already been called
      */
@@ -359,7 +359,7 @@
      * the format out of each instruction into a separate array, to be
      * further manipulated as things progress.
      * 
-     * @return non-null; the array of formats
+     * @return {@code non-null;} the array of formats
      */
     private InsnFormat[] makeFormatsArray() {
         int size = insns.size();
@@ -375,11 +375,11 @@
     /**
      * Helper for {@link #finishProcessingAndGetList}, which figures
      * out how many reserved registers are required and then reserving
-     * them. It also updates the given <code>formats</code> array so
+     * them. It also updates the given {@code formats} array so
      * as to avoid extra work when constructing the massaged
      * instruction list.
      * 
-     * @param formats non-null; array of per-instruction format selections
+     * @param formats {@code non-null;} array of per-instruction format selections
      */
     private void reserveRegisters(InsnFormat[] formats) {
         int oldReservedCount = (reservedCount < 0) ? 0 : reservedCount;
@@ -425,11 +425,11 @@
      * Helper for {@link #reserveRegisters}, which does one
      * pass over the instructions, calculating the number of
      * registers that need to be reserved. It also updates the
-     * <code>formats</code> list to help avoid extra work in future
+     * {@code formats} list to help avoid extra work in future
      * register reservation passes.
      * 
-     * @param formats non-null; array of per-instruction format selections
-     * @return &gt;= 0; the count of reserved registers
+     * @param formats {@code non-null;} array of per-instruction format selections
+     * @return {@code >= 0;} the count of reserved registers
      */
     private int calculateReservedCount(InsnFormat[] formats) {
         int size = insns.size();
@@ -470,16 +470,16 @@
 
     /**
      * Attempts to fit the given instruction into a format, returning
-     * either a format that the instruction fits into or <code>null</code>
+     * either a format that the instruction fits into or {@code null}
      * to indicate that the instruction will need to be expanded. This
      * fitting process starts with the given format as a first "best
      * guess" and then pessimizes from there if necessary.
      *
-     * @param insn non-null; the instruction in question
-     * @param format null-ok; the current guess as to the best instruction
-     * format to use; <code>null</code> means that no simple format fits
-     * @return null-ok; a possibly-different format, which is either a
-     * good fit or <code>null</code> to indicate that no simple format
+     * @param insn {@code non-null;} the instruction in question
+     * @param format {@code null-ok;} the current guess as to the best instruction
+     * format to use; {@code null} means that no simple format fits
+     * @return {@code null-ok;} a possibly-different format, which is either a
+     * good fit or {@code null} to indicate that no simple format
      * fits
      */
     private InsnFormat findFormatForInsn(DalvInsn insn, InsnFormat format) {
@@ -527,7 +527,7 @@
      * final addresses aren't known at the point that this method is
      * called.</p>
      * 
-     * @param formats non-null; array of per-instruction format selections
+     * @param formats {@code non-null;} array of per-instruction format selections
      */
     private void massageInstructions(InsnFormat[] formats) {
         if (reservedCount == 0) {
@@ -566,8 +566,8 @@
      * problems) is expanded into a series of instances that together
      * perform the proper function.
      * 
-     * @param formats non-null; array of per-instruction format selections
-     * @return non-null; the replacement list
+     * @param formats {@code non-null;} array of per-instruction format selections
+     * @return {@code non-null;} the replacement list
      */
     private ArrayList<DalvInsn> performExpansion(InsnFormat[] formats) {
         int size = insns.size();
@@ -651,9 +651,9 @@
      * Helper for {@link #assignAddressesAndFixBranches}, which checks
      * the branch target size requirement of each branch instruction
      * to make sure it fits. For instructions that don't fit, this
-     * rewrites them to use a <code>goto</code> of some sort. In the
+     * rewrites them to use a {@code goto} of some sort. In the
      * case of a conditional branch that doesn't fit, the sense of the
-     * test is reversed in order to branch around a <code>goto</code>
+     * test is reversed in order to branch around a {@code goto}
      * to the original target.
      * 
      * @return whether any branches had to be fixed
diff --git a/dx/src/com/android/dx/dex/code/PositionList.java b/dx/src/com/android/dx/dex/code/PositionList.java
index d8f76eb..41e3667 100644
--- a/dx/src/com/android/dx/dex/code/PositionList.java
+++ b/dx/src/com/android/dx/dex/code/PositionList.java
@@ -24,7 +24,7 @@
  * method to extract an instance out of a {@link DalvInsnList}.
  */
 public final class PositionList extends FixedSizeList {
-    /** non-null; empty instance */
+    /** {@code non-null;} empty instance */
     public static final PositionList EMPTY = new PositionList(0);
 
     /**
@@ -50,10 +50,10 @@
      * Extracts and returns the source position information out of an
      * instruction list.
      * 
-     * @param insns non-null; instructions to convert
+     * @param insns {@code non-null;} instructions to convert
      * @param howMuch how much information should be included; one of the
      * static constants defined by this class
-     * @return non-null; the positions list
+     * @return {@code non-null;} the positions list
      */
     public static PositionList make(DalvInsnList insns, int howMuch) {
         switch (howMuch) {
@@ -112,9 +112,9 @@
     }
 
     /**
-     * Constructs an instance. All indices initially contain <code>null</code>.
+     * Constructs an instance. All indices initially contain {@code null}.
      * 
-     * @param size &gt;= 0; the size of the list
+     * @param size {@code >= 0;} the size of the list
      */
     public PositionList(int size) {
         super(size);
@@ -123,10 +123,10 @@
     /**
      * Gets the element at the given index. It is an error to call
      * this with the index for an element which was never set; if you
-     * do that, this will throw <code>NullPointerException</code>.
+     * do that, this will throw {@code NullPointerException}.
      * 
-     * @param n &gt;= 0, &lt; size(); which index
-     * @return non-null; element at that index
+     * @param n {@code >= 0, < size();} which index
+     * @return {@code non-null;} element at that index
      */
     public Entry get(int n) {
         return (Entry) get0(n);
@@ -135,8 +135,8 @@
     /**
      * Sets the entry at the given index.
      * 
-     * @param n &gt;= 0, &lt; size(); which index
-     * @param entry non-null; the entry to set at <code>n</code>
+     * @param n {@code >= 0, < size();} which index
+     * @param entry {@code non-null;} the entry to set at {@code n}
      */
     public void set(int n, Entry entry) {
         set0(n, entry);
@@ -146,17 +146,17 @@
      * Entry in a position list.
      */
     public static class Entry {
-        /** &gt;= 0; address of this entry */
+        /** {@code >= 0;} address of this entry */
         private final int address;
 
-        /** non-null; corresponding source position information */
+        /** {@code non-null;} corresponding source position information */
         private final SourcePosition position;
 
         /**
          * Constructs an instance.
          * 
-         * @param address &gt;= 0; address of this entry
-         * @param position non-null; corresponding source position information
+         * @param address {@code >= 0;} address of this entry
+         * @param position {@code non-null;} corresponding source position information
          */
         public Entry (int address, SourcePosition position) {
             if (address < 0) {
@@ -174,7 +174,7 @@
         /**
          * Gets the address.
          * 
-         * @return &gt;= 0; the address
+         * @return {@code >= 0;} the address
          */
         public int getAddress() {
             return address;
@@ -183,7 +183,7 @@
         /**
          * Gets the source position information.
          * 
-         * @return non-null; the position information
+         * @return {@code non-null;} the position information
          */
         public SourcePosition getPosition() {
             return position;
diff --git a/dx/src/com/android/dx/dex/code/RopToDop.java b/dx/src/com/android/dx/dex/code/RopToDop.java
index 8ad0e64..0385467 100644
--- a/dx/src/com/android/dx/dex/code/RopToDop.java
+++ b/dx/src/com/android/dx/dex/code/RopToDop.java
@@ -35,7 +35,7 @@
  * {@link Dop} instances.
  */
 public final class RopToDop {
-    /** non-null; map from all the common rops to dalvik opcodes */
+    /** {@code non-null;} map from all the common rops to dalvik opcodes */
     private static final HashMap<Rop, Dop> MAP;
 
     /**
@@ -278,7 +278,7 @@
      * Returns the dalvik opcode appropriate for the given register-based
      * instruction.
      * 
-     * @param insn non-null; the original instruction
+     * @param insn {@code non-null;} the original instruction
      * @return the corresponding dalvik opcode; one of the constants in
      * {@link Dops}
      */
diff --git a/dx/src/com/android/dx/dex/code/RopTranslator.java b/dx/src/com/android/dx/dex/code/RopTranslator.java
index f3dfe0b..9f47b13 100644
--- a/dx/src/com/android/dx/dex/code/RopTranslator.java
+++ b/dx/src/com/android/dx/dex/code/RopTranslator.java
@@ -46,7 +46,7 @@
  * #translate} method is the thing to call on this class.
  */
 public final class RopTranslator {
-    /** non-null; method to translate */
+    /** {@code non-null;} method to translate */
     private final RopMethod method;
 
     /**
@@ -55,22 +55,22 @@
      */
     private final int positionInfo;
 
-    /** null-ok; local variable info to use */
+    /** {@code null-ok;} local variable info to use */
     private final LocalVariableInfo locals;
 
-    /** non-null; container for all the address objects for the method */
+    /** {@code non-null;} container for all the address objects for the method */
     private final BlockAddresses addresses;
 
-    /** non-null; list of output instructions in-progress */
+    /** {@code non-null;} list of output instructions in-progress */
     private final OutputCollector output;
 
-    /** non-null; visitor to use during translation */
+    /** {@code non-null;} visitor to use during translation */
     private final TranslationVisitor translationVisitor;
 
-    /** &gt;= 0; register count for the method */
+    /** {@code >= 0;} register count for the method */
     private final int regCount;
 
-    /** null-ok; block output order; becomes non-null in {@link #pickOrder} */
+    /** {@code null-ok;} block output order; becomes non-null in {@link #pickOrder} */
     private int[] order;
 
     /** size, in register units, of all the parameters to this method */
@@ -86,13 +86,13 @@
      * Translates a {@link RopMethod}. This may modify the given
      * input.
      * 
-     * @param method non-null; the original method
+     * @param method {@code non-null;} the original method
      * @param positionInfo how much position info to preserve; one of the
      * static constants in {@link PositionList}
-     * @param locals null-ok; local variable information to use
+     * @param locals {@code null-ok;} local variable information to use
      * @param paramSize size, in register units, of all the parameters to
      * this method
-     * @return non-null; the translated version
+     * @return {@code non-null;} the translated version
      */
     public static DalvCode translate(RopMethod method, int positionInfo,
                                      LocalVariableInfo locals, int paramSize) {
@@ -105,10 +105,10 @@
     /**
      * Constructs an instance. This method is private. Use {@link #translate}.
      * 
-     * @param method non-null; the original method
+     * @param method {@code non-null;} the original method
      * @param positionInfo how much position info to preserve; one of the
      * static constants in {@link PositionList}
-     * @param locals null-ok; local variable information to use
+     * @param locals {@code null-ok;} local variable information to use
      * @param paramSize size, in register units, of all the parameters to
      * this method
      */
@@ -177,7 +177,7 @@
 
         /*
          * We almost could just check the first block here, but the
-         * <code>cf</code> layer will put in a second move-param in a
+         * {@code cf} layer will put in a second move-param in a
          * subsequent block in the case of synchronized methods.
          */
         method.getBlocks().forEachInsn(new Insn.BaseVisitor() {
@@ -199,7 +199,7 @@
     /**
      * Does the translation and returns the result.
      * 
-     * @return non-null; the result
+     * @return {@code non-null;} the result
      */
     private DalvCode translateAndGetResult() {
         pickOrder();
@@ -232,9 +232,9 @@
      * Helper for {@link #outputInstructions}, which does the processing
      * and output of one block.
      * 
-     * @param block non-null; the block to process and output
-     * @param nextLabel &gt;= -1; the next block that will be processed, or
-     * <code>-1</code> if there is no next block
+     * @param block {@code non-null;} the block to process and output
+     * @param nextLabel {@code >= -1;} the next block that will be processed, or
+     * {@code -1} if there is no next block
      */
     private void outputBlock(BasicBlock block, int nextLabel) {
         // Append the code address for this block.
@@ -440,8 +440,8 @@
      * two register sources, and have a source equal to the result,
      * place that source first.
      *
-     * @param insn non-null; instruction in question
-     * @return non-null; the instruction's complete register list
+     * @param insn {@code non-null;} instruction in question
+     * @return {@code non-null;} the instruction's complete register list
      */
     private static RegisterSpecList getRegs(Insn insn) {
         return getRegs(insn, insn.getResult());
@@ -453,9 +453,9 @@
      * two register sources, and have a source equal to the result,
      * place that source first.
      *
-     * @param insn non-null; instruction in question
-     * @param resultReg null-ok; the real result to use (ignore the insn's)
-     * @return non-null; the instruction's complete register list
+     * @param insn {@code non-null;} instruction in question
+     * @param resultReg {@code null-ok;} the real result to use (ignore the insn's)
+     * @return {@code non-null;} the instruction's complete register list
      */
     private static RegisterSpecList getRegs(Insn insn,
             RegisterSpec resultReg) {
@@ -486,14 +486,14 @@
      * Instruction visitor class for doing the instruction translation per se.
      */
     private class TranslationVisitor implements Insn.Visitor {
-        /** non-null; list of output instructions in-progress */
+        /** {@code non-null;} list of output instructions in-progress */
         private final OutputCollector output;
 
-        /** non-null; basic block being worked on */
+        /** {@code non-null;} basic block being worked on */
         private BasicBlock block;
 
         /**
-         * null-ok; code address for the salient last instruction of the
+         * {@code null-ok;} code address for the salient last instruction of the
          * block (used before switches and throwing instructions) 
          */
         private CodeAddress lastAddress;
@@ -501,7 +501,7 @@
         /**
          * Constructs an instance.
          * 
-         * @param output non-null; destination for instruction output
+         * @param output {@code non-null;} destination for instruction output
          */
         public TranslationVisitor(OutputCollector output) {
             this.output = output;
@@ -510,8 +510,8 @@
         /**
          * Sets the block currently being worked on.
          * 
-         * @param block non-null; the block
-         * @param lastAddress non-null; code address for the salient
+         * @param block {@code non-null;} the block
+         * @param lastAddress {@code non-null;} code address for the salient
          * last instruction of the block
          */
         public void setBlock(BasicBlock block, CodeAddress lastAddress) {
@@ -654,7 +654,7 @@
          * the RegisterSpec of the result of the move-result-pseudo at the
          * top of that block or null if none.
          *
-         * @return null-ok; result of move-result-pseudo at the beginning of
+         * @return {@code null-ok;} result of move-result-pseudo at the beginning of
          * primary successor
          */
         private RegisterSpec getNextMoveResultPseudo()
@@ -783,7 +783,7 @@
         /**
          * Adds to the output.
          * 
-         * @param insn non-null; instruction to add
+         * @param insn {@code non-null;} instruction to add
          */
         protected void addOutput(DalvInsn insn) {
             output.add(insn);
@@ -792,7 +792,7 @@
         /**
          * Adds to the output suffix.
          * 
-         * @param insn non-null; instruction to add
+         * @param insn {@code non-null;} instruction to add
          */
         protected void addOutputSuffix(DalvInsn insn) {
             output.addSuffix(insn);
@@ -805,14 +805,14 @@
      */
     private class LocalVariableAwareTranslationVisitor
             extends TranslationVisitor {
-        /** non-null; local variable info */
+        /** {@code non-null;} local variable info */
         private LocalVariableInfo locals;
 
         /**
          * Constructs an instance.
          * 
-         * @param output non-null; destination for instruction output
-         * @param locals non-null; the local variable info
+         * @param output {@code non-null;} destination for instruction output
+         * @param locals {@code non-null;} the local variable info
          */
         public LocalVariableAwareTranslationVisitor(OutputCollector output,
                                                     LocalVariableInfo locals) {
@@ -859,7 +859,7 @@
          * Adds a {@link LocalStart} to the output if the given
          * instruction in fact introduces a local variable.
          * 
-         * @param insn non-null; instruction in question
+         * @param insn {@code non-null;} instruction in question
          */
         public void addIntroductionIfNecessary(Insn insn) {
             RegisterSpec spec = locals.getAssignment(insn);
diff --git a/dx/src/com/android/dx/dex/code/SimpleInsn.java b/dx/src/com/android/dx/dex/code/SimpleInsn.java
index ba20409..5e7b259 100644
--- a/dx/src/com/android/dx/dex/code/SimpleInsn.java
+++ b/dx/src/com/android/dx/dex/code/SimpleInsn.java
@@ -26,11 +26,11 @@
 public final class SimpleInsn extends FixedSizeInsn {
     /**
      * Constructs an instance. The output address of this instance is initially
-     * unknown (<code>-1</code>).
+     * unknown ({@code -1}).
      * 
      * @param opcode the opcode; one of the constants from {@link Dops}
-     * @param position non-null; source position
-     * @param registers non-null; register list, including a
+     * @param position {@code non-null;} source position
+     * @param registers {@code non-null;} register list, including a
      * result register if appropriate (that is, registers may be either
      * ins or outs)
      */
diff --git a/dx/src/com/android/dx/dex/code/StdCatchBuilder.java b/dx/src/com/android/dx/dex/code/StdCatchBuilder.java
index 1240f3f..6e3a169 100644
--- a/dx/src/com/android/dx/dex/code/StdCatchBuilder.java
+++ b/dx/src/com/android/dx/dex/code/StdCatchBuilder.java
@@ -35,22 +35,22 @@
     /** the maximum range of a single catch handler, in code units */
     private static final int MAX_CATCH_RANGE = 65535;
     
-    /** non-null; method to build the list for */
+    /** {@code non-null;} method to build the list for */
     private final RopMethod method;
 
-    /** non-null; block output order */
+    /** {@code non-null;} block output order */
     private final int[] order;
 
-    /** non-null; address objects for each block */
+    /** {@code non-null;} address objects for each block */
     private final BlockAddresses addresses;
     
     /**
      * Constructs an instance. It merely holds onto its parameters for
      * a subsequent call to {@link #build}.
      * 
-     * @param method non-null; method to build the list for
-     * @param order non-null; block output order
-     * @param addresses non-null; address objects for each block
+     * @param method {@code non-null;} method to build the list for
+     * @param order {@code non-null;} block output order
+     * @param addresses {@code non-null;} address objects for each block
      */
     public StdCatchBuilder(RopMethod method, int[] order,
             BlockAddresses addresses) {
@@ -78,7 +78,6 @@
 
     /** {@inheritDoc} */
     public boolean hasAnyCatches() {
-        HashSet<Type> result = new HashSet<Type>(20);
         BasicBlockList blocks = method.getBlocks();
         int size = blocks.size();
         
@@ -115,10 +114,10 @@
     /**
      * Builds and returns the catch table for a given method.
      * 
-     * @param method non-null; method to build the list for
-     * @param order non-null; block output order
-     * @param addresses non-null; address objects for each block
-     * @return non-null; the constructed table
+     * @param method {@code non-null;} method to build the list for
+     * @param order {@code non-null;} block output order
+     * @param addresses {@code non-null;} address objects for each block
+     * @return {@code non-null;} the constructed table
      */
     public static CatchTable build(RopMethod method, int[] order,
             BlockAddresses addresses) {
@@ -210,9 +209,9 @@
     /**
      * Makes the {@link CatchHandlerList} for the given basic block.
      * 
-     * @param block non-null; block to get entries for
-     * @param addresses non-null; address objects for each block
-     * @return non-null; array of entries
+     * @param block {@code non-null;} block to get entries for
+     * @param addresses {@code non-null;} address objects for each block
+     * @return {@code non-null;} array of entries
      */
     private static CatchHandlerList handlersFor(BasicBlock block,
             BlockAddresses addresses) {
@@ -267,10 +266,10 @@
      * Makes a {@link CatchTable#Entry} for the given block range and
      * handlers.
      *
-     * @param start non-null; the start block for the range (inclusive)
-     * @param end non-null; the start block for the range (also inclusive)
-     * @param handlers non-null; the handlers for the range
-     * @param addresses non-null; address objects for each block
+     * @param start {@code non-null;} the start block for the range (inclusive)
+     * @param end {@code non-null;} the start block for the range (also inclusive)
+     * @param handlers {@code non-null;} the handlers for the range
+     * @param addresses {@code non-null;} address objects for each block
      */
     private static CatchTable.Entry makeEntry(BasicBlock start,
             BasicBlock end, CatchHandlerList handlers,
@@ -293,10 +292,10 @@
      * for a catch handler. This is true as long as the covered range is
      * under 65536 code units.
      * 
-     * @param start non-null; the start block for the range (inclusive)
-     * @param end non-null; the start block for the range (also inclusive)
-     * @param addresses non-null; address objects for each block
-     * @return <code>true</code> if the range is valid as a catch range
+     * @param start {@code non-null;} the start block for the range (inclusive)
+     * @param end {@code non-null;} the start block for the range (also inclusive)
+     * @param addresses {@code non-null;} address objects for each block
+     * @return {@code true} if the range is valid as a catch range
      */
     private static boolean rangeIsValid(BasicBlock start, BasicBlock end,
             BlockAddresses addresses) {
diff --git a/dx/src/com/android/dx/dex/code/SwitchData.java b/dx/src/com/android/dx/dex/code/SwitchData.java
index 1aaafa9..e5a8da4 100644
--- a/dx/src/com/android/dx/dex/code/SwitchData.java
+++ b/dx/src/com/android/dx/dex/code/SwitchData.java
@@ -29,16 +29,16 @@
  */
 public final class SwitchData extends VariableSizeInsn {
     /**
-     * non-null; address representing the instruction that uses this
+     * {@code non-null;} address representing the instruction that uses this
      * instance 
      */
     private final CodeAddress user;
 
-    /** non-null; sorted list of switch cases (keys) */
+    /** {@code non-null;} sorted list of switch cases (keys) */
     private final IntList cases;
 
     /**
-     * non-null; corresponding list of code addresses; the branch
+     * {@code non-null;} corresponding list of code addresses; the branch
      * target for each case 
      */
     private final CodeAddress[] targets;
@@ -48,13 +48,13 @@
 
     /**
      * Constructs an instance. The output address of this instance is initially
-     * unknown (<code>-1</code>).
+     * unknown ({@code -1}).
      * 
-     * @param position non-null; source position
-     * @param user non-null; address representing the instruction that
+     * @param position {@code non-null;} source position
+     * @param user {@code non-null;} address representing the instruction that
      * uses this instance
-     * @param cases non-null; sorted list of switch cases (keys)
-     * @param targets non-null; corresponding list of code addresses; the
+     * @param cases {@code non-null;} sorted list of switch cases (keys)
+     * @param targets {@code non-null;} corresponding list of code addresses; the
      * branch target for each case
      */
     public SwitchData(SourcePosition position, CodeAddress user,
@@ -151,7 +151,7 @@
     /**
      * Returns whether or not this instance's data will be output as packed.
      * 
-     * @return <code>true</code> iff the data is to be packed
+     * @return {@code true} iff the data is to be packed
      */
     public boolean isPacked() {
         return packed;
@@ -202,8 +202,8 @@
      * Gets the size of a packed table for the given cases, in 16-bit code
      * units.
      * 
-     * @param cases non-null; sorted list of cases
-     * @return &gt;= -1; the packed table size or <code>-1</code> if the
+     * @param cases {@code non-null;} sorted list of cases
+     * @return {@code >= -1;} the packed table size or {@code -1} if the
      * cases couldn't possibly be represented as a packed table
      */
     private static long packedCodeSize(IntList cases) {
@@ -219,8 +219,8 @@
      * Gets the size of a sparse table for the given cases, in 16-bit code
      * units.
      * 
-     * @param cases non-null; sorted list of cases
-     * @return &gt; 0; the sparse table size
+     * @param cases {@code non-null;} sorted list of cases
+     * @return {@code > 0;} the sparse table size
      */
     private static long sparseCodeSize(IntList cases) {
         int sz = cases.size();
@@ -231,8 +231,8 @@
     /**
      * Determines whether the given list of cases warrant being packed.
      * 
-     * @param cases non-null; sorted list of cases
-     * @return <code>true</code> iff the table encoding the cases
+     * @param cases {@code non-null;} sorted list of cases
+     * @return {@code true} iff the table encoding the cases
      * should be packed
      */
     private static boolean shouldPack(IntList cases) {
diff --git a/dx/src/com/android/dx/dex/code/TargetInsn.java b/dx/src/com/android/dx/dex/code/TargetInsn.java
index 5620795..0faaada 100644
--- a/dx/src/com/android/dx/dex/code/TargetInsn.java
+++ b/dx/src/com/android/dx/dex/code/TargetInsn.java
@@ -23,20 +23,20 @@
  * Instruction which has a single branch target.
  */
 public final class TargetInsn extends FixedSizeInsn {
-    /** non-null; the branch target */
+    /** {@code non-null;} the branch target */
     private CodeAddress target;
 
     /**
      * Constructs an instance. The output address of this instance is initially
-     * unknown (<code>-1</code>), and the target is initially
-     * <code>null</code>.
+     * unknown ({@code -1}), and the target is initially
+     * {@code null}.
      * 
      * @param opcode the opcode; one of the constants from {@link Dops}
-     * @param position non-null; source position
-     * @param registers non-null; register list, including a
+     * @param position {@code non-null;} source position
+     * @param registers {@code non-null;} register list, including a
      * result register if appropriate (that is, registers may be either
      * ins or outs)
-     * @param target non-null; the branch target
+     * @param target {@code non-null;} the branch target
      */
     public TargetInsn(Dop opcode, SourcePosition position,
                       RegisterSpecList registers, CodeAddress target) {
@@ -64,12 +64,12 @@
     /**
      * Returns an instance that is just like this one, except that its
      * opcode has the opposite sense (as a test; e.g. a
-     * <code>lt</code> test becomes a <code>ge</code>), and its branch
+     * {@code lt} test becomes a {@code ge}), and its branch
      * target is replaced by the one given, and all set-once values
      * associated with the class (such as its address) are reset.
      * 
-     * @param target non-null; the new branch target
-     * @return non-null; an appropriately-constructed instance
+     * @param target {@code non-null;} the new branch target
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public TargetInsn withNewTargetAndReversed(CodeAddress target) {
         Dop opcode = getOpcode().getOppositeTest();
@@ -80,7 +80,7 @@
     /**
      * Gets the unique branch target of this instruction.
      * 
-     * @return non-null; the branch target
+     * @return {@code non-null;} the branch target
      */
     public CodeAddress getTarget() {
         return target;
@@ -90,9 +90,9 @@
      * Gets the target address of this instruction. This is only valid
      * to call if the target instruction has been assigned an address,
      * and it is merely a convenient shorthand for
-     * <code>getTarget().getAddress()</code>.
+     * {@code getTarget().getAddress()}.
      * 
-     * @return &gt;= 0; the target address
+     * @return {@code >= 0;} the target address
      */
     public int getTargetAddress() {
         return target.getAddress();
@@ -102,7 +102,7 @@
      * Gets the branch offset of this instruction. This is only valid to
      * call if both this and the target instruction each has been assigned
      * an address, and it is merely a convenient shorthand for
-     * <code>getTargetAddress() - getAddress()</code>.
+     * {@code getTargetAddress() - getAddress()}.
      * 
      * @return the branch offset
      */
@@ -113,8 +113,8 @@
     /**
      * Returns whether the target offset is known.
      * 
-     * @return <code>true</code> if the target offset is known or
-     * <code>false</code> if not
+     * @return {@code true} if the target offset is known or
+     * {@code false} if not
      */
     public boolean hasTargetOffset() {
         return hasAddress() && target.hasAddress();
diff --git a/dx/src/com/android/dx/dex/code/VariableSizeInsn.java b/dx/src/com/android/dx/dex/code/VariableSizeInsn.java
index 7884249..889a50c 100644
--- a/dx/src/com/android/dx/dex/code/VariableSizeInsn.java
+++ b/dx/src/com/android/dx/dex/code/VariableSizeInsn.java
@@ -25,10 +25,10 @@
 public abstract class VariableSizeInsn extends DalvInsn {
     /**
      * Constructs an instance. The output address of this instance is initially
-     * unknown (<code>-1</code>).
+     * unknown ({@code -1}).
      * 
-     * @param position non-null; source position
-     * @param registers non-null; source registers
+     * @param position {@code non-null;} source position
+     * @param registers {@code non-null;} source registers
      */
     public VariableSizeInsn(SourcePosition position,
                             RegisterSpecList registers) {
diff --git a/dx/src/com/android/dx/dex/code/ZeroSizeInsn.java b/dx/src/com/android/dx/dex/code/ZeroSizeInsn.java
index 2ddb181..198bebf 100644
--- a/dx/src/com/android/dx/dex/code/ZeroSizeInsn.java
+++ b/dx/src/com/android/dx/dex/code/ZeroSizeInsn.java
@@ -28,9 +28,9 @@
 public abstract class ZeroSizeInsn extends DalvInsn {
     /**
      * Constructs an instance. The output address of this instance is initially
-     * unknown (<code>-1</code>).
+     * unknown ({@code -1}).
      * 
-     * @param position non-null; source position
+     * @param position {@code non-null;} source position
      */
     public ZeroSizeInsn(SourcePosition position) {
         super(Dops.SPECIAL_FORMAT, position, RegisterSpecList.EMPTY);
diff --git a/dx/src/com/android/dx/dex/code/form/Form10t.java b/dx/src/com/android/dx/dex/code/form/Form10t.java
index 8551012..82b731d 100644
--- a/dx/src/com/android/dx/dex/code/form/Form10t.java
+++ b/dx/src/com/android/dx/dex/code/form/Form10t.java
@@ -22,11 +22,11 @@
 import com.android.dx.util.AnnotatedOutput;
 
 /**
- * Instruction format <code>10t</code>. See the instruction format spec
+ * Instruction format {@code 10t}. See the instruction format spec
  * for details.
  */
 public final class Form10t extends InsnFormat {
-    /** non-null; unique instance of this class */
+    /** {@code non-null;} unique instance of this class */
     public static final InsnFormat THE_ONE = new Form10t();
 
     /**
diff --git a/dx/src/com/android/dx/dex/code/form/Form10x.java b/dx/src/com/android/dx/dex/code/form/Form10x.java
index 7dc7c43..c7a22a6 100644
--- a/dx/src/com/android/dx/dex/code/form/Form10x.java
+++ b/dx/src/com/android/dx/dex/code/form/Form10x.java
@@ -22,11 +22,11 @@
 import com.android.dx.util.AnnotatedOutput;
 
 /**
- * Instruction format <code>10x</code>. See the instruction format spec
+ * Instruction format {@code 10x}. See the instruction format spec
  * for details.
  */
 public final class Form10x extends InsnFormat {
-    /** non-null; unique instance of this class */
+    /** {@code non-null;} unique instance of this class */
     public static final InsnFormat THE_ONE = new Form10x();
 
     /**
diff --git a/dx/src/com/android/dx/dex/code/form/Form11n.java b/dx/src/com/android/dx/dex/code/form/Form11n.java
index b94038b..d63fc6f 100644
--- a/dx/src/com/android/dx/dex/code/form/Form11n.java
+++ b/dx/src/com/android/dx/dex/code/form/Form11n.java
@@ -25,11 +25,11 @@
 import com.android.dx.util.AnnotatedOutput;
 
 /**
- * Instruction format <code>11n</code>. See the instruction format spec
+ * Instruction format {@code 11n}. See the instruction format spec
  * for details.
  */
 public final class Form11n extends InsnFormat {
-    /** non-null; unique instance of this class */
+    /** {@code non-null;} unique instance of this class */
     public static final InsnFormat THE_ONE = new Form11n();
 
     /**
diff --git a/dx/src/com/android/dx/dex/code/form/Form11x.java b/dx/src/com/android/dx/dex/code/form/Form11x.java
index d656147..b4acc1a 100644
--- a/dx/src/com/android/dx/dex/code/form/Form11x.java
+++ b/dx/src/com/android/dx/dex/code/form/Form11x.java
@@ -23,11 +23,11 @@
 import com.android.dx.util.AnnotatedOutput;
 
 /**
- * Instruction format <code>11x</code>. See the instruction format spec
+ * Instruction format {@code 11x}. See the instruction format spec
  * for details.
  */
 public final class Form11x extends InsnFormat {
-    /** non-null; unique instance of this class */
+    /** {@code non-null;} unique instance of this class */
     public static final InsnFormat THE_ONE = new Form11x();
 
     /**
diff --git a/dx/src/com/android/dx/dex/code/form/Form12x.java b/dx/src/com/android/dx/dex/code/form/Form12x.java
index 3ed8ce9..c7754be 100644
--- a/dx/src/com/android/dx/dex/code/form/Form12x.java
+++ b/dx/src/com/android/dx/dex/code/form/Form12x.java
@@ -25,11 +25,11 @@
 import com.android.dx.util.AnnotatedOutput;
 
 /**
- * Instruction format <code>12x</code>. See the instruction format spec
+ * Instruction format {@code 12x}. See the instruction format spec
  * for details.
  */
 public final class Form12x extends InsnFormat {
-    /** non-null; unique instance of this class */
+    /** {@code non-null;} unique instance of this class */
     public static final InsnFormat THE_ONE = new Form12x();
 
     /**
diff --git a/dx/src/com/android/dx/dex/code/form/Form20t.java b/dx/src/com/android/dx/dex/code/form/Form20t.java
index 341bef3..0b5a3b2 100644
--- a/dx/src/com/android/dx/dex/code/form/Form20t.java
+++ b/dx/src/com/android/dx/dex/code/form/Form20t.java
@@ -22,11 +22,11 @@
 import com.android.dx.util.AnnotatedOutput;
 
 /**
- * Instruction format <code>20t</code>. See the instruction format spec
+ * Instruction format {@code 20t}. See the instruction format spec
  * for details.
  */
 public final class Form20t extends InsnFormat {
-    /** non-null; unique instance of this class */
+    /** {@code non-null;} unique instance of this class */
     public static final InsnFormat THE_ONE = new Form20t();
 
     /**
diff --git a/dx/src/com/android/dx/dex/code/form/Form21c.java b/dx/src/com/android/dx/dex/code/form/Form21c.java
index 5695e7a..ed1ec3c 100644
--- a/dx/src/com/android/dx/dex/code/form/Form21c.java
+++ b/dx/src/com/android/dx/dex/code/form/Form21c.java
@@ -28,11 +28,11 @@
 import com.android.dx.util.AnnotatedOutput;
 
 /**
- * Instruction format <code>21c</code>. See the instruction format spec
+ * Instruction format {@code 21c}. See the instruction format spec
  * for details.
  */
 public final class Form21c extends InsnFormat {
-    /** non-null; unique instance of this class */
+    /** {@code non-null;} unique instance of this class */
     public static final InsnFormat THE_ONE = new Form21c();
 
     /**
diff --git a/dx/src/com/android/dx/dex/code/form/Form21h.java b/dx/src/com/android/dx/dex/code/form/Form21h.java
index cf4b471..e0bd751 100644
--- a/dx/src/com/android/dx/dex/code/form/Form21h.java
+++ b/dx/src/com/android/dx/dex/code/form/Form21h.java
@@ -25,11 +25,11 @@
 import com.android.dx.util.AnnotatedOutput;
 
 /**
- * Instruction format <code>21h</code>. See the instruction format spec
+ * Instruction format {@code 21h}. See the instruction format spec
  * for details.
  */
 public final class Form21h extends InsnFormat {
-    /** non-null; unique instance of this class */
+    /** {@code non-null;} unique instance of this class */
     public static final InsnFormat THE_ONE = new Form21h();
 
     /**
diff --git a/dx/src/com/android/dx/dex/code/form/Form21s.java b/dx/src/com/android/dx/dex/code/form/Form21s.java
index df10f80..a03ee43 100644
--- a/dx/src/com/android/dx/dex/code/form/Form21s.java
+++ b/dx/src/com/android/dx/dex/code/form/Form21s.java
@@ -25,11 +25,11 @@
 import com.android.dx.util.AnnotatedOutput;
 
 /**
- * Instruction format <code>21s</code>. See the instruction format spec
+ * Instruction format {@code 21s}. See the instruction format spec
  * for details.
  */
 public final class Form21s extends InsnFormat {
-    /** non-null; unique instance of this class */
+    /** {@code non-null;} unique instance of this class */
     public static final InsnFormat THE_ONE = new Form21s();
 
     /**
diff --git a/dx/src/com/android/dx/dex/code/form/Form21t.java b/dx/src/com/android/dx/dex/code/form/Form21t.java
index 03f2ddf..f0ce644 100644
--- a/dx/src/com/android/dx/dex/code/form/Form21t.java
+++ b/dx/src/com/android/dx/dex/code/form/Form21t.java
@@ -23,11 +23,11 @@
 import com.android.dx.util.AnnotatedOutput;
 
 /**
- * Instruction format <code>21t</code>. See the instruction format spec
+ * Instruction format {@code 21t}. See the instruction format spec
  * for details.
  */
 public final class Form21t extends InsnFormat {
-    /** non-null; unique instance of this class */
+    /** {@code non-null;} unique instance of this class */
     public static final InsnFormat THE_ONE = new Form21t();
 
     /**
diff --git a/dx/src/com/android/dx/dex/code/form/Form22b.java b/dx/src/com/android/dx/dex/code/form/Form22b.java
index e2a777f..2884fbb 100644
--- a/dx/src/com/android/dx/dex/code/form/Form22b.java
+++ b/dx/src/com/android/dx/dex/code/form/Form22b.java
@@ -25,11 +25,11 @@
 import com.android.dx.util.AnnotatedOutput;
 
 /**
- * Instruction format <code>22b</code>. See the instruction format spec
+ * Instruction format {@code 22b}. See the instruction format spec
  * for details.
  */
 public final class Form22b extends InsnFormat {
-    /** non-null; unique instance of this class */
+    /** {@code non-null;} unique instance of this class */
     public static final InsnFormat THE_ONE = new Form22b();
 
     /**
diff --git a/dx/src/com/android/dx/dex/code/form/Form22c.java b/dx/src/com/android/dx/dex/code/form/Form22c.java
index 547eea8..e77677f 100644
--- a/dx/src/com/android/dx/dex/code/form/Form22c.java
+++ b/dx/src/com/android/dx/dex/code/form/Form22c.java
@@ -27,11 +27,11 @@
 import com.android.dx.util.AnnotatedOutput;
 
 /**
- * Instruction format <code>22c</code>. See the instruction format spec
+ * Instruction format {@code 22c}. See the instruction format spec
  * for details.
  */
 public final class Form22c extends InsnFormat {
-    /** non-null; unique instance of this class */
+    /** {@code non-null;} unique instance of this class */
     public static final InsnFormat THE_ONE = new Form22c();
 
     /**
diff --git a/dx/src/com/android/dx/dex/code/form/Form22s.java b/dx/src/com/android/dx/dex/code/form/Form22s.java
index 3ed173f..5964217 100644
--- a/dx/src/com/android/dx/dex/code/form/Form22s.java
+++ b/dx/src/com/android/dx/dex/code/form/Form22s.java
@@ -25,11 +25,11 @@
 import com.android.dx.util.AnnotatedOutput;
 
 /**
- * Instruction format <code>22s</code>. See the instruction format spec
+ * Instruction format {@code 22s}. See the instruction format spec
  * for details.
  */
 public final class Form22s extends InsnFormat {
-    /** non-null; unique instance of this class */
+    /** {@code non-null;} unique instance of this class */
     public static final InsnFormat THE_ONE = new Form22s();
 
     /**
diff --git a/dx/src/com/android/dx/dex/code/form/Form22t.java b/dx/src/com/android/dx/dex/code/form/Form22t.java
index 1034b92..1577803 100644
--- a/dx/src/com/android/dx/dex/code/form/Form22t.java
+++ b/dx/src/com/android/dx/dex/code/form/Form22t.java
@@ -23,11 +23,11 @@
 import com.android.dx.util.AnnotatedOutput;
 
 /**
- * Instruction format <code>22t</code>. See the instruction format spec
+ * Instruction format {@code 22t}. See the instruction format spec
  * for details.
  */
 public final class Form22t extends InsnFormat {
-    /** non-null; unique instance of this class */
+    /** {@code non-null;} unique instance of this class */
     public static final InsnFormat THE_ONE = new Form22t();
 
     /**
diff --git a/dx/src/com/android/dx/dex/code/form/Form22x.java b/dx/src/com/android/dx/dex/code/form/Form22x.java
index ee91e85..b7ce4e7 100644
--- a/dx/src/com/android/dx/dex/code/form/Form22x.java
+++ b/dx/src/com/android/dx/dex/code/form/Form22x.java
@@ -23,11 +23,11 @@
 import com.android.dx.util.AnnotatedOutput;
 
 /**
- * Instruction format <code>22x</code>. See the instruction format spec
+ * Instruction format {@code 22x}. See the instruction format spec
  * for details.
  */
 public final class Form22x extends InsnFormat {
-    /** non-null; unique instance of this class */
+    /** {@code non-null;} unique instance of this class */
     public static final InsnFormat THE_ONE = new Form22x();
 
     /**
diff --git a/dx/src/com/android/dx/dex/code/form/Form23x.java b/dx/src/com/android/dx/dex/code/form/Form23x.java
index c0a4482..64dd6b0 100644
--- a/dx/src/com/android/dx/dex/code/form/Form23x.java
+++ b/dx/src/com/android/dx/dex/code/form/Form23x.java
@@ -23,11 +23,11 @@
 import com.android.dx.util.AnnotatedOutput;
 
 /**
- * Instruction format <code>23x</code>. See the instruction format spec
+ * Instruction format {@code 23x}. See the instruction format spec
  * for details.
  */
 public final class Form23x extends InsnFormat {
-    /** non-null; unique instance of this class */
+    /** {@code non-null;} unique instance of this class */
     public static final InsnFormat THE_ONE = new Form23x();
 
     /**
diff --git a/dx/src/com/android/dx/dex/code/form/Form30t.java b/dx/src/com/android/dx/dex/code/form/Form30t.java
index 32e2efa..af0a699 100644
--- a/dx/src/com/android/dx/dex/code/form/Form30t.java
+++ b/dx/src/com/android/dx/dex/code/form/Form30t.java
@@ -22,11 +22,11 @@
 import com.android.dx.util.AnnotatedOutput;
 
 /**
- * Instruction format <code>30t</code>. See the instruction format spec
+ * Instruction format {@code 30t}. See the instruction format spec
  * for details.
  */
 public final class Form30t extends InsnFormat {
-    /** non-null; unique instance of this class */
+    /** {@code non-null;} unique instance of this class */
     public static final InsnFormat THE_ONE = new Form30t();
 
     /**
diff --git a/dx/src/com/android/dx/dex/code/form/Form31c.java b/dx/src/com/android/dx/dex/code/form/Form31c.java
index 5837009..0c983c5 100644
--- a/dx/src/com/android/dx/dex/code/form/Form31c.java
+++ b/dx/src/com/android/dx/dex/code/form/Form31c.java
@@ -28,11 +28,11 @@
 import com.android.dx.util.AnnotatedOutput;
 
 /**
- * Instruction format <code>31c</code>. See the instruction format spec
+ * Instruction format {@code 31c}. See the instruction format spec
  * for details.
  */
 public final class Form31c extends InsnFormat {
-    /** non-null; unique instance of this class */
+    /** {@code non-null;} unique instance of this class */
     public static final InsnFormat THE_ONE = new Form31c();
 
     /**
diff --git a/dx/src/com/android/dx/dex/code/form/Form31i.java b/dx/src/com/android/dx/dex/code/form/Form31i.java
index 2855bcb..c893a12 100644
--- a/dx/src/com/android/dx/dex/code/form/Form31i.java
+++ b/dx/src/com/android/dx/dex/code/form/Form31i.java
@@ -25,11 +25,11 @@
 import com.android.dx.util.AnnotatedOutput;
 
 /**
- * Instruction format <code>31i</code>. See the instruction format spec
+ * Instruction format {@code 31i}. See the instruction format spec
  * for details.
  */
 public final class Form31i extends InsnFormat {
-    /** non-null; unique instance of this class */
+    /** {@code non-null;} unique instance of this class */
     public static final InsnFormat THE_ONE = new Form31i();
 
     /**
diff --git a/dx/src/com/android/dx/dex/code/form/Form31t.java b/dx/src/com/android/dx/dex/code/form/Form31t.java
index 5472687..682408c 100644
--- a/dx/src/com/android/dx/dex/code/form/Form31t.java
+++ b/dx/src/com/android/dx/dex/code/form/Form31t.java
@@ -23,11 +23,11 @@
 import com.android.dx.util.AnnotatedOutput;
 
 /**
- * Instruction format <code>31t</code>. See the instruction format spec
+ * Instruction format {@code 31t}. See the instruction format spec
  * for details.
  */
 public final class Form31t extends InsnFormat {
-    /** non-null; unique instance of this class */
+    /** {@code non-null;} unique instance of this class */
     public static final InsnFormat THE_ONE = new Form31t();
 
     /**
diff --git a/dx/src/com/android/dx/dex/code/form/Form32x.java b/dx/src/com/android/dx/dex/code/form/Form32x.java
index 9c52d93..4a981ee 100644
--- a/dx/src/com/android/dx/dex/code/form/Form32x.java
+++ b/dx/src/com/android/dx/dex/code/form/Form32x.java
@@ -23,11 +23,11 @@
 import com.android.dx.util.AnnotatedOutput;
 
 /**
- * Instruction format <code>32x</code>. See the instruction format spec
+ * Instruction format {@code 32x}. See the instruction format spec
  * for details.
  */
 public final class Form32x extends InsnFormat {
-    /** non-null; unique instance of this class */
+    /** {@code non-null;} unique instance of this class */
     public static final InsnFormat THE_ONE = new Form32x();
 
     /**
diff --git a/dx/src/com/android/dx/dex/code/form/Form35c.java b/dx/src/com/android/dx/dex/code/form/Form35c.java
index 6be55fc..411e3c3 100644
--- a/dx/src/com/android/dx/dex/code/form/Form35c.java
+++ b/dx/src/com/android/dx/dex/code/form/Form35c.java
@@ -28,11 +28,11 @@
 import com.android.dx.util.AnnotatedOutput;
 
 /**
- * Instruction format <code>35c</code>. See the instruction format spec
+ * Instruction format {@code 35c}. See the instruction format spec
  * for details.
  */
 public final class Form35c extends InsnFormat {
-    /** non-null; unique instance of this class */
+    /** {@code non-null;} unique instance of this class */
     public static final InsnFormat THE_ONE = new Form35c();
 
     /** Maximal number of operands */
@@ -120,12 +120,12 @@
 
     /**
      * Gets the number of words required for the given register list, where
-     * category-2 values count as two words. Return <code>-1</code> if the
+     * category-2 values count as two words. Return {@code -1} if the
      * list requires more than five words or contains registers that need
      * more than a nibble to identify them.
      * 
-     * @param regs non-null; the register list in question
-     * @return &gt;= -1; the number of words required, or <code>-1</code> 
+     * @param regs {@code non-null;} the register list in question
+     * @return {@code >= -1;} the number of words required, or {@code -1} 
      * if the list couldn't possibly fit in this format
      */
     private static int wordCount(RegisterSpecList regs) {
@@ -161,8 +161,8 @@
      * entries. This returns the original list if no modification is
      * required
      * 
-     * @param orig non-null; the original list
-     * @return non-null; the list with the described transformation
+     * @param orig {@code non-null;} the original list
+     * @return {@code non-null;} the list with the described transformation
      */
     private static RegisterSpecList explicitize(RegisterSpecList orig) {
         int wordCount = wordCount(orig);
diff --git a/dx/src/com/android/dx/dex/code/form/Form3rc.java b/dx/src/com/android/dx/dex/code/form/Form3rc.java
index 0accbc2..2d185cf 100644
--- a/dx/src/com/android/dx/dex/code/form/Form3rc.java
+++ b/dx/src/com/android/dx/dex/code/form/Form3rc.java
@@ -27,11 +27,11 @@
 import com.android.dx.util.AnnotatedOutput;
 
 /**
- * Instruction format <code>3rc</code>. See the instruction format spec
+ * Instruction format {@code 3rc}. See the instruction format spec
  * for details.
  */
 public final class Form3rc extends InsnFormat {
-    /** non-null; unique instance of this class */
+    /** {@code non-null;} unique instance of this class */
     public static final InsnFormat THE_ONE = new Form3rc();
 
     /**
diff --git a/dx/src/com/android/dx/dex/code/form/Form51l.java b/dx/src/com/android/dx/dex/code/form/Form51l.java
index 09a32f6..9e3ab6a 100644
--- a/dx/src/com/android/dx/dex/code/form/Form51l.java
+++ b/dx/src/com/android/dx/dex/code/form/Form51l.java
@@ -26,11 +26,11 @@
 import com.android.dx.util.AnnotatedOutput;
 
 /**
- * Instruction format <code>51l</code>. See the instruction format spec
+ * Instruction format {@code 51l}. See the instruction format spec
  * for details.
  */
 public final class Form51l extends InsnFormat {
-    /** non-null; unique instance of this class */
+    /** {@code non-null;} unique instance of this class */
     public static final InsnFormat THE_ONE = new Form51l();
 
     /**
diff --git a/dx/src/com/android/dx/dex/code/form/SpecialFormat.java b/dx/src/com/android/dx/dex/code/form/SpecialFormat.java
index 79efd67..8a2e5ed 100644
--- a/dx/src/com/android/dx/dex/code/form/SpecialFormat.java
+++ b/dx/src/com/android/dx/dex/code/form/SpecialFormat.java
@@ -27,10 +27,10 @@
  * lists. Most of the overridden methods on this class end up throwing
  * exceptions, as code should know (implicitly or explicitly) to avoid
  * using this class. The one exception is {@link #isCompatible}, which
- * always returns <code>true</code>.
+ * always returns {@code true}.
  */
 public final class SpecialFormat extends InsnFormat {
-    /** non-null; unique instance of this class */
+    /** {@code non-null;} unique instance of this class */
     public static final InsnFormat THE_ONE = new SpecialFormat();
 
     /**
diff --git a/dx/src/com/android/dx/dex/file/AnnotationItem.java b/dx/src/com/android/dx/dex/file/AnnotationItem.java
index 43ac362..08422bc 100644
--- a/dx/src/com/android/dx/dex/file/AnnotationItem.java
+++ b/dx/src/com/android/dx/dex/file/AnnotationItem.java
@@ -46,20 +46,20 @@
     /** the required alignment for instances of this class */
     private static final int ALIGNMENT = 1;
 
-    /** non-null; unique instance of {@link #TypeIdSorter} */
+    /** {@code non-null;} unique instance of {@link #TypeIdSorter} */
     private static final TypeIdSorter TYPE_ID_SORTER = new TypeIdSorter();
     
-    /** non-null; the annotation to represent */
+    /** {@code non-null;} the annotation to represent */
     private final Annotation annotation;
 
     /**
-     * null-ok; type reference for the annotation type; set during
+     * {@code null-ok;} type reference for the annotation type; set during
      * {@link #addContents}
      */
     private TypeIdItem type;
 
     /**
-     * null-ok; encoded form, ready for writing to a file; set during
+     * {@code null-ok;} encoded form, ready for writing to a file; set during
      * {@link #place0}
      */
     private byte[] encodedForm;
@@ -88,7 +88,7 @@
      * ignoring all other aspects of the elements. This is only valid
      * to use after type id indices are known.
      * 
-     * @param array non-null; array to sort
+     * @param array {@code non-null;} array to sort
      */
     public static void sortByTypeIdIndex(AnnotationItem[] array) {
         Arrays.sort(array, TYPE_ID_SORTER);
@@ -97,7 +97,7 @@
     /**
      * Constructs an instance.
      * 
-     * @param annotation non-null; annotation to represent
+     * @param annotation {@code non-null;} annotation to represent
      */
     public AnnotationItem(Annotation annotation) {
         /*
@@ -167,8 +167,8 @@
      * output, that consumes no bytes of output. This is for annotating
      * a reference to this instance at the point of the reference.
      * 
-     * @param out non-null; where to output to
-     * @param prefix non-null; prefix for each line of output
+     * @param out {@code non-null;} where to output to
+     * @param prefix {@code non-null;} prefix for each line of output
      */
     public void annotateTo(AnnotatedOutput out, String prefix) {
         out.annotate(0, prefix + "visibility: " +
diff --git a/dx/src/com/android/dx/dex/file/AnnotationSetItem.java b/dx/src/com/android/dx/dex/file/AnnotationSetItem.java
index f03cc08..2ff005a 100644
--- a/dx/src/com/android/dx/dex/file/AnnotationSetItem.java
+++ b/dx/src/com/android/dx/dex/file/AnnotationSetItem.java
@@ -28,14 +28,14 @@
     /** the required alignment for instances of this class */
     private static final int ALIGNMENT = 4;
 
-    /** the size of an entry int the set: one <code>uint</code> */
+    /** the size of an entry int the set: one {@code uint} */
     private static final int ENTRY_WRITE_SIZE = 4;
 
-    /** non-null; the set of annotations */
+    /** {@code non-null;} the set of annotations */
     private final Annotations annotations;
     
     /**
-     * non-null; set of annotations as individual items in an array.
+     * {@code non-null;} set of annotations as individual items in an array.
      * <b>Note:</b> The contents have to get sorted by type id before
      * writing.
      */
@@ -44,7 +44,7 @@
     /**
      * Constructs an instance.
      * 
-     * @param annotations non-null; set of annotations
+     * @param annotations {@code non-null;} set of annotations
      */
     public AnnotationSetItem(Annotations annotations) {
         super(ALIGNMENT, writeSize(annotations));
@@ -62,8 +62,8 @@
     /**
      * Gets the write size for the given set.
      * 
-     * @param annotations non-null; the set
-     * @return &gt; 0; the write size
+     * @param annotations {@code non-null;} the set
+     * @return {@code > 0;} the write size
      */
     private static int writeSize(Annotations annotations) {
         // This includes an int size at the start of the list.
@@ -79,7 +79,7 @@
     /**
      * Gets the underlying annotations of this instance
      * 
-     * @return non-null; the annotations
+     * @return {@code non-null;} the annotations
      */
     public Annotations getAnnotations() {
         return annotations;
diff --git a/dx/src/com/android/dx/dex/file/AnnotationSetRefItem.java b/dx/src/com/android/dx/dex/file/AnnotationSetRefItem.java
index 422e2f0..1427e6a 100644
--- a/dx/src/com/android/dx/dex/file/AnnotationSetRefItem.java
+++ b/dx/src/com/android/dx/dex/file/AnnotationSetRefItem.java
@@ -29,13 +29,13 @@
     /** write size of this class, in bytes */
     private static final int WRITE_SIZE = 4;
 
-    /** non-null; the annotation set to refer to */
+    /** {@code non-null;} the annotation set to refer to */
     private AnnotationSetItem annotations;
 
     /**
      * Constructs an instance.
      * 
-     * @param annotations non-null; the annotation set to refer to
+     * @param annotations {@code non-null;} the annotation set to refer to
      */
     public AnnotationSetRefItem(AnnotationSetItem annotations) {
         super(ALIGNMENT, WRITE_SIZE);
diff --git a/dx/src/com/android/dx/dex/file/AnnotationUtils.java b/dx/src/com/android/dx/dex/file/AnnotationUtils.java
index c9d7968..8431d35 100644
--- a/dx/src/com/android/dx/dex/file/AnnotationUtils.java
+++ b/dx/src/com/android/dx/dex/file/AnnotationUtils.java
@@ -38,41 +38,41 @@
  * Utility class for dealing with annotations.
  */
 public final class AnnotationUtils {
-    /** non-null; type for <code>AnnotationDefault</code> annotations */
+    /** {@code non-null;} type for {@code AnnotationDefault} annotations */
     private static final CstType ANNOTATION_DEFAULT_TYPE = 
         CstType.intern(Type.intern("Ldalvik/annotation/AnnotationDefault;"));
 
-    /** non-null; type for <code>EnclosingClass</code> annotations */
+    /** {@code non-null;} type for {@code EnclosingClass} annotations */
     private static final CstType ENCLOSING_CLASS_TYPE = 
         CstType.intern(Type.intern("Ldalvik/annotation/EnclosingClass;"));
 
-    /** non-null; type for <code>EnclosingMethod</code> annotations */
+    /** {@code non-null;} type for {@code EnclosingMethod} annotations */
     private static final CstType ENCLOSING_METHOD_TYPE = 
         CstType.intern(Type.intern("Ldalvik/annotation/EnclosingMethod;"));
 
-    /** non-null; type for <code>InnerClass</code> annotations */
+    /** {@code non-null;} type for {@code InnerClass} annotations */
     private static final CstType INNER_CLASS_TYPE = 
         CstType.intern(Type.intern("Ldalvik/annotation/InnerClass;"));
 
-    /** non-null; type for <code>MemberClasses</code> annotations */
+    /** {@code non-null;} type for {@code MemberClasses} annotations */
     private static final CstType MEMBER_CLASSES_TYPE = 
         CstType.intern(Type.intern("Ldalvik/annotation/MemberClasses;"));
 
-    /** non-null; type for <code>Signature</code> annotations */
+    /** {@code non-null;} type for {@code Signature} annotations */
     private static final CstType SIGNATURE_TYPE = 
         CstType.intern(Type.intern("Ldalvik/annotation/Signature;"));
 
-    /** non-null; type for <code>Throws</code> annotations */
+    /** {@code non-null;} type for {@code Throws} annotations */
     private static final CstType THROWS_TYPE = 
         CstType.intern(Type.intern("Ldalvik/annotation/Throws;"));
 
-    /** non-null; the UTF-8 constant <code>"accessFlags"</code> */
+    /** {@code non-null;} the UTF-8 constant {@code "accessFlags"} */
     private static final CstUtf8 ACCESS_FLAGS_UTF = new CstUtf8("accessFlags");
 
-    /** non-null; the UTF-8 constant <code>"name"</code> */
+    /** {@code non-null;} the UTF-8 constant {@code "name"} */
     private static final CstUtf8 NAME_UTF = new CstUtf8("name");
 
-    /** non-null; the UTF-8 constant <code>"value"</code> */
+    /** {@code non-null;} the UTF-8 constant {@code "value"} */
     private static final CstUtf8 VALUE_UTF = new CstUtf8("value");
 
     /**
@@ -83,10 +83,10 @@
     }
 
     /**
-     * Constructs a standard <code>AnnotationDefault</code> annotation.
+     * Constructs a standard {@code AnnotationDefault} annotation.
      * 
-     * @param defaults non-null; the defaults, itself as an annotation
-     * @return non-null; the constructed annotation
+     * @param defaults {@code non-null;} the defaults, itself as an annotation
+     * @return {@code non-null;} the constructed annotation
      */
     public static Annotation makeAnnotationDefault(Annotation defaults) {
         Annotation result = new Annotation(ANNOTATION_DEFAULT_TYPE, SYSTEM);
@@ -97,10 +97,10 @@
     }
 
     /**
-     * Constructs a standard <code>EnclosingClass</code> annotation.
+     * Constructs a standard {@code EnclosingClass} annotation.
      * 
-     * @param clazz non-null; the enclosing class
-     * @return non-null; the annotation
+     * @param clazz {@code non-null;} the enclosing class
+     * @return {@code non-null;} the annotation
      */
     public static Annotation makeEnclosingClass(CstType clazz) {
         Annotation result = new Annotation(ENCLOSING_CLASS_TYPE, SYSTEM);
@@ -111,10 +111,10 @@
     }
 
     /**
-     * Constructs a standard <code>EnclosingMethod</code> annotation.
+     * Constructs a standard {@code EnclosingMethod} annotation.
      * 
-     * @param method non-null; the enclosing method
-     * @return non-null; the annotation
+     * @param method {@code non-null;} the enclosing method
+     * @return {@code non-null;} the annotation
      */
     public static Annotation makeEnclosingMethod(CstMethodRef method) {
         Annotation result = new Annotation(ENCLOSING_METHOD_TYPE, SYSTEM);
@@ -125,12 +125,12 @@
     }
 
     /**
-     * Constructs a standard <code>InnerClass</code> annotation.
+     * Constructs a standard {@code InnerClass} annotation.
      * 
-     * @param name null-ok; the original name of the class, or
-     * <code>null</code> to represent an anonymous class
+     * @param name {@code null-ok;} the original name of the class, or
+     * {@code null} to represent an anonymous class
      * @param accessFlags the original access flags
-     * @return non-null; the annotation
+     * @return {@code non-null;} the annotation
      */
     public static Annotation makeInnerClass(CstUtf8 name, int accessFlags) {
         Annotation result = new Annotation(INNER_CLASS_TYPE, SYSTEM);
@@ -145,10 +145,10 @@
     }
 
     /**
-     * Constructs a standard <code>MemberClasses</code> annotation.
+     * Constructs a standard {@code MemberClasses} annotation.
      * 
-     * @param types non-null; the list of (the types of) the member classes
-     * @return non-null; the annotation
+     * @param types {@code non-null;} the list of (the types of) the member classes
+     * @return {@code non-null;} the annotation
      */
     public static Annotation makeMemberClasses(TypeList types) {
         CstArray array = makeCstArray(types);
@@ -159,10 +159,10 @@
     }
 
     /**
-     * Constructs a standard <code>Signature</code> annotation.
+     * Constructs a standard {@code Signature} annotation.
      * 
-     * @param signature non-null; the signature string
-     * @return non-null; the annotation
+     * @param signature {@code non-null;} the signature string
+     * @return {@code non-null;} the annotation
      */
     public static Annotation makeSignature(CstUtf8 signature) {
         Annotation result = new Annotation(SIGNATURE_TYPE, SYSTEM);
@@ -221,10 +221,10 @@
     }
 
     /**
-     * Constructs a standard <code>Throws</code> annotation.
+     * Constructs a standard {@code Throws} annotation.
      * 
-     * @param types non-null; the list of thrown types
-     * @return non-null; the annotation
+     * @param types {@code non-null;} the list of thrown types
+     * @return {@code non-null;} the annotation
      */
     public static Annotation makeThrows(TypeList types) {
         CstArray array = makeCstArray(types);
@@ -237,8 +237,8 @@
     /**
      * Converts a {@link TypeList} to a {@link CstArray}.
      * 
-     * @param types non-null; the type list
-     * @return non-null; the corresponding array constant
+     * @param types {@code non-null;} the type list
+     * @return {@code non-null;} the corresponding array constant
      */
     private static CstArray makeCstArray(TypeList types) {
         int size = types.size();
diff --git a/dx/src/com/android/dx/dex/file/AnnotationsDirectoryItem.java b/dx/src/com/android/dx/dex/file/AnnotationsDirectoryItem.java
index 4521e4c..d55195f 100644
--- a/dx/src/com/android/dx/dex/file/AnnotationsDirectoryItem.java
+++ b/dx/src/com/android/dx/dex/file/AnnotationsDirectoryItem.java
@@ -40,16 +40,16 @@
     /** write size of a list element, in bytes */
     private static final int ELEMENT_SIZE = 8;
 
-    /** null-ok; the class-level annotations, if any */
+    /** {@code null-ok;} the class-level annotations, if any */
     private AnnotationSetItem classAnnotations;
     
-    /** null-ok; the annotated fields, if any */
+    /** {@code null-ok;} the annotated fields, if any */
     private ArrayList<FieldAnnotationStruct> fieldAnnotations;
 
-    /** null-ok; the annotated methods, if any */
+    /** {@code null-ok;} the annotated methods, if any */
     private ArrayList<MethodAnnotationStruct> methodAnnotations;
 
-    /** null-ok; the annotated parameters, if any */
+    /** {@code null-ok;} the annotated parameters, if any */
     private ArrayList<ParameterAnnotationStruct> parameterAnnotations;
 
     /**
@@ -73,7 +73,7 @@
     /**
      * Returns whether this item is empty (has no contents).
      * 
-     * @return <code>true</code> if this item is empty, or <code>false</code>
+     * @return {@code true} if this item is empty, or {@code false}
      * if not
      */
     public boolean isEmpty() {
@@ -88,8 +88,8 @@
      * interning candidates are ones that <i>only</i> have a non-null
      * set of class annotations, with no other lists.
      *
-     * @return <code>true</code> if this is an interning candidate, or
-     * <code>false</code> if not
+     * @return {@code true} if this is an interning candidate, or
+     * {@code false} if not
      */
     public boolean isInternable() {
         return (classAnnotations != null) &&
@@ -132,7 +132,7 @@
      * made on the class, per se, as opposed to on one of its members.
      * It is only valid to call this method at most once per instance.
      * 
-     * @param annotations non-null; annotations to set for this class
+     * @param annotations {@code non-null;} annotations to set for this class
      */
     public void setClassAnnotations(Annotations annotations) {
         if (annotations == null) {
@@ -150,8 +150,8 @@
     /**
      * Adds a field annotations item to this instance.
      * 
-     * @param field non-null; field in question
-     * @param annotations non-null; associated annotations to add
+     * @param field {@code non-null;} field in question
+     * @param annotations {@code non-null;} associated annotations to add
      */
     public void addFieldAnnotations(CstFieldRef field,
             Annotations annotations) {
@@ -166,8 +166,8 @@
     /**
      * Adds a method annotations item to this instance.
      * 
-     * @param method non-null; method in question
-     * @param annotations non-null; associated annotations to add
+     * @param method {@code non-null;} method in question
+     * @param annotations {@code non-null;} associated annotations to add
      */
     public void addMethodAnnotations(CstMethodRef method,
             Annotations annotations) {
@@ -182,8 +182,8 @@
     /**
      * Adds a parameter annotations item to this instance.
      * 
-     * @param method non-null; method in question
-     * @param list non-null; associated list of annotation sets to add
+     * @param method {@code non-null;} method in question
+     * @param list {@code non-null;} associated list of annotation sets to add
      */
     public void addParameterAnnotations(CstMethodRef method,
             AnnotationsList list) {
@@ -198,8 +198,8 @@
      * Gets the method annotations for a given method, if any. This is
      * meant for use by debugging / dumping code.
      * 
-     * @param method non-null; the method
-     * @return null-ok; the method annotations, if any
+     * @param method {@code non-null;} the method
+     * @return {@code null-ok;} the method annotations, if any
      */
     public Annotations getMethodAnnotations(CstMethodRef method) {
         if (methodAnnotations == null) {
@@ -219,8 +219,8 @@
      * Gets the parameter annotations for a given method, if any. This is
      * meant for use by debugging / dumping code.
      * 
-     * @param method non-null; the method
-     * @return null-ok; the parameter annotations, if any
+     * @param method {@code non-null;} the method
+     * @return {@code null-ok;} the parameter annotations, if any
      */
     public AnnotationsList getParameterAnnotations(CstMethodRef method) {
         if (parameterAnnotations == null) {
@@ -336,11 +336,11 @@
     }
 
     /**
-     * Gets the list size of the given list, or <code>0</code> if given
-     * <code>null</code>.
+     * Gets the list size of the given list, or {@code 0} if given
+     * {@code null}.
      * 
-     * @param list null-ok; the list in question
-     * @return &gt;= 0; its size
+     * @param list {@code null-ok;} the list in question
+     * @return {@code >= 0;} its size
      */
     private static int listSize(ArrayList<?> list) {
         if (list == null) {
@@ -354,7 +354,7 @@
      * Prints out the contents of this instance, in a debugging-friendly
      * way. This is meant to be called from {@link ClassDefItem#debugPrint}.
      * 
-     * @param out non-null; where to output to
+     * @param out {@code non-null;} where to output to
      */
     /*package*/ void debugPrint(PrintWriter out) {
         if (classAnnotations != null) {
diff --git a/dx/src/com/android/dx/dex/file/CatchStructs.java b/dx/src/com/android/dx/dex/file/CatchStructs.java
index b7abc3f..3412015 100644
--- a/dx/src/com/android/dx/dex/file/CatchStructs.java
+++ b/dx/src/com/android/dx/dex/file/CatchStructs.java
@@ -32,27 +32,27 @@
 /**
  * List of exception handlers (tuples of covered range, catch type,
  * handler address) for a particular piece of code. Instances of this
- * class correspond to a <code>try_item[]</code> and a
- * <code>catch_handler_item[]</code>.
+ * class correspond to a {@code try_item[]} and a
+ * {@code catch_handler_item[]}.
  */
 public final class CatchStructs {
     /**
-     * the size of a <code>try_item</code>: a <code>uint</code>
-     * and two <code>ushort</code>s 
+     * the size of a {@code try_item}: a {@code uint}
+     * and two {@code ushort}s 
      */
     private static final int TRY_ITEM_WRITE_SIZE = 4 + (2 * 2);
 
-    /** non-null; code that contains the catches */
+    /** {@code non-null;} code that contains the catches */
     private final DalvCode code;
     
     /**
-     * null-ok; the underlying table; set in
+     * {@code null-ok;} the underlying table; set in
      * {@link #finishProcessingIfNecessary}
      */
     private CatchTable table;
 
     /**
-     * null-ok; the encoded handler list, if calculated; set in
+     * {@code null-ok;} the encoded handler list, if calculated; set in
      * {@link #encode}
      */
     private byte[] encodedHandlers;
@@ -64,7 +64,7 @@
     private int encodedHandlerHeaderSize;
 
     /**
-     * null-ok; map from handler lists to byte offsets, if calculated; set in
+     * {@code null-ok;} map from handler lists to byte offsets, if calculated; set in
      * {@link #encode}
      */
     private TreeMap<CatchHandlerList, Integer> handlerOffsets;
@@ -72,7 +72,7 @@
     /**
      * Constructs an instance.
      * 
-     * @param code non-null; code that contains the catches
+     * @param code {@code non-null;} code that contains the catches
      */
     public CatchStructs(DalvCode code) {
         this.code = code;
@@ -94,7 +94,7 @@
     /**
      * Gets the size of the tries list, in entries.
      * 
-     * @return &gt;= 0; the tries list size
+     * @return {@code >= 0;} the tries list size
      */
     public int triesSize() {
         finishProcessingIfNecessary();
@@ -104,8 +104,8 @@
     /**
      * Does a human-friendly dump of this instance.
      * 
-     * @param out non-null; where to dump
-     * @param prefix non-null; prefix to attach to each line of output
+     * @param out {@code non-null;} where to dump
+     * @param prefix {@code non-null;} prefix to attach to each line of output
      */
     public void debugPrint(PrintWriter out, String prefix) {
         annotateEntries(prefix, out, null);
@@ -114,7 +114,7 @@
     /**
      * Encodes the handler lists.
      * 
-     * @param file non-null; file this instance is part of
+     * @param file {@code non-null;} file this instance is part of
      */
     public void encode(DexFile file) {
         finishProcessingIfNecessary();
@@ -179,7 +179,7 @@
     /**
      * Gets the write size of this instance, in bytes.
      * 
-     * @return &gt;= 0; the write size
+     * @return {@code >= 0;} the write size
      */
     public int writeSize() {
         return (triesSize() * TRY_ITEM_WRITE_SIZE) +
@@ -189,20 +189,17 @@
     /**
      * Writes this instance to the given stream.
      * 
-     * @param file non-null; file this instance is part of
-     * @param out non-null; where to write to
+     * @param file {@code non-null;} file this instance is part of
+     * @param out {@code non-null;} where to write to
      */
     public void writeTo(DexFile file, AnnotatedOutput out) {
         finishProcessingIfNecessary();
 
-        TypeIdsSection typeIds = file.getTypeIds();
-        int tableSize = table.size();
-        int handlersSize = handlerOffsets.size();
-        
         if (out.annotates()) {
             annotateEntries("  ", null, out);
         }
 
+        int tableSize = table.size();
         for (int i = 0; i < tableSize; i++) {
             CatchTable.Entry one = table.get(i);
             int start = one.getStart();
@@ -225,12 +222,12 @@
 
     /**
      * Helper method to annotate or simply print the exception handlers.
-     * Only one of <code>printTo</code> or <code>annotateTo</code> should
+     * Only one of {@code printTo} or {@code annotateTo} should
      * be non-null.
      * 
-     * @param prefix non-null; prefix for each line
-     * @param printTo null-ok; where to print to
-     * @param annotateTo null-ok; where to consume bytes and annotate to
+     * @param prefix {@code non-null;} prefix for each line
+     * @param printTo {@code null-ok;} where to print to
+     * @param annotateTo {@code null-ok;} where to consume bytes and annotate to
      */
     private void annotateEntries(String prefix, PrintWriter printTo,
             AnnotatedOutput annotateTo) {
@@ -299,12 +296,12 @@
      * Helper for {@link #annotateEntries} to annotate a catch handler list
      * while consuming it.
      * 
-     * @param handlers non-null; handlers to annotate
-     * @param offset &gt;= 0; the offset of this handler
-     * @param size &gt;= 1; the number of bytes the handlers consume
-     * @param prefix non-null; prefix for each line
-     * @param printTo null-ok; where to print to
-     * @param annotateTo non-null; where to annotate to
+     * @param handlers {@code non-null;} handlers to annotate
+     * @param offset {@code >= 0;} the offset of this handler
+     * @param size {@code >= 1;} the number of bytes the handlers consume
+     * @param prefix {@code non-null;} prefix for each line
+     * @param printTo {@code null-ok;} where to print to
+     * @param annotateTo {@code non-null;} where to annotate to
      */
     private static void annotateAndConsumeHandlers(CatchHandlerList handlers,
             int offset, int size, String prefix, PrintWriter printTo,
diff --git a/dx/src/com/android/dx/dex/file/ClassDataItem.java b/dx/src/com/android/dx/dex/file/ClassDataItem.java
index 638daed..4823f9f 100644
--- a/dx/src/com/android/dx/dex/file/ClassDataItem.java
+++ b/dx/src/com/android/dx/dex/file/ClassDataItem.java
@@ -38,32 +38,32 @@
  * Representation of all the parts of a Dalvik class that are generally
  * "inflated" into an in-memory representation at runtime. Instances of
  * this class are represented in a compact streamable form in a
- * <code>dex</code> file, as opposed to a random-access form.
+ * {@code dex} file, as opposed to a random-access form.
  */
 public final class ClassDataItem extends OffsettedItem {
-    /** non-null; what class this data is for, just for listing generation */
+    /** {@code non-null;} what class this data is for, just for listing generation */
     private final CstType thisClass;
     
-    /** non-null; list of static fields */
+    /** {@code non-null;} list of static fields */
     private final ArrayList<EncodedField> staticFields;
 
-    /** non-null; list of initial values for static fields */
+    /** {@code non-null;} list of initial values for static fields */
     private final HashMap<EncodedField, Constant> staticValues;
 
-    /** non-null; list of instance fields */
+    /** {@code non-null;} list of instance fields */
     private final ArrayList<EncodedField> instanceFields;
 
-    /** non-null; list of direct methods */
+    /** {@code non-null;} list of direct methods */
     private final ArrayList<EncodedMethod> directMethods;
 
-    /** non-null; list of virtual methods */
+    /** {@code non-null;} list of virtual methods */
     private final ArrayList<EncodedMethod> virtualMethods;
 
-    /** null-ok; static initializer list; set in {@link #addContents} */
+    /** {@code null-ok;} static initializer list; set in {@link #addContents} */
     private CstArray staticValuesConstant;
 
     /**
-     * null-ok; encoded form, ready for writing to a file; set during
+     * {@code null-ok;} encoded form, ready for writing to a file; set during
      * {@link #place0}
      */
     private byte[] encodedForm;
@@ -72,7 +72,7 @@
      * Constructs an instance. Its sets of members are initially
      * empty.
      * 
-     * @param thisClass non-null; what class this data is for, just
+     * @param thisClass {@code non-null;} what class this data is for, just
      * for listing generation
      */
     public ClassDataItem(CstType thisClass) {
@@ -106,8 +106,8 @@
     /**
      * Returns whether this instance is empty.
      * 
-     * @return <code>true</code> if this instance is empty or
-     * <code>false</code> if at least one element has been added to it
+     * @return {@code true} if this instance is empty or
+     * {@code false} if at least one element has been added to it
      */
     public boolean isEmpty() {
         return staticFields.isEmpty() && instanceFields.isEmpty()
@@ -117,8 +117,8 @@
     /**
      * Adds a static field.
      * 
-     * @param field non-null; the field to add
-     * @param value null-ok; initial value for the field, if any
+     * @param field {@code non-null;} the field to add
+     * @param value {@code null-ok;} initial value for the field, if any
      */
     public void addStaticField(EncodedField field, Constant value) {
         if (field == null) {
@@ -137,7 +137,7 @@
     /**
      * Adds an instance field.
      * 
-     * @param field non-null; the field to add
+     * @param field {@code non-null;} the field to add
      */
     public void addInstanceField(EncodedField field) {
         if (field == null) {
@@ -148,9 +148,9 @@
     }
 
     /**
-     * Adds a direct (<code>static</code> and/or <code>private</code>) method.
+     * Adds a direct ({@code static} and/or {@code private}) method.
      * 
-     * @param method non-null; the method to add
+     * @param method {@code non-null;} the method to add
      */
     public void addDirectMethod(EncodedMethod method) {
         if (method == null) {
@@ -163,7 +163,7 @@
     /**
      * Adds a virtual method.
      * 
-     * @param method non-null; the method to add
+     * @param method {@code non-null;} the method to add
      */
     public void addVirtualMethod(EncodedMethod method) {
         if (method == null) {
@@ -178,7 +178,7 @@
      * in any way to the underlying lists contained in this instance, but
      * the objects contained in the list are shared.
      * 
-     * @return non-null; list of all methods
+     * @return {@code non-null;} list of all methods
      */
     public ArrayList<EncodedMethod> getMethods() {
         int sz = directMethods.size() + virtualMethods.size();
@@ -195,7 +195,7 @@
      * Prints out the contents of this instance, in a debugging-friendly
      * way.
      * 
-     * @param out non-null; where to output to
+     * @param out {@code non-null;} where to output to
      * @param verbose whether to be verbose with the output
      */
     public void debugPrint(Writer out, boolean verbose) {
@@ -258,9 +258,9 @@
 
     /**
      * Gets a {@link CstArray} corresponding to {@link #staticValues} if
-     * it contains any non-zero non-<code>null</code> values.
+     * it contains any non-zero non-{@code null} values.
      * 
-     * @return null-ok; the corresponding constant or <code>null</code> if
+     * @return {@code null-ok;} the corresponding constant or {@code null} if
      * there are no values to encode
      */
     public CstArray getStaticValuesConstant() {
@@ -273,9 +273,9 @@
 
     /**
      * Gets a {@link CstArray} corresponding to {@link #staticValues} if
-     * it contains any non-zero non-<code>null</code> values.
+     * it contains any non-zero non-{@code null} values.
      * 
-     * @return null-ok; the corresponding constant or <code>null</code> if
+     * @return {@code null-ok;} the corresponding constant or {@code null} if
      * there are no values to encode
      */
     private CstArray makeStaticValuesConstant() {
@@ -337,13 +337,11 @@
     /**
      * Writes out the encoded form of this instance.
      * 
-     * @param file non-null; file this instance is part of
-     * @param out non-null; where to write to
+     * @param file {@code non-null;} file this instance is part of
+     * @param out {@code non-null;} where to write to
      */
     private void encodeOutput(DexFile file, AnnotatedOutput out) {
         boolean annotates = out.annotates();
-        int svSize = (staticValuesConstant == null) ? 0 :
-            staticValuesConstant.getList().size();
 
         if (annotates) {
             out.annotate(0, offsetString() + " class data for " +
@@ -369,10 +367,10 @@
      * Helper for {@link #encodeOutput}, which writes out the given
      * size value, annotating it as well (if annotations are enabled).
      * 
-     * @param file non-null; file this instance is part of
-     * @param out non-null; where to write to
-     * @param label non-null; the label for the purposes of annotation
-     * @param size &gt;= 0; the size to write
+     * @param file {@code non-null;} file this instance is part of
+     * @param out {@code non-null;} where to write to
+     * @param label {@code non-null;} the label for the purposes of annotation
+     * @param size {@code >= 0;} the size to write
      */
     private static void encodeSize(DexFile file, AnnotatedOutput out,
             String label, int size) {
@@ -389,10 +387,10 @@
      * list. It also annotates the items (if any and if annotations
      * are enabled).
      * 
-     * @param file non-null; file this instance is part of
-     * @param out non-null; where to write to
-     * @param label non-null; the label for the purposes of annotation
-     * @param list non-null; the list in question
+     * @param file {@code non-null;} file this instance is part of
+     * @param out {@code non-null;} where to write to
+     * @param label {@code non-null;} the label for the purposes of annotation
+     * @param list {@code non-null;} the list in question
      */
     private static void encodeList(DexFile file, AnnotatedOutput out,
             String label, ArrayList<? extends EncodedMember> list) {
diff --git a/dx/src/com/android/dx/dex/file/ClassDefItem.java b/dx/src/com/android/dx/dex/file/ClassDefItem.java
index 5a0b27c..acd8cf5 100644
--- a/dx/src/com/android/dx/dex/file/ClassDefItem.java
+++ b/dx/src/com/android/dx/dex/file/ClassDefItem.java
@@ -45,47 +45,47 @@
     /** size of instances when written out to a file, in bytes */
     public static final int WRITE_SIZE = 32;
 
-    /** non-null; type constant for this class */
+    /** {@code non-null;} type constant for this class */
     private final CstType thisClass;
 
     /** access flags */
     private final int accessFlags;
 
     /**
-     * null-ok; superclass or <code>null</code> if this class is a/the
+     * {@code null-ok;} superclass or {@code null} if this class is a/the
      * root class 
      */
     private final CstType superclass;
 
-    /** null-ok; list of implemented interfaces */
+    /** {@code null-ok;} list of implemented interfaces */
     private TypeListItem interfaces;
 
-    /** null-ok; source file name or <code>null</code> if unknown */
+    /** {@code null-ok;} source file name or {@code null} if unknown */
     private final CstUtf8 sourceFile;
 
-    /** non-null; associated class data object */
+    /** {@code non-null;} associated class data object */
     private final ClassDataItem classData;
 
     /**
-     * null-ok; item wrapper for the static values, initialized
+     * {@code null-ok;} item wrapper for the static values, initialized
      * in {@link #addContents}
      */
     private EncodedArrayItem staticValuesItem;
 
-    /** non-null; annotations directory */
+    /** {@code non-null;} annotations directory */
     private AnnotationsDirectoryItem annotationsDirectory;
 
     /**
      * Constructs an instance. Its sets of members and annotations are
      * initially empty.
      * 
-     * @param thisClass non-null; type constant for this class
+     * @param thisClass {@code non-null;} type constant for this class
      * @param accessFlags access flags
-     * @param superclass null-ok; superclass or <code>null</code> if
+     * @param superclass {@code null-ok;} superclass or {@code null} if
      * this class is a/the root class
-     * @param interfaces non-null; list of implemented interfaces
-     * @param sourceFile null-ok; source file name or
-     * <code>null</code> if unknown
+     * @param interfaces {@code non-null;} list of implemented interfaces
+     * @param sourceFile {@code null-ok;} source file name or
+     * {@code null} if unknown
      */
     public ClassDefItem(CstType thisClass, int accessFlags,
             CstType superclass, TypeList interfaces, CstUtf8 sourceFile) {
@@ -223,7 +223,7 @@
     /**
      * Gets the constant corresponding to this class.
      * 
-     * @return non-null; the constant
+     * @return {@code non-null;} the constant
      */
     public CstType getThisClass() {
         return thisClass;
@@ -241,7 +241,7 @@
     /**
      * Gets the superclass.
      * 
-     * @return null-ok; the superclass or <code>null</code> if
+     * @return {@code null-ok;} the superclass or {@code null} if
      * this class is a/the root class
      */
     public CstType getSuperclass() {
@@ -251,7 +251,7 @@
     /**
      * Gets the list of interfaces implemented.
      * 
-     * @return non-null; the interfaces list
+     * @return {@code non-null;} the interfaces list
      */
     public TypeList getInterfaces() {
         if (interfaces == null) {
@@ -264,7 +264,7 @@
     /**
      * Gets the source file name.
      * 
-     * @return null-ok; the source file name or <code>null</code> if unknown
+     * @return {@code null-ok;} the source file name or {@code null} if unknown
      */
     public CstUtf8 getSourceFile() {
         return sourceFile;
@@ -273,8 +273,8 @@
     /**
      * Adds a static field.
      * 
-     * @param field non-null; the field to add
-     * @param value null-ok; initial value for the field, if any
+     * @param field {@code non-null;} the field to add
+     * @param value {@code null-ok;} initial value for the field, if any
      */
     public void addStaticField(EncodedField field, Constant value) {
         classData.addStaticField(field, value);
@@ -283,16 +283,16 @@
     /**
      * Adds an instance field.
      * 
-     * @param field non-null; the field to add
+     * @param field {@code non-null;} the field to add
      */
     public void addInstanceField(EncodedField field) {
         classData.addInstanceField(field);
     }
 
     /**
-     * Adds a direct (<code>static</code> and/or <code>private</code>) method.
+     * Adds a direct ({@code static} and/or {@code private}) method.
      * 
-     * @param method non-null; the method to add
+     * @param method {@code non-null;} the method to add
      */
     public void addDirectMethod(EncodedMethod method) {
         classData.addDirectMethod(method);
@@ -301,7 +301,7 @@
     /**
      * Adds a virtual method.
      * 
-     * @param method non-null; the method to add
+     * @param method {@code non-null;} the method to add
      */
     public void addVirtualMethod(EncodedMethod method) {
         classData.addVirtualMethod(method);
@@ -312,7 +312,7 @@
      * in any way to the underlying lists contained in this instance, but
      * the objects contained in the list are shared.
      * 
-     * @return non-null; list of all methods
+     * @return {@code non-null;} list of all methods
      */
     public ArrayList<EncodedMethod> getMethods() {
         return classData.getMethods();
@@ -323,7 +323,7 @@
      * made on the class, per se, as opposed to on one of its members.
      * It is only valid to call this method at most once per instance.
      * 
-     * @param annotations non-null; annotations to set for this class
+     * @param annotations {@code non-null;} annotations to set for this class
      */
     public void setClassAnnotations(Annotations annotations) {
         annotationsDirectory.setClassAnnotations(annotations);
@@ -332,8 +332,8 @@
     /**
      * Adds a field annotations item to this class.
      * 
-     * @param field non-null; field in question
-     * @param annotations non-null; associated annotations to add
+     * @param field {@code non-null;} field in question
+     * @param annotations {@code non-null;} associated annotations to add
      */
     public void addFieldAnnotations(CstFieldRef field,
             Annotations annotations) {
@@ -343,8 +343,8 @@
     /**
      * Adds a method annotations item to this class.
      * 
-     * @param method non-null; method in question
-     * @param annotations non-null; associated annotations to add
+     * @param method {@code non-null;} method in question
+     * @param annotations {@code non-null;} associated annotations to add
      */
     public void addMethodAnnotations(CstMethodRef method,
             Annotations annotations) {
@@ -354,8 +354,8 @@
     /**
      * Adds a parameter annotations item to this class.
      * 
-     * @param method non-null; method in question
-     * @param list non-null; associated list of annotation sets to add
+     * @param method {@code non-null;} method in question
+     * @param list {@code non-null;} associated list of annotation sets to add
      */
     public void addParameterAnnotations(CstMethodRef method,
             AnnotationsList list) {
@@ -366,8 +366,8 @@
      * Gets the method annotations for a given method, if any. This is
      * meant for use by debugging / dumping code.
      * 
-     * @param method non-null; the method
-     * @return null-ok; the method annotations, if any
+     * @param method {@code non-null;} the method
+     * @return {@code null-ok;} the method annotations, if any
      */
     public Annotations getMethodAnnotations(CstMethodRef method) {
         return annotationsDirectory.getMethodAnnotations(method);
@@ -377,8 +377,8 @@
      * Gets the parameter annotations for a given method, if any. This is
      * meant for use by debugging / dumping code.
      * 
-     * @param method non-null; the method
-     * @return null-ok; the parameter annotations, if any
+     * @param method {@code non-null;} the method
+     * @return {@code null-ok;} the parameter annotations, if any
      */
     public AnnotationsList getParameterAnnotations(CstMethodRef method) {
         return annotationsDirectory.getParameterAnnotations(method);
@@ -388,7 +388,7 @@
      * Prints out the contents of this instance, in a debugging-friendly
      * way.
      * 
-     * @param out non-null; where to output to
+     * @param out {@code non-null;} where to output to
      * @param verbose whether to be verbose with the output
      */
     public void debugPrint(Writer out, boolean verbose) {
diff --git a/dx/src/com/android/dx/dex/file/ClassDefsSection.java b/dx/src/com/android/dx/dex/file/ClassDefsSection.java
index cf61b47..e8efd57 100644
--- a/dx/src/com/android/dx/dex/file/ClassDefsSection.java
+++ b/dx/src/com/android/dx/dex/file/ClassDefsSection.java
@@ -28,22 +28,22 @@
 import java.util.TreeMap;
 
 /**
- * Class definitions list section of a <code>.dex</code> file.
+ * Class definitions list section of a {@code .dex} file.
  */
 public final class ClassDefsSection extends UniformItemSection {
     /**
-     * non-null; map from type constants for classes to {@link
+     * {@code non-null;} map from type constants for classes to {@link
      * ClassDefItem} instances that define those classes
      */
     private final TreeMap<Type, ClassDefItem> classDefs;
 
-    /** null-ok; ordered list of classes; set in {@link #orderItems} */
+    /** {@code null-ok;} ordered list of classes; set in {@link #orderItems} */
     private ArrayList<ClassDefItem> orderedDefs;
 
     /**
      * Constructs an instance. The file offset is initially unknown.
      * 
-     * @param file non-null; file that this instance is part of
+     * @param file {@code non-null;} file that this instance is part of
      */
     public ClassDefsSection(DexFile file) {
         super("class_defs", file, 4);
@@ -84,7 +84,7 @@
     /**
      * Writes the portion of the file header that refers to this instance.
      * 
-     * @param out non-null; where to write
+     * @param out {@code non-null;} where to write
      */
     public void writeHeaderPart(AnnotatedOutput out) {
         throwIfNotPrepared();
@@ -105,7 +105,7 @@
      * Adds an element to this instance. It is illegal to attempt to add more
      * than one class with the same name.
      * 
-     * @param clazz non-null; the class def to add
+     * @param clazz {@code non-null;} the class def to add
      */
     public void add(ClassDefItem clazz) {
         Type type;
@@ -149,11 +149,11 @@
      * Helper for {@link #orderItems}, which recursively assigns indices
      * to classes.
      * 
-     * @param type null-ok; type ref to assign, if any
-     * @param idx &gt;= 0; the next index to assign
+     * @param type {@code null-ok;} type ref to assign, if any
+     * @param idx {@code >= 0;} the next index to assign
      * @param maxDepth maximum recursion depth; if negative, this will
      * throw an exception indicating class definition circularity
-     * @return &gt;= 0; the next index to assign
+     * @return {@code >= 0;} the next index to assign
      */
     private int orderItems0(Type type, int idx, int maxDepth) {
         ClassDefItem c = classDefs.get(type);
diff --git a/dx/src/com/android/dx/dex/file/CodeItem.java b/dx/src/com/android/dx/dex/file/CodeItem.java
index dc0bb52..ab7abbe 100644
--- a/dx/src/com/android/dx/dex/file/CodeItem.java
+++ b/dx/src/com/android/dx/dex/file/CodeItem.java
@@ -39,7 +39,7 @@
 
 /**
  * Representation of all the parts needed for concrete methods in a
- * <code>dex</code> file.
+ * {@code dex} file.
  */
 public final class CodeItem extends OffsettedItem {
     /** file alignment of this class, in bytes */
@@ -48,26 +48,26 @@
     /** write size of the header of this class, in bytes */
     private static final int HEADER_SIZE = 16;
 
-    /** non-null; method that this code implements */
+    /** {@code non-null;} method that this code implements */
     private final CstMethodRef ref;
 
-    /** non-null; the bytecode instructions and associated data */
+    /** {@code non-null;} the bytecode instructions and associated data */
     private final DalvCode code;
 
-    /** null-ok; the catches, if needed; set in {@link #addContents} */
+    /** {@code null-ok;} the catches, if needed; set in {@link #addContents} */
     private CatchStructs catches;
 
-    /** whether this instance is for a <code>static</code> method */
+    /** whether this instance is for a {@code static} method */
     private final boolean isStatic;
 
     /**
-     * non-null; list of possibly-thrown exceptions; just used in
+     * {@code non-null;} list of possibly-thrown exceptions; just used in
      * generating debugging output (listings) 
      */
     private final TypeList throwsList;
 
     /**
-     * null-ok; the debug info or <code>null</code> if there is none;
+     * {@code null-ok;} the debug info or {@code null} if there is none;
      * set in {@link #addContents}
      */
     private DebugInfoItem debugInfo;
@@ -75,11 +75,11 @@
     /**
      * Constructs an instance.
      * 
-     * @param ref non-null; method that this code implements
-     * @param code non-null; the underlying code
-     * @param isStatic whether this instance is for a <code>static</code>
+     * @param ref {@code non-null;} method that this code implements
+     * @param code {@code non-null;} the underlying code
+     * @param isStatic whether this instance is for a {@code static}
      * method
-     * @param throwsList non-null; list of possibly-thrown exceptions,
+     * @param throwsList {@code non-null;} list of possibly-thrown exceptions,
      * just used in generating debugging output (listings)
      */
     public CodeItem(CstMethodRef ref, DalvCode code, boolean isStatic,
@@ -114,7 +114,6 @@
 
     /** {@inheritDoc} */
     public void addContents(DexFile file) {
-        MixedItemSection wordData = file.getWordData();
         MixedItemSection byteData = file.getByteData();
         TypeIdsSection typeIds = file.getTypeIds();
 
@@ -150,7 +149,7 @@
     /**
      * Gets the reference to the method this instance implements.
      * 
-     * @return non-null; the method reference
+     * @return {@code non-null;} the method reference
      */
     public CstMethodRef getRef() {
         return ref;
@@ -159,8 +158,8 @@
     /**
      * Does a human-friendly dump of this instance.
      * 
-     * @param out non-null; where to dump
-     * @param prefix non-null; per-line prefix to use
+     * @param out {@code non-null;} where to dump
+     * @param prefix {@code non-null;} per-line prefix to use
      * @param verbose whether to be verbose with the output
      */
     public void debugPrint(PrintWriter out, String prefix, boolean verbose) {
@@ -292,8 +291,8 @@
     /**
      * Helper for {@link #writeTo0} which writes out the actual bytecode.
      *
-     * @param file non-null; file we are part of
-     * @param out non-null; where to write to
+     * @param file {@code non-null;} file we are part of
+     * @param out {@code non-null;} where to write to
      */
     private void writeCodes(DexFile file, AnnotatedOutput out) {
         DalvInsnList insns = code.getInsns();
diff --git a/dx/src/com/android/dx/dex/file/DebugInfoConstants.java b/dx/src/com/android/dx/dex/file/DebugInfoConstants.java
index 010acb4..78b6b04 100644
--- a/dx/src/com/android/dx/dex/file/DebugInfoConstants.java
+++ b/dx/src/com/android/dx/dex/file/DebugInfoConstants.java
@@ -110,8 +110,8 @@
      * next position entry that is added should be considered the end of
      * a method prologue (an appropriate place for a method breakpoint).<p>
      *
-     * The prologue_end register is cleared by any special (&gt= OPCODE_BASE)
-     * opcode.
+     * The prologue_end register is cleared by any special
+     * ({@code >= OPCODE_BASE}) opcode.
      */
     static final int DBG_SET_PROLOGUE_END = 0x07;
 
@@ -121,8 +121,8 @@
      * a method epilogue (an appropriate place to suspend execution before
      * method exit).<p>
      *
-     * The epilogue_begin register is cleared by any special (&gt= OPCODE_BASE)
-     * opcode.
+     * The epilogue_begin register is cleared by any special
+     * ({@code >= OPCODE_BASE}) opcode.
      */
     static final int DBG_SET_EPILOGUE_BEGIN = 0x08;
 
diff --git a/dx/src/com/android/dx/dex/file/DebugInfoDecoder.java b/dx/src/com/android/dx/dex/file/DebugInfoDecoder.java
index 3ffd276..cd20055 100644
--- a/dx/src/com/android/dx/dex/file/DebugInfoDecoder.java
+++ b/dx/src/com/android/dx/dex/file/DebugInfoDecoder.java
@@ -38,7 +38,7 @@
 /**
  * A decoder for the dex debug info state machine format.
  * This code exists mostly as a reference implementation and test for
- * for the <code>DebugInfoEncoder</code>
+ * for the {@code DebugInfoEncoder}
  */
 public class DebugInfoDecoder {
     /** encoded debug info */
@@ -180,7 +180,7 @@
 
     /**
      * Gets the decoded positions list.
-     * Valid after calling <code>decode</code>.
+     * Valid after calling {@code decode}.
      *
      * @return positions list in ascending address order.
      */
@@ -190,7 +190,7 @@
 
     /**
      * Gets the decoded locals list, in ascending start-address order.
-     * Valid after calling <code>decode</code>.
+     * Valid after calling {@code decode}.
      *
      * @return locals list in ascending address order.
      */
@@ -227,7 +227,7 @@
     /**
      * Gets the register that begins the method's parameter range (including
      * the 'this' parameter for non-static methods). The range continues until
-     * <code>regSize</code>
+     * {@code regSize}
      *
      * @return register as noted above.
      */
@@ -416,9 +416,9 @@
      * encoder.
      *
      * @param info encoded debug info
-     * @param file non-null; file to refer to during decoding
-     * @param ref non-null; method whose info is being decoded
-     * @param code non-null; original code object that was encoded
+     * @param file {@code non-null;} file to refer to during decoding
+     * @param ref {@code non-null;} method whose info is being decoded
+     * @param code {@code non-null;} original code object that was encoded
      * @param isStatic whether the method is static
      */
     public static void validateEncode(byte[] info, DexFile file,
diff --git a/dx/src/com/android/dx/dex/file/DebugInfoEncoder.java b/dx/src/com/android/dx/dex/file/DebugInfoEncoder.java
index 780e18d..08b6637 100644
--- a/dx/src/com/android/dx/dex/file/DebugInfoEncoder.java
+++ b/dx/src/com/android/dx/dex/file/DebugInfoEncoder.java
@@ -46,19 +46,19 @@
  * <li> signed LEB128: initial value for line register.
  * <li> n instances of signed LEB128: string indicies (offset by 1)
  * for each method argument in left-to-right order
- * with <code>this</code> excluded. A value of '0' indicates "no name"
+ * with {@code this} excluded. A value of '0' indicates "no name"
  * <li> A sequence of special or normal opcodes as defined in
- * <code>DebugInfoConstants</code>.
- * <li> A single terminating <code>OP_END_SEQUENCE</code>
+ * {@code DebugInfoConstants}.
+ * <li> A single terminating {@code OP_END_SEQUENCE}
  * </ol>
  */
 public final class DebugInfoEncoder {
     private static final boolean DEBUG = false;
 
-    /** null-ok; positions (line numbers) to encode */
+    /** {@code null-ok;} positions (line numbers) to encode */
     private final PositionList positions;
 
-    /** null-ok; local variables to encode */
+    /** {@code null-ok;} local variables to encode */
     private final LocalList locals;
 
     private final ByteArrayAnnotatedOutput output;
@@ -96,33 +96,32 @@
     /**
      * Creates an instance.
      *
-     * @param pl null-ok; positions (line numbers) to encode
-     * @param ll null-ok; local variables to encode
-     * @param file null-ok; may only be <code>null</code> if simply using
+     * @param positions {@code null-ok;} positions (line numbers) to encode
+     * @param locals {@code null-ok;} local variables to encode
+     * @param file {@code null-ok;} may only be {@code null} if simply using
      * this class to do a debug print
      * @param codeSize
      * @param regSize
      * @param isStatic
      * @param ref
      */
-    public DebugInfoEncoder(PositionList pl, LocalList ll,
+    public DebugInfoEncoder(PositionList positions, LocalList locals,
             DexFile file, int codeSize, int regSize,
             boolean isStatic, CstMethodRef ref) {
-        this.positions = pl;
-        this.locals = ll;
+        this.positions = positions;
+        this.locals = locals;
         this.file = file;
-        output = new ByteArrayAnnotatedOutput();
         this.desc = ref.getPrototype();
         this.isStatic = isStatic;
-
         this.codeSize = codeSize;
         this.regSize = regSize;
 
+        output = new ByteArrayAnnotatedOutput();
         lastEntryForReg = new LocalList.Entry[regSize];
     }
 
     /**
-     * Annotates or writes a message to the <code>debugPrint</code> writer
+     * Annotates or writes a message to the {@code debugPrint} writer
      * if applicable.
      *
      * @param length the number of bytes associated with this message
@@ -146,8 +145,8 @@
      * Converts this (PositionList, LocalList) pair into a state machine
      * sequence.
      *
-     * @return encoded byte sequence without padding and
-     * terminated with a <code>'\00'</code>
+     * @return {@code non-null;} encoded byte sequence without padding and
+     * terminated with a {@code 0x00} byte
      */
     public byte[] convert() {
         try {
@@ -169,15 +168,15 @@
 
     /**
      * Converts and produces annotations on a stream. Does not write
-     * actual bits to the <code>AnnotatedOutput</code>.
+     * actual bits to the {@code AnnotatedOutput}.
      *
-     * @param prefix null-ok; prefix to attach to each line of output
-     * @param debugPrint null-ok; if specified, an alternate output for
+     * @param prefix {@code null-ok;} prefix to attach to each line of output
+     * @param debugPrint {@code null-ok;} if specified, an alternate output for
      * annotations
-     * @param out null-ok; if specified, where annotations should go
+     * @param out {@code null-ok;} if specified, where annotations should go
      * @param consume whether to claim to have consumed output for
-     * <code>out</code>
-     * @return output sequence
+     * {@code out}
+     * @return {@code non-null;} encoded output
      */
     public byte[] convertAndAnnotate(String prefix, PrintWriter debugPrint,
             AnnotatedOutput out, boolean consume) {
@@ -190,7 +189,7 @@
 
         return result;
     }
-    
+
     private byte[] convert0() throws IOException {
         ArrayList<PositionList.Entry> sortedPositions = buildSortedPositions();
         ArrayList<LocalList.Entry> methodArgs = extractMethodArguments();
@@ -204,21 +203,22 @@
             annotate(1, String.format("%04x: prologue end",address));
         }
 
-        int szp = sortedPositions.size();
-        int szl = locals.size();
+        int positionsSz = sortedPositions.size();
+        int localsSz = locals.size();
 
         // Current index in sortedPositions
-        int curp = 0;
+        int curPositionIdx = 0;
         // Current index in locals
-        int curl = 0;
+        int curLocalIdx = 0;
 
         for (;;) {
             /*
              * Emit any information for the current address.
              */
 
-            curl = emitLocalsAtAddress(curl);
-            curp = emitPositionsAtAddress(curp, sortedPositions);
+            curLocalIdx = emitLocalsAtAddress(curLocalIdx);
+            curPositionIdx =
+                emitPositionsAtAddress(curPositionIdx, sortedPositions);
 
             /*
              * Figure out what the next important address is.
@@ -227,12 +227,12 @@
             int nextAddrL = Integer.MAX_VALUE; // local variable
             int nextAddrP = Integer.MAX_VALUE; // position (line number)
 
-            if (curl < szl) {
-                nextAddrL = locals.get(curl).getAddress();
+            if (curLocalIdx < localsSz) {
+                nextAddrL = locals.get(curLocalIdx).getAddress();
             }
 
-            if (curp < szp) {
-                nextAddrP = sortedPositions.get(curp).getAddress();
+            if (curPositionIdx < positionsSz) {
+                nextAddrP = sortedPositions.get(curPositionIdx).getAddress();
             }
 
             int next = Math.min(nextAddrP, nextAddrL);
@@ -249,12 +249,12 @@
             if (next == codeSize
                     && nextAddrL == Integer.MAX_VALUE
                     && nextAddrP == Integer.MAX_VALUE) {
-                break;                
+                break;
             }
 
             if (next == nextAddrP) {
                 // Combined advance PC + position entry
-                emitPosition(sortedPositions.get(curp++));
+                emitPosition(sortedPositions.get(curPositionIdx++));
             } else {
                 emitAdvancePc(next - address);
             }
@@ -271,96 +271,96 @@
      * locals} and including all subsequent activity at the same
      * address.
      *
-     * @param curl Current index in locals
-     * @return new value for <code>curl</code>
+     * @param curLocalIdx Current index in locals
+     * @return new value for {@code curLocalIdx}
      * @throws IOException
      */
-    private int emitLocalsAtAddress(int curl)
+    private int emitLocalsAtAddress(int curLocalIdx)
             throws IOException {
         int sz = locals.size();
 
         // TODO: Don't emit ends implied by starts.
 
-        while ((curl < sz)
-                && (locals.get(curl).getAddress() == address)) {
-            LocalList.Entry lle = locals.get(curl++);
-            int reg = lle.getRegister();
-            LocalList.Entry prevlle = lastEntryForReg[reg];
+        while ((curLocalIdx < sz)
+                && (locals.get(curLocalIdx).getAddress() == address)) {
+            LocalList.Entry entry = locals.get(curLocalIdx++);
+            int reg = entry.getRegister();
+            LocalList.Entry prevEntry = lastEntryForReg[reg];
 
-            if (lle == prevlle) {
+            if (entry == prevEntry) {
                 /*
                  * Here we ignore locals entries for parameters,
                  * which have already been represented and placed in the
                  * lastEntryForReg array.
                  */
                 continue;
-            } 
+            }
 
             // At this point we have a new entry one way or another.
-            lastEntryForReg[reg] = lle;
+            lastEntryForReg[reg] = entry;
 
-            if (lle.isStart()) {
-                if ((prevlle != null) && lle.matches(prevlle)) {
+            if (entry.isStart()) {
+                if ((prevEntry != null) && entry.matches(prevEntry)) {
                     /*
                      * The previous local in this register has the same
                      * name and type as the one being introduced now, so
                      * use the more efficient "restart" form.
                      */
-                    if (prevlle.isStart()) {
+                    if (prevEntry.isStart()) {
                         /*
                          * We should never be handed a start when a
                          * a matching local is already active.
                          */
                         throw new RuntimeException("shouldn't happen");
                     }
-                    emitLocalRestart(lle);
+                    emitLocalRestart(entry);
                 } else {
-                    emitLocalStart(lle);
+                    emitLocalStart(entry);
                 }
             } else {
                 /*
                  * Only emit a local end if it is *not* due to a direct
                  * replacement. Direct replacements imply an end of the
                  * previous local in the same register.
-                 * 
+                 *
                  * TODO: Make sure the runtime can deal with implied
                  * local ends from category-2 interactions, and when so,
                  * also stop emitting local ends for those cases.
                  */
-                if (lle.getDisposition()
+                if (entry.getDisposition()
                         != LocalList.Disposition.END_REPLACED) {
-                    emitLocalEnd(lle);
+                    emitLocalEnd(entry);
                 }
             }
         }
 
-        return curl;
+        return curLocalIdx;
     }
 
     /**
-     * Emits all positions that occur at the current <code>address</code>
+     * Emits all positions that occur at the current {@code address}
      *
-     * @param curp Current index in sortedPositions
+     * @param curPositionIdx Current index in sortedPositions
      * @param sortedPositions positions, sorted by ascending address
-     * @return new value for <code>curp</code>
+     * @return new value for {@code curPositionIdx}
      * @throws IOException
      */
-    private int emitPositionsAtAddress(int curp,
+    private int emitPositionsAtAddress(int curPositionIdx,
             ArrayList<PositionList.Entry> sortedPositions)
             throws IOException {
-
-        int szp = sortedPositions.size();
-        while (curp < szp
-                && sortedPositions.get(curp).getAddress() == address) {
-            emitPosition(sortedPositions.get(curp++));
+        int positionsSz = sortedPositions.size();
+        while ((curPositionIdx < positionsSz)
+                && (sortedPositions.get(curPositionIdx).getAddress()
+                        == address)) {
+            emitPosition(sortedPositions.get(curPositionIdx++));
         }
-        return curp;
+        return curPositionIdx;
     }
 
     /**
      * Emits the header sequence, which consists of LEB128-encoded initial
      * line number and string indicies for names of all non-"this" arguments.
-     *  
+     *
      * @param sortedPositions positions, sorted by ascending address
      * @param methodArgs local list entries for method argumens arguments,
      * in left-to-right order omitting "this"
@@ -392,7 +392,7 @@
          * entry for the 'this' pointer.
          */
         if (!isStatic) {
-            for (LocalList.Entry arg: methodArgs) {
+            for (LocalList.Entry arg : methodArgs) {
                 if (curParam == arg.getRegister()) {
                     lastEntryForReg[curParam] = arg;
                     break;
@@ -406,7 +406,7 @@
         output.writeUnsignedLeb128(szParamTypes);
 
         if (annotate) {
-            annotate(output.getCursor() - mark, 
+            annotate(output.getCursor() - mark,
                     String.format("parameters_size: %04x", szParamTypes));
         }
 
@@ -420,7 +420,7 @@
 
             mark = output.getCursor();
 
-            for (LocalList.Entry arg: methodArgs) {
+            for (LocalList.Entry arg : methodArgs) {
                 if (curParam == arg.getRegister()) {
                     found = arg;
 
@@ -507,7 +507,7 @@
     /**
      * Gets the register that begins the method's parameter range (including
      * the 'this' parameter for non-static methods). The range continues until
-     * <code>regSize</code>
+     * {@code regSize}
      *
      * @return register as noted above
      */
@@ -521,7 +521,7 @@
      * from the input list and sorted by ascending register in the
      * returned list.
      *
-     * @return list of non-<code>this</code> method argument locals,
+     * @return list of non-{@code this} method argument locals,
      * sorted by ascending register
      */
     private ArrayList<LocalList.Entry> extractMethodArguments() {
@@ -566,8 +566,8 @@
      * Returns a string representation of this LocalList entry that is
      * appropriate for emitting as an annotation.
      *
-     * @param e non-null; entry
-     * @return non-null; annotation string
+     * @param e {@code non-null;} entry
+     * @return {@code non-null;} annotation string
      */
     private String entryAnnotationString(LocalList.Entry e) {
         StringBuilder sb = new StringBuilder();
@@ -633,7 +633,7 @@
      * null symbol is used in some cases by the parameter name list
      * at the beginning of the sequence.
      *
-     * @param string null-ok; string to emit
+     * @param string {@code null-ok;} string to emit
      * @throws IOException
      */
     private void emitStringIndex(CstUtf8 string) throws IOException {
@@ -654,7 +654,7 @@
      * Emits a type index as an unsigned LEB128. The actual value written
      * is shifted by 1, so that the '0' value is reserved for "null".
      *
-     * @param type null-ok; type to emit
+     * @param type {@code null-ok;} type to emit
      * @throws IOException
      */
     private void emitTypeIndex(CstType type) throws IOException {
@@ -739,7 +739,7 @@
     /**
      * Emits a {@link DebugInfoConstants#DBG_END_LOCAL DBG_END_LOCAL} sequence.
      *
-     * @param entry entry non-null; entry associated with end.
+     * @param entry {@code entry non-null;} entry associated with end.
      * @throws IOException
      */
     private void emitLocalEnd(LocalList.Entry entry)
@@ -823,16 +823,17 @@
      * Essentially the same as described in "DWARF Debugging Format Version 3"
      * section 6.2.5.1.
      *
-     * @param deltaLines &gt;= DBG_LINE_BASE and &lt;= DBG_LINE_BASE +
-     * DBG_LINE_RANGE, the line change to encode
-     * @param deltaAddress &gt;= 0; the address change to encode
-     * @return &lt;= 0xff if in range, otherwise parameters are out of range
+     * @param deltaLines {@code >= DBG_LINE_BASE, <= DBG_LINE_BASE +
+     * DBG_LINE_RANGE;} the line change to encode
+     * @param deltaAddress {@code >= 0;} the address change to encode
+     * @return {@code <= 0xff} if in range, otherwise parameters are out
+     * of range
      */
     private static int computeOpcode(int deltaLines, int deltaAddress) {
         if (deltaLines < DBG_LINE_BASE
                 || deltaLines > (DBG_LINE_BASE + DBG_LINE_RANGE -1)) {
 
-            throw new RuntimeException("Parameter out of range");            
+            throw new RuntimeException("Parameter out of range");
         }
 
         return (deltaLines - DBG_LINE_BASE)
@@ -864,10 +865,10 @@
     }
 
     /**
-     * Emits an  {@link DebugInfoConstants#DBG_ADVANCE_PC DBG_ADVANCE_PC} 
+     * Emits an  {@link DebugInfoConstants#DBG_ADVANCE_PC DBG_ADVANCE_PC}
      * sequence.
      *
-     * @param deltaAddress &gt;= 0 amount to change program counter by
+     * @param deltaAddress {@code >= 0;} amount to change program counter by
      * @throws IOException
      */
     private void emitAdvancePc(int deltaAddress) throws IOException {
@@ -890,8 +891,9 @@
     /**
      * Emits an unsigned LEB128 value.
      *
-     * @param n &gt= 0 vallue to emit. Note that, although this can represent
-     * integers larger than Integer.MAX_VALUE, we currently don't allow that.
+     * @param n {@code >= 0;} value to emit. Note that, although this can
+     * represent integers larger than Integer.MAX_VALUE, we currently don't
+     * allow that.
      * @throws IOException
      */
     private void emitUnsignedLeb128(int n) throws IOException {
@@ -901,7 +903,7 @@
                     "Signed value where unsigned required: " + n);
         }
 
-        output.writeSignedLeb128(n);
+        output.writeUnsignedLeb128(n);
     }
 
     /**
diff --git a/dx/src/com/android/dx/dex/file/DebugInfoItem.java b/dx/src/com/android/dx/dex/file/DebugInfoItem.java
index 0e4329b..1c32bd7 100644
--- a/dx/src/com/android/dx/dex/file/DebugInfoItem.java
+++ b/dx/src/com/android/dx/dex/file/DebugInfoItem.java
@@ -34,7 +34,7 @@
 
     private static final boolean ENABLE_ENCODER_SELF_CHECK = false;
 
-    /** non-null; the code this item represents */
+    /** {@code non-null;} the code this item represents */
     private final DalvCode code;
     
     private byte[] encoded;
@@ -93,9 +93,9 @@
      * directly after a code dump (with the real local list actually
      * existing elsewhere in the output).
      *
-     * @param file non-null; the file to use for referencing other sections
-     * @param out non-null; where to annotate to
-     * @param prefix null-ok; prefix to attach to each line of output
+     * @param file {@code non-null;} the file to use for referencing other sections
+     * @param out {@code non-null;} where to annotate to
+     * @param prefix {@code null-ok;} prefix to attach to each line of output
      */
     public void annotateTo(DexFile file, AnnotatedOutput out, String prefix) {
         encode(file, prefix, null, out, false);
@@ -104,8 +104,8 @@
     /**
      * Does a human-friendly dump of this instance.
      *
-     * @param out non-null; where to dump
-     * @param prefix non-null; prefix to attach to each line of output
+     * @param out {@code non-null;} where to dump
+     * @param prefix {@code non-null;} prefix to attach to each line of output
      */
     public void debugPrint(PrintWriter out, String prefix) {
         encode(null, prefix, out, null, false);
@@ -130,14 +130,14 @@
     /**
      * Performs debug info encoding.
      *
-     * @param file null-ok; file to refer to during encoding
-     * @param prefix null-ok; prefix to attach to each line of output
-     * @param debugPrint null-ok; if specified, an alternate output for
+     * @param file {@code null-ok;} file to refer to during encoding
+     * @param prefix {@code null-ok;} prefix to attach to each line of output
+     * @param debugPrint {@code null-ok;} if specified, an alternate output for
      * annotations
-     * @param out null-ok; if specified, where annotations should go
+     * @param out {@code null-ok;} if specified, where annotations should go
      * @param consume whether to claim to have consumed output for
-     * <code>out</code>
-     * @return non-null; the encoded array
+     * {@code out}
+     * @return {@code non-null;} the encoded array
      */
     private byte[] encode(DexFile file, String prefix, PrintWriter debugPrint,
             AnnotatedOutput out, boolean consume) {
@@ -161,14 +161,14 @@
     /**
      * Helper for {@link #encode} to do most of the work.
      *
-     * @param file null-ok; file to refer to during encoding
-     * @param prefix null-ok; prefix to attach to each line of output
-     * @param debugPrint null-ok; if specified, an alternate output for
+     * @param file {@code null-ok;} file to refer to during encoding
+     * @param prefix {@code null-ok;} prefix to attach to each line of output
+     * @param debugPrint {@code null-ok;} if specified, an alternate output for
      * annotations
-     * @param out null-ok; if specified, where annotations should go
+     * @param out {@code null-ok;} if specified, where annotations should go
      * @param consume whether to claim to have consumed output for
-     * <code>out</code>
-     * @return non-null; the encoded array
+     * {@code out}
+     * @return {@code non-null;} the encoded array
      */
     private byte[] encode0(DexFile file, String prefix, PrintWriter debugPrint,
             AnnotatedOutput out, boolean consume) {
diff --git a/dx/src/com/android/dx/dex/file/DexFile.java b/dx/src/com/android/dx/dex/file/DexFile.java
index 8a4075d..a829fed 100644
--- a/dx/src/com/android/dx/dex/file/DexFile.java
+++ b/dx/src/com/android/dx/dex/file/DexFile.java
@@ -38,67 +38,67 @@
 import static com.android.dx.dex.file.MixedItemSection.SortType;
 
 /**
- * Representation of an entire <code>.dex</code> (Dalvik EXecutable)
+ * Representation of an entire {@code .dex} (Dalvik EXecutable)
  * file, which itself consists of a set of Dalvik classes.
  */
 public final class DexFile {
-    /** non-null; word data section */
+    /** {@code non-null;} word data section */
     private final MixedItemSection wordData;
 
     /** 
-     * non-null; type lists section. This is word data, but separating
+     * {@code non-null;} type lists section. This is word data, but separating
      * it from {@link #wordData} helps break what would otherwise be a
      * circular dependency between the that and {@link #protoIds}.
      */
     private final MixedItemSection typeLists;
 
     /**
-     * non-null; map section. The map needs to be in a section by itself
+     * {@code non-null;} map section. The map needs to be in a section by itself
      * for the self-reference mechanics to work in a reasonably
      * straightforward way. See {@link MapItem#addMap} for more detail.
      */
     private final MixedItemSection map;
 
-    /** non-null; string data section */
+    /** {@code non-null;} string data section */
     private final MixedItemSection stringData;
 
-    /** non-null; string identifiers section */
+    /** {@code non-null;} string identifiers section */
     private final StringIdsSection stringIds;
 
-    /** non-null; type identifiers section */
+    /** {@code non-null;} type identifiers section */
     private final TypeIdsSection typeIds;
 
-    /** non-null; prototype identifiers section */
+    /** {@code non-null;} prototype identifiers section */
     private final ProtoIdsSection protoIds;
 
-    /** non-null; field identifiers section */
+    /** {@code non-null;} field identifiers section */
     private final FieldIdsSection fieldIds;
 
-    /** non-null; method identifiers section */
+    /** {@code non-null;} method identifiers section */
     private final MethodIdsSection methodIds;
 
-    /** non-null; class definitions section */
+    /** {@code non-null;} class definitions section */
     private final ClassDefsSection classDefs;
 
-    /** non-null; class data section */
+    /** {@code non-null;} class data section */
     private final MixedItemSection classData;
 
-    /** non-null; byte data section */
+    /** {@code non-null;} byte data section */
     private final MixedItemSection byteData;
 
-    /** non-null; file header */
+    /** {@code non-null;} file header */
     private final HeaderSection header;
 
     /**
-     * non-null; array of sections in the order they will appear in the
+     * {@code non-null;} array of sections in the order they will appear in the
      * final output file
      */
     private final Section[] sections;
 
-    /** &gt;= -1; total file size or <code>-1</code> if unknown */
+    /** {@code >= -1;} total file size or {@code -1} if unknown */
     private int fileSize;
 
-    /** &gt;= 40; maximum width of the file dump */
+    /** {@code >= 40;} maximum width of the file dump */
     private int dumpWidth;
 
     /**
@@ -137,7 +137,7 @@
      * Adds a class to this instance. It is illegal to attempt to add more
      * than one class with the same name.
      * 
-     * @param clazz non-null; the class to add
+     * @param clazz {@code non-null;} the class to add
      */
     public void add(ClassDefItem clazz) {
         classDefs.add(clazz);
@@ -146,8 +146,8 @@
     /**
      * Gets the class definition with the given name, if any.
      * 
-     * @param name non-null; the class name to look for
-     * @return null-ok; the class with the given name, or <code>null</code>
+     * @param name {@code non-null;} the class name to look for
+     * @return {@code null-ok;} the class with the given name, or {@code null}
      * if there is no such class
      */
     public ClassDefItem getClassOrNull(String name) {
@@ -164,8 +164,8 @@
      * Writes the contents of this instance as either a binary or a
      * human-readable form, or both.
      * 
-     * @param out null-ok; where to write to
-     * @param humanOut null-ok; where to write human-oriented output to
+     * @param out {@code null-ok;} where to write to
+     * @param humanOut {@code null-ok;} where to write human-oriented output to
      * @param verbose whether to be verbose when writing human-oriented output
      */
     public void writeTo(OutputStream out, Writer humanOut, boolean verbose)
@@ -183,12 +183,12 @@
     }
 
     /**
-     * Returns the contents of this instance as a <code>.dex</code> file,
-     * in <code>byte[]</code> form.
+     * Returns the contents of this instance as a {@code .dex} file,
+     * in {@code byte[]} form.
      * 
-     * @param humanOut null-ok; where to write human-oriented output to
+     * @param humanOut {@code null-ok;} where to write human-oriented output to
      * @param verbose whether to be verbose when writing human-oriented output
-     * @return non-null; a <code>.dex</code> file for this instance
+     * @return {@code non-null;} a {@code .dex} file for this instance
      */
     public byte[] toDex(Writer humanOut, boolean verbose) 
         throws IOException {
@@ -205,7 +205,7 @@
     /**
      * Sets the maximum width of the human-oriented dump of the instance.
      * 
-     * @param dumpWidth &gt;= 40; the width
+     * @param dumpWidth {@code >= 40;} the width
      */
     public void setDumpWidth(int dumpWidth) {
         if (dumpWidth < 40) {
@@ -221,7 +221,7 @@
      * <p>This is package-scope in order to allow
      * the {@link HeaderSection} to set itself up properly.</p>
      * 
-     * @return &gt;= 0; the total file size
+     * @return {@code >= 0;} the total file size
      * @throws RuntimeException thrown if the file size is not yet known
      */
     /*package*/ int getFileSize() {
@@ -239,7 +239,7 @@
      * the various {@link Item} instances to add items to the
      * instance.</p>
      * 
-     * @return non-null; the string data section
+     * @return {@code non-null;} the string data section
      */
     /*package*/ MixedItemSection getStringData() {
         return stringData;
@@ -252,7 +252,7 @@
      * the various {@link Item} instances to add items to the
      * instance.</p>
      * 
-     * @return non-null; the word data section
+     * @return {@code non-null;} the word data section
      */
     /*package*/ MixedItemSection getWordData() {
         return wordData;
@@ -265,7 +265,7 @@
      * the various {@link Item} instances to add items to the
      * instance.</p>
      * 
-     * @return non-null; the word data section
+     * @return {@code non-null;} the word data section
      */
     /*package*/ MixedItemSection getTypeLists() {
         return typeLists;
@@ -277,7 +277,7 @@
      * <p>This is package-scope in order to allow the header section
      * to query it.</p>
      * 
-     * @return non-null; the map section
+     * @return {@code non-null;} the map section
      */
     /*package*/ MixedItemSection getMap() {
         return map;
@@ -290,7 +290,7 @@
      * the various {@link Item} instances to add items to the
      * instance.</p>
      * 
-     * @return non-null; the string identifiers section
+     * @return {@code non-null;} the string identifiers section
      */
     /*package*/ StringIdsSection getStringIds() {
         return stringIds;
@@ -303,7 +303,7 @@
      * the various {@link Item} instances to add items to the
      * instance.</p>
      * 
-     * @return non-null; the class definitions section
+     * @return {@code non-null;} the class definitions section
      */
     /*package*/ ClassDefsSection getClassDefs() {
         return classDefs;
@@ -316,7 +316,7 @@
      * the various {@link Item} instances to add items to the
      * instance.</p>
      * 
-     * @return non-null; the class data section
+     * @return {@code non-null;} the class data section
      */
     /*package*/ MixedItemSection getClassData() {
         return classData;
@@ -329,7 +329,7 @@
      * the various {@link Item} instances to add items to the
      * instance.</p>
      * 
-     * @return non-null; the class identifiers section
+     * @return {@code non-null;} the class identifiers section
      */
     /*package*/ TypeIdsSection getTypeIds() {
         return typeIds;
@@ -342,7 +342,7 @@
      * the various {@link Item} instances to add items to the
      * instance.</p>
      * 
-     * @return non-null; the prototype identifiers section
+     * @return {@code non-null;} the prototype identifiers section
      */
     /*package*/ ProtoIdsSection getProtoIds() {
         return protoIds;
@@ -355,7 +355,7 @@
      * the various {@link Item} instances to add items to the
      * instance.</p>
      * 
-     * @return non-null; the field identifiers section
+     * @return {@code non-null;} the field identifiers section
      */
     /*package*/ FieldIdsSection getFieldIds() {
         return fieldIds;
@@ -368,7 +368,7 @@
      * the various {@link Item} instances to add items to the
      * instance.</p>
      * 
-     * @return non-null; the method identifiers section
+     * @return {@code non-null;} the method identifiers section
      */
     /*package*/ MethodIdsSection getMethodIds() {
         return methodIds;
@@ -381,7 +381,7 @@
      * the various {@link Item} instances to add items to the
      * instance.</p>
      *
-     * @return non-null; the byte data section
+     * @return {@code non-null;} the byte data section
      */
     /*package*/ MixedItemSection getByteData() {
         return byteData;
@@ -394,7 +394,7 @@
      * <p>This is package-scope in order to allow the header section
      * to query it.</p>
      * 
-     * @return non-null; the section
+     * @return {@code non-null;} the section
      */
     /*package*/ Section getFirstDataSection() {
         return wordData;
@@ -407,7 +407,7 @@
      * <p>This is package-scope in order to allow the header section
      * to query it.</p>
      * 
-     * @return non-null; the section
+     * @return {@code non-null;} the section
      */
     /*package*/ Section getLastDataSection() {
         return map;
@@ -418,7 +418,7 @@
      * instance, or do nothing if the given constant isn't the sort
      * that should be interned.
      * 
-     * @param cst non-null; constant to possibly intern
+     * @param cst {@code non-null;} constant to possibly intern
      */
     /*package*/ void internIfAppropriate(Constant cst) {
         if (cst instanceof CstString) {
@@ -441,13 +441,13 @@
     /**
      * Gets the {@link IndexedItem} corresponding to the given constant,
      * if it is a constant that has such a correspondence, or return
-     * <code>null</code> if it isn't such a constant. This will throw
+     * {@code null} if it isn't such a constant. This will throw
      * an exception if the given constant <i>should</i> have been found
      * but wasn't.
      * 
-     * @param cst non-null; the constant to look up
-     * @return null-ok; its corresponding item, if it has a corresponding
-     * item, or <code>null</code> if it's not that sort of constant
+     * @param cst {@code non-null;} the constant to look up
+     * @return {@code null-ok;} its corresponding item, if it has a corresponding
+     * item, or {@code null} if it's not that sort of constant
      */
     /*package*/ IndexedItem findItemOrNull(Constant cst) {
         IndexedItem item;
@@ -466,12 +466,12 @@
     }
 
     /**
-     * Returns the contents of this instance as a <code>.dex</code> file,
+     * Returns the contents of this instance as a {@code .dex} file,
      * in a {@link ByteArrayAnnotatedOutput} instance.
      * 
      * @param annotate whether or not to keep annotations
      * @param verbose if annotating, whether to be verbose
-     * @return non-null; a <code>.dex</code> file for this instance
+     * @return {@code non-null;} a {@code .dex} file for this instance
      */
     private ByteArrayAnnotatedOutput toDex0(boolean annotate,
             boolean verbose) {
@@ -586,7 +586,7 @@
     /**
      * Generates and returns statistics for all the items in the file.
      * 
-     * @return non-null; the statistics
+     * @return {@code non-null;} the statistics
      */
     public Statistics getStatistics() {
         Statistics stats = new Statistics();
@@ -599,10 +599,10 @@
     }
 
     /**
-     * Calculates the signature for the <code>.dex</code> file in the
+     * Calculates the signature for the {@code .dex} file in the
      * given array, and modify the array to contain it.
      * 
-     * @param bytes non-null; the bytes of the file
+     * @param bytes {@code non-null;} the bytes of the file
      */
     private static void calcSignature(byte[] bytes) {
         MessageDigest md;
@@ -627,10 +627,10 @@
     }
 
     /**
-     * Calculates the checksum for the <code>.dex</code> file in the
+     * Calculates the checksum for the {@code .dex} file in the
      * given array, and modify the array to contain it.
      * 
-     * @param bytes non-null; the bytes of the file
+     * @param bytes {@code non-null;} the bytes of the file
      */
     private static void calcChecksum(byte[] bytes) {
         Adler32 a32 = new Adler32();
diff --git a/dx/src/com/android/dx/dex/file/EncodedArrayItem.java b/dx/src/com/android/dx/dex/file/EncodedArrayItem.java
index 9ec72fa..c55c6f5 100644
--- a/dx/src/com/android/dx/dex/file/EncodedArrayItem.java
+++ b/dx/src/com/android/dx/dex/file/EncodedArrayItem.java
@@ -36,11 +36,11 @@
     /** the required alignment for instances of this class */
     private static final int ALIGNMENT = 1;
 
-    /** non-null; the array to represent */
+    /** {@code non-null;} the array to represent */
     private final CstArray array;
 
     /**
-     * null-ok; encoded form, ready for writing to a file; set during
+     * {@code null-ok;} encoded form, ready for writing to a file; set during
      * {@link #place0}
      */
     private byte[] encodedForm;
@@ -48,7 +48,7 @@
     /**
      * Constructs an instance.
      * 
-     * @param array non-null; array to represent
+     * @param array {@code non-null;} array to represent
      */
     public EncodedArrayItem(CstArray array) {
         /*
diff --git a/dx/src/com/android/dx/dex/file/EncodedField.java b/dx/src/com/android/dx/dex/file/EncodedField.java
index 62a5789..146a604 100644
--- a/dx/src/com/android/dx/dex/file/EncodedField.java
+++ b/dx/src/com/android/dx/dex/file/EncodedField.java
@@ -30,13 +30,13 @@
  */
 public final class EncodedField extends EncodedMember
         implements Comparable<EncodedField> {
-    /** non-null; constant for the field */
+    /** {@code non-null;} constant for the field */
     private final CstFieldRef field;
 
     /**
      * Constructs an instance.
      * 
-     * @param field non-null; constant for the field
+     * @param field {@code non-null;} constant for the field
      * @param accessFlags access flags
      */
     public EncodedField(CstFieldRef field, int accessFlags) {
@@ -122,7 +122,7 @@
     /**
      * Gets the constant for the field.
      * 
-     * @return non-null; the constant
+     * @return {@code non-null;} the constant
      */
     public CstFieldRef getRef() {
         return field;
diff --git a/dx/src/com/android/dx/dex/file/EncodedMember.java b/dx/src/com/android/dx/dex/file/EncodedMember.java
index 3ae0d09..68119f3 100644
--- a/dx/src/com/android/dx/dex/file/EncodedMember.java
+++ b/dx/src/com/android/dx/dex/file/EncodedMember.java
@@ -51,14 +51,14 @@
     /**
      * Gets the name.
      *
-     * @return non-null; the name
+     * @return {@code non-null;} the name
      */
     public abstract CstUtf8 getName();
 
     /**
      * Does a human-friendly dump of this instance.
      *
-     * @param out non-null; where to dump
+     * @param out {@code non-null;} where to dump
      * @param verbose whether to be verbose with the output
      */
     public abstract void debugPrint(PrintWriter out, boolean verbose);
@@ -66,20 +66,20 @@
     /**
      * Populates a {@link DexFile} with items from within this instance.
      * 
-     * @param file non-null; the file to populate
+     * @param file {@code non-null;} the file to populate
      */
     public abstract void addContents(DexFile file);
 
     /**
      * Encodes this instance to the given output.
      * 
-     * @param file non-null; file this instance is part of
-     * @param out non-null; where to write to
-     * @param lastIndex &gt;= 0; the previous member index value encoded, or
-     * <code>0</code> if this is the first element to encode
-     * @param dumpSeq &gt;= 0; sequence number of this instance for
+     * @param file {@code non-null;} file this instance is part of
+     * @param out {@code non-null;} where to write to
+     * @param lastIndex {@code >= 0;} the previous member index value encoded, or
+     * {@code 0} if this is the first element to encode
+     * @param dumpSeq {@code >= 0;} sequence number of this instance for
      * annotation purposes
-     * @return &gt;= 0; the member index value that was encoded
+     * @return {@code >= 0;} the member index value that was encoded
      */
     public abstract int encode(DexFile file, AnnotatedOutput out, 
             int lastIndex, int dumpSeq);
diff --git a/dx/src/com/android/dx/dex/file/EncodedMethod.java b/dx/src/com/android/dx/dex/file/EncodedMethod.java
index 319fbb7..dff1a07 100644
--- a/dx/src/com/android/dx/dex/file/EncodedMethod.java
+++ b/dx/src/com/android/dx/dex/file/EncodedMethod.java
@@ -32,23 +32,23 @@
  */
 public final class EncodedMethod extends EncodedMember 
         implements Comparable<EncodedMethod> {
-    /** non-null; constant for the method */
+    /** {@code non-null;} constant for the method */
     private final CstMethodRef method;
 
     /**
-     * null-ok; code for the method, if the method is neither
-     * <code>abstract</code> nor <code>native</code> 
+     * {@code null-ok;} code for the method, if the method is neither
+     * {@code abstract} nor {@code native} 
      */
     private final CodeItem code;
 
     /**
      * Constructs an instance.
      * 
-     * @param method non-null; constant for the method
+     * @param method {@code non-null;} constant for the method
      * @param accessFlags access flags
-     * @param code null-ok; code for the method, if it is neither
-     * <code>abstract</code> nor <code>native</code>
-     * @param throwsList non-null; list of possibly-thrown exceptions,
+     * @param code {@code null-ok;} code for the method, if it is neither
+     * {@code abstract} nor {@code native}
+     * @param throwsList {@code non-null;} list of possibly-thrown exceptions,
      * just used in generating debugging output (listings)
      */
     public EncodedMethod(CstMethodRef method, int accessFlags,
@@ -148,7 +148,7 @@
     /**
      * Gets the constant for the method.
      * 
-     * @return non-null; the constant
+     * @return {@code non-null;} the constant
      */
     public final CstMethodRef getRef() {
         return method;
diff --git a/dx/src/com/android/dx/dex/file/FieldAnnotationStruct.java b/dx/src/com/android/dx/dex/file/FieldAnnotationStruct.java
index e6169bd..6a76ca9 100644
--- a/dx/src/com/android/dx/dex/file/FieldAnnotationStruct.java
+++ b/dx/src/com/android/dx/dex/file/FieldAnnotationStruct.java
@@ -27,17 +27,17 @@
  */
 public final class FieldAnnotationStruct
         implements ToHuman, Comparable<FieldAnnotationStruct> {
-    /** non-null; the field in question */
+    /** {@code non-null;} the field in question */
     private final CstFieldRef field;
 
-    /** non-null; the associated annotations */
+    /** {@code non-null;} the associated annotations */
     private AnnotationSetItem annotations;
 
     /**
      * Constructs an instance.
      * 
-     * @param field non-null; the field in question
-     * @param annotations non-null; the associated annotations
+     * @param field {@code non-null;} the field in question
+     * @param annotations {@code non-null;} the associated annotations
      */
     public FieldAnnotationStruct(CstFieldRef field,
             AnnotationSetItem annotations) {
@@ -105,7 +105,7 @@
     /**
      * Gets the field this item is for.
      * 
-     * @return non-null; the field
+     * @return {@code non-null;} the field
      */
     public CstFieldRef getField() {
         return field;
@@ -114,7 +114,7 @@
     /**
      * Gets the associated annotations.
      * 
-     * @return non-null; the annotations
+     * @return {@code non-null;} the annotations
      */
     public Annotations getAnnotations() {
         return annotations.getAnnotations();
diff --git a/dx/src/com/android/dx/dex/file/FieldIdItem.java b/dx/src/com/android/dx/dex/file/FieldIdItem.java
index d098d52..d6d01d5 100644
--- a/dx/src/com/android/dx/dex/file/FieldIdItem.java
+++ b/dx/src/com/android/dx/dex/file/FieldIdItem.java
@@ -25,7 +25,7 @@
     /**
      * Constructs an instance.
      * 
-     * @param field non-null; the constant for the field
+     * @param field {@code non-null;} the constant for the field
      */
     public FieldIdItem(CstFieldRef field) {
         super(field);
@@ -49,7 +49,7 @@
     /**
      * Gets the field constant.
      * 
-     * @return non-null; the constant
+     * @return {@code non-null;} the constant
      */
     public CstFieldRef getFieldRef() {
         return (CstFieldRef) getRef();
diff --git a/dx/src/com/android/dx/dex/file/FieldIdsSection.java b/dx/src/com/android/dx/dex/file/FieldIdsSection.java
index fddf55f..59ef229 100644
--- a/dx/src/com/android/dx/dex/file/FieldIdsSection.java
+++ b/dx/src/com/android/dx/dex/file/FieldIdsSection.java
@@ -25,11 +25,11 @@
 import java.util.TreeMap;
 
 /**
- * Field refs list section of a <code>.dex</code> file.
+ * Field refs list section of a {@code .dex} file.
  */
 public final class FieldIdsSection extends MemberIdsSection {
     /**
-     * non-null; map from field constants to {@link
+     * {@code non-null;} map from field constants to {@link
      * FieldIdItem} instances 
      */
     private final TreeMap<CstFieldRef, FieldIdItem> fieldIds;
@@ -37,7 +37,7 @@
     /**
      * Constructs an instance. The file offset is initially unknown.
      * 
-     * @param file non-null; file that this instance is part of
+     * @param file {@code non-null;} file that this instance is part of
      */
     public FieldIdsSection(DexFile file) {
         super("field_ids", file);
@@ -72,7 +72,7 @@
     /**
      * Writes the portion of the file header that refers to this instance.
      * 
-     * @param out non-null; where to write
+     * @param out {@code non-null;} where to write
      */
     public void writeHeaderPart(AnnotatedOutput out) {
         throwIfNotPrepared();
@@ -92,8 +92,8 @@
     /**
      * Interns an element into this instance.
      * 
-     * @param field non-null; the reference to intern
-     * @return non-null; the interned reference
+     * @param field {@code non-null;} the reference to intern
+     * @return {@code non-null;} the interned reference
      */
     public FieldIdItem intern(CstFieldRef field) {
         if (field == null) {
@@ -116,8 +116,8 @@
      * Gets the index of the given reference, which must have been added
      * to this instance.
      * 
-     * @param ref non-null; the reference to look up
-     * @return &gt;= 0; the reference's index
+     * @param ref {@code non-null;} the reference to look up
+     * @return {@code >= 0;} the reference's index
      */
     public int indexOf(CstFieldRef ref) {
         if (ref == null) {
diff --git a/dx/src/com/android/dx/dex/file/HeaderItem.java b/dx/src/com/android/dx/dex/file/HeaderItem.java
index 55c1f1c..6593859 100644
--- a/dx/src/com/android/dx/dex/file/HeaderItem.java
+++ b/dx/src/com/android/dx/dex/file/HeaderItem.java
@@ -21,11 +21,11 @@
 import com.android.dx.util.Hex;
 
 /**
- * File header section of a <code>.dex</code> file.
+ * File header section of a {@code .dex} file.
  */
 public final class HeaderItem extends IndexedItem {
     /**
-     * non-null; the file format magic number, represented as the
+     * {@code non-null;} the file format magic number, represented as the
      * low-order bytes of a string
      */
     private static final String MAGIC = "dex\n035\0";
diff --git a/dx/src/com/android/dx/dex/file/HeaderSection.java b/dx/src/com/android/dx/dex/file/HeaderSection.java
index 9022e0f..5bc6278 100644
--- a/dx/src/com/android/dx/dex/file/HeaderSection.java
+++ b/dx/src/com/android/dx/dex/file/HeaderSection.java
@@ -23,16 +23,16 @@
 import java.util.List;
 
 /**
- * File header section of a <code>.dex</code> file.
+ * File header section of a {@code .dex} file.
  */
 public final class HeaderSection extends UniformItemSection {
-    /** non-null; the list of the one item in the section */
+    /** {@code non-null;} the list of the one item in the section */
     private final List<HeaderItem> list;
     
     /**
      * Constructs an instance. The file offset is initially unknown.
      * 
-     * @param file non-null; file that this instance is part of
+     * @param file {@code non-null;} file that this instance is part of
      */
     public HeaderSection(DexFile file) {
         super(null, file, 4);
diff --git a/dx/src/com/android/dx/dex/file/IdItem.java b/dx/src/com/android/dx/dex/file/IdItem.java
index 8342514..5d7c9e3 100644
--- a/dx/src/com/android/dx/dex/file/IdItem.java
+++ b/dx/src/com/android/dx/dex/file/IdItem.java
@@ -23,7 +23,7 @@
  */
 public abstract class IdItem extends IndexedItem {
     /**
-     * non-null; the type constant for the defining class of
+     * {@code non-null;} the type constant for the defining class of
      * the reference 
      */
     private final CstType type;
@@ -31,7 +31,7 @@
     /**
      * Constructs an instance.
      * 
-     * @param type non-null; the type constant for the defining
+     * @param type {@code non-null;} the type constant for the defining
      * class of the reference
      */
     public IdItem(CstType type) {
@@ -53,7 +53,7 @@
      * Gets the type constant for the defining class of the
      * reference.
      * 
-     * @return non-null; the type constant
+     * @return {@code non-null;} the type constant
      */
     public final CstType getDefiningClass() {
         return type;
diff --git a/dx/src/com/android/dx/dex/file/IndexedItem.java b/dx/src/com/android/dx/dex/file/IndexedItem.java
index 9bf7fd2..32d69ea 100644
--- a/dx/src/com/android/dx/dex/file/IndexedItem.java
+++ b/dx/src/com/android/dx/dex/file/IndexedItem.java
@@ -20,7 +20,7 @@
  * An item in a Dalvik file which is referenced by index.
  */
 public abstract class IndexedItem extends Item {
-    /** &gt;= -1; assigned index of the item, or <code>-1</code> if not
+    /** {@code >= -1;} assigned index of the item, or {@code -1} if not
      * yet assigned */
     private int index;
 
@@ -34,7 +34,7 @@
     /**
      * Gets whether or not this instance has been assigned an index.
      * 
-     * @return <code>true</code> iff this instance has been assigned an index
+     * @return {@code true} iff this instance has been assigned an index
      */
     public final boolean hasIndex() {
         return (index >= 0);
@@ -43,7 +43,7 @@
     /**
      * Gets the item index.
      *
-     * @return &gt;= 0; the index
+     * @return {@code >= 0;} the index
      * @throws RuntimeException thrown if the item index is not yet assigned
      */
     public final int getIndex() {
@@ -56,10 +56,10 @@
 
     /**
      * Sets the item index. This method may only ever be called once
-     * per instance, and this will throw a <code>RuntimeException</code> if
+     * per instance, and this will throw a {@code RuntimeException} if
      * called a second (or subsequent) time.
      *
-     * @param index &gt;= 0; the item index
+     * @param index {@code >= 0;} the item index
      */
     public final void setIndex(int index) {
         if (this.index != -1) {
@@ -73,7 +73,7 @@
      * Gets the index of this item as a string, suitable for including in
      * annotations.
      * 
-     * @return non-null; the index string
+     * @return {@code non-null;} the index string
      */
     public final String indexString() {
         return '[' + Integer.toHexString(index) + ']';
diff --git a/dx/src/com/android/dx/dex/file/Item.java b/dx/src/com/android/dx/dex/file/Item.java
index 3708d45..057f218 100644
--- a/dx/src/com/android/dx/dex/file/Item.java
+++ b/dx/src/com/android/dx/dex/file/Item.java
@@ -33,7 +33,7 @@
     /**
      * Returns the item type for this instance.
      * 
-     * @return non-null; the item type
+     * @return {@code non-null;} the item type
      */
     public abstract ItemType itemType();
     
@@ -41,7 +41,7 @@
      * Returns the human name for the particular type of item this
      * instance is.
      * 
-     * @return non-null; the name
+     * @return {@code non-null;} the name
      */
     public final String typeName() {
         return itemType().toHuman();
@@ -50,7 +50,7 @@
     /**
      * Gets the size of this instance when written, in bytes.
      * 
-     * @return &gt;= 0; the write size
+     * @return {@code >= 0;} the write size
      */
     public abstract int writeSize();
 
@@ -62,7 +62,7 @@
      * <p><b>Note:</b> Subclasses must override this to do something
      * appropriate.</p>
      * 
-     * @param file non-null; the file to populate
+     * @param file {@code non-null;} the file to populate
      */
     public abstract void addContents(DexFile file);
 
@@ -73,8 +73,8 @@
      * note the written offset and will also throw an exception if this
      * instance has already been written.
      * 
-     * @param file non-null; the file to use for reference
-     * @param out non-null; where to write to
+     * @param file {@code non-null;} the file to use for reference
+     * @param out {@code non-null;} where to write to
      */
     public abstract void writeTo(DexFile file, AnnotatedOutput out);
 }
diff --git a/dx/src/com/android/dx/dex/file/ItemType.java b/dx/src/com/android/dx/dex/file/ItemType.java
index ffa6573..83843b7 100644
--- a/dx/src/com/android/dx/dex/file/ItemType.java
+++ b/dx/src/com/android/dx/dex/file/ItemType.java
@@ -48,17 +48,17 @@
     /** value when represented in a {@link MapItem} */
     private final int mapValue;
 
-    /** non-null; name of the type */
+    /** {@code non-null;} name of the type */
     private final String typeName;
 
-    /** non-null; the short human name */
+    /** {@code non-null;} the short human name */
     private final String humanName;
    
     /**
      * Constructs an instance.
      * 
      * @param mapValue value when represented in a {@link MapItem}
-     * @param typeName non-null; name of the type
+     * @param typeName {@code non-null;} name of the type
      */
     private ItemType(int mapValue, String typeName) {
         this.mapValue = mapValue;
@@ -84,7 +84,7 @@
     /**
      * Gets the type name.
      * 
-     * @return non-null; the type name
+     * @return {@code non-null;} the type name
      */
     public String getTypeName() {
         return typeName;
diff --git a/dx/src/com/android/dx/dex/file/MapItem.java b/dx/src/com/android/dx/dex/file/MapItem.java
index 5e7465c..c728dd7 100644
--- a/dx/src/com/android/dx/dex/file/MapItem.java
+++ b/dx/src/com/android/dx/dex/file/MapItem.java
@@ -28,29 +28,29 @@
     /** file alignment of this class, in bytes */
     private static final int ALIGNMENT = 4;
 
-    /** write size of this class, in bytes: three <code>uint</code>s */
+    /** write size of this class, in bytes: three {@code uint}s */
     private static final int WRITE_SIZE = (4 * 3);
 
-    /** non-null; item type this instance covers */
+    /** {@code non-null;} item type this instance covers */
     private final ItemType type;
 
-    /** non-null; section this instance covers */
+    /** {@code non-null;} section this instance covers */
     private final Section section;
 
     /**
-     * null-ok; first item covered or <code>null</code> if this is
+     * {@code null-ok;} first item covered or {@code null} if this is
      * a self-reference
      */
     private final Item firstItem;
 
     /**
-     * null-ok; last item covered or <code>null</code> if this is
+     * {@code null-ok;} last item covered or {@code null} if this is
      * a self-reference
      */
     private final Item lastItem;
 
     /**
-     * &gt; 0; count of items covered; <code>1</code> if this
+     * {@code > 0;} count of items covered; {@code 1} if this
      * is a self-reference
      */
     private final int itemCount;
@@ -60,8 +60,8 @@
      * the contents of the given array of sections, adding it to the
      * given map section.
      *
-     * @param sections non-null; the sections
-     * @param mapSection non-null; the section that the resulting map
+     * @param sections {@code non-null;} the sections
+     * @param mapSection {@code non-null;} the section that the resulting map
      * should be added to; it should be empty on entry to this method
      */
     public static void addMap(Section[] sections,
@@ -115,11 +115,11 @@
     /**
      * Constructs an instance.
      * 
-     * @param type non-null; item type this instance covers
-     * @param section non-null; section this instance covers
-     * @param firstItem non-null; first item covered
-     * @param lastItem non-null; last item covered
-     * @param itemCount &gt; 0; count of items covered
+     * @param type {@code non-null;} item type this instance covers
+     * @param section {@code non-null;} section this instance covers
+     * @param firstItem {@code non-null;} first item covered
+     * @param lastItem {@code non-null;} last item covered
+     * @param itemCount {@code > 0;} count of items covered
      */
     private MapItem(ItemType type, Section section, Item firstItem,
             Item lastItem, int itemCount) {
@@ -154,9 +154,9 @@
 
     /**
      * Constructs a self-referential instance. This instance is meant to
-     * represent the section containing the <code>map_list</code>.
+     * represent the section containing the {@code map_list}.
      * 
-     * @param section non-null; section this instance covers
+     * @param section {@code non-null;} section this instance covers
      */
     private MapItem(Section section) {
         super(ALIGNMENT, WRITE_SIZE);
diff --git a/dx/src/com/android/dx/dex/file/MemberIdItem.java b/dx/src/com/android/dx/dex/file/MemberIdItem.java
index d437152..574d413 100644
--- a/dx/src/com/android/dx/dex/file/MemberIdItem.java
+++ b/dx/src/com/android/dx/dex/file/MemberIdItem.java
@@ -29,13 +29,13 @@
     /** size of instances when written out to a file, in bytes */
     public static final int WRITE_SIZE = 8;
 
-    /** non-null; the constant for the member */
+    /** {@code non-null;} the constant for the member */
     private final CstMemberRef cst;
 
     /**
      * Constructs an instance.
      * 
-     * @param cst non-null; the constant for the member
+     * @param cst {@code non-null;} the constant for the member
      */
     public MemberIdItem(CstMemberRef cst) {
         super(cst.getDefiningClass());
@@ -86,7 +86,7 @@
      * this item, in order that it may be written out. Subclasses must
      * override this to get whatever it is they need to store.
      * 
-     * @param file non-null; the file being written
+     * @param file {@code non-null;} the file being written
      * @return the index in question
      */
     protected abstract int getTypoidIdx(DexFile file);
@@ -96,14 +96,14 @@
      * this item, for listing-generating purposes. Subclasses must override
      * this.
      * 
-     * @return non-null; the name in question
+     * @return {@code non-null;} the name in question
      */
     protected abstract String getTypoidName();
 
     /**
      * Gets the member constant.
      * 
-     * @return non-null; the constant
+     * @return {@code non-null;} the constant
      */
     public final CstMemberRef getRef() {
         return cst;
diff --git a/dx/src/com/android/dx/dex/file/MemberIdsSection.java b/dx/src/com/android/dx/dex/file/MemberIdsSection.java
index 885b559..20b1605 100644
--- a/dx/src/com/android/dx/dex/file/MemberIdsSection.java
+++ b/dx/src/com/android/dx/dex/file/MemberIdsSection.java
@@ -17,15 +17,15 @@
 package com.android.dx.dex.file;
 
 /**
- * Member (field or method) refs list section of a <code>.dex</code> file.
+ * Member (field or method) refs list section of a {@code .dex} file.
  */
 public abstract class MemberIdsSection extends UniformItemSection {
     /**
      * Constructs an instance. The file offset is initially unknown.
      * 
-     * @param name null-ok; the name of this instance, for annotation
+     * @param name {@code null-ok;} the name of this instance, for annotation
      * purposes
-     * @param file non-null; file that this instance is part of
+     * @param file {@code non-null;} file that this instance is part of
      */
     public MemberIdsSection(String name, DexFile file) {
         super(name, file, 4);
diff --git a/dx/src/com/android/dx/dex/file/MethodAnnotationStruct.java b/dx/src/com/android/dx/dex/file/MethodAnnotationStruct.java
index 175c1d2..3c254a1 100644
--- a/dx/src/com/android/dx/dex/file/MethodAnnotationStruct.java
+++ b/dx/src/com/android/dx/dex/file/MethodAnnotationStruct.java
@@ -27,17 +27,17 @@
  */
 public final class MethodAnnotationStruct
         implements ToHuman, Comparable<MethodAnnotationStruct> {
-    /** non-null; the method in question */
+    /** {@code non-null;} the method in question */
     private final CstMethodRef method;
 
-    /** non-null; the associated annotations */
+    /** {@code non-null;} the associated annotations */
     private AnnotationSetItem annotations;
 
     /**
      * Constructs an instance.
      * 
-     * @param method non-null; the method in question
-     * @param annotations non-null; the associated annotations
+     * @param method {@code non-null;} the method in question
+     * @param annotations {@code non-null;} the associated annotations
      */
     public MethodAnnotationStruct(CstMethodRef method,
             AnnotationSetItem annotations) {
@@ -105,7 +105,7 @@
     /**
      * Gets the method this item is for.
      * 
-     * @return non-null; the method
+     * @return {@code non-null;} the method
      */
     public CstMethodRef getMethod() {
         return method;
@@ -114,7 +114,7 @@
     /**
      * Gets the associated annotations.
      * 
-     * @return non-null; the annotations
+     * @return {@code non-null;} the annotations
      */
     public Annotations getAnnotations() {
         return annotations.getAnnotations();
diff --git a/dx/src/com/android/dx/dex/file/MethodIdItem.java b/dx/src/com/android/dx/dex/file/MethodIdItem.java
index 5d78e96..bbd6c93 100644
--- a/dx/src/com/android/dx/dex/file/MethodIdItem.java
+++ b/dx/src/com/android/dx/dex/file/MethodIdItem.java
@@ -25,7 +25,7 @@
     /**
      * Constructs an instance.
      * 
-     * @param method non-null; the constant for the method
+     * @param method {@code non-null;} the constant for the method
      */
     public MethodIdItem(CstBaseMethodRef method) {
         super(method);
@@ -49,7 +49,7 @@
     /**
      * Gets the method constant.
      * 
-     * @return non-null; the constant
+     * @return {@code non-null;} the constant
      */
     public CstBaseMethodRef getMethodRef() {
         return (CstBaseMethodRef) getRef();
diff --git a/dx/src/com/android/dx/dex/file/MethodIdsSection.java b/dx/src/com/android/dx/dex/file/MethodIdsSection.java
index 6ba7cac..f3e7dee 100644
--- a/dx/src/com/android/dx/dex/file/MethodIdsSection.java
+++ b/dx/src/com/android/dx/dex/file/MethodIdsSection.java
@@ -25,11 +25,11 @@
 import java.util.TreeMap;
 
 /**
- * Method refs list section of a <code>.dex</code> file.
+ * Method refs list section of a {@code .dex} file.
  */
 public final class MethodIdsSection extends MemberIdsSection {
     /**
-     * non-null; map from method constants to {@link
+     * {@code non-null;} map from method constants to {@link
      * MethodIdItem} instances 
      */
     private final TreeMap<CstBaseMethodRef, MethodIdItem> methodIds;
@@ -37,7 +37,7 @@
     /**
      * Constructs an instance. The file offset is initially unknown.
      * 
-     * @param file non-null; file that this instance is part of
+     * @param file {@code non-null;} file that this instance is part of
      */
     public MethodIdsSection(DexFile file) {
         super("method_ids", file);
@@ -72,7 +72,7 @@
     /**
      * Writes the portion of the file header that refers to this instance.
      * 
-     * @param out non-null; where to write
+     * @param out {@code non-null;} where to write
      */
     public void writeHeaderPart(AnnotatedOutput out) {
         throwIfNotPrepared();
@@ -92,8 +92,8 @@
     /**
      * Interns an element into this instance.
      * 
-     * @param method non-null; the reference to intern
-     * @return non-null; the interned reference
+     * @param method {@code non-null;} the reference to intern
+     * @return {@code non-null;} the interned reference
      */
     public MethodIdItem intern(CstBaseMethodRef method) {
         if (method == null) {
@@ -116,8 +116,8 @@
      * Gets the index of the given reference, which must have been added
      * to this instance.
      * 
-     * @param ref non-null; the reference to look up
-     * @return &gt;= 0; the reference's index
+     * @param ref {@code non-null;} the reference to look up
+     * @return {@code >= 0;} the reference's index
      */
     public int indexOf(CstBaseMethodRef ref) {
         if (ref == null) {
diff --git a/dx/src/com/android/dx/dex/file/MixedItemSection.java b/dx/src/com/android/dx/dex/file/MixedItemSection.java
index f03a9a3..0929fe7 100644
--- a/dx/src/com/android/dx/dex/file/MixedItemSection.java
+++ b/dx/src/com/android/dx/dex/file/MixedItemSection.java
@@ -31,7 +31,7 @@
 import java.util.TreeMap;
 
 /**
- * A section of a <code>.dex</code> file which consists of a sequence of
+ * A section of a {@code .dex} file which consists of a sequence of
  * {@link OffsettedItem} objects, which may each be of a different concrete
  * class and/or size.
  * 
@@ -50,7 +50,7 @@
         INSTANCE;
     };
 
-    /** non-null; sorter which sorts instances by type */
+    /** {@code non-null;} sorter which sorts instances by type */
     private static final Comparator<OffsettedItem> TYPE_SORTER =
         new Comparator<OffsettedItem>() {
         public int compare(OffsettedItem item1, OffsettedItem item2) {
@@ -60,17 +60,17 @@
         }
     };
     
-    /** non-null; the items in this part */
+    /** {@code non-null;} the items in this part */
     private final ArrayList<OffsettedItem> items;
 
-    /** non-null; items that have been explicitly interned */
+    /** {@code non-null;} items that have been explicitly interned */
     private final HashMap<OffsettedItem, OffsettedItem> interns;
 
-    /** non-null; how to sort the items */
+    /** {@code non-null;} how to sort the items */
     private final SortType sort;
 
     /**
-     * &gt;= -1; the current size of this part, in bytes, or <code>-1</code>
+     * {@code >= -1;} the current size of this part, in bytes, or {@code -1}
      * if not yet calculated
      */
     private int writeSize;
@@ -78,10 +78,10 @@
     /**
      * Constructs an instance. The file offset is initially unknown.
      * 
-     * @param name null-ok; the name of this instance, for annotation
+     * @param name {@code null-ok;} the name of this instance, for annotation
      * purposes
-     * @param file non-null; file that this instance is part of
-     * @param alignment &gt; 0; alignment requirement for the final output;
+     * @param file {@code non-null;} file that this instance is part of
+     * @param alignment {@code > 0;} alignment requirement for the final output;
      * must be a power of 2
      * @param sort how the items should be sorted in the final output
      */
@@ -118,7 +118,7 @@
     /**
      * Gets the size of this instance, in items.
      * 
-     * @return &gt;= 0; the size
+     * @return {@code >= 0;} the size
      */
     public int size() {
         return items.size();
@@ -127,7 +127,7 @@
     /**
      * Writes the portion of the file header that refers to this instance.
      *
-     * @param out non-null; where to write
+     * @param out {@code non-null;} where to write
      */
     public void writeHeaderPart(AnnotatedOutput out) {
         throwIfNotPrepared();
@@ -164,7 +164,7 @@
      * same item to more than one instance, nor to add the same items
      * multiple times to a single instance.
      * 
-     * @param item non-null; the item to add
+     * @param item {@code non-null;} the item to add
      */
     public void add(OffsettedItem item) {
         throwIfPrepared();
@@ -187,8 +187,8 @@
      * (which may not be the one passed in). This will add the item if no
      * equal item has been added.
      * 
-     * @param item non-null; the item to intern
-     * @return non-null; the equivalent interned instance
+     * @param item {@code non-null;} the item to intern
+     * @return {@code non-null;} the equivalent interned instance
      */
     public <T extends OffsettedItem> T intern(T item) {
         throwIfPrepared();
@@ -207,8 +207,8 @@
     /**
      * Gets an item which was previously interned.
      * 
-     * @param item non-null; the item to look for
-     * @return non-null; the equivalent already-interned instance
+     * @param item {@code non-null;} the item to look for
+     * @return {@code non-null;} the equivalent already-interned instance
      */
     public <T extends OffsettedItem> T get(T item) {
         throwIfNotPrepared();
@@ -227,9 +227,9 @@
      * given type. If there are none, this writes nothing. If there are any,
      * then the index is preceded by the given intro string.
      * 
-     * @param out non-null; where to write to
-     * @param itemType non-null; the item type of interest
-     * @param intro non-null; the introductory string for non-empty indices
+     * @param out {@code non-null;} where to write to
+     * @param itemType {@code non-null;} the item type of interest
+     * @param intro {@code non-null;} the introductory string for non-empty indices
      */
     public void writeIndexAnnotation(AnnotatedOutput out, ItemType itemType,
             String intro) {
@@ -285,7 +285,7 @@
     /**
      * Places all the items in this instance at particular offsets. This
      * will call {@link OffsettedItem#place} on each item. If an item
-     * does not know its write size before the call to <code>place</code>,
+     * does not know its write size before the call to {@code place},
      * it is that call which is responsible for setting the write size.
      * This method may only be called once per instance; subsequent calls
      * will throw an exception.
diff --git a/dx/src/com/android/dx/dex/file/OffsettedItem.java b/dx/src/com/android/dx/dex/file/OffsettedItem.java
index 030c370..c8e2d74 100644
--- a/dx/src/com/android/dx/dex/file/OffsettedItem.java
+++ b/dx/src/com/android/dx/dex/file/OffsettedItem.java
@@ -24,32 +24,32 @@
  */
 public abstract class OffsettedItem extends Item
         implements Comparable<OffsettedItem> {
-    /** &gt; 0; alignment requirement */
+    /** {@code > 0;} alignment requirement */
     private final int alignment;
 
-    /** &gt;= -1; the size of this instance when written, in bytes, or
-     * <code>-1</code> if not yet known */
+    /** {@code >= -1;} the size of this instance when written, in bytes, or
+     * {@code -1} if not yet known */
     private int writeSize;
 
     /**
-     * null-ok; section the item was added to, or <code>null</code> if
+     * {@code null-ok;} section the item was added to, or {@code null} if
      * not yet added 
      */
     private Section addedTo;
 
     /**
-     * &gt;= -1; assigned offset of the item from the start of its section,
-     * or <code>-1</code> if not yet assigned 
+     * {@code >= -1;} assigned offset of the item from the start of its section,
+     * or {@code -1} if not yet assigned 
      */
     private int offset;
 
     /**
-     * Gets the absolute offset of the given item, returning <code>0</code>
-     * if handed <code>null</code>.
+     * Gets the absolute offset of the given item, returning {@code 0}
+     * if handed {@code null}.
      * 
-     * @param item null-ok; the item in question
-     * @return &gt;= 0; the item's absolute offset, or <code>0</code>
-     * if <code>item == null</code>
+     * @param item {@code null-ok;} the item in question
+     * @return {@code >= 0;} the item's absolute offset, or {@code 0}
+     * if {@code item == null}
      */
     public static int getAbsoluteOffsetOr0(OffsettedItem item) {
         if (item == null) {
@@ -62,10 +62,10 @@
     /**
      * Constructs an instance. The offset is initially unassigned.
      * 
-     * @param alignment &gt; 0; output alignment requirement; must be a
+     * @param alignment {@code > 0;} output alignment requirement; must be a
      * power of 2
-     * @param writeSize &gt;= -1; the size of this instance when written,
-     * in bytes, or <code>-1</code> if not immediately known
+     * @param writeSize {@code >= -1;} the size of this instance when written,
+     * in bytes, or {@code -1} if not immediately known
      */
     public OffsettedItem(int alignment, int writeSize) {
         Section.validateAlignment(alignment);
@@ -131,7 +131,7 @@
      * per instance, and only if the size was unknown upon instance
      * creation.
      * 
-     * @param writeSize &gt; 0; the write size, in bytes
+     * @param writeSize {@code > 0;} the write size, in bytes
      */
     public final void setWriteSize(int writeSize) {
         if (writeSize < 0) {
@@ -182,7 +182,7 @@
      * Gets the relative item offset. The offset is from the start of
      * the section which the instance was written to.
      * 
-     * @return &gt;= 0; the offset
+     * @return {@code >= 0;} the offset
      * @throws RuntimeException thrown if the offset is not yet known
      */
     public final int getRelativeOffset() {
@@ -197,7 +197,7 @@
      * Gets the absolute item offset. The offset is from the start of
      * the file which the instance was written to.
      * 
-     * @return &gt;= 0; the offset
+     * @return {@code >= 0;} the offset
      * @throws RuntimeException thrown if the offset is not yet known
      */
     public final int getAbsoluteOffset() {
@@ -213,10 +213,11 @@
      * the given offset. It is only valid to call this method once per
      * instance.
      * 
-     * @param addedTo non-null; the section this instance has been added to
-     * @param offset &gt;= 0; the desired offset from the start of the
+     * @param addedTo {@code non-null;} the section this instance has
+     * been added to
+     * @param offset {@code >= 0;} the desired offset from the start of the
      * section where this instance was placed
-     * @return &gt;= 0; the offset that this instance should be placed at
+     * @return {@code >= 0;} the offset that this instance should be placed at
      * in order to meet its alignment constraint
      */
     public final int place(Section addedTo, int offset) {
@@ -247,7 +248,7 @@
      * Gets the alignment requirement of this instance. An instance should
      * only be written when so aligned.
      * 
-     * @return &gt; 0; the alignment requirement; must be a power of 2
+     * @return {@code > 0;} the alignment requirement; must be a power of 2
      */
     public final int getAlignment() {
         return alignment;
@@ -257,7 +258,7 @@
      * Gets the absolute offset of this item as a string, suitable for
      * including in annotations.
      * 
-     * @return non-null; the offset string
+     * @return {@code non-null;} the offset string
      */
     public final String offsetString() {
         return '[' + Integer.toHexString(getAbsoluteOffset()) + ']';
@@ -266,7 +267,7 @@
     /**
      * Gets a short human-readable string representing this instance.
      * 
-     * @return non-null; the human form
+     * @return {@code non-null;} the human form
      */
     public abstract String toHuman();
 
@@ -277,8 +278,8 @@
      * class needs to actually sort, then it should override this
      * method.
      * 
-     * @param other non-null; instance to compare to
-     * @return <code>-1</code>, <code>0</code>, or <code>1</code>, depending
+     * @param other {@code non-null;} instance to compare to
+     * @return {@code -1}, {@code 0}, or {@code 1}, depending
      * on the sort order of this instance and the other
      */
     protected int compareTo0(OffsettedItem other) {
@@ -293,8 +294,8 @@
      * know its write size up-front, then this method is responsible
      * for setting it.
      * 
-     * @param addedTo non-null; the section this instance has been added to
-     * @param offset &gt;= 0; the offset from the start of the
+     * @param addedTo {@code non-null;} the section this instance has been added to
+     * @param offset {@code >= 0;} the offset from the start of the
      * section where this instance was placed
      */
     protected void place0(Section addedTo, int offset) {
@@ -306,8 +307,8 @@
      * the given data section. This is called by {@link #writeTo},
      * which will have taken care of ensuring alignment.
      * 
-     * @param file non-null; the file to use for reference
-     * @param out non-null; where to write to
+     * @param file {@code non-null;} the file to use for reference
+     * @param out {@code non-null;} where to write to
      */
     protected abstract void writeTo0(DexFile file, AnnotatedOutput out);
 }
diff --git a/dx/src/com/android/dx/dex/file/ParameterAnnotationStruct.java b/dx/src/com/android/dx/dex/file/ParameterAnnotationStruct.java
index 0c2d286..46d0450 100644
--- a/dx/src/com/android/dx/dex/file/ParameterAnnotationStruct.java
+++ b/dx/src/com/android/dx/dex/file/ParameterAnnotationStruct.java
@@ -30,20 +30,20 @@
  */
 public final class ParameterAnnotationStruct
         implements ToHuman, Comparable<ParameterAnnotationStruct> {
-    /** non-null; the method in question */
+    /** {@code non-null;} the method in question */
     private final CstMethodRef method;
 
-    /** non-null; the associated annotations list */
+    /** {@code non-null;} the associated annotations list */
     private final AnnotationsList annotationsList;
 
-    /** non-null; the associated annotations list, as an item */
+    /** {@code non-null;} the associated annotations list, as an item */
     private final UniformListItem<AnnotationSetRefItem> annotationsItem;
 
     /**
      * Constructs an instance.
      * 
-     * @param method non-null; the method in question
-     * @param annotationsList non-null; the associated annotations list
+     * @param method {@code non-null;} the method in question
+     * @param annotationsList {@code non-null;} the associated annotations list
      */
     public ParameterAnnotationStruct(CstMethodRef method,
             AnnotationsList annotationsList) {
@@ -144,7 +144,7 @@
     /**
      * Gets the method this item is for.
      * 
-     * @return non-null; the method
+     * @return {@code non-null;} the method
      */
     public CstMethodRef getMethod() {
         return method;
@@ -153,7 +153,7 @@
     /**
      * Gets the associated annotations list.
      * 
-     * @return non-null; the annotations list
+     * @return {@code non-null;} the annotations list
      */
     public AnnotationsList getAnnotationsList() {
         return annotationsList;
diff --git a/dx/src/com/android/dx/dex/file/ProtoIdItem.java b/dx/src/com/android/dx/dex/file/ProtoIdItem.java
index a144c30..afc227c 100644
--- a/dx/src/com/android/dx/dex/file/ProtoIdItem.java
+++ b/dx/src/com/android/dx/dex/file/ProtoIdItem.java
@@ -31,14 +31,14 @@
     /** size of instances when written out to a file, in bytes */
     public static final int WRITE_SIZE = 12;
 
-    /** non-null; the wrapped prototype */
+    /** {@code non-null;} the wrapped prototype */
     private final Prototype prototype;
 
-    /** non-null; the short-form of the prototype */
+    /** {@code non-null;} the short-form of the prototype */
     private final CstUtf8 shortForm;
 
     /**
-     * null-ok; the list of parameter types or <code>null</code> if this
+     * {@code null-ok;} the list of parameter types or {@code null} if this
      * prototype has no parameters
      */
     private TypeListItem parameterTypes;
@@ -46,7 +46,7 @@
     /**
      * Constructs an instance.
      * 
-     * @param prototype non-null; the constant for the prototype
+     * @param prototype {@code non-null;} the constant for the prototype
      */
     public ProtoIdItem(Prototype prototype) {
         if (prototype == null) {
@@ -64,8 +64,8 @@
     /**
      * Creates the short-form of the given prototype.
      * 
-     * @param prototype non-null; the prototype
-     * @return non-null; the short form
+     * @param prototype {@code non-null;} the prototype
+     * @return {@code non-null;} the short form
      */
     private static CstUtf8 makeShortForm(Prototype prototype) {
         StdTypeList parameters = prototype.getParameterTypes();
@@ -84,7 +84,7 @@
     /**
      * Gets the short-form character for the given type.
      * 
-     * @param type non-null; the type
+     * @param type {@code non-null;} the type
      * @return the corresponding short-form character
      */
     private static char shortFormCharFor(Type type) {
diff --git a/dx/src/com/android/dx/dex/file/ProtoIdsSection.java b/dx/src/com/android/dx/dex/file/ProtoIdsSection.java
index 852ab9d..8a95434 100644
--- a/dx/src/com/android/dx/dex/file/ProtoIdsSection.java
+++ b/dx/src/com/android/dx/dex/file/ProtoIdsSection.java
@@ -26,18 +26,18 @@
 
 /**
  * Proto (method prototype) identifiers list section of a
- * <code>.dex</code> file.
+ * {@code .dex} file.
  */
 public final class ProtoIdsSection extends UniformItemSection {
     /**
-     * non-null; map from method prototypes to {@link ProtoIdItem} instances
+     * {@code non-null;} map from method prototypes to {@link ProtoIdItem} instances
      */
     private final TreeMap<Prototype, ProtoIdItem> protoIds;
 
     /**
      * Constructs an instance. The file offset is initially unknown.
      * 
-     * @param file non-null; file that this instance is part of
+     * @param file {@code non-null;} file that this instance is part of
      */
     public ProtoIdsSection(DexFile file) {
         super("proto_ids", file, 4);
@@ -60,7 +60,7 @@
     /**
      * Writes the portion of the file header that refers to this instance.
      * 
-     * @param out non-null; where to write
+     * @param out {@code non-null;} where to write
      */
     public void writeHeaderPart(AnnotatedOutput out) {
         throwIfNotPrepared();
@@ -84,8 +84,8 @@
     /**
      * Interns an element into this instance.
      * 
-     * @param prototype non-null; the prototype to intern
-     * @return non-null; the interned reference
+     * @param prototype {@code non-null;} the prototype to intern
+     * @return {@code non-null;} the interned reference
      */
     public ProtoIdItem intern(Prototype prototype) {
         if (prototype == null) {
@@ -108,8 +108,8 @@
      * Gets the index of the given prototype, which must have
      * been added to this instance.
      * 
-     * @param prototype non-null; the prototype to look up
-     * @return &gt;= 0; the reference's index
+     * @param prototype {@code non-null;} the prototype to look up
+     * @return {@code >= 0;} the reference's index
      */
     public int indexOf(Prototype prototype) {
         if (prototype == null) {
diff --git a/dx/src/com/android/dx/dex/file/Section.java b/dx/src/com/android/dx/dex/file/Section.java
index 9f7657c..f5b43af 100644
--- a/dx/src/com/android/dx/dex/file/Section.java
+++ b/dx/src/com/android/dx/dex/file/Section.java
@@ -21,22 +21,22 @@
 import java.util.Collection;
 
 /**
- * A section of a <code>.dex</code> file. Each section consists of a list
+ * A section of a {@code .dex} file. Each section consists of a list
  * of items of some sort or other.
  */
 public abstract class Section {
-    /** null-ok; name of this part, for annotation purposes */
+    /** {@code null-ok;} name of this part, for annotation purposes */
     private final String name;
 
-    /** non-null; file that this instance is part of */
+    /** {@code non-null;} file that this instance is part of */
     private final DexFile file;
 
-    /** &gt; 0; alignment requirement for the final output;
+    /** {@code > 0;} alignment requirement for the final output;
      * must be a power of 2 */
     private final int alignment;
 
-    /** &gt;= -1; offset from the start of the file to this part, or
-     * <code>-1</code> if not yet known */
+    /** {@code >= -1;} offset from the start of the file to this part, or
+     * {@code -1} if not yet known */
     private int fileOffset;
 
     /** whether {@link #prepare} has been called successfully on this
@@ -47,7 +47,7 @@
      * Validates an alignment.
      * 
      * @param alignment the alignment
-     * @throws IllegalArgumentException thrown if <code>alignment</code>
+     * @throws IllegalArgumentException thrown if {@code alignment}
      * isn't a positive power of 2
      */
     public static void validateAlignment(int alignment) {
@@ -60,10 +60,10 @@
     /**
      * Constructs an instance. The file offset is initially unknown.
      *
-     * @param name null-ok; the name of this instance, for annotation
+     * @param name {@code null-ok;} the name of this instance, for annotation
      * purposes
-     * @param file non-null; file that this instance is part of
-     * @param alignment &gt; 0; alignment requirement for the final output;
+     * @param file {@code non-null;} file that this instance is part of
+     * @param alignment {@code > 0;} alignment requirement for the final output;
      * must be a power of 2
      */
     public Section(String name, DexFile file, int alignment) {
@@ -83,7 +83,7 @@
     /**
      * Gets the file that this instance is part of.
      *
-     * @return non-null; the file
+     * @return {@code non-null;} the file
      */
     public final DexFile getFile() {
         return file;
@@ -92,7 +92,7 @@
     /** 
      * Gets the alignment for this instance's final output.
      * 
-     * @return &gt; 0; the alignment
+     * @return {@code > 0;} the alignment
      */
     public final int getAlignment() {
         return alignment;
@@ -102,7 +102,7 @@
      * Gets the offset from the start of the file to this part. This
      * throws an exception if the offset has not yet been set.
      *
-     * @return &gt;= 0; the file offset
+     * @return {@code >= 0;} the file offset
      */
     public final int getFileOffset() {
         if (fileOffset < 0) {
@@ -116,9 +116,9 @@
      * Sets the file offset. It is only valid to call this method once
      * once per instance.
      *
-     * @param fileOffset &gt;= 0; the desired offset from the start of the
+     * @param fileOffset {@code >= 0;} the desired offset from the start of the
      * file where this for this instance
-     * @return &gt;= 0; the offset that this instance should be placed at
+     * @return {@code >= 0;} the offset that this instance should be placed at
      * in order to meet its alignment constraint
      */
     public final int setFileOffset(int fileOffset) {
@@ -141,7 +141,7 @@
     /**
      * Writes this instance to the given raw data object.
      *
-     * @param out non-null; where to write to
+     * @param out {@code non-null;} where to write to
      */
     public final void writeTo(AnnotatedOutput out) {
         throwIfNotPrepared();        
@@ -174,8 +174,8 @@
      * once this instance has been assigned a file offset (via {@link
      * #setFileOffset}).
      * 
-     * @param relative &gt;= 0; the relative offset
-     * @return &gt;= 0; the corresponding absolute file offset
+     * @param relative {@code >= 0;} the relative offset
+     * @return {@code >= 0;} the corresponding absolute file offset
      */
     public final int getAbsoluteOffset(int relative) {
         if (relative < 0) {
@@ -198,8 +198,8 @@
      * <p><b>Note:</b> Subclasses must implement this as appropriate for
      * their contents.</p>
      * 
-     * @param item non-null; the item in question
-     * @return &gt;= 0; the item's absolute file offset
+     * @param item {@code non-null;} the item in question
+     * @return {@code >= 0;} the item's absolute file offset
      */
     public abstract int getAbsoluteItemOffset(Item item);
 
@@ -219,7 +219,7 @@
      * Gets the collection of all the items in this section.
      * It is not valid to attempt to change the returned list.
      *
-     * @return non-null; the items
+     * @return {@code non-null;} the items
      */
     public abstract Collection<? extends Item> items();
 
@@ -231,7 +231,7 @@
     /**
      * Gets the size of this instance when output, in bytes.
      *
-     * @return &gt;= 0; the size of this instance, in bytes
+     * @return {@code >= 0;} the size of this instance, in bytes
      */
     public abstract int writeSize();
 
@@ -258,7 +258,7 @@
     /**
      * Aligns the output of the given data to the alignment of this instance.
      * 
-     * @param out non-null; the output to align
+     * @param out {@code non-null;} the output to align
      */
     protected final void align(AnnotatedOutput out) {
         out.alignTo(alignment);
@@ -267,19 +267,19 @@
     /**
      * Writes this instance to the given raw data object. This gets
      * called by {@link #writeTo} after aligning the cursor of
-     * <code>out</code> and verifying that either the assigned file
-     * offset matches the actual cursor <code>out</code> or that the
+     * {@code out} and verifying that either the assigned file
+     * offset matches the actual cursor {@code out} or that the
      * file offset was not previously assigned, in which case it gets
-     * assigned to <code>out</code>'s cursor.
+     * assigned to {@code out}'s cursor.
      * 
-     * @param out non-null; where to write to
+     * @param out {@code non-null;} where to write to
      */
     protected abstract void writeTo0(AnnotatedOutput out);
 
     /**
      * Returns the name of this section, for annotation purposes.
      * 
-     * @return null-ok; name of this part, for annotation purposes
+     * @return {@code null-ok;} name of this part, for annotation purposes
      */
     protected final String getName() {
         return name;
diff --git a/dx/src/com/android/dx/dex/file/Statistics.java b/dx/src/com/android/dx/dex/file/Statistics.java
index b11ab6e..9a2efb3 100644
--- a/dx/src/com/android/dx/dex/file/Statistics.java
+++ b/dx/src/com/android/dx/dex/file/Statistics.java
@@ -26,7 +26,7 @@
  * Statistics about the contents of a file.
  */
 public final class Statistics {
-    /** non-null; data about each type of item */
+    /** {@code non-null;} data about each type of item */
     private final HashMap<String, Data> dataMap;
 
     /**
@@ -39,7 +39,7 @@
     /**
      * Adds the given item to the statistics.
      * 
-     * @param item non-null; the item to add
+     * @param item {@code non-null;} the item to add
      */
     public void add(Item item) {
         String typeName = item.typeName();
@@ -55,7 +55,7 @@
     /**
      * Adds the given list of items to the statistics.
      * 
-     * @param list non-null; the list of items to add
+     * @param list {@code non-null;} the list of items to add
      */
     public void addAll(Section list) {
         Collection<? extends Item> items = list.items();
@@ -67,7 +67,7 @@
     /**
      * Writes the statistics as an annotation.
      * 
-     * @param out non-null; where to write to
+     * @param out {@code non-null;} where to write to
      */
     public final void writeAnnotation(AnnotatedOutput out) {
         if (dataMap.size() == 0) {
@@ -109,26 +109,26 @@
      * Statistical data about a particular class.
      */
     private static class Data {
-        /** non-null; name to use as a label */
+        /** {@code non-null;} name to use as a label */
         private final String name;
 
-        /** &gt;= 0; number of instances */
+        /** {@code >= 0;} number of instances */
         private int count;
 
-        /** &gt;= 0; total size of instances in bytes */
+        /** {@code >= 0;} total size of instances in bytes */
         private int totalSize;
 
-        /** &gt;= 0; largest size of any individual item */
+        /** {@code >= 0;} largest size of any individual item */
         private int largestSize;
 
-        /** &gt;= 0; smallest size of any individual item */
+        /** {@code >= 0;} smallest size of any individual item */
         private int smallestSize;
 
         /**
          * Constructs an instance for the given item.
          * 
-         * @param item non-null; item in question
-         * @param name non-null; type name to use
+         * @param item {@code non-null;} item in question
+         * @param name {@code non-null;} type name to use
          */
         public Data(Item item, String name) {
             int size = item.writeSize();
@@ -143,7 +143,7 @@
         /**
          * Incorporates a new item. This assumes the type name matches.
          * 
-         * @param item non-null; item to incorporate
+         * @param item {@code non-null;} item to incorporate
          */
         public void add(Item item) {
             int size = item.writeSize();
@@ -163,7 +163,7 @@
         /**
          * Writes this instance as an annotation.
          * 
-         * @param out non-null; where to write to
+         * @param out {@code non-null;} where to write to
          */
         public void writeAnnotation(AnnotatedOutput out) {
             out.annotate(toHuman());
diff --git a/dx/src/com/android/dx/dex/file/StringDataItem.java b/dx/src/com/android/dx/dex/file/StringDataItem.java
index 49eea57..b9eeb9b 100644
--- a/dx/src/com/android/dx/dex/file/StringDataItem.java
+++ b/dx/src/com/android/dx/dex/file/StringDataItem.java
@@ -26,13 +26,13 @@
  * Representation of string data for a particular string, in a Dalvik file.
  */
 public final class StringDataItem extends OffsettedItem {
-    /** non-null; the string value */
+    /** {@code non-null;} the string value */
     private final CstUtf8 value;
 
     /**
      * Constructs an instance.
      * 
-     * @param value non-null; the string value
+     * @param value {@code non-null;} the string value
      */
     public StringDataItem(CstUtf8 value) {
         super(1, writeSize(value));
@@ -43,8 +43,8 @@
     /**
      * Gets the write size for a given value.
      * 
-     * @param value non-null; the string value
-     * @return &gt;= 2 the write size, in bytes
+     * @param value {@code non-null;} the string value
+     * @return {@code >= 2}; the write size, in bytes
      */
     private static int writeSize(CstUtf8 value) {
         int utf16Size = value.getUtf16Size();
diff --git a/dx/src/com/android/dx/dex/file/StringIdItem.java b/dx/src/com/android/dx/dex/file/StringIdItem.java
index e80a7f8..401a0be 100644
--- a/dx/src/com/android/dx/dex/file/StringIdItem.java
+++ b/dx/src/com/android/dx/dex/file/StringIdItem.java
@@ -28,16 +28,16 @@
     /** size of instances when written out to a file, in bytes */
     public static final int WRITE_SIZE = 4;
 
-    /** non-null; the string value */
+    /** {@code non-null;} the string value */
     private final CstUtf8 value;
 
-    /** null-ok; associated string data object, if known */
+    /** {@code null-ok;} associated string data object, if known */
     private StringDataItem data;
 
     /**
      * Constructs an instance.
      * 
-     * @param value non-null; the string value
+     * @param value {@code non-null;} the string value
      */
     public StringIdItem(CstUtf8 value) {
         if (value == null) {
@@ -110,7 +110,7 @@
     /**
      * Gets the string value.
      * 
-     * @return non-null; the value
+     * @return {@code non-null;} the value
      */
     public CstUtf8 getValue() {
         return value;
@@ -119,7 +119,7 @@
     /**
      * Gets the associated data object for this instance, if known.
      * 
-     * @return null-ok; the associated data object or <code>null</code>
+     * @return {@code null-ok;} the associated data object or {@code null}
      * if not yet known
      */
     public StringDataItem getData() {
diff --git a/dx/src/com/android/dx/dex/file/StringIdsSection.java b/dx/src/com/android/dx/dex/file/StringIdsSection.java
index 17fbb57..b2e8683 100644
--- a/dx/src/com/android/dx/dex/file/StringIdsSection.java
+++ b/dx/src/com/android/dx/dex/file/StringIdsSection.java
@@ -27,12 +27,12 @@
 import java.util.TreeMap;
 
 /**
- * Strings list section of a <code>.dex</code> file.
+ * Strings list section of a {@code .dex} file.
  */
 public final class StringIdsSection
         extends UniformItemSection {
     /**
-     * non-null; map from string constants to {@link
+     * {@code non-null;} map from string constants to {@link
      * StringIdItem} instances 
      */
     private final TreeMap<CstUtf8, StringIdItem> strings;
@@ -40,7 +40,7 @@
     /**
      * Constructs an instance. The file offset is initially unknown.
      * 
-     * @param file non-null; file that this instance is part of
+     * @param file {@code non-null;} file that this instance is part of
      */
     public StringIdsSection(DexFile file) {
         super("string_ids", file, 4);
@@ -79,7 +79,7 @@
     /**
      * Writes the portion of the file header that refers to this instance.
      * 
-     * @param out non-null; where to write
+     * @param out {@code non-null;} where to write
      */
     public void writeHeaderPart(AnnotatedOutput out) {
         throwIfNotPrepared();
@@ -99,9 +99,9 @@
     /**
      * Interns an element into this instance.
      * 
-     * @param string non-null; the string to intern, as a regular Java
-     * <code>String</code>
-     * @return non-null; the interned string
+     * @param string {@code non-null;} the string to intern, as a regular Java
+     * {@code String}
+     * @return {@code non-null;} the interned string
      */
     public StringIdItem intern(String string) {
         CstUtf8 utf8 = new CstUtf8(string);
@@ -111,8 +111,8 @@
     /**
      * Interns an element into this instance.
      * 
-     * @param string non-null; the string to intern, as a {@link CstString}
-     * @return non-null; the interned string
+     * @param string {@code non-null;} the string to intern, as a {@link CstString}
+     * @return {@code non-null;} the interned string
      */
     public StringIdItem intern(CstString string) {
         CstUtf8 utf8 = string.getString();
@@ -122,8 +122,8 @@
     /**
      * Interns an element into this instance.
      * 
-     * @param string non-null; the string to intern, as a constant
-     * @return non-null; the interned string
+     * @param string {@code non-null;} the string to intern, as a constant
+     * @return {@code non-null;} the interned string
      */
     public StringIdItem intern(CstUtf8 string) {
         return intern(new StringIdItem(string));
@@ -132,8 +132,8 @@
     /**
      * Interns an element into this instance.
      * 
-     * @param string non-null; the string to intern
-     * @return non-null; the interned string
+     * @param string {@code non-null;} the string to intern
+     * @return {@code non-null;} the interned string
      */
     public StringIdItem intern(StringIdItem string) {
         if (string == null) {
@@ -156,7 +156,7 @@
     /**
      * Interns the components of a name-and-type into this instance.
      * 
-     * @param nat non-null; the name-and-type
+     * @param nat {@code non-null;} the name-and-type
      */
     public void intern(CstNat nat) {
         intern(nat.getName());
@@ -167,8 +167,8 @@
      * Gets the index of the given string, which must have been added
      * to this instance.
      * 
-     * @param string non-null; the string to look up
-     * @return &gt;= 0; the string's index
+     * @param string {@code non-null;} the string to look up
+     * @return {@code >= 0;} the string's index
      */
     public int indexOf(CstUtf8 string) {
         if (string == null) {
@@ -190,8 +190,8 @@
      * Gets the index of the given string, which must have been added
      * to this instance.
      * 
-     * @param string non-null; the string to look up
-     * @return &gt;= 0; the string's index
+     * @param string {@code non-null;} the string to look up
+     * @return {@code >= 0;} the string's index
      */
     public int indexOf(CstString string) {
         return indexOf(string.getString());
diff --git a/dx/src/com/android/dx/dex/file/TypeIdItem.java b/dx/src/com/android/dx/dex/file/TypeIdItem.java
index f3402e6..01b1417 100644
--- a/dx/src/com/android/dx/dex/file/TypeIdItem.java
+++ b/dx/src/com/android/dx/dex/file/TypeIdItem.java
@@ -31,7 +31,7 @@
     /**
      * Constructs an instance.
      * 
-     * @param type non-null; the constant for the type
+     * @param type {@code non-null;} the constant for the type
      */
     public TypeIdItem(CstType type) {
         super(type);
diff --git a/dx/src/com/android/dx/dex/file/TypeIdsSection.java b/dx/src/com/android/dx/dex/file/TypeIdsSection.java
index 296263f..b1b9c58 100644
--- a/dx/src/com/android/dx/dex/file/TypeIdsSection.java
+++ b/dx/src/com/android/dx/dex/file/TypeIdsSection.java
@@ -26,18 +26,18 @@
 import java.util.TreeMap;
 
 /**
- * Type identifiers list section of a <code>.dex</code> file.
+ * Type identifiers list section of a {@code .dex} file.
  */
 public final class TypeIdsSection extends UniformItemSection {
     /**
-     * non-null; map from types to {@link TypeIdItem} instances
+     * {@code non-null;} map from types to {@link TypeIdItem} instances
      */
     private final TreeMap<Type, TypeIdItem> typeIds;
 
     /**
      * Constructs an instance. The file offset is initially unknown.
      * 
-     * @param file non-null; file that this instance is part of
+     * @param file {@code non-null;} file that this instance is part of
      */
     public TypeIdsSection(DexFile file) {
         super("type_ids", file, 4);
@@ -73,7 +73,7 @@
     /**
      * Writes the portion of the file header that refers to this instance.
      * 
-     * @param out non-null; where to write
+     * @param out {@code non-null;} where to write
      */
     public void writeHeaderPart(AnnotatedOutput out) {
         throwIfNotPrepared();
@@ -97,8 +97,8 @@
     /**
      * Interns an element into this instance.
      * 
-     * @param type non-null; the type to intern
-     * @return non-null; the interned reference
+     * @param type {@code non-null;} the type to intern
+     * @return {@code non-null;} the interned reference
      */
     public TypeIdItem intern(Type type) {
         if (type == null) {
@@ -120,8 +120,8 @@
     /**
      * Interns an element into this instance.
      * 
-     * @param type non-null; the type to intern
-     * @return non-null; the interned reference
+     * @param type {@code non-null;} the type to intern
+     * @return {@code non-null;} the interned reference
      */
     public TypeIdItem intern(CstType type) {
         if (type == null) {
@@ -145,8 +145,8 @@
      * Gets the index of the given type, which must have
      * been added to this instance.
      * 
-     * @param type non-null; the type to look up
-     * @return &gt;= 0; the reference's index
+     * @param type {@code non-null;} the type to look up
+     * @return {@code >= 0;} the reference's index
      */
     public int indexOf(Type type) {
         if (type == null) {
@@ -168,8 +168,8 @@
      * Gets the index of the given type, which must have
      * been added to this instance.
      * 
-     * @param type non-null; the type to look up
-     * @return &gt;= 0; the reference's index
+     * @param type {@code non-null;} the type to look up
+     * @return {@code >= 0;} the reference's index
      */
     public int indexOf(CstType type) {
         if (type == null) {
diff --git a/dx/src/com/android/dx/dex/file/TypeListItem.java b/dx/src/com/android/dx/dex/file/TypeListItem.java
index 6557ca4..3278aef 100644
--- a/dx/src/com/android/dx/dex/file/TypeListItem.java
+++ b/dx/src/com/android/dx/dex/file/TypeListItem.java
@@ -36,13 +36,13 @@
     /** header size in bytes */
     private static final int HEADER_SIZE = 4;
 
-    /** non-null; the actual list */
+    /** {@code non-null;} the actual list */
     private final TypeList list;
 
     /**
      * Constructs an instance.
      * 
-     * @param list non-null; the actual list
+     * @param list {@code non-null;} the actual list
      */
     public TypeListItem(TypeList list) {
         super(ALIGNMENT, (list.size() * ELEMENT_SIZE) + HEADER_SIZE);
@@ -81,7 +81,7 @@
     /**
      * Gets the underlying list.
      * 
-     * @return non-null; the list
+     * @return {@code non-null;} the list
      */
     public TypeList getList() {
         return list;
diff --git a/dx/src/com/android/dx/dex/file/UniformItemSection.java b/dx/src/com/android/dx/dex/file/UniformItemSection.java
index 602bc2d..e182438 100644
--- a/dx/src/com/android/dx/dex/file/UniformItemSection.java
+++ b/dx/src/com/android/dx/dex/file/UniformItemSection.java
@@ -22,7 +22,7 @@
 import java.util.Collection;
 
 /**
- * A section of a <code>.dex</code> file which consists of a sequence of
+ * A section of a {@code .dex} file which consists of a sequence of
  * {@link Item} objects. Each of the items must have the same size in
  * the output.
  */
@@ -30,10 +30,10 @@
     /**
      * Constructs an instance. The file offset is initially unknown.
      * 
-     * @param name null-ok; the name of this instance, for annotation
+     * @param name {@code null-ok;} the name of this instance, for annotation
      * purposes
-     * @param file non-null; file that this instance is part of
-     * @param alignment &gt; 0; alignment requirement for the final output;
+     * @param file {@code non-null;} file that this instance is part of
+     * @param alignment {@code > 0;} alignment requirement for the final output;
      * must be a power of 2
      */
     public UniformItemSection(String name, DexFile file, int alignment) {
@@ -60,8 +60,8 @@
      * if this instance isn't the sort that maps constants to {@link
      * IndexedItem} instances.
      * 
-     * @param cst non-null; constant to look for
-     * @return non-null; the corresponding item found in this instance
+     * @param cst {@code non-null;} constant to look for
+     * @return {@code non-null;} the corresponding item found in this instance
      */
     public abstract IndexedItem get(Constant cst);
 
diff --git a/dx/src/com/android/dx/dex/file/UniformListItem.java b/dx/src/com/android/dx/dex/file/UniformListItem.java
index 3af3942..3c1f4d3 100644
--- a/dx/src/com/android/dx/dex/file/UniformListItem.java
+++ b/dx/src/com/android/dx/dex/file/UniformListItem.java
@@ -28,8 +28,8 @@
  * alignment.
  * 
  * <p>This class inherits its alignment from its items, bumped up to
- * <code>4</code> if the items have a looser alignment requirement. If
- * it is more than <code>4</code>, then there will be a gap after the
+ * {@code 4} if the items have a looser alignment requirement. If
+ * it is more than {@code 4}, then there will be a gap after the
  * output list size (which is four bytes) and before the first item.</p>
  * 
  * @param <T> type of element contained in an instance
@@ -39,18 +39,18 @@
     /** the size of the list header */
     private static final int HEADER_SIZE = 4;
 
-    /** non-null; the item type */
+    /** {@code non-null;} the item type */
     private final ItemType itemType;
     
-    /** non-null; the contents */
+    /** {@code non-null;} the contents */
     private final List<T> items;
 
     /**
      * Constructs an instance. It is illegal to modify the given list once
      * it is used to construct an instance of this class.
      * 
-     * @param itemType non-null; the type of the item
-     * @param items non-null and non-empty; list of items to represent
+     * @param itemType {@code non-null;} the type of the item
+     * @param items {@code non-null and non-empty;} list of items to represent
      */
     public UniformListItem(ItemType itemType, List<T> items) {
         super(getAlignment(items), writeSize(items));
@@ -68,8 +68,8 @@
      * requirement implied by the given list. See the header comment for
      * more details.
      * 
-     * @param items non-null; list of items being represented
-     * @return &gt;= 4; the alignment requirement
+     * @param items {@code non-null;} list of items being represented
+     * @return {@code >= 4;} the alignment requirement
      */
     private static int getAlignment(List<? extends OffsettedItem> items) {
         try {
@@ -87,8 +87,8 @@
     /**
      * Calculates the write size for the given list.
      * 
-     * @param items non-null; the list in question
-     * @return &gt;= 0; the write size
+     * @param items {@code non-null;} the list in question
+     * @return {@code >= 0;} the write size
      */
     private static int writeSize(List<? extends OffsettedItem> items) {
         /*
@@ -148,7 +148,7 @@
     /**
      * Gets the underlying list of items.
      * 
-     * @return non-null; the list
+     * @return {@code non-null;} the list
      */
     public final List<T> getItems() {
         return items;
@@ -204,7 +204,7 @@
     /**
      * Get the size of the header of this list.
      * 
-     * @return &gt;= 0; the header size
+     * @return {@code >= 0;} the header size
      */
     private int headerSize() {
         /*
diff --git a/dx/src/com/android/dx/dex/file/ValueEncoder.java b/dx/src/com/android/dx/dex/file/ValueEncoder.java
index 02a3419..f7e364a 100644
--- a/dx/src/com/android/dx/dex/file/ValueEncoder.java
+++ b/dx/src/com/android/dx/dex/file/ValueEncoder.java
@@ -43,69 +43,69 @@
 import java.util.Collection;
 
 /**
- * Handler for writing out <code>encoded_values</code> and parts
+ * Handler for writing out {@code encoded_values} and parts
  * thereof.
  */
 public final class ValueEncoder {
-    /** annotation value type constant: <code>byte</code> */
+    /** annotation value type constant: {@code byte} */
     private static final int VALUE_BYTE = 0x00;
 
-    /** annotation value type constant: <code>short</code> */
+    /** annotation value type constant: {@code short} */
     private static final int VALUE_SHORT = 0x02;
 
-    /** annotation value type constant: <code>char</code> */
+    /** annotation value type constant: {@code char} */
     private static final int VALUE_CHAR = 0x03;
 
-    /** annotation value type constant: <code>int</code> */
+    /** annotation value type constant: {@code int} */
     private static final int VALUE_INT = 0x04;
 
-    /** annotation value type constant: <code>long</code> */
+    /** annotation value type constant: {@code long} */
     private static final int VALUE_LONG = 0x06;
 
-    /** annotation value type constant: <code>float</code> */
+    /** annotation value type constant: {@code float} */
     private static final int VALUE_FLOAT = 0x10;
 
-    /** annotation value type constant: <code>double</code> */
+    /** annotation value type constant: {@code double} */
     private static final int VALUE_DOUBLE = 0x11;
 
-    /** annotation value type constant: <code>string</code> */
+    /** annotation value type constant: {@code string} */
     private static final int VALUE_STRING = 0x17;
 
-    /** annotation value type constant: <code>type</code> */
+    /** annotation value type constant: {@code type} */
     private static final int VALUE_TYPE = 0x18;
 
-    /** annotation value type constant: <code>field</code> */
+    /** annotation value type constant: {@code field} */
     private static final int VALUE_FIELD = 0x19;
 
-    /** annotation value type constant: <code>method</code> */
+    /** annotation value type constant: {@code method} */
     private static final int VALUE_METHOD = 0x1a;
 
-    /** annotation value type constant: <code>enum</code> */
+    /** annotation value type constant: {@code enum} */
     private static final int VALUE_ENUM = 0x1b;
 
-    /** annotation value type constant: <code>array</code> */
+    /** annotation value type constant: {@code array} */
     private static final int VALUE_ARRAY = 0x1c;
 
-    /** annotation value type constant: <code>annotation</code> */
+    /** annotation value type constant: {@code annotation} */
     private static final int VALUE_ANNOTATION = 0x1d;
 
-    /** annotation value type constant: <code>null</code> */
+    /** annotation value type constant: {@code null} */
     private static final int VALUE_NULL = 0x1e;
 
-    /** annotation value type constant: <code>boolean</code> */
+    /** annotation value type constant: {@code boolean} */
     private static final int VALUE_BOOLEAN = 0x1f;
 
-    /** non-null; file being written */
+    /** {@code non-null;} file being written */
     private final DexFile file;
 
-    /** non-null; output stream to write to */
+    /** {@code non-null;} output stream to write to */
     private final AnnotatedOutput out;
     
     /**
      * Construct an instance.
      * 
-     * @param file non-null; file being written
-     * @param out non-null; output stream to write to
+     * @param file {@code non-null;} file being written
+     * @param out {@code non-null;} output stream to write to
      */
     public ValueEncoder(DexFile file, AnnotatedOutput out) {
         if (file == null) {
@@ -123,7 +123,7 @@
     /**
      * Writes out the encoded form of the given constant.
      * 
-     * @param cst non-null; the constant to write
+     * @param cst {@code non-null;} the constant to write
      */
     public void writeConstant(Constant cst) {
         int type = constantToValueType(cst);
@@ -209,8 +209,8 @@
     /**
      * Gets the value type for the given constant.
      * 
-     * @param cst non-null; the constant
-     * @return the value type; one of the <code>VALUE_*</code> constants
+     * @param cst {@code non-null;} the constant
+     * @return the value type; one of the {@code VALUE_*} constants
      * defined by this class
      */
     private static int constantToValueType(Constant cst) {
@@ -257,15 +257,15 @@
 
     /**
      * Writes out the encoded form of the given array, that is, as
-     * an <code>encoded_array</code> and not including a
-     * <code>value_type</code> prefix. If the output stream keeps
-     * (debugging) annotations and <code>topLevel</code> is
-     * <code>true</code>, then this method will write (debugging)
+     * an {@code encoded_array} and not including a
+     * {@code value_type} prefix. If the output stream keeps
+     * (debugging) annotations and {@code topLevel} is
+     * {@code true}, then this method will write (debugging)
      * annotations.
      *
-     * @param array non-null; array instance to write
-     * @param topLevel <code>true</code> iff the given annotation is the
-     * top-level annotation or <code>false</code> if it is a sub-annotation
+     * @param array {@code non-null;} array instance to write
+     * @param topLevel {@code true} iff the given annotation is the
+     * top-level annotation or {@code false} if it is a sub-annotation
      * of some other annotation
      */
     public void writeArray(CstArray array, boolean topLevel) {
@@ -295,15 +295,15 @@
 
     /**
      * Writes out the encoded form of the given annotation, that is,
-     * as an <code>encoded_annotation</code> and not including a
-     * <code>value_type</code> prefix. If the output stream keeps
-     * (debugging) annotations and <code>topLevel</code> is
-     * <code>true</code>, then this method will write (debugging)
+     * as an {@code encoded_annotation} and not including a
+     * {@code value_type} prefix. If the output stream keeps
+     * (debugging) annotations and {@code topLevel} is
+     * {@code true}, then this method will write (debugging)
      * annotations.
      * 
-     * @param annotation non-null; annotation instance to write
-     * @param topLevel <code>true</code> iff the given annotation is the
-     * top-level annotation or <code>false</code> if it is a sub-annotation
+     * @param annotation {@code non-null;} annotation instance to write
+     * @param topLevel {@code true} iff the given annotation is the
+     * top-level annotation or {@code false} if it is a sub-annotation
      * of some other annotation
      */
     public void writeAnnotation(Annotation annotation, boolean topLevel) {
@@ -361,8 +361,8 @@
      * Gets the colloquial type name and human form of the type of the
      * given constant, when used as an encoded value.
      * 
-     * @param cst non-null; the constant
-     * @return non-null; its type name and human form
+     * @param cst {@code non-null;} the constant
+     * @return {@code non-null;} its type name and human form
      */
     public static String constantToHuman(Constant cst) {
         int type = constantToValueType(cst);
@@ -385,7 +385,7 @@
      * for any signed integral type.
      * 
      * @param type the type constant
-     * @param value <code>long</code> bits of the value
+     * @param value {@code long} bits of the value
      */
     private void writeSignedIntegralValue(int type, long value) {
         /*
@@ -422,7 +422,7 @@
      * for any unsigned integral type.
      * 
      * @param type the type constant
-     * @param value <code>long</code> bits of the value
+     * @param value {@code long} bits of the value
      */
     private void writeUnsignedIntegralValue(int type, long value) {
         // Figure out how many bits are needed to represent the value.
@@ -453,7 +453,7 @@
      * right-zero-extended value.
      * 
      * @param type the type constant
-     * @param value <code>long</code> bits of the value
+     * @param value {@code long} bits of the value
      */
     private void writeRightZeroExtendedValue(int type, long value) {
         // Figure out how many bits are needed to represent the value.
@@ -484,12 +484,12 @@
 
 
     /**
-     * Helper for <code>addContents()</code> methods, which adds
+     * Helper for {@code addContents()} methods, which adds
      * contents for a particular {@link Annotation}, calling itself
      * recursively should it encounter a nested annotation.
      *
-     * @param file non-null; the file to add to 
-     * @param annotation non-null; the annotation to add contents for
+     * @param file {@code non-null;} the file to add to 
+     * @param annotation {@code non-null;} the annotation to add contents for
      */
     public static void addContents(DexFile file, Annotation annotation) {
         TypeIdsSection typeIds = file.getTypeIds();
@@ -504,19 +504,16 @@
     }
 
     /**
-     * Helper for <code>addContents()</code> methods, which adds
+     * Helper for {@code addContents()} methods, which adds
      * contents for a particular constant, calling itself recursively
      * should it encounter a {@link CstArray} and calling {@link
      * #addContents(DexFile,Annotation)} recursively should it
      * encounter a {@link CstAnnotation}.
      * 
-     * @param file non-null; the file to add to 
-     * @param cst non-null; the constant to add contents for
+     * @param file {@code non-null;} the file to add to 
+     * @param cst {@code non-null;} the constant to add contents for
      */
     public static void addContents(DexFile file, Constant cst) {
-        TypeIdsSection typeIds = file.getTypeIds();
-        StringIdsSection stringIds = file.getStringIds();
-
         if (cst instanceof CstAnnotation) {
             addContents(file, ((CstAnnotation) cst).getAnnotation());
         } else if (cst instanceof CstArray) {
diff --git a/dx/src/com/android/dx/rop/annotation/Annotation.java b/dx/src/com/android/dx/rop/annotation/Annotation.java
index b7cf164..6154c61 100644
--- a/dx/src/com/android/dx/rop/annotation/Annotation.java
+++ b/dx/src/com/android/dx/rop/annotation/Annotation.java
@@ -41,20 +41,20 @@
  */
 public final class Annotation extends MutabilityControl 
         implements Comparable<Annotation>, ToHuman {
-    /** non-null; type of the annotation */
+    /** {@code non-null;} type of the annotation */
     private final CstType type;
 
-    /** non-null; the visibility of the annotation */
+    /** {@code non-null;} the visibility of the annotation */
     private final AnnotationVisibility visibility;
 
-    /** non-null; map from names to {@link NameValuePair} instances */
+    /** {@code non-null;} map from names to {@link NameValuePair} instances */
     private final TreeMap<CstUtf8, NameValuePair> elements;
     
     /**
      * Construct an instance. It initially contains no elements.
      * 
-     * @param type non-null; type of the annotation
-     * @param visibility non-null; the visibility of the annotation
+     * @param type {@code non-null;} type of the annotation
+     * @param visibility {@code non-null;} the visibility of the annotation
      */
     public Annotation(CstType type, AnnotationVisibility visibility) {
         if (type == null) {
@@ -165,7 +165,7 @@
     /**
      * Gets the type of this instance.
      * 
-     * @return non-null; the type
+     * @return {@code non-null;} the type
      */
     public CstType getType() {
         return type;
@@ -174,7 +174,7 @@
     /**
      * Gets the visibility of this instance.
      * 
-     * @return non-null; the visibility
+     * @return {@code non-null;} the visibility
      */
     public AnnotationVisibility getVisibility() {
         return visibility;
@@ -185,7 +185,7 @@
      * If there is a preexisting element with the same name, it will be
      * replaced by this method.
      * 
-     * @param pair non-null; the (name, value) pair to place into this instance
+     * @param pair {@code non-null;} the (name, value) pair to place into this instance
      */
     public void put(NameValuePair pair) {
         throwIfImmutable();
@@ -202,7 +202,7 @@
      * It is an error to call this method if there is a preexisting element
      * with the same name.
      * 
-     * @param pair non-null; the (name, value) pair to add to this instance
+     * @param pair {@code non-null;} the (name, value) pair to add to this instance
      */
     public void add(NameValuePair pair) {
         throwIfImmutable();
@@ -224,7 +224,7 @@
      * Gets the set of name-value pairs contained in this instance. The
      * result is always unmodifiable.
      * 
-     * @return non-null; the set of name-value pairs
+     * @return {@code non-null;} the set of name-value pairs
      */
     public Collection<NameValuePair> getNameValuePairs() {
         return Collections.unmodifiableCollection(elements.values());
diff --git a/dx/src/com/android/dx/rop/annotation/AnnotationVisibility.java b/dx/src/com/android/dx/rop/annotation/AnnotationVisibility.java
index c53fcd8..26246bb 100644
--- a/dx/src/com/android/dx/rop/annotation/AnnotationVisibility.java
+++ b/dx/src/com/android/dx/rop/annotation/AnnotationVisibility.java
@@ -27,13 +27,13 @@
     SYSTEM("system"),
     EMBEDDED("embedded");
 
-    /** non-null; the human-oriented string representation */
+    /** {@code non-null;} the human-oriented string representation */
     private final String human;
 
     /**
      * Constructs an instance.
      * 
-     * @param human non-null; the human-oriented string representation
+     * @param human {@code non-null;} the human-oriented string representation
      */
     private AnnotationVisibility(String human) {
         this.human = human;
diff --git a/dx/src/com/android/dx/rop/annotation/Annotations.java b/dx/src/com/android/dx/rop/annotation/Annotations.java
index c1da883..dcb74a1 100644
--- a/dx/src/com/android/dx/rop/annotation/Annotations.java
+++ b/dx/src/com/android/dx/rop/annotation/Annotations.java
@@ -29,14 +29,14 @@
  */
 public final class Annotations extends MutabilityControl 
         implements Comparable<Annotations> {
-    /** non-null; immutable empty instance */
+    /** {@code non-null;} immutable empty instance */
     public static final Annotations EMPTY = new Annotations();
 
     static {
         EMPTY.setImmutable();
     }
     
-    /** non-null; map from types to annotations */
+    /** {@code non-null;} map from types to annotations */
     private final TreeMap<CstType, Annotation> annotations;
 
     /**
@@ -44,9 +44,9 @@
      * two given instances. The two instances must contain disjoint sets
      * of types.
      * 
-     * @param a1 non-null; an instance
-     * @param a2 non-null; the other instance
-     * @return non-null; the combination
+     * @param a1 {@code non-null;} an instance
+     * @param a2 {@code non-null;} the other instance
+     * @return {@code non-null;} the combination
      * @throws IllegalArgumentException thrown if there is a duplicate type
      */
     public static Annotations combine(Annotations a1, Annotations a2) {
@@ -64,9 +64,9 @@
      * given instance with the given additional annotation. The latter's
      * type must not already appear in the former.
      * 
-     * @param annotations non-null; the instance to augment
-     * @param annotation non-null; the additional annotation
-     * @return non-null; the combination
+     * @param annotations {@code non-null;} the instance to augment
+     * @param annotation {@code non-null;} the additional annotation
+     * @return {@code non-null;} the combination
      * @throws IllegalArgumentException thrown if there is a duplicate type
      */
     public static Annotations combine(Annotations annotations,
@@ -152,7 +152,7 @@
     /**
      * Gets the number of elements in this instance.
      * 
-     * @return &gt;= 0; the size
+     * @return {@code >= 0;} the size
      */
     public int size() {
         return annotations.size();
@@ -162,7 +162,7 @@
      * Adds an element to this instance. There must not already be an
      * element of the same type.
      * 
-     * @param annotation non-null; the element to add
+     * @param annotation {@code non-null;} the element to add
      * @throws IllegalArgumentException thrown if there is a duplicate type
      */
     public void add(Annotation annotation) {
@@ -186,7 +186,7 @@
      * Adds all of the elements of the given instance to this one. The
      * instances must not have any duplicate types.
      * 
-     * @param toAdd non-null; the annotations to add
+     * @param toAdd {@code non-null;} the annotations to add
      * @throws IllegalArgumentException thrown if there is a duplicate type
      */
     public void addAll(Annotations toAdd) {
@@ -205,7 +205,7 @@
      * Gets the set of annotations contained in this instance. The
      * result is always unmodifiable.
      * 
-     * @return non-null; the set of annotations
+     * @return {@code non-null;} the set of annotations
      */
     public Collection<Annotation> getAnnotations() {
         return Collections.unmodifiableCollection(annotations.values());
diff --git a/dx/src/com/android/dx/rop/annotation/AnnotationsList.java b/dx/src/com/android/dx/rop/annotation/AnnotationsList.java
index 43a07ba..0f4207b 100644
--- a/dx/src/com/android/dx/rop/annotation/AnnotationsList.java
+++ b/dx/src/com/android/dx/rop/annotation/AnnotationsList.java
@@ -23,7 +23,7 @@
  */
 public final class AnnotationsList
         extends FixedSizeList {
-    /** non-null; immutable empty instance */
+    /** {@code non-null;} immutable empty instance */
     public static final AnnotationsList EMPTY = new AnnotationsList(0);
     
     /**
@@ -32,9 +32,9 @@
      * same number of elements, and each pair of elements must contain
      * disjoint sets of types.
      * 
-     * @param list1 non-null; an instance
-     * @param list2 non-null; the other instance
-     * @return non-null; the combination
+     * @param list1 {@code non-null;} an instance
+     * @param list2 {@code non-null;} the other instance
+     * @return {@code non-null;} the combination
      */
     public static AnnotationsList combine(AnnotationsList list1,
             AnnotationsList list2) {
@@ -57,7 +57,7 @@
     }
 
     /**
-     * Constructs an instance. All indices initially contain <code>null</code>.
+     * Constructs an instance. All indices initially contain {@code null}.
      * 
      * @param size the size of the list
      */
@@ -68,10 +68,10 @@
     /**
      * Gets the element at the given index. It is an error to call
      * this with the index for an element which was never set; if you
-     * do that, this will throw <code>NullPointerException</code>.
+     * do that, this will throw {@code NullPointerException}.
      * 
-     * @param n &gt;= 0, &lt; size(); which index
-     * @return non-null; element at that index
+     * @param n {@code >= 0, < size();} which index
+     * @return {@code non-null;} element at that index
      */
     public Annotations get(int n) {
         return (Annotations) get0(n);
@@ -81,8 +81,8 @@
      * Sets the element at the given index. The given element must be
      * immutable.
      * 
-     * @param n &gt;= 0, &lt; size(); which index
-     * @param a null-ok; the element to set at <code>n</code>
+     * @param n {@code >= 0, < size();} which index
+     * @param a {@code null-ok;} the element to set at {@code n}
      */
     public void set(int n, Annotations a) {
         a.throwIfMutable();
diff --git a/dx/src/com/android/dx/rop/annotation/NameValuePair.java b/dx/src/com/android/dx/rop/annotation/NameValuePair.java
index dadabaa..7137a60 100644
--- a/dx/src/com/android/dx/rop/annotation/NameValuePair.java
+++ b/dx/src/com/android/dx/rop/annotation/NameValuePair.java
@@ -24,17 +24,17 @@
  * A (name, value) pair. These are used as the contents of an annotation.
  */
 public final class NameValuePair implements Comparable<NameValuePair> {
-    /** non-null; the name */
+    /** {@code non-null;} the name */
     private final CstUtf8 name;
 
-    /** non-null; the value */
+    /** {@code non-null;} the value */
     private final Constant value;
     
     /**
      * Construct an instance.
      * 
-     * @param name non-null; the name
-     * @param value non-null; the value
+     * @param name {@code non-null;} the name
+     * @param value {@code non-null;} the value
      */
     public NameValuePair(CstUtf8 name, Constant value) {
         if (name == null) {
@@ -95,7 +95,7 @@
     /**
      * Gets the name.
      * 
-     * @return non-null; the name
+     * @return {@code non-null;} the name
      */
     public CstUtf8 getName() {
         return name;
@@ -104,7 +104,7 @@
     /**
      * Gets the value.
      * 
-     * @return non-null; the valute
+     * @return {@code non-null;} the value
      */
     public Constant getValue() {
         return value;
diff --git a/dx/src/com/android/dx/rop/code/AccessFlags.java b/dx/src/com/android/dx/rop/code/AccessFlags.java
index 265cfa6..b76b610 100644
--- a/dx/src/com/android/dx/rop/code/AccessFlags.java
+++ b/dx/src/com/android/dx/rop/code/AccessFlags.java
@@ -23,8 +23,8 @@
  * related utilities. Although, at the rop layer, flags are generally
  * ignored, this is the layer of communication, and as such, this
  * package is where these definitions belong. The flag definitions are
- * identical to Java access flags, but <code>ACC_SUPER</code> isn't
- * used at all in translated code, and <code>ACC_SYNCHRONIZED</code>
+ * identical to Java access flags, but {@code ACC_SUPER} isn't
+ * used at all in translated code, and {@code ACC_SYNCHRONIZED}
  * is only used in a very limited way.
  */
 public final class AccessFlags {
@@ -44,13 +44,13 @@
     public static final int ACC_FINAL = 0x0010;
 
     /**
-     * synchronized method; only valid in dex files for <code>native</code>
+     * synchronized method; only valid in dex files for {@code native}
      * methods
      */
     public static final int ACC_SYNCHRONIZED = 0x0020;
 
     /**
-     * class with new-style <code>invokespecial</code> for superclass
+     * class with new-style {@code invokespecial} for superclass
      * method access 
      */
     public static final int ACC_SUPER = 0x0020;
@@ -77,7 +77,7 @@
     public static final int ACC_ABSTRACT = 0x0400;
 
     /**
-     * method with strict floating point (<code>strictfp</code>)
+     * method with strict floating point ({@code strictfp})
      * behavior 
      */
     public static final int ACC_STRICT = 0x0800;
@@ -98,7 +98,7 @@
     public static final int ACC_CONSTRUCTOR = 0x10000;
 
     /**
-     * method was declared <code>synchronized</code>; has no effect on
+     * method was declared {@code synchronized}; has no effect on
      * execution (other than inspecting this flag, per se)
      */
     public static final int ACC_DECLARED_SYNCHRONIZED = 0x20000;
@@ -147,7 +147,7 @@
      * as defined on classes (not fields or methods).
      * 
      * @param flags the flags
-     * @return non-null; human-oriented string
+     * @return {@code non-null;} human-oriented string
      */
     public static String classString(int flags) {
         return humanHelper(flags, CLASS_FLAGS, CONV_CLASS);
@@ -158,7 +158,7 @@
      * as defined on inner classes.
      * 
      * @param flags the flags
-     * @return non-null; human-oriented string
+     * @return {@code non-null;} human-oriented string
      */
     public static String innerClassString(int flags) {
         return humanHelper(flags, INNER_CLASS_FLAGS, CONV_CLASS);
@@ -169,7 +169,7 @@
      * as defined on fields (not classes or methods).
      * 
      * @param flags the flags
-     * @return non-null; human-oriented string
+     * @return {@code non-null;} human-oriented string
      */
     public static String fieldString(int flags) {
         return humanHelper(flags, FIELD_FLAGS, CONV_FIELD);
@@ -180,106 +180,106 @@
      * as defined on methods (not classes or fields).
      * 
      * @param flags the flags
-     * @return non-null; human-oriented string
+     * @return {@code non-null;} human-oriented string
      */
     public static String methodString(int flags) {
         return humanHelper(flags, METHOD_FLAGS, CONV_METHOD);
     }
 
     /**
-     * Returns whether the flag <code>ACC_PUBLIC</code> is on in the given
+     * Returns whether the flag {@code ACC_PUBLIC} is on in the given
      * flags.
      * 
      * @param flags the flags to check
-     * @return the value of the <code>ACC_PUBLIC</code> flag
+     * @return the value of the {@code ACC_PUBLIC} flag
      */
     public static boolean isPublic(int flags) {
         return (flags & ACC_PUBLIC) != 0;
     }
 
     /**
-     * Returns whether the flag <code>ACC_PROTECTED</code> is on in the given
+     * Returns whether the flag {@code ACC_PROTECTED} is on in the given
      * flags.
      * 
      * @param flags the flags to check
-     * @return the value of the <code>ACC_PROTECTED</code> flag
+     * @return the value of the {@code ACC_PROTECTED} flag
      */
     public static boolean isProtected(int flags) {
         return (flags & ACC_PROTECTED) != 0;
     }
 
     /**
-     * Returns whether the flag <code>ACC_PRIVATE</code> is on in the given
+     * Returns whether the flag {@code ACC_PRIVATE} is on in the given
      * flags.
      * 
      * @param flags the flags to check
-     * @return the value of the <code>ACC_PRIVATE</code> flag
+     * @return the value of the {@code ACC_PRIVATE} flag
      */
     public static boolean isPrivate(int flags) {
         return (flags & ACC_PRIVATE) != 0;
     }
 
     /**
-     * Returns whether the flag <code>ACC_STATIC</code> is on in the given
+     * Returns whether the flag {@code ACC_STATIC} is on in the given
      * flags.
      * 
      * @param flags the flags to check
-     * @return the value of the <code>ACC_STATIC</code> flag
+     * @return the value of the {@code ACC_STATIC} flag
      */
     public static boolean isStatic(int flags) {
         return (flags & ACC_STATIC) != 0;
     }
     
     /**
-     * Returns whether the flag <code>ACC_SYNCHRONIZED</code> is on in
+     * Returns whether the flag {@code ACC_SYNCHRONIZED} is on in
      * the given flags.
      * 
      * @param flags the flags to check
-     * @return the value of the <code>ACC_SYNCHRONIZED</code> flag
+     * @return the value of the {@code ACC_SYNCHRONIZED} flag
      */
     public static boolean isSynchronized(int flags) {
         return (flags & ACC_SYNCHRONIZED) != 0;
     }
 
     /**
-     * Returns whether the flag <code>ACC_ABSTRACT</code> is on in the given
+     * Returns whether the flag {@code ACC_ABSTRACT} is on in the given
      * flags.
      * 
      * @param flags the flags to check
-     * @return the value of the <code>ACC_ABSTRACT</code> flag
+     * @return the value of the {@code ACC_ABSTRACT} flag
      */
     public static boolean isAbstract(int flags) {
         return (flags & ACC_ABSTRACT) != 0;
     }
 
     /**
-     * Returns whether the flag <code>ACC_NATIVE</code> is on in the given
+     * Returns whether the flag {@code ACC_NATIVE} is on in the given
      * flags.
      * 
      * @param flags the flags to check
-     * @return the value of the <code>ACC_NATIVE</code> flag
+     * @return the value of the {@code ACC_NATIVE} flag
      */
     public static boolean isNative(int flags) {
         return (flags & ACC_NATIVE) != 0;
     }
 
     /**
-     * Returns whether the flag <code>ACC_ANNOTATION</code> is on in the given
+     * Returns whether the flag {@code ACC_ANNOTATION} is on in the given
      * flags.
      * 
      * @param flags the flags to check
-     * @return the value of the <code>ACC_ANNOTATION</code> flag
+     * @return the value of the {@code ACC_ANNOTATION} flag
      */
     public static boolean isAnnotation(int flags) {
         return (flags & ACC_ANNOTATION) != 0;
     }
 
     /**
-     * Returns whether the flag <code>ACC_DECLARED_SYNCHRONIZED</code> is
+     * Returns whether the flag {@code ACC_DECLARED_SYNCHRONIZED} is
      * on in the given flags.
      * 
      * @param flags the flags to check
-     * @return the value of the <code>ACC_DECLARED_SYNCHRONIZED</code> flag
+     * @return the value of the {@code ACC_DECLARED_SYNCHRONIZED} flag
      */
     public static boolean isDeclaredSynchronized(int flags) {
         return (flags & ACC_DECLARED_SYNCHRONIZED) != 0;
@@ -291,8 +291,8 @@
      * 
      * @param flags the defined flags
      * @param mask mask for the "defined" bits
-     * @param what what the flags represent (one of <code>CONV_*</code>)
-     * @return non-null; human-oriented string
+     * @param what what the flags represent (one of {@code CONV_*})
+     * @return {@code non-null;} human-oriented string
      */
     private static String humanHelper(int flags, int mask, int what) {
         StringBuffer sb = new StringBuffer(80);
diff --git a/dx/src/com/android/dx/rop/code/BasicBlock.java b/dx/src/com/android/dx/rop/code/BasicBlock.java
index 66db5aa..7bb2d9b 100644
--- a/dx/src/com/android/dx/rop/code/BasicBlock.java
+++ b/dx/src/com/android/dx/rop/code/BasicBlock.java
@@ -25,34 +25,34 @@
  * Basic block of register-based instructions.
  */
 public final class BasicBlock implements LabeledItem {
-    /** &gt;= 0; target label for this block */
+    /** {@code >= 0;} target label for this block */
     private final int label;
 
-    /** non-null; list of instructions in this block */
+    /** {@code non-null;} list of instructions in this block */
     private final InsnList insns;
 
     /**
-     * non-null; full list of successors that this block may
+     * {@code non-null;} full list of successors that this block may
      * branch to 
      */
     private final IntList successors;
 
     /**
-     * &gt;= -1; the primary / standard-flow / "default" successor, or
-     * <code>-1</code> if this block has no successors (that is, it
+     * {@code >= -1;} the primary / standard-flow / "default" successor, or
+     * {@code -1} if this block has no successors (that is, it
      * exits the function/method) 
      */
     private final int primarySuccessor;
 
     /**
-     * Constructs an instance. The predecessor set is set to <code>null</code>.
+     * Constructs an instance. The predecessor set is set to {@code null}.
      * 
-     * @param label &gt;= 0; target label for this block
-     * @param insns non-null; list of instructions in this block
-     * @param successors non-null; full list of successors that this
+     * @param label {@code >= 0;} target label for this block
+     * @param insns {@code non-null;} list of instructions in this block
+     * @param successors {@code non-null;} full list of successors that this
      * block may branch to
-     * @param primarySuccessor &gt;= -1; the primary / standard-flow /
-     * "default" successor, or <code>-1</code> if this block has no
+     * @param primarySuccessor {@code >= -1;} the primary / standard-flow /
+     * "default" successor, or {@code -1} if this block has no
      * successors (that is, it exits the function/method or is an
      * unconditional throw)
      */
@@ -116,7 +116,7 @@
      * {@inheritDoc}
      * 
      * Instances of this class compare by identity. That is,
-     * <code>x.equals(y)</code> is only true if <code>x == y</code>.
+     * {@code x.equals(y)} is only true if {@code x == y}.
      */
     @Override
     public boolean equals(Object other) {
@@ -137,7 +137,7 @@
     /**
      * Gets the target label of this block.
      * 
-     * @return &gt;= 0; the label
+     * @return {@code >= 0;} the label
      */
     public int getLabel() {
         return label;
@@ -146,7 +146,7 @@
     /**
      * Gets the list of instructions inside this block.
      * 
-     * @return non-null; the instruction list
+     * @return {@code non-null;} the instruction list
      */
     public InsnList getInsns() {
         return insns;
@@ -155,7 +155,7 @@
     /**
      * Gets the list of successors that this block may branch to.
      * 
-     * @return non-null; the successors list
+     * @return {@code non-null;} the successors list
      */
     public IntList getSuccessors() {
         return successors;
@@ -164,7 +164,7 @@
     /**
      * Gets the primary successor of this block.
      * 
-     * @return &gt;= -1; the primary successor, or <code>-1</code> if this
+     * @return {@code >= -1;} the primary successor, or {@code -1} if this
      * block has no successors at all
      */
     public int getPrimarySuccessor() {
@@ -175,7 +175,7 @@
      * Gets the secondary successor of this block. It is only valid to call
      * this method on blocks that have exactly two successors.
      * 
-     * @return &gt;= 0; the secondary successor
+     * @return {@code >= 0;} the secondary successor
      */
     public int getSecondarySuccessor() {
         if (successors.size() != 2) {
@@ -193,9 +193,9 @@
 
     /**
      * Gets the first instruction of this block. This is just a
-     * convenient shorthand for <code>getInsns().get(0)</code>.
+     * convenient shorthand for {@code getInsns().get(0)}.
      * 
-     * @return non-null; the first instruction
+     * @return {@code non-null;} the first instruction
      */
     public Insn getFirstInsn() {
         return insns.get(0);
@@ -203,9 +203,9 @@
 
     /**
      * Gets the last instruction of this block. This is just a
-     * convenient shorthand for <code>getInsns().getLast()</code>.
+     * convenient shorthand for {@code getInsns().getLast()}.
      * 
-     * @return non-null; the last instruction
+     * @return {@code non-null;} the last instruction
      */
     public Insn getLastInsn() {
         return insns.getLast();
@@ -213,9 +213,9 @@
 
     /**
      * Returns whether this block might throw an exception. This is
-     * just a convenient shorthand for <code>getLastInsn().canThrow()</code>.
+     * just a convenient shorthand for {@code getLastInsn().canThrow()}.
      * 
-     * @return <code>true</code> iff this block might throw an
+     * @return {@code true} iff this block might throw an
      * exception
      */
     public boolean canThrow() {
@@ -228,7 +228,7 @@
      * the block to see if it could throw, and if so, whether it in fact
      * has any associated handlers.
      * 
-     * @return <code>true</code> iff this block has any associated
+     * @return {@code true} iff this block has any associated
      * exception handlers
      */
     public boolean hasExceptionHandlers() {
@@ -241,9 +241,9 @@
      * if any. This is just a shorthand for inspecting the last
      * instruction in the block to see if it could throw, and if so,
      * grabbing the catch list out of it. If not, this returns an
-     * empty list (not <code>null</code>).
+     * empty list (not {@code null}).
      *
-     * @return non-null; the exception handler types associated with
+     * @return {@code non-null;} the exception handler types associated with
      * this block
      */
     public TypeList getExceptionHandlerTypes() {
@@ -257,7 +257,7 @@
      * amount.
      * 
      * @param delta the amount to offset register numbers by
-     * @return non-null; an appropriately-constructed instance
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public BasicBlock withRegisterOffset(int delta) {
         return new BasicBlock(label, insns.withRegisterOffset(delta),
diff --git a/dx/src/com/android/dx/rop/code/BasicBlockList.java b/dx/src/com/android/dx/rop/code/BasicBlockList.java
index 6564318..0627425 100644
--- a/dx/src/com/android/dx/rop/code/BasicBlockList.java
+++ b/dx/src/com/android/dx/rop/code/BasicBlockList.java
@@ -27,14 +27,14 @@
  */
 public final class BasicBlockList extends LabeledList {
     /**
-     * &gt;= -1; the count of registers required by this method or
-     * <code>-1</code> if not yet calculated 
+     * {@code >= -1;} the count of registers required by this method or
+     * {@code -1} if not yet calculated 
      */
     private int regCount;
 
     /**
-     * Constructs an instance. All indices initially contain <code>null</code>,
-     * and the first-block label is initially <code>-1</code>.
+     * Constructs an instance. All indices initially contain {@code null},
+     * and the first-block label is initially {@code -1}.
      * 
      * @param size the size of the list
      */
@@ -45,7 +45,7 @@
     }
 
     /**
-     * Constructs a mutable copy for <code>getMutableCopy()</code>.
+     * Constructs a mutable copy for {@code getMutableCopy()}.
      * 
      * @param old block to copy
      */
@@ -58,10 +58,10 @@
     /**
      * Gets the element at the given index. It is an error to call
      * this with the index for an element which was never set; if you
-     * do that, this will throw <code>NullPointerException</code>.
+     * do that, this will throw {@code NullPointerException}.
      * 
-     * @param n &gt;= 0, &lt; size(); which index
-     * @return non-null; element at that index
+     * @param n {@code >= 0, < size();} which index
+     * @return {@code non-null;} element at that index
      */
     public BasicBlock get(int n) {
         return (BasicBlock) get0(n);
@@ -70,8 +70,8 @@
     /**
      * Sets the basic block at the given index.
      * 
-     * @param n &gt;= 0, &lt; size(); which index
-     * @param bb null-ok; the element to set at <code>n</code>
+     * @param n {@code >= 0, < size();} which index
+     * @param bb {@code null-ok;} the element to set at {@code n}
      */
     public void set(int n, BasicBlock bb) {
         super.set(n, bb);
@@ -86,7 +86,7 @@
      * instance's instructions (indirectly through {@link BasicBlock}
      * instances).
      * 
-     * @return &gt;= 0; the register count
+     * @return {@code >= 0;} the register count
      */
     public int getRegCount() {
         if (regCount == -1) {
@@ -102,7 +102,7 @@
      * Gets the total instruction count for this instance. This is the
      * sum of the instruction counts of each block.
      * 
-     * @return &gt;= 0; the total instruction count
+     * @return {@code >= 0;} the total instruction count
      */
     public int getInstructionCount() {
         int sz = size();
@@ -122,7 +122,7 @@
      * Gets the total instruction count for this instance, ignoring
      * mark-local instructions which are not actually emitted.
      *
-     * @return &gt;= 0; the total instruction count
+     * @return {@code >= 0;} the total instruction count
      */
     public int getEffectiveInstructionCount() {
         int sz = size();
@@ -151,8 +151,8 @@
     /**
      * Gets the first block in the list with the given label, if any.
      *
-     * @param label &gt;= 0; the label to look for
-     * @return non-null; the so-labelled block
+     * @param label {@code >= 0;} the label to look for
+     * @return {@code non-null;} the so-labelled block
      * @throws IllegalArgumentException thrown if the label isn't found
      */
     public BasicBlock labelToBlock(int label) {
@@ -169,7 +169,7 @@
     /**
      * Visits each instruction of each block in the list, in order.
      * 
-     * @param visitor non-null; visitor to use
+     * @param visitor {@code non-null;} visitor to use
      */
     public void forEachInsn(Insn.Visitor visitor) {
         int sz = size();
@@ -188,7 +188,7 @@
      * original.
      * 
      * @param delta the amount to offset register numbers by
-     * @return non-null; an appropriately-constructed instance
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public BasicBlockList withRegisterOffset(int delta) {
         int sz = size();
@@ -211,7 +211,7 @@
     /**
      * Returns a mutable copy of this list.
      *
-     * @return non-null; an appropriately-constructed instance
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public BasicBlockList getMutableCopy() {
         return new BasicBlockList(this);
@@ -222,10 +222,10 @@
      * only has one successor, then that is the preferred successor.
      * Otherwise, if the block has a primay successor, then that is
      * the preferred successor. If the block has no successors, then
-     * this returns <code>null</code>.
+     * this returns {@code null}.
      * 
-     * @param block non-null; the block in question
-     * @return null-ok; the preferred successor, if any
+     * @param block {@code non-null;} the block in question
+     * @return {@code null-ok;} the preferred successor, if any
      */
     public BasicBlock preferredSuccessorOf(BasicBlock block) {
         int primarySuccessor = block.getPrimarySuccessor();
@@ -252,9 +252,9 @@
      * Compares the catches of two blocks for equality. This includes
      * both the catch types and target labels.
      * 
-     * @param block1 non-null; one block to compare
-     * @param block2 non-null; the other block to compare
-     * @return <code>true</code> if the two blocks' non-primary successors
+     * @param block1 {@code non-null;} one block to compare
+     * @param block2 {@code non-null;} the other block to compare
+     * @return {@code true} if the two blocks' non-primary successors
      * are identical
      */
     public boolean catchesEqual(BasicBlock block1,
@@ -313,7 +313,7 @@
      */
     private static class RegCountVisitor
             implements Insn.Visitor {
-        /** &gt;= 0; register count in-progress */
+        /** {@code >= 0;} register count in-progress */
         private int regCount;
 
         /**
@@ -326,7 +326,7 @@
         /**
          * Gets the register count.
          * 
-         * @return &gt;= 0; the count
+         * @return {@code >= 0;} the count
          */
         public int getRegCount() {
             return regCount;
@@ -363,9 +363,9 @@
         }
 
         /**
-         * Helper for all the <code>visit*</code> methods.
+         * Helper for all the {@code visit*} methods.
          * 
-         * @param insn non-null; instruction being visited
+         * @param insn {@code non-null;} instruction being visited
          */
         private void visit(Insn insn) {
             RegisterSpec result = insn.getResult();
@@ -385,7 +385,7 @@
         /**
          * Processes the given register spec.
          * 
-         * @param spec non-null; the register spec
+         * @param spec {@code non-null;} the register spec
          */
         private void processReg(RegisterSpec spec) {
             int reg = spec.getNextReg();
diff --git a/dx/src/com/android/dx/rop/code/ConservativeTranslationAdvice.java b/dx/src/com/android/dx/rop/code/ConservativeTranslationAdvice.java
index a9da109..1ecf02c 100644
--- a/dx/src/com/android/dx/rop/code/ConservativeTranslationAdvice.java
+++ b/dx/src/com/android/dx/rop/code/ConservativeTranslationAdvice.java
@@ -18,11 +18,11 @@
 
 /**
  * Implementation of {@link TranslationAdvice} which conservatively answers
- * <code>false</code> to all methods.
+ * {@code false} to all methods.
  */
 public final class ConservativeTranslationAdvice
         implements TranslationAdvice {
-    /** non-null; standard instance of this class */
+    /** {@code non-null;} standard instance of this class */
     public static final ConservativeTranslationAdvice THE_ONE =
         new ConservativeTranslationAdvice();
 
diff --git a/dx/src/com/android/dx/rop/code/CstInsn.java b/dx/src/com/android/dx/rop/code/CstInsn.java
index d1cf523..26df1a9 100644
--- a/dx/src/com/android/dx/rop/code/CstInsn.java
+++ b/dx/src/com/android/dx/rop/code/CstInsn.java
@@ -23,17 +23,17 @@
  */
 public abstract class CstInsn
         extends Insn {
-    /** non-null; the constant */
+    /** {@code non-null;} the constant */
     private final Constant cst;
 
     /**
      * Constructs an instance.
      * 
-     * @param opcode non-null; the opcode
-     * @param position non-null; source position
-     * @param result null-ok; spec for the result, if any
-     * @param sources non-null; specs for all the sources
-     * @param cst non-null; constant
+     * @param opcode {@code non-null;} the opcode
+     * @param position {@code non-null;} source position
+     * @param result {@code null-ok;} spec for the result, if any
+     * @param sources {@code non-null;} specs for all the sources
+     * @param cst {@code non-null;} constant
      */
     public CstInsn(Rop opcode, SourcePosition position, RegisterSpec result,
                    RegisterSpecList sources, Constant cst) {
@@ -55,7 +55,7 @@
     /**
      * Gets the constant.
      * 
-     * @return non-null; the constant
+     * @return {@code non-null;} the constant
      */
     public Constant getConstant() {
         return cst;
diff --git a/dx/src/com/android/dx/rop/code/DexTranslationAdvice.java b/dx/src/com/android/dx/rop/code/DexTranslationAdvice.java
index 1c23824..8dbc00b 100644
--- a/dx/src/com/android/dx/rop/code/DexTranslationAdvice.java
+++ b/dx/src/com/android/dx/rop/code/DexTranslationAdvice.java
@@ -25,7 +25,7 @@
  */
 public final class DexTranslationAdvice
         implements TranslationAdvice {
-    /** non-null; standard instance of this class */
+    /** {@code non-null;} standard instance of this class */
     public static final DexTranslationAdvice THE_ONE =
         new DexTranslationAdvice();
 
@@ -98,8 +98,8 @@
     /**
      * Calculates the total rop width of the list of SSA registers
      *
-     * @param sources non-null; list of SSA registers
-     * @return &gt;= 0 rop-form width in register units
+     * @param sources {@code non-null;} list of SSA registers
+     * @return {@code >= 0;} rop-form width in register units
      */
     private int totalRopWidth(RegisterSpecList sources) {
         int sz = sources.size();
diff --git a/dx/src/com/android/dx/rop/code/Exceptions.java b/dx/src/com/android/dx/rop/code/Exceptions.java
index 3ef4879..f99a760 100644
--- a/dx/src/com/android/dx/rop/code/Exceptions.java
+++ b/dx/src/com/android/dx/rop/code/Exceptions.java
@@ -23,78 +23,78 @@
  * Common exception types.
  */
 public final class Exceptions {
-    /** non-null; the type <code>java.lang.ArithmeticException</code> */
+    /** {@code non-null;} the type {@code java.lang.ArithmeticException} */
     public static final Type TYPE_ArithmeticException =
         Type.intern("Ljava/lang/ArithmeticException;");
 
     /**
-     * non-null; the type
-     * <code>java.lang.ArrayIndexOutOfBoundsException</code> 
+     * {@code non-null;} the type
+     * {@code java.lang.ArrayIndexOutOfBoundsException} 
      */
     public static final Type TYPE_ArrayIndexOutOfBoundsException =
         Type.intern("Ljava/lang/ArrayIndexOutOfBoundsException;");
 
-    /** non-null; the type <code>java.lang.ArrayStoreException</code> */
+    /** {@code non-null;} the type {@code java.lang.ArrayStoreException} */
     public static final Type TYPE_ArrayStoreException =
         Type.intern("Ljava/lang/ArrayStoreException;");
 
-    /** non-null; the type <code>java.lang.ClassCastException</code> */
+    /** {@code non-null;} the type {@code java.lang.ClassCastException} */
     public static final Type TYPE_ClassCastException =
         Type.intern("Ljava/lang/ClassCastException;");
 
-    /** non-null; the type <code>java.lang.Error</code> */
+    /** {@code non-null;} the type {@code java.lang.Error} */
     public static final Type TYPE_Error = Type.intern("Ljava/lang/Error;");
 
     /**
-     * non-null; the type
-     * <code>java.lang.IllegalMonitorStateException</code> 
+     * {@code non-null;} the type
+     * {@code java.lang.IllegalMonitorStateException} 
      */
     public static final Type TYPE_IllegalMonitorStateException =
         Type.intern("Ljava/lang/IllegalMonitorStateException;");
 
-    /** non-null; the type <code>java.lang.NegativeArraySizeException</code> */
+    /** {@code non-null;} the type {@code java.lang.NegativeArraySizeException} */
     public static final Type TYPE_NegativeArraySizeException =
         Type.intern("Ljava/lang/NegativeArraySizeException;");
 
-    /** non-null; the type <code>java.lang.NullPointerException</code> */
+    /** {@code non-null;} the type {@code java.lang.NullPointerException} */
     public static final Type TYPE_NullPointerException =
         Type.intern("Ljava/lang/NullPointerException;");
 
-    /** non-null; the list <code>[java.lang.Error]</code> */
+    /** {@code non-null;} the list {@code [java.lang.Error]} */
     public static final StdTypeList LIST_Error = StdTypeList.make(TYPE_Error);
 
     /**
-     * non-null; the list <code>[java.lang.Error,
-     * java.lang.ArithmeticException]</code> 
+     * {@code non-null;} the list {@code[java.lang.Error,
+     * java.lang.ArithmeticException]}
      */
     public static final StdTypeList LIST_Error_ArithmeticException =
         StdTypeList.make(TYPE_Error, TYPE_ArithmeticException);
 
     /**
-     * non-null; the list <code>[java.lang.Error,
-     * java.lang.ClassCastException]</code> 
+     * {@code non-null;} the list {@code[java.lang.Error,
+     * java.lang.ClassCastException]}
      */
     public static final StdTypeList LIST_Error_ClassCastException =
         StdTypeList.make(TYPE_Error, TYPE_ClassCastException);
 
     /**
-     * non-null; the list <code>[java.lang.Error,
-     * java.lang.NegativeArraySizeException]</code> 
+     * {@code non-null;} the list {@code [java.lang.Error,
+     * java.lang.NegativeArraySizeException]} 
      */
     public static final StdTypeList LIST_Error_NegativeArraySizeException =
         StdTypeList.make(TYPE_Error, TYPE_NegativeArraySizeException);
 
     /**
-     * non-null; the list <code>[java.lang.Error,
-     * java.lang.NullPointerException]</code> 
+     * {@code non-null;} the list {@code [java.lang.Error,
+     * java.lang.NullPointerException]}
      */
     public static final StdTypeList LIST_Error_NullPointerException =
         StdTypeList.make(TYPE_Error, TYPE_NullPointerException);
 
     /**
-     * non-null; the list <code>[java.lang.Error,
+     * {@code non-null;} the list {@code [java.lang.Error,
      * java.lang.NullPointerException,
-     * java.lang.ArrayIndexOutOfBoundsException]</code> 
+     * java.lang.ArrayIndexOutOfBoundsException]}
      */
     public static final StdTypeList LIST_Error_Null_ArrayIndexOutOfBounds =
         StdTypeList.make(TYPE_Error,
@@ -102,10 +102,10 @@
                       TYPE_ArrayIndexOutOfBoundsException);
 
     /**
-     * non-null; the list <code>[java.lang.Error,
+     * {@code non-null;} the list {@code [java.lang.Error,
      * java.lang.NullPointerException,
      * java.lang.ArrayIndexOutOfBoundsException,
-     * java.lang.ArrayStoreException]</code> 
+     * java.lang.ArrayStoreException]}
      */
     public static final StdTypeList LIST_Error_Null_ArrayIndex_ArrayStore =
         StdTypeList.make(TYPE_Error,
@@ -114,9 +114,9 @@
                       TYPE_ArrayStoreException);
 
     /**
-     * non-null; the list <code>[java.lang.Error,
+     * {@code non-null;} the list {@code [java.lang.Error,
      * java.lang.NullPointerException,
-     * java.lang.IllegalMonitorStateException]</code> 
+     * java.lang.IllegalMonitorStateException]}
      */
     public static final StdTypeList
         LIST_Error_Null_IllegalMonitorStateException =
diff --git a/dx/src/com/android/dx/rop/code/FillArrayDataInsn.java b/dx/src/com/android/dx/rop/code/FillArrayDataInsn.java
index 3798afb..0fc7d2b 100644
--- a/dx/src/com/android/dx/rop/code/FillArrayDataInsn.java
+++ b/dx/src/com/android/dx/rop/code/FillArrayDataInsn.java
@@ -42,11 +42,11 @@
     /**
      * Constructs an instance.
      * 
-     * @param opcode non-null; the opcode
-     * @param position non-null; source position
-     * @param sources non-null; specs for all the sources
-     * @param initValues non-null; list of initial values to fill the array
-     * @param cst non-null; type of the new array
+     * @param opcode {@code non-null;} the opcode
+     * @param position {@code non-null;} source position
+     * @param sources {@code non-null;} specs for all the sources
+     * @param initValues {@code non-null;} list of initial values to fill the array
+     * @param cst {@code non-null;} type of the new array
      */
     public FillArrayDataInsn(Rop opcode, SourcePosition position,
                              RegisterSpecList sources,
@@ -71,7 +71,7 @@
 
     /**
      * Return the list of init values
-     * @return non-null; list of init values
+     * @return {@code non-null;} list of init values
      */
     public ArrayList<Constant> getInitValues() {
         return initValues;
@@ -79,7 +79,7 @@
 
     /**
      * Return the type of the newly created array
-     * @return non-null; array type
+     * @return {@code non-null;} array type
      */
     public Constant getConstant() {
         return arrayType;
diff --git a/dx/src/com/android/dx/rop/code/Insn.java b/dx/src/com/android/dx/rop/code/Insn.java
index b1ad0ad..77ab9c0 100644
--- a/dx/src/com/android/dx/rop/code/Insn.java
+++ b/dx/src/com/android/dx/rop/code/Insn.java
@@ -30,25 +30,25 @@
  * information.
  */
 public abstract class Insn implements ToHuman {
-    /** non-null; opcode */
+    /** {@code non-null;} opcode */
     private final Rop opcode;
 
-    /** non-null; source position */
+    /** {@code non-null;} source position */
     private final SourcePosition position;
 
-    /** null-ok; spec for the result of this instruction, if any */
+    /** {@code null-ok;} spec for the result of this instruction, if any */
     private final RegisterSpec result;
 
-    /** non-null; specs for all the sources of this instruction */
+    /** {@code non-null;} specs for all the sources of this instruction */
     private final RegisterSpecList sources;
 
     /**
      * Constructs an instance.
      * 
-     * @param opcode non-null; the opcode
-     * @param position non-null; source position
-     * @param result null-ok; spec for the result, if any
-     * @param sources non-null; specs for all the sources
+     * @param opcode {@code non-null;} the opcode
+     * @param position {@code non-null;} source position
+     * @param result {@code null-ok;} spec for the result, if any
+     * @param sources {@code non-null;} specs for all the sources
      */
     public Insn(Rop opcode, SourcePosition position, RegisterSpec result,
                 RegisterSpecList sources) {
@@ -74,7 +74,7 @@
      * {@inheritDoc}
      * 
      * Instances of this class compare by identity. That is,
-     * <code>x.equals(y)</code> is only true if <code>x == y</code>.
+     * {@code x.equals(y)} is only true if {@code x == y}.
      */
     @Override
     public final boolean equals(Object other) {
@@ -102,7 +102,7 @@
     /**
      * Gets a human-oriented (and slightly lossy) string for this instance.
      * 
-     * @return non-null; the human string form
+     * @return {@code non-null;} the human string form
      */
     public String toHuman() {
         return toHumanWithInline(getInlineString());
@@ -112,7 +112,7 @@
      * Gets an "inline" string portion for toHuman(), if available. This
      * is the portion that appears after the Rop opcode
      * 
-     * @return null-ok; if non-null, the inline text for toHuman()
+     * @return {@code null-ok;} if non-null, the inline text for toHuman()
      */
     public String getInlineString() {
         return null;
@@ -121,7 +121,7 @@
     /**
      * Gets the opcode.
      * 
-     * @return non-null; the opcode
+     * @return {@code non-null;} the opcode
      */
     public final Rop getOpcode() {
         return opcode;
@@ -130,17 +130,17 @@
     /**
      * Gets the source position.
      * 
-     * @return non-null; the source position
+     * @return {@code non-null;} the source position
      */
     public final SourcePosition getPosition() {
         return position;
     }
 
     /**
-     * Gets the result spec, if any. A return value of <code>null</code>
+     * Gets the result spec, if any. A return value of {@code null}
      * means this instruction returns nothing.
      * 
-     * @return null-ok; the result spec, if any
+     * @return {@code null-ok;} the result spec, if any
      */
     public final RegisterSpec getResult() {
         return result;
@@ -149,10 +149,10 @@
     /**
      * Gets the spec of a local variable assignment that occurs at this
      * instruction, or null if no local variable assignment occurs. This
-     * may be the result register, or for <code>mark-local</code> insns
+     * may be the result register, or for {@code mark-local} insns
      * it may be the source.
      * 
-     * @return null-ok; a named register spec or null
+     * @return {@code null-ok;} a named register spec or null
      */
     public final RegisterSpec getLocalAssignment() {
         RegisterSpec assignment;
@@ -178,7 +178,7 @@
     /**
      * Gets the source specs.
      * 
-     * @return non-null; the source specs
+     * @return {@code non-null;} the source specs
      */
     public final RegisterSpecList getSources() {
         return sources;
@@ -186,9 +186,9 @@
 
     /**
      * Gets whether this instruction can possibly throw an exception. This
-     * is just a convenient wrapper for <code>getOpcode().canThrow()</code>.
+     * is just a convenient wrapper for {@code getOpcode().canThrow()}.
      * 
-     * @return <code>true</code> iff this instruction can possibly throw
+     * @return {@code true} iff this instruction can possibly throw
      */
     public final boolean canThrow() {
         return opcode.canThrow();
@@ -202,7 +202,7 @@
      * exceptions. To determine whether this instruction can throw,
      * use {@link #canThrow}.
      * 
-     * @return non-null; the catches list
+     * @return {@code non-null;} the catches list
      */
     public abstract TypeList getCatches();
 
@@ -210,7 +210,7 @@
      * Calls the appropriate method on the given visitor, depending on the
      * class of this instance. Subclasses must override this.
      * 
-     * @param visitor non-null; the visitor to call on
+     * @param visitor {@code non-null;} the visitor to call on
      */
     public abstract void accept(Visitor visitor);
 
@@ -221,8 +221,8 @@
      * throw. To determine whether this instruction can throw, use
      * {@link #canThrow}.
      * 
-     * @param type non-null; type to append to the catch list
-     * @return non-null; an appropriately-constructed instance
+     * @param type {@code non-null;} type to append to the catch list
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public abstract Insn withAddedCatch(Type type);
 
@@ -231,7 +231,7 @@
      * register references have been offset by the given delta.
      * 
      * @param delta the amount to offset register references by
-     * @return non-null; an appropriately-constructed instance
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public abstract Insn withRegisterOffset(int delta);
 
@@ -239,10 +239,10 @@
      * Returns an instance that is just like this one, except that, if
      * possible, the insn is converted into a version in which the last
      * source (if it is a constant) is represented directly rather than
-     * as a register reference. <code>this</code> is returned in cases where
+     * as a register reference. {@code this} is returned in cases where
      * the translation is not possible.
      * 
-     * @return non-null; an appropriately-constructed instance
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public Insn withLastSourceLiteral() {
         return this;
@@ -251,7 +251,7 @@
     /**
      * Returns an exact copy of this Insn
      *
-     * @return non-null; an appropriately-constructed instance
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public Insn copy() {
         return withRegisterOffset(0);
@@ -270,8 +270,8 @@
     }
 
     /**
-     * Compares Insn contents, since <code>Insn.equals()</code> is defined
-     * to be an identity compare. Insn's are <code>contentEquals()</code>
+     * Compares Insn contents, since {@code Insn.equals()} is defined
+     * to be an identity compare. Insn's are {@code contentEquals()}
      * if they have the same opcode, registers, source position, and other
      * metadata.
      * 
@@ -290,9 +290,9 @@
      * Returns an instance that is just like this one, except
      * with new result and source registers.
      *
-     * @param result null-ok; new result register
-     * @param sources non-null; new sources registers
-     * @return non-null; an appropriately-constructed instance
+     * @param result {@code null-ok;} new result register
+     * @param sources {@code non-null;} new sources registers
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public abstract Insn withNewRegisters(RegisterSpec result,
             RegisterSpecList sources);
@@ -301,8 +301,8 @@
      * Returns the string form of this instance, with the given bit added in
      * the standard location for an inline argument.
      * 
-     * @param extra null-ok; the inline argument string
-     * @return non-null; the string form
+     * @param extra {@code null-ok;} the inline argument string
+     * @return {@code non-null;} the string form
      */
     protected final String toStringWithInline(String extra) {
         StringBuffer sb = new StringBuffer(80);
@@ -334,8 +334,8 @@
      * Returns the human string form of this instance, with the given
      * bit added in the standard location for an inline argument.
      * 
-     * @param extra null-ok; the inline argument string
-     * @return non-null; the human string form
+     * @param extra {@code null-ok;} the inline argument string
+     * @return {@code non-null;} the human string form
      */
     protected final String toHumanWithInline(String extra) {
         StringBuffer sb = new StringBuffer(80);
@@ -380,42 +380,42 @@
         /**
          * Visits a {@link PlainInsn}.
          * 
-         * @param insn non-null; the instruction to visit
+         * @param insn {@code non-null;} the instruction to visit
          */
         public void visitPlainInsn(PlainInsn insn);
 
         /**
          * Visits a {@link PlainCstInsn}.
          * 
-         * @param insn non-null; the instruction to visit
+         * @param insn {@code non-null;} the instruction to visit
          */
         public void visitPlainCstInsn(PlainCstInsn insn);
 
         /**
          * Visits a {@link SwitchInsn}.
          * 
-         * @param insn non-null; the instruction to visit
+         * @param insn {@code non-null;} the instruction to visit
          */
         public void visitSwitchInsn(SwitchInsn insn);
 
         /**
          * Visits a {@link ThrowingCstInsn}.
          * 
-         * @param insn non-null; the instruction to visit
+         * @param insn {@code non-null;} the instruction to visit
          */
         public void visitThrowingCstInsn(ThrowingCstInsn insn);
 
         /**
          * Visits a {@link ThrowingInsn}.
          * 
-         * @param insn non-null; the instruction to visit
+         * @param insn {@code non-null;} the instruction to visit
          */
         public void visitThrowingInsn(ThrowingInsn insn);
 
         /**
          * Visits a {@link FillArrayDataInsn}.
          *
-         * @param insn non-null; the instruction to visit
+         * @param insn {@code non-null;} the instruction to visit
          */
         public void visitFillArrayDataInsn(FillArrayDataInsn insn);
     }
diff --git a/dx/src/com/android/dx/rop/code/InsnList.java b/dx/src/com/android/dx/rop/code/InsnList.java
index 34f124c..493f7fc 100644
--- a/dx/src/com/android/dx/rop/code/InsnList.java
+++ b/dx/src/com/android/dx/rop/code/InsnList.java
@@ -24,7 +24,7 @@
 public final class InsnList
         extends FixedSizeList {
     /**
-     * Constructs an instance. All indices initially contain <code>null</code>.
+     * Constructs an instance. All indices initially contain {@code null}.
      *
      * @param size the size of the list
      */
@@ -35,10 +35,10 @@
     /**
      * Gets the element at the given index. It is an error to call
      * this with the index for an element which was never set; if you
-     * do that, this will throw <code>NullPointerException</code>.
+     * do that, this will throw {@code NullPointerException}.
      *
-     * @param n &gt;= 0, &lt; size(); which index
-     * @return non-null; element at that index
+     * @param n {@code >= 0, < size();} which index
+     * @return {@code non-null;} element at that index
      */
     public Insn get(int n) {
         return (Insn) get0(n);
@@ -47,8 +47,8 @@
     /**
      * Sets the instruction at the given index.
      *
-     * @param n &gt;= 0, &lt; size(); which index
-     * @param insn non-null; the instruction to set at <code>n</code>
+     * @param n {@code >= 0, < size();} which index
+     * @param insn {@code non-null;} the instruction to set at {@code n}
      */
     public void set(int n, Insn insn) {
         set0(n, insn);
@@ -56,9 +56,9 @@
 
     /**
      * Gets the last instruction. This is just a convenient shorthand for
-     * <code>get(size() - 1)</code>.
+     * {@code get(size() - 1)}.
      * 
-     * @return non-null; the last instruction
+     * @return {@code non-null;} the last instruction
      */
     public Insn getLast() {
         return get(size() - 1);
@@ -67,7 +67,7 @@
     /**
      * Visits each instruction in the list, in order.
      *
-     * @param visitor non-null; visitor to use
+     * @param visitor {@code non-null;} visitor to use
      */
     public void forEach(Insn.Visitor visitor) {
         int sz = size();
@@ -78,9 +78,9 @@
     }
 
     /**
-     * Compares the contents of this <code>InsnList</code> with another.
+     * Compares the contents of this {@code InsnList} with another.
      * The blocks must have the same number of insns, and each Insn must
-     * also return true to <code>Insn.contentEquals()</code>.
+     * also return true to {@code Insn.contentEquals()}.
      *
      * @param b to compare
      * @return true in the case described above.
@@ -108,7 +108,7 @@
      * original.
      * 
      * @param delta the amount to offset register numbers by
-     * @return non-null; an appropriately-constructed instance
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public InsnList withRegisterOffset(int delta) {
         int sz = size();
diff --git a/dx/src/com/android/dx/rop/code/LocalItem.java b/dx/src/com/android/dx/rop/code/LocalItem.java
index bac6ce2..7d6bebe 100644
--- a/dx/src/com/android/dx/rop/code/LocalItem.java
+++ b/dx/src/com/android/dx/rop/code/LocalItem.java
@@ -22,10 +22,10 @@
  * A local variable item: either a name or a signature or both.
  */
 public class LocalItem implements Comparable<LocalItem> {
-    /** null-ok; local variable name */
+    /** {@code null-ok;} local variable name */
     private final CstUtf8 name;
 
-    /** null-ok; local variable signature */
+    /** {@code null-ok;} local variable signature */
     private final CstUtf8 signature;
 
     /**
@@ -33,9 +33,9 @@
      *
      * TODO: intern these
      *
-     * @param name null-ok; local variable name
-     * @param signature null-ok; local variable signature
-     * @return non-null; appropriate instance.
+     * @param name {@code null-ok;} local variable name
+     * @param signature {@code null-ok;} local variable signature
+     * @return {@code non-null;} appropriate instance.
      */
     public static LocalItem make(CstUtf8 name, CstUtf8 signature) {
         if (name == null && signature == null) {
@@ -48,8 +48,8 @@
     /**
      * Constructs instance.
      *
-     * @param name null-ok; local variable name
-     * @param signature null-ok; local variable signature
+     * @param name {@code null-ok;} local variable name
+     * @param signature {@code null-ok;} local variable signature
      */
     private LocalItem(CstUtf8 name, CstUtf8 signature) {
         this.name = name;
@@ -126,7 +126,7 @@
     /**
      * Gets name.
      *
-     * @return null-ok; name
+     * @return {@code null-ok;} name
      */
     public CstUtf8 getName() {
         return name;
@@ -135,7 +135,7 @@
     /**
      * Gets signature.
      *
-     * @return null-ok; signature
+     * @return {@code null-ok;} signature
      */
     public CstUtf8 getSignature() {
         return signature;
diff --git a/dx/src/com/android/dx/rop/code/LocalVariableExtractor.java b/dx/src/com/android/dx/rop/code/LocalVariableExtractor.java
index 2d4cbce..db142c2 100644
--- a/dx/src/com/android/dx/rop/code/LocalVariableExtractor.java
+++ b/dx/src/com/android/dx/rop/code/LocalVariableExtractor.java
@@ -24,23 +24,23 @@
  * a method.
  */
 public final class LocalVariableExtractor {
-    /** non-null; method being extracted from */
+    /** {@code non-null;} method being extracted from */
     private final RopMethod method;
 
-    /** non-null; block list for the method */
+    /** {@code non-null;} block list for the method */
     private final BasicBlockList blocks;
 
-    /** non-null; result in-progress */
+    /** {@code non-null;} result in-progress */
     private final LocalVariableInfo resultInfo;
 
-    /** non-null; work set indicating blocks needing to be processed */
+    /** {@code non-null;} work set indicating blocks needing to be processed */
     private final int[] workSet;
 
     /**
      * Extracts out all the local variable information from the given method.
      * 
-     * @param method non-null; the method to extract from
-     * @return non-null; the extracted information
+     * @param method {@code non-null;} the method to extract from
+     * @return {@code non-null;} the extracted information
      */
     public static LocalVariableInfo extract(RopMethod method) {
         LocalVariableExtractor lve = new LocalVariableExtractor(method);
@@ -50,7 +50,7 @@
     /**
      * Constructs an instance. This method is private. Use {@link #extract}.
      * 
-     * @param method non-null; the method to extract from
+     * @param method {@code non-null;} the method to extract from
      */
     private LocalVariableExtractor(RopMethod method) {
         if (method == null) {
@@ -69,7 +69,7 @@
     /**
      * Does the extraction.
      * 
-     * @return non-null; the extracted information
+     * @return {@code non-null;} the extracted information
      */
     private LocalVariableInfo doit() {
         for (int label = method.getFirstLabel();
@@ -86,7 +86,7 @@
     /**
      * Processes a single block.
      * 
-     * @param label &gt;= 0; label of the block to process
+     * @param label {@code >= 0;} label of the block to process
      */
     private void processBlock(int label) {
         RegisterSpecSet primaryState = resultInfo.mutableCopyOfStarts(label);
@@ -101,7 +101,6 @@
          * state *before* executing it to be what is merged into
          * exception targets.
          */
-        Insn lastInsn = insns.getLast();
         boolean canThrowDuringLastInsn = block.hasExceptionHandlers() &&
             (insns.getLast().getResult() != null);
         int freezeSecondaryStateAt = insnSz - 1;
diff --git a/dx/src/com/android/dx/rop/code/LocalVariableInfo.java b/dx/src/com/android/dx/rop/code/LocalVariableInfo.java
index 29c239b..fa5e7cc 100644
--- a/dx/src/com/android/dx/rop/code/LocalVariableInfo.java
+++ b/dx/src/com/android/dx/rop/code/LocalVariableInfo.java
@@ -27,30 +27,30 @@
  */
 public final class LocalVariableInfo
         extends MutabilityControl {
-    /** &gt;= 0; the register count for the method */
+    /** {@code >= 0;} the register count for the method */
     private final int regCount;
 
     /**
-     * non-null; {@link RegisterSpecSet} to use when indicating a block
+     * {@code non-null;} {@link RegisterSpecSet} to use when indicating a block
      * that has no locals; it is empty and immutable but has an appropriate
      * max size for the method 
      */
     private final RegisterSpecSet emptySet;
 
     /**
-     * non-null; array consisting of register sets representing the
+     * {@code non-null;} array consisting of register sets representing the
      * sets of variables already assigned upon entry to each block,
      * where array indices correspond to block labels 
      */
     private final RegisterSpecSet[] blockStarts;
 
-    /** non-null; map from instructions to the variable each assigns */
+    /** {@code non-null;} map from instructions to the variable each assigns */
     private final HashMap<Insn, RegisterSpec> insnAssignments;
 
     /**
      * Constructs an instance.
      * 
-     * @param method non-null; the method being represented by this instance
+     * @param method {@code non-null;} the method being represented by this instance
      */
     public LocalVariableInfo(RopMethod method) {
         if (method == null) {
@@ -73,8 +73,8 @@
      * Sets the register set associated with the start of the block with
      * the given label.
      * 
-     * @param label &gt;= 0; the block label
-     * @param specs non-null; the register set to associate with the block
+     * @param label {@code >= 0;} the block label
+     * @param specs {@code non-null;} the register set to associate with the block
      */
     public void setStarts(int label, RegisterSpecSet specs) {
         throwIfImmutable();
@@ -98,12 +98,12 @@
      * merge the two sets and call {@link #setStarts} on the result of the
      * merge.
      * 
-     * @param label &gt;= 0; the block label
-     * @param specs non-null; the register set to merge into the start set
+     * @param label {@code >= 0;} the block label
+     * @param specs {@code non-null;} the register set to merge into the start set
      * for the block
-     * @return <code>true</code> if the merge resulted in an actual change
+     * @return {@code true} if the merge resulted in an actual change
      * to the associated set (including storing one for the first time) or
-     * <code>false</code> if there was no change
+     * {@code false} if there was no change
      */
     public boolean mergeStarts(int label, RegisterSpecSet specs) {
         RegisterSpecSet start = getStarts0(label);
@@ -132,8 +132,8 @@
      * with the given label. This returns an empty set with the appropriate
      * max size if no set was associated with the block in question.
      * 
-     * @param label &gt;= 0; the block label
-     * @return non-null; the associated register set
+     * @param label {@code >= 0;} the block label
+     * @return {@code non-null;} the associated register set
      */
     public RegisterSpecSet getStarts(int label) {
         RegisterSpecSet result = getStarts0(label);
@@ -144,10 +144,10 @@
     /**
      * Gets the register set associated with the start of the given
      * block. This is just convenient shorthand for
-     * <code>getStarts(block.getLabel())</code>.
+     * {@code getStarts(block.getLabel())}.
      * 
-     * @param block non-null; the block in question
-     * @return non-null; the associated register set
+     * @param block {@code non-null;} the block in question
+     * @return {@code non-null;} the associated register set
      */
     public RegisterSpecSet getStarts(BasicBlock block) {
         return getStarts(block.getLabel());
@@ -159,8 +159,8 @@
      * newly-allocated empty {@link RegisterSpecSet} of appropriate
      * max size if there is not yet any set associated with the block.
      * 
-     * @param label &gt;= 0; the block label
-     * @return non-null; the associated register set
+     * @param label {@code >= 0;} the block label
+     * @return {@code non-null;} the associated register set
      */
     public RegisterSpecSet mutableCopyOfStarts(int label) {
         RegisterSpecSet result = getStarts0(label);
@@ -180,8 +180,8 @@
      * simple type and the one in the instruction can be an arbitrary
      * {@link TypeBearer} (such as a constant value).
      * 
-     * @param insn non-null; the instruction in question
-     * @param spec non-null; the associated register spec
+     * @param insn {@code non-null;} the instruction in question
+     * @param spec {@code non-null;} the associated register spec
      */
     public void addAssignment(Insn insn, RegisterSpec spec) {
         throwIfImmutable();
@@ -201,8 +201,8 @@
      * Gets the named register being assigned by the given instruction, if
      * previously stored in this instance.
      * 
-     * @param insn non-null; instruction in question
-     * @return null-ok; the named register being assigned, if any
+     * @param insn {@code non-null;} instruction in question
+     * @return {@code null-ok;} the named register being assigned, if any
      */
     public RegisterSpec getAssignment(Insn insn) {
         return insnAssignments.get(insn);
@@ -211,7 +211,7 @@
     /**
      * Gets the number of assignments recorded by this instance.
      * 
-     * @return &gt;= 0; the number of assignments
+     * @return {@code >= 0;} the number of assignments
      */
     public int getAssignmentCount() {
         return insnAssignments.size();
@@ -235,8 +235,8 @@
      * Helper method, to get the starts for a label, throwing the
      * right exception for range problems.
      * 
-     * @param label &gt;= 0; the block label
-     * @return null-ok; associated register set or <code>null</code> if there
+     * @param label {@code >= 0;} the block label
+     * @return {@code null-ok;} associated register set or {@code null} if there
      * is none
      */
     private RegisterSpecSet getStarts0(int label) {
diff --git a/dx/src/com/android/dx/rop/code/PlainCstInsn.java b/dx/src/com/android/dx/rop/code/PlainCstInsn.java
index 908b3cb..7a3ac38 100644
--- a/dx/src/com/android/dx/rop/code/PlainCstInsn.java
+++ b/dx/src/com/android/dx/rop/code/PlainCstInsn.java
@@ -30,11 +30,11 @@
     /**
      * Constructs an instance.
      * 
-     * @param opcode non-null; the opcode
-     * @param position non-null; source position
-     * @param result null-ok; spec for the result, if any
-     * @param sources non-null; specs for all the sources
-     * @param cst non-null; the constant
+     * @param opcode {@code non-null;} the opcode
+     * @param position {@code non-null;} source position
+     * @param result {@code null-ok;} spec for the result, if any
+     * @param sources {@code non-null;} specs for all the sources
+     * @param cst {@code non-null;} the constant
      */
     public PlainCstInsn(Rop opcode, SourcePosition position,
                         RegisterSpec result, RegisterSpecList sources,
diff --git a/dx/src/com/android/dx/rop/code/PlainInsn.java b/dx/src/com/android/dx/rop/code/PlainInsn.java
index 4c5c9b7..d1db646 100644
--- a/dx/src/com/android/dx/rop/code/PlainInsn.java
+++ b/dx/src/com/android/dx/rop/code/PlainInsn.java
@@ -31,10 +31,10 @@
     /**
      * Constructs an instance.
      * 
-     * @param opcode non-null; the opcode
-     * @param position non-null; source position
-     * @param result null-ok; spec for the result, if any
-     * @param sources non-null; specs for all the sources
+     * @param opcode {@code non-null;} the opcode
+     * @param position {@code non-null;} source position
+     * @param result {@code null-ok;} spec for the result, if any
+     * @param sources {@code non-null;} specs for all the sources
      */
     public PlainInsn(Rop opcode, SourcePosition position,
                      RegisterSpec result, RegisterSpecList sources) {
@@ -57,10 +57,10 @@
     /**
      * Constructs a single-source instance.
      * 
-     * @param opcode non-null; the opcode
-     * @param position non-null; source position
-     * @param result null-ok; spec for the result, if any
-     * @param source non-null; spec for the source
+     * @param opcode {@code non-null;} the opcode
+     * @param position {@code non-null;} source position
+     * @param result {@code null-ok;} spec for the result, if any
+     * @param source {@code non-null;} spec for the source
      */
     public PlainInsn(Rop opcode, SourcePosition position, RegisterSpec result,
                      RegisterSpec source) {
diff --git a/dx/src/com/android/dx/rop/code/RegOps.java b/dx/src/com/android/dx/rop/code/RegOps.java
index f201f68..2084a69 100644
--- a/dx/src/com/android/dx/rop/code/RegOps.java
+++ b/dx/src/com/android/dx/rop/code/RegOps.java
@@ -21,283 +21,279 @@
 /**
  * All the register-based opcodes, and related utilities.
  * 
- * <p><b>Note:</b> Opcode descriptions use a rough pseudocode. <code>r</code>
- * is the result register, <code>x</code> is the first argument,
- * <code>y</code> is the second argument, and <code>z</code> is the
+ * <p><b>Note:</b> Opcode descriptions use a rough pseudocode. {@code r}
+ * is the result register, {@code x} is the first argument,
+ * {@code y} is the second argument, and {@code z} is the
  * third argument. The expression which describes
  * the operation uses Java-ish syntax but is preceded by type indicators for
  * each of the values.
  */
 public final class RegOps {
-    /** <code>nop()</code> */
+    /** {@code nop()} */
     public static final int NOP = 1;
 
-    /** <code>T: any type; r,x: T :: r = x;</code> */
+    /** {@code T: any type; r,x: T :: r = x;} */
     public static final int MOVE = 2;
 
-    /** <code>T: any type; r,param(x): T :: r = param(x)</code> */
+    /** {@code T: any type; r,param(x): T :: r = param(x)} */
     public static final int MOVE_PARAM = 3;
 
     /**
-     * <code>T: Throwable; r: T :: r = caught_exception</code>.
+     * {@code T: Throwable; r: T :: r = caught_exception}.
      * <b>Note:</b> This opcode should only ever be used in the
      * first instruction of a block, and such blocks must be
      * the start of an exception handler.
      */
     public static final int MOVE_EXCEPTION = 4;
 
-    /** <code>T: any type; r, literal: T :: r = literal;</code> */
+    /** {@code T: any type; r, literal: T :: r = literal;} */
     public static final int CONST = 5;
 
-    /** <code>goto <i>label</i></code> */
+    /** {@code goto label} */
     public static final int GOTO = 6;
 
     /**
-     * <code>T: int or Object; x,y: T :: if (x == y) goto
-     * <i>label</i></code> 
+     * {@code T: int or Object; x,y: T :: if (x == y) goto
+     * label}
      */
     public static final int IF_EQ = 7;
 
     /**
-     * <code>T: int or Object; x,y: T :: if (x != y) goto
-     * <i>label</i></code> 
+     * {@code T: int or Object; x,y: T :: if (x != y) goto
+     * label}
      */
     public static final int IF_NE = 8;
 
-    /** <code>x,y: int :: if (x &lt; y) goto <i>label</i></code> */
+    /** {@code x,y: int :: if (x < y) goto label} */
     public static final int IF_LT = 9;
 
-    /** <code>x,y: int :: if (x &gt;= y) goto <i>label</i></code> */
+    /** {@code x,y: int :: if (x >= y) goto label} */
     public static final int IF_GE = 10;
 
-    /** <code>x,y: int :: if (x &lt;= y) goto <i>label</i></code> */
+    /** {@code x,y: int :: if (x <= y) goto label} */
     public static final int IF_LE = 11;
 
-    /** <code>x,y: int :: if (x &gt; y) goto <i>label</i></code> */
+    /** {@code x,y: int :: if (x > y) goto label} */
     public static final int IF_GT = 12;
 
-    /** <code>x: int :: goto <i>table[x]</i></code> */
+    /** {@code x: int :: goto table[x]} */
     public static final int SWITCH = 13;
 
-    /** <code>T: any numeric type; r,x,y: T :: r = x + y</code> */
+    /** {@code T: any numeric type; r,x,y: T :: r = x + y} */
     public static final int ADD = 14;
 
-    /** <code>T: any numeric type; r,x,y: T :: r = x - y</code> */
+    /** {@code T: any numeric type; r,x,y: T :: r = x - y} */
     public static final int SUB = 15;
 
-    /** <code>T: any numeric type; r,x,y: T :: r = x * y</code> */
+    /** {@code T: any numeric type; r,x,y: T :: r = x * y} */
     public static final int MUL = 16;
 
-    /** <code>T: any numeric type; r,x,y: T :: r = x / y</code> */
+    /** {@code T: any numeric type; r,x,y: T :: r = x / y} */
     public static final int DIV = 17;
 
     /**
-     * <code>T: any numeric type; r,x,y: T :: r = x % y</code>
+     * {@code T: any numeric type; r,x,y: T :: r = x % y}
      * (Java-style remainder) 
      */
     public static final int REM = 18;
 
-    /** <code>T: any numeric type; r,x: T :: r = -x</code> */
+    /** {@code T: any numeric type; r,x: T :: r = -x} */
     public static final int NEG = 19;
 
-    /** <code>T: any integral type; r,x,y: T :: r = x &amp; y</code> */
+    /** {@code T: any integral type; r,x,y: T :: r = x & y} */
     public static final int AND = 20;
 
-    /** <code>T: any integral type; r,x,y: T :: r = x | y</code> */
+    /** {@code T: any integral type; r,x,y: T :: r = x | y} */
     public static final int OR = 21;
 
-    /** <code>T: any integral type; r,x,y: T :: r = x ^ y</code> */
+    /** {@code T: any integral type; r,x,y: T :: r = x ^ y} */
     public static final int XOR = 22;
 
     /**
-     * <code>T: any integral type; r,x: T; y: int :: r = x &lt;&lt;
-     * y</code> 
+     * {@code T: any integral type; r,x: T; y: int :: r = x << y}
      */
     public static final int SHL = 23;
 
     /**
-     * <code>T: any integral type; r,x: T; y: int :: r = x &gt;&gt;
-     * y</code> (signed right-shift) 
+     * {@code T: any integral type; r,x: T; y: int :: r = x >> y}
+     * (signed right-shift) 
      */
     public static final int SHR = 24;
 
     /**
-     * <code>T: any integral type; r,x: T; y: int :: r = x
-     * &gt;&gt;&gt; y</code> (unsigned right-shift) 
+     * {@code T: any integral type; r,x: T; y: int :: r = x >>> y}
+     * (unsigned right-shift) 
      */
     public static final int USHR = 25;
 
-    /** <code>T: any integral type; r,x: T :: r = ~x</code> */
+    /** {@code T: any integral type; r,x: T :: r = ~x} */
     public static final int NOT = 26;
 
     /**
-     * <code>T: any numeric type; r: int; x,y: T :: r = (x == y) ? 0
-     * : (x &gt; y) ? 1 : -1</code> (Java-style "cmpl" where a NaN is
+     * {@code T: any numeric type; r: int; x,y: T :: r = (x == y) ? 0
+     * : (x > y) ? 1 : -1} (Java-style "cmpl" where a NaN is
      * considered "less than" all other values; also used for integral
      * comparisons) 
      */
     public static final int CMPL = 27;
 
     /**
-     * <code>T: any floating point type; r: int; x,y: T :: r = (x == y) ? 0
-     * : (x &lt; y) ? -1 : 1</code> (Java-style "cmpg" where a NaN is
+     * {@code T: any floating point type; r: int; x,y: T :: r = (x == y) ? 0
+     * : (x < y) ? -1 : 1} (Java-style "cmpg" where a NaN is
      * considered "greater than" all other values) 
      */
     public static final int CMPG = 28;
 
     /**
-     * <code>T: any numeric type; U: any numeric type; r: T; x: U ::
-     * r = (T) x</code> (numeric type conversion between the four
+     * {@code T: any numeric type; U: any numeric type; r: T; x: U ::
+     * r = (T) x} (numeric type conversion between the four
      * "real" numeric types) 
      */
     public static final int CONV = 29;
 
     /**
-     * <code>r,x: int :: r = (x &lt;&lt; 24) &gt;&gt; 24</code> (Java-style
+     * {@code r,x: int :: r = (x << 24) >> 24} (Java-style
      * convert int to byte) 
      */
     public static final int TO_BYTE = 30;
 
     /**
-     * <code>r,x: int :: r = x &amp; 0xffff</code> (Java-style
-     * convert int to char) 
+     * {@code r,x: int :: r = x & 0xffff} (Java-style convert int to char) 
      */
     public static final int TO_CHAR = 31;
 
     /**
-     * <code>r,x: int :: r = (x &lt;&lt; 16) &gt;&gt; 16</code> (Java-style
+     * {@code r,x: int :: r = (x << 16) >> 16} (Java-style
      * convert int to short) 
      */
     public static final int TO_SHORT = 32;
 
-    /** <code>T: return type for the method; x: T; return x</code> */
+    /** {@code T: return type for the method; x: T; return x} */
     public static final int RETURN = 33;
 
-    /** <code>T: any type; r: int; x: T[]; :: r = x.length</code> */
+    /** {@code T: any type; r: int; x: T[]; :: r = x.length} */
     public static final int ARRAY_LENGTH = 34;
 
-    /** <code>x: Throwable :: throw(x)</code> */
+    /** {@code x: Throwable :: throw(x)} */
     public static final int THROW = 35;
 
-    /** <code>x: Object :: monitorenter(x)</code> */
+    /** {@code x: Object :: monitorenter(x)} */
     public static final int MONITOR_ENTER = 36;
 
-    /** <code>x: Object :: monitorexit(x)</code> */
+    /** {@code x: Object :: monitorexit(x)} */
     public static final int MONITOR_EXIT = 37;
 
-    /** <code>T: any type; r: T; x: T[]; y: int :: r = x[y]</code> */
+    /** {@code T: any type; r: T; x: T[]; y: int :: r = x[y]} */
     public static final int AGET = 38;
 
-    /** <code>T: any type; x: T; y: T[]; z: int :: x[y] = z</code> */
+    /** {@code T: any type; x: T; y: T[]; z: int :: x[y] = z} */
     public static final int APUT = 39;
 
     /**
-     * <code>T: any non-array object type :: r =
-     * alloc(T)</code> (allocate heap space for an object) 
+     * {@code T: any non-array object type :: r =
+     * alloc(T)} (allocate heap space for an object) 
      */
     public static final int NEW_INSTANCE = 40;
 
-    /** <code>T: any array type; r: T; x: int :: r = new T[x]</code> */
+    /** {@code T: any array type; r: T; x: int :: r = new T[x]} */
     public static final int NEW_ARRAY = 41;
 
     /**
-     * <code>T: any array type; r: T; x: int; v0..vx: T :: r = new T[x]
-     * {v0, ..., vx}</code> 
+     * {@code T: any array type; r: T; x: int; v0..vx: T :: r = new T[x]
+     * {v0, ..., vx}}
      */
     public static final int FILLED_NEW_ARRAY = 42;
 
     /**
-     * <code>T: any object type; x: Object :: (T) x</code> (can
-     * throw <code>ClassCastException</code>) 
+     * {@code T: any object type; x: Object :: (T) x} (can
+     * throw {@code ClassCastException}) 
      */
     public static final int CHECK_CAST = 43;
 
     /**
-     * <code>T: any object type; x: Object :: x instanceof
-     * T</code> 
+     * {@code T: any object type; x: Object :: x instanceof T}
      */
     public static final int INSTANCE_OF = 44;
 
     /**
-     * <code>T: any type; r: T; x: Object; f: instance field spec of
-     * type T :: r = x.f</code> 
+     * {@code T: any type; r: T; x: Object; f: instance field spec of
+     * type T :: r = x.f}
      */
     public static final int GET_FIELD = 45;
 
     /**
-     * <code>T: any type; r: T; f: static field spec of type T :: r =
-     * f</code> 
+     * {@code T: any type; r: T; f: static field spec of type T :: r =
+     * f} 
      */
     public static final int GET_STATIC = 46;
 
     /**
-     * <code>T: any type; x: T; y: Object; f: instance field spec of type
-     * T :: y.f = x</code> 
+     * {@code T: any type; x: T; y: Object; f: instance field spec of type
+     * T :: y.f = x} 
      */
     public static final int PUT_FIELD = 47;
 
     /**
-     * <code>T: any type; f: static field spec of type T; x: T :: f =
-     * x</code>
+     * {@code T: any type; f: static field spec of type T; x: T :: f = x}
      */
     public static final int PUT_STATIC = 48;
 
     /**
-     * <code>Tr, T0, T1...: any types; r: Tr; m: static method spec;
-     * y0: T0; y1: T1 ... :: r = m(y0, y1, ...)</code> (call static
+     * {@code Tr, T0, T1...: any types; r: Tr; m: static method spec;
+     * y0: T0; y1: T1 ... :: r = m(y0, y1, ...)} (call static
      * method) 
      */
     public static final int INVOKE_STATIC = 49;
 
     /**
-     * <code>Tr, T0, T1...: any types; r: Tr; x: Object; m: instance method
-     * spec; y0: T0; y1: T1 ... :: r = x.m(y0, y1, ...)</code> (call normal
+     * {@code Tr, T0, T1...: any types; r: Tr; x: Object; m: instance method
+     * spec; y0: T0; y1: T1 ... :: r = x.m(y0, y1, ...)} (call normal
      * virtual method) 
      */
     public static final int INVOKE_VIRTUAL = 50;
 
     /**
-     * <code>Tr, T0, T1...: any types; r: Tr; x: Object; m: instance method
-     * spec; y0: T0; y1: T1 ... :: r = x.m(y0, y1, ...)</code> (call
+     * {@code Tr, T0, T1...: any types; r: Tr; x: Object; m: instance method
+     * spec; y0: T0; y1: T1 ... :: r = x.m(y0, y1, ...)} (call
      * superclass virtual method) 
      */
     public static final int INVOKE_SUPER = 51;
 
     /**
-     * <code>Tr, T0, T1...: any types; r: Tr; x: Object; m: instance method
-     * spec; y0: T0; y1: T1 ... :: r = x.m(y0, y1, ...)</code> (call
+     * {@code Tr, T0, T1...: any types; r: Tr; x: Object; m: instance method
+     * spec; y0: T0; y1: T1 ... :: r = x.m(y0, y1, ...)} (call
      * direct/special method) 
      */
     public static final int INVOKE_DIRECT = 52;
 
     /**
-     * <code>Tr, T0, T1...: any types; r: Tr; x: Object; m: interface
+     * {@code Tr, T0, T1...: any types; r: Tr; x: Object; m: interface
      * (instance) method spec; y0: T0; y1: T1 ... :: r = x.m(y0, y1,
-     * ...)</code> (call interface method) 
+     * ...)} (call interface method) 
      */
     public static final int INVOKE_INTERFACE = 53;
 
     /**
-     * <code> T0: any type; </code> (mark beginning or end of local variable
-     * name
+     * {@code T0: any type; name: local variable name  :: mark(name,T0)}
+     * (mark beginning or end of local variable name)
      */
     public static final int MARK_LOCAL = 54;
 
     /**
-     * <code>T: Any type; r: T :: r = return_type</code>.
+     * {@code T: Any type; r: T :: r = return_type}.
      * <b>Note:</b> This opcode should only ever be used in the
      * first instruction of a block following an invoke-*.
      */
     public static final int MOVE_RESULT = 55;
 
     /**
-     * <code>T: Any type; r: T :: r = return_type</code>.
+     * {@code T: Any type; r: T :: r = return_type}.
      * <b>Note:</b> This opcode should only ever be used in the
      * first instruction of a block following a non-invoke throwing insn
      */
     public static final int MOVE_RESULT_PSEUDO = 56;
 
-    /** <code>T: Any primitive type; v0..vx: T :: {v0, ..., vx}</code> */
+    /** {@code T: Any primitive type; v0..vx: T :: {v0, ..., vx}} */
     public static final int FILL_ARRAY_DATA = 57;
 
     /**
@@ -310,8 +306,8 @@
     /**
      * Gets the name of the given opcode.
      * 
-     * @param opcode &gt;= 0, &lt;= 255; the opcode
-     * @return non-null; its name
+     * @param opcode {@code >= 0, <= 255;} the opcode
+     * @return {@code non-null;} its name
      */
     public static String opName(int opcode) {
         switch (opcode) {
diff --git a/dx/src/com/android/dx/rop/code/RegisterSpec.java b/dx/src/com/android/dx/rop/code/RegisterSpec.java
index 73af91f..1f14767 100644
--- a/dx/src/com/android/dx/rop/code/RegisterSpec.java
+++ b/dx/src/com/android/dx/rop/code/RegisterSpec.java
@@ -30,33 +30,33 @@
  */
 public final class RegisterSpec
         implements TypeBearer, ToHuman, Comparable<RegisterSpec> {
-    /** non-null; string to prefix register numbers with */
+    /** {@code non-null;} string to prefix register numbers with */
     public static final String PREFIX = "v";
 
-    /** non-null; intern table for instances */
+    /** {@code non-null;} intern table for instances */
     private static final HashMap<Object, RegisterSpec> theInterns =
         new HashMap<Object, RegisterSpec>(1000);
 
-    /** non-null; common comparison instance used while interning */
+    /** {@code non-null;} common comparison instance used while interning */
     private static final ForComparison theInterningItem = new ForComparison();
 
-    /** &gt;= 0; register number */
+    /** {@code >= 0;} register number */
     private final int reg;
 
-    /** non-null; type loaded or stored */
+    /** {@code non-null;} type loaded or stored */
     private final TypeBearer type;
 
-    /** null-ok; local variable info associated with this register, if any */
+    /** {@code null-ok;} local variable info associated with this register, if any */
     private final LocalItem local;
 
     /**
      * Intern the given triple as an instance of this class.
      *
-     * @param reg &gt;= 0; the register number
-     * @param type non-null; the type (or possibly actual value) which
+     * @param reg {@code >= 0;} the register number
+     * @param type {@code non-null;} the type (or possibly actual value) which
      * is loaded from or stored to the indicated register
-     * @param local null-ok; the associated local variable, if any
-     * @return non-null; an appropriately-constructed instance
+     * @param local {@code null-ok;} the associated local variable, if any
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     private static RegisterSpec intern(int reg, TypeBearer type,
             LocalItem local) {
@@ -77,10 +77,10 @@
      * no variable info. This method is allowed to return shared
      * instances (but doesn't necessarily do so).
      * 
-     * @param reg &gt;= 0; the register number
-     * @param type non-null; the type (or possibly actual value) which
+     * @param reg {@code >= 0;} the register number
+     * @param type {@code non-null;} the type (or possibly actual value) which
      * is loaded from or stored to the indicated register
-     * @return non-null; an appropriately-constructed instance
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public static RegisterSpec make(int reg, TypeBearer type) {
         return intern(reg, type, null);
@@ -91,11 +91,11 @@
      * variable info. This method is allowed to return shared
      * instances (but doesn't necessarily do so).
      *
-     * @param reg &gt;= 0; the register number
-     * @param type non-null; the type (or possibly actual value) which
+     * @param reg {@code >= 0;} the register number
+     * @param type {@code non-null;} the type (or possibly actual value) which
      * is loaded from or stored to the indicated register
-     * @param local non-null; the associated local variable
-     * @return non-null; an appropriately-constructed instance
+     * @param local {@code non-null;} the associated local variable
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public static RegisterSpec make(int reg, TypeBearer type,
             LocalItem local) {
@@ -111,12 +111,12 @@
      * variable info. This method is allowed to return shared
      * instances (but doesn't necessarily do so).
      *
-     * @param reg &gt;= 0; the register number
-     * @param type non-null; the type (or possibly actual value) which
+     * @param reg {@code >= 0;} the register number
+     * @param type {@code non-null;} the type (or possibly actual value) which
      * is loaded from or stored to the indicated register
-     * @param local null-ok; the associated variable info or null for
+     * @param local {@code null-ok;} the associated variable info or null for
      * none
-     * @return non-null; an appropriately-constructed instance
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public static RegisterSpec makeLocalOptional(
             int reg, TypeBearer type, LocalItem local) {
@@ -127,8 +127,8 @@
     /**
      * Gets the string form for the given register number.
      * 
-     * @param reg &gt= 0; the register number
-     * @return non-null; the string form
+     * @param reg {@code >= 0;} the register number
+     * @return {@code non-null;} the string form
      */
     public static String regString(int reg) {
         return PREFIX + reg;
@@ -138,10 +138,10 @@
      * Constructs an instance. This constructor is private. Use
      * {@link #make}.
      * 
-     * @param reg &gt;= 0; the register number
-     * @param type non-null; the type (or possibly actual value) which
+     * @param reg {@code >= 0;} the register number
+     * @param type {@code non-null;} the type (or possibly actual value) which
      * is loaded from or stored to the indicated register
-     * @param local null-ok; the associated local variable, if any
+     * @param local {@code null-ok;} the associated local variable, if any
      */
     private RegisterSpec(int reg, TypeBearer type, LocalItem local) {
         if (reg < 0) {
@@ -178,7 +178,7 @@
      * to ignore whatever arbitrary extra stuff might be carried around
      * by an outer {@link TypeBearer}.
      * 
-     * @param other null-ok; spec to compare to
+     * @param other {@code null-ok;} spec to compare to
      * @return {@code true} iff {@code this} and {@code other} are equal
      * in the stated way
      */
@@ -195,7 +195,7 @@
      * This is useful to determine if two instances refer to the "same"
      * local variable.
      * 
-     * @param other null-ok; spec to compare to
+     * @param other {@code null-ok;} spec to compare to
      * @return {@code true} iff {@code this} and {@code other} are equal
      * in the stated way
      */
@@ -230,8 +230,8 @@
      * Compares by (in priority order) register number, unwrapped type
      * (that is types not {@link TypeBearer}s, and local info.
      * 
-     * @param other non-null; spec to compare to
-     * @return {@code -1..1}; standard result of comparison
+     * @param other {@code non-null;} spec to compare to
+     * @return {@code -1..1;} standard result of comparison
      */
     public int compareTo(RegisterSpec other) {
         if (this.reg < other.reg) {
@@ -316,7 +316,7 @@
     /**
      * Gets the register number.
      * 
-     * @return &gt;= 0; the register number
+     * @return {@code >= 0;} the register number
      */
     public int getReg() {
         return reg;
@@ -326,7 +326,7 @@
      * Gets the type (or actual value) which is loaded from or stored
      * to the register associated with this instance.
      * 
-     * @return non-null; the type
+     * @return {@code non-null;} the type
      */
     public TypeBearer getTypeBearer() {
         return type;
@@ -335,7 +335,7 @@
     /**
      * Gets the variable info associated with this instance, if any.
      *
-     * @return null-ok; the variable info, or <code>null</code> if this
+     * @return {@code null-ok;} the variable info, or {@code null} if this
      * instance has none
      */
     public LocalItem getLocalItem() {
@@ -349,7 +349,7 @@
      * be used to determine the minimum required register count
      * implied by this instance.
      * 
-     * @return &gt;= 0; the required registers size
+     * @return {@code >= 0;} the required registers size
      */
     public int getNextReg() {
         return reg + getCategory();
@@ -357,11 +357,11 @@
 
     /**
      * Gets the category of this instance's type. This is just a convenient
-     * shorthand for <code>getType().getCategory()</code>.
+     * shorthand for {@code getType().getCategory()}.
      * 
      * @see #isCategory1
      * @see #isCategory2
-     * @return 1..2; the category of this instance's type
+     * @return {@code 1..2;} the category of this instance's type
      */
     public int getCategory() {
         return type.getType().getCategory();
@@ -369,7 +369,7 @@
 
     /**
      * Gets whether this instance's type is category 1. This is just a
-     * convenient shorthand for <code>getType().isCategory1()</code>.
+     * convenient shorthand for {@code getType().isCategory1()}.
      * 
      * @see #getCategory
      * @see #isCategory2
@@ -381,7 +381,7 @@
 
     /**
      * Gets whether this instance's type is category 2. This is just a
-     * convenient shorthand for <code>getType().isCategory2()</code>.
+     * convenient shorthand for {@code getType().isCategory2()}.
      * 
      * @see #getCategory
      * @see #isCategory1
@@ -394,7 +394,7 @@
     /**
      * Gets the string form for just the register number of this instance.
      * 
-     * @return non-null; the register string form
+     * @return {@code non-null;} the register string form
      */
     public String regString() {
         return regString(reg);
@@ -405,28 +405,28 @@
      * and the given one, if any. The intersection is defined as follows:
      * 
      * <ul>
-     *   <li>If <code>other</code> is <code>null</code>, then the result
-     *     is <code>null</code>.
+     *   <li>If {@code other} is {@code null}, then the result
+     *     is {@code null}.
      *   <li>If the register numbers don't match, then the intersection
-     *     is <code>null</code>. Otherwise, the register number of the
+     *     is {@code null}. Otherwise, the register number of the
      *     intersection is the same as the one in the two instances.</li>
-     *   <li>If the types returned by <code>getType()</code> are not
-     *     <code>equals()</code>, then the intersection is null.</li>
-     *   <li>If the type bearers returned by <code>getTypeBearer()</code>
-     *     are <code>equals()</code>, then the intersection's type bearer
+     *   <li>If the types returned by {@code getType()} are not
+     *     {@code equals()}, then the intersection is null.</li>
+     *   <li>If the type bearers returned by {@code getTypeBearer()}
+     *     are {@code equals()}, then the intersection's type bearer
      *     is the one from this instance. Otherwise, the intersection's
-     *     type bearer is the <code>getType()</code> of this instance.</li>
-     *   <li>If the locals are <code>equals()</code>, then the local info
+     *     type bearer is the {@code getType()} of this instance.</li>
+     *   <li>If the locals are {@code equals()}, then the local info
      *     of the intersection is the local info of this instance. Otherwise,
-     *     the local info of the intersection is <code>null</code>.</li>
+     *     the local info of the intersection is {@code null}.</li>
      * </ul>
      * 
-     * @param other null-ok; instance to intersect with (or <code>null</code>)
+     * @param other {@code null-ok;} instance to intersect with (or {@code null})
      * @param localPrimary whether local variables are primary to the
-     * intersection; if <code>true</code>, then the only non-null
+     * intersection; if {@code true}, then the only non-null
      * results occur when registers being intersected have equal local
-     * infos (or both have <code>null</code> local infos)
-     * @return null-ok; the intersection
+     * infos (or both have {@code null} local infos)
+     * @return {@code null-ok;} the intersection
      */
     public RegisterSpec intersect(RegisterSpec other, boolean localPrimary) {
         if (this == other) {
@@ -471,8 +471,8 @@
      * Returns an instance that is identical to this one, except that the
      * register number is replaced by the given one.
      * 
-     * @param newReg &gt;= 0; the new register number
-     * @return non-null; an appropriately-constructed instance
+     * @param newReg {@code >= 0;} the new register number
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public RegisterSpec withReg(int newReg) {
         if (reg == newReg) {
@@ -486,8 +486,8 @@
      * Returns an instance that is identical to this one, except that
      * the type is replaced by the given one.
      *
-     * @param newType non-null; the new type
-     * @return non-null; an appropriately-constructed instance
+     * @param newType {@code non-null;} the new type
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public RegisterSpec withType(TypeBearer newType) {
         return makeLocalOptional(reg, newType, local);
@@ -498,7 +498,7 @@
      * register number is offset by the given amount.
      * 
      * @param delta the amount to offset the register number by
-     * @return non-null; an appropriately-constructed instance
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public RegisterSpec withOffset(int delta) {
         if (delta == 0) {
@@ -514,7 +514,7 @@
      * (thereby stripping off non-type information) with any
      * initialization information stripped away as well.
      * 
-     * @return non-null; an appropriately-constructed instance
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public RegisterSpec withSimpleType() {
         TypeBearer orig = type;
@@ -541,7 +541,7 @@
      * Returns an instance that is identical to this one except that the
      * local variable is as specified in the parameter.
      *
-     * @param local null-ok; the local item or null for none
+     * @param local {@code null-ok;} the local item or null for none
      * @return an appropriate instance
      */
     public RegisterSpec withLocalItem(LocalItem local) {
@@ -559,7 +559,7 @@
      * Helper for {@link #toString} and {@link #toHuman}.
      * 
      * @param human whether to be human-oriented
-     * @return non-null; the string form
+     * @return {@code non-null;} the string form
      */
     private String toString0(boolean human) {
         StringBuffer sb = new StringBuffer(40);
@@ -588,27 +588,31 @@
 
     /**
      * Holder of register spec data for the purposes of comparison (so that
-     * <code>RegisterSpec</code> itself can still keep <code>final</code>
+     * {@code RegisterSpec} itself can still keep {@code final}
      * instance variables.
      */
     private static class ForComparison {
-        /** &gt;= 0; register number */
+        /** {@code >= 0;} register number */
         private int reg;
         
-        /** non-null; type loaded or stored */
+        /** {@code non-null;} type loaded or stored */
         private TypeBearer type;
 
-        /** null-ok; local variable associated with this register, if any */
+        /**
+         * {@code null-ok;} local variable associated with this
+         * register, if any
+         */
         private LocalItem local;
 
         /**
          * Set all the instance variables.
          * 
-         * @param reg &gt;= 0; the register number
-         * @param type non-null; the type (or possibly actual value) which
-         * is loaded from or stored to the indicated register
-         * @param local null-ok; the associated local variable, if any
-         * @return non-null; an appropriately-constructed instance
+         * @param reg {@code >= 0;} the register number
+         * @param type {@code non-null;} the type (or possibly actual
+         * value) which is loaded from or stored to the indicated
+         * register
+         * @param local {@code null-ok;} the associated local variable, if any
+         * @return {@code non-null;} an appropriately-constructed instance
          */
         public void set(int reg, TypeBearer type, LocalItem local) {
             this.reg = reg;
@@ -617,10 +621,10 @@
         }
 
         /**
-         * Construct a <code>RegisterSpec</code> of this instance's
+         * Construct a {@code RegisterSpec} of this instance's
          * contents.
          * 
-         * @return non-null; an appropriately-constructed instance
+         * @return {@code non-null;} an appropriately-constructed instance
          */
         public RegisterSpec toRegisterSpec() {
             return new RegisterSpec(reg, type, local);
diff --git a/dx/src/com/android/dx/rop/code/RegisterSpecList.java b/dx/src/com/android/dx/rop/code/RegisterSpecList.java
index 28657a1..5a02a8d 100644
--- a/dx/src/com/android/dx/rop/code/RegisterSpecList.java
+++ b/dx/src/com/android/dx/rop/code/RegisterSpecList.java
@@ -25,14 +25,14 @@
  */
 public final class RegisterSpecList
         extends FixedSizeList implements TypeList {
-    /** non-null; no-element instance */
+    /** {@code non-null;} no-element instance */
     public static final RegisterSpecList EMPTY = new RegisterSpecList(0);
 
     /**
      * Makes a single-element instance.
      * 
-     * @param spec non-null; the element
-     * @return non-null; an appropriately-constructed instance
+     * @param spec {@code non-null;} the element
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public static RegisterSpecList make(RegisterSpec spec) {
         RegisterSpecList result = new RegisterSpecList(1);
@@ -43,9 +43,9 @@
     /**
      * Makes a two-element instance.
      * 
-     * @param spec0 non-null; the first element
-     * @param spec1 non-null; the second element
-     * @return non-null; an appropriately-constructed instance
+     * @param spec0 {@code non-null;} the first element
+     * @param spec1 {@code non-null;} the second element
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public static RegisterSpecList make(RegisterSpec spec0,
                                         RegisterSpec spec1) {
@@ -58,10 +58,10 @@
     /**
      * Makes a three-element instance.
      * 
-     * @param spec0 non-null; the first element
-     * @param spec1 non-null; the second element
-     * @param spec2 non-null; the third element
-     * @return non-null; an appropriately-constructed instance
+     * @param spec0 {@code non-null;} the first element
+     * @param spec1 {@code non-null;} the second element
+     * @param spec2 {@code non-null;} the third element
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public static RegisterSpecList make(RegisterSpec spec0, RegisterSpec spec1,
                                         RegisterSpec spec2) {
@@ -75,11 +75,11 @@
     /**
      * Makes a four-element instance.
      * 
-     * @param spec0 non-null; the first element
-     * @param spec1 non-null; the second element
-     * @param spec2 non-null; the third element
-     * @param spec3 non-null; the fourth element
-     * @return non-null; an appropriately-constructed instance
+     * @param spec0 {@code non-null;} the first element
+     * @param spec1 {@code non-null;} the second element
+     * @param spec2 {@code non-null;} the third element
+     * @param spec3 {@code non-null;} the fourth element
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public static RegisterSpecList make(RegisterSpec spec0, RegisterSpec spec1,
                                         RegisterSpec spec2,
@@ -93,7 +93,7 @@
     }
 
     /**
-     * Constructs an instance. All indices initially contain <code>null</code>.
+     * Constructs an instance. All indices initially contain {@code null}.
      * 
      * @param size the size of the list
      */
@@ -126,10 +126,10 @@
     /**
      * Gets the indicated element. It is an error to call this with the
      * index for an element which was never set; if you do that, this
-     * will throw <code>NullPointerException</code>.
+     * will throw {@code NullPointerException}.
      * 
-     * @param n &gt;= 0, &lt; size(); which element
-     * @return non-null; the indicated element
+     * @param n {@code >= 0, < size();} which element
+     * @return {@code non-null;} the indicated element
      */
     public RegisterSpec get(int n) {
         return (RegisterSpec) get0(n);
@@ -180,8 +180,8 @@
     /**
      * Sets the element at the given index.
      * 
-     * @param n &gt;= 0, &lt; size(); which element
-     * @param spec non-null; the value to store
+     * @param n {@code >= 0, < size();} which element
+     * @param spec {@code non-null;} the value to store
      */
     public void set(int n, RegisterSpec spec) {
         set0(n, spec);
@@ -193,7 +193,7 @@
      * to plus the widest width (largest category) of the type used in
      * that register.
      * 
-     * @return &gt;= 0; the required registers size
+     * @return {@code >= 0;} the required registers size
      */
     public int getRegistersSize() {
         int sz = size();
@@ -217,8 +217,8 @@
      * except that it has an additional element prepended to the original.
      * Mutability of the result is inherited from the original.
      * 
-     * @param spec non-null; the new first spec (to prepend)
-     * @return non-null; an appropriately-constructed instance
+     * @param spec {@code non-null;} the new first spec (to prepend)
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public RegisterSpecList withFirst(RegisterSpec spec) {
         int sz = size();
@@ -241,7 +241,7 @@
      * except that its first element is removed. Mutability of the
      * result is inherited from the original.
      * 
-     * @return non-null; an appropriately-constructed instance
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public RegisterSpecList withoutFirst() {
         int newSize = size() - 1;
@@ -268,7 +268,7 @@
      * except that its last element is removed. Mutability of the
      * result is inherited from the original.
      * 
-     * @return non-null; an appropriately-constructed instance
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public RegisterSpecList withoutLast() {
         int newSize = size() - 1;
@@ -296,7 +296,7 @@
      * of the result is inherited from the original.
      * 
      * @param delta the amount to offset the register numbers by
-     * @return non-null; an appropriately-constructed instance
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public RegisterSpecList withOffset(int delta) {
         int sz = size();
@@ -329,7 +329,7 @@
      * 
      * @param base the base register number
      * @param duplicateFirst whether to duplicate the first number
-     * @return non-null; an appropriately-constructed instance
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public RegisterSpecList withSequentialRegisters(int base,
                                                     boolean duplicateFirst) {
diff --git a/dx/src/com/android/dx/rop/code/RegisterSpecSet.java b/dx/src/com/android/dx/rop/code/RegisterSpecSet.java
index adc77c3..68009d9 100644
--- a/dx/src/com/android/dx/rop/code/RegisterSpecSet.java
+++ b/dx/src/com/android/dx/rop/code/RegisterSpecSet.java
@@ -25,23 +25,23 @@
  */
 public final class RegisterSpecSet
         extends MutabilityControl {
-    /** non-null; no-element instance */
+    /** {@code non-null;} no-element instance */
     public static final RegisterSpecSet EMPTY = new RegisterSpecSet(0);
 
     /**
-     * non-null; array of register specs, where each element is
-     * <code>null</code> or is an instance whose <code>reg</code>
+     * {@code non-null;} array of register specs, where each element is
+     * {@code null} or is an instance whose {@code reg}
      * matches the array index 
      */
     private final RegisterSpec[] specs;
 
-    /** &gt;= -1; size of the set or <code>-1</code> if not yet calculated */
+    /** {@code >= -1;} size of the set or {@code -1} if not yet calculated */
     private int size;
 
     /**
      * Constructs an instance. The instance is initially empty.
      * 
-     * @param maxSize &gt;= 0; the maximum register number (exclusive) that
+     * @param maxSize {@code >= 0;} the maximum register number (exclusive) that
      * may be represented in this instance
      */
     public RegisterSpecSet(int maxSize) {
@@ -127,7 +127,7 @@
      * is also the maximum-plus-one of register numbers that may be
      * represented.
      * 
-     * @return &gt;= 0; the maximum size
+     * @return {@code >= 0;} the maximum size
      */
     public int getMaxSize() {
         return specs.length;
@@ -136,7 +136,7 @@
     /**
      * Gets the current size of this instance.
      * 
-     * @return &gt;= 0; the size
+     * @return {@code >= 0;} the size
      */
     public int size() {
         int result = size;
@@ -160,9 +160,9 @@
     /**
      * Gets the element with the given register number, if any.
      * 
-     * @param reg &gt;= 0; the desired register number
-     * @return null-ok; the element with the given register number or
-     * <code>null</code> if there is none
+     * @param reg {@code >= 0;} the desired register number
+     * @return {@code null-ok;} the element with the given register number or
+     * {@code null} if there is none
      */
     public RegisterSpec get(int reg) {
         try {
@@ -176,11 +176,11 @@
     /**
      * Gets the element with the same register number as the given
      * spec, if any. This is just a convenient shorthand for
-     * <code>get(spec.getReg())</code>.
+     * {@code get(spec.getReg())}.
      * 
-     * @param spec non-null; spec with the desired register number
-     * @return null-ok; the element with the matching register number or
-     * <code>null</code> if there is none
+     * @param spec {@code non-null;} spec with the desired register number
+     * @return {@code null-ok;} the element with the matching register number or
+     * {@code null} if there is none
      */
     public RegisterSpec get(RegisterSpec spec) {
         return get(spec.getReg());
@@ -192,8 +192,8 @@
      * none. This ignores the register number of the given spec but
      * matches on everything else.
      * 
-     * @param spec non-null; local to look for
-     * @return null-ok; first register found that matches, if any
+     * @param spec {@code non-null;} local to look for
+     * @return {@code null-ok;} first register found that matches, if any
      */
     public RegisterSpec findMatchingLocal(RegisterSpec spec) {
         int length = specs.length;
@@ -217,8 +217,8 @@
      * Returns the spec in this set that's currently associated with a given
      * local (name and signature), or {@code null} if there is none.
      *
-     * @param local non-null; local item to search for
-     * @return null-ok; first register found with matching name and signature
+     * @param local {@code non-null;} local item to search for
+     * @return {@code null-ok;} first register found with matching name and signature
      */
     public RegisterSpec localItemToSpec(LocalItem local) {
         int length = specs.length;
@@ -238,7 +238,7 @@
      * Removes a spec from the set. Only the register number
      * of the parameter is significant.
      *
-     * @param toRemove non-null; register to remove.
+     * @param toRemove {@code non-null;} register to remove.
      */
     public void remove(RegisterSpec toRemove) {
         try {
@@ -258,7 +258,7 @@
      * a category-2 register, then the immediately subsequent element
      * is nullified.
      * 
-     * @param spec non-null; the register spec to put in the instance
+     * @param spec {@code non-null;} the register spec to put in the instance
      */
     public void put(RegisterSpec spec) {
         throwIfImmutable();
@@ -293,7 +293,7 @@
     /**
      * Put the entire contents of the given set into this one.
      * 
-     * @param set non-null; the set to put into this instance
+     * @param set {@code non-null;} the set to put into this instance
      */
     public void putAll(RegisterSpecSet set) {
         int max = set.getMaxSize();
@@ -312,11 +312,11 @@
      * {@link RegisterSpec#intersect} of corresponding elements from
      * this instance and the given one where both are non-null.
      * 
-     * @param other non-null; set to intersect with
+     * @param other {@code non-null;} set to intersect with
      * @param localPrimary whether local variables are primary to
-     * the intersection; if <code>true</code>, then the only non-null
+     * the intersection; if {@code true}, then the only non-null
      * result elements occur when registers being intersected have
-     * equal names (or both have <code>null</code> names)
+     * equal names (or both have {@code null} names)
      */
     public void intersect(RegisterSpecSet other, boolean localPrimary) {
         throwIfImmutable();
@@ -352,7 +352,7 @@
      * of the result is inherited from the original.
      * 
      * @param delta the amount to offset the register numbers by
-     * @return non-null; an appropriately-constructed instance
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public RegisterSpecSet withOffset(int delta) {
         int len = specs.length;
@@ -377,7 +377,7 @@
     /**
      * Makes and return a mutable copy of this instance.
      * 
-     * @return non-null; the mutable copy
+     * @return {@code non-null;} the mutable copy
      */
     public RegisterSpecSet mutableCopy() {
         int len = specs.length;
diff --git a/dx/src/com/android/dx/rop/code/Rop.java b/dx/src/com/android/dx/rop/code/Rop.java
index f918e12..fbd9a16 100644
--- a/dx/src/com/android/dx/rop/code/Rop.java
+++ b/dx/src/com/android/dx/rop/code/Rop.java
@@ -25,7 +25,7 @@
  * Class that describes all the immutable parts of register-based operations.
  */
 public final class Rop {
-    /** minimum <code>BRANCH_*</code> value */
+    /** minimum {@code BRANCH_*} value */
     public static final int BRANCH_MIN = 1;
 
     /** indicates a non-branching op */
@@ -46,26 +46,26 @@
     /** indicates a throw-style branch (both always-throws and may-throw) */
     public static final int BRANCH_THROW = 6;
 
-    /** maximum <code>BRANCH_*</code> value */
+    /** maximum {@code BRANCH_*} value */
     public static final int BRANCH_MAX = 6;
 
     /** the opcode; one of the constants in {@link RegOps} */
     private final int opcode;
 
     /**
-     * non-null; result type of this operation; {@link Type#VOID} for
+     * {@code non-null;} result type of this operation; {@link Type#VOID} for
      * no-result operations 
      */
     private final Type result;
 
-    /** non-null; types of all the sources of this operation */
+    /** {@code non-null;} types of all the sources of this operation */
     private final TypeList sources;
 
-    /** non-null; list of possible types thrown by this operation */
+    /** {@code non-null;} list of possible types thrown by this operation */
     private final TypeList exceptions;
 
     /**
-     * the branchingness of this op; one of the <code>BRANCH_*</code>
+     * the branchingness of this op; one of the {@code BRANCH_*}
      * constants in this class 
      */
     private final int branchingness;
@@ -73,7 +73,7 @@
     /** whether this is a function/method call op or similar */
     private final boolean isCallLike;
 
-    /** null-ok; nickname, if specified (used for debugging) */
+    /** {@code null-ok;} nickname, if specified (used for debugging) */
     private final String nickname;
 
     /**
@@ -81,15 +81,15 @@
      * public constructors.
      * 
      * @param opcode the opcode; one of the constants in {@link RegOps}
-     * @param result non-null; result type of this operation; {@link
+     * @param result {@code non-null;} result type of this operation; {@link
      * Type#VOID} for no-result operations
-     * @param sources non-null; types of all the sources of this operation
-     * @param exceptions non-null; list of possible types thrown by this
+     * @param sources {@code non-null;} types of all the sources of this operation
+     * @param exceptions {@code non-null;} list of possible types thrown by this
      * operation
      * @param branchingness the branchingness of this op; one of the
-     * <code>BRANCH_*</code> constants
+     * {@code BRANCH_*} constants
      * @param isCallLike whether the op is a function/method call or similar
-     * @param nickname null-ok; optional nickname (used for debugging)
+     * @param nickname {@code null-ok;} optional nickname (used for debugging)
      */
     public Rop(int opcode, Type result, TypeList sources,
                TypeList exceptions, int branchingness, boolean isCallLike,
@@ -129,14 +129,14 @@
      * call-like op (see {@link #isCallLike}).
      * 
      * @param opcode the opcode; one of the constants in {@link RegOps}
-     * @param result non-null; result type of this operation; {@link
+     * @param result {@code non-null;} result type of this operation; {@link
      * Type#VOID} for no-result operations
-     * @param sources non-null; types of all the sources of this operation
-     * @param exceptions non-null; list of possible types thrown by this
+     * @param sources {@code non-null;} types of all the sources of this operation
+     * @param exceptions {@code non-null;} list of possible types thrown by this
      * operation
      * @param branchingness the branchingness of this op; one of the
-     * <code>BRANCH_*</code> constants
-     * @param nickname null-ok; optional nickname (used for debugging)
+     * {@code BRANCH_*} constants
+     * @param nickname {@code null-ok;} optional nickname (used for debugging)
      */
     public Rop(int opcode, Type result, TypeList sources,
                TypeList exceptions, int branchingness, String nickname) {
@@ -149,12 +149,12 @@
      * call-like op (see {@link #isCallLike}).
      * 
      * @param opcode the opcode; one of the constants in {@link RegOps}
-     * @param result non-null; result type of this operation; {@link
+     * @param result {@code non-null;} result type of this operation; {@link
      * Type#VOID} for no-result operations
-     * @param sources non-null; types of all the sources of this operation
+     * @param sources {@code non-null;} types of all the sources of this operation
      * @param branchingness the branchingness of this op; one of the
-     * <code>BRANCH_*</code> constants
-     * @param nickname null-ok; optional nickname (used for debugging)
+     * {@code BRANCH_*} constants
+     * @param nickname {@code null-ok;} optional nickname (used for debugging)
      */
     public Rop(int opcode, Type result, TypeList sources, int branchingness,
                String nickname) {
@@ -164,14 +164,14 @@
 
     /**
      * Constructs a non-branching no-exception instance. The
-     * <code>branchingness</code> is always <code>BRANCH_NONE</code>,
+     * {@code branchingness} is always {@code BRANCH_NONE},
      * and it is never a call-like op (see {@link #isCallLike}).
      * 
      * @param opcode the opcode; one of the constants in {@link RegOps}
-     * @param result non-null; result type of this operation; {@link
+     * @param result {@code non-null;} result type of this operation; {@link
      * Type#VOID} for no-result operations
-     * @param sources non-null; types of all the sources of this operation
-     * @param nickname null-ok; optional nickname (used for debugging)
+     * @param sources {@code non-null;} types of all the sources of this operation
+     * @param nickname {@code null-ok;} optional nickname (used for debugging)
      */
     public Rop(int opcode, Type result, TypeList sources, String nickname) {
         this(opcode, result, sources, StdTypeList.EMPTY, Rop.BRANCH_NONE,
@@ -180,16 +180,16 @@
 
     /**
      * Constructs a non-empty exceptions instance. Its
-     * <code>branchingness</code> is always <code>BRANCH_THROW</code>,
+     * {@code branchingness} is always {@code BRANCH_THROW},
      * but it is never a call-like op (see {@link #isCallLike}).
      * 
      * @param opcode the opcode; one of the constants in {@link RegOps}
-     * @param result non-null; result type of this operation; {@link
+     * @param result {@code non-null;} result type of this operation; {@link
      * Type#VOID} for no-result operations
-     * @param sources non-null; types of all the sources of this operation
-     * @param exceptions non-null; list of possible types thrown by this
+     * @param sources {@code non-null;} types of all the sources of this operation
+     * @param exceptions {@code non-null;} list of possible types thrown by this
      * operation
-     * @param nickname null-ok; optional nickname (used for debugging)
+     * @param nickname {@code null-ok;} optional nickname (used for debugging)
      */
     public Rop(int opcode, Type result, TypeList sources, TypeList exceptions,
                String nickname) {
@@ -200,11 +200,11 @@
     /**
      * Constructs a non-nicknamed instance with non-empty exceptions, which
      * is always a call-like op (see {@link #isCallLike}). Its
-     * <code>branchingness</code> is always <code>BRANCH_THROW</code>.
+     * {@code branchingness} is always {@code BRANCH_THROW}.
      * 
      * @param opcode the opcode; one of the constants in {@link RegOps}
-     * @param sources non-null; types of all the sources of this operation
-     * @param exceptions non-null; list of possible types thrown by this
+     * @param sources {@code non-null;} types of all the sources of this operation
+     * @param exceptions {@code non-null;} list of possible types thrown by this
      * operation
      */
     public Rop(int opcode, TypeList sources, TypeList exceptions) {
@@ -317,7 +317,7 @@
      * Gets the result type. A return value of {@link Type#VOID}
      * means this operation returns nothing.
      * 
-     * @return null-ok; the result spec
+     * @return {@code null-ok;} the result spec
      */
     public Type getResult() {
         return result;
@@ -326,7 +326,7 @@
     /**
      * Gets the source types.
      * 
-     * @return non-null; the source types
+     * @return {@code non-null;} the source types
      */
     public TypeList getSources() {
         return sources;
@@ -335,7 +335,7 @@
     /**
      * Gets the list of exception types that might be thrown.
      * 
-     * @return non-null; the list of exception types
+     * @return {@code non-null;} the list of exception types
      */
     public TypeList getExceptions() {
         return exceptions;
@@ -353,7 +353,7 @@
     /**
      * Gets whether this opcode is a function/method call or similar.
      * 
-     * @return <code>true</code> iff this opcode is call-like
+     * @return {@code true} iff this opcode is call-like
      */
     public boolean isCallLike() {
         return isCallLike;
@@ -384,7 +384,7 @@
      * Gets the nickname. If this instance has no nickname, this returns
      * the result of calling {@link #toString}.
      * 
-     * @return non-null; the nickname
+     * @return {@code non-null;} the nickname
      */
     public String getNickname() {
         if (nickname != null) {
@@ -397,9 +397,9 @@
     /**
      * Gets whether this operation can possibly throw an exception. This
      * is just a convenient wrapper for
-     * <code>getExceptions().size() != 0</code>.
+     * {@code getExceptions().size() != 0}.
      * 
-     * @return <code>true</code> iff this operation can possibly throw
+     * @return {@code true} iff this operation can possibly throw
      */
     public final boolean canThrow() {
         return (exceptions.size() != 0);
diff --git a/dx/src/com/android/dx/rop/code/RopMethod.java b/dx/src/com/android/dx/rop/code/RopMethod.java
index 0c0d8f1..3957532 100644
--- a/dx/src/com/android/dx/rop/code/RopMethod.java
+++ b/dx/src/com/android/dx/rop/code/RopMethod.java
@@ -24,20 +24,20 @@
  * All of the parts that make up a method at the rop layer.
  */
 public final class RopMethod {
-    /** non-null; basic block list of the method */
+    /** {@code non-null;} basic block list of the method */
     private final BasicBlockList blocks;
 
-    /** &gt;= 0; label for the block which starts the method */
+    /** {@code >= 0;} label for the block which starts the method */
     private final int firstLabel;
 
     /**
-     * null-ok; array of predecessors for each block, indexed by block
+     * {@code null-ok;} array of predecessors for each block, indexed by block
      * label 
      */
     private IntList[] predecessors;
 
     /**
-     * null-ok; the predecessors for the implicit "exit" block, that is
+     * {@code null-ok;} the predecessors for the implicit "exit" block, that is
      * the labels for the blocks that return, if calculated 
      */
     private IntList exitPredecessors;
@@ -45,8 +45,8 @@
     /**
      * Constructs an instance.
      * 
-     * @param blocks non-null; basic block list of the method
-     * @param firstLabel &gt;= 0; the label of the first block to execute
+     * @param blocks {@code non-null;} basic block list of the method
+     * @param firstLabel {@code >= 0;} the label of the first block to execute
      */
     public RopMethod(BasicBlockList blocks, int firstLabel) {
         if (blocks == null) {
@@ -67,7 +67,7 @@
     /**
      * Gets the basic block list for this method.
      * 
-     * @return non-null; the list
+     * @return {@code non-null;} the list
      */
     public BasicBlockList getBlocks() {
         return blocks;
@@ -77,7 +77,7 @@
      * Gets the label for the first block in the method that this list
      * represents.
      * 
-     * @return &gt;= 0; the first-block label
+     * @return {@code >= 0;} the first-block label
      */
     public int getFirstLabel() {
         return firstLabel;
@@ -87,8 +87,8 @@
      * Gets the predecessors associated with the given block. This throws
      * an exception if there is no block with the given label.
      * 
-     * @param label &gt;= 0; the label of the block in question
-     * @return non-null; the predecessors of that block
+     * @param label {@code >= 0;} the label of the block in question
+     * @return {@code non-null;} the predecessors of that block
      */
     public IntList labelToPredecessors(int label) {
         if (exitPredecessors == null) {
@@ -107,7 +107,7 @@
     /**
      * Gets the exit predecessors for this instance.
      * 
-     * @return non-null; the exit predecessors
+     * @return {@code non-null;} the exit predecessors
      */
     public IntList getExitPredecessors() {
         if (exitPredecessors == null) {
@@ -124,7 +124,7 @@
      * amount.
      * 
      * @param delta the amount to offset register numbers by
-     * @return non-null; an appropriately-constructed instance
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public RopMethod withRegisterOffset(int delta) {
         RopMethod result = new RopMethod(blocks.withRegisterOffset(delta),
diff --git a/dx/src/com/android/dx/rop/code/Rops.java b/dx/src/com/android/dx/rop/code/Rops.java
index b662656..15c2e17 100644
--- a/dx/src/com/android/dx/rop/code/Rops.java
+++ b/dx/src/com/android/dx/rop/code/Rops.java
@@ -30,32 +30,32 @@
  * Standard instances of {@link Rop}.
  */
 public final class Rops {
-    /** <code>nop()</code> */
+    /** {@code nop()} */
     public static final Rop NOP =
         new Rop(RegOps.NOP, Type.VOID, StdTypeList.EMPTY, "nop");
 
-    /** <code>r,x: int :: r = x;</code> */
+    /** {@code r,x: int :: r = x;} */
     public static final Rop MOVE_INT =
         new Rop(RegOps.MOVE, Type.INT, StdTypeList.INT, "move-int");
 
-    /** <code>r,x: long :: r = x;</code> */
+    /** {@code r,x: long :: r = x;} */
     public static final Rop MOVE_LONG =
         new Rop(RegOps.MOVE, Type.LONG, StdTypeList.LONG, "move-long");
 
-    /** <code>r,x: float :: r = x;</code> */
+    /** {@code r,x: float :: r = x;} */
     public static final Rop MOVE_FLOAT =
         new Rop(RegOps.MOVE, Type.FLOAT, StdTypeList.FLOAT, "move-float");
 
-    /** <code>r,x: double :: r = x;</code> */
+    /** {@code r,x: double :: r = x;} */
     public static final Rop MOVE_DOUBLE =
         new Rop(RegOps.MOVE, Type.DOUBLE, StdTypeList.DOUBLE, "move-double");
 
-    /** <code>r,x: Object :: r = x;</code> */
+    /** {@code r,x: Object :: r = x;} */
     public static final Rop MOVE_OBJECT =
         new Rop(RegOps.MOVE, Type.OBJECT, StdTypeList.OBJECT, "move-object");
 
     /**
-     * <code>r,x: ReturnAddress :: r = x;</code>
+     * {@code r,x: ReturnAddress :: r = x;}
      *
      * Note that this rop-form instruction has no dex-form equivilent and
      * must be removed before the dex conversion.
@@ -64,756 +64,756 @@
         new Rop(RegOps.MOVE, Type.RETURN_ADDRESS,
                 StdTypeList.RETURN_ADDRESS, "move-return-address");
 
-    /** <code>r,param(x): int :: r = param(x);</code> */
+    /** {@code r,param(x): int :: r = param(x);} */
     public static final Rop MOVE_PARAM_INT =
         new Rop(RegOps.MOVE_PARAM, Type.INT, StdTypeList.EMPTY,
                 "move-param-int");
 
-    /** <code>r,param(x): long :: r = param(x);</code> */
+    /** {@code r,param(x): long :: r = param(x);} */
     public static final Rop MOVE_PARAM_LONG =
         new Rop(RegOps.MOVE_PARAM, Type.LONG, StdTypeList.EMPTY,
                 "move-param-long");
 
-    /** <code>r,param(x): float :: r = param(x);</code> */
+    /** {@code r,param(x): float :: r = param(x);} */
     public static final Rop MOVE_PARAM_FLOAT =
         new Rop(RegOps.MOVE_PARAM, Type.FLOAT, StdTypeList.EMPTY,
                 "move-param-float");
 
-    /** <code>r,param(x): double :: r = param(x);</code> */
+    /** {@code r,param(x): double :: r = param(x);} */
     public static final Rop MOVE_PARAM_DOUBLE =
         new Rop(RegOps.MOVE_PARAM, Type.DOUBLE, StdTypeList.EMPTY,
                 "move-param-double");
 
-    /** <code>r,param(x): Object :: r = param(x);</code> */
+    /** {@code r,param(x): Object :: r = param(x);} */
     public static final Rop MOVE_PARAM_OBJECT =
         new Rop(RegOps.MOVE_PARAM, Type.OBJECT, StdTypeList.EMPTY,
                 "move-param-object");
 
-    /** <code>r, literal: int :: r = literal;</code> */
+    /** {@code r, literal: int :: r = literal;} */
     public static final Rop CONST_INT =
         new Rop(RegOps.CONST, Type.INT, StdTypeList.EMPTY, "const-int");
 
-    /** <code>r, literal: long :: r = literal;</code> */
+    /** {@code r, literal: long :: r = literal;} */
     public static final Rop CONST_LONG =
         new Rop(RegOps.CONST, Type.LONG, StdTypeList.EMPTY, "const-long");
 
-    /** <code>r, literal: float :: r = literal;</code> */
+    /** {@code r, literal: float :: r = literal;} */
     public static final Rop CONST_FLOAT =
         new Rop(RegOps.CONST, Type.FLOAT, StdTypeList.EMPTY, "const-float");
 
-    /** <code>r, literal: double :: r = literal;</code> */
+    /** {@code r, literal: double :: r = literal;} */
     public static final Rop CONST_DOUBLE =
         new Rop(RegOps.CONST, Type.DOUBLE, StdTypeList.EMPTY, "const-double");
 
-    /** <code>r, literal: Object :: r = literal;</code> */
+    /** {@code r, literal: Object :: r = literal;} */
     public static final Rop CONST_OBJECT =
         new Rop(RegOps.CONST, Type.OBJECT, StdTypeList.EMPTY,
                 Exceptions.LIST_Error, "const-object");
 
-    /** <code>r, literal: Object :: r = literal;</code> */
+    /** {@code r, literal: Object :: r = literal;} */
     public static final Rop CONST_OBJECT_NOTHROW =
         new Rop(RegOps.CONST, Type.OBJECT, StdTypeList.EMPTY,
                 "const-object-nothrow");
 
-    /** <code>goto <i>label</i></code> */
+    /** {@code goto label} */
     public static final Rop GOTO =
         new Rop(RegOps.GOTO, Type.VOID, StdTypeList.EMPTY, Rop.BRANCH_GOTO,
                 "goto");
 
-    /** <code>x: int :: if (x == 0) goto <i>label</i></code> */
+    /** {@code x: int :: if (x == 0) goto label} */
     public static final Rop IF_EQZ_INT =
         new Rop(RegOps.IF_EQ, Type.VOID, StdTypeList.INT, Rop.BRANCH_IF,
                 "if-eqz-int");
 
-    /** <code>x: int :: if (x != 0) goto <i>label</i></code> */
+    /** {@code x: int :: if (x != 0) goto label} */
     public static final Rop IF_NEZ_INT =
         new Rop(RegOps.IF_NE, Type.VOID, StdTypeList.INT, Rop.BRANCH_IF,
                 "if-nez-int");
 
-    /** <code>x: int :: if (x &lt; 0) goto <i>label</i></code> */
+    /** {@code x: int :: if (x < 0) goto label} */
     public static final Rop IF_LTZ_INT =
         new Rop(RegOps.IF_LT, Type.VOID, StdTypeList.INT, Rop.BRANCH_IF,
                 "if-ltz-int");
 
-    /** <code>x: int :: if (x &gt;= 0) goto <i>label</i></code> */
+    /** {@code x: int :: if (x >= 0) goto label} */
     public static final Rop IF_GEZ_INT =
         new Rop(RegOps.IF_GE, Type.VOID, StdTypeList.INT, Rop.BRANCH_IF,
                 "if-gez-int");
 
-    /** <code>x: int :: if (x &lt;= 0) goto <i>label</i></code> */
+    /** {@code x: int :: if (x <= 0) goto label} */
     public static final Rop IF_LEZ_INT =
         new Rop(RegOps.IF_LE, Type.VOID, StdTypeList.INT, Rop.BRANCH_IF,
                 "if-lez-int");
 
-    /** <code>x: int :: if (x &gt; 0) goto <i>label</i></code> */
+    /** {@code x: int :: if (x > 0) goto label} */
     public static final Rop IF_GTZ_INT =
         new Rop(RegOps.IF_GT, Type.VOID, StdTypeList.INT, Rop.BRANCH_IF,
                 "if-gtz-int");
 
-    /** <code>x: Object :: if (x == null) goto <i>label</i></code> */
+    /** {@code x: Object :: if (x == null) goto label} */
     public static final Rop IF_EQZ_OBJECT =
         new Rop(RegOps.IF_EQ, Type.VOID, StdTypeList.OBJECT, Rop.BRANCH_IF,
                 "if-eqz-object");
 
-    /** <code>x: Object :: if (x != null) goto <i>label</i></code> */
+    /** {@code x: Object :: if (x != null) goto label} */
     public static final Rop IF_NEZ_OBJECT =
         new Rop(RegOps.IF_NE, Type.VOID, StdTypeList.OBJECT, Rop.BRANCH_IF,
                 "if-nez-object");
 
-    /** <code>x,y: int :: if (x == y) goto <i>label</i></code> */
+    /** {@code x,y: int :: if (x == y) goto label} */
     public static final Rop IF_EQ_INT =
         new Rop(RegOps.IF_EQ, Type.VOID, StdTypeList.INT_INT, Rop.BRANCH_IF,
                 "if-eq-int");
 
-    /** <code>x,y: int :: if (x != y) goto <i>label</i></code> */
+    /** {@code x,y: int :: if (x != y) goto label} */
     public static final Rop IF_NE_INT =
         new Rop(RegOps.IF_NE, Type.VOID, StdTypeList.INT_INT, Rop.BRANCH_IF,
                 "if-ne-int");
 
-    /** <code>x,y: int :: if (x &lt; y) goto <i>label</i></code> */
+    /** {@code x,y: int :: if (x < y) goto label} */
     public static final Rop IF_LT_INT =
         new Rop(RegOps.IF_LT, Type.VOID, StdTypeList.INT_INT, Rop.BRANCH_IF,
                 "if-lt-int");
 
-    /** <code>x,y: int :: if (x &gt;= y) goto <i>label</i></code> */
+    /** {@code x,y: int :: if (x >= y) goto label} */
     public static final Rop IF_GE_INT =
         new Rop(RegOps.IF_GE, Type.VOID, StdTypeList.INT_INT, Rop.BRANCH_IF,
                 "if-ge-int");
 
-    /** <code>x,y: int :: if (x &lt;= y) goto <i>label</i></code> */
+    /** {@code x,y: int :: if (x <= y) goto label} */
     public static final Rop IF_LE_INT =
         new Rop(RegOps.IF_LE, Type.VOID, StdTypeList.INT_INT, Rop.BRANCH_IF,
                 "if-le-int");
 
-    /** <code>x,y: int :: if (x &gt; y) goto <i>label</i></code> */
+    /** {@code x,y: int :: if (x > y) goto label} */
     public static final Rop IF_GT_INT =
         new Rop(RegOps.IF_GT, Type.VOID, StdTypeList.INT_INT, Rop.BRANCH_IF,
                 "if-gt-int");
 
-    /** <code>x,y: Object :: if (x == y) goto <i>label</i></code> */
+    /** {@code x,y: Object :: if (x == y) goto label} */
     public static final Rop IF_EQ_OBJECT =
         new Rop(RegOps.IF_EQ, Type.VOID, StdTypeList.OBJECT_OBJECT,
                 Rop.BRANCH_IF, "if-eq-object");
 
-    /** <code>x,y: Object :: if (x != y) goto <i>label</i></code> */
+    /** {@code x,y: Object :: if (x != y) goto label} */
     public static final Rop IF_NE_OBJECT =
         new Rop(RegOps.IF_NE, Type.VOID, StdTypeList.OBJECT_OBJECT,
                 Rop.BRANCH_IF, "if-ne-object");
 
-    /** <code>x: int :: goto switchtable[x]</code> */
+    /** {@code x: int :: goto switchtable[x]} */
     public static final Rop SWITCH = 
         new Rop(RegOps.SWITCH, Type.VOID, StdTypeList.INT, Rop.BRANCH_SWITCH,
                 "switch");
 
-    /** <code>r,x,y: int :: r = x + y;</code> */
+    /** {@code r,x,y: int :: r = x + y;} */
     public static final Rop ADD_INT =
         new Rop(RegOps.ADD, Type.INT, StdTypeList.INT_INT, "add-int");
 
-    /** <code>r,x,y: long :: r = x + y;</code> */
+    /** {@code r,x,y: long :: r = x + y;} */
     public static final Rop ADD_LONG =
         new Rop(RegOps.ADD, Type.LONG, StdTypeList.LONG_LONG, "add-long");
 
-    /** <code>r,x,y: float :: r = x + y;</code> */
+    /** {@code r,x,y: float :: r = x + y;} */
     public static final Rop ADD_FLOAT =
         new Rop(RegOps.ADD, Type.FLOAT, StdTypeList.FLOAT_FLOAT, "add-float");
 
-    /** <code>r,x,y: double :: r = x + y;</code> */
+    /** {@code r,x,y: double :: r = x + y;} */
     public static final Rop ADD_DOUBLE =
         new Rop(RegOps.ADD, Type.DOUBLE, StdTypeList.DOUBLE_DOUBLE,
                 Rop.BRANCH_NONE, "add-double");
 
-    /** <code>r,x,y: int :: r = x - y;</code> */
+    /** {@code r,x,y: int :: r = x - y;} */
     public static final Rop SUB_INT =
         new Rop(RegOps.SUB, Type.INT, StdTypeList.INT_INT, "sub-int");
 
-    /** <code>r,x,y: long :: r = x - y;</code> */
+    /** {@code r,x,y: long :: r = x - y;} */
     public static final Rop SUB_LONG =
         new Rop(RegOps.SUB, Type.LONG, StdTypeList.LONG_LONG, "sub-long");
 
-    /** <code>r,x,y: float :: r = x - y;</code> */
+    /** {@code r,x,y: float :: r = x - y;} */
     public static final Rop SUB_FLOAT =
         new Rop(RegOps.SUB, Type.FLOAT, StdTypeList.FLOAT_FLOAT, "sub-float");
 
-    /** <code>r,x,y: double :: r = x - y;</code> */
+    /** {@code r,x,y: double :: r = x - y;} */
     public static final Rop SUB_DOUBLE =
         new Rop(RegOps.SUB, Type.DOUBLE, StdTypeList.DOUBLE_DOUBLE,
                 Rop.BRANCH_NONE, "sub-double");
 
-    /** <code>r,x,y: int :: r = x * y;</code> */
+    /** {@code r,x,y: int :: r = x * y;} */
     public static final Rop MUL_INT =
         new Rop(RegOps.MUL, Type.INT, StdTypeList.INT_INT, "mul-int");
 
-    /** <code>r,x,y: long :: r = x * y;</code> */
+    /** {@code r,x,y: long :: r = x * y;} */
     public static final Rop MUL_LONG =
         new Rop(RegOps.MUL, Type.LONG, StdTypeList.LONG_LONG, "mul-long");
 
-    /** <code>r,x,y: float :: r = x * y;</code> */
+    /** {@code r,x,y: float :: r = x * y;} */
     public static final Rop MUL_FLOAT =
         new Rop(RegOps.MUL, Type.FLOAT, StdTypeList.FLOAT_FLOAT, "mul-float");
 
-    /** <code>r,x,y: double :: r = x * y;</code> */
+    /** {@code r,x,y: double :: r = x * y;} */
     public static final Rop MUL_DOUBLE =
         new Rop(RegOps.MUL, Type.DOUBLE, StdTypeList.DOUBLE_DOUBLE,
                 Rop.BRANCH_NONE, "mul-double");
 
-    /** <code>r,x,y: int :: r = x / y;</code> */
+    /** {@code r,x,y: int :: r = x / y;} */
     public static final Rop DIV_INT =
         new Rop(RegOps.DIV, Type.INT, StdTypeList.INT_INT,
                 Exceptions.LIST_Error_ArithmeticException, "div-int");
 
-    /** <code>r,x,y: long :: r = x / y;</code> */
+    /** {@code r,x,y: long :: r = x / y;} */
     public static final Rop DIV_LONG =
         new Rop(RegOps.DIV, Type.LONG, StdTypeList.LONG_LONG,
                 Exceptions.LIST_Error_ArithmeticException, "div-long");
 
-    /** <code>r,x,y: float :: r = x / y;</code> */
+    /** {@code r,x,y: float :: r = x / y;} */
     public static final Rop DIV_FLOAT =
         new Rop(RegOps.DIV, Type.FLOAT, StdTypeList.FLOAT_FLOAT, "div-float");
 
-    /** <code>r,x,y: double :: r = x / y;</code> */
+    /** {@code r,x,y: double :: r = x / y;} */
     public static final Rop DIV_DOUBLE =
         new Rop(RegOps.DIV, Type.DOUBLE, StdTypeList.DOUBLE_DOUBLE,
                 "div-double");
 
-    /** <code>r,x,y: int :: r = x % y;</code> */
+    /** {@code r,x,y: int :: r = x % y;} */
     public static final Rop REM_INT =
         new Rop(RegOps.REM, Type.INT, StdTypeList.INT_INT,
                 Exceptions.LIST_Error_ArithmeticException, "rem-int");
 
-    /** <code>r,x,y: long :: r = x % y;</code> */
+    /** {@code r,x,y: long :: r = x % y;} */
     public static final Rop REM_LONG =
         new Rop(RegOps.REM, Type.LONG, StdTypeList.LONG_LONG,
                 Exceptions.LIST_Error_ArithmeticException, "rem-long");
 
-    /** <code>r,x,y: float :: r = x % y;</code> */
+    /** {@code r,x,y: float :: r = x % y;} */
     public static final Rop REM_FLOAT =
         new Rop(RegOps.REM, Type.FLOAT, StdTypeList.FLOAT_FLOAT, "rem-float");
 
-    /** <code>r,x,y: double :: r = x % y;</code> */
+    /** {@code r,x,y: double :: r = x % y;} */
     public static final Rop REM_DOUBLE =
         new Rop(RegOps.REM, Type.DOUBLE, StdTypeList.DOUBLE_DOUBLE,
                 "rem-double");
 
-    /** <code>r,x: int :: r = -x;</code> */
+    /** {@code r,x: int :: r = -x;} */
     public static final Rop NEG_INT =
         new Rop(RegOps.NEG, Type.INT, StdTypeList.INT, "neg-int");
 
-    /** <code>r,x: long :: r = -x;</code> */
+    /** {@code r,x: long :: r = -x;} */
     public static final Rop NEG_LONG =
         new Rop(RegOps.NEG, Type.LONG, StdTypeList.LONG, "neg-long");
 
-    /** <code>r,x: float :: r = -x;</code> */
+    /** {@code r,x: float :: r = -x;} */
     public static final Rop NEG_FLOAT =
         new Rop(RegOps.NEG, Type.FLOAT, StdTypeList.FLOAT, "neg-float");
 
-    /** <code>r,x: double :: r = -x;</code> */
+    /** {@code r,x: double :: r = -x;} */
     public static final Rop NEG_DOUBLE =
         new Rop(RegOps.NEG, Type.DOUBLE, StdTypeList.DOUBLE, "neg-double");
 
-    /** <code>r,x,y: int :: r = x &amp; y;</code> */
+    /** {@code r,x,y: int :: r = x & y;} */
     public static final Rop AND_INT =
         new Rop(RegOps.AND, Type.INT, StdTypeList.INT_INT, "and-int");
 
-    /** <code>r,x,y: long :: r = x &amp; y;</code> */
+    /** {@code r,x,y: long :: r = x & y;} */
     public static final Rop AND_LONG =
         new Rop(RegOps.AND, Type.LONG, StdTypeList.LONG_LONG, "and-long");
 
-    /** <code>r,x,y: int :: r = x | y;</code> */
+    /** {@code r,x,y: int :: r = x | y;} */
     public static final Rop OR_INT =
         new Rop(RegOps.OR, Type.INT, StdTypeList.INT_INT, "or-int");
 
-    /** <code>r,x,y: long :: r = x | y;</code> */
+    /** {@code r,x,y: long :: r = x | y;} */
     public static final Rop OR_LONG =
         new Rop(RegOps.OR, Type.LONG, StdTypeList.LONG_LONG, "or-long");
 
-    /** <code>r,x,y: int :: r = x ^ y;</code> */
+    /** {@code r,x,y: int :: r = x ^ y;} */
     public static final Rop XOR_INT =
         new Rop(RegOps.XOR, Type.INT, StdTypeList.INT_INT, "xor-int");
 
-    /** <code>r,x,y: long :: r = x ^ y;</code> */
+    /** {@code r,x,y: long :: r = x ^ y;} */
     public static final Rop XOR_LONG =
         new Rop(RegOps.XOR, Type.LONG, StdTypeList.LONG_LONG, "xor-long");
 
-    /** <code>r,x,y: int :: r = x &lt;&lt; y;</code> */
+    /** {@code r,x,y: int :: r = x << y;} */
     public static final Rop SHL_INT =
         new Rop(RegOps.SHL, Type.INT, StdTypeList.INT_INT, "shl-int");
 
-    /** <code>r,x: long; y: int :: r = x &lt;&lt; y;</code> */
+    /** {@code r,x: long; y: int :: r = x << y;} */
     public static final Rop SHL_LONG =
         new Rop(RegOps.SHL, Type.LONG, StdTypeList.LONG_INT, "shl-long");
 
-    /** <code>r,x,y: int :: r = x &gt;&gt; y;</code> */
+    /** {@code r,x,y: int :: r = x >> y;} */
     public static final Rop SHR_INT =
         new Rop(RegOps.SHR, Type.INT, StdTypeList.INT_INT, "shr-int");
 
-    /** <code>r,x: long; y: int :: r = x &gt;&gt; y;</code> */
+    /** {@code r,x: long; y: int :: r = x >> y;} */
     public static final Rop SHR_LONG =
         new Rop(RegOps.SHR, Type.LONG, StdTypeList.LONG_INT, "shr-long");
 
-    /** <code>r,x,y: int :: r = x &gt;&gt;&gt; y;</code> */
+    /** {@code r,x,y: int :: r = x >>> y;} */
     public static final Rop USHR_INT =
         new Rop(RegOps.USHR, Type.INT, StdTypeList.INT_INT, "ushr-int");
 
-    /** <code>r,x: long; y: int :: r = x &gt;&gt;&gt; y;</code> */
+    /** {@code r,x: long; y: int :: r = x >>> y;} */
     public static final Rop USHR_LONG =
         new Rop(RegOps.USHR, Type.LONG, StdTypeList.LONG_INT, "ushr-long");
 
-    /** <code>r,x: int :: r = ~x;</code> */
+    /** {@code r,x: int :: r = ~x;} */
     public static final Rop NOT_INT =
         new Rop(RegOps.NOT, Type.INT, StdTypeList.INT, "not-int");
 
-    /** <code>r,x: long :: r = ~x;</code> */
+    /** {@code r,x: long :: r = ~x;} */
     public static final Rop NOT_LONG =
         new Rop(RegOps.NOT, Type.LONG, StdTypeList.LONG, "not-long");
 
-    /** <code>r,x,c: int :: r = x + c;</code> */
+    /** {@code r,x,c: int :: r = x + c;} */
     public static final Rop ADD_CONST_INT =
         new Rop(RegOps.ADD, Type.INT, StdTypeList.INT, "add-const-int");
 
-    /** <code>r,x,c: long :: r = x + c;</code> */
+    /** {@code r,x,c: long :: r = x + c;} */
     public static final Rop ADD_CONST_LONG =
         new Rop(RegOps.ADD, Type.LONG, StdTypeList.LONG, "add-const-long");
 
-    /** <code>r,x,c: float :: r = x + c;</code> */
+    /** {@code r,x,c: float :: r = x + c;} */
     public static final Rop ADD_CONST_FLOAT =
         new Rop(RegOps.ADD, Type.FLOAT, StdTypeList.FLOAT, "add-const-float");
 
-    /** <code>r,x,c: double :: r = x + c;</code> */
+    /** {@code r,x,c: double :: r = x + c;} */
     public static final Rop ADD_CONST_DOUBLE =
         new Rop(RegOps.ADD, Type.DOUBLE, StdTypeList.DOUBLE,
                 "add-const-double");
 
-    /** <code>r,x,c: int :: r = x - c;</code> */
+    /** {@code r,x,c: int :: r = x - c;} */
     public static final Rop SUB_CONST_INT =
         new Rop(RegOps.SUB, Type.INT, StdTypeList.INT, "sub-const-int");
 
-    /** <code>r,x,c: long :: r = x - c;</code> */
+    /** {@code r,x,c: long :: r = x - c;} */
     public static final Rop SUB_CONST_LONG =
         new Rop(RegOps.SUB, Type.LONG, StdTypeList.LONG, "sub-const-long");
 
-    /** <code>r,x,c: float :: r = x - c;</code> */
+    /** {@code r,x,c: float :: r = x - c;} */
     public static final Rop SUB_CONST_FLOAT =
         new Rop(RegOps.SUB, Type.FLOAT, StdTypeList.FLOAT, "sub-const-float");
 
-    /** <code>r,x,c: double :: r = x - c;</code> */
+    /** {@code r,x,c: double :: r = x - c;} */
     public static final Rop SUB_CONST_DOUBLE =
         new Rop(RegOps.SUB, Type.DOUBLE, StdTypeList.DOUBLE,
                 "sub-const-double");
 
-    /** <code>r,x,c: int :: r = x * c;</code> */
+    /** {@code r,x,c: int :: r = x * c;} */
     public static final Rop MUL_CONST_INT =
         new Rop(RegOps.MUL, Type.INT, StdTypeList.INT, "mul-const-int");
 
-    /** <code>r,x,c: long :: r = x * c;</code> */
+    /** {@code r,x,c: long :: r = x * c;} */
     public static final Rop MUL_CONST_LONG =
         new Rop(RegOps.MUL, Type.LONG, StdTypeList.LONG, "mul-const-long");
 
-    /** <code>r,x,c: float :: r = x * c;</code> */
+    /** {@code r,x,c: float :: r = x * c;} */
     public static final Rop MUL_CONST_FLOAT =
         new Rop(RegOps.MUL, Type.FLOAT, StdTypeList.FLOAT, "mul-const-float");
 
-    /** <code>r,x,c: double :: r = x * c;</code> */
+    /** {@code r,x,c: double :: r = x * c;} */
     public static final Rop MUL_CONST_DOUBLE =
         new Rop(RegOps.MUL, Type.DOUBLE, StdTypeList.DOUBLE,
                 "mul-const-double");
 
-    /** <code>r,x,c: int :: r = x / c;</code> */
+    /** {@code r,x,c: int :: r = x / c;} */
     public static final Rop DIV_CONST_INT =
         new Rop(RegOps.DIV, Type.INT, StdTypeList.INT,
                 Exceptions.LIST_Error_ArithmeticException, "div-const-int");
 
-    /** <code>r,x,c: long :: r = x / c;</code> */
+    /** {@code r,x,c: long :: r = x / c;} */
     public static final Rop DIV_CONST_LONG =
         new Rop(RegOps.DIV, Type.LONG, StdTypeList.LONG,
                 Exceptions.LIST_Error_ArithmeticException, "div-const-long");
 
-    /** <code>r,x,c: float :: r = x / c;</code> */
+    /** {@code r,x,c: float :: r = x / c;} */
     public static final Rop DIV_CONST_FLOAT =
         new Rop(RegOps.DIV, Type.FLOAT, StdTypeList.FLOAT, "div-const-float");
 
-    /** <code>r,x,c: double :: r = x / c;</code> */
+    /** {@code r,x,c: double :: r = x / c;} */
     public static final Rop DIV_CONST_DOUBLE =
         new Rop(RegOps.DIV, Type.DOUBLE, StdTypeList.DOUBLE,
                 "div-const-double");
 
-    /** <code>r,x,c: int :: r = x % c;</code> */
+    /** {@code r,x,c: int :: r = x % c;} */
     public static final Rop REM_CONST_INT =
         new Rop(RegOps.REM, Type.INT, StdTypeList.INT,
                 Exceptions.LIST_Error_ArithmeticException, "rem-const-int");
 
-    /** <code>r,x,c: long :: r = x % c;</code> */
+    /** {@code r,x,c: long :: r = x % c;} */
     public static final Rop REM_CONST_LONG =
         new Rop(RegOps.REM, Type.LONG, StdTypeList.LONG,
                 Exceptions.LIST_Error_ArithmeticException, "rem-const-long");
 
-    /** <code>r,x,c: float :: r = x % c;</code> */
+    /** {@code r,x,c: float :: r = x % c;} */
     public static final Rop REM_CONST_FLOAT =
         new Rop(RegOps.REM, Type.FLOAT, StdTypeList.FLOAT, "rem-const-float");
 
-    /** <code>r,x,c: double :: r = x % c;</code> */
+    /** {@code r,x,c: double :: r = x % c;} */
     public static final Rop REM_CONST_DOUBLE =
         new Rop(RegOps.REM, Type.DOUBLE, StdTypeList.DOUBLE,
                 "rem-const-double");
 
-    /** <code>r,x,c: int :: r = x &amp; c;</code> */
+    /** {@code r,x,c: int :: r = x & c;} */
     public static final Rop AND_CONST_INT =
         new Rop(RegOps.AND, Type.INT, StdTypeList.INT, "and-const-int");
 
-    /** <code>r,x,c: long :: r = x &amp; c;</code> */
+    /** {@code r,x,c: long :: r = x & c;} */
     public static final Rop AND_CONST_LONG =
         new Rop(RegOps.AND, Type.LONG, StdTypeList.LONG, "and-const-long");
 
-    /** <code>r,x,c: int :: r = x | c;</code> */
+    /** {@code r,x,c: int :: r = x | c;} */
     public static final Rop OR_CONST_INT =
         new Rop(RegOps.OR, Type.INT, StdTypeList.INT, "or-const-int");
 
-    /** <code>r,x,c: long :: r = x | c;</code> */
+    /** {@code r,x,c: long :: r = x | c;} */
     public static final Rop OR_CONST_LONG =
         new Rop(RegOps.OR, Type.LONG, StdTypeList.LONG, "or-const-long");
 
-    /** <code>r,x,c: int :: r = x ^ c;</code> */
+    /** {@code r,x,c: int :: r = x ^ c;} */
     public static final Rop XOR_CONST_INT =
         new Rop(RegOps.XOR, Type.INT, StdTypeList.INT, "xor-const-int");
 
-    /** <code>r,x,c: long :: r = x ^ c;</code> */
+    /** {@code r,x,c: long :: r = x ^ c;} */
     public static final Rop XOR_CONST_LONG =
         new Rop(RegOps.XOR, Type.LONG, StdTypeList.LONG, "xor-const-long");
 
-    /** <code>r,x,c: int :: r = x &lt;&lt; c;</code> */
+    /** {@code r,x,c: int :: r = x << c;} */
     public static final Rop SHL_CONST_INT =
         new Rop(RegOps.SHL, Type.INT, StdTypeList.INT, "shl-const-int");
 
-    /** <code>r,x: long; c: int :: r = x &lt;&lt; c;</code> */
+    /** {@code r,x: long; c: int :: r = x << c;} */
     public static final Rop SHL_CONST_LONG =
         new Rop(RegOps.SHL, Type.LONG, StdTypeList.INT, "shl-const-long");
 
-    /** <code>r,x,c: int :: r = x &gt;&gt; c;</code> */
+    /** {@code r,x,c: int :: r = x >> c;} */
     public static final Rop SHR_CONST_INT =
         new Rop(RegOps.SHR, Type.INT, StdTypeList.INT, "shr-const-int");
 
-    /** <code>r,x: long; c: int :: r = x &gt;&gt; c;</code> */
+    /** {@code r,x: long; c: int :: r = x >> c;} */
     public static final Rop SHR_CONST_LONG =
         new Rop(RegOps.SHR, Type.LONG, StdTypeList.INT, "shr-const-long");
 
-    /** <code>r,x,c: int :: r = x &gt;&gt;&gt; c;</code> */
+    /** {@code r,x,c: int :: r = x >>> c;} */
     public static final Rop USHR_CONST_INT =
         new Rop(RegOps.USHR, Type.INT, StdTypeList.INT, "ushr-const-int");
 
-    /** <code>r,x: long; c: int :: r = x &gt;&gt;&gt; c;</code> */
+    /** {@code r,x: long; c: int :: r = x >>> c;} */
     public static final Rop USHR_CONST_LONG =
         new Rop(RegOps.USHR, Type.LONG, StdTypeList.INT, "ushr-const-long");
 
-    /** <code>r: int; x,y: long :: r = cmp(x, y);</code> */
+    /** {@code r: int; x,y: long :: r = cmp(x, y);} */
     public static final Rop CMPL_LONG =
         new Rop(RegOps.CMPL, Type.INT, StdTypeList.LONG_LONG, "cmpl-long");
 
-    /** <code>r: int; x,y: float :: r = cmpl(x, y);</code> */
+    /** {@code r: int; x,y: float :: r = cmpl(x, y);} */
     public static final Rop CMPL_FLOAT =
         new Rop(RegOps.CMPL, Type.INT, StdTypeList.FLOAT_FLOAT, "cmpl-float");
 
-    /** <code>r: int; x,y: double :: r = cmpl(x, y);</code> */
+    /** {@code r: int; x,y: double :: r = cmpl(x, y);} */
     public static final Rop CMPL_DOUBLE =
         new Rop(RegOps.CMPL, Type.INT, StdTypeList.DOUBLE_DOUBLE,
                 "cmpl-double");
 
-    /** <code>r: int; x,y: float :: r = cmpg(x, y);</code> */
+    /** {@code r: int; x,y: float :: r = cmpg(x, y);} */
     public static final Rop CMPG_FLOAT =
         new Rop(RegOps.CMPG, Type.INT, StdTypeList.FLOAT_FLOAT, "cmpg-float");
 
-    /** <code>r: int; x,y: double :: r = cmpg(x, y);</code> */
+    /** {@code r: int; x,y: double :: r = cmpg(x, y);} */
     public static final Rop CMPG_DOUBLE =
         new Rop(RegOps.CMPG, Type.INT, StdTypeList.DOUBLE_DOUBLE,
                 "cmpg-double");
 
-    /** <code>r: int; x: long :: r = (int) x</code> */
+    /** {@code r: int; x: long :: r = (int) x} */
     public static final Rop CONV_L2I =
         new Rop(RegOps.CONV, Type.INT, StdTypeList.LONG, "conv-l2i");
 
-    /** <code>r: int; x: float :: r = (int) x</code> */
+    /** {@code r: int; x: float :: r = (int) x} */
     public static final Rop CONV_F2I =
         new Rop(RegOps.CONV, Type.INT, StdTypeList.FLOAT, "conv-f2i");
 
-    /** <code>r: int; x: double :: r = (int) x</code> */
+    /** {@code r: int; x: double :: r = (int) x} */
     public static final Rop CONV_D2I =
         new Rop(RegOps.CONV, Type.INT, StdTypeList.DOUBLE, "conv-d2i");
 
-    /** <code>r: long; x: int :: r = (long) x</code> */
+    /** {@code r: long; x: int :: r = (long) x} */
     public static final Rop CONV_I2L =
         new Rop(RegOps.CONV, Type.LONG, StdTypeList.INT, "conv-i2l");
 
-    /** <code>r: long; x: float :: r = (long) x</code> */
+    /** {@code r: long; x: float :: r = (long) x} */
     public static final Rop CONV_F2L =
         new Rop(RegOps.CONV, Type.LONG, StdTypeList.FLOAT, "conv-f2l");
 
-    /** <code>r: long; x: double :: r = (long) x</code> */
+    /** {@code r: long; x: double :: r = (long) x} */
     public static final Rop CONV_D2L =
         new Rop(RegOps.CONV, Type.LONG, StdTypeList.DOUBLE, "conv-d2l");
 
-    /** <code>r: float; x: int :: r = (float) x</code> */
+    /** {@code r: float; x: int :: r = (float) x} */
     public static final Rop CONV_I2F =
         new Rop(RegOps.CONV, Type.FLOAT, StdTypeList.INT, "conv-i2f");
 
-    /** <code>r: float; x: long :: r = (float) x</code> */
+    /** {@code r: float; x: long :: r = (float) x} */
     public static final Rop CONV_L2F =
         new Rop(RegOps.CONV, Type.FLOAT, StdTypeList.LONG, "conv-l2f");
 
-    /** <code>r: float; x: double :: r = (float) x</code> */
+    /** {@code r: float; x: double :: r = (float) x} */
     public static final Rop CONV_D2F =
         new Rop(RegOps.CONV, Type.FLOAT, StdTypeList.DOUBLE, "conv-d2f");
 
-    /** <code>r: double; x: int :: r = (double) x</code> */
+    /** {@code r: double; x: int :: r = (double) x} */
     public static final Rop CONV_I2D =
         new Rop(RegOps.CONV, Type.DOUBLE, StdTypeList.INT, "conv-i2d");
 
-    /** <code>r: double; x: long :: r = (double) x</code> */
+    /** {@code r: double; x: long :: r = (double) x} */
     public static final Rop CONV_L2D =
         new Rop(RegOps.CONV, Type.DOUBLE, StdTypeList.LONG, "conv-l2d");
 
-    /** <code>r: double; x: float :: r = (double) x</code> */
+    /** {@code r: double; x: float :: r = (double) x} */
     public static final Rop CONV_F2D =
         new Rop(RegOps.CONV, Type.DOUBLE, StdTypeList.FLOAT, "conv-f2d");
 
     /**
-     * <code>r,x: int :: r = (x &lt;&lt; 24) &gt;&gt; 24</code> (Java-style
+     * {@code r,x: int :: r = (x << 24) >> 24} (Java-style
      * convert int to byte) 
      */
     public static final Rop TO_BYTE = 
         new Rop(RegOps.TO_BYTE, Type.INT, StdTypeList.INT, "to-byte");
 
     /**
-     * <code>r,x: int :: r = x &amp; 0xffff</code> (Java-style
+     * {@code r,x: int :: r = x & 0xffff} (Java-style
      * convert int to char) 
      */
     public static final Rop TO_CHAR =
         new Rop(RegOps.TO_CHAR, Type.INT, StdTypeList.INT, "to-char");
 
     /**
-     * <code>r,x: int :: r = (x &lt;&lt; 16) &gt;&gt; 16</code> (Java-style
+     * {@code r,x: int :: r = (x << 16) >> 16} (Java-style
      * convert int to short) 
      */
     public static final Rop TO_SHORT =
         new Rop(RegOps.TO_SHORT, Type.INT, StdTypeList.INT, "to-short");
 
-    /** <code>return void</code> */
+    /** {@code return void} */
     public static final Rop RETURN_VOID =
         new Rop(RegOps.RETURN, Type.VOID, StdTypeList.EMPTY, Rop.BRANCH_RETURN,
                 "return-void");
 
-    /** <code>x: int; return x</code> */
+    /** {@code x: int; return x} */
     public static final Rop RETURN_INT =
         new Rop(RegOps.RETURN, Type.VOID, StdTypeList.INT, Rop.BRANCH_RETURN,
                 "return-int");
 
-    /** <code>x: long; return x</code> */
+    /** {@code x: long; return x} */
     public static final Rop RETURN_LONG =
         new Rop(RegOps.RETURN, Type.VOID, StdTypeList.LONG, Rop.BRANCH_RETURN,
                 "return-long");
 
-    /** <code>x: float; return x</code> */
+    /** {@code x: float; return x} */
     public static final Rop RETURN_FLOAT =
         new Rop(RegOps.RETURN, Type.VOID, StdTypeList.FLOAT, Rop.BRANCH_RETURN,
                 "return-float");
 
-    /** <code>x: double; return x</code> */
+    /** {@code x: double; return x} */
     public static final Rop RETURN_DOUBLE =
         new Rop(RegOps.RETURN, Type.VOID, StdTypeList.DOUBLE,
                 Rop.BRANCH_RETURN, "return-double");
 
-    /** <code>x: Object; return x</code> */
+    /** {@code x: Object; return x} */
     public static final Rop RETURN_OBJECT =
         new Rop(RegOps.RETURN, Type.VOID, StdTypeList.OBJECT,
                 Rop.BRANCH_RETURN, "return-object");
 
-    /** <code>T: any type; r: int; x: T[]; :: r = x.length</code> */
+    /** {@code T: any type; r: int; x: T[]; :: r = x.length} */
     public static final Rop ARRAY_LENGTH =
         new Rop(RegOps.ARRAY_LENGTH, Type.INT, StdTypeList.OBJECT,
                 Exceptions.LIST_Error_NullPointerException, "array-length");
 
-    /** <code>x: Throwable :: throw(x)</code> */
+    /** {@code x: Throwable :: throw(x)} */
     public static final Rop THROW =
         new Rop(RegOps.THROW, Type.VOID, StdTypeList.THROWABLE,
                 StdTypeList.THROWABLE, "throw");
 
-    /** <code>x: Object :: monitorenter(x)</code> */
+    /** {@code x: Object :: monitorenter(x)} */
     public static final Rop MONITOR_ENTER =
         new Rop(RegOps.MONITOR_ENTER, Type.VOID, StdTypeList.OBJECT,
                 Exceptions.LIST_Error_NullPointerException, "monitor-enter");
 
-    /** <code>x: Object :: monitorexit(x)</code> */
+    /** {@code x: Object :: monitorexit(x)} */
     public static final Rop MONITOR_EXIT =
         new Rop(RegOps.MONITOR_EXIT, Type.VOID, StdTypeList.OBJECT,
                 Exceptions.LIST_Error_Null_IllegalMonitorStateException,
                 "monitor-exit");
 
-    /** <code>r,y: int; x: int[] :: r = x[y]</code> */
+    /** {@code r,y: int; x: int[] :: r = x[y]} */
     public static final Rop AGET_INT = 
         new Rop(RegOps.AGET, Type.INT, StdTypeList.INTARR_INT,
                 Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds,
                 "aget-int");
 
-    /** <code>r: long; x: long[]; y: int :: r = x[y]</code> */
+    /** {@code r: long; x: long[]; y: int :: r = x[y]} */
     public static final Rop AGET_LONG = 
         new Rop(RegOps.AGET, Type.LONG, StdTypeList.LONGARR_INT,
                 Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds,
                 "aget-long");
 
-    /** <code>r: float; x: float[]; y: int :: r = x[y]</code> */
+    /** {@code r: float; x: float[]; y: int :: r = x[y]} */
     public static final Rop AGET_FLOAT = 
         new Rop(RegOps.AGET, Type.FLOAT, StdTypeList.FLOATARR_INT,
                 Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds,
                 "aget-float");
 
-    /** <code>r: double; x: double[]; y: int :: r = x[y]</code> */
+    /** {@code r: double; x: double[]; y: int :: r = x[y]} */
     public static final Rop AGET_DOUBLE = 
         new Rop(RegOps.AGET, Type.DOUBLE, StdTypeList.DOUBLEARR_INT,
                 Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds,
                 "aget-double");
 
-    /** <code>r: Object; x: Object[]; y: int :: r = x[y]</code> */
+    /** {@code r: Object; x: Object[]; y: int :: r = x[y]} */
     public static final Rop AGET_OBJECT = 
         new Rop(RegOps.AGET, Type.OBJECT, StdTypeList.OBJECTARR_INT,
                 Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds,
                 "aget-object");
 
-    /** <code>r: boolean; x: boolean[]; y: int :: r = x[y]</code> */
+    /** {@code r: boolean; x: boolean[]; y: int :: r = x[y]} */
     public static final Rop AGET_BOOLEAN = 
         new Rop(RegOps.AGET, Type.INT, StdTypeList.BOOLEANARR_INT,
                 Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds,
                 "aget-boolean");
 
-    /** <code>r: byte; x: byte[]; y: int :: r = x[y]</code> */
+    /** {@code r: byte; x: byte[]; y: int :: r = x[y]} */
     public static final Rop AGET_BYTE = 
         new Rop(RegOps.AGET, Type.INT, StdTypeList.BYTEARR_INT,
                 Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds, "aget-byte");
 
-    /** <code>r: char; x: char[]; y: int :: r = x[y]</code> */
+    /** {@code r: char; x: char[]; y: int :: r = x[y]} */
     public static final Rop AGET_CHAR = 
         new Rop(RegOps.AGET, Type.INT, StdTypeList.CHARARR_INT,
                 Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds, "aget-char");
 
-    /** <code>r: short; x: short[]; y: int :: r = x[y]</code> */
+    /** {@code r: short; x: short[]; y: int :: r = x[y]} */
     public static final Rop AGET_SHORT = 
         new Rop(RegOps.AGET, Type.INT, StdTypeList.SHORTARR_INT,
                 Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds,
                 "aget-short");
 
-    /** <code>x,z: int; y: int[] :: y[z] = x</code> */
+    /** {@code x,z: int; y: int[] :: y[z] = x} */
     public static final Rop APUT_INT = 
         new Rop(RegOps.APUT, Type.VOID, StdTypeList.INT_INTARR_INT,
                 Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds, "aput-int");
 
-    /** <code>x: long; y: long[]; z: int :: y[z] = x</code> */
+    /** {@code x: long; y: long[]; z: int :: y[z] = x} */
     public static final Rop APUT_LONG = 
         new Rop(RegOps.APUT, Type.VOID, StdTypeList.LONG_LONGARR_INT,
                 Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds, "aput-long");
 
-    /** <code>x: float; y: float[]; z: int :: y[z] = x</code> */
+    /** {@code x: float; y: float[]; z: int :: y[z] = x} */
     public static final Rop APUT_FLOAT = 
         new Rop(RegOps.APUT, Type.VOID, StdTypeList.FLOAT_FLOATARR_INT,
                 Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds,
                 "aput-float");
 
-    /** <code>x: double; y: double[]; z: int :: y[z] = x</code> */
+    /** {@code x: double; y: double[]; z: int :: y[z] = x} */
     public static final Rop APUT_DOUBLE = 
         new Rop(RegOps.APUT, Type.VOID, StdTypeList.DOUBLE_DOUBLEARR_INT,
                 Exceptions.LIST_Error_Null_ArrayIndexOutOfBounds,
                 "aput-double");
 
-    /** <code>x: Object; y: Object[]; z: int :: y[z] = x</code> */
+    /** {@code x: Object; y: Object[]; z: int :: y[z] = x} */
     public static final Rop APUT_OBJECT = 
         new Rop(RegOps.APUT, Type.VOID, StdTypeList.OBJECT_OBJECTARR_INT,
                 Exceptions.LIST_Error_Null_ArrayIndex_ArrayStore,
                 "aput-object");
 
-    /** <code>x: boolean; y: boolean[]; z: int :: y[z] = x</code> */
+    /** {@code x: boolean; y: boolean[]; z: int :: y[z] = x} */
     public static final Rop APUT_BOOLEAN = 
         new Rop(RegOps.APUT, Type.VOID, StdTypeList.INT_BOOLEANARR_INT,
                 Exceptions.LIST_Error_Null_ArrayIndex_ArrayStore,
                 "aput-boolean");
 
-    /** <code>x: byte; y: byte[]; z: int :: y[z] = x</code> */
+    /** {@code x: byte; y: byte[]; z: int :: y[z] = x} */
     public static final Rop APUT_BYTE = 
         new Rop(RegOps.APUT, Type.VOID, StdTypeList.INT_BYTEARR_INT,
                 Exceptions.LIST_Error_Null_ArrayIndex_ArrayStore, "aput-byte");
 
-    /** <code>x: char; y: char[]; z: int :: y[z] = x</code> */
+    /** {@code x: char; y: char[]; z: int :: y[z] = x} */
     public static final Rop APUT_CHAR = 
         new Rop(RegOps.APUT, Type.VOID, StdTypeList.INT_CHARARR_INT,
                 Exceptions.LIST_Error_Null_ArrayIndex_ArrayStore, "aput-char");
 
-    /** <code>x: short; y: short[]; z: int :: y[z] = x</code> */
+    /** {@code x: short; y: short[]; z: int :: y[z] = x} */
     public static final Rop APUT_SHORT = 
         new Rop(RegOps.APUT, Type.VOID, StdTypeList.INT_SHORTARR_INT,
                 Exceptions.LIST_Error_Null_ArrayIndex_ArrayStore,
                 "aput-short");
 
     /**
-     * <code>T: any non-array object type :: r =
-     * alloc(T)</code> (allocate heap space for an object) 
+     * {@code T: any non-array object type :: r =
+     * alloc(T)} (allocate heap space for an object) 
      */
     public static final Rop NEW_INSTANCE =
         new Rop(RegOps.NEW_INSTANCE, Type.OBJECT, StdTypeList.EMPTY,
                 Exceptions.LIST_Error, "new-instance");
 
-    /** <code>r: int[]; x: int :: r = new int[x]</code> */
+    /** {@code r: int[]; x: int :: r = new int[x]} */
     public static final Rop NEW_ARRAY_INT =
         new Rop(RegOps.NEW_ARRAY, Type.INT_ARRAY, StdTypeList.INT,
                 Exceptions.LIST_Error_NegativeArraySizeException,
                 "new-array-int");
 
-    /** <code>r: long[]; x: int :: r = new long[x]</code> */
+    /** {@code r: long[]; x: int :: r = new long[x]} */
     public static final Rop NEW_ARRAY_LONG =
         new Rop(RegOps.NEW_ARRAY, Type.LONG_ARRAY, StdTypeList.INT,
                 Exceptions.LIST_Error_NegativeArraySizeException,
                 "new-array-long");
 
-    /** <code>r: float[]; x: int :: r = new float[x]</code> */
+    /** {@code r: float[]; x: int :: r = new float[x]} */
     public static final Rop NEW_ARRAY_FLOAT =
         new Rop(RegOps.NEW_ARRAY, Type.FLOAT_ARRAY, StdTypeList.INT,
                 Exceptions.LIST_Error_NegativeArraySizeException,
                 "new-array-float");
 
-    /** <code>r: double[]; x: int :: r = new double[x]</code> */
+    /** {@code r: double[]; x: int :: r = new double[x]} */
     public static final Rop NEW_ARRAY_DOUBLE =
         new Rop(RegOps.NEW_ARRAY, Type.DOUBLE_ARRAY, StdTypeList.INT,
                 Exceptions.LIST_Error_NegativeArraySizeException,
                 "new-array-double");
 
-    /** <code>r: boolean[]; x: int :: r = new boolean[x]</code> */
+    /** {@code r: boolean[]; x: int :: r = new boolean[x]} */
     public static final Rop NEW_ARRAY_BOOLEAN =
         new Rop(RegOps.NEW_ARRAY, Type.BOOLEAN_ARRAY, StdTypeList.INT,
                 Exceptions.LIST_Error_NegativeArraySizeException,
                 "new-array-boolean");
 
-    /** <code>r: byte[]; x: int :: r = new byte[x]</code> */
+    /** {@code r: byte[]; x: int :: r = new byte[x]} */
     public static final Rop NEW_ARRAY_BYTE =
         new Rop(RegOps.NEW_ARRAY, Type.BYTE_ARRAY, StdTypeList.INT,
                 Exceptions.LIST_Error_NegativeArraySizeException,
                 "new-array-byte");
 
-    /** <code>r: char[]; x: int :: r = new char[x]</code> */
+    /** {@code r: char[]; x: int :: r = new char[x]} */
     public static final Rop NEW_ARRAY_CHAR =
         new Rop(RegOps.NEW_ARRAY, Type.CHAR_ARRAY, StdTypeList.INT,
                 Exceptions.LIST_Error_NegativeArraySizeException,
                 "new-array-char");
 
-    /** <code>r: short[]; x: int :: r = new short[x]</code> */
+    /** {@code r: short[]; x: int :: r = new short[x]} */
     public static final Rop NEW_ARRAY_SHORT =
         new Rop(RegOps.NEW_ARRAY, Type.SHORT_ARRAY, StdTypeList.INT,
                 Exceptions.LIST_Error_NegativeArraySizeException,
                 "new-array-short");
 
     /**
-     * <code>T: any non-array object type; x: Object :: (T) x</code> (can
-     * throw <code>ClassCastException</code>) 
+     * {@code T: any non-array object type; x: Object :: (T) x} (can
+     * throw {@code ClassCastException}) 
      */
     public static final Rop CHECK_CAST = 
         new Rop(RegOps.CHECK_CAST, Type.VOID, StdTypeList.OBJECT,
                 Exceptions.LIST_Error_ClassCastException, "check-cast");
 
     /**
-     * <code>T: any non-array object type; x: Object :: x instanceof
-     * T</code>. Note: This is listed as throwing <code>Error</code>
+     * {@code T: any non-array object type; x: Object :: x instanceof
+     * T}. Note: This is listed as throwing {@code Error}
      * explicitly because the op <i>can</i> throw, but there are no
      * other predefined exceptions for it. 
      */
@@ -822,24 +822,24 @@
                 Exceptions.LIST_Error, "instance-of");
 
     /**
-     * <code>r: int; x: Object; f: instance field spec of
-     * type int :: r = x.f</code> 
+     * {@code r: int; x: Object; f: instance field spec of
+     * type int :: r = x.f} 
      */
     public static final Rop GET_FIELD_INT =
         new Rop(RegOps.GET_FIELD, Type.INT, StdTypeList.OBJECT,
                 Exceptions.LIST_Error_NullPointerException, "get-field-int");
 
     /**
-     * <code>r: long; x: Object; f: instance field spec of
-     * type long :: r = x.f</code> 
+     * {@code r: long; x: Object; f: instance field spec of
+     * type long :: r = x.f} 
      */
     public static final Rop GET_FIELD_LONG =
         new Rop(RegOps.GET_FIELD, Type.LONG, StdTypeList.OBJECT,
                 Exceptions.LIST_Error_NullPointerException, "get-field-long");
 
     /**
-     * <code>r: float; x: Object; f: instance field spec of
-     * type float :: r = x.f</code> 
+     * {@code r: float; x: Object; f: instance field spec of
+     * type float :: r = x.f} 
      */
     public static final Rop GET_FIELD_FLOAT =
         new Rop(RegOps.GET_FIELD, Type.FLOAT, StdTypeList.OBJECT,
@@ -847,8 +847,8 @@
                 "get-field-float");
 
     /**
-     * <code>r: double; x: Object; f: instance field spec of
-     * type double :: r = x.f</code> 
+     * {@code r: double; x: Object; f: instance field spec of
+     * type double :: r = x.f} 
      */
     public static final Rop GET_FIELD_DOUBLE =
         new Rop(RegOps.GET_FIELD, Type.DOUBLE, StdTypeList.OBJECT,
@@ -856,8 +856,8 @@
                 "get-field-double");
 
     /**
-     * <code>r: Object; x: Object; f: instance field spec of
-     * type Object :: r = x.f</code> 
+     * {@code r: Object; x: Object; f: instance field spec of
+     * type Object :: r = x.f} 
      */
     public static final Rop GET_FIELD_OBJECT =
         new Rop(RegOps.GET_FIELD, Type.OBJECT, StdTypeList.OBJECT,
@@ -865,8 +865,8 @@
                 "get-field-object");
 
     /**
-     * <code>r: boolean; x: Object; f: instance field spec of
-     * type boolean :: r = x.f</code> 
+     * {@code r: boolean; x: Object; f: instance field spec of
+     * type boolean :: r = x.f} 
      */
     public static final Rop GET_FIELD_BOOLEAN =
         new Rop(RegOps.GET_FIELD, Type.INT, StdTypeList.OBJECT,
@@ -874,8 +874,8 @@
                 "get-field-boolean");
 
     /**
-     * <code>r: byte; x: Object; f: instance field spec of
-     * type byte :: r = x.f</code> 
+     * {@code r: byte; x: Object; f: instance field spec of
+     * type byte :: r = x.f} 
      */
     public static final Rop GET_FIELD_BYTE =
         new Rop(RegOps.GET_FIELD, Type.INT, StdTypeList.OBJECT,
@@ -883,8 +883,8 @@
                 "get-field-byte");
 
     /**
-     * <code>r: char; x: Object; f: instance field spec of
-     * type char :: r = x.f</code> 
+     * {@code r: char; x: Object; f: instance field spec of
+     * type char :: r = x.f} 
      */
     public static final Rop GET_FIELD_CHAR =
         new Rop(RegOps.GET_FIELD, Type.INT, StdTypeList.OBJECT,
@@ -892,105 +892,78 @@
                 "get-field-char");
 
     /**
-     * <code>r: short; x: Object; f: instance field spec of
-     * type short :: r = x.f</code> 
+     * {@code r: short; x: Object; f: instance field spec of
+     * type short :: r = x.f} 
      */
     public static final Rop GET_FIELD_SHORT =
         new Rop(RegOps.GET_FIELD, Type.INT, StdTypeList.OBJECT,
                 Exceptions.LIST_Error_NullPointerException,
                 "get-field-short");
 
-    /**
-     * <code>r: int; f: static field spec of type int :: r =
-     * f</code> 
-     */
+    /** {@code r: int; f: static field spec of type int :: r = f} */
     public static final Rop GET_STATIC_INT =
         new Rop(RegOps.GET_STATIC, Type.INT, StdTypeList.EMPTY,
                 Exceptions.LIST_Error, "get-static-int");
 
-    /**
-     * <code>r: long; f: static field spec of type long :: r =
-     * f</code> 
-     */
+    /** {@code r: long; f: static field spec of type long :: r = f} */
     public static final Rop GET_STATIC_LONG =
         new Rop(RegOps.GET_STATIC, Type.LONG, StdTypeList.EMPTY,
                 Exceptions.LIST_Error, "get-static-long");
 
-    /**
-     * <code>r: float; f: static field spec of type float :: r =
-     * f</code> 
-     */
+    /** {@code r: float; f: static field spec of type float :: r = f} */
     public static final Rop GET_STATIC_FLOAT =
         new Rop(RegOps.GET_STATIC, Type.FLOAT, StdTypeList.EMPTY,
                 Exceptions.LIST_Error, "get-static-float");
 
-    /**
-     * <code>r: double; f: static field spec of type double :: r =
-     * f</code> 
-     */
+    /** {@code r: double; f: static field spec of type double :: r = f} */
     public static final Rop GET_STATIC_DOUBLE =
         new Rop(RegOps.GET_STATIC, Type.DOUBLE, StdTypeList.EMPTY,
                 Exceptions.LIST_Error, "get-static-double");
 
-    /**
-     * <code>r: Object; f: static field spec of type Object :: r =
-     * f</code> 
-     */
+    /** {@code r: Object; f: static field spec of type Object :: r = f} */
     public static final Rop GET_STATIC_OBJECT =
         new Rop(RegOps.GET_STATIC, Type.OBJECT, StdTypeList.EMPTY,
                 Exceptions.LIST_Error, "get-static-object");
 
-    /**
-     * <code>r: boolean; f: static field spec of type boolean :: r =
-     * f</code> 
-     */
+    /** {@code r: boolean; f: static field spec of type boolean :: r = f} */
     public static final Rop GET_STATIC_BOOLEAN =
         new Rop(RegOps.GET_STATIC, Type.INT, StdTypeList.EMPTY,
                 Exceptions.LIST_Error, "get-field-boolean");
 
-    /**
-     * <code>r: byte; f: static field spec of type byte :: r =
-     * f</code> 
-     */
+    /** {@code r: byte; f: static field spec of type byte :: r = f} */
     public static final Rop GET_STATIC_BYTE =
         new Rop(RegOps.GET_STATIC, Type.INT, StdTypeList.EMPTY,
                 Exceptions.LIST_Error, "get-field-byte");
 
-    /**
-     * <code>r: char; f: static field spec of type char :: r =
-     * f</code> 
-     */
+    /** {@code r: char; f: static field spec of type char :: r = f} */
     public static final Rop GET_STATIC_CHAR =
         new Rop(RegOps.GET_STATIC, Type.INT, StdTypeList.EMPTY,
                 Exceptions.LIST_Error, "get-field-char");
 
-    /**
-     * <code>r: short; f: static field spec of type short :: r =
-     * f</code> 
-     */
+    /** {@code r: short; f: static field spec of type short :: r = f} */
     public static final Rop GET_STATIC_SHORT =
         new Rop(RegOps.GET_STATIC, Type.INT, StdTypeList.EMPTY,
                 Exceptions.LIST_Error, "get-field-short");
 
     /**
-     * <code>x: int; y: Object; f: instance field spec of type
-     * int :: y.f = x</code> 
+     * {@code x: int; y: Object; f: instance field spec of type
+     * int :: y.f = x} 
      */
     public static final Rop PUT_FIELD_INT =
         new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.INT_OBJECT,
                 Exceptions.LIST_Error_NullPointerException, "put-field-int");
 
     /**
-     * <code>x: long; y: Object; f: instance field spec of type
-     * long :: y.f = x</code> 
+     * {@code x: long; y: Object; f: instance field spec of type
+     * long :: y.f = x} 
      */
     public static final Rop PUT_FIELD_LONG =
         new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.LONG_OBJECT,
                 Exceptions.LIST_Error_NullPointerException, "put-field-long");
 
     /**
-     * <code>x: float; y: Object; f: instance field spec of type
-     * float :: y.f = x</code> 
+     * {@code x: float; y: Object; f: instance field spec of type
+     * float :: y.f = x} 
      */
     public static final Rop PUT_FIELD_FLOAT =
         new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.FLOAT_OBJECT,
@@ -998,8 +971,8 @@
                 "put-field-float");
 
     /**
-     * <code>x: double; y: Object; f: instance field spec of type
-     * double :: y.f = x</code> 
+     * {@code x: double; y: Object; f: instance field spec of type
+     * double :: y.f = x} 
      */
     public static final Rop PUT_FIELD_DOUBLE =
         new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.DOUBLE_OBJECT,
@@ -1007,8 +980,8 @@
                 "put-field-double");
 
     /**
-     * <code>x: Object; y: Object; f: instance field spec of type
-     * Object :: y.f = x</code> 
+     * {@code x: Object; y: Object; f: instance field spec of type
+     * Object :: y.f = x} 
      */
     public static final Rop PUT_FIELD_OBJECT =
         new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.OBJECT_OBJECT,
@@ -1016,8 +989,8 @@
                 "put-field-object");
 
     /**
-     * <code>x: int; y: Object; f: instance field spec of type
-     * boolean :: y.f = x</code> 
+     * {@code x: int; y: Object; f: instance field spec of type
+     * boolean :: y.f = x} 
      */
     public static final Rop PUT_FIELD_BOOLEAN =
         new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.INT_OBJECT,
@@ -1025,8 +998,8 @@
                 "put-field-boolean");
 
     /**
-     * <code>x: int; y: Object; f: instance field spec of type
-     * byte :: y.f = x</code> 
+     * {@code x: int; y: Object; f: instance field spec of type
+     * byte :: y.f = x} 
      */
     public static final Rop PUT_FIELD_BYTE =
         new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.INT_OBJECT,
@@ -1034,8 +1007,8 @@
                 "put-field-byte");
 
     /**
-     * <code>x: int; y: Object; f: instance field spec of type
-     * char :: y.f = x</code> 
+     * {@code x: int; y: Object; f: instance field spec of type
+     * char :: y.f = x} 
      */
     public static final Rop PUT_FIELD_CHAR =
         new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.INT_OBJECT,
@@ -1043,112 +1016,88 @@
                 "put-field-char");
 
     /**
-     * <code>x: int; y: Object; f: instance field spec of type
-     * short :: y.f = x</code> 
+     * {@code x: int; y: Object; f: instance field spec of type
+     * short :: y.f = x} 
      */
     public static final Rop PUT_FIELD_SHORT =
         new Rop(RegOps.PUT_FIELD, Type.VOID, StdTypeList.INT_OBJECT,
                 Exceptions.LIST_Error_NullPointerException,
                 "put-field-short");
 
-    /**
-     * <code>f: static field spec of type int; x: int :: f =
-     * x</code>
-     */
+    /** {@code f: static field spec of type int; x: int :: f = x} */
     public static final Rop PUT_STATIC_INT =
         new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.INT,
                 Exceptions.LIST_Error, "put-static-int");
 
-    /**
-     * <code>f: static field spec of type long; x: long :: f =
-     * x</code>
-     */
+    /** {@code f: static field spec of type long; x: long :: f = x} */
     public static final Rop PUT_STATIC_LONG =
         new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.LONG,
                 Exceptions.LIST_Error, "put-static-long");
 
-    /**
-     * <code>f: static field spec of type float; x: float :: f =
-     * x</code>
-     */
+    /** {@code f: static field spec of type float; x: float :: f = x} */
     public static final Rop PUT_STATIC_FLOAT =
         new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.FLOAT,
                 Exceptions.LIST_Error, "put-static-float");
 
-    /**
-     * <code>f: static field spec of type double; x: double :: f =
-     * x</code>
-     */
+    /** {@code f: static field spec of type double; x: double :: f = x} */
     public static final Rop PUT_STATIC_DOUBLE =
         new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.DOUBLE,
                 Exceptions.LIST_Error, "put-static-double");
 
-    /**
-     * <code>f: static field spec of type Object; x: Object :: f =
-     * x</code>
-     */
+    /** {@code f: static field spec of type Object; x: Object :: f = x} */
     public static final Rop PUT_STATIC_OBJECT =
         new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.OBJECT,
                 Exceptions.LIST_Error, "put-static-object");
 
     /**
-     * <code>f: static field spec of type boolean; x: boolean :: f =
-     * x</code>
+     * {@code f: static field spec of type boolean; x: boolean :: f =
+     * x}
      */
     public static final Rop PUT_STATIC_BOOLEAN =
         new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.INT,
                 Exceptions.LIST_Error, "put-static-boolean");
 
-    /**
-     * <code>f: static field spec of type byte; x: byte :: f =
-     * x</code>
-     */
+    /** {@code f: static field spec of type byte; x: byte :: f = x} */
     public static final Rop PUT_STATIC_BYTE =
         new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.INT,
                 Exceptions.LIST_Error, "put-static-byte");
 
-    /**
-     * <code>f: static field spec of type char; x: char :: f =
-     * x</code>
-     */
+    /** {@code f: static field spec of type char; x: char :: f = x} */
     public static final Rop PUT_STATIC_CHAR =
         new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.INT,
                 Exceptions.LIST_Error, "put-static-char");
 
-    /**
-     * <code>f: static field spec of type short; x: short :: f =
-     * x</code>
-     */
+    /** {@code f: static field spec of type short; x: short :: f = x} */
     public static final Rop PUT_STATIC_SHORT =
         new Rop(RegOps.PUT_STATIC, Type.VOID, StdTypeList.INT,
                 Exceptions.LIST_Error, "put-static-short");
 
-    /** <code>x: Int :: local variable begins in x */
+    /** {@code x: Int :: local variable begins in x} */
     public static final Rop MARK_LOCAL_INT =
             new Rop (RegOps.MARK_LOCAL, Type.VOID,
                     StdTypeList.INT, "mark-local-int");
 
-    /** <code>x: Long :: local variable begins in x */
+    /** {@code x: Long :: local variable begins in x} */
     public static final Rop MARK_LOCAL_LONG =
             new Rop (RegOps.MARK_LOCAL, Type.VOID,
                     StdTypeList.LONG, "mark-local-long");
 
-    /** <code>x: Float :: local variable begins in x */
+    /** {@code x: Float :: local variable begins in x} */
     public static final Rop MARK_LOCAL_FLOAT =
             new Rop (RegOps.MARK_LOCAL, Type.VOID,
                     StdTypeList.FLOAT, "mark-local-float");
 
-    /** <code>x: Double :: local variable begins in x */
+    /** {@code x: Double :: local variable begins in x} */
     public static final Rop MARK_LOCAL_DOUBLE =
             new Rop (RegOps.MARK_LOCAL, Type.VOID,
                     StdTypeList.DOUBLE, "mark-local-double");
 
-    /** <code>x: Object :: local variable begins in x */
+    /** {@code x: Object :: local variable begins in x} */
     public static final Rop MARK_LOCAL_OBJECT =
             new Rop (RegOps.MARK_LOCAL, Type.VOID,
                     StdTypeList.OBJECT, "mark-local-object");
 
-    /** <code>T: Any primitive type; v0..vx: T :: {v0, ..., vx}</code> */
+    /** {@code T: Any primitive type; v0..vx: T :: {v0, ..., vx}} */
     public static final Rop FILL_ARRAY_DATA =
         new Rop(RegOps.FILL_ARRAY_DATA, Type.VOID, StdTypeList.EMPTY,
                 "fill-array-data");
@@ -1164,13 +1113,14 @@
      * match what is returned. TODO: Revisit this issue.</p>
      * 
      * @param opcode the opcode
-     * @param dest non-null; destination type, or {@link Type#VOID} if none
-     * @param sources non-null; list of source types
-     * @param cst null-ok; associated constant, if any
-     * @return non-null; an appropriate instance
+     * @param dest {@code non-null;} destination (result) type, or
+     * {@link Type#VOID} if none
+     * @param sources {@code non-null;} list of source types
+     * @param cst {@code null-ok;} associated constant, if any
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop ropFor(int opcode, TypeBearer dest, TypeList sources,
-                             Constant cst) {
+            Constant cst) {
         switch (opcode) {
             case RegOps.NOP: return NOP;
             case RegOps.MOVE: return opMove(dest);
@@ -1216,19 +1166,31 @@
             case RegOps.MONITOR_EXIT: return MONITOR_EXIT;
             case RegOps.AGET: {
                 Type source = sources.getType(0);
+                Type componentType;
                 if (source == Type.KNOWN_NULL) {
-                    // Treat a known-null as an Object[] in this context.
-                    source = Type.OBJECT_ARRAY;
-                } 
-                return opAget(source.getComponentType());
+                    /*
+                     * Treat a known-null as an array of the expected
+                     * result type.
+                     */
+                    componentType = dest.getType();
+                } else {
+                    componentType = source.getComponentType();
+                }
+                return opAget(componentType);
             }
             case RegOps.APUT: {
                 Type source = sources.getType(1);
+                Type componentType;
                 if (source == Type.KNOWN_NULL) {
-                    // Treat a known-null as an Object[] in this context.
-                    source = Type.OBJECT_ARRAY;
-                } 
-                return opAput(source.getComponentType());
+                    /*
+                     * Treat a known-null as an array of the type being
+                     * stored.
+                     */
+                    componentType = sources.getType(0);
+                } else {
+                    componentType = source.getComponentType();
+                }
+                return opAput(componentType);
             }
             case RegOps.NEW_INSTANCE: return NEW_INSTANCE;
             case RegOps.NEW_ARRAY: return opNewArray(dest.getType());
@@ -1275,11 +1237,11 @@
     }
 
     /**
-     * Returns the appropriate <code>move</code> rop for the given type. The
+     * Returns the appropriate {@code move} rop for the given type. The
      * result is a shared instance.
      * 
-     * @param type non-null; type of value being moved
-     * @return non-null; an appropriate instance
+     * @param type {@code non-null;} type of value being moved
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opMove(TypeBearer type) {
         switch (type.getBasicFrameType()) {
@@ -1295,11 +1257,11 @@
     }
 
     /**
-     * Returns the appropriate <code>move-param</code> rop for the
+     * Returns the appropriate {@code move-param} rop for the
      * given type. The result is a shared instance.
      * 
-     * @param type non-null; type of value being moved
-     * @return non-null; an appropriate instance
+     * @param type {@code non-null;} type of value being moved
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opMoveParam(TypeBearer type) {
         switch (type.getBasicFrameType()) {
@@ -1314,11 +1276,11 @@
     }
 
     /**
-     * Returns the appropriate <code>move-exception</code> rop for the
+     * Returns the appropriate {@code move-exception} rop for the
      * given type. The result may be a shared instance.
      * 
-     * @param type non-null; type of the exception
-     * @return non-null; an appropriate instance
+     * @param type {@code non-null;} type of the exception
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opMoveException(TypeBearer type) {
         return new Rop(RegOps.MOVE_EXCEPTION, type.getType(),
@@ -1326,11 +1288,11 @@
     }
 
     /**
-     * Returns the appropriate <code>move-result</code> rop for the
+     * Returns the appropriate {@code move-result} rop for the
      * given type. The result may be a shared instance.
      *
-     * @param type non-null; type of the parameter
-     * @return non-null; an appropriate instance
+     * @param type {@code non-null;} type of the parameter
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opMoveResult(TypeBearer type) {
         return new Rop(RegOps.MOVE_RESULT, type.getType(),
@@ -1338,11 +1300,11 @@
     }
 
     /**
-     * Returns the appropriate <code>move-result-pseudo</code> rop for the
+     * Returns the appropriate {@code move-result-pseudo} rop for the
      * given type. The result may be a shared instance.
      *
-     * @param type non-null; type of the parameter
-     * @return non-null; an appropriate instance
+     * @param type {@code non-null;} type of the parameter
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opMoveResultPseudo(TypeBearer type) {
         return new Rop(RegOps.MOVE_RESULT_PSEUDO, type.getType(),
@@ -1350,11 +1312,11 @@
     }
 
     /**
-     * Returns the appropriate <code>const</code> rop for the given
+     * Returns the appropriate {@code const} rop for the given
      * type. The result is a shared instance.
      * 
-     * @param type non-null; type of the constant
-     * @return non-null; an appropriate instance
+     * @param type {@code non-null;} type of the constant
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opConst(TypeBearer type) {
         if (type.getType() == Type.KNOWN_NULL) {
@@ -1373,11 +1335,11 @@
     }
 
     /**
-     * Returns the appropriate <code>if-eq</code> rop for the given
+     * Returns the appropriate {@code if-eq} rop for the given
      * sources. The result is a shared instance.
      * 
-     * @param types non-null; source types
-     * @return non-null; an appropriate instance
+     * @param types {@code non-null;} source types
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opIfEq(TypeList types) {
         return pickIf(types, IF_EQZ_INT, IF_EQZ_OBJECT,
@@ -1385,11 +1347,11 @@
     }
 
     /**
-     * Returns the appropriate <code>if-ne</code> rop for the given
+     * Returns the appropriate {@code if-ne} rop for the given
      * sources. The result is a shared instance.
      * 
-     * @param types non-null; source types
-     * @return non-null; an appropriate instance
+     * @param types {@code non-null;} source types
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opIfNe(TypeList types) {
         return pickIf(types, IF_NEZ_INT, IF_NEZ_OBJECT,
@@ -1397,60 +1359,60 @@
     }
 
     /**
-     * Returns the appropriate <code>if-lt</code> rop for the given
+     * Returns the appropriate {@code if-lt} rop for the given
      * sources. The result is a shared instance.
      * 
-     * @param types non-null; source types
-     * @return non-null; an appropriate instance
+     * @param types {@code non-null;} source types
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opIfLt(TypeList types) {
         return pickIf(types, IF_LTZ_INT, null, IF_LT_INT, null);
     }
 
     /**
-     * Returns the appropriate <code>if-ge</code> rop for the given
+     * Returns the appropriate {@code if-ge} rop for the given
      * sources. The result is a shared instance.
      * 
-     * @param types non-null; source types
-     * @return non-null; an appropriate instance
+     * @param types {@code non-null;} source types
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opIfGe(TypeList types) {
         return pickIf(types, IF_GEZ_INT, null, IF_GE_INT, null);
     }
 
     /**
-     * Returns the appropriate <code>if-gt</code> rop for the given
+     * Returns the appropriate {@code if-gt} rop for the given
      * sources. The result is a shared instance.
      * 
-     * @param types non-null; source types
-     * @return non-null; an appropriate instance
+     * @param types {@code non-null;} source types
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opIfGt(TypeList types) {
         return pickIf(types, IF_GTZ_INT, null, IF_GT_INT, null);
     }
 
     /**
-     * Returns the appropriate <code>if-le</code> rop for the given
+     * Returns the appropriate {@code if-le} rop for the given
      * sources. The result is a shared instance.
      * 
-     * @param types non-null; source types
-     * @return non-null; an appropriate instance
+     * @param types {@code non-null;} source types
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opIfLe(TypeList types) {
         return pickIf(types, IF_LEZ_INT, null, IF_LE_INT, null);
     }
 
     /**
-     * Helper for all the <code>if*</code>-related methods, which
+     * Helper for all the {@code if*}-related methods, which
      * checks types and picks one of the four variants, throwing if
      * there's a problem.
      * 
-     * @param types non-null; the types
-     * @param intZ non-null; the int-to-0 comparison
-     * @param objZ null-ok; the object-to-null comparison
-     * @param intInt non-null; the int-to-int comparison
-     * @param objObj non-null; the object-to-object comparison
-     * @return non-null; the appropriate instance
+     * @param types {@code non-null;} the types
+     * @param intZ {@code non-null;} the int-to-0 comparison
+     * @param objZ {@code null-ok;} the object-to-null comparison
+     * @param intInt {@code non-null;} the int-to-int comparison
+     * @param objObj {@code non-null;} the object-to-object comparison
+     * @return {@code non-null;} the appropriate instance
      */
     private static Rop pickIf(TypeList types, Rop intZ, Rop objZ, Rop intInt,
                               Rop objObj) {
@@ -1490,11 +1452,11 @@
     }
 
     /**
-     * Returns the appropriate <code>add</code> rop for the given
+     * Returns the appropriate {@code add} rop for the given
      * types. The result is a shared instance.
      * 
-     * @param types non-null; types of the sources
-     * @return non-null; an appropriate instance
+     * @param types {@code non-null;} types of the sources
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opAdd(TypeList types) {
         return pickBinaryOp(types, ADD_CONST_INT, ADD_CONST_LONG,
@@ -1503,11 +1465,11 @@
     }
 
     /**
-     * Returns the appropriate <code>sub</code> rop for the given
+     * Returns the appropriate {@code sub} rop for the given
      * types. The result is a shared instance.
      * 
-     * @param types non-null; types of the sources
-     * @return non-null; an appropriate instance
+     * @param types {@code non-null;} types of the sources
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opSub(TypeList types) {
         return pickBinaryOp(types, SUB_CONST_INT, SUB_CONST_LONG,
@@ -1516,11 +1478,11 @@
     }
 
     /**
-     * Returns the appropriate <code>mul</code> rop for the given
+     * Returns the appropriate {@code mul} rop for the given
      * types. The result is a shared instance.
      * 
-     * @param types non-null; types of the sources
-     * @return non-null; an appropriate instance
+     * @param types {@code non-null;} types of the sources
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opMul(TypeList types) {
         return pickBinaryOp(types, MUL_CONST_INT, MUL_CONST_LONG,
@@ -1529,11 +1491,11 @@
     }
 
     /**
-     * Returns the appropriate <code>div</code> rop for the given
+     * Returns the appropriate {@code div} rop for the given
      * types. The result is a shared instance.
      * 
-     * @param types non-null; types of the sources
-     * @return non-null; an appropriate instance
+     * @param types {@code non-null;} types of the sources
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opDiv(TypeList types) {
         return pickBinaryOp(types, DIV_CONST_INT, DIV_CONST_LONG,
@@ -1542,11 +1504,11 @@
     }
 
     /**
-     * Returns the appropriate <code>rem</code> rop for the given
+     * Returns the appropriate {@code rem} rop for the given
      * types. The result is a shared instance.
      * 
-     * @param types non-null; types of the sources
-     * @return non-null; an appropriate instance
+     * @param types {@code non-null;} types of the sources
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opRem(TypeList types) {
         return pickBinaryOp(types, REM_CONST_INT, REM_CONST_LONG,
@@ -1555,11 +1517,11 @@
     }
 
     /**
-     * Returns the appropriate <code>and</code> rop for the given
+     * Returns the appropriate {@code and} rop for the given
      * types. The result is a shared instance.
      * 
-     * @param types non-null; types of the sources
-     * @return non-null; an appropriate instance
+     * @param types {@code non-null;} types of the sources
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opAnd(TypeList types) {
         return pickBinaryOp(types, AND_CONST_INT, AND_CONST_LONG, null, null,
@@ -1567,11 +1529,11 @@
     }
 
     /**
-     * Returns the appropriate <code>or</code> rop for the given
+     * Returns the appropriate {@code or} rop for the given
      * types. The result is a shared instance.
      * 
-     * @param types non-null; types of the sources
-     * @return non-null; an appropriate instance
+     * @param types {@code non-null;} types of the sources
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opOr(TypeList types) {
         return pickBinaryOp(types, OR_CONST_INT, OR_CONST_LONG, null, null,
@@ -1579,11 +1541,11 @@
     }
 
     /**
-     * Returns the appropriate <code>xor</code> rop for the given
+     * Returns the appropriate {@code xor} rop for the given
      * types. The result is a shared instance.
      * 
-     * @param types non-null; types of the sources
-     * @return non-null; an appropriate instance
+     * @param types {@code non-null;} types of the sources
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opXor(TypeList types) {
         return pickBinaryOp(types, XOR_CONST_INT, XOR_CONST_LONG, null, null,
@@ -1591,11 +1553,11 @@
     }
 
     /**
-     * Returns the appropriate <code>shl</code> rop for the given
+     * Returns the appropriate {@code shl} rop for the given
      * types. The result is a shared instance.
      * 
-     * @param types non-null; types of the sources
-     * @return non-null; an appropriate instance
+     * @param types {@code non-null;} types of the sources
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opShl(TypeList types) {
         return pickBinaryOp(types, SHL_CONST_INT, SHL_CONST_LONG, null, null,
@@ -1603,11 +1565,11 @@
     }
 
     /**
-     * Returns the appropriate <code>shr</code> rop for the given
+     * Returns the appropriate {@code shr} rop for the given
      * types. The result is a shared instance.
      * 
-     * @param types non-null; types of the sources
-     * @return non-null; an appropriate instance
+     * @param types {@code non-null;} types of the sources
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opShr(TypeList types) {
         return pickBinaryOp(types, SHR_CONST_INT, SHR_CONST_LONG, null, null,
@@ -1615,11 +1577,11 @@
     }
 
     /**
-     * Returns the appropriate <code>ushr</code> rop for the given
+     * Returns the appropriate {@code ushr} rop for the given
      * types. The result is a shared instance.
      * 
-     * @param types non-null; types of the sources
-     * @return non-null; an appropriate instance
+     * @param types {@code non-null;} types of the sources
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opUshr(TypeList types) {
         return pickBinaryOp(types, USHR_CONST_INT, USHR_CONST_LONG, null, null,
@@ -1630,16 +1592,16 @@
      * Returns the appropriate binary arithmetic rop for the given type
      * and arguments. The result is a shared instance.
      * 
-     * @param types non-null; sources of the operation
-     * @param int1 non-null; the int-to-constant rop
-     * @param long1 non-null; the long-to-constant rop
-     * @param float1 null-ok; the float-to-constant rop, if any
-     * @param double1 null-ok; the double-to-constant rop, if any
-     * @param int2 non-null; the int-to-int rop
-     * @param long2 non-null; the long-to-long or long-to-int rop
-     * @param float2 null-ok; the float-to-float rop, if any
-     * @param double2 null-ok; the double-to-double rop, if any
-     * @return non-null; an appropriate instance
+     * @param types {@code non-null;} sources of the operation
+     * @param int1 {@code non-null;} the int-to-constant rop
+     * @param long1 {@code non-null;} the long-to-constant rop
+     * @param float1 {@code null-ok;} the float-to-constant rop, if any
+     * @param double1 {@code null-ok;} the double-to-constant rop, if any
+     * @param int2 {@code non-null;} the int-to-int rop
+     * @param long2 {@code non-null;} the long-to-long or long-to-int rop
+     * @param float2 {@code null-ok;} the float-to-float rop, if any
+     * @param double2 {@code null-ok;} the double-to-double rop, if any
+     * @return {@code non-null;} an appropriate instance
      */
     private static Rop pickBinaryOp(TypeList types, Rop int1, Rop long1,
                                     Rop float1, Rop double1, Rop int2,
@@ -1676,11 +1638,11 @@
     }
 
     /**
-     * Returns the appropriate <code>neg</code> rop for the given type. The
+     * Returns the appropriate {@code neg} rop for the given type. The
      * result is a shared instance.
      * 
-     * @param type non-null; type of value being operated on
-     * @return non-null; an appropriate instance
+     * @param type {@code non-null;} type of value being operated on
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opNeg(TypeBearer type) {
         switch (type.getBasicFrameType()) {
@@ -1694,11 +1656,11 @@
     }
 
     /**
-     * Returns the appropriate <code>not</code> rop for the given type. The
+     * Returns the appropriate {@code not} rop for the given type. The
      * result is a shared instance.
      * 
-     * @param type non-null; type of value being operated on
-     * @return non-null; an appropriate instance
+     * @param type {@code non-null;} type of value being operated on
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opNot(TypeBearer type) {
         switch (type.getBasicFrameType()) {
@@ -1710,11 +1672,11 @@
     }
 
     /**
-     * Returns the appropriate <code>cmpl</code> rop for the given type. The
+     * Returns the appropriate {@code cmpl} rop for the given type. The
      * result is a shared instance.
      * 
-     * @param type non-null; type of value being compared
-     * @return non-null; an appropriate instance
+     * @param type {@code non-null;} type of value being compared
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opCmpl(TypeBearer type) {
         switch (type.getBasicType()) {
@@ -1727,11 +1689,11 @@
     }
 
     /**
-     * Returns the appropriate <code>cmpg</code> rop for the given type. The
+     * Returns the appropriate {@code cmpg} rop for the given type. The
      * result is a shared instance.
      * 
-     * @param type non-null; type of value being compared
-     * @return non-null; an appropriate instance
+     * @param type {@code non-null;} type of value being compared
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opCmpg(TypeBearer type) {
         switch (type.getBasicType()) {
@@ -1743,12 +1705,12 @@
     }
 
     /**
-     * Returns the appropriate <code>conv</code> rop for the given types. The
+     * Returns the appropriate {@code conv} rop for the given types. The
      * result is a shared instance.
      * 
-     * @param dest non-null; target value type
-     * @param source non-null; source value type
-     * @return non-null; an appropriate instance
+     * @param dest {@code non-null;} target value type
+     * @param source {@code non-null;} source value type
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opConv(TypeBearer dest, TypeBearer source) {
         int dbt = dest.getBasicFrameType();
@@ -1788,11 +1750,11 @@
     }
 
     /**
-     * Returns the appropriate <code>return</code> rop for the given type. The
+     * Returns the appropriate {@code return} rop for the given type. The
      * result is a shared instance.
      * 
-     * @param type non-null; type of value being returned
-     * @return non-null; an appropriate instance
+     * @param type {@code non-null;} type of value being returned
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opReturn(TypeBearer type) {
         switch (type.getBasicFrameType()) {
@@ -1808,11 +1770,11 @@
     }
 
     /**
-     * Returns the appropriate <code>aget</code> rop for the given type. The
+     * Returns the appropriate {@code aget} rop for the given type. The
      * result is a shared instance.
      * 
-     * @param type non-null; element type of array being accessed
-     * @return non-null; an appropriate instance
+     * @param type {@code non-null;} element type of array being accessed
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opAget(TypeBearer type) {
         switch (type.getBasicType()) {
@@ -1831,11 +1793,11 @@
     }
 
     /**
-     * Returns the appropriate <code>aput</code> rop for the given type. The
+     * Returns the appropriate {@code aput} rop for the given type. The
      * result is a shared instance.
      * 
-     * @param type non-null; element type of array being accessed
-     * @return non-null; an appropriate instance
+     * @param type {@code non-null;} element type of array being accessed
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opAput(TypeBearer type) {
         switch (type.getBasicType()) {
@@ -1854,11 +1816,11 @@
     }
 
     /**
-     * Returns the appropriate <code>new-array</code> rop for the given
+     * Returns the appropriate {@code new-array} rop for the given
      * type. The result is a shared instance.
      * 
-     * @param arrayType non-null; array type of array being created
-     * @return non-null; an appropriate instance
+     * @param arrayType {@code non-null;} array type of array being created
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opNewArray(TypeBearer arrayType) {
         Type type = arrayType.getType();
@@ -1884,12 +1846,12 @@
     }
 
     /**
-     * Returns the appropriate <code>filled-new-array</code> rop for the given
+     * Returns the appropriate {@code filled-new-array} rop for the given
      * type. The result may be a shared instance.
      * 
-     * @param arrayType non-null; type of array being created
-     * @param count &gt;= 0; number of elements that the array should have
-     * @return non-null; an appropriate instance
+     * @param arrayType {@code non-null;} type of array being created
+     * @param count {@code >= 0;} number of elements that the array should have
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opFilledNewArray(TypeBearer arrayType, int count) {
         Type type = arrayType.getType();
@@ -1916,11 +1878,11 @@
     }
 
     /**
-     * Returns the appropriate <code>get-field</code> rop for the given
+     * Returns the appropriate {@code get-field} rop for the given
      * type. The result is a shared instance.
      * 
-     * @param type non-null; type of the field in question
-     * @return non-null; an appropriate instance
+     * @param type {@code non-null;} type of the field in question
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opGetField(TypeBearer type) {
         switch (type.getBasicType()) {
@@ -1939,11 +1901,11 @@
     }
 
     /**
-     * Returns the appropriate <code>put-field</code> rop for the given
+     * Returns the appropriate {@code put-field} rop for the given
      * type. The result is a shared instance.
      * 
-     * @param type non-null; type of the field in question
-     * @return non-null; an appropriate instance
+     * @param type {@code non-null;} type of the field in question
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opPutField(TypeBearer type) {
         switch (type.getBasicType()) {
@@ -1962,11 +1924,11 @@
     }
 
     /**
-     * Returns the appropriate <code>get-static</code> rop for the given
+     * Returns the appropriate {@code get-static} rop for the given
      * type. The result is a shared instance.
      * 
-     * @param type non-null; type of the field in question
-     * @return non-null; an appropriate instance
+     * @param type {@code non-null;} type of the field in question
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opGetStatic(TypeBearer type) {
         switch (type.getBasicType()) {
@@ -1985,11 +1947,11 @@
     }
 
     /**
-     * Returns the appropriate <code>put-static</code> rop for the given
+     * Returns the appropriate {@code put-static} rop for the given
      * type. The result is a shared instance.
      * 
-     * @param type non-null; type of the field in question
-     * @return non-null; an appropriate instance
+     * @param type {@code non-null;} type of the field in question
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opPutStatic(TypeBearer type) {
         switch (type.getBasicType()) {
@@ -2008,11 +1970,11 @@
     }
 
     /**
-     * Returns the appropriate <code>invoke-static</code> rop for the
+     * Returns the appropriate {@code invoke-static} rop for the
      * given type. The result is typically a newly-allocated instance.
      * 
-     * @param meth non-null; descriptor of the method
-     * @return non-null; an appropriate instance
+     * @param meth {@code non-null;} descriptor of the method
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opInvokeStatic(Prototype meth) {
         return new Rop(RegOps.INVOKE_STATIC,
@@ -2021,12 +1983,12 @@
     }
 
     /**
-     * Returns the appropriate <code>invoke-virtual</code> rop for the
+     * Returns the appropriate {@code invoke-virtual} rop for the
      * given type. The result is typically a newly-allocated instance.
      * 
-     * @param meth non-null; descriptor of the method, including the
-     * <code>this</code> parameter
-     * @return non-null; an appropriate instance
+     * @param meth {@code non-null;} descriptor of the method, including the
+     * {@code this} parameter
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opInvokeVirtual(Prototype meth) {
         return new Rop(RegOps.INVOKE_VIRTUAL,
@@ -2035,12 +1997,12 @@
     }
 
     /**
-     * Returns the appropriate <code>invoke-super</code> rop for the
+     * Returns the appropriate {@code invoke-super} rop for the
      * given type. The result is typically a newly-allocated instance.
      * 
-     * @param meth non-null; descriptor of the method, including the
-     * <code>this</code> parameter
-     * @return non-null; an appropriate instance
+     * @param meth {@code non-null;} descriptor of the method, including the
+     * {@code this} parameter
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opInvokeSuper(Prototype meth) {
         return new Rop(RegOps.INVOKE_SUPER,
@@ -2049,12 +2011,12 @@
     }
 
     /**
-     * Returns the appropriate <code>invoke-direct</code> rop for the
+     * Returns the appropriate {@code invoke-direct} rop for the
      * given type. The result is typically a newly-allocated instance.
      * 
-     * @param meth non-null; descriptor of the method, including the
-     * <code>this</code> parameter
-     * @return non-null; an appropriate instance
+     * @param meth {@code non-null;} descriptor of the method, including the
+     * {@code this} parameter
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opInvokeDirect(Prototype meth) {
         return new Rop(RegOps.INVOKE_DIRECT,
@@ -2063,12 +2025,12 @@
     }
 
     /**
-     * Returns the appropriate <code>invoke-interface</code> rop for the
+     * Returns the appropriate {@code invoke-interface} rop for the
      * given type. The result is typically a newly-allocated instance.
      * 
-     * @param meth non-null; descriptor of the method, including the
-     * <code>this</code> parameter
-     * @return non-null; an appropriate instance
+     * @param meth {@code non-null;} descriptor of the method, including the
+     * {@code this} parameter
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opInvokeInterface(Prototype meth) {
         return new Rop(RegOps.INVOKE_INTERFACE,
@@ -2077,11 +2039,11 @@
     }
     
     /**
-     * Returns the appropriate <code>mark-local</code> rop for the given type.
+     * Returns the appropriate {@code mark-local} rop for the given type.
      * The result is a shared instance.
      *
-     * @param type non-null; type of value being marked
-     * @return non-null; an appropriate instance
+     * @param type {@code non-null;} type of value being marked
+     * @return {@code non-null;} an appropriate instance
      */
     public static Rop opMarkLocal(TypeBearer type) {
         switch (type.getBasicFrameType()) {
@@ -2105,7 +2067,7 @@
     /**
      * Throws the right exception to complain about a bogus type.
      * 
-     * @param type non-null; the bad type
+     * @param type {@code non-null;} the bad type
      * @return never
      */
     private static Rop throwBadType(TypeBearer type) {
@@ -2115,7 +2077,7 @@
     /**
      * Throws the right exception to complain about a bogus list of types.
      * 
-     * @param types non-null; the bad types
+     * @param types {@code non-null;} the bad types
      * @return never
      */
     private static Rop throwBadTypes(TypeList types) {
diff --git a/dx/src/com/android/dx/rop/code/SourcePosition.java b/dx/src/com/android/dx/rop/code/SourcePosition.java
index da66c7d..f32caa1 100644
--- a/dx/src/com/android/dx/rop/code/SourcePosition.java
+++ b/dx/src/com/android/dx/rop/code/SourcePosition.java
@@ -24,21 +24,21 @@
  * line number and original bytecode address.
  */
 public final class SourcePosition {
-    /** non-null; convenient "no information known" instance */
+    /** {@code non-null;} convenient "no information known" instance */
     public static final SourcePosition NO_INFO =
         new SourcePosition(null, -1, -1);
 
-    /** null-ok; name of the file of origin or <code>null</code> if unknown */
+    /** {@code null-ok;} name of the file of origin or {@code null} if unknown */
     private final CstUtf8 sourceFile;
 
     /**
-     * &gt;= -1; the bytecode address, or <code>-1</code> if that
+     * {@code >= -1;} the bytecode address, or {@code -1} if that
      * information is unknown 
      */
     private final int address;
 
     /**
-     * &gt;= -1; the line number, or <code>-1</code> if that
+     * {@code >= -1;} the line number, or {@code -1} if that
      * information is unknown 
      */
     private final int line;
@@ -46,11 +46,11 @@
     /**
      * Constructs an instance.
      * 
-     * @param sourceFile null-ok; name of the file of origin or
-     * <code>null</code> if unknown
-     * @param address &gt;= -1; original bytecode address or <code>-1</code>
+     * @param sourceFile {@code null-ok;} name of the file of origin or
+     * {@code null} if unknown
+     * @param address {@code >= -1;} original bytecode address or {@code -1}
      * if unknown
-     * @param line &gt;= -1; original line number or <code>-1</code> if
+     * @param line {@code >= -1;} original line number or {@code -1} if
      * unknown
      */
     public SourcePosition(CstUtf8 sourceFile, int address, int line) {
@@ -118,8 +118,8 @@
      * Returns whether the lines match between this instance and
      * the one given.
      * 
-     * @param other non-null; the instance to compare to
-     * @return <code>true</code> iff the lines match
+     * @param other {@code non-null;} the instance to compare to
+     * @return {@code true} iff the lines match
      */
     public boolean sameLine(SourcePosition other) {
         return (line == other.line);
@@ -129,8 +129,8 @@
      * Returns whether the lines and files match between this instance and
      * the one given.
      * 
-     * @param other non-null; the instance to compare to
-     * @return <code>true</code> iff the lines and files match
+     * @param other {@code non-null;} the instance to compare to
+     * @return {@code true} iff the lines and files match
      */
     public boolean sameLineAndFile(SourcePosition other) {
         return (line == other.line) &&
@@ -141,7 +141,7 @@
     /**
      * Gets the source file, if known.
      * 
-     * @return null-ok; the source file or <code>null</code> if unknown
+     * @return {@code null-ok;} the source file or {@code null} if unknown
      */
     public CstUtf8 getSourceFile() {
         return sourceFile;
@@ -150,7 +150,7 @@
     /**
      * Gets the original bytecode address.
      * 
-     * @return &gt;= -1; the address or <code>-1</code> if unknown
+     * @return {@code >= -1;} the address or {@code -1} if unknown
      */
     public int getAddress() {
         return address;
@@ -159,7 +159,7 @@
     /**
      * Gets the original line number.
      * 
-     * @return &gt;= -1; the original line number or <code>-1</code> if
+     * @return {@code >= -1;} the original line number or {@code -1} if
      * unknown
      */
     public int getLine() {
diff --git a/dx/src/com/android/dx/rop/code/SwitchInsn.java b/dx/src/com/android/dx/rop/code/SwitchInsn.java
index fdf1a46..586205b 100644
--- a/dx/src/com/android/dx/rop/code/SwitchInsn.java
+++ b/dx/src/com/android/dx/rop/code/SwitchInsn.java
@@ -26,17 +26,17 @@
  */
 public final class SwitchInsn
         extends Insn {
-    /** non-null; list of switch cases */
+    /** {@code non-null;} list of switch cases */
     private final IntList cases;
 
     /**
      * Constructs an instance.
      * 
-     * @param opcode non-null; the opcode
-     * @param position non-null; source position
-     * @param result null-ok; spec for the result, if any
-     * @param sources non-null; specs for all the sources
-     * @param cases non-null; list of switch cases
+     * @param opcode {@code non-null;} the opcode
+     * @param position {@code non-null;} source position
+     * @param result {@code null-ok;} spec for the result, if any
+     * @param sources {@code non-null;} specs for all the sources
+     * @param cases {@code non-null;} list of switch cases
      */
     public SwitchInsn(Rop opcode, SourcePosition position, RegisterSpec result,
                       RegisterSpecList sources, IntList cases) {
@@ -90,7 +90,7 @@
      * {@inheritDoc}
      *
      * <p> SwitchInsn always compares false. The current use for this method
-     * never encounters <code>SwitchInsn</code>s
+     * never encounters {@code SwitchInsn}s
      */
     @Override
     public boolean contentEquals(Insn b) {
@@ -111,7 +111,7 @@
     /**
      * Gets the list of switch cases.
      * 
-     * @return non-null; the case list
+     * @return {@code non-null;} the case list
      */
     public IntList getCases() {
         return cases;
diff --git a/dx/src/com/android/dx/rop/code/ThrowingCstInsn.java b/dx/src/com/android/dx/rop/code/ThrowingCstInsn.java
index 49ebc91..b14e758 100644
--- a/dx/src/com/android/dx/rop/code/ThrowingCstInsn.java
+++ b/dx/src/com/android/dx/rop/code/ThrowingCstInsn.java
@@ -26,17 +26,17 @@
  */
 public final class ThrowingCstInsn
         extends CstInsn {
-    /** non-null; list of exceptions caught */
+    /** {@code non-null;} list of exceptions caught */
     private final TypeList catches;
 
     /**
      * Constructs an instance.
      * 
-     * @param opcode non-null; the opcode
-     * @param position non-null; source position
-     * @param sources non-null; specs for all the sources
-     * @param catches non-null; list of exceptions caught
-     * @param cst non-null; the constant
+     * @param opcode {@code non-null;} the opcode
+     * @param position {@code non-null;} source position
+     * @param sources {@code non-null;} specs for all the sources
+     * @param catches {@code non-null;} list of exceptions caught
+     * @param cst {@code non-null;} the constant
      */
     public ThrowingCstInsn(Rop opcode, SourcePosition position,
                            RegisterSpecList sources,
diff --git a/dx/src/com/android/dx/rop/code/ThrowingInsn.java b/dx/src/com/android/dx/rop/code/ThrowingInsn.java
index 24a5bed..78dc874 100644
--- a/dx/src/com/android/dx/rop/code/ThrowingInsn.java
+++ b/dx/src/com/android/dx/rop/code/ThrowingInsn.java
@@ -20,22 +20,22 @@
 import com.android.dx.rop.type.TypeList;
 
 /**
- * Instruction which possibly throws. The <code>successors</code> list in the
+ * Instruction which possibly throws. The {@code successors} list in the
  * basic block an instance of this class is inside corresponds in-order to
  * the list of exceptions handled by this instruction, with the
  * no-exception case appended as the final target.
  */
 public final class ThrowingInsn
         extends Insn {
-    /** non-null; list of exceptions caught */
+    /** {@code non-null;} list of exceptions caught */
     private final TypeList catches;
 
     /**
      * Gets the string form of a register spec list to be used as a catches
      * list.
      * 
-     * @param catches non-null; the catches list
-     * @return non-null; the string form
+     * @param catches {@code non-null;} the catches list
+     * @return {@code non-null;} the string form
      */
     public static String toCatchString(TypeList catches) {
         StringBuffer sb = new StringBuffer(100);
@@ -54,10 +54,10 @@
     /**
      * Constructs an instance.
      * 
-     * @param opcode non-null; the opcode
-     * @param position non-null; source position
-     * @param sources non-null; specs for all the sources
-     * @param catches non-null; list of exceptions caught
+     * @param opcode {@code non-null;} the opcode
+     * @param position {@code non-null;} source position
+     * @param sources {@code non-null;} specs for all the sources
+     * @param catches {@code non-null;} list of exceptions caught
      */
     public ThrowingInsn(Rop opcode, SourcePosition position,
                         RegisterSpecList sources,
diff --git a/dx/src/com/android/dx/rop/code/TranslationAdvice.java b/dx/src/com/android/dx/rop/code/TranslationAdvice.java
index 8c2cde9..832d84d 100644
--- a/dx/src/com/android/dx/rop/code/TranslationAdvice.java
+++ b/dx/src/com/android/dx/rop/code/TranslationAdvice.java
@@ -30,10 +30,10 @@
      * last argument must have a type which indicates it is a known constant.)
      * The instruction associated must have exactly two sources.
      *
-     * @param opcode non-null; the opcode
-     * @param sourceA non-null; the first source
-     * @param sourceB non-null; the second source
-     * @return <code>true</code> iff the target can represent the operation
+     * @param opcode {@code non-null;} the opcode
+     * @param sourceA {@code non-null;} the first source
+     * @param sourceB {@code non-null;} the second source
+     * @return {@code true} iff the target can represent the operation
      * using a constant for the last argument
      */
     public boolean hasConstantOperation(Rop opcode,
@@ -43,9 +43,9 @@
      * Returns true if the translation target requires the sources of the
      * specified opcode to be in order and contiguous (eg, for an invoke-range)
      *
-     * @param opcode non-null; opcode
-     * @param sources non-null; source list
-     * @return <code>true</code> iff the target requires the sources to be
+     * @param opcode {@code non-null;} opcode
+     * @param sources {@code non-null;} source list
+     * @return {@code true} iff the target requires the sources to be
      * in order and contiguous.
      */
     public boolean requiresSourcesInOrder(Rop opcode, RegisterSpecList sources);
diff --git a/dx/src/com/android/dx/rop/cst/Constant.java b/dx/src/com/android/dx/rop/cst/Constant.java
index 0f44010..64231d3 100644
--- a/dx/src/com/android/dx/rop/cst/Constant.java
+++ b/dx/src/com/android/dx/rop/cst/Constant.java
@@ -24,11 +24,11 @@
 public abstract class Constant
         implements ToHuman, Comparable<Constant> {
     /**
-     * Returns <code>true</code> if this instance is a category-2 constant,
+     * Returns {@code true} if this instance is a category-2 constant,
      * meaning it takes up two slots in the constant pool, or
-     * <code>false</code> if this instance is category-1.
+     * {@code false} if this instance is category-1.
      *
-     * @return <code>true</code> iff this instance is category-2
+     * @return {@code true} iff this instance is category-2
      */
     public abstract boolean isCategory2();
 
@@ -36,7 +36,7 @@
      * Returns the human name for the particular type of constant
      * this instance is.
      *
-     * @return non-null; the name
+     * @return {@code non-null;} the name
      */
     public abstract String typeName();
 
@@ -60,8 +60,8 @@
      * Compare the values of this and another instance, which are guaranteed
      * to be of the same class. Subclasses must implement this.
      * 
-     * @param other non-null; the instance to compare to
-     * @return <code>-1</code>, <code>0</code>, or <code>1</code>, as usual
+     * @param other {@code non-null;} the instance to compare to
+     * @return {@code -1}, {@code 0}, or {@code 1}, as usual
      * for a comparison
      */
     protected abstract int compareTo0(Constant other);
diff --git a/dx/src/com/android/dx/rop/cst/ConstantPool.java b/dx/src/com/android/dx/rop/cst/ConstantPool.java
index 9a64a2a..efc394d 100644
--- a/dx/src/com/android/dx/rop/cst/ConstantPool.java
+++ b/dx/src/com/android/dx/rop/cst/ConstantPool.java
@@ -23,47 +23,47 @@
 public interface ConstantPool {
     /**
      * Get the "size" of the constant pool. This corresponds to the
-     * class file field <code>constant_pool_count</code>, and is in fact
+     * class file field {@code constant_pool_count}, and is in fact
      * always at least one more than the actual size of the constant pool,
-     * as element <code>0</code> is always invalid.
+     * as element {@code 0} is always invalid.
      *
-     * @return <code>&gt;= 1</code>; the size
+     * @return {@code >= 1;} the size
      */
     public int size();
 
     /**
-     * Get the <code>n</code>th entry in the constant pool, which must
+     * Get the {@code n}th entry in the constant pool, which must
      * be valid.
      *
-     * @param n <code>n &gt;= 0, n &lt; size()</code>; the constant pool index
-     * @return non-null; the corresponding entry
-     * @throws IllegalArgumentException thrown if <code>n</code> is
+     * @param n {@code n >= 0, n < size();} the constant pool index
+     * @return {@code non-null;} the corresponding entry
+     * @throws IllegalArgumentException thrown if {@code n} is
      * in-range but invalid
      */
     public Constant get(int n);
 
     /**
-     * Get the <code>n</code>th entry in the constant pool, which must
-     * be valid unless <code>n == 0</code>, in which case <code>null</code>
+     * Get the {@code n}th entry in the constant pool, which must
+     * be valid unless {@code n == 0}, in which case {@code null}
      * is returned.
      *
-     * @param n <code>n &gt;= 0, n &lt; size()</code>; the constant pool index
-     * @return null-ok; the corresponding entry, if <code>n != 0</code>
-     * @throws IllegalArgumentException thrown if <code>n</code> is
+     * @param n {@code n >= 0, n < size();} the constant pool index
+     * @return {@code null-ok;} the corresponding entry, if {@code n != 0}
+     * @throws IllegalArgumentException thrown if {@code n} is
      * in-range and non-zero but invalid
      */
     public Constant get0Ok(int n);
 
     /**
-     * Get the <code>n</code>th entry in the constant pool, or
-     * <code>null</code> if the index is in-range but invalid. In
-     * particular, <code>null</code> is returned for index <code>0</code>
+     * Get the {@code n}th entry in the constant pool, or
+     * {@code null} if the index is in-range but invalid. In
+     * particular, {@code null} is returned for index {@code 0}
      * as well as the index after any entry which is defined to take up
-     * two slots (that is, <code>Long</code> and <code>Double</code>
+     * two slots (that is, {@code Long} and {@code Double}
      * entries).
      *
-     * @param n <code>n &gt;= 0, n &lt; size()</code>; the constant pool index
-     * @return null-ok; the corresponding entry, or <code>null</code> if
+     * @param n {@code n >= 0, n < size();} the constant pool index
+     * @return {@code null-ok;} the corresponding entry, or {@code null} if
      * the index is in-range but invalid
      */
     public Constant getOrNull(int n);
diff --git a/dx/src/com/android/dx/rop/cst/CstAnnotation.java b/dx/src/com/android/dx/rop/cst/CstAnnotation.java
index d6dc1f2..1385798 100644
--- a/dx/src/com/android/dx/rop/cst/CstAnnotation.java
+++ b/dx/src/com/android/dx/rop/cst/CstAnnotation.java
@@ -22,13 +22,13 @@
  * Constant type that represents an annotation.
  */
 public final class CstAnnotation extends Constant {
-    /** non-null; the actual annotation */
+    /** {@code non-null;} the actual annotation */
     private final Annotation annotation;
     
     /**
      * Constructs an instance.
      *
-     * @param annotation non-null; the annotation to hold
+     * @param annotation {@code non-null;} the annotation to hold
      */
     public CstAnnotation(Annotation annotation) {
         if (annotation == null) {
@@ -88,7 +88,7 @@
     /**
      * Get the underlying annotation.
      * 
-     * @return non-null; the annotation
+     * @return {@code non-null;} the annotation
      */
     public Annotation getAnnotation() {
         return annotation;
diff --git a/dx/src/com/android/dx/rop/cst/CstArray.java b/dx/src/com/android/dx/rop/cst/CstArray.java
index 69c0aef..8b521bd 100644
--- a/dx/src/com/android/dx/rop/cst/CstArray.java
+++ b/dx/src/com/android/dx/rop/cst/CstArray.java
@@ -24,13 +24,13 @@
  * may be of any type <i>other</i> than {@link CstUtf8}.
  */
 public final class CstArray extends Constant {
-    /** non-null; the actual list of contents */
+    /** {@code non-null;} the actual list of contents */
     private final List list;
     
     /**
      * Constructs an instance.
      *
-     * @param list non-null; the actual list of contents
+     * @param list {@code non-null;} the actual list of contents
      */
     public CstArray(List list) {
         if (list == null) {
@@ -90,7 +90,7 @@
     /**
      * Get the underlying list.
      * 
-     * @return non-null; the list
+     * @return {@code non-null;} the list
      */
     public List getList() {
         return list;
@@ -103,7 +103,7 @@
             extends FixedSizeList implements Comparable<List> {
         /**
          * Constructs an instance. All indices initially contain
-         * <code>null</code>.
+         * {@code null}.
          * 
          * @param size the size of the list
          */
@@ -138,10 +138,10 @@
         /**
          * Gets the element at the given index. It is an error to call
          * this with the index for an element which was never set; if you
-         * do that, this will throw <code>NullPointerException</code>.
+         * do that, this will throw {@code NullPointerException}.
          * 
-         * @param n &gt;= 0, &lt; size(); which index
-         * @return non-null; element at that index
+         * @param n {@code >= 0, < size();} which index
+         * @return {@code non-null;} element at that index
          */
         public Constant get(int n) {
             return (Constant) get0(n);
@@ -150,8 +150,8 @@
         /**
          * Sets the element at the given index.
          * 
-         * @param n &gt;= 0, &lt; size(); which index
-         * @param a null-ok; the element to set at <code>n</code>
+         * @param n {@code >= 0, < size();} which index
+         * @param a {@code null-ok;} the element to set at {@code n}
          */
         public void set(int n, Constant a) {
             if (a instanceof CstUtf8) {
diff --git a/dx/src/com/android/dx/rop/cst/CstBaseMethodRef.java b/dx/src/com/android/dx/rop/cst/CstBaseMethodRef.java
index c885601..039d7ed 100644
--- a/dx/src/com/android/dx/rop/cst/CstBaseMethodRef.java
+++ b/dx/src/com/android/dx/rop/cst/CstBaseMethodRef.java
@@ -28,20 +28,20 @@
  */
 public abstract class CstBaseMethodRef
         extends CstMemberRef {
-    /** non-null; the raw prototype for this method */
+    /** {@code non-null;} the raw prototype for this method */
     private final Prototype prototype;
 
     /**
-     * null-ok; the prototype for this method taken to be an instance
-     * method, or <code>null</code> if not yet calculated
+     * {@code null-ok;} the prototype for this method taken to be an instance
+     * method, or {@code null} if not yet calculated
      */
     private Prototype instancePrototype;
 
     /**
      * Constructs an instance.
      *
-     * @param definingClass non-null; the type of the defining class
-     * @param nat non-null; the name-and-type
+     * @param definingClass {@code non-null;} the type of the defining class
+     * @param nat {@code non-null;} the name-and-type
      */
     /*package*/ CstBaseMethodRef(CstType definingClass, CstNat nat) {
         super(definingClass, nat);
@@ -53,9 +53,9 @@
 
     /**
      * Gets the raw prototype of this method. This doesn't include a
-     * <code>this</code> argument.
+     * {@code this} argument.
      *
-     * @return non-null; the method prototype
+     * @return {@code non-null;} the method prototype
      */
     public final Prototype getPrototype() {
         return prototype;
@@ -63,14 +63,14 @@
 
     /**
      * Gets the prototype of this method as either a
-     * <code>static</code> or instance method. In the case of a
-     * <code>static</code> method, this is the same as the raw
+     * {@code static} or instance method. In the case of a
+     * {@code static} method, this is the same as the raw
      * prototype. In the case of an instance method, this has an
-     * appropriately-typed <code>this</code> argument as the first
+     * appropriately-typed {@code this} argument as the first
      * one.
      *
      * @param isStatic whether the method should be considered static
-     * @return non-null; the method prototype
+     * @return {@code non-null;} the method prototype
      */
     public final Prototype getPrototype(boolean isStatic) {
         if (isStatic) {
@@ -102,7 +102,7 @@
      * 
      * In this case, this method returns the <i>return type</i> of this method.
      *
-     * @return non-null; the method's return type
+     * @return {@code non-null;} the method's return type
      */
     public final Type getType() {
         return prototype.getReturnType();
@@ -111,15 +111,15 @@
     /**
      * Gets the number of words of parameters required by this
      * method's descriptor. Since instances of this class have no way
-     * to know if they will be used in a <code>static</code> or
+     * to know if they will be used in a {@code static} or
      * instance context, one has to indicate this explicitly as an
      * argument. This method is just a convenient shorthand for
-     * <code>getPrototype().getParameterTypes().getWordCount()</code>,
-     * plus <code>1</code> if the method is to be treated as an
+     * {@code getPrototype().getParameterTypes().getWordCount()},
+     * plus {@code 1} if the method is to be treated as an
      * instance method.
      * 
      * @param isStatic whether the method should be considered static
-     * @return &gt;= 0; the argument word count
+     * @return {@code >= 0;} the argument word count
      */
     public final int getParameterWordCount(boolean isStatic) {
         return getPrototype(isStatic).getParameterTypes().getWordCount();
@@ -128,9 +128,9 @@
     /**
      * Gets whether this is a reference to an instance initialization
      * method. This is just a convenient shorthand for
-     * <code>getNat().isInstanceInit()</code>.
+     * {@code getNat().isInstanceInit()}.
      *
-     * @return <code>true</code> iff this is a reference to an
+     * @return {@code true} iff this is a reference to an
      * instance initialization method
      */
     public final boolean isInstanceInit() {
@@ -140,9 +140,9 @@
     /**
      * Gets whether this is a reference to a class initialization
      * method. This is just a convenient shorthand for
-     * <code>getNat().isClassInit()</code>.
+     * {@code getNat().isClassInit()}.
      *
-     * @return <code>true</code> iff this is a reference to an
+     * @return {@code true} iff this is a reference to an
      * instance initialization method
      */
     public final boolean isClassInit() {
diff --git a/dx/src/com/android/dx/rop/cst/CstBoolean.java b/dx/src/com/android/dx/rop/cst/CstBoolean.java
index ab25d5b..8c290ef 100644
--- a/dx/src/com/android/dx/rop/cst/CstBoolean.java
+++ b/dx/src/com/android/dx/rop/cst/CstBoolean.java
@@ -19,33 +19,33 @@
 import com.android.dx.rop.type.Type;
 
 /**
- * Constants of type <code>boolean</code>.
+ * Constants of type {@code boolean}.
  */
 public final class CstBoolean
         extends CstLiteral32 {
-    /** non-null; instance representing <code>false</code> */
+    /** {@code non-null;} instance representing {@code false} */
     public static final CstBoolean VALUE_FALSE = new CstBoolean(false);
 
-    /** non-null; instance representing <code>true</code> */
+    /** {@code non-null;} instance representing {@code true} */
     public static final CstBoolean VALUE_TRUE = new CstBoolean(true);
 
     /**
      * Makes an instance for the given value. This will return an
      * already-allocated instance.
      * 
-     * @param value the <code>boolean</code> value
-     * @return non-null; the appropriate instance
+     * @param value the {@code boolean} value
+     * @return {@code non-null;} the appropriate instance
      */
     public static CstBoolean make(boolean value) {
         return value ? VALUE_TRUE : VALUE_FALSE;
     }
 
     /**
-     * Makes an instance for the given <code>int</code> value. This
+     * Makes an instance for the given {@code int} value. This
      * will return an already-allocated instance.
      * 
-     * @param value must be either <code>0</code> or <code>1</code>
-     * @return non-null; the appropriate instance
+     * @param value must be either {@code 0} or {@code 1}
+     * @return {@code non-null;} the appropriate instance
      */
     public static CstBoolean make(int value) {
         if (value == 0) {
@@ -60,7 +60,7 @@
     /**
      * Constructs an instance. This constructor is private; use {@link #make}.
      * 
-     * @param value the <code>boolean</code> value
+     * @param value the {@code boolean} value
      */
     private CstBoolean(boolean value) {
         super(value ? 1 : 0);
@@ -89,7 +89,7 @@
     }
 
     /**
-     * Gets the <code>boolean</code> value.
+     * Gets the {@code boolean} value.
      * 
      * @return the value
      */
diff --git a/dx/src/com/android/dx/rop/cst/CstByte.java b/dx/src/com/android/dx/rop/cst/CstByte.java
index ffc3206..a8af9f7 100644
--- a/dx/src/com/android/dx/rop/cst/CstByte.java
+++ b/dx/src/com/android/dx/rop/cst/CstByte.java
@@ -20,30 +20,30 @@
 import com.android.dx.util.Hex;
 
 /**
- * Constants of type <code>byte</code>.
+ * Constants of type {@code byte}.
  */
 public final class CstByte
         extends CstLiteral32 {
-    /** non-null; the value <code>0</code> as an instance of this class */
+    /** {@code non-null;} the value {@code 0} as an instance of this class */
     public static final CstByte VALUE_0 = make((byte) 0);
     
     /**
      * Makes an instance for the given value. This may (but does not
      * necessarily) return an already-allocated instance.
      * 
-     * @param value the <code>byte</code> value
+     * @param value the {@code byte} value
      */
     public static CstByte make(byte value) {
         return new CstByte(value);
     }
 
     /**
-     * Makes an instance for the given <code>int</code> value. This
+     * Makes an instance for the given {@code int} value. This
      * may (but does not necessarily) return an already-allocated
      * instance.
      * 
-     * @param value the value, which must be in range for a <code>byte</code>
-     * @return non-null; the appropriate instance
+     * @param value the value, which must be in range for a {@code byte}
+     * @return {@code non-null;} the appropriate instance
      */
     public static CstByte make(int value) {
         byte cast = (byte) value;
@@ -59,7 +59,7 @@
     /**
      * Constructs an instance. This constructor is private; use {@link #make}.
      * 
-     * @param value the <code>byte</code> value
+     * @param value the {@code byte} value
      */
     private CstByte(byte value) {
         super(value);
@@ -89,7 +89,7 @@
     }
 
     /**
-     * Gets the <code>byte</code> value.
+     * Gets the {@code byte} value.
      * 
      * @return the value
      */
diff --git a/dx/src/com/android/dx/rop/cst/CstChar.java b/dx/src/com/android/dx/rop/cst/CstChar.java
index a31bd7f..0a87cbc 100644
--- a/dx/src/com/android/dx/rop/cst/CstChar.java
+++ b/dx/src/com/android/dx/rop/cst/CstChar.java
@@ -20,30 +20,30 @@
 import com.android.dx.util.Hex;
 
 /**
- * Constants of type <code>char</code>.
+ * Constants of type {@code char}.
  */
 public final class CstChar
         extends CstLiteral32 {
-    /** non-null; the value <code>0</code> as an instance of this class */
+    /** {@code non-null;} the value {@code 0} as an instance of this class */
     public static final CstChar VALUE_0 = make((char) 0);
 
     /**
      * Makes an instance for the given value. This may (but does not
      * necessarily) return an already-allocated instance.
      * 
-     * @param value the <code>char</code> value
+     * @param value the {@code char} value
      */
     public static CstChar make(char value) {
         return new CstChar(value);
     }
 
     /**
-     * Makes an instance for the given <code>int</code> value. This
+     * Makes an instance for the given {@code int} value. This
      * may (but does not necessarily) return an already-allocated
      * instance.
      * 
-     * @param value the value, which must be in range for a <code>char</code>
-     * @return non-null; the appropriate instance
+     * @param value the value, which must be in range for a {@code char}
+     * @return {@code non-null;} the appropriate instance
      */
     public static CstChar make(int value) {
         char cast = (char) value;
@@ -59,7 +59,7 @@
     /**
      * Constructs an instance. This constructor is private; use {@link #make}.
      * 
-     * @param value the <code>char</code> value
+     * @param value the {@code char} value
      */
     private CstChar(char value) {
         super(value);
@@ -89,7 +89,7 @@
     }
 
     /**
-     * Gets the <code>char</code> value.
+     * Gets the {@code char} value.
      * 
      * @return the value
      */
diff --git a/dx/src/com/android/dx/rop/cst/CstDouble.java b/dx/src/com/android/dx/rop/cst/CstDouble.java
index 4516667..df4a2cf 100644
--- a/dx/src/com/android/dx/rop/cst/CstDouble.java
+++ b/dx/src/com/android/dx/rop/cst/CstDouble.java
@@ -20,15 +20,15 @@
 import com.android.dx.util.Hex;
 
 /**
- * Constants of type <code>CONSTANT_Double_info</code>.
+ * Constants of type {@code CONSTANT_Double_info}.
  */
 public final class CstDouble
         extends CstLiteral64 {
-    /** non-null; instance representing <code>0</code> */
+    /** {@code non-null;} instance representing {@code 0} */
     public static final CstDouble VALUE_0 =
         new CstDouble(Double.doubleToLongBits(0.0));
 
-    /** non-null; instance representing <code>1</code> */
+    /** {@code non-null;} instance representing {@code 1} */
     public static final CstDouble VALUE_1 =
         new CstDouble(Double.doubleToLongBits(1.0));
 
@@ -36,7 +36,7 @@
      * Makes an instance for the given value. This may (but does not
      * necessarily) return an already-allocated instance.
      * 
-     * @param bits the <code>double</code> value as <code>long</code> bits
+     * @param bits the {@code double} value as {@code long} bits
      */
     public static CstDouble make(long bits) {
         /*
@@ -49,7 +49,7 @@
     /**
      * Constructs an instance. This constructor is private; use {@link #make}.
      * 
-     * @param bits the <code>double</code> value as <code>long</code> bits
+     * @param bits the {@code double} value as {@code long} bits
      */
     private CstDouble(long bits) {
         super(bits);
@@ -80,7 +80,7 @@
     }
 
     /**
-     * Gets the <code>double</code> value.
+     * Gets the {@code double} value.
      * 
      * @return the value
      */
diff --git a/dx/src/com/android/dx/rop/cst/CstEnumRef.java b/dx/src/com/android/dx/rop/cst/CstEnumRef.java
index f5aec05..78cab9d 100644
--- a/dx/src/com/android/dx/rop/cst/CstEnumRef.java
+++ b/dx/src/com/android/dx/rop/cst/CstEnumRef.java
@@ -23,13 +23,13 @@
  * value of an enumerated type.
  */
 public final class CstEnumRef extends CstMemberRef {
-    /** null-ok; the corresponding field ref, lazily initialized */
+    /** {@code null-ok;} the corresponding field ref, lazily initialized */
     private CstFieldRef fieldRef;
     
     /**
      * Constructs an instance.
      *
-     * @param nat non-null; the name-and-type; the defining class is derived
+     * @param nat {@code non-null;} the name-and-type; the defining class is derived
      * from this
      */
     public CstEnumRef(CstNat nat) {
@@ -56,7 +56,7 @@
     /**
      * Get a {@link CstFieldRef} that corresponds with this instance.
      * 
-     * @return non-null; the corresponding field reference
+     * @return {@code non-null;} the corresponding field reference
      */
     public CstFieldRef getFieldRef() {
         if (fieldRef == null) {
diff --git a/dx/src/com/android/dx/rop/cst/CstFieldRef.java b/dx/src/com/android/dx/rop/cst/CstFieldRef.java
index 306eca9..497531f 100644
--- a/dx/src/com/android/dx/rop/cst/CstFieldRef.java
+++ b/dx/src/com/android/dx/rop/cst/CstFieldRef.java
@@ -19,7 +19,7 @@
 import com.android.dx.rop.type.Type;
 
 /**
- * Constants of type <code>CONSTANT_Fieldref_info</code>.
+ * Constants of type {@code CONSTANT_Fieldref_info}.
  */
 public final class CstFieldRef extends CstMemberRef {
     /**
@@ -27,10 +27,10 @@
      * field which should hold the class corresponding to a given
      * primitive type. For example, if given {@link Type#INT}, this
      * method returns an instance corresponding to the field
-     * <code>java.lang.Integer.TYPE</code>.
+     * {@code java.lang.Integer.TYPE}.
      * 
-     * @param primitiveType non-null; the primitive type
-     * @return non-null; the corresponding static field
+     * @param primitiveType {@code non-null;} the primitive type
+     * @return {@code non-null;} the corresponding static field
      */
     public static CstFieldRef forPrimitiveType(Type primitiveType) {
         return new CstFieldRef(CstType.forBoxedPrimitiveType(primitiveType),
@@ -40,8 +40,8 @@
     /**
      * Constructs an instance.
      * 
-     * @param definingClass non-null; the type of the defining class
-     * @param nat non-null; the name-and-type
+     * @param definingClass {@code non-null;} the type of the defining class
+     * @param nat {@code non-null;} the name-and-type
      */
     public CstFieldRef(CstType definingClass, CstNat nat) {
         super(definingClass, nat);
@@ -56,7 +56,7 @@
     /**
      * Returns the type of this field.
      * 
-     * @return non-null; the field's type
+     * @return {@code non-null;} the field's type
      */
     public Type getType() {
         return getNat().getFieldType();
diff --git a/dx/src/com/android/dx/rop/cst/CstFloat.java b/dx/src/com/android/dx/rop/cst/CstFloat.java
index 08b7f76..531a20d 100644
--- a/dx/src/com/android/dx/rop/cst/CstFloat.java
+++ b/dx/src/com/android/dx/rop/cst/CstFloat.java
@@ -20,24 +20,24 @@
 import com.android.dx.util.Hex;
 
 /**
- * Constants of type <code>CONSTANT_Float_info</code>.
+ * Constants of type {@code CONSTANT_Float_info}.
  */
 public final class CstFloat
         extends CstLiteral32 {
-    /** non-null; instance representing <code>0</code> */
+    /** {@code non-null;} instance representing {@code 0} */
     public static final CstFloat VALUE_0 = make(Float.floatToIntBits(0.0f));
 
-    /** non-null; instance representing <code>1</code> */
+    /** {@code non-null;} instance representing {@code 1} */
     public static final CstFloat VALUE_1 = make(Float.floatToIntBits(1.0f));
 
-    /** non-null; instance representing <code>2</code> */
+    /** {@code non-null;} instance representing {@code 2} */
     public static final CstFloat VALUE_2 = make(Float.floatToIntBits(2.0f));
 
     /**
      * Makes an instance for the given value. This may (but does not
      * necessarily) return an already-allocated instance.
      * 
-     * @param bits the <code>float</code> value as <code>int</code> bits
+     * @param bits the {@code float} value as {@code int} bits
      */
     public static CstFloat make(int bits) {
         /*
@@ -50,7 +50,7 @@
     /**
      * Constructs an instance. This constructor is private; use {@link #make}.
      * 
-     * @param bits the <code>float</code> value as <code>int</code> bits
+     * @param bits the {@code float} value as {@code int} bits
      */
     private CstFloat(int bits) {
         super(bits);
@@ -81,7 +81,7 @@
     }
 
     /**
-     * Gets the <code>float</code> value.
+     * Gets the {@code float} value.
      * 
      * @return the value
      */
diff --git a/dx/src/com/android/dx/rop/cst/CstInteger.java b/dx/src/com/android/dx/rop/cst/CstInteger.java
index d3fafcc..8fae4fa 100644
--- a/dx/src/com/android/dx/rop/cst/CstInteger.java
+++ b/dx/src/com/android/dx/rop/cst/CstInteger.java
@@ -20,40 +20,40 @@
 import com.android.dx.util.Hex;
 
 /**
- * Constants of type <code>CONSTANT_Integer_info</code>.
+ * Constants of type {@code CONSTANT_Integer_info}.
  */
 public final class CstInteger
         extends CstLiteral32 {
-    /** non-null; array of cached instances */
+    /** {@code non-null;} array of cached instances */
     private static final CstInteger[] cache = new CstInteger[511];
 
-    /** non-null; instance representing <code>-1</code> */
+    /** {@code non-null;} instance representing {@code -1} */
     public static final CstInteger VALUE_M1 = make(-1);
 
-    /** non-null; instance representing <code>0</code> */
+    /** {@code non-null;} instance representing {@code 0} */
     public static final CstInteger VALUE_0 = make(0);
 
-    /** non-null; instance representing <code>1</code> */
+    /** {@code non-null;} instance representing {@code 1} */
     public static final CstInteger VALUE_1 = make(1);
 
-    /** non-null; instance representing <code>2</code> */
+    /** {@code non-null;} instance representing {@code 2} */
     public static final CstInteger VALUE_2 = make(2);
 
-    /** non-null; instance representing <code>3</code> */
+    /** {@code non-null;} instance representing {@code 3} */
     public static final CstInteger VALUE_3 = make(3);
 
-    /** non-null; instance representing <code>4</code> */
+    /** {@code non-null;} instance representing {@code 4} */
     public static final CstInteger VALUE_4 = make(4);
 
-    /** non-null; instance representing <code>5</code> */
+    /** {@code non-null;} instance representing {@code 5} */
     public static final CstInteger VALUE_5 = make(5);
 
     /**
      * Makes an instance for the given value. This may (but does not
      * necessarily) return an already-allocated instance.
      * 
-     * @param value the <code>int</code> value
-     * @return non-null; the appropriate instance
+     * @param value the {@code int} value
+     * @return {@code non-null;} the appropriate instance
      */
     public static CstInteger make(int value) {
         /*
@@ -76,7 +76,7 @@
     /**
      * Constructs an instance. This constructor is private; use {@link #make}.
      * 
-     * @param value the <code>int</code> value
+     * @param value the {@code int} value
      */
     private CstInteger(int value) {
         super(value);
@@ -106,7 +106,7 @@
     }
 
     /**
-     * Gets the <code>int</code> value.
+     * Gets the {@code int} value.
      * 
      * @return the value
      */
diff --git a/dx/src/com/android/dx/rop/cst/CstInterfaceMethodRef.java b/dx/src/com/android/dx/rop/cst/CstInterfaceMethodRef.java
index f169ec9..55a7599 100644
--- a/dx/src/com/android/dx/rop/cst/CstInterfaceMethodRef.java
+++ b/dx/src/com/android/dx/rop/cst/CstInterfaceMethodRef.java
@@ -17,12 +17,12 @@
 package com.android.dx.rop.cst;
 
 /**
- * Constants of type <code>CONSTANT_InterfaceMethodref_info</code>.
+ * Constants of type {@code CONSTANT_InterfaceMethodref_info}.
  */
 public final class CstInterfaceMethodRef
         extends CstBaseMethodRef {
     /**
-     * null-ok; normal {@link CstMethodRef} that corresponds to this
+     * {@code null-ok;} normal {@link CstMethodRef} that corresponds to this
      * instance, if calculated 
      */
     private CstMethodRef methodRef;
@@ -30,8 +30,8 @@
     /**
      * Constructs an instance.
      * 
-     * @param definingClass non-null; the type of the defining class
-     * @param nat non-null; the name-and-type
+     * @param definingClass {@code non-null;} the type of the defining class
+     * @param nat {@code non-null;} the name-and-type
      */
     public CstInterfaceMethodRef(CstType definingClass, CstNat nat) {
         super(definingClass, nat);
@@ -48,7 +48,7 @@
      * Gets a normal (non-interface) {@link CstMethodRef} that corresponds to
      * this instance.
      * 
-     * @return non-null; an appropriate instance
+     * @return {@code non-null;} an appropriate instance
      */
     public CstMethodRef toMethodRef() {
         if (methodRef == null) {
diff --git a/dx/src/com/android/dx/rop/cst/CstKnownNull.java b/dx/src/com/android/dx/rop/cst/CstKnownNull.java
index 853e57e..09dde1b 100644
--- a/dx/src/com/android/dx/rop/cst/CstKnownNull.java
+++ b/dx/src/com/android/dx/rop/cst/CstKnownNull.java
@@ -19,10 +19,10 @@
 import com.android.dx.rop.type.Type;
 
 /**
- * Constant type to represent a known-<code>null</code> value.
+ * Constant type to represent a known-{@code null} value.
  */
 public final class CstKnownNull extends CstLiteralBits {
-    /** non-null; unique instance of this class */
+    /** {@code non-null;} unique instance of this class */
     public static final CstKnownNull THE_ONE = new CstKnownNull();
 
     /**
diff --git a/dx/src/com/android/dx/rop/cst/CstLiteral32.java b/dx/src/com/android/dx/rop/cst/CstLiteral32.java
index 31e96dd..c6e3021 100644
--- a/dx/src/com/android/dx/rop/cst/CstLiteral32.java
+++ b/dx/src/com/android/dx/rop/cst/CstLiteral32.java
@@ -21,13 +21,13 @@
  */
 public abstract class CstLiteral32
         extends CstLiteralBits {
-    /** the value as <code>int</code> bits */
+    /** the value as {@code int} bits */
     private final int bits;
 
     /**
      * Constructs an instance.
      * 
-     * @param bits the value as <code>int</code> bits
+     * @param bits the value as {@code int} bits
      */
     /*package*/ CstLiteral32(int bits) {
         this.bits = bits;
diff --git a/dx/src/com/android/dx/rop/cst/CstLiteral64.java b/dx/src/com/android/dx/rop/cst/CstLiteral64.java
index dd7d24d..d0b27d2 100644
--- a/dx/src/com/android/dx/rop/cst/CstLiteral64.java
+++ b/dx/src/com/android/dx/rop/cst/CstLiteral64.java
@@ -21,13 +21,13 @@
  */
 public abstract class CstLiteral64
         extends CstLiteralBits {
-    /** the value as <code>long</code> bits */
+    /** the value as {@code long} bits */
     private final long bits;
 
     /**
      * Constructs an instance.
      * 
-     * @param bits the value as <code>long</code> bits
+     * @param bits the value as {@code long} bits
      */
     /*package*/ CstLiteral64(long bits) {
         this.bits = bits;
diff --git a/dx/src/com/android/dx/rop/cst/CstLiteralBits.java b/dx/src/com/android/dx/rop/cst/CstLiteralBits.java
index 98a3f0e..6415487 100644
--- a/dx/src/com/android/dx/rop/cst/CstLiteralBits.java
+++ b/dx/src/com/android/dx/rop/cst/CstLiteralBits.java
@@ -23,18 +23,18 @@
         extends TypedConstant {
     /**
      * Returns whether or not this instance's value may be accurately
-     * represented as an <code>int</code>. The rule is that if there
-     * is an <code>int</code> which may be sign-extended to yield this
-     * instance's value, then this method returns <code>true</code>.
-     * Otherwise, it returns <code>false</code>.
+     * represented as an {@code int}. The rule is that if there
+     * is an {@code int} which may be sign-extended to yield this
+     * instance's value, then this method returns {@code true}.
+     * Otherwise, it returns {@code false}.
      *
-     * @return <code>true</code> iff this instance fits in an <code>int</code>
+     * @return {@code true} iff this instance fits in an {@code int}
      */
     public abstract boolean fitsInInt();
 
     /**
-     * Gets the value as <code>int</code> bits. If this instance contains
-     * more bits than fit in an <code>int</code>, then this returns only
+     * Gets the value as {@code int} bits. If this instance contains
+     * more bits than fit in an {@code int}, then this returns only
      * the low-order bits.
      *
      * @return the bits
@@ -42,8 +42,8 @@
     public abstract int getIntBits();
 
     /**
-     * Gets the value as <code>long</code> bits. If this instance contains
-     * fewer bits than fit in a <code>long</code>, then the result of this
+     * Gets the value as {@code long} bits. If this instance contains
+     * fewer bits than fit in a {@code long}, then the result of this
      * method is the sign extension of the value.
      * 
      * @return the bits
diff --git a/dx/src/com/android/dx/rop/cst/CstLong.java b/dx/src/com/android/dx/rop/cst/CstLong.java
index 377eb93..c89a339 100644
--- a/dx/src/com/android/dx/rop/cst/CstLong.java
+++ b/dx/src/com/android/dx/rop/cst/CstLong.java
@@ -20,21 +20,21 @@
 import com.android.dx.util.Hex;
 
 /**
- * Constants of type <code>CONSTANT_Long_info</code>.
+ * Constants of type {@code CONSTANT_Long_info}.
  */
 public final class CstLong
         extends CstLiteral64 {
-    /** non-null; instance representing <code>0</code> */
+    /** {@code non-null;} instance representing {@code 0} */
     public static final CstLong VALUE_0 = make(0);
 
-    /** non-null; instance representing <code>1</code> */
+    /** {@code non-null;} instance representing {@code 1} */
     public static final CstLong VALUE_1 = make(1);
 
     /**
      * Makes an instance for the given value. This may (but does not
      * necessarily) return an already-allocated instance.
      * 
-     * @param value the <code>long</code> value
+     * @param value the {@code long} value
      */
     public static CstLong make(long value) {
         /*
@@ -47,7 +47,7 @@
     /**
      * Constructs an instance. This constructor is private; use {@link #make}.
      * 
-     * @param value the <code>long</code> value
+     * @param value the {@code long} value
      */
     private CstLong(long value) {
         super(value);
@@ -77,7 +77,7 @@
     }
 
     /**
-     * Gets the <code>long</code> value.
+     * Gets the {@code long} value.
      * 
      * @return the value
      */
diff --git a/dx/src/com/android/dx/rop/cst/CstMemberRef.java b/dx/src/com/android/dx/rop/cst/CstMemberRef.java
index dbaad47..bae47c2 100644
--- a/dx/src/com/android/dx/rop/cst/CstMemberRef.java
+++ b/dx/src/com/android/dx/rop/cst/CstMemberRef.java
@@ -17,20 +17,20 @@
 package com.android.dx.rop.cst;
 
 /**
- * Constants of type <code>CONSTANT_*ref_info</code>.
+ * Constants of type {@code CONSTANT_*ref_info}.
  */
 public abstract class CstMemberRef extends TypedConstant {
-    /** non-null; the type of the defining class */
+    /** {@code non-null;} the type of the defining class */
     private final CstType definingClass;
 
-    /** non-null; the name-and-type */
+    /** {@code non-null;} the name-and-type */
     private final CstNat nat;
 
     /**
      * Constructs an instance.
      * 
-     * @param definingClass non-null; the type of the defining class
-     * @param nat non-null; the name-and-type
+     * @param definingClass {@code non-null;} the type of the defining class
+     * @param nat {@code non-null;} the name-and-type
      */
     /*package*/ CstMemberRef(CstType definingClass, CstNat nat) {
         if (definingClass == null) {
@@ -68,7 +68,7 @@
      *
      * <p><b>Note:</b> This implementation just compares the defining
      * class and name, and it is up to subclasses to compare the rest
-     * after calling <code>super.compareTo0()</code>.</p>
+     * after calling {@code super.compareTo0()}.</p>
      */
     @Override
     protected int compareTo0(Constant other) {
@@ -105,7 +105,7 @@
     /**
      * Gets the type of the defining class.
      * 
-     * @return non-null; the type of defining class
+     * @return {@code non-null;} the type of defining class
      */
     public final CstType getDefiningClass() {
         return definingClass;
@@ -114,7 +114,7 @@
     /**
      * Gets the defining name-and-type.
      * 
-     * @return non-null; the name-and-type
+     * @return {@code non-null;} the name-and-type
      */
     public final CstNat getNat() {
         return nat;
diff --git a/dx/src/com/android/dx/rop/cst/CstMethodRef.java b/dx/src/com/android/dx/rop/cst/CstMethodRef.java
index 766c9bf..77c97e9 100644
--- a/dx/src/com/android/dx/rop/cst/CstMethodRef.java
+++ b/dx/src/com/android/dx/rop/cst/CstMethodRef.java
@@ -17,15 +17,15 @@
 package com.android.dx.rop.cst;
 
 /**
- * Constants of type <code>CONSTANT_Methodref_info</code>.
+ * Constants of type {@code CONSTANT_Methodref_info}.
  */
 public final class CstMethodRef
         extends CstBaseMethodRef {
     /**
      * Constructs an instance.
      * 
-     * @param definingClass non-null; the type of the defining class
-     * @param nat non-null; the name-and-type
+     * @param definingClass {@code non-null;} the type of the defining class
+     * @param nat {@code non-null;} the name-and-type
      */
     public CstMethodRef(CstType definingClass, CstNat nat) {
         super(definingClass, nat);
diff --git a/dx/src/com/android/dx/rop/cst/CstNat.java b/dx/src/com/android/dx/rop/cst/CstNat.java
index 106b599..5270fd2 100644
--- a/dx/src/com/android/dx/rop/cst/CstNat.java
+++ b/dx/src/com/android/dx/rop/cst/CstNat.java
@@ -19,29 +19,29 @@
 import com.android.dx.rop.type.Type;
 
 /**
- * Constants of type <code>CONSTANT_NameAndType_info</code>.
+ * Constants of type {@code CONSTANT_NameAndType_info}.
  */
 public final class CstNat extends Constant {
     /**
-     * non-null; the instance for name <code>TYPE</code> and descriptor
-     * <code>java.lang.Class</code>, which is useful when dealing with
+     * {@code non-null;} the instance for name {@code TYPE} and descriptor
+     * {@code java.lang.Class}, which is useful when dealing with
      * wrapped primitives 
      */
     public static final CstNat PRIMITIVE_TYPE_NAT =
         new CstNat(new CstUtf8("TYPE"),
                    new CstUtf8("Ljava/lang/Class;"));
 
-    /** non-null; the name */
+    /** {@code non-null;} the name */
     private final CstUtf8 name;
 
-    /** non-null; the descriptor (type) */
+    /** {@code non-null;} the descriptor (type) */
     private final CstUtf8 descriptor;
 
     /**
      * Constructs an instance.
      * 
-     * @param name non-null; the name
-     * @param descriptor non-null; the descriptor
+     * @param name {@code non-null;} the name
+     * @param descriptor {@code non-null;} the descriptor
      */
     public CstNat(CstUtf8 name, CstUtf8 descriptor) {
         if (name == null) {
@@ -108,7 +108,7 @@
     /**
      * Gets the name.
      * 
-     * @return non-null; the name
+     * @return {@code non-null;} the name
      */
     public CstUtf8 getName() {
         return name;
@@ -117,7 +117,7 @@
     /**
      * Gets the descriptor.
      * 
-     * @return non-null; the descriptor
+     * @return {@code non-null;} the descriptor
      */
     public CstUtf8 getDescriptor() {
         return descriptor;
@@ -127,7 +127,7 @@
      * Returns an unadorned but human-readable version of the name-and-type
      * value.
      * 
-     * @return non-null; the human form
+     * @return {@code non-null;} the human form
      */
     public String toHuman() {
         return name.toHuman() + ':' + descriptor.toHuman();
@@ -138,7 +138,7 @@
      * This method is only valid to call if the descriptor in fact describes
      * a field (and not a method).
      * 
-     * @return non-null; the field type
+     * @return {@code non-null;} the field type
      */
     public Type getFieldType() {
         return Type.intern(descriptor.getString());
@@ -147,9 +147,9 @@
     /**
      * Gets whether this instance has the name of a standard instance
      * initialization method. This is just a convenient shorthand for
-     * <code>getName().getString().equals("&lt;init&gt;")</code>.
+     * {@code getName().getString().equals("<init>")}.
      * 
-     * @return <code>true</code> iff this is a reference to an
+     * @return {@code true} iff this is a reference to an
      * instance initialization method
      */
     public final boolean isInstanceInit() {
@@ -159,9 +159,9 @@
     /**
      * Gets whether this instance has the name of a standard class
      * initialization method. This is just a convenient shorthand for
-     * <code>getName().getString().equals("&lt;clinit&gt;")</code>.
+     * {@code getName().getString().equals("<clinit>")}.
      * 
-     * @return <code>true</code> iff this is a reference to an
+     * @return {@code true} iff this is a reference to an
      * instance initialization method
      */
     public final boolean isClassInit() {
diff --git a/dx/src/com/android/dx/rop/cst/CstShort.java b/dx/src/com/android/dx/rop/cst/CstShort.java
index 3804254..4ac2f68 100644
--- a/dx/src/com/android/dx/rop/cst/CstShort.java
+++ b/dx/src/com/android/dx/rop/cst/CstShort.java
@@ -20,31 +20,31 @@
 import com.android.dx.util.Hex;
 
 /**
- * Constants of type <code>short</code>.
+ * Constants of type {@code short}.
  */
 public final class CstShort
         extends CstLiteral32 {
-    /** non-null; the value <code>0</code> as an instance of this class */
+    /** {@code non-null;} the value {@code 0} as an instance of this class */
     public static final CstShort VALUE_0 = make((short) 0);
 
     /**
      * Makes an instance for the given value. This may (but does not
      * necessarily) return an already-allocated instance.
      * 
-     * @param value the <code>short</code> value
-     * @return non-null; the appropriate instance
+     * @param value the {@code short} value
+     * @return {@code non-null;} the appropriate instance
      */
     public static CstShort make(short value) {
         return new CstShort(value);
     }
 
     /**
-     * Makes an instance for the given <code>int</code> value. This
+     * Makes an instance for the given {@code int} value. This
      * may (but does not necessarily) return an already-allocated
      * instance.
      * 
-     * @param value the value, which must be in range for a <code>short</code>
-     * @return non-null; the appropriate instance
+     * @param value the value, which must be in range for a {@code short}
+     * @return {@code non-null;} the appropriate instance
      */
     public static CstShort make(int value) {
         short cast = (short) value;
@@ -60,7 +60,7 @@
     /**
      * Constructs an instance. This constructor is private; use {@link #make}.
      * 
-     * @param value the <code>short</code> value
+     * @param value the {@code short} value
      */
     private CstShort(short value) {
         super(value);
@@ -90,7 +90,7 @@
     }
 
     /**
-     * Gets the <code>short</code> value.
+     * Gets the {@code short} value.
      * 
      * @return the value
      */
diff --git a/dx/src/com/android/dx/rop/cst/CstString.java b/dx/src/com/android/dx/rop/cst/CstString.java
index 89a4c8b..ce00f52 100644
--- a/dx/src/com/android/dx/rop/cst/CstString.java
+++ b/dx/src/com/android/dx/rop/cst/CstString.java
@@ -19,17 +19,17 @@
 import com.android.dx.rop.type.Type;
 
 /**
- * Constants of type <code>CONSTANT_String_info</code>.
+ * Constants of type {@code CONSTANT_String_info}.
  */
 public final class CstString
         extends TypedConstant {
-    /** non-null; the string value */
+    /** {@code non-null;} the string value */
     private final CstUtf8 string;
 
     /**
      * Constructs an instance.
      * 
-     * @param string non-null; the string value
+     * @param string {@code non-null;} the string value
      */
     public CstString(CstUtf8 string) {
         if (string == null) {
@@ -42,7 +42,7 @@
     /**
      * Constructs an instance.
      * 
-     * @param string non-null; the string value
+     * @param string {@code non-null;} the string value
      */
     public CstString(String string) {
         this(new CstUtf8(string));
@@ -101,7 +101,7 @@
     /**
      * Gets the string value.
      * 
-     * @return non-null; the string value
+     * @return {@code non-null;} the string value
      */
     public CstUtf8 getString() {
         return string;
diff --git a/dx/src/com/android/dx/rop/cst/CstType.java b/dx/src/com/android/dx/rop/cst/CstType.java
index 02df28d..6dc9867 100644
--- a/dx/src/com/android/dx/rop/cst/CstType.java
+++ b/dx/src/com/android/dx/rop/cst/CstType.java
@@ -24,69 +24,69 @@
  * Constants that represent an arbitrary type (reference or primitive).
  */
 public final class CstType extends TypedConstant {
-    /** non-null; map of interned types */
+    /** {@code non-null;} map of interned types */
     private static final HashMap<Type, CstType> interns =
         new HashMap<Type, CstType>(100);
 
-    /** non-null; instance corresponding to the class <code>Object</code> */
+    /** {@code non-null;} instance corresponding to the class {@code Object} */
     public static final CstType OBJECT = intern(Type.OBJECT);
 
-    /** non-null; instance corresponding to the class <code>Boolean</code> */
+    /** {@code non-null;} instance corresponding to the class {@code Boolean} */
     public static final CstType BOOLEAN = intern(Type.BOOLEAN_CLASS);
 
-    /** non-null; instance corresponding to the class <code>Byte</code> */
+    /** {@code non-null;} instance corresponding to the class {@code Byte} */
     public static final CstType BYTE = intern(Type.BYTE_CLASS);
 
-    /** non-null; instance corresponding to the class <code>Character</code> */
+    /** {@code non-null;} instance corresponding to the class {@code Character} */
     public static final CstType CHARACTER = intern(Type.CHARACTER_CLASS);
 
-    /** non-null; instance corresponding to the class <code>Double</code> */
+    /** {@code non-null;} instance corresponding to the class {@code Double} */
     public static final CstType DOUBLE = intern(Type.DOUBLE_CLASS);
 
-    /** non-null; instance corresponding to the class <code>Float</code> */
+    /** {@code non-null;} instance corresponding to the class {@code Float} */
     public static final CstType FLOAT = intern(Type.FLOAT_CLASS);
 
-    /** non-null; instance corresponding to the class <code>Long</code> */
+    /** {@code non-null;} instance corresponding to the class {@code Long} */
     public static final CstType LONG = intern(Type.LONG_CLASS);
 
-    /** non-null; instance corresponding to the class <code>Integer</code> */
+    /** {@code non-null;} instance corresponding to the class {@code Integer} */
     public static final CstType INTEGER = intern(Type.INTEGER_CLASS);
 
-    /** non-null; instance corresponding to the class <code>Short</code> */
+    /** {@code non-null;} instance corresponding to the class {@code Short} */
     public static final CstType SHORT = intern(Type.SHORT_CLASS);
 
-    /** non-null; instance corresponding to the class <code>Void</code> */
+    /** {@code non-null;} instance corresponding to the class {@code Void} */
     public static final CstType VOID = intern(Type.VOID_CLASS);
 
-    /** non-null; instance corresponding to the type <code>boolean[]</code> */
+    /** {@code non-null;} instance corresponding to the type {@code boolean[]} */
     public static final CstType BOOLEAN_ARRAY = intern(Type.BOOLEAN_ARRAY);
 
-    /** non-null; instance corresponding to the type <code>byte[]</code> */
+    /** {@code non-null;} instance corresponding to the type {@code byte[]} */
     public static final CstType BYTE_ARRAY = intern(Type.BYTE_ARRAY);
 
-    /** non-null; instance corresponding to the type <code>char[]</code> */
+    /** {@code non-null;} instance corresponding to the type {@code char[]} */
     public static final CstType CHAR_ARRAY = intern(Type.CHAR_ARRAY);
 
-    /** non-null; instance corresponding to the type <code>double[]</code> */
+    /** {@code non-null;} instance corresponding to the type {@code double[]} */
     public static final CstType DOUBLE_ARRAY = intern(Type.DOUBLE_ARRAY);
 
-    /** non-null; instance corresponding to the type <code>float[]</code> */
+    /** {@code non-null;} instance corresponding to the type {@code float[]} */
     public static final CstType FLOAT_ARRAY = intern(Type.FLOAT_ARRAY);
 
-    /** non-null; instance corresponding to the type <code>long[]</code> */
+    /** {@code non-null;} instance corresponding to the type {@code long[]} */
     public static final CstType LONG_ARRAY = intern(Type.LONG_ARRAY);
 
-    /** non-null; instance corresponding to the type <code>int[]</code> */
+    /** {@code non-null;} instance corresponding to the type {@code int[]} */
     public static final CstType INT_ARRAY = intern(Type.INT_ARRAY);
 
-    /** non-null; instance corresponding to the type <code>short[]</code> */
+    /** {@code non-null;} instance corresponding to the type {@code short[]} */
     public static final CstType SHORT_ARRAY = intern(Type.SHORT_ARRAY);
 
-    /** non-null; the underlying type */
+    /** {@code non-null;} the underlying type */
     private final Type type;
 
     /**
-     * null-ok; the type descriptor corresponding to this instance, if
+     * {@code null-ok;} the type descriptor corresponding to this instance, if
      * calculated
      */
     private CstUtf8 descriptor;
@@ -95,10 +95,10 @@
      * Returns an instance of this class that represents the wrapper
      * class corresponding to a given primitive type. For example, if
      * given {@link Type#INT}, this method returns the class reference
-     * <code>java.lang.Integer</code>.
+     * {@code java.lang.Integer}.
      * 
-     * @param primitiveType non-null; the primitive type
-     * @return non-null; the corresponding wrapper class
+     * @param primitiveType {@code non-null;} the primitive type
+     * @return {@code non-null;} the corresponding wrapper class
      */
     public static CstType forBoxedPrimitiveType(Type primitiveType) {
         switch (primitiveType.getBasicType()) {
@@ -119,8 +119,8 @@
     /**
      * Returns an interned instance of this class for the given type.
      * 
-     * @param type non-null; the underlying type
-     * @return non-null; an appropriately-constructed instance
+     * @param type {@code non-null;} the underlying type
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public static CstType intern(Type type) {
         CstType cst = interns.get(type);
@@ -136,7 +136,7 @@
     /**
      * Constructs an instance.
      * 
-     * @param type non-null; the underlying type
+     * @param type {@code non-null;} the underlying type
      */
     public CstType(Type type) {
         if (type == null) {
@@ -207,9 +207,9 @@
     /**
      * Gets the underlying type (as opposed to the type corresponding
      * to this instance as a constant, which is always
-     * <code>Class</code>).
+     * {@code Class}).
      * 
-     * @return non-null; the type corresponding to the name
+     * @return {@code non-null;} the type corresponding to the name
      */
     public Type getClassType() {
         return type;
@@ -218,7 +218,7 @@
     /**
      * Gets the type descriptor for this instance.
      * 
-     * @return non-null; the descriptor
+     * @return {@code non-null;} the descriptor
      */
     public CstUtf8 getDescriptor() {
         if (descriptor == null) {
diff --git a/dx/src/com/android/dx/rop/cst/CstUtf8.java b/dx/src/com/android/dx/rop/cst/CstUtf8.java
index f0ca5f5..2c7a1df 100644
--- a/dx/src/com/android/dx/rop/cst/CstUtf8.java
+++ b/dx/src/com/android/dx/rop/cst/CstUtf8.java
@@ -20,19 +20,19 @@
 import com.android.dx.util.Hex;
 
 /**
- * Constants of type <code>CONSTANT_Utf8_info</code>.
+ * Constants of type {@code CONSTANT_Utf8_info}.
  */
 public final class CstUtf8 extends Constant {
     /** 
-     * non-null; instance representing <code>""</code>, that is, the
+     * {@code non-null;} instance representing {@code ""}, that is, the
      * empty string 
      */
     public static final CstUtf8 EMPTY_STRING = new CstUtf8("");
     
-    /** non-null; the UTF-8 value as a string */
+    /** {@code non-null;} the UTF-8 value as a string */
     private final String string;
 
-    /** non-null; the UTF-8 value as bytes */
+    /** {@code non-null;} the UTF-8 value as bytes */
     private final ByteArray bytes;
 
     /**
@@ -40,8 +40,8 @@
      * differs from normal UTF-8 in the handling of character '\0' and
      * surrogate pairs.
      * 
-     * @param string non-null; the string to convert
-     * @return non-null; the UTF-8 bytes for it
+     * @param string {@code non-null;} the string to convert
+     * @return {@code non-null;} the UTF-8 bytes for it
      */
     public static byte[] stringToUtf8Bytes(String string) {
         int len = string.length();
@@ -73,8 +73,8 @@
     /**
      * Converts an array of UTF-8 bytes into a string.
      * 
-     * @param bytes non-null; the bytes to convert
-     * @return non-null; the converted string
+     * @param bytes {@code non-null;} the bytes to convert
+     * @return {@code non-null;} the converted string
      */
     public static String utf8BytesToString(ByteArray bytes) {
         int length = bytes.size();
@@ -173,9 +173,9 @@
     }
 
     /**
-     * Constructs an instance from a <code>String</code>.
+     * Constructs an instance from a {@code String}.
      * 
-     * @param string non-null; the UTF-8 value as a string
+     * @param string {@code non-null;} the UTF-8 value as a string
      */
     public CstUtf8(String string) {
         if (string == null) {
@@ -189,7 +189,7 @@
     /**
      * Constructs an instance from some UTF-8 bytes.
      * 
-     * @param bytes non-null; array of the UTF-8 bytes
+     * @param bytes {@code non-null;} array of the UTF-8 bytes
      */
     public CstUtf8(ByteArray bytes) {
         if (bytes == null) {
@@ -299,7 +299,7 @@
      * Gets the value as a human-oriented string, surrounded by double
      * quotes.
      * 
-     * @return non-null; the quoted string
+     * @return {@code non-null;} the quoted string
      */
     public String toQuoted() {
         return '\"' + toHuman() + '\"';
@@ -310,8 +310,8 @@
      * quotes, but ellipsizes the result if it is longer than the given
      * maximum length
      * 
-     * @param maxLength &gt;= 5; the maximum length of the string to return
-     * @return non-null; the quoted string
+     * @param maxLength {@code >= 5;} the maximum length of the string to return
+     * @return {@code non-null;} the quoted string
      */
     public String toQuoted(int maxLength) {
         String string = toHuman();
@@ -332,7 +332,7 @@
      * Gets the UTF-8 value as a string.
      * The returned string is always already interned.
      * 
-     * @return non-null; the UTF-8 value as a string
+     * @return {@code non-null;} the UTF-8 value as a string
      */
     public String getString() {
         return string;
@@ -341,7 +341,7 @@
     /**
      * Gets the UTF-8 value as UTF-8 encoded bytes.
      * 
-     * @return non-null; an array of the UTF-8 bytes
+     * @return {@code non-null;} an array of the UTF-8 bytes
      */
     public ByteArray getBytes() {
         return bytes;
@@ -351,7 +351,7 @@
      * Gets the size of this instance as UTF-8 code points. That is,
      * get the number of bytes in the UTF-8 encoding of this instance.
      * 
-     * @return &gt;= 0; the UTF-8 size
+     * @return {@code >= 0;} the UTF-8 size
      */
     public int getUtf8Size() {
         return bytes.size();
@@ -360,10 +360,10 @@
     /**
      * Gets the size of this instance as UTF-16 code points. That is,
      * get the number of 16-bit chars in the UTF-16 encoding of this
-     * instance. This is the same as the <code>length</code> of the
-     * Java <code>String</code> representation of this instance.
+     * instance. This is the same as the {@code length} of the
+     * Java {@code String} representation of this instance.
      * 
-     * @return &gt;= 0; the UTF-16 size
+     * @return {@code >= 0;} the UTF-16 size
      */
     public int getUtf16Size() {
         return string.length();
diff --git a/dx/src/com/android/dx/rop/cst/StdConstantPool.java b/dx/src/com/android/dx/rop/cst/StdConstantPool.java
index 6979102..82c3ab7 100644
--- a/dx/src/com/android/dx/rop/cst/StdConstantPool.java
+++ b/dx/src/com/android/dx/rop/cst/StdConstantPool.java
@@ -26,16 +26,16 @@
  */
 public final class StdConstantPool
         extends MutabilityControl implements ConstantPool {
-    /** non-null; array of entries */
+    /** {@code non-null;} array of entries */
     private final Constant[] entries;
 
     /**
-     * Constructs an instance. All indices initially contain <code>null</code>.
+     * Constructs an instance. All indices initially contain {@code null}.
      * 
      * @param size the size of the pool; this corresponds to the
-     * class file field <code>constant_pool_count</code>, and is in fact
+     * class file field {@code constant_pool_count}, and is in fact
      * always at least one more than the actual size of the constant pool,
-     * as element <code>0</code> is always invalid.
+     * as element {@code 0} is always invalid.
      */
     public StdConstantPool(int size) {
         super(size > 1);
@@ -90,8 +90,8 @@
     /**
      * Sets the entry at the given index.
      * 
-     * @param n &gt;= 1, &lt; size(); which entry
-     * @param cst null-ok; the constant to store
+     * @param n {@code >= 1, < size();} which entry
+     * @param cst {@code null-ok;} the constant to store
      */
     public void set(int n, Constant cst) {
         throwIfImmutable();
diff --git a/dx/src/com/android/dx/rop/cst/TypedConstant.java b/dx/src/com/android/dx/rop/cst/TypedConstant.java
index 54472b0..823d9c4 100644
--- a/dx/src/com/android/dx/rop/cst/TypedConstant.java
+++ b/dx/src/com/android/dx/rop/cst/TypedConstant.java
@@ -26,7 +26,7 @@
     /**
      * {@inheritDoc}
      * 
-     * This implentation always returns <code>this</code>.
+     * This implentation always returns {@code this}.
      */
     public final TypeBearer getFrameType() {
         return this;
diff --git a/dx/src/com/android/dx/rop/cst/Zeroes.java b/dx/src/com/android/dx/rop/cst/Zeroes.java
index 3379b6c..8bed657 100644
--- a/dx/src/com/android/dx/rop/cst/Zeroes.java
+++ b/dx/src/com/android/dx/rop/cst/Zeroes.java
@@ -30,10 +30,10 @@
     }
      
     /**
-     * Gets the "zero" (or <code>null</code>) value for the given type.
+     * Gets the "zero" (or {@code null}) value for the given type.
      * 
-     * @param type non-null; the type in question
-     * @return non-null; its "zero" value
+     * @param type {@code non-null;} the type in question
+     * @return {@code non-null;} its "zero" value
      */
     public static Constant zeroFor(Type type) {
         switch (type.getBasicType()) {
diff --git a/dx/src/com/android/dx/rop/package-info.java b/dx/src/com/android/dx/rop/package-info.java
index 97fe9de..aaf21ee 100644
--- a/dx/src/com/android/dx/rop/package-info.java
+++ b/dx/src/com/android/dx/rop/package-info.java
@@ -19,7 +19,7 @@
 /**
  * <h1>An Introduction to Rop Form</h1>
  *
- * This package contains classes associated with dx's <code>Rop</code>
+ * This package contains classes associated with dx's {@code Rop}
  * intermediate form.<p>
  *
  * The Rop form is intended to represent the instructions and the control-flow
@@ -33,16 +33,16 @@
  * <li> {@link BasicBlock} and its per-method container, {@link BasicBlockList},
  * the representation of control flow elements.
  * <li> {@link Insn} and its subclasses along with its per-basic block
- * container {@link InsnList}. <code>Insn</code> instances represent
+ * container {@link InsnList}. {@code Insn} instances represent
  * individual instructions in the abstract register machine.
  * <li> {@link RegisterSpec} and its container {@link RegisterSpecList}. A
  * register spec encodes register number, register width, type information,
  * and potentially local variable information as well for instruction sources
  * and results.
  * <li> {@link Rop} instances represent opcodes in the abstract machine. Many
- * <code>Rop</code> instances are singletons defined in static fields in
+ * {@code Rop} instances are singletons defined in static fields in
  * {@link Rops}. The rest are constructed dynamically using static methods
- * in <code>Rops</code>
+ * in {@code Rops}
  * <li> {@link RegOps} lists numeric constants for the opcodes
  * <li> {@link Constant} and its subclasses represent constant data values
  * that opcodes may refer to.
@@ -62,8 +62,8 @@
  * bytecode. Blocks that don't originate directly from source bytecode have
  * labels generated for them in a mostly arbitrary order.<p>
  *
- * Blocks are referred to by their label, for the most part, because <code>
- * BasicBlock</code> instances are immutable and thus any modification to
+ * Blocks are referred to by their label, for the most part, because
+ * {@code BasicBlock} instances are immutable and thus any modification to
  * the control flow graph or the instruction list results in replacement
  * instances (with identical labels) being created.<p>
  *
@@ -105,7 +105,7 @@
  * instruction where a catch block exists inside the current method for that
  * exception class. Since the only possible path is the exception path, only
  * the exception path (which cannot be a primary successor) is a successor.
- * An example of this is shown in <code>dx/tests/092-ssa-cfg-edge-cases</code>.
+ * An example of this is shown in {@code dx/tests/092-ssa-cfg-edge-cases}.
  *
  * <h2>Rop Instructions</h2>
  *
@@ -123,18 +123,18 @@
  * Rops#MOVE_RESULT move-result} or {@link Rops#MOVE_RESULT_PSEUDO
  * move-result-pseudo} instructions at the top of the primary successor block.
  *
- * Only a single <code>move-result</code> or <code>move-result-pseudo</code>
+ * Only a single {@code move-result} or {@code move-result-pseudo}
  * may exist in any block and it must be exactly the first instruction in the
  * block.
  *
- * A <code>move-result</code> instruction is used for the results of call-like
- * instructions. If the value produced by a <code>move-result</code> is not
+ * A {@code move-result} instruction is used for the results of call-like
+ * instructions. If the value produced by a {@code move-result} is not
  * used by the method, it may be eliminated as dead code.
  *
- * A <code>move-result-pseudo</code> instruction is used for the results of
+ * A {@code move-result-pseudo} instruction is used for the results of
  * non-call-like throwing instructions. It may never be considered dead code
  * since the final dex instruction will always indicate a result register.
- * If a required <code>move-result-pseudo</code> instruction is not found
+ * If a required {@code move-result-pseudo} instruction is not found
  * during conversion to dex bytecode, an exception will be thrown.
  *
  * <h3>move-exception</h3>
@@ -148,25 +148,25 @@
  * <h3>move-param</h3>
  *
  * A {@link RegOps.MOVE_PARAM move-param} instruction represents a method
- * parameter. Every <code>move-param</code> instruction is a
+ * parameter. Every {@code move-param} instruction is a
  * {@link PlainCstInsn}. The index of the method parameter they refer to is
  * carried as the {@link CstInteger integer constant} associated with the
  * instruction.
  *
- * Any number of <code>move-param</code> instructions referring to the same
+ * Any number of {@code move-param} instructions referring to the same
  * parameter index may be included in a method's instruction lists. They
  * have no restrictions on placement beyond those of any other
  * {@link Rop.BRANCH_NONE} instruction. Note that the SSA optimizer arranges the
  * parameter assignments to align with the dex bytecode calling conventions.
  * With parameter assignments so arranged, the
- * {@link com.android.dx.dex.code.RopTranslator} sees Rop <code>move-param</code>
+ * {@link com.android.dx.dex.code.RopTranslator} sees Rop {@code move-param}
  * instructions as unnecessary in dex form and eliminates them.
  *
  * <h3>mark-local</h3>
  *
  * A {@link RegOps.MARK_LOCAL mark-local} instruction indicates that a local
  * variable becomes live in a specified register specified register for the
- * purposes of debug information. A <code>mark-local</code> instruction has
+ * purposes of debug information. A {@code mark-local} instruction has
  * a single source (the register which will now be considered a local variable)
  * and no results. The instruction has no side effect.<p>
  *
@@ -179,23 +179,22 @@
  * an assignment occurring. A common example of this is occurs in the Rop
  * representation of the following code:<p>
  *
- * <code>
+ * <pre>
  * try {
  *     Object foo = null;
  *     foo = new Object();
- * } catch (Throwable ex) {
- * }
- * </code>
+ * } catch (Throwable ex) { }
+ * </pre>
  *
- * An object's initialization occurs in two steps. First, a <code>new-instance
- * </code> instruction is executed, whose result is stored in a register.
- * However, that register can not yet be considered to contain "foo". That's
- * because the instance's constructor method must be called via an
- * <code>invoke</code> instruction. The constructor method, however, may
+ * An object's initialization occurs in two steps. First, a
+ * {@code new-instance} instruction is executed, whose result is stored in a
+ * register. However, that register can not yet be considered to contain
+ * "foo". That's because the instance's constructor method must be called
+ * via an {@code invoke} instruction. The constructor method, however, may
  * throw an exception. And if an exception occurs, then "foo" should remain
- * null. So "foo" becomes the value of the result of the <code>new-instance
- * </code> instruction after the (void) constructor method is invoked and
- * returns successfully. In such a case, a <code>mark-local</code> will
+ * null. So "foo" becomes the value of the result of the {@code new-instance}
+ * instruction after the (void) constructor method is invoked and
+ * returns successfully. In such a case, a {@code mark-local} will
  * typically occur at the beginning of the primary successor block following
  * the invocation to the constructor.
  */
diff --git a/dx/src/com/android/dx/rop/type/Prototype.java b/dx/src/com/android/dx/rop/type/Prototype.java
index a6ee742..7e6ab59 100644
--- a/dx/src/com/android/dx/rop/type/Prototype.java
+++ b/dx/src/com/android/dx/rop/type/Prototype.java
@@ -21,23 +21,23 @@
 /**
  * Representation of a method decriptor. Instances of this class are
  * generally interned and may be usefully compared with each other
- * using <code>==</code>.
+ * using {@code ==}.
  */
 public final class Prototype implements Comparable<Prototype> {
-    /** non-null; intern table mapping string descriptors to instances */
+    /** {@code non-null;} intern table mapping string descriptors to instances */
     private static final HashMap<String, Prototype> internTable =
         new HashMap<String, Prototype>(500);
 
-    /** non-null; method descriptor */
+    /** {@code non-null;} method descriptor */
     private final String descriptor;
 
-    /** non-null; return type */
+    /** {@code non-null;} return type */
     private final Type returnType;
 
-    /** non-null; list of parameter types */
+    /** {@code non-null;} list of parameter types */
     private final StdTypeList parameterTypes;
 
-    /** null-ok; list of parameter frame types, if calculated */
+    /** {@code null-ok;} list of parameter frame types, if calculated */
     private StdTypeList parameterFrameTypes;
 
     /**
@@ -45,8 +45,8 @@
      * given method descriptor. See vmspec-2 sec4.3.3 for details on the
      * field descriptor syntax.
      * 
-     * @param descriptor non-null; the descriptor
-     * @return non-null; the corresponding instance
+     * @param descriptor {@code non-null;} the descriptor
+     * @return {@code non-null;} the corresponding instance
      * @throws IllegalArgumentException thrown if the descriptor has
      * invalid syntax
      */
@@ -111,8 +111,8 @@
      * that there is a '(' at the start of the descriptor and a
      * single ')' somewhere before the end.
      * 
-     * @param descriptor non-null; the descriptor string
-     * @return non-null; array large enough to hold all parsed parameter
+     * @param descriptor {@code non-null;} the descriptor string
+     * @return {@code non-null;} array large enough to hold all parsed parameter
      * types, but which is likely actually larger than needed
      */
     private static Type[] makeParameterArray(String descriptor) {
@@ -153,14 +153,14 @@
     /**
      * Interns an instance, adding to the descriptor as necessary based
      * on the given definer, name, and flags. For example, an init
-     * method has an uninitialized object of type <code>definer</code>
+     * method has an uninitialized object of type {@code definer}
      * as its first argument.
      * 
-     * @param descriptor non-null; the descriptor string
-     * @param definer non-null; class the method is defined on
+     * @param descriptor {@code non-null;} the descriptor string
+     * @param definer {@code non-null;} class the method is defined on
      * @param isStatic whether this is a static method
      * @param isInit whether this is an init method
-     * @return non-null; the interned instance
+     * @return {@code non-null;} the interned instance
      */
     public static Prototype intern(String descriptor, Type definer,
             boolean isStatic, boolean isInit) {
@@ -179,11 +179,11 @@
 
     /**
      * Interns an instance which consists of the given number of
-     * <code>int</code>s along with the given return type
+     * {@code int}s along with the given return type
      * 
-     * @param returnType non-null; the return type
-     * @param count &gt; 0; the number of elements in the prototype
-     * @return non-null; the interned instance
+     * @param returnType {@code non-null;} the return type
+     * @param count {@code > 0;} the number of elements in the prototype
+     * @return {@code non-null;} the interned instance
      */
     public static Prototype internInts(Type returnType, int count) {
         // Make the descriptor...
@@ -207,7 +207,7 @@
      * Constructs an instance. This is a private constructor; use one
      * of the public static methods to get instances.
      * 
-     * @param descriptor non-null; the descriptor string
+     * @param descriptor {@code non-null;} the descriptor string
      */
     private Prototype(String descriptor, Type returnType,
             StdTypeList parameterTypes) {
@@ -304,7 +304,7 @@
     /**
      * Gets the descriptor string.
      * 
-     * @return non-null; the descriptor
+     * @return {@code non-null;} the descriptor
      */
     public String getDescriptor() {
         return descriptor;
@@ -313,7 +313,7 @@
     /**
      * Gets the return type.
      * 
-     * @return non-null; the return type
+     * @return {@code non-null;} the return type
      */
     public Type getReturnType() {
         return returnType;
@@ -322,7 +322,7 @@
     /**
      * Gets the list of parameter types.
      * 
-     * @return non-null; the list of parameter types
+     * @return {@code non-null;} the list of parameter types
      */
     public StdTypeList getParameterTypes() {
         return parameterTypes;
@@ -334,7 +334,7 @@
      * "intlike" types (see {@link Type#isIntlike}) are replaced by
      * {@link Type#INT}.
      * 
-     * @return non-null; the list of parameter frame types
+     * @return {@code non-null;} the list of parameter frame types
      */
     public StdTypeList getParameterFrameTypes() {
         if (parameterFrameTypes == null) {
@@ -360,8 +360,8 @@
      * except that it has an additional parameter prepended to the original's
      * argument list.
      * 
-     * @param param non-null; the new first parameter
-     * @return non-null; an appropriately-constructed instance
+     * @param param {@code non-null;} the new first parameter
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public Prototype withFirstParameter(Type param) {
         String newDesc = "(" + param.getDescriptor() + descriptor.substring(1);
@@ -380,8 +380,8 @@
      * there. If a conflicting value is already in the table, then leave it.
      * Return the interned value.
      * 
-     * @param desc non-null; instance to make interned
-     * @return non-null; the actual interned object
+     * @param desc {@code non-null;} instance to make interned
+     * @return {@code non-null;} the actual interned object
      */
     private static Prototype putIntern(Prototype desc) {
         synchronized (internTable) {
diff --git a/dx/src/com/android/dx/rop/type/StdTypeList.java b/dx/src/com/android/dx/rop/type/StdTypeList.java
index a4c2d44..a023812 100644
--- a/dx/src/com/android/dx/rop/type/StdTypeList.java
+++ b/dx/src/com/android/dx/rop/type/StdTypeList.java
@@ -23,149 +23,149 @@
  */
 public final class StdTypeList
         extends FixedSizeList implements TypeList {
-    /** non-null; no-element instance */
+    /** {@code non-null;} no-element instance */
     public static final StdTypeList EMPTY = new StdTypeList(0);
 
-    /** non-null; the list <code>[int]</code> */
+    /** {@code non-null;} the list {@code [int]} */
     public static final StdTypeList INT = StdTypeList.make(Type.INT);
 
-    /** non-null; the list <code>[long]</code> */
+    /** {@code non-null;} the list {@code [long]} */
     public static final StdTypeList LONG = StdTypeList.make(Type.LONG);
 
-    /** non-null; the list <code>[float]</code> */
+    /** {@code non-null;} the list {@code [float]} */
     public static final StdTypeList FLOAT = StdTypeList.make(Type.FLOAT);
 
-    /** non-null; the list <code>[double]</code> */
+    /** {@code non-null;} the list {@code [double]} */
     public static final StdTypeList DOUBLE = StdTypeList.make(Type.DOUBLE);
 
-    /** non-null; the list <code>[Object]</code> */
+    /** {@code non-null;} the list {@code [Object]} */
     public static final StdTypeList OBJECT = StdTypeList.make(Type.OBJECT);
 
-    /** non-null; the list <code>[ReturnAddress]</code> */
+    /** {@code non-null;} the list {@code [ReturnAddress]} */
     public static final StdTypeList RETURN_ADDRESS
             = StdTypeList.make(Type.RETURN_ADDRESS);
 
-    /** non-null; the list <code>[Throwable]</code> */
+    /** {@code non-null;} the list {@code [Throwable]} */
     public static final StdTypeList THROWABLE =
         StdTypeList.make(Type.THROWABLE);
 
-    /** non-null; the list <code>[int, int]</code> */
+    /** {@code non-null;} the list {@code [int, int]} */
     public static final StdTypeList INT_INT =
         StdTypeList.make(Type.INT, Type.INT);
 
-    /** non-null; the list <code>[long, long]</code> */
+    /** {@code non-null;} the list {@code [long, long]} */
     public static final StdTypeList LONG_LONG =
         StdTypeList.make(Type.LONG, Type.LONG);
 
-    /** non-null; the list <code>[float, float]</code> */
+    /** {@code non-null;} the list {@code [float, float]} */
     public static final StdTypeList FLOAT_FLOAT =
         StdTypeList.make(Type.FLOAT, Type.FLOAT);
 
-    /** non-null; the list <code>[double, double]</code> */
+    /** {@code non-null;} the list {@code [double, double]} */
     public static final StdTypeList DOUBLE_DOUBLE =
         StdTypeList.make(Type.DOUBLE, Type.DOUBLE);
 
-    /** non-null; the list <code>[Object, Object]</code> */
+    /** {@code non-null;} the list {@code [Object, Object]} */
     public static final StdTypeList OBJECT_OBJECT =
         StdTypeList.make(Type.OBJECT, Type.OBJECT);
 
-    /** non-null; the list <code>[int, Object]</code> */
+    /** {@code non-null;} the list {@code [int, Object]} */
     public static final StdTypeList INT_OBJECT =
         StdTypeList.make(Type.INT, Type.OBJECT);
 
-    /** non-null; the list <code>[long, Object]</code> */
+    /** {@code non-null;} the list {@code [long, Object]} */
     public static final StdTypeList LONG_OBJECT =
         StdTypeList.make(Type.LONG, Type.OBJECT);
 
-    /** non-null; the list <code>[float, Object]</code> */
+    /** {@code non-null;} the list {@code [float, Object]} */
     public static final StdTypeList FLOAT_OBJECT =
         StdTypeList.make(Type.FLOAT, Type.OBJECT);
 
-    /** non-null; the list <code>[double, Object]</code> */
+    /** {@code non-null;} the list {@code [double, Object]} */
     public static final StdTypeList DOUBLE_OBJECT =
         StdTypeList.make(Type.DOUBLE, Type.OBJECT);
 
-    /** non-null; the list <code>[long, int]</code> */
+    /** {@code non-null;} the list {@code [long, int]} */
     public static final StdTypeList LONG_INT =
         StdTypeList.make(Type.LONG, Type.INT);
 
-    /** non-null; the list <code>[int[], int]</code> */
+    /** {@code non-null;} the list {@code [int[], int]} */
     public static final StdTypeList INTARR_INT =
         StdTypeList.make(Type.INT_ARRAY, Type.INT);
 
-    /** non-null; the list <code>[long[], int]</code> */
+    /** {@code non-null;} the list {@code [long[], int]} */
     public static final StdTypeList LONGARR_INT =
         StdTypeList.make(Type.LONG_ARRAY, Type.INT);
 
-    /** non-null; the list <code>[float[], int]</code> */
+    /** {@code non-null;} the list {@code [float[], int]} */
     public static final StdTypeList FLOATARR_INT =
         StdTypeList.make(Type.FLOAT_ARRAY, Type.INT);
 
-    /** non-null; the list <code>[double[], int]</code> */
+    /** {@code non-null;} the list {@code [double[], int]} */
     public static final StdTypeList DOUBLEARR_INT =
         StdTypeList.make(Type.DOUBLE_ARRAY, Type.INT);
 
-    /** non-null; the list <code>[Object[], int]</code> */
+    /** {@code non-null;} the list {@code [Object[], int]} */
     public static final StdTypeList OBJECTARR_INT =
         StdTypeList.make(Type.OBJECT_ARRAY, Type.INT);
 
-    /** non-null; the list <code>[boolean[], int]</code> */
+    /** {@code non-null;} the list {@code [boolean[], int]} */
     public static final StdTypeList BOOLEANARR_INT =
         StdTypeList.make(Type.BOOLEAN_ARRAY, Type.INT);
 
-    /** non-null; the list <code>[byte[], int]</code> */
+    /** {@code non-null;} the list {@code [byte[], int]} */
     public static final StdTypeList BYTEARR_INT =
         StdTypeList.make(Type.BYTE_ARRAY, Type.INT);
 
-    /** non-null; the list <code>[char[], int]</code> */
+    /** {@code non-null;} the list {@code [char[], int]} */
     public static final StdTypeList CHARARR_INT =
         StdTypeList.make(Type.CHAR_ARRAY, Type.INT);
 
-    /** non-null; the list <code>[short[], int]</code> */
+    /** {@code non-null;} the list {@code [short[], int]} */
     public static final StdTypeList SHORTARR_INT =
         StdTypeList.make(Type.SHORT_ARRAY, Type.INT);
 
-    /** non-null; the list <code>[int, int[], int]</code> */
+    /** {@code non-null;} the list {@code [int, int[], int]} */
     public static final StdTypeList INT_INTARR_INT =
         StdTypeList.make(Type.INT, Type.INT_ARRAY, Type.INT);
 
-    /** non-null; the list <code>[long, long[], int]</code> */
+    /** {@code non-null;} the list {@code [long, long[], int]} */
     public static final StdTypeList LONG_LONGARR_INT =
         StdTypeList.make(Type.LONG, Type.LONG_ARRAY, Type.INT);
 
-    /** non-null; the list <code>[float, float[], int]</code> */
+    /** {@code non-null;} the list {@code [float, float[], int]} */
     public static final StdTypeList FLOAT_FLOATARR_INT =
         StdTypeList.make(Type.FLOAT, Type.FLOAT_ARRAY, Type.INT);
 
-    /** non-null; the list <code>[double, double[], int]</code> */
+    /** {@code non-null;} the list {@code [double, double[], int]} */
     public static final StdTypeList DOUBLE_DOUBLEARR_INT =
         StdTypeList.make(Type.DOUBLE, Type.DOUBLE_ARRAY, Type.INT);
 
-    /** non-null; the list <code>[Object, Object[], int]</code> */
+    /** {@code non-null;} the list {@code [Object, Object[], int]} */
     public static final StdTypeList OBJECT_OBJECTARR_INT =
         StdTypeList.make(Type.OBJECT, Type.OBJECT_ARRAY, Type.INT);
 
-    /** non-null; the list <code>[int, boolean[], int]</code> */
+    /** {@code non-null;} the list {@code [int, boolean[], int]} */
     public static final StdTypeList INT_BOOLEANARR_INT =
         StdTypeList.make(Type.INT, Type.BOOLEAN_ARRAY, Type.INT);
 
-    /** non-null; the list <code>[int, byte[], int]</code> */
+    /** {@code non-null;} the list {@code [int, byte[], int]} */
     public static final StdTypeList INT_BYTEARR_INT =
         StdTypeList.make(Type.INT, Type.BYTE_ARRAY, Type.INT);
 
-    /** non-null; the list <code>[int, char[], int]</code> */
+    /** {@code non-null;} the list {@code [int, char[], int]} */
     public static final StdTypeList INT_CHARARR_INT =
         StdTypeList.make(Type.INT, Type.CHAR_ARRAY, Type.INT);
 
-    /** non-null; the list <code>[int, short[], int]</code> */
+    /** {@code non-null;} the list {@code [int, short[], int]} */
     public static final StdTypeList INT_SHORTARR_INT =
         StdTypeList.make(Type.INT, Type.SHORT_ARRAY, Type.INT);
 
     /**
      * Makes a single-element instance.
      * 
-     * @param type non-null; the element
-     * @return non-null; an appropriately-constructed instance
+     * @param type {@code non-null;} the element
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public static StdTypeList make(Type type) {
         StdTypeList result = new StdTypeList(1);
@@ -176,9 +176,9 @@
     /**
      * Makes a two-element instance.
      * 
-     * @param type0 non-null; the first element
-     * @param type1 non-null; the second element
-     * @return non-null; an appropriately-constructed instance
+     * @param type0 {@code non-null;} the first element
+     * @param type1 {@code non-null;} the second element
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public static StdTypeList make(Type type0, Type type1) {
         StdTypeList result = new StdTypeList(2);
@@ -190,10 +190,10 @@
     /**
      * Makes a three-element instance.
      * 
-     * @param type0 non-null; the first element
-     * @param type1 non-null; the second element
-     * @param type2 non-null; the third element
-     * @return non-null; an appropriately-constructed instance
+     * @param type0 {@code non-null;} the first element
+     * @param type1 {@code non-null;} the second element
+     * @param type2 {@code non-null;} the third element
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public static StdTypeList make(Type type0, Type type1, Type type2) {
         StdTypeList result = new StdTypeList(3);
@@ -206,11 +206,11 @@
     /**
      * Makes a four-element instance.
      * 
-     * @param type0 non-null; the first element
-     * @param type1 non-null; the second element
-     * @param type2 non-null; the third element
-     * @param type3 non-null; the fourth element
-     * @return non-null; an appropriately-constructed instance
+     * @param type0 {@code non-null;} the first element
+     * @param type1 {@code non-null;} the second element
+     * @param type2 {@code non-null;} the third element
+     * @param type3 {@code non-null;} the fourth element
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public static StdTypeList make(Type type0, Type type1, Type type2,
                                    Type type3) {
@@ -227,8 +227,8 @@
      * is a static method so as to work on arbitrary {@link TypeList}
      * instances.
      * 
-     * @param list non-null; the list to convert
-     * @return non-null; the human form
+     * @param list {@code non-null;} the list to convert
+     * @return {@code non-null;} the human form
      */
     public static String toHuman(TypeList list) {
         int size = list.size();
@@ -254,8 +254,8 @@
      * is a static method so as to work on arbitrary {@link TypeList}
      * instances.
      * 
-     * @param list non-null; the list to inspect
-     * @return non-null; the hash code
+     * @param list {@code non-null;} the list to inspect
+     * @return {@code non-null;} the hash code
      */
     public static int hashContents(TypeList list) {
         int size = list.size();
@@ -273,8 +273,8 @@
      * is a static method so as to work on arbitrary {@link TypeList}
      * instances.
      * 
-     * @param list1 non-null; one list to compare
-     * @param list2 non-null; another list to compare
+     * @param list1 {@code non-null;} one list to compare
+     * @param list2 {@code non-null;} another list to compare
      * @return whether the two lists contain corresponding equal elements
      */
     public static boolean equalContents(TypeList list1, TypeList list2) {
@@ -298,8 +298,8 @@
      * is a static method so as to work on arbitrary {@link TypeList}
      * instances.
      * 
-     * @param list1 non-null; one list to compare
-     * @param list2 non-null; another list to compare
+     * @param list1 {@code non-null;} one list to compare
+     * @param list2 {@code non-null;} another list to compare
      * @return the order of the two lists
      */
     public static int compareContents(TypeList list1, TypeList list2) {
@@ -324,7 +324,7 @@
     }
     
     /**
-     * Constructs an instance. All indices initially contain <code>null</code>.
+     * Constructs an instance. All indices initially contain {@code null}.
      * 
      * @param size the size of the list
      */
@@ -366,10 +366,10 @@
     /**
      * Gets the indicated element. It is an error to call this with the
      * index for an element which was never set; if you do that, this
-     * will throw <code>NullPointerException</code>.
+     * will throw {@code NullPointerException}.
      * 
-     * @param n &gt;= 0, &lt; size(); which element
-     * @return non-null; the indicated element
+     * @param n {@code >= 0, < size();} which element
+     * @return {@code non-null;} the indicated element
      */
     public Type get(int n) {
         return (Type) get0(n);
@@ -378,8 +378,8 @@
     /**
      * Sets the type at the given index.
      * 
-     * @param n &gt;= 0, &lt; size(); which element
-     * @param type non-null; the type to store
+     * @param n {@code >= 0, < size();} which element
+     * @param type {@code non-null;} the type to store
      */
     public void set(int n, Type type) {
         set0(n, type);
@@ -390,8 +390,8 @@
      * except that it has an additional type prepended to the
      * original.
      * 
-     * @param type non-null; the new first element
-     * @return non-null; an appropriately-constructed instance
+     * @param type {@code non-null;} the new first element
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public StdTypeList withFirst(Type type) {
         int sz = size();
diff --git a/dx/src/com/android/dx/rop/type/Type.java b/dx/src/com/android/dx/rop/type/Type.java
index 09ea2e2..64c3c30 100644
--- a/dx/src/com/android/dx/rop/type/Type.java
+++ b/dx/src/com/android/dx/rop/type/Type.java
@@ -24,41 +24,41 @@
  * Representation of a value type, such as may appear in a field, in a
  * local, on a stack, or in a method descriptor. Instances of this
  * class are generally interned and may be usefully compared with each
- * other using <code>==</code>.
+ * other using {@code ==}.
  */
 public final class Type implements TypeBearer, Comparable<Type> {
-    /** non-null; intern table mapping string descriptors to instances */
+    /** {@code non-null;} intern table mapping string descriptors to instances */
     private static final HashMap<String, Type> internTable = 
         new HashMap<String, Type>(500);
 
-    /** basic type constant for <code>void</code> */
+    /** basic type constant for {@code void} */
     public static final int BT_VOID = 0;
 
-    /** basic type constant for <code>boolean</code> */
+    /** basic type constant for {@code boolean} */
     public static final int BT_BOOLEAN = 1;
 
-    /** basic type constant for <code>byte</code> */
+    /** basic type constant for {@code byte} */
     public static final int BT_BYTE = 2;
 
-    /** basic type constant for <code>char</code> */
+    /** basic type constant for {@code char} */
     public static final int BT_CHAR = 3;
 
-    /** basic type constant for <code>double</code> */
+    /** basic type constant for {@code double} */
     public static final int BT_DOUBLE = 4;
 
-    /** basic type constant for <code>float</code> */
+    /** basic type constant for {@code float} */
     public static final int BT_FLOAT = 5;
 
-    /** basic type constant for <code>int</code> */
+    /** basic type constant for {@code int} */
     public static final int BT_INT = 6;
 
-    /** basic type constant for <code>long</code> */
+    /** basic type constant for {@code long} */
     public static final int BT_LONG = 7;
 
-    /** basic type constant for <code>short</code> */
+    /** basic type constant for {@code short} */
     public static final int BT_SHORT = 8;
 
-    /** basic type constant for <code>Object</code> */
+    /** basic type constant for {@code Object} */
     public static final int BT_OBJECT = 9;
 
     /** basic type constant for a return address */
@@ -67,37 +67,37 @@
     /** count of basic type constants */
     public static final int BT_COUNT = 11;
 
-    /** non-null; instance representing <code>boolean</code> */
+    /** {@code non-null;} instance representing {@code boolean} */
     public static final Type BOOLEAN = new Type("Z", BT_BOOLEAN);
 
-    /** non-null; instance representing <code>byte</code> */
+    /** {@code non-null;} instance representing {@code byte} */
     public static final Type BYTE = new Type("B", BT_BYTE);
 
-    /** non-null; instance representing <code>char</code> */
+    /** {@code non-null;} instance representing {@code char} */
     public static final Type CHAR = new Type("C", BT_CHAR);
 
-    /** non-null; instance representing <code>double</code> */
+    /** {@code non-null;} instance representing {@code double} */
     public static final Type DOUBLE = new Type("D", BT_DOUBLE);
 
-    /** non-null; instance representing <code>float</code> */
+    /** {@code non-null;} instance representing {@code float} */
     public static final Type FLOAT = new Type("F", BT_FLOAT);
 
-    /** non-null; instance representing <code>int</code> */
+    /** {@code non-null;} instance representing {@code int} */
     public static final Type INT = new Type("I", BT_INT);
 
-    /** non-null; instance representing <code>long</code> */
+    /** {@code non-null;} instance representing {@code long} */
     public static final Type LONG = new Type("J", BT_LONG);
 
-    /** non-null; instance representing <code>short</code> */
+    /** {@code non-null;} instance representing {@code short} */
     public static final Type SHORT = new Type("S", BT_SHORT);
 
-    /** non-null; instance representing <code>void</code> */
+    /** {@code non-null;} instance representing {@code void} */
     public static final Type VOID = new Type("V", BT_VOID);
 
-    /** non-null; instance representing a known-<code>null</code> */
+    /** {@code non-null;} instance representing a known-{@code null} */
     public static final Type KNOWN_NULL = new Type("<null>", BT_OBJECT);
 
-    /** non-null; instance representing a subroutine return address */
+    /** {@code non-null;} instance representing a subroutine return address */
     public static final Type RETURN_ADDRESS = new Type("<addr>", BT_ADDR);
 
     static {
@@ -120,158 +120,158 @@
     }
 
     /**
-     * non-null; instance representing
-     * <code>java.lang.annotation.Annotation</code>
+     * {@code non-null;} instance representing
+     * {@code java.lang.annotation.Annotation}
      */
     public static final Type ANNOTATION =
         intern("Ljava/lang/annotation/Annotation;");
 
-    /** non-null; instance representing <code>java.lang.Class</code> */
+    /** {@code non-null;} instance representing {@code java.lang.Class} */
     public static final Type CLASS = intern("Ljava/lang/Class;");
 
-    /** non-null; instance representing <code>java.lang.Cloneable</code> */
+    /** {@code non-null;} instance representing {@code java.lang.Cloneable} */
     public static final Type CLONEABLE = intern("Ljava/lang/Cloneable;");
 
-    /** non-null; instance representing <code>java.lang.Object</code> */
+    /** {@code non-null;} instance representing {@code java.lang.Object} */
     public static final Type OBJECT = intern("Ljava/lang/Object;");
 
-    /** non-null; instance representing <code>java.io.Serializable</code> */
+    /** {@code non-null;} instance representing {@code java.io.Serializable} */
     public static final Type SERIALIZABLE = intern("Ljava/io/Serializable;");
 
-    /** non-null; instance representing <code>java.lang.String</code> */
+    /** {@code non-null;} instance representing {@code java.lang.String} */
     public static final Type STRING = intern("Ljava/lang/String;");
 
-    /** non-null; instance representing <code>java.lang.Throwable</code> */
+    /** {@code non-null;} instance representing {@code java.lang.Throwable} */
     public static final Type THROWABLE = intern("Ljava/lang/Throwable;");
 
     /**
-     * non-null; instance representing <code>java.lang.Boolean</code>; the
+     * {@code non-null;} instance representing {@code java.lang.Boolean}; the
      * suffix on the name helps disambiguate this from the instance
      * representing a primitive type 
      */
     public static final Type BOOLEAN_CLASS = intern("Ljava/lang/Boolean;");
 
     /**
-     * non-null; instance representing <code>java.lang.Byte</code>; the
+     * {@code non-null;} instance representing {@code java.lang.Byte}; the
      * suffix on the name helps disambiguate this from the instance
      * representing a primitive type 
      */
     public static final Type BYTE_CLASS = intern("Ljava/lang/Byte;");
 
     /**
-     * non-null; instance representing <code>java.lang.Character</code>; the
+     * {@code non-null;} instance representing {@code java.lang.Character}; the
      * suffix on the name helps disambiguate this from the instance
      * representing a primitive type 
      */
     public static final Type CHARACTER_CLASS = intern("Ljava/lang/Character;");
 
     /**
-     * non-null; instance representing <code>java.lang.Double</code>; the
+     * {@code non-null;} instance representing {@code java.lang.Double}; the
      * suffix on the name helps disambiguate this from the instance
      * representing a primitive type 
      */
     public static final Type DOUBLE_CLASS = intern("Ljava/lang/Double;");
 
     /**
-     * non-null; instance representing <code>java.lang.Float</code>; the
+     * {@code non-null;} instance representing {@code java.lang.Float}; the
      * suffix on the name helps disambiguate this from the instance
      * representing a primitive type 
      */
     public static final Type FLOAT_CLASS = intern("Ljava/lang/Float;");
 
     /**
-     * non-null; instance representing <code>java.lang.Integer</code>; the
+     * {@code non-null;} instance representing {@code java.lang.Integer}; the
      * suffix on the name helps disambiguate this from the instance
      * representing a primitive type 
      */
     public static final Type INTEGER_CLASS = intern("Ljava/lang/Integer;");
 
     /**
-     * non-null; instance representing <code>java.lang.Long</code>; the
+     * {@code non-null;} instance representing {@code java.lang.Long}; the
      * suffix on the name helps disambiguate this from the instance
      * representing a primitive type 
      */
     public static final Type LONG_CLASS = intern("Ljava/lang/Long;");
 
     /**
-     * non-null; instance representing <code>java.lang.Short</code>; the
+     * {@code non-null;} instance representing {@code java.lang.Short}; the
      * suffix on the name helps disambiguate this from the instance
      * representing a primitive type 
      */
     public static final Type SHORT_CLASS = intern("Ljava/lang/Short;");
 
     /**
-     * non-null; instance representing <code>java.lang.Void</code>; the
+     * {@code non-null;} instance representing {@code java.lang.Void}; the
      * suffix on the name helps disambiguate this from the instance
      * representing a primitive type 
      */
     public static final Type VOID_CLASS = intern("Ljava/lang/Void;");
 
-    /** non-null; instance representing <code>boolean[]</code> */
+    /** {@code non-null;} instance representing {@code boolean[]} */
     public static final Type BOOLEAN_ARRAY = BOOLEAN.getArrayType();
 
-    /** non-null; instance representing <code>byte[]</code> */
+    /** {@code non-null;} instance representing {@code byte[]} */
     public static final Type BYTE_ARRAY = BYTE.getArrayType();
 
-    /** non-null; instance representing <code>char[]</code> */
+    /** {@code non-null;} instance representing {@code char[]} */
     public static final Type CHAR_ARRAY = CHAR.getArrayType();
 
-    /** non-null; instance representing <code>double[]</code> */
+    /** {@code non-null;} instance representing {@code double[]} */
     public static final Type DOUBLE_ARRAY = DOUBLE.getArrayType();
 
-    /** non-null; instance representing <code>float[]</code> */
+    /** {@code non-null;} instance representing {@code float[]} */
     public static final Type FLOAT_ARRAY = FLOAT.getArrayType();
 
-    /** non-null; instance representing <code>int[]</code> */
+    /** {@code non-null;} instance representing {@code int[]} */
     public static final Type INT_ARRAY = INT.getArrayType();
 
-    /** non-null; instance representing <code>long[]</code> */
+    /** {@code non-null;} instance representing {@code long[]} */
     public static final Type LONG_ARRAY = LONG.getArrayType();
 
-    /** non-null; instance representing <code>Object[]</code> */
+    /** {@code non-null;} instance representing {@code Object[]} */
     public static final Type OBJECT_ARRAY = OBJECT.getArrayType();
 
-    /** non-null; instance representing <code>short[]</code> */
+    /** {@code non-null;} instance representing {@code short[]} */
     public static final Type SHORT_ARRAY = SHORT.getArrayType();
 
-    /** non-null; field descriptor for the type */
+    /** {@code non-null;} field descriptor for the type */
     private final String descriptor;
 
     /**
      * basic type corresponding to this type; one of the
-     * <code>BT_*</code> constants 
+     * {@code BT_*} constants 
      */
     private final int basicType;
 
     /**
-     * &gt;= -1; for an uninitialized type, bytecode index that this
-     * instance was allocated at; <code>Integer.MAX_VALUE</code> if it
-     * was an incoming uninitialized instance; <code>-1</code> if this
+     * {@code >= -1;} for an uninitialized type, bytecode index that this
+     * instance was allocated at; {@code Integer.MAX_VALUE} if it
+     * was an incoming uninitialized instance; {@code -1} if this
      * is an <i>inititialized</i> instance 
      */
     private final int newAt;
 
     /**
-     * null-ok; the internal-form class name corresponding to this type, if
-     * calculated; only valid if <code>this</code> is a reference type and
+     * {@code null-ok;} the internal-form class name corresponding to this type, if
+     * calculated; only valid if {@code this} is a reference type and
      * additionally not a return address 
      */
     private String className;
 
     /**
-     * null-ok; the type corresponding to an array of this type, if
+     * {@code null-ok;} the type corresponding to an array of this type, if
      * calculated 
      */
     private Type arrayType;
 
     /**
-     * null-ok; the type corresponding to elements of this type, if
-     * calculated; only valid if <code>this</code> is an array type 
+     * {@code null-ok;} the type corresponding to elements of this type, if
+     * calculated; only valid if {@code this} is an array type 
      */
     private Type componentType;
 
     /**
-     * null-ok; the type corresponding to the initialized version of
+     * {@code null-ok;} the type corresponding to the initialized version of
      * this type, if this instance is in fact an uninitialized type 
      */
     private Type initializedType;
@@ -280,11 +280,11 @@
      * Returns the unique instance corresponding to the type with the
      * given descriptor. See vmspec-2 sec4.3.2 for details on the
      * field descriptor syntax. This method does <i>not</i> allow
-     * <code>"V"</code> (that is, type <code>void</code>) as a valid
+     * {@code "V"} (that is, type {@code void}) as a valid
      * descriptor.
      * 
-     * @param descriptor non-null; the descriptor
-     * @return non-null; the corresponding instance
+     * @param descriptor {@code non-null;} the descriptor
+     * @return {@code non-null;} the corresponding instance
      * @throws IllegalArgumentException thrown if the descriptor has
      * invalid syntax
      */
@@ -362,12 +362,12 @@
 
     /**
      * Returns the unique instance corresponding to the type with the
-     * given descriptor, allowing <code>"V"</code> to return the type
-     * for <code>void</code>. Other than that one caveat, this method
+     * given descriptor, allowing {@code "V"} to return the type
+     * for {@code void}. Other than that one caveat, this method
      * is identical to {@link #intern}.
      * 
-     * @param descriptor non-null; the descriptor
-     * @return non-null; the corresponding instance
+     * @param descriptor {@code non-null;} the descriptor
+     * @return {@code non-null;} the corresponding instance
      * @throws IllegalArgumentException thrown if the descriptor has
      * invalid syntax
      */
@@ -388,12 +388,12 @@
     /**
      * Returns the unique instance corresponding to the type of the
      * class with the given name. Calling this method is equivalent to
-     * calling <code>intern(name)</code> if <code>name</code> begins
-     * with <code>"["</code> and calling <code>intern("L" + name + ";")</code>
+     * calling {@code intern(name)} if {@code name} begins
+     * with {@code "["} and calling {@code intern("L" + name + ";")}
      * in all other cases.
      * 
-     * @param name non-null; the name of the class whose type is desired
-     * @return non-null; the corresponding type
+     * @param name {@code non-null;} the name of the class whose type is desired
+     * @return {@code non-null;} the corresponding type
      * @throws IllegalArgumentException thrown if the name has
      * invalid syntax
      */
@@ -414,10 +414,10 @@
      * This is a private constructor; use one of the public static
      * methods to get instances.
      * 
-     * @param descriptor non-null; the field descriptor for the type
+     * @param descriptor {@code non-null;} the field descriptor for the type
      * @param basicType basic type corresponding to this type; one of the
-     * <code>BT_*</code> constants
-     * @param newAt &gt;= -1 allocation bytecode index
+     * {@code BT_*} constants
+     * @param newAt {@code >= -1;} allocation bytecode index
      */
     private Type(String descriptor, int basicType, int newAt) {
         if (descriptor == null) {
@@ -445,9 +445,9 @@
      * This is a private constructor; use one of the public static
      * methods to get instances.
      * 
-     * @param descriptor non-null; the field descriptor for the type
+     * @param descriptor {@code non-null;} the field descriptor for the type
      * @param basicType basic type corresponding to this type; one of the
-     * <code>BT_*</code> constants
+     * {@code BT_*} constants
      */
     private Type(String descriptor, int basicType) {
         this(descriptor, basicType, -1);
@@ -560,7 +560,7 @@
     /**
      * Gets the descriptor.
      * 
-     * @return non-null; the descriptor
+     * @return {@code non-null;} the descriptor
      */
     public String getDescriptor() {
         return descriptor;
@@ -572,7 +572,7 @@
      * normal reference type (that is, a reference type and
      * additionally not a return address).
      * 
-     * @return non-null; the internal-form class name
+     * @return {@code non-null;} the internal-form class name
      */
     public String getClassName() {
         if (className == null) {
@@ -592,8 +592,8 @@
     }
 
     /**
-     * Gets the category. Most instances are category 1. <code>long</code>
-     * and <code>double</code> are the only category 2 types.
+     * Gets the category. Most instances are category 1. {@code long}
+     * and {@code double} are the only category 2 types.
      * 
      * @see #isCategory1
      * @see #isCategory2
@@ -649,7 +649,7 @@
     /**
      * Gets whether this type is "intlike." An intlike type is one which, when
      * placed on a stack or in a local, is automatically converted to an
-     * <code>int</code>.
+     * {@code int}.
      * 
      * @return whether this type is "intlike"
      */
@@ -695,7 +695,7 @@
      * Gets whether this type is a normal reference type. A normal
      * reference type is a reference type that is not a return
      * address. This method is just convenient shorthand for
-     * <code>getBasicType() == Type.BT_OBJECT</code>.
+     * {@code getBasicType() == Type.BT_OBJECT}.
      * 
      * @return whether this type is a normal reference type
      */
@@ -705,7 +705,7 @@
 
     /**
      * Gets whether this type is an array type. If this method returns
-     * <code>true</code>, then it is safe to use {@link #getComponentType}
+     * {@code true}, then it is safe to use {@link #getComponentType}
      * to determine the component type.
      * 
      * @return whether this type is an array type
@@ -726,7 +726,7 @@
 
     /**
      * Gets whether this type represents an uninitialized instance. An
-     * uninitialized instance is what one gets back from the <code>new</code>
+     * uninitialized instance is what one gets back from the {@code new}
      * opcode, and remains uninitialized until a valid constructor is
      * invoked on it.
      * 
@@ -738,12 +738,12 @@
 
     /**
      * Gets the bytecode index at which this uninitialized type was
-     * allocated.  This returns <code>Integer.MAX_VALUE</code> if this
+     * allocated.  This returns {@code Integer.MAX_VALUE} if this
      * type is an uninitialized incoming parameter (i.e., the
-     * <code>this</code> of an <code>&lt;init&gt;</code> method) or
-     * <code>-1</code> if this type is in fact <i>initialized</i>.
+     * {@code this} of an {@code <init>} method) or
+     * {@code -1} if this type is in fact <i>initialized</i>.
      * 
-     * @return &gt;= -1; the allocation bytecode index
+     * @return {@code >= -1;} the allocation bytecode index
      */
     public int getNewAt() {
         return newAt;
@@ -753,7 +753,7 @@
      * Gets the initialized type corresponding to this instance, but only
      * if this instance is in fact an uninitialized object type.
      * 
-     * @return non-null; the initialized type
+     * @return {@code non-null;} the initialized type
      */
     public Type getInitializedType() {
         if (initializedType == null) {
@@ -767,7 +767,7 @@
     /**
      * Gets the type corresponding to an array of this type.
      * 
-     * @return non-null; the array type
+     * @return {@code non-null;} the array type
      */
     public Type getArrayType() {
         if (arrayType == null) {
@@ -781,7 +781,7 @@
      * Gets the component type of this type. This method is only valid on
      * array types.
      * 
-     * @return non-null; the component type
+     * @return {@code non-null;} the component type
      */
     public Type getComponentType() {
         if (componentType == null) {
@@ -800,8 +800,8 @@
      * it is indicated as uninitialized and allocated at the given bytecode
      * index. This instance must be an initialized object type.
      * 
-     * @param newAt &gt;= 0; the allocation bytecode index
-     * @return non-null; an appropriately-constructed instance
+     * @param newAt {@code >= 0;} the allocation bytecode index
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public Type asUninitialized(int newAt) {
         if (newAt < 0) {
@@ -838,8 +838,8 @@
      * there. If a conflicting value is already in the table, then leave it.
      * Return the interned value.
      * 
-     * @param type non-null; instance to make interned
-     * @return non-null; the actual interned object
+     * @param type {@code non-null;} instance to make interned
+     * @return {@code non-null;} the actual interned object
      */
     private static Type putIntern(Type type) {
         synchronized (internTable) {
diff --git a/dx/src/com/android/dx/rop/type/TypeBearer.java b/dx/src/com/android/dx/rop/type/TypeBearer.java
index b9e4ea5..2f2f274 100644
--- a/dx/src/com/android/dx/rop/type/TypeBearer.java
+++ b/dx/src/com/android/dx/rop/type/TypeBearer.java
@@ -26,40 +26,40 @@
     /**
      * Gets the type associated with this instance.
      *
-     * @return non-null; the type
+     * @return {@code non-null;} the type
      */
     public Type getType();
 
     /**
      * Gets the frame type corresponding to this type. This method returns
-     * <code>this</code>, except if {@link Type#isIntlike} on the underlying
-     * type returns <code>true</code> but the underlying type is not in
+     * {@code this}, except if {@link Type#isIntlike} on the underlying
+     * type returns {@code true} but the underlying type is not in
      * fact {@link Type#INT}, in which case this method returns an instance
-     * whose underlying type <i>is</i> <code>INT</code>.
+     * whose underlying type <i>is</i> {@code INT}.
      *
-     * @return non-null; the frame type for this instance
+     * @return {@code non-null;} the frame type for this instance
      */
     public TypeBearer getFrameType();
 
     /**
      * Gets the basic type corresponding to this instance.
      *
-     * @return the basic type; one of the <code>BT_*</code> constants
+     * @return the basic type; one of the {@code BT_*} constants
      * defined by {@link Type}
      */
     public int getBasicType();
 
     /**
      * Gets the basic type corresponding to this instance's frame type. This
-     * is equivalent to <code>getFrameType().getBasicType()</code>, and
-     * is the same as calling <code>getFrameType()</code> unless this
+     * is equivalent to {@code getFrameType().getBasicType()}, and
+     * is the same as calling {@code getFrameType()} unless this
      * instance is an int-like type, in which case this method returns
-     * <code>BT_INT</code>.
+     * {@code BT_INT}.
      * 
      * @see #getBasicType
      * @see #getFrameType
      * 
-     * @return the basic frame type; one of the <code>BT_*</code> constants
+     * @return the basic frame type; one of the {@code BT_*} constants
      * defined by {@link Type}
      */
     public int getBasicFrameType();
@@ -67,8 +67,8 @@
     /**
      * Returns whether this instance represents a constant value.
      * 
-     * @return <code>true</code> if this instance represents a constant value
-     * and <code>false</code> if not
+     * @return {@code true} if this instance represents a constant value
+     * and {@code false} if not
      */
     public boolean isConstant();
 }
diff --git a/dx/src/com/android/dx/rop/type/TypeList.java b/dx/src/com/android/dx/rop/type/TypeList.java
index 0944fe2..e82cca7 100644
--- a/dx/src/com/android/dx/rop/type/TypeList.java
+++ b/dx/src/com/android/dx/rop/type/TypeList.java
@@ -22,29 +22,29 @@
 public interface TypeList {
     /**
      * Returns whether this instance is mutable. Note that the
-     * <code>TypeList</code> interface itself doesn't provide any
+     * {@code TypeList} interface itself doesn't provide any
      * means of mutation, but that doesn't mean that there isn't an
      * extra-interface way of mutating an instance.
      * 
-     * @return <code>true</code> if this instance is mutable or
-     * <code>false</code> if it is immutable
+     * @return {@code true} if this instance is mutable or
+     * {@code false} if it is immutable
      */
     public boolean isMutable();
     
     /**
      * Gets the size of this list.
      *
-     * @return &gt;= 0; the size
+     * @return {@code >= 0;} the size
      */
     public int size();
 
     /**
      * Gets the indicated element. It is an error to call this with the
      * index for an element which was never set; if you do that, this
-     * will throw <code>NullPointerException</code>.
+     * will throw {@code NullPointerException}.
      *
-     * @param n &gt;= 0, &lt; size(); which element
-     * @return non-null; the indicated element
+     * @param n {@code >= 0, < size();} which element
+     * @return {@code non-null;} the indicated element
      */
     public Type getType(int n);
 
@@ -53,7 +53,7 @@
      * all the elements of this list. This is a sum of the widths (categories)
      * of all the elements.
      * 
-     * @return &gt;= 0; the required number of words
+     * @return {@code >= 0;} the required number of words
      */
     public int getWordCount();
 
@@ -62,8 +62,8 @@
      * the given item is appended to the end and it is guaranteed to be
      * immutable.
      * 
-     * @param type non-null; item to append
-     * @return non-null; an appropriately-constructed instance
+     * @param type {@code non-null;} item to append
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public TypeList withAddedType(Type type);
 }
diff --git a/dx/src/com/android/dx/ssa/BasicRegisterMapper.java b/dx/src/com/android/dx/ssa/BasicRegisterMapper.java
index 86fcf81..fdabaab 100644
--- a/dx/src/com/android/dx/ssa/BasicRegisterMapper.java
+++ b/dx/src/com/android/dx/ssa/BasicRegisterMapper.java
@@ -24,17 +24,16 @@
  * This class maps one register space into another, with
  * each mapping built up individually and added via addMapping()
  */
-public class BasicRegisterMapper
-        extends RegisterMapper {
-
+public class BasicRegisterMapper extends RegisterMapper {
     /** indexed by old register, containing new name */
     private IntList oldToNew;
 
-    /** Running count of used registers in new namespace */
+    /** running count of used registers in new namespace */
     private int runningCountNewRegisters;
 
     /**
-     * Creates a new OneToOneRegisterMapper
+     * Creates a new OneToOneRegisterMapper.
+     * 
      * @param countOldRegisters the number of registers in the old name space
      */
     public BasicRegisterMapper(int countOldRegisters) {
@@ -70,15 +69,16 @@
 
     /**
      * Returns the new-namespace mapping for the specified
-     * old-namespace register, or -1 if one exists
+     * old-namespace register, or -1 if one exists.
      *
-     * @param oldReg &gt;=0; old-namespace register
-     * @return new-namespace register or -1 if none.
+     * @param oldReg {@code >= 0;} old-namespace register
+     * @return new-namespace register or -1 if none
      */
     public int oldToNew(int oldReg) {
-        if(oldReg >= oldToNew.size()) {
+        if (oldReg >= oldToNew.size()) {
             return -1;
         }
+
         return oldToNew.get(oldReg);
     }
 
@@ -88,7 +88,8 @@
 
         sb.append("Old\tNew\n");
         int sz = oldToNew.size();
-        for(int i = 0; i < sz; i++) {
+
+        for (int i = 0; i < sz; i++) {
             sb.append(i);
             sb.append('\t');
             sb.append(oldToNew.get(i));
@@ -104,12 +105,12 @@
     }
 
     /**
-     * adds a mapping to the mapper. If oldReg has already been mapped,
+     * Adds a mapping to the mapper. If oldReg has already been mapped,
      * overwrites previous mapping with new mapping.
      *
-     * @param oldReg >=0
-     * @param newReg >=0
-     * @param category width of reg (1 or 2)
+     * @param oldReg {@code >= 0;} old register
+     * @param newReg {@code >= 0;} new register
+     * @param category {@code 1..2;} width of reg
      */
     public void addMapping(int oldReg, int newReg, int category) {
         if (oldReg >= oldToNew.size()) {
@@ -118,6 +119,7 @@
                 oldToNew.add(-1);
             }
         }
+
         oldToNew.set(oldReg, newReg);
 
         if (runningCountNewRegisters < (newReg + category)) {
diff --git a/dx/src/com/android/dx/ssa/ConstCollector.java b/dx/src/com/android/dx/ssa/ConstCollector.java
index afdede7..03252d1 100644
--- a/dx/src/com/android/dx/ssa/ConstCollector.java
+++ b/dx/src/com/android/dx/ssa/ConstCollector.java
@@ -17,19 +17,20 @@
 package com.android.dx.ssa;
 
 import com.android.dx.rop.code.*;
-import com.android.dx.rop.type.TypeBearer;
+import com.android.dx.rop.cst.Constant;
+import com.android.dx.rop.cst.CstString;
+import com.android.dx.rop.cst.TypedConstant;
 import com.android.dx.rop.type.StdTypeList;
 import com.android.dx.rop.type.Type;
-import com.android.dx.rop.cst.Constant;
-import com.android.dx.rop.cst.TypedConstant;
-import com.android.dx.rop.cst.CstString;
+import com.android.dx.rop.type.TypeBearer;
 
-import java.util.HashMap;
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
 
 /**
  * Collects constants that are used more than once at the top of the
@@ -37,7 +38,6 @@
  * insn size by about 3%.
  */
 public class ConstCollector {
-
     /** Maximum constants to collect per method. Puts cap on reg use */
     private static final int MAX_COLLECTED_CONSTANTS = 5;
 
@@ -60,18 +60,20 @@
     private final SsaMethod ssaMeth;
 
     /**
-     * Process a method.
+     * Processes a method.
      *
-     * @param ssaMethod non-null; method to process
+     * @param ssaMethod {@code non-null;} method to process
      */
     public static void process(SsaMethod ssaMethod) {
-        ConstCollector dc;
-
-        dc = new ConstCollector(ssaMethod);
-            
-        dc.run();
+        ConstCollector cc = new ConstCollector(ssaMethod);
+        cc.run();
     }
 
+    /**
+     * Constructs an instance.
+     * 
+     * @param ssaMethod {@code non-null;} method to process
+     */
     private ConstCollector(SsaMethod ssaMethod) {
         this.ssaMeth = ssaMethod;
     }
@@ -111,9 +113,7 @@
                 SsaBasicBlock successorBlock
                         = entryBlock.getPrimarySuccessor();
 
-                /*
-                 * Insert a block containing the const insn
-                 */
+                // Insert a block containing the const insn.
                 SsaBasicBlock constBlock
                         = entryBlock.insertNewSuccessor(successorBlock);
 
@@ -122,18 +122,17 @@
                                 RegisterSpecList.EMPTY,
                                 StdTypeList.EMPTY, cst));
 
-                /*
-                 * Insert a block containing the move-result-pseudo insn
-                 */
+                // Insert a block containing the move-result-pseudo insn.
 
                 SsaBasicBlock resultBlock
                         = constBlock.insertNewSuccessor(successorBlock);
+                PlainInsn insn 
+                    = new PlainInsn(
+                            Rops.opMoveResultPseudo(result.getTypeBearer()),
+                            SourcePosition.NO_INFO,
+                            result, RegisterSpecList.EMPTY);
 
-                resultBlock.addInsnToHead(
-                        new PlainInsn(
-                                Rops.opMoveResultPseudo(result.getTypeBearer()),
-                                SourcePosition.NO_INFO,
-                                result, RegisterSpecList.EMPTY));
+                resultBlock.addInsnToHead(insn);
             }
 
             newRegs.put(cst, result);
@@ -147,7 +146,7 @@
      * sorted by most used first. Skips non-collectable consts, such as
      * non-string object constants
      *
-     * @return non-null; list of constants in most-to-least used order
+     * @return {@code non-null;} list of constants in most-to-least used order
      */
     private ArrayList<TypedConstant> getConstsSortedByCountUse() {
         int regSz = ssaMeth.getRegCount();
@@ -155,20 +154,21 @@
         final HashMap<TypedConstant, Integer> countUses
                 = new HashMap<TypedConstant, Integer>();
 
-        // Each collected constant can be used by just one local
-        // (used only if COLLECT_ONE_LOCAL is true)
+        /*
+         * Each collected constant can be used by just one local
+         * (used only if COLLECT_ONE_LOCAL is true).
+         */
         final HashSet<TypedConstant> usedByLocal
                 = new HashSet<TypedConstant>();
 
-        // Count how many times each const value is used
+        // Count how many times each const value is used.
         for (int i = 0; i < regSz; i++) {
             SsaInsn insn = ssaMeth.getDefinitionForRegister(i);
 
             if (insn == null) continue;
 
             RegisterSpec result = insn.getResult();
-
-            TypeBearer typeBearer = insn.getResult().getTypeBearer();
+            TypeBearer typeBearer = result.getTypeBearer();
 
             if (!typeBearer.isConstant()) continue;
 
@@ -177,28 +177,30 @@
             if (insn.canThrow()) {
                 /*
                  * Don't move anything other than strings -- the risk
-                 * of changing where an exception is thrown is too high.                
+                 * of changing where an exception is thrown is too high.
                  */
                 if (!(cst instanceof CstString) || !COLLECT_STRINGS) {
                     continue;
                 }
                 /*
-                 * We can't move any throwable const whose throw will be caught,
-                 * so don't count them.                 
+                 * We can't move any throwable const whose throw will be
+                 * caught, so don't count them.                 
                  */
                 if (insn.getBlock().getSuccessors().cardinality() > 1) {
                     continue;
                 }
             }
 
-            // TODO might be nice to try and figure out which local wins most
-            // when collected
+            /*
+             * TODO: Might be nice to try and figure out which local
+             * wins most when collected.
+             */
             if (ssaMeth.isRegALocal(result)) {
                 if (!COLLECT_ONE_LOCAL) {
                     continue;
                 } else {
                     if (usedByLocal.contains(cst)) {
-                        // Count one local usage only
+                        // Count one local usage only.
                         continue;
                     } else {
                         usedByLocal.add(cst);
@@ -214,18 +216,15 @@
             }
         }
 
-        // Collect constants that have been reused
-        Iterator<TypedConstant> it = countUses.keySet().iterator();
+        // Collect constants that have been reused.
         ArrayList<TypedConstant> constantList = new ArrayList<TypedConstant>();
-        while (it.hasNext()) {
-            TypedConstant cst = it.next();
-
-            if (countUses.get(cst) > 1) {
-                constantList.add(cst);
+        for (Map.Entry<TypedConstant, Integer> entry : countUses.entrySet()) {
+            if (entry.getValue() > 1) {
+                constantList.add(entry.getKey());
             }
         }
 
-        // Sort by use, with most used at the beginning of the list
+        // Sort by use, with most used at the beginning of the list.
         Collections.sort(constantList, new Comparator<Constant>() {
             public int compare(Constant a, Constant b) {
                 int ret;
@@ -241,47 +240,48 @@
 
                 return ret;
             }
+
             public boolean equals (Object obj) {
                 return obj == this;
             }
         });
+
         return constantList;
     }
 
     /**
      * Inserts mark-locals if necessary when changing a register. If
-     * the definition of <code>origReg</code> is associated with a local
-     * variable, then insert a mark-local for <code>newReg</code> just below
-     * it. We expect the definition of  <code>origReg</code> to ultimately
+     * the definition of {@code origReg} is associated with a local
+     * variable, then insert a mark-local for {@code newReg} just below
+     * it. We expect the definition of  {@code origReg} to ultimately
      * be removed by the dead code eliminator
      * 
-     * @param origReg non-null; original register
-     * @param newReg non-null; new register that will replace
-     * <code>origReg</code>
+     * @param origReg {@code non-null;} original register
+     * @param newReg {@code non-null;} new register that will replace
+     * {@code origReg}
      */
-    private void fixLocalAssignment(RegisterSpec origReg, RegisterSpec newReg) {
-        for (SsaInsn use: ssaMeth.getUseListForRegister(origReg.getReg())) {
+    private void fixLocalAssignment(RegisterSpec origReg,
+            RegisterSpec newReg) {
+        for (SsaInsn use : ssaMeth.getUseListForRegister(origReg.getReg())) {
             RegisterSpec localAssignment = use.getLocalAssignment();
             if (localAssignment == null) {
                 continue;
             }
 
             if (use.getResult() == null) {
-                // this is a mark-local. it will be updated when all uses
-                // are updated
+                /*
+                 * This is a mark-local. it will be updated when all uses
+                 * are updated.
+                 */
                 continue;
             }
 
             LocalItem local = localAssignment.getLocalItem();
 
-            /*
-             * un-associate original use
-             */
+            // Un-associate original use.
             use.setResultLocal(null);
 
-            /*
-             * now add a mark-local to the new reg immediately after
-             */                       
+            // Now add a mark-local to the new reg immediately after.
             newReg = newReg.withLocalItem(local);
 
             SsaInsn newInsn
@@ -301,15 +301,17 @@
      * Updates all uses of various consts to use the values in the newly
      * assigned registers.
      *
-     * @param newRegs non-null; mapping between constant and new reg
-     * @param origRegCount &gt;=0; original SSA reg count, not including
+     * @param newRegs {@code non-null;} mapping between constant and new reg
+     * @param origRegCount {@code >=0;} original SSA reg count, not including
      * newly added constant regs
      */
     private void updateConstUses(HashMap<TypedConstant, RegisterSpec> newRegs,
             int origRegCount) {
 
-        // Set of constants associated with a local variable
-        // Used only if COLLECT_ONE_LOCAL is true
+        /*
+         * set of constants associated with a local variable; used
+         * only if COLLECT_ONE_LOCAL is true.
+         */
         final HashSet<TypedConstant> usedByLocal
                 = new HashSet<TypedConstant>();
 
@@ -338,8 +340,11 @@
                 if (!COLLECT_ONE_LOCAL) {
                     continue;                    
                 } else {
-                    // TODO if the same local gets the same cst multiple times,
-                    // it would be nice to reuse the register
+                    /*
+                     * TODO: If the same local gets the same cst
+                     * multiple times, it would be nice to reuse the
+                     * register.
+                     */
                     if (usedByLocal.contains(cst)) {
                         continue;
                     } else {
@@ -349,7 +354,7 @@
                 }
             }
 
-            // Maps an original const register to the new collected register
+            // maps an original const register to the new collected register
             RegisterMapper mapper = new RegisterMapper() {
                 @Override
                 public int getNewRegisterCount() {
@@ -359,14 +364,15 @@
                 @Override
                 public RegisterSpec map(RegisterSpec registerSpec) {
                     if (registerSpec.getReg() == origReg.getReg()) {
-                        return newReg.withLocalItem(registerSpec.getLocalItem());
+                        return newReg.withLocalItem(
+                                registerSpec.getLocalItem());
                     }
 
                     return registerSpec;
                 }
             };
 
-            for (SsaInsn use: useList[origReg.getReg()]) {
+            for (SsaInsn use : useList[origReg.getReg()]) {
                 if (use.canThrow()
                         && use.getBlock().getSuccessors().cardinality() > 1) {
                     continue;
diff --git a/dx/src/com/android/dx/ssa/DeadCodeRemover.java b/dx/src/com/android/dx/ssa/DeadCodeRemover.java
index 4fded44..ec960b8 100644
--- a/dx/src/com/android/dx/ssa/DeadCodeRemover.java
+++ b/dx/src/com/android/dx/ssa/DeadCodeRemover.java
@@ -36,55 +36,55 @@
  * block to entry block.
  */
 public class DeadCodeRemover {
-
     /** method we're processing */
-    private SsaMethod ssaMeth;
+    private final SsaMethod ssaMeth;
+
     /** ssaMeth.getRegCount() */
-    private int regCount;
+    private final int regCount;
 
     /**
      * indexed by register: whether reg should be examined
      * (does it correspond to a no-side-effect insn?)
      */
-    private BitSet worklist;
+    private final BitSet worklist;
 
     /** use list indexed by register; modified during operation */
-    private ArrayList<SsaInsn>[] useList;
+    private final ArrayList<SsaInsn>[] useList;
 
     /**
      * Process a method with the dead-code remver
+     * 
      * @param ssaMethod method to process
      */
     public static void process(SsaMethod ssaMethod) {
-        DeadCodeRemover dc;
-
-        dc = new DeadCodeRemover(ssaMethod);
-            
+        DeadCodeRemover dc = new DeadCodeRemover(ssaMethod);
         dc.run();
     }
 
+    /**
+     * Constructs an instance.
+     * 
+     * @param ssaMethod method to process
+     */
     private DeadCodeRemover(SsaMethod ssaMethod) {
         this.ssaMeth = ssaMethod;
 
         regCount = ssaMethod.getRegCount();
-
         worklist = new BitSet(regCount);
-
         useList = ssaMeth.getUseListCopy();
     }
 
     /**
-     * Run the dead code remover
+     * Runs the dead code remover.
      */
     private void run() {
-
         HashSet<SsaInsn> deletedInsns = (HashSet<SsaInsn>) new HashSet();
 
         ssaMeth.forEachInsn(new NoSideEffectVisitor(worklist));
 
         int regV;
 
-        while ( 0 <=  (regV = worklist.nextSetBit(0)) ) {
+        while ( 0 <= (regV = worklist.nextSetBit(0)) ) {
             worklist.clear(regV);
 
             if (useList[regV].size() == 0
@@ -92,7 +92,7 @@
 
                 SsaInsn insnS = ssaMeth.getDefinitionForRegister(regV);
 
-                // This insn has already been deleted
+                // This insn has already been deleted.
                 if (deletedInsns.contains(insnS)) {
                     continue;
                 }
@@ -101,8 +101,7 @@
 
                 int sz = sources.size();
                 for (int i = 0; i < sz; i++) {
-
-                    // Delete this insn from all usage lists
+                    // Delete this insn from all usage lists.
                     RegisterSpec source = sources.get(i);
                     useList[source.getReg()].remove(insnS);
 
@@ -110,14 +109,14 @@
                             ssaMeth.getDefinitionForRegister(
                                     source.getReg()))) {
                         /*
-                         * Only registers who's definition has no side effect
-                         * should be added back to the worklist
+                         * Only registers whose definition has no side effect
+                         * should be added back to the worklist.
                          */
                         worklist.set(source.getReg());
                     }
                 }
 
-                // Schedule this insn for later deletion
+                // Schedule this insn for later deletion.
                 deletedInsns.add(insnS);
             }
         }
@@ -127,7 +126,8 @@
 
     /**
      * Returns true if the only uses of this register form a circle of
-     * operations with no side effects
+     * operations with no side effects.
+     * 
      * @param regV register to examine
      * @param set a set of registers that we've already determined
      * are only used as sources in operations with no side effect or null
@@ -139,7 +139,7 @@
             return true;
         }
 
-        for (SsaInsn use: useList[regV]) {
+        for (SsaInsn use : useList[regV]) {
             if (hasSideEffect(use)) {
                 return false;
             }
@@ -152,7 +152,7 @@
         // This register is only used in operations that have no side effect.
         set.set(regV);
 
-        for (SsaInsn use: useList[regV]) {
+        for (SsaInsn use : useList[regV]) {
             RegisterSpec result = use.getResult();
 
             if (result == null
@@ -167,13 +167,14 @@
     /**
      * Returns true if this insn has a side-effect. Returns true
      * if the insn is null for reasons stated in the code block.
-     * @param insn null-ok; instruction in question
+     *
+     * @param insn {@code null-ok;} instruction in question
      * @return true if it has a side-effect
      */
     private static boolean hasSideEffect(SsaInsn insn) {
         if (insn == null) {
-            /* while false would seem to make more sense here, true
-             * prevents us from adding this back to a worklist unnecessarally
+            /* While false would seem to make more sense here, true
+             * prevents us from adding this back to a worklist unnecessarally.
              */
             return true;
         }
@@ -185,7 +186,7 @@
      * A callback class used to build up the initial worklist of
      * registers defined by an instruction with no side effect.
      */
-    static class NoSideEffectVisitor implements SsaInsn.Visitor {
+    static private class NoSideEffectVisitor implements SsaInsn.Visitor {
         BitSet noSideEffectRegs;
 
         /**
@@ -195,13 +196,13 @@
          * @param noSideEffectRegs to-build bitset of regs that are
          * results of regs with no side effects
          */
-        NoSideEffectVisitor(BitSet noSideEffectRegs) {
+        public NoSideEffectVisitor(BitSet noSideEffectRegs) {
             this.noSideEffectRegs = noSideEffectRegs;
         }
 
         /** {@inheritDoc} */
         public void visitMoveInsn (NormalSsaInsn insn) {
-            // If we're tracking local vars, some moves have side effects
+            // If we're tracking local vars, some moves have side effects.
             if (!hasSideEffect(insn)) {
                 noSideEffectRegs.set(insn.getResult().getReg());
             }
@@ -209,7 +210,7 @@
 
         /** {@inheritDoc} */
         public void visitPhiInsn (PhiInsn phi) {
-            // If we're tracking local vars, then some phis have side effects
+            // If we're tracking local vars, then some phis have side effects.
             if (!hasSideEffect(phi)) {
                 noSideEffectRegs.set(phi.getResult().getReg());
             }
diff --git a/dx/src/com/android/dx/ssa/DomFront.java b/dx/src/com/android/dx/ssa/DomFront.java
index ea089ec..3005015 100644
--- a/dx/src/com/android/dx/ssa/DomFront.java
+++ b/dx/src/com/android/dx/ssa/DomFront.java
@@ -30,27 +30,34 @@
  * Harvey, and Kennedy; transliterated to Java.
  */
 public class DomFront {
+    /** local debug flag */
     private static boolean DEBUG = false;
 
+    /** {@code non-null;} method being processed */
     private final SsaMethod meth;
+
     private final ArrayList<SsaBasicBlock> nodes;
+    
     private final DomInfo[] domInfos;
 
     /**
      * Dominance-frontier information for a single basic block.
      */
     public static class DomInfo {
-        /** non-null; the dominance frontier set indexed by block index */
-        IntSet dominanceFrontiers;
-        /** &gt= 0 after run(); the index of the immediate dominator */
-        int idom = -1;
-        /** depth-first traversal index */
-        int traversalIndex;
+        /**
+         * {@code null-ok;} the dominance frontier set indexed by
+         * block index
+         */
+        public IntSet dominanceFrontiers;
+
+        /** {@code >= 0 after run();} the index of the immediate dominator */
+        public int idom = -1;
     }
 
     /**
      * Constructs instance. Call {@link DomFront#run} to process. 
-     * @param meth
+     * 
+     * @param meth {@code non-null;} method to process
      */
     public DomFront(SsaMethod meth) {
         this.meth = meth;
@@ -67,7 +74,7 @@
     /**
      * Calculates the dominance frontier information for the method.
      *
-     * @return non-null; an array of DomInfo structures
+     * @return {@code non-null;} an array of DomInfo structures
      */
     public DomInfo[] run() {
         int szNodes = nodes.size();
@@ -80,8 +87,7 @@
             }
         }
 
-        Dominators methDom = new Dominators(domInfos, false);
-        methDom.run(meth);
+        Dominators methDom = Dominators.make(meth, domInfos, false);
 
         if (DEBUG) {
             for (int i = 0; i < szNodes; i++) {
@@ -123,7 +129,7 @@
 
             sb.append('{');
             boolean comma = false;
-            for (SsaBasicBlock child: node.getDomChildren()) {
+            for (SsaBasicBlock child : node.getDomChildren()) {
                 if (comma) {
                     sb.append(',');
                 }
@@ -164,20 +170,25 @@
             SsaBasicBlock nb = nodes.get(b);
             DomInfo nbInfo = domInfos[b];
             BitSet pred = nb.getPredecessors();
+
             if (pred.cardinality() > 1) {
                 for (int i = pred.nextSetBit(0); i >= 0;
                      i = pred.nextSetBit(i + 1)) {
 
-                    for(int runnerIndex = i
-                            ; runnerIndex != nbInfo.idom
-                            ;) {
-                        // We can stop if we hit a block we already
-                        // added label to, since we must be at a part
-                        // of the dom tree we have seen before.
+                    for (int runnerIndex = i;
+                         runnerIndex != nbInfo.idom; /* empty */) {
+                        /*
+                         * We can stop if we hit a block we already
+                         * added label to, since we must be at a part
+                         * of the dom tree we have seen before.
+                         */
                         DomInfo runnerInfo = domInfos[runnerIndex];
-                        if (runnerInfo.dominanceFrontiers.has(b))
+
+                        if (runnerInfo.dominanceFrontiers.has(b)) {
                             break;
-                        // "add b to runner's dominance frontier set"
+                        }
+
+                        // Add b to runner's dominance frontier set.
                         runnerInfo.dominanceFrontiers.add(b);
                         runnerIndex = runnerInfo.idom;
                     }
diff --git a/dx/src/com/android/dx/ssa/Dominators.java b/dx/src/com/android/dx/ssa/Dominators.java
index 1af2cbc..f7d7da6 100644
--- a/dx/src/com/android/dx/ssa/Dominators.java
+++ b/dx/src/com/android/dx/ssa/Dominators.java
@@ -41,31 +41,55 @@
  * rank to keep the union-find tree balanced.
  */
 public final class Dominators {
-    /* postdom is true if we want post dominators. */
-    private boolean postdom;
+    /* postdom is true if we want post dominators */
+    private final boolean postdom;
+
+    /* {@code non-null;} method being processed */
+    private final SsaMethod meth;
+
     /* Method's basic blocks. */
-    private ArrayList<SsaBasicBlock> blocks;
+    private final ArrayList<SsaBasicBlock> blocks;
 
-    private static final class DFSInfo {
-        int semidom;
-        SsaBasicBlock parent;
-        // rep(resentative) is known as "label" in the paper. It is the node
-        // that our block's DFS info has been unioned to.
-        SsaBasicBlock rep;
-        SsaBasicBlock ancestor;
-        ArrayList<SsaBasicBlock> bucket;
+    /** indexed by basic block index */
+    private final DFSInfo[] info;
 
-        public DFSInfo() {
-            bucket = new ArrayList<SsaBasicBlock>();
-        }
+    private final ArrayList<SsaBasicBlock> vertex;
 
+    /** {@code non-null;} the raw dominator info */
+    private final DomFront.DomInfo domInfos[];
+
+    /**
+     * Constructs an instance.
+     * 
+     * @param meth {@code non-null;} method to process
+     * @param domInfos {@code non-null;} the raw dominator info
+     * @param postdom true for postdom information, false for normal dom info
+     */
+    private Dominators(SsaMethod meth, DomFront.DomInfo[] domInfos,
+            boolean postdom) {
+        this.meth = meth;
+        this.domInfos = domInfos;
+        this.postdom = postdom;
+        this.blocks = meth.getBlocks();
+        this.info = new DFSInfo[blocks.size() + 2];
+        this.vertex = new ArrayList<SsaBasicBlock>();
     }
 
-    /** Indexed by basic block index */
-    private DFSInfo[] info;
-    private ArrayList<SsaBasicBlock> vertex;
+    /**
+     * Constructs a fully-initialized instance. (This method exists so as
+     * to avoid calling a large amount of code in the constructor.)
+     * 
+     * @param meth {@code non-null;} method to process
+     * @param domInfos {@code non-null;} the raw dominator info
+     * @param postdom true for postdom information, false for normal dom info
+     */
+    public static Dominators make(SsaMethod meth, DomFront.DomInfo[] domInfos,
+            boolean postdom) {
+        Dominators result = new Dominators(meth, domInfos, postdom);
 
-    private DomFront.DomInfo domInfos[];
+        result.run();
+        return result;
+    }
 
     private BitSet getSuccs(SsaBasicBlock block) {
         if (postdom) {
@@ -85,6 +109,7 @@
 
     /**
      * Performs path compress on the DFS info.
+     * 
      * @param in Basic block whose DFS info we are path compressing.
      */
     private void compress(SsaBasicBlock in) {
@@ -110,7 +135,7 @@
                 }
                 worklist.remove(wsize - 1);
 
-                // Update based on ancestor info
+                // Update based on ancestor info.
                 if (vabbInfo.ancestor == null) {
                     continue;
                 }
@@ -124,42 +149,25 @@
             }
         }
     }
+
     private SsaBasicBlock eval(SsaBasicBlock v) {
         DFSInfo bbInfo = info[v.getIndex()];
+
         if (bbInfo.ancestor == null) {
             return v;
         }
+
         compress(v);
         return bbInfo.rep;
     }
 
     /**
-     * Callback for depth-first walk through control flow graph (either
-     * from the entry block or the exit block). Records the traversal order
-     * in the <code>info</code>list.
+     * Performs dominator/post-dominator calculation for the control
+     * flow graph.
+     * 
+     * @param meth {@code non-null;} method to analyze
      */
-    private class DfsWalker implements SsaBasicBlock.Visitor {
-        int dfsNum = 0;
-
-        public void visitBlock (SsaBasicBlock v, SsaBasicBlock parent) {
-            DFSInfo bbInfo = new DFSInfo();
-            bbInfo.semidom = ++dfsNum;
-            bbInfo.rep = v;
-            bbInfo.parent = parent;
-            vertex.add(v);
-            info[v.getIndex()] = bbInfo;
-        }
-    }
-
-    /**
-     * Performs dominator/post-dominator calculation for the control flow graph.
-     * @param meth Method to analyze
-     */
-    public void run(SsaMethod meth) {
-
-        this.blocks = meth.getBlocks();
-        this.info = new DFSInfo[blocks.size() + 2];
-        this.vertex = new ArrayList<SsaBasicBlock>();
+    private void run() {
         SsaBasicBlock root = postdom
                 ? meth.getExitBlock() : meth.getEntryBlock();
 
@@ -168,8 +176,10 @@
             domInfos[root.getIndex()].idom = root.getIndex();
         }
         
-        // First we perform a DFS numbering of the blocks, by numbering the dfs
-        // tree roots
+        /*
+         * First we perform a DFS numbering of the blocks, by
+         * numbering the dfs tree roots.
+         */
 
         DfsWalker walker = new DfsWalker();
         meth.forEachBlockDepthFirst(postdom, walker);
@@ -184,12 +194,15 @@
 
             BitSet preds = getPreds(w);
             for (int j = preds.nextSetBit(0);
-                    j >= 0;
-                    j = preds.nextSetBit(j + 1)) {
+                 j >= 0;
+                 j = preds.nextSetBit(j + 1)) {
                 SsaBasicBlock predBlock = blocks.get(j);
                 DFSInfo predInfo = info[predBlock.getIndex()];
-                // PredInfo may not exist in case the predecessor is not
-                // reachable
+
+                /*
+                 * PredInfo may not exist in case the predecessor is
+                 * not reachable.
+                 */
                 if (predInfo != null) {
                     int predSemidom = info[eval(predBlock).getIndex()].semidom;
                     if (predSemidom < wInfo.semidom) {
@@ -199,11 +212,14 @@
             }
             info[vertex.get(wInfo.semidom).getIndex()].bucket.add(w);
 
-            // Normally we would call link here, but in our  m log n
-            // implementation this is equivalent to the following single line
+            /*
+             * Normally we would call link here, but in our O(m log n)
+             * implementation this is equivalent to the following
+             * single line.
+             */
             wInfo.ancestor = wInfo.parent;
 
-            // Implicity define idom for each vertex
+            // Implicity define idom for each vertex.
             ArrayList<SsaBasicBlock> wParentBucket;
             wParentBucket = info[wInfo.parent.getIndex()].bucket;
 
@@ -219,6 +235,7 @@
                 }
             }
         }
+
         // Now explicitly define the immediate dominator of each vertex
         for (int i =  2; i <= dfsMax; ++i) {
             SsaBasicBlock w = vertex.get(i);
@@ -231,10 +248,38 @@
     }
 
     /**
-     * @param postdom true for postdom information, false for normal dom info
+     * Callback for depth-first walk through control flow graph (either
+     * from the entry block or the exit block). Records the traversal order
+     * in the {@code info}list.
      */
-    public Dominators(DomFront.DomInfo[] domInfos, boolean postdom) {
-        this.domInfos = domInfos;
-        this.postdom = postdom;
+    private class DfsWalker implements SsaBasicBlock.Visitor {
+        private int dfsNum = 0;
+
+        public void visitBlock(SsaBasicBlock v, SsaBasicBlock parent) {
+            DFSInfo bbInfo = new DFSInfo();
+            bbInfo.semidom = ++dfsNum;
+            bbInfo.rep = v;
+            bbInfo.parent = parent;
+            vertex.add(v);
+            info[v.getIndex()] = bbInfo;
+        }
+    }
+
+    private static final class DFSInfo {
+        public int semidom;
+        public SsaBasicBlock parent;
+
+        /**
+         * rep(resentative) is known as "label" in the paper. It is the node
+         * that our block's DFS info has been unioned to.
+         */
+        public SsaBasicBlock rep;
+
+        public SsaBasicBlock ancestor;
+        public ArrayList<SsaBasicBlock> bucket;
+
+        public DFSInfo() {
+            bucket = new ArrayList<SsaBasicBlock>();
+        }
     }
 }
diff --git a/dx/src/com/android/dx/ssa/InterferenceRegisterMapper.java b/dx/src/com/android/dx/ssa/InterferenceRegisterMapper.java
index be678dd..392579d 100644
--- a/dx/src/com/android/dx/ssa/InterferenceRegisterMapper.java
+++ b/dx/src/com/android/dx/ssa/InterferenceRegisterMapper.java
@@ -33,7 +33,6 @@
  * have variable register widths/categories, and the new namespace does.
  */
 public class InterferenceRegisterMapper extends BasicRegisterMapper {
-
     /**
      * Array of interference sets. ArrayList is indexed by new namespace
      * and BitIntSet's are indexed by old namespace.  The list expands
@@ -45,16 +44,15 @@
      */
     private final ArrayList<BitIntSet> newRegInterference;
 
-    /**
-     * The interference graph for the old namespace
-     */
+    /** the interference graph for the old namespace */
     private final InterferenceGraph oldRegInterference;
 
     /**
-     * @param countOldRegisters number of registers in old namespace.
+     * Constructs an instance
+     * 
+     * @param countOldRegisters number of registers in old namespace
      */
-    public InterferenceRegisterMapper(
-            InterferenceGraph oldRegInterference,
+    public InterferenceRegisterMapper(InterferenceGraph oldRegInterference,
             int countOldRegisters) {
         super(countOldRegisters);
 
@@ -75,8 +73,8 @@
     }
 
     /**
-     * Checks to see if old namespace reg <code>oldReg</code> interferes
-     * with what currently maps to <code>newReg</code>.
+     * Checks to see if old namespace reg {@code oldReg} interferes
+     * with what currently maps to {@code newReg}.
      *
      * @param oldReg old namespace register
      * @param newReg new namespace register
@@ -101,10 +99,10 @@
     }
 
     /**
-     * Checks to see if old namespace reg <code>oldReg</code> interferes
-     * with what currently maps to <code>newReg</code>.
+     * Checks to see if old namespace reg {@code oldReg} interferes
+     * with what currently maps to {@code newReg}.
      *
-     * @param oldSpec non-null; old namespace register
+     * @param oldSpec {@code non-null;} old namespace register
      * @param newReg new namespace register
      * @return true if oldReg will interfere with newReg
      */
@@ -115,6 +113,7 @@
     /**
      * Adds a register's interference set to the interference list,
      * growing it if necessary.
+     * 
      * @param newReg register in new namespace
      * @param oldReg register in old namespace
      */
@@ -134,17 +133,17 @@
      * pinned to the specified new-namespace reg + category. Takes into
      * account the category of the old-namespace registers.
      *
-     * @param oldSpecs non-null; set of old-namespace regs
-     * @param newReg &gt;= 0 new-namespace register
-     * @param targetCategory 1 or 2; the number of adjacent new-namespace
+     * @param oldSpecs {@code non-null;} set of old-namespace regs
+     * @param newReg {@code >= 0;} new-namespace register
+     * @param targetCategory {@code 1..2;} the number of adjacent new-namespace
      * registers (starting at ropReg) to consider
      * @return true if any of the old-namespace register have been mapped
      * to the new-namespace register + category
      */
     public boolean areAnyPinned(RegisterSpecList oldSpecs,
             int newReg, int targetCategory) {
-
         int sz = oldSpecs.size();
+
         for (int i = 0; i < sz; i++) {
             RegisterSpec oldSpec = oldSpecs.get(i);
             int r = oldToNew(oldSpec.getReg());
@@ -159,6 +158,7 @@
                 return true;
             }
         }
+        
         return false;
     }
 }
diff --git a/dx/src/com/android/dx/ssa/LiteralOpUpgrader.java b/dx/src/com/android/dx/ssa/LiteralOpUpgrader.java
index ad10cd7..a70b5bb 100644
--- a/dx/src/com/android/dx/ssa/LiteralOpUpgrader.java
+++ b/dx/src/com/android/dx/ssa/LiteralOpUpgrader.java
@@ -42,7 +42,7 @@
     /**
      * Process a method.
      *
-     * @param ssaMethod non-null; method to process
+     * @param ssaMethod {@code non-null;} method to process
      */
     public static void process(SsaMethod ssaMethod) {
         LiteralOpUpgrader dc;
@@ -135,8 +135,8 @@
      *
      * TODO move this somewhere else.
      *
-     * @param insn non-null; an SsaInsn containing a PlainInsn
-     * @param newSources non-null; new sources list for new insn
+     * @param insn {@code non-null;} an SsaInsn containing a PlainInsn
+     * @param newSources {@code non-null;} new sources list for new insn
      * @param newOpcode A RegOp from {@link RegOps}
      */
     private void replacePlainInsn(NormalSsaInsn insn,
diff --git a/dx/src/com/android/dx/ssa/LocalVariableExtractor.java b/dx/src/com/android/dx/ssa/LocalVariableExtractor.java
index 21c306b..11d53cf 100644
--- a/dx/src/com/android/dx/ssa/LocalVariableExtractor.java
+++ b/dx/src/com/android/dx/ssa/LocalVariableExtractor.java
@@ -33,23 +33,23 @@
  * converted, and adapted through edge-splitting.
  */
 public class LocalVariableExtractor {
-    /** non-null; method being extracted from */
+    /** {@code non-null;} method being extracted from */
     private final SsaMethod method;
 
-    /** non-null; block list for the method */
+    /** {@code non-null;} block list for the method */
     private final ArrayList<SsaBasicBlock> blocks;
 
-    /** non-null; result in-progress */
+    /** {@code non-null;} result in-progress */
     private final LocalVariableInfo resultInfo;
 
-    /** non-null; work set indicating blocks needing to be processed */
+    /** {@code non-null;} work set indicating blocks needing to be processed */
     private final BitSet workSet;
 
     /**
      * Extracts out all the local variable information from the given method.
      *
-     * @param method non-null; the method to extract from
-     * @return non-null; the extracted information
+     * @param method {@code non-null;} the method to extract from
+     * @return {@code non-null;} the extracted information
      */
     public static LocalVariableInfo extract(SsaMethod method) {
         LocalVariableExtractor lve = new LocalVariableExtractor(method);
@@ -59,7 +59,7 @@
     /**
      * Constructs an instance. This method is private. Use {@link #extract}.
      *
-     * @param method non-null; the method to extract from
+     * @param method {@code non-null;} the method to extract from
      */
     private LocalVariableExtractor(SsaMethod method) {
         if (method == null) {
@@ -77,7 +77,7 @@
     /**
      * Does the extraction.
      *
-     * @return non-null; the extracted information
+     * @return {@code non-null;} the extracted information
      */
     private LocalVariableInfo doit() {
 
@@ -98,7 +98,7 @@
     /**
      * Processes a single block.
      *
-     * @param blockIndex &gt;= 0; block index of the block to process
+     * @param blockIndex {@code >= 0;} block index of the block to process
      */
     private void processBlock(int blockIndex) {
         RegisterSpecSet primaryState
diff --git a/dx/src/com/android/dx/ssa/LocalVariableInfo.java b/dx/src/com/android/dx/ssa/LocalVariableInfo.java
index f7c37d2..8845270 100644
--- a/dx/src/com/android/dx/ssa/LocalVariableInfo.java
+++ b/dx/src/com/android/dx/ssa/LocalVariableInfo.java
@@ -29,30 +29,30 @@
  * Stolen from {@link com.android.dx.rop.code.LocalVariableInfo}.
  */
 public class LocalVariableInfo         extends MutabilityControl {
-    /** &gt;= 0; the register count for the method */
+    /** {@code >= 0;} the register count for the method */
     private final int regCount;
 
     /**
-     * non-null; {@link com.android.dx.rop.code.RegisterSpecSet} to use when indicating a block
+     * {@code non-null;} {@link com.android.dx.rop.code.RegisterSpecSet} to use when indicating a block
      * that has no locals; it is empty and immutable but has an appropriate
      * max size for the method
      */
     private final RegisterSpecSet emptySet;
 
     /**
-     * non-null; array consisting of register sets representing the
+     * {@code non-null;} array consisting of register sets representing the
      * sets of variables already assigned upon entry to each block,
      * where array indices correspond to block indices
      */
     private final RegisterSpecSet[] blockStarts;
 
-    /** non-null; map from instructions to the variable each assigns */
+    /** {@code non-null;} map from instructions to the variable each assigns */
     private final HashMap<SsaInsn, RegisterSpec> insnAssignments;
 
     /**
      * Constructs an instance.
      *
-     * @param method non-null; the method being represented by this instance
+     * @param method {@code non-null;} the method being represented by this instance
      */
     public LocalVariableInfo(SsaMethod method) {
         if (method == null) {
@@ -74,8 +74,8 @@
      * Sets the register set associated with the start of the block with
      * the given index.
      *
-     * @param index &gt;= 0; the block index
-     * @param specs non-null; the register set to associate with the block
+     * @param index {@code >= 0;} the block index
+     * @param specs {@code non-null;} the register set to associate with the block
      */
     public void setStarts(int index, RegisterSpecSet specs) {
         throwIfImmutable();
@@ -99,12 +99,12 @@
      * merge the two sets and call {@link #setStarts} on the result of the
      * merge.
      *
-     * @param index &gt;= 0; the block index
-     * @param specs non-null; the register set to merge into the start set
+     * @param index {@code >= 0;} the block index
+     * @param specs {@code non-null;} the register set to merge into the start set
      * for the block
-     * @return <code>true</code> if the merge resulted in an actual change
+     * @return {@code true} if the merge resulted in an actual change
      * to the associated set (including storing one for the first time) or
-     * <code>false</code> if there was no change
+     * {@code false} if there was no change
      */
     public boolean mergeStarts(int index, RegisterSpecSet specs) {
         RegisterSpecSet start = getStarts0(index);
@@ -133,8 +133,8 @@
      * with the given index. This returns an empty set with the appropriate
      * max size if no set was associated with the block in question.
      *
-     * @param index &gt;= 0; the block index
-     * @return non-null; the associated register set
+     * @param index {@code >= 0;} the block index
+     * @return {@code non-null;} the associated register set
      */
     public RegisterSpecSet getStarts(int index) {
         RegisterSpecSet result = getStarts0(index);
@@ -145,10 +145,10 @@
     /**
      * Gets the register set associated with the start of the given
      * block. This is just convenient shorthand for
-     * <code>getStarts(block.getLabel())</code>.
+     * {@code getStarts(block.getLabel())}.
      *
-     * @param block non-null; the block in question
-     * @return non-null; the associated register set
+     * @param block {@code non-null;} the block in question
+     * @return {@code non-null;} the associated register set
      */
     public RegisterSpecSet getStarts(SsaBasicBlock block) {
         return getStarts(block.getIndex());
@@ -160,8 +160,8 @@
      * newly-allocated empty {@link RegisterSpecSet} of appropriate
      * max size if there is not yet any set associated with the block.
      *
-     * @param index &gt;= 0; the block index
-     * @return non-null; the associated register set
+     * @param index {@code >= 0;} the block index
+     * @return {@code non-null;} the associated register set
      */
     public RegisterSpecSet mutableCopyOfStarts(int index) {
         RegisterSpecSet result = getStarts0(index);
@@ -181,8 +181,8 @@
      * simple type and the one in the instruction can be an arbitrary
      * {@link com.android.dx.rop.type.TypeBearer} (such as a constant value).
      *
-     * @param insn non-null; the instruction in question
-     * @param spec non-null; the associated register spec
+     * @param insn {@code non-null;} the instruction in question
+     * @param spec {@code non-null;} the associated register spec
      */
     public void addAssignment(SsaInsn insn, RegisterSpec spec) {
         throwIfImmutable();
@@ -202,8 +202,8 @@
      * Gets the named register being assigned by the given instruction, if
      * previously stored in this instance.
      *
-     * @param insn non-null; instruction in question
-     * @return null-ok; the named register being assigned, if any
+     * @param insn {@code non-null;} instruction in question
+     * @return {@code null-ok;} the named register being assigned, if any
      */
     public RegisterSpec getAssignment(SsaInsn insn) {
         return insnAssignments.get(insn);
@@ -212,7 +212,7 @@
     /**
      * Gets the number of assignments recorded by this instance.
      *
-     * @return &gt;= 0; the number of assignments
+     * @return {@code >= 0;} the number of assignments
      */
     public int getAssignmentCount() {
         return insnAssignments.size();
@@ -236,8 +236,8 @@
      * Helper method, to get the starts for a index, throwing the
      * right exception for range problems.
      *
-     * @param index &gt;= 0; the block index
-     * @return null-ok; associated register set or <code>null</code> if there
+     * @param index {@code >= 0;} the block index
+     * @return {@code null-ok;} associated register set or {@code null} if there
      * is none
      */
     private RegisterSpecSet getStarts0(int index) {
diff --git a/dx/src/com/android/dx/ssa/MoveParamCombiner.java b/dx/src/com/android/dx/ssa/MoveParamCombiner.java
index a27aec5..352e3e6 100644
--- a/dx/src/com/android/dx/ssa/MoveParamCombiner.java
+++ b/dx/src/com/android/dx/ssa/MoveParamCombiner.java
@@ -143,8 +143,8 @@
      * Returns the parameter index associated with a move-param insn. Does
      * not verify that the insn is a move-param insn.
      *
-     * @param insn non-null; a move-param insn
-     * @return &gt;=0 parameter index
+     * @param insn {@code non-null;} a move-param insn
+     * @return {@code >=0;} parameter index
      */
     private int getParamIndex(NormalSsaInsn insn) {
         CstInsn cstInsn = (CstInsn)(insn.getOriginalRopInsn());
diff --git a/dx/src/com/android/dx/ssa/NormalSsaInsn.java b/dx/src/com/android/dx/ssa/NormalSsaInsn.java
index ad9315a..d3392ca 100644
--- a/dx/src/com/android/dx/ssa/NormalSsaInsn.java
+++ b/dx/src/com/android/dx/ssa/NormalSsaInsn.java
@@ -19,13 +19,10 @@
 import com.android.dx.rop.code.*;
 
 /**
- * A "normal" (non-phi) instruction in SSA form. Always wraps a ROP insn.
+ * A "normal" (non-phi) instruction in SSA form. Always wraps a rop insn.
  */
 public final class NormalSsaInsn extends SsaInsn implements Cloneable {
-
-    /**
-     * ROP insn that we're wrapping
-     */
+    /** {@code non-null;} rop insn that we're wrapping */
     private Insn insn;
 
     /**
@@ -35,21 +32,19 @@
      * @param block block that contains this insn
      */
     NormalSsaInsn(final Insn insn, final SsaBasicBlock block) {
-        super(block);
+        super(insn.getResult(), block);
         this.insn = insn;
-        this.result = insn.getResult();
     }
 
     /** {@inheritDoc} */
     @Override
     public final void mapSourceRegisters(RegisterMapper mapper) {
-
         RegisterSpecList oldSources = insn.getSources();
         RegisterSpecList newSources = mapper.map(oldSources);
 
         if (newSources != oldSources) {
-            insn = insn.withNewRegisters(result, newSources);
-            block.getParent().onSourcesChanged(this, oldSources);
+            insn = insn.withNewRegisters(getResult(), newSources);
+            getBlock().getParent().onSourcesChanged(this, oldSources);
         }
     }
 
@@ -57,7 +52,7 @@
      * Changes one of the insn's sources. New source should be of same type
      * and category.
      *
-     * @param index &gt;=0; index of source to change
+     * @param index {@code >=0;} index of source to change
      * @param newSpec spec for new source
      */
     public final void changeOneSource(int index, RegisterSpec newSpec) {
@@ -68,6 +63,7 @@
         for (int i = 0; i < sz; i++) {
             newSources.set(i, i == index ? newSpec : origSources.get(i));
         }
+        
         newSources.setImmutable();
 
         RegisterSpec origSpec = origSources.get(index);
@@ -76,10 +72,10 @@
              * If the register remains unchanged, we're only changing 
              * the type or local var name so don't update use list
              */
-            block.getParent().onSourceChanged(this, origSpec, newSpec);
+            getBlock().getParent().onSourceChanged(this, origSpec, newSpec);
         }
 
-        insn = insn.withNewRegisters(result, newSources);
+        insn = insn.withNewRegisters(getResult(), newSources);
     }
 
     /**
@@ -90,22 +86,24 @@
      */
     public final void setNewSources (RegisterSpecList newSources) {
         RegisterSpecList origSources = insn.getSources();
+
         if (origSources.size() != newSources.size()) {
             throw new RuntimeException("Sources counts don't match");
         }
 
-        insn = insn.withNewRegisters(result, newSources);
+        insn = insn.withNewRegisters(getResult(), newSources);
     }
 
     /** {@inheritDoc} */
     @Override
     public NormalSsaInsn clone() {
-        return (NormalSsaInsn)super.clone();
+        return (NormalSsaInsn) super.clone();
     }
 
     /**
-     * Like rop.Insn.getSources()
-     * @return null-ok; sources list
+     * Like rop.Insn.getSources().
+     * 
+     * @return {@code null-ok;} sources list
      */
     public RegisterSpecList getSources() {
         return insn.getSources();
@@ -119,7 +117,7 @@
     /** {@inheritDoc} */
     @Override
     public Insn toRopInsn() {
-        return insn.withNewRegisters(result,insn.getSources());
+        return insn.withNewRegisters(getResult(), insn.getSources());
     }
 
     /**
@@ -143,7 +141,7 @@
         if (insn.getOpcode().getOpcode() == RegOps.MARK_LOCAL) {
             assignment = insn.getSources().get(0);
         } else {
-            assignment = result;
+            assignment = getResult();
         }
 
         if (assignment == null) {
@@ -167,8 +165,9 @@
      */
     public void upgradeToLiteral() {
         RegisterSpecList oldSources = insn.getSources();
+
         insn = insn.withLastSourceLiteral();
-        block.getParent().onSourcesChanged(this, oldSources);
+        getBlock().getParent().onSourcesChanged(this, oldSources);
     }
 
     /**
@@ -210,7 +209,7 @@
     /**
      * {@inheritDoc}
      *
-     * TODO increase the scope of this.
+     * TODO: Increase the scope of this.
      */
     @Override
     public boolean hasSideEffect() {
@@ -221,7 +220,7 @@
         }
 
         boolean hasLocalSideEffect
-                = Optimizer.getPreserveLocals() && getLocalAssignment() != null;
+            = Optimizer.getPreserveLocals() && getLocalAssignment() != null;
 
         switch (opcode.getOpcode()) {
             case RegOps.MOVE_RESULT:
diff --git a/dx/src/com/android/dx/ssa/Optimizer.java b/dx/src/com/android/dx/ssa/Optimizer.java
index cee6d7b..c5f6dc9 100644
--- a/dx/src/com/android/dx/ssa/Optimizer.java
+++ b/dx/src/com/android/dx/ssa/Optimizer.java
@@ -48,7 +48,7 @@
     }
 
     /**
-     * @return non-null; translation advice
+     * @return {@code non-null;} translation advice
      */
     public static TranslationAdvice getAdvice() {
         return advice;
@@ -64,7 +64,7 @@
      * @param isStatic true if this method has no 'this' pointer argument.
      * @param inPreserveLocals true if local variable info should be preserved,
      * at the cost of some registers and insns
-     * @param inAdvice non-null; translation advice
+     * @param inAdvice {@code non-null;} translation advice
      * @return optimized method
      */
     public static RopMethod optimize(RopMethod rmeth, int paramWidth,
@@ -85,7 +85,7 @@
      * @param isStatic true if this method has no 'this' pointer argument.
      * @param inPreserveLocals true if local variable info should be preserved,
      * at the cost of some registers and insns
-     * @param inAdvice non-null; translation advice
+     * @param inAdvice {@code non-null;} translation advice
      * @param steps set of optional optimization steps to run
      * @return optimized method
      */
diff --git a/dx/src/com/android/dx/ssa/PhiInsn.java b/dx/src/com/android/dx/ssa/PhiInsn.java
index 1829133..64e85ac 100644
--- a/dx/src/com/android/dx/ssa/PhiInsn.java
+++ b/dx/src/com/android/dx/ssa/PhiInsn.java
@@ -30,67 +30,53 @@
  * conversion back to ROP form.
  */
 public final class PhiInsn extends SsaInsn {
+    /**
+     * result register. The original result register of the phi insn
+     * is needed during the renaming process after the new result
+     * register has already been chosen.
+     */
+    private final int ropResultReg;
 
     /**
-     * the original result register of the phi insn is needed during the
-     * renaming process after the new result register has already been chosen.
+     * {@code non-null;} operands of the instruction; built up by
+     * {@link #addPhiOperand}
      */
-    private int ropResultReg;
-    private ArrayList<Operand> operands = new ArrayList<Operand>();
+    private final ArrayList<Operand> operands = new ArrayList<Operand>();
+
+    /** {@code null-ok;} source registers; constructed lazily */
     private RegisterSpecList sources;
 
     /**
-     * A single phi operand, consiting of source register and block index
-     * for move.
-     */
-    class Operand {
-        RegisterSpec regSpec;
-        int blockIndex;
-        int ropLabel;       //mostly for debugging
-
-        Operand (final RegisterSpec regSpec, final int blockIndex,
-                final int ropLabel){
-            this.regSpec = regSpec;
-            this.blockIndex = blockIndex;
-            this.ropLabel = ropLabel;
-        }
-    }
-
-    public static interface Visitor {
-        public void visitPhiInsn(PhiInsn insn);
-    }
-
-    public PhiInsn clone() {
-        throw new UnsupportedOperationException("can't clone phi");
-    }
-
-    /**
      * Constructs a new phi insn with no operands.
+     * 
      * @param resultReg the result reg for this phi insn
      * @param block block containing this insn.
      */
-    PhiInsn(final RegisterSpec resultReg, final SsaBasicBlock block) {
-        super(block);
-        this.result = resultReg;
+    public PhiInsn(RegisterSpec resultReg, SsaBasicBlock block) {
+        super(resultReg, block);
         ropResultReg = resultReg.getReg();
     }
 
     /**
      * Makes a phi insn with a void result type.
+     * 
      * @param resultReg the result register for this phi insn.
      * @param block block containing this insn.
      */
-    PhiInsn(final int resultReg, final SsaBasicBlock block) {
-        super(block);
-
+    public PhiInsn(final int resultReg, final SsaBasicBlock block) {
         /*
-         * The type here is bogus: the type depends on the operand and
-         * will be derived later.
+         * The result type here is bogus: The type depends on the
+         * operand and will be derived later.
          */
-        this.result = RegisterSpec.make(resultReg, Type.VOID);
+        super(RegisterSpec.make(resultReg, Type.VOID), block);
         ropResultReg = resultReg;
     }
 
+    /** {@inheritDoc} */
+    public PhiInsn clone() {
+        throw new UnsupportedOperationException("can't clone phi");
+    }
+
     /**
      * Updates the TypeBearers of all the sources (phi operands) to be
      * the current TypeBearer of the register-defining instruction's result.
@@ -100,9 +86,8 @@
      *
      * @param ssaMeth method that contains this insn
      */
-    void updateSourcesToDefinitions(SsaMethod ssaMeth) {
-
-        for (Operand o: operands) {
+    public void updateSourcesToDefinitions(SsaMethod ssaMeth) {
+        for (Operand o : operands) {
             RegisterSpec def 
                 = ssaMeth.getDefinitionForRegister(
                     o.regSpec.getReg()).getResult();
@@ -116,37 +101,42 @@
     /**
      * Changes the result type. Used during phi type resolution
      *
-     * @param type non-null; new TypeBearer
-     * @param local null-ok; new local info, if available
+     * @param type {@code non-null;} new TypeBearer
+     * @param local {@code null-ok;} new local info, if available
      */
-    void changeResultType(TypeBearer type, LocalItem local) {
-        result = RegisterSpec.makeLocalOptional(result.getReg(), type, local);
+    public void changeResultType(TypeBearer type, LocalItem local) {
+        setResult(RegisterSpec.makeLocalOptional(
+                          getResult().getReg(), type, local));
     }
 
     /**
-     * @return the original rop-form result reg. Useful during renaming.
+     * Gets the original rop-form result reg. This is useful during renaming.
+     * 
+     * @return the original rop-form result reg
      */
-    int getRopResultReg() {
+    public int getRopResultReg() {
         return ropResultReg;
     }
 
     /**
-     * Add an operand to this phi instruction
+     * Adds an operand to this phi instruction.
+     * 
      * @param registerSpec register spec, including type and reg of operand
-     * @param predBlock Predecessor block to be associated with this operand
+     * @param predBlock predecessor block to be associated with this operand
      */
     public void addPhiOperand(RegisterSpec registerSpec,
             SsaBasicBlock predBlock) {
         operands.add(new Operand(registerSpec, predBlock.getIndex(),
                 predBlock.getRopLabel()));
         
-        // in case someone has already called getSources()
+        // Un-cache sources, in case someone has already called getSources().
         sources = null;
     }
 
     /**
      * Gets the index of the pred block associated with the RegisterSpec
      * at the particular getSources() index.
+     * 
      * @param sourcesIndex index of source in getSources()
      * @return block index
      */
@@ -157,7 +147,7 @@
     /**
      * {@inheritDoc}
      *
-     * Always returns null for <code>PhiInsn</code>s
+     * Always returns null for {@code PhiInsn}s.
      */
     @Override
     public Rop getOpcode() {
@@ -167,18 +157,17 @@
     /**
      * {@inheritDoc}
      *
-     * Always returns null for <code>PhiInsn</code>s
+     * Always returns null for {@code PhiInsn}s.
      */
     @Override
     public Insn getOriginalRopInsn() {
         return null;
     }
 
-
     /**
      * {@inheritDoc}
      *
-     * Always returns false for <code>PhiInsn</code>s
+     * Always returns false for {@code PhiInsn}s.
      */
     @Override
     public boolean canThrow() {
@@ -188,10 +177,10 @@
     /**
      * Gets sources. Constructed lazily from phi operand data structures and
      * then cached.
-     * @return sources list
+     * 
+     * @return {@code non-null;} sources list
      */
     public RegisterSpecList getSources() {
-
         if (sources != null) {
             return sources;
         }
@@ -219,10 +208,10 @@
     public boolean isRegASource(int reg) {
         /*
          * Avoid creating a sources list in case it has not already been
-         * created
+         * created.
          */
 
-        for (Operand o: operands) {
+        for (Operand o : operands) {
             if (o.regSpec.getReg() == reg) {
                 return true;
             }
@@ -236,12 +225,12 @@
      */
     public boolean areAllOperandsEqual() {
         if (operands.size() == 0 ) {
-            // this should never happen
+            // This should never happen.
             return true;
         }
 
         int firstReg = operands.get(0).regSpec.getReg();
-        for (Operand o: operands) {
+        for (Operand o : operands) {
             if (firstReg != o.regSpec.getReg()) {
                 return false;
             }
@@ -253,19 +242,20 @@
     /** {@inheritDoc} */
     @Override
     public final void mapSourceRegisters(RegisterMapper mapper) {
-        for (Operand o: operands) {
+        for (Operand o : operands) {
             RegisterSpec old = o.regSpec;
             o.regSpec = mapper.map(old);
             if (old != o.regSpec) {
-                block.getParent().onSourceChanged(this, old, o.regSpec);
+                getBlock().getParent().onSourceChanged(this, old, o.regSpec);
             }
         }
         sources = null;
     }
 
     /**
-     * Always throws an exeption, since
-     * a phi insn may not be converted back to rop form
+     * Always throws an exeption, since a phi insn may not be
+     * converted back to rop form.
+     * 
      * @return always throws exception
      */
     @Override
@@ -276,17 +266,16 @@
 
     /**
      * Returns the list of predecessor blocks associated with all operands
-     * that have <code>reg</code> as an operand register.
+     * that have {@code reg} as an operand register.
      *
      * @param reg register to look up
      * @param ssaMeth method we're operating on
-     * @return List of predecessor blocks, empty if none
+     * @return list of predecessor blocks, empty if none
      */
-    public List<SsaBasicBlock> predBlocksForReg (int reg, SsaMethod ssaMeth) {
-        ArrayList<SsaBasicBlock> ret 
-            = (ArrayList<SsaBasicBlock>)new ArrayList();
+    public List<SsaBasicBlock> predBlocksForReg(int reg, SsaMethod ssaMeth) {
+        ArrayList<SsaBasicBlock> ret = new ArrayList<SsaBasicBlock>();
 
-        for (Operand o: operands) {
+        for (Operand o : operands) {
             if (o.regSpec.getReg() == reg) {
                 ret.add(ssaMeth.getBlocks().get(o.blockIndex));
             }
@@ -297,12 +286,13 @@
 
     /** {@inheritDoc} */
     @Override
-    public  boolean isPhiOrMove() {
+    public boolean isPhiOrMove() {
         return true;    
     }
 
     /** {@inheritDoc} */
-    @Override public boolean hasSideEffect() {
+    @Override
+    public boolean hasSideEffect() {
         return Optimizer.getPreserveLocals() && getLocalAssignment() != null;
     }
 
@@ -312,25 +302,23 @@
         v.visitPhiInsn(this);
     }
 
-    /**
-     * @return human-readable string for listing dumps
-     */
+    /** {@inheritDoc} */
     public String toHuman() {
         return toHumanWithInline(null);
     }
 
     /**
-     * Returns human-readable string for listing dumps.
-     * Allows sub-classes to specify extra text
-     * @param extra null-ok; the argument to print after the opcode
+     * Returns human-readable string for listing dumps. This method
+     * allows sub-classes to specify extra text.
+     * 
+     * @param extra {@code null-ok;} the argument to print after the opcode
      * @return human-readable string for listing dumps
      */
     protected final String toHumanWithInline(String extra) {
         StringBuffer sb = new StringBuffer(80);
 
         sb.append(SourcePosition.NO_INFO);
-        sb.append(": ");
-        sb.append("phi");       
+        sb.append(": phi");       
 
         if (extra != null) {
             sb.append("(");
@@ -338,6 +326,8 @@
             sb.append(")");
         }
 
+        RegisterSpec result = getResult();
+        
         if (result == null) {
             sb.append(" .");
         } else {
@@ -361,4 +351,27 @@
 
         return sb.toString();
     }
+
+    /**
+     * A single phi operand, consiting of source register and block index
+     * for move.
+     */
+    private static class Operand {
+        public RegisterSpec regSpec;
+        public final int blockIndex;
+        public final int ropLabel;       // only used for debugging
+
+        public Operand(RegisterSpec regSpec, int blockIndex, int ropLabel) {
+            this.regSpec = regSpec;
+            this.blockIndex = blockIndex;
+            this.ropLabel = ropLabel;
+        }
+    }
+
+    /**
+     * Visitor interface for instances of this (outer) class.
+     */
+    public static interface Visitor {
+        public void visitPhiInsn(PhiInsn insn);
+    }
 }
diff --git a/dx/src/com/android/dx/ssa/RegisterMapper.java b/dx/src/com/android/dx/ssa/RegisterMapper.java
index 98503e2..1f45b42 100644
--- a/dx/src/com/android/dx/ssa/RegisterMapper.java
+++ b/dx/src/com/android/dx/ssa/RegisterMapper.java
@@ -21,13 +21,12 @@
 import com.android.dx.util.ToHuman;
 
 /**
- * Represents a mapping between two register numbering schemes.
- * Subclasses of this may be mutable, and as such the mapping provided is only
- * valid for the lifetime of the method call in which instances of this class
- * are passed.
+ * Represents a mapping between two register numbering schemes. 
+ * Subclasses of this may be mutable, and as such the mapping provided
+ * is only valid for the lifetime of the method call in which
+ * instances of this class are passed.
  */
 public abstract class RegisterMapper {
-
     /**
      * Gets the count of registers (really, the total register width, since
      * category width is counted) in the new namespace.
@@ -47,17 +46,16 @@
      * @return new mapped register list, or old if nothing has changed.
      */
     public final RegisterSpecList map(RegisterSpecList sources) {
-        RegisterSpecList newSources;
-
-        newSources = new RegisterSpecList(sources.size());
-
         int sz = sources.size();
+        RegisterSpecList newSources = new RegisterSpecList(sz);
+
         for (int i = 0; i < sz; i++) {
             newSources.set(i, map(sources.get(i)));
         }
 
         newSources.setImmutable();
-        // Return the old sources if nothing has changed
-        return newSources.equals(sources)? sources: newSources;
+
+        // Return the old sources if nothing has changed.
+        return newSources.equals(sources) ? sources : newSources;
     }
 }
diff --git a/dx/src/com/android/dx/ssa/SCCP.java b/dx/src/com/android/dx/ssa/SCCP.java
index 1d95da6..73e9b49 100644
--- a/dx/src/com/android/dx/ssa/SCCP.java
+++ b/dx/src/com/android/dx/ssa/SCCP.java
@@ -102,11 +102,11 @@
      */
     private void addUsersToWorklist(int reg, int latticeValue) {
         if (latticeValue == VARYING) {
-            for (SsaInsn insn: ssaMeth.getUseListForRegister(reg)) {
+            for (SsaInsn insn : ssaMeth.getUseListForRegister(reg)) {
                 varyingWorklist.add(insn);
             }
         } else {
-            for (SsaInsn insn: ssaMeth.getUseListForRegister(reg)) {
+            for (SsaInsn insn : ssaMeth.getUseListForRegister(reg)) {
                 ssaWorklist.add(insn);
             }
         }
@@ -137,9 +137,6 @@
         }
     }
     
-    private boolean setLatticeValueTo(int reg, int value) {
-        return setLatticeValueTo(reg, value, null);
-    }
     /**
      * Simulates a PHI node and set the lattice for the result
      * to the approriate value.
@@ -160,6 +157,7 @@
         int phiResultValue = TOP;
         Constant phiConstant = null;
         int sourceSize = sources.size();
+
         for (int i = 0; i < sourceSize; i++) {
             int predBlockIndex = insn.predBlockIndexForSourcesIndex(i);
             int sourceReg = sources.get(i).getReg();
@@ -194,7 +192,7 @@
      * @param block Block to visit
      */
     private void simulateBlock(SsaBasicBlock block) {
-        for (SsaInsn insn: block.getInsns()) {
+        for (SsaInsn insn : block.getInsns()) {
             if (insn instanceof PhiInsn) {
                 simulatePhi((PhiInsn) insn);
             } else {
@@ -464,7 +462,7 @@
              * Update the sources RegisterSpec's of all non-move uses.
              * These will be used in later steps.
              */
-            for(SsaInsn insn: ssaMeth.getUseListForRegister(reg)) {
+            for (SsaInsn insn : ssaMeth.getUseListForRegister(reg)) {
                 if (insn.isPhiOrMove()) {
                     continue;
                 }
@@ -478,7 +476,6 @@
                 RegisterSpec newSpec
                         = spec.withType((TypedConstant)latticeConstants[reg]);
 
-
                 nInsn.changeOneSource(index, newSpec);
             }
         }
diff --git a/dx/src/com/android/dx/ssa/SetFactory.java b/dx/src/com/android/dx/ssa/SetFactory.java
index f34d08d..92e965f 100644
--- a/dx/src/com/android/dx/ssa/SetFactory.java
+++ b/dx/src/com/android/dx/ssa/SetFactory.java
@@ -59,8 +59,8 @@
     /**
      * Make IntSet for the dominance-frontier sets.
      *
-     * @param szBlocks &gt;=0; count of basic blocks in method
-     * @return non-null; appropriate set
+     * @param szBlocks {@code >=0;} count of basic blocks in method
+     * @return {@code non-null;} appropriate set
      */
     /*package*/ static IntSet makeDomFrontSet(int szBlocks) {
         return szBlocks <= DOMFRONT_SET_THRESHOLD_SIZE
@@ -72,8 +72,8 @@
      * Make IntSet for the interference graph sets. Public because
      * InterferenceGraph is in another package.
      *
-     * @param countRegs &gt;=0; count of SSA registers used in method
-     * @return non-null; appropriate set
+     * @param countRegs {@code >=0;} count of SSA registers used in method
+     * @return {@code non-null;} appropriate set
      */
     public static IntSet makeInterferenceSet(int countRegs) {
         return countRegs <= INTERFERENCE_SET_THRESHOLD_SIZE
@@ -84,8 +84,8 @@
     /**
      * Make IntSet for register live in/out sets.
      *
-     * @param countRegs &gt;=0; count of SSA registers used in method
-     * @return non-null; appropriate set
+     * @param countRegs {@code >=0;} count of SSA registers used in method
+     * @return {@code non-null;} appropriate set
      */
     /*package*/ static IntSet makeLivenessSet(int countRegs) {
         return countRegs <= LIVENESS_SET_THRESHOLD_SIZE
diff --git a/dx/src/com/android/dx/ssa/SsaBasicBlock.java b/dx/src/com/android/dx/ssa/SsaBasicBlock.java
index 99ada7e..ab0e122 100644
--- a/dx/src/com/android/dx/ssa/SsaBasicBlock.java
+++ b/dx/src/com/android/dx/ssa/SsaBasicBlock.java
@@ -36,53 +36,80 @@
 import java.util.ArrayList;
 import java.util.BitSet;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
 
 /**
  * An SSA representation of a basic block.
  */
 public final class SsaBasicBlock {
-
-    /** non-null; insn list associated with this instance */
-    private ArrayList<SsaInsn> insns;
-    /** non-null; predecessor set (by block list index) */
-    private BitSet predecessors;
-    /** non-null; successor set (by block list index) */
-    private BitSet successors;
     /**
-     * non-null; ordered successor list
+     * {@code non-null;} comparator for instances of this class that
+     * just compares block labels
+     */
+    public static final Comparator<SsaBasicBlock> LABEL_COMPARATOR =
+        new LabelComparator();
+
+    /** {@code non-null;} insn list associated with this instance */
+    private ArrayList<SsaInsn> insns;
+
+    /** {@code non-null;} predecessor set (by block list index) */
+    private BitSet predecessors;
+
+    /** {@code non-null;} successor set (by block list index) */
+    private BitSet successors;
+
+    /**
+     * {@code non-null;} ordered successor list
      * (same block may be listed more than once)
      */
     private IntList successorList;
-    /** block list index of primary successor, or -1 for no primary successor */
+
+    /**
+     * block list index of primary successor, or {@code -1} for no primary
+     * successor
+     */
     private int primarySuccessor = -1;
+
     /** label of block in rop form */
     private int ropLabel;
-    /** non-null; method we belong to */
+
+    /** {@code non-null;} method we belong to */
     private SsaMethod parent;
+
     /** our index into parent.getBlock() */
     private int index;
+
     /** list of dom children */
     private final ArrayList<SsaBasicBlock> domChildren;
 
-    /** 
-     * The number of moves added to the end of the block during the
+    /**
+     * the number of moves added to the end of the block during the
      * phi-removal process. Retained for subsequent move scheduling.
      */
     private int movesFromPhisAtEnd = 0;
-    /** 
-     * The number of moves added to the beginning of the block during the
+
+    /**
+     * the number of moves added to the beginning of the block during the
      * phi-removal process. Retained for subsequent move scheduling.
      */
     private int movesFromPhisAtBeginning = 0;
 
-    /** null-ok; indexed by reg: the regs that are live-in at this block */
+    /**
+     * {@code null-ok;} indexed by reg: the regs that are live-in at
+     * this block
+     */
     private IntSet liveIn;
-    /** null-ok; indexed by reg: the regs that are live-out at this block */
+
+    /**
+     * {@code null-ok;} indexed by reg: the regs that are live-out at
+     * this block
+     */
     private IntSet liveOut;
 
     /**
-     * Create a new empty basic block
+     * Creates a new empty basic block.
+     *
      * @param basicBlockIndex index this block will have
      * @param ropLabel original rop-form label
      * @param parent method of this block
@@ -106,26 +133,20 @@
      *
      * @param rmeth original method
      * @param basicBlockIndex index this block will have
-     * @param parent method of this block
-     * predecessor set will be updated.
+     * @param parent method of this block predecessor set will be
+     * updated
      * @return new instance
      */
     public static SsaBasicBlock newFromRop(RopMethod rmeth,
             int basicBlockIndex, final SsaMethod parent) {
-
-        BasicBlockList ropBlocks;
-        SsaBasicBlock result;
-        InsnList ropInsns;
-        BasicBlock bb;
-
-        ropBlocks = rmeth.getBlocks();
-        bb = ropBlocks.get(basicBlockIndex);
-
-        result = new SsaBasicBlock(basicBlockIndex, bb.getLabel(), parent);
-
-        ropInsns = bb.getInsns();
+        BasicBlockList ropBlocks = rmeth.getBlocks();
+        BasicBlock bb = ropBlocks.get(basicBlockIndex);
+        SsaBasicBlock result =
+            new SsaBasicBlock(basicBlockIndex, bb.getLabel(), parent);
+        InsnList ropInsns = bb.getInsns();
 
         result.insns.ensureCapacity(ropInsns.size());
+
         for (int i = 0, sz = ropInsns.size() ; i < sz ; i++) {
             result.insns.add(new NormalSsaInsn (ropInsns.get(i), result));
         }
@@ -141,7 +162,6 @@
                 = SsaMethod.indexListFromLabelList(ropBlocks,
                     bb.getSuccessors());
 
-
         if (result.successorList.size() != 0) {
             int primarySuccessor = bb.getPrimarySuccessor();
 
@@ -156,18 +176,18 @@
      * Adds a basic block as a dom child for this block. Used when constructing
      * the dom tree.
      *
-     * @param child non-null; new dom child
+     * @param child {@code non-null;} new dom child
      */
-    void addDomChild(SsaBasicBlock child) {
+    public void addDomChild(SsaBasicBlock child) {
         domChildren.add(child);
     }
 
     /**
      * Gets the dom children for this node. Don't modify this list.
      *
-     * @return non-null; list of dom children
+     * @return {@code non-null;} list of dom children
      */
-    ArrayList<SsaBasicBlock> getDomChildren() {
+    public ArrayList<SsaBasicBlock> getDomChildren() {
         return domChildren;
     }
 
@@ -175,9 +195,9 @@
      * Adds a phi insn to the beginning of this block. The result type of
      * the phi will be set to void, to indicate that it's currently unknown.
      *
-     * @param reg &gt;=0 result reg
+     * @param reg {@code >=0;} result reg
      */
-    void addPhiInsnForReg(int reg) {
+    public void addPhiInsnForReg(int reg) {
         insns.add(0, new PhiInsn(reg, this));
     }
 
@@ -186,9 +206,9 @@
      * when the result type or local-association can be determined at phi
      * insert time.
      *
-     * @param resultSpec non-null; reg
+     * @param resultSpec {@code non-null;} reg
      */
-    void addPhiInsnForReg(RegisterSpec resultSpec) {
+    public void addPhiInsnForReg(RegisterSpec resultSpec) {
         insns.add(0, new PhiInsn(resultSpec, this));
     }
 
@@ -196,9 +216,9 @@
      * Adds an insn to the head of this basic block, just after any phi
      * insns.
      *
-     * @param insn non-null; rop-form insn to add
+     * @param insn {@code non-null;} rop-form insn to add
      */
-    void addInsnToHead(Insn insn) {
+    public void addInsnToHead(Insn insn) {
         SsaInsn newInsn = SsaInsn.makeFromRop(insn, this);
         insns.add(getCountPhiInsns(), newInsn);
         parent.onInsnAdded(newInsn);
@@ -208,9 +228,9 @@
      * Replaces the last insn in this block. The provided insn must have
      * some branchingness.
      *
-     * @param insn non-null; rop-form insn to add, which must branch.
+     * @param insn {@code non-null;} rop-form insn to add, which must branch.
      */
-    void replaceLastInsn(Insn insn) {
+    public void replaceLastInsn(Insn insn) {
         if (insn.getOpcode().getBranchingness() == Rop.BRANCH_NONE) {
             throw new IllegalArgumentException("last insn must branch");
         }
@@ -225,12 +245,13 @@
     }
 
     /**
-     * Visits each phi insn
-     * @param v callback
+     * Visits each phi insn.
+     *
+     * @param v {@code non-null;} the callback
      */
     public void forEachPhiInsn(PhiInsn.Visitor v) {
-
         int sz = insns.size();
+
         for (int i = 0; i < sz; i++) {
             SsaInsn insn = insns.get(i);
             if (insn instanceof PhiInsn) {
@@ -251,7 +272,7 @@
     public void removeAllPhiInsns() {
         /*
          * Presently we assume PhiInsn's are in a continuous
-         * block at the top of the list
+         * block at the top of the list.
          */
 
         insns.subList(0, getCountPhiInsns()).clear();
@@ -259,6 +280,7 @@
 
     /**
      * Gets the number of phi insns at the top of this basic block.
+     *
      * @return count of phi insns
      */
     private int getCountPhiInsns() {
@@ -276,15 +298,15 @@
     }
 
     /**
-     * @return non-null;the (mutable) instruction list for this block,
-     * with phi insns at the beginning.
+     * @return {@code non-null;} the (mutable) instruction list for this block,
+     * with phi insns at the beginning
      */
     public ArrayList<SsaInsn> getInsns() {
         return insns;
     }
 
     /**
-     * @return non-null; the (mutable) list of phi insns for this block
+     * @return {@code non-null;} the (mutable) list of phi insns for this block
      */
     public List<SsaInsn> getPhiInsns() {
         return insns.subList(0, getCountPhiInsns());
@@ -312,29 +334,30 @@
     }
 
     /**
-     * @return non-null;predecessors set, indexed by block index
+     * @return {@code non-null;} predecessors set, indexed by block index
      */
     public BitSet getPredecessors() {
         return predecessors;
     }
 
     /**
-     * @return non-null;successors set, indexed by block index
+     * @return {@code non-null;} successors set, indexed by block index
      */
     public BitSet getSuccessors() {
         return successors;
     }
 
     /**
-     * @return non-null;ordered successor list, containing block indicies
+     * @return {@code non-null;} ordered successor list, containing block
+     * indicies
      */
     public IntList getSuccessorList() {
         return successorList;
     }
 
     /**
-     * @return &gt;= -1; block index of primary successor or -1 if no
-     * primary successor.
+     * @return {@code >= -1;} block index of primary successor or
+     * {@code -1} if no primary successor
      */
     public int getPrimarySuccessorIndex() {
         return primarySuccessor;
@@ -348,7 +371,8 @@
     }
 
     /**
-     * @return null-ok; the primary successor block or null if there is none.
+     * @return {@code null-ok;} the primary successor block or {@code null}
+     * if there is none
      */
     public SsaBasicBlock getPrimarySuccessor() {
         if (primarySuccessor < 0) {
@@ -373,7 +397,7 @@
     }
 
     /**
-     * @return non-null; method that contains this block
+     * @return {@code non-null;} method that contains this block
      */
     public SsaMethod getParent() {
         return parent;
@@ -383,23 +407,23 @@
      * Inserts a new empty GOTO block as a predecessor to this block.
      * All previous predecessors will be predecessors to the new block.
      *
-     * @return non-null; an appropriately-constructed instance
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public SsaBasicBlock insertNewPredecessor() {
         SsaBasicBlock newPred = parent.makeNewGotoBlock();
 
-        // Update the new block
+        // Update the new block.
         newPred.predecessors = predecessors;
         newPred.successors.set(index) ;
         newPred.successorList.add(index);
         newPred.primarySuccessor = index;
 
 
-        // Update us
+        // Update us.
         predecessors = new BitSet(parent.getBlocks().size());
         predecessors.set(newPred.index);
 
-        // Update our (soon-to-be) old predecessors
+        // Update our (soon-to-be) old predecessors.
         for (int i = newPred.predecessors.nextSetBit(0); i >= 0;
                 i = newPred.predecessors.nextSetBit(i + 1)) {
 
@@ -412,15 +436,15 @@
     }
 
     /**
-     * Constructs and inserts a new empty GOTO block <code>Z</code> between
-     * this block (<code>A</code>) and a current successor block
-     * (<code>B</code>). The new block will replace B as A's successor and
+     * Constructs and inserts a new empty GOTO block {@code Z} between
+     * this block ({@code A}) and a current successor block
+     * ({@code B}). The new block will replace B as A's successor and
      * A as B's predecessor. A and B will no longer be directly connected.
      * If B is listed as a successor multiple times, all references
      * are replaced.
      *
      * @param other current successor (B)
-     * @return non-null; an appropriately-constructed instance
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public SsaBasicBlock insertNewSuccessor(SsaBasicBlock other) {
         SsaBasicBlock newSucc = parent.makeNewGotoBlock();
@@ -430,15 +454,15 @@
                     + " not successor of " + getRopLabelString());
         }
 
-        // Update the new block
+        // Update the new block.
         newSucc.predecessors.set(this.index);
         newSucc.successors.set(other.index) ;
         newSucc.successorList.add(other.index);
         newSucc.primarySuccessor = other.index;
 
-        // Update us
+        // Update us.
         for (int i = successorList.size() - 1 ;  i >= 0; i--) {
-            if(successorList.get(i) == other.index) {
+            if (successorList.get(i) == other.index) {
                 successorList.set(i, newSucc.index);
             }
         }
@@ -449,7 +473,7 @@
         successors.clear(other.index);
         successors.set(newSucc.index);
 
-        // Update "other"
+        // Update "other".
         other.predecessors.set(newSucc.index);
         other.predecessors.set(index, successors.get(other.index));
 
@@ -457,17 +481,18 @@
     }
 
     /**
-     * Replace an old successor with a new successor.
-     * Throws RuntimeException if oldIndex was not a successor.
+     * Replaces an old successor with a new successor. This will throw
+     * RuntimeException if {@code oldIndex} was not a successor.
+     *
      * @param oldIndex index of old successor block
-     * @param newIndex index of new successor block.
+     * @param newIndex index of new successor block
      */
     public void replaceSuccessor(int oldIndex, int newIndex) {
         if (oldIndex == newIndex) {
             return;
         }
 
-        // Update us
+        // Update us.
         successors.set(newIndex);
 
         if (primarySuccessor == oldIndex) {
@@ -475,17 +500,17 @@
         }
 
         for (int i = successorList.size() - 1 ;  i >= 0; i--) {
-            if(successorList.get(i) == oldIndex) {
+            if (successorList.get(i) == oldIndex) {
                 successorList.set(i, newIndex);
             }
         }
 
         successors.clear(oldIndex);
 
-        // Update new successor
+        // Update new successor.
         parent.getBlocks().get(newIndex).predecessors.set(index);
 
-        // Update old successor
+        // Update old successor.
         parent.getBlocks().get(oldIndex).predecessors.clear(index);
     }
 
@@ -495,7 +520,7 @@
      * is not an exit predecessor or is the exit block, this block does
      * nothing. For use by {@link com.android.dx.ssa.SsaMethod#makeExitBlock}
      *
-     * @param exitBlock non-null; exit block
+     * @param exitBlock {@code non-null;} exit block
      */
     public void exitBlockFixup(SsaBasicBlock exitBlock) {
         if (this == exitBlock) {
@@ -519,6 +544,7 @@
      * before the last instruction. If the result of the final instruction
      * is the source in question, then the move is placed at the beginning of
      * the primary successor block. This is for unversioned registers.
+     *
      * @param result move destination
      * @param source move source
      */
@@ -538,12 +564,13 @@
 
         if (lastInsn.getResult() != null || lastInsn.getSources().size() > 0) {
             /*
-             * The final insn in this block has a source or result register,
-             * and the moves we may need to place and schedule may interfere.
-             * We need to insert this instruction at the
-             * beginning of the primary successor block instead. We know
-             * this is safe, because when we edge-split earlier, we ensured
-             * that each successor has only us as a predecessor.
+             * The final insn in this block has a source or result
+             * register, and the moves we may need to place and
+             * schedule may interfere. We need to insert this
+             * instruction at the beginning of the primary successor
+             * block instead. We know this is safe, because when we
+             * edge-split earlier, we ensured that each successor has
+             * only us as a predecessor.
              */
 
             for (int i = successors.nextSetBit(0)
@@ -557,19 +584,14 @@
             }
         } else {
             /*
-             * We can safely add a move to the end of the block
-             * just before the last instruction because
-             * the final insn does not assign to anything.
+             * We can safely add a move to the end of the block just
+             * before the last instruction, because the final insn does
+             * not assign to anything.
              */
-
-            RegisterSpecList sources;
-            sources = RegisterSpecList.make(source);
-
-            NormalSsaInsn toAdd;
-
-            toAdd = new NormalSsaInsn(
-                        new PlainInsn(Rops.opMove(result.getType()),
-                                SourcePosition.NO_INFO, result, sources), this);
+            RegisterSpecList sources = RegisterSpecList.make(source);
+            NormalSsaInsn toAdd = new NormalSsaInsn(
+                    new PlainInsn(Rops.opMove(result.getType()),
+                            SourcePosition.NO_INFO, result, sources), this);
 
             insns.add(insns.size() - 1, toAdd);
 
@@ -578,28 +600,24 @@
     }
 
     /**
-     * Add a move instruction after the phi insn block.
+     * Adds a move instruction after the phi insn block.
+     *
      * @param result move destination
      * @param source move source
      */
     public void addMoveToBeginning (RegisterSpec result, RegisterSpec source) {
-               
         if (result.getReg() == source.getReg()) {
             // Sometimes we end up with no-op moves. Ignore them here.
             return;
         }
 
-        RegisterSpecList sources;
-        sources = RegisterSpecList.make(source);
-
-        NormalSsaInsn toAdd;
-
-        toAdd = new NormalSsaInsn(
-                    new PlainInsn(Rops.opMove(result.getType()),
-                            SourcePosition.NO_INFO, result, sources), this);
+        RegisterSpecList sources = RegisterSpecList.make(source);
+        NormalSsaInsn toAdd = new NormalSsaInsn(
+                new PlainInsn(Rops.opMove(result.getType()),
+                        SourcePosition.NO_INFO, result, sources), this);
 
         insns.add(getCountPhiInsns(), toAdd);
-        movesFromPhisAtBeginning++;        
+        movesFromPhisAtBeginning++;
     }
 
     /**
@@ -612,7 +630,7 @@
     private static void setRegsUsed (BitSet regsUsed, RegisterSpec rs) {
         regsUsed.set(rs.getReg());
         if (rs.getCategory() > 1) {
-            regsUsed.set(rs.getReg() + 1);            
+            regsUsed.set(rs.getReg() + 1);
         }
     }
 
@@ -638,14 +656,16 @@
      * reads of any register happen before writes to that register.
      * NOTE: caller is expected to returnSpareRegisters()!
      *
-     * TODO See Briggs, et al "Practical Improvements to the Construction and
+     * TODO: See Briggs, et al "Practical Improvements to the Construction and
      * Destruction of Static Single Assignment Form" section 5. a) This can
      * be done in three passes.
+     *
      * @param toSchedule List of instructions. Must consist only of moves.
      */
     private void scheduleUseBeforeAssigned(List<SsaInsn> toSchedule) {
         BitSet regsUsedAsSources = new BitSet(parent.getRegCount());
-        // TODO get rid of this
+
+        // TODO: Get rid of this.
         BitSet regsUsedAsResults = new BitSet(parent.getRegCount());
 
         int sz = toSchedule.size();
@@ -680,8 +700,10 @@
                 }
             }
 
-            // If we've made no progress in this iteration, there's a
-            // circular dependency.  Split it using the temp reg.
+            /*
+             * If we've made no progress in this iteration, there's a
+             * circular dependency. Split it using the temp reg.
+             */
             if (oldInsertPlace == insertPlace) {
 
                 SsaInsn insnToSplit = null;
@@ -694,43 +716,40 @@
                                 insn.getSources().get(0))) {
 
                         insnToSplit = insn;
-                        // We're going to split this insn--move it to the
-                        // front
+                        /*
+                         * We're going to split this insn; move it to the
+                         * front.
+                         */
                         Collections.swap(toSchedule, insertPlace, i);
                         break;
                     }
                 }
 
-                // At least one insn will be set above
+                // At least one insn will be set above.
 
                 RegisterSpec result = insnToSplit.getResult();
                 RegisterSpec tempSpec = result.withReg(
                         parent.borrowSpareRegister(result.getCategory()));
 
-                NormalSsaInsn toAdd;
-
-                toAdd = new NormalSsaInsn(
-                            new PlainInsn(Rops.opMove(result.getType()),
-                                    SourcePosition.NO_INFO,
-                                    tempSpec,
-                                    insnToSplit.getSources()), this);
+                NormalSsaInsn toAdd = new NormalSsaInsn(
+                        new PlainInsn(Rops.opMove(result.getType()),
+                                SourcePosition.NO_INFO,
+                                tempSpec,
+                                insnToSplit.getSources()), this);
 
                 toSchedule.add(insertPlace++, toAdd);
 
-                NormalSsaInsn toReplace;
-                RegisterSpecList newSources;
+                RegisterSpecList newSources = RegisterSpecList.make(tempSpec);
 
-                newSources = RegisterSpecList.make(tempSpec);
-
-                toReplace = new NormalSsaInsn(
-                            new PlainInsn(Rops.opMove(result.getType()),
-                                    SourcePosition.NO_INFO,
-                                    result,
-                                    newSources), this);
+                NormalSsaInsn toReplace = new NormalSsaInsn(
+                        new PlainInsn(Rops.opMove(result.getType()),
+                                SourcePosition.NO_INFO,
+                                result,
+                                newSources), this);
 
                 toSchedule.set(insertPlace, toReplace);
 
-                // size has changed
+                // The size changed.
                 sz = toSchedule.size();
             }
 
@@ -740,12 +759,12 @@
     }
 
     /**
-     * Adds regV to the live-out list for this block.
-     * Called by the liveness analyzer.
+     * Adds {@code regV} to the live-out list for this block. This is called
+     * by the liveness analyzer.
+     *
      * @param regV register that is live-out for this block.
      */
-    public void
-    addLiveOut (int regV) {
+    public void addLiveOut (int regV) {
         if (liveOut == null) {
             liveOut = SetFactory.makeLivenessSet(parent.getRegCount());
         }
@@ -754,24 +773,24 @@
     }
 
     /**
-     * Adds regV to the live-in list for this block.
-     * Called by the liveness analyzer.
+     * Adds {@code regV} to the live-in list for this block. This is
+     * called by the liveness analyzer.
+     *
      * @param regV register that is live-in for this block.
      */
-    public void
-    addLiveIn (int regV) {
+    public void addLiveIn (int regV) {
         if (liveIn == null) {
             liveIn = SetFactory.makeLivenessSet(parent.getRegCount());
         }
 
-        liveIn.add(regV);       
+        liveIn.add(regV);
     }
 
     /**
      * Returns the set of live-in registers. Valid after register
      * interference graph has been generated, otherwise empty.
      *
-     * @return non-null; live-in register set.
+     * @return {@code non-null;} live-in register set.
      */
     public IntSet getLiveInRegs() {
         if (liveIn == null) {
@@ -783,8 +802,8 @@
     /**
      * Returns the set of live-out registers. Valid after register
      * interference graph has been generated, otherwise empty.
-     * 
-     * @return non-null; live-out register set.
+     *
+     * @return {@code non-null;} live-out register set
      */
     public IntSet getLiveOutRegs() {
         if (liveOut == null) {
@@ -806,15 +825,15 @@
      * that it's either the start block or it has predecessors, which suffices
      * for all current control flow transformations.
      *
-     * @return true if reachable
+     * @return {@code true} if reachable
      */
     public boolean isReachable() {
         return index == parent.getEntryBlockIndex()
                 || predecessors.cardinality() > 0;
     }
-        
+
     /**
-     * Sorts move instructions added via <code>addMoveToEnd</code> during
+     * Sorts move instructions added via {@code addMoveToEnd} during
      * phi removal so that results don't overwrite sources that are used.
      * For use after all phis have been removed and all calls to
      * addMoveToEnd() have been made.<p>
@@ -825,7 +844,6 @@
      * refers value before any other phis have executed.
      */
     public void scheduleMovesFromPhis() {
-
         if (movesFromPhisAtBeginning > 1) {
             List<SsaInsn> toSchedule;
 
@@ -835,32 +853,37 @@
 
             SsaInsn firstNonPhiMoveInsn = insns.get(movesFromPhisAtBeginning);
 
-            //TODO it's actually possible that this case never happens,
-            //because a move-exception block, having only one predecessor
-            //in SSA form, perhaps is never on a dominance frontier.
+            /*
+             * TODO: It's actually possible that this case never happens,
+             * because a move-exception block, having only one predecessor
+             * in SSA form, perhaps is never on a dominance frontier.
+             */
             if (firstNonPhiMoveInsn.isMoveException()) {
                 if (true) {
                     /*
                      * We've yet to observe this case, and if it can
-                     * occur the code written to handle it probably 
+                     * occur the code written to handle it probably
                      * does not work.
                      */
                     throw new RuntimeException(
                             "Unexpected: moves from "
                                     +"phis before move-exception");
                 } else {
-
-                    // A move-exception insn must be placed first in this block
-                    // We need to move it there, and deal with possible
-                    // interference.
+                    /*
+                     * A move-exception insn must be placed first in this block
+                     * We need to move it there, and deal with possible
+                     * interference.
+                     */
                     boolean moveExceptionInterferes = false;
 
                     int moveExceptionResult
                             = firstNonPhiMoveInsn.getResult().getReg();
 
-                    // Does the move-exception result reg interfere with the
-                    // phi moves?
-                    for(SsaInsn insn: toSchedule) {
+                    /*
+                     * Does the move-exception result reg interfere with the
+                     * phi moves?
+                     */
+                    for (SsaInsn insn : toSchedule) {
                         if (insn.isResultReg(moveExceptionResult)
                                 || insn.isRegASource(moveExceptionResult)) {
                             moveExceptionInterferes = true;
@@ -869,81 +892,107 @@
                     }
 
                     if (!moveExceptionInterferes) {
-                        // The easy case
+                        // This is the easy case.
                         insns.remove(movesFromPhisAtBeginning);
                         insns.add(0, firstNonPhiMoveInsn);
                     } else {
-                        // We need to move the result to a spare reg and move it
-                        // back.
-
-                        int spareRegister;
-                        RegisterSpec originalResultSpec;
-
-                        originalResultSpec = firstNonPhiMoveInsn.getResult();
-                        spareRegister = parent.borrowSpareRegister(
+                        /*
+                         * We need to move the result to a spare reg
+                         * and move it back.
+                         */
+                        RegisterSpec originalResultSpec
+                            = firstNonPhiMoveInsn.getResult();
+                        int spareRegister = parent.borrowSpareRegister(
                                 originalResultSpec.getCategory());
 
-                        // We now move it to a spare register
+                        // We now move it to a spare register.
                         firstNonPhiMoveInsn.changeResultReg(spareRegister);
-                        RegisterSpec tempSpec = firstNonPhiMoveInsn.getResult();
+                        RegisterSpec tempSpec =
+                            firstNonPhiMoveInsn.getResult();
 
                         insns.add(0, firstNonPhiMoveInsn);
 
-                        // And here we move it back
+                        // And here we move it back.
 
-                        NormalSsaInsn toAdd;
-
-                        toAdd = new NormalSsaInsn(
-                                    new PlainInsn(Rops.opMove(
-                                            tempSpec.getType()),
-                                            SourcePosition.NO_INFO,
-                                            originalResultSpec,
-                                            RegisterSpecList.make(tempSpec)),
+                        NormalSsaInsn toAdd = new NormalSsaInsn(
+                                new PlainInsn(
+                                        Rops.opMove(tempSpec.getType()),
+                                        SourcePosition.NO_INFO,
+                                        originalResultSpec,
+                                        RegisterSpecList.make(tempSpec)),
                                 this);
 
 
-                        // Place it immediately after the phi-moves,
-                        // overwriting the move-exception that was there.
+                        /*
+                         * Place it immediately after the phi-moves,
+                         * overwriting the move-exception that was there.
+                         */
                         insns.set(movesFromPhisAtBeginning + 1, toAdd);
                     }
                 }
             }
         }
+
         if (movesFromPhisAtEnd > 1) {
             scheduleUseBeforeAssigned(
                     insns.subList(insns.size() - movesFromPhisAtEnd - 1,
                                 insns.size() - 1));
         }
 
-        // Return registers borrowed here and in scheduleUseBeforeAssigned()
+        // Return registers borrowed here and in scheduleUseBeforeAssigned().
         parent.returnSpareRegisters();
 
     }
 
     /**
-     * Visit all insns in this block
-     * @param visitor callback interface
+     * Visits all insns in this block.
+     *
+     * @param visitor {@code non-null;} callback interface
      */
     public void forEachInsn(SsaInsn.Visitor visitor) {
-        for (SsaInsn insn: insns) {
-            insn.accept(visitor);
+        // This gets called a LOT, and not using an iterator
+        // saves a lot of allocations and reduces memory usage
+        int len = insns.size();
+        for (int i = 0; i < len; i++) {
+            insns.get(i).accept(visitor);
         }
     }
 
+    /** {@inheritDoc} */
     public String toString() {
         return "{" + index + ":" + Hex.u2(ropLabel) + '}';
     }
 
     /**
-     * Visitor interface for basic blocks
+     * Visitor interface for basic blocks.
      */
     public interface Visitor {
-
         /**
          * Indicates a block has been visited by an iterator method.
-         * @param v non-null; block visited
-         * @param parent null-ok; parent node if applicable.
+         *
+         * @param v {@code non-null;} block visited
+         * @param parent {@code null-ok;} parent node if applicable
          */
         void visitBlock (SsaBasicBlock v, SsaBasicBlock parent);
     }
+
+    /**
+     * Label comparator.
+     */
+    public static final class LabelComparator
+            implements Comparator<SsaBasicBlock> {
+        /** {@inheritDoc} */
+        public int compare(SsaBasicBlock b1, SsaBasicBlock b2) {
+            int label1 = b1.ropLabel;
+            int label2 = b2.ropLabel;
+
+            if (label1 < label2) {
+                return -1;
+            } else if (label1 > label2) {
+                return 1;
+            } else {
+                return 0;
+            }
+        }
+    }
 }
diff --git a/dx/src/com/android/dx/ssa/SsaConverter.java b/dx/src/com/android/dx/ssa/SsaConverter.java
index a731fcb..d5be287 100644
--- a/dx/src/com/android/dx/ssa/SsaConverter.java
+++ b/dx/src/com/android/dx/ssa/SsaConverter.java
@@ -27,22 +27,23 @@
  * Converts ROP methods to SSA Methods
  */
 public class SsaConverter {
-    public static boolean DEBUG = false;
+    public static final boolean DEBUG = false;
 
     /**
-     * returns an SSA representation, edge-split and with phi functions placed
+     * Returns an SSA representation, edge-split and with phi
+     * functions placed.
+     *
      * @param rmeth input
      * @param paramWidth the total width, in register-units, of the method's
      * parameters
-     * @param isStatic true if this method has no 'this'
+     * @param isStatic {@code true} if this method has no {@code this}
      * pointer argument
      * @return output in SSA form
      */
-    public static SsaMethod convertToSsaMethod(RopMethod rmeth, 
+    public static SsaMethod convertToSsaMethod(RopMethod rmeth,
             int paramWidth, boolean isStatic) {
-        SsaMethod result;
-
-        result = SsaMethod.newFromRopMethod(rmeth, paramWidth, isStatic);
+        SsaMethod result
+            = SsaMethod.newFromRopMethod(rmeth, paramWidth, isStatic);
 
         edgeSplit(result);
 
@@ -52,7 +53,7 @@
         new SsaRenamer(result).run();
 
         /*
-         * Exit block, added here,  is not considered for edge splitting
+         * The exit block, added here, is not considered for edge splitting
          * or phi placement since no actual control flows to it.
          */
         result.makeExitBlock();
@@ -62,10 +63,12 @@
 
     /**
      * Returns an SSA represention with only the edge-splitter run.
+     *
      * @param rmeth method to process
      * @param paramWidth width of all arguments in the method
-     * @param isStatic true if this method has no 'this' pointer argument
-     * @return an SSA represention with only the edge-splitter run.
+     * @param isStatic {@code true} if this method has no {@code this}
+     * pointer argument
+     * @return an SSA represention with only the edge-splitter run
      */
     public static SsaMethod testEdgeSplit (RopMethod rmeth, int paramWidth,
             boolean isStatic) {
@@ -80,10 +83,12 @@
     /**
      * Returns an SSA represention with only the steps through the
      * phi placement run.
+     *
      * @param rmeth method to process
      * @param paramWidth width of all arguments in the method
-     * @param isStatic true if this method has no 'this' pointer argument
-     * @return an SSA represention with only the edge-splitter run.
+     * @param isStatic {@code true} if this method has no {@code this}
+     * pointer argument
+     * @return an SSA represention with only the edge-splitter run
      */
     public static SsaMethod testPhiPlacement (RopMethod rmeth, int paramWidth,
             boolean isStatic) {
@@ -100,7 +105,8 @@
     }
 
     /**
-     * See Appel section 19.1
+     * See Appel section 19.1:
+     *
      * Converts CFG into "edge-split" form, such that each node either a
      * unique successor or unique predecessor.<p>
      *
@@ -109,11 +115,10 @@
      * value to have a primary successor that has no other
      * predecessor. This ensures move statements can always be
      * inserted correctly when phi statements are removed.
-     * 
+     *
      * @param result method to process
      */
     private static void edgeSplit(SsaMethod result) {
-
         edgeSplitPredecessors(result);
         edgeSplitMoveExceptionsAndResults(result);
         edgeSplitSuccessors(result);
@@ -122,13 +127,16 @@
     /**
      * Inserts Z nodes as new predecessors for every node that has multiple
      * successors and multiple predecessors.
-     * @param result non-null; method to process
+     *
+     * @param result {@code non-null;} method to process
      */
     private static void edgeSplitPredecessors(SsaMethod result) {
         ArrayList<SsaBasicBlock> blocks = result.getBlocks();
-        
-        // New blocks are added to the end of the block list during
-        // this iteration
+
+        /*
+         * New blocks are added to the end of the block list during
+         * this iteration.
+         */
         for (int i = blocks.size() - 1; i >= 0; i-- ) {
             SsaBasicBlock block = blocks.get(i);
             if (nodeNeedsUniquePredecessor(block)) {
@@ -138,12 +146,11 @@
     }
 
     /**
-     * @param block non-null; block in question
-     * @return true if this node needs to have a unique predecessor created for
-     * it.
+     * @param block {@code non-null;} block in question
+     * @return {@code true} if this node needs to have a unique
+     * predecessor created for it
      */
     private static boolean nodeNeedsUniquePredecessor(SsaBasicBlock block) {
-
         /*
          * Any block with that has both multiple successors and multiple
          * predecessors needs a new predecessor node.
@@ -161,59 +168,68 @@
      * We may need room to insert move insns later, so make sure to split
      * any block that starts with a move-exception such that there is a
      * unique move-exception block for each predecessor.
+     *
      * @param ssaMeth method to process
      */
     private static void edgeSplitMoveExceptionsAndResults(SsaMethod ssaMeth) {
         ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks();
 
-        // New blocks are added to the end of the block list during
-        // this iteration
+        /*
+         * New blocks are added to the end of the block list during
+         * this iteration.
+         */
         for (int i = blocks.size() - 1; i >= 0; i-- ) {
             SsaBasicBlock block = blocks.get(i);
-        
-            // Any block that starts with a move-exception and has more than
-            // one predecessor...
+
+            /*
+             * Any block that starts with a move-exception and has more than
+             * one predecessor...
+             */
             if (!block.isExitBlock()
-                    && block.getPredecessors().cardinality() > 1 
+                    && block.getPredecessors().cardinality() > 1
                     && block.getInsns().get(0).isMoveException()) {
 
-                // block.getPredecessors() is changed in the loop below
+                // block.getPredecessors() is changed in the loop below.
                 BitSet preds = (BitSet)block.getPredecessors().clone();
                 for (int j = preds.nextSetBit(0); j >= 0;
-                        j = preds.nextSetBit(j + 1)) {
-
+                     j = preds.nextSetBit(j + 1)) {
                     SsaBasicBlock predecessor = blocks.get(j);
+                    SsaBasicBlock zNode
+                        = predecessor.insertNewSuccessor(block);
 
-                    SsaBasicBlock zNode = predecessor.insertNewSuccessor(block);
-
-                    // Make sure to place the move-exception as the
-                    // first insn...
+                    /*
+                     * Make sure to place the move-exception as the
+                     * first insn.
+                     */
                     zNode.getInsns().add(0, block.getInsns().get(0).clone());
                 }
 
-                // remove the move-exception from the original block...
+                // Remove the move-exception from the original block.
                 block.getInsns().remove(0);
             }
         }
     }
 
     /**
-     * Inserts Z nodes for every node that needs a new 
+     * Inserts Z nodes for every node that needs a new
      * successor.
-     * @param result non-null; method to process
+     *
+     * @param result {@code non-null;} method to process
      */
     private static void edgeSplitSuccessors(SsaMethod result) {
         ArrayList<SsaBasicBlock> blocks = result.getBlocks();
 
-        // New blocks are added to the end of the block list during
-        // this iteration
+        /*
+         * New blocks are added to the end of the block list during
+         * this iteration.
+         */
         for (int i = blocks.size() - 1; i >= 0; i-- ) {
             SsaBasicBlock block = blocks.get(i);
 
-            // successors list is modified in loop below
+            // Successors list is modified in loop below.
             BitSet successors = (BitSet)block.getSuccessors().clone();
-            for(int j = successors.nextSetBit(0);
-                    j >= 0; j = successors.nextSetBit(j+1)) {
+            for (int j = successors.nextSetBit(0);
+                 j >= 0; j = successors.nextSetBit(j+1)) {
 
                 SsaBasicBlock succ = blocks.get(j);
 
@@ -225,17 +241,17 @@
     }
 
     /**
-     * Returns true if block and successor need a Z-node between them.
-     * Presently, this is true if the final instruction has any sources
-     * or results and the current successor block has more than one
-     * predecessor.
+     * Returns {@code true} if block and successor need a Z-node
+     * between them. Presently, this is {@code true} if the final
+     * instruction has any sources or results and the current
+     * successor block has more than one predecessor.
+     *
      * @param block predecessor node
      * @param succ successor node
-     * @return true if a Z node is needed
+     * @return {@code true} if a Z node is needed
      */
     private static boolean needsNewSuccessor(SsaBasicBlock block,
             SsaBasicBlock succ) {
-
         ArrayList<SsaInsn> insns = block.getInsns();
         SsaInsn lastInsn = insns.get(insns.size() - 1);
 
@@ -245,11 +261,14 @@
     }
 
     /**
-     * See Appel algorithm 19.6
+     * See Appel algorithm 19.6:
+     *
      * Place Phi functions in appropriate locations.
      *
-     * @param ssaMeth non-null; method to process. Modifications made in-place
-     * @param localInfo non-null; Local variable info, used when placing phis
+     * @param ssaMeth {@code non-null;} method to process.
+     * Modifications are made in-place.
+     * @param localInfo {@code non-null;} local variable info, used
+     * when placing phis
      */
     private static void placePhiFunctions (SsaMethod ssaMeth,
             LocalVariableInfo localInfo) {
@@ -282,8 +301,7 @@
         for (int bi = 0, s = ssaBlocks.size(); bi < s; bi++) {
             SsaBasicBlock b = ssaBlocks.get(bi);
 
-            for (SsaInsn insn: b.getInsns()) {
-
+            for (SsaInsn insn : b.getInsns()) {
                 RegisterSpec rs = insn.getResult();
 
                 if (rs != null) {
@@ -297,11 +315,8 @@
 
             for (int i = 0; i < regCount; i++) {
                 StringBuilder sb = new StringBuilder();
-
                 sb.append('v').append(i).append(": ");
-
                 sb.append(defsites[i].toString());
-
                 System.out.println(sb);
             }
         }
@@ -315,15 +330,14 @@
         for (int reg = 0, s = ssaMeth.getRegCount() ; reg < s ; reg++ ) {
             int workBlockIndex;
 
-            /* Worklist set starts out with each node where reg is assigned */
+            /* Worklist set starts out with each node where reg is assigned. */
 
-            worklist = (BitSet)(defsites[reg].clone());
+            worklist = (BitSet) (defsites[reg].clone());
 
             while (0 <= (workBlockIndex = worklist.nextSetBit(0))) {
                 worklist.clear(workBlockIndex);
                 IntIterator dfIterator
-                        = domInfos[workBlockIndex]
-                        .dominanceFrontiers.iterator();
+                    = domInfos[workBlockIndex].dominanceFrontiers.iterator();
 
                 while (dfIterator.hasNext()) {
                     int dfBlockIndex = dfIterator.next();
@@ -353,11 +367,8 @@
 
             for (int i = 0; i < regCount; i++) {
                 StringBuilder sb = new StringBuilder();
-
                 sb.append('v').append(i).append(": ");
-
                 sb.append(phisites[i].toString());
-
                 System.out.println(sb);
             }
         }
diff --git a/dx/src/com/android/dx/ssa/SsaInsn.java b/dx/src/com/android/dx/ssa/SsaInsn.java
index d9e33a0..815f82d 100644
--- a/dx/src/com/android/dx/ssa/SsaInsn.java
+++ b/dx/src/com/android/dx/ssa/SsaInsn.java
@@ -23,24 +23,34 @@
  * An instruction in SSA form
  */
 public abstract class SsaInsn implements ToHuman, Cloneable {
+    /** {@code non-null;} the block that contains this instance */
+    private final SsaBasicBlock block;
 
-    protected RegisterSpec result;
-    protected final SsaBasicBlock block;
+    /** {@code null-ok;} result register */
+    private RegisterSpec result;
 
     /**
-     * Constructs an instance
-     * @param block block containing this insn. Can never change.
+     * Constructs an instance.
+     * 
+     * @param result {@code null-ok;} initial result register. May be changed.
+     * @param block {@code non-null;} block containing this insn. Can
+     * never change.
      */
-    protected SsaInsn(final SsaBasicBlock block) {
+    protected SsaInsn(RegisterSpec result, SsaBasicBlock block) {
+        if (block == null) {
+            throw new NullPointerException("block == null");
+        }
+
         this.block = block;
+        this.result = result;
     }
 
     /**
-     * Makes a new SSA insn form a ROP insn
+     * Makes a new SSA insn form a rop insn.
      *
-     * @param insn non-null; rop insn
-     * @param block non-null; owning block
-     * @return non-null; an appropriately constructed instance
+     * @param insn {@code non-null;} rop insn
+     * @param block {@code non-null;} owning block
+     * @return {@code non-null;} an appropriately constructed instance
      */
     public static SsaInsn makeFromRop(Insn insn, SsaBasicBlock block) {
         return new NormalSsaInsn(insn, block);
@@ -58,6 +68,7 @@
 
     /**
      * Like {@link com.android.dx.rop.code.Insn getResult()}.
+     * 
      * @return result register
      */
     public RegisterSpec getResult() {
@@ -65,8 +76,22 @@
     }
 
     /**
+     * Set the result register.
+     * 
+     * @param result {@code non-null;} the new result register
+     */
+    protected void setResult(RegisterSpec result) {
+        if (result == null) {
+            throw new NullPointerException("result == null");
+        }
+
+        this.result = result;
+    }
+
+    /**
      * Like {@link com.android.dx.rop.code.Insn getSources()}.
-     * @return non-null; sources list
+     * 
+     * @return {@code non-null;} sources list
      */
     abstract public RegisterSpecList getSources();
 
@@ -80,7 +105,8 @@
     }
 
     /**
-     * is the specified reg the result reg?
+     * Returns whether or not the specified reg is the result reg.
+     * 
      * @param reg register to test
      * @return true if there is a result and it is stored in the specified
      * register
@@ -91,9 +117,10 @@
 
 
     /**
-     * Changes the result register if this insn has a result.
-     * Used during renaming.
-     * @param reg new result register.
+     * Changes the result register if this insn has a result. This is used
+     * during renaming.
+     * 
+     * @param reg new result register
      */
     public void changeResultReg(int reg) {
         if (result != null) {
@@ -102,10 +129,10 @@
     }
 
     /**
-     * Sets the local association for the result of this insn.
-     * This is sometimes updated during the SsaRenamer process.
+     * Sets the local association for the result of this insn. This is
+     * sometimes updated during the SsaRenamer process.
      *
-     * @param local null-ok; New debug/local variable info.
+     * @param local {@code null-ok;} new debug/local variable info
      */
     public final void setResultLocal(LocalItem local) {
         LocalItem oldItem = result.getLocalItem();
@@ -120,10 +147,11 @@
     /**
      * Map registers after register allocation.
      *
-     * @param mapper
+     * @param mapper {@code non-null;} mapping from old to new registers
      */
     public final void mapRegisters(RegisterMapper mapper) {
         RegisterSpec oldResult = result;
+
         result = mapper.map(result);
         block.getParent().updateOneDefinition(this, oldResult);
         mapSourceRegisters(mapper);        
@@ -136,13 +164,12 @@
      */
     abstract public void mapSourceRegisters(RegisterMapper mapper);
 
-
     /**
-     * Returns the Rop opcode for this insn, or null if this is a phi insn
+     * Returns the Rop opcode for this insn, or null if this is a phi insn.
      *
-     * TODO move this up into NormalSsaInsn
+     * TODO: Move this up into NormalSsaInsn.
      *
-     * @return null-ok; Rop opcode if there is one.
+     * @return {@code null-ok;} Rop opcode if there is one.
      */
     abstract public Rop getOpcode();
 
@@ -150,20 +177,21 @@
      * Returns the original Rop insn for this insn, or null if this is
      * a phi insn.
      * 
-     * TODO move this up into NormalSsaInsn
+     * TODO: Move this up into NormalSsaInsn.
      *
-     * @return null-ok; Rop insn if there is one.
+     * @return {@code null-ok;} Rop insn if there is one.
      */
     abstract public Insn getOriginalRopInsn();
 
     /**
      * Gets the spec of a local variable assignment that occurs at this
      * instruction, or null if no local variable assignment occurs. This
-     * may be the result register, or for <code>mark-local</code> insns
+     * may be the result register, or for {@code mark-local} insns
      * it may be the source.
      *
-     * @return null-ok; a local-associated register spec or null
      * @see com.android.dx.rop.code.Insn#getLocalAssignment() 
+     * 
+     * @return {@code null-ok;} a local-associated register spec or null
      */
     public RegisterSpec getLocalAssignment() {
         if (result != null && result.getLocalItem() != null) {
@@ -176,7 +204,8 @@
     /**
      * Indicates whether the specified register is amongst the registers
      * used as sources for this instruction.
-     * @param reg The register in question
+     * 
+     * @param reg the register in question
      * @return true if the reg is a source
      */
     public boolean isRegASource(int reg) {
@@ -186,9 +215,9 @@
     /**
      * Transform back to ROP form.
      *
-     * TODO move this up into NormalSsaInsn
+     * TODO: Move this up into NormalSsaInsn.
      *
-     * @return non-null; a ROP representation of this instruction, with
+     * @return {@code non-null;} a ROP representation of this instruction, with
      * updated registers.
      */
     public abstract Insn toRopInsn();
@@ -208,8 +237,8 @@
     public abstract boolean hasSideEffect();
 
     /**
-     * @return true if this is a move (but not a move-operand or move-exception)
-     * instruction
+     * @return true if this is a move (but not a move-operand or
+     * move-exception) instruction
      */
     public boolean isNormalMoveInsn() {
         return false;
@@ -229,8 +258,9 @@
     abstract public boolean canThrow();
 
     /**
-     * accepts a visitor
-     * @param v visitor
+     * Accepts a visitor.
+     * 
+     * @param v {@code non-null} the visitor
      */
     public abstract void accept(Visitor v);
 
@@ -238,22 +268,21 @@
      * Visitor interface for this class.
      */
     public static interface Visitor {
-
         /**
          * Any non-phi move instruction
-         * @param insn non-null; the instruction to visit
+         * @param insn {@code non-null;} the instruction to visit
          */
         public void visitMoveInsn(NormalSsaInsn insn);
 
         /**
          * Any phi insn
-         * @param insn non-null; the instruction to visit
+         * @param insn {@code non-null;} the instruction to visit
          */
         public void visitPhiInsn(PhiInsn insn);
 
         /**
          * Any insn that isn't a move or a phi (which is also a move).
-         * @param insn non-null; the instruction to visit
+         * @param insn {@code non-null;} the instruction to visit
          */
         public void visitNonMoveInsn(NormalSsaInsn insn);
     }
diff --git a/dx/src/com/android/dx/ssa/SsaMethod.java b/dx/src/com/android/dx/ssa/SsaMethod.java
index 49f8ea5..073e515 100644
--- a/dx/src/com/android/dx/ssa/SsaMethod.java
+++ b/dx/src/com/android/dx/ssa/SsaMethod.java
@@ -36,10 +36,9 @@
 import java.util.Set;
 
 /**
- * A method in SSA form
+ * A method in SSA form.
  */
 public final class SsaMethod {
-    
     /** basic blocks, indexed by block index */
     private ArrayList<SsaBasicBlock> blocks;
 
@@ -48,12 +47,17 @@
 
     /**
      * Index of exit block, which exists only in SSA form,
-     * or or -1 if there is none
+     * or or {@code -1} if there is none
      */
     private int exitBlockIndex;
 
+    /** total number of registers required */
     private int registerCount;
+
+    /** first register number to use for any temporary "spares" */
     private int spareRegisterBase;
+
+    /** current count of spare registers used */
     private int borrowedSpareRegisters;
 
     /** really one greater than the max label */
@@ -62,7 +66,7 @@
     /** the total width, in register-units, of the method's parameters */
     private final int paramWidth;
 
-    /** true if this method has no 'this' pointer argument */
+    /** true if this method has no {@code this} pointer argument */
     private final boolean isStatic;
 
     /**
@@ -73,6 +77,7 @@
 
     /** indexed by register: the list of all insns that use a register */
     private ArrayList<SsaInsn>[] useList;
+
     /** A version of useList with each List unmodifiable */
     private List<SsaInsn>[] unmodifiableUseList;
 
@@ -81,47 +86,58 @@
      * are about to be mapped into a non-SSA namespace. When true,
      * use and def lists are unavailable.
      *
-     * TODO remove this mode, plase the functionality elsewhere
+     * TODO: Remove this mode, and place the functionality elsewhere
      */
-    private boolean backMode = false;
+    private boolean backMode;
 
     /**
-     * @param rmeth RopMethod to convert from
+     * @param ropMethod rop-form method to convert from
      * @param paramWidth the total width, in register-units, of the
      * method's parameters
-     * @param isStatic true if this method has no 'this' pointer argument
-     * @return SsaMethod representation
+     * @param isStatic {@code true} if this method has no {@code this}
+     * pointer argument
      */
-    static SsaMethod newFromRopMethod(RopMethod rmeth, int paramWidth,
-            boolean isStatic) {
-        SsaMethod result;
+    public static SsaMethod newFromRopMethod(RopMethod ropMethod,
+            int paramWidth, boolean isStatic) {
+        SsaMethod result = new SsaMethod(ropMethod, paramWidth, isStatic);
 
-        result = new SsaMethod(paramWidth, isStatic);
-
-        result.maxLabel = rmeth.getBlocks().getMaxLabel();
-        result.registerCount = rmeth.getBlocks().getRegCount();
-        result.spareRegisterBase = result.registerCount;
-
-        result.convertRopToSsaBlocks(rmeth);
+        result.convertRopToSsaBlocks(ropMethod);
 
         return result;
     }
 
     /**
+     * Constructs an instance.
+     *
+     * @param ropMethod {@code non-null;} the original rop-form method that
+     * this instance is based on
+     * @param paramWidth the total width, in register-units, of the
+     * method's parameters
+     * @param isStatic {@code true} if this method has no {@code this}
+     * pointer argument
+     */
+    private SsaMethod(RopMethod ropMethod, int paramWidth, boolean isStatic) {
+        this.paramWidth = paramWidth;
+        this.isStatic = isStatic;
+        this.backMode = false;
+        this.maxLabel = ropMethod.getBlocks().getMaxLabel();
+        this.registerCount = ropMethod.getBlocks().getRegCount();
+        this.spareRegisterBase = registerCount;
+    }
+
+    /**
      * Builds a BitSet of block indices from a basic block list and a list
-     * of labels taken from Rop form
+     * of labels taken from Rop form.
+     *
      * @param blocks Rop blocks
      * @param labelList list of rop block labels
      * @return BitSet of block indices
      */
     static BitSet bitSetFromLabelList(BasicBlockList blocks,
             IntList labelList) {
+        BitSet result = new BitSet(blocks.size());
 
-        BitSet result;
-
-        result = new BitSet(blocks.size());
-
-        for (int i = 0, sz = labelList.size() ; i < sz ; i++) {
+        for (int i = 0, sz = labelList.size(); i < sz; i++) {
             result.set(blocks.indexOfLabel(labelList.get(i)));
         }
 
@@ -130,7 +146,8 @@
 
     /**
      * Builds an IntList of block indices from a basic block list and a list
-     * of labels taken from Rop form
+     * of labels taken from Rop form.
+     *
      * @param ropBlocks Rop blocks
      * @param labelList list of rop block labels
      * @return IntList of block indices
@@ -138,35 +155,27 @@
     public static IntList indexListFromLabelList(BasicBlockList ropBlocks,
             IntList labelList) {
 
-        IntList result;
+        IntList result = new IntList(labelList.size());
 
-        result = new IntList(labelList.size());
-
-        for (int i = 0, sz = labelList.size() ; i < sz ; i++) {
+        for (int i = 0, sz = labelList.size(); i < sz; i++) {
             result.add(ropBlocks.indexOfLabel(labelList.get(i)));
         }
 
         return result;
     }
 
-    private void convertRopToSsaBlocks(
-            RopMethod rmeth) {
+    private void convertRopToSsaBlocks(RopMethod rmeth) {
+        BasicBlockList ropBlocks = rmeth.getBlocks();
+        int sz = ropBlocks.size();
 
-        BasicBlockList ropBlocks;
+        blocks = new ArrayList<SsaBasicBlock>(sz + 2);
 
-        ropBlocks = rmeth.getBlocks();
-
-        blocks = new ArrayList<SsaBasicBlock>(ropBlocks.size() + 2);
-
-        for (int i = 0, sz = ropBlocks.size() ; i < sz ; i++) {
-            SsaBasicBlock sbb;
-
-            sbb = SsaBasicBlock.newFromRop(rmeth, i, this);
-
+        for (int i = 0; i < sz; i++) {
+            SsaBasicBlock sbb = SsaBasicBlock.newFromRop(rmeth, i, this);
             blocks.add(sbb);
         }
 
-        // Add an no-op entry block
+        // Add an no-op entry block.
         int origEntryBlockIndex = rmeth.getBlocks()
                 .indexOfLabel(rmeth.getFirstLabel());
 
@@ -174,18 +183,16 @@
                 = blocks.get(origEntryBlockIndex).insertNewPredecessor();
 
         entryBlockIndex = entryBlock.getIndex();
-        exitBlockIndex = -1; // this gets made later
-
+        exitBlockIndex = -1; // This gets made later.
     }
 
-
     /**
      * Creates an exit block and attaches it to the CFG if this method
      * exits. Methods that never exit will not have an exit block. This
      * is called after edge-splitting and phi insertion, since the edges
      * going into the exit block should not be considered in those steps.
      */
-    void makeExitBlock() {
+    /*package*/ void makeExitBlock() {
         if (exitBlockIndex >= 0) {
             throw new RuntimeException("must be called at most once");
         }
@@ -196,7 +203,7 @@
 
         blocks.add(exitBlock);
 
-        for (SsaBasicBlock block: blocks) {
+        for (SsaBasicBlock block : blocks) {
             block.exitBlockFixup(exitBlock);
         }
 
@@ -209,22 +216,10 @@
     }
 
     /**
-     * Constructor
-     *
-     * @param paramWidth the total width, in register-units, of the
-     * method's parameters
-     * @param isStatic true if this method has no 'this' pointer argument
-     */
-    private SsaMethod(int paramWidth, boolean isStatic) {
-        this.paramWidth = paramWidth;
-        this.isStatic = isStatic;
-    }
-
-    /**
-     * Gets a new GOTO insn.
+     * Gets a new {@code GOTO} insn.
      *
      * @param block block to which this GOTO will be added
-     * (not it's destination!) 
+     * (not it's destination!)
      * @return an appropriately-constructed instance.
      */
     private static SsaInsn getGoto(SsaBasicBlock block) {
@@ -232,11 +227,11 @@
                 new PlainInsn(Rops.GOTO, SourcePosition.NO_INFO,
                     null, RegisterSpecList.EMPTY), block);
     }
-    
+
     /**
-     * Makes a new basic block for this method,
-     * which is empty besides a single <code>GOTO</code>. Successors and
-     * predecessors are not yet set.
+     * Makes a new basic block for this method, which is empty besides
+     * a single {@code GOTO}. Successors and predecessors are not yet
+     * set.
      *
      * @return new block
      */
@@ -265,22 +260,23 @@
     }
 
     /**
-     * @return block index of exit block or -1 if there is none
+     * @return block index of exit block or {@code -1} if there is none
      */
     public int getExitBlockIndex() {
         return exitBlockIndex;
     }
 
     /**
-     * @return null-ok; block of exit block or null if there is none
+     * @return {@code null-ok;} block of exit block or {@code null} if
+     * there is none
      */
     public SsaBasicBlock getExitBlock() {
         return exitBlockIndex < 0 ? null : blocks.get(exitBlockIndex);
     }
 
     /**
-     * @param bi block index or -1 for none
-     * @return rop label or -1 if bi was -1
+     * @param bi block index or {@code -1} for none
+     * @return rop label or {code -1} if {@code bi} was {@code -1}
      */
     public int blockIndexToRopLabel(int bi) {
         if (bi < 0) {
@@ -297,7 +293,7 @@
     }
 
     /**
-     * @return the total width, in register units, of the method's 
+     * @return the total width, in register units, of the method's
      * parameters
      */
     public int getParamWidth() {
@@ -305,27 +301,25 @@
     }
 
     /**
-     * Returns true if this is a static method.
+     * Returns {@code true} if this is a static method.
      *
-     * @return true if this is a static method
+     * @return {@code true} if this is a static method
      */
     public boolean isStatic() {
         return isStatic;
     }
 
     /**
-     * Borrow a register to use as a temp. Used in the phi removal process.
+     * Borrows a register to use as a temp. Used in the phi removal process.
      * Call returnSpareRegisters() when done.
+     *
      * @param category width (1 or 2) of the register
      * @return register number to use
      */
     public int borrowSpareRegister(int category) {
-        int result;
-
-        result = spareRegisterBase + borrowedSpareRegisters;
+        int result = spareRegisterBase + borrowedSpareRegisters;
 
         borrowedSpareRegisters += category;
-
         registerCount = Math.max(registerCount, result + category);
 
         return result;
@@ -339,7 +333,7 @@
     }
 
     /**
-     * @return non-null; basic block list, do not modify.
+     * @return {@code non-null;} basic block list. Do not modify.
      */
     public ArrayList<SsaBasicBlock> getBlocks() {
         return blocks;
@@ -349,12 +343,12 @@
      * Returns the count of reachable blocks in this method: blocks that have
      * predecessors (or are the start block)
      *
-     * @return &gt;= 0; number of reachable basic blocks
+     * @return {@code >= 0;} number of reachable basic blocks
      */
     public int getCountReachableBlocks() {
         int ret = 0;
 
-        for (SsaBasicBlock b: blocks) {
+        for (SsaBasicBlock b : blocks) {
             // Blocks that have been disconnected don't count.
             if (b.isReachable()) {
                 ret++;
@@ -366,16 +360,16 @@
 
     /**
      * Remaps unversioned registers.
+     *
      * @param mapper maps old registers to new.
      */
     public void mapRegisters(RegisterMapper mapper) {
-
-        for (SsaBasicBlock block: getBlocks()) {
-            for (SsaInsn insn: block.getInsns()) {
+        for (SsaBasicBlock block : getBlocks()) {
+            for (SsaInsn insn : block.getInsns()) {
                 insn.mapRegisters(mapper);
             }
-        }        
-        
+        }
+
         registerCount = mapper.getNewRegisterCount();
         spareRegisterBase = registerCount;
     }
@@ -425,7 +419,7 @@
 
         useList = new ArrayList[registerCount];
 
-        for (int i = 0 ; i < registerCount; i++) {
+        for (int i = 0; i < registerCount; i++) {
             useList[i] = new ArrayList();
         }
 
@@ -444,7 +438,7 @@
             }
             /**
              * Adds specified insn to the uses list for all of its sources.
-             * @param insn non-null; insn to process
+             * @param insn {@code non-null;} insn to process
              */
             private void addToUses(SsaInsn insn) {
                 RegisterSpecList rl = insn.getSources();
@@ -458,7 +452,7 @@
 
         unmodifiableUseList = new List[registerCount];
 
-        for (int i = 0 ; i < registerCount; i++) {
+        for (int i = 0; i < registerCount; i++) {
             unmodifiableUseList[i] = Collections.unmodifiableList(useList[i]);
         }
     }
@@ -466,15 +460,15 @@
     /**
      * Updates the use list for a single change in source register.
      *
-     * @param insn non-null; insn being changed
-     * @param oldSource null-ok; The source that was used, if applicable
-     * @param newSource non-null; the new source being used
+     * @param insn {@code non-null;} insn being changed
+     * @param oldSource {@code null-ok;} The source that was used, if
+     * applicable
+     * @param newSource {@code non-null;} the new source being used
      */
-    void onSourceChanged(SsaInsn insn,
+    /*package*/ void onSourceChanged(SsaInsn insn,
             RegisterSpec oldSource, RegisterSpec newSource) {
-
         if (useList == null) return;
-        
+
         if (oldSource != null) {
             int reg = oldSource.getReg();
             useList[reg].remove(insn);
@@ -491,11 +485,13 @@
     /**
      * Updates the use list for a source list change.
      *
-     * @param insn insn non-null; insn being changed. insn.getSources()
-     * must return the new source list.
-     * @param oldSources null-ok; list of sources that were previously used.
+     * @param insn {@code insn non-null;} insn being changed.
+     * {@code insn.getSources()} must return the new source list.
+     * @param oldSources {@code null-ok;} list of sources that were
+     * previously used
      */
-    void onSourcesChanged(SsaInsn insn, RegisterSpecList oldSources) {
+    /*package*/ void onSourcesChanged(SsaInsn insn,
+            RegisterSpecList oldSources) {
         if (useList == null) return;
 
         if (oldSources != null) {
@@ -505,27 +501,28 @@
         RegisterSpecList sources = insn.getSources();
         int szNew = sources.size();
 
-        for(int i = 0; i < szNew; i++) {
+        for (int i = 0; i < szNew; i++) {
             int reg = sources.get(i).getReg();
             useList[reg].add(insn);
-        }        
+        }
     }
 
     /**
-     * Removes a given <code>insn</code> from the use lists for the given
-     * <code>oldSources</code> (rather than the sources currently
+     * Removes a given {@code insn} from the use lists for the given
+     * {@code oldSources} (rather than the sources currently
      * returned by insn.getSources()).
      *
-     * @param insn non-null; insn in question
-     * @param oldSources null-ok; registers whose use lists <code>insn</code>
-     * should be removed form.
+     * @param insn {@code non-null;} insn in question
+     * @param oldSources {@code null-ok;} registers whose use lists
+     * {@code insn} should be removed form
      */
     private void removeFromUseList(SsaInsn insn, RegisterSpecList oldSources) {
         if (oldSources == null) {
             return;
         }
+
         int szNew = oldSources.size();
-        for(int i = 0; i < szNew; i++) {
+        for (int i = 0; i < szNew; i++) {
             if (!useList[oldSources.get(i).getReg()].remove(insn)) {
                 throw new RuntimeException("use not found");
             }
@@ -536,35 +533,35 @@
      * Adds an insn to both the use and def lists. For use when adding
      * a new insn to the method.
      *
-     * @param insn non-null; insn to add
+     * @param insn {@code non-null;} insn to add
      */
-    void onInsnAdded(SsaInsn insn) {
+    /*package*/ void onInsnAdded(SsaInsn insn) {
         onSourcesChanged(insn, null);
         updateOneDefinition(insn, null);
     }
 
     /**
-      * Removes an instruction from use and def lists. For use during
-      * instruction removal.
-      *
-      * @param insn non-null; insn to remove.
-      */
-     void onInsnRemoved(SsaInsn insn) {
-         if (useList != null) {
-             removeFromUseList(insn, insn.getSources());
-         }
+     * Removes an instruction from use and def lists. For use during
+     * instruction removal.
+     *
+     * @param insn {@code non-null;} insn to remove
+     */
+    /*package*/ void onInsnRemoved(SsaInsn insn) {
+        if (useList != null) {
+            removeFromUseList(insn, insn.getSources());
+        }
 
-         RegisterSpec resultReg = insn.getResult();
-         if (definitionList != null && resultReg != null) {
-             definitionList[resultReg.getReg()] = null;
-         }
-     }
+        RegisterSpec resultReg = insn.getResult();
+        if (definitionList != null && resultReg != null) {
+            definitionList[resultReg.getReg()] = null;
+        }
+    }
 
     /**
      * Indicates that the instruction list has changed or the SSA register
      * count has increased, so that internal datastructures that rely on
      * it should be rebuild. In general, the various other on* methods
-     * should be called in preference when changes occur if they are 
+     * should be called in preference when changes occur if they are
      * applicable.
      */
     public void onInsnsChanged() {
@@ -579,19 +576,22 @@
     /**
      * Updates a single definition.
      *
-     * @param insn non-null; insn who's result should be recorded as
+     * @param insn {@code non-null;} insn who's result should be recorded as
      * a definition
-     * @param oldResult null-ok; a previous result that should be no longer
-     * considered a definition by this insn
+     * @param oldResult {@code null-ok;} a previous result that should
+     * be no longer considered a definition by this insn
      */
-    void updateOneDefinition(SsaInsn insn, RegisterSpec oldResult) {
+    /*package*/ void updateOneDefinition(SsaInsn insn,
+            RegisterSpec oldResult) {
         if (definitionList == null) return;
+
         if (oldResult != null) {
             int reg = oldResult.getReg();
             definitionList[reg] = null;
         }
 
         RegisterSpec resultReg = insn.getResult();
+
         if (resultReg != null) {
             int reg = resultReg.getReg();
 
@@ -604,7 +604,8 @@
     }
 
     /**
-     * Returns the list of all source uses (not results) for a register
+     * Returns the list of all source uses (not results) for a register.
+     *
      * @param reg register in question
      * @return unmodifiable instruction list
      */
@@ -619,6 +620,7 @@
 
     /**
      * Returns a modifiable copy of the register use list.
+     *
      * @return modifiable copy of the use-list, indexed by register
      */
     public ArrayList<SsaInsn>[] getUseListCopy() {
@@ -641,7 +643,7 @@
      * local variable. Each SSA reg may be associated with at most one
      * local var.
      *
-     * @param spec non-null; ssa reg
+     * @param spec {@code non-null;} ssa reg
      * @return true if reg is ever associated with a local
      */
     public boolean isRegALocal(RegisterSpec spec) {
@@ -656,7 +658,7 @@
         if (defn.getLocalAssignment() != null) return true;
 
         // If not, is there a mark-local insn?
-        for (SsaInsn use: getUseListForRegister(spec.getReg())) {
+        for (SsaInsn use : getUseListForRegister(spec.getReg())) {
             Insn insn = use.getOriginalRopInsn();
 
             if (insn != null
@@ -664,12 +666,13 @@
                 return true;
             }
         }
-        
+
         return false;
     }
 
     /**
      * Sets the new register count after renaming.
+     *
      * @param newRegCount new register count
      */
     /*package*/ void setNewRegCount(int newRegCount) {
@@ -681,48 +684,52 @@
     /**
      * Makes a new SSA register. For use after renaming has completed.
      *
-     * @return &gt;=0 new SSA register.
+     * @return {@code >=0;} new SSA register.
      */
     public int makeNewSsaReg() {
         int reg = registerCount++;
         spareRegisterBase = registerCount;
         onInsnsChanged();
-        return reg;        
+        return reg;
     }
 
     /**
-     * Visit all insns in this method
-     * @param visitor non-null; callback interface
+     * Visits all insns in this method.
+     *
+     * @param visitor {@code non-null;} callback interface
      */
     public void forEachInsn(SsaInsn.Visitor visitor) {
-        for (SsaBasicBlock block: blocks) {
+        for (SsaBasicBlock block : blocks) {
             block.forEachInsn(visitor);
         }
     }
 
     /**
      * Visits each phi insn in this method
-     * @param v non-null; callback
+     * @param v {@code non-null;} callback.
+     *
      */
     public void forEachPhiInsn(PhiInsn.Visitor v) {
-        for (SsaBasicBlock block: blocks) {
+        for (SsaBasicBlock block : blocks) {
             block.forEachPhiInsn(v);
         }
     }
 
 
     /**
-     * Walk the basic block tree in depth-first order, calling the visitor
+     * Walks the basic block tree in depth-first order, calling the visitor
      * method once for every block. This depth-first walk may be run forward
      * from the method entry point or backwards from the method exit points.
+     *
      * @param reverse true if this should walk backwards from the exit points
-     * @param v non-null; callback interface. <code>parent</code>is set
+     * @param v {@code non-null;} callback interface. {@code parent} is set
      * unless this is the root node
      */
     public void forEachBlockDepthFirst(boolean reverse,
             SsaBasicBlock.Visitor v) {
         BitSet visited = new BitSet(blocks.size());
-        // We push the parent first, then the child on the stack
+
+        // We push the parent first, then the child on the stack.
         Stack<SsaBasicBlock> stack = new Stack<SsaBasicBlock>();
 
         SsaBasicBlock rootBlock = reverse ? getExitBlock() : getEntryBlock();
@@ -732,7 +739,7 @@
             return;
         }
 
-        stack.add(null);    // start with null parent
+        stack.add(null);    // Start with null parent.
         stack.add(rootBlock);
 
         while (stack.size() > 0) {
@@ -741,7 +748,7 @@
 
             if (!visited.get(cur.getIndex())) {
                 BitSet children
-                        = reverse ? cur.getPredecessors() : cur.getSuccessors();
+                    = reverse ? cur.getPredecessors() : cur.getSuccessors();
                 for (int i = children.nextSetBit(0); i >= 0
                         ; i = children.nextSetBit(i + 1)) {
                     stack.add(cur);
@@ -755,10 +762,10 @@
 
     /**
      * Visits blocks in dom-tree order, starting at the current node.
-     * The <code>parent</code> parameter of the Visitor.visitBlock callback
+     * The {@code parent} parameter of the Visitor.visitBlock callback
      * is currently always set to null.
      *
-     * @param v non-null; callback interface
+     * @param v {@code non-null;} callback interface
      */
     public void forEachBlockDepthFirstDom(SsaBasicBlock.Visitor v) {
         BitSet visited = new BitSet(getBlocks().size());
@@ -783,12 +790,12 @@
     }
 
     /**
-     * Deletes all insns in the set from this method
+     * Deletes all insns in the set from this method.
      *
-     * @param deletedInsns non-null; insns to delete
+     * @param deletedInsns {@code non-null;} insns to delete
      */
     public void deleteInsns(Set<SsaInsn> deletedInsns) {
-        for (SsaBasicBlock block: getBlocks()) {
+        for (SsaBasicBlock block : getBlocks()) {
             ArrayList<SsaInsn> insns = block.getInsns();
 
             for (int i = insns.size() - 1; i >= 0; i--) {
@@ -819,7 +826,7 @@
     }
 
     /**
-     * Set "back-convert mode". Set during back-conversion when registers
+     * Sets "back-convert mode". Set during back-conversion when registers
      * are about to be mapped into a non-SSA namespace. When true,
      * use and def lists are unavailable.
      */
diff --git a/dx/src/com/android/dx/ssa/SsaRenamer.java b/dx/src/com/android/dx/ssa/SsaRenamer.java
index 64bad2c..8452c03 100644
--- a/dx/src/com/android/dx/ssa/SsaRenamer.java
+++ b/dx/src/com/android/dx/ssa/SsaRenamer.java
@@ -54,11 +54,11 @@
  * current block has been processed, this mapping table is then copied
  * and used as the initial state for child blocks.<p>
  */
-class SsaRenamer implements Runnable {
-
+public class SsaRenamer implements Runnable {
+    /** debug flag */
     private static final boolean DEBUG = false;
 
-    /** Method we're processing */
+    /** method we're processing */
     private final SsaMethod ssaMeth;
 
     /** next available SSA register */
@@ -68,10 +68,10 @@
     private final int ropRegCount;
 
     /**
-     * Indexed by block index; register version state for each block start.
+     * indexed by block index; register version state for each block start.
      * This list is updated by each dom parent for its children. The only
      * sub-arrays that exist at any one time are the start states for blocks
-     * yet to be processed by a <code>BlockRenamer</code> instance.
+     * yet to be processed by a {@code BlockRenamer} instance.
      */
     private final RegisterSpec[][] startsForBlocks;
 
@@ -79,24 +79,25 @@
     private final ArrayList<LocalItem> ssaRegToLocalItems;
 
     /**
-     * Maps SSA registers back to the original rop number.
-     * Used for debug only.
+     * maps SSA registers back to the original rop number. Used for
+     * debug only.
      */
     private IntList ssaRegToRopReg;
 
     /**
      * Constructs an instance of the renamer
      *
-     * @param ssaMeth non-null; un-renamed SSA method that will
+     * @param ssaMeth {@code non-null;} un-renamed SSA method that will
      * be renamed.
      */
-    SsaRenamer (final SsaMethod ssaMeth) {
+    public SsaRenamer(SsaMethod ssaMeth) {
         ropRegCount = ssaMeth.getRegCount();
 
         this.ssaMeth = ssaMeth;
+
         /*
          * Reserve the first N registers in the SSA register space for
-         * "version 0" registers
+         * "version 0" registers.
          */
         nextSsaReg = ropRegCount;
         startsForBlocks = new RegisterSpec[ssaMeth.getBlocks().size()][];
@@ -138,10 +139,10 @@
      * in-place.
      */
     public void run() {
-
         // Rename each block in dom-tree DFS order.
         ssaMeth.forEachBlockDepthFirstDom(new SsaBasicBlock.Visitor() {
-            public void visitBlock (SsaBasicBlock block, SsaBasicBlock unused) {
+            public void visitBlock (SsaBasicBlock block,
+                    SsaBasicBlock unused) {
                 new BlockRenamer(block).process();
             }
         });
@@ -151,15 +152,17 @@
 
         if (DEBUG) {
             System.out.println("SSA\tRop");
-            // We're going to compute the version of the rop register
-            // by keeping a running total of how many times the rop register
-            // has been mapped.
+            /*
+             * We're going to compute the version of the rop register
+             * by keeping a running total of how many times the rop
+             * register has been mapped.
+             */
             int[] versions = new int[ropRegCount];
 
             int sz = ssaRegToRopReg.size();
-            for(int i = 0; i < sz; i++) {
-                int ropReg =  ssaRegToRopReg.get(i);
-                System.out.println(i +"\t" + ropReg + "["
+            for (int i = 0; i < sz; i++) {
+                int ropReg = ssaRegToRopReg.get(i);
+                System.out.println(i + "\t" + ropReg + "["
                         + versions[ropReg] + "]");
                 versions[ropReg]++;
             }
@@ -167,9 +170,10 @@
     }
 
     /**
-     * Duplicates a RegisterSpec array
-     * @param orig non-null; array to duplicate
-     * @return non-null; new instance
+     * Duplicates a RegisterSpec array.
+     *
+     * @param orig {@code non-null;} array to duplicate
+     * @return {@code non-null;} new instance
      */
     private static  RegisterSpec[] dupArray(RegisterSpec[] orig) {
         RegisterSpec[] copy = new RegisterSpec[orig.length];
@@ -183,7 +187,7 @@
      * Gets a local variable item for a specified register.
      *
      * @param ssaReg register in SSA name space
-     * @return null-ok; Local variable name or null if none
+     * @return {@code null-ok;} Local variable name or null if none
      */
     private LocalItem getLocalForNewReg(int ssaReg) {
         if (ssaReg < ssaRegToLocalItems.size()) {
@@ -223,8 +227,8 @@
     }
 
     /**
-     * Returns true if a and b are equal or are both null
-
+     * Returns true if a and b are equal or are both null.
+     *
      * @param a null-ok
      * @param b null-ok
      * @return Returns true if a and b are equal or are both null
@@ -238,26 +242,26 @@
      * as appropriate.
      */
     private class BlockRenamer implements SsaInsn.Visitor{
-        /** non-null; block we're processing. */
+        /** {@code non-null;} block we're processing. */
         private final SsaBasicBlock block;
 
         /**
-         * non-null; indexed by old register name. The current top of the
-         * version stack as seen by this block. It's initialized from
-         * the ending state of its dom parent, updated as the block's
-         * instructions are processed, and then copied to each one of its
-         * dom children.
+         * {@code non-null;} indexed by old register name. The current
+         * top of the version stack as seen by this block. It's
+         * initialized from the ending state of its dom parent,
+         * updated as the block's instructions are processed, and then
+         * copied to each one of its dom children.
          */
         private final RegisterSpec[] currentMapping;
 
         /**
-         * Contains the set of moves we need to keep
-         * to preserve local var info. All other moves will be deleted.
+         * contains the set of moves we need to keep to preserve local
+         * var info. All other moves will be deleted.
          */
         private final HashSet<SsaInsn> movesToKeep;
 
         /**
-         * Maps the set of insns to replace after renaming is finished
+         * maps the set of insns to replace after renaming is finished
          * on the block.
          */
         private final HashMap<SsaInsn, SsaInsn> insnsToReplace;
@@ -265,10 +269,10 @@
         private final RenamingMapper mapper;
 
         /**
-         * Constructs a block renamer instance. Call <code>process</code>
+         * Constructs a block renamer instance. Call {@code process}
          * to process.
          *
-         * @param block non-null; block to process
+         * @param block {@code non-null;} block to process
          */
         BlockRenamer(final SsaBasicBlock block) {
             this.block = block;
@@ -287,8 +291,8 @@
          * as the current block's instructions are processed.
          */
         private class RenamingMapper extends RegisterMapper {
-
-            RenamingMapper() {
+            public RenamingMapper() {
+                // This space intentionally left blank.
             }
 
             /** {@inheritDoc} */
@@ -304,8 +308,8 @@
 
                 int reg = registerSpec.getReg();
 
-                // for debugging: assert that the mapped types are compatible
-                if(DEBUG) {
+                // For debugging: assert that the mapped types are compatible.
+                if (DEBUG) {
                     RegisterSpec newVersion = currentMapping[reg];
                     if (newVersion.getBasicType() != Type.BT_VOID
                             && registerSpec.getBasicFrameType()
@@ -338,7 +342,7 @@
 
             updateSuccessorPhis();
 
-            // Delete all move insns in this block
+            // Delete all move insns in this block.
             ArrayList<SsaInsn> insns = block.getInsns();
             int szInsns = insns.size();
 
@@ -349,29 +353,27 @@
                 replaceInsn = insnsToReplace.get(insn);
 
                 if (replaceInsn != null) {
-                    insns.set(i, replaceInsn);                    
+                    insns.set(i, replaceInsn);
                 } else if (insn.isNormalMoveInsn()
                         && !movesToKeep.contains(insn)) {
                     insns.remove(i);
                 }
             }
 
-            // Store the start states for our dom children
+            // Store the start states for our dom children.
             boolean first = true;
-            for (SsaBasicBlock child: block.getDomChildren()) {
+            for (SsaBasicBlock child : block.getDomChildren()) {
                 if (child != block) {
-                    RegisterSpec[] childStart;
-
-                    // don't bother duplicating the array for the first child
-                    childStart = first ? currentMapping
-                            : dupArray(currentMapping);
+                    // Don't bother duplicating the array for the first child.
+                    RegisterSpec[] childStart = first ? currentMapping
+                        : dupArray(currentMapping);
 
                     startsForBlocks[child.getIndex()] = childStart;
                     first = false;
                 }
             }
 
-            // currentMapping is owned by a child now
+            // currentMapping is owned by a child now.
         }
 
         /**
@@ -388,13 +390,13 @@
          * local.
          * <li> ensures that only one SSA register
          * at a time is considered to be associated with a local variable. When
-         * <code>currentMapping</code> is updated and the newly added element
+         * {@code currentMapping} is updated and the newly added element
          * is named, strip that name from any other SSA registers.
          * </ol>
          *
-         * @param ropReg &gt;= 0 Rop register number
-         * @param ssaReg non-null; An SSA register that has just
-         * been added to <code>currentMapping</code>
+         * @param ropReg {@code >= 0;} rop register number
+         * @param ssaReg {@code non-null;} an SSA register that has just
+         * been added to {@code currentMapping}
          */
         private void addMapping(int ropReg, RegisterSpec ssaReg) {
             int ssaRegNum = ssaReg.getReg();
@@ -413,15 +415,15 @@
                 }
             }
 
-            // All further steps are for registers with local information
+            // All further steps are for registers with local information.
             if (ssaRegLocal == null) {
                 return;
             }
 
-            // Record that this SSA reg has been associated with a local
+            // Record that this SSA reg has been associated with a local.
             setNameForSsaReg(ssaReg);
 
-            // Ensure that no other SSA regs are associated with this local
+            // Ensure that no other SSA regs are associated with this local.
             for (int i = currentMapping.length - 1; i >= 0; i--) {
                 RegisterSpec cur = currentMapping[i];
 
@@ -436,7 +438,7 @@
          * {@inheritDoc}
          *
          * Phi insns have their result registers renamed.
-         * */
+         */
         public void visitPhiInsn(PhiInsn phi) {
             /* don't process sources for phi's */
             processResultReg(phi);
@@ -452,7 +454,7 @@
          */
         public void visitMoveInsn(NormalSsaInsn insn) {
             /*
-             * for moves: copy propogate the move if we can, but don't
+             * For moves: copy propogate the move if we can, but don't
              * if we need to preserve local variable info and the
              * result has a different name than the source.
              */
@@ -464,7 +466,8 @@
             insn.mapSourceRegisters(mapper);
             int ssaSourceReg = insn.getSources().get(0).getReg();
 
-            LocalItem sourceLocal = currentMapping[ropSourceReg].getLocalItem();
+            LocalItem sourceLocal
+                = currentMapping[ropSourceReg].getLocalItem();
             LocalItem resultLocal = ropResult.getLocalItem();
 
             /*
@@ -475,25 +478,26 @@
              */
 
             LocalItem newLocal
-                    = (resultLocal == null) ? sourceLocal : resultLocal;
-
+                = (resultLocal == null) ? sourceLocal : resultLocal;
             LocalItem associatedLocal = getLocalForNewReg(ssaSourceReg);
 
-            // If we take the new local, will only one local have ever
-            // been associated with this SSA reg?
+            /*
+             * If we take the new local, will only one local have ever
+             * been associated with this SSA reg?
+             */
             boolean onlyOneAssociatedLocal
                     = associatedLocal == null || newLocal == null
                     || newLocal.equals(associatedLocal);
-                    
+
             /*
-             * If we're going to copy-propogate, then the ssa register spec
-             * that's going to go into the mapping is made up of the
-             * source register number mapped from above, the type
+             * If we're going to copy-propogate, then the ssa register
+             * spec that's going to go into the mapping is made up of
+             * the source register number mapped from above, the type
              * of the result, and the name either from the result (if
              * specified) or inherited from the existing mapping.
              *
-             * The move source has incomplete type information
-             * in null object cases, so the result type is used.
+             * The move source has incomplete type information in null
+             * object cases, so the result type is used.
              */
             RegisterSpec ssaReg
                     = RegisterSpec.makeLocalOptional(
@@ -509,15 +513,12 @@
 
                 addMapping(ropResultReg, ssaReg);
             } else if (onlyOneAssociatedLocal && sourceLocal == null) {
-
                 /*
                  * The register was previously unnamed. This means that a
                  * local starts after it's first assignment in SSA form
                  */
 
-                RegisterSpecList ssaSources;
-
-                ssaSources = RegisterSpecList.make(
+                RegisterSpecList ssaSources = RegisterSpecList.make(
                         RegisterSpec.make(ssaReg.getReg(),
                                 ssaReg.getType(), newLocal));
 
@@ -528,12 +529,12 @@
 
                 insnsToReplace.put(insn, newInsn);
 
-                // Just map as above
+                // Just map as above.
                 addMapping(ropResultReg, ssaReg);
             } else {
                 /*
-                 * Do not copy-propogate, since the two registers
-                 * have two different local-variable names
+                 * Do not copy-propogate, since the two registers have
+                 * two different local-variable names.
                  */
                 processResultReg(insn);
 
@@ -594,11 +595,12 @@
                     ropReg = insn.getRopResultReg();
 
                     /*
-                     * Never add a version 0 register as a phi operand.
-                     * Version 0 registers represent the initial register state,
-                     * and thus are never significant. Furthermore,
-                     * the register liveness algorithm doesn't properly
-                     * count them as "live in" at the beginning of the method.
+                     * Never add a version 0 register as a phi
+                     * operand. Version 0 registers represent the
+                     * initial register state, and thus are never
+                     * significant. Furthermore, the register liveness
+                     * algorithm doesn't properly count them as "live
+                     * in" at the beginning of the method.
                      */
 
                     RegisterSpec stackTop = currentMapping[ropReg];
@@ -611,9 +613,7 @@
             BitSet successors = block.getSuccessors();
             for (int i = successors.nextSetBit(0); i >= 0;
                     i = successors.nextSetBit(i + 1)) {
-
                 SsaBasicBlock successor = ssaMeth.getBlocks().get(i);
-
                 successor.forEachPhiInsn(visitor);
             }
         }
diff --git a/dx/src/com/android/dx/ssa/_tests/_DomFront.java b/dx/src/com/android/dx/ssa/_tests/_DomFront.java
index 997da21..3d891c9 100644
--- a/dx/src/com/android/dx/ssa/_tests/_DomFront.java
+++ b/dx/src/com/android/dx/ssa/_tests/_DomFront.java
@@ -19,7 +19,7 @@
 import junit.framework.TestCase;
 
 /**
- * Test the class <code>com.android.dx.ssa.DomFront</code>.
+ * Test the class {@code com.android.dx.ssa.DomFront}.
  */
 public class _DomFront
         extends TestCase {
diff --git a/dx/src/com/android/dx/ssa/back/FirstFitAllocator.java b/dx/src/com/android/dx/ssa/back/FirstFitAllocator.java
index d3ff7c7..6416e84 100644
--- a/dx/src/com/android/dx/ssa/back/FirstFitAllocator.java
+++ b/dx/src/com/android/dx/ssa/back/FirstFitAllocator.java
@@ -106,7 +106,6 @@
             }
 
             for (int j = i + 1; j < oldRegCount; j++) {
-
                 if (mapped.get(j) || isDefinitionMoveParam(j)) {
                     continue;
                 }
diff --git a/dx/src/com/android/dx/ssa/back/FirstFitLocalCombiningAllocator.java b/dx/src/com/android/dx/ssa/back/FirstFitLocalCombiningAllocator.java
index 14eac90..0cffcfa 100644
--- a/dx/src/com/android/dx/ssa/back/FirstFitLocalCombiningAllocator.java
+++ b/dx/src/com/android/dx/ssa/back/FirstFitLocalCombiningAllocator.java
@@ -40,9 +40,10 @@
  * kept together if possible.
  */
 public class FirstFitLocalCombiningAllocator extends RegisterAllocator {
+    /** local debug flag */
     private static final boolean DEBUG = false;
 
-    /** maps local variable to a list of associated SSA registers*/
+    /** maps local variable to a list of associated SSA registers */
     private final Map<LocalItem, ArrayList<RegisterSpec>> localVariables;
 
     /** list of move-result-pesudo instructions seen in this method */
@@ -57,29 +58,28 @@
     /** Register mapper which will be our result */
     private final InterferenceRegisterMapper mapper;
 
-    /** end of rop registers range (starting at 0) reserved for parameters. */
+    /** end of rop registers range (starting at 0) reserved for parameters */
     private final int paramRangeEnd;
 
-    /** set of Rop registers reserved for parameters or local variables. */
+    /** set of rop registers reserved for parameters or local variables */
     private final BitSet reservedRopRegs;
 
-    /** set of Rop registers that have been used by anything.*/
+    /** set of rop registers that have been used by anything */
     private final BitSet usedRopRegs;
 
-    /** true if converter should take steps to minimize rop-form registers*/
+    /** true if converter should take steps to minimize rop-form registers */
     private final boolean minimizeRegisters;
 
-
     /**
      * Constructs instance.
      *
-     * @param ssaMeth non-null; method to process
+     * @param ssaMeth {@code non-null;} method to process
      * @param interference non-null interference graph for SSA registers
      * @param minimizeRegisters true if converter should take steps to
      * minimize rop-form registers
      */
     public FirstFitLocalCombiningAllocator(
-            final SsaMethod ssaMeth, InterferenceGraph interference,
+            SsaMethod ssaMeth, InterferenceGraph interference,
             boolean minimizeRegisters) {
         super(ssaMeth, interference);
 
@@ -122,22 +122,24 @@
             printLocalVars();
         }
 
-        if(DEBUG) System.out.println("--->Mapping local-associated params");
+        if (DEBUG) System.out.println("--->Mapping local-associated params");
         handleLocalAssociatedParams();
 
-        if(DEBUG) System.out.println("--->Mapping other params");
+        if (DEBUG) System.out.println("--->Mapping other params");
         handleUnassociatedParameters();
 
-        if(DEBUG) System.out.println("--->Mapping invoke-range");
+        if (DEBUG) System.out.println("--->Mapping invoke-range");
         handleInvokeRangeInsns();
-        
-        if(DEBUG) System.out.println("--->Mapping local-associated non-params");
+
+        if (DEBUG) {
+            System.out.println("--->Mapping local-associated non-params");
+        }
         handleLocalAssociatedOther();
 
-        if(DEBUG) System.out.println("--->Mapping check-cast results");
+        if (DEBUG) System.out.println("--->Mapping check-cast results");
         handleCheckCastResults();
 
-        if(DEBUG) System.out.println("--->Mapping others");
+        if (DEBUG) System.out.println("--->Mapping others");
         handleNormalUnassociated();
 
         return mapper;
@@ -148,13 +150,13 @@
      */
     private void printLocalVars() {
         System.out.println("Printing local vars");
-        for (Map.Entry<LocalItem, ArrayList<RegisterSpec>> e:
+        for (Map.Entry<LocalItem, ArrayList<RegisterSpec>> e :
                 localVariables.entrySet()) {
             StringBuilder regs = new StringBuilder();
 
             regs.append('{');
             regs.append(' ');
-            for(RegisterSpec reg: e.getValue()) {
+            for (RegisterSpec reg : e.getValue()) {
                 regs.append('v');
                 regs.append(reg.getReg());
                 regs.append(' ');
@@ -165,16 +167,16 @@
     }
 
     /**
-     * Maps all local-associated parameters to Rop registers.
+     * Maps all local-associated parameters to rop registers.
      */
     private void handleLocalAssociatedParams() {
-        for (ArrayList<RegisterSpec> ssaRegs: localVariables.values()) {
+        for (ArrayList<RegisterSpec> ssaRegs : localVariables.values()) {
             int sz = ssaRegs.size();
             int paramIndex = -1;
             int paramCategory = 0;
 
-            // First, find out if this local variable is a parameter
-            for (int i = 0 ; i < sz ; i++) {
+            // First, find out if this local variable is a parameter.
+            for (int i = 0; i < sz; i++) {
                 RegisterSpec ssaSpec = ssaRegs.get(i);
                 int ssaReg = ssaSpec.getReg();
 
@@ -188,31 +190,31 @@
             }
 
             if (paramIndex < 0) {
-                // this local wasn't a parameter
+                // This local wasn't a parameter.
                 continue;
             }
 
-            // Any remaining local-associated registers will be mapped later
+            // Any remaining local-associated registers will be mapped later.
             tryMapRegs(ssaRegs, paramIndex, paramCategory, true);
         }
     }
 
     /**
      * Gets the parameter index for SSA registers that are method parameters.
-     * -1 is returned for non-parameter registers.
+     * {@code -1} is returned for non-parameter registers.
      *
-     * @param ssaReg &gt;=0 SSA register to look up
-     * @return parameter index or -1 if not a parameter
+     * @param ssaReg {@code >=0;} SSA register to look up
+     * @return parameter index or {@code -1} if not a parameter
      */
     private int getParameterIndexForReg(int ssaReg) {
         SsaInsn defInsn = ssaMeth.getDefinitionForRegister(ssaReg);
         if (defInsn == null) {
             return -1;
         }
-        
+
         Rop opcode = defInsn.getOpcode();
 
-        // opcode == null for phi insns
+        // opcode == null for phi insns.
         if (opcode != null && opcode.getOpcode() == RegOps.MOVE_PARAM) {
             CstInsn origInsn = (CstInsn) defInsn.getOriginalRopInsn();
             return  ((CstInteger) origInsn.getConstant()).getValue();
@@ -222,20 +224,21 @@
     }
 
     /**
-     * Maps all local-associated registers that are not parameters. Tries to
-     * find an unreserved range that's wide enough for all of the SSA registers,
-     * and then tries to map them all to that range. If not all fit,
-     * a new range is tried until all registers have been fit.
+     * Maps all local-associated registers that are not parameters.
+     * Tries to find an unreserved range that's wide enough for all of
+     * the SSA registers, and then tries to map them all to that
+     * range. If not all fit, a new range is tried until all registers
+     * have been fit.
      */
     private void handleLocalAssociatedOther() {
-        for (ArrayList<RegisterSpec> specs: localVariables.values()) {
+        for (ArrayList<RegisterSpec> specs : localVariables.values()) {
             int ropReg = 0;
 
             boolean done;
             do {
                 int maxCategory = 1;
 
-                // compute max category for remaining unmapped registers
+                // Compute max category for remaining unmapped registers.
                 int sz = specs.size();
                 for (int i = 0; i < sz; i++) {
                     RegisterSpec ssaSpec = specs.get(i);
@@ -250,7 +253,7 @@
 
                 done = tryMapRegs(specs, ropReg, maxCategory, true);
 
-                // Increment for next call to findNext
+                // Increment for next call to findNext.
                 ropReg++;
             } while (!done);
         }
@@ -261,17 +264,19 @@
      * used rop space as reserved. SSA registers that don't fit are left
      * unmapped.
      *
-     * @param specs non-null; SSA registers to attempt to map
-     * @param ropReg &gt;=0 rop register to map to
-     * @param maxAllowedCategory 1 or 2, maximum category allowed in mapping.
-     * @param markReserved do so if true
-     * @return true if all registers wew mapped, false if some remain unmapped.
+     * @param specs {@code non-null;} SSA registers to attempt to map
+     * @param ropReg {@code >=0;} rop register to map to
+     * @param maxAllowedCategory {@code 1..2;} maximum category
+     * allowed in mapping.
+     * @param markReserved do so if {@code true}
+     * @return {@code true} if all registers were mapped, {@code false}
+     * if some remain unmapped
      */
     private boolean tryMapRegs(
             ArrayList<RegisterSpec> specs, int ropReg,
             int maxAllowedCategory, boolean markReserved) {
         boolean remaining = false;
-        for(RegisterSpec spec: specs) {
+        for (RegisterSpec spec : specs) {
             if (ssaRegsMapped.get(spec.getReg())) {
                 continue;
             }
@@ -291,11 +296,11 @@
     /**
      * Tries to map an SSA register to a rop register.
      *
-     * @param ssaSpec non-null; SSA register
-     * @param ropReg &gt;=0 rop register
-     * @param maxAllowedCategory 1 or 2, the maximum category that the SSA
-     * register is allowed to be.
-     * @return true if map succeeded, false if not.
+     * @param ssaSpec {@code non-null;} SSA register
+     * @param ropReg {@code >=0;} rop register
+     * @param maxAllowedCategory {@code 1..2;} the maximum category
+     * that the SSA register is allowed to be
+     * @return {@code true} if map succeeded, {@code false} if not
      */
     private boolean tryMapReg(RegisterSpec ssaSpec, int ropReg,
             int maxAllowedCategory) {
@@ -310,22 +315,22 @@
     }
 
     /**
-     * Marks a range of Rop registers as "reserved for a local variable"
+     * Marks a range of rop registers as "reserved for a local variable."
      *
-     * @param ropReg &gt;= 0 rop register to reserve
-     * @param category &gt; 0 width to reserve
+     * @param ropReg {@code >= 0;} rop register to reserve
+     * @param category {@code > 0;} width to reserve
      */
     private void markReserved(int ropReg, int category) {
         reservedRopRegs.set(ropReg, ropReg + category, true);
     }
 
     /**
-     * Checks to see if any Rop registers in the specified range are reserved
-     * for local variables or parameters
+     * Checks to see if any rop registers in the specified range are reserved
+     * for local variables or parameters.
      *
-     * @param ropRangeStart &gt;= 0 lowest Rop register
-     * @param width &gt; 0 number of Rop registers in range.
-     * @return true if any register in range is marked reserved
+     * @param ropRangeStart {@code >= 0;} lowest rop register
+     * @param width {@code > 0;} number of rop registers in range.
+     * @return {@code true} if any register in range is marked reserved
      */
     private boolean rangeContainsReserved(int ropRangeStart, int width) {
         for (int i = ropRangeStart; i < (ropRangeStart + width); i++) {
@@ -337,23 +342,23 @@
     }
 
     /**
-     * Returns true if given rop register represents the "this" pointer
-     * for a non-static method
+     * Returns true if given rop register represents the {@code this} pointer
+     * for a non-static method.
      *
      * @param startReg rop register
      * @return true if the "this" pointer is located here.
      */
     private boolean isThisPointerReg(int startReg) {
-        // "this" is always the first parameter
+        // "this" is always the first parameter.
         return startReg == 0 && !ssaMeth.isStatic();
     }
 
     /**
-     * Finds a range of unreserved Rop registers.
+     * Finds a range of unreserved rop registers.
      *
-     * @param startReg &gt;= 0; a Rop register to start the search at
-     * @param width &gt; 0; the width, in registers, required.
-     * @return &gt;= 0; start of available register range.
+     * @param startReg {@code >= 0;} a rop register to start the search at
+     * @param width {@code > 0;} the width, in registers, required.
+     * @return {@code >= 0;} start of available register range.
      */
     private int findNextUnreservedRopReg(int startReg, int width) {
         if (minimizeRegisters && !isThisPointerReg(startReg)) {
@@ -381,12 +386,12 @@
 
     /**
      * Finds a range of rop regs that can be used for local variables.
-     * If <code>MIX_LOCALS_AND_OTHER</code> is false, this means any
+     * If {@code MIX_LOCALS_AND_OTHER} is {@code false}, this means any
      * rop register that has not yet been used.
      *
-     * @param startReg &gt;= 0; a Rop register to start the search at
-     * @param width &gt; 0; the width, in registers, required.
-     * @return &gt;= 0; start of available register range.
+     * @param startReg {@code >= 0;} a rop register to start the search at
+     * @param width {@code > 0;} the width, in registers, required.
+     * @return {@code >= 0;} start of available register range.
      */
     private int findRopRegForLocal(int startReg, int width) {
         if (minimizeRegisters && !isThisPointerReg(startReg)) {
@@ -418,6 +423,7 @@
      */
     private void handleUnassociatedParameters() {
         int szSsaRegs = ssaMeth.getRegCount();
+
         for (int ssaReg = 0; ssaReg < szSsaRegs; ssaReg++) {
             if (ssaRegsMapped.get(ssaReg)) {
                 // We already did this one above
@@ -429,7 +435,7 @@
             RegisterSpec ssaSpec = getDefinitionSpecForSsaReg(ssaReg);
             if (paramIndex >= 0) {
                 addMapping(ssaSpec, paramIndex);
-            }            
+            }
         }
     }
 
@@ -437,13 +443,14 @@
      * Handles all insns that want a register range for their sources.
      */
     private void handleInvokeRangeInsns() {
-        for(NormalSsaInsn insn: invokeRangeInsns) {
+        for (NormalSsaInsn insn : invokeRangeInsns) {
             adjustAndMapSourceRangeRange(insn);
         }
     }
 
     /**
-     * Handles check cast results to reuse the same source register if possible
+     * Handles check cast results to reuse the same source register if
+     * possible.
      */
     private void handleCheckCastResults() {
         for (NormalSsaInsn insn : moveResultPseudoInsns) {
@@ -498,11 +505,11 @@
     }
 
     /**
-     * Maps all non-parameter, non-local variable
-     * registers.
+     * Maps all non-parameter, non-local variable registers.
      */
     private void handleNormalUnassociated() {
         int szSsaRegs = ssaMeth.getRegCount();
+
         for (int ssaReg = 0; ssaReg < szSsaRegs; ssaReg++) {
             if (ssaRegsMapped.get(ssaReg)) {
                 // We already did this one
@@ -525,30 +532,30 @@
     }
 
     /**
-     * Checks to see if <code>ssaSpec</code> can be mapped to
-     * <code>ropReg</code>. Checks interference graph and ensures
+     * Checks to see if {@code ssaSpec} can be mapped to
+     * {@code ropReg}. Checks interference graph and ensures
      * the range does not cross the parameter range.
      *
-     * @param ssaSpec non-null; SSA spec
+     * @param ssaSpec {@code non-null;} SSA spec
      * @param ropReg prosepctive new-namespace reg
-     * @return true if mapping is possible
+     * @return {@code true} if mapping is possible
      */
     private boolean canMapReg(RegisterSpec ssaSpec, int ropReg) {
         int category = ssaSpec.getCategory();
         return !(spansParamRange(ropReg, category)
                 || mapper.interferes(ssaSpec, ropReg));
     }
- 
+
     /**
-     * Returns true if the specified Rop register + category
-     * will cross the boundry between the lower <code>paramWidth</code>
+     * Returns true if the specified rop register + category
+     * will cross the boundry between the lower {@code paramWidth}
      * registers reserved for method params and the upper registers. We cannot
      * allocate a register that spans the param block and the normal block,
      * because we will be moving the param block to high registers later.
-     * 
+     *
      * @param ssaReg register in new namespace
      * @param category width that the register will have
-     * @return true in the case noted above.
+     * @return {@code true} in the case noted above
      */
     private boolean spansParamRange(int ssaReg, int category) {
         return ((ssaReg < paramRangeEnd)
@@ -561,7 +568,6 @@
      */
     private void analyzeInstructions() {
         ssaMeth.forEachInsn(new SsaInsn.Visitor() {
-
             /** {@inheritDoc} */
             public void visitMoveInsn(NormalSsaInsn insn) {
                 processInsn(insn);
@@ -579,15 +585,16 @@
 
             /**
              * This method collects three types of instructions:
-             * 1) Adds a local variable assignment to the
-             *    <code>localVariables</code> map.
-             * 2) Add move-result-pseudo to the
-             *    <code>moveResultPseudoInsns</code> list.
-             * 3) Add invoke-range to the
-             *    <code>invokeRangeInsns</code> list.
              *
-             * @param insn non-null; insn that may represent a local variable
-             * assignment.
+             * 1) Adds a local variable assignment to the
+             *    {@code localVariables} map.
+             * 2) Add move-result-pseudo to the
+             *    {@code moveResultPseudoInsns} list.
+             * 3) Add invoke-range to the
+             *    {@code invokeRangeInsns} list.
+             *
+             * @param insn {@code non-null;} insn that may represent a
+             * local variable assignment
              */
             private void processInsn(SsaInsn insn) {
                 RegisterSpec assignment;
@@ -596,7 +603,8 @@
                 if (assignment != null) {
                     LocalItem local = assignment.getLocalItem();
 
-                    ArrayList<RegisterSpec> regList = localVariables.get(local);
+                    ArrayList<RegisterSpec> regList
+                        = localVariables.get(local);
 
                     if (regList == null) {
                         regList = new ArrayList<RegisterSpec>();
@@ -622,16 +630,16 @@
     }
 
     /**
-     * Adds a mapping from an SSA register to a Rop register. <code>
-     * canMapReg</code> should have already been called.
+     * Adds a mapping from an SSA register to a rop register.
+     * {@link #canMapReg} should have already been called.
      *
-     * @param ssaSpec non-null; SSA register to map from
-     * @param ropReg &gt;=0; Rop register to map to
+     * @param ssaSpec {@code non-null;} SSA register to map from
+     * @param ropReg {@code >=0;} rop register to map to
      */
     private void addMapping(RegisterSpec ssaSpec, int ropReg) {
         int ssaReg = ssaSpec.getReg();
 
-        // An assertion
+        // An assertion.
         if (ssaRegsMapped.get(ssaReg) || !canMapReg(ssaSpec, ropReg)) {
             throw new RuntimeException(
                     "attempt to add invalid register mapping");
@@ -639,8 +647,7 @@
 
         if (DEBUG) {
             System.out.printf("Add mapping s%d -> v%d c:%d\n",
-                    ssaSpec.getReg(), ropReg, ssaSpec.getCategory());               
-
+                    ssaSpec.getReg(), ropReg, ssaSpec.getCategory());
         }
 
         int category = ssaSpec.getCategory();
@@ -652,19 +659,18 @@
 
     /**
      * Maps the source registers of the specified instruction such that they
-     * will fall in a contiguous range in Rop form. Moves are inserted as
+     * will fall in a contiguous range in rop form. Moves are inserted as
      * necessary to allow the range to be allocated.
      *
-     * @param insn non-null; insn whos sources to process
+     * @param insn {@code non-null;} insn whos sources to process
      */
     private void adjustAndMapSourceRangeRange(NormalSsaInsn insn) {
-        int newRegStart;
-
-        newRegStart = findRangeAndAdjust(insn);
+        int newRegStart = findRangeAndAdjust(insn);
 
         RegisterSpecList sources = insn.getSources();
         int szSources = sources.size();
         int nextRopReg = newRegStart;
+
         for (int i = 0; i < szSources; i++) {
             RegisterSpec source = sources.get(i);
             int sourceReg = source.getReg();
@@ -686,17 +692,20 @@
 
                 int szSimilar = similarRegisters.size();
 
-                // Try to map all SSA registers also associated with this local
+                /*
+                 * Try to map all SSA registers also associated with
+                 * this local.
+                 */
                 for (int j = 0; j < szSimilar; j++) {
                     RegisterSpec similarSpec = similarRegisters.get(j);
                     int similarReg = similarSpec.getReg();
 
-                    // ...and don't map anything that's also a source...
+                    // Don't map anything that's also a source.
                     if (-1 != sources.indexOfRegister(similarReg)) {
                         continue;
                     }
 
-                    // Registers left unmapped will get handled later
+                    // Registers left unmapped will get handled later.
                     tryMapReg(similarSpec, curRopReg, category);
                 }
             }
@@ -706,12 +715,12 @@
     /**
      * Find a contiguous rop register range that fits the specified
      * instruction's sources. First, try to center the range around
-     * sources that have already been mapped to Rop registers. If that fails,
+     * sources that have already been mapped to rop registers. If that fails,
      * just find a new contiguous range that doesn't interfere.
-
-     * @param insn non-null; the insn whose sources need to fit. Must be
-     * last insn in basic block.
-     * @return &gt;= 0 rop register of start of range
+     *
+     * @param insn {@code non-null;} the insn whose sources need to
+     * fit. Must be last insn in basic block.
+     * @return {@code >= 0;} rop register of start of range
      */
     private int findRangeAndAdjust(NormalSsaInsn insn) {
         RegisterSpecList sources = insn.getSources();
@@ -727,7 +736,7 @@
             rangeLength += categoriesForIndex[i];
         }
 
-        // The highest score of fits tried so far
+        // the highest score of fits tried so far
         int maxScore = Integer.MIN_VALUE;
         // the high scoring range's start
         int resultRangeStart = -1;
@@ -736,7 +745,7 @@
 
         /*
          * First, go through each source that's already been mapped. Try
-         * to center the range around the Rop register this source is mapped
+         * to center the range around the rop register this source is mapped
          * to.
          */
         int rangeStartOffset = 0;
@@ -794,13 +803,12 @@
         }
 
         /*
-         * Now, insert any moves required
+         * Now, insert any moves required.
          */
 
-        for (int i = resultMovesRequired.nextSetBit(0); i >= 0
-                ; i = resultMovesRequired.nextSetBit(i+1)) {
-            insn.changeOneSource(i,
-                    insertMoveBefore(insn, sources.get(i)));
+        for (int i = resultMovesRequired.nextSetBit(0); i >= 0;
+             i = resultMovesRequired.nextSetBit(i+1)) {
+            insn.changeOneSource(i, insertMoveBefore(insn, sources.get(i)));
         }
 
         return resultRangeStart;
@@ -811,14 +819,14 @@
      * specified instruction. Does not bother trying to center the range
      * around an already-mapped source register;
      *
-     * @param insn non-null; insn to build range for
-     * @param rangeLength &gt;=0 length required in register units.
-     * @param categoriesForIndex non-null; indexed by source index;
-     * the category for each source.
-     * @param outMovesRequired non-null; an output parameter indexed by
+     * @param insn {@code non-null;} insn to build range for
+     * @param rangeLength {@code >=0;} length required in register units
+     * @param categoriesForIndex {@code non-null;} indexed by source index;
+     * the category for each source
+     * @param outMovesRequired {@code non-null;} an output parameter indexed by
      * source index that will contain the set of sources which need
-     * moves inserted.
-     * @return the rop register that starts the fitting range.
+     * moves inserted
+     * @return the rop register that starts the fitting range
      */
     private int findAnyFittingRange(NormalSsaInsn insn, int rangeLength,
             int[] categoriesForIndex, BitSet outMovesRequired) {
@@ -842,15 +850,15 @@
      * Attempts to build a plan for fitting a range of sources into rop
      * registers.
      *
-     * @param ropReg &gt;=0 rop reg that begins range
-     * @param insn non-null; insn to plan range for
-     * @param categoriesForIndex non-null; indexed by source index;
-     * the category for each source.
-     * @param outMovesRequired non-null; an output parameter indexed by
+     * @param ropReg {@code >= 0;} rop reg that begins range
+     * @param insn {@code non-null;} insn to plan range for
+     * @param categoriesForIndex {@code non-null;} indexed by source index;
+     * the category for each source
+     * @param outMovesRequired {@code non-null;} an output parameter indexed by
      * source index that will contain the set of sources which need
-     * moves inserted.
+     * moves inserted
      * @return the width of the fit that that does not involve added moves or
-     * -1 if "no fit possible"
+     * {@code -1} if "no fit possible"
      */
     private int fitPlanForRange(int ropReg, NormalSsaInsn insn,
             int[] categoriesForIndex, BitSet outMovesRequired) {
@@ -860,7 +868,7 @@
         IntSet liveOut = insn.getBlock().getLiveOutRegs();
         RegisterSpecList liveOutSpecs = ssaSetToSpecs(liveOut);
 
-        // An SSA reg may only be mapped into a range once
+        // An SSA reg may only be mapped into a range once.
         BitSet seen = new BitSet(ssaMeth.getRegCount());
 
         for (int i = 0; i < szSources ; i++) {
@@ -874,7 +882,7 @@
 
             if (ssaRegsMapped.get(ssaReg)
                     && mapper.oldToNew(ssaReg) == ropReg) {
-                // A register already mapped appropriately
+                // This is a register that is already mapped appropriately.
                 fitWidth += category;
             } else if (rangeContainsReserved(ropReg, category)) {
                 fitWidth = -1;
@@ -882,19 +890,20 @@
             } else if (!ssaRegsMapped.get(ssaReg)
                     && canMapReg(ssaSpec, ropReg)
                     && !seen.get(ssaReg)) {
-                // A register that can be mapped appropriately
+                // This is a register that can be mapped appropriately.
                 fitWidth += category;
             } else if (!mapper.areAnyPinned(liveOutSpecs, ropReg, category)
                     && !mapper.areAnyPinned(sources, ropReg, category)) {
                 /*
-                 * A source that can be moved
-                 * We can insert a move as long as:
+                 * This is a source that can be moved. We can insert a
+                 * move as long as:
                  *
-                 *  - no SSA register pinned to the desired rop reg
-                 * is live out on the block
-                 *  - no SSA register pinned to desired rop reg is
-                 *  a source of this insn (since this may require
-                 * overlapping moves, which we can't presently handle)
+                 *   * no SSA register pinned to the desired rop reg
+                 *     is live out on the block
+                 *
+                 *   * no SSA register pinned to desired rop reg is
+                 *     a source of this insn (since this may require
+                 *     overlapping moves, which we can't presently handle)
                  */
 
                 outMovesRequired.set(i);
@@ -912,7 +921,7 @@
      * Converts a bit set of SSA registers into a RegisterSpecList containing
      * the definition specs of all the registers.
      *
-     * @param ssaSet non-null; set of SSA registers
+     * @param ssaSet {@code non-null;} set of SSA registers
      * @return list of RegisterSpecs as noted above
      */
     RegisterSpecList ssaSetToSpecs(IntSet ssaSet) {
@@ -924,21 +933,20 @@
         while (iter.hasNext()) {
             result.set(i++, getDefinitionSpecForSsaReg(iter.next()));
         }
-        
+
         return result;
     }
 
     /**
-     * Gets a local item associated with an ssa register, if one exists
+     * Gets a local item associated with an ssa register, if one exists.
      *
-     * @param ssaReg &gt;= 0 SSA register
-     * @return null-ok; associated local item or null
+     * @param ssaReg {@code >= 0;} SSA register
+     * @return {@code null-ok;} associated local item or null
      */
     private LocalItem getLocalItemForReg(int ssaReg) {
-        for(Map.Entry<LocalItem, ArrayList<RegisterSpec>> entry:
-                localVariables.entrySet()) {
-
-            for (RegisterSpec spec: entry.getValue()) {
+        for (Map.Entry<LocalItem, ArrayList<RegisterSpec>> entry :
+                 localVariables.entrySet()) {
+            for (RegisterSpec spec : entry.getValue()) {
                 if (spec.getReg() == ssaReg) {
                     return entry.getKey();
                 }
diff --git a/dx/src/com/android/dx/ssa/back/IdenticalBlockCombiner.java b/dx/src/com/android/dx/ssa/back/IdenticalBlockCombiner.java
index abc5fca..a639af5 100644
--- a/dx/src/com/android/dx/ssa/back/IdenticalBlockCombiner.java
+++ b/dx/src/com/android/dx/ssa/back/IdenticalBlockCombiner.java
@@ -34,14 +34,14 @@
  * frequently are created when catch blocks are edge-split.
  */
 public class IdenticalBlockCombiner {
-
-    private RopMethod ropMethod;
-    private BasicBlockList blocks;
-    private BasicBlockList newBlocks;
+    private final RopMethod ropMethod;
+    private final BasicBlockList blocks;
+    private final BasicBlockList newBlocks;
 
     /**
-     * Constructs instance. Call <code>process()</code> to run.
-     * @param rm instance to process
+     * Constructs instance. Call {@code process()} to run.
+     * 
+     * @param rm {@code non-null;} instance to process
      */
     public IdenticalBlockCombiner(RopMethod rm) {
         ropMethod = rm;
@@ -50,10 +50,11 @@
     }
 
     /**
-     * Runs algorithm.  TODO: this is n^2, and could be made linear-ish with
-     * a hash.
+     * Runs algorithm. TODO: This is n^2, and could be made linear-ish with
+     * a hash. In particular, hash the contents of each block and only
+     * compare blocks with the same hash.
      *
-     * @return new method that has been processed
+     * @return {@code non-null;} new method that has been processed
      */
     public RopMethod process() {
         int szBlocks = blocks.size();
@@ -78,14 +79,15 @@
 
                 BasicBlock iBlock = blocks.labelToBlock(iLabel);
 
-                if (toDelete.get(iLabel) || iBlock.getSuccessors().size() > 1) {
+                if (toDelete.get(iLabel)
+                        || iBlock.getSuccessors().size() > 1) {
                     continue;
                 }
 
                 IntList toCombine = new IntList();
 
                 // ...and see if they can be combined with any other preds...
-                for (int j = i + 1; j <szPreds; j++) {
+                for (int j = i + 1; j < szPreds; j++) {
                     int jLabel = preds.get(j);
                     BasicBlock jBlock = blocks.labelToBlock(jLabel);
 
@@ -101,7 +103,7 @@
             }
         }
 
-        for (int i = szBlocks - 1; i > 0; i--) {
+        for (int i = szBlocks - 1; i >= 0; i--) {
             if (toDelete.get(newBlocks.get(i).getLabel())) {
                 newBlocks.set(i, null);
             }
@@ -113,7 +115,14 @@
         return new RopMethod(newBlocks, ropMethod.getFirstLabel());
     }
 
-    private boolean compareInsns(BasicBlock a, BasicBlock b) {
+    /**
+     * Helper method to compare the contents of two blocks.
+     * 
+     * @param a {@code non-null;} a block to compare
+     * @param b {@code non-null;} another block to compare
+     * @return {@code true} iff the two blocks' instructions are the same
+     */
+    private static boolean compareInsns(BasicBlock a, BasicBlock b) {
         return a.getInsns().contentEquals(b.getInsns());
     }
 
@@ -131,11 +140,7 @@
         for (int i = 0; i < szBetas; i++) {
             int betaLabel = betaLabels.get(i);
             BasicBlock bb = blocks.labelToBlock(betaLabel);
-
-            IntList preds;
-
-            preds = ropMethod.labelToPredecessors(bb.getLabel());
-
+            IntList preds = ropMethod.labelToPredecessors(bb.getLabel());
             int szPreds = preds.size();
 
             for (int j = 0; j < szPreds; j++) {
@@ -147,19 +152,19 @@
 
     /**
      * Replaces one of a block's successors with a different label. Constructs
-     * an updated BasicBlock instance and places it in <code>newBlocks</code>.
+     * an updated BasicBlock instance and places it in {@code newBlocks}.
      *
      * @param block block to replace
      * @param oldLabel label of successor to replace
      * @param newLabel label of new successor
      */
     private void replaceSucc(BasicBlock block, int oldLabel, int newLabel) {
-
         IntList newSuccessors = block.getSuccessors().mutableCopy();
         int newPrimarySuccessor;
 
         newSuccessors.set(newSuccessors.indexOf(oldLabel), newLabel);
         newPrimarySuccessor = block.getPrimarySuccessor();
+
         if (newPrimarySuccessor == oldLabel) {
             newPrimarySuccessor = newLabel;
         }
diff --git a/dx/src/com/android/dx/ssa/back/InterferenceGraph.java b/dx/src/com/android/dx/ssa/back/InterferenceGraph.java
index 282420b..e6cde62 100644
--- a/dx/src/com/android/dx/ssa/back/InterferenceGraph.java
+++ b/dx/src/com/android/dx/ssa/back/InterferenceGraph.java
@@ -34,14 +34,17 @@
  * A register interference graph
  */
 public class InterferenceGraph {
-    /** interference graph, indexed by register in both dimensions  */
+    /**
+     * {@code non-null;} interference graph, indexed by register in
+     * both dimensions
+     */
     private final ArrayList<IntSet> interference;
 
     /**
      * Creates a new graph.
      *
-     * @param countRegs &gt;=0 the start count of registers in the namespace.
-     * New registers can be added subsequently.
+     * @param countRegs {@code >= 0;} the start count of registers in
+     * the namespace. New registers can be added subsequently.
      */
     public InterferenceGraph(int countRegs) {
         interference = new ArrayList<IntSet>(countRegs);
@@ -83,9 +86,9 @@
     /**
      * Merges the interference set for a register into a given bit set
      *
-     * @param reg &gt;=0 register
-     * @param set non-null; interference set; will be merged with set for
-     * given register
+     * @param reg {@code >= 0;} register
+     * @param set {@code non-null;} interference set; will be merged
+     * with set for given register
      */
     public void mergeInterferenceSet(int reg, IntSet set) {
         if (reg < interference.size()) {
@@ -100,8 +103,10 @@
      */
     private void ensureCapacity(int size) {
         int countRegs = interference.size();
+
         interference.ensureCapacity(size);
-        for (int i = countRegs ; i < size; i++) {
+
+        for (int i = countRegs; i < size; i++) {
             interference.add(SetFactory.makeInterferenceSet(size));
         }
     }
diff --git a/dx/src/com/android/dx/ssa/back/LivenessAnalyzer.java b/dx/src/com/android/dx/ssa/back/LivenessAnalyzer.java
index 5ae6e07..cd3f7d2 100644
--- a/dx/src/com/android/dx/ssa/back/LivenessAnalyzer.java
+++ b/dx/src/com/android/dx/ssa/back/LivenessAnalyzer.java
@@ -28,28 +28,27 @@
 
 /**
  * From Appel "Modern Compiler Implementation in Java" algorithm 19.17
- * Calculate the live ranges for register <code>reg</code>.<p>
+ * Calculate the live ranges for register {@code reg}.<p>
  *
  * v = regV <p>
  * s = insn <p>
  * M = visitedBlocks <p>
  */
 public class LivenessAnalyzer {
-
     /**
-     * non-null; index by basic block indexed set of basic blocks
+     * {@code non-null;} index by basic block indexed set of basic blocks
      * that have already been visited. "M" as written in the original Appel
      * algorithm.
      */
     private final BitSet visitedBlocks;
 
     /**
-     * non-null; set of blocks remaing to visit as "live out as block"
+     * {@code non-null;} set of blocks remaing to visit as "live out as block"
      */
     private final BitSet liveOutBlocks;
 
     /**
-     * &gt;=0; SSA register currently being analyzed.
+     * {@code >=0;} SSA register currently being analyzed.
      * "v" in the original Appel algorithm.
      */
     private final int regV;
@@ -61,33 +60,34 @@
     private final InterferenceGraph interference;
 
     /** block "n" in Appel 19.17 */
-    SsaBasicBlock blockN;
+    private SsaBasicBlock blockN;
 
-    /** index of statement <code>s</code> in <code>blockN</code>*/
+    /** index of statement {@code s} in {@code blockN} */
     private int statementIndex;
 
-    /** the next function to call. one of the four constants below */
-    private int nextFunction;
+    /** the next function to call */
+    private NextFunction nextFunction;
 
-    /** constants for nextFunction */
-    static final int LIVE_IN_AT_STATEMENT = 1;
-    static final int LIVE_OUT_AT_STATEMENT = 2;
-    static final int LIVE_OUT_AT_BLOCK = 3;
-    static final int DONE = 4;
+    /** constants for {@link #nextFunction} */
+    private static enum NextFunction {
+        LIVE_IN_AT_STATEMENT,
+            LIVE_OUT_AT_STATEMENT,
+            LIVE_OUT_AT_BLOCK,
+            DONE;
+    }
 
     /**
      * Runs register liveness algorithm for a method, updating the
-     * live in/out information in <code>SsaBasicBlock</code> instances and
+     * live in/out information in {@code SsaBasicBlock} instances and
      * returning an interference graph.
      *
-     * @param ssaMeth non-null; Method to process.
-     * @return non-null; interference graph indexed by SSA registers in both
-     * directions.
+     * @param ssaMeth {@code non-null;} method to process
+     * @return {@code non-null;} interference graph indexed by SSA
+     * registers in both directions
      */
     public static InterferenceGraph constructInterferenceGraph(
             SsaMethod ssaMeth) {
         int szRegs = ssaMeth.getRegCount();
-
         InterferenceGraph interference = new InterferenceGraph(szRegs);
 
         for (int i = 0; i < szRegs; i++) {
@@ -102,42 +102,43 @@
     /**
      * Makes liveness analyzer instance for specific register.
      *
-     * @param ssaMeth non-null; method to process
+     * @param ssaMeth {@code non-null;} method to process
      * @param reg register whose liveness to analyze
-     * @param interference non-null; indexed by SSA reg in both dimensions;
-     * graph to update
+     * @param interference {@code non-null;} indexed by SSA reg in
+     * both dimensions; graph to update
      *
      */
-    private LivenessAnalyzer(final SsaMethod ssaMeth, final int reg,
+    private LivenessAnalyzer(SsaMethod ssaMeth, int reg,
             InterferenceGraph interference) {
+        int blocksSz = ssaMeth.getBlocks().size();
+
         this.ssaMeth = ssaMeth;
         this.regV = reg;
-        visitedBlocks = new BitSet(ssaMeth.getBlocks().size());
-        liveOutBlocks = new BitSet(ssaMeth.getBlocks().size());
+        visitedBlocks = new BitSet(blocksSz);
+        liveOutBlocks = new BitSet(blocksSz);
         this.interference = interference;
     }
 
     /**
-     * The algorithm in Appel is presented in
-     * partial tail-recursion form. Obviously, that's not
-     * efficient in java, so this function serves
-     * as the dispatcher instead.
+     * The algorithm in Appel is presented in partial tail-recursion
+     * form. Obviously, that's not efficient in java, so this function
+     * serves as the dispatcher instead.
      */
     private void handleTailRecursion() {
-        while (nextFunction != DONE) {
+        while (nextFunction != NextFunction.DONE) {
             switch (nextFunction) {
                 case LIVE_IN_AT_STATEMENT:
-                    nextFunction = DONE;
+                    nextFunction = NextFunction.DONE;
                     liveInAtStatement();
                     break;
 
                 case LIVE_OUT_AT_STATEMENT:
-                    nextFunction = DONE;
+                    nextFunction = NextFunction.DONE;
                     liveOutAtStatement();
                     break;
 
                 case LIVE_OUT_AT_BLOCK:
-                    nextFunction = DONE;
+                    nextFunction = NextFunction.DONE;
                     liveOutAtBlock();
                     break;
 
@@ -147,23 +148,23 @@
     }
 
     /**
-     * From Appel algorithm 19.17
+     * From Appel algorithm 19.17.
      */
     public void run() {
         List<SsaInsn> useList = ssaMeth.getUseListForRegister(regV);
 
-        for (SsaInsn insn: useList) {
-            nextFunction = DONE;
+        for (SsaInsn insn : useList) {
+            nextFunction = NextFunction.DONE;
 
             if (insn instanceof PhiInsn) {
-                // If s is a phi-function with V as it's ith argument
+                // If s is a phi-function with V as it's ith argument.
                 PhiInsn phi = (PhiInsn) insn;
 
-                for (SsaBasicBlock pred: phi.predBlocksForReg(regV, ssaMeth)) {
-
+                for (SsaBasicBlock pred :
+                         phi.predBlocksForReg(regV, ssaMeth)) {
                     blockN = pred;
 
-                    nextFunction = LIVE_OUT_AT_BLOCK;
+                    nextFunction = NextFunction.LIVE_OUT_AT_BLOCK;
                     handleTailRecursion();
                 }
             } else {
@@ -175,7 +176,7 @@
                             "insn not found in it's own block");
                 }
 
-                nextFunction = LIVE_IN_AT_STATEMENT;
+                nextFunction = NextFunction.LIVE_IN_AT_STATEMENT;
                 handleTailRecursion();
             }
         }
@@ -184,13 +185,13 @@
         while ((nextLiveOutBlock = liveOutBlocks.nextSetBit(0)) >= 0) {
             blockN = ssaMeth.getBlocks().get(nextLiveOutBlock);
             liveOutBlocks.clear(nextLiveOutBlock);
-            nextFunction = LIVE_OUT_AT_BLOCK;
+            nextFunction = NextFunction.LIVE_OUT_AT_BLOCK;
             handleTailRecursion();
         }
     }
 
     /**
-     * "v is live-out at n"
+     * "v is live-out at n."
      */
     private void liveOutAtBlock() {
         if (! visitedBlocks.get(blockN.getIndex())) {
@@ -204,15 +205,14 @@
 
             // Live out at last statement in blockN
             statementIndex = insns.size() - 1;
-            nextFunction = LIVE_OUT_AT_STATEMENT;
+            nextFunction = NextFunction.LIVE_OUT_AT_STATEMENT;
         }
     }
 
     /**
-     * "v is live-in at s"
+     * "v is live-in at s."
      */
     private void liveInAtStatement() {
-
         // if s is the first statement in block N
         if (statementIndex == 0) {
             // v is live-in at n
@@ -224,23 +224,22 @@
         } else {
             // Let s' be the statement preceeding s
             statementIndex -= 1;
-            nextFunction = LIVE_OUT_AT_STATEMENT;
+            nextFunction = NextFunction.LIVE_OUT_AT_STATEMENT;
         }
     }
 
     /**
-     * "v is live-out at s"
+     * "v is live-out at s."
      */
     private void liveOutAtStatement() {
-
         SsaInsn statement = blockN.getInsns().get(statementIndex);
         RegisterSpec rs = statement.getResult();
 
         if (!statement.isResultReg(regV)) {
-            if(rs != null) {
+            if (rs != null) {
                 interference.add(regV, rs.getReg());
             }
-            nextFunction = LIVE_IN_AT_STATEMENT;
+            nextFunction = NextFunction.LIVE_IN_AT_STATEMENT;
         }
     }
 
@@ -253,12 +252,12 @@
      * as the result of another phi, and the phi removal move scheduler may
      * generate moves that over-write the live result.
      *
-     * @param ssaMeth non-null; method to pricess
-     * @param interference non-null; interference graph
+     * @param ssaMeth {@code non-null;} method to pricess
+     * @param interference {@code non-null;} interference graph
      */
     private static void coInterferePhis(SsaMethod ssaMeth,
             InterferenceGraph interference) {
-        for (SsaBasicBlock b: ssaMeth.getBlocks()) {
+        for (SsaBasicBlock b : ssaMeth.getBlocks()) {
             List<SsaInsn> phis = b.getPhiInsns();
 
             int szPhis = phis.size();
diff --git a/dx/src/com/android/dx/ssa/back/NullRegisterAllocator.java b/dx/src/com/android/dx/ssa/back/NullRegisterAllocator.java
index cd3b2f1..f6dc961 100644
--- a/dx/src/com/android/dx/ssa/back/NullRegisterAllocator.java
+++ b/dx/src/com/android/dx/ssa/back/NullRegisterAllocator.java
@@ -29,11 +29,9 @@
  * about normal or wide categories. Used for debugging.
  */
 public class NullRegisterAllocator extends RegisterAllocator {
-
     /** {@inheritDoc} */
-    public NullRegisterAllocator(
-            final SsaMethod ssaMeth, final InterferenceGraph interference) {
-
+    public NullRegisterAllocator(SsaMethod ssaMeth,
+            InterferenceGraph interference) {
         super(ssaMeth, interference);
     }
 
@@ -49,8 +47,7 @@
     public RegisterMapper allocateRegisters() {
         int oldRegCount = ssaMeth.getRegCount();
 
-        BasicRegisterMapper mapper
-                = new BasicRegisterMapper(oldRegCount);
+        BasicRegisterMapper mapper = new BasicRegisterMapper(oldRegCount);
 
         for (int i = 0; i < oldRegCount; i++) {
             mapper.addMapping(i, i*2, 2);
diff --git a/dx/src/com/android/dx/ssa/back/RegisterAllocator.java b/dx/src/com/android/dx/ssa/back/RegisterAllocator.java
index 764b03a..e75eee1 100644
--- a/dx/src/com/android/dx/ssa/back/RegisterAllocator.java
+++ b/dx/src/com/android/dx/ssa/back/RegisterAllocator.java
@@ -34,10 +34,9 @@
 import java.util.ArrayList;
 
 /**
- * Base class of all register allocators
+ * Base class of all register allocators.
  */
 public abstract class RegisterAllocator {
-
     /** method being processed */
     protected final SsaMethod ssaMeth;
 
@@ -45,13 +44,13 @@
     protected final InterferenceGraph interference;
 
     /**
-     * Creates an instance. Call <code>allocateRegisters</code> to run.
+     * Creates an instance. Call {@code allocateRegisters} to run.
      * @param ssaMeth method to process.
      * @param interference Interference graph, indexed by register in both
      * dimensions.
      */
-    public RegisterAllocator(
-            final SsaMethod ssaMeth, final InterferenceGraph interference) {
+    public RegisterAllocator(SsaMethod ssaMeth,
+            InterferenceGraph interference) {
         this.ssaMeth = ssaMeth;
         this.interference = interference;
     }
@@ -61,26 +60,26 @@
      * of the namespace, and thus should be moved up to the top of the
      * namespace after phi removal.
      *
-     * @return true if params should be moved from low to high.
+     * @return {@code true} if params should be moved from low to high
      */
     public abstract boolean wantsParamsMovedHigh();
 
     /**
      * Runs the algorithm.
-     * @return a register mapper to apply to the <code>SsaMethod</code>
+     * 
+     * @return a register mapper to apply to the {@code SsaMethod}
      */
     public abstract RegisterMapper allocateRegisters();
 
     /**
      * Returns the category (width) of the definition site of the register.
-     * Returns 1 for undefined registers.
+     * Returns {@code 1} for undefined registers.
      *
      * @param reg register
-     * @return 1 or 2
+     * @return {@code 1..2}
      */
-    protected int getCategoryForSsaReg(int reg) {
-        SsaInsn definition;
-        definition = ssaMeth.getDefinitionForRegister(reg);
+    protected final int getCategoryForSsaReg(int reg) {
+        SsaInsn definition = ssaMeth.getDefinitionForRegister(reg);
 
         if (definition == null) {
             // an undefined reg
@@ -93,25 +92,26 @@
     /**
      * Returns the RegisterSpec of the definition of the register.
      *
-     * @param reg &gt;= 0 SSA register
+     * @param reg {@code >= 0;} SSA register
      * @return definition spec of the register or null if it is never defined
-     * (for the case of "version 0" SSA registers).
+     * (for the case of "version 0" SSA registers)
      */
-    protected RegisterSpec getDefinitionSpecForSsaReg(int reg) {
-        SsaInsn definition;
-        definition = ssaMeth.getDefinitionForRegister(reg);
+    protected final RegisterSpec getDefinitionSpecForSsaReg(int reg) {
+        SsaInsn definition = ssaMeth.getDefinitionForRegister(reg);
 
         return definition == null ? null : definition.getResult();
     }
 
     /**
      * Returns true if the definition site of this register is a
-     * move-param (ie, this is a method parameter)
+     * move-param (ie, this is a method parameter).
+     * 
      * @param reg register in question
-     * @return true if this is a method parameter
+     * @return {@code true} if this is a method parameter
      */
     protected boolean isDefinitionMoveParam(int reg) {
         SsaInsn defInsn = ssaMeth.getDefinitionForRegister(reg);
+
         if (defInsn instanceof NormalSsaInsn) {
             NormalSsaInsn ndefInsn = (NormalSsaInsn) defInsn;
 
@@ -127,19 +127,18 @@
      * interference graph in the process. The insn currently must be the
      * last insn in a block.
      *
-     * @param insn non-null; insn to insert move before, must be last insn
-     * in block.
-     * @param reg non-null; SSA register to duplicate
-     * @return non-null; spec of new SSA register created by move
+     * @param insn {@code non-null;} insn to insert move before, must
+     * be last insn in block
+     * @param reg {@code non-null;} SSA register to duplicate
+     * @return {@code non-null;} spec of new SSA register created by move
      */
     protected final RegisterSpec insertMoveBefore(SsaInsn insn,
             RegisterSpec reg) {
-
         SsaBasicBlock block = insn.getBlock();
         ArrayList<SsaInsn> insns = block.getInsns();
         int insnIndex = insns.indexOf(insn);
 
-        if (insnIndex < 0 ) {
+        if (insnIndex < 0) {
             throw new IllegalArgumentException (
                     "specified insn is not in this block");
         }
@@ -155,19 +154,17 @@
         }
 
         /*
-         * Get new register and make new move instruction
+         * Get new register and make new move instruction.
          */
 
-        // new result must not have associated local variable
+        // The new result must not have an associated local variable.
         RegisterSpec newRegSpec = RegisterSpec.make(ssaMeth.makeNewSsaReg(),
                 reg.getTypeBearer());
 
-        SsaInsn toAdd;
-
-        toAdd = SsaInsn.makeFromRop(
-                    new PlainInsn(Rops.opMove(newRegSpec.getType()),
-                            SourcePosition.NO_INFO, newRegSpec,
-                            RegisterSpecList.make(reg)), block);
+        SsaInsn toAdd = SsaInsn.makeFromRop(
+                new PlainInsn(Rops.opMove(newRegSpec.getType()),
+                        SourcePosition.NO_INFO, newRegSpec,
+                        RegisterSpecList.make(reg)), block);
 
         insns.add(insnIndex, toAdd);
 
@@ -179,17 +176,13 @@
          */
 
         IntSet liveOut = block.getLiveOutRegs();
-
-        RegisterSpec result = insn.getResult();
-        int resultReg = (result == null) ? -1 : result.getReg();
-
         IntIterator liveOutIter = liveOut.iterator();
 
-        while(liveOutIter.hasNext()) {
+        while (liveOutIter.hasNext()) {
             interference.add(newReg, liveOutIter.next());
         }
 
-        // Everything that's a source in the last insn interferes
+        // Everything that's a source in the last insn interferes.
         RegisterSpecList sources = insn.getSources();
         int szSources = sources.size();
 
diff --git a/dx/src/com/android/dx/ssa/back/SsaToRop.java b/dx/src/com/android/dx/ssa/back/SsaToRop.java
index 1c59549..0ecbead 100644
--- a/dx/src/com/android/dx/ssa/back/SsaToRop.java
+++ b/dx/src/com/android/dx/ssa/back/SsaToRop.java
@@ -38,7 +38,9 @@
 import com.android.dx.util.Hex;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.BitSet;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 
@@ -46,55 +48,67 @@
  * Converts a method in SSA form to ROP form.
  */
 public class SsaToRop {
-
+    /** local debug flag */
     private static final boolean DEBUG = false;
 
-    /** non-null; method to process */
+    /** {@code non-null;} method to process */
     private final SsaMethod ssaMeth;
 
     /**
-     * true if the converter should attempt to minimize
+     * {@code true} if the converter should attempt to minimize
      * the rop-form register count
      */
     private final boolean minimizeRegisters;
 
-    /** interference graph */
-    private InterferenceGraph interference;
+    /** {@code non-null;} interference graph */
+    private final InterferenceGraph interference;
 
     /**
      * Converts a method in SSA form to ROP form.
-     * @param ssaMeth input
-     * @return non-null; rop-form output
+     * 
+     * @param ssaMeth {@code non-null;} method to process
+     * @param minimizeRegisters {@code true} if the converter should
+     * attempt to minimize the rop-form register count
+     * @return {@code non-null;} rop-form output
      */
     public static RopMethod convertToRopMethod(SsaMethod ssaMeth,
             boolean minimizeRegisters) {
         return new SsaToRop(ssaMeth, minimizeRegisters).convert();
     }
 
-    private SsaToRop(final SsaMethod ssaMethod, boolean minimizeRegisters) {
+    /**
+     * Constructs an instance.
+     * 
+     * @param ssaMeth {@code non-null;} method to process
+     * @param minimizeRegisters {@code true} if the converter should
+     * attempt to minimize the rop-form register count
+     */
+    private SsaToRop(SsaMethod ssaMethod, boolean minimizeRegisters) {
         this.minimizeRegisters = minimizeRegisters;
         this.ssaMeth = ssaMethod;
+        this.interference =
+            LivenessAnalyzer.constructInterferenceGraph(ssaMethod);
     }
 
+    /**
+     * Performs the conversion.
+     * 
+     * @return {@code non-null;} rop-form output
+     */
     private RopMethod convert() {
-        interference = LivenessAnalyzer.constructInterferenceGraph(ssaMeth);
-
         if (DEBUG) {
             interference.dumpToStdout();
         }
 
-        RegisterAllocator allocator;
-        RegisterMapper mapper;
+        // These are other allocators for debugging or historical comparison:
+        // allocator = new NullRegisterAllocator(ssaMeth, interference);
+        // allocator = new FirstFitAllocator(ssaMeth, interference);
 
-        // These are other allocators for debugging or historical comparison
+        RegisterAllocator allocator =
+            new FirstFitLocalCombiningAllocator(ssaMeth, interference,
+                    minimizeRegisters);
 
-        //allocator = new NullRegisterAllocator(ssaMeth, interference);
-        //allocator = new FirstFitAllocator(ssaMeth, interference);
-
-        allocator = new FirstFitLocalCombiningAllocator(ssaMeth, interference,
-                minimizeRegisters);
-
-        mapper = allocator.allocateRegisters();
+        RegisterMapper mapper = allocator.allocateRegisters();
 
         if (DEBUG) {
             System.out.println("Printing reg map");
@@ -113,22 +127,20 @@
 
         removeEmptyGotos();
 
-        RopMethod ropMethod;
-
-        ropMethod = convertToRop();
-
+        RopMethod ropMethod = new RopMethod(convertBasicBlocks(),
+                ssaMeth.blockIndexToRopLabel(ssaMeth.getEntryBlockIndex()));
         ropMethod = new IdenticalBlockCombiner(ropMethod).process();
 
         return ropMethod;
     }
 
-
     /**
-     * Removes all blocks containing only GOTOs from the control flow. Although
-     * much of this work will be done later when converting from rop to dex,
-     * not all simplification cases can be handled there. Furthermore, any no-op
-     * block between the exit block and blocks containing the real return or
-     * throw statements must be removed.
+     * Removes all blocks containing only GOTOs from the control flow. 
+     * Although much of this work will be done later when converting
+     * from rop to dex, not all simplification cases can be handled
+     * there. Furthermore, any no-op block between the exit block and
+     * blocks containing the real return or throw statements must be
+     * removed.
      */
     private void removeEmptyGotos() {
         final ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks();
@@ -139,8 +151,7 @@
 
                 if ((insns.size() == 1)
                         && (insns.get(0).getOpcode() == Rops.GOTO)) {
-
-                    BitSet preds = (BitSet)b.getPredecessors().clone();
+                    BitSet preds = (BitSet) b.getPredecessors().clone();
 
                     for (int i = preds.nextSetBit(0); i >= 0;
                             i = preds.nextSetBit(i + 1)) {
@@ -154,89 +165,49 @@
     }
 
     /**
-     * This method is not presently used.
-     * @return a list of registers ordered by most-frequently-used
-     * to least-frequently-used. Each register is listed once and only once.
-     */
-    public int[] getRegistersByFrequency() {
-        int regCount = ssaMeth.getRegCount();
-        Integer[] ret = new Integer[ssaMeth.getRegCount()];
-
-        for (int i = 0; i < regCount; i++) {
-            ret[i] = i;
-        }
-
-        java.util.Arrays.sort(ret, new java.util.Comparator<Integer>() {
-            public int compare (Integer o1, Integer o2) {
-                return ssaMeth.getUseListForRegister(o2).size()
-                        - ssaMeth.getUseListForRegister(o1).size();
-            }
-
-            public boolean equals(Object o) {
-                return o == this;
-            }
-        });
-
-        int result[] = new int[regCount];
-
-        for (int i = 0; i < regCount; i++) {
-            result[i] = ret[i];
-        }
-
-        return result;
-    }
-
-    /**
-     * See Appel 19.6
-     * To remove the phi instructions in an edge-split SSA representation
-     * we know we can always insert a move in a predecessor block
+     * See Appel 19.6. To remove the phi instructions in an edge-split
+     * SSA representation we know we can always insert a move in a
+     * predecessor block.
      */
     private void removePhiFunctions() {
-        for (SsaBasicBlock block: ssaMeth.getBlocks()) {
-            // Add moves in all the pred blocks for each phi insn`
-            block.forEachPhiInsn(new PhiVisitor(block));
-            // Delete the phi insns
+        ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks();
+        
+        for (SsaBasicBlock block : blocks) {
+            // Add moves in all the pred blocks for each phi insn.
+            block.forEachPhiInsn(new PhiVisitor(blocks));
+
+            // Delete the phi insns.
             block.removeAllPhiInsns();
         }
 
         /*
-         * After all move insns have been added: sort them so they don't
-         * destructively interfere
+         * After all move insns have been added, sort them so they don't
+         * destructively interfere.
          */
-        for (SsaBasicBlock block: ssaMeth.getBlocks()) {
+        for (SsaBasicBlock block : blocks) {
             block.scheduleMovesFromPhis();
         }
     }
 
     /**
-     * PhiSuccessorUpdater for adding move instructions to predecessors based
-     * on phi insns.
+     * Helper for {@link #removePhiFunctions}: PhiSuccessorUpdater for
+     * adding move instructions to predecessors based on phi insns.
      */
-    private class PhiVisitor implements PhiInsn.Visitor {
-        SsaBasicBlock block;
+    private static class PhiVisitor implements PhiInsn.Visitor {
+        private final ArrayList<SsaBasicBlock> blocks;
 
-        PhiVisitor (final SsaBasicBlock block) {
-            this.block = block;
+        public PhiVisitor(ArrayList<SsaBasicBlock> blocks) {
+            this.blocks = blocks;
         }
 
-        public void visitPhiInsn (PhiInsn insn) {
-            RegisterSpecList sources;
-            RegisterSpec result;
-            ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks();
-
-            sources = insn.getSources();
-            result = insn.getResult();
-
+        public void visitPhiInsn(PhiInsn insn) {
+            RegisterSpecList sources = insn.getSources();
+            RegisterSpec result = insn.getResult();
             int sz = sources.size();
 
-            for (int i = 0; i <sz; i++) {
-                RegisterSpec source;
-
-                source = sources.get(i);
-
-                SsaBasicBlock predBlock;
-
-                predBlock = blocks.get(
+            for (int i = 0; i < sz; i++) {
+                RegisterSpec source = sources.get(i);
+                SsaBasicBlock predBlock = blocks.get(
                         insn.predBlockIndexForSourcesIndex(i));
 
                 predBlock.addMoveToEnd(result, source);
@@ -250,9 +221,7 @@
      * Dalvik calling convention.
      */
     private void moveParametersToHighRegisters() {
-
         int paramWidth = ssaMeth.getParamWidth();
-
         BasicRegisterMapper mapper
                 = new BasicRegisterMapper(ssaMeth.getRegCount());
         int regCount = ssaMeth.getRegCount();
@@ -273,29 +242,25 @@
         ssaMeth.mapRegisters(mapper);
     }
 
-    private RopMethod convertToRop() {
-        return new RopMethod(convertBasicBlocks(),
-                ssaMeth.blockIndexToRopLabel(ssaMeth.getEntryBlockIndex()));
-    }
-
     /**
      * @return rop-form basic block list
      */
     private BasicBlockList convertBasicBlocks() {
         ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks();
-        // Exit block may be null
+
+        // Exit block may be null.
         SsaBasicBlock exitBlock = ssaMeth.getExitBlock();
 
         int ropBlockCount = ssaMeth.getCountReachableBlocks();
 
-        // Don't count the exit block, if it exists
+        // Don't count the exit block, if it exists.
         ropBlockCount -= (exitBlock == null) ? 0 : 1;
 
         BasicBlockList result = new BasicBlockList(ropBlockCount);
 
-        // Convert all the reachable blocks except the exit block
+        // Convert all the reachable blocks except the exit block.
         int ropBlockIndex = 0;
-        for(SsaBasicBlock b : blocks) {
+        for (SsaBasicBlock b : blocks) {
             if (b.isReachable() && b != exitBlock) {
                 result.set(ropBlockIndex++, convertBasicBlock(b));
             }
@@ -303,8 +268,8 @@
 
         // The exit block, which is discarded, must do nothing.
         if (exitBlock != null && exitBlock.getInsns().size() != 0) {
-            throw new RuntimeException
-                    ("Exit block must have no insns when leaving SSA form");
+            throw new RuntimeException(
+                    "Exit block must have no insns when leaving SSA form");
         }
 
         return result;
@@ -314,11 +279,10 @@
      * Validates that a basic block is a valid end predecessor. It must
      * end in a RETURN or a THROW. Throws a runtime exception on error.
      *
-     * @param b non-null; block to validate
+     * @param b {@code non-null;} block to validate
      * @throws RuntimeException on error
      */
     private void verifyValidExitPredecessor(SsaBasicBlock b) {
-
         ArrayList<SsaInsn> insns = b.getInsns();
         SsaInsn lastInsn = insns.get(insns.size() - 1);
         Rop opcode = lastInsn.getOpcode();
@@ -334,22 +298,21 @@
      * Converts a single basic block to rop form.
      *
      * @param block SSA block to process
-     * @return ROP block
+     * @return {@code non-null;} ROP block
      */
     private BasicBlock convertBasicBlock(SsaBasicBlock block) {
-        BasicBlock result;
         IntList successorList = block.getRopLabelSuccessorList();
         int primarySuccessorLabel = block.getPrimarySuccessorRopLabel();
-        // Filter out any reference to the SSA form's exit block
 
-        // exit block may be null
+        // Filter out any reference to the SSA form's exit block.
+
+        // Exit block may be null.
         SsaBasicBlock exitBlock = ssaMeth.getExitBlock();
-
         int exitRopLabel = (exitBlock == null) ? -1 : exitBlock.getRopLabel();
 
         if (successorList.contains(exitRopLabel)) {
             if (successorList.size() > 1) {
-                throw new RuntimeException (
+                throw new RuntimeException(
                         "Exit predecessor must have no other successors"
                                 + Hex.u2(block.getRopLabel()));
             } else {
@@ -362,7 +325,7 @@
 
         successorList.setImmutable();
 
-        result = new BasicBlock(
+        BasicBlock result = new BasicBlock(
                 block.getRopLabel(), convertInsns(block.getInsns()),
                 successorList,
                 primarySuccessorLabel);
@@ -371,16 +334,14 @@
     }
 
     /**
-     * Converts an insn list to rop form
-     * @param ssaInsns non-null;old instructions
-     * @return non-null; immutable instruction list
+     * Converts an insn list to rop form.
+     * 
+     * @param ssaInsns {@code non-null;} old instructions
+     * @return {@code non-null;} immutable instruction list
      */
     private InsnList convertInsns(ArrayList<SsaInsn> ssaInsns) {
-        InsnList result;
-        int insnCount;
-
-        insnCount = ssaInsns.size();
-        result = new InsnList (insnCount);
+        int insnCount = ssaInsns.size();
+        InsnList result = new InsnList(insnCount);
 
         for (int i = 0; i < insnCount; i++) {
             result.set(i, ssaInsns.get(i).toRopInsn());
@@ -390,4 +351,35 @@
 
         return result;
     }
+
+    /**
+     * <b>Note:</b> This method is not presently used.
+     * 
+     * @return a list of registers ordered by most-frequently-used to
+     * least-frequently-used. Each register is listed once and only
+     * once.
+     */
+    public int[] getRegistersByFrequency() {
+        int regCount = ssaMeth.getRegCount();
+        Integer[] ret = new Integer[regCount];
+
+        for (int i = 0; i < regCount; i++) {
+            ret[i] = i;
+        }
+
+        Arrays.sort(ret, new Comparator<Integer>() {
+            public int compare(Integer o1, Integer o2) {
+                return ssaMeth.getUseListForRegister(o2).size()
+                        - ssaMeth.getUseListForRegister(o1).size();
+            }
+        });
+
+        int result[] = new int[regCount];
+
+        for (int i = 0; i < regCount; i++) {
+            result[i] = ret[i];
+        }
+
+        return result;
+    }    
 }
diff --git a/dx/src/com/android/dx/ssa/package-info.java b/dx/src/com/android/dx/ssa/package-info.java
index 45d9ad6..582a327 100644
--- a/dx/src/com/android/dx/ssa/package-info.java
+++ b/dx/src/com/android/dx/ssa/package-info.java
@@ -19,7 +19,7 @@
 /**
  * <h1>An introduction to SSA Form</h1>
  *
- * This package contains classes associated with dx's <code>SSA</code>
+ * This package contains classes associated with dx's {@code SSA}
  * intermediate form. This form is a static-single-assignment representation of
  * Rop-form a method with Rop-form-like instructions (with the addition of a
  * {@link PhiInsn phi instriction}. This form is intended to make it easy to
@@ -47,7 +47,7 @@
  * <li> {@link PhiInsn} instances represent "phi" operators defined in SSA
  * literature. They must be the first N instructions in a basic block.
  * <li> {@link NormalSsaInsn} instances represent instructions that directly
- * correspond to <code>Rop</code> form.
+ * correspond to {@code Rop} form.
  * </ul>
  *
  * <h3>Classes related to optimization steps</h3>
@@ -74,14 +74,14 @@
  *
  * <h3>Conversion into SSA Form</h3>
  *
- * {@link SsaConverter#convertToSsaMethod} takes a <code>RopMethod</code> and
- * returns a fully-converted <code>SsaMethod</code>. The conversion process
+ * {@link SsaConverter#convertToSsaMethod} takes a {@code RopMethod} and
+ * returns a fully-converted {@code SsaMethod}. The conversion process
  * is roughly as follows:
  *
  * <ol>
  * <li> The Rop-form method, its blocks and their instructions are directly
- * wrapped in <code>SsaMethod</code>, <code>SsaBasicBlock</code> and
- * <code>SsaInsn</code> instances. Nothing else changes.
+ * wrapped in {@code SsaMethod}, {@code SsaBasicBlock} and
+ * {@code SsaInsn} instances. Nothing else changes.
  * <li> Critical control-flow graph edges are {@link SsaConverter#edgeSplit
  * split} and new basic blocks inserted as required to meet the constraints
  * necessary for the ultimate SSA representation.
@@ -89,7 +89,7 @@
  * Rop registers to local variables necessary during phi placement. This
  * step could also be done in Rop form and then updated through the preceding
  * steps.
- * <li> <code>Phi</code> instructions are {link SsaConverter#placePhiFunctions}
+ * <li> {@code Phi} instructions are {link SsaConverter#placePhiFunctions}
  * placed in a semi-pruned fashion, which requires computation of {@link
  * Dominators dominance graph} and each node's {@link DomFront
  * dominance-frontier set}.
diff --git a/dx/src/com/android/dx/util/AnnotatedOutput.java b/dx/src/com/android/dx/util/AnnotatedOutput.java
index 0d95041..9b69a36 100644
--- a/dx/src/com/android/dx/util/AnnotatedOutput.java
+++ b/dx/src/com/android/dx/util/AnnotatedOutput.java
@@ -25,7 +25,7 @@
     /**
      * Get whether this instance will actually keep annotations.
      * 
-     * @return <code>true</code> iff annotations are being kept
+     * @return {@code true} iff annotations are being kept
      */
     public boolean annotates();
 
@@ -34,7 +34,7 @@
      * Annotators may use the result of calling this method to inform their
      * annotation activity.
      * 
-     * @return <code>true</code> iff annotations are to be verbose
+     * @return {@code true} iff annotations are to be verbose
      */
     public boolean isVerbose();
 
@@ -44,7 +44,7 @@
      * annotation marks all subsequent output until another annotation
      * call.
      * 
-     * @param msg non-null; the annotation message
+     * @param msg {@code non-null;} the annotation message
      */
     public void annotate(String msg);
 
@@ -55,9 +55,9 @@
      * previous calls to this method, the new call "consumes" output
      * after all the output covered by the previous calls.
      * 
-     * @param amt &gt;= 0; the amount of output for this annotation to
+     * @param amt {@code >= 0;} the amount of output for this annotation to
      * cover
-     * @param msg non-null; the annotation message
+     * @param msg {@code non-null;} the annotation message
      */
     public void annotate(int amt, String msg);
 
@@ -73,7 +73,7 @@
      * output, but annotaters are encouraged to attempt to avoid exceeding
      * the indicated width.
      * 
-     * @return &gt;= 1; the maximum width
+     * @return {@code >= 1;} the maximum width
      */
     public int getAnnotationWidth();
 }
diff --git a/dx/src/com/android/dx/util/BitIntSet.java b/dx/src/com/android/dx/util/BitIntSet.java
index c8588f8..db85571 100644
--- a/dx/src/com/android/dx/util/BitIntSet.java
+++ b/dx/src/com/android/dx/util/BitIntSet.java
@@ -44,7 +44,7 @@
     /**
      * Ensures that the bit set has the capacity to represent the given value.
      *
-     * @param value &gt;= 0 value to represent
+     * @param value {@code >= 0;} value to represent
      */
     private void ensureCapacity(int value) {
         if (value >= Bits.getMax(bits)) {
@@ -118,12 +118,6 @@
 
                 return ret;
             }
-
-            /** @inheritDoc */
-            public void remove() {
-                BitIntSet.this.remove(idx);
-                idx = Bits.findFirst(bits, idx+1);
-            }
         };
     }
 
diff --git a/dx/src/com/android/dx/util/Bits.java b/dx/src/com/android/dx/util/Bits.java
index 0bc124c..1f45bd3 100644
--- a/dx/src/com/android/dx/util/Bits.java
+++ b/dx/src/com/android/dx/util/Bits.java
@@ -17,7 +17,7 @@
 package com.android.dx.util;
 
 /**
- * Utilities for treating <code>int[]</code>s as bit sets.
+ * Utilities for treating {@code int[]}s as bit sets.
  */
 public final class Bits {
     /**
@@ -30,8 +30,8 @@
     /**
      * Constructs a bit set to contain bits up to the given index (exclusive).
      * 
-     * @param max &gt;= 0; the maximum bit index (exclusive)
-     * @return non-null; an appropriately-constructed instance
+     * @param max {@code >= 0;} the maximum bit index (exclusive)
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public static int[] makeBitSet(int max) {
         int size = (max + 0x1f) >> 5;
@@ -41,8 +41,8 @@
     /**
      * Gets the maximum index (exclusive) for the given bit set.
      * 
-     * @param bits non-null; bit set in question
-     * @return &gt;= 0; the maximum index (exclusive) that may be set
+     * @param bits {@code non-null;} bit set in question
+     * @return {@code >= 0;} the maximum index (exclusive) that may be set
      */
     public static int getMax(int[] bits) {
         return bits.length * 0x20;
@@ -51,8 +51,8 @@
     /**
      * Gets the value of the bit at the given index.
      * 
-     * @param bits non-null; bit set to operate on
-     * @param idx &gt;= 0, &lt; getMax(set); which bit
+     * @param bits {@code non-null;} bit set to operate on
+     * @param idx {@code >= 0, < getMax(set);} which bit
      * @return the value of the indicated bit
      */
     public static boolean get(int[] bits, int idx) {
@@ -64,8 +64,8 @@
     /**
      * Sets the given bit to the given value.
      * 
-     * @param bits non-null; bit set to operate on
-     * @param idx &gt;= 0, &lt; getMax(set); which bit
+     * @param bits {@code non-null;} bit set to operate on
+     * @param idx {@code >= 0, < getMax(set);} which bit
      * @param value the new value for the bit
      */
     public static void set(int[] bits, int idx, boolean value) {
@@ -80,10 +80,10 @@
     }
 
     /**
-     * Sets the given bit to <code>true</code>.
+     * Sets the given bit to {@code true}.
      * 
-     * @param bits non-null; bit set to operate on
-     * @param idx &gt;= 0, &lt; getMax(set); which bit
+     * @param bits {@code non-null;} bit set to operate on
+     * @param idx {@code >= 0, < getMax(set);} which bit
      */
     public static void set(int[] bits, int idx) {
         int arrayIdx = idx >> 5;
@@ -92,10 +92,10 @@
     }
 
     /**
-     * Sets the given bit to <code>false</code>.
+     * Sets the given bit to {@code false}.
      * 
-     * @param bits non-null; bit set to operate on
-     * @param idx &gt;= 0, &lt; getMax(set); which bit
+     * @param bits {@code non-null;} bit set to operate on
+     * @param idx {@code >= 0, < getMax(set);} which bit
      */
     public static void clear(int[] bits, int idx) {
         int arrayIdx = idx >> 5;
@@ -105,10 +105,10 @@
 
     /**
      * Returns whether or not the given bit set is empty, that is, whether
-     * no bit is set to <code>true</code>.
+     * no bit is set to {@code true}.
      * 
-     * @param bits non-null; bit set to operate on
-     * @return <code>true</code> iff all bits are <code>false</code>
+     * @param bits {@code non-null;} bit set to operate on
+     * @return {@code true} iff all bits are {@code false}
      */
     public static boolean isEmpty(int[] bits) {
         int len = bits.length;
@@ -123,10 +123,10 @@
     }
 
     /**
-     * Gets the number of bits set to <code>true</code> in the given bit set.
+     * Gets the number of bits set to {@code true} in the given bit set.
      * 
-     * @param bits non-null; bit set to operate on
-     * @return &gt;= 0; the bit count (aka population count) of the set
+     * @param bits {@code non-null;} bit set to operate on
+     * @return {@code >= 0;} the bit count (aka population count) of the set
      */
     public static int bitCount(int[] bits) {
         int len = bits.length;
@@ -140,13 +140,13 @@
     }
 
     /**
-     * Returns whether any bits are set to <code>true</code> in the
+     * Returns whether any bits are set to {@code true} in the
      * specified range.
      * 
-     * @param bits non-null; bit set to operate on
-     * @param start &gt;= 0; index of the first bit in the range (inclusive)
-     * @param end &gt;= 0; index of the last bit in the range (exclusive)
-     * @return <code>true</code> if any bit is set to <code>true</code> in
+     * @param bits {@code non-null;} bit set to operate on
+     * @param start {@code >= 0;} index of the first bit in the range (inclusive)
+     * @param end {@code >= 0;} index of the last bit in the range (exclusive)
+     * @return {@code true} if any bit is set to {@code true} in
      * the indicated range
      */
     public static boolean anyInRange(int[] bits, int start, int end) {
@@ -158,10 +158,10 @@
      * Finds the lowest-order bit set at or after the given index in the
      * given bit set.
      * 
-     * @param bits non-null; bit set to operate on
-     * @param idx &gt;= 0; minimum index to return
-     * @return &gt;= -1; lowest-order bit set at or after <code>idx</code>,
-     * or <code>-1</code> if there is no appropriate bit index to return
+     * @param bits {@code non-null;} bit set to operate on
+     * @param idx {@code >= 0;} minimum index to return
+     * @return {@code >= -1;} lowest-order bit set at or after {@code idx},
+     * or {@code -1} if there is no appropriate bit index to return
      */
     public static int findFirst(int[] bits, int idx) {
         int len = bits.length;
@@ -183,12 +183,12 @@
 
     /**
      * Finds the lowest-order bit set at or after the given index in the
-     * given <code>int</code>.
+     * given {@code int}.
      * 
      * @param value the value in question
      * @param idx 0..31 the minimum bit index to return
-     * @return &gt;= -1; lowest-order bit set at or after <code>idx</code>,
-     * or <code>-1</code> if there is no appropriate bit index to return
+     * @return {@code >= -1;} lowest-order bit set at or after {@code idx},
+     * or {@code -1} if there is no appropriate bit index to return
      */
     public static int findFirst(int value, int idx) {
         value &= ~((1 << idx) - 1); // Mask off too-low bits.
@@ -197,13 +197,13 @@
     }
 
     /**
-     * Ors bit array <code>b</code> into bit array <code>a</code>.
-     * <code>a.length</code> must be greater than or equal to
-     * <code>b.length</code>.
+     * Ors bit array {@code b} into bit array {@code a}.
+     * {@code a.length} must be greater than or equal to
+     * {@code b.length}.
      *
-     * @param a non-null; int array to be ored with other argument. This
+     * @param a {@code non-null;} int array to be ored with other argument. This
      * argument is modified.
-     * @param b non-null; int array to be ored into <code>a</code>. This
+     * @param b {@code non-null;} int array to be ored into {@code a}. This
      * argument is not modified.
      */
     public static void or(int[] a, int[] b) {
diff --git a/dx/src/com/android/dx/util/ByteArray.java b/dx/src/com/android/dx/util/ByteArray.java
index 3fcf293..6bd6e5f 100644
--- a/dx/src/com/android/dx/util/ByteArray.java
+++ b/dx/src/com/android/dx/util/ByteArray.java
@@ -21,28 +21,28 @@
 import java.io.InputStream;
 
 /**
- * Wrapper for a <code>byte[]</code>, which provides read-only access and
+ * Wrapper for a {@code byte[]}, which provides read-only access and
  * can "reveal" a partial slice of the underlying array.
  *
  * <b>Note:</b> Multibyte accessors all use big-endian order.
  */
 public final class ByteArray {
-    /** non-null; underlying array */
+    /** {@code non-null;} underlying array */
     private final byte[] bytes;
 
-    /** <code>&gt;= 0</code>; start index of the slice (inclusive) */
+    /** {@code >= 0}; start index of the slice (inclusive) */
     private final int start;
 
-    /** <code>&gt;= 0, &lt;= bytes.length</code>; size computed as
-     * <code>end - start</code> (in the constructor) */
+    /** {@code >= 0, <= bytes.length}; size computed as
+     * {@code end - start} (in the constructor) */
     private final int size;
 
     /**
      * Constructs an instance.
      *
-     * @param bytes non-null; the underlying array
-     * @param start <code>&gt;= 0</code>; start index of the slice (inclusive)
-     * @param end <code>&gt;= start, &lt;= bytes.length</code>; end index of
+     * @param bytes {@code non-null;} the underlying array
+     * @param start {@code >= 0;} start index of the slice (inclusive)
+     * @param end {@code >= start, <= bytes.length;} end index of
      * the slice (exclusive)
      */
     public ByteArray(byte[] bytes, int start, int end) {
@@ -68,9 +68,9 @@
     }
 
     /**
-     * Constructs an instance from an entire <code>byte[]</code>.
+     * Constructs an instance from an entire {@code byte[]}.
      *
-     * @param bytes non-null; the underlying array
+     * @param bytes {@code non-null;} the underlying array
      */
     public ByteArray(byte[] bytes) {
         this(bytes, 0, bytes.length);
@@ -79,7 +79,7 @@
     /**
      * Gets the size of the array, in bytes.
      *
-     * @return &gt;= 0; the size
+     * @return {@code >= 0;} the size
      */
     public int size() {
         return size;
@@ -88,10 +88,10 @@
     /**
      * Returns a slice (that is, a sub-array) of this instance.
      *
-     * @param start <code>&gt;= 0</code>; start index of the slice (inclusive)
-     * @param end <code>&gt;= start, &lt;= size()</code>; end index of
+     * @param start {@code >= 0;} start index of the slice (inclusive)
+     * @param end {@code >= start, <= size();} end index of
      * the slice (exclusive)
-     * @return non-null; the slice
+     * @return {@code non-null;} the slice
      */
     public ByteArray slice(int start, int end) {
         checkOffsets(start, end);
@@ -103,9 +103,9 @@
      * offset into this instance.
      *
      * @param offset offset into this instance
-     * @param bytes non-null; (alleged) underlying array
-     * @return corresponding offset into <code>bytes</code>
-     * @throws IllegalArgumentException thrown if <code>bytes</code> is
+     * @param bytes {@code non-null;} (alleged) underlying array
+     * @return corresponding offset into {@code bytes}
+     * @throws IllegalArgumentException thrown if {@code bytes} is
      * not the underlying array of this instance
      */
     public int underlyingOffset(int offset, byte[] bytes) {
@@ -117,10 +117,10 @@
     }
 
     /**
-     * Gets the <code>signed byte</code> value at a particular offset.
+     * Gets the {@code signed byte} value at a particular offset.
      *
-     * @param off <code>&gt;= 0, &lt; size(); offset to fetch
-     * @return <code>signed byte</code> at that offset
+     * @param off {@code >= 0, < size();} offset to fetch
+     * @return {@code signed byte} at that offset
      */
     public int getByte(int off) {
         checkOffsets(off, off + 1);
@@ -128,10 +128,10 @@
     }
 
     /**
-     * Gets the <code>signed short</code> value at a particular offset.
+     * Gets the {@code signed short} value at a particular offset.
      *
-     * @param off <code>&gt;= 0, &lt; (size() - 1); offset to fetch
-     * @return <code>signed short</code> at that offset
+     * @param off {@code >= 0, < (size() - 1);} offset to fetch
+     * @return {@code signed short} at that offset
      */
     public int getShort(int off) {
         checkOffsets(off, off + 2);
@@ -139,10 +139,10 @@
     }
 
     /**
-     * Gets the <code>signed int</code> value at a particular offset.
+     * Gets the {@code signed int} value at a particular offset.
      *
-     * @param off <code>&gt;= 0, &lt; (size() - 3); offset to fetch
-     * @return <code>signed int</code> at that offset
+     * @param off {@code >= 0, < (size() - 3);} offset to fetch
+     * @return {@code signed int} at that offset
      */
     public int getInt(int off) {
         checkOffsets(off, off + 4);
@@ -153,10 +153,10 @@
     }
 
     /**
-     * Gets the <code>signed long</code> value at a particular offset.
+     * Gets the {@code signed long} value at a particular offset.
      *
-     * @param off <code>&gt;= 0, &lt; (size() - 7); offset to fetch
-     * @return <code>signed int</code> at that offset
+     * @param off {@code >= 0, < (size() - 7);} offset to fetch
+     * @return {@code signed int} at that offset
      */
     public long getLong(int off) {
         checkOffsets(off, off + 8);
@@ -173,10 +173,10 @@
     }
 
     /**
-     * Gets the <code>unsigned byte</code> value at a particular offset.
+     * Gets the {@code unsigned byte} value at a particular offset.
      *
-     * @param off <code>&gt;= 0, &lt; size(); offset to fetch
-     * @return <code>unsigned byte</code> at that offset
+     * @param off {@code >= 0, < size();} offset to fetch
+     * @return {@code unsigned byte} at that offset
      */
     public int getUnsignedByte(int off) {
         checkOffsets(off, off + 1);
@@ -184,10 +184,10 @@
     }
 
     /**
-     * Gets the <code>unsigned short</code> value at a particular offset.
+     * Gets the {@code unsigned short} value at a particular offset.
      *
-     * @param off <code>&gt;= 0, &lt; (size() - 1); offset to fetch
-     * @return <code>unsigned short</code> at that offset
+     * @param off {@code >= 0, < (size() - 1);} offset to fetch
+     * @return {@code unsigned short} at that offset
      */
     public int getUnsignedShort(int off) {
         checkOffsets(off, off + 2);
@@ -196,11 +196,11 @@
 
     /**
      * Copies the contents of this instance into the given raw
-     * <code>byte[]</code> at the given offset. The given array must be
+     * {@code byte[]} at the given offset. The given array must be
      * large enough.
      * 
-     * @param out non-null; array to hold the output
-     * @param offset non-null; index into <code>out</code> for the first
+     * @param out {@code non-null;} array to hold the output
+     * @param offset {@code non-null;} index into {@code out} for the first
      * byte of output
      */
     public void getBytes(byte[] out, int offset) {
@@ -226,7 +226,7 @@
     }
 
     /**
-     * Gets the <code>signed byte</code> value at the given offset,
+     * Gets the {@code signed byte} value at the given offset,
      * without doing any argument checking.
      *
      * @param off offset to fetch
@@ -237,7 +237,7 @@
     }
 
     /**
-     * Gets the <code>unsigned byte</code> value at the given offset,
+     * Gets the {@code unsigned byte} value at the given offset,
      * without doing any argument checking.
      *
      * @param off offset to fetch
@@ -248,26 +248,26 @@
     }
 
     /**
-     * Gets a <code>DataInputStream</code> that reads from this instance,
+     * Gets a {@code DataInputStream} that reads from this instance,
      * with the cursor starting at the beginning of this instance's data.
      * <b>Note:</b> The returned instance may be cast to {@link #GetCursor}
      * if needed.
      * 
-     * @return non-null; an appropriately-constructed
-     * <code>DataInputStream</code> instance
+     * @return {@code non-null;} an appropriately-constructed
+     * {@code DataInputStream} instance
      */
     public MyDataInputStream makeDataInputStream() {
         return new MyDataInputStream(makeInputStream());
     }
 
     /**
-     * Gets a <code>InputStream</code> that reads from this instance,
+     * Gets a {@code InputStream} that reads from this instance,
      * with the cursor starting at the beginning of this instance's data.
      * <b>Note:</b> The returned instance may be cast to {@link #GetCursor}
      * if needed.
      * 
-     * @return non-null; an appropriately-constructed
-     * <code>InputStream</code> instancex
+     * @return {@code non-null;} an appropriately-constructed
+     * {@code InputStream} instancex
      */
     public MyInputStream makeInputStream() {
         return new MyInputStream();
@@ -280,7 +280,7 @@
         /**
          * Gets the current cursor.
          * 
-         * @return 0..size(); the cursor
+         * @return {@code 0..size();} the cursor
          */
         public int getCursor();
     }
@@ -345,7 +345,7 @@
         /**
          * Gets the current cursor.
          * 
-         * @return 0..size(); the cursor
+         * @return {@code 0..size();} the cursor
          */
         public int getCursor() {
             return cursor;
@@ -357,8 +357,8 @@
      * simply so that the cursor of a wrapped {@link #MyInputStream}
      * instance may be easily determined.
      */
-    public class MyDataInputStream extends DataInputStream {
-        /** non-null; the underlying {@link #MyInputStream} */
+    public static class MyDataInputStream extends DataInputStream {
+        /** {@code non-null;} the underlying {@link #MyInputStream} */
         private final MyInputStream wrapped;
         
         public MyDataInputStream(MyInputStream wrapped) {
@@ -370,7 +370,7 @@
         /**
          * Gets the current cursor.
          * 
-         * @return 0..size(); the cursor
+         * @return {@code 0..size();} the cursor
          */
         public int getCursor() {
             return wrapped.getCursor();
diff --git a/dx/src/com/android/dx/util/ByteArrayAnnotatedOutput.java b/dx/src/com/android/dx/util/ByteArrayAnnotatedOutput.java
index 457a603..5fcf5d8 100644
--- a/dx/src/com/android/dx/util/ByteArrayAnnotatedOutput.java
+++ b/dx/src/com/android/dx/util/ByteArrayAnnotatedOutput.java
@@ -22,7 +22,7 @@
 
 /**
  * Implementation of {@link AnnotatedOutput} which stores the written data
- * into a <code>byte[]</code>.
+ * into a {@code byte[]}.
  * 
  * <p><b>Note:</b> As per the {@link Output} interface, multi-byte
  * writes all use little-endian order.</p>
@@ -38,26 +38,26 @@
      */
     private final boolean stretchy;
 
-    /** non-null; the data itself */
+    /** {@code non-null;} the data itself */
     private byte[] data;
 
-    /** &gt;= 0; current output cursor */
+    /** {@code >= 0;} current output cursor */
     private int cursor;
 
     /** whether annotations are to be verbose */
     private boolean verbose;
 
     /**
-     * null-ok; list of annotations, or <code>null</code> if this instance
+     * {@code null-ok;} list of annotations, or {@code null} if this instance
      * isn't keeping them 
      */
     private ArrayList<Annotation> annotations;
 
-    /** &gt;= 40 (if used); the desired maximum annotation width */
+    /** {@code >= 40 (if used);} the desired maximum annotation width */
     private int annotationWidth;
 
     /**
-     * &gt;= 8 (if used); the number of bytes of hex output to use
+     * {@code >= 8 (if used);} the number of bytes of hex output to use
      * in annotations 
      */
     private int hexCols;
@@ -69,7 +69,7 @@
      * capacity of the resulting instance. Also, the constructed
      * instance does not keep annotations by default.
      * 
-     * @param data non-null; data array to use for output
+     * @param data {@code non-null;} data array to use for output
      */
     public ByteArrayAnnotatedOutput(byte[] data) {
         this(data, false);
@@ -87,7 +87,7 @@
     /**
      * Internal constructor.
      * 
-     * @param data non-null; data array to use for output
+     * @param data {@code non-null;} data array to use for output
      * @param stretchy whether the instance is to be stretchy
      */
     private ByteArrayAnnotatedOutput(byte[] data, boolean stretchy) {
@@ -105,25 +105,25 @@
     }
 
     /**
-     * Gets the underlying <code>byte[]</code> of this instance, which
+     * Gets the underlying {@code byte[]} of this instance, which
      * may be larger than the number of bytes written
      * 
      * @see #toByteArray
      * 
-     * @return non-null; the <code>byte[]</code>
+     * @return {@code non-null;} the {@code byte[]}
      */
     public byte[] getArray() {
         return data;
     }
 
     /**
-     * Constructs and returns a new <code>byte[]</code> that contains
+     * Constructs and returns a new {@code byte[]} that contains
      * the written contents exactly (that is, with no extra unwritten
      * bytes at the end).
      * 
      * @see #getArray
      * 
-     * @return non-null; an appropriately-constructed array
+     * @return {@code non-null;} an appropriately-constructed array
      */
     public byte[] toByteArray() {
         byte[] result = new byte[cursor];
@@ -419,7 +419,7 @@
      * be called only once per instance, and only before any data has been
      * written to the it.
      * 
-     * @param annotationWidth &gt;= 40; the desired maximum annotation width
+     * @param annotationWidth {@code >= 40;} the desired maximum annotation width
      * @param verbose whether or not to indicate verbose annotations
      */
     public void enableAnnotations(int annotationWidth, boolean verbose) {
@@ -474,7 +474,7 @@
     /**
      * Writes the annotated content of this instance to the given writer.
      * 
-     * @param out non-null; where to write to
+     * @param out {@code non-null;} where to write to
      */
     public void writeAnnotationsTo(Writer out) throws IOException {
         int width2 = getAnnotationWidth();
@@ -538,7 +538,7 @@
      * Reallocates the underlying array if necessary. Calls to this method
      * should be guarded by a test of {@link #stretchy}.
      * 
-     * @param desiredSize &gt;= 0; the desired minimum total size of the array
+     * @param desiredSize {@code >= 0;} the desired minimum total size of the array
      */
     private void ensureCapacity(int desiredSize) {
         if (data.length < desiredSize) {
@@ -552,25 +552,25 @@
      * Annotation on output.
      */
     private static class Annotation {
-        /** &gt;= 0; start of annotated range (inclusive) */
+        /** {@code >= 0;} start of annotated range (inclusive) */
         private final int start;
 
         /**
-         * &gt;= 0; end of annotated range (exclusive);
-         * <code>Integer.MAX_VALUE</code> if unclosed 
+         * {@code >= 0;} end of annotated range (exclusive);
+         * {@code Integer.MAX_VALUE} if unclosed 
          */
         private int end;
 
-        /** non-null; annotation text */
+        /** {@code non-null;} annotation text */
         private final String text;
 
         /**
          * Constructs an instance.
          * 
-         * @param start &gt;= 0; start of annotated range
-         * @param end &gt;= start; end of annotated range (exclusive) or
-         * <code>Integer.MAX_VALUE</code> if unclosed
-         * @param text non-null; annotation text
+         * @param start {@code >= 0;} start of annotated range
+         * @param end {@code >= start;} end of annotated range (exclusive) or
+         * {@code Integer.MAX_VALUE} if unclosed
+         * @param text {@code non-null;} annotation text
          */
         public Annotation(int start, int end, String text) {
             this.start = start;
@@ -581,8 +581,8 @@
         /**
          * Constructs an instance. It is initally unclosed.
          * 
-         * @param start &gt;= 0; start of annotated range
-         * @param text non-null; annotation text
+         * @param start {@code >= 0;} start of annotated range
+         * @param text {@code non-null;} annotation text
          */
         public Annotation(int start, String text) {
             this(start, Integer.MAX_VALUE, text);
@@ -592,7 +592,7 @@
          * Sets the end as given, but only if the instance is unclosed;
          * otherwise, do nothing.
          * 
-         * @param end &gt;= start; the end
+         * @param end {@code >= start;} the end
          */
         public void setEndIfUnset(int end) {
             if (this.end == Integer.MAX_VALUE) {
@@ -603,7 +603,7 @@
         /**
          * Sets the end as given.
          * 
-         * @param end &gt;= start; the end
+         * @param end {@code >= start;} the end
          */
         public void setEnd(int end) {
             this.end = end;
@@ -630,7 +630,7 @@
         /**
          * Gets the text.
          * 
-         * @return non-null; the text
+         * @return {@code non-null;} the text
          */
         public String getText() {
             return text;
diff --git a/dx/src/com/android/dx/util/ExceptionWithContext.java b/dx/src/com/android/dx/util/ExceptionWithContext.java
index 035546e..7f8523c 100644
--- a/dx/src/com/android/dx/util/ExceptionWithContext.java
+++ b/dx/src/com/android/dx/util/ExceptionWithContext.java
@@ -24,7 +24,7 @@
  */
 public class ExceptionWithContext
         extends RuntimeException {
-    /** non-null; human-oriented context of the exception */
+    /** {@code non-null;} human-oriented context of the exception */
     private StringBuffer context;
 
     /**
@@ -33,9 +33,9 @@
      * {@link ExceptionWithContext}, or a newly-constructed exception if it
      * was not.
      *
-     * @param ex non-null; the exception to augment
-     * @param str non-null; context to add
-     * @return non-null; an appropriate instance
+     * @param ex {@code non-null;} the exception to augment
+     * @param str {@code non-null;} context to add
+     * @return {@code non-null;} an appropriate instance
      */
     public static ExceptionWithContext withContext(Throwable ex, String str) {
         ExceptionWithContext ewc;
@@ -62,7 +62,7 @@
     /**
      * Constructs an instance.
      *
-     * @param cause null-ok; exception that caused this one
+     * @param cause {@code null-ok;} exception that caused this one
      */
     public ExceptionWithContext(Throwable cause) {
         this(null, cause);
@@ -72,7 +72,7 @@
      * Constructs an instance.
      *
      * @param message human-oriented message
-     * @param cause null-ok; exception that caused this one
+     * @param cause {@code null-ok;} exception that caused this one
      */
     public ExceptionWithContext(String message, Throwable cause) {
         super((message != null) ? message :
@@ -105,7 +105,7 @@
     /**
      * Adds a line of context to this instance.
      *
-     * @param str non-null; new context
+     * @param str {@code non-null;} new context
      */
     public void addContext(String str) {
         if (str == null) {
@@ -121,7 +121,7 @@
     /**
      * Gets the context.
      *
-     * @return non-null; the context
+     * @return {@code non-null;} the context
      */
     public String getContext() {
         return context.toString();
@@ -130,7 +130,7 @@
     /**
      * Prints the message and context.
      *
-     * @param out non-null; where to print to
+     * @param out {@code non-null;} where to print to
      */
     public void printContext(PrintStream out) {
         out.println(getMessage());
@@ -140,7 +140,7 @@
     /**
      * Prints the message and context.
      *
-     * @param out non-null; where to print to
+     * @param out {@code non-null;} where to print to
      */
     public void printContext(PrintWriter out) {
         out.println(getMessage());
diff --git a/dx/src/com/android/dx/util/FileUtils.java b/dx/src/com/android/dx/util/FileUtils.java
index 07a7c7e..3f51207 100644
--- a/dx/src/com/android/dx/util/FileUtils.java
+++ b/dx/src/com/android/dx/util/FileUtils.java
@@ -35,8 +35,8 @@
      * Reads the named file, translating {@link IOException} to a
      * {@link RuntimeException} of some sort.
      * 
-     * @param fileName non-null; name of the file to read
-     * @return non-null; contents of the file
+     * @param fileName {@code non-null;} name of the file to read
+     * @return {@code non-null;} contents of the file
      */
     public static byte[] readFile(String fileName) {
         File file = new File(fileName);
@@ -47,8 +47,8 @@
      * Reads the given file, translating {@link IOException} to a
      * {@link RuntimeException} of some sort.
      * 
-     * @param file non-null; the file to read
-     * @return non-null; contents of the file
+     * @param file {@code non-null;} the file to read
+     * @return {@code non-null;} contents of the file
      */
     public static byte[] readFile(File file) {
         if (!file.exists()) {
diff --git a/dx/src/com/android/dx/util/FixedSizeList.java b/dx/src/com/android/dx/util/FixedSizeList.java
index 7b7d325..17d773c 100644
--- a/dx/src/com/android/dx/util/FixedSizeList.java
+++ b/dx/src/com/android/dx/util/FixedSizeList.java
@@ -23,11 +23,11 @@
  */
 public class FixedSizeList
         extends MutabilityControl implements ToHuman {
-    /** non-null; array of elements */
+    /** {@code non-null;} array of elements */
     private Object[] arr;
 
     /**
-     * Constructs an instance. All indices initially contain <code>null</code>.
+     * Constructs an instance. All indices initially contain {@code null}.
      * 
      * @param size the size of the list
      */
@@ -94,10 +94,10 @@
     /**
      * Gets a customized string form for this instance.
      * 
-     * @param prefix null-ok; prefix for the start of the result
-     * @param separator null-ok; separator to insert between each item
-     * @param suffix null-ok; suffix for the end of the result
-     * @return non-null; the custom string
+     * @param prefix {@code null-ok;} prefix for the start of the result
+     * @param separator {@code null-ok;} separator to insert between each item
+     * @param suffix {@code null-ok;} suffix for the end of the result
+     * @return {@code non-null;} the custom string
      */
     public String toString(String prefix, String separator, String suffix) {
         return toString0(prefix, separator, suffix, false);
@@ -108,10 +108,10 @@
      * only work if every element of the list implements {@link
      * ToHuman}.
      * 
-     * @param prefix null-ok; prefix for the start of the result
-     * @param separator null-ok; separator to insert between each item
-     * @param suffix null-ok; suffix for the end of the result
-     * @return non-null; the custom string
+     * @param prefix {@code null-ok;} prefix for the start of the result
+     * @param separator {@code null-ok;} separator to insert between each item
+     * @param suffix {@code null-ok;} suffix for the end of the result
+     * @return {@code non-null;} the custom string
      */
     public String toHuman(String prefix, String separator, String suffix) {
         return toString0(prefix, separator, suffix, true);
@@ -126,7 +126,7 @@
 
     /**
      * Shrinks this instance to fit, by removing any unset
-     * (<code>null</code>) elements, leaving the remaining elements in
+     * ({@code null}) elements, leaving the remaining elements in
      * their original order.
      */
     public void shrinkToFit() {
@@ -165,12 +165,12 @@
     /**
      * Gets the indicated element. It is an error to call this with the
      * index for an element which was never set; if you do that, this
-     * will throw <code>NullPointerException</code>. This method is
+     * will throw {@code NullPointerException}. This method is
      * protected so that subclasses may offer a safe type-checked
      * public interface to their clients.
      * 
-     * @param n &gt;= 0, &lt; size(); which element
-     * @return non-null; the indicated element
+     * @param n {@code >= 0, < size();} which element
+     * @return {@code non-null;} the indicated element
      */
     protected final Object get0(int n) {
         try {
@@ -188,13 +188,13 @@
     }
 
     /**
-     * Gets the indicated element, allowing <code>null</code>s to be
+     * Gets the indicated element, allowing {@code null}s to be
      * returned. This method is protected so that subclasses may
      * (optionally) offer a safe type-checked public interface to
      * their clients.
      * 
-     * @param n &gt;= 0, &lt; size(); which element
-     * @return null-ok; the indicated element
+     * @param n {@code >= 0, < size();} which element
+     * @return {@code null-ok;} the indicated element
      */
     protected final Object getOrNull0(int n) {
         return arr[n];
@@ -206,8 +206,8 @@
      * subclasses may offer a safe type-checked public interface to
      * their clients.
      * 
-     * @param n &gt;= 0, &lt; size(); which element
-     * @param obj null-ok; the value to store
+     * @param n {@code >= 0, < size();} which element
+     * @param obj {@code null-ok;} the value to store
      */
     protected final void set0(int n, Object obj) {
         throwIfImmutable();
@@ -239,11 +239,11 @@
      * Helper for {@link #toString} and {@link #toHuman}, which both of
      * those call to pretty much do everything.
      * 
-     * @param prefix null-ok; prefix for the start of the result
-     * @param separator null-ok; separator to insert between each item
-     * @param suffix null-ok; suffix for the end of the result
+     * @param prefix {@code null-ok;} prefix for the start of the result
+     * @param separator {@code null-ok;} separator to insert between each item
+     * @param suffix {@code null-ok;} suffix for the end of the result
      * @param human whether the output is to be human 
-     * @return non-null; the custom string
+     * @return {@code non-null;} the custom string
      */
     private String toString0(String prefix, String separator, String suffix,
                              boolean human) {
diff --git a/dx/src/com/android/dx/util/Hex.java b/dx/src/com/android/dx/util/Hex.java
index cf4c130..cb71e5e 100644
--- a/dx/src/com/android/dx/util/Hex.java
+++ b/dx/src/com/android/dx/util/Hex.java
@@ -28,10 +28,10 @@
     }
 
     /**
-     * Formats a <code>long</code> as an 8-byte unsigned hex value.
+     * Formats a {@code long} as an 8-byte unsigned hex value.
      * 
      * @param v value to format
-     * @return non-null; formatted form
+     * @return {@code non-null;} formatted form
      */
     public static String u8(long v) {
         char[] result = new char[16];
@@ -44,10 +44,10 @@
     }
 
     /**
-     * Formats an <code>int</code> as a 4-byte unsigned hex value.
+     * Formats an {@code int} as a 4-byte unsigned hex value.
      * 
      * @param v value to format
-     * @return non-null; formatted form
+     * @return {@code non-null;} formatted form
      */
     public static String u4(int v) {
         char[] result = new char[8];
@@ -60,10 +60,10 @@
     }
 
     /**
-     * Formats an <code>int</code> as a 3-byte unsigned hex value.
+     * Formats an {@code int} as a 3-byte unsigned hex value.
      * 
      * @param v value to format
-     * @return non-null; formatted form
+     * @return {@code non-null;} formatted form
      */
     public static String u3(int v) {
         char[] result = new char[6];
@@ -76,10 +76,10 @@
     }
 
     /**
-     * Formats an <code>int</code> as a 2-byte unsigned hex value.
+     * Formats an {@code int} as a 2-byte unsigned hex value.
      * 
      * @param v value to format
-     * @return non-null; formatted form
+     * @return {@code non-null;} formatted form
      */
     public static String u2(int v) {
         char[] result = new char[4];
@@ -92,12 +92,12 @@
     }
 
     /**
-     * Formats an <code>int</code> as either a 2-byte unsigned hex value
+     * Formats an {@code int} as either a 2-byte unsigned hex value
      * (if the value is small enough) or a 4-byte unsigned hex value (if
      * not).
      * 
      * @param v value to format
-     * @return non-null; formatted form
+     * @return {@code non-null;} formatted form
      */
     public static String u2or4(int v) {
         if (v == (char) v) {
@@ -108,10 +108,10 @@
     }
 
     /**
-     * Formats an <code>int</code> as a 1-byte unsigned hex value.
+     * Formats an {@code int} as a 1-byte unsigned hex value.
      * 
      * @param v value to format
-     * @return non-null; formatted form
+     * @return {@code non-null;} formatted form
      */
     public static String u1(int v) {
         char[] result = new char[2];
@@ -124,10 +124,10 @@
     }
 
     /**
-     * Formats an <code>int</code> as a 4-bit unsigned hex nibble.
+     * Formats an {@code int} as a 4-bit unsigned hex nibble.
      * 
      * @param v value to format
-     * @return non-null; formatted form
+     * @return {@code non-null;} formatted form
      */
     public static String uNibble(int v) {
         char[] result = new char[1];
@@ -137,10 +137,10 @@
     }
 
     /**
-     * Formats a <code>long</code> as an 8-byte signed hex value.
+     * Formats a {@code long} as an 8-byte signed hex value.
      * 
      * @param v value to format
-     * @return non-null; formatted form
+     * @return {@code non-null;} formatted form
      */
     public static String s8(long v) {
         char[] result = new char[17];
@@ -161,10 +161,10 @@
     }
 
     /**
-     * Formats an <code>int</code> as a 4-byte signed hex value.
+     * Formats an {@code int} as a 4-byte signed hex value.
      * 
      * @param v value to format
-     * @return non-null; formatted form
+     * @return {@code non-null;} formatted form
      */
     public static String s4(int v) {
         char[] result = new char[9];
@@ -185,10 +185,10 @@
     }
 
     /**
-     * Formats an <code>int</code> as a 2-byte signed hex value.
+     * Formats an {@code int} as a 2-byte signed hex value.
      * 
      * @param v value to format
-     * @return non-null; formatted form
+     * @return {@code non-null;} formatted form
      */
     public static String s2(int v) {
         char[] result = new char[5];
@@ -209,10 +209,10 @@
     }
 
     /**
-     * Formats an <code>int</code> as a 1-byte signed hex value.
+     * Formats an {@code int} as a 1-byte signed hex value.
      * 
      * @param v value to format
-     * @return non-null; formatted form
+     * @return {@code non-null;} formatted form
      */
     public static String s1(int v) {
         char[] result = new char[3];
@@ -233,18 +233,18 @@
     }
 
     /**
-     * Formats a hex dump of a portion of a <code>byte[]</code>. The result
+     * Formats a hex dump of a portion of a {@code byte[]}. The result
      * is always newline-terminated, unless the passed-in length was zero,
-     * in which case the result is always the empty string (<code>""</code>).
+     * in which case the result is always the empty string ({@code ""}).
      * 
-     * @param arr non-null; array to format
-     * @param offset &gt;= 0; offset to the part to dump
-     * @param length &gt;= 0; number of bytes to dump
-     * @param outOffset &gt;= 0; first output offset to print
-     * @param bpl &gt;= 0; number of bytes of output per line
-     * @param addressLength {2,4,6,8}; number of characters for each address
+     * @param arr {@code non-null;} array to format
+     * @param offset {@code >= 0;} offset to the part to dump
+     * @param length {@code >= 0;} number of bytes to dump
+     * @param outOffset {@code >= 0;} first output offset to print
+     * @param bpl {@code >= 0;} number of bytes of output per line
+     * @param addressLength {@code {2,4,6,8};} number of characters for each address
      * header
-     * @return non-null; a string of the dump
+     * @return {@code non-null;} a string of the dump
      */
     public static String dump(byte[] arr, int offset, int length,
                               int outOffset, int bpl, int addressLength) {
diff --git a/dx/src/com/android/dx/util/HexParser.java b/dx/src/com/android/dx/util/HexParser.java
index 4b6b7b2..3d0c992 100644
--- a/dx/src/com/android/dx/util/HexParser.java
+++ b/dx/src/com/android/dx/util/HexParser.java
@@ -28,7 +28,7 @@
     }
 
     /**
-     * Parses the given text as hex, returning a <code>byte[]</code>
+     * Parses the given text as hex, returning a {@code byte[]}
      * corresponding to the text. The format is simple: Each line may
      * start with a hex offset followed by a colon (which is verified
      * and presumably used just as a comment), and then consists of
@@ -38,8 +38,8 @@
      * of the subsequent characters is used, until the next double
      * quote. Quoted strings may not span multiple lines.
      * 
-     * @param src non-null; the source string
-     * @return non-null; the parsed form
+     * @param src {@code non-null;} the source string
+     * @return {@code non-null;} the parsed form
      */
     public static byte[] parse(String src) {
         int len = src.length();
diff --git a/dx/src/com/android/dx/util/IndentingWriter.java b/dx/src/com/android/dx/util/IndentingWriter.java
index db4e0a2..92f0b55 100644
--- a/dx/src/com/android/dx/util/IndentingWriter.java
+++ b/dx/src/com/android/dx/util/IndentingWriter.java
@@ -27,31 +27,31 @@
  * line.
  */
 public final class IndentingWriter extends FilterWriter {
-    /** null-ok; optional prefix for every line */
+    /** {@code null-ok;} optional prefix for every line */
     private final String prefix;
 
-    /** &gt; 0; the maximum output width */
+    /** {@code > 0;} the maximum output width */
     private final int width;
 
-    /** &gt; 0; the maximum indent */
+    /** {@code > 0;} the maximum indent */
     private final int maxIndent;
 
-    /** &gt;= 0; current output column (zero-based) */
+    /** {@code >= 0;} current output column (zero-based) */
     private int column;
 
     /** whether indent spaces are currently being collected */
     private boolean collectingIndent;
 
-    /** &gt;= 0; current indent amount */
+    /** {@code >= 0;} current indent amount */
     private int indent;
 
     /**
      * Constructs an instance.
      * 
-     * @param out non-null; writer to send final output to
-     * @param width &gt;= 0; the maximum output width (not including
-     * <code>prefix</code>), or <code>0</code> for no maximum
-     * @param prefix non-null; the prefix for each line
+     * @param out {@code non-null;} writer to send final output to
+     * @param width {@code >= 0;} the maximum output width (not including
+     * {@code prefix}), or {@code 0} for no maximum
+     * @param prefix {@code non-null;} the prefix for each line
      */
     public IndentingWriter(Writer out, int width, String prefix) {
         super(out);
@@ -78,9 +78,9 @@
     /**
      * Constructs a no-prefix instance.
      * 
-     * @param out non-null; writer to send final output to
-     * @param width &gt;= 0; the maximum output width (not including
-     * <code>prefix</code>), or <code>0</code> for no maximum
+     * @param out {@code non-null;} writer to send final output to
+     * @param width {@code >= 0;} the maximum output width (not including
+     * {@code prefix}), or {@code 0} for no maximum
      */
     public IndentingWriter(Writer out, int width) {
         this(out, width, "");
diff --git a/dx/src/com/android/dx/util/IntIterator.java b/dx/src/com/android/dx/util/IntIterator.java
index 88181b5..4caa439 100644
--- a/dx/src/com/android/dx/util/IntIterator.java
+++ b/dx/src/com/android/dx/util/IntIterator.java
@@ -35,10 +35,4 @@
      * @throws java.util.NoSuchElementException if no next element exists
      */
     int next();
-
-    /**
-     * Removes a value from the collection underlying this iterator.
-     * May throw UnsupportedOperationException().
-     */
-//    void remove();
 }
diff --git a/dx/src/com/android/dx/util/IntList.java b/dx/src/com/android/dx/util/IntList.java
index f60bbb5..c51c028 100644
--- a/dx/src/com/android/dx/util/IntList.java
+++ b/dx/src/com/android/dx/util/IntList.java
@@ -19,16 +19,16 @@
 import java.util.Arrays;
 
 /**
- * Simple list of <code>int</code>s.
+ * Simple list of {@code int}s.
  */
 public final class IntList extends MutabilityControl {
-    /** non-null; immutable, no-element instance */
+    /** {@code non-null;} immutable, no-element instance */
     public static final IntList EMPTY = new IntList(0);
 
-    /** non-null; array of elements */
+    /** {@code non-null;} array of elements */
     private int[] values;
 
-    /** &gt;= 0; current size of the list */
+    /** {@code >= 0;} current size of the list */
     private int size;
 
     /** whether the values are currently sorted */
@@ -78,7 +78,7 @@
     /**
      * Constructs an empty instance.
      * 
-     * @param initialCapacity &gt;= 0; initial capacity of the list
+     * @param initialCapacity {@code >= 0;} initial capacity of the list
      */
     public IntList(int initialCapacity) {
         super(true);
@@ -165,7 +165,7 @@
     /**
      * Gets the indicated value.
      * 
-     * @param n &gt;= 0, &lt; size(); which element
+     * @param n {@code >= 0, < size();} which element
      * @return the indicated element's value
      */
     public int get(int n) {
@@ -184,7 +184,7 @@
     /**
      * Sets the value at the given index.
      * 
-     * @param n &gt;= 0, &lt; size(); which element
+     * @param n {@code >= 0, < size();} which element
      * @param value value to store
      */
     public void set(int n, int value) {
@@ -229,7 +229,7 @@
      * current size (that is, insertion as a last element is legal but
      * no further).
      *
-     * @param n &gt=0 &lt=size(); index of where to insert
+     * @param n {@code >= 0, <=size();} index of where to insert
      * @param value value to insert
      */
     public void insert(int n, int value) {
@@ -252,7 +252,7 @@
      * Removes an element at a given index, shifting elements at greater
      * indicies down one.
      *
-     * @param n  &gt=0 &lt size(); index of element to remove
+     * @param n  {@code >=0, < size();} index of element to remove
      */
     public void removeIndex(int n) {
         if (n >= size) {
@@ -307,7 +307,7 @@
     /**
      * Pops N elements off the end of the list and decreasing the size by N.
      *
-     * @param n &gt;= 0; number of elements to remove from end.
+     * @param n {@code >= 0;} number of elements to remove from end.
      * @exception IndexOutOfBoundsException if stack is smaller than N
      */
     public void pop(int n) {
@@ -319,7 +319,7 @@
     /**
      * Shrinks the size of the list.
      * 
-     * @param newSize &gt;= 0; the new size
+     * @param newSize {@code >= 0;} the new size
      */
     public void shrink(int newSize) {
         if (newSize < 0) {
@@ -338,7 +338,7 @@
     /**
      * Makes and returns a mutable copy of the list.
      * 
-     * @return non-null; an appropriately-constructed instance
+     * @return {@code non-null;} an appropriately-constructed instance
      */
     public IntList mutableCopy() {
         int sz = size;
@@ -380,12 +380,12 @@
     /**
      * Performs a binary search on a sorted list, returning the index of
      * the given value if it is present or
-     * <code>(-(insertion point) - 1)</code> if the value is not present.
+     * {@code (-(insertion point) - 1)} if the value is not present.
      * If the list is not sorted, then reverts to linear search and returns
-     * <code>-size()</code> if the element is not found.
+     * {@code -size()} if the element is not found.
      *
      * @param value value to find
-     * @return index of value or <code>(-(insertion point) - 1)</code> if the
+     * @return index of value or {@code (-(insertion point) - 1)} if the
      * value is not present
      */
     public int binarysearch(int value) {
diff --git a/dx/src/com/android/dx/util/IntSet.java b/dx/src/com/android/dx/util/IntSet.java
index 10b6ee0..33b6bdd 100644
--- a/dx/src/com/android/dx/util/IntSet.java
+++ b/dx/src/com/android/dx/util/IntSet.java
@@ -44,24 +44,24 @@
     boolean has(int value);
 
     /**
-     * Merges <code>other</code> into this set, so this set becomes the
+     * Merges {@code other} into this set, so this set becomes the
      * union of the two.
      *
-     * @param other non-null; other set to merge with.
+     * @param other {@code non-null;} other set to merge with.
      */
     void merge(IntSet other);
 
     /**
      * Returns the count of unique elements in this set.
      *
-     * @return &gt; = 0; count of unique elements
+     * @return {@code > = 0;} count of unique elements
      */
     int elements();
 
     /**
      * Iterates the set
      *
-     * @return non-null; a set iterator
+     * @return {@code non-null;} a set iterator
      */
     IntIterator iterator();
 }
diff --git a/dx/src/com/android/dx/util/LabeledItem.java b/dx/src/com/android/dx/util/LabeledItem.java
index cc6a0d2..b4856cf 100644
--- a/dx/src/com/android/dx/util/LabeledItem.java
+++ b/dx/src/com/android/dx/util/LabeledItem.java
@@ -24,7 +24,7 @@
     /*
      * Gets the label of this block.
      *
-     * @return &gt;= 0; the label
+     * @return {@code >= 0;} the label
      */
     public int getLabel();
 }
diff --git a/dx/src/com/android/dx/util/LabeledList.java b/dx/src/com/android/dx/util/LabeledList.java
index 3168a38..28a148b 100644
--- a/dx/src/com/android/dx/util/LabeledList.java
+++ b/dx/src/com/android/dx/util/LabeledList.java
@@ -58,7 +58,7 @@
     /**
      * Gets the maximum label (exclusive) of any block added to this instance.
      *
-     * @return &gt;= 0; the maximum label
+     * @return {@code >= 0;} the maximum label
      */
     public int getMaxLabel() {
         int sz = labelToIndex.size();
@@ -102,8 +102,8 @@
      * Gets the index of the first item in the list with the given
      * label, if any.
      *
-     * @param label &gt;= 0; the label to look for
-     * @return &gt;= -1; the index of the so-labelled item, or <code>-1</code>
+     * @param label {@code >= 0;} the label to look for
+     * @return {@code >= -1;} the index of the so-labelled item, or {@code -1}
      * if none is found
      */
     public int indexOfLabel(int label) {
@@ -142,8 +142,8 @@
     /**
      * Sets the element at the given index.
      *
-     * @param n &gt;= 0, &lt; size(); which element
-     * @param item null-ok; the value to store
+     * @param n {@code >= 0, < size();} which element
+     * @param item {@code null-ok;} the value to store
      */
     protected void set(int n, LabeledItem item) {
         LabeledItem old = (LabeledItem) getOrNull0(n);
diff --git a/dx/src/com/android/dx/util/Leb128Utils.java b/dx/src/com/android/dx/util/Leb128Utils.java
index dfd416f..6ed3a61 100644
--- a/dx/src/com/android/dx/util/Leb128Utils.java
+++ b/dx/src/com/android/dx/util/Leb128Utils.java
@@ -41,7 +41,6 @@
         int count = 0;
 
         while (remaining != 0) {
-            value = remaining;
             remaining >>= 7;
             count++;
         }
diff --git a/dx/src/com/android/dx/util/ListIntSet.java b/dx/src/com/android/dx/util/ListIntSet.java
index a9f79af..6d28a18 100644
--- a/dx/src/com/android/dx/util/ListIntSet.java
+++ b/dx/src/com/android/dx/util/ListIntSet.java
@@ -122,11 +122,6 @@
 
                 return ints.get(idx++);
             }
-
-            /** @inheritDoc */
-            public void remove() {
-                throw new UnsupportedOperationException();
-            }
         };
     }
 
diff --git a/dx/src/com/android/dx/util/MutabilityControl.java b/dx/src/com/android/dx/util/MutabilityControl.java
index 8b3383b..14e0f2e 100644
--- a/dx/src/com/android/dx/util/MutabilityControl.java
+++ b/dx/src/com/android/dx/util/MutabilityControl.java
@@ -36,7 +36,7 @@
     /**
      * Constructs an instance, explicitly indicating the mutability.
      *
-     * @param mutable <code>true</code> iff this instance is mutable
+     * @param mutable {@code true} iff this instance is mutable
      */
     public MutabilityControl(boolean mutable) {
         this.mutable = mutable;
@@ -51,9 +51,9 @@
 
     /**
      * Checks to see whether or not this instance is immutable. This is the
-     * same as calling <code>!isMutable()</code>.
+     * same as calling {@code !isMutable()}.
      *
-     * @return <code>true</code> iff this instance is immutable
+     * @return {@code true} iff this instance is immutable
      */
     public final boolean isImmutable() {
         return !mutable;
@@ -62,7 +62,7 @@
     /**
      * Checks to see whether or not this instance is mutable.
      *
-     * @return <code>true</code> iff this instance is mutable
+     * @return {@code true} iff this instance is mutable
      */
     public final boolean isMutable() {
         return mutable;
diff --git a/dx/src/com/android/dx/util/Output.java b/dx/src/com/android/dx/util/Output.java
index b3c3747..5e737ae 100644
--- a/dx/src/com/android/dx/util/Output.java
+++ b/dx/src/com/android/dx/util/Output.java
@@ -18,7 +18,7 @@
 
 /**
  * Interface for a sink for binary output. This is similar to 
- * <code>java.util.DataOutput</code>, but no <code>IOExceptions</code>
+ * {@code java.util.DataOutput}, but no {@code IOExceptions}
  * are declared, and multibyte output is defined to be little-endian.
  */
 public interface Output {
@@ -26,7 +26,7 @@
      * Gets the current cursor position. This is the same as the number of
      * bytes written to this instance.
      * 
-     * @return &gt;= 0; the cursor position
+     * @return {@code >= 0;} the cursor position
      */
     public int getCursor();
 
@@ -34,34 +34,34 @@
      * Asserts that the cursor is the given value.
      * 
      * @param expectedCursor the expected cursor value
-     * @throws RuntimeException thrown if <code>getCursor() !=
-     * expectedCursor</code>
+     * @throws RuntimeException thrown if {@code getCursor() !=
+     * expectedCursor}
      */
     public void assertCursor(int expectedCursor);
  
     /**
-     * Writes a <code>byte</code> to this instance.
+     * Writes a {@code byte} to this instance.
      * 
      * @param value the value to write; all but the low 8 bits are ignored
      */
     public void writeByte(int value);
 
     /**
-     * Writes a <code>short</code> to this instance.
+     * Writes a {@code short} to this instance.
      * 
      * @param value the value to write; all but the low 16 bits are ignored
      */
     public void writeShort(int value);
 
     /**
-     * Writes an <code>int</code> to this instance.
+     * Writes an {@code int} to this instance.
      * 
      * @param value the value to write
      */
     public void writeInt(int value);
 
     /**
-     * Writes a <code>long</code> to this instance.
+     * Writes a {@code long} to this instance.
      * 
      * @param value the value to write
      */
@@ -73,7 +73,7 @@
      * 7.6.
      *
      * @param value value to write, treated as an unsigned value
-     * @return 1..5; the number of bytes actually written
+     * @return {@code 1..5;} the number of bytes actually written
      */
     public int writeUnsignedLeb128(int value);
 
@@ -83,47 +83,47 @@
      * 7.6.
      *
      * @param value value to write
-     * @return 1..5; the number of bytes actually written
+     * @return {@code 1..5;} the number of bytes actually written
      */
     public int writeSignedLeb128(int value);
 
     /**
      * Writes a {@link ByteArray} to this instance.
      * 
-     * @param bytes non-null; the array to write
+     * @param bytes {@code non-null;} the array to write
      */
     public void write(ByteArray bytes);
 
     /**
-     * Writes a portion of a <code>byte[]</code> to this instance.
+     * Writes a portion of a {@code byte[]} to this instance.
      * 
-     * @param bytes non-null; the array to write
-     * @param offset &gt;= 0; offset into <code>bytes</code> for the first
+     * @param bytes {@code non-null;} the array to write
+     * @param offset {@code >= 0;} offset into {@code bytes} for the first
      * byte to write
-     * @param length &gt;= 0; number of bytes to write
+     * @param length {@code >= 0;} number of bytes to write
      */
     public void write(byte[] bytes, int offset, int length);
 
     /**
-     * Writes a <code>byte[]</code> to this instance. This is just
-     * a convenient shorthand for <code>write(bytes, 0, bytes.length)</code>.
+     * Writes a {@code byte[]} to this instance. This is just
+     * a convenient shorthand for {@code write(bytes, 0, bytes.length)}.
      * 
-     * @param bytes non-null; the array to write
+     * @param bytes {@code non-null;} the array to write
      */
     public void write(byte[] bytes);
 
     /** 
-     * Writes the given number of <code>0</code> bytes.
+     * Writes the given number of {@code 0} bytes.
      * 
-     * @param count &gt;= 0; the number of zeroes to write
+     * @param count {@code >= 0;} the number of zeroes to write
      */
     public void writeZeroes(int count);
 
     /** 
-     * Adds extra bytes if necessary (with value <code>0</code>) to
+     * Adds extra bytes if necessary (with value {@code 0}) to
      * force alignment of the output cursor as given.
      * 
-     * @param alignment &gt; 0; the alignment; must be a power of two
+     * @param alignment {@code > 0;} the alignment; must be a power of two
      */
     public void alignTo(int alignment);
 }
diff --git a/dx/src/com/android/dx/util/ToHuman.java b/dx/src/com/android/dx/util/ToHuman.java
index 89bf4f7..b3a31a5 100644
--- a/dx/src/com/android/dx/util/ToHuman.java
+++ b/dx/src/com/android/dx/util/ToHuman.java
@@ -23,9 +23,9 @@
 public interface ToHuman {
     /**
      * Return the "human" string form of this instance.  This is
-     * generally less "debuggy" than <code>toString()</code>.
+     * generally less "debuggy" than {@code toString()}.
      *
-     * @return non-null; the human string form
+     * @return {@code non-null;} the human string form
      */
     public String toHuman();
 }
diff --git a/dx/src/com/android/dx/util/TwoColumnOutput.java b/dx/src/com/android/dx/util/TwoColumnOutput.java
index cc9f7d4..a155c15 100644
--- a/dx/src/com/android/dx/util/TwoColumnOutput.java
+++ b/dx/src/com/android/dx/util/TwoColumnOutput.java
@@ -28,34 +28,34 @@
  * one which goes on the right.
  */
 public final class TwoColumnOutput {
-    /** non-null; underlying writer for final output */
+    /** {@code non-null;} underlying writer for final output */
     private final Writer out;
 
-    /** &gt; 0; the left column width */
+    /** {@code > 0;} the left column width */
     private final int leftWidth;
 
-    /** non-null; pending left column output */
+    /** {@code non-null;} pending left column output */
     private final StringBuffer leftBuf;
 
-    /** non-null; pending right column output */
+    /** {@code non-null;} pending right column output */
     private final StringBuffer rightBuf;
 
-    /** non-null; left column writer */
+    /** {@code non-null;} left column writer */
     private final IndentingWriter leftColumn;
 
-    /** non-null; right column writer */
+    /** {@code non-null;} right column writer */
     private final IndentingWriter rightColumn;
 
     /**
      * Turns the given two strings (with widths) and spacer into a formatted
      * two-column string.
      * 
-     * @param s1 non-null; first string
-     * @param width1 &gt; 0; width of the first column
-     * @param spacer non-null; spacer string
-     * @param s2 non-null; second string
-     * @param width2 &gt; 0; width of the second column
-     * @return non-null; an appropriately-formatted string
+     * @param s1 {@code non-null;} first string
+     * @param width1 {@code > 0;} width of the first column
+     * @param spacer {@code non-null;} spacer string
+     * @param s2 {@code non-null;} second string
+     * @param width2 {@code > 0;} width of the second column
+     * @return {@code non-null;} an appropriately-formatted string
      */
     public static String toString(String s1, int width1, String spacer,
                                   String s2, int width2) {
@@ -80,10 +80,10 @@
     /**
      * Constructs an instance.
      * 
-     * @param out non-null; writer to send final output to
-     * @param leftWidth &gt; 0; width of the left column, in characters
-     * @param rightWidth &gt; 0; width of the right column, in characters
-     * @param spacer non-null; spacer string to sit between the two columns
+     * @param out {@code non-null;} writer to send final output to
+     * @param leftWidth {@code > 0;} width of the left column, in characters
+     * @param rightWidth {@code > 0;} width of the right column, in characters
+     * @param spacer {@code non-null;} spacer string to sit between the two columns
      */
     public TwoColumnOutput(Writer out, int leftWidth, int rightWidth,
                            String spacer) {
@@ -118,10 +118,10 @@
     /**
      * Constructs an instance.
      * 
-     * @param out non-null; stream to send final output to
-     * @param leftWidth &gt;= 1; width of the left column, in characters
-     * @param rightWidth &gt;= 1; width of the right column, in characters
-     * @param spacer non-null; spacer string to sit between the two columns
+     * @param out {@code non-null;} stream to send final output to
+     * @param leftWidth {@code >= 1;} width of the left column, in characters
+     * @param rightWidth {@code >= 1;} width of the right column, in characters
+     * @param spacer {@code non-null;} spacer string to sit between the two columns
      */
     public TwoColumnOutput(OutputStream out, int leftWidth, int rightWidth,
                            String spacer) {
@@ -131,7 +131,7 @@
     /**
      * Gets the writer to use to write to the left column.
      * 
-     * @return non-null; the left column writer
+     * @return {@code non-null;} the left column writer
      */
     public Writer getLeft() {
         return leftColumn;
@@ -140,7 +140,7 @@
     /**
      * Gets the writer to use to write to the right column.
      * 
-     * @return non-null; the right column writer
+     * @return {@code non-null;} the right column writer
      */
     public Writer getRight() {
         return rightColumn;
@@ -226,8 +226,8 @@
      * Appends a newline to the given buffer via the given writer, but
      * only if it isn't empty and doesn't already end with one.
      * 
-     * @param buf non-null; the buffer in question
-     * @param out non-null; the writer to use
+     * @param buf {@code non-null;} the buffer in question
+     * @param out {@code non-null;} the writer to use
      */
     private static void appendNewlineIfNecessary(StringBuffer buf,
                                                  Writer out) 
@@ -242,8 +242,8 @@
     /**
      * Writes the given number of spaces to the given writer.
      * 
-     * @param out non-null; where to write
-     * @param amt &gt;= 0; the number of spaces to write
+     * @param out {@code non-null;} where to write
+     * @param amt {@code >= 0;} the number of spaces to write
      */
     private static void writeSpaces(Writer out, int amt) throws IOException {
         while (amt > 0) {
diff --git a/dx/src/com/android/dx/util/Writers.java b/dx/src/com/android/dx/util/Writers.java
index f10e400..632b082 100644
--- a/dx/src/com/android/dx/util/Writers.java
+++ b/dx/src/com/android/dx/util/Writers.java
@@ -20,7 +20,7 @@
 import java.io.Writer;
 
 /**
- * Utilities for dealing with <code>Writer</code>s.
+ * Utilities for dealing with {@code Writer}s.
  */
 public final class Writers {
     /**
@@ -31,12 +31,12 @@
     }
 
     /**
-     * Makes a <code>PrintWriter</code> for the given <code>Writer</code>,
+     * Makes a {@code PrintWriter} for the given {@code Writer},
      * returning the given writer if it already happens to be the right
      * class.
      * 
-     * @param writer non-null; writer to (possibly) wrap
-     * @return non-null; an appropriate instance
+     * @param writer {@code non-null;} writer to (possibly) wrap
+     * @return {@code non-null;} an appropriate instance
      */
     public static PrintWriter printWriterFor(Writer writer) {
         if (writer instanceof PrintWriter) {
diff --git a/dx/src/com/android/dx/util/_tests/_Bits.java b/dx/src/com/android/dx/util/_tests/_Bits.java
index e529b50..a95fc14 100644
--- a/dx/src/com/android/dx/util/_tests/_Bits.java
+++ b/dx/src/com/android/dx/util/_tests/_Bits.java
@@ -21,7 +21,7 @@
 import junit.framework.TestCase;
 
 /**
- * Test the class <code>com.android.dx.util.Bits</code>.
+ * Test the class {@code com.android.dx.util.Bits}.
  */
 public class _Bits
         extends TestCase {
diff --git a/dx/src/com/android/dx/util/_tests/_IntList.java b/dx/src/com/android/dx/util/_tests/_IntList.java
index 241e8be..dadbd54 100644
--- a/dx/src/com/android/dx/util/_tests/_IntList.java
+++ b/dx/src/com/android/dx/util/_tests/_IntList.java
@@ -21,7 +21,7 @@
 import junit.framework.TestCase;
 
 /**
- * Test the class <code>com.android.dx.util.IntList</code>.
+ * Test the class {@code com.android.dx.util.IntList}.
  */
 public class _IntList
     extends TestCase {
diff --git a/dx/tests/111-use-null-as-array/Blort.java b/dx/tests/111-use-null-as-array/Blort.java
new file mode 100644
index 0000000..c16684f
--- /dev/null
+++ b/dx/tests/111-use-null-as-array/Blort.java
@@ -0,0 +1,108 @@
+/*
+ * 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 Blort {
+    public static boolean test_getBooleanArray() {
+        boolean[] arr = null;
+        return arr[1];
+    }
+
+    public static byte test_getByteArray() {
+        byte[] arr = null;
+        return arr[2];
+    }
+
+    public static char test_getCharArray() {
+        char[] arr = null;
+        return arr[3];
+    }
+
+    public static double test_getDoubleArray() {
+        double[] arr = null;
+        return arr[4];
+    }
+
+    public static float test_getFloatArray() {
+        float[] arr = null;
+        return arr[5];
+    }
+
+    public static int test_getIntArray() {
+        int[] arr = null;
+        return arr[6];
+    }
+
+    public static long test_getLongArray() {
+        long[] arr = null;
+        return arr[7];
+    }
+
+    public static Object test_getObjectArray() {
+        Object[] arr = null;
+        return arr[8];
+    }
+
+    public static short test_getShortArray() {
+        short[] arr = null;
+        return arr[9];
+    }
+
+    public static void test_setBooleanArray() {
+        boolean[] arr = null;
+        arr[1] = true;
+    }
+
+    public static void test_setByteArray() {
+        byte[] arr = null;
+        arr[2] = (byte) 3;
+    }
+
+    public static void test_setCharArray() {
+        char[] arr = null;
+        arr[4] = (char) 5;
+    }
+
+    public static void test_setDoubleArray() {
+        double[] arr = null;
+        arr[6] = 7.0F;
+    }
+
+    public static void test_setFloatArray() {
+        float[] arr = null;
+        arr[8] = 9.0F;
+    }
+
+    public static void test_setIntArray() {
+        int[] arr = null;
+        arr[10] = 11;
+    }
+
+    public static void test_setLongArray() {
+        long[] arr = null;
+        arr[12] = 13;
+    }
+
+    public static void test_setObjectArray() {
+        Object[] arr = null;
+        arr[14] = "blort";
+    }
+
+    public static void test_setShortArray() {
+        short[] arr = null;
+        arr[15] = (short) 16;
+    }
+}
+
diff --git a/dx/tests/111-use-null-as-array/expected.txt b/dx/tests/111-use-null-as-array/expected.txt
new file mode 100644
index 0000000..7e2116b
--- /dev/null
+++ b/dx/tests/111-use-null-as-array/expected.txt
@@ -0,0 +1,116 @@
+Blort.test_getBooleanArray:()Z:
+regs: 0002; ins: 0000; outs: 0000
+  0000: const/4 v0, #null // #0
+  0001: const/4 v1, #int 1 // #1
+  0002: aget-byte v0, v0, v1
+  0004: return v0
+Blort.test_getByteArray:()B:
+regs: 0002; ins: 0000; outs: 0000
+  0000: const/4 v0, #null // #0
+  0001: const/4 v1, #int 2 // #2
+  0002: aget-byte v0, v0, v1
+  0004: return v0
+Blort.test_getCharArray:()C:
+regs: 0002; ins: 0000; outs: 0000
+  0000: const/4 v0, #null // #0
+  0001: const/4 v1, #int 3 // #3
+  0002: aget-char v0, v0, v1
+  0004: return v0
+Blort.test_getDoubleArray:()D:
+regs: 0002; ins: 0000; outs: 0000
+  0000: const/4 v0, #null // #0
+  0001: const/4 v1, #int 4 // #4
+  0002: aget-wide v0, v0, v1
+  0004: return-wide v0
+Blort.test_getFloatArray:()F:
+regs: 0002; ins: 0000; outs: 0000
+  0000: const/4 v0, #null // #0
+  0001: const/4 v1, #int 5 // #5
+  0002: aget v0, v0, v1
+  0004: return v0
+Blort.test_getIntArray:()I:
+regs: 0002; ins: 0000; outs: 0000
+  0000: const/4 v0, #null // #0
+  0001: const/4 v1, #int 6 // #6
+  0002: aget v0, v0, v1
+  0004: return v0
+Blort.test_getLongArray:()J:
+regs: 0002; ins: 0000; outs: 0000
+  0000: const/4 v0, #null // #0
+  0001: const/4 v1, #int 7 // #7
+  0002: aget-wide v0, v0, v1
+  0004: return-wide v0
+Blort.test_getObjectArray:()Ljava/lang/Object;:
+regs: 0002; ins: 0000; outs: 0000
+  0000: const/4 v0, #null // #0
+  0001: const/16 v1, #int 8 // #0008
+  0003: aget-object v0, v0, v1
+  0005: return-object v0
+Blort.test_getShortArray:()S:
+regs: 0002; ins: 0000; outs: 0000
+  0000: const/4 v0, #null // #0
+  0001: const/16 v1, #int 9 // #0009
+  0003: aget-short v0, v0, v1
+  0005: return v0
+Blort.test_setBooleanArray:()V:
+regs: 0002; ins: 0000; outs: 0000
+  0000: const/4 v1, #int 1 // #1
+  0001: const/4 v0, #null // #0
+  0002: aput v1, v0, v1
+  0004: return-void
+Blort.test_setByteArray:()V:
+regs: 0003; ins: 0000; outs: 0000
+  0000: const/4 v0, #null // #0
+  0001: const/4 v1, #int 2 // #2
+  0002: const/4 v2, #int 3 // #3
+  0003: aput v2, v0, v1
+  0005: return-void
+Blort.test_setCharArray:()V:
+regs: 0003; ins: 0000; outs: 0000
+  0000: const/4 v0, #null // #0
+  0001: const/4 v1, #int 4 // #4
+  0002: const/4 v2, #int 5 // #5
+  0003: aput v2, v0, v1
+  0005: return-void
+Blort.test_setDoubleArray:()V:
+regs: 0004; ins: 0000; outs: 0000
+  0000: const/4 v0, #null // #0
+  0001: const/4 v1, #int 6 // #6
+  0002: const-wide/high16 v2, #double 7.0 // #401c000000000000
+  0004: aput-wide v2, v0, v1
+  0006: return-void
+Blort.test_setFloatArray:()V:
+regs: 0003; ins: 0000; outs: 0000
+  0000: const/4 v0, #null // #0
+  0001: const/16 v1, #int 8 // #0008
+  0003: const/high16 v2, #float 9.0 // #41100000
+  0005: aput v2, v0, v1
+  0007: return-void
+Blort.test_setIntArray:()V:
+regs: 0003; ins: 0000; outs: 0000
+  0000: const/4 v0, #null // #0
+  0001: const/16 v1, #int 10 // #000a
+  0003: const/16 v2, #int 11 // #000b
+  0005: aput v2, v0, v1
+  0007: return-void
+Blort.test_setLongArray:()V:
+regs: 0004; ins: 0000; outs: 0000
+  0000: const/4 v0, #null // #0
+  0001: const/16 v1, #int 12 // #000c
+  0003: const-wide/16 v2, #long 13 // #000d
+  0005: aput-wide v2, v0, v1
+  0007: return-void
+Blort.test_setObjectArray:()V:
+regs: 0003; ins: 0000; outs: 0000
+  0000: const/4 v0, #null // #0
+  0001: const/16 v1, #int 14 // #000e
+  0003: const-string v2, "blort"
+  0005: aput-object v2, v0, v1
+  0007: return-void
+Blort.test_setShortArray:()V:
+regs: 0003; ins: 0000; outs: 0000
+  0000: const/4 v0, #null // #0
+  0001: const/16 v1, #int 15 // #000f
+  0003: const/16 v2, #int 16 // #0010
+  0005: aput v2, v0, v1
+  0007: return-void
diff --git a/dx/tests/111-use-null-as-array/info.txt b/dx/tests/111-use-null-as-array/info.txt
new file mode 100644
index 0000000..624386d
--- /dev/null
+++ b/dx/tests/111-use-null-as-array/info.txt
@@ -0,0 +1,18 @@
+This is a smoke test of dex conversion, which checks to see that uses
+of a known-null in contexts that require a specific type end up getting
+converted to the type in question. When executed, this sort of code
+will inevitably throw a NullPointerException, but if the opcode weren't
+correct, they would instead incorrectly fail verification.
+
+If you inspect the expected output of this test, you will see that
+there are some surprising instructions in there, such as using
+aget-byte for what was a boolean[] in the source code. In these cases,
+the resulting output is still correct (passes verification and will
+throw a NullPointerException if ever executed). However, it happens
+that during translation there simply wasn't enough information to
+recover the "true" original meaning at the level of actual opcode
+selection.
+
+This test compares emitted code against a known-good (via eyeballing)
+version, so it is possible for this test to spuriously fail if other
+aspects of conversion end up altering the output in innocuous ways.
diff --git a/dx/tests/111-use-null-as-array/run b/dx/tests/111-use-null-as-array/run
new file mode 100644
index 0000000..7e4e1e8
--- /dev/null
+++ b/dx/tests/111-use-null-as-array/run
@@ -0,0 +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.
+
+$JAVAC -g -d . Blort.java
+dx --debug --dex --positions=none --no-locals \
+    --dump-to=- --dump-method="Blort.test*" *.class
diff --git a/libcore/Android.mk b/libcore/Android.mk
index b22b4c0..7de73be 100644
--- a/libcore/Android.mk
+++ b/libcore/Android.mk
@@ -51,7 +51,7 @@
 # resource with a "#" in its name, but Perforce doesn't
 # allow us to submit such a file. So we create it here
 # on-the-fly.
-TMP_RESOURCE_DIR := /tmp/
+TMP_RESOURCE_DIR := $(OUT_DIR)/tmp/
 TMP_RESOURCE_FILE := org/apache/harmony/luni/tests/java/lang/test\#.properties
 
 $(TMP_RESOURCE_DIR)$(TMP_RESOURCE_FILE):
diff --git a/libcore/annotation/src/main/java/java/lang/annotation/Annotation.java b/libcore/annotation/src/main/java/java/lang/annotation/Annotation.java
index 43ad1bb..00707b1 100644
--- a/libcore/annotation/src/main/java/java/lang/annotation/Annotation.java
+++ b/libcore/annotation/src/main/java/java/lang/annotation/Annotation.java
@@ -22,17 +22,15 @@
  * itself is <i>not</i> an annotation, and neither is an interface that simply
  * extends this one. Only the compiler is able to create proper annotation
  * types.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public interface Annotation {
 
     /**
      * Returns the type of this annotation.
-     * 
+     *
      * @return A {@code Class} instance representing the annotation type.
-     * 
-     * @since Android 1.0
      */
     Class<? extends Annotation> annotationType();
 
@@ -70,14 +68,12 @@
      *         calling their {@code equals()} method.
      *     </li>
      * </ul>
-     * 
+     *
      * @param obj
      *            The object to compare to.
-     * 
-     * @return {@code true} if {@code obj} is equal to this annotation, 
-     * {@code false} otherwise.
-     *         
-     * @since Android 1.0
+     *
+     * @return {@code true} if {@code obj} is equal to this annotation,
+     *            {@code false} otherwise.
      */
     boolean equals(Object obj);
 
@@ -111,10 +107,8 @@
      *         calling their {@code hashCode} method.
      *     </li>
      * </ul>
-     * 
+     *
      * @return the hash code.
-     * 
-     * @since Android 1.0
      */
     int hashCode();
 
@@ -123,11 +117,9 @@
      * strictly defined what the representation has to look like, but it usually
      * consists of the name of the annotation, preceded by a "@". If the
      * annotation contains field members, their names and values are also
-     * included in the result. 
+     * included in the result.
      * 
      * @return the {@code String} that represents this annotation.
-     * 
-     * @since Android 1.0
      */
     String toString();
 }
diff --git a/libcore/annotation/src/main/java/java/lang/annotation/AnnotationFormatError.java b/libcore/annotation/src/main/java/java/lang/annotation/AnnotationFormatError.java
index ce5c3a0..67775c7 100644
--- a/libcore/annotation/src/main/java/java/lang/annotation/AnnotationFormatError.java
+++ b/libcore/annotation/src/main/java/java/lang/annotation/AnnotationFormatError.java
@@ -22,8 +22,8 @@
  * syntactically incorrect and the annotation parser is unable to process it.
  * This exception is unlikely to ever occur, given that the code has been
  * compiled by an ordinary Java compiler.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public class AnnotationFormatError extends Error {
 
@@ -31,11 +31,9 @@
 
     /**
      * Constructs an instance with the message provided.
-     * 
+     *
      * @param message
      *            the details of the error.
-     *            
-     * @since Android 1.0
      */
     public AnnotationFormatError(String message) {
         super(message);
@@ -43,14 +41,11 @@
 
     /**
      * Constructs an instance with a message and a cause.
-     * 
+     *
      * @param message
      *            the details of the error.
-     * 
      * @param cause
      *            the cause of the error or {@code null} if none.
-     * 
-     * @since Android 1.0
      */
     public AnnotationFormatError(String message, Throwable cause) {
         super(message, cause);
@@ -60,11 +55,9 @@
      * Constructs an instance with a cause. If the cause is not
      * {@code null}, then {@code cause.toString()} is used as the
      * error's message.
-     * 
+     *
      * @param cause
      *            the cause of the error or {@code null} if none.
-     * 
-     * @since Android 1.0
      */
     public AnnotationFormatError(Throwable cause) {
         super(cause == null ? null : cause.toString(), cause);
diff --git a/libcore/annotation/src/main/java/java/lang/annotation/AnnotationTypeMismatchException.java b/libcore/annotation/src/main/java/java/lang/annotation/AnnotationTypeMismatchException.java
index 5bb3cbf..0ff79ec 100644
--- a/libcore/annotation/src/main/java/java/lang/annotation/AnnotationTypeMismatchException.java
+++ b/libcore/annotation/src/main/java/java/lang/annotation/AnnotationTypeMismatchException.java
@@ -24,8 +24,8 @@
 /**
  * Indicates that an annotation type has changed since it was compiled or
  * serialized.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public class AnnotationTypeMismatchException extends RuntimeException {
 
@@ -37,16 +37,13 @@
 
     /**
      * Constructs an instance for the given type element and the type found.
-     * 
+     *
      * @param element
      *            the annotation type element.
-     * 
      * @param foundType
      *            the invalid type that was found. This is actually the textual
      *            type description found in the binary class representation,
      *            so it may not be human-readable.
-     *            
-     * @since Android 1.0
      */
     public AnnotationTypeMismatchException(Method element, String foundType) {
         super(Messages.getString("annotation.1", element, foundType)); //$NON-NLS-1$
@@ -56,10 +53,8 @@
 
     /**
      * Returns the method object for the invalid type.
-     * 
+     *
      * @return a {@link Method} instance.
-     *            
-     * @since Android 1.0
      */
     public Method element() {
         return element;
@@ -67,10 +62,8 @@
 
     /**
      * Returns the invalid type.
-     * 
+     *
      * @return a string describing the invalid data.
-     *            
-     * @since Android 1.0
      */
     public String foundType() {
         return foundType;
diff --git a/libcore/annotation/src/main/java/java/lang/annotation/Documented.java b/libcore/annotation/src/main/java/java/lang/annotation/Documented.java
index 2849fd2..7e7f72f 100644
--- a/libcore/annotation/src/main/java/java/lang/annotation/Documented.java
+++ b/libcore/annotation/src/main/java/java/lang/annotation/Documented.java
@@ -20,8 +20,8 @@
 /**
  * Defines a meta-annotation for indicating that an annotation is documented and
  * considered part of the public API.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 @Documented
 @Retention(RetentionPolicy.RUNTIME)
diff --git a/libcore/annotation/src/main/java/java/lang/annotation/ElementType.java b/libcore/annotation/src/main/java/java/lang/annotation/ElementType.java
index 92f5109..f0f52aa 100644
--- a/libcore/annotation/src/main/java/java/lang/annotation/ElementType.java
+++ b/libcore/annotation/src/main/java/java/lang/annotation/ElementType.java
@@ -21,8 +21,8 @@
  * Defines an enumeration for Java program elements. It is used in conjunction
  * with the {@link Target} meta-annotation to restrict the use of an annotation
  * to certain program elements.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public enum ElementType {
     /**
diff --git a/libcore/annotation/src/main/java/java/lang/annotation/IncompleteAnnotationException.java b/libcore/annotation/src/main/java/java/lang/annotation/IncompleteAnnotationException.java
index 3a31551..a5d2068 100644
--- a/libcore/annotation/src/main/java/java/lang/annotation/IncompleteAnnotationException.java
+++ b/libcore/annotation/src/main/java/java/lang/annotation/IncompleteAnnotationException.java
@@ -23,8 +23,8 @@
  * Indicates that an element of an annotation type was accessed that was added
  * after the type was compiled or serialized. This does not apply to new
  * elements that have default values.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public class IncompleteAnnotationException extends RuntimeException {
 
@@ -37,13 +37,11 @@
     /**
      * Constructs an instance with the incomplete annotation type and the name
      * of the element that's missing.
-     * 
+     *
      * @param annotationType
      *            the annotation type.
      * @param elementName
      *            the name of the incomplete element.
-     *            
-     * @since Android 1.0
      */
     public IncompleteAnnotationException(
             Class<? extends Annotation> annotationType, String elementName) {
@@ -54,10 +52,8 @@
 
     /**
      * Returns the annotation type.
-     * 
+     *
      * @return a Class instance.
-     *            
-     * @since Android 1.0
      */
     public Class<? extends Annotation> annotationType() {
         return annotationType;
@@ -65,10 +61,8 @@
 
     /**
      * Returns the incomplete element's name.
-     * 
+     *
      * @return the name of the element.
-     *            
-     * @since Android 1.0
      */
     public String elementName() {
         return elementName;
diff --git a/libcore/annotation/src/main/java/java/lang/annotation/Inherited.java b/libcore/annotation/src/main/java/java/lang/annotation/Inherited.java
index cf16928..730d30a 100644
--- a/libcore/annotation/src/main/java/java/lang/annotation/Inherited.java
+++ b/libcore/annotation/src/main/java/java/lang/annotation/Inherited.java
@@ -20,8 +20,8 @@
 /**
  * Defines a meta-annotation for indicating that an annotation is automatically
  * inherited.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 @Documented
 @Retention(RetentionPolicy.RUNTIME)
diff --git a/libcore/annotation/src/main/java/java/lang/annotation/Retention.java b/libcore/annotation/src/main/java/java/lang/annotation/Retention.java
index 198fccc..275739e 100644
--- a/libcore/annotation/src/main/java/java/lang/annotation/Retention.java
+++ b/libcore/annotation/src/main/java/java/lang/annotation/Retention.java
@@ -21,15 +21,12 @@
  * Defines a meta-annotation for determining the scope of retention for an
  * annotation. If the retention annotation is not set {@code
  * RetentionPolicy.CLASS} is used as default retention.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 @Documented
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.ANNOTATION_TYPE)
 public @interface Retention {
-    // BEGIN android-changed
-    // copied from newer version of harmony
     RetentionPolicy value();
-    // END android-changed
 }
diff --git a/libcore/annotation/src/main/java/java/lang/annotation/RetentionPolicy.java b/libcore/annotation/src/main/java/java/lang/annotation/RetentionPolicy.java
index 014b910..70de3b0 100644
--- a/libcore/annotation/src/main/java/java/lang/annotation/RetentionPolicy.java
+++ b/libcore/annotation/src/main/java/java/lang/annotation/RetentionPolicy.java
@@ -21,8 +21,8 @@
  * Defines an enumeration for annotation retention policies. Used in conjunction
  * with the {@link Retention} annotation to specify an annotation's time-to-live
  * in the overall development life cycle.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public enum RetentionPolicy {
     /**
diff --git a/libcore/annotation/src/main/java/java/lang/annotation/Target.java b/libcore/annotation/src/main/java/java/lang/annotation/Target.java
index 1f53fa0..4ba0938 100644
--- a/libcore/annotation/src/main/java/java/lang/annotation/Target.java
+++ b/libcore/annotation/src/main/java/java/lang/annotation/Target.java
@@ -20,8 +20,8 @@
 /**
  * Defines a meta-annotation for determining what {@link ElementType}s an
  * annotation can be applied to.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 @Documented
 @Retention(RetentionPolicy.RUNTIME)
diff --git a/libcore/annotation/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/AnnotationTypeMismatchExceptionTest.java b/libcore/annotation/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/AnnotationTypeMismatchExceptionTest.java
index 1134887..5430286 100644
--- a/libcore/annotation/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/AnnotationTypeMismatchExceptionTest.java
+++ b/libcore/annotation/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/AnnotationTypeMismatchExceptionTest.java
@@ -65,7 +65,7 @@
         Method m = methods[0];
         AnnotationTypeMismatchException e = new AnnotationTypeMismatchException(
                 m, "some type");
-        assertNotNull("can not instanciate AnnotationTypeMismatchException", e);
+        assertNotNull("can not instantiate AnnotationTypeMismatchException", e);
         assertSame("wrong method name", m, e.element());
         assertEquals("wrong found type", "some type", e.foundType());
     }
diff --git a/libcore/annotation/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/IncompleteAnnotationExceptionTest.java b/libcore/annotation/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/IncompleteAnnotationExceptionTest.java
index de56330..5c718ed 100644
--- a/libcore/annotation/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/IncompleteAnnotationExceptionTest.java
+++ b/libcore/annotation/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/IncompleteAnnotationExceptionTest.java
@@ -80,7 +80,7 @@
         String elementName = "some element";
         IncompleteAnnotationException e = new IncompleteAnnotationException(
                 clazz, elementName);
-        assertNotNull("can not instanciate IncompleteAnnotationException", e);
+        assertNotNull("can not instantiate IncompleteAnnotationException", e);
         assertSame("wrong annotation type", clazz, e.annotationType());
         assertSame("wrong element name", elementName, e.elementName());
     }
diff --git a/libcore/archive/src/main/java/java/util/jar/Attributes.java b/libcore/archive/src/main/java/java/util/jar/Attributes.java
index 5a4d923..4ee94df 100644
--- a/libcore/archive/src/main/java/java/util/jar/Attributes.java
+++ b/libcore/archive/src/main/java/java/util/jar/Attributes.java
@@ -17,6 +17,7 @@
 
 package java.util.jar;
 
+import java.io.UnsupportedEncodingException;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
@@ -28,7 +29,6 @@
  * The {@code Attributes} class is used to store values for manifest entries.
  * Attribute keys are generally instances of {@code Attributes.Name}. Values
  * associated with attribute keys are of type {@code String}.
- * @since Android 1.0
  */
 public class Attributes implements Cloneable, Map<Object, Object> {
 
@@ -37,8 +37,6 @@
      * {@link Attributes.Name}) of a JAR file manifest to arbitrary values. The
      * attribute names thus are obtained from the {@link Manifest} for
      * convenience.
-     * 
-     * @since Android 1.0
      */
     protected Map<Object, Object> map;
 
@@ -46,46 +44,35 @@
      * The name part of the name/value pairs constituting an attribute as
      * defined by the specification of the JAR manifest. May be composed of the
      * following ASCII signs as defined in the EBNF below:
-     * 
+     *
      * <pre>
      * name       = alphanum *headerchar
      * headerchar = alphanum | - | _
-     * alphanum   = {A-Z} | {a-z} | {0-9} 
+     * alphanum   = {A-Z} | {a-z} | {0-9}
      * </pre>
-     * 
-     * @since Android 1.0
      */
     public static class Name {
-        private final String name;
+        private final byte[] name;
 
         private int hashCode;
 
         /**
          * The class path (a main attribute).
-         * 
-         * @since Android 1.0
          */
         public static final Name CLASS_PATH = new Name("Class-Path"); //$NON-NLS-1$
 
         /**
          * The version of the manifest file (a main attribute).
-         * 
-         * @since Android 1.0
          */
-        public static final Name MANIFEST_VERSION = new Name(
-                "Manifest-Version"); //$NON-NLS-1$
+        public static final Name MANIFEST_VERSION = new Name("Manifest-Version"); //$NON-NLS-1$
 
         /**
          * The main class's name (for stand-alone applications).
-         * 
-         * @since Android 1.0
          */
         public static final Name MAIN_CLASS = new Name("Main-Class"); //$NON-NLS-1$
 
         /**
          * Defines the signature version of the JAR file.
-         * 
-         * @since Android 1.0
          */
         public static final Name SIGNATURE_VERSION = new Name(
                 "Signature-Version"); //$NON-NLS-1$
@@ -98,16 +85,12 @@
         /**
          * The {@code Sealed} manifest attribute which may have the value
          * {@code true} for sealed archives.
-         * 
-         * @since Android 1.0
          */
         public static final Name SEALED = new Name("Sealed"); //$NON-NLS-1$
 
         /**
          * The {@code Implementation-Title} attribute whose value is a string
          * that defines the title of the extension implementation.
-         * 
-         * @since Android 1.0
          */
         public static final Name IMPLEMENTATION_TITLE = new Name(
                 "Implementation-Title"); //$NON-NLS-1$
@@ -115,8 +98,6 @@
         /**
          * The {@code Implementation-Version} attribute defining the version of
          * the extension implementation.
-         * 
-         * @since Android 1.0
          */
         public static final Name IMPLEMENTATION_VERSION = new Name(
                 "Implementation-Version"); //$NON-NLS-1$
@@ -124,8 +105,6 @@
         /**
          * The {@code Implementation-Vendor} attribute defining the organization
          * that maintains the extension implementation.
-         * 
-         * @since Android 1.0
          */
         public static final Name IMPLEMENTATION_VENDOR = new Name(
                 "Implementation-Vendor"); //$NON-NLS-1$
@@ -133,8 +112,6 @@
         /**
          * The {@code Specification-Title} attribute defining the title of the
          * extension specification.
-         * 
-         * @since Android 1.0
          */
         public static final Name SPECIFICATION_TITLE = new Name(
                 "Specification-Title"); //$NON-NLS-1$
@@ -142,8 +119,6 @@
         /**
          * The {@code Specification-Version} attribute defining the version of
          * the extension specification.
-         * 
-         * @since Android 1.0
          */
         public static final Name SPECIFICATION_VERSION = new Name(
                 "Specification-Version"); //$NON-NLS-1$
@@ -151,8 +126,6 @@
         /**
          * The {@code Specification-Vendor} attribute defining the organization
          * that maintains the extension specification.
-         * 
-         * @since Android 1.0
          */
         public static final Name SPECIFICATION_VENDOR = new Name(
                 "Specification-Vendor"); //$NON-NLS-1$
@@ -160,23 +133,17 @@
         /**
          * The {@code Extension-List} attribute defining the extensions that are
          * needed by the applet.
-         * 
-         * @since Android 1.0
          */
         public static final Name EXTENSION_LIST = new Name("Extension-List"); //$NON-NLS-1$
 
         /**
          * The {@code Extension-Name} attribute which defines the unique name of
          * the extension.
-         * 
-         * @since Android 1.0
          */
         public static final Name EXTENSION_NAME = new Name("Extension-Name"); //$NON-NLS-1$
 
         /**
          * The {@code Extension-Installation} attribute.
-         * 
-         * @since Android 1.0
          */
         public static final Name EXTENSION_INSTALLATION = new Name(
                 "Extension-Installation"); //$NON-NLS-1$
@@ -185,8 +152,6 @@
          * The {@code Implementation-Vendor-Id} attribute specifies the vendor
          * of an extension implementation if the applet requires an
          * implementation from a specific vendor.
-         * 
-         * @since Android 1.0
          */
         public static final Name IMPLEMENTATION_VENDOR_ID = new Name(
                 "Implementation-Vendor-Id"); //$NON-NLS-1$
@@ -195,91 +160,112 @@
          * The {@code Implementation-URL} attribute specifying a URL that can be
          * used to obtain the most recent version of the extension if the
          * required version is not already installed.
-         * 
-         * @since Android 1.0
          */
         public static final Name IMPLEMENTATION_URL = new Name(
                 "Implementation-URL"); //$NON-NLS-1$
 
+        static final Name NAME = new Name("Name");
+
         /**
          * A String which must satisfy the following EBNF grammar to specify an
          * additional attribute:
-         * 
+         *
          * <pre>
          * name       = alphanum *headerchar
          * headerchar = alphanum | - | _
          * alphanum   = {A-Z} | {a-z} | {0-9}
          * </pre>
-         * 
+         *
          * @param s
          *            The Attribute string.
          * @exception IllegalArgumentException
          *                if the string does not satisfy the EBNF grammar.
-         * @since Android 1.0
          */
         public Name(String s) {
             int i = s.length();
-            if (i == 0 || i > 70) {
+            if (i == 0 || i > Manifest.LINE_LENGTH_LIMIT - 2) {
                 throw new IllegalArgumentException();
             }
+
+            name = new byte[i];
+
             for (; --i >= 0;) {
                 char ch = s.charAt(i);
                 if (!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')
                         || ch == '_' || ch == '-' || (ch >= '0' && ch <= '9'))) {
                     throw new IllegalArgumentException(s);
                 }
+                name[i] = (byte) ch;
             }
-            name = s;
+        }
+
+        /**
+         * A private constructor for a trusted attribute name.
+         */
+        Name(byte[] buf) {
+            name = buf;
+        }
+
+        byte[] getBytes() {
+            return name;
         }
 
         /**
          * Returns this attribute name.
-         * 
+         *
          * @return the attribute name.
-         * @since Android 1.0
          */
         @Override
         public String toString() {
-            return name;
+            try {
+                return new String(name, "ISO-8859-1");
+            } catch (UnsupportedEncodingException iee) {
+                throw new InternalError(iee.getLocalizedMessage());
+            }
         }
 
         /**
          * returns whether the argument provided is the same as the attribute
          * name.
-         * 
+         *
          * @return if the attribute names correspond.
-         * @param an
+         * @param object
          *            An attribute name to be compared with this name.
-         * @since Android 1.0
          */
         @Override
-        public boolean equals(Object an) {
-            if (an == null) {
+        public boolean equals(Object object) {
+            if (object == null || object.getClass() != getClass()
+                    || object.hashCode() != hashCode()) {
                 return false;
             }
-            return an.getClass() == this.getClass()
-                    && name.equalsIgnoreCase(((Name) an).name);
+
+            return Util.equalsIgnoreCase(name, ((Name) object).name);
         }
 
         /**
          * Computes a hash code of the name.
-         * 
+         *
          * @return the hash value computed from the name.
-         * @since Android 1.0
          */
         @Override
         public int hashCode() {
             if (hashCode == 0) {
-                hashCode = Util.toASCIILowerCase("name").hashCode();
+                int hash = 0, multiplier = 1;
+                for (int i = name.length - 1; i >= 0; i--) {
+                    // 'A' & 0xDF == 'a' & 0xDF, ..., 'Z' & 0xDF == 'z' & 0xDF
+                    hash += (name[i] & 0xDF) * multiplier;
+                    int shifted = multiplier << 5;
+                    multiplier = shifted - multiplier;
+                }
+                hashCode = hash;
             }
             return hashCode;
         }
+
     }
 
     /**
      * Constructs an {@code Attributes} instance.
-     * 
-     * @since Android 1.0
      */
     public Attributes() {
         map = new HashMap<Object, Object>();
@@ -288,23 +274,21 @@
     /**
      * Constructs an {@code Attributes} instance obtaining keys and values from
      * the parameter {@code attrib}.
-     * 
+     *
      * @param attrib
      *            The attributes to obtain entries from.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public Attributes(Attributes attrib) {
-        map = (Map<Object, Object>)((HashMap) attrib.map).clone();
+        map = (Map<Object, Object>) ((HashMap) attrib.map).clone();
     }
 
     /**
      * Constructs an {@code Attributes} instance with initial capacity of size
      * {@code size}.
-     * 
+     *
      * @param size
      *            Initial size of this {@code Attributes} instance.
-     * @since Android 1.0
      */
     public Attributes(int size) {
         map = new HashMap<Object, Object>(size);
@@ -312,8 +296,6 @@
 
     /**
      * Removes all key/value pairs from this {@code Attributes}.
-     * 
-     * @since Android 1.0
      */
     public void clear() {
         map.clear();
@@ -321,11 +303,10 @@
 
     /**
      * Determines whether this {@code Attributes} contains the specified key.
-     * 
+     *
      * @param key
      *            The key to search for.
      * @return {@code true} if the key is found, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean containsKey(Object key) {
         return map.containsKey(key);
@@ -333,11 +314,10 @@
 
     /**
      * Determines whether this {@code Attributes} contains the specified value.
-     * 
+     *
      * @param value
      *            the value to search for.
      * @return {@code true} if the value is found, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean containsValue(Object value) {
         return map.containsValue(value);
@@ -346,9 +326,8 @@
     /**
      * Returns a set containing map entries for each of the key/value pair
      * contained in this {@code Attributes}.
-     * 
+     *
      * @return a set of Map.Entry's
-     * @since Android 1.0
      */
     public Set<Map.Entry<Object, Object>> entrySet() {
         return map.entrySet();
@@ -356,12 +335,11 @@
 
     /**
      * Returns the value associated with the parameter key.
-     * 
+     *
      * @param key
      *            the key to search for.
      * @return Object associated with key, or {@code null} if key does not
      *         exist.
-     * @since Android 1.0
      */
     public Object get(Object key) {
         return map.get(key);
@@ -369,9 +347,8 @@
 
     /**
      * Determines whether this {@code Attributes} contains any keys.
-     * 
+     *
      * @return {@code true} if one or more keys exist, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isEmpty() {
         return map.isEmpty();
@@ -380,9 +357,8 @@
     /**
      * Returns a {@code Set} containing all the keys found in this {@code
      * Attributes}.
-     * 
+     *
      * @return a {@code Set} of all keys.
-     * @since Android 1.0
      */
     public Set<Object> keySet() {
         return map.keySet();
@@ -390,7 +366,7 @@
 
     /**
      * Stores key/value pairs in this {@code Attributes}.
-     * 
+     *
      * @param key
      *            the key to associate with value.
      * @param value
@@ -399,21 +375,20 @@
      * @exception ClassCastException
      *                when key is not an {@code Attributes.Name} or value is not
      *                a {@code String}.
-     *@since Android 1.0
      */
-    @SuppressWarnings("cast") // Require cast to force ClassCastException
+    @SuppressWarnings("cast")
+    // Require cast to force ClassCastException
     public Object put(Object key, Object value) {
-        return map.put((Name)key, (String)value);
+        return map.put((Name) key, (String) value);
     }
 
     /**
-     * Stores all the key/value pairs in the argument in this {@code Attributes}
-     * .
-     * 
+     * Stores all the key/value pairs in the argument in this {@code
+     * Attributes}.
+     *
      * @param attrib
-     *            the associations to store (must be of type {@code Attributes}
-     *            ).
-     * @since Android 1.0
+     *            the associations to store (must be of type {@code
+     *            Attributes}).
      */
     public void putAll(Map<?, ?> attrib) {
         if (attrib == null || !(attrib instanceof Attributes)) {
@@ -425,12 +400,11 @@
     /**
      * Deletes the key/value pair with key {@code key} from this {@code
      * Attributes}.
-     * 
+     *
      * @param key
      *            the key to remove.
      * @return the values associated with the removed key, {@code null} if not
      *         present.
-     * @since Android 1.0
      */
     public Object remove(Object key) {
         return map.remove(key);
@@ -439,20 +413,18 @@
     /**
      * Returns the number of key/value pairs associated with this {@code
      * Attributes}.
-     * 
+     *
      * @return the size of this {@code Attributes}.
-     * @since Android 1.0
      */
     public int size() {
         return map.size();
     }
 
     /**
-     * Returns a collection of all the values present in this {@code Attributes}
-     * .
-     * 
+     * Returns a collection of all the values present in this {@code
+     * Attributes}.
+     *
      * @return a collection of all values present.
-     * @since Android 1.0
      */
     public Collection<Object> values() {
         return map.values();
@@ -473,9 +445,8 @@
 
     /**
      * Returns the hash code of this {@code Attributes}.
-     * 
+     *
      * @return the hash code of this object.
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -486,12 +457,11 @@
      * Determines if this {@code Attributes} and the parameter {@code
      * Attributes} are equal. Two {@code Attributes} instances are equal if they
      * contain the same keys and values.
-     * 
+     *
      * @param obj
      *            the object with which this {@code Attributes} is compared.
      * @return {@code true} if the {@code Attributes} are equal, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object obj) {
@@ -507,12 +477,11 @@
     /**
      * Returns the value associated with the parameter {@code Attributes.Name}
      * key.
-     * 
+     *
      * @param name
      *            the key to obtain the value for.
      * @return the {@code String} associated with name, or {@code null} if name
      *         is not a valid key.
-     * @since Android 1.0
      */
     public String getValue(Attributes.Name name) {
         return (String) map.get(name);
@@ -520,12 +489,11 @@
 
     /**
      * Returns the string associated with the parameter name.
-     * 
+     *
      * @param name
      *            the key to obtain the value for.
      * @return the string associated with name, or {@code null} if name is not a
      *         valid key.
-     * @since Android 1.0
      */
     public String getValue(String name) {
         return (String) map.get(new Attributes.Name(name));
@@ -534,13 +502,12 @@
     /**
      * Stores the value {@code val} associated with the key {@code name} in this
      * {@code Attributes}.
-     * 
+     *
      * @param name
      *            the key to store.
      * @param val
      *            the value to store in this {@code Attributes}.
      * @return the value being stored.
-     * @since Android 1.0
      */
     public String putValue(String name, String val) {
         return (String) map.put(new Attributes.Name(name), val);
diff --git a/libcore/archive/src/main/java/java/util/jar/InitManifest.java b/libcore/archive/src/main/java/java/util/jar/InitManifest.java
index 47fdf1c..bf9c397 100644
--- a/libcore/archive/src/main/java/java/util/jar/InitManifest.java
+++ b/libcore/archive/src/main/java/java/util/jar/InitManifest.java
@@ -17,279 +17,206 @@
 
 package java.util.jar;
 
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.io.InputStream;
-import java.io.UTFDataFormatException;
-import java.security.AccessController;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CoderResult;
 import java.util.Map;
 
 import org.apache.harmony.archive.internal.nls.Messages;
-import org.apache.harmony.luni.util.PriviAction;
-import org.apache.harmony.luni.util.Util;
+import org.apache.harmony.luni.util.ThreadLocalCache;
 
 class InitManifest {
-    private final byte[] inbuf = new byte[1024];
 
-    private int inbufCount = 0, inbufPos = 0;
+    private byte[] buf;
 
-    private byte[] buffer = new byte[5];
+    private int pos;
 
-    private char[] charbuf = new char[0];
+    Attributes.Name name;
 
-    private final ByteArrayOutputStream out = new ByteArrayOutputStream(256);
+    String value;
 
-    private String encoding;
+    CharsetDecoder decoder = ThreadLocalCache.utf8Decoder.get();
+    CharBuffer cBuf = ThreadLocalCache.charBuffer.get();
 
-    private boolean usingUTF8 = true;
+    InitManifest(byte[] buf, Attributes main, Attributes.Name ver)
+            throws IOException {
 
-    private final Map<String, Attributes.Name> attributeNames = new HashMap<String, Attributes.Name>();
+        this.buf = buf;
 
-    private final byte[] mainAttributesChunk;
-
-    InitManifest(InputStream is, Attributes main, Map<String, Attributes> entries, Map<String, byte[]> chunks,
-            String verString) throws IOException {
-        encoding = AccessController.doPrivileged(new PriviAction<String>(
-                "manifest.read.encoding")); //$NON-NLS-1$
-        if ("".equals(encoding)) { //$NON-NLS-1$
-            encoding = null;
+        // check a version attribute
+        if (!readHeader() || (ver != null && !name.equals(ver))) {
+            throw new IOException(Messages.getString(
+                    "archive.2D", ver)); //$NON-NLS-1$
         }
 
-        Attributes current = main;
-        ArrayList<String> list = new ArrayList<String>();
-
-        // Return the chunk of main attributes in the manifest.
-        mainAttributesChunk = nextChunk(is, list);
-
-        Iterator<String> it = list.iterator();
-        while (it.hasNext()) {
-            addAttribute(it.next(), current);
+        main.put(name, value);
+        while (readHeader()) {
+            main.put(name, value);
         }
+    }
 
-        // Check for version attribute
-        if (verString != null && main.getValue(verString) == null) {
-            throw new IOException(Messages.getString("archive.2D", verString)); //$NON-NLS-1$
-        }
+    void initEntries(Map<String, Attributes> entries,
+            Map<String, Manifest.Chunk> chunks) throws IOException {
 
-        list.clear();
-        byte[] chunk = null;
-        while (chunks == null ? readLines(is, list) : (chunk = nextChunk(is,
-                list)) != null) {
-            it = list.iterator();
-            String line = it.next();
-            if (line.length() < 7
-                    || !Util.toASCIILowerCase(line.substring(0, 5)).equals("name:")) { //$NON-NLS-1$
+        int mark = pos;
+        while (readHeader()) {
+            if (!Attributes.Name.NAME.equals(name)) {
                 throw new IOException(Messages.getString("archive.23")); //$NON-NLS-1$
             }
-            // Name: length required space char
-            String name = line.substring(6, line.length());
-            current = new Attributes(12);
+            String entryNameValue = value;
+
+            Attributes entry = entries.get(entryNameValue);
+            if (entry == null) {
+                entry = new Attributes(12);
+            }
+
+            while (readHeader()) {
+                entry.put(name, value);
+            }
+
             if (chunks != null) {
-                chunks.put(name, chunk);
-            }
-            entries.put(name, current);
-            while (it.hasNext()) {
-                addAttribute(it.next(), current);
-            }
-            list.clear();
-        }
-
-    }
-
-    byte[] getMainAttributesChunk() {
-        return mainAttributesChunk;
-    }
-
-    private void addLine(int length, List<String> lines) throws IOException {
-        if (encoding != null) {
-            lines.add(new String(buffer, 0, length, encoding));
-        } else {
-            if (usingUTF8) {
-                try {
-                    if (charbuf.length < length) {
-                        charbuf = new char[length];
-                    }
-                    lines.add(Util.convertUTF8WithBuf(buffer, charbuf, 0,
-                            length));
-                } catch (UTFDataFormatException e) {
-                    usingUTF8 = false;
+                if (chunks.get(entryNameValue) != null) {
+                    // TODO A bug: there might be several verification chunks for
+                    // the same name. I believe they should be used to update
+                    // signature in order of appearance; there are two ways to fix
+                    // this: either use a list of chunks, or decide on used
+                    // signature algorithm in advance and reread the chunks while
+                    // updating the signature; for now a defensive error is thrown
+                    throw new IOException(Messages.getString("archive.34")); //$NON-NLS-1$
                 }
+                chunks.put(entryNameValue, new Manifest.Chunk(mark, pos));
+                mark = pos;
             }
-            if (!usingUTF8) {
-                if (charbuf.length < length) {
-                    charbuf = new char[length];
-                }
-                // If invalid UTF8, convert bytes to chars setting the upper
-                // bytes to zeros
-                int charOffset = 0;
-                int offset = 0;
-                for (int i = length; --i >= 0;) {
-                    charbuf[charOffset++] = (char) (buffer[offset++] & 0xff);
-                }
-                lines.add(new String(charbuf, 0, length));
-            }
+
+            entries.put(entryNameValue, entry);
         }
     }
 
-    private byte[] nextChunk(InputStream in, List<String> lines)
-            throws IOException {
-        if (inbufCount == -1) {
-            return null;
-        }
-        byte next;
-        int pos = 0;
-        boolean blankline = false, lastCr = false;
-        out.reset();
-        while (true) {
-            if (inbufPos == inbufCount) {
-                if ((inbufCount = in.read(inbuf)) == -1) {
-                    if (out.size() == 0) {
-                        return null;
-                    }
-                    if (blankline) {
-                        addLine(pos, lines);
-                    }
-                    return out.toByteArray();
-                }
-                if (inbufCount == inbuf.length && in.available() == 0) {
-                    /* archive.2E = "line too long" */
-                    throw new IOException(Messages.getString("archive.2E")); //$NON-NLS-1$
-                }
-                inbufPos = 0;
-            }
-            next = inbuf[inbufPos++];
-            if (lastCr) {
-                if (next != '\n') {
-                    inbufPos--;
-                    next = '\r';
-                } else {
-                    if (out.size() == 0) {
-                        continue;
-                    }
-                    out.write('\r');
-                }
-                lastCr = false;
-            } else if (next == '\r') {
-                lastCr = true;
-                continue;
-            }
-            if (blankline) {
-                if (next == ' ') {
-                    out.write(next);
-                    blankline = false;
-                    continue;
-                }
-                addLine(pos, lines);
-                if (next == '\n') {
-                    out.write(next);
-                    return out.toByteArray();
-                }
-                pos = 0;
-            } else if (next == '\n') {
-                if (out.size() == 0) {
-                    continue;
-                }
-                out.write(next);
-                blankline = true;
-                continue;
-            }
-            blankline = false;
-            out.write(next);
-            if (pos == buffer.length) {
-                byte[] newBuf = new byte[buffer.length * 2];
-                System.arraycopy(buffer, 0, newBuf, 0, buffer.length);
-                buffer = newBuf;
-            }
-            buffer[pos++] = next;
-        }
+    int getPos() {
+        return pos;
     }
 
-    private boolean readLines(InputStream in, List<String> lines)
-            throws IOException {
-        if (inbufCount == -1) {
+    /**
+     * Number of subsequent line breaks.
+     */
+    int linebreak = 0;
+
+    /**
+     * Read a single line from the manifest buffer.
+     */
+    private boolean readHeader() throws IOException {
+        if (linebreak > 1) {
+            // break a section on an empty line
+            linebreak = 0;
             return false;
         }
-        byte next;
-        int pos = 0;
-        boolean blankline = false, lastCr = false;
-        while (true) {
-            if (inbufPos == inbufCount) {
-                if ((inbufCount = in.read(inbuf)) == -1) {
-                    if (blankline) {
-                        addLine(pos, lines);
-                    }
-                    return lines.size() != 0;
+        readName();
+        linebreak = 0;
+        readValue();
+        // if the last line break is missed, the line
+        // is ignored by the reference implementation
+        return linebreak > 0;
+    }
+
+    private byte[] wrap(int mark, int pos) {
+        byte[] buffer = new byte[pos - mark];
+        System.arraycopy(buf, mark, buffer, 0, pos - mark);
+        return buffer;
+    }
+
+    private void readName() throws IOException {
+        int i = 0;
+        int mark = pos;
+
+        while (pos < buf.length) {
+            byte b = buf[pos++];
+
+            if (b == ':') {
+                byte[] nameBuffer = wrap(mark, pos - 1);
+
+                if (buf[pos++] != ' ') {
+                    throw new IOException(Messages.getString(
+                            "archive.30", nameBuffer)); //$NON-NLS-1$
                 }
-                if (inbufCount == inbuf.length && in.available() == 0) {
-                    /* archive.2E = "line too long" */
-                    throw new IOException(Messages.getString("archive.2E")); //$NON-NLS-1$
-                }
-                inbufPos = 0;
+
+                name = new Attributes.Name(nameBuffer);
+                return;
             }
-            next = inbuf[inbufPos++];
-            if (lastCr) {
-                if (next != '\n') {
-                    inbufPos--;
-                    next = '\r';
-                }
-                lastCr = false;
-            } else if (next == '\r') {
-                lastCr = true;
-                continue;
+
+            if (!((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_'
+                    || b == '-' || (b >= '0' && b <= '9'))) {
+                throw new IOException(Messages.getString("archive.30", b)); //$NON-NLS-1$
             }
-            if (blankline) {
-                if (next == ' ') {
-                    blankline = false;
-                    continue;
-                }
-                addLine(pos, lines);
-                if (next == '\n') {
-                    return true;
-                }
-                pos = 0;
-            } else if (next == '\n') {
-                if (pos == 0 && lines.size() == 0) {
-                    continue;
-                }
-                blankline = true;
-                continue;
-            }
-            blankline = false;
-            if (pos == buffer.length) {
-                byte[] newBuf = new byte[buffer.length * 2];
-                System.arraycopy(buffer, 0, newBuf, 0, buffer.length);
-                buffer = newBuf;
-            }
-            buffer[pos++] = next;
+        }
+        if (i > 0) {
+            throw new IOException(Messages.getString(
+                    "archive.30", wrap(mark, buf.length))); //$NON-NLS-1$
         }
     }
 
-    /* Get the next attribute and add it */
-    private void addAttribute(String line, Attributes current)
-            throws IOException {
-        String header;
-        int hdrIdx = line.indexOf(':');
-        if (hdrIdx < 1) {
-            throw new IOException(Messages.getString("archive.2F", line)); //$NON-NLS-1$
-        }
-        header = line.substring(0, hdrIdx);
-        Attributes.Name name = attributeNames.get(header);
-        if (name == null) {
-            try {
-                name = new Attributes.Name(header);
-            } catch (IllegalArgumentException e) {
-                throw new IOException(e.toString());
+    private void readValue() throws IOException {
+        byte next;
+        boolean lastCr = false;
+        int mark = pos;
+        int last = pos;
+
+        decoder.reset();
+        cBuf.clear();
+
+        while (pos < buf.length) {
+            next = buf[pos++];
+
+            switch (next) {
+            case 0:
+                throw new IOException(Messages.getString("archive.2F")); //$NON-NLS-1$
+            case '\n':
+                if (lastCr) {
+                    lastCr = false;
+                } else {
+                    linebreak++;
+                }
+                continue;
+            case '\r':
+                lastCr = true;
+                linebreak++;
+                continue;
+            case ' ':
+                if (linebreak == 1) {
+                    decode(mark, last, false);
+                    mark = pos;
+                    linebreak = 0;
+                    continue;
+                }
             }
-            attributeNames.put(header, name);
+
+            if (linebreak >= 1) {
+                pos--;
+                break;
+            }
+            last = pos;
         }
-        if (hdrIdx + 1 >= line.length() || line.charAt(hdrIdx + 1) != ' ') {
-            throw new IOException(Messages.getString("archive.2F", line)); //$NON-NLS-1$
+
+        decode(mark, last, true);
+        while (CoderResult.OVERFLOW == decoder.flush(cBuf)) {
+            enlargeBuffer();
         }
-        // +2 due to required SPACE char
-        current.put(name, line.substring(hdrIdx + 2, line.length()));
+        value = new String(cBuf.array(), cBuf.arrayOffset(), cBuf.position());
+    }
+
+    private void decode(int mark, int pos, boolean endOfInput)
+            throws IOException {
+        ByteBuffer bBuf = ByteBuffer.wrap(buf, mark, pos - mark);
+        while (CoderResult.OVERFLOW == decoder.decode(bBuf, cBuf, endOfInput)) {
+            enlargeBuffer();
+        }
+    }
+
+    private void enlargeBuffer() {
+        CharBuffer newBuf = CharBuffer.allocate(cBuf.capacity() * 2);
+        newBuf.put(cBuf.array(), cBuf.arrayOffset(), cBuf.position());
+        cBuf = newBuf;
+        ThreadLocalCache.charBuffer.set(cBuf);
     }
 }
diff --git a/libcore/archive/src/main/java/java/util/jar/JarEntry.java b/libcore/archive/src/main/java/java/util/jar/JarEntry.java
index b8dabee..869e4b4 100644
--- a/libcore/archive/src/main/java/java/util/jar/JarEntry.java
+++ b/libcore/archive/src/main/java/java/util/jar/JarEntry.java
@@ -33,27 +33,27 @@
 /**
  * Represents a single file in a JAR archive together with the manifest
  * attributes and digital signatures associated with it.
- * 
- * @since Android 1.0
+ *
+ * @see JarFile
+ * @see JarInputStream
  */
 public class JarEntry extends ZipEntry {
     private Attributes attributes;
 
     JarFile parentJar;
-   
+
     CodeSigner signers[];
 
     // Cached factory used to build CertPath-s in <code>getCodeSigners()</code>.
     private CertificateFactory factory;
 
-    private boolean isFactoryChecked = false;     
+    private boolean isFactoryChecked = false;
 
     /**
      * Creates a new {@code JarEntry} named name.
      * 
      * @param name
      *            The name of the new {@code JarEntry}.
-     * @since Android 1.0
      */
     public JarEntry(String name) {
         super(name);
@@ -64,7 +64,6 @@
      * 
      * @param entry
      *            The ZipEntry to obtain values from.
-     * @since Android 1.0
      */
     public JarEntry(ZipEntry entry) {
         super(entry);
@@ -78,7 +77,6 @@
      * @exception IOException
      *                If an error occurs obtaining the {@code Attributes}.
      * @see Attributes
-     * @since Android 1.0
      */
     public Attributes getAttributes() throws IOException {
         if (attributes != null || parentJar == null) {
@@ -99,7 +97,6 @@
      * 
      * @return the certificate for this entry.
      * @see java.security.cert.Certificate
-     * @since Android 1.0
      */
     public Certificate[] getCertificates() {
         if (null == parentJar) {
@@ -122,12 +119,11 @@
      * 
      * @param je
      *            The {@code JarEntry} to obtain values from.
-     * @since Android 1.0
      */
     public JarEntry(JarEntry je) {
         super(je);
         parentJar = je.parentJar;
-        attributes = je.attributes;        
+        attributes = je.attributes;
         signers = je.signers;
     }
 
@@ -139,7 +135,6 @@
      * 
      * @return the code signers for the JAR entry.
      * @see CodeSigner
-     * @since Android 1.0
      */
     public CodeSigner[] getCodeSigners() {
         if (null == signers) {
@@ -155,7 +150,7 @@
     }
 
     private CodeSigner[] getCodeSigners(Certificate[] certs) {
-        if(null == certs) {
+        if (null == certs) {
             return null;
         }
 
diff --git a/libcore/archive/src/main/java/java/util/jar/JarException.java b/libcore/archive/src/main/java/java/util/jar/JarException.java
index f18d639..d6943c4 100644
--- a/libcore/archive/src/main/java/java/util/jar/JarException.java
+++ b/libcore/archive/src/main/java/java/util/jar/JarException.java
@@ -22,8 +22,6 @@
 /**
  * This runtime exception is thrown when a problem occurs while reading a JAR
  * file.
- * 
- * @since Android 1.0
  */
 public class JarException extends ZipException {
 
@@ -31,8 +29,6 @@
 
     /**
      * Constructs a new {@code JarException} instance.
-     * 
-     * @since Android 1.0
      */
     public JarException() {
         super();
@@ -41,10 +37,9 @@
     /**
      * Constructs a new {@code JarException} instance with the specified
      * message.
-     * 
+     *
      * @param detailMessage
      *            the detail message for the exception.
-     * @since Android 1.0
      */
     public JarException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/archive/src/main/java/java/util/jar/JarFile.java b/libcore/archive/src/main/java/java/util/jar/JarFile.java
index 9af9056..6f4eb83 100644
--- a/libcore/archive/src/main/java/java/util/jar/JarFile.java
+++ b/libcore/archive/src/main/java/java/util/jar/JarFile.java
@@ -29,7 +29,6 @@
 import java.io.FilterInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.security.MessageDigest;
 import java.util.Enumeration;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
@@ -39,17 +38,14 @@
 /**
  * {@code JarFile} is used to read jar entries and their associated data from
  * jar files.
- * 
+ *
  * @see JarInputStream
  * @see JarEntry
- * @since Android 1.0
  */
 public class JarFile extends ZipFile {
 
     /**
      * The MANIFEST file name.
-     * 
-     * @since Android 1.0
      */
     public static final String MANIFEST_NAME = "META-INF/MANIFEST.MF"; //$NON-NLS-1$
 
@@ -70,63 +66,88 @@
 
         private ZipEntry zipEntry;
 
-        private JarVerifier verifier;
-
         private JarVerifier.VerifierEntry entry;
 
-        private MessageDigest digest;
+        // BEGIN android-added
+        private boolean done = false;
+        // END android-added
 
-        JarFileInputStream(InputStream is, ZipEntry ze, JarVerifier ver) {
+        JarFileInputStream(InputStream is, ZipEntry ze,
+                JarVerifier.VerifierEntry e) {
             super(is);
-            if (ver != null) {
-                zipEntry = ze;
-                verifier = ver;
-                count = zipEntry.getSize();
-                entry = verifier.initEntry(ze.getName());
-                if (entry != null) {
-                    digest = entry.digest;
-                }
-            }
+            zipEntry = ze;
+            count = zipEntry.getSize();
+            entry = e;
         }
 
         @Override
         public int read() throws IOException {
-            int r = super.read();
-            if (entry != null) {
-                if (r != -1) {
-                    digest.update((byte) r);
-                    count--;
-                }
-                if (r == -1 || count <= 0) {
-                    JarVerifier.VerifierEntry temp = entry;
-                    entry = null;
-                    verifier.verifySignatures(temp, zipEntry);
-                }
+            // BEGIN android-changed
+            if (done) {
+                return -1;
             }
-            return r;
+            if (count > 0) {
+                int r = super.read();
+                if (r != -1) {
+                    entry.write(r);
+                    count--;
+                } else {
+                    count = 0;
+                }
+                if (count == 0) {
+                    done = true;
+                    entry.verify();
+                }
+                return r;
+            } else {
+                done = true;
+                entry.verify();
+                return -1;
+            }
+            // END android-changed
         }
 
         @Override
         public int read(byte[] buf, int off, int nbytes) throws IOException {
-            int r = super.read(buf, off, nbytes);
-            if (entry != null) {
+            // BEGIN android-changed
+            if (done) {
+                return -1;
+            }
+            if (count > 0) {
+                int r = super.read(buf, off, nbytes);
                 if (r != -1) {
                     int size = r;
                     if (count < size) {
                         size = (int) count;
                     }
-                    digest.update(buf, off, size);
-                    count -= r;
+                    entry.write(buf, off, size);
+                    count -= size;
+                } else {
+                    count = 0;
                 }
-                if (r == -1 || count <= 0) {
-                    JarVerifier.VerifierEntry temp = entry;
-                    entry = null;
-                    verifier.verifySignatures(temp, zipEntry);
+                if (count == 0) {
+                    done = true;
+                    entry.verify();
                 }
+                return r;
+            } else {
+                done = true;
+                entry.verify();
+                return -1;
             }
-            return r;
+            // END android-changed
         }
 
+        // BEGIN android-added
+        @Override
+        public int available() throws IOException {
+            if (done) {
+                return 0;
+            }
+            return super.available();
+        }
+        // END android-added
+
         @Override
         public long skip(long nbytes) throws IOException {
             long cnt = 0, rem = 0;
@@ -146,12 +167,11 @@
 
     /**
      * Create a new {@code JarFile} using the contents of the specified file.
-     * 
+     *
      * @param file
      *            the JAR file as {@link File}.
      * @throws IOException
      *             If the file cannot be read.
-     * @since Android 1.0
      */
     public JarFile(File file) throws IOException {
         this(file, true);
@@ -159,14 +179,13 @@
 
     /**
      * Create a new {@code JarFile} using the contents of the specified file.
-     * 
+     *
      * @param file
      *            the JAR file as {@link File}.
      * @param verify
      *            if this JAR file is signed whether it must be verified.
      * @throws IOException
      *             If the file cannot be read.
-     * @since Android 1.0
      */
     public JarFile(File file, boolean verify) throws IOException {
         super(file);
@@ -178,7 +197,7 @@
 
     /**
      * Create a new {@code JarFile} using the contents of file.
-     * 
+     *
      * @param file
      *            the JAR file as {@link File}.
      * @param verify
@@ -188,7 +207,6 @@
      *            {@link ZipFile#OPEN_DELETE OPEN_DELETE}.
      * @throws IOException
      *             If the file cannot be read.
-     * @since Android 1.0
      */
     public JarFile(File file, boolean verify, int mode) throws IOException {
         super(file, mode);
@@ -201,12 +219,11 @@
     /**
      * Create a new {@code JarFile} from the contents of the file specified by
      * filename.
-     * 
+     *
      * @param filename
      *            the file name referring to the JAR file.
      * @throws IOException
      *             if file name cannot be opened for reading.
-     * @since Android 1.0
      */
     public JarFile(String filename) throws IOException {
         this(filename, true);
@@ -216,14 +233,13 @@
     /**
      * Create a new {@code JarFile} from the contents of the file specified by
      * {@code filename}.
-     * 
+     *
      * @param filename
      *            the file name referring to the JAR file.
      * @param verify
      *            if this JAR filed is signed whether it must be verified.
      * @throws IOException
      *             If file cannot be opened or read.
-     * @since Android 1.0
      */
     public JarFile(String filename, boolean verify) throws IOException {
         super(filename);
@@ -236,11 +252,10 @@
     /**
      * Return an enumeration containing the {@code JarEntrys} contained in this
      * {@code JarFile}.
-     * 
+     *
      * @return the {@code Enumeration} containing the JAR entries.
      * @throws IllegalStateException
      *             if this {@code JarFile} is closed.
-     * @since Android 1.0
      */
     @Override
     public Enumeration<JarEntry> entries() {
@@ -260,7 +275,7 @@
 
             public JarEntry nextElement() {
                 JarEntry je = new JarEntry(ze.nextElement());
-                je.parentJar = jf;                
+                je.parentJar = jf;
                 return je;
             }
         }
@@ -270,11 +285,10 @@
     /**
      * Return the {@code JarEntry} specified by its name or {@code null} if no
      * such entry exists.
-     * 
+     *
      * @param name
      *            the name of the entry in the JAR file.
      * @return the JAR entry defined by the name.
-     * @since Android 1.0
      */
     public JarEntry getJarEntry(String name) {
         return (JarEntry) getEntry(name);
@@ -302,14 +316,13 @@
     /**
      * Returns the {@code Manifest} object associated with this {@code JarFile}
      * or {@code null} if no MANIFEST entry exists.
-     * 
+     *
      * @return the MANIFEST.
      * @throws IOException
      *             if an error occurs reading the MANIFEST file.
      * @throws IllegalStateException
      *             if the jar file is closed.
      * @see Manifest
-     * @since Android 1.0
      */
     public Manifest getManifest() throws IOException {
         // BEGIN android-added
@@ -358,10 +371,14 @@
                     if (verifier == null) {
                         break;
                     }
-                } else if (verifier != null && entryName.length() > dirLength
-                        && (Util.ASCIIIgnoreCaseRegionMatches(entryName, entryName.length() - 3, ".SF", 0 ,3) //$NON-NLS-1$
-                           || Util.ASCIIIgnoreCaseRegionMatches(entryName, entryName.length() - 4, ".DSA", 0 ,4) //$NON-NLS-1$
-                           || Util.ASCIIIgnoreCaseRegionMatches(entryName, entryName.length() - 4, ".RSA", 0 ,4))){ //$NON-NLS-1$
+                } else if (verifier != null
+                        && entryName.length() > dirLength
+                        && (Util.ASCIIIgnoreCaseRegionMatches(entryName,
+                                entryName.length() - 3, ".SF", 0, 3) //$NON-NLS-1$
+                                || Util.ASCIIIgnoreCaseRegionMatches(entryName,
+                                        entryName.length() - 4, ".DSA", 0, 4) //$NON-NLS-1$
+                        || Util.ASCIIIgnoreCaseRegionMatches(entryName,
+                                entryName.length() - 4, ".RSA", 0, 4))) { //$NON-NLS-1$
                     signed = true;
                     InputStream is = super.getInputStream(entry);
                     // BEGIN android-modified
@@ -379,13 +396,12 @@
     /**
      * Return an {@code InputStream} for reading the decompressed contents of
      * ZIP entry.
-     * 
+     *
      * @param ze
      *            the ZIP entry to be read.
      * @return the input stream to read from.
      * @throws IOException
      *             if an error occurred while creating the input stream.
-     * @since Android 1.0
      */
     @Override
     public InputStream getInputStream(ZipEntry ze) throws IOException {
@@ -395,8 +411,7 @@
         if (verifier != null) {
             verifier.setManifest(getManifest());
             if (manifest != null) {
-                verifier.mainAttributesChunk = manifest
-                        .getMainAttributesChunk();
+                verifier.mainAttributesEnd = manifest.getMainAttributesEnd();
             }
             if (verifier.readCertificates()) {
                 verifier.removeMetaEntries();
@@ -412,19 +427,24 @@
         if (in == null) {
             return null;
         }
-        return new JarFileInputStream(in, ze, ze.getSize() >= 0 ? verifier
-                : null);
+        if (verifier == null || ze.getSize() == -1) {
+            return in;
+        }
+        JarVerifier.VerifierEntry entry = verifier.initEntry(ze.getName());
+        if (entry == null) {
+            return in;
+        }
+        return new JarFileInputStream(in, ze, entry);
     }
 
     /**
      * Return the {@code JarEntry} specified by name or {@code null} if no such
      * entry exists.
-     * 
+     *
      * @param name
      *            the name of the entry in the JAR file.
      * @return the ZIP entry extracted.
-     * @since Android 1.0
-     */         
+     */
     @Override
     public ZipEntry getEntry(String name) {
         ZipEntry ze = super.getEntry(name);
@@ -432,16 +452,16 @@
             return ze;
         }
         JarEntry je = new JarEntry(ze);
-        je.parentJar = this;        
+        je.parentJar = this;
         return je;
     }
 
     // BEGIN android-modified
     private ZipEntry[] getMetaEntriesImpl(byte[] buf) {
         int n = 0;
-        
+
         List<ZipEntry> list = new ArrayList<ZipEntry>();
-        
+
         Enumeration<? extends ZipEntry> allEntries = entries();
         while (allEntries.hasMoreElements()) {
             ZipEntry ze = allEntries.nextElement();
@@ -463,10 +483,9 @@
     // BEGIN android-added
     /**
      * Closes this {@code JarFile}.
-     * 
+     *
      * @throws IOException
      *             if an error occurs.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
diff --git a/libcore/archive/src/main/java/java/util/jar/JarInputStream.java b/libcore/archive/src/main/java/java/util/jar/JarInputStream.java
index ef353ab..c803183 100644
--- a/libcore/archive/src/main/java/java/util/jar/JarInputStream.java
+++ b/libcore/archive/src/main/java/java/util/jar/JarInputStream.java
@@ -24,14 +24,13 @@
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 
-import org.apache.harmony.archive.util.Util;
+import org.apache.harmony.luni.util.Util;
 
 /**
  * The input stream from which the JAR file to be read may be fetched. It is
  * used like the {@code ZipInputStream}.
- * 
+ *
  * @see ZipInputStream
- * @since Android 1.0
  */
 public class JarInputStream extends ZipInputStream {
 
@@ -51,7 +50,7 @@
 
     /**
      * Constructs a new {@code JarInputStream} from an input stream.
-     * 
+     *
      * @param stream
      *            the input stream containing the JAR file.
      * @param verify
@@ -59,7 +58,6 @@
      * @throws IOException
      *             If an error occurs reading entries from the input stream.
      * @see ZipInputStream#ZipInputStream(InputStream)
-     * @since Android 1.0
      */
     public JarInputStream(InputStream stream, boolean verify)
             throws IOException {
@@ -84,8 +82,8 @@
             if (verify) {
                 verifier.setManifest(manifest);
                 if (manifest != null) {
-                    verifier.mainAttributesChunk = manifest
-                            .getMainAttributesChunk();
+                    verifier.mainAttributesEnd = manifest
+                            .getMainAttributesEnd();
                 }
             }
 
@@ -103,13 +101,12 @@
 
     /**
      * Constructs a new {@code JarInputStream} from an input stream.
-     * 
+     *
      * @param stream
      *            the input stream containing the JAR file.
      * @throws IOException
      *             If an error occurs reading entries from the input stream.
      * @see ZipInputStream#ZipInputStream(InputStream)
-     * @since Android 1.0
      */
     public JarInputStream(InputStream stream) throws IOException {
         this(stream, true);
@@ -120,7 +117,6 @@
      * JarInputStream} or {@code null} if no manifest entry exists.
      * 
      * @return the MANIFEST specifying the contents of the JAR file.
-     * @since Android 1.0
      */
     public Manifest getManifest() {
         return manifest;
@@ -133,7 +129,6 @@
      * @return the next JAR entry.
      * @throws IOException
      *             if an error occurs while reading the entry.
-     * @since Android 1.0
      */
     public JarEntry getNextJarEntry() throws IOException {
         return (JarEntry) getNextEntry();
@@ -142,7 +137,7 @@
     /**
      * Reads up to {@code length} of decompressed data and stores it in
      * {@code buffer} starting at {@code offset}.
-     * 
+     *
      * @param buffer
      *            Buffer to store into
      * @param offset
@@ -152,7 +147,6 @@
      * @return Number of uncompressed bytes read
      * @throws IOException
      *             if an IOException occurs.
-     * @since Android 1.0
      */
     @Override
     public int read(byte[] buffer, int offset, int length) throws IOException {
@@ -175,9 +169,7 @@
                             throw e;
                         }
                     } else {
-                        verifier.verifySignatures(
-                                (JarVerifier.VerifierEntry) verStream,
-                                jarEntry);
+                        ((JarVerifier.VerifierEntry) verStream).verify();
                     }
                 }
             } else {
@@ -194,7 +186,6 @@
      * @return the next extracted ZIP entry.
      * @throws IOException
      *             if an error occurs while reading the entry.
-     * @since Android 1.0
      */
     @Override
     public ZipEntry getNextEntry() throws IOException {
diff --git a/libcore/archive/src/main/java/java/util/jar/JarOutputStream.java b/libcore/archive/src/main/java/java/util/jar/JarOutputStream.java
index 640f4ef..e901d87 100644
--- a/libcore/archive/src/main/java/java/util/jar/JarOutputStream.java
+++ b/libcore/archive/src/main/java/java/util/jar/JarOutputStream.java
@@ -25,8 +25,6 @@
 /**
  * The {@code JarOutputStream} is used to write data in the {@code JarFile}
  * format to an arbitrary output stream
- * 
- * @since Android 1.0
  */
 public class JarOutputStream extends ZipOutputStream {
 
@@ -79,7 +77,6 @@
      * @throws IOException
      *             if an error occurs writing to the entry.
      * @see ZipEntry
-     * @since Android 1.0
      */
     @Override
     public void putNextEntry(ZipEntry ze) throws IOException {
diff --git a/libcore/archive/src/main/java/java/util/jar/JarVerifier.java b/libcore/archive/src/main/java/java/util/jar/JarVerifier.java
index b9173f2..6c1ee93 100644
--- a/libcore/archive/src/main/java/java/util/jar/JarVerifier.java
+++ b/libcore/archive/src/main/java/java/util/jar/JarVerifier.java
@@ -31,13 +31,12 @@
 import java.util.Map;
 import java.util.StringTokenizer;
 import java.util.Vector;
-import java.util.zip.ZipEntry;
 
 import org.apache.harmony.archive.internal.nls.Messages;
 import org.apache.harmony.luni.util.Base64;
 import org.apache.harmony.security.utils.JarUtils;
 
-import org.apache.harmony.archive.util.Util;
+import org.apache.harmony.luni.util.Util;
 
 // BEGIN android-added
 import org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK;
@@ -65,65 +64,81 @@
 
     private HashMap<String, byte[]> metaEntries = new HashMap<String, byte[]>(5);
 
-    private final Hashtable<String, HashMap<String, Attributes>> signatures =
-        new Hashtable<String, HashMap<String, Attributes>>(5);
+    private final Hashtable<String, HashMap<String, Attributes>> signatures = new Hashtable<String, HashMap<String, Attributes>>(
+            5);
 
-    private final Hashtable<String, Certificate[]> certificates =
-        new Hashtable<String, Certificate[]>(5);
+    private final Hashtable<String, Certificate[]> certificates = new Hashtable<String, Certificate[]>(
+            5);
 
-    private final Hashtable<String, Certificate[]> verifiedEntries =
-        new Hashtable<String, Certificate[]>();
+    private final Hashtable<String, Certificate[]> verifiedEntries = new Hashtable<String, Certificate[]>();
 
-    byte[] mainAttributesChunk;
+    int mainAttributesEnd;
 
-    // BEGIN android-added
-    private static long measureCount = 0;
-    
-    private static long averageTime = 0;
-    // END android-added
-    
     /**
-     * TODO Type description
+     * Stores and a hash and a message digest and verifies that massage digest
+     * matches the hash.
      */
-    static class VerifierEntry extends OutputStream {
+    class VerifierEntry extends OutputStream {
 
-        MessageDigest digest;
+        private String name;
 
-        byte[] hash;
+        private MessageDigest digest;
 
-        Certificate[] certificates;
+        private byte[] hash;
 
-        VerifierEntry(MessageDigest digest, byte[] hash,
+        private Certificate[] certificates;
+
+        VerifierEntry(String name, MessageDigest digest, byte[] hash,
                 Certificate[] certificates) {
+            this.name = name;
             this.digest = digest;
             this.hash = hash;
             this.certificates = certificates;
         }
 
-        /*
-         * (non-Javadoc)
-         * 
-         * @see java.io.OutputStream#write(int)
+        /**
+         * Updates a digest with one byte.
          */
         @Override
         public void write(int value) {
             digest.update((byte) value);
         }
 
-        /*
-         * (non-Javadoc)
-         * 
-         * @see java.io.OutputStream#write(byte[], int, int)
+        /**
+         * Updates a digest with byte array.
          */
         @Override
         public void write(byte[] buf, int off, int nbytes) {
             digest.update(buf, off, nbytes);
         }
+
+        /**
+         * Verifies that the digests stored in the manifest match the decrypted
+         * digests from the .SF file. This indicates the validity of the
+         * signing, not the integrity of the file, as it's digest must be
+         * calculated and verified when its contents are read.
+         *
+         * @throws SecurityException
+         *             if the digest value stored in the manifest does <i>not</i>
+         *             agree with the decrypted digest as recovered from the
+         *             <code>.SF</code> file.
+         * @see #initEntry(String)
+         */
+        void verify() {
+            byte[] d = digest.digest();
+            if (!MessageDigest.isEqual(d, Base64.decode(hash))) {
+                throw new SecurityException(Messages.getString(
+                        "archive.32", new Object[] { //$NON-NLS-1$
+                        JarFile.MANIFEST_NAME, name, jarName }));
+            }
+            verifiedEntries.put(name, certificates);
+        }
+
     }
 
     /**
      * Constructs and returns a new instance of {@code JarVerifier}.
-     * 
+     *
      * @param name
      *            the name of the JAR file being verified.
      */
@@ -136,13 +151,12 @@
      * stream. This method constructs and returns a new {@link VerifierEntry}
      * which contains the certificates used to sign the entry and its hash value
      * as specified in the JAR MANIFEST format.
-     * 
+     *
      * @param name
      *            the name of an entry in a JAR file which is <b>not</b> in the
      *            {@code META-INF} directory.
      * @return a new instance of {@link VerifierEntry} which can be used by
      *         callers as an {@link OutputStream}.
-     * @since Android 1.0
      */
     VerifierEntry initEntry(String name) {
         // If no manifest is present by the time an entry is found,
@@ -159,8 +173,8 @@
         }
 
         Vector<Certificate> certs = new Vector<Certificate>();
-        Iterator<Map.Entry<String, HashMap<String, Attributes>>> it =
-            signatures.entrySet().iterator();
+        Iterator<Map.Entry<String, HashMap<String, Attributes>>> it = signatures
+                .entrySet().iterator();
         while (it.hasNext()) {
             Map.Entry<String, HashMap<String, Attributes>> entry = it.next();
             HashMap<String, Attributes> hm = entry.getValue();
@@ -197,18 +211,18 @@
             }
             byte[] hashBytes;
             try {
-                hashBytes = hash.getBytes("ISO8859_1"); //$NON-NLS-1$
+                hashBytes = hash.getBytes("ISO-8859-1"); //$NON-NLS-1$
             } catch (UnsupportedEncodingException e) {
                 throw new RuntimeException(e.toString());
             }
 
             try {
                 // BEGIN android-changed
-                return new VerifierEntry(OpenSSLMessageDigestJDK.getInstance(algorithm),
+                return new VerifierEntry(name, OpenSSLMessageDigestJDK.getInstance(algorithm),
                         hashBytes, certificatesArray);
                 // END android-changed
             } catch (NoSuchAlgorithmException e) {
-                // Ignored
+                // ignored
             }
         }
         return null;
@@ -219,7 +233,7 @@
      * entry in the {@code META-INF} directory including the manifest
      * file itself. Files associated with the signing of a JAR would also be
      * added to this collection.
-     * 
+     *
      * @param name
      *            the name of the file located in the {@code META-INF}
      *            directory.
@@ -234,7 +248,7 @@
     /**
      * If the associated JAR file is signed, check on the validity of all of the
      * known signatures.
-     * 
+     *
      * @return {@code true} if the associated JAR is signed and an internal
      *         check verifies the validity of the signature(s). {@code false} if
      *         the associated JAR file has no entries at all in its {@code
@@ -243,12 +257,10 @@
      *         <p>
      *         Will also return {@code true} if the JAR file is <i>not</i>
      *         signed.
-     *         </p>
      * @throws SecurityException
      *             if the JAR file is signed and it is determined that a
      *             signature block file contains an invalid signature for the
      *             corresponding signature file.
-     * @since Android 1.0
      */
     synchronized boolean readCertificates() {
         if (metaEntries == null) {
@@ -281,6 +293,12 @@
             return;
         }
 
+        byte[] manifest = metaEntries.get(JarFile.MANIFEST_NAME);
+        // Manifest entry is required for any verifications.
+        if (manifest == null) {
+            return;
+        }
+
         byte[] sBlockBytes = metaEntries.get(certFile);
         try {
             Certificate[] signerCertChain = JarUtils.verifySignature(
@@ -288,7 +306,7 @@
                     new ByteArrayInputStream(sBlockBytes));
             /*
              * Recursive call in loading security provider related class which
-             * is in a signed JAR. 
+             * is in a signed JAR.
              */
             if (null == metaEntries) {
                 return;
@@ -299,74 +317,70 @@
         } catch (IOException e) {
             return;
         } catch (GeneralSecurityException e) {
-            /* [MSG "archive.30", "{0} failed verification of {1}"] */
-            throw new SecurityException(
-                    Messages.getString("archive.30", jarName, signatureFile)); //$NON-NLS-1$
+            /* [MSG "archive.31", "{0} failed verification of {1}"] */
+            throw new SecurityException(Messages.getString(
+                    "archive.31", jarName, signatureFile)); //$NON-NLS-1$
         }
 
         // Verify manifest hash in .sf file
         Attributes attributes = new Attributes();
-        HashMap<String, Attributes> hm = new HashMap<String, Attributes>();
+        HashMap<String, Attributes> entries = new HashMap<String, Attributes>();
         try {
-            new InitManifest(new ByteArrayInputStream(sfBytes), attributes, hm,
-                    null, "Signature-Version"); //$NON-NLS-1$
+            InitManifest im = new InitManifest(sfBytes, attributes, Attributes.Name.SIGNATURE_VERSION);
+            im.initEntries(entries, null);
         } catch (IOException e) {
             return;
         }
 
         boolean createdBySigntool = false;
-        String createdByValue = attributes.getValue("Created-By"); //$NON-NLS-1$
-        if (createdByValue != null) {
-            createdBySigntool = createdByValue.indexOf("signtool") != -1; //$NON-NLS-1$
+        String createdBy = attributes.getValue("Created-By"); //$NON-NLS-1$
+        if (createdBy != null) {
+            createdBySigntool = createdBy.indexOf("signtool") != -1; //$NON-NLS-1$
         }
 
         // Use .SF to verify the mainAttributes of the manifest
         // If there is no -Digest-Manifest-Main-Attributes entry in .SF
         // file, such as those created before java 1.5, then we ignore
         // such verification.
-        // FIXME: The meaning of createdBySigntool
-        if (mainAttributesChunk != null && !createdBySigntool) {
+        if (mainAttributesEnd > 0 && !createdBySigntool) {
             String digestAttribute = "-Digest-Manifest-Main-Attributes"; //$NON-NLS-1$
-            if (!verify(attributes, digestAttribute, mainAttributesChunk,
-                    false, true)) {
-                /* [MSG "archive.30", "{0} failed verification of {1}"] */
-                throw new SecurityException(
-                        Messages.getString("archive.30", jarName, signatureFile)); //$NON-NLS-1$
+            if (!verify(attributes, digestAttribute, manifest, 0,
+                    mainAttributesEnd, false, true)) {
+                /* [MSG "archive.31", "{0} failed verification of {1}"] */
+                throw new SecurityException(Messages.getString(
+                        "archive.31", jarName, signatureFile)); //$NON-NLS-1$
             }
         }
 
-        byte[] manifest = metaEntries.get(JarFile.MANIFEST_NAME);
-        if (manifest == null) {
-            return;
-        }
-        // Use .SF to verify the whole manifest
+        // Use .SF to verify the whole manifest.
         String digestAttribute = createdBySigntool ? "-Digest" //$NON-NLS-1$
                 : "-Digest-Manifest"; //$NON-NLS-1$
-        if (!verify(attributes, digestAttribute, manifest, false, false)) {
-            Iterator<Map.Entry<String, Attributes>> it = hm.entrySet()
+        if (!verify(attributes, digestAttribute, manifest, 0, manifest.length,
+                false, false)) {
+            Iterator<Map.Entry<String, Attributes>> it = entries.entrySet()
                     .iterator();
             while (it.hasNext()) {
                 Map.Entry<String, Attributes> entry = it.next();
-                byte[] chunk = man.getChunk(entry.getKey());
+                Manifest.Chunk chunk = man.getChunk(entry.getKey());
                 if (chunk == null) {
                     return;
                 }
-                if (!verify(entry.getValue(), "-Digest", chunk, //$NON-NLS-1$
-                        createdBySigntool, false)) {
-                    /* [MSG "archive.31", "{0} has invalid digest for {1} in {2}"] */
-                    throw new SecurityException(
-                        Messages.getString("archive.31", //$NON-NLS-1$
-                            new Object[] { signatureFile, entry.getKey(), jarName }));
+                if (!verify(entry.getValue(), "-Digest", manifest, //$NON-NLS-1$
+                        chunk.start, chunk.end, createdBySigntool, false)) {
+                    throw new SecurityException(Messages.getString(
+                            "archive.32", //$NON-NLS-1$
+                            new Object[] { signatureFile, entry.getKey(),
+                                    jarName }));
                 }
             }
         }
         metaEntries.put(signatureFile, null);
-        signatures.put(signatureFile, hm);
+        signatures.put(signatureFile, entries);
     }
 
     /**
      * Associate this verifier with the specified {@link Manifest} object.
-     * 
+     *
      * @param mf
      *            a {@code java.util.jar.Manifest} object.
      */
@@ -375,36 +389,9 @@
     }
 
     /**
-     * Verifies that the digests stored in the manifest match the decrypted
-     * digests from the .SF file. This indicates the validity of the signing,
-     * not the integrity of the file, as it's digest must be calculated and
-     * verified when its contents are read.
-     * 
-     * @param entry
-     *            the {@link VerifierEntry} associated with the specified
-     *            {@code zipEntry}.
-     * @param zipEntry
-     *            an entry in the JAR file
-     * @throws SecurityException
-     *             if the digest value stored in the manifest does <i>not</i>
-     *             agree with the decrypted digest as recovered from the
-     *             {@code .SF} file.
-     * @see #initEntry(String)
-     */
-    void verifySignatures(VerifierEntry entry, ZipEntry zipEntry) {
-        byte[] digest = entry.digest.digest();
-        if (!MessageDigest.isEqual(digest, Base64.decode(entry.hash))) {
-            /* [MSG "archive.31", "{0} has invalid digest for {1} in {2}"] */
-            throw new SecurityException(Messages.getString("archive.31", new Object[] { //$NON-NLS-1$
-                    JarFile.MANIFEST_NAME, zipEntry.getName(), jarName }));
-        }
-        verifiedEntries.put(zipEntry.getName(), entry.certificates);
-    }
-
-    /**
-     * Returns a {@code boolean} indication of whether or not the
-     * associated JAR file is signed.
-     * 
+     * Returns a <code>boolean</code> indication of whether or not the
+     * associated jar file is signed.
+     *
      * @return {@code true} if the JAR is signed, {@code false}
      *         otherwise.
      */
@@ -413,7 +400,7 @@
     }
 
     private boolean verify(Attributes attributes, String entry, byte[] data,
-            boolean ignoreSecondEndline, boolean ignorable) {
+            int start, int end, boolean ignoreSecondEndline, boolean ignorable) {
         String algorithms = attributes.getValue("Digest-Algorithms"); //$NON-NLS-1$
         if (algorithms == null) {
             algorithms = "SHA SHA1"; //$NON-NLS-1$
@@ -434,16 +421,16 @@
             } catch (NoSuchAlgorithmException e) {
                 continue;
             }
-            if (ignoreSecondEndline && data[data.length - 1] == '\n'
-                    && data[data.length - 2] == '\n') {
-                md.update(data, 0, data.length - 1);
+            if (ignoreSecondEndline && data[end - 1] == '\n'
+                    && data[end - 2] == '\n') {
+                md.update(data, start, end - 1 - start);
             } else {
-                md.update(data, 0, data.length);
+                md.update(data, start, end - start);
             }
             byte[] b = md.digest();
             byte[] hashBytes;
             try {
-                hashBytes = hash.getBytes("ISO8859_1"); //$NON-NLS-1$
+                hashBytes = hash.getBytes("ISO-8859-1"); //$NON-NLS-1$
             } catch (UnsupportedEncodingException e) {
                 throw new RuntimeException(e.toString());
             }
@@ -456,7 +443,7 @@
      * Returns all of the {@link java.security.cert.Certificate} instances that
      * were used to verify the signature on the JAR entry called
      * {@code name}.
-     * 
+     *
      * @param name
      *            the name of a JAR entry.
      * @return an array of {@link java.security.cert.Certificate}.
@@ -472,7 +459,7 @@
     /**
      * Remove all entries from the internal collection of data held about each
      * JAR entry in the {@code META-INF} directory.
-     * 
+     *
      * @see #addMetaEntry(String, byte[])
      */
     void removeMetaEntries() {
@@ -483,7 +470,7 @@
      * Returns a {@code Vector} of all of the
      * {@link java.security.cert.Certificate}s that are associated with the
      * signing of the named signature file.
-     * 
+     *
      * @param signatureFileName
      *            the name of a signature file.
      * @param certificates
diff --git a/libcore/archive/src/main/java/java/util/jar/Manifest.java b/libcore/archive/src/main/java/java/util/jar/Manifest.java
index 3b0d89a..b28f3fb 100644
--- a/libcore/archive/src/main/java/java/util/jar/Manifest.java
+++ b/libcore/archive/src/main/java/java/util/jar/Manifest.java
@@ -17,47 +17,65 @@
 
 package java.util.jar;
 
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
-import java.nio.charset.Charset;
-import java.security.AccessController;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 
-import org.apache.harmony.luni.util.PriviAction;
+import org.apache.harmony.archive.internal.nls.Messages;
+import org.apache.harmony.luni.util.InputStreamExposer;
+import org.apache.harmony.luni.util.ThreadLocalCache;
 
 /**
  * The {@code Manifest} class is used to obtain attribute information for a
  * {@code JarFile} and its entries.
- * 
- * @since Android 1.0
  */
 public class Manifest implements Cloneable {
-    private static final int LINE_LENGTH_LIMIT = 70;
+    static final int LINE_LENGTH_LIMIT = 72;
 
     private static final byte[] LINE_SEPARATOR = new byte[] { '\r', '\n' };
 
-    private static final Attributes.Name NAME_ATTRIBUTE = new Attributes.Name("Name"); //$NON-NLS-1$
+    private static final byte[] VALUE_SEPARATOR = new byte[] { ':', ' ' };
+
+    private static final Attributes.Name NAME_ATTRIBUTE = new Attributes.Name(
+            "Name"); //$NON-NLS-1$
 
     private Attributes mainAttributes = new Attributes();
 
-    private HashMap<String, Attributes> entryAttributes = new HashMap<String, Attributes>();
+    private HashMap<String, Attributes> entries = new HashMap<String, Attributes>();
 
-    private HashMap<String, byte[]> chunks;
+    static class Chunk {
+        int start;
+        int end;
+
+        Chunk(int start, int end) {
+            this.start = start;
+            this.end = end;
+        }
+    }
+
+    private HashMap<String, Chunk> chunks;
 
     /**
-     * The data chunk of main attributes in the manifest is needed in
+     * Manifest bytes are used for delayed entry parsing.
+     */
+    private InitManifest im;
+
+    /**
+     * The end of the main attributes section in the manifest is needed in
      * verification.
      */
-    private byte[] mainAttributesChunk;
+    private int mainEnd;
 
     /**
      * Creates a new {@code Manifest} instance.
-     * 
-     * @since Android 1.0
      */
     public Manifest() {
         super();
@@ -66,12 +84,11 @@
     /**
      * Creates a new {@code Manifest} instance using the attributes obtained
      * from the input stream.
-     * 
+     *
      * @param is
      *            {@code InputStream} to parse for attributes.
      * @throws IOException
      *             if an IO error occurs while creating this {@code Manifest}
-     * @since Android 1.0
      */
     public Manifest(InputStream is) throws IOException {
         super();
@@ -81,20 +98,20 @@
     /**
      * Creates a new {@code Manifest} instance. The new instance will have the
      * same attributes as those found in the parameter {@code Manifest}.
-     * 
+     *
      * @param man
      *            {@code Manifest} instance to obtain attributes from.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public Manifest(Manifest man) {
         mainAttributes = (Attributes) man.mainAttributes.clone();
-        entryAttributes = (HashMap<String, Attributes>) man.entryAttributes.clone();
+        entries = (HashMap<String, Attributes>) ((HashMap<String, Attributes>) man
+                .getEntries()).clone();
     }
 
     Manifest(InputStream is, boolean readChunks) throws IOException {
         if (readChunks) {
-            chunks = new HashMap<String, byte[]>();
+            chunks = new HashMap<String, Chunk>();
         }
         read(is);
     }
@@ -102,23 +119,21 @@
     /**
      * Resets the both the main attributes as well as the entry attributes
      * associated with this {@code Manifest}.
-     * 
-     * @since Android 1.0
      */
     public void clear() {
-        entryAttributes.clear();
+        im = null;
+        entries.clear();
         mainAttributes.clear();
     }
 
     /**
      * Returns the {@code Attributes} associated with the parameter entry
      * {@code name}.
-     * 
+     *
      * @param name
      *            the name of the entry to obtain {@code Attributes} from.
      * @return the Attributes for the entry or {@code null} if the entry does
      *         not exist.
-     * @since Android 1.0
      */
     public Attributes getAttributes(String name) {
         return getEntries().get(name);
@@ -127,20 +142,31 @@
     /**
      * Returns a map containing the {@code Attributes} for each entry in the
      * {@code Manifest}.
-     * 
+     *
      * @return the map of entry attributes.
-     * @since Android 1.0
      */
     public Map<String, Attributes> getEntries() {
-        return entryAttributes;
+        initEntries();
+        return entries;
+    }
+
+    private void initEntries() {
+        if (im == null) {
+            return;
+        }
+        // try {
+        // im.initEntries(entries, chunks);
+        // } catch (IOException ioe) {
+        // throw new RuntimeException(ioe);
+        // }
+        // im = null;
     }
 
     /**
      * Returns the main {@code Attributes} of the {@code JarFile}.
-     * 
+     *
      * @return main {@code Attributes} associated with the source {@code
      *         JarFile}.
-     * @since Android 1.0
      */
     public Attributes getMainAttributes() {
         return mainAttributes;
@@ -149,9 +175,8 @@
     /**
      * Creates a copy of this {@code Manifest}. The returned {@code Manifest}
      * will equal the {@code Manifest} from which it was cloned.
-     * 
+     *
      * @return a copy of this instance.
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -161,12 +186,11 @@
     /**
      * Writes out the attribute information of the receiver to the specified
      * {@code OutputStream}.
-     * 
+     *
      * @param os
      *            The {@code OutputStream} to write to.
      * @throws IOException
      *             If an error occurs writing the {@code Manifest}.
-     * @since Android 1.0
      */
     public void write(OutputStream os) throws IOException {
         write(this, os);
@@ -175,39 +199,98 @@
     /**
      * Constructs a new {@code Manifest} instance obtaining attribute
      * information from the specified input stream.
-     * 
+     *
      * @param is
      *            The {@code InputStream} to read from.
      * @throws IOException
      *             If an error occurs reading the {@code Manifest}.
-     * @since Android 1.0
      */
     public void read(InputStream is) throws IOException {
-        InitManifest initManifest = new InitManifest(is, mainAttributes, entryAttributes,
-                chunks, null);
-        mainAttributesChunk = initManifest.getMainAttributesChunk();
+        byte[] buf;
+        // Try to read get a reference to the bytes directly
+        try {
+            buf = InputStreamExposer.expose(is);
+        } catch (UnsupportedOperationException uoe) {
+            buf = readFully(is);
+        }
+
+        if (buf.length == 0) {
+            return;
+        }
+
+        // a workaround for HARMONY-5662
+        // replace EOF and NUL with another new line
+        // which does not trigger an error
+        byte b = buf[buf.length - 1];
+        if (0 == b || 26 == b) {
+            buf[buf.length - 1] = '\n';
+        }
+
+        // Attributes.Name.MANIFEST_VERSION is not used for
+        // the second parameter for RI compatibility
+        im = new InitManifest(buf, mainAttributes, null);
+        mainEnd = im.getPos();
+        // FIXME
+        im.initEntries(entries, chunks);
+        im = null;
+    }
+
+    /*
+     * Helper to read the entire contents of the manifest from the
+     * given input stream.  Usually we can do this in a single read
+     * but we need to account for 'infinite' streams, by ensuring we
+     * have a line feed within a reasonable number of characters.
+     */
+    private byte[] readFully(InputStream is) throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        byte[] buffer = new byte[8192];
+
+        while (true) {
+            int count = is.read(buffer);
+            if (count == -1) {
+                // TODO: Do we need to copy this, or can we live with junk at the end?
+                return baos.toByteArray();
+            }
+            baos.write(buffer, 0, count);
+
+            if (!containsLine(buffer, count)) {
+                throw new IOException(Messages.getString("archive.2E")); //$NON-NLS-1$
+            }
+        }
+    }
+
+    /*
+     * Check to see if the buffer contains a newline or carriage
+     * return character within the first 'length' bytes.  Used to
+     * check the validity of the manifest input stream.
+     */
+    private boolean containsLine(byte[] buffer, int length) {
+        for (int i = 0; i < length; i++) {
+            if (buffer[i] == 0x0A || buffer[i] == 0x0D) {
+                return true;
+            }
+        }
+        return false;
     }
 
     /**
      * Returns the hash code for this instance.
-     * 
+     *
      * @return this {@code Manifest}'s hashCode.
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
-        return mainAttributes.hashCode() ^ entryAttributes.hashCode();
+        return mainAttributes.hashCode() ^ getEntries().hashCode();
     }
 
     /**
      * Determines if the receiver is equal to the parameter object. Two {@code
      * Manifest}s are equal if they have identical main attributes as well as
      * identical entry attributes.
-     * 
+     *
      * @param o
      *            the object to compare against.
      * @return {@code true} if the manifests are equal, {@code false} otherwise
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object o) {
@@ -220,10 +303,10 @@
         if (!mainAttributes.equals(((Manifest) o).mainAttributes)) {
             return false;
         }
-        return entryAttributes.equals(((Manifest) o).entryAttributes);
+        return getEntries().equals(((Manifest) o).getEntries());
     }
 
-    byte[] getChunk(String name) {
+    Chunk getChunk(String name) {
         return chunks.get(name);
     }
 
@@ -231,114 +314,84 @@
         chunks = null;
     }
 
-    byte[] getMainAttributesChunk() {
-        return mainAttributesChunk;
+    int getMainAttributesEnd() {
+        return mainEnd;
     }
 
     /**
      * Writes out the attribute information of the specified manifest to the
      * specified {@code OutputStream}
-     * 
+     *
      * @param manifest
      *            the manifest to write out.
      * @param out
      *            The {@code OutputStream} to write to.
      * @throws IOException
      *             If an error occurs writing the {@code Manifest}.
-     * @since Android 1.0
      */
     static void write(Manifest manifest, OutputStream out) throws IOException {
-        Charset charset = null;
-        String encoding = AccessController.doPrivileged(new PriviAction<String>(
-                "manifest.write.encoding")); //$NON-NLS-1$
-        if (encoding != null) {
-            if (encoding.length() == 0) {
-                encoding = "UTF8"; //$NON-NLS-1$
-            }
-            charset = Charset.forName(encoding);
-        }
-        String version = manifest.mainAttributes.getValue(Attributes.Name.MANIFEST_VERSION);
+        CharsetEncoder encoder = ThreadLocalCache.utf8Encoder.get();
+        ByteBuffer buffer = ThreadLocalCache.byteBuffer.get();
+
+        String version = manifest.mainAttributes
+                .getValue(Attributes.Name.MANIFEST_VERSION);
         if (version != null) {
-            writeEntry(out, charset, Attributes.Name.MANIFEST_VERSION, version);
+            writeEntry(out, Attributes.Name.MANIFEST_VERSION, version, encoder,
+                    buffer);
             Iterator<?> entries = manifest.mainAttributes.keySet().iterator();
             while (entries.hasNext()) {
                 Attributes.Name name = (Attributes.Name) entries.next();
                 if (!name.equals(Attributes.Name.MANIFEST_VERSION)) {
-                    writeEntry(out, charset, name, manifest.mainAttributes.getValue(name));
+                    writeEntry(out, name, manifest.mainAttributes
+                            .getValue(name), encoder, buffer);
                 }
             }
         }
         out.write(LINE_SEPARATOR);
-        Iterator<String> i = manifest.entryAttributes.keySet().iterator();
+        Iterator<String> i = manifest.getEntries().keySet().iterator();
         while (i.hasNext()) {
             String key = i.next();
-            writeEntry(out, charset, NAME_ATTRIBUTE, key);
-            Attributes attrib = manifest.entryAttributes.get(key);
+            writeEntry(out, NAME_ATTRIBUTE, key, encoder, buffer);
+            Attributes attrib = manifest.entries.get(key);
             Iterator<?> entries = attrib.keySet().iterator();
             while (entries.hasNext()) {
                 Attributes.Name name = (Attributes.Name) entries.next();
-                writeEntry(out, charset, name, attrib.getValue(name));
+                writeEntry(out, name, attrib.getValue(name), encoder, buffer);
             }
             out.write(LINE_SEPARATOR);
         }
     }
 
-    private static void writeEntry(OutputStream os, Charset charset, Attributes.Name name,
-            String value) throws IOException {
-        int offset = 0;
-        int limit = LINE_LENGTH_LIMIT;
-        byte[] out = (name.toString() + ": ").getBytes("ISO8859_1"); //$NON-NLS-1$ //$NON-NLS-2$
-        if (out.length > limit) {
-            while (out.length - offset >= limit) {
-                int len = out.length - offset;
-                if (len > limit) {
-                    len = limit;
-                }
-                if (offset > 0) {
-                    os.write(' ');
-                }
-                os.write(out, offset, len);
-                os.write(LINE_SEPARATOR);
-                offset += len;
-                limit = LINE_LENGTH_LIMIT - 1;
-            }
+    private static void writeEntry(OutputStream os, Attributes.Name name,
+            String value, CharsetEncoder encoder, ByteBuffer bBuf)
+            throws IOException {
+        byte[] out = name.getBytes();
+        if (out.length > LINE_LENGTH_LIMIT) {
+            throw new IOException(Messages.getString(
+                    "archive.33", name, Integer.valueOf(LINE_LENGTH_LIMIT))); //$NON-NLS-1$
         }
-        int size = out.length - offset;
-        final byte[] outBuf = new byte[LINE_LENGTH_LIMIT];
-        System.arraycopy(out, offset, outBuf, 0, size);
-        for (int i = 0; i < value.length(); i++) {
-            char[] oneChar = new char[1];
-            oneChar[0] = value.charAt(i);
-            byte[] buf;
-            if (oneChar[0] < 128 || charset == null) {
-                byte[] oneByte = new byte[1];
-                oneByte[0] = (byte) oneChar[0];
-                buf = oneByte;
-            } else {
-                buf = charset.encode(CharBuffer.wrap(oneChar, 0, 1)).array();
+
+        os.write(out);
+        os.write(VALUE_SEPARATOR);
+
+        encoder.reset();
+        bBuf.clear().limit(LINE_LENGTH_LIMIT - out.length - 2);
+
+        CharBuffer cBuf = CharBuffer.wrap(value);
+        CoderResult r;
+
+        while (true) {
+            r = encoder.encode(cBuf, bBuf, true);
+            if (CoderResult.UNDERFLOW == r) {
+                r = encoder.flush(bBuf);
             }
-            if (size + buf.length > limit) {
-                if (limit != LINE_LENGTH_LIMIT) {
-                    os.write(' ');
-                }
-                os.write(outBuf, 0, size);
-                os.write(LINE_SEPARATOR);
-                limit = LINE_LENGTH_LIMIT - 1;
-                size = 0;
-            }
-            if (buf.length == 1) {
-                outBuf[size] = buf[0];
-            } else {
-                System.arraycopy(buf, 0, outBuf, size, buf.length);
-            }
-            size += buf.length;
-        }
-        if (size > 0) {
-            if (limit != LINE_LENGTH_LIMIT) {
-                os.write(' ');
-            }
-            os.write(outBuf, 0, size);
+            os.write(bBuf.array(), bBuf.arrayOffset(), bBuf.position());
             os.write(LINE_SEPARATOR);
+            if (CoderResult.UNDERFLOW == r) {
+                break;
+            }
+            os.write(' ');
+            bBuf.clear().limit(LINE_LENGTH_LIMIT - 1);
         }
     }
 }
diff --git a/libcore/archive/src/main/java/java/util/jar/Pack200.java b/libcore/archive/src/main/java/java/util/jar/Pack200.java
index e0689e0..3e7081d 100644
--- a/libcore/archive/src/main/java/java/util/jar/Pack200.java
+++ b/libcore/archive/src/main/java/java/util/jar/Pack200.java
@@ -27,8 +27,6 @@
 
 /**
  * Class factory for {@link Pack200.Packer} and {@link Pack200.Unpacker}.
- * 
- * @since Android 1.0
  */
 public abstract class Pack200 {
 
@@ -39,8 +37,8 @@
     /**
      * Prevent this class from being instantiated.
      */
-    private Pack200(){
-        //do nothing
+    private Pack200() {
+        // do nothing
     }
 
     /**
@@ -50,10 +48,8 @@
      * {@code 'java.util.jar.Pack200.Packer'}. If this system property is
      * defined an instance of the specified class is returned, otherwise the
      * system's default implementation is returned.
-     * </p>
      * 
      * @return an instance of {@code Packer}
-     * @since Android 1.0
      */
     public static Pack200.Packer newPacker() {
         return (Packer) AccessController
@@ -61,7 +57,7 @@
                     public Object run() {
                         String className = System
                                 .getProperty(SYSTEM_PROPERTY_PACKER,
-                                        "org.apache.harmony.archive.internal.pack200.Pack200PackerAdapter"); //$NON-NLS-1$
+                                        "org.apache.harmony.pack200.Pack200PackerAdapter"); //$NON-NLS-1$
                         try {
                             // TODO Not sure if this will cause problems with
                             // loading the packer
@@ -82,10 +78,8 @@
      * property {@code 'java.util.jar.Pack200.Unpacker'}. If this system
      * property is defined an instance of the specified class is returned,
      * otherwise the system's default implementation is returned.
-     * </p>
      * 
      * @return a instance of {@code Unpacker}.
-     * @since Android 1.0
      */
     public static Pack200.Unpacker newUnpacker() {
         return (Unpacker) AccessController
@@ -93,7 +87,7 @@
                     public Object run() {
                         String className = System
                                 .getProperty(SYSTEM_PROPERTY_UNPACKER,
-                                        "org.apache.harmony.archive.internal.pack200.Pack200UnpackerAdapter");//$NON-NLS-1$
+                                        "org.apache.harmony.unpack200.Pack200UnpackerAdapter");//$NON-NLS-1$
                         try {
                             return ClassLoader.getSystemClassLoader()
                                     .loadClass(className).newInstance();
@@ -107,150 +101,109 @@
     /**
      * The interface defining the API for converting a JAR file to an output
      * stream in the Pack200 format.
-     * 
-     * @since Android 1.0
      */
     public static interface Packer {
 
         /**
          * the format of a class attribute name.
-         * 
-         * @since Android 1.0
          */
         static final String CLASS_ATTRIBUTE_PFX = "pack.class.attribute."; //$NON-NLS-1$
 
         /**
          * the format of a code attribute name.
-         * 
-         * @since Android 1.0
          */
         static final String CODE_ATTRIBUTE_PFX = "pack.code.attribute."; //$NON-NLS-1$
 
         /**
          * the deflation hint to set in the output archive.
-         * 
-         * @since Android 1.0
          */
         static final String DEFLATE_HINT = "pack.deflate.hint";//$NON-NLS-1$
 
         /**
          * the indicated amount of effort to use in compressing the archive.
-         * 
-         * @since Android 1.0
          */
         static final String EFFORT = "pack.effort";//$NON-NLS-1$
 
         /**
          * a String representation for {@code error}.
-         * 
-         * @since Android 1.0
          */
         static final String ERROR = "error";//$NON-NLS-1$
 
         /**
          * a String representation of {@code false}.
-         * 
-         * @since Android 1.0
          */
         static final String FALSE = "false";//$NON-NLS-1$
 
         /**
          * the format of a field attribute name.
-         * 
-         * @since Android 1.0
          */
         static final String FIELD_ATTRIBUTE_PFX = "pack.field.attribute.";//$NON-NLS-1$
 
         /**
          * a String representation for {@code keep}.
-         * 
-         * @since Android 1.0
          */
         static final String KEEP = "keep";//$NON-NLS-1$
 
         /**
          * decide if all elements shall transmit in their original order.
-         * 
-         * @since Android 1.0
          */
         static final String KEEP_FILE_ORDER = "pack.keep.file.order";//$NON-NLS-1$
 
         /**
          * a String representation for {@code latest}.
-         * 
-         * @since Android 1.0
          */
         static final String LATEST = "latest";//$NON-NLS-1$
 
         /**
          * the format of a method attribute name.
-         * 
-         * @since Android 1.0
          */
         static final String METHOD_ATTRIBUTE_PFX = "pack.method.attribute.";//$NON-NLS-1$
 
         /**
          * if it shall attempt to determine the latest modification time if this
          * is set to {@code LATEST}.
-         * 
-         * @since Android 1.0
          */
         static final String MODIFICATION_TIME = "pack.modification.time";//$NON-NLS-1$
 
         /**
          * a String representation of {@code pass}.
-         * 
-         * @since Android 1.0
          */
         static final String PASS = "pass";//$NON-NLS-1$
 
         /**
          * the file that will not be compressed.
-         * 
-         * @since Android 1.0
          */
         static final String PASS_FILE_PFX = "pack.pass.file.";//$NON-NLS-1$
 
         /**
          * packer progress as a percentage.
-         * 
-         * @since Android 1.0
          */
         static final String PROGRESS = "pack.progress";//$NON-NLS-1$
 
         /**
          * The number of bytes of each archive segment.
-         * 
-         * @since Android 1.0
          */
         static final String SEGMENT_LIMIT = "pack.segment.limit";//$NON-NLS-1$
 
         /**
          * a String representation of {@code strip}.
-         * 
-         * @since Android 1.0
          */
         static final String STRIP = "strip";//$NON-NLS-1$
 
         /**
          * a String representation of {@code true}.
-         * 
-         * @since Android 1.0
          */
         static final String TRUE = "true";//$NON-NLS-1$
 
         /**
          * the action to take if an unknown attribute is encountered.
-         * 
-         * @since Android 1.0
          */
         static final String UNKNOWN_ATTRIBUTE = "pack.unknown.attribute";//$NON-NLS-1$
 
         /**
          * Returns a sorted map of the properties of this packer.
-         * 
+         *
          * @return the properties of the packer.
-         * @since Android 1.0
          */
         SortedMap<String, String> properties();
 
@@ -263,7 +216,6 @@
          *            stream of compressed data.
          * @throws IOException
          *             if I/O exception occurs.
-         * @since Android 1.0
          */
         void pack(JarFile in, OutputStream out) throws IOException;
 
@@ -277,7 +229,6 @@
          *            stream of compressed data.
          * @throws IOException
          *             if I/O exception occurs.
-         * @since Android 1.0
          */
         void pack(JarInputStream in, OutputStream out) throws IOException;
 
@@ -301,52 +252,39 @@
     /**
      * The interface defining the API for converting a packed stream in the
      * Pack200 format to a JAR file.
-     * 
-     * @since Android 1.0
      */
     public static interface Unpacker {
 
         /**
          * The String indicating if the unpacker should ignore all transmitted
          * values,can be replaced by either {@code true} or {@code false}.
-         * 
-         * @since Android 1.0
          */
         static final String DEFLATE_HINT = "unpack.deflate.hint";//$NON-NLS-1$
 
         /**
          * a String representation of {@code false}.
-         * 
-         * @since Android 1.0
          */
         static final String FALSE = "false";//$NON-NLS-1$
 
         /**
          * a String representation of {@code keep}.
-         * 
-         * @since Android 1.0
          */
         static final String KEEP = "keep";//$NON-NLS-1$
 
         /**
          * the progress as a {@code percentage}.
-         * 
-         * @since Android 1.0
          */
         static final String PROGRESS = "unpack.progress";//$NON-NLS-1$
 
         /**
          * a String representation of {@code true}.
-         * 
-         * @since Android 1.0
          */
         static final String TRUE = "true";//$NON-NLS-1$
 
         /**
          * Returns a sorted map of the properties of this unpacker.
-         * 
+         *
          * @return the properties of unpacker.
-         * @since Android 1.0
          */
         SortedMap<String, String> properties();
 
@@ -359,7 +297,6 @@
          *            JAR output stream of uncompressed data.
          * @throws IOException
          *             if I/O exception occurs.
-         * @since Android 1.0
          */
         void unpack(InputStream in, JarOutputStream out) throws IOException;
 
@@ -373,7 +310,6 @@
          *            JAR output stream of uncompressed data.
          * @throws IOException
          *             if I/O exception occurs.
-         * @since Android 1.0
          */
         void unpack(File in, JarOutputStream out) throws IOException;
 
diff --git a/libcore/archive/src/main/java/java/util/zip/Adler32.java b/libcore/archive/src/main/java/java/util/zip/Adler32.java
index 8eaa18e..a5f77d7 100644
--- a/libcore/archive/src/main/java/java/util/zip/Adler32.java
+++ b/libcore/archive/src/main/java/java/util/zip/Adler32.java
@@ -17,14 +17,12 @@
 
 package java.util.zip;
 
-
 /**
  * The Adler-32 class is used to compute the {@code Adler32} checksum from a set
  * of data. Compared to the CRC-32 algorithm it trades reliabilty for speed.
  * Refer to RFC 1950 for the specification.
- * 
+ *
  * @see CRC32
- * @since Android 1.0
  */
 public class Adler32 implements java.util.zip.Checksum {
 
@@ -34,7 +32,6 @@
      * Returns the {@code Adler32} checksum for all input received.
      * 
      * @return The checksum for this instance.
-     * @since Android 1.0
      */
     public long getValue() {
         return adler;
@@ -42,8 +39,6 @@
 
     /**
      * Reset this instance to its initial checksum.
-     * 
-     * @since Android 1.0
      */
     public void reset() {
         adler = 1;
@@ -55,7 +50,6 @@
      * 
      * @param i
      *            the byte to update checksum with.
-     * @since Android 1.0
      */
     public void update(int i) {
         adler = updateByteImpl(i, adler);
@@ -66,7 +60,6 @@
      * 
      * @param buf
      *            bytes to update checksum with.
-     * @since Android 1.0
      */
     public void update(byte[] buf) {
         update(buf, 0, buf.length);
@@ -85,7 +78,6 @@
      * @throws ArrayIndexOutOfBoundsException
      *             if {@code offset > buf.length} or {@code nbytes} is negative
      *             or {@code offset + nbytes > buf.length}.
-     * @since Android 1.0
      */
     public void update(byte[] buf, int off, int nbytes) {
         // avoid int overflow, check null buf
diff --git a/libcore/archive/src/main/java/java/util/zip/CRC32.java b/libcore/archive/src/main/java/java/util/zip/CRC32.java
index 36dc376..59e8f81 100644
--- a/libcore/archive/src/main/java/java/util/zip/CRC32.java
+++ b/libcore/archive/src/main/java/java/util/zip/CRC32.java
@@ -17,12 +17,9 @@
 
 package java.util.zip;
 
-
 /**
  * The CRC32 class is used to compute a CRC32 checksum from data provided as
  * input value.
- * 
- * @since Android 1.0
  */
 public class CRC32 implements java.util.zip.Checksum {
 
@@ -34,7 +31,6 @@
      * Returns the CRC32 checksum for all input received.
      * 
      * @return The checksum for this instance.
-     * @since Android 1.0
      */
     public long getValue() {
         return crc;
@@ -42,8 +38,6 @@
 
     /**
      * Resets the CRC32 checksum to it initial state.
-     * 
-     * @since Android 1.0
      */
     public void reset() {
         tbytes = crc = 0;
@@ -52,10 +46,9 @@
 
     /**
      * Updates this checksum with the byte value provided as integer.
-     * 
+     *
      * @param val
      *            represents the byte to update the checksum.
-     * @since Android 1.0
      */
     public void update(int val) {
         crc = updateByteImpl((byte) val, crc);
@@ -66,7 +59,6 @@
      * 
      * @param buf
      *            the buffer holding the data to update the checksum with.
-     * @since Android 1.0
      */
     public void update(byte[] buf) {
         update(buf, 0, buf.length);
@@ -82,7 +74,6 @@
      *            the offset in {@code buf} to obtain data from.
      * @param nbytes
      *            the number of bytes to read from {@code buf}.
-     * @since Android 1.0
      */
     public void update(byte[] buf, int off, int nbytes) {
         // avoid int overflow, check null buf
diff --git a/libcore/archive/src/main/java/java/util/zip/CheckedInputStream.java b/libcore/archive/src/main/java/java/util/zip/CheckedInputStream.java
index 659125a..6513e66 100644
--- a/libcore/archive/src/main/java/java/util/zip/CheckedInputStream.java
+++ b/libcore/archive/src/main/java/java/util/zip/CheckedInputStream.java
@@ -17,7 +17,6 @@
 
 package java.util.zip;
 
-
 import java.io.IOException;
 import java.io.InputStream;
 
@@ -26,8 +25,6 @@
  * same time as the data, on which the checksum is computed, is read from a
  * stream. The purpose of this checksum is to establish data integrity,
  * comparing the computed checksum against a published checksum value.
- * 
- * @since Android 1.0
  */
 public class CheckedInputStream extends java.io.FilterInputStream {
 
@@ -42,7 +39,6 @@
      *            the input stream to calculate checksum from.
      * @param csum
      *            an entity implementing the checksum algorithm.
-     * @since Android 1.0
      */
     public CheckedInputStream(InputStream is, Checksum csum) {
         super(is);
@@ -57,7 +53,6 @@
      *         otherwise.
      * @throws IOException
      *             if an {@code IOException} occurs.
-     * @since Android 1.0
      */
     @Override
     public int read() throws IOException {
@@ -84,7 +79,6 @@
      *         end of the filtered stream while reading the data.
      * @throws IOException
      *             if this stream is closed or some I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public int read(byte[] buf, int off, int nbytes) throws IOException {
@@ -99,7 +93,6 @@
      * Returns the checksum calculated on the stream read so far.
      * 
      * @return the updated checksum.
-     * @since Android 1.0
      */
     public Checksum getChecksum() {
         return check;
@@ -114,7 +107,6 @@
      * @throws IOException
      *             if this stream is closed or another I/O error occurs.
      * @return the number of bytes skipped.
-     * @since Android 1.0
      */
     @Override
     public long skip(long nbytes) throws IOException {
diff --git a/libcore/archive/src/main/java/java/util/zip/CheckedOutputStream.java b/libcore/archive/src/main/java/java/util/zip/CheckedOutputStream.java
index 9699492..08fe799 100644
--- a/libcore/archive/src/main/java/java/util/zip/CheckedOutputStream.java
+++ b/libcore/archive/src/main/java/java/util/zip/CheckedOutputStream.java
@@ -17,7 +17,6 @@
 
 package java.util.zip;
 
-
 import java.io.IOException;
 import java.io.OutputStream;
 
@@ -26,8 +25,6 @@
  * of all data written to a stream. The purpose of this checksum is to establish
  * data integrity, by publishing the checksum to other parties wanting to read
  * the non corrupted data.
- * 
- * @since Android 1.0
  */
 public class CheckedOutputStream extends java.io.FilterOutputStream {
 
@@ -42,7 +39,6 @@
      *            the output stream to calculate checksum for.
      * @param cs
      *            an entity implementing the checksum algorithm.
-     * @since Android 1.0
      */
     public CheckedOutputStream(OutputStream os, Checksum cs) {
         super(os);
@@ -53,7 +49,6 @@
      * Returns the checksum calculated on the stream read so far.
      * 
      * @return the updated checksum.
-     * @since Android 1.0
      */
     public Checksum getChecksum() {
         return check;
@@ -67,7 +62,6 @@
      *            the data value to written to the output stream.
      * @throws IOException
      *             if an IO error has occurred.
-     * @since Android 1.0
      */
     @Override
     public void write(int val) throws IOException {
@@ -88,7 +82,6 @@
      *            number of bytes to write to the output stream.
      * @throws IOException
      *             if an IO error has occurred.
-     * @since Android 1.0
      */
     @Override
     public void write(byte[] buf, int off, int nbytes) throws IOException {
diff --git a/libcore/archive/src/main/java/java/util/zip/Checksum.java b/libcore/archive/src/main/java/java/util/zip/Checksum.java
index 0405c08..901ff7a 100644
--- a/libcore/archive/src/main/java/java/util/zip/Checksum.java
+++ b/libcore/archive/src/main/java/java/util/zip/Checksum.java
@@ -20,8 +20,6 @@
 /**
  * Holds information about a checksum which was computed with the methods
  * implementing a checksum algorithm.
- * 
- * @since Android 1.0
  */
 public interface Checksum {
 
@@ -29,37 +27,32 @@
      * Returns the current calculated checksum value.
      * 
      * @return the checksum.
-     * @since Android 1.0
      */
     public long getValue();
 
     /**
      * Resets the checksum value applied before beginning calculations on a new
      * stream of data.
-     * 
-     * @since Android 1.0
      */
     public void reset();
 
     /**
-     * Updates the checksum value with the given byte.
-     * 
-     * @param val
-     *            the byte to update the checksum with.
-     * @since Android 1.0
-     */
-    public void update(int val);
-
-    /**
      * Updates the checksum with the given bytes.
-     * 
+     *
      * @param buf
      *            the byte array from which to read the bytes.
      * @param off
      *            the initial position in {@code buf} to read the bytes from.
      * @param nbytes
      *            the number of bytes to read from {@code buf}.
-     * @since Android 1.0
      */
     public void update(byte[] buf, int off, int nbytes);
+
+    /**
+     * Updates the checksum value with the given byte.
+     * 
+     * @param val
+     *            the byte to update the checksum with.
+     */
+    public void update(int val);
 }
diff --git a/libcore/archive/src/main/java/java/util/zip/DataFormatException.java b/libcore/archive/src/main/java/java/util/zip/DataFormatException.java
index 9ffe2ab..1e9c5a2 100644
--- a/libcore/archive/src/main/java/java/util/zip/DataFormatException.java
+++ b/libcore/archive/src/main/java/java/util/zip/DataFormatException.java
@@ -20,8 +20,6 @@
 /**
  * {@code DataFormatException} is used to indicate an error in the format of a
  * particular data stream which is to be uncompressed.
- * 
- * @since Android 1.0
  */
 public class DataFormatException extends Exception {
 
@@ -29,8 +27,6 @@
 
     /**
      * Constructs a new {@code DataFormatException} instance.
-     * 
-     * @since Android 1.0
      */
     public DataFormatException() {
         super();
@@ -39,10 +35,9 @@
     /**
      * Constructs a new {@code DataFormatException} instance with the specified
      * message.
-     * 
+     *
      * @param detailMessage
      *            the detail message for the exception.
-     * @since Android 1.0
      */
     public DataFormatException(String detailMessage) {
         super(detailMessage);
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 f91f1ca..38771a8 100644
--- a/libcore/archive/src/main/java/java/util/zip/Deflater.java
+++ b/libcore/archive/src/main/java/java/util/zip/Deflater.java
@@ -17,6 +17,10 @@
 
 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
  * href="http://www.gzip.org/algorithm.txt">specification</a>).
@@ -24,83 +28,65 @@
  * Basically this class is part of the API to the stream based ZLIB compression
  * library and is used as such by {@code DeflaterOutputStream} and its
  * descendants.
- * </p>
  * <p>
  * The typical usage of a {@code Deflater} instance outside this package
  * consists of a specific call to one of its constructors before being passed to
  * an instance of {@code DeflaterOutputStream}.
- * </p>
- * 
+ *
  * @see DeflaterOutputStream
  * @see Inflater
- * @since Android 1.0
  */
 public class Deflater {
 
     /**
      * Upper bound for the compression level range.
-     * 
-     * @since Android 1.0
      */
     public static final int BEST_COMPRESSION = 9;
 
     /**
      * Lower bound for compression level range.
-     * 
-     * @since Android 1.0
      */
     public static final int BEST_SPEED = 1;
-    
+
     /**
      * Usage of the default compression level.
-     * 
-     * @since Android 1.0
      */
     public static final int DEFAULT_COMPRESSION = -1;
-    
+
     /**
      * Default value for compression strategy.
-     * 
-     * @since Android 1.0
      */
     public static final int DEFAULT_STRATEGY = 0;
-    
+
     /**
      * Default value for compression method.
-     * 
-     * @since Android 1.0
      */
     public static final int DEFLATED = 8;
-    
+
     /**
      * Possible value for compression strategy.
-     * 
-     * @since Android 1.0
      */
     public static final int FILTERED = 1;
-    
+
     /**
      * Possible value for compression strategy.
-     * 
-     * @since Android 1.0
      */
     public static final int HUFFMAN_ONLY = 2;
-    
+
     /**
      * Possible value for compression level.
-     * 
-     * @since Android 1.0
      */
     public static final int NO_COMPRESSION = 0;
 
     private static final int Z_NO_FLUSH = 0;
 
     private static final int Z_FINISH = 4;
-    
+
     // Fill in the JNI id caches
     private static native void oneTimeInitialization();
-    
-    // A stub buffer used when deflate() called while inputBuffer has not been set.
+
+    // A stub buffer used when deflate() called while inputBuffer has not been
+    // set.
     private static final byte[] STUB_INPUT_BUFFER = new byte[0];
 
     static {
@@ -120,21 +106,19 @@
     private byte[] inputBuffer;
 
     private int inRead;
-    
+
     private int inLength;
-    
+
     /**
      * Constructs a new {@code Deflater} instance with default compression
      * level. The strategy can be specified with {@link #setStrategy}, only. A
      * header is added to the output by default; use constructor {@code
      * Deflater(level, boolean)} if you need to omit the header.
-     * 
-     * @since Android 1.0
      */
     public Deflater() {
         this(DEFAULT_COMPRESSION, false);
     }
-    
+
     /**
      * Constructs a new {@code Deflater} instance with a specific compression
      * level. The strategy can be specified with {@code setStrategy}, only. A
@@ -143,7 +127,6 @@
      * 
      * @param level
      *            the compression level in the range between 0 and 9.
-     * @since Android 1.0
      */
     public Deflater(int level) {
         this(level, false);
@@ -159,7 +142,6 @@
      *            the compression level in the range between 0 and 9.
      * @param noHeader
      *            {@code true} indicates that no ZLIB header should be written.
-     * @since Android 1.0
      */
     public Deflater(int level, boolean noHeader) {
         super();
@@ -167,7 +149,8 @@
             throw new IllegalArgumentException();
         }
         compressLevel = level;
-        streamHandle = createStream(compressLevel, strategy, noHeader);
+        streamHandle = createStreamWithMemoryEnsurance(compressLevel, strategy,
+                noHeader);
     }
 
     /**
@@ -178,7 +161,6 @@
      *            buffer to write compressed data to.
      * @return number of bytes of compressed data written to {@code buf}.
      * @see #deflate(byte[], int, int)
-     * @since Android 1.0
      */
     public int deflate(byte[] buf) {
         return deflate(buf, 0, buf.length);
@@ -195,7 +177,6 @@
      * @param nbytes
      *            maximum number of bytes of compressed data to be written.
      * @return the number of bytes of compressed data written to {@code buf}.
-     * @since Android 1.0
      */
     public synchronized int deflate(byte[] buf, int off, int nbytes) {
         if (streamHandle == -1) {
@@ -224,8 +205,6 @@
      * finalize()}, it can be called explicitly in order to free native
      * resources before the next GC cycle. After {@code end()} was called other
      * methods will typically throw an {@code IllegalStateException}.
-     * 
-     * @since Android 1.0
      */
     public synchronized void end() {
         if (streamHandle != -1) {
@@ -245,7 +224,6 @@
      * to it.
      * 
      * @see #finished
-     * @since Android 1.0
      */
     public synchronized void finish() {
         flushParm = Z_FINISH;
@@ -256,7 +234,6 @@
      * compressed.
      * 
      * @return true if all data has been compressed, false otherwise.
-     * @since Android 1.0
      */
     public synchronized boolean finished() {
         return finished;
@@ -271,7 +248,6 @@
      *         used.
      * @see #setDictionary(byte[])
      * @see #setDictionary(byte[], int, int)
-     * @since Android 1.0
      */
     public synchronized int getAdler() {
         if (streamHandle == -1) {
@@ -287,14 +263,13 @@
      * Returns the total number of bytes of input consumed by the {@code Deflater}.
      * 
      * @return number of bytes of input read.
-     * @since Android 1.0
      */
     public synchronized int getTotalIn() {
         if (streamHandle == -1) {
             throw new IllegalStateException();
         }
 
-        return (int)getTotalInImpl(streamHandle);
+        return (int) getTotalInImpl(streamHandle);
     }
 
     private synchronized native long getTotalInImpl(long handle);
@@ -303,14 +278,13 @@
      * Returns the total number of compressed bytes output by this {@code Deflater}.
      * 
      * @return number of compressed bytes output.
-     * @since Android 1.0
      */
     public synchronized int getTotalOut() {
         if (streamHandle == -1) {
             throw new IllegalStateException();
         }
 
-        return (int)getTotalOutImpl(streamHandle);
+        return (int) getTotalOutImpl(streamHandle);
     }
 
     private synchronized native long getTotalOutImpl(long handle);
@@ -327,7 +301,6 @@
      * @see #finished()
      * @see #setInput(byte[])
      * @see #setInput(byte[], int, int)
-     * @since Android 1.0
      */
     public synchronized boolean needsInput() {
         if (inputBuffer == null) {
@@ -343,7 +316,6 @@
      * {@code true} if the {@code Deflater} is to be reused.
      * 
      * @see #finished
-     * @since Android 1.0
      */
     public synchronized void reset() {
         if (streamHandle == -1) {
@@ -367,7 +339,6 @@
      * @param buf
      *            the buffer containing the dictionary data bytes.
      * @see Deflater#Deflater(int, boolean)
-     * @since Android 1.0
      */
     public void setDictionary(byte[] buf) {
         setDictionary(buf, 0, buf.length);
@@ -378,7 +349,7 @@
      * setDictionary() can only be called if this {@code Deflater} supports the writing
      * of ZLIB headers. This is the default behaviour but can be overridden
      * using {@code Deflater(int, boolean)}.
-     * 
+     *
      * @param buf
      *            the buffer containing the dictionary data bytes.
      * @param off
@@ -386,7 +357,6 @@
      * @param nbytes
      *            the length of the data.
      * @see Deflater#Deflater(int, boolean)
-     * @since Android 1.0
      */
     public synchronized void setDictionary(byte[] buf, int off, int nbytes) {
         if (streamHandle == -1) {
@@ -410,7 +380,6 @@
      * 
      * @param buf
      *            the buffer.
-     * @since Android 1.0
      */
     public void setInput(byte[] buf) {
         setInput(buf, 0, buf.length);
@@ -427,7 +396,6 @@
      *            the offset of the data.
      * @param nbytes
      *            the length of the data.
-     * @since Android 1.0
      */
     public synchronized void setInput(byte[] buf, int off, int nbytes) {
         if (streamHandle == -1) {
@@ -463,7 +431,6 @@
      *            compression level to use
      * @exception IllegalArgumentException
      *                If the compression level is invalid.
-     * @since Android 1.0
      */
     public synchronized void setLevel(int level) {
         if (level < DEFAULT_COMPRESSION || level > BEST_COMPRESSION) {
@@ -485,7 +452,6 @@
      * @exception IllegalArgumentException
      *                If the strategy specified is not one of FILTERED,
      *                HUFFMAN_ONLY or DEFAULT_STRATEGY.
-     * @since Android 1.0
      */
     public synchronized void setStrategy(int strategy) {
         if (strategy < DEFAULT_STRATEGY || strategy > HUFFMAN_ONLY) {
@@ -496,14 +462,14 @@
         }
         this.strategy = strategy;
     }
-    
+
     /**
      * Returns a long int of total number of bytes read by the {@code Deflater}. This
      * method performs the same as {@code getTotalIn} except it returns a long value
      * instead of an integer
      * 
+     * @see #getTotalIn()
      * @return total number of bytes read by {@code Deflater}.
-     * @since Android 1.0
      */
     public synchronized long getBytesRead() {
         // Throw NPE here
@@ -518,8 +484,8 @@
      * method performs the same as {@code getTotalOut} except it returns a long
      * value instead of an integer
      * 
+     * @see #getTotalOut()
      * @return bytes exactly write by {@code Deflater}
-     * @since Android 1.0
      */
     public synchronized long getBytesWritten() {
         // Throw NPE here
@@ -529,5 +495,13 @@
         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/DeflaterOutputStream.java b/libcore/archive/src/main/java/java/util/zip/DeflaterOutputStream.java
index 773e4c4..03769fb 100644
--- a/libcore/archive/src/main/java/java/util/zip/DeflaterOutputStream.java
+++ b/libcore/archive/src/main/java/java/util/zip/DeflaterOutputStream.java
@@ -17,7 +17,6 @@
 
 package java.util.zip;
 
-
 import java.io.FilterOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
@@ -28,24 +27,19 @@
  * This class provides an implementation of {@code FilterOutputStream} that
  * compresses data using the <i>DEFLATE</i> algorithm. Basically it wraps the
  * {@code Deflater} class and takes care of the buffering.
- * 
+ *
  * @see Deflater
- * @since Android 1.0
  */
 public class DeflaterOutputStream extends FilterOutputStream {
     static final int BUF_SIZE = 512;
 
     /**
      * The buffer for the data to be written to.
-     * 
-     * @since Android 1.0
      */
     protected byte[] buf;
 
     /**
      * The deflater used.
-     * 
-     * @since Android 1.0
      */
     protected Deflater def;
 
@@ -61,7 +55,6 @@
      * @param def
      *            is the specific {@code Deflater} that is used to compress
      *            data.
-     * @since Android 1.0
      */
     public DeflaterOutputStream(OutputStream os, Deflater def) {
         this(os, def, BUF_SIZE);
@@ -76,7 +69,6 @@
      * 
      * @param os
      *            is the OutputStream where to write the compressed data to.
-     * @since Android 1.0
      */
     public DeflaterOutputStream(OutputStream os) {
         this(os, new Deflater());
@@ -94,7 +86,6 @@
      *            data.
      * @param bsize
      *            is the size to be used for the internal buffer.
-     * @since Android 1.0
      */
     public DeflaterOutputStream(OutputStream os, Deflater def, int bsize) {
         super(os);
@@ -114,7 +105,6 @@
      * 
      * @throws IOException
      *             If an error occurs during deflation.
-     * @since Android 1.0
      */
     protected void deflate() throws IOException {
         int x = 0;
@@ -132,7 +122,6 @@
      * @throws IOException
      *             If an error occurs while closing the data compression
      *             process.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -149,7 +138,6 @@
      * 
      * @throws IOException
      *             If an error occurs.
-     * @since Android 1.0
      */
     public void finish() throws IOException {
         if (done) {
@@ -186,7 +174,6 @@
      *            the number of bytes of data to read from the buffer.
      * @throws IOException
      *             If an error occurs during writing.
-     * @since Android 1.0
      */
     @Override
     public void write(byte[] buffer, int off, int nbytes) throws IOException {
diff --git a/libcore/archive/src/main/java/java/util/zip/GZIPInputStream.java b/libcore/archive/src/main/java/java/util/zip/GZIPInputStream.java
index fc70d62..cc7a019 100644
--- a/libcore/archive/src/main/java/java/util/zip/GZIPInputStream.java
+++ b/libcore/archive/src/main/java/java/util/zip/GZIPInputStream.java
@@ -17,7 +17,6 @@
 
 package java.util.zip;
 
-
 import java.io.EOFException;
 import java.io.IOException;
 import java.io.InputStream;
@@ -28,49 +27,40 @@
  * The {@code GZIPInputStream} class is used to read data stored in the GZIP
  * format, reading and decompressing GZIP data from the underlying stream into
  * its buffer.
- * 
- * @since Android 1.0
  */
-public class GZIPInputStream extends java.util.zip.InflaterInputStream {
+public class GZIPInputStream extends InflaterInputStream {
+
+    private static final int FCOMMENT = 16;
+
+    private static final int FEXTRA = 4;
+
+    private static final int FHCRC = 2;
+
+    private static final int FNAME = 8;
+
+    /**
+     * The magic header for the GZIP format.
+     */
+    public final static int GZIP_MAGIC = 0x8b1f;
 
     /**
      * The checksum algorithm used when handling uncompressed data.
-     * 
-     * @since Android 1.0
      */
     protected CRC32 crc = new CRC32();
 
     /**
      * Indicates the end of the input stream.
-     * 
-     * @since Android 1.0
      */
     protected boolean eos = false;
 
     /**
-     * The magic header for the GZIP format.
-     * 
-     * @since Android 1.0
-     */
-    public final static int GZIP_MAGIC = 0x8b1f;
-
-    private static final int FHCRC = 2;
-
-    private static final int FEXTRA = 4;
-
-    private static final int FNAME = 8;
-
-    private static final int FCOMMENT = 16;
-
-    /**
      * Construct a {@code GZIPInputStream} to read from GZIP data from the
      * underlying stream.
-     * 
+     *
      * @param is
      *            the {@code InputStream} to read data from.
      * @throws IOException
      *             if an {@code IOException} occurs.
-     * @since Android 1.0
      */
     public GZIPInputStream(InputStream is) throws IOException {
         this(is, BUF_SIZE);
@@ -86,7 +76,6 @@
      *            the internal read buffer size.
      * @throws IOException
      *             if an {@code IOException} occurs.
-     * @since Android 1.0
      */
     public GZIPInputStream(InputStream is, int size) throws IOException {
         super(is, new Inflater(true), size);
@@ -134,6 +123,15 @@
         }
     }
 
+    /**
+     * Closes this stream and any underlying streams.
+     */
+    @Override
+    public void close() throws IOException {
+        eos = true;
+        super.close();
+    }
+
     private long getLong(byte[] buffer, int off) {
         long l = 0;
         l |= (buffer[off] & 0xFF);
@@ -147,51 +145,70 @@
         return (buffer[off] & 0xFF) | ((buffer[off + 1] & 0xFF) << 8);
     }
 
+    /**
+     * Reads and decompresses GZIP data from the underlying stream into the
+     * given buffer.
+     *
+     * @param buffer
+     *            Buffer to receive data
+     * @param off
+     *            Offset in buffer to store data
+     * @param nbytes
+     *            Number of bytes to read
+     */
     @Override
     public int read(byte[] buffer, int off, int nbytes) throws IOException {
         if (closed) {
             throw new IOException(Messages.getString("archive.1E")); //$NON-NLS-1$
         }
-        if(eof){
+        // BEGIN android-changed
+        if (eos) {
             return -1;
         }
         // avoid int overflow, check null buffer
-        if (off <= buffer.length && nbytes >= 0 && off >= 0
-                && buffer.length - off >= nbytes) {
-            int val = super.read(buffer, off, nbytes);
-            if (val != -1) {
-                crc.update(buffer, off, val);
-            } else if (!eos) {
-                eos = true;
-                // Get non-compressed bytes read by fill
-                // BEGIN android-changed
-                // copied from newer version of harmony
-                int size = inf.getRemaining();
-                final int trailerSize = 8; // crc (4 bytes) + total out (4
-                                            // bytes)
-                byte[] b = new byte[trailerSize];
-                int copySize = (size > trailerSize) ? trailerSize : size;
-
-                System.arraycopy(buf, len - size, b, 0, copySize);
-                readFully(b, copySize, trailerSize - copySize);                
-                // END android-changed
-                if (getLong(b, 0) != crc.getValue()) {
-                    throw new IOException(Messages.getString("archive.20")); //$NON-NLS-1$
-                }
-                if ((int) getLong(b, 4) != inf.getTotalOut()) {
-                    throw new IOException(Messages.getString("archive.21")); //$NON-NLS-1$
-                }
-            }
-            return val;
+        if (off > buffer.length || nbytes < 0 || off < 0
+                || buffer.length - off < nbytes) {
+            throw new ArrayIndexOutOfBoundsException();
         }
-        throw new ArrayIndexOutOfBoundsException();
+
+        int bytesRead;
+        try {
+            bytesRead = super.read(buffer, off, nbytes);
+        } finally {
+            eos = eof; // update eos after every read(), even when it throws
+        }
+
+        if (bytesRead != -1) {
+            crc.update(buffer, off, bytesRead);
+        }
+
+        if (eos) {
+            verifyCrc();
+        }
+
+        return bytesRead;
+        // END android-changed
     }
-    
-    @Override
-    public void close() throws IOException {
-        eos = true;
-        super.close();
+
+    // BEGIN android-added
+    private void verifyCrc() throws IOException {
+        // Get non-compressed bytes read by fill
+        int size = inf.getRemaining();
+        final int trailerSize = 8; // crc (4 bytes) + total out (4 bytes)
+        byte[] b = new byte[trailerSize];
+        int copySize = (size > trailerSize) ? trailerSize : size;
+
+        System.arraycopy(buf, len - size, b, 0, copySize);
+        readFully(b, copySize, trailerSize - copySize);
+
+        if (getLong(b, 0) != crc.getValue()) {
+            throw new IOException(Messages.getString("archive.20")); //$NON-NLS-1$
+        }
+        if ((int) getLong(b, 4) != inf.getTotalOut()) {
+            throw new IOException(Messages.getString("archive.21")); //$NON-NLS-1$
+        }
     }
+    // END android-added
 
     private void readFully(byte[] buffer, int offset, int length)
             throws IOException {
diff --git a/libcore/archive/src/main/java/java/util/zip/GZIPOutputStream.java b/libcore/archive/src/main/java/java/util/zip/GZIPOutputStream.java
index fa41e19..f146da1 100644
--- a/libcore/archive/src/main/java/java/util/zip/GZIPOutputStream.java
+++ b/libcore/archive/src/main/java/java/util/zip/GZIPOutputStream.java
@@ -17,22 +17,17 @@
 
 package java.util.zip;
 
-
 import java.io.IOException;
 import java.io.OutputStream;
 
 /**
  * The {@code GZIPOutputStream} class is used to write data to a stream in the
  * GZIP storage format.
- * 
- * @since Android 1.0
  */
 public class GZIPOutputStream extends DeflaterOutputStream {
 
     /**
      * The checksum algorithm used when treating uncompressed data.
-     * 
-     * @since Android 1.0
      */
     protected CRC32 crc = new CRC32();
 
@@ -44,7 +39,6 @@
      *            the {@code OutputStream} to write data to.
      * @throws IOException
      *             if an {@code IOException} occurs.
-     * @since Android 1.0
      */
     public GZIPOutputStream(OutputStream os) throws IOException {
         this(os, BUF_SIZE);
@@ -61,7 +55,6 @@
      *            the internal buffer size.
      * @throws IOException
      *             if an {@code IOException} occurs.
-     * @since Android 1.0
      */
     public GZIPOutputStream(OutputStream os, int size) throws IOException {
         super(os, new Deflater(Deflater.DEFAULT_COMPRESSION, true), size);
@@ -76,10 +69,9 @@
     /**
      * Indicates to the stream that all data has been written out, and any GZIP
      * terminal data can now be written.
-     * 
+     *
      * @throws IOException
      *             if an {@code IOException} occurs.
-     * @since Android 1.0
      */
     @Override
     public void finish() throws IOException {
@@ -88,24 +80,29 @@
         writeLong(crc.tbytes);
     }
 
+    /**
+     * Write up to nbytes of data from the given buffer, starting at offset off,
+     * to the underlying stream in GZIP format.
+     */
     @Override
     public void write(byte[] buffer, int off, int nbytes) throws IOException {
         super.write(buffer, off, nbytes);
         crc.update(buffer, off, nbytes);
     }
 
-    private int writeShort(int i) throws IOException {
-        out.write(i & 0xFF);
-        out.write((i >> 8) & 0xFF);
+    private long writeLong(long i) throws IOException {
+        // Write out the long value as an unsigned int
+        int unsigned = (int) i;
+        out.write(unsigned & 0xFF);
+        out.write((unsigned >> 8) & 0xFF);
+        out.write((unsigned >> 16) & 0xFF);
+        out.write((unsigned >> 24) & 0xFF);
         return i;
     }
 
-    private long writeLong(long i) throws IOException {
-        // Write out the long value as an unsigned int
-        out.write((int) (i & 0xFF));
-        out.write((int) (i >> 8) & 0xFF);
-        out.write((int) (i >> 16) & 0xFF);
-        out.write((int) (i >> 24) & 0xFF);
+    private int writeShort(int i) throws IOException {
+        out.write(i & 0xFF);
+        out.write((i >> 8) & 0xFF);
         return i;
     }
 }
diff --git a/libcore/archive/src/main/java/java/util/zip/Inflater.java b/libcore/archive/src/main/java/java/util/zip/Inflater.java
index 9b93e54..048d959 100644
--- a/libcore/archive/src/main/java/java/util/zip/Inflater.java
+++ b/libcore/archive/src/main/java/java/util/zip/Inflater.java
@@ -30,45 +30,72 @@
  * Basically this class is part of the API to the stream based ZLIB compression
  * library and is used as such by {@code InflaterInputStream} and its
  * descendants.
- * </p>
  * <p>
  * The typical usage of a {@code Inflater} outside this package consists of a
  * specific call to one of its constructors before being passed to an instance
  * of {@code InflaterInputStream}.
- * </p>
- * 
+ *
  * @see InflaterInputStream
  * @see Deflater
- * @since Android 1.0
  */
 public class Inflater {
 
-    private boolean finished; // Set by the inflateImpl native
-
-    private boolean needsDictionary; // Set by the inflateImpl native
-
-    private long streamHandle = -1;
-
-    int inRead;
-    
-    int inLength;
-
-    // Fill in the JNI id caches
-    private static native void oneTimeInitialization();
+    private static final byte MAGIC_NUMBER = 120;
 
     static {
         oneTimeInitialization();
     }
-    
-    private static final byte MAGIC_NUMBER = 120;
-    private boolean gotFirstByte = false;
-    private boolean pass_magic_number_check = true;
-    
+
+    // Fill in the JNI id caches
+    private static native void oneTimeInitialization();
+
+    private boolean finished; // Set by the inflateImpl native
+
+    // BEGIN android-removed
+    // private boolean gotFirstHeaderByte;
+    // END android-removed
+
+    int inLength;
+
+    int inRead;
+
+    private boolean needsDictionary; // Set by the inflateImpl native
+
+    // BEGIN android-removed
+    // private boolean pass_magic_number_check = true;
+    // END android-removed
+
+    private long streamHandle = -1;
+
+    /**
+     * This constructor creates an inflater that expects a header from the input
+     * stream. Use {@code Inflater(boolean)} if the input comes without a ZLIB
+     * header.
+     */
+    public Inflater() {
+        this(false);
+    }
+
+    /**
+     * This constructor allows to create an inflater that expects no header from
+     * the input stream.
+     *
+     * @param noHeader
+     *            {@code true} indicates that no ZLIB header comes with the
+     *            input.
+     */
+    public Inflater(boolean noHeader) {
+        streamHandle = createStream(noHeader);
+        // BEGIN android-removed
+        // gotFirstHeaderByte = noHeader;
+        // END android-removed
+    }
+
+    private native long createStream(boolean noHeader1);
+
     /**
      * Release any resources associated with this {@code Inflater}. Any unused
      * input/output is discarded. This is also called by the finalize method.
-     * 
-     * @since Android 1.0
      */
     public synchronized void end() {
         if (streamHandle != -1) {
@@ -91,10 +118,9 @@
      * stream. If deflated bytes remain and {@code needsInput()} returns {@code
      * true} this method will return {@code false}. This method should be
      * called after all deflated input is supplied to the {@code Inflater}.
-     * 
+     *
      * @return {@code true} if all input has been inflated, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public synchronized boolean finished() {
         return finished;
@@ -103,10 +129,9 @@
     /**
      * Returns the <i>Adler32</i> checksum of either all bytes inflated, or the
      * checksum of the preset dictionary if one has been supplied.
-     * 
+     *
      * @return The <i>Adler32</i> checksum associated with this
      *         {@code Inflater}.
-     * @since Android 1.0 .
      */
     public synchronized int getAdler() {
         if (streamHandle == -1) {
@@ -118,11 +143,40 @@
     private native synchronized int getAdlerImpl(long handle);
 
     /**
+     * Returns the total number of bytes read by the {@code Inflater}. This
+     * method performs the same as {@code getTotalIn()} except that it returns a
+     * {@code long} value instead of an integer.
+     *
+     * @return the total number of bytes read.
+     */
+    public synchronized long getBytesRead() {
+        // Throw NPE here
+        if (streamHandle == -1) {
+            throw new NullPointerException();
+        }
+        return getTotalInImpl(streamHandle);
+    }
+
+    /**
+     * Returns a the total number of bytes read by the {@code Inflater}. This
+     * method performs the same as {@code getTotalOut} except it returns a
+     * {@code long} value instead of an integer.
+     *
+     * @return the total bytes written to the output buffer.
+     */
+    public synchronized long getBytesWritten() {
+        // Throw NPE here
+        if (streamHandle == -1) {
+            throw new NullPointerException();
+        }
+        return getTotalOutImpl(streamHandle);
+    }
+
+    /**
      * Returns the number of bytes of current input remaining to be read by the
      * inflater.
-     * 
+     *
      * @return the number of bytes of unread input.
-     * @since Android 1.0
      */
     public synchronized int getRemaining() {
         return inLength - inRead;
@@ -131,9 +185,8 @@
     /**
      * Returns total number of bytes of input read by the {@code Inflater}. The
      * result value is limited by {@code Integer.MAX_VALUE}.
-     * 
+     *
      * @return the total number of bytes read.
-     * @since Android 1.0
      */
     public synchronized int getTotalIn() {
         if (streamHandle == -1) {
@@ -149,9 +202,8 @@
     /**
      * Returns total number of bytes written to the output buffer by the {@code
      * Inflater}. The result value is limited by {@code Integer.MAX_VALUE}.
-     * 
+     *
      * @return the total bytes of output data written.
-     * @since Android 1.0
      */
     public synchronized int getTotalOut() {
         if (streamHandle == -1) {
@@ -166,14 +218,13 @@
 
     /**
      * Inflates bytes from current input and stores them in {@code buf}.
-     * 
+     *
      * @param buf
      *            the buffer where decompressed data bytes are written.
      * @return the number of bytes inflated.
      * @throws DataFormatException
      *             if the underlying stream is corrupted or was not compressed
      *             using a {@code Deflater}.
-     * @since Android 1.0
      */
     public int inflate(byte[] buf) throws DataFormatException {
         return inflate(buf, 0, buf.length);
@@ -182,7 +233,7 @@
     /**
      * Inflates up to n bytes from the current input and stores them in {@code
      * buf} starting at {@code off}.
-     * 
+     *
      * @param buf
      *            the buffer to write inflated bytes to.
      * @param off
@@ -205,15 +256,17 @@
             if (streamHandle == -1) {
                 throw new IllegalStateException();
             }
-            
-            if (!pass_magic_number_check) {
-                throw new DataFormatException();
-            }
+
+            // BEGIN android-removed
+            // if (!pass_magic_number_check) {
+            //     throw new DataFormatException();
+            // }
+            // END android-removed
 
             if (needsInput()) {
                 return 0;
             }
-            
+
             boolean neededDict = needsDictionary;
             needsDictionary = false;
             int result = inflateImpl(buf, off, nbytes, streamHandle);
@@ -229,41 +282,15 @@
             int nbytes, long handle);
 
     /**
-     * This constructor creates an inflater that expects a header from the input
-     * stream. Use {@code Inflater(boolean)} if the input comes without a ZLIB
-     * header.
-     * 
-     * @since Android 1.0
-     * @since Android 1.0
-     */
-    public Inflater() {
-        this(false);
-    }
-
-    /**
-     * This constructor allows to create an inflater that expects no header from
-     * the input stream.
-     * 
-     * @param noHeader
-     *            {@code true} indicates that no ZLIB header comes with the
-     *            input.
-     * @since Android 1.0
-     */
-    public Inflater(boolean noHeader) {
-        streamHandle = createStream(noHeader);
-    }
-
-    /**
      * Indicates whether the input bytes were compressed with a preset
      * dictionary. This method should be called prior to {@code inflate()} to
      * determine whether a dictionary is required. If so {@code setDictionary()}
      * should be called with the appropriate dictionary prior to calling {@code
      * inflate()}.
-     * 
+     *
      * @return {@code true} if a preset dictionary is required for inflation.
      * @see #setDictionary(byte[])
      * @see #setDictionary(byte[], int, int)
-     * @since Android 1.0
      */
     public synchronized boolean needsDictionary() {
         return needsDictionary;
@@ -271,11 +298,10 @@
 
     /**
      * Indicates that input has to be passed to the inflater.
-     * 
+     *
      * @return {@code true} if {@code setInput} has to be called before
      *         inflation can proceed.
      * @see #setInput(byte[])
-     * @since Android 1.0
      */
     public synchronized boolean needsInput() {
         return inRead == inLength;
@@ -284,8 +310,6 @@
     /**
      * Resets the {@code Inflater}. Should be called prior to inflating a new
      * set of data.
-     * 
-     * @since Android 1.0
      */
     public synchronized void reset() {
         if (streamHandle == -1) {
@@ -303,11 +327,10 @@
      * Sets the preset dictionary to be used for inflation to {@code buf}.
      * {@code needsDictionary()} can be called to determine whether the current
      * input was deflated using a preset dictionary.
-     * 
+     *
      * @param buf
      *            The buffer containing the dictionary bytes.
      * @see #needsDictionary
-     * @since Android 1.0
      */
     public synchronized void setDictionary(byte[] buf) {
         setDictionary(buf, 0, buf.length);
@@ -316,7 +339,11 @@
     /**
      * Like {@code setDictionary(byte[])}, allowing to define a specific region
      * inside {@code buf} to be used as a dictionary.
-     * 
+     * <p>
+     * The dictionary should be set if the {@link #inflate(byte[])} returned
+     * zero bytes inflated and {@link #needsDictionary()} returns
+     * <code>true</code>.
+     *
      * @param buf
      *            the buffer containing the dictionary data bytes.
      * @param off
@@ -324,7 +351,6 @@
      * @param nbytes
      *            the length of the data.
      * @see #needsDictionary
-     * @since Android 1.0
      */
     public synchronized void setDictionary(byte[] buf, int off, int nbytes) {
         if (streamHandle == -1) {
@@ -345,11 +371,10 @@
     /**
      * Sets the current input to to be decrompressed. This method should only be
      * called if {@code needsInput()} returns {@code true}.
-     * 
+     *
      * @param buf
      *            the input buffer.
      * @see #needsInput
-     * @since Android 1.0
      */
     public synchronized void setInput(byte[] buf) {
         setInput(buf, 0, buf.length);
@@ -360,7 +385,7 @@
      * {@code off} and ending at {@code nbytes - 1} where data is written after
      * decompression. This method should only be called if {@code needsInput()}
      * returns {@code true}.
-     * 
+     *
      * @param buf
      *            the input buffer.
      * @param off
@@ -368,7 +393,6 @@
      * @param nbytes
      *            the number of bytes to read.
      * @see #needsInput
-     * @since Android 1.0
      */
     public synchronized void setInput(byte[] buf, int off, int nbytes) {
         if (streamHandle == -1) {
@@ -383,22 +407,13 @@
         } else {
             throw new ArrayIndexOutOfBoundsException();
         }
-        // BEGIN android-note
-        // Note:  pass_magic_number_check is set to false when setInput is
-        //        called for the first time and for a single byte.
-        //        Since setInput is called only by InflaterInputStream.fill
-        //        with an arbitrary byte len this check seems quite useless.
-        // FIXME: We should find out whether the first byte has to be the magic
-        //        number in all cases and correct the check as well as place it
-        //        in setFileInput accordingly.
-        //        And at a first glance it doesn't look like the first byte has
-        //        to be 120.
-        // END android-note
-        if(!gotFirstByte && nbytes>0)
-        {
-           pass_magic_number_check = (buf[off] == MAGIC_NUMBER || nbytes > 1);           
-           gotFirstByte = true;
-        }
+
+        // BEGIN android-removed
+        // if (!gotFirstHeaderByte && nbytes > 0) {
+        //     pass_magic_number_check = (buf[off] == MAGIC_NUMBER);
+        //     gotFirstHeaderByte = true;
+        //}
+        // END android-removed
     }
 
     // BEGIN android-added
@@ -407,14 +422,13 @@
      * off} and ending at {@code nbytes - 1}. This method should only be called
      * if {@code needsInput()} returns {@code true}.
      * 
-     * @param file
+     * @param fd
      *            the input file.
      * @param off
      *            the offset to read from in buffer.
      * @param nbytes
      *            the number of bytes to read.
      * @see #needsInput
-     * @since Android 1.0
      */
     synchronized int setFileInput(FileDescriptor fd, long off, int nbytes) {
         if (streamHandle == -1) {
@@ -426,38 +440,6 @@
     }
     // END android-added
 
-    /**
-     * Returns the total number of bytes read by the {@code Inflater}. This
-     * method performs the same as {@code getTotalIn()} except that it returns a
-     * {@code long} value instead of an integer.
-     * 
-     * @return the total number of bytes read.
-     * @since Android 1.0
-     */
-    public synchronized long getBytesRead() {
-        // Throw NPE here
-        if (streamHandle == -1) {
-            throw new NullPointerException();
-        }
-        return getTotalInImpl(streamHandle);
-    }
-
-    /**
-     * Returns a the total number of bytes read by the {@code Inflater}. This
-     * method performs the same as {@code getTotalOut} except it returns a
-     * {@code long} value instead of an integer.
-     * 
-     * @return the total bytes written to the output buffer.
-     * @since Android 1.0
-     */
-    public synchronized long getBytesWritten() {
-        // Throw NPE here
-        if (streamHandle == -1) {
-            throw new NullPointerException();
-        }
-        return getTotalOutImpl(streamHandle);
-    }
-
     private native synchronized void setInputImpl(byte[] buf, int off,
             int nbytes, long handle);
 
@@ -465,6 +447,4 @@
     private native synchronized int setFileInputImpl(FileDescriptor fd, long off,
             int nbytes, long handle);
     // END android-added
-
-    private native long createStream(boolean noHeader1);
 }
diff --git a/libcore/archive/src/main/java/java/util/zip/InflaterInputStream.java b/libcore/archive/src/main/java/java/util/zip/InflaterInputStream.java
index 5d3bda0..8a7c86b 100644
--- a/libcore/archive/src/main/java/java/util/zip/InflaterInputStream.java
+++ b/libcore/archive/src/main/java/java/util/zip/InflaterInputStream.java
@@ -17,7 +17,6 @@
 
 package java.util.zip;
 
-
 import java.io.EOFException;
 import java.io.FilterInputStream;
 import java.io.IOException;
@@ -31,36 +30,34 @@
  * (see <a href="http://www.gzip.org/algorithm.txt">specification</a>).
  * Basically it wraps the {@code Inflater} class and takes care of the
  * buffering.
- * 
+ *
  * @see Inflater
  * @see DeflaterOutputStream
- * @since Android 1.0
  */
 public class InflaterInputStream extends FilterInputStream {
 
     /**
      * The inflater used for this stream.
-     * 
-     * @since Android 1.0
      */
     protected Inflater inf;
 
     /**
      * The input buffer used for decompression.
-     * 
-     * @since Android 1.0
      */
     protected byte[] buf;
 
     /**
      * The length of the buffer.
-     * 
-     * @since Android 1.0
      */
     protected int len;
 
     boolean closed;
 
+    /**
+     * True if this stream's last byte has been returned to the user. This
+     * could be because the underlying stream has been exhausted, or if errors
+     * were encountered while inflating that stream.
+     */
     boolean eof;
 
     static final int BUF_SIZE = 512;
@@ -74,10 +71,9 @@
      * InputStream} from which the compressed data is to be read from. Default
      * settings for the {@code Inflater} and internal buffer are be used. In
      * particular the Inflater expects a ZLIB header from the input stream.
-     * 
+     *
      * @param is
      *            the {@code InputStream} to read data from.
-     * @since Android 1.0
      */
     public InflaterInputStream(InputStream is) {
         this(is, new Inflater(), BUF_SIZE);
@@ -86,12 +82,11 @@
     /**
      * This constructor lets you pass a specifically initialized Inflater,
      * for example one that expects no ZLIB header.
-     * 
+     *
      * @param is
      *            the {@code InputStream} to read data from.
      * @param inf
      *            the specific {@code Inflater} for uncompressing data.
-     * @since Android 1.0 
      */
     public InflaterInputStream(InputStream is, Inflater inf) {
         this(is, inf, BUF_SIZE);
@@ -100,14 +95,13 @@
     /**
      * This constructor lets you specify both the {@code Inflater} as well as
      * the internal buffer size to be used.
-     * 
+     *
      * @param is
      *            the {@code InputStream} to read data from.
      * @param inf
      *            the specific {@code Inflater} for uncompressing data.
      * @param bsize
      *            the size to be used for the internal buffer.
-     * @since Android 1.0
      */
     public InflaterInputStream(InputStream is, Inflater inf, int bsize) {
         super(is);
@@ -129,11 +123,10 @@
 
     /**
      * Reads a single byte of decompressed data.
-     * 
+     *
      * @return the byte read.
      * @throws IOException
      *             if an error occurs reading the byte.
-     * @since Android 1.0
      */
     @Override
     public int read() throws IOException {
@@ -147,7 +140,7 @@
     /**
      * Reads up to {@code nbytes} of decompressed data and stores it in
      * {@code buffer} starting at {@code off}.
-     * 
+     *
      * @param buffer
      *            the buffer to write data to.
      * @param off
@@ -157,7 +150,6 @@
      * @return Number of uncompressed bytes read
      * @throws IOException
      *             if an IOException occurs.
-     * @since Android 1.0
      */
     @Override
     public int read(byte[] buffer, int off, int nbytes) throws IOException {
@@ -178,50 +170,54 @@
             return 0;
         }
 
-        if (inf.finished()) {
-            eof = true;
+        // BEGIN android-changed
+        if (eof) {
             return -1;
         }
 
         // avoid int overflow, check null buffer
-        if (off <= buffer.length && nbytes >= 0 && off >= 0
-                && buffer.length - off >= nbytes) {
-            do {
-                if (inf.needsInput()) {
-                    fill();
-                }
-                int result;
-                try {
-                    result = inf.inflate(buffer, off, nbytes);
-                } catch (DataFormatException e) {
-                    if (len == -1) {
-                        throw new EOFException();
-                    }
-                    throw (IOException)(new IOException().initCause(e));
-                }
+        if (off > buffer.length || nbytes < 0 || off < 0
+                || buffer.length - off < nbytes) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+
+        do {
+            if (inf.needsInput()) {
+                fill();
+            }
+            // Invariant: if reading returns -1 or throws, eof must be true.
+            // It may also be true if the next read() should return -1.
+            try {
+                int result = inf.inflate(buffer, off, nbytes);
+                eof = inf.finished();
                 if (result > 0) {
                     return result;
-                } else if (inf.finished()) {
-                    eof = true;
+                } else if (eof) {
                     return -1;
                 } else if (inf.needsDictionary()) {
+                    eof = true;
                     return -1;
                 } else if (len == -1) {
+                    eof = true;
                     throw new EOFException();
-                // If result == 0, fill() and try again
+                    // If result == 0, fill() and try again
                 }
-            } while (true);
-        }
-        throw new ArrayIndexOutOfBoundsException();
+            } catch (DataFormatException e) {
+                eof = true;
+                if (len == -1) {
+                    throw new EOFException();
+                }
+                throw (IOException) (new IOException().initCause(e));
+            }
+        } while (true);
+        // END android-changed
     }
 
-    
     /**
      * Fills the input buffer with data to be decompressed.
-     * 
+     *
      * @throws IOException
      *             if an {@code IOException} occurs.
-     * @since Android 1.0
      */
     protected void fill() throws IOException {
         if (closed) {
@@ -246,24 +242,30 @@
 
     /**
      * Skips up to n bytes of uncompressed data.
-     * 
+     *
      * @param nbytes
      *            the number of bytes to skip.
      * @return the number of uncompressed bytes skipped.
      * @throws IOException
      *             if an error occurs skipping.
-     * @since Android 1.0
      */
     @Override
     public long skip(long nbytes) throws IOException {
         if (nbytes >= 0) {
+            // BEGIN android-changed
+            if (buf == null) {
+                buf = new byte[BUF_SIZE];
+            }
+            // END android-changed
             long count = 0, rem = 0;
             while (count < nbytes) {
                 int x = read(buf, 0,
                         (rem = nbytes - count) > buf.length ? buf.length
                                 : (int) rem);
                 if (x == -1) {
-                    eof = true;
+                    // BEGIN android-removed
+                    // eof = true;
+                    // END android-removed
                     return count;
                 }
                 count += x;
@@ -274,12 +276,20 @@
     }
 
     /**
-     * Returns whether data can be read from this stream.
-     * 
-     * @return 0 if this stream has been closed, 1 otherwise.
+     * Returns 0 when when this stream has exhausted its input; and 1 otherwise.
+     * A result of 1 does not guarantee that further bytes can be returned,
+     * with or without blocking.
+     *
+     * <p>Although consistent with the RI, this behavior is inconsistent with
+     * {@link InputStream#available()}, and violates the <a
+     * href="http://en.wikipedia.org/wiki/Liskov_substitution_principle">Liskov
+     * Substitution Principle</a>. This method should not be used.
+     *
+     * @return 0 if no further bytes are available. Otherwise returns 1,
+     *         which suggests (but does not guarantee) that additional bytes are
+     *         available.
      * @throws IOException
      *             If an error occurs.
-     * @since Android 1.0
      */
     @Override
     public int available() throws IOException {
@@ -295,10 +305,9 @@
 
     /**
      * Closes the input stream.
-     * 
+     *
      * @throws IOException
      *             If an error occurs closing the input stream.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -309,17 +318,15 @@
             super.close();
         }
     }
-    
+
     /**
-     * This implementation overrides the super type implementation to do nothing
-     * at all.
-     * 
+     * Marks the current position in the stream. This implementation overrides
+     * the super type implementation to do nothing at all.
+     *
      * @param readlimit
      *            of no use.
-     * @since Android 1.0
      */
     @Override
-    @SuppressWarnings("unused")
     public void mark(int readlimit) {
         // do nothing
     }
@@ -328,22 +335,20 @@
      * Reset the position of the stream to the last marked position. This
      * implementation overrides the supertype implementation and always throws
      * an {@link IOException IOException} when called.
-     * 
+     *
      * @throws IOException
      *             if the method is called
-     * @since Android 1.0
      */
     @Override
-    public void reset() throws IOException{
+    public void reset() throws IOException {
         throw new IOException();
     }
-    
+
     /**
      * Returns whether the receiver implements {@code mark} semantics. This type
      * does not support {@code mark()}, so always responds {@code false}.
-     * 
+     *
      * @return false, always
-     * @since Android 1.0
      */
     @Override
     public boolean markSupported() {
diff --git a/libcore/archive/src/main/java/java/util/zip/ZipConstants.java b/libcore/archive/src/main/java/java/util/zip/ZipConstants.java
index d804b0e..d00adc9 100644
--- a/libcore/archive/src/main/java/java/util/zip/ZipConstants.java
+++ b/libcore/archive/src/main/java/java/util/zip/ZipConstants.java
@@ -17,7 +17,6 @@
 
 package java.util.zip;
 
-
 interface ZipConstants {
 
     public static final long LOCSIG = 0x4034b50, EXTSIG = 0x8074b50,
diff --git a/libcore/archive/src/main/java/java/util/zip/ZipEntry.java b/libcore/archive/src/main/java/java/util/zip/ZipEntry.java
index 2cc7a9c..9774b6a 100644
--- a/libcore/archive/src/main/java/java/util/zip/ZipEntry.java
+++ b/libcore/archive/src/main/java/java/util/zip/ZipEntry.java
@@ -36,10 +36,9 @@
  * itself. For example when reading a <i>ZIP-file</i> you will first retrieve
  * all its entries in a collection and then read the data for a specific entry
  * through an input stream.
- * 
+ *
  * @see ZipFile
  * @see ZipOutputStream
- * @since Android 1.0
  */
 public class ZipEntry implements ZipConstants, Cloneable {
     String name, comment;
@@ -94,26 +93,21 @@
 
     /**
      * Zip entry state: Deflated.
-     * 
-     * @since Android 1.0
      */
     public static final int DEFLATED = 8;
 
     /**
      * Zip entry state: Stored.
-     * 
-     * @since Android 1.0
      */
     public static final int STORED = 0;
 
     /**
      * Constructs a new {@code ZipEntry} with the specified name.
-     * 
+     *
      * @param name
      *            the name of the ZIP entry.
      * @throws IllegalArgumentException
      *             if the name length is outside the range (> 0xFFFF).
-     * @since Android 1.0
      */
     public ZipEntry(String name) {
         if (name == null) {
@@ -147,11 +141,10 @@
 
     /**
      * Gets the comment for this {@code ZipEntry}.
-     * 
+     *
      * @return the comment for this {@code ZipEntry}, or {@code null} if there
      *         is no comment. If we're reading an archive with
      *         {@code ZipInputStream} the comment is not available.
-     * @since Android 1.0
      */
     public String getComment() {
         return comment;
@@ -159,10 +152,9 @@
 
     /**
      * Gets the compressed size of this {@code ZipEntry}.
-     * 
+     *
      * @return the compressed size, or -1 if the compressed size has not been
      *         set.
-     * @since Android 1.0
      */
     public long getCompressedSize() {
         return compressedSize;
@@ -170,9 +162,8 @@
 
     /**
      * Gets the checksum for this {@code ZipEntry}.
-     * 
+     *
      * @return the checksum, or -1 if the checksum has not been set.
-     * @since Android 1.0
      */
     public long getCrc() {
         return crc;
@@ -180,10 +171,9 @@
 
     /**
      * Gets the extra information for this {@code ZipEntry}.
-     * 
+     *
      * @return a byte array containing the extra information, or {@code null} if
      *         there is none.
-     * @since Android 1.0
      */
     public byte[] getExtra() {
         return extra;
@@ -191,10 +181,9 @@
 
     /**
      * Gets the compression method for this {@code ZipEntry}.
-     * 
+     *
      * @return the compression method, either {@code DEFLATED}, {@code STORED}
      *         or -1 if the compression method has not been set.
-     * @since Android 1.0
      */
     public int getMethod() {
         return compressionMethod;
@@ -202,9 +191,8 @@
 
     /**
      * Gets the name of this {@code ZipEntry}.
-     * 
+     *
      * @return the entry name.
-     * @since Android 1.0
      */
     public String getName() {
         return name;
@@ -212,10 +200,9 @@
 
     /**
      * Gets the uncompressed size of this {@code ZipEntry}.
-     * 
+     *
      * @return the uncompressed size, or {@code -1} if the size has not been
      *         set.
-     * @since Android 1.0
      */
     public long getSize() {
         return size;
@@ -223,10 +210,9 @@
 
     /**
      * Gets the last modification time of this {@code ZipEntry}.
-     * 
+     *
      * @return the last modification time as the number of milliseconds since
      *         Jan. 1, 1970.
-     * @since Android 1.0
      */
     public long getTime() {
         if (time != -1) {
@@ -242,10 +228,9 @@
 
     /**
      * Determine whether or not this {@code ZipEntry} is a directory.
-     * 
+     *
      * @return {@code true} when this {@code ZipEntry} is a directory, {@code
      *         false} otherwise.
-     * @since Android 1.0
      */
     public boolean isDirectory() {
         return name.charAt(name.length() - 1) == '/';
@@ -253,10 +238,9 @@
 
     /**
      * Sets the comment for this {@code ZipEntry}.
-     * 
+     *
      * @param string
      *            the comment for this entry.
-     * @since Android 1.0
      */
     public void setComment(String string) {
         if (string == null || string.length() <= 0xFFFF) {
@@ -268,10 +252,9 @@
 
     /**
      * Sets the compressed size for this {@code ZipEntry}.
-     * 
+     *
      * @param value
      *            the compressed size (in bytes).
-     * @since Android 1.0
      */
     public void setCompressedSize(long value) {
         compressedSize = value;
@@ -279,12 +262,11 @@
 
     /**
      * Sets the checksum for this {@code ZipEntry}.
-     * 
+     *
      * @param value
      *            the checksum for this entry.
      * @throws IllegalArgumentException
      *             if {@code value} is < 0 or > 0xFFFFFFFFL.
-     * @since Android 1.0
      */
     public void setCrc(long value) {
         if (value >= 0 && value <= 0xFFFFFFFFL) {
@@ -296,12 +278,11 @@
 
     /**
      * Sets the extra information for this {@code ZipEntry}.
-     * 
+     *
      * @param data
      *            a byte array containing the extra information.
      * @throws IllegalArgumentException
      *             when the length of data is greater than 0xFFFF bytes.
-     * @since Android 1.0
      */
     public void setExtra(byte[] data) {
         if (data == null || data.length <= 0xFFFF) {
@@ -313,13 +294,12 @@
 
     /**
      * Sets the compression method for this {@code ZipEntry}.
-     * 
+     *
      * @param value
      *            the compression method, either {@code DEFLATED} or {@code
      *            STORED}.
      * @throws IllegalArgumentException
      *             when value is not {@code DEFLATED} or {@code STORED}.
-     * @since Android 1.0
      */
     public void setMethod(int value) {
         if (value != STORED && value != DEFLATED) {
@@ -330,12 +310,11 @@
 
     /**
      * Sets the uncompressed size of this {@code ZipEntry}.
-     * 
+     *
      * @param value
      *            the uncompressed size for this entry.
      * @throws IllegalArgumentException
      *             if {@code value} < 0 or {@code value} > 0xFFFFFFFFL.
-     * @since Android 1.0
      */
     public void setSize(long value) {
         if (value >= 0 && value <= 0xFFFFFFFFL) {
@@ -347,11 +326,10 @@
 
     /**
      * Sets the modification time of this {@code ZipEntry}.
-     * 
+     *
      * @param value
      *            the modification time as the number of milliseconds since Jan.
      *            1, 1970.
-     * @since Android 1.0
      */
     public void setTime(long value) {
         GregorianCalendar cal = new GregorianCalendar();
@@ -372,9 +350,8 @@
 
     /**
      * Returns the string representation of this {@code ZipEntry}.
-     * 
+     *
      * @return the string representation of this {@code ZipEntry}.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -401,10 +378,9 @@
     /**
      * Constructs a new {@code ZipEntry} using the values obtained from {@code
      * ze}.
-     * 
+     *
      * @param ze
      *            the {@code ZipEntry} from which to obtain values.
-     * @since Android 1.0
      */
     public ZipEntry(ZipEntry ze) {
         name = ze.name;
@@ -434,9 +410,8 @@
 
     /**
      * Returns a shallow copy of this entry.
-     * 
+     *
      * @return a copy of this entry.
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -445,9 +420,8 @@
 
     /**
      * Returns the hash code for this {@code ZipEntry}.
-     * 
+     *
      * @return the hash code of the entry.
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -471,7 +445,7 @@
          * readIntLE, so we're going to read the entire header at once
          * and then parse the results out without using any function calls.
          * Uglier, but should be much faster.
-         * 
+         *
          * Note that some lines look a bit different, because the corresponding
          * fields or locals are long and so we need to do & 0xffffffffl to avoid
          * problems induced by sign extension.
@@ -549,7 +523,7 @@
         int count;
         int len = b.length;
         int off = 0;
-    
+
         while (len > 0) {
             count = in.read(b, off, len);
             if (count <= 0)
diff --git a/libcore/archive/src/main/java/java/util/zip/ZipException.java b/libcore/archive/src/main/java/java/util/zip/ZipException.java
index 590117b..6dab26f 100644
--- a/libcore/archive/src/main/java/java/util/zip/ZipException.java
+++ b/libcore/archive/src/main/java/java/util/zip/ZipException.java
@@ -17,7 +17,6 @@
 
 package java.util.zip;
 
-
 import java.io.IOException;
 
 /**
@@ -26,7 +25,6 @@
  * 
  * @see ZipFile
  * @see ZipInputStream
- * @since Android 1.0
  */
 public class ZipException extends IOException {
 
@@ -34,8 +32,6 @@
 
     /**
      * Constructs a new {@code ZipException} instance.
-     * 
-     * @since Android 1.0
      */
     public ZipException() {
         super();
@@ -44,10 +40,9 @@
     /**
      * Constructs a new {@code ZipException} instance with the specified
      * message.
-     * 
+     *
      * @param detailMessage
      *            the detail message for the exception.
-     * @since Android 1.0
      */
     public ZipException(String detailMessage) {
         super(detailMessage);
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 f1415d9..653b2c9 100644
--- a/libcore/archive/src/main/java/java/util/zip/ZipFile.java
+++ b/libcore/archive/src/main/java/java/util/zip/ZipFile.java
@@ -37,17 +37,13 @@
  * While {@code ZipInputStream} provides stream based read access to a
  * <i>ZIP-archive</i>, this class implements more efficient (file based) access
  * and makes use of the <i>central directory</i> within a <i>ZIP-archive</i>.
- * </p>
  * <p>
  * Use {@code ZipOutputStream} if you want to create an archive.
- * </p>
  * <p>
  * A temporary ZIP file can be marked for automatic deletion upon closing it.
- * </p>
- * 
+ *
  * @see ZipEntry
  * @see ZipOutputStream
- * @since Android 1.0
  */
 public class ZipFile implements ZipConstants {
 
@@ -57,28 +53,23 @@
 
     /**
      * Open zip file for read.
-     * 
-     * @since Android 1.0
      */
     public static final int OPEN_READ = 1;
 
     /**
      * Delete zip file when closed.
-     * 
-     * @since Android 1.0
      */
     public static final int OPEN_DELETE = 4;
 
     /**
      * Constructs a new {@code ZipFile} with the specified file.
-     * 
+     *
      * @param file
      *            the file to read from.
      * @throws ZipException
      *             if a ZIP error occurs.
      * @throws IOException
      *             if an {@code IOException} occurs.
-     * @since Android 1.0
      */
     public ZipFile(File file) throws ZipException, IOException {
         this(file, OPEN_READ);
@@ -88,22 +79,31 @@
      * Opens a file as <i>ZIP-archive</i>. "mode" must be {@code OPEN_READ} or
      * {@code OPEN_DELETE} . The latter sets the "delete on exit" flag through a
      * file.
-     * 
+     *
      * @param file
      *            the ZIP file to read.
      * @param mode
      *            the mode of the file open operation.
      * @throws IOException
      *             if an {@code IOException} occurs.
-     * @since Android 1.0
      */
     public ZipFile(File file, int mode) throws IOException {
-        if (mode == (OPEN_READ | OPEN_DELETE))
-            fileToDeleteOnClose = file; // file.deleteOnExit();
-        else if (mode != OPEN_READ)
-            throw new IllegalArgumentException("invalid mode");
-
         fileName = file.getPath();
+        if (mode == OPEN_READ || mode == (OPEN_READ | OPEN_DELETE)) {
+            SecurityManager security = System.getSecurityManager();
+            if (security != null) {
+                security.checkRead(fileName);
+            }
+            if ((mode & OPEN_DELETE) != 0) {
+                if (security != null) {
+                    security.checkDelete(fileName);
+                }
+                fileToDeleteOnClose = file; // file.deleteOnExit();
+            }
+        } else {
+            throw new IllegalArgumentException();
+        }
+
         mRaf = new RandomAccessFile(fileName, "r");
 
         mEntryList = new ArrayList<ZipEntry>();
@@ -124,12 +124,11 @@
 
     /**
      * Opens a ZIP archived file.
-     * 
+     *
      * @param name
      *            the name of the ZIP file.
      * @throws IOException
      *             if an IOException occurs.
-     * @since Android 1.0
      */
     public ZipFile(String name) throws IOException {
         this(new File(name), OPEN_READ);
@@ -142,10 +141,9 @@
 
     /**
      * Closes this ZIP file.
-     * 
+     *
      * @throws IOException
      *             if an IOException occurs.
-     * @since Android 1.0
      */
     public void close() throws IOException {
         RandomAccessFile raf = mRaf;
@@ -171,9 +169,8 @@
     /**
      * 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.
-     * @since Android 1.0
      */
     public Enumeration<? extends ZipEntry> entries() {
         return new Enumeration<ZipEntry>() {
@@ -195,12 +192,11 @@
 
     /**
      * Gets the ZIP entry with the specified name from this {@code ZipFile}.
-     * 
+     *
      * @param entryName
      *            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.
-     * @since Android 1.0
      */
     public ZipEntry getEntry(String entryName) {
         if (entryName != null) {
@@ -213,13 +209,12 @@
 
     /**
      * Returns an input stream on the data of the specified {@code ZipEntry}.
-     * 
+     *
      * @param entry
      *            the ZipEntry.
      * @return an input stream of the data contained in the {@code ZipEntry}.
      * @throws IOException
      *             if an {@code IOException} occurs.
-     * @since Android 1.0
      */
     public InputStream getInputStream(ZipEntry entry) throws IOException {
         /*
@@ -259,9 +254,8 @@
 
     /**
      * Gets the file name of this {@code ZipFile}.
-     * 
+     *
      * @return the file name of this {@code ZipFile}.
-     * @since Android 1.0
      */
     public String getName() {
         return fileName;
@@ -269,9 +263,8 @@
 
     /**
      * Returns the number of {@code ZipEntries} in this {@code ZipFile}.
-     * 
+     *
      * @return the number of entries in this file.
-     * @since Android 1.0
      */
     public int size() {
         return mEntryList.size();
diff --git a/libcore/archive/src/main/java/java/util/zip/ZipInputStream.java b/libcore/archive/src/main/java/java/util/zip/ZipInputStream.java
index 262fa3f..f86cbe0 100644
--- a/libcore/archive/src/main/java/java/util/zip/ZipInputStream.java
+++ b/libcore/archive/src/main/java/java/util/zip/ZipInputStream.java
@@ -17,7 +17,6 @@
 
 package java.util.zip;
 
-
 import java.io.EOFException;
 import java.io.IOException;
 import java.io.InputStream;
@@ -36,18 +35,14 @@
  * the so called ZIP entries. Therefore when reading from a {@code
  * ZipInputStream} first the entry's attributes will be retrieved with {@code
  * getNextEntry} before its data is read.
- * </p>
  * <p>
  * While {@code InflaterInputStream} can read a compressed <i>ZIP-archive</i>
  * entry, this extension can read uncompressed entries as well.
- * </p>
  * <p>
  * Use {@code ZipFile} if you can access the archive as a file directly.
- * </p>
- * 
+ *
  * @see ZipEntry
  * @see ZipFile
- * @since Android 1.0
  */
 public class ZipInputStream extends InflaterInputStream implements ZipConstants {
     static final int DEFLATED = 8;
@@ -58,7 +53,7 @@
 
     static final int ZIPLocalHeaderVersionNeeded = 20;
 
-    // BEGI android-removed
+    // BEGIN android-removed
     // private boolean zipClosed = false;
     // END android-removed
 
@@ -82,10 +77,9 @@
 
     /**
      * Constructs a new {@code ZipInputStream} from the specified input stream.
-     * 
+     *
      * @param stream
      *            the input stream to representing a ZIP archive.
-     * @since Android 1.0
      */
     public ZipInputStream(InputStream stream) {
         super(new PushbackInputStream(stream, BUF_SIZE), new Inflater(true));
@@ -96,10 +90,9 @@
 
     /**
      * Closes this {@code ZipInputStream}.
-     * 
+     *
      * @throws IOException
      *             if an {@code IOException} occurs.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -113,10 +106,9 @@
 
     /**
      * Closes the current ZIP entry and positions to read the next entry.
-     * 
+     *
      * @throws IOException
      *             if an {@code IOException} occurs.
-     * @since Android 1.0
      */
     public void closeEntry() throws IOException {
         // BEGIN android-changed
@@ -133,8 +125,24 @@
                 return;
             }
         }
+
+        /*
+         * The following code is careful to leave the ZipInputStream in a
+         * consistent state, even when close() results in an exception. It does
+         * so by:
+         *  - pushing bytes back into the source stream
+         *  - reading a data descriptor footer from the source stream
+         *  - resetting fields that manage the entry being closed
+         */
+
         // Ensure all entry bytes are read
-        skip(Long.MAX_VALUE);
+        Exception failure = null;
+        try {
+            skip(Long.MAX_VALUE);
+        } catch (Exception e) {
+            failure = e;
+        }
+
         int inB, out;
         if (currentEntry.compressionMethod == DEFLATED) {
             inB = inf.getTotalIn();
@@ -143,12 +151,38 @@
             inB = inRead;
             out = inRead;
         }
-        int diff = 0;
+        int diff = entryIn - inB;
         // Pushback any required bytes
-        if ((diff = entryIn - inB) != 0) {
+        if (diff != 0) {
             ((PushbackInputStream) in).unread(buf, len - diff, diff);
         }
 
+        try {
+            readAndVerifyDataDescriptor(inB, out);
+        } catch (Exception e) {
+            if (failure == null) { // otherwise we're already going to throw
+                failure = e;
+            }
+        }
+
+        inf.reset();
+        lastRead = inRead = entryIn = len = 0;
+        crc.reset();
+        currentEntry = null;
+
+        if (failure != null) {
+            if (failure instanceof IOException) {
+                throw (IOException) failure;
+            } else if (failure instanceof RuntimeException) {
+                throw (RuntimeException) failure;
+            }
+            AssertionError error = new AssertionError();
+            error.initCause(failure);
+            throw error;
+        }
+    }
+
+    private void readAndVerifyDataDescriptor(int inB, int out) throws IOException {
         if (hasDD) {
             in.read(hdrBuf, 0, EXTHDR);
             if (getLong(hdrBuf, 0) != EXTSIG) {
@@ -164,27 +198,19 @@
         if (currentEntry.compressedSize != inB || currentEntry.size != out) {
             throw new ZipException(Messages.getString("archive.21")); //$NON-NLS-1$
         }
-
-        inf.reset();
-        lastRead = inRead = entryIn = len = 0;
-        crc.reset();
-        currentEntry = null;
     }
 
     /**
-     * Reads the next entry from this {@code ZipInputStream}.
-     * 
+     * Reads the next entry from this {@code ZipInputStream} or {@code null} if
+     * no more entries are present.
+     *
      * @return the next {@code ZipEntry} contained in the input stream.
      * @throws IOException
-     *             if the stream is not positioned at the beginning of an entry
-     *             or if an other {@code IOException} occurs.
+     *             if an {@code IOException} occurs.
      * @see ZipEntry
-     * @since Android 1.0
      */
     public ZipEntry getNextEntry() throws IOException {
-        if (currentEntry != null) {
-            closeEntry();
-        }
+        closeEntry();
         if (entriesEnd) {
             return null;
         }
@@ -266,87 +292,89 @@
             }
             currentEntry.setExtra(e);
         }
-        // BEGIN android-added
-        eof = false;
-        // END android-added
         return currentEntry;
     }
 
     /* Read 4 bytes from the buffer and store it as an int */
 
+    /**
+     * Reads up to the specified number of uncompressed bytes into the buffer
+     * starting at the offset.
+     *
+     * @param buffer
+     *            a byte array
+     * @param start
+     *            the starting offset into the buffer
+     * @param length
+     *            the number of bytes to read
+     * @return the number of bytes read
+     */
     @Override
     public int read(byte[] buffer, int start, int length) throws IOException {
         // BEGIN android-changed
         if (closed) {
             throw new IOException(Messages.getString("archive.1E")); //$NON-NLS-1$
         }
-        // END android-changed
         if (inf.finished() || currentEntry == null) {
             return -1;
         }
         // avoid int overflow, check null buffer
-        if (start <= buffer.length && length >= 0 && start >= 0
-                && buffer.length - start >= length) {
-            if (currentEntry.compressionMethod == STORED) {
-                int csize = (int) currentEntry.size;
-                if (inRead >= csize) {
-                    // BEGIN android-added
-                    eof = true;
-                    // END android-added
-                    return -1;
-                }
-                if (lastRead >= len) {
-                    lastRead = 0;
-                    if ((len = in.read(buf)) == -1) {
-                        // BEGIN android-added
-                        eof = true;
-                        // END android-added
-                        return -1;
-                    }
-                    entryIn += len;
-                }
-                // BEGIN android-changed
-                int toRead = length > (len - lastRead) ? len - lastRead : length;
-                // END android-changed
-                if ((csize - inRead) < toRead) {
-                    toRead = csize - inRead;
-                }
-                System.arraycopy(buf, lastRead, buffer, start, toRead);
-                lastRead += toRead;
-                inRead += toRead;
-                crc.update(buffer, start, toRead);
-                return toRead;
-            }
-            if (inf.needsInput()) {
-                fill();
-                if (len > 0) {
-                    entryIn += len;
-                }
-            }
-            int read = 0;
-            try {
-                read = inf.inflate(buffer, start, length);
-            } catch (DataFormatException e) {
-                throw new ZipException(e.getMessage());
-            }
-            if (read == 0 && inf.finished()) {
+        if (start > buffer.length || length < 0 || start < 0
+                || buffer.length - start < length) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+
+        if (currentEntry.compressionMethod == STORED) {
+            int csize = (int) currentEntry.size;
+            if (inRead >= csize) {
                 return -1;
             }
-            crc.update(buffer, start, read);
-            return read;
+            if (lastRead >= len) {
+                lastRead = 0;
+                if ((len = in.read(buf)) == -1) {
+                    eof = true;
+                    return -1;
+                }
+                entryIn += len;
+            }
+            int toRead = length > (len - lastRead) ? len - lastRead : length;
+            if ((csize - inRead) < toRead) {
+                toRead = csize - inRead;
+            }
+            System.arraycopy(buf, lastRead, buffer, start, toRead);
+            lastRead += toRead;
+            inRead += toRead;
+            crc.update(buffer, start, toRead);
+            return toRead;
         }
-        throw new ArrayIndexOutOfBoundsException();
+        if (inf.needsInput()) {
+            fill();
+            if (len > 0) {
+                entryIn += len;
+            }
+        }
+        int read;
+        try {
+            read = inf.inflate(buffer, start, length);
+        } catch (DataFormatException e) {
+            throw new ZipException(e.getMessage());
+        }
+        if (read == 0 && inf.finished()) {
+            return -1;
+        }
+        crc.update(buffer, start, read);
+        return read;
+        // END android-changed
     }
 
     /**
      * Skips up to the specified number of bytes in the current ZIP entry.
-     * 
+     *
      * @param value
      *            the number of bytes to skip.
      * @return the number of bytes skipped.
      * @throws IOException
      *             if an {@code IOException} occurs.
-     * @since Android 1.0
      */
     @Override
     public long skip(long value) throws IOException {
@@ -364,15 +392,14 @@
             return skipped;
         }
         throw new IllegalArgumentException();
-}
+    }
 
     /**
      * Returns 0 if the {@code EOF} has been reached, otherwise returns 1.
-     * 
+     *
      * @return 0 after {@code EOF} of current entry, 1 otherwise.
      * @throws IOException
      *             if an IOException occurs.
-     * @since Android 1.0
      */
     @Override
     public int available() throws IOException {
@@ -380,20 +407,16 @@
         if (closed) {
             throw new IOException(Messages.getString("archive.1E")); //$NON-NLS-1$
         }
-        if (currentEntry == null) {
-            return 1;
-        }
-        return super.available();
+        return (currentEntry == null || inRead < currentEntry.size) ? 1 : 0;
         // END android-changed
     }
 
     /**
      * creates a {@link ZipEntry } with the given name.
-     * 
+     *
      * @param name
      *            the name of the entry.
      * @return the created {@code ZipEntry}.
-     * @since Android 1.0
      */
     protected ZipEntry createZipEntry(String name) {
         return new ZipEntry(name);
diff --git a/libcore/archive/src/main/java/java/util/zip/ZipOutputStream.java b/libcore/archive/src/main/java/java/util/zip/ZipOutputStream.java
index 4ddf643..58e781f 100644
--- a/libcore/archive/src/main/java/java/util/zip/ZipOutputStream.java
+++ b/libcore/archive/src/main/java/java/util/zip/ZipOutputStream.java
@@ -17,7 +17,6 @@
 
 package java.util.zip;
 
-
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
@@ -32,33 +31,26 @@
  * {@code ZipOutputStream} is used to write {@code ZipEntries} to the underlying
  * stream. Output from {@code ZipOutputStream} conforms to the {@code ZipFile}
  * file format.
- * </p>
  * <p>
  * While {@code DeflaterOutputStream} can write a compressed <i>ZIP-archive</i>
  * entry, this extension can write uncompressed entries as well. In this case
  * special rules apply, for this purpose refer to the <a
  * href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">file format
  * specification</a>.
- * </p>
- * 
+ *
  * @see ZipEntry
  * @see ZipFile
- * @since Android 1.0
  */
 public class ZipOutputStream extends DeflaterOutputStream implements
         ZipConstants {
 
     /**
      * Indicates deflated entries.
-     * 
-     * @since Android 1.0
      */
     public static final int DEFLATED = 8;
 
     /**
      * Indicates uncompressed entries.
-     * 
-     * @since Android 1.0
      */
     public static final int STORED = 0;
 
@@ -90,7 +82,6 @@
      * 
      * @param p1
      *            the {@code OutputStream} to write the data to.
-     * @since Android 1.0
      */
     public ZipOutputStream(OutputStream p1) {
         super(p1, new Deflater(Deflater.DEFAULT_COMPRESSION, true));
@@ -102,7 +93,6 @@
      * 
      * @throws IOException
      *             If an error occurs closing the stream.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -119,7 +109,6 @@
      * 
      * @throws IOException
      *             If an error occurs closing the entry.
-     * @since Android 1.0
      */
     public void closeEntry() throws IOException {
         if (cDir == null) {
@@ -205,7 +194,6 @@
      * 
      * @throws IOException
      *             if an error occurs while terminating the stream.
-     * @since Android 1.0
      */
     @Override
     public void finish() throws IOException {
@@ -253,7 +241,6 @@
      * @throws IOException
      *             If an error occurs storing the entry.
      * @see #write
-     * @since Android 1.0
      */
     public void putNextEntry(ZipEntry ze) throws java.io.IOException {
         if (currentEntry != null) {
@@ -286,7 +273,8 @@
         nameLength = utf8Count(ze.name);
         if (nameLength > 0xffff) {
             /* [MSG "archive.2A", "Name too long: {0}"] */
-            throw new IllegalArgumentException(Messages.getString("archive.2A", ze.name)); //$NON-NLS-1$
+            throw new IllegalArgumentException(Messages.getString(
+                    "archive.2A", ze.name)); //$NON-NLS-1$
         }
 
         def.setLevel(compressLevel);
@@ -338,7 +326,6 @@
      * 
      * @param comment
      *            the comment associated with the file.
-     * @since Android 1.0
      */
     public void setComment(String comment) {
         if (comment.length() > 0xFFFF) {
@@ -355,7 +342,6 @@
      * @param level
      *            the compression level (ranging from -1 to 8).
      * @see Deflater
-     * @since Android 1.0
      */
     public void setLevel(int level) {
         if (level < Deflater.DEFAULT_COMPRESSION
@@ -372,7 +358,6 @@
      * 
      * @param method
      *            the compression method to use.
-     * @since Android 1.0
      */
     public void setMethod(int method) {
         if (method != STORED && method != DEFLATED) {
@@ -398,11 +383,17 @@
 
     }
 
+    /**
+     * Writes data for the current entry to the underlying stream.
+     * 
+     * @exception IOException
+     *                If an error occurs writing to the stream
+     */
     @Override
     public void write(byte[] buffer, int off, int nbytes)
             throws java.io.IOException {
         // avoid int overflow, check null buf
-        if ((off > buffer.length) || (nbytes < 0) || (off < 0)
+        if ((off < 0 || (nbytes < 0) || off > buffer.length)
                 || (buffer.length - off < nbytes)) {
             throw new IndexOutOfBoundsException();
         }
diff --git a/libcore/archive/src/main/java/org/apache/harmony/archive/internal/nls/Messages.java b/libcore/archive/src/main/java/org/apache/harmony/archive/internal/nls/Messages.java
index 764f34d..3ba50fa 100644
--- a/libcore/archive/src/main/java/org/apache/harmony/archive/internal/nls/Messages.java
+++ b/libcore/archive/src/main/java/org/apache/harmony/archive/internal/nls/Messages.java
@@ -27,7 +27,6 @@
 
 package org.apache.harmony.archive.internal.nls;
 
-
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.Locale;
@@ -50,7 +49,7 @@
  * is looked up, or resource bundle support is not available, the key itself
  * will be returned as the associated message. This means that the <em>KEY</em>
  * should a reasonable human-readable (english) string.
- * 
+ *
  */
 public class Messages {
 
@@ -61,7 +60,7 @@
 
     /**
      * Retrieves a message which has no arguments.
-     * 
+     *
      * @param msg
      *            String the key to look up.
      * @return String the message for that key in the system message bundle.
@@ -74,7 +73,7 @@
 
     /**
      * Retrieves a message which takes 1 argument.
-     * 
+     *
      * @param msg
      *            String the key to look up.
      * @param arg
@@ -87,7 +86,7 @@
 
     /**
      * Retrieves a message which takes 1 integer argument.
-     * 
+     *
      * @param msg
      *            String the key to look up.
      * @param arg
@@ -100,7 +99,7 @@
 
     /**
      * Retrieves a message which takes 1 character argument.
-     * 
+     *
      * @param msg
      *            String the key to look up.
      * @param arg
@@ -113,7 +112,7 @@
 
     /**
      * Retrieves a message which takes 2 arguments.
-     * 
+     *
      * @param msg
      *            String the key to look up.
      * @param arg1
@@ -128,7 +127,7 @@
 
     /**
      * Retrieves a message which takes several arguments.
-     * 
+     *
      * @param msg
      *            String the key to look up.
      * @param args
diff --git a/libcore/archive/src/main/java/org/apache/harmony/archive/internal/nls/messages.properties b/libcore/archive/src/main/java/org/apache/harmony/archive/internal/nls/messages.properties
index 1ae5c5e..e909af0 100644
--- a/libcore/archive/src/main/java/org/apache/harmony/archive/internal/nls/messages.properties
+++ b/libcore/archive/src/main/java/org/apache/harmony/archive/internal/nls/messages.properties
@@ -60,8 +60,11 @@
 archive.2A=Name too long: {0}
 archive.2B=String is too long
 archive.2C=No active entry
-archive.2D=Missing version string\: {0}
-archive.2E=Line too long
-archive.2F=Invalid attribute {0}
-archive.30={0} failed verification of {1}
-archive.31={0} has invalid digest for {1} in {2}
+archive.2D=Missing version attribute\: {0}
+archive.2E=Manifest is too long
+archive.2F=NUL character in a manifest
+archive.30=Invalid attribute {0}
+archive.31={0} failed verification of {1}
+archive.32={0} has invalid digest for {1} in {2}
+archive.33=A length of the encoded header name "{1}" exceeded maximum length {2}
+archive.34=A jar verifier does not support more than one entry with the same name
diff --git a/libcore/archive/src/main/java/org/apache/harmony/archive/util/Util.java b/libcore/archive/src/main/java/org/apache/harmony/archive/util/Util.java
index bed3e91..b15108a 100644
--- a/libcore/archive/src/main/java/org/apache/harmony/archive/util/Util.java
+++ b/libcore/archive/src/main/java/org/apache/harmony/archive/util/Util.java
@@ -30,39 +30,49 @@
                 return false;
             }
 
-            s1 = s1.substring(start1, start1 + length);
-            s2 = s2.substring(start2, start2 + length);
-
-            return toASCIILowerCase(s1).equals(toASCIILowerCase(s2));
+            char c1, c2;
+            for (int i = 0; i < length; i++) {
+                if ((c1 = s1.charAt(start1++)) != (c2 = s2.charAt(start2++))
+                        && toASCIIUpperCase(c1) != toASCIIUpperCase(c2)) {
+                    return false;
+                }
+            }
+            return true;
         }
         throw new NullPointerException();
     }
 
-    public static String toASCIILowerCase(String s) {
-        int len = s.length();
-        StringBuilder buffer = new StringBuilder(len);
-        for (int i = 0; i < len; i++) {
-            char c = s.charAt(i);
-            if ('A' <= c && c <= 'Z') {
-                buffer.append((char) (c + ('a' - 'A')));
-            } else {
-                buffer.append(c);
+    public static final boolean equalsIgnoreCase(byte[] buf1, byte[] buf2) {
+        if (buf1 == buf2) {
+            return true;
+        }
+
+        if (buf1 == null || buf2 == null || buf1.length != buf2.length) {
+            return false;
+        }
+
+        byte b1, b2;
+
+        for (int i = 0; i < buf1.length; i++) {
+            if ((b1 = buf1[i]) != (b2 = buf2[i])
+                    && toASCIIUpperCase(b1) != toASCIIUpperCase(b2)) {
+                return false;
             }
         }
-        return buffer.toString();
+        return true;
     }
 
-    public static String toASCIIUpperCase(String s) {
-        int len = s.length();
-        StringBuilder buffer = new StringBuilder(len);
-        for (int i = 0; i < len; i++) {
-            char c = s.charAt(i);
-            if ('a' <= c && c <= 'z') {
-                buffer.append((char) (c - ('a' - 'A')));
-            } else {
-                buffer.append(c);
-            }
+    static final char toASCIIUpperCase(char c) {
+        if ('a' <= c && c <= 'z') {
+            return (char) (c - ('a' - 'A'));
         }
-        return buffer.toString();
+        return c;
+    }
+
+    static final byte toASCIIUpperCase(byte b) {
+        if ('a' <= b && b <= 'z') {
+            return (byte) (b - ('a' - 'A'));
+        }
+        return b;
     }
 }
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 a7a182a..1b02a11 100644
--- a/libcore/archive/src/main/native/java_util_zip_Adler32.c
+++ b/libcore/archive/src/main/native/java_util_zip_Adler32.c
@@ -15,23 +15,25 @@
  * limitations under the License.
  */
 
+#include "jni.h"
 #include "hy2sie.h"
-
 #include "zlib.h"
-
+#include "sieb.h"
 
 JNIEXPORT jlong JNICALL
 Java_java_util_zip_Adler32_updateImpl (JNIEnv * env, jobject recv,
                                        jbyteArray buf, int off, int len,
                                        jlong crc)
 {
-  PORT_ACCESS_FROM_ENV (env);
-
   jbyte *b;
   jboolean isCopy;
   jlong result;
 
   b = (*env)->GetPrimitiveArrayCritical (env, buf, &isCopy);
+  if (b == NULL) {
+    throwNewOutOfMemoryError(env, "");
+    return 0;
+  }
   result = (jlong) adler32 ((uLong) crc, (Bytef *) (b + off), (uInt) len);
   (*env)->ReleasePrimitiveArrayCritical (env, buf, b, JNI_ABORT);
 
@@ -42,9 +44,8 @@
 Java_java_util_zip_Adler32_updateByteImpl (JNIEnv * env, jobject recv,
                                            jint val, jlong crc)
 {
-  PORT_ACCESS_FROM_ENV (env);
-
-  return adler32 ((uLong) crc, (Bytef *) (&val), 1);
+  Bytef bytefVal = val;
+  return adler32 ((uLong) crc, (Bytef *) (&bytefVal), 1);
 }
 
 
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 0688868..cee25e5 100644
--- a/libcore/archive/src/main/native/java_util_zip_CRC32.c
+++ b/libcore/archive/src/main/native/java_util_zip_CRC32.c
@@ -16,6 +16,7 @@
  */
 
 #include "hy2sie.h"
+#include "sieb.h"
 
 #include "zlib.h"
 
@@ -28,8 +29,10 @@
   jlong result;
 
   b = ((*env)->GetPrimitiveArrayCritical (env, buf, 0));
-  if (b == NULL)
+  if (b == NULL) {
+    throwNewOutOfMemoryError(env, "");
     return -1;
+  }
   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 c8bd199..2e0e268 100644
--- a/libcore/archive/src/main/native/java_util_zip_Deflater.c
+++ b/libcore/archive/src/main/native/java_util_zip_Deflater.c
@@ -18,11 +18,13 @@
 #include "hy2sie.h"
 
 #include "zlib.h"
-#include "zipsup.h"
+#include "zip.h"
+#include "jni.h"
 
-
+#ifndef HY_ZIP_API
 void zfree PROTOTYPE ((void *opaque, void *address));
 void *zalloc PROTOTYPE ((void *opaque, U_32 items, U_32 size));
+#endif
 
 
 static struct {
@@ -52,10 +54,10 @@
   if (err != Z_OK)
     {
       jclmem_free_memory (env, dBytes);
-      throwNewIllegalArgumentException (env, "");
+      THROW_ZIP_EXCEPTION(env, err, IllegalArgumentException);
       return;
     }
-  stream->dict = dBytes;
+  stream->dict = (U_8*) dBytes;
 }
 
 JNIEXPORT jlong JNICALL
@@ -94,9 +96,8 @@
 Java_java_util_zip_Deflater_createStream (JNIEnv * env, jobject recv,
 					  jint level, jint strategy,
 					  jboolean noHeader)
-{  
+{
   PORT_ACCESS_FROM_ENV (env);
-
   JCLZipStream *jstream;
   z_stream *stream;
   int err = 0;
@@ -109,7 +110,12 @@
                   // results in 2 x 128K being allocated per Deflater, which is
                   // not acceptable.
   // END android-changed
-  
+#ifdef HY_ZIP_API
+  VMI_ACCESS_FROM_ENV (env);
+  VMIZipFunctionTable *zipFuncs;
+  zipFuncs = (*VMI)->GetZipFunctions(VMI);
+#endif
+
   /*Allocate mem for wrapped struct */
   jstream = jclmem_allocate_memory (env, sizeof (JCLZipStream));
   if (jstream == NULL)
@@ -141,11 +147,10 @@
 		      mlevel,	/*Memory allocation for internal compression state. 9 uses the most. */
 		      // END android-changed
 		      strategy);
-  if (err != Z_OK)
-    {
-      throwNewIllegalArgumentException (env, "");
-      return -1;
-    }
+  if (err != Z_OK) {
+    THROW_ZIP_EXCEPTION(env, err, IllegalArgumentException);
+    return -1;
+  }
 
   return (jlong) ((IDATA) jstream);
 }
@@ -170,8 +175,10 @@
       return;
     }
   in = ((*env)->GetPrimitiveArrayCritical (env, buf, 0));
-  if (in == NULL)
+  if (in == NULL) {
+    throwNewOutOfMemoryError(env, "");
     return;
+  }
   memcpy (stream->inaddr, (in + off), len);
   ((*env)->ReleasePrimitiveArrayCritical (env, buf, in, JNI_ABORT));
   stream->stream->next_in = (Bytef *) stream->inaddr;
@@ -185,8 +192,6 @@
 					 jbyteArray buf, int off, int len,
 					 jlong handle, int flushParm)
 {
-  PORT_ACCESS_FROM_ENV (env);
-
   jbyte *out;
   JCLZipStream *stream;
   jint err = 0;
@@ -203,29 +208,34 @@
   sin = stream->stream->total_in;
   sout = stream->stream->total_out;
   out = ((*env)->GetPrimitiveArrayCritical (env, buf, 0));
-  if (out == NULL)
+  if (out == NULL) {
+    throwNewOutOfMemoryError(env, "");
     return -1;
+  }
   stream->stream->next_out = (Bytef *) out + off;
   err = deflate (stream->stream, flushParm);
   ((*env)->ReleasePrimitiveArrayCritical (env, buf, out, 0));
-  if (err != Z_OK)
-    {
-      if (err == Z_STREAM_END)
-	{
-	  ((*env)->
-	   SetBooleanField (env, recv,
-			    gCachedFields.finished,
-			    JNI_TRUE));
-	  return stream->stream->total_out - sout;
-	}
+  if (err != Z_OK) {
+    if (err == Z_MEM_ERROR) {
+      throwNewOutOfMemoryError(env, "");
+      return 0;
     }
+    if (err == Z_STREAM_END)
+      {
+        ((*env)->
+         SetBooleanField (env, recv,
+                          gCachedFields.finished,
+                          JNI_TRUE));
+        return stream->stream->total_out - sout;
+      }
+  }
   if (flushParm != Z_FINISH)
     {
       /* Need to update the number of input bytes read. */
       ((*env)->
        SetIntField (env, recv,
-		    gCachedFields.inRead,
-		    (jint) stream->stream->total_in - sin + inBytes));
+                    gCachedFields.inRead,
+                    (jint) stream->stream->total_in - sin + inBytes));
     }
   return stream->stream->total_out - sout;
 }
@@ -262,8 +272,6 @@
 					   int level, int strategy,
 					   jlong handle)
 {
-  PORT_ACCESS_FROM_ENV (env);
-
   JCLZipStream *stream;
   jbyte b = 0;
   int err = 0;
@@ -276,8 +284,9 @@
   stream = (JCLZipStream *) ((IDATA) handle);
   stream->stream->next_out = (Bytef *) & b;
   err = deflateParams (stream->stream, level, strategy);
-  if (err != Z_OK)
-    throwNewIllegalStateException (env, "");
+  if (err != Z_OK) {
+    THROW_ZIP_EXCEPTION(env, err, IllegalStateException);
+  }
 }
 
 JNIEXPORT void JNICALL
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 d3a7d7c..4b30d4e 100644
--- a/libcore/archive/src/main/native/java_util_zip_Inflater.c
+++ b/libcore/archive/src/main/native/java_util_zip_Inflater.c
@@ -16,6 +16,7 @@
  */
 
 #include "hy2sie.h"
+#include "zip.h"
 
 #include "zlib.h"
 #include <memory.h>
@@ -24,6 +25,7 @@
 
 #include <fcntl.h>
 
+void throwNewDataFormatException (JNIEnv * env, const char *message);
 
 void zfree PROTOTYPE ((void *opaque, void *address));
 void *zalloc PROTOTYPE ((void *opaque, U_32 items, U_32 size));
@@ -36,27 +38,6 @@
 } gCachedFields;
 
 
-// Contents from Harmony's inflater.h was put here:
-//
-typedef struct JCLZipStream
-{
-  U_8 *inaddr;
-  int inCap;
-  U_8 *dict;
-  z_stream *stream;
-} JCLZipStream;
-
-
-
-/**
-  * Throw java.util.zip.DataFormatException
-  */
-void
-throwNewDataFormatException (JNIEnv * env, const char *message)
-{
-  jniThrowException(env, "java/util/zip/DataFormatException", message);
-}
-
 
 /* Create a new stream . This stream cannot be used until it has been properly initialized. */
 JNIEXPORT jlong JNICALL
@@ -69,6 +50,11 @@
   z_stream *stream;
   int err = 0;
   int wbits = 15;               /*Use MAX for fastest */
+#ifdef HY_ZIP_API
+  VMI_ACCESS_FROM_ENV (env);
+  VMIZipFunctionTable *zipFuncs;
+  zipFuncs = (*VMI)->GetZipFunctions(VMI);
+#endif
 
   /*Allocate mem for wrapped struct */
   jstream = jclmem_allocate_memory (env, sizeof (JCLZipStream));
@@ -104,7 +90,7 @@
     {
       jclmem_free_memory (env, stream);
       jclmem_free_memory (env, jstream);
-      throwNewIllegalArgumentException (env, "");
+      THROW_ZIP_EXCEPTION(env, err, IllegalArgumentException);
       return -1;
     }
 
@@ -134,8 +120,10 @@
   stream->stream->next_in = (Bytef *) baseAddr;
   stream->stream->avail_in = len;
   in = ((*env)->GetPrimitiveArrayCritical (env, buf, 0));
-  if (in == NULL)
+  if (in == NULL) {
+    throwNewOutOfMemoryError(env, "");
     return;
+  }
   memcpy (baseAddr, (in + off), len);
   ((*env)->ReleasePrimitiveArrayCritical (env, buf, in, JNI_ABORT));
   return;
@@ -176,8 +164,6 @@
                                          jbyteArray buf, int off, int len,
                                          jlong handle)
 {
-  PORT_ACCESS_FROM_ENV (env);
-
   jbyte *out;
   JCLZipStream *stream = (JCLZipStream *) ((IDATA) handle);
   jint err = 0;
@@ -192,9 +178,10 @@
   sin = stream->stream->total_in;
   sout = stream->stream->total_out;
   out = ((*env)->GetPrimitiveArrayCritical (env, buf, 0));
-
-  if (out == NULL)
+  if (out == NULL) {
+    throwNewOutOfMemoryError(env, "");
     return -1;
+  }
   stream->stream->next_out = (Bytef *) out + off;
   err = inflate (stream->stream, Z_SYNC_FLUSH);
   ((*env)->ReleasePrimitiveArrayCritical (env, buf, out, 0));
@@ -217,7 +204,7 @@
         }
       else
         {
-          throwNewDataFormatException (env, "");
+          THROW_ZIP_EXCEPTION(env, err, DataFormatException);
           return -1;
         }
     }
@@ -280,7 +267,7 @@
   if (err != Z_OK)
     {
       jclmem_free_memory (env, dBytes);
-      throwNewIllegalArgumentException (env, "");
+      THROW_ZIP_EXCEPTION(env, err, IllegalArgumentException);
       return;
     }
   stream->dict = dBytes;
@@ -297,11 +284,19 @@
   err = inflateReset (stream->stream);
   if (err != Z_OK)
     {
-      throwNewIllegalArgumentException (env, "");
+      THROW_ZIP_EXCEPTION(env, err, IllegalArgumentException);
       return;
     }
 }
 
+/**
+  * Throw java.util.zip.DataFormatException
+  */
+void
+throwNewDataFormatException (JNIEnv * env, const char *message)
+{
+  jniThrowException(env, "java/util/zip/DataFormatException", message);
+}
 
 JNIEXPORT jlong JNICALL
 Java_java_util_zip_Inflater_getTotalOutImpl (JNIEnv * env, jobject recv,
@@ -311,6 +306,7 @@
 
   stream = (JCLZipStream *) ((IDATA) handle);
   return stream->stream->total_out;
+
 }
 
 JNIEXPORT jlong JNICALL
diff --git a/libcore/archive/src/main/native/sieb.c b/libcore/archive/src/main/native/sieb.c
index ab9430b..6881cf6 100644
--- a/libcore/archive/src/main/native/sieb.c
+++ b/libcore/archive/src/main/native/sieb.c
@@ -10,20 +10,6 @@
     jniThrowException(env, "java/lang/OutOfMemoryError", message);
 }
 
-// Throw java.lang.IllegalStateException
-void throwNewIllegalStateException (JNIEnv * env, const char *message)
-{
-  jniThrowException(env, "java/lang/IllegalStateException", message);
-}
-
-// Throw java.lang.IllegalArgumentException
-void throwNewIllegalArgumentException (JNIEnv * env, const char *message)
-{
-  jniThrowException(env, "java/lang/IllegalArgumentException", message);
-}
-
-
-
 void * sieb_malloc (JNIEnv * env, size_t byteCnt) {
     void * adr = malloc(byteCnt);
     if (adr == 0) {
diff --git a/libcore/archive/src/main/native/sieb.h b/libcore/archive/src/main/native/sieb.h
index 536c806..541ad90 100644
--- a/libcore/archive/src/main/native/sieb.h
+++ b/libcore/archive/src/main/native/sieb.h
@@ -7,9 +7,8 @@
 
 
 
-void throwNewOutOfMemoryError (JNIEnv * env, const char *message);
-void throwNewIllegalArgumentException (JNIEnv * env, const char *message);
-void throwNewIllegalStateException (JNIEnv * env, const char *message);
+void throwNewOutOfMemoryError (JNIEnv * env,
+                               const char *message);
 
 
 void * sieb_malloc (JNIEnv * env, size_t byteCnt);
diff --git a/libcore/archive/src/main/native/sub.mk b/libcore/archive/src/main/native/sub.mk
index 047c319..694c185 100644
--- a/libcore/archive/src/main/native/sub.mk
+++ b/libcore/archive/src/main/native/sub.mk
@@ -7,7 +7,8 @@
 	java_util_zip_CRC32.c \
 	java_util_zip_Deflater.c \
 	java_util_zip_Inflater.c \
-  zipalloc.c \
+	zip.c \
+	zipalloc.c \
 	sieb.c
 
 LOCAL_C_INCLUDES += \
diff --git a/libcore/archive/src/main/native/zip.c b/libcore/archive/src/main/native/zip.c
new file mode 100644
index 0000000..3d15d2a
--- /dev/null
+++ b/libcore/archive/src/main/native/zip.c
@@ -0,0 +1,37 @@
+/* 
+ * 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 "zip.h"
+#include "jni.h"
+
+/**
+  * Throw java.lang.IllegalStateException
+  */
+void
+throwNewIllegalStateException (JNIEnv * env, const char *message)
+{
+  jniThrowException(env, "java/lang/IllegalStateException", message);
+}
+
+/**
+  * Throw java.lang.IllegalArgumentException
+  */
+void
+throwNewIllegalArgumentException (JNIEnv * env, const char *message)
+{
+  jniThrowException(env, "java/lang/IllegalArgumentException", message);
+}
diff --git a/libcore/archive/src/main/native/zip.h b/libcore/archive/src/main/native/zip.h
new file mode 100644
index 0000000..1452073
--- /dev/null
+++ b/libcore/archive/src/main/native/zip.h
@@ -0,0 +1,70 @@
+/* 
+ * 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.
+ */
+
+#if !defined(zip_h)
+#define zip_h
+
+#ifndef HY_ZIP_API
+#include "zipsup.h"
+#else /* HY_ZIP_API */
+#include "vmizip.h"
+#endif /* HY_ZIP_API */
+
+#include "hymutex.h"
+
+typedef struct JCLZipFile
+{
+  struct JCLZipFile *last;
+  struct JCLZipFile *next;
+#ifndef HY_ZIP_API
+  HyZipFile hyZipFile;
+#else
+  VMIZipFile hyZipFile;
+#endif
+} JCLZipFile;
+
+/* Fake JCLZipFile entry. last, next must be in the same position as JCLZipFile */
+typedef struct JCLZipFileLink
+{
+  JCLZipFile *last;
+  JCLZipFile *next;
+  MUTEX mutex;
+} JCLZipFileLink;
+
+// Contents from Harmony's inflater.h was put here:
+//
+typedef struct JCLZipStream
+{
+  U_8 *inaddr;
+  int inCap;
+  U_8 *dict;
+  z_stream *stream;
+} JCLZipStream;
+
+#define THROW_ZIP_EXCEPTION(env, err, type)            \
+  if (err == Z_MEM_ERROR) {                            \
+    throwNewOutOfMemoryError(env, "");                 \
+  } else {                                             \
+    throwNew##type(env, (const char*) zError(err));    \
+  }
+
+void throwNewIllegalStateException PROTOTYPE((JNIEnv* env,
+                                              const char* message));
+void throwNewIllegalArgumentException PROTOTYPE((JNIEnv* env,
+                                                 const char* message));
+
+#endif /* zip_h */
diff --git a/libcore/archive/src/main/native/zipsup.c b/libcore/archive/src/main/native/zipsup.c
index 1bbe51f..22ea7e9 100644
--- a/libcore/archive/src/main/native/zipsup.c
+++ b/libcore/archive/src/main/native/zipsup.c
@@ -1438,7 +1438,7 @@
                   return ZIP_ERR_FILE_CORRUPT;  /* should never happen! */
                 }
               result = zip_establishCache (portLib, zipFile);
-              if (result)
+              if (!result)
                 {
                   /* (silently start operating without a cache if we couldn't make a new one) */
                 }
diff --git a/libcore/archive/src/main/native/zipsup.h b/libcore/archive/src/main/native/zipsup.h
index adc086a..67a2eda 100644
--- a/libcore/archive/src/main/native/zipsup.h
+++ b/libcore/archive/src/main/native/zipsup.h
@@ -34,23 +34,17 @@
 #include "zlib.h"
 
 
-// Contents from Harmony's inflater.h was put here:
-//
-typedef struct JCLZipStream
-{
-  U_8 *inaddr;
-  U_8 *dict;
-  z_stream *stream;
-} JCLZipStream;
-
-
 typedef struct HyZipCachePool HyZipCachePool;
 
 HyZipCachePool *
 zipsup_GetZipCachePool(HyPortLibrary * portLib);
 
 
+#if defined(HY_LOCAL_ZLIB)
+#define HY_ZIP_DLL_NAME "z"
+#else
 #define HY_ZIP_DLL_NAME "hyzlib"
+#endif
 
 #define ZIP_INTERNAL_MAX  80
 #define ZIP_CM_Reduced1  2
@@ -156,18 +150,6 @@
 
 
 
-// Contents from Harmony's zip.h were put in java_util_zip_ZipFile.c
-// and here:
-typedef struct JCLZipFile
-{
-  struct JCLZipFile *last;
-  struct JCLZipFile *next;
-  HyZipFile hyZipFile;
-} JCLZipFile;
-
-
-
-
 #include "hymutex.h"
 extern MUTEX zip_GlobalMutex;
 
diff --git a/libcore/archive/src/test/java-internal/org/apache/harmony/archive/util/UtilTest.java b/libcore/archive/src/test/java-internal/org/apache/harmony/archive/util/UtilTest.java
new file mode 100644
index 0000000..9c28dc2
--- /dev/null
+++ b/libcore/archive/src/test/java-internal/org/apache/harmony/archive/util/UtilTest.java
@@ -0,0 +1,87 @@
+/*
+ *  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.archive.util;
+
+import junit.framework.TestCase;
+
+public class UtilTest extends TestCase {
+    private static final String ASCII_ALPHABET_LC = "abcdefghijklmnopqrstuvwxyz";
+    private static final String ASCII_ALPHABET_UC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+    private static final byte[] ASCII_ALPHABET_LC_BYTES;
+    private static final byte[] ASCII_ALPHABET_UC_BYTES;
+
+    static {
+        ASCII_ALPHABET_LC_BYTES = new byte[ASCII_ALPHABET_LC.length()];
+        for (int i = 0; i < ASCII_ALPHABET_LC_BYTES.length; i++) {
+            final char c = ASCII_ALPHABET_LC.charAt(i);
+            final byte b = (byte) c;
+            assert ((char) b) == c;
+            ASCII_ALPHABET_LC_BYTES[i] = b;
+        }
+
+        ASCII_ALPHABET_UC_BYTES = new byte[ASCII_ALPHABET_UC.length()];
+        for (int i = 0; i < ASCII_ALPHABET_UC_BYTES.length; i++) {
+            final char c = ASCII_ALPHABET_UC.charAt(i);
+            final byte b = (byte) c;
+            assert ((char) b) == c;
+            ASCII_ALPHABET_UC_BYTES[i] = b;
+        }
+    }
+
+    public void testASCIIIgnoreCaseRegionMatches() {
+        final String s1 = ASCII_ALPHABET_LC;
+        final String s2 = ASCII_ALPHABET_UC;
+        for (int i = 0; i < s1.length(); i++) {
+            assertTrue(Util.ASCIIIgnoreCaseRegionMatches(s1, i, s2, i, s1
+                    .length()
+                    - i));
+        }
+    }
+
+    public void testToASCIIUpperCaseByte() {
+        for (int i = 0; i < ASCII_ALPHABET_LC_BYTES.length; i++) {
+            assertEquals(ASCII_ALPHABET_UC_BYTES[i], Util
+                    .toASCIIUpperCase(ASCII_ALPHABET_LC_BYTES[i]));
+        }
+        for (int i = 0; i < ASCII_ALPHABET_UC_BYTES.length; i++) {
+            assertEquals(ASCII_ALPHABET_UC_BYTES[i], Util
+                    .toASCIIUpperCase(ASCII_ALPHABET_UC_BYTES[i]));
+        }
+    }
+
+    public void testToASCIIUpperCaseChar() {
+        for (int i = 0; i < ASCII_ALPHABET_LC.length(); i++) {
+            assertEquals(ASCII_ALPHABET_UC.charAt(i), Util
+                    .toASCIIUpperCase(ASCII_ALPHABET_LC.charAt(i)));
+        }
+        for (int i = 0; i < ASCII_ALPHABET_UC.length(); i++) {
+            assertEquals(ASCII_ALPHABET_UC.charAt(i), Util
+                    .toASCIIUpperCase(ASCII_ALPHABET_UC.charAt(i)));
+        }
+    }
+
+    public void testEqualsIgnoreCaseByteArrayByteArray() {
+        assertTrue(Util.equalsIgnoreCase(ASCII_ALPHABET_LC_BYTES,
+                ASCII_ALPHABET_LC_BYTES));
+        assertTrue(Util.equalsIgnoreCase(ASCII_ALPHABET_LC_BYTES,
+                ASCII_ALPHABET_UC_BYTES));
+        assertTrue(Util.equalsIgnoreCase(ASCII_ALPHABET_UC_BYTES,
+                ASCII_ALPHABET_UC_BYTES));
+    }
+
+}
diff --git a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/AttributesTest.java b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/AttributesTest.java
index 0a8b037..0b3d2cf 100644
--- a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/AttributesTest.java
+++ b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/AttributesTest.java
@@ -421,6 +421,27 @@
         assertNull(attribute.get(name));
     }
 
+    /**
+     * @tests java.util.jar.Attributes.hashCode()
+     */
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "",
+            method = "hashCode",
+            args = {}
+    )
+    public void test_hashCode_consistent_with_map() {
+        MockAttributes mockAttr = new MockAttributes();
+        mockAttr.putValue("1", "one");
+        assertEquals(mockAttr.getMap().hashCode(), mockAttr.hashCode());
+    }
+
+    private static class MockAttributes extends Attributes {
+        public Map<Object, Object> getMap() {
+            return map;
+        }
+    }
+
     @TestTargetNew(
         level = TestLevel.COMPLETE,
         notes = "",
@@ -470,7 +491,7 @@
     }
 
     @TestTargetNew(
-        level = TestLevel.COMPLETE,
+        level = TestLevel.PARTIAL_COMPLETE,
         notes = "",
         method = "hashCode",
         args = {}
diff --git a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarEntryTest.java b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarEntryTest.java
index 40eff3b..90144be 100644
--- a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarEntryTest.java
+++ b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarEntryTest.java
@@ -72,6 +72,29 @@
     }
 
     /**
+     * @throws IOException
+     * @tests java.util.jar.JarEntry#JarEntry(java.util.jar.JarEntry)
+     */
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "",
+            method = "JarEntry",
+            args = {java.util.jar.JarEntry.class}
+    )
+    public void test_ConstructorLjava_util_jar_JarEntry_on_null() throws IOException {
+        JarEntry newJarEntry = new JarEntry(jarFile.getJarEntry(entryName));
+        assertNotNull(newJarEntry);
+
+        jarEntry = null;
+        try {
+            newJarEntry = new JarEntry(jarEntry);
+            fail("Should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // Expected
+        }
+    }
+
+    /**
      * @tests java.util.jar.JarEntry#JarEntry(java.util.zip.ZipEntry)
      */
     @TestTargetNew(
@@ -163,10 +186,21 @@
         JarEntry jarEntry2 = jarFile.getJarEntry("Test.class");
         InputStream in = jarFile.getInputStream(jarEntry1);
         byte[] buffer = new byte[1024];
+        // BEGIN android-changed
+        // the certificates are non-null too early and in.available() fails
+        // while (in.available() > 0) {
+        //     assertNull("getCertificates() should be null until the entry is read",
+        //             jarEntry1.getCertificates());
+        //     assertNull(jarEntry2.getCertificates());
+        //     in.read(buffer);
+        // }
         while (in.read(buffer) >= 0);
         in.close();
+        // END android-changed
+        assertEquals("the file is fully read", -1, in.read());
         assertNotNull(jarEntry1.getCertificates());
         assertNotNull(jarEntry2.getCertificates());
+        in.close();
     }
 
     /**
@@ -187,8 +221,14 @@
         InputStream in = jarFile.getInputStream(jarEntry);
         byte[] buffer = new byte[1024];
         while (in.available() > 0) {
+            // BEGIN android-changed
+            // the code signers are non-null too early
+            // assertNull("getCodeSigners() should be null until the entry is read",
+            //         jarEntry.getCodeSigners());
+            // END android-changed
             in.read(buffer);
         }
+        assertEquals("the file is fully read", -1, in.read());
         CodeSigner[] codeSigners = jarEntry.getCodeSigners();
         assertEquals(2, codeSigners.length);
         List<?> certs_bob = codeSigners[0].getSignerCertPath()
@@ -240,7 +280,7 @@
     }
 
     @TestTargetNew(
-        level = TestLevel.COMPLETE,
+        level = TestLevel.PARTIAL_COMPLETE,
         notes = "",
         method = "JarEntry",
         args = {java.util.jar.JarEntry.class}
diff --git a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarFileTest.java b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarFileTest.java
index 720f78d..d2a5110 100644
--- a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarFileTest.java
+++ b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarFileTest.java
@@ -14,16 +14,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package org.apache.harmony.archive.tests.java.util.jar;
 
 
 import dalvik.annotation.AndroidOnly;
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
 import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
 
+import junit.framework.TestCase;
+
+import tests.support.Support_PlatformFile;
+import tests.support.resource.Support_Resources;
+
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
@@ -43,10 +46,6 @@
 import java.util.zip.ZipException;
 import java.util.zip.ZipFile;
 
-import junit.framework.TestCase;
-import tests.support.Support_PlatformFile;
-import tests.support.resource.Support_Resources;
-
 
 @TestTargetClass(JarFile.class)
 public class JarFileTest extends TestCase {
@@ -73,13 +72,25 @@
     private final String jarName3 = "hyts_manifest1.jar";
 
     private final String jarName4 = "hyts_signed.jar";
-    
+
     private final String jarName5 = "hyts_signed_inc.jar";
 
     private final String entryName = "foo/bar/A.class";
 
     private final String entryName3 = "coucou/FileAccess.class";
 
+    private final String integrateJar = "Integrate.jar";
+
+    private final String integrateJarEntry = "Test.class";
+
+    private final String emptyEntryJar = "EmptyEntries_signed.jar";
+
+    private final String emptyEntry1 = "subfolder/internalSubset01.js";
+
+    private final String emptyEntry2 = "svgtest.js";
+
+    private final String emptyEntry3 = "svgunit.js";
+
     private File resources;
 
     // custom security manager
@@ -102,7 +113,7 @@
      * @tests java.util.jar.JarFile#JarFile(java.io.File)
      */
     @TestTargetNew(
-        level = TestLevel.COMPLETE,
+        level = TestLevel.PARTIAL_COMPLETE,
         notes = "",
         method = "JarFile",
         args = {java.io.File.class}
@@ -300,6 +311,27 @@
     }
 
     /**
+     * Constructs JarFile object.
+     *
+     * @tests java.util.jar.JarFile#JarFile(java.io.File)
+     * @tests java.util.jar.JarFile#JarFile(java.lang.String)
+     */
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "",
+            method = "JarFile",
+            args = {java.io.File.class}
+    )
+    public void testConstructor_file() throws IOException {
+        File f = new File(resources, jarName);
+        Support_Resources.copyFile(resources, null, jarName);
+        assertTrue(new JarFile(f).getEntry(entryName).getName().equals(
+                entryName));
+        assertTrue(new JarFile(f.getPath()).getEntry(entryName).getName()
+                .equals(entryName));
+    }
+
+    /**
      * @tests java.util.jar.JarFile#entries()
      */
     @TestTargetNew(
@@ -316,11 +348,11 @@
         Support_Resources.copyFile(resources, null, jarName);
         JarFile jarFile = new JarFile(new File(resources, jarName));
         Enumeration<JarEntry> e = jarFile.entries();
-        int i = 0;
-        while (e.hasMoreElements()) {
-            i++;
+        int i;
+        for (i = 0; e.hasMoreElements(); i++) {
             e.nextElement();
         }
+        assertEquals(jarFile.size(), i);
         jarFile.close();
         assertEquals(6, i);
     }
@@ -336,24 +368,20 @@
         JarFile jarFile = new JarFile(new File(resources, jarName));
         Enumeration<JarEntry> enumeration = jarFile.entries();
         jarFile.close();
-        boolean pass = false;
         try {
             enumeration.hasMoreElements();
+            fail("hasMoreElements() did not detect a closed jar file");
         } catch (IllegalStateException e) {
-            pass = true;
         }
-        assertTrue("hasMoreElements did not detect closed jar file", pass);
         Support_Resources.copyFile(resources, null, jarName);
         jarFile = new JarFile(new File(resources, jarName));
         enumeration = jarFile.entries();
         jarFile.close();
-        pass = false;
         try {
             enumeration.nextElement();
+            fail("nextElement() did not detect closed jar file");
         } catch (IllegalStateException e) {
-            pass = true;
         }
-        assertTrue("nextElement did not detect closed jar file", pass);
     }
 
     /**
@@ -361,7 +389,7 @@
      * @tests java.util.jar.JarFile#getJarEntry(java.lang.String)
      */
     @TestTargetNew(
-        level = TestLevel.COMPLETE,
+        level = TestLevel.PARTIAL_COMPLETE,
         notes = "",
         method = "getEntry",
         args = {java.lang.String.class}
@@ -442,6 +470,92 @@
         }
     }
 
+
+    /**
+     * @tests java.util.jar.JarFile#getJarEntry(java.lang.String)
+     */
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "",
+            method = "getEntry",
+            args = {java.lang.String.class}
+    )
+    public void testGetJarEntry() throws Exception {
+        Support_Resources.copyFile(resources, null, jarName);
+        JarFile jarFile = new JarFile(new File(resources, jarName));
+        assertEquals("Error in returned entry", 311, jarFile.getEntry(
+                entryName).getSize());
+        jarFile.close();
+
+        // tests for signed jars
+        // test all signed jars in the /Testres/Internal/SignedJars directory
+        String jarDirUrl = Support_Resources
+                .getResourceURL("/../internalres/signedjars");
+        Vector<String> signedJars = new Vector<String>();
+        try {
+            InputStream is = new URL(jarDirUrl + "/jarlist.txt").openStream();
+            while (is.available() > 0) {
+                StringBuilder linebuff = new StringBuilder(80); // Typical line
+                // length
+                done: while (true) {
+                    int nextByte = is.read();
+                    switch (nextByte) {
+                        case -1:
+                            break done;
+                        case (byte) '\r':
+                            if (linebuff.length() == 0) {
+                                // ignore
+                            }
+                            break done;
+                        case (byte) '\n':
+                            if (linebuff.length() == 0) {
+                                // ignore
+                            }
+                            break done;
+                        default:
+                            linebuff.append((char) nextByte);
+                    }
+                }
+                if (linebuff.length() == 0) {
+                    break;
+                }
+                String line = linebuff.toString();
+                signedJars.add(line);
+            }
+            is.close();
+        } catch (IOException e) {
+            // no list of jars found
+        }
+
+        for (int i = 0; i < signedJars.size(); i++) {
+            String jarName = signedJars.get(i);
+            try {
+                File file = Support_Resources.getExternalLocalFile(jarDirUrl
+                        + "/" + jarName);
+                jarFile = new JarFile(file, true);
+                boolean foundCerts = false;
+                Enumeration<JarEntry> e = jarFile.entries();
+                while (e.hasMoreElements()) {
+                    JarEntry entry = e.nextElement();
+                    InputStream is = jarFile.getInputStream(entry);
+                    is.skip(100000);
+                    is.close();
+                    Certificate[] certs = entry.getCertificates();
+                    if (certs != null && certs.length > 0) {
+                        foundCerts = true;
+                        break;
+                    }
+                }
+                assertTrue(
+                        "No certificates found during signed jar test for jar \""
+                                + jarName + "\"", foundCerts);
+            } catch (IOException e) {
+                fail("Exception during signed jar test for jar \"" + jarName
+                        + "\": " + e.toString());
+            }
+        }
+    }
+
     /**
      * @tests java.util.jar.JarFile#getManifest()
      */
@@ -540,85 +654,6 @@
     }
 
     /**
-     * @throws IOException
-     * @tests java.util.jar.JarFile#getInputStream(java.util.zip.ZipEntry)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "getInputStream",
-        args = {java.util.zip.ZipEntry.class}
-    )
-    public void test_getInputStreamLjava_util_jar_JarEntry() throws IOException {
-        File localFile = null;
-        try {
-            Support_Resources.copyFile(resources, null, jarName);
-            localFile = new File(resources, jarName);
-        } catch (Exception e) {
-            fail("Failed to create local file: " + e);
-        }
-
-        byte[] b = new byte[1024];
-        try {
-            JarFile jf = new JarFile(localFile);
-            java.io.InputStream is = jf.getInputStream(jf.getEntry(entryName));
-            // BEGIN android-removed
-            // jf.close();
-            // END android-removed
-            assertTrue("Returned invalid stream", is.available() > 0);
-            int r = is.read(b, 0, 1024);
-            is.close();
-            StringBuffer sb = new StringBuffer(r);
-            for (int i = 0; i < r; i++) {
-                sb.append((char) (b[i] & 0xff));
-            }
-            String contents = sb.toString();
-            assertTrue("Incorrect stream read", contents.indexOf("bar") > 0);
-            // BEGIN android-added
-            jf.close();
-            // END android-added
-        } catch (Exception e) {
-            fail("Exception during test: " + e.toString());
-        }
-
-        try {
-            JarFile jf = new JarFile(localFile);
-            InputStream in = jf.getInputStream(new JarEntry("invalid"));
-            assertNull("Got stream for non-existent entry", in);
-        } catch (Exception e) {
-            fail("Exception during test 2: " + e);
-        }
-
-        try {
-            Support_Resources.copyFile(resources, null, jarName);
-            File signedFile = new File(resources, jarName);
-            JarFile jf = new JarFile(signedFile);
-            JarEntry jre = new JarEntry("foo/bar/A.class");
-            jf.getInputStream(jre);
-            // InputStream returned in any way, exception can be thrown in case
-            // of reading from this stream only.
-            // fail("Should throw ZipException");
-        } catch (ZipException ee) {
-            // expected
-        }
-
-        try {
-            Support_Resources.copyFile(resources, null, jarName);
-            File signedFile = new File(resources, jarName);
-            JarFile jf = new JarFile(signedFile);
-            JarEntry jre = new JarEntry("foo/bar/A.class");
-            jf.close();
-            jf.getInputStream(jre);
-            // InputStream returned in any way, exception can be thrown in case
-            // of reading from this stream only.
-            // The same for IOException
-            fail("Should throw IllegalStateException");
-        } catch (IllegalStateException ee) {
-            // expected
-        }
-    }
-
-    /**
      * @tests java.util.jar.JarFile#getInputStream(java.util.zip.ZipEntry)
      */
     @TestTargetNew(
@@ -660,7 +695,7 @@
         } catch (Exception e) {
             fail("Exception during test 4: " + e);
         }
-        
+
         try {
             JarFile jar = new JarFile(signedFile);
             JarEntry entry = new JarEntry(entryName3);
@@ -682,7 +717,7 @@
         } catch (Exception e) {
             fail("Failed to create local file 5: " + e);
         }
-        
+
         try {
             JarFile jar = new JarFile(signedFile);
             JarEntry entry = new JarEntry(entryName3);
@@ -732,7 +767,37 @@
         Enumeration<JarEntry> entries = jarFile.entries();
         while (entries.hasMoreElements()) {
             ZipEntry zipEntry = entries.nextElement();
-            jarFile.getInputStream(zipEntry);
+            jarFile.getInputStream(zipEntry).skip(Long.MAX_VALUE);
+        }
+    }
+
+    /**
+     * The jar is intact, but the entry object is modified.
+     */
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "",
+            method = "getInputStream",
+            args = {ZipEntry.class}
+    )
+    public void testJarVerificationModifiedEntry() throws IOException {
+        Support_Resources.copyFile(resources, null, integrateJar);
+        File f = new File(resources, integrateJar);
+
+        JarFile jarFile = new JarFile(f);
+        ZipEntry zipEntry = jarFile.getJarEntry(integrateJarEntry);
+        zipEntry.setSize(zipEntry.getSize() + 1);
+        jarFile.getInputStream(zipEntry).skip(Long.MAX_VALUE);
+
+        jarFile = new JarFile(f);
+        zipEntry = jarFile.getJarEntry(integrateJarEntry);
+        zipEntry.setSize(zipEntry.getSize() - 1);
+        try {
+            //jarFile.getInputStream(zipEntry).skip(Long.MAX_VALUE);
+            jarFile.getInputStream(zipEntry).read(new byte[5000], 0, 5000);
+            fail("SecurityException expected");
+        } catch (SecurityException e) {
+            // desired
         }
     }
 
@@ -781,7 +846,6 @@
         Enumeration<JarEntry> entries = jarFile.entries();
         int count = 0;
         while (entries.hasMoreElements()) {
-
             ZipEntry zipEntry = entries.nextElement();
             jarFile.getInputStream(zipEntry);
             count++;
@@ -818,7 +882,7 @@
             while (in.available() > 0) {
                 in.read(buffer);
             }
-            fail("should throw Security Exception");
+            fail("SecurityException expected");
         } catch (SecurityException e) {
             // desired
         }
@@ -827,7 +891,7 @@
     /*
      * In the Modified.jar, the main attributes of META-INF/MANIFEST.MF is
      * tampered manually. Hence the RI 5.0 JarFile.getInputStream of any
-     * JarEntry will throw security exception, but the apache harmony will not.
+     * JarEntry will throw security exception.
      */
     @TestTargetNew(
         level = TestLevel.PARTIAL_COMPLETE,
@@ -846,7 +910,7 @@
             ZipEntry zipEntry = entries.nextElement();
             try {
                 jarFile.getInputStream(zipEntry);
-                fail("should throw Security Exception");
+                fail("SecurityException expected");
             } catch (SecurityException e) {
                 // desired
             }
@@ -927,4 +991,112 @@
 
         // Can not check IOException
     }
+
+    /**
+     * @throws IOException
+     * @tests java.util.jar.JarFile#getInputStream(java.util.zip.ZipEntry)
+     */
+    @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            notes = "",
+            method = "getInputStream",
+            args = {java.util.zip.ZipEntry.class}
+    )
+    public void test_getInputStreamLjava_util_jar_JarEntry() throws IOException {
+        File localFile = null;
+        try {
+            Support_Resources.copyFile(resources, null, jarName);
+            localFile = new File(resources, jarName);
+        } catch (Exception e) {
+            fail("Failed to create local file: " + e);
+        }
+
+        byte[] b = new byte[1024];
+        try {
+            JarFile jf = new JarFile(localFile);
+            java.io.InputStream is = jf.getInputStream(jf.getEntry(entryName));
+            // BEGIN android-removed
+            // jf.close();
+            // END android-removed
+            assertTrue("Returned invalid stream", is.available() > 0);
+            int r = is.read(b, 0, 1024);
+            is.close();
+            StringBuffer sb = new StringBuffer(r);
+            for (int i = 0; i < r; i++) {
+                sb.append((char) (b[i] & 0xff));
+            }
+            String contents = sb.toString();
+            assertTrue("Incorrect stream read", contents.indexOf("bar") > 0);
+            // BEGIN android-added
+            jf.close();
+            // END android-added
+        } catch (Exception e) {
+            fail("Exception during test: " + e.toString());
+        }
+
+        try {
+            JarFile jf = new JarFile(localFile);
+            InputStream in = jf.getInputStream(new JarEntry("invalid"));
+            assertNull("Got stream for non-existent entry", in);
+        } catch (Exception e) {
+            fail("Exception during test 2: " + e);
+        }
+
+        try {
+            Support_Resources.copyFile(resources, null, jarName);
+            File signedFile = new File(resources, jarName);
+            JarFile jf = new JarFile(signedFile);
+            JarEntry jre = new JarEntry("foo/bar/A.class");
+            jf.getInputStream(jre);
+            // InputStream returned in any way, exception can be thrown in case
+            // of reading from this stream only.
+            // fail("Should throw ZipException");
+        } catch (ZipException ee) {
+            // expected
+        }
+
+        try {
+            Support_Resources.copyFile(resources, null, jarName);
+            File signedFile = new File(resources, jarName);
+            JarFile jf = new JarFile(signedFile);
+            JarEntry jre = new JarEntry("foo/bar/A.class");
+            jf.close();
+            jf.getInputStream(jre);
+            // InputStream returned in any way, exception can be thrown in case
+            // of reading from this stream only.
+            // The same for IOException
+            fail("Should throw IllegalStateException");
+        } catch (IllegalStateException ee) {
+            // expected
+        }
+    }
+
+    /**
+     * The jar is intact, but the entry object is modified.
+     */
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "Regression test for issue introduced by HAROMNY-4569. "
+                + "signed archives containing files with size 0 could not get verified",
+            method = "getInputStream",
+            args = {ZipEntry.class}
+    )
+    public void testJarVerificationEmptyEntry() throws IOException {
+        Support_Resources.copyFile(resources, null, emptyEntryJar);
+        File f = new File(resources, emptyEntryJar);
+
+        JarFile jarFile = new JarFile(f);
+
+        ZipEntry zipEntry = jarFile.getJarEntry(emptyEntry1);
+        int res = jarFile.getInputStream(zipEntry).read(new byte[100], 0, 100);
+        assertEquals("Wrong length of empty jar entry", -1, res);
+
+        zipEntry = jarFile.getJarEntry(emptyEntry2);
+        res = jarFile.getInputStream(zipEntry).read(new byte[100], 0, 100);
+        assertEquals("Wrong length of empty jar entry", -1, res);
+
+        zipEntry = jarFile.getJarEntry(emptyEntry3);
+        res = jarFile.getInputStream(zipEntry).read();
+        assertEquals("Wrong length of empty jar entry", -1, res);
+    }
 }
diff --git a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarInputStreamTest.java b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarInputStreamTest.java
index 64e0e1a..5befa77 100644
--- a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarInputStreamTest.java
+++ b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarInputStreamTest.java
@@ -154,12 +154,12 @@
         assertEquals(actual, desired);
         jis.close();
 
-//        try {
-//            jis.getNextJarEntry(); //Android implementation does not throw exception
-//            fail("IOException expected");
-//        } catch (IOException ee) {
-//            // expected
-//        }
+        try {
+            jis.getNextJarEntry();
+            fail("IOException expected");
+        } catch (IOException ee) {
+            // expected
+        }
 
         File resources = Support_Resources.createTempFolder();
         Support_Resources.copyFile(resources, null, "Broken_entry.jar");
@@ -179,11 +179,9 @@
         method = "getNextJarEntry",
         args = {}
     )
-    @KnownFailure("IOException not thrown when using getNextJarEntry() after close().")
     public void test_getNextJarEntry_Ex() throws Exception {
         final Set<String> desired = new HashSet<String>(Arrays
-                .asList(new String[] {
-                        "foo/", "foo/bar/", "foo/bar/A.class", "Blah.txt"}));
+                .asList("foo/", "foo/bar/", "foo/bar/A.class", "Blah.txt"));
         Set<String> actual = new HashSet<String>();
         InputStream is = new URL(jarName).openConnection().getInputStream();
         JarInputStream jis = new JarInputStream(is);
@@ -196,7 +194,7 @@
         jis.close();
 
         try {
-            jis.getNextJarEntry(); //Android implementation does not throw exception
+            jis.getNextJarEntry();
             fail("IOException expected");
         } catch (IOException ee) {
             // expected
@@ -276,29 +274,21 @@
     )
     public void test_JarInputStream_Modified_Manifest_MainAttributes_getNextEntry()
             throws IOException {
-        String modJarName = Support_Resources
-                .getURL("Modified_Manifest_MainAttributes.jar");
-        InputStream is = new URL(modJarName).openConnection().getInputStream();
+        String modJarName = Support_Resources.getURL("Modified_Manifest_MainAttributes.jar");
+        InputStream is = new URL(modJarName).openConnection()
+                .getInputStream();
         JarInputStream jin = new JarInputStream(is, true);
-        ZipEntry zipEntry = null;
 
-        final int indexofDSA = 2;
-        final int totalEntries = 4;
-        int count = 0;
-        while (count == 0 || zipEntry != null) {
-            count++;
-            try {
-                zipEntry = jin.getNextEntry();
-                if (count == indexofDSA + 1) {
-                    fail("Should throw Security Exception");
-                }
-            } catch (SecurityException e) {
-                if (count != indexofDSA + 1) {
-                    throw e;
-                }
-            }
+        assertEquals("META-INF/TESTROOT.SF", jin.getNextEntry().getName());
+        assertEquals("META-INF/TESTROOT.DSA", jin.getNextEntry().getName());
+        try {
+            jin.getNextEntry();
+            fail();
+        } catch (SecurityException expected) {
         }
-        assertEquals(totalEntries + 2, count);
+        assertEquals("META-INF/", jin.getNextEntry().getName());
+        assertEquals("Test.class", jin.getNextEntry().getName());
+        assertNull(jin.getNextEntry());
         jin.close();
     }
 
@@ -542,7 +532,6 @@
         method = "close",
         args = {}
     )
-    @KnownFailure("The behaviour is different from RI, but not neccessarily wrong. However a strange exception message is given anyway!")
     public void test_closeAfterException() throws Exception {
         File resources = Support_Resources.createTempFolder();
         Support_Resources.copyFile(resources, null, "Broken_entry.jar");
@@ -555,7 +544,7 @@
         } catch (ZipException ee) {
             // expected
         }
-        jis.close(); // Android throws exception here, but RI throws when getNextEntry/read/skip are called.
+        jis.close();
         try {
             jis.getNextEntry();
             fail("IOException expected");
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 e652137..acdad71 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
@@ -48,7 +48,7 @@
         method = "putNextEntry",
         args = {java.util.zip.ZipEntry.class}
     )
-    public void test_putNextEntryLjava_util_zip_ZipEntry() {
+    public void test_putNextEntryLjava_util_zip_ZipEntry() throws Exception {
         // testClass file`s actual extension is .class, since having .class
         // extension files in source dir causes
         // problems on eclipse, the extension is changed into .ser or it can be
@@ -76,35 +76,30 @@
             File outputJar = null;
             JarOutputStream jout = null;
 
-            try {
-                // open the output jarfile
-                outputJar = File.createTempFile("hyts_", ".jar");
-                jout = new JarOutputStream(new FileOutputStream(outputJar),
-                        newman);
-                jout.putNextEntry(new JarEntry(entryName));
-            } catch (Exception e) {
-                fail("Error creating JarOutputStream: " + e);
-            }
+            // open the output jarfile
+            outputJar = File.createTempFile("hyts_", ".jar");
+            jout = new JarOutputStream(new FileOutputStream(outputJar),
+                    newman);
+            jout.putNextEntry(new JarEntry(entryName));
+
             File resources = Support_Resources.createTempFolder();
-            try {
-                // read in the class file, and output it to the jar
-                Support_Resources.copyFile(resources, null, testClass);
-                URL jarURL = new URL((new File(resources, testClass)).toURL()
-                        .toString());
-                InputStream jis = jarURL.openStream();
 
-                byte[] bytes = new byte[1024];
-                int len;
-                while ((len = jis.read(bytes)) != -1) {
-                    jout.write(bytes, 0, len);
-                }
+            // read in the class file, and output it to the jar
+            Support_Resources.copyFile(resources, null, testClass);
+            URL jarURL = new URL((new File(resources, testClass)).toURL()
+                    .toString());
+            InputStream jis = jarURL.openStream();
 
-                jout.flush();
-                jout.close();
-                jis.close();
-            } catch (Exception e) {
-                fail("Error writing JAR file for testing: " + e);
+            byte[] bytes = new byte[1024];
+            int len;
+            while ((len = jis.read(bytes)) != -1) {
+                jout.write(bytes, 0, len);
             }
+
+            jout.flush();
+            jout.close();
+            jis.close();
+
             String res = null;
             // set up the VM parameters
             String[] args = new String[2];
diff --git a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/ManifestTest.java b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/ManifestTest.java
index 57e4744..42b2543 100644
--- a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/ManifestTest.java
+++ b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/jar/ManifestTest.java
@@ -14,12 +14,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package org.apache.harmony.archive.tests.java.util.jar;
 
-import dalvik.annotation.TestTargetClass;
-import dalvik.annotation.TestTargets;
+import dalvik.annotation.KnownFailure;
 import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
 
 import java.io.ByteArrayInputStream;
@@ -28,14 +27,15 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.MalformedURLException;
 import java.net.URL;
+import java.net.MalformedURLException;
 import java.util.Map;
 import java.util.jar.Attributes;
 import java.util.jar.JarFile;
 import java.util.jar.Manifest;
 
 import junit.framework.TestCase;
+
 import tests.support.resource.Support_Resources;
 
 @TestTargetClass(Manifest.class)
@@ -49,6 +49,10 @@
 
     private Manifest m2;
 
+    private final String ATT_ENTRY_NAME = "HasAttributes.txt";
+
+    private final String MANIFEST_NAME = "manifest/hyts_MANIFEST.MF";
+
     private File resources;
 
     @Override
@@ -68,6 +72,19 @@
         }
     }
 
+    private Manifest getManifest(String fileName) {
+        try {
+            Support_Resources.copyFile(resources, null, fileName);
+            JarFile jarFile = new JarFile(new File(resources, fileName));
+            Manifest m = jarFile.getManifest();
+            jarFile.close();
+            return m;
+        } catch (Exception e) {
+            fail("Exception during setup: " + e.toString());
+            return null;
+        }
+    }
+
     /**
      * @tests java.util.jar.Manifest#Manifest()
      */
@@ -87,245 +104,29 @@
     }
 
     /**
-     * @tests java.util.jar.Manifest#Manifest(java.io.InputStream)
+     * @tests java.util.jar.Manifest#Manifest(java.util.jar.Manifest)
      */
     @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "IOException checking missed.",
-        method = "Manifest",
-        args = {java.io.InputStream.class}
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "",
+            method = "Manifest",
+            args = {java.util.jar.Manifest.class}
     )
-    public void test_ConstructorLjava_io_InputStream() {
-        // Test for method java.util.jar.Manifest(java.io.InputStream)
-        /*
-         * ByteArrayOutputStream baos = new ByteArrayOutputStream();
-         * m2.write(baos); InputSteam is = new ByteArrayInputStream
-         * (baos.toByteArray()); Manifest myManifest = new Manifest (is);
-         * assertTrue("Manifests should be equal", myManifest.equals(m2));
-         */
-
-        Manifest manifest = null;
-        InputStream is = null;
-        try {
-            is = new URL(Support_Resources.getURL("manifest/hyts_MANIFEST.MF"))
-                    .openStream();
-        } catch (MalformedURLException e1) {
-            fail("Failed to create InputStream object");
-        } catch (IOException e1) {
-            fail("Failed to create InputStream object");
-        }
-        try {
-            manifest = new Manifest(is);
-        } catch (MalformedURLException e) {
-            fail("Malformed URL");
-        } catch (IOException e) {
-            fail("IOException");
-        }
-        Attributes main = manifest.getMainAttributes();
-        assertEquals("Bundle-Name not correct", "ClientSupport", main
-                .getValue("Bundle-Name"));
-        assertEquals(
-                "Bundle-Description not correct",
-
-                "Provides SessionService, AuthenticationService. Extends RegistryService.",
-                main.getValue("Bundle-Description"));
-        assertEquals("Bundle-Activator not correct",
-                "com.ibm.ive.eccomm.client.support.ClientSupportActivator",
-                main.getValue("Bundle-Activator"));
-        assertEquals(
-                "Import-Package not correct",
-
-                "com.ibm.ive.eccomm.client.services.log,com.ibm.ive.eccomm.client.services.registry,com.ibm.ive.eccomm.service.registry; specification-version=1.0.0,com.ibm.ive.eccomm.service.session; specification-version=1.0.0,com.ibm.ive.eccomm.service.framework; specification-version=1.2.0,org.osgi.framework; specification-version=1.0.0,org.osgi.service.log; specification-version=1.0.0,com.ibm.ive.eccomm.flash; specification-version=1.2.0,com.ibm.ive.eccomm.client.xml,com.ibm.ive.eccomm.client.http.common,com.ibm.ive.eccomm.client.http.client",
-                main.getValue("Import-Package"));
-        assertEquals(
-                "Import-Service not correct",
-
-                "org.osgi.service.log.LogReaderServiceorg.osgi.service.log.LogService,com.ibm.ive.eccomm.service.registry.RegistryService",
-                main.getValue("Import-Service"));
-        assertEquals(
-                "Export-Package not correct",
-
-                "com.ibm.ive.eccomm.client.services.authentication; specification-version=1.0.0,com.ibm.ive.eccomm.service.authentication; specification-version=1.0.0,com.ibm.ive.eccomm.common; specification-version=1.0.0,com.ibm.ive.eccomm.client.services.registry.store; specification-version=1.0.0",
-                main.getValue("Export-Package"));
-        assertEquals(
-                "Export-Service not correct",
-
-                "com.ibm.ive.eccomm.service.authentication.AuthenticationService,com.ibm.ive.eccomm.service.session.SessionService",
-                main.getValue("Export-Service"));
-        assertEquals("Bundle-Vendor not correct", "IBM", main
-                .getValue("Bundle-Vendor"));
-        assertEquals("Bundle-Version not correct", "1.2.0", main
-                .getValue("Bundle-Version"));
-        try {
-            is.close();
-        } catch (IOException e1) {
-            fail("Failed to close InputStream object");
-        }
-        try {
-            manifest = new Manifest(is);
-            fail("IOException expected");
-        } catch (MalformedURLException e) {
-            fail("IOException expected");
-        } catch (IOException e) {
-            // expected
-        }
-    }
-
-    /**
-     * @tests java.util.jar.Manifest#clear()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "clear",
-        args = {}
-    )
-    public void test_clear() {
-        // Test for method void java.util.jar.Manifest.clear()
-        m2.clear();
-        assertTrue("Should have no entries", m2.getEntries().isEmpty());
-        assertTrue("Should have no main attributes", m2.getMainAttributes()
-                .isEmpty());
-    }
-
-    /**
-     * @tests java.util.jar.Manifest#getAttributes(java.lang.String)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "getAttributes",
-        args = {java.lang.String.class}
-    )
-    public void test_getAttributesLjava_lang_String() {
-        // Test for method java.util.jar.Attributes
-        // java.util.jar.Manifest.getAttributes(java.lang.String)
-        assertNull("Should not exist", m2.getAttributes("Doesn't Exist"));
-        assertEquals("Should exist", "OK", m2
-                .getAttributes("HasAttributes.txt").get(
-                        new Attributes.Name("MyAttribute")));
-    }
-
-    /**
-     * @tests java.util.jar.Manifest#getEntries()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "getEntries",
-        args = {}
-    )
-    public void test_getEntries() {
-        // Test for method java.util.Map java.util.jar.Manifest.getEntries()
-        Map<String, Attributes> myMap = m2.getEntries();
-        assertNull("Shouldn't exist", myMap.get("Doesn't exist"));
-        assertEquals("Should exist", "OK", myMap.get("HasAttributes.txt").get(
-                new Attributes.Name("MyAttribute")));
-
-    }
-
-    /**
-     * @tests java.util.jar.Manifest#getMainAttributes()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "getMainAttributes",
-        args = {}
-    )
-    public void test_getMainAttributes() {
-        // Test for method java.util.jar.Attributes
-        // java.util.jar.Manifest.getMainAttributes()
-        Attributes a = m.getMainAttributes();
-        assertEquals("Manifest_Version should return 1.0", "1.0", a
-                .get(Attributes.Name.MANIFEST_VERSION));
-    }
-
-    /**
-     * @tests {@link java.util.jar.Manifest#read(java.io.InputStream)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "read",
-        args = {java.io.InputStream.class}
-    )
-    public void test_readLjava_io_InputStream() {
-        // Regression for HARMONY-89
-        InputStream is = new InputStreamImpl();
-        try {
-            new Manifest().read(is);
-            fail("Assert 0: Should have thrown IOException");
-        } catch (IOException e) {
-            // expected
-        }
-
-        Manifest manifest = new Manifest();
-        try {
-            manifest.read(new URL(Support_Resources
-                    .getURL("manifest/hyts_MANIFEST.MF")).openStream());
-        } catch (MalformedURLException e) {
-            fail("Can nor read manifest");
-        } catch (IOException e) {
-            fail("Can nor read manifest");
-        }
-        Attributes main = manifest.getMainAttributes();
-        assertEquals("Bundle-Name not correct", "ClientSupport", main
-                .getValue("Bundle-Name"));
-        assertEquals(
-                "Bundle-Description not correct",
-
-                "Provides SessionService, AuthenticationService. Extends RegistryService.",
-                main.getValue("Bundle-Description"));
-        assertEquals("Bundle-Activator not correct",
-                "com.ibm.ive.eccomm.client.support.ClientSupportActivator",
-                main.getValue("Bundle-Activator"));
-        assertEquals(
-                "Import-Package not correct",
-
-                "com.ibm.ive.eccomm.client.services.log,com.ibm.ive.eccomm.client.services.registry,com.ibm.ive.eccomm.service.registry; specification-version=1.0.0,com.ibm.ive.eccomm.service.session; specification-version=1.0.0,com.ibm.ive.eccomm.service.framework; specification-version=1.2.0,org.osgi.framework; specification-version=1.0.0,org.osgi.service.log; specification-version=1.0.0,com.ibm.ive.eccomm.flash; specification-version=1.2.0,com.ibm.ive.eccomm.client.xml,com.ibm.ive.eccomm.client.http.common,com.ibm.ive.eccomm.client.http.client",
-                main.getValue("Import-Package"));
-        assertEquals(
-                "Import-Service not correct",
-
-                "org.osgi.service.log.LogReaderServiceorg.osgi.service.log.LogService,com.ibm.ive.eccomm.service.registry.RegistryService",
-                main.getValue("Import-Service"));
-        assertEquals(
-                "Export-Package not correct",
-
-                "com.ibm.ive.eccomm.client.services.authentication; specification-version=1.0.0,com.ibm.ive.eccomm.service.authentication; specification-version=1.0.0,com.ibm.ive.eccomm.common; specification-version=1.0.0,com.ibm.ive.eccomm.client.services.registry.store; specification-version=1.0.0",
-                main.getValue("Export-Package"));
-        assertEquals(
-                "Export-Service not correct",
-
-                "com.ibm.ive.eccomm.service.authentication.AuthenticationService,com.ibm.ive.eccomm.service.session.SessionService",
-                main.getValue("Export-Service"));
-        assertEquals("Bundle-Vendor not correct", "IBM", main
-                .getValue("Bundle-Vendor"));
-        assertEquals("Bundle-Version not correct", "1.2.0", main
-                .getValue("Bundle-Version"));
-    }
-
-    // helper class
-    class InputStreamImpl extends InputStream {
-        public InputStreamImpl() {
-            super();
-        }
-
-        @Override
-        public int read() {
-            return 0;
-        }
+    public void testCopyingConstructor() throws IOException {
+        Manifest firstManifest = new Manifest(new URL(Support_Resources
+                .getURL(MANIFEST_NAME)).openStream());
+        Manifest secondManifest = new Manifest(firstManifest);
+        assertEquals(firstManifest, secondManifest);
     }
 
     /**
      * @tests java.util.jar.Manifest#Manifest(Manifest)
      */
     @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "Manifest",
-        args = {java.util.jar.Manifest.class}
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "",
+            method = "Manifest",
+            args = {java.util.jar.Manifest.class}
     )
     public void test_ConstructorLjava_util_jar_Manifest() {
         // Test for method java.util.jar.Manifest()
@@ -338,13 +139,101 @@
         assertEquals(emptyClone, emptyManifest.clone());
     }
 
+    private void assertAttribute(Attributes attr, String name, String value) {
+        assertEquals("Incorrect " + name, value, attr.getValue(name));
+    }
+
+    private void checkManifest(Manifest manifest) {
+        Attributes main = manifest.getMainAttributes();
+        assertAttribute(main, "Bundle-Name", "ClientSupport");
+        assertAttribute(main, "Bundle-Description",
+                "Provides SessionService, AuthenticationService. Extends RegistryService.");
+        assertAttribute(main, "Bundle-Activator",
+                "com.ibm.ive.eccomm.client.support.ClientSupportActivator");
+        assertAttribute(
+                main,
+                "Import-Package",
+                "com.ibm.ive.eccomm.client.services.log,com.ibm.ive.eccomm.client.services.registry,com.ibm.ive.eccomm.service.registry; specification-version=1.0.0,com.ibm.ive.eccomm.service.session; specification-version=1.0.0,com.ibm.ive.eccomm.service.framework; specification-version=1.2.0,org.osgi.framework; specification-version=1.0.0,org.osgi.service.log; specification-version=1.0.0,com.ibm.ive.eccomm.flash; specification-version=1.2.0,com.ibm.ive.eccomm.client.xml,com.ibm.ive.eccomm.client.http.common,com.ibm.ive.eccomm.client.http.client");
+        assertAttribute(
+                main,
+                "Import-Service",
+                "org.osgi.service.log.LogReaderServiceorg.osgi.service.log.LogService,com.ibm.ive.eccomm.service.registry.RegistryService");
+        assertAttribute(
+                main,
+                "Export-Package",
+                "com.ibm.ive.eccomm.client.services.authentication; specification-version=1.0.0,com.ibm.ive.eccomm.service.authentication; specification-version=1.0.0,com.ibm.ive.eccomm.common; specification-version=1.0.0,com.ibm.ive.eccomm.client.services.registry.store; specification-version=1.0.0");
+        assertAttribute(
+                main,
+                "Export-Service",
+                "com.ibm.ive.eccomm.service.authentication.AuthenticationService,com.ibm.ive.eccomm.service.session.SessionService");
+        assertAttribute(main, "Bundle-Vendor", "IBM");
+        assertAttribute(main, "Bundle-Version", "1.2.0");
+    }
+
+    /**
+     * @tests java.util.jar.Manifest#Manifest(java.io.InputStream)
+     */
     @TestTargetNew(
         level = TestLevel.COMPLETE,
-        notes = "",
-        method = "clone",
-        args = {}
+        notes = "IOException checking missed.",
+        method = "Manifest",
+        args = {java.io.InputStream.class}
     )
-    public void test_clone() {
+    public void test_ConstructorLjava_io_InputStream() throws IOException {
+        Manifest m = getManifest(attJarName);
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        m.write(baos);
+        InputStream is = new ByteArrayInputStream(baos.toByteArray());
+        Manifest mCopy = new Manifest(is);
+        assertEquals(m, mCopy);
+
+        Manifest manifest = new Manifest(new URL(Support_Resources
+                .getURL(MANIFEST_NAME)).openStream());
+        checkManifest(manifest);
+
+        // regression test for HARMONY-5424
+        String manifestContent = "Manifest-Version: 1.0\nCreated-By: Apache\nPackage: \nBuild-Jdk: 1.4.1_01\n\n"
+                + "Name: \nSpecification-Title: foo\nSpecification-Version: 1.0\nSpecification-Vendor: \n"
+                + "Implementation-Title: \nImplementation-Version: 1.0\nImplementation-Vendor: \n\n";
+        ByteArrayInputStream bis = new ByteArrayInputStream(manifestContent
+                .getBytes("ISO-8859-1"));
+
+
+        Manifest mf = new Manifest(bis);
+        assertEquals("Should be 4 main attributes", 4, mf.getMainAttributes()
+                .size());
+
+        Map<String, Attributes> entries = mf.getEntries();
+        assertEquals("Should be one named entry", 1, entries.size());
+
+        Attributes namedEntryAttributes = (Attributes) (entries.get(""));
+        assertEquals("Should be 6 named entry attributes", 6,
+                namedEntryAttributes.size());
+    }
+
+    /**
+     * @tests java.util.jar.Manifest#clear()
+     */
+    @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            notes = "",
+            method = "clear",
+            args = {}
+    )
+    public void test_clear() {
+        m2.clear();
+        assertTrue("Should have no entries", m2.getEntries().isEmpty());
+        assertTrue("Should have no main attributes", m2.getMainAttributes()
+                .isEmpty());
+    }
+
+    @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            notes = "",
+            method = "clone",
+            args = {}
+    )
+    public void test_clone() throws IOException {
         Manifest emptyManifest = new Manifest();
         Manifest emptyClone = (Manifest) emptyManifest.clone();
         assertTrue("Should have no entries", emptyClone.getEntries().isEmpty());
@@ -354,88 +243,25 @@
         assertEquals(emptyManifest.clone().getClass().getName(),
                 "java.util.jar.Manifest");
 
-        Manifest manifest = null;
-        try {
-            manifest = new Manifest(new URL(Support_Resources
-                    .getURL("manifest/hyts_MANIFEST.MF")).openStream());
-        } catch (MalformedURLException e) {
-            fail("Malformed URL");
-        } catch (IOException e) {
-            fail("IOException");
-        }
+        Manifest manifest = new Manifest(new URL(Support_Resources
+                .getURL("manifest/hyts_MANIFEST.MF")).openStream());
         Manifest manifestClone = (Manifest) manifest.clone();
-        Attributes main = manifestClone.getMainAttributes();
-        assertEquals("Bundle-Name not correct", "ClientSupport", main
-                .getValue("Bundle-Name"));
-        assertEquals(
-                "Bundle-Description not correct",
-
-                "Provides SessionService, AuthenticationService. Extends RegistryService.",
-                main.getValue("Bundle-Description"));
-        assertEquals("Bundle-Activator not correct",
-                "com.ibm.ive.eccomm.client.support.ClientSupportActivator",
-                main.getValue("Bundle-Activator"));
-        assertEquals(
-                "Import-Package not correct",
-
-                "com.ibm.ive.eccomm.client.services.log,com.ibm.ive.eccomm.client.services.registry,com.ibm.ive.eccomm.service.registry; specification-version=1.0.0,com.ibm.ive.eccomm.service.session; specification-version=1.0.0,com.ibm.ive.eccomm.service.framework; specification-version=1.2.0,org.osgi.framework; specification-version=1.0.0,org.osgi.service.log; specification-version=1.0.0,com.ibm.ive.eccomm.flash; specification-version=1.2.0,com.ibm.ive.eccomm.client.xml,com.ibm.ive.eccomm.client.http.common,com.ibm.ive.eccomm.client.http.client",
-                main.getValue("Import-Package"));
-        assertEquals(
-                "Import-Service not correct",
-
-                "org.osgi.service.log.LogReaderServiceorg.osgi.service.log.LogService,com.ibm.ive.eccomm.service.registry.RegistryService",
-                main.getValue("Import-Service"));
-        assertEquals(
-                "Export-Package not correct",
-
-                "com.ibm.ive.eccomm.client.services.authentication; specification-version=1.0.0,com.ibm.ive.eccomm.service.authentication; specification-version=1.0.0,com.ibm.ive.eccomm.common; specification-version=1.0.0,com.ibm.ive.eccomm.client.services.registry.store; specification-version=1.0.0",
-                main.getValue("Export-Package"));
-        assertEquals(
-                "Export-Service not correct",
-
-                "com.ibm.ive.eccomm.service.authentication.AuthenticationService,com.ibm.ive.eccomm.service.session.SessionService",
-                main.getValue("Export-Service"));
-        assertEquals("Bundle-Vendor not correct", "IBM", main
-                .getValue("Bundle-Vendor"));
-        assertEquals("Bundle-Version not correct", "1.2.0", main
-                .getValue("Bundle-Version"));
+        manifestClone.getMainAttributes();
+        checkManifest(manifestClone);
     }
 
     @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "equals",
-        args = {java.lang.Object.class}
+            level = TestLevel.COMPLETE,
+            notes = "",
+            method = "equals",
+            args = {java.lang.Object.class}
     )
-    public void test_equals() {
-        Manifest manifest1 = null;
-        Manifest manifest2 = null;
+    public void test_equals() throws IOException {
+        Manifest manifest1 = new Manifest(new URL(Support_Resources.getURL(
+                "manifest/hyts_MANIFEST.MF")).openStream());
+        Manifest manifest2 = new Manifest(new URL(Support_Resources.getURL(
+                "manifest/hyts_MANIFEST.MF")).openStream());
         Manifest manifest3 = new Manifest();
-        InputStream is = null;
-        try {
-            is = new URL(Support_Resources.getURL("manifest/hyts_MANIFEST.MF"))
-                    .openStream();
-        } catch (MalformedURLException e1) {
-            fail("Failed to create InputStream object");
-        } catch (IOException e1) {
-            fail("Failed to create InputStream object");
-        }
-        try {
-            manifest1 = new Manifest(is);
-        } catch (MalformedURLException e) {
-            fail("Malformed URL");
-        } catch (IOException e) {
-            fail("IOException");
-        }
-
-        try {
-            manifest2 = new Manifest(new URL(Support_Resources
-                    .getURL("manifest/hyts_MANIFEST.MF")).openStream());
-        } catch (MalformedURLException e) {
-            fail("Malformed URL");
-        } catch (IOException e) {
-            fail("IOException");
-        }
 
         assertTrue(manifest1.equals(manifest1));
         assertTrue(manifest1.equals(manifest2));
@@ -444,27 +270,69 @@
     }
 
     @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "hashCode",
-        args = {}
+            level = TestLevel.COMPLETE,
+            notes = "",
+            method = "hashCode",
+            args = {}
     )
-    public void test_hashCode() {
-        Manifest manifest1 = null;
+    public void test_hashCode() throws IOException {
+        Manifest manifest1 = new Manifest(new URL(Support_Resources
+                .getURL("manifest/hyts_MANIFEST.MF")).openStream());
         Manifest manifest2 = new Manifest();
-        InputStream is = null;
-        try {
-            manifest1 = new Manifest(new URL(Support_Resources
-                    .getURL("manifest/hyts_MANIFEST.MF")).openStream());
-        } catch (MalformedURLException e) {
-            fail("Malformed URL");
-        } catch (IOException e) {
-            fail("IOException");
-        }
         assertEquals(manifest1.hashCode(), manifest1.hashCode());
         assertNotSame(manifest1.hashCode(), manifest2.hashCode());
     }
 
+	/**
+	 * @tests java.util.jar.Manifest#getAttributes(java.lang.String)
+	 */
+    @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            notes = "",
+            method = "getAttributes",
+            args = {String.class}
+    )
+	public void test_getAttributesLjava_lang_String() {
+		assertNull("Should not exist",
+				m2.getAttributes("Doesn't Exist"));
+		assertEquals("Should exist", "OK", m2.getAttributes("HasAttributes.txt").get(
+				new Attributes.Name("MyAttribute")));
+	}
+
+	/**
+	 * @tests java.util.jar.Manifest#getEntries()
+	 */
+    @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            notes = "",
+            method = "getEntries",
+            args = {}
+    )
+	public void test_getEntries() {
+		Map<String, Attributes> myMap = m2.getEntries();
+		assertNull("Shouldn't exist", myMap.get("Doesn't exist"));
+		assertEquals("Should exist",
+				"OK", myMap.get("HasAttributes.txt").get(
+						new Attributes.Name("MyAttribute")));
+	}
+
+	/**
+	 * @tests java.util.jar.Manifest#getMainAttributes()
+	 */
+    @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            notes = "",
+            method = "getMainAttributes",
+            args = {}
+    )
+	public void test_getMainAttributes() {
+		// Test for method java.util.jar.Attributes
+		// java.util.jar.Manifest.getMainAttributes()
+		Attributes a = m.getMainAttributes();
+		assertEquals("Manifest_Version should return 1.0", "1.0", a.get(
+				Attributes.Name.MANIFEST_VERSION));
+	}
+
     @TestTargetNew(
         level = TestLevel.COMPLETE,
         notes = "",
@@ -510,4 +378,219 @@
 
         assertTrue(manifest1.equals(manifest2));
     }
+
+    /**
+     * Ensures compatibility with manifests produced by gcc.
+     *
+     * @see <a
+     *      href="http://issues.apache.org/jira/browse/HARMONY-5662">HARMONY-5662</a>
+     */
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "",
+            method = "Manifest",
+            args = {InputStream.class}
+    )
+    public void testNul() throws IOException {
+        String manifestContent =
+                "Manifest-Version: 1.0\nCreated-By: nasty gcc tool\n\n\0";
+
+        byte[] bytes = manifestContent.getBytes("ISO-8859-1");
+        new Manifest(new ByteArrayInputStream(bytes)); // the last NUL is ok
+
+        bytes[bytes.length - 1] = 26;
+        new Manifest(new ByteArrayInputStream(bytes)); // the last EOF is ok
+
+        bytes[bytes.length - 1] = 'A'; // the last line ignored
+        new Manifest(new ByteArrayInputStream(bytes));
+
+        bytes[2] = 0; // NUL char in Manifest
+        try {
+            new Manifest(new ByteArrayInputStream(bytes));
+            fail("IOException expected");
+        } catch (IOException e) {
+            // desired
+        }
+    }
+
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            method = "Manifest",
+            args = {InputStream.class}
+    )
+    @KnownFailure("CharsetDecoder fails with an IllegalStateException")
+    public void testDecoding() throws IOException {
+        Manifest m = getManifest(attJarName);
+        final byte[] bVendor = new byte[] { (byte) 0xd0, (byte) 0x9C,
+                (byte) 0xd0, (byte) 0xb8, (byte) 0xd0, (byte) 0xbb,
+                (byte) 0xd0, (byte) 0xb0, (byte) 0xd1, (byte) 0x8f, ' ',
+                (byte) 0xd0, (byte) 0xb4, (byte) 0xd0, (byte) 0xbe,
+                (byte) 0xd1, (byte) 0x87, (byte) 0xd1, (byte) 0x83,
+                (byte) 0xd0, (byte) 0xbd, (byte) 0xd1, (byte) 0x8C,
+                (byte) 0xd0, (byte) 0xba, (byte) 0xd0, (byte) 0xb0, ' ',
+                (byte) 0xd0, (byte) 0x9C, (byte) 0xd0, (byte) 0xb0,
+                (byte) 0xd1, (byte) 0x88, (byte) 0xd0, (byte) 0xb0 };
+
+        final byte[] bSpec = new byte[] { (byte) 0xe1, (byte) 0x88,
+                (byte) 0xb0, (byte) 0xe1, (byte) 0x88, (byte) 0x8b,
+                (byte) 0xe1, (byte) 0x88, (byte) 0x9d, ' ', (byte) 0xe1,
+                (byte) 0x9a, (byte) 0xa0, (byte) 0xe1, (byte) 0x9a,
+                (byte) 0xb1, (byte) 0xe1, (byte) 0x9b, (byte) 0x81,
+                (byte) 0xe1, (byte) 0x9a, (byte) 0xa6, ' ', (byte) 0xd8,
+                (byte) 0xb3, (byte) 0xd9, (byte) 0x84, (byte) 0xd8,
+                (byte) 0xa7, (byte) 0xd9, (byte) 0x85, ' ', (byte) 0xd8,
+                (byte) 0xb9, (byte) 0xd8, (byte) 0xb3, (byte) 0xd9,
+                (byte) 0x84, (byte) 0xd8, (byte) 0xa7, (byte) 0xd9,
+                (byte) 0x85, (byte) 0xd8, (byte) 0xa9, ' ', (byte) 0xdc,
+                (byte) 0xab, (byte) 0xdc, (byte) 0xa0, (byte) 0xdc,
+                (byte) 0xa1, (byte) 0xdc, (byte) 0x90, ' ', (byte) 0xe0,
+                (byte) 0xa6, (byte) 0xb6, (byte) 0xe0, (byte) 0xa6,
+                (byte) 0xbe, (byte) 0xe0, (byte) 0xa6, (byte) 0xa8,
+                (byte) 0xe0, (byte) 0xa7, (byte) 0x8d, (byte) 0xe0,
+                (byte) 0xa6, (byte) 0xa4, (byte) 0xe0, (byte) 0xa6,
+                (byte) 0xbf, ' ', (byte) 0xd0, (byte) 0xa0, (byte) 0xd0,
+                (byte) 0xb5, (byte) 0xd0, (byte) 0xba, (byte) 0xd1,
+                (byte) 0x8a, (byte) 0xd0, (byte) 0xb5, (byte) 0xd0,
+                (byte) 0xbb, ' ', (byte) 0xd0, (byte) 0x9c, (byte) 0xd0,
+                (byte) 0xb8, (byte) 0xd1, (byte) 0x80, ' ', (byte) 0xe0,
+                (byte) 0xa6, (byte) 0xb6, (byte) 0xe0, (byte) 0xa6,
+                (byte) 0xbe, (byte) 0xe0, (byte) 0xa6, (byte) 0xa8,
+                (byte) 0xe0, (byte) 0xa7, (byte) 0x8d, (byte) 0xe0,
+                (byte) 0xa6, (byte) 0xa4, (byte) 0xe0, (byte) 0xa6,
+                (byte) 0xbf, ' ', (byte) 0xe0, (byte) 0xbd, (byte) 0x9e,
+                (byte) 0xe0, (byte) 0xbd, (byte) 0xb2, (byte) 0xe0,
+                (byte) 0xbc, (byte) 0x8b, (byte) 0xe0, (byte) 0xbd,
+                (byte) 0x96, (byte) 0xe0, (byte) 0xbd, (byte) 0x91,
+                (byte) 0xe0, (byte) 0xbd, (byte) 0xba, ' ', (byte) 0xd0,
+                (byte) 0x9c, (byte) 0xd0, (byte) 0xb0, (byte) 0xd1,
+                (byte) 0x88, (byte) 0xd0, (byte) 0xb0, (byte) 0xd1,
+                (byte) 0x80, ' ', (byte) 0xe1, (byte) 0x8f, (byte) 0x99,
+                (byte) 0xe1, (byte) 0x8e, (byte) 0xaf, (byte) 0xe1,
+                (byte) 0x8f, (byte) 0xb1, ' ', (byte) 0xcf, (byte) 0xa8,
+                (byte) 0xce, (byte) 0xb9, (byte) 0xcf, (byte) 0x81,
+                (byte) 0xce, (byte) 0xb7, (byte) 0xce, (byte) 0xbd,
+                (byte) 0xce, (byte) 0xb7, ' ', (byte) 0xde, (byte) 0x90,
+                (byte) 0xde, (byte) 0xaa, (byte) 0xde, (byte) 0x85,
+                (byte) 0xde, (byte) 0xa6, ' ', (byte) 0xe0, (byte) 0xbd,
+                (byte) 0x82, (byte) 0xe0, (byte) 0xbd, (byte) 0x9e,
+                (byte) 0xe0, (byte) 0xbd, (byte) 0xb2, (byte) 0xe0,
+                (byte) 0xbc, (byte) 0x8b, (byte) 0xe0, (byte) 0xbd,
+                (byte) 0x96, (byte) 0xe0, (byte) 0xbd, (byte) 0x91,
+                (byte) 0xe0, (byte) 0xbd, (byte) 0xba, ' ', (byte) 0xce,
+                (byte) 0x95, (byte) 0xce, (byte) 0xb9, (byte) 0xcf,
+                (byte) 0x81, (byte) 0xce, (byte) 0xae, (byte) 0xce,
+                (byte) 0xbd, (byte) 0xce, (byte) 0xb7, ' ', (byte) 0xd8,
+                (byte) 0xb5, (byte) 0xd9, (byte) 0x84, (byte) 0xd8,
+                (byte) 0xad, ' ', (byte) 0xe0, (byte) 0xaa, (byte) 0xb6,
+                (byte) 0xe0, (byte) 0xaa, (byte) 0xbe, (byte) 0xe0,
+                (byte) 0xaa, (byte) 0x82, (byte) 0xe0, (byte) 0xaa,
+                (byte) 0xa4, (byte) 0xe0, (byte) 0xaa, (byte) 0xbf, ' ',
+                (byte) 0xe5, (byte) 0xb9, (byte) 0xb3, (byte) 0xe5,
+                (byte) 0x92, (byte) 0x8c, ' ', (byte) 0xd7, (byte) 0xa9,
+                (byte) 0xd7, (byte) 0x9c, (byte) 0xd7, (byte) 0x95,
+                (byte) 0xd7, (byte) 0x9d, ' ', (byte) 0xd7, (byte) 0xa4,
+                (byte) 0xd7, (byte) 0xa8, (byte) 0xd7, (byte) 0x99,
+                (byte) 0xd7, (byte) 0x93, (byte) 0xd7, (byte) 0x9f, ' ',
+                (byte) 0xe5, (byte) 0x92, (byte) 0x8c, (byte) 0xe5,
+                (byte) 0xb9, (byte) 0xb3, ' ', (byte) 0xe5, (byte) 0x92,
+                (byte) 0x8c, (byte) 0xe5, (byte) 0xb9, (byte) 0xb3, ' ',
+                (byte) 0xd8, (byte) 0xaa, (byte) 0xd9, (byte) 0x89,
+                (byte) 0xd9, (byte) 0x86, (byte) 0xda, (byte) 0x86,
+                (byte) 0xd9, (byte) 0x84, (byte) 0xd9, (byte) 0x89,
+                (byte) 0xd9, (byte) 0x82, ' ', (byte) 0xe0, (byte) 0xae,
+                (byte) 0x85, (byte) 0xe0, (byte) 0xae, (byte) 0xae,
+                (byte) 0xe0, (byte) 0xaf, (byte) 0x88, (byte) 0xe0,
+                (byte) 0xae, (byte) 0xa4, (byte) 0xe0, (byte) 0xae,
+                (byte) 0xbf, ' ', (byte) 0xe0, (byte) 0xb0, (byte) 0xb6,
+                (byte) 0xe0, (byte) 0xb0, (byte) 0xbe, (byte) 0xe0,
+                (byte) 0xb0, (byte) 0x82, (byte) 0xe0, (byte) 0xb0,
+                (byte) 0xa4, (byte) 0xe0, (byte) 0xb0, (byte) 0xbf, ' ',
+                (byte) 0xe0, (byte) 0xb8, (byte) 0xaa, (byte) 0xe0,
+                (byte) 0xb8, (byte) 0xb1, (byte) 0xe0, (byte) 0xb8,
+                (byte) 0x99, (byte) 0xe0, (byte) 0xb8, (byte) 0x95,
+                (byte) 0xe0, (byte) 0xb8, (byte) 0xb4, (byte) 0xe0,
+                (byte) 0xb8, (byte) 0xa0, (byte) 0xe0, (byte) 0xb8,
+                (byte) 0xb2, (byte) 0xe0, (byte) 0xb8, (byte) 0x9e, ' ',
+                (byte) 0xe1, (byte) 0x88, (byte) 0xb0, (byte) 0xe1,
+                (byte) 0x88, (byte) 0x8b, (byte) 0xe1, (byte) 0x88,
+                (byte) 0x9d, ' ', (byte) 0xe0, (byte) 0xb7, (byte) 0x83,
+                (byte) 0xe0, (byte) 0xb7, (byte) 0x8f, (byte) 0xe0,
+                (byte) 0xb6, (byte) 0xb8, (byte) 0xe0, (byte) 0xb6,
+                (byte) 0xba, ' ', (byte) 0xe0, (byte) 0xa4, (byte) 0xb6,
+                (byte) 0xe0, (byte) 0xa4, (byte) 0xbe, (byte) 0xe0,
+                (byte) 0xa4, (byte) 0xa8, (byte) 0xe0, (byte) 0xa5,
+                (byte) 0x8d, (byte) 0xe0, (byte) 0xa4, (byte) 0xa4,
+                (byte) 0xe0, (byte) 0xa4, (byte) 0xbf, (byte) 0xe0,
+                (byte) 0xa4, (byte) 0x83, ' ', (byte) 0xe1, (byte) 0x83,
+                (byte) 0x9b, (byte) 0xe1, (byte) 0x83, (byte) 0xa8,
+                (byte) 0xe1, (byte) 0x83, (byte) 0x95, (byte) 0xe1,
+                (byte) 0x83, (byte) 0x98, (byte) 0xe1, (byte) 0x83,
+                (byte) 0x93, (byte) 0xe1, (byte) 0x83, (byte) 0x9d,
+                (byte) 0xe1, (byte) 0x83, (byte) 0x91, (byte) 0xe1,
+                (byte) 0x83, (byte) 0x90 };
+        // TODO Cannot make the following word work, encoder changes needed
+        // (byte) 0xed, (byte) 0xa0, (byte) 0x80,
+        // (byte) 0xed, (byte) 0xbc, (byte) 0xb2, (byte) 0xed,
+        // (byte) 0xa0, (byte) 0x80, (byte) 0xed, (byte) 0xbc,
+        // (byte) 0xb0, (byte) 0xed, (byte) 0xa0, (byte) 0x80,
+        // (byte) 0xed, (byte) 0xbd, (byte) 0x85, (byte) 0xed,
+        // (byte) 0xa0, (byte) 0x80, (byte) 0xed, (byte) 0xbc,
+        // (byte) 0xb0, (byte) 0xed, (byte) 0xa0, (byte) 0x80,
+        // (byte) 0xed, (byte) 0xbc, (byte) 0xb9, (byte) 0xed,
+        // (byte) 0xa0, (byte) 0x80, (byte) 0xed, (byte) 0xbc,
+        // (byte) 0xb8, (byte) 0xed, (byte) 0xa0, (byte) 0x80,
+        // (byte) 0xed, (byte) 0xbc, (byte) 0xb9, ' '
+
+        final String vendor = new String(bVendor, "UTF-8");
+        final String spec = new String(bSpec, "UTF-8");
+        m.getMainAttributes()
+                .put(Attributes.Name.IMPLEMENTATION_VENDOR, vendor);
+        m.getAttributes(ATT_ENTRY_NAME).put(
+                Attributes.Name.IMPLEMENTATION_VENDOR, vendor);
+        m.getEntries().get(ATT_ENTRY_NAME).put(
+                Attributes.Name.SPECIFICATION_TITLE, spec);
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        m.write(baos);
+        m = new Manifest(new ByteArrayInputStream(baos.toByteArray()));
+
+        assertEquals(vendor, m.getMainAttributes().get(
+                Attributes.Name.IMPLEMENTATION_VENDOR));
+        assertEquals(vendor, m.getEntries().get(ATT_ENTRY_NAME).get(
+                Attributes.Name.IMPLEMENTATION_VENDOR));
+        assertEquals(spec, m.getAttributes(ATT_ENTRY_NAME).get(
+                Attributes.Name.SPECIFICATION_TITLE));
+    }
+
+    /**
+     * @tests {@link java.util.jar.Manifest#read(java.io.InputStream)
+     */
+    @TestTargetNew(
+            level = TestLevel.PARTIAL,
+            notes = "",
+            method = "read",
+            args = {InputStream.class}
+    )
+    public void testRead() {
+        // Regression for HARMONY-89
+        InputStream is = new InputStreamImpl();
+        try {
+            new Manifest().read(is);
+            fail("IOException expected");
+        } catch (IOException e) {
+            // desired
+        }
+    }
+
+    // helper class
+    private class InputStreamImpl extends InputStream {
+        public InputStreamImpl() {
+            super();
+        }
+
+        @Override
+        public int read() {
+            return 0;
+        }
+    }
 }
diff --git a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/DeflaterOutputStreamTest.java b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/DeflaterOutputStreamTest.java
index ed7238c..738f610 100644
--- a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/DeflaterOutputStreamTest.java
+++ b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/DeflaterOutputStreamTest.java
@@ -211,21 +211,22 @@
     )
     public void test_close() throws Exception {
         File f1 = File.createTempFile("close", ".tst");
-        FileOutputStream fos = new FileOutputStream(f1);
-        DeflaterOutputStream dos = new DeflaterOutputStream(fos);
-        byte byteArray[] = {1, 3, 4, 6};
-        dos.write(byteArray);
 
-        FileInputStream fis = new FileInputStream(f1);
-        InflaterInputStream iis = new InflaterInputStream(fis);
+        InflaterInputStream iis = new InflaterInputStream(new FileInputStream(f1));
         try {
             iis.read();
             fail("EOFException Not Thrown");
         } catch (EOFException e) {
         }
 
+        FileOutputStream fos = new FileOutputStream(f1);
+        DeflaterOutputStream dos = new DeflaterOutputStream(fos);
+        byte byteArray[] = {1, 3, 4, 6};
+        dos.write(byteArray);
         dos.close();
 
+        iis = new InflaterInputStream(new FileInputStream(f1));
+
         // Test to see if the finish method wrote the bytes to the file.
         assertEquals("Incorrect Byte Returned.", 1, iis.read());
         assertEquals("Incorrect Byte Returned.", 3, iis.read());
diff --git a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/GZIPInputStreamTest.java b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/GZIPInputStreamTest.java
index 75060bd..1e8ddb4 100644
--- a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/GZIPInputStreamTest.java
+++ b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/GZIPInputStreamTest.java
@@ -25,6 +25,8 @@
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
@@ -310,7 +312,43 @@
         }
     }
 
-    @Override
+    /**
+     * Regression test for HARMONY-3703.
+     * @tests java.util.zip.GZIPInputStream#read()
+     */
+    @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            notes = "",
+            method = "read",
+            args = {byte[].class}
+    )
+    public void test_read() throws IOException {
+        GZIPInputStream gis = null;
+        int result = 0;
+        byte[] buffer = new byte[] {1,2,3,4,5,6,7,8,9,10};
+        File f = new File(resources.getAbsolutePath() + "test.gz");
+        FileOutputStream out = new FileOutputStream(f);
+        GZIPOutputStream gout = new GZIPOutputStream(out);
+
+        // write 100 bytes to the stream
+        for(int i = 0; i < 10; i++) {
+            gout.write(buffer);
+        }
+        gout.finish();
+        out.write(1);
+        out.close();
+
+        gis = new GZIPInputStream(new FileInputStream(f));
+        buffer = new byte[100];
+        gis.read(buffer);
+        result = gis.read();
+        gis.close();
+        f.delete();
+
+        assertEquals("Incorrect value returned at the end of the file", -1, result);
+    }
+
+	@Override
     protected void setUp() {
         resources = Support_Resources.createTempFolder();
     }
diff --git a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/GZIPOutputStreamTest.java b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/GZIPOutputStreamTest.java
index 9b23b56..b71ce63 100644
--- a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/GZIPOutputStreamTest.java
+++ b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/GZIPOutputStreamTest.java
@@ -201,8 +201,6 @@
             int r = 0;
             try {
                 outGZIP.write(byteArray, 0, 11);
-            } catch (ArrayIndexOutOfBoundsException e) {
-                r = 1;
             } catch (IndexOutOfBoundsException ee) {
                 r = 1;
             }
diff --git a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/InflaterInputStreamTest.java b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/InflaterInputStreamTest.java
index 2de996e..707f13b 100644
--- a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/InflaterInputStreamTest.java
+++ b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/InflaterInputStreamTest.java
@@ -32,6 +32,8 @@
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.FileOutputStream;
+import java.io.EOFException;
 import java.util.zip.DeflaterOutputStream;
 import java.util.zip.Inflater;
 import java.util.zip.InflaterInputStream;
@@ -208,6 +210,42 @@
         }
     }
 
+    public void testAvailableNonEmptySource() throws Exception {
+        // this byte[] is a deflation of these bytes: { 1, 3, 4, 6 }
+        byte[] deflated = { 72, -119, 99, 100, 102, 97, 3, 0, 0, 31, 0, 15, 0 };
+        InputStream in = new InflaterInputStream(new ByteArrayInputStream(deflated));
+        // InflaterInputStream.available() returns either 1 or 0, even though
+        // that contradicts the behavior defined in InputStream.available()
+        assertEquals(1, in.read());
+        assertEquals(1, in.available());
+        assertEquals(3, in.read());
+        assertEquals(1, in.available());
+        assertEquals(4, in.read());
+        assertEquals(1, in.available());
+        assertEquals(6, in.read());
+        assertEquals(0, in.available());
+        assertEquals(-1, in.read());
+        assertEquals(-1, in.read());
+    }
+
+    public void testAvailableSkip() throws Exception {
+        // this byte[] is a deflation of these bytes: { 1, 3, 4, 6 }
+        byte[] deflated = { 72, -119, 99, 100, 102, 97, 3, 0, 0, 31, 0, 15, 0 };
+        InputStream in = new InflaterInputStream(new ByteArrayInputStream(deflated));
+        assertEquals(1, in.available());
+        assertEquals(4, in.skip(4));
+        assertEquals(0, in.available());
+    }
+
+    public void testAvailableEmptySource() throws Exception {
+        // this byte[] is a deflation of the empty file
+        byte[] deflated = { 120, -100, 3, 0, 0, 0, 0, 1 };
+        InputStream in = new InflaterInputStream(new ByteArrayInputStream(deflated));
+        assertEquals(-1, in.read());
+        assertEquals(-1, in.read());
+        assertEquals(0, in.available());
+    }
+
     /**
      * @tests java.util.zip.InflaterInputStream#read(byte[], int, int)
      */
@@ -471,12 +509,11 @@
         InflaterInputStream iis = new InflaterInputStream(is);
 
         int available;
-        int read;
         for (int i = 0; i < 11; i++) {
-            read = iis.read();
+            iis.read();
             available = iis.available();
-            if (read == -1) {
-                assertEquals("Bytes Available Should Return 0 ", 0, available);
+            if (available == 0) {
+                assertEquals("Expected no more bytes to read", -1, iis.read());
             } else {
                 assertEquals("Bytes Available Should Return 1.", 1, available);
             }
diff --git a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/InflaterTest.java b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/InflaterTest.java
index 8b89180..cd5d538 100644
--- a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/InflaterTest.java
+++ b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/InflaterTest.java
@@ -409,6 +409,22 @@
     }
 
     /**
+     * @tests java.util.zip.Inflater#Inflater()
+     */
+    @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            notes = "",
+            method = "Inflater",
+            args = {}
+    )
+    public void test_Constructor() {
+        // test method of java.util.zip.inflater.Inflater()
+        Inflater inflate = new Inflater();
+        assertNotNull("failed to create the instance of inflater",
+                        inflate);
+    }
+
+    /**
      * @tests java.util.zip.Inflater#inflate(byte[], int, int)
      */
     @TestTargetNew(
@@ -504,27 +520,6 @@
     }
 
     /**
-     * @tests java.util.zip.Inflater#Inflater()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "Inflater",
-        args = {}
-    )
-    public void test_Constructor() {
-        // test method of java.util.zip.inflater.Inflater()
-        try {
-            Inflater inflate = new Inflater();
-            assertNotNull("failed to create the instance of inflater", inflate);
-
-        } catch (Exception e) {
-
-            assertTrue("Inflate () constructor threw an exception", true);
-        }
-    }
-
-    /**
      * @tests java.util.zip.Inflater#Inflater(boolean)
      */
     @TestTargetNew(
@@ -867,17 +862,6 @@
         byte[] b = new byte[1024];
         assertEquals(0, inflater.inflate(b));
         inflater.end();
-
-        // Regression for HARMONY-2510
-        inflater = new Inflater();
-        byte[] input = new byte[] {-1};
-        inflater.setInput(input);
-        try {
-            inflater.inflate(b);
-            fail("should throw DataFormateException");
-        } catch (DataFormatException e) {
-            // expected
-        }
     }
 
     /**
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 5530a2e..b025e11 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
@@ -18,7 +18,6 @@
 package org.apache.harmony.archive.tests.java.util.zip;
 
 import dalvik.annotation.KnownFailure;
-import dalvik.annotation.BrokenTest;
 import dalvik.annotation.TestLevel;
 import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
@@ -67,7 +66,7 @@
         public void checkPermission(Permission perm) {
             // only check if it's a FilePermission because Locale checks
             // for a PropertyPermission with action"read" to get system props.
-            if (perm instanceof FilePermission 
+            if (perm instanceof FilePermission
                     && perm.getActions().equals(forbidenPermissionAction)) {
                 throw new SecurityException();
             }
@@ -145,7 +144,7 @@
     public void test_ConstructorLjava_lang_String() throws IOException {
         String oldUserDir = System.getProperty("user.dir");
         System.setProperty("user.dir", System.getProperty("java.io.tmpdir"));
-        
+
         zfile.close(); // about to reopen the same temp file
         ZipFile zip = new ZipFile(tempFileName);
         zip.close();
@@ -260,7 +259,7 @@
         method = "entries",
         args = {}
     )
-    public void test_entries() {
+    public void test_entries() throws Exception {
         // Test for method java.util.Enumeration java.util.zip.ZipFile.entries()
         Enumeration<? extends ZipEntry> enumer = zfile.entries();
         int c = 0;
@@ -270,20 +269,16 @@
         }
         assertTrue("Incorrect number of entries returned: " + c, c == 6);
 
+        Enumeration<? extends ZipEntry> enumeration = zfile.entries();
+        zfile.close();
+        zfile = null;
+        boolean pass = false;
         try {
-            Enumeration<? extends ZipEntry> enumeration = zfile.entries();
-            zfile.close();
-            zfile = null;
-            boolean pass = false;
-            try {
-                enumeration.hasMoreElements();
-            } catch (IllegalStateException e) {
-                pass = true;
-            }
-            assertTrue("did not detect closed jar file", pass);
-        } catch (Exception e) {
-            fail("Exception during entries test: " + e.toString());
+            enumeration.hasMoreElements();
+        } catch (IllegalStateException e) {
+            pass = true;
         }
+        assertTrue("did not detect closed jar file", pass);
     }
 
     /**
@@ -454,6 +449,99 @@
     }
 
     /**
+     * @tests java.io.InputStream#reset()
+     */
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            method = "getInputStream",
+            args = {java.util.zip.ZipEntry.class}
+    )
+    @KnownFailure("ZipEntry.getInputStream().reset() fails with an IOException")
+    public void test_reset() throws IOException {
+        // read an uncompressed entry
+        ZipEntry zentry = zfile.getEntry("File1.txt");
+        InputStream is = zfile.getInputStream(zentry);
+        byte[] rbuf1 = new byte[6];
+        byte[] rbuf2 = new byte[6];
+        int r1, r2;
+        r1 = is.read(rbuf1);
+        assertEquals(rbuf1.length, r1);
+        r2 = is.read(rbuf2);
+        assertEquals(rbuf2.length, r2);
+
+        is.reset();
+        r2 = is.read(rbuf2);
+        assertEquals(rbuf2.length, r2);
+        is.close();
+
+        // read a compressed entry
+        byte[] rbuf3 = new byte[4185];
+        ZipEntry zentry2 = zfile.getEntry("File3.txt");
+        is = zfile.getInputStream(zentry2);
+        r1 = is.read(rbuf3);
+        assertEquals(4183, r1);
+        is.reset();
+
+        r1 = is.read(rbuf3);
+        assertEquals(4183, r1);
+        is.close();
+
+        is = zfile.getInputStream(zentry2);
+        r1 = is.read(rbuf3, 0, 3000);
+        assertEquals(3000, r1);
+        is.reset();
+        r1 = is.read(rbuf3, 0, 3000);
+        assertEquals(3000, r1);
+        is.close();
+    }
+
+    /**
+     * @tests java.io.InputStream#reset()
+     */
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            method = "getInputStream",
+            args = {java.util.zip.ZipEntry.class}
+    )
+    @KnownFailure("ZipEntry.getInputStream().reset() fails with an IOException")
+    public void test_reset_subtest0() throws IOException {
+        // read an uncompressed entry
+        ZipEntry zentry = zfile.getEntry("File1.txt");
+        InputStream is = zfile.getInputStream(zentry);
+        byte[] rbuf1 = new byte[12];
+        byte[] rbuf2 = new byte[12];
+        int r = is.read(rbuf1, 0, 4);
+        assertEquals(4, r);
+        is.mark(0);
+        r = is.read(rbuf1);
+        assertEquals(8, r);
+        assertEquals(-1, is.read());
+
+        is.reset();
+        r = is.read(rbuf2);
+        assertEquals(8, r);
+        assertEquals(-1, is.read());
+        is.close();
+
+        // read a compressed entry
+        byte[] rbuf3 = new byte[4185];
+        ZipEntry zentry2 = zfile.getEntry("File3.txt");
+        is = zfile.getInputStream(zentry2);
+        r = is.read(rbuf3, 0, 3000);
+        assertEquals(3000, r);
+        is.mark(0);
+        r = is.read(rbuf3);
+        assertEquals(1183, r);
+        assertEquals(-1, is.read());
+
+        is.reset();
+        r = is.read(rbuf3);
+        assertEquals(1183, r);
+        assertEquals(-1, is.read());
+        is.close();
+    }
+
+	/**
      * Sets up the fixture, for example, open a network connection. This method
      * is called before a test is executed.
      */
diff --git a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipInputStreamTest.java b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipInputStreamTest.java
index ac332fa..c5efedc 100644
--- a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipInputStreamTest.java
+++ b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipInputStreamTest.java
@@ -17,7 +17,6 @@
 
 package org.apache.harmony.archive.tests.java.util.zip;
 
-import dalvik.annotation.KnownFailure;
 import dalvik.annotation.TestLevel;
 import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
@@ -30,6 +29,7 @@
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.FilterInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.zip.ZipEntry;
@@ -174,8 +174,6 @@
         method = "close",
         args = {}
     )
-    @KnownFailure("after an exception has been thrown wile reading a "
-            + "call to close also throws an exception.")
     public void test_closeAfterException() throws Exception {
         File resources = Support_Resources.createTempFolder();
         Support_Resources.copyFile(resources, null, "Broken_manifest.jar");
@@ -281,6 +279,31 @@
         }
     }
 
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            method = "read",
+            args = {byte[].class, int.class, int.class}
+    )
+    public void testReadOneByteAtATime() throws IOException {
+        InputStream in = new FilterInputStream(Support_Resources.getStream("hyts_ZipFile.zip")) {
+            @Override
+            public int read(byte[] buffer, int offset, int count) throws IOException {
+                return super.read(buffer, offset, 1); // one byte at a time
+            }
+
+            @Override
+            public int read(byte[] buffer) throws IOException {
+                return super.read(buffer, 0, 1); // one byte at a time
+            }
+        };
+
+        zis = new ZipInputStream(in);
+        while ((zentry = zis.getNextEntry()) != null) {
+            zentry.getName();
+        }
+        zis.close();
+    }
+
     /**
      * @tests java.util.zip.ZipInputStream#skip(long)
      */
@@ -360,19 +383,19 @@
         long entrySize = entry.getSize();
         assertTrue("Entry size was < 1", entrySize > 0);
         int i = 0;
-        for (i = 0; i < entrySize; i++) {
+        while (zis1.available() > 0) {
             zis1.skip(1);
-            if (zis1.available() == 0) break;
+            i++;
         }
         if (i != entrySize) {
             fail("ZipInputStream.available or ZipInputStream.skip does not " +
                     "working properly. Only skipped " + i +
                     " bytes instead of " + entrySize);
         }
-        zis1.skip(1);
-        assertTrue(zis1.available() == 0);
+        assertEquals(0, zis1.skip(1));
+        assertEquals(0, zis1.available());
         zis1.closeEntry();
-        assertFalse(zis.available() == 0);
+        assertEquals(1, zis.available());
         zis1.close();
         try {
             zis1.available();
diff --git a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipOutputStreamTest.java b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipOutputStreamTest.java
index 9a5f63a..0398f03 100644
--- a/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipOutputStreamTest.java
+++ b/libcore/archive/src/test/java/org/apache/harmony/archive/tests/java/util/zip/ZipOutputStreamTest.java
@@ -86,7 +86,7 @@
         ZipEntry ze = new ZipEntry("testEntry");
         ze.setTime(System.currentTimeMillis());
         zos.putNextEntry(ze);
-        zos.write("Hello World".getBytes());
+        zos.write("Hello World".getBytes("UTF-8"));
         zos.closeEntry();
         assertTrue("closeEntry failed to update required fields",
                 ze.getSize() == 11 && ze.getCompressedSize() == 13);
@@ -170,11 +170,8 @@
     public void test_setCommentLjava_lang_String() {
         // There is no way to get the comment back, so no way to determine if
         // the comment is set correct
-        try {
-            zos.setComment("test setComment");
-        } catch (Exception e) {
-            fail("Trying to set comment failed");
-        }
+        zos.setComment("test setComment");
+
         try {
             zos.setComment(new String(new byte[0xFFFF + 1]));
             fail("Comment over 0xFFFF in length should throw exception");
@@ -301,6 +298,17 @@
         } catch (IndexOutOfBoundsException e) {
             // expected
         }
+        
+        // Regression for HARMONY-4405
+        try {
+            zip.write(null, 0, -2);
+            fail("Should throw IndexOutOfBoundsException");
+        } catch (IndexOutOfBoundsException e) {
+            // expected
+        }
+
+        // Close stream because ZIP is invalid
+        stream.close();
     }
 
     /**
@@ -337,6 +345,8 @@
         } catch (IOException e2) {
             // expected
         }
+        
+        zip1.close();
     }
 
     @Override
diff --git a/libcore/auth/src/main/java/javax/security/auth/AuthPermission.java b/libcore/auth/src/main/java/javax/security/auth/AuthPermission.java
index 06ea3fb..697d5c7 100644
--- a/libcore/auth/src/main/java/javax/security/auth/AuthPermission.java
+++ b/libcore/auth/src/main/java/javax/security/auth/AuthPermission.java
@@ -26,33 +26,31 @@
  * <i>target name</i> of the permission specifies which methods are allowed
  * without specifying the concrete action lists. Possible target names and
  * associated authentication permissions are:
- * 
+ *
  * <pre>
  *    doAs                      invoke Subject.doAs methods.
  *    doAsPrivileged            invoke the Subject.doAsPrivileged methods.
  *    getSubject                invoke Subject.getSubject().
  *    getSubjectFromDomainCombiner    invoke SubjectDomainCombiner.getSubject().
  *    setReadOnly               invoke Subject.setReadonly().
- *    modifyPrincipals          modify the set of principals 
+ *    modifyPrincipals          modify the set of principals
  *                              associated with a Subject.
  *    modifyPublicCredentials   modify the set of public credentials
  *                              associated with a Subject.
  *    modifyPrivateCredentials  modify the set of private credentials
  *                              associated with a Subject.
- *    refreshCredential         invoke the refresh method on a credential of a 
+ *    refreshCredential         invoke the refresh method on a credential of a
  *                              refreshable credential class.
  *    destroyCredential         invoke the destroy method on a credential of a
  *                              destroyable credential class.
  *    createLoginContext.<i>name</i>   instantiate a LoginContext with the
  *                              specified name. The wildcard name ('*')
  *                              allows to a LoginContext of any name.
- *    getLoginConfiguration     invoke the getConfiguration method of 
+ *    getLoginConfiguration     invoke the getConfiguration method of
  *                              javax.security.auth.login.Configuration.
- *    refreshLoginConfiguration Invoke the refresh method of 
+ *    refreshLoginConfiguration Invoke the refresh method of
  *                              javax.security.auth.login.Configuration.
  * </pre>
- * 
- * @since Android 1.0
  */
 public final class AuthPermission extends BasicPermission {
 
@@ -77,7 +75,7 @@
 
     /**
      * Creates an authentication permission with the specified target name.
-     * 
+     *
      * @param name
      *            the target name of this authentication permission.
      */
@@ -87,7 +85,7 @@
 
     /**
      * Creates an authentication permission with the specified target name.
-     * 
+     *
      * @param name
      *            the target name of this authentication permission.
      * @param actions
diff --git a/libcore/auth/src/main/java/javax/security/auth/DestroyFailedException.java b/libcore/auth/src/main/java/javax/security/auth/DestroyFailedException.java
index a5438a6..27d4dfd 100644
--- a/libcore/auth/src/main/java/javax/security/auth/DestroyFailedException.java
+++ b/libcore/auth/src/main/java/javax/security/auth/DestroyFailedException.java
@@ -19,8 +19,6 @@
 
 /**
  * Signals that the {@link Destroyable#destroy()} method failed.
- * 
- * @since Android 1.0
  */
 public class DestroyFailedException extends Exception {
 
@@ -35,7 +33,7 @@
 
     /**
      * Creates an exception of type {@code DestroyFailedException}.
-     * 
+     *
      * @param message
      *            A detail message that describes the reason for this exception.
      */
diff --git a/libcore/auth/src/main/java/javax/security/auth/Destroyable.java b/libcore/auth/src/main/java/javax/security/auth/Destroyable.java
index 6194db6..b4d0fa2 100644
--- a/libcore/auth/src/main/java/javax/security/auth/Destroyable.java
+++ b/libcore/auth/src/main/java/javax/security/auth/Destroyable.java
@@ -20,8 +20,6 @@
 /**
  * Allows for special treatment of sensitive information, when it comes to
  * destroying or clearing of the data.
- * 
- * @since Android 1.0
  */
 public interface Destroyable {
 
@@ -29,7 +27,7 @@
      * Erases the sensitive information. Once an object is destroyed any calls
      * to its methods will throw an {@code IllegalStateException}. If it does
      * not succeed a DestroyFailedException is thrown.
-     * 
+     *
      * @throws DestroyFailedException
      *             if the information cannot be erased.
      */
@@ -37,7 +35,7 @@
 
     /**
      * Returns {@code true} once an object has been safely destroyed.
-     * 
+     *
      * @return whether the object has been safely destroyed.
      */
     boolean isDestroyed();
diff --git a/libcore/auth/src/main/java/javax/security/auth/PrivateCredentialPermission.java b/libcore/auth/src/main/java/javax/security/auth/PrivateCredentialPermission.java
index d92ede5..35072b8 100644
--- a/libcore/auth/src/main/java/javax/security/auth/PrivateCredentialPermission.java
+++ b/libcore/auth/src/main/java/javax/security/auth/PrivateCredentialPermission.java
@@ -31,11 +31,11 @@
  * Protects private credential objects belonging to a {@code Subject}. It has
  * only one action which is "read". The target name of this permission has a
  * special syntax:
- * 
+ *
  * <pre>
  * targetName = CredentialClass {PrincipalClass &quot;PrincipalName&quot;}*
  * </pre>
- * 
+ *
  * First it states a credential class and is followed then by a list of one or
  * more principals identifying the subject.
  * <p>
@@ -43,12 +43,11 @@
  * Principal} class followed by the principal name in quotes. For example, the
  * following file may define permission to read the private credentials of a
  * principal named "Bob": "com.sun.PrivateCredential com.sun.Principal \"Bob\""
- * </p>
+ * <p>
  * The syntax also allows the use of the wildcard "*" in place of {@code
  * CredentialClass} or {@code PrincipalClass} and/or {@code PrincipalName}.
- * 
+ *
  * @see Principal
- * @since Android 1.0
  */
 public final class PrivateCredentialPermission extends Permission {
 
@@ -69,7 +68,7 @@
      * Creates a new permission for private credentials specified by the target
      * name {@code name} and an {@code action}. The action is always
      * {@code "read"}.
-     * 
+     *
      * @param name
      *            the target name of the permission.
      * @param action
@@ -197,13 +196,13 @@
      * dimension of the array corresponds to the number of principals. The
      * second dimension defines either the name of the {@code PrincipalClass}
      * [x][0] or the value of {@code PrincipalName} [x][1].
-     * 
+     * <p>
      * This corresponds to the the target name's syntax:
-     * 
+     *
      * <pre>
      * targetName = CredentialClass {PrincipalClass &quot;PrincipalName&quot;}*
      * </pre>
-     * 
+     *
      * @return the principal classes and names associated with this {@code
      *         PrivateCredentialPermission}.
      */
@@ -225,7 +224,7 @@
 
     /**
      * Returns the class name of the credential associated with this permission.
-     * 
+     *
      * @return the class name of the credential associated with this permission.
      */
     public String getCredentialClass() {
diff --git a/libcore/auth/src/main/java/javax/security/auth/Subject.java b/libcore/auth/src/main/java/javax/security/auth/Subject.java
index 5a4cceb..5bf6bba 100644
--- a/libcore/auth/src/main/java/javax/security/auth/Subject.java
+++ b/libcore/auth/src/main/java/javax/security/auth/Subject.java
@@ -51,8 +51,6 @@
  * <li>Credentials (public and private) such as certificates, keys, or
  * authentication proofs such as tickets</li>
  * </ul>
- * </p>
- * @since Android 1.0
  */
 public final class Subject implements Serializable {
 
@@ -104,7 +102,7 @@
     /**
      * The constructor for the subject, setting its public and private
      * credentials and principals according to the arguments.
-     * 
+     *
      * @param readOnly
      *            {@code true} if this {@code Subject} is read-only, thus
      *            preventing any modifications to be done.
@@ -135,7 +133,7 @@
     /**
      * Runs the code defined by {@code action} using the permissions granted to
      * the {@code Subject} itself and to the code as well.
-     * 
+     *
      * @param subject
      *            the distinguished {@code Subject}.
      * @param action
@@ -154,7 +152,7 @@
      * Run the code defined by {@code action} using the permissions granted to
      * the {@code Subject} and to the code itself, additionally providing a more
      * specific context.
-     * 
+     *
      * @param subject
      *            the distinguished {@code Subject}.
      * @param action
@@ -209,7 +207,7 @@
     /**
      * Runs the code defined by {@code action} using the permissions granted to
      * the subject and to the code itself.
-     * 
+     *
      * @param subject
      *            the distinguished {@code Subject}.
      * @param action
@@ -231,7 +229,7 @@
      * Runs the code defined by {@code action} using the permissions granted to
      * the subject and to the code itself, additionally providing a more
      * specific context.
-     * 
+     *
      * @param subject
      *            the distinguished {@code Subject}.
      * @param action
@@ -290,7 +288,7 @@
      * Checks two Subjects for equality. More specifically if the principals,
      * public and private credentials are equal, equality for two {@code
      * Subjects} is implied.
-     * 
+     *
      * @param obj
      *            the {@code Object} checked for equality with this {@code
      *            Subject}.
@@ -320,18 +318,18 @@
 
     /**
      * Returns this {@code Subject}'s {@link Principal}.
-     * 
+     *
      * @return this {@code Subject}'s {@link Principal}.
      */
     public Set<Principal> getPrincipals() {
         return principals;
     }
 
-    
+
     /**
      * Returns this {@code Subject}'s {@link Principal} which is a subclass of
      * the {@code Class} provided.
-     * 
+     *
      * @param c
      *            the {@code Class} as a criteria which the {@code Principal}
      *            returned must satisfy.
@@ -345,7 +343,7 @@
 
     /**
      * Returns the private credentials associated with this {@code Subject}.
-     * 
+     *
      * @return the private credentials associated with this {@code Subject}.
      */
     public Set<Object> getPrivateCredentials() {
@@ -355,7 +353,7 @@
     /**
      * Returns this {@code Subject}'s private credentials which are a subclass
      * of the {@code Class} provided.
-     * 
+     *
      * @param c
      *            the {@code Class} as a criteria which the private credentials
      *            returned must satisfy.
@@ -369,18 +367,18 @@
 
     /**
      * Returns the public credentials associated with this {@code Subject}.
-     * 
+     *
      * @return the public credentials associated with this {@code Subject}.
      */
     public Set<Object> getPublicCredentials() {
         return publicCredentials;
     }
 
-    
+
     /**
      * Returns this {@code Subject}'s public credentials which are a subclass of
      * the {@code Class} provided.
-     * 
+     *
      * @param c
      *            the {@code Class} as a criteria which the public credentials
      *            returned must satisfy.
@@ -394,7 +392,7 @@
 
     /**
      * Returns a hash code of this {@code Subject}.
-     * 
+     *
      * @return a hash code of this {@code Subject}.
      */
     @Override
@@ -417,7 +415,7 @@
 
     /**
      * Returns whether this {@code Subject} is read-only or not.
-     * 
+     *
      * @return whether this {@code Subject} is read-only or not.
      */
     public boolean isReadOnly() {
@@ -426,7 +424,7 @@
 
     /**
      * Returns a {@code String} representation of this {@code Subject}.
-     * 
+     *
      * @return a {@code String} representation of this {@code Subject}.
      */
     @Override
@@ -479,7 +477,7 @@
     /**
      * Returns the {@code Subject} that was last associated with the {@code
      * context} provided as argument.
-     * 
+     *
      * @param context
      *            the {@code context} that was associated with the
      *            {@code Subject}.
@@ -781,4 +779,4 @@
             }
         }
     }
-}
+}
\ No newline at end of file
diff --git a/libcore/auth/src/main/java/javax/security/auth/SubjectDomainCombiner.java b/libcore/auth/src/main/java/javax/security/auth/SubjectDomainCombiner.java
index 6a8f00b..4b91084 100644
--- a/libcore/auth/src/main/java/javax/security/auth/SubjectDomainCombiner.java
+++ b/libcore/auth/src/main/java/javax/security/auth/SubjectDomainCombiner.java
@@ -25,8 +25,6 @@
 /**
  * Merges permissions based on code source and code signers with permissions
  * granted to the specified {@link Subject}.
- * 
- * @since Android 1.0
  */
 public class SubjectDomainCombiner implements DomainCombiner {
 
@@ -39,7 +37,7 @@
 
     /**
      * Creates a domain combiner for the entity provided in {@code subject}.
-     * 
+     *
      * @param subject
      *            the entity to which this domain combiner is associated.
      */
@@ -53,7 +51,7 @@
 
     /**
      * Returns the entity to which this domain combiner is associated.
-     * 
+     *
      * @return the entity to which this domain combiner is associated.
      */
     public Subject getSubject() {
@@ -68,7 +66,7 @@
     /**
      * Merges the {@code ProtectionDomain} with the {@code Principal}s
      * associated with the subject of this {@code SubjectDomainCombiner}.
-     * 
+     *
      * @param currentDomains
      *            the {@code ProtectionDomain}s associated with the context of
      *            the current thread. The domains must be sorted according to
diff --git a/libcore/auth/src/main/java/javax/security/auth/callback/Callback.java b/libcore/auth/src/main/java/javax/security/auth/callback/Callback.java
index 6cf46b8..4854d3f 100644
--- a/libcore/auth/src/main/java/javax/security/auth/callback/Callback.java
+++ b/libcore/auth/src/main/java/javax/security/auth/callback/Callback.java
@@ -20,8 +20,6 @@
 /**
  * Defines an empty base interface for all {@code Callback}s used during
  * authentication.
- * 
- * @since Android 1.0
  */
 public interface Callback {
 }
\ No newline at end of file
diff --git a/libcore/auth/src/main/java/javax/security/auth/callback/CallbackHandler.java b/libcore/auth/src/main/java/javax/security/auth/callback/CallbackHandler.java
index 952b81a..21bf30b 100644
--- a/libcore/auth/src/main/java/javax/security/auth/callback/CallbackHandler.java
+++ b/libcore/auth/src/main/java/javax/security/auth/callback/CallbackHandler.java
@@ -27,8 +27,6 @@
  * also possible to configure a system-default {@code CallbackHandler} by
  * setting the {@code auth.login.defaultCallbackHandler} property in the
  * standard {@code security.properties} file.
- * 
- * @since Android 1.0
  */
 public interface CallbackHandler {
 
@@ -42,7 +40,7 @@
      * values. If a {@code CallbackHandler} is not able to handle a specific
      * {@code Callback}, it needs to throw an
      * {@link UnsupportedCallbackException}.
-     * 
+     *
      * @param callbacks
      *            the array of {@code Callback}s that need handling
      * @throws IOException
diff --git a/libcore/auth/src/main/java/javax/security/auth/callback/PasswordCallback.java b/libcore/auth/src/main/java/javax/security/auth/callback/PasswordCallback.java
index 00020fe..3617b75 100644
--- a/libcore/auth/src/main/java/javax/security/auth/callback/PasswordCallback.java
+++ b/libcore/auth/src/main/java/javax/security/auth/callback/PasswordCallback.java
@@ -25,8 +25,6 @@
 /**
  * Is used in conjunction with a {@link CallbackHandler} to retrieve a password
  * when needed.
- * 
- * @since Android 1.0
  */
 public class PasswordCallback implements Callback, Serializable {
 
@@ -47,7 +45,7 @@
 
     /**
      * Creates a new {@code PasswordCallback} instance.
-     * 
+     *
      * @param prompt
      *            the message that should be displayed to the user
      * @param echoOn
@@ -62,7 +60,7 @@
     /**
      * Returns the prompt that was specified when creating this {@code
      * PasswordCallback}
-     * 
+     *
      * @return the prompt
      */
     public String getPrompt() {
@@ -72,7 +70,7 @@
     /**
      * Queries whether this {@code PasswordCallback} expects user input to be
      * echoed, which is specified during the creation of the object.
-     * 
+     *
      * @return {@code true} if (and only if) user input should be echoed
      */
     public boolean isEchoOn() {
@@ -83,7 +81,7 @@
      * Sets the password. The {@link CallbackHandler} that performs the actual
      * provisioning or input of the password needs to call this method to hand
      * back the password to the security service that requested it.
-     * 
+     *
      * @param password
      *            the password. A copy of this is stored, so subsequent changes
      *            to the input array do not affect the {@code PasswordCallback}.
@@ -101,7 +99,7 @@
      * Returns the password. The security service that needs the password
      * usually calls this method once the {@link CallbackHandler} has finished
      * its work.
-     * 
+     *
      * @return the password. A copy of the internal password is created and
      *         returned, so subsequent changes to the internal password do not
      *         affect the result.
diff --git a/libcore/auth/src/main/java/javax/security/auth/callback/UnsupportedCallbackException.java b/libcore/auth/src/main/java/javax/security/auth/callback/UnsupportedCallbackException.java
index d40ff45..bee7bd3 100644
--- a/libcore/auth/src/main/java/javax/security/auth/callback/UnsupportedCallbackException.java
+++ b/libcore/auth/src/main/java/javax/security/auth/callback/UnsupportedCallbackException.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when a {@link CallbackHandler} does not support a particular {@link
  * Callback}.
- * 
- * @since Android 1.0
  */
 public class UnsupportedCallbackException extends Exception {
 
@@ -32,7 +30,7 @@
     /**
      * Creates a new exception instance and initializes it with just the
      * unsupported {@code Callback}, but no error message.
-     * 
+     *
      * @param callback
      *            the {@code Callback}
      */
@@ -44,7 +42,7 @@
     /**
      * Creates a new exception instance and initializes it with both the
      * unsupported {@code Callback} and an error message.
-     * 
+     *
      * @param callback
      *            the {@code Callback}
      * @param message
@@ -57,7 +55,7 @@
 
     /**
      * Returns the unsupported {@code Callback} that triggered this exception.
-     * 
+     *
      * @return the {@code Callback}
      */
     public Callback getCallback() {
diff --git a/libcore/auth/src/main/java/javax/security/auth/login/LoginException.java b/libcore/auth/src/main/java/javax/security/auth/login/LoginException.java
index a1d6ec0..9433c43 100644
--- a/libcore/auth/src/main/java/javax/security/auth/login/LoginException.java
+++ b/libcore/auth/src/main/java/javax/security/auth/login/LoginException.java
@@ -21,8 +21,6 @@
 
 /**
  * Base class for exceptions that are thrown when a login error occurs.
- * 
- * @since Android 1.0
  */
 public class LoginException extends GeneralSecurityException {
 
@@ -37,7 +35,7 @@
 
     /**
      * Creates a new exception instance and initializes it with a given message.
-     * 
+     *
      * @param message the error message
      */
     public LoginException(String message) {
diff --git a/libcore/auth/src/main/java/javax/security/auth/x500/X500Principal.java b/libcore/auth/src/main/java/javax/security/auth/x500/X500Principal.java
index efc57d1..19254a0 100644
--- a/libcore/auth/src/main/java/javax/security/auth/x500/X500Principal.java
+++ b/libcore/auth/src/main/java/javax/security/auth/x500/X500Principal.java
@@ -29,13 +29,11 @@
 
 /**
  * Represents an X.500 principal, which holds the distinguished name of some
- * network entity. An example of a distinguished name is {@code "O=Google,
- * OU=Android, C=US"}. The class can be instantiated from a byte representation
+ * network entity. An example of a distinguished name is {@code "O=SomeOrg,
+ * OU=SomeOrgUnit, C=US"}. The class can be instantiated from a byte representation
  * of an object identifier (OID), an ASN.1 DER-encoded version, or a simple
  * string holding the distinguished name. The representations must follow either
  * RFC 2253, RFC 1779, or RFC2459.
- * 
- * @since Android 1.0
  */
 public final class X500Principal implements Serializable, Principal {
 
@@ -65,10 +63,10 @@
     /**
      * Creates a new X500Principal from a given ASN.1 DER encoding of a
      * distinguished name.
-     * 
+     *
      * @param name
      *            the ASN.1 DER-encoded distinguished name
-     * 
+     *
      * @throws IllegalArgumentException
      *             if the ASN.1 DER-encoded distinguished name is incorrect
      */
@@ -91,11 +89,11 @@
     /**
      * Creates a new X500Principal from a given ASN.1 DER encoding of a
      * distinguished name.
-     * 
+     *
      * @param in
      *            an {@code InputStream} holding the ASN.1 DER-encoded
      *            distinguished name
-     * 
+     *
      * @throws IllegalArgumentException
      *             if the ASN.1 DER-encoded distinguished name is incorrect
      */
@@ -118,10 +116,10 @@
     /**
      * Creates a new X500Principal from a string representation of a
      * distinguished name.
-     * 
+     *
      * @param name
      *            the string representation of the distinguished name
-     * 
+     *
      * @throws IllegalArgumentException
      *             if the string representation of the distinguished name is
      *             incorrect
@@ -167,8 +165,8 @@
 
     /**
      * Returns an ASN.1 DER-encoded representation of the distinguished name
-     * contained in this X.500 principal. 
-     * 
+     * contained in this X.500 principal.
+     *
      * @return the ASN.1 DER-encoded representation
      */
     public byte[] getEncoded() {
@@ -179,9 +177,9 @@
     }
 
     /**
-     * Returns a human-readable string representation of the distinguished name 
+     * Returns a human-readable string representation of the distinguished name
      * contained in this X.500 principal.
-     * 
+     *
      * @return the string representation
      */
     public String getName() {
@@ -197,12 +195,12 @@
      * some canonicalizing operations like removing leading and trailing
      * whitespace, lower-casing the whole name, and bringing it into a
      * normalized Unicode representation.
-     * 
+     *
      * @param format
      *            the name of the format to use for the representation
-     * 
+     *
      * @return the string representation
-     * 
+     *
      * @throws IllegalArgumentException
      *             if the {@code format} argument is not one of the three
      *             mentioned above
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/AbstractExecutorService.java b/libcore/concurrent/src/main/java/java/util/concurrent/AbstractExecutorService.java
index ed4ce4f..f7ed15c 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/AbstractExecutorService.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/AbstractExecutorService.java
@@ -5,11 +5,10 @@
  */
 
 package java.util.concurrent;
-
 import java.util.*;
 
 /**
- * Provides default implementation of {@link ExecutorService}
+ * Provides default implementations of {@link ExecutorService}
  * execution methods. This class implements the <tt>submit</tt>,
  * <tt>invokeAny</tt> and <tt>invokeAll</tt> methods using the default
  * {@link FutureTask} class provided in this package.  For example,
@@ -24,6 +23,10 @@
  */
 public abstract class AbstractExecutorService implements ExecutorService {
 
+    /**
+     * @throws RejectedExecutionException {@inheritDoc}
+     * @throws NullPointerException       {@inheritDoc}
+     */
     public Future<?> submit(Runnable task) {
         if (task == null) throw new NullPointerException();
         FutureTask<Object> ftask = new FutureTask<Object>(task, null);
@@ -31,6 +34,10 @@
         return ftask;
     }
 
+    /**
+     * @throws RejectedExecutionException {@inheritDoc}
+     * @throws NullPointerException       {@inheritDoc}
+     */
     public <T> Future<T> submit(Runnable task, T result) {
         if (task == null) throw new NullPointerException();
         FutureTask<T> ftask = new FutureTask<T>(task, result);
@@ -38,6 +45,10 @@
         return ftask;
     }
 
+    /**
+     * @throws RejectedExecutionException {@inheritDoc}
+     * @throws NullPointerException       {@inheritDoc}
+     */
     public <T> Future<T> submit(Callable<T> task) {
         if (task == null) throw new NullPointerException();
         FutureTask<T> ftask = new FutureTask<T>(task);
@@ -57,7 +68,7 @@
         if (ntasks == 0)
             throw new IllegalArgumentException();
         List<Future<T>> futures= new ArrayList<Future<T>>(ntasks);
-        ExecutorCompletionService<T> ecs = 
+        ExecutorCompletionService<T> ecs =
             new ExecutorCompletionService<T>(this);
 
         // For efficiency, especially in executors with limited
@@ -79,14 +90,14 @@
             int active = 1;
 
             for (;;) {
-                Future<T> f = ecs.poll(); 
+                Future<T> f = ecs.poll();
                 if (f == null) {
                     if (ntasks > 0) {
                         --ntasks;
                         futures.add(ecs.submit(it.next()));
                         ++active;
                     }
-                    else if (active == 0) 
+                    else if (active == 0)
                         break;
                     else if (timed) {
                         f = ecs.poll(nanos, TimeUnit.NANOSECONDS);
@@ -96,29 +107,29 @@
                         nanos -= now - lastTime;
                         lastTime = now;
                     }
-                    else 
+                    else
                         f = ecs.take();
                 }
                 if (f != null) {
                     --active;
                     try {
                         return f.get();
-                    } catch(InterruptedException ie) {
+                    } catch (InterruptedException ie) {
                         throw ie;
-                    } catch(ExecutionException eex) {
+                    } catch (ExecutionException eex) {
                         ee = eex;
-                    } catch(RuntimeException rex) {
+                    } catch (RuntimeException rex) {
                         ee = new ExecutionException(rex);
                     }
                 }
-            }    
+            }
 
             if (ee == null)
                 ee = new ExecutionException();
             throw ee;
 
         } finally {
-            for (Future<T> f : futures) 
+            for (Future<T> f : futures)
                 f.cancel(true);
         }
     }
@@ -133,8 +144,8 @@
         }
     }
 
-    public <T> T invokeAny(Collection<Callable<T>> tasks, 
-                           long timeout, TimeUnit unit) 
+    public <T> T invokeAny(Collection<Callable<T>> tasks,
+                           long timeout, TimeUnit unit)
         throws InterruptedException, ExecutionException, TimeoutException {
         return doInvokeAny(tasks, true, unit.toNanos(timeout));
     }
@@ -153,10 +164,10 @@
             }
             for (Future<T> f : futures) {
                 if (!f.isDone()) {
-                    try { 
-                        f.get(); 
-                    } catch(CancellationException ignore) {
-                    } catch(ExecutionException ignore) {
+                    try {
+                        f.get();
+                    } catch (CancellationException ignore) {
+                    } catch (ExecutionException ignore) {
                     }
                 }
             }
@@ -164,13 +175,13 @@
             return futures;
         } finally {
             if (!done)
-                for (Future<T> f : futures) 
+                for (Future<T> f : futures)
                     f.cancel(true);
         }
     }
 
-    public <T> List<Future<T>> invokeAll(Collection<Callable<T>> tasks, 
-                                         long timeout, TimeUnit unit) 
+    public <T> List<Future<T>> invokeAll(Collection<Callable<T>> tasks,
+                                         long timeout, TimeUnit unit)
         throws InterruptedException {
         if (tasks == null || unit == null)
             throw new NullPointerException();
@@ -178,7 +189,7 @@
         List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
         boolean done = false;
         try {
-            for (Callable<T> t : tasks) 
+            for (Callable<T> t : tasks)
                 futures.add(new FutureTask<T>(t));
 
             long lastTime = System.nanoTime();
@@ -192,18 +203,18 @@
                 nanos -= now - lastTime;
                 lastTime = now;
                 if (nanos <= 0)
-                    return futures; 
+                    return futures;
             }
 
             for (Future<T> f : futures) {
                 if (!f.isDone()) {
-                    if (nanos <= 0) 
-                        return futures; 
-                    try { 
-                        f.get(nanos, TimeUnit.NANOSECONDS); 
-                    } catch(CancellationException ignore) {
-                    } catch(ExecutionException ignore) {
-                    } catch(TimeoutException toe) {
+                    if (nanos <= 0)
+                        return futures;
+                    try {
+                        f.get(nanos, TimeUnit.NANOSECONDS);
+                    } catch (CancellationException ignore) {
+                    } catch (ExecutionException ignore) {
+                    } catch (TimeoutException toe) {
                         return futures;
                     }
                     long now = System.nanoTime();
@@ -215,7 +226,7 @@
             return futures;
         } finally {
             if (!done)
-                for (Future<T> f : futures) 
+                for (Future<T> f : futures)
                     f.cancel(true);
         }
     }
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/ArrayBlockingQueue.java b/libcore/concurrent/src/main/java/java/util/concurrent/ArrayBlockingQueue.java
index 43b9fd0..0082f07 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/ArrayBlockingQueue.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/ArrayBlockingQueue.java
@@ -24,8 +24,8 @@
  * <p>This is a classic &quot;bounded buffer&quot;, in which a
  * fixed-sized array holds elements inserted by producers and
  * extracted by consumers.  Once created, the capacity cannot be
- * increased.  Attempts to offer an element to a full queue will
- * result in the offer operation blocking; attempts to retrieve an
+ * increased.  Attempts to <tt>put</tt> an element into a full queue
+ * will result in the operation blocking; attempts to <tt>take</tt> an
  * element from an empty queue will similarly block.
  *
  * <p> This class supports an optional fairness policy for ordering
@@ -35,8 +35,9 @@
  * generally decreases throughput but reduces variability and avoids
  * starvation.
  *
- * <p>This class implements all of the <em>optional</em> methods
- * of the {@link Collection} and {@link Iterator} interfaces.
+ * <p>This class and its iterator implement all of the
+ * <em>optional</em> methods of the {@link Collection} and {@link
+ * Iterator} interfaces.
  *
  * @since 1.5
  * @author Doug Lea
@@ -56,9 +57,9 @@
     /** The queued items  */
     private final E[] items;
     /** items index for next take, poll or remove */
-    private transient int takeIndex;
+    private int takeIndex;
     /** items index for next put, offer, or add. */
-    private transient int putIndex;
+    private int putIndex;
     /** Number of items in the queue */
     private int count;
 
@@ -84,7 +85,7 @@
     }
 
     /**
-     * Insert element at current put position, advance, and signal.
+     * Inserts element at current put position, advances, and signals.
      * Call only when holding lock.
      */
     private void insert(E x) {
@@ -95,7 +96,7 @@
     }
 
     /**
-     * Extract element at current take position, advance, and signal.
+     * Extracts element at current take position, advances, and signals.
      * Call only when holding lock.
      */
     private E extract() {
@@ -139,6 +140,7 @@
     /**
      * Creates an <tt>ArrayBlockingQueue</tt> with the given (fixed)
      * capacity and default access policy.
+     *
      * @param capacity the capacity of this queue
      * @throws IllegalArgumentException if <tt>capacity</tt> is less than 1
      */
@@ -149,10 +151,11 @@
     /**
      * Creates an <tt>ArrayBlockingQueue</tt> with the given (fixed)
      * capacity and the specified access policy.
+     *
      * @param capacity the capacity of this queue
      * @param fair if <tt>true</tt> then queue accesses for threads blocked
-     * on insertion or removal, are processed in FIFO order; if <tt>false</tt>
-     * the access order is unspecified.
+     *        on insertion or removal, are processed in FIFO order;
+     *        if <tt>false</tt> the access order is unspecified.
      * @throws IllegalArgumentException if <tt>capacity</tt> is less than 1
      */
     public ArrayBlockingQueue(int capacity, boolean fair) {
@@ -169,15 +172,16 @@
      * capacity, the specified access policy and initially containing the
      * elements of the given collection,
      * added in traversal order of the collection's iterator.
+     *
      * @param capacity the capacity of this queue
      * @param fair if <tt>true</tt> then queue accesses for threads blocked
-     * on insertion or removal, are processed in FIFO order; if <tt>false</tt>
-     * the access order is unspecified.
+     *        on insertion or removal, are processed in FIFO order;
+     *        if <tt>false</tt> the access order is unspecified.
      * @param c the collection of elements to initially contain
      * @throws IllegalArgumentException if <tt>capacity</tt> is less than
-     * <tt>c.size()</tt>, or less than 1.
-     * @throws NullPointerException if <tt>c</tt> or any element within it
-     * is <tt>null</tt>
+     *         <tt>c.size()</tt>, or less than 1.
+     * @throws NullPointerException if the specified collection or any
+     *         of its elements are null
      */
     public ArrayBlockingQueue(int capacity, boolean fair,
                               Collection<? extends E> c) {
@@ -190,23 +194,38 @@
     }
 
     /**
-     * Inserts the specified element at the tail of this queue if possible,
-     * returning immediately if this queue is full.
+     * Inserts the specified element at the tail of this queue if it is
+     * possible to do so immediately without exceeding the queue's capacity,
+     * returning <tt>true</tt> upon success and throwing an
+     * <tt>IllegalStateException</tt> if this queue is full.
      *
-     * @param o the element to add.
-     * @return <tt>true</tt> if it was possible to add the element to
-     *         this queue, else <tt>false</tt>
-     * @throws NullPointerException if the specified element is <tt>null</tt>
+     * @param e the element to add
+     * @return <tt>true</tt> (as specified by {@link Collection#add})
+     * @throws IllegalStateException if this queue is full
+     * @throws NullPointerException if the specified element is null
      */
-    public boolean offer(E o) {
-        if (o == null) throw new NullPointerException();
+    public boolean add(E e) {
+        return super.add(e);
+    }
+
+    /**
+     * Inserts the specified element at the tail of this queue if it is
+     * possible to do so immediately without exceeding the queue's capacity,
+     * returning <tt>true</tt> upon success and <tt>false</tt> if this queue
+     * is full.  This method is generally preferable to method {@link #add},
+     * which can fail to insert an element only by throwing an exception.
+     *
+     * @throws NullPointerException if the specified element is null
+     */
+    public boolean offer(E e) {
+        if (e == null) throw new NullPointerException();
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             if (count == items.length)
                 return false;
             else {
-                insert(o);
+                insert(e);
                 return true;
             }
         } finally {
@@ -215,29 +234,50 @@
     }
 
     /**
-     * Inserts the specified element at the tail of this queue, waiting if
-     * necessary up to the specified wait time for space to become available.
-     * @param o the element to add
-     * @param timeout how long to wait before giving up, in units of
-     * <tt>unit</tt>
-     * @param unit a <tt>TimeUnit</tt> determining how to interpret the
-     * <tt>timeout</tt> parameter
-     * @return <tt>true</tt> if successful, or <tt>false</tt> if
-     * the specified waiting time elapses before space is available.
-     * @throws InterruptedException if interrupted while waiting.
-     * @throws NullPointerException if the specified element is <tt>null</tt>.
+     * Inserts the specified element at the tail of this queue, waiting
+     * for space to become available if the queue is full.
+     *
+     * @throws InterruptedException {@inheritDoc}
+     * @throws NullPointerException {@inheritDoc}
      */
-    public boolean offer(E o, long timeout, TimeUnit unit)
-        throws InterruptedException {
-
-        if (o == null) throw new NullPointerException();
+    public void put(E e) throws InterruptedException {
+        if (e == null) throw new NullPointerException();
+        final E[] items = this.items;
         final ReentrantLock lock = this.lock;
         lock.lockInterruptibly();
         try {
-            long nanos = unit.toNanos(timeout);
+            try {
+                while (count == items.length)
+                    notFull.await();
+            } catch (InterruptedException ie) {
+                notFull.signal(); // propagate to non-interrupted thread
+                throw ie;
+            }
+            insert(e);
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Inserts the specified element at the tail of this queue, waiting
+     * up to the specified wait time for space to become available if
+     * the queue is full.
+     *
+     * @throws InterruptedException {@inheritDoc}
+     * @throws NullPointerException {@inheritDoc}
+     */
+    public boolean offer(E e, long timeout, TimeUnit unit)
+        throws InterruptedException {
+
+        if (e == null) throw new NullPointerException();
+        long nanos = unit.toNanos(timeout);
+        final ReentrantLock lock = this.lock;
+        lock.lockInterruptibly();
+        try {
             for (;;) {
                 if (count != items.length) {
-                    insert(o);
+                    insert(e);
                     return true;
                 }
                 if (nanos <= 0)
@@ -254,7 +294,6 @@
         }
     }
 
-
     public E poll() {
         final ReentrantLock lock = this.lock;
         lock.lock();
@@ -268,65 +307,6 @@
         }
     }
 
-    public E poll(long timeout, TimeUnit unit) throws InterruptedException {
-        final ReentrantLock lock = this.lock;
-        lock.lockInterruptibly();
-        try {
-            long nanos = unit.toNanos(timeout);
-            for (;;) {
-                if (count != 0) {
-                    E x = extract();
-                    return x;
-                }
-                if (nanos <= 0)
-                    return null;
-                try {
-                    nanos = notEmpty.awaitNanos(nanos);
-                } catch (InterruptedException ie) {
-                    notEmpty.signal(); // propagate to non-interrupted thread
-                    throw ie;
-                }
-
-            }
-        } finally {
-            lock.unlock();
-        }
-    }
-
-
-    public boolean remove(Object o) {
-        if (o == null) return false;
-        final E[] items = this.items;
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
-            int i = takeIndex;
-            int k = 0;
-            for (;;) {
-                if (k++ >= count)
-                    return false;
-                if (o.equals(items[i])) {
-                    removeAt(i);
-                    return true;
-                }
-                i = inc(i);
-            }
-
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    public E peek() {
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
-            return (count == 0) ? null : items[takeIndex];
-        } finally {
-            lock.unlock();
-        }
-    }
-
     public E take() throws InterruptedException {
         final ReentrantLock lock = this.lock;
         lock.lockInterruptibly();
@@ -345,27 +325,36 @@
         }
     }
 
-    /**
-     * Adds the specified element to the tail of this queue, waiting if
-     * necessary for space to become available.
-     * @param o the element to add
-     * @throws InterruptedException if interrupted while waiting.
-     * @throws NullPointerException if the specified element is <tt>null</tt>.
-     */
-    public void put(E o) throws InterruptedException {
-        if (o == null) throw new NullPointerException();
-        final E[] items = this.items;
+    public E poll(long timeout, TimeUnit unit) throws InterruptedException {
+        long nanos = unit.toNanos(timeout);
         final ReentrantLock lock = this.lock;
         lock.lockInterruptibly();
         try {
-            try {
-                while (count == items.length)
-                    notFull.await();
-            } catch (InterruptedException ie) {
-                notFull.signal(); // propagate to non-interrupted thread
-                throw ie;
+            for (;;) {
+                if (count != 0) {
+                    E x = extract();
+                    return x;
+                }
+                if (nanos <= 0)
+                    return null;
+                try {
+                    nanos = notEmpty.awaitNanos(nanos);
+                } catch (InterruptedException ie) {
+                    notEmpty.signal(); // propagate to non-interrupted thread
+                    throw ie;
+                }
+
             }
-            insert(o);
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    public E peek() {
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            return (count == 0) ? null : items[takeIndex];
         } finally {
             lock.unlock();
         }
@@ -376,7 +365,7 @@
     /**
      * Returns the number of elements in this queue.
      *
-     * @return  the number of elements in this queue.
+     * @return the number of elements in this queue
      */
     public int size() {
         final ReentrantLock lock = this.lock;
@@ -391,17 +380,15 @@
     // this doc comment is a modified copy of the inherited doc comment,
     // without the reference to unlimited queues.
     /**
-     * Returns the number of elements that this queue can ideally (in
-     * the absence of memory or resource constraints) accept without
+     * Returns the number of additional elements that this queue can ideally
+     * (in the absence of memory or resource constraints) accept without
      * blocking. This is always equal to the initial capacity of this queue
      * less the current <tt>size</tt> of this queue.
-     * <p>Note that you <em>cannot</em> always tell if
-     * an attempt to <tt>add</tt> an element will succeed by
-     * inspecting <tt>remainingCapacity</tt> because it may be the
-     * case that a waiting consumer is ready to <tt>take</tt> an
-     * element out of an otherwise full queue.
-     * 
-     * @return the remaining capacity
+     *
+     * <p>Note that you <em>cannot</em> always tell if an attempt to insert
+     * an element will succeed by inspecting <tt>remainingCapacity</tt>
+     * because it may be the case that another thread is about to
+     * insert or remove an element.
      */
     public int remainingCapacity() {
         final ReentrantLock lock = this.lock;
@@ -413,7 +400,48 @@
         }
     }
 
+    /**
+     * Removes a single instance of the specified element from this queue,
+     * if it is present.  More formally, removes an element <tt>e</tt> such
+     * that <tt>o.equals(e)</tt>, if this queue contains one or more such
+     * elements.
+     * Returns <tt>true</tt> if this queue contained the specified element
+     * (or equivalently, if this queue changed as a result of the call).
+     *
+     * @param o element to be removed from this queue, if present
+     * @return <tt>true</tt> if this queue changed as a result of the call
+     */
+    public boolean remove(Object o) {
+        if (o == null) return false;
+        final E[] items = this.items;
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            int i = takeIndex;
+            int k = 0;
+            for (;;) {
+                if (k++ >= count)
+                    return false;
+                if (o.equals(items[i])) {
+                    removeAt(i);
+                    return true;
+                }
+                i = inc(i);
+            }
 
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Returns <tt>true</tt> if this queue contains the specified element.
+     * More formally, returns <tt>true</tt> if and only if this queue contains
+     * at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>.
+     *
+     * @param o object to be checked for containment in this queue
+     * @return <tt>true</tt> if this queue contains the specified element
+     */
     public boolean contains(Object o) {
         if (o == null) return false;
         final E[] items = this.items;
@@ -433,6 +461,19 @@
         }
     }
 
+    /**
+     * Returns an array containing all of the elements in this queue, in
+     * proper sequence.
+     *
+     * <p>The returned array will be "safe" in that no references to it are
+     * maintained by this queue.  (In other words, this method must allocate
+     * a new array).  The caller is thus free to modify the returned array.
+     *
+     * <p>This method acts as bridge between array-based and collection-based
+     * APIs.
+     *
+     * @return an array containing all of the elements in this queue
+     */
     public Object[] toArray() {
         final E[] items = this.items;
         final ReentrantLock lock = this.lock;
@@ -451,6 +492,42 @@
         }
     }
 
+    /**
+     * Returns an array containing all of the elements in this queue, in
+     * proper sequence; the runtime type of the returned array is that of
+     * the specified array.  If the queue fits in the specified array, it
+     * is returned therein.  Otherwise, a new array is allocated with the
+     * runtime type of the specified array and the size of this queue.
+     *
+     * <p>If this queue fits in the specified array with room to spare
+     * (i.e., the array has more elements than this queue), the element in
+     * the array immediately following the end of the queue is set to
+     * <tt>null</tt>.
+     *
+     * <p>Like the {@link #toArray()} method, this method acts as bridge between
+     * array-based and collection-based APIs.  Further, this method allows
+     * precise control over the runtime type of the output array, and may,
+     * under certain circumstances, be used to save allocation costs.
+     *
+     * <p>Suppose <tt>x</tt> is a queue known to contain only strings.
+     * The following code can be used to dump the queue into a newly
+     * allocated array of <tt>String</tt>:
+     *
+     * <pre>
+     *     String[] y = x.toArray(new String[0]);</pre>
+     *
+     * Note that <tt>toArray(new Object[0])</tt> is identical in function to
+     * <tt>toArray()</tt>.
+     *
+     * @param a the array into which the elements of the queue are to
+     *          be stored, if it is big enough; otherwise, a new array of the
+     *          same runtime type is allocated for this purpose
+     * @return an array containing all of the elements in this queue
+     * @throws ArrayStoreException if the runtime type of the specified array
+     *         is not a supertype of the runtime type of every element in
+     *         this queue
+     * @throws NullPointerException if the specified array is null
+     */
     public <T> T[] toArray(T[] a) {
         final E[] items = this.items;
         final ReentrantLock lock = this.lock;
@@ -486,7 +563,10 @@
         }
     }
 
-
+    /**
+     * Atomically removes all of the elements from this queue.
+     * The queue will be empty after this call returns.
+     */
     public void clear() {
         final E[] items = this.items;
         final ReentrantLock lock = this.lock;
@@ -507,6 +587,12 @@
         }
     }
 
+    /**
+     * @throws UnsupportedOperationException {@inheritDoc}
+     * @throws ClassCastException            {@inheritDoc}
+     * @throws NullPointerException          {@inheritDoc}
+     * @throws IllegalArgumentException      {@inheritDoc}
+     */
     public int drainTo(Collection<? super E> c) {
         if (c == null)
             throw new NullPointerException();
@@ -537,7 +623,12 @@
         }
     }
 
-
+    /**
+     * @throws UnsupportedOperationException {@inheritDoc}
+     * @throws ClassCastException            {@inheritDoc}
+     * @throws NullPointerException          {@inheritDoc}
+     * @throws IllegalArgumentException      {@inheritDoc}
+     */
     public int drainTo(Collection<? super E> c, int maxElements) {
         if (c == null)
             throw new NullPointerException();
@@ -574,12 +665,12 @@
     /**
      * Returns an iterator over the elements in this queue in proper sequence.
      * The returned <tt>Iterator</tt> is a "weakly consistent" iterator that
-     * will never throw {@link java.util.ConcurrentModificationException},
+     * will never throw {@link ConcurrentModificationException},
      * and guarantees to traverse elements as they existed upon
      * construction of the iterator, and may (but is not guaranteed to)
      * reflect any modifications subsequent to construction.
      *
-     * @return an iterator over the elements in this queue in proper sequence.
+     * @return an iterator over the elements in this queue in proper sequence
      */
     public Iterator<E> iterator() {
         final ReentrantLock lock = this.lock;
@@ -606,7 +697,7 @@
          * that an element exists in hasNext(), we must return it in
          * the following next() call even if it was in the process of
          * being removed when hasNext() was called.
-         **/
+         */
         private E nextItem;
 
         /**
@@ -635,7 +726,7 @@
         }
 
         /**
-         * Check whether nextIndex is valid; if so setting nextItem.
+         * Checks whether nextIndex is valid; if so setting nextItem.
          * Stops iterator when either hits putIndex or sees null item.
          */
         private void checkNext() {
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/BlockingQueue.java b/libcore/concurrent/src/main/java/java/util/concurrent/BlockingQueue.java
index ddb7d77..d01c097 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/BlockingQueue.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/BlockingQueue.java
@@ -15,9 +15,50 @@
 
 /**
  * A {@link java.util.Queue} that additionally supports operations
- * that wait for the queue to become non-empty when retrieving an element,
- * and wait for space to become available in the queue when storing an 
- * element.
+ * that wait for the queue to become non-empty when retrieving an
+ * element, and wait for space to become available in the queue when
+ * storing an element.
+ *
+ * <p><tt>BlockingQueue</tt> methods come in four forms, with different ways
+ * of handling operations that cannot be satisfied immediately, but may be
+ * satisfied at some point in the future:
+ * one throws an exception, the second returns a special value (either
+ * <tt>null</tt> or <tt>false</tt>, depending on the operation), the third
+ * blocks the current thread indefinitely until the operation can succeed,
+ * and the fourth blocks for only a given maximum time limit before giving
+ * up.  These methods are summarized in the following table:
+ *
+ * <p>
+ * <table BORDER CELLPADDING=3 CELLSPACING=1>
+ *  <tr>
+ *    <td></td>
+ *    <td ALIGN=CENTER><em>Throws exception</em></td>
+ *    <td ALIGN=CENTER><em>Special value</em></td>
+ *    <td ALIGN=CENTER><em>Blocks</em></td>
+ *    <td ALIGN=CENTER><em>Times out</em></td>
+ *  </tr>
+ *  <tr>
+ *    <td><b>Insert</b></td>
+ *    <td>{@link #add add(e)}</td>
+ *    <td>{@link #offer offer(e)}</td>
+ *    <td>{@link #put put(e)}</td>
+ *    <td>{@link #offer offer(e, time, unit)}</td>
+ *  </tr>
+ *  <tr>
+ *    <td><b>Remove</b></td>
+ *    <td>{@link #remove remove()}</td>
+ *    <td>{@link #poll poll()}</td>
+ *    <td>{@link #take take()}</td>
+ *    <td>{@link #poll(long, TimeUnit) poll(time, unit)}</td>
+ *  </tr>
+ *  <tr>
+ *    <td><b>Examine</b></td>
+ *    <td>{@link #element element()}</td>
+ *    <td>{@link #peek peek()}</td>
+ *    <td><em>not applicable</em></td>
+ *    <td><em>not applicable</em></td>
+ *  </tr>
+ * </table>
  *
  * <p>A <tt>BlockingQueue</tt> does not accept <tt>null</tt> elements.
  * Implementations throw <tt>NullPointerException</tt> on attempts
@@ -31,16 +72,22 @@
  * A <tt>BlockingQueue</tt> without any intrinsic capacity constraints always
  * reports a remaining capacity of <tt>Integer.MAX_VALUE</tt>.
  *
- * <p> While <tt>BlockingQueue</tt> is designed to be used primarily
- * for producer-consumer queues, it additionally supports the {@link
- * java.util.Collection} interface.  So, for example, it is possible
- * to remove an arbitrary element from a queue using
+ * <p> <tt>BlockingQueue</tt> implementations are designed to be used
+ * primarily for producer-consumer queues, but additionally support
+ * the {@link java.util.Collection} interface.  So, for example, it is
+ * possible to remove an arbitrary element from a queue using
  * <tt>remove(x)</tt>. However, such operations are in general
  * <em>not</em> performed very efficiently, and are intended for only
- * occasional use, such as when a queued message is cancelled.  Also,
- * the bulk Collection operations, most notably <tt>addAll</tt>, are
- * <em>not</em> necessarily performed atomically, so it is possible
- * for <tt>addAll(c)</tt> to fail (throwing an exception) after adding
+ * occasional use, such as when a queued message is cancelled.
+ *
+ * <p> <tt>BlockingQueue</tt> implementations are thread-safe.  All
+ * queuing methods achieve their effects atomically using internal
+ * locks or other forms of concurrency control. However, the
+ * <em>bulk</em> Collection operations <tt>addAll</tt>,
+ * <tt>containsAll</tt>, <tt>retainAll</tt> and <tt>removeAll</tt> are
+ * <em>not</em> necessarily performed atomically unless specified
+ * otherwise in an implementation. So it is possible, for example, for
+ * <tt>addAll(c)</tt> to fail (throwing an exception) after adding
  * only some of the elements in <tt>c</tt>.
  *
  * <p>A <tt>BlockingQueue</tt> does <em>not</em> intrinsically support
@@ -61,7 +108,7 @@
  *   Producer(BlockingQueue q) { queue = q; }
  *   public void run() {
  *     try {
- *       while(true) { queue.put(produce()); }
+ *       while (true) { queue.put(produce()); }
  *     } catch (InterruptedException ex) { ... handle ...}
  *   }
  *   Object produce() { ... }
@@ -72,7 +119,7 @@
  *   Consumer(BlockingQueue q) { queue = q; }
  *   public void run() {
  *     try {
- *       while(true) { consume(queue.take()); }
+ *       while (true) { consume(queue.take()); }
  *     } catch (InterruptedException ex) { ... handle ...}
  *   }
  *   void consume(Object x) { ... }
@@ -91,137 +138,207 @@
  * }
  * </pre>
  *
+ * <p>Memory consistency effects: As with other concurrent
+ * collections, actions in a thread prior to placing an object into a
+ * {@code BlockingQueue}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * actions subsequent to the access or removal of that element from
+ * the {@code BlockingQueue} in another thread.
+ *
  * @since 1.5
  * @author Doug Lea
  * @param <E> the type of elements held in this collection
  */
 public interface BlockingQueue<E> extends Queue<E> {
+    /**
+     * Inserts the specified element into this queue if it is possible to do
+     * so immediately without violating capacity restrictions, returning
+     * <tt>true</tt> upon success and throwing an
+     * <tt>IllegalStateException</tt> if no space is currently available.
+     * When using a capacity-restricted queue, it is generally preferable to
+     * use {@link #offer offer}.
+     *
+     * @param e the element to add
+     * @return <tt>true</tt> (as specified by {@link Collection#add})
+     * @throws IllegalStateException if the element cannot be added at this
+     *         time due to capacity restrictions
+     * @throws ClassCastException if the class of the specified element
+     *         prevents it from being added to this queue
+     * @throws NullPointerException if the specified element is null
+     * @throws IllegalArgumentException if some property of the specified
+     *         element prevents it from being added to this queue
+     */
+    boolean add(E e);
 
     /**
-     * Inserts the specified element into this queue, if possible.  When
-     * using queues that may impose insertion restrictions (for
-     * example capacity bounds), method <tt>offer</tt> is generally
-     * preferable to method {@link Collection#add}, which can fail to
-     * insert an element only by throwing an exception.
+     * Inserts the specified element into this queue if it is possible to do
+     * so immediately without violating capacity restrictions, returning
+     * <tt>true</tt> upon success and <tt>false</tt> if no space is currently
+     * available.  When using a capacity-restricted queue, this method is
+     * generally preferable to {@link #add}, which can fail to insert an
+     * element only by throwing an exception.
      *
-     * @param o the element to add.
-     * @return <tt>true</tt> if it was possible to add the element to
-     *         this queue, else <tt>false</tt>
-     * @throws NullPointerException if the specified element is <tt>null</tt>
+     * @param e the element to add
+     * @return <tt>true</tt> if the element was added to this queue, else
+     *         <tt>false</tt>
+     * @throws ClassCastException if the class of the specified element
+     *         prevents it from being added to this queue
+     * @throws NullPointerException if the specified element is null
+     * @throws IllegalArgumentException if some property of the specified
+     *         element prevents it from being added to this queue
      */
-    boolean offer(E o);
-    
+    boolean offer(E e);
+
     /**
      * Inserts the specified element into this queue, waiting if necessary
-     * up to the specified wait time for space to become available.
-     * @param o the element to add
-     * @param timeout how long to wait before giving up, in units of
-     * <tt>unit</tt>
-     * @param unit a <tt>TimeUnit</tt> determining how to interpret the
-     * <tt>timeout</tt> parameter
-     * @return <tt>true</tt> if successful, or <tt>false</tt> if
-     * the specified waiting time elapses before space is available.
-     * @throws InterruptedException if interrupted while waiting.
-     * @throws NullPointerException if the specified element is <tt>null</tt>.
+     * for space to become available.
+     *
+     * @param e the element to add
+     * @throws InterruptedException if interrupted while waiting
+     * @throws ClassCastException if the class of the specified element
+     *         prevents it from being added to this queue
+     * @throws NullPointerException if the specified element is null
+     * @throws IllegalArgumentException if some property of the specified
+     *         element prevents it from being added to this queue
      */
-    boolean offer(E o, long timeout, TimeUnit unit)
+    void put(E e) throws InterruptedException;
+
+    /**
+     * Inserts the specified element into this queue, waiting up to the
+     * specified wait time if necessary for space to become available.
+     *
+     * @param e the element to add
+     * @param timeout how long to wait before giving up, in units of
+     *        <tt>unit</tt>
+     * @param unit a <tt>TimeUnit</tt> determining how to interpret the
+     *        <tt>timeout</tt> parameter
+     * @return <tt>true</tt> if successful, or <tt>false</tt> if
+     *         the specified waiting time elapses before space is available
+     * @throws InterruptedException if interrupted while waiting
+     * @throws ClassCastException if the class of the specified element
+     *         prevents it from being added to this queue
+     * @throws NullPointerException if the specified element is null
+     * @throws IllegalArgumentException if some property of the specified
+     *         element prevents it from being added to this queue
+     */
+    boolean offer(E e, long timeout, TimeUnit unit)
         throws InterruptedException;
 
     /**
-     * Retrieves and removes the head of this queue, waiting
-     * if necessary up to the specified wait time if no elements are
-     * present on this queue.
+     * Retrieves and removes the head of this queue, waiting if necessary
+     * until an element becomes available.
+     *
+     * @return the head of this queue
+     * @throws InterruptedException if interrupted while waiting
+     */
+    E take() throws InterruptedException;
+
+    /**
+     * Retrieves and removes the head of this queue, waiting up to the
+     * specified wait time if necessary for an element to become available.
+     *
      * @param timeout how long to wait before giving up, in units of
-     * <tt>unit</tt>
+     *        <tt>unit</tt>
      * @param unit a <tt>TimeUnit</tt> determining how to interpret the
-     * <tt>timeout</tt> parameter
+     *        <tt>timeout</tt> parameter
      * @return the head of this queue, or <tt>null</tt> if the
-     * specified waiting time elapses before an element is present.
-     * @throws InterruptedException if interrupted while waiting.
+     *         specified waiting time elapses before an element is available
+     * @throws InterruptedException if interrupted while waiting
      */
     E poll(long timeout, TimeUnit unit)
         throws InterruptedException;
 
     /**
-     * Retrieves and removes the head of this queue, waiting
-     * if no elements are present on this queue.
-     * @return the head of this queue
-     * @throws InterruptedException if interrupted while waiting.
-     */
-    E take() throws InterruptedException;
-
-    /**
-     * Adds the specified element to this queue, waiting if necessary for
-     * space to become available.
-     * @param o the element to add
-     * @throws InterruptedException if interrupted while waiting.
-     * @throws NullPointerException if the specified element is <tt>null</tt>.
-     */
-    void put(E o) throws InterruptedException;
-
-    /**
-     * Returns the number of elements that this queue can ideally (in
-     * the absence of memory or resource constraints) accept without
-     * blocking, or <tt>Integer.MAX_VALUE</tt> if there is no
-     * intrinsic limit.
-     * <p>Note that you <em>cannot</em> always tell if
-     * an attempt to <tt>add</tt> an element will succeed by
-     * inspecting <tt>remainingCapacity</tt> because it may be the
-     * case that a waiting consumer is ready to <tt>take</tt> an
-     * element out of an otherwise full queue.
+     * Returns the number of additional elements that this queue can ideally
+     * (in the absence of memory or resource constraints) accept without
+     * blocking, or <tt>Integer.MAX_VALUE</tt> if there is no intrinsic
+     * limit.
+     *
+     * <p>Note that you <em>cannot</em> always tell if an attempt to insert
+     * an element will succeed by inspecting <tt>remainingCapacity</tt>
+     * because it may be the case that another thread is about to
+     * insert or remove an element.
+     *
      * @return the remaining capacity
      */
     int remainingCapacity();
 
     /**
-     * Adds the specified element to this queue if it is possible to
-     * do so immediately, returning <tt>true</tt> upon success, else
-     * throwing an IllegalStateException.  
-     * @param o the element
-     * @return <tt>true</tt> (as per the general contract of
-     *         <tt>Collection.add</tt>).
+     * Removes a single instance of the specified element from this queue,
+     * if it is present.  More formally, removes an element <tt>e</tt> such
+     * that <tt>o.equals(e)</tt>, if this queue contains one or more such
+     * elements.
+     * Returns <tt>true</tt> if this queue contained the specified element
+     * (or equivalently, if this queue changed as a result of the call).
      *
-     * @throws NullPointerException if the specified element is <tt>null</tt>
-     * @throws IllegalStateException if element cannot be added
+     * @param o element to be removed from this queue, if present
+     * @return <tt>true</tt> if this queue changed as a result of the call
+     * @throws ClassCastException if the class of the specified element
+     *         is incompatible with this queue (optional)
+     * @throws NullPointerException if the specified element is null (optional)
      */
-    boolean add(E o);
+    boolean remove(Object o);
+
+    /**
+     * Returns <tt>true</tt> if this queue contains the specified element.
+     * More formally, returns <tt>true</tt> if and only if this queue contains
+     * at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>.
+     *
+     * @param o object to be checked for containment in this queue
+     * @return <tt>true</tt> if this queue contains the specified element
+     * @throws ClassCastException if the class of the specified element
+     *         is incompatible with this queue (optional)
+     * @throws NullPointerException if the specified element is null (optional)
+     */
+    public boolean contains(Object o);
 
     /**
      * Removes all available elements from this queue and adds them
-     * into the given collection.  This operation may be more
+     * to the given collection.  This operation may be more
      * efficient than repeatedly polling this queue.  A failure
-     * encountered while attempting to <tt>add</tt> elements to
+     * encountered while attempting to add elements to
      * collection <tt>c</tt> may result in elements being in neither,
      * either or both collections when the associated exception is
-     * thrown. Attempts to drain a queue to itself result in
+     * thrown.  Attempts to drain a queue to itself result in
      * <tt>IllegalArgumentException</tt>. Further, the behavior of
      * this operation is undefined if the specified collection is
      * modified while the operation is in progress.
      *
      * @param c the collection to transfer elements into
-     * @return the number of elements transferred.
-     * @throws NullPointerException if c is null
-     * @throws IllegalArgumentException if c is this queue
-     * 
+     * @return the number of elements transferred
+     * @throws UnsupportedOperationException if addition of elements
+     *         is not supported by the specified collection
+     * @throws ClassCastException if the class of an element of this queue
+     *         prevents it from being added to the specified collection
+     * @throws NullPointerException if the specified collection is null
+     * @throws IllegalArgumentException if the specified collection is this
+     *         queue, or some property of an element of this queue prevents
+     *         it from being added to the specified collection
      */
     int drainTo(Collection<? super E> c);
-    
+
     /**
      * Removes at most the given number of available elements from
-     * this queue and adds them into the given collection.  A failure
-     * encountered while attempting to <tt>add</tt> elements to
+     * this queue and adds them to the given collection.  A failure
+     * encountered while attempting to add elements to
      * collection <tt>c</tt> may result in elements being in neither,
      * either or both collections when the associated exception is
-     * thrown. Attempts to drain a queue to itself result in
+     * thrown.  Attempts to drain a queue to itself result in
      * <tt>IllegalArgumentException</tt>. Further, the behavior of
      * this operation is undefined if the specified collection is
      * modified while the operation is in progress.
      *
      * @param c the collection to transfer elements into
      * @param maxElements the maximum number of elements to transfer
-     * @return the number of elements transferred.
-     * @throws NullPointerException if c is null
-     * @throws IllegalArgumentException if c is this queue
+     * @return the number of elements transferred
+     * @throws UnsupportedOperationException if addition of elements
+     *         is not supported by the specified collection
+     * @throws ClassCastException if the class of an element of this queue
+     *         prevents it from being added to the specified collection
+     * @throws NullPointerException if the specified collection is null
+     * @throws IllegalArgumentException if the specified collection is this
+     *         queue, or some property of an element of this queue prevents
+     *         it from being added to the specified collection
      */
     int drainTo(Collection<? super E> c, int maxElements);
 }
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/CompletionService.java b/libcore/concurrent/src/main/java/java/util/concurrent/CompletionService.java
index e349e5f..df9f719 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/CompletionService.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/CompletionService.java
@@ -16,52 +16,56 @@
  * submitted in one part of a program or system, and then acted upon
  * in a different part of the program when the reads complete,
  * possibly in a different order than they were requested.
-
- * <p>
  *
- * Typically, a <tt>CompletionService</tt> relies on a separate {@link
- * Executor} to actually execute the tasks, in which case the
+ * <p>Typically, a <tt>CompletionService</tt> relies on a separate
+ * {@link Executor} to actually execute the tasks, in which case the
  * <tt>CompletionService</tt> only manages an internal completion
  * queue. The {@link ExecutorCompletionService} class provides an
  * implementation of this approach.
  *
+ * <p>Memory consistency effects: Actions in a thread prior to
+ * submitting a task to a {@code CompletionService}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * actions taken by that task, which in turn <i>happen-before</i>
+ * actions following a successful return from the corresponding {@code take()}.
+ *
  */
 public interface CompletionService<V> {
     /**
      * Submits a value-returning task for execution and returns a Future
-     * representing the pending results of the task. Upon completion,
+     * representing the pending results of the task.  Upon completion,
      * this task may be taken or polled.
      *
      * @param task the task to submit
      * @return a Future representing pending completion of the task
-     * @throws RejectedExecutionException if task cannot be scheduled
-     * for execution
-     * @throws NullPointerException if task null     
+     * @throws RejectedExecutionException if the task cannot be
+     *         scheduled for execution
+     * @throws NullPointerException if the task is null
      */
     Future<V> submit(Callable<V> task);
 
-
     /**
-     * Submits a Runnable task for execution and returns a Future 
-     * representing that task. Upon completion,
-     * this task may be taken or polled.
+     * Submits a Runnable task for execution and returns a Future
+     * representing that task.  Upon completion, this task may be
+     * taken or polled.
      *
      * @param task the task to submit
      * @param result the result to return upon successful completion
      * @return a Future representing pending completion of the task,
-     * and whose <tt>get()</tt> method will return the given result value 
-     * upon completion
-     * @throws RejectedExecutionException if task cannot be scheduled
-     * for execution
-     * @throws NullPointerException if task null     
+     *         and whose <tt>get()</tt> method will return the given
+     *         result value upon completion
+     * @throws RejectedExecutionException if the task cannot be
+     *         scheduled for execution
+     * @throws NullPointerException if the task is null
      */
     Future<V> submit(Runnable task, V result);
 
     /**
      * Retrieves and removes the Future representing the next
      * completed task, waiting if none are yet present.
+     *
      * @return the Future representing the next completed task
-     * @throws InterruptedException if interrupted while waiting.
+     * @throws InterruptedException if interrupted while waiting
      */
     Future<V> take() throws InterruptedException;
 
@@ -71,7 +75,7 @@
      * completed task or <tt>null</tt> if none are present.
      *
      * @return the Future representing the next completed task, or
-     * <tt>null</tt> if none are present.
+     *         <tt>null</tt> if none are present
      */
     Future<V> poll();
 
@@ -79,14 +83,15 @@
      * Retrieves and removes the Future representing the next
      * completed task, waiting if necessary up to the specified wait
      * time if none are yet present.
+     *
      * @param timeout how long to wait before giving up, in units of
-     * <tt>unit</tt>
+     *        <tt>unit</tt>
      * @param unit a <tt>TimeUnit</tt> determining how to interpret the
-     * <tt>timeout</tt> parameter
+     *        <tt>timeout</tt> parameter
      * @return the Future representing the next completed task or
-     * <tt>null</tt> if the specified waiting time elapses before one
-     * is present.
-     * @throws InterruptedException if interrupted while waiting.
+     *         <tt>null</tt> if the specified waiting time elapses
+     *         before one is present
+     * @throws InterruptedException if interrupted while waiting
      */
     Future<V> poll(long timeout, TimeUnit unit) throws InterruptedException;
 }
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/ConcurrentHashMap.java b/libcore/concurrent/src/main/java/java/util/concurrent/ConcurrentHashMap.java
index f72c6fe..cb5fb3f 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/ConcurrentHashMap.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/ConcurrentHashMap.java
@@ -14,7 +14,6 @@
 
 // BEGIN android-note
 // removed link to collections framework docs
-// removed cloneable interface from ConcurrentMap interface
 // END android-note
 
 /**
@@ -38,13 +37,12 @@
  * removal of only some entries.  Similarly, Iterators and
  * Enumerations return elements reflecting the state of the hash table
  * at some point at or since the creation of the iterator/enumeration.
- * They do <em>not</em> throw
- * {@link ConcurrentModificationException}.  However, iterators are
- * designed to be used by only one thread at a time.
+ * They do <em>not</em> throw {@link ConcurrentModificationException}.
+ * However, iterators are designed to be used by only one thread at a time.
  *
  * <p> The allowed concurrency among update operations is guided by
  * the optional <tt>concurrencyLevel</tt> constructor argument
- * (default 16), which is used as a hint for internal sizing.  The
+ * (default <tt>16</tt>), which is used as a hint for internal sizing.  The
  * table is internally partitioned to try to permit the indicated
  * number of concurrent updates without contention. Because placement
  * in hash tables is essentially random, the actual concurrency will
@@ -54,20 +52,23 @@
  * and a significantly lower value can lead to thread contention. But
  * overestimates and underestimates within an order of magnitude do
  * not usually have much noticeable impact. A value of one is
- * appropriate when it is known that only one thread will modify
- * and all others will only read.
+ * appropriate when it is known that only one thread will modify and
+ * all others will only read. Also, resizing this or any other kind of
+ * hash table is a relatively slow operation, so, when possible, it is
+ * a good idea to provide estimates of expected table sizes in
+ * constructors.
  *
- * <p>This class implements all of the <em>optional</em> methods
- * of the {@link Map} and {@link Iterator} interfaces.
+ * <p>This class and its views and iterators implement all of the
+ * <em>optional</em> methods of the {@link Map} and {@link Iterator}
+ * interfaces.
  *
- * <p> Like {@link java.util.Hashtable} but unlike {@link
- * java.util.HashMap}, this class does NOT allow <tt>null</tt> to be
- * used as a key or value.
+ * <p> Like {@link Hashtable} but unlike {@link HashMap}, this class
+ * does <em>not</em> allow <tt>null</tt> to be used as a key or value.
  *
  * @since 1.5
  * @author Doug Lea
  * @param <K> the type of keys maintained by this map
- * @param <V> the type of mapped values 
+ * @param <V> the type of mapped values
  */
 public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
         implements ConcurrentMap<K, V>, Serializable {
@@ -81,29 +82,30 @@
     /* ---------------- Constants -------------- */
 
     /**
-     * The default initial number of table slots for this table.
-     * Used when not otherwise specified in constructor.
+     * The default initial capacity for this table,
+     * used when not otherwise specified in a constructor.
      */
-    static int DEFAULT_INITIAL_CAPACITY = 16;
+    static final int DEFAULT_INITIAL_CAPACITY = 16;
 
     /**
-     * The maximum capacity, used if a higher value is implicitly
-     * specified by either of the constructors with arguments.  MUST
-     * be a power of two <= 1<<30 to ensure that entries are indexible
-     * using ints.
-     */
-    static final int MAXIMUM_CAPACITY = 1 << 30; 
-
-    /**
-     * The default load factor for this table.  Used when not
-     * otherwise specified in constructor.
+     * The default load factor for this table, used when not
+     * otherwise specified in a constructor.
      */
     static final float DEFAULT_LOAD_FACTOR = 0.75f;
 
     /**
-     * The default number of concurrency control segments.
-     **/
-    static final int DEFAULT_SEGMENTS = 16;
+     * The default concurrency level for this table, used when not
+     * otherwise specified in a constructor.
+     */
+    static final int DEFAULT_CONCURRENCY_LEVEL = 16;
+
+    /**
+     * The maximum capacity, used if a higher value is implicitly
+     * specified by either of the constructors with arguments.  MUST
+     * be a power of two <= 1<<30 to ensure that entries are indexable
+     * using ints.
+     */
+    static final int MAXIMUM_CAPACITY = 1 << 30;
 
     /**
      * The maximum number of segments to allow; used to bound
@@ -111,23 +113,31 @@
      */
     static final int MAX_SEGMENTS = 1 << 16; // slightly conservative
 
+    /**
+     * Number of unsynchronized retries in size and containsValue
+     * methods before resorting to locking. This is used to avoid
+     * unbounded retries if tables undergo continuous modification
+     * which would make it impossible to obtain an accurate result.
+     */
+    static final int RETRIES_BEFORE_LOCK = 2;
+
     /* ---------------- Fields -------------- */
 
     /**
      * Mask value for indexing into segments. The upper bits of a
      * key's hash code are used to choose the segment.
-     **/
+     */
     final int segmentMask;
 
     /**
      * Shift value for indexing within segments.
-     **/
+     */
     final int segmentShift;
 
     /**
      * The segments, each of which is a specialized hash table
      */
-    final Segment[] segments;
+    final Segment<K,V>[] segments;
 
     transient Set<K> keySet;
     transient Set<Map.Entry<K,V>> entrySet;
@@ -136,18 +146,21 @@
     /* ---------------- Small Utilities -------------- */
 
     /**
-     * Returns a hash code for non-null Object x.
-     * Uses the same hash code spreader as most other java.util hash tables.
-     * @param x the object serving as a key
-     * @return the hash code
+     * Applies a supplemental hash function to a given hashCode, which
+     * defends against poor quality hash functions.  This is critical
+     * because ConcurrentHashMap uses power-of-two length hash tables,
+     * that otherwise encounter collisions for hashCodes that do not
+     * differ in lower or upper bits.
      */
-    static int hash(Object x) {
-        int h = x.hashCode();
-        h += ~(h << 9);
-        h ^=  (h >>> 14);
-        h +=  (h << 4);
-        h ^=  (h >>> 10);
-        return h;
+    private static int hash(int h) {
+        // Spread bits to regularize both segment and index locations,
+        // using variant of single-word Wang/Jenkins hash.
+        h += (h <<  15) ^ 0xffffcd7d;
+        h ^= (h >>> 10);
+        h += (h <<   3);
+        h ^= (h >>>  6);
+        h += (h <<   2) + (h << 14);
+        return h ^ (h >>> 16);
     }
 
     /**
@@ -156,16 +169,47 @@
      * @return the segment
      */
     final Segment<K,V> segmentFor(int hash) {
-        return (Segment<K,V>) segments[(hash >>> segmentShift) & segmentMask];
+        return segments[(hash >>> segmentShift) & segmentMask];
     }
 
     /* ---------------- Inner Classes -------------- */
 
     /**
+     * ConcurrentHashMap list entry. Note that this is never exported
+     * out as a user-visible Map.Entry.
+     *
+     * Because the value field is volatile, not final, it is legal wrt
+     * the Java Memory Model for an unsynchronized reader to see null
+     * instead of initial value when read via a data race.  Although a
+     * reordering leading to this is not likely to ever actually
+     * occur, the Segment.readValueUnderLock method is used as a
+     * backup in case a null (pre-initialized) value is ever seen in
+     * an unsynchronized access method.
+     */
+    static final class HashEntry<K,V> {
+        final K key;
+        final int hash;
+        volatile V value;
+        final HashEntry<K,V> next;
+
+        HashEntry(K key, int hash, HashEntry<K,V> next, V value) {
+            this.key = key;
+            this.hash = hash;
+            this.next = next;
+            this.value = value;
+        }
+
+        @SuppressWarnings("unchecked")
+        static final <K,V> HashEntry<K,V>[] newArray(int i) {
+            return new HashEntry[i];
+        }
+    }
+
+    /**
      * Segments are specialized versions of hash tables.  This
      * subclasses from ReentrantLock opportunistically, just to
      * simplify some locking and avoid separate construction.
-     **/
+     */
     static final class Segment<K,V> extends ReentrantLock implements Serializable {
         /*
          * Segments maintain a table of entry lists that are ALWAYS
@@ -179,58 +223,59 @@
          * is less than two for the default load factor threshold.)
          *
          * Read operations can thus proceed without locking, but rely
-         * on a memory barrier to ensure that completed write
-         * operations performed by other threads are
-         * noticed. Conveniently, the "count" field, tracking the
-         * number of elements, can also serve as the volatile variable
-         * providing proper read/write barriers. This is convenient
-         * because this field needs to be read in many read operations
-         * anyway. 
+         * on selected uses of volatiles to ensure that completed
+         * write operations performed by other threads are
+         * noticed. For most purposes, the "count" field, tracking the
+         * number of elements, serves as that volatile variable
+         * ensuring visibility.  This is convenient because this field
+         * needs to be read in many read operations anyway:
          *
-         * Implementors note. The basic rules for all this are:
-         *
-         *   - All unsynchronized read operations must first read the
+         *   - All (unsynchronized) read operations must first read the
          *     "count" field, and should not look at table entries if
          *     it is 0.
          *
-         *   - All synchronized write operations should write to
-         *     the "count" field after updating. The operations must not
-         *     take any action that could even momentarily cause
-         *     a concurrent read operation to see inconsistent
-         *     data. This is made easier by the nature of the read
-         *     operations in Map. For example, no operation
+         *   - All (synchronized) write operations should write to
+         *     the "count" field after structurally changing any bin.
+         *     The operations must not take any action that could even
+         *     momentarily cause a concurrent read operation to see
+         *     inconsistent data. This is made easier by the nature of
+         *     the read operations in Map. For example, no operation
          *     can reveal that the table has grown but the threshold
          *     has not yet been updated, so there are no atomicity
          *     requirements for this with respect to reads.
          *
-         * As a guide, all critical volatile reads and writes are marked
-         * in code comments.
+         * As a guide, all critical volatile reads and writes to the
+         * count field are marked in code comments.
          */
 
         private static final long serialVersionUID = 2249069246763182397L;
 
         /**
          * The number of elements in this segment's region.
-         **/
+         */
         transient volatile int count;
 
         /**
-         * Number of updates; used for checking lack of modifications
-         * in bulk-read methods.
+         * Number of updates that alter the size of the table. This is
+         * used during bulk-read methods to make sure they see a
+         * consistent snapshot: If modCounts change during a traversal
+         * of segments computing size or checking containsValue, then
+         * we might have an inconsistent view of state so (usually)
+         * must retry.
          */
         transient int modCount;
 
         /**
          * The table is rehashed when its size exceeds this threshold.
-         * (The value of this field is always (int)(capacity *
-         * loadFactor).)
+         * (The value of this field is always <tt>(int)(capacity *
+         * loadFactor)</tt>.)
          */
         transient int threshold;
 
         /**
-         * The per-segment table
+         * The per-segment table.
          */
-        transient HashEntry[] table;
+        transient volatile HashEntry<K,V>[] table;
 
         /**
          * The load factor for the hash table.  Even though this value
@@ -242,29 +287,59 @@
 
         Segment(int initialCapacity, float lf) {
             loadFactor = lf;
-            setTable(new HashEntry[initialCapacity]);
+            setTable(HashEntry.<K,V>newArray(initialCapacity));
+        }
+
+        @SuppressWarnings("unchecked")
+        static final <K,V> Segment<K,V>[] newArray(int i) {
+            return new Segment[i];
         }
 
         /**
-         * Set table to new HashEntry array.
+         * Sets table to new HashEntry array.
          * Call only while holding lock or in constructor.
-         **/
-        void setTable(HashEntry[] newTable) {
-            table = newTable;
+         */
+        void setTable(HashEntry<K,V>[] newTable) {
             threshold = (int)(newTable.length * loadFactor);
-            count = count; // write-volatile
+            table = newTable;
+        }
+
+        /**
+         * Returns properly casted first entry of bin for given hash.
+         */
+        HashEntry<K,V> getFirst(int hash) {
+            HashEntry<K,V>[] tab = table;
+            return tab[hash & (tab.length - 1)];
+        }
+
+        /**
+         * Reads value field of an entry under lock. Called if value
+         * field ever appears to be null. This is possible only if a
+         * compiler happens to reorder a HashEntry initialization with
+         * its table assignment, which is legal under memory model
+         * but is not known to ever occur.
+         */
+        V readValueUnderLock(HashEntry<K,V> e) {
+            lock();
+            try {
+                return e.value;
+            } finally {
+                unlock();
+            }
         }
 
         /* Specialized implementations of map methods */
 
         V get(Object key, int hash) {
             if (count != 0) { // read-volatile
-                HashEntry[] tab = table;
-                int index = hash & (tab.length - 1);
-                HashEntry<K,V> e = (HashEntry<K,V>) tab[index];
+                HashEntry<K,V> e = getFirst(hash);
                 while (e != null) {
-                    if (e.hash == hash && key.equals(e.key))
-                        return e.value;
+                    if (e.hash == hash && key.equals(e.key)) {
+                        V v = e.value;
+                        if (v != null)
+                            return v;
+                        return readValueUnderLock(e); // recheck
+                    }
                     e = e.next;
                 }
             }
@@ -273,9 +348,7 @@
 
         boolean containsKey(Object key, int hash) {
             if (count != 0) { // read-volatile
-                HashEntry[] tab = table;
-                int index = hash & (tab.length - 1);
-                HashEntry<K,V> e = (HashEntry<K,V>) tab[index];
+                HashEntry<K,V> e = getFirst(hash);
                 while (e != null) {
                     if (e.hash == hash && key.equals(e.key))
                         return true;
@@ -287,12 +360,17 @@
 
         boolean containsValue(Object value) {
             if (count != 0) { // read-volatile
-                HashEntry[] tab = table;
+                HashEntry<K,V>[] tab = table;
                 int len = tab.length;
-                for (int i = 0 ; i < len; i++)
-                    for (HashEntry<K,V> e = (HashEntry<K,V>)tab[i] ; e != null ; e = e.next)
-                        if (value.equals(e.value))
+                for (int i = 0 ; i < len; i++) {
+                    for (HashEntry<K,V> e = tab[i]; e != null; e = e.next) {
+                        V v = e.value;
+                        if (v == null) // recheck
+                            v = readValueUnderLock(e);
+                        if (value.equals(v))
                             return true;
+                    }
+                }
             }
             return false;
         }
@@ -300,27 +378,16 @@
         boolean replace(K key, int hash, V oldValue, V newValue) {
             lock();
             try {
-                int c = count;
-                HashEntry[] tab = table;
-                int index = hash & (tab.length - 1);
-                HashEntry<K,V> first = (HashEntry<K,V>) tab[index];
-                HashEntry<K,V> e = first;
-                for (;;) {
-                    if (e == null)
-                        return false;
-                    if (e.hash == hash && key.equals(e.key))
-                        break;
+                HashEntry<K,V> e = getFirst(hash);
+                while (e != null && (e.hash != hash || !key.equals(e.key)))
                     e = e.next;
+
+                boolean replaced = false;
+                if (e != null && oldValue.equals(e.value)) {
+                    replaced = true;
+                    e.value = newValue;
                 }
-
-                V v = e.value;
-                if (v == null || !oldValue.equals(v))
-                    return false;
-
-                e.value = newValue;
-                count = c; // write-volatile
-                return true;
-                
+                return replaced;
             } finally {
                 unlock();
             }
@@ -329,24 +396,16 @@
         V replace(K key, int hash, V newValue) {
             lock();
             try {
-                int c = count;
-                HashEntry[] tab = table;
-                int index = hash & (tab.length - 1);
-                HashEntry<K,V> first = (HashEntry<K,V>) tab[index];
-                HashEntry<K,V> e = first;
-                for (;;) {
-                    if (e == null)
-                        return null;
-                    if (e.hash == hash && key.equals(e.key))
-                        break;
+                HashEntry<K,V> e = getFirst(hash);
+                while (e != null && (e.hash != hash || !key.equals(e.key)))
                     e = e.next;
-                }
 
-                V v = e.value;
-                e.value = newValue;
-                count = c; // write-volatile
-                return v;
-                
+                V oldValue = null;
+                if (e != null) {
+                    oldValue = e.value;
+                    e.value = newValue;
+                }
+                return oldValue;
             } finally {
                 unlock();
             }
@@ -357,37 +416,38 @@
             lock();
             try {
                 int c = count;
-                HashEntry[] tab = table;
+                if (c++ > threshold) // ensure capacity
+                    rehash();
+                HashEntry<K,V>[] tab = table;
                 int index = hash & (tab.length - 1);
-                HashEntry<K,V> first = (HashEntry<K,V>) tab[index];
+                HashEntry<K,V> first = tab[index];
+                HashEntry<K,V> e = first;
+                while (e != null && (e.hash != hash || !key.equals(e.key)))
+                    e = e.next;
 
-                for (HashEntry<K,V> e = first; e != null; e = (HashEntry<K,V>) e.next) {
-                    if (e.hash == hash && key.equals(e.key)) {
-                        V oldValue = e.value;
-                        if (!onlyIfAbsent)
-                            e.value = value;
-                        ++modCount;
-                        count = c; // write-volatile
-                        return oldValue;
-                    }
+                V oldValue;
+                if (e != null) {
+                    oldValue = e.value;
+                    if (!onlyIfAbsent)
+                        e.value = value;
                 }
-
-                tab[index] = new HashEntry<K,V>(hash, key, value, first);
-                ++modCount;
-                ++c;
-                count = c; // write-volatile
-                if (c > threshold)
-                    setTable(rehash(tab));
-                return null;
+                else {
+                    oldValue = null;
+                    ++modCount;
+                    tab[index] = new HashEntry<K,V>(key, hash, first, value);
+                    count = c; // write-volatile
+                }
+                return oldValue;
             } finally {
                 unlock();
             }
         }
 
-        HashEntry[] rehash(HashEntry[] oldTable) {
+        void rehash() {
+            HashEntry<K,V>[] oldTable = table;
             int oldCapacity = oldTable.length;
             if (oldCapacity >= MAXIMUM_CAPACITY)
-                return oldTable;
+                return;
 
             /*
              * Reclassify nodes in each list to new Map.  Because we are
@@ -403,12 +463,13 @@
              * right now.
              */
 
-            HashEntry[] newTable = new HashEntry[oldCapacity << 1];
+            HashEntry<K,V>[] newTable = HashEntry.newArray(oldCapacity<<1);
+            threshold = (int)(newTable.length * loadFactor);
             int sizeMask = newTable.length - 1;
             for (int i = 0; i < oldCapacity ; i++) {
                 // We need to guarantee that any existing reads of old Map can
                 //  proceed. So we cannot yet null out each bin.
-                HashEntry<K,V> e = (HashEntry<K,V>)oldTable[i];
+                HashEntry<K,V> e = oldTable[i];
 
                 if (e != null) {
                     HashEntry<K,V> next = e.next;
@@ -436,15 +497,14 @@
                         // Clone all remaining nodes
                         for (HashEntry<K,V> p = e; p != lastRun; p = p.next) {
                             int k = p.hash & sizeMask;
-                            newTable[k] = new HashEntry<K,V>(p.hash,
-                                                             p.key,
-                                                             p.value,
-                                                             (HashEntry<K,V>) newTable[k]);
+                            HashEntry<K,V> n = newTable[k];
+                            newTable[k] = new HashEntry<K,V>(p.key, p.hash,
+                                                             n, p.value);
                         }
                     }
                 }
             }
-            return newTable;
+            table = newTable;
         }
 
         /**
@@ -453,33 +513,31 @@
         V remove(Object key, int hash, Object value) {
             lock();
             try {
-                int c = count;
-                HashEntry[] tab = table;
+                int c = count - 1;
+                HashEntry<K,V>[] tab = table;
                 int index = hash & (tab.length - 1);
-                HashEntry<K,V> first = (HashEntry<K,V>)tab[index];
-
+                HashEntry<K,V> first = tab[index];
                 HashEntry<K,V> e = first;
-                for (;;) {
-                    if (e == null)
-                        return null;
-                    if (e.hash == hash && key.equals(e.key))
-                        break;
+                while (e != null && (e.hash != hash || !key.equals(e.key)))
                     e = e.next;
+
+                V oldValue = null;
+                if (e != null) {
+                    V v = e.value;
+                    if (value == null || value.equals(v)) {
+                        oldValue = v;
+                        // All entries following removed node can stay
+                        // in list, but all preceding ones need to be
+                        // cloned.
+                        ++modCount;
+                        HashEntry<K,V> newFirst = e.next;
+                        for (HashEntry<K,V> p = first; p != e; p = p.next)
+                            newFirst = new HashEntry<K,V>(p.key, p.hash,
+                                                          newFirst, p.value);
+                        tab[index] = newFirst;
+                        count = c; // write-volatile
+                    }
                 }
-
-                V oldValue = e.value;
-                if (value != null && !value.equals(oldValue))
-                    return null;
-
-                // All entries following removed node can stay in list, but
-                // all preceding ones need to be cloned.
-                HashEntry<K,V> newFirst = e.next;
-                for (HashEntry<K,V> p = first; p != e; p = p.next)
-                    newFirst = new HashEntry<K,V>(p.hash, p.key,
-                                                  p.value, newFirst);
-                tab[index] = newFirst;
-                ++modCount;
-                count = c-1; // write-volatile
                 return oldValue;
             } finally {
                 unlock();
@@ -487,50 +545,37 @@
         }
 
         void clear() {
-            lock();
-            try {
-                HashEntry[] tab = table;
-                for (int i = 0; i < tab.length ; i++)
-                    tab[i] = null;
-                ++modCount;
-                count = 0; // write-volatile
-            } finally {
-                unlock();
+            if (count != 0) {
+                lock();
+                try {
+                    HashEntry<K,V>[] tab = table;
+                    for (int i = 0; i < tab.length ; i++)
+                        tab[i] = null;
+                    ++modCount;
+                    count = 0; // write-volatile
+                } finally {
+                    unlock();
+                }
             }
         }
     }
 
-    /**
-     * ConcurrentHashMap list entry. Note that this is never exported
-     * out as a user-visible Map.Entry
-     */
-    static final class HashEntry<K,V> {
-        final K key;
-        V value;
-        final int hash;
-        final HashEntry<K,V> next;
-
-        HashEntry(int hash, K key, V value, HashEntry<K,V> next) {
-            this.value = value;
-            this.hash = hash;
-            this.key = key;
-            this.next = next;
-        }
-    }
 
 
     /* ---------------- Public operations -------------- */
 
     /**
      * Creates a new, empty map with the specified initial
-     * capacity and the specified load factor.
+     * capacity, load factor and concurrency level.
      *
      * @param initialCapacity the initial capacity. The implementation
      * performs internal sizing to accommodate this many elements.
      * @param loadFactor  the load factor threshold, used to control resizing.
+     * Resizing may be performed when the average number of elements per
+     * bin exceeds this threshold.
      * @param concurrencyLevel the estimated number of concurrently
      * updating threads. The implementation performs internal sizing
-     * to try to accommodate this many threads.  
+     * to try to accommodate this many threads.
      * @throws IllegalArgumentException if the initial capacity is
      * negative or the load factor or concurrencyLevel are
      * nonpositive.
@@ -552,7 +597,7 @@
         }
         segmentShift = 32 - sshift;
         segmentMask = ssize - 1;
-        this.segments = new Segment[ssize];
+        this.segments = Segment.newArray(ssize);
 
         if (initialCapacity > MAXIMUM_CAPACITY)
             initialCapacity = MAXIMUM_CAPACITY;
@@ -568,44 +613,50 @@
     }
 
     /**
-     * Creates a new, empty map with the specified initial
-     * capacity,  and with default load factor and concurrencyLevel.
+     * Creates a new, empty map with the specified initial capacity,
+     * and with default load factor (0.75) and concurrencyLevel (16).
      *
-     * @param initialCapacity The implementation performs internal
-     * sizing to accommodate this many elements.
+     * @param initialCapacity the initial capacity. The implementation
+     * performs internal sizing to accommodate this many elements.
      * @throws IllegalArgumentException if the initial capacity of
      * elements is negative.
      */
     public ConcurrentHashMap(int initialCapacity) {
-        this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_SEGMENTS);
+        this(initialCapacity, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
     }
 
     /**
-     * Creates a new, empty map with a default initial capacity,
-     * load factor, and concurrencyLevel.
+     * Creates a new, empty map with a default initial capacity (16),
+     * load factor (0.75) and concurrencyLevel (16).
      */
     public ConcurrentHashMap() {
-        this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_SEGMENTS);
+        this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
     }
 
     /**
-     * Creates a new map with the same mappings as the given map.  The
-     * map is created with a capacity of twice the number of mappings in
-     * the given map or 11 (whichever is greater), and a default load factor.
-     * @param t the map
+     * Creates a new map with the same mappings as the given map.
+     * The map is created with a capacity of 1.5 times the number
+     * of mappings in the given map or 16 (whichever is greater),
+     * and a default load factor (0.75) and concurrencyLevel (16).
+     *
+     * @param m the map
      */
-    public ConcurrentHashMap(Map<? extends K, ? extends V> t) {
-        this(Math.max((int) (t.size() / DEFAULT_LOAD_FACTOR) + 1,
-                      11),
-             DEFAULT_LOAD_FACTOR, DEFAULT_SEGMENTS);
-        putAll(t);
+    public ConcurrentHashMap(Map<? extends K, ? extends V> m) {
+        this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
+                      DEFAULT_INITIAL_CAPACITY),
+             DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);
+        putAll(m);
     }
 
-    // inherit Map javadoc
+    /**
+     * Returns <tt>true</tt> if this map contains no key-value mappings.
+     *
+     * @return <tt>true</tt> if this map contains no key-value mappings
+     */
     public boolean isEmpty() {
-        final Segment[] segments = this.segments;
+        final Segment<K,V>[] segments = this.segments;
         /*
-         * We need to keep track of per-segment modCounts to avoid ABA
+         * We keep track of per-segment modCounts to avoid ABA
          * problems in which an element in one segment was added and
          * in another removed during traversal, in which case the
          * table was never actually empty at any point. Note the
@@ -618,7 +669,7 @@
         for (int i = 0; i < segments.length; ++i) {
             if (segments[i].count != 0)
                 return false;
-            else 
+            else
                 mcsum += mc[i] = segments[i].modCount;
         }
         // If mcsum happens to be zero, then we know we got a snapshot
@@ -627,25 +678,35 @@
         if (mcsum != 0) {
             for (int i = 0; i < segments.length; ++i) {
                 if (segments[i].count != 0 ||
-                    mc[i] != segments[i].modCount) 
+                    mc[i] != segments[i].modCount)
                     return false;
             }
         }
         return true;
     }
 
-    // inherit Map javadoc
+    /**
+     * Returns the number of key-value mappings in this map.  If the
+     * map contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
+     * <tt>Integer.MAX_VALUE</tt>.
+     *
+     * @return the number of key-value mappings in this map
+     */
     public int size() {
-        final Segment[] segments = this.segments;
+        final Segment<K,V>[] segments = this.segments;
+        long sum = 0;
+        long check = 0;
         int[] mc = new int[segments.length];
-        for (;;) {
-            long sum = 0;
+        // Try a few times to get accurate count. On failure due to
+        // continuous async changes in table, resort to locking.
+        for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) {
+            check = 0;
+            sum = 0;
             int mcsum = 0;
             for (int i = 0; i < segments.length; ++i) {
                 sum += segments[i].count;
                 mcsum += mc[i] = segments[i].modCount;
             }
-            int check = 0;
             if (mcsum != 0) {
                 for (int i = 0; i < segments.length; ++i) {
                     check += segments[i].count;
@@ -655,43 +716,51 @@
                     }
                 }
             }
-            if (check == sum) {
-                if (sum > Integer.MAX_VALUE)
-                    return Integer.MAX_VALUE;
-                else
-                    return (int)sum;
-            }
+            if (check == sum)
+                break;
         }
+        if (check != sum) { // Resort to locking all segments
+            sum = 0;
+            for (int i = 0; i < segments.length; ++i)
+                segments[i].lock();
+            for (int i = 0; i < segments.length; ++i)
+                sum += segments[i].count;
+            for (int i = 0; i < segments.length; ++i)
+                segments[i].unlock();
+        }
+        if (sum > Integer.MAX_VALUE)
+            return Integer.MAX_VALUE;
+        else
+            return (int)sum;
     }
 
-
     /**
-     * Returns the value to which the specified key is mapped in this table.
+     * Returns the value to which the specified key is mapped,
+     * or {@code null} if this map contains no mapping for the key.
      *
-     * @param   key   a key in the table.
-     * @return  the value to which the key is mapped in this table;
-     *          <tt>null</tt> if the key is not mapped to any value in
-     *          this table.
-     * @throws  NullPointerException  if the key is
-     *               <tt>null</tt>.
+     * <p>More formally, if this map contains a mapping from a key
+     * {@code k} to a value {@code v} such that {@code key.equals(k)},
+     * then this method returns {@code v}; otherwise it returns
+     * {@code null}.  (There can be at most one such mapping.)
+     *
+     * @throws NullPointerException if the specified key is null
      */
     public V get(Object key) {
-        int hash = hash(key); // throws NullPointerException if key null
+        int hash = hash(key.hashCode());
         return segmentFor(hash).get(key, hash);
     }
 
     /**
      * Tests if the specified object is a key in this table.
      *
-     * @param   key   possible key.
-     * @return  <tt>true</tt> if and only if the specified object
-     *          is a key in this table, as determined by the
-     *          <tt>equals</tt> method; <tt>false</tt> otherwise.
-     * @throws  NullPointerException  if the key is
-     *               <tt>null</tt>.
+     * @param  key   possible key
+     * @return <tt>true</tt> if and only if the specified object
+     *         is a key in this table, as determined by the
+     *         <tt>equals</tt> method; <tt>false</tt> otherwise.
+     * @throws NullPointerException if the specified key is null
      */
     public boolean containsKey(Object key) {
-        int hash = hash(key); // throws NullPointerException if key null
+        int hash = hash(key.hashCode());
         return segmentFor(hash).containsKey(key, hash);
     }
 
@@ -701,18 +770,22 @@
      * traversal of the hash table, and so is much slower than
      * method <tt>containsKey</tt>.
      *
-     * @param value value whose presence in this map is to be tested.
+     * @param value value whose presence in this map is to be tested
      * @return <tt>true</tt> if this map maps one or more keys to the
-     * specified value.
-     * @throws  NullPointerException  if the value is <tt>null</tt>.
+     *         specified value
+     * @throws NullPointerException if the specified value is null
      */
     public boolean containsValue(Object value) {
         if (value == null)
             throw new NullPointerException();
 
-        final Segment[] segments = this.segments;
+        // See explanation of modCount use above
+
+        final Segment<K,V>[] segments = this.segments;
         int[] mc = new int[segments.length];
-        for (;;) {
+
+        // Try a few times without locking
+        for (int k = 0; k < RETRIES_BEFORE_LOCK; ++k) {
             int sum = 0;
             int mcsum = 0;
             for (int i = 0; i < segments.length; ++i) {
@@ -734,287 +807,217 @@
             if (cleanSweep)
                 return false;
         }
+        // Resort to locking all segments
+        for (int i = 0; i < segments.length; ++i)
+            segments[i].lock();
+        boolean found = false;
+        try {
+            for (int i = 0; i < segments.length; ++i) {
+                if (segments[i].containsValue(value)) {
+                    found = true;
+                    break;
+                }
+            }
+        } finally {
+            for (int i = 0; i < segments.length; ++i)
+                segments[i].unlock();
+        }
+        return found;
     }
 
     /**
      * Legacy method testing if some key maps into the specified value
      * in this table.  This method is identical in functionality to
-     * {@link #containsValue}, and  exists solely to ensure
+     * {@link #containsValue}, and exists solely to ensure
      * full compatibility with class {@link java.util.Hashtable},
      * which supported this method prior to introduction of the
      * Java Collections framework.
 
-     * @param      value   a value to search for.
-     * @return     <tt>true</tt> if and only if some key maps to the
-     *             <tt>value</tt> argument in this table as
-     *             determined by the <tt>equals</tt> method;
-     *             <tt>false</tt> otherwise.
-     * @throws  NullPointerException  if the value is <tt>null</tt>.
+     * @param  value a value to search for
+     * @return <tt>true</tt> if and only if some key maps to the
+     *         <tt>value</tt> argument in this table as
+     *         determined by the <tt>equals</tt> method;
+     *         <tt>false</tt> otherwise
+     * @throws NullPointerException if the specified value is null
      */
     public boolean contains(Object value) {
         return containsValue(value);
     }
 
     /**
-     * Maps the specified <tt>key</tt> to the specified
-     * <tt>value</tt> in this table. Neither the key nor the
-     * value can be <tt>null</tt>. 
+     * Maps the specified key to the specified value in this table.
+     * Neither the key nor the value can be null.
      *
      * <p> The value can be retrieved by calling the <tt>get</tt> method
      * with a key that is equal to the original key.
      *
-     * @param      key     the table key.
-     * @param      value   the value.
-     * @return     the previous value of the specified key in this table,
-     *             or <tt>null</tt> if it did not have one.
-     * @throws  NullPointerException  if the key or value is
-     *               <tt>null</tt>.
+     * @param key key with which the specified value is to be associated
+     * @param value value to be associated with the specified key
+     * @return the previous value associated with <tt>key</tt>, or
+     *         <tt>null</tt> if there was no mapping for <tt>key</tt>
+     * @throws NullPointerException if the specified key or value is null
      */
     public V put(K key, V value) {
         if (value == null)
             throw new NullPointerException();
-        int hash = hash(key);
+        int hash = hash(key.hashCode());
         return segmentFor(hash).put(key, hash, value, false);
     }
 
     /**
-     * If the specified key is not already associated
-     * with a value, associate it with the given value.
-     * This is equivalent to
-     * <pre>
-     *   if (!map.containsKey(key)) 
-     *      return map.put(key, value);
-     *   else
-     *      return map.get(key);
-     * </pre>
-     * Except that the action is performed atomically.
-     * @param key key with which the specified value is to be associated.
-     * @param value value to be associated with the specified key.
-     * @return previous value associated with specified key, or <tt>null</tt>
-     *         if there was no mapping for key.  A <tt>null</tt> return can
-     *         also indicate that the map previously associated <tt>null</tt>
-     *         with the specified key, if the implementation supports
-     *         <tt>null</tt> values.
+     * {@inheritDoc}
      *
-     * @throws UnsupportedOperationException if the <tt>put</tt> operation is
-     *            not supported by this map.
-     * @throws ClassCastException if the class of the specified key or value
-     *            prevents it from being stored in this map.
-     * @throws NullPointerException if the specified key or value is
-     *            <tt>null</tt>.
-     *
-     **/
+     * @return the previous value associated with the specified key,
+     *         or <tt>null</tt> if there was no mapping for the key
+     * @throws NullPointerException if the specified key or value is null
+     */
     public V putIfAbsent(K key, V value) {
         if (value == null)
             throw new NullPointerException();
-        int hash = hash(key);
+        int hash = hash(key.hashCode());
         return segmentFor(hash).put(key, hash, value, true);
     }
 
-
     /**
      * Copies all of the mappings from the specified map to this one.
-     *
      * These mappings replace any mappings that this map had for any of the
-     * keys currently in the specified Map.
+     * keys currently in the specified map.
      *
-     * @param t Mappings to be stored in this map.
+     * @param m mappings to be stored in this map
      */
-    public void putAll(Map<? extends K, ? extends V> t) {
-        for (Iterator<? extends Map.Entry<? extends K, ? extends V>> it = (Iterator<? extends Map.Entry<? extends K, ? extends V>>) t.entrySet().iterator(); it.hasNext(); ) {
-            Entry<? extends K, ? extends V> e = it.next();
+    public void putAll(Map<? extends K, ? extends V> m) {
+        for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
             put(e.getKey(), e.getValue());
-        }
     }
 
     /**
-     * Removes the key (and its corresponding value) from this
-     * table. This method does nothing if the key is not in the table.
+     * Removes the key (and its corresponding value) from this map.
+     * This method does nothing if the key is not in the map.
      *
-     * @param   key   the key that needs to be removed.
-     * @return  the value to which the key had been mapped in this table,
-     *          or <tt>null</tt> if the key did not have a mapping.
-     * @throws  NullPointerException  if the key is
-     *               <tt>null</tt>.
+     * @param  key the key that needs to be removed
+     * @return the previous value associated with <tt>key</tt>, or
+     *         <tt>null</tt> if there was no mapping for <tt>key</tt>
+     * @throws NullPointerException if the specified key is null
      */
     public V remove(Object key) {
-        int hash = hash(key);
+        int hash = hash(key.hashCode());
         return segmentFor(hash).remove(key, hash, null);
     }
 
     /**
-     * Remove entry for key only if currently mapped to given value.
-     * Acts as
-     * <pre> 
-     *  if (map.get(key).equals(value)) {
-     *     map.remove(key);
-     *     return true;
-     * } else return false;
-     * </pre>
-     * except that the action is performed atomically.
-     * @param key key with which the specified value is associated.
-     * @param value value associated with the specified key.
-     * @return true if the value was removed
-     * @throws NullPointerException if the specified key is
-     *            <tt>null</tt>.
+     * {@inheritDoc}
+     *
+     * @throws NullPointerException if the specified key is null
      */
     public boolean remove(Object key, Object value) {
-        int hash = hash(key);
+        int hash = hash(key.hashCode());
+        if (value == null)
+            return false;
         return segmentFor(hash).remove(key, hash, value) != null;
     }
 
-
     /**
-     * Replace entry for key only if currently mapped to given value.
-     * Acts as
-     * <pre> 
-     *  if (map.get(key).equals(oldValue)) {
-     *     map.put(key, newValue);
-     *     return true;
-     * } else return false;
-     * </pre>
-     * except that the action is performed atomically.
-     * @param key key with which the specified value is associated.
-     * @param oldValue value expected to be associated with the specified key.
-     * @param newValue value to be associated with the specified key.
-     * @return true if the value was replaced
-     * @throws NullPointerException if the specified key or values are
-     * <tt>null</tt>.
+     * {@inheritDoc}
+     *
+     * @throws NullPointerException if any of the arguments are null
      */
     public boolean replace(K key, V oldValue, V newValue) {
         if (oldValue == null || newValue == null)
             throw new NullPointerException();
-        int hash = hash(key);
+        int hash = hash(key.hashCode());
         return segmentFor(hash).replace(key, hash, oldValue, newValue);
     }
 
     /**
-     * Replace entry for key only if currently mapped to some value.
-     * Acts as
-     * <pre> 
-     *  if ((map.containsKey(key)) {
-     *     return map.put(key, value);
-     * } else return null;
-     * </pre>
-     * except that the action is performed atomically.
-     * @param key key with which the specified value is associated.
-     * @param value value to be associated with the specified key.
-     * @return previous value associated with specified key, or <tt>null</tt>
-     *         if there was no mapping for key.  
-     * @throws NullPointerException if the specified key or value is
-     *            <tt>null</tt>.
+     * {@inheritDoc}
+     *
+     * @return the previous value associated with the specified key,
+     *         or <tt>null</tt> if there was no mapping for the key
+     * @throws NullPointerException if the specified key or value is null
      */
     public V replace(K key, V value) {
         if (value == null)
             throw new NullPointerException();
-        int hash = hash(key);
+        int hash = hash(key.hashCode());
         return segmentFor(hash).replace(key, hash, value);
     }
 
-
     /**
-     * Removes all mappings from this map.
+     * Removes all of the mappings from this map.
      */
     public void clear() {
         for (int i = 0; i < segments.length; ++i)
             segments[i].clear();
     }
 
-
-    // BEGIN android-removed
-    // /**
-    //  * Returns a shallow copy of this
-    //  * <tt>ConcurrentHashMap</tt> instance: the keys and
-    //  * values themselves are not cloned.
-    //  *
-    //  * @return a shallow copy of this map.
-    //  */
-    // public Object clone() {
-    //     // We cannot call super.clone, since it would share final
-    //     // segments array, and there's no way to reassign finals.
-    //
-    //     float lf = segments[0].loadFactor;
-    //     int segs = segments.length;
-    //     int cap = (int)(size() / lf);
-    //     if (cap < segs) cap = segs;
-    //     ConcurrentHashMap<K,V> t = new ConcurrentHashMap<K,V>(cap, lf, segs);
-    //     t.putAll(this);
-    //     return t;
-    // }
-    // END android-changed
-
     /**
-     * Returns a set view of the keys contained in this map.  The set is
-     * backed by the map, so changes to the map are reflected in the set, and
-     * vice-versa.  The set supports element removal, which removes the
-     * corresponding mapping from this map, via the <tt>Iterator.remove</tt>,
-     * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt>, and
-     * <tt>clear</tt> operations.  It does not support the <tt>add</tt> or
+     * Returns a {@link Set} view of the keys contained in this map.
+     * The set is backed by the map, so changes to the map are
+     * reflected in the set, and vice-versa.  The set supports element
+     * removal, which removes the corresponding mapping from this map,
+     * via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
+     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
+     * operations.  It does not support the <tt>add</tt> or
      * <tt>addAll</tt> operations.
-     * The returned <tt>iterator</tt> is a "weakly consistent" iterator that
-     * will never throw {@link java.util.ConcurrentModificationException},
+     *
+     * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
+     * that will never throw {@link ConcurrentModificationException},
      * and guarantees to traverse elements as they existed upon
      * construction of the iterator, and may (but is not guaranteed to)
      * reflect any modifications subsequent to construction.
-     *
-     * @return a set view of the keys contained in this map.
      */
     public Set<K> keySet() {
         Set<K> ks = keySet;
         return (ks != null) ? ks : (keySet = new KeySet());
     }
 
-
     /**
-     * Returns a collection view of the values contained in this map.  The
-     * collection is backed by the map, so changes to the map are reflected in
-     * the collection, and vice-versa.  The collection supports element
-     * removal, which removes the corresponding mapping from this map, via the
-     * <tt>Iterator.remove</tt>, <tt>Collection.remove</tt>,
-     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt> operations.
-     * It does not support the <tt>add</tt> or <tt>addAll</tt> operations.
-     * The returned <tt>iterator</tt> is a "weakly consistent" iterator that
-     * will never throw {@link java.util.ConcurrentModificationException},
+     * Returns a {@link Collection} view of the values contained in this map.
+     * The collection is backed by the map, so changes to the map are
+     * reflected in the collection, and vice-versa.  The collection
+     * supports element removal, which removes the corresponding
+     * mapping from this map, via the <tt>Iterator.remove</tt>,
+     * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
+     * <tt>retainAll</tt>, and <tt>clear</tt> operations.  It does not
+     * support the <tt>add</tt> or <tt>addAll</tt> operations.
+     *
+     * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
+     * that will never throw {@link ConcurrentModificationException},
      * and guarantees to traverse elements as they existed upon
      * construction of the iterator, and may (but is not guaranteed to)
      * reflect any modifications subsequent to construction.
-     *
-     * @return a collection view of the values contained in this map.
      */
     public Collection<V> values() {
         Collection<V> vs = values;
         return (vs != null) ? vs : (values = new Values());
     }
 
-
     /**
-     * Returns a collection view of the mappings contained in this map.  Each
-     * element in the returned collection is a <tt>Map.Entry</tt>.  The
-     * collection is backed by the map, so changes to the map are reflected in
-     * the collection, and vice-versa.  The collection supports element
-     * removal, which removes the corresponding mapping from the map, via the
-     * <tt>Iterator.remove</tt>, <tt>Collection.remove</tt>,
-     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt> operations.
-     * It does not support the <tt>add</tt> or <tt>addAll</tt> operations.
-     * The returned <tt>iterator</tt> is a "weakly consistent" iterator that
-     * will never throw {@link java.util.ConcurrentModificationException},
+     * Returns a {@link Set} view of the mappings contained in this map.
+     * The set is backed by the map, so changes to the map are
+     * reflected in the set, and vice-versa.  The set supports element
+     * removal, which removes the corresponding mapping from the map,
+     * via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
+     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
+     * operations.  It does not support the <tt>add</tt> or
+     * <tt>addAll</tt> operations.
+     *
+     * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
+     * that will never throw {@link ConcurrentModificationException},
      * and guarantees to traverse elements as they existed upon
      * construction of the iterator, and may (but is not guaranteed to)
      * reflect any modifications subsequent to construction.
-     *
-     * @return a collection view of the mappings contained in this map.
      */
     public Set<Map.Entry<K,V>> entrySet() {
         Set<Map.Entry<K,V>> es = entrySet;
-        return (es != null) ? es : (entrySet = (Set<Map.Entry<K,V>>) (Set) new EntrySet());
+        return (es != null) ? es : (entrySet = new EntrySet());
     }
 
-
     /**
      * Returns an enumeration of the keys in this table.
      *
-     * @return  an enumeration of the keys in this table.
-     * @see     #keySet
+     * @return an enumeration of the keys in this table
+     * @see #keySet()
      */
     public Enumeration<K> keys() {
         return new KeyIterator();
@@ -1023,8 +1026,8 @@
     /**
      * Returns an enumeration of the values in this table.
      *
-     * @return  an enumeration of the values in this table.
-     * @see     #values
+     * @return an enumeration of the values in this table
+     * @see #values()
      */
     public Enumeration<V> elements() {
         return new ValueIterator();
@@ -1035,7 +1038,7 @@
     abstract class HashIterator {
         int nextSegmentIndex;
         int nextTableIndex;
-        HashEntry[] currentTable;
+        HashEntry<K,V>[] currentTable;
         HashEntry<K, V> nextEntry;
         HashEntry<K, V> lastReturned;
 
@@ -1052,16 +1055,16 @@
                 return;
 
             while (nextTableIndex >= 0) {
-                if ( (nextEntry = (HashEntry<K,V>)currentTable[nextTableIndex--]) != null)
+                if ( (nextEntry = currentTable[nextTableIndex--]) != null)
                     return;
             }
 
             while (nextSegmentIndex >= 0) {
-                Segment<K,V> seg = (Segment<K,V>)segments[nextSegmentIndex--];
+                Segment<K,V> seg = segments[nextSegmentIndex--];
                 if (seg.count != 0) {
                     currentTable = seg.table;
                     for (int j = currentTable.length - 1; j >= 0; --j) {
-                        if ( (nextEntry = (HashEntry<K,V>)currentTable[j]) != null) {
+                        if ( (nextEntry = currentTable[j]) != null) {
                             nextTableIndex = j - 1;
                             return;
                         }
@@ -1088,81 +1091,58 @@
         }
     }
 
-    final class KeyIterator extends HashIterator implements Iterator<K>, Enumeration<K> {
-        public K next() { return super.nextEntry().key; }
+    final class KeyIterator
+        extends HashIterator
+        implements Iterator<K>, Enumeration<K>
+    {
+        public K next()        { return super.nextEntry().key; }
         public K nextElement() { return super.nextEntry().key; }
     }
 
-    final class ValueIterator extends HashIterator implements Iterator<V>, Enumeration<V> {
-        public V next() { return super.nextEntry().value; }
+    final class ValueIterator
+        extends HashIterator
+        implements Iterator<V>, Enumeration<V>
+    {
+        public V next()        { return super.nextEntry().value; }
         public V nextElement() { return super.nextEntry().value; }
     }
 
-    
-
     /**
-     * Entry iterator. Exported Entry objects must write-through
-     * changes in setValue, even if the nodes have been cloned. So we
-     * cannot return internal HashEntry objects. Instead, the iterator
-     * itself acts as a forwarding pseudo-entry.
+     * Custom Entry class used by EntryIterator.next(), that relays
+     * setValue changes to the underlying map.
      */
-    final class EntryIterator extends HashIterator implements Map.Entry<K,V>, Iterator<Entry<K,V>> {
-        public Map.Entry<K,V> next() {
-            nextEntry();
-            return this;
+    final class WriteThroughEntry
+        extends SimpleEntry<K,V>
+    {
+        WriteThroughEntry(K k, V v) {
+            super(k,v);
         }
 
-        public K getKey() {
-            if (lastReturned == null)
-                throw new IllegalStateException("Entry was removed");
-            return lastReturned.key;
-        }
-
-        public V getValue() {
-            if (lastReturned == null)
-                throw new IllegalStateException("Entry was removed");
-            return ConcurrentHashMap.this.get(lastReturned.key);
-        }
-
+        /**
+         * Set our entry's value and write through to the map. The
+         * value to return is somewhat arbitrary here. Since a
+         * WriteThroughEntry does not necessarily track asynchronous
+         * changes, the most recent "previous" value could be
+         * different from what we return (or could even have been
+         * removed in which case the put will re-establish). We do not
+         * and cannot guarantee more.
+         */
         public V setValue(V value) {
-            if (lastReturned == null)
-                throw new IllegalStateException("Entry was removed");
-            return ConcurrentHashMap.this.put(lastReturned.key, value);
+            if (value == null) throw new NullPointerException();
+            V v = super.setValue(value);
+            ConcurrentHashMap.this.put(getKey(), value);
+            return v;
         }
+    }
 
-        public boolean equals(Object o) {
-            // If not acting as entry, just use default.
-            if (lastReturned == null)
-                return super.equals(o);
-            if (!(o instanceof Map.Entry))
-                return false;
-            Map.Entry e = (Map.Entry)o;
-            return eq(getKey(), e.getKey()) && eq(getValue(), e.getValue());
+    final class EntryIterator
+        extends HashIterator
+        implements Iterator<Entry<K,V>>
+    {
+        public Map.Entry<K,V> next() {
+            HashEntry<K,V> e = super.nextEntry();
+            return new WriteThroughEntry(e.key, e.value);
         }
-
-        public int hashCode() {
-            // If not acting as entry, just use default.
-            if (lastReturned == null)
-                return super.hashCode();
-
-            Object k = getKey();
-            Object v = getValue();
-            return ((k == null) ? 0 : k.hashCode()) ^
-                   ((v == null) ? 0 : v.hashCode());
-        }
-
-        public String toString() {
-            // If not acting as entry, just use default.
-            if (lastReturned == null)
-                return super.toString();
-            else
-                return getKey() + "=" + getValue();
-        }
-
-        boolean eq(Object o1, Object o2) {
-            return (o1 == null ? o2 == null : o1.equals(o2));
-        }
-
     }
 
     final class KeySet extends AbstractSet<K> {
@@ -1172,6 +1152,9 @@
         public int size() {
             return ConcurrentHashMap.this.size();
         }
+        public boolean isEmpty() {
+            return ConcurrentHashMap.this.isEmpty();
+        }
         public boolean contains(Object o) {
             return ConcurrentHashMap.this.containsKey(o);
         }
@@ -1190,6 +1173,9 @@
         public int size() {
             return ConcurrentHashMap.this.size();
         }
+        public boolean isEmpty() {
+            return ConcurrentHashMap.this.isEmpty();
+        }
         public boolean contains(Object o) {
             return ConcurrentHashMap.this.containsValue(o);
         }
@@ -1205,44 +1191,32 @@
         public boolean contains(Object o) {
             if (!(o instanceof Map.Entry))
                 return false;
-            Map.Entry<K,V> e = (Map.Entry<K,V>)o;
+            Map.Entry<?,?> e = (Map.Entry<?,?>)o;
             V v = ConcurrentHashMap.this.get(e.getKey());
             return v != null && v.equals(e.getValue());
         }
         public boolean remove(Object o) {
             if (!(o instanceof Map.Entry))
                 return false;
-            Map.Entry<K,V> e = (Map.Entry<K,V>)o;
+            Map.Entry<?,?> e = (Map.Entry<?,?>)o;
             return ConcurrentHashMap.this.remove(e.getKey(), e.getValue());
         }
         public int size() {
             return ConcurrentHashMap.this.size();
         }
+        public boolean isEmpty() {
+            return ConcurrentHashMap.this.isEmpty();
+        }
         public void clear() {
             ConcurrentHashMap.this.clear();
         }
-        public Object[] toArray() {
-            // Since we don't ordinarily have distinct Entry objects, we
-            // must pack elements using exportable SimpleEntry
-            Collection<Map.Entry<K,V>> c = new ArrayList<Map.Entry<K,V>>(size());
-            for (Iterator<Map.Entry<K,V>> i = iterator(); i.hasNext(); )
-                c.add(new SimpleEntry<K,V>(i.next()));
-            return c.toArray();
-        }
-        public <T> T[] toArray(T[] a) {
-            Collection<Map.Entry<K,V>> c = new ArrayList<Map.Entry<K,V>>(size());
-            for (Iterator<Map.Entry<K,V>> i = iterator(); i.hasNext(); )
-                c.add(new SimpleEntry<K,V>(i.next()));
-            return c.toArray(a);
-        }
-
     }
 
     /**
      * This duplicates java.util.AbstractMap.SimpleEntry until this class
      * is made accessible.
      */
-    static final class SimpleEntry<K,V> implements Entry<K,V> {
+    static class SimpleEntry<K,V> implements Entry<K,V> {
         K key;
         V value;
 
@@ -1279,7 +1253,7 @@
 
         public int hashCode() {
             return ((key   == null)   ? 0 :   key.hashCode()) ^
-                   ((value == null)   ? 0 : value.hashCode());
+                    ((value == null)   ? 0 : value.hashCode());
         }
 
         public String toString() {
@@ -1291,12 +1265,11 @@
         }
     }
 
-    /* ---------------- Serialization Support -------------- */
+   /* ---------------- Serialization Support -------------- */
 
     /**
-     * Save the state of the <tt>ConcurrentHashMap</tt>
-     * instance to a stream (i.e.,
-     * serialize it).
+     * Save the state of the <tt>ConcurrentHashMap</tt> instance to a
+     * stream (i.e., serialize it).
      * @param s the stream
      * @serialData
      * the key (Object) and value (Object)
@@ -1307,12 +1280,12 @@
         s.defaultWriteObject();
 
         for (int k = 0; k < segments.length; ++k) {
-            Segment<K,V> seg = (Segment<K,V>)segments[k];
+            Segment<K,V> seg = segments[k];
             seg.lock();
             try {
-                HashEntry[] tab = seg.table;
+                HashEntry<K,V>[] tab = seg.table;
                 for (int i = 0; i < tab.length; ++i) {
-                    for (HashEntry<K,V> e = (HashEntry<K,V>)tab[i]; e != null; e = e.next) {
+                    for (HashEntry<K,V> e = tab[i]; e != null; e = e.next) {
                         s.writeObject(e.key);
                         s.writeObject(e.value);
                     }
@@ -1326,9 +1299,8 @@
     }
 
     /**
-     * Reconstitute the <tt>ConcurrentHashMap</tt>
-     * instance from a stream (i.e.,
-     * deserialize it).
+     * Reconstitute the <tt>ConcurrentHashMap</tt> instance from a
+     * stream (i.e., deserialize it).
      * @param s the stream
      */
     private void readObject(java.io.ObjectInputStream s)
@@ -1350,4 +1322,3 @@
         }
     }
 }
-
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java b/libcore/concurrent/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java
index 794142d..2253823 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java
@@ -14,7 +14,7 @@
 // END android-note
 
 /**
- * An unbounded thread-safe {@linkplain Queue queue} based on linked nodes.  
+ * An unbounded thread-safe {@linkplain Queue queue} based on linked nodes.
  * This queue orders elements FIFO (first-in-first-out).
  * The <em>head</em> of the queue is that element that has been on the
  * queue the longest time.
@@ -22,23 +22,31 @@
  * queue the shortest time. New elements
  * are inserted at the tail of the queue, and the queue retrieval
  * operations obtain elements at the head of the queue.
- * A <tt>ConcurrentLinkedQueue</tt> is an appropriate choice when 
+ * A {@code ConcurrentLinkedQueue} is an appropriate choice when
  * many threads will share access to a common collection.
- * This queue does not permit <tt>null</tt> elements.
+ * This queue does not permit {@code null} elements.
  *
- * <p>This implementation employs an efficient &quot;wait-free&quot; 
+ * <p>This implementation employs an efficient &quot;wait-free&quot;
  * algorithm based on one described in <a
  * href="http://www.cs.rochester.edu/u/michael/PODC96.html"> Simple,
  * Fast, and Practical Non-Blocking and Blocking Concurrent Queue
  * Algorithms</a> by Maged M. Michael and Michael L. Scott.
  *
- * <p>Beware that, unlike in most collections, the <tt>size</tt> method
+ * <p>Beware that, unlike in most collections, the {@code size} method
  * is <em>NOT</em> a constant-time operation. Because of the
  * asynchronous nature of these queues, determining the current number
  * of elements requires a traversal of the elements.
  *
- * <p>This class implements all of the <em>optional</em> methods
- * of the {@link Collection} and {@link Iterator} interfaces.
+ * <p>This class and its iterator implement all of the
+ * <em>optional</em> methods of the {@link Collection} and {@link
+ * Iterator} interfaces.
+ *
+ * <p>Memory consistency effects: As with other concurrent
+ * collections, actions in a thread prior to placing an object into a
+ * {@code ConcurrentLinkedQueue}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * actions subsequent to the access or removal of that element from
+ * the {@code ConcurrentLinkedQueue} in another thread.
  *
  * @since 1.5
  * @author Doug Lea
@@ -50,68 +58,126 @@
     private static final long serialVersionUID = 196745693267521676L;
 
     /*
-     * This is a straight adaptation of Michael & Scott algorithm.
-     * For explanation, read the paper.  The only (minor) algorithmic
-     * difference is that this version supports lazy deletion of
-     * internal nodes (method remove(Object)) -- remove CAS'es item
-     * fields to null. The normal queue operations unlink but then
-     * pass over nodes with null item fields. Similarly, iteration
-     * methods ignore those with nulls.
+     * This is a modification of the Michael & Scott algorithm,
+     * adapted for a garbage-collected environment, with support for
+     * interior node deletion (to support remove(Object)).  For
+     * explanation, read the paper.
+     *
+     * Note that like most non-blocking algorithms in this package,
+     * this implementation relies on the fact that in garbage
+     * collected systems, there is no possibility of ABA problems due
+     * to recycled nodes, so there is no need to use "counted
+     * pointers" or related techniques seen in versions used in
+     * non-GC'ed settings.
+     *
+     * The fundamental invariants are:
+     * - There is exactly one (last) Node with a null next reference,
+     *   which is CASed when enqueueing.  This last Node can be
+     *   reached in O(1) time from tail, but tail is merely an
+     *   optimization - it can always be reached in O(N) time from
+     *   head as well.
+     * - The elements contained in the queue are the non-null items in
+     *   Nodes that are reachable from head.  CASing the item
+     *   reference of a Node to null atomically removes it from the
+     *   queue.  Reachability of all elements from head must remain
+     *   true even in the case of concurrent modifications that cause
+     *   head to advance.  A dequeued Node may remain in use
+     *   indefinitely due to creation of an Iterator or simply a
+     *   poll() that has lost its time slice.
+     *
+     * The above might appear to imply that all Nodes are GC-reachable
+     * from a predecessor dequeued Node.  That would cause two problems:
+     * - allow a rogue Iterator to cause unbounded memory retention
+     * - cause cross-generational linking of old Nodes to new Nodes if
+     *   a Node was tenured while live, which generational GCs have a
+     *   hard time dealing with, causing repeated major collections.
+     * However, only non-deleted Nodes need to be reachable from
+     * dequeued Nodes, and reachability does not necessarily have to
+     * be of the kind understood by the GC.  We use the trick of
+     * linking a Node that has just been dequeued to itself.  Such a
+     * self-link implicitly means to advance to head.
+     *
+     * Both head and tail are permitted to lag.  In fact, failing to
+     * update them every time one could is a significant optimization
+     * (fewer CASes). This is controlled by local "hops" variables
+     * that only trigger helping-CASes after experiencing multiple
+     * lags.
+     *
+     * Since head and tail are updated concurrently and independently,
+     * it is possible for tail to lag behind head (why not)?
+     *
+     * CASing a Node's item reference to null atomically removes the
+     * element from the queue.  Iterators skip over Nodes with null
+     * items.  Prior implementations of this class had a race between
+     * poll() and remove(Object) where the same element would appear
+     * to be successfully removed by two concurrent operations.  The
+     * method remove(Object) also lazily unlinks deleted Nodes, but
+     * this is merely an optimization.
+     *
+     * When constructing a Node (before enqueuing it) we avoid paying
+     * for a volatile write to item by using lazySet instead of a
+     * normal write.  This allows the cost of enqueue to be
+     * "one-and-a-half" CASes.
+     *
+     * Both head and tail may or may not point to a Node with a
+     * non-null item.  If the queue is empty, all items must of course
+     * be null.  Upon creation, both head and tail refer to a dummy
+     * Node with null item.  Both head and tail are only updated using
+     * CAS, so they never regress, although again this is merely an
+     * optimization.
      */
-
     private static class Node<E> {
         private volatile E item;
         private volatile Node<E> next;
-        
-        private static final 
-            AtomicReferenceFieldUpdater<Node, Node> 
+
+        private static final
+            AtomicReferenceFieldUpdater<Node, Node>
             nextUpdater =
             AtomicReferenceFieldUpdater.newUpdater
             (Node.class, Node.class, "next");
-        private static final 
-            AtomicReferenceFieldUpdater<Node, Object> 
+        private static final
+            AtomicReferenceFieldUpdater<Node, Object>
             itemUpdater =
             AtomicReferenceFieldUpdater.newUpdater
             (Node.class, Object.class, "item");
-        
-        Node(E x) { item = x; }
-        
-        Node(E x, Node<E> n) { item = x; next = n; }
-        
+
+
+        Node(E item) { setItem(item); }
+
         E getItem() {
             return item;
         }
-        
+
         boolean casItem(E cmp, E val) {
             return itemUpdater.compareAndSet(this, cmp, val);
         }
-        
+
         void setItem(E val) {
             itemUpdater.set(this, val);
         }
-        
+
         Node<E> getNext() {
             return next;
         }
-        
+
         boolean casNext(Node<E> cmp, Node<E> val) {
             return nextUpdater.compareAndSet(this, cmp, val);
         }
-        
+
         void setNext(Node<E> val) {
             nextUpdater.set(this, val);
-        }
-        
     }
 
-    private static final 
-        AtomicReferenceFieldUpdater<ConcurrentLinkedQueue, Node> 
-        tailUpdater = 
+    }
+
+    private static final
+        AtomicReferenceFieldUpdater<ConcurrentLinkedQueue, Node>
+        tailUpdater =
         AtomicReferenceFieldUpdater.newUpdater
         (ConcurrentLinkedQueue.class, Node.class, "tail");
-    private static final 
-        AtomicReferenceFieldUpdater<ConcurrentLinkedQueue, Node> 
-        headUpdater = 
+    private static final
+        AtomicReferenceFieldUpdater<ConcurrentLinkedQueue, Node>
+        headUpdater =
         AtomicReferenceFieldUpdater.newUpdater
         (ConcurrentLinkedQueue.class,  Node.class, "head");
 
@@ -124,118 +190,141 @@
     }
 
 
-    /**
-     * Pointer to header node, initialized to a dummy node.  The first
-     * actual node is at head.getNext().
-     */
-    private transient volatile Node<E> head = new Node<E>(null, null);
 
-    /** Pointer to last node on list **/
+    /**
+     * Pointer to first node, initialized to a dummy node.
+     */
+    private transient volatile Node<E> head = new Node<E>(null);
+
+    /** Pointer to last node on list */
     private transient volatile Node<E> tail = head;
 
 
     /**
-     * Creates a <tt>ConcurrentLinkedQueue</tt> that is initially empty.
+     * Creates a {@code ConcurrentLinkedQueue} that is initially empty.
      */
     public ConcurrentLinkedQueue() {}
 
     /**
-     * Creates a <tt>ConcurrentLinkedQueue</tt> 
+     * Creates a {@code ConcurrentLinkedQueue}
      * initially containing the elements of the given collection,
      * added in traversal order of the collection's iterator.
      * @param c the collection of elements to initially contain
-     * @throws NullPointerException if <tt>c</tt> or any element within it
-     * is <tt>null</tt>
+     * @throws NullPointerException if the specified collection or any
+     *         of its elements are null
      */
     public ConcurrentLinkedQueue(Collection<? extends E> c) {
         for (Iterator<? extends E> it = c.iterator(); it.hasNext();)
             add(it.next());
     }
 
-    // Have to override just to update the javadoc 
+    // Have to override just to update the javadoc
 
     /**
-     * Adds the specified element to the tail of this queue.
-     * @param o the element to add.
-     * @return <tt>true</tt> (as per the general contract of
-     * <tt>Collection.add</tt>).
+     * Inserts the specified element at the tail of this queue.
      *
-     * @throws NullPointerException if the specified element is <tt>null</tt>
+     * @return {@code true} (as specified by {@link Collection#add})
+     * @throws NullPointerException if the specified element is null
      */
-    public boolean add(E o) {
-        return offer(o);
+    public boolean add(E e) {
+        return offer(e);
     }
 
     /**
-     * Inserts the specified element to the tail of this queue.
-     *
-     * @param o the element to add.
-     * @return <tt>true</tt> (as per the general contract of
-     * <tt>Queue.offer</tt>).
-     * @throws NullPointerException if the specified element is <tt>null</tt>
+     * We don't bother to update head or tail pointers if less than
+     * HOPS links from "true" location.  We assume that volatile
+     * writes are significantly more expensive than volatile reads.
      */
-    public boolean offer(E o) {
-        if (o == null) throw new NullPointerException();
-        Node<E> n = new Node<E>(o, null);
-        for(;;) {
+    private static final int HOPS = 1;
+
+    /**
+     * Try to CAS head to p. If successful, repoint old head to itself
+     * as sentinel for succ(), below.
+     */
+    final void updateHead(Node<E> h, Node<E> p) {
+        if (h != p && casHead(h, p))
+            h.setNext(h);
+    }
+
+    /**
+     * Returns the successor of p, or the head node if p.next has been
+     * linked to self, which will only be true if traversing with a
+     * stale pointer that is now off the list.
+     */
+    final Node<E> succ(Node<E> p) {
+        Node<E> next = p.getNext();
+        return (p == next) ? head : next;
+    }
+
+    /**
+     * Inserts the specified element at the tail of this queue.
+     *
+     * @return {@code true} (as specified by {@link Queue#offer})
+     * @throws NullPointerException if the specified element is null
+     */
+    public boolean offer(E e) {
+        if (e == null) throw new NullPointerException();
+        Node<E> n = new Node<E>(e);
+        retry:
+        for (;;) {
             Node<E> t = tail;
-            Node<E> s = t.getNext();
-            if (t == tail) {
-                if (s == null) {
-                    if (t.casNext(s, n)) {
-                        casTail(t, n);
-                        return true;
-                    }
+            Node<E> p = t;
+            for (int hops = 0; ; hops++) {
+                Node<E> next = succ(p);
+                if (next != null) {
+                    if (hops > HOPS && t != tail)
+                        continue retry;
+                    p = next;
+                } else if (p.casNext(null, n)) {
+                    if (hops >= HOPS)
+                        casTail(t, n);  // Failure is OK.
+                    return true;
                 } else {
-                    casTail(t, s);
+                    p = succ(p);
                 }
             }
         }
     }
 
     public E poll() {
-        for (;;) {
-            Node<E> h = head;
-            Node<E> t = tail;
-            Node<E> first = h.getNext();
-            if (h == head) {
-                if (h == t) {
-                    if (first == null)
-                        return null;
-                    else
-                        casTail(t, first);
-                } else if (casHead(h, first)) {
-                    E item = first.getItem();
-                    if (item != null) {
-                        first.setItem(null);
-                        return item;
-                    }
-                    // else skip over deleted item, continue loop,
+        Node<E> h = head;
+        Node<E> p = h;
+        for (int hops = 0; ; hops++) {
+            E item = p.getItem();
+
+            if (item != null && p.casItem(item, null)) {
+                if (hops >= HOPS) {
+                    Node<E> q = p.getNext();
+                    updateHead(h, (q != null) ? q : p);
                 }
+                return item;
             }
+            Node<E> next = succ(p);
+            if (next == null) {
+                updateHead(h, p);
+                break;
+            }
+            p = next;
         }
+        return null;
     }
 
-    public E peek() { // same as poll except don't remove item
+    public E peek() {
+        Node<E> h = head;
+        Node<E> p = h;
+        E item;
         for (;;) {
-            Node<E> h = head;
-            Node<E> t = tail;
-            Node<E> first = h.getNext();
-            if (h == head) {
-                if (h == t) {
-                    if (first == null)
-                        return null;
-                    else
-                        casTail(t, first);
-                } else {
-                    E item = first.getItem();
-                    if (item != null)
-                        return item;
-                    else // remove deleted node and continue
-                        casHead(h, first);
-                }
+            item = p.getItem();
+            if (item != null)
+                break;
+            Node<E> next = succ(p);
+            if (next == null) {
+                break;
             }
+            p = next;
         }
+        updateHead(h, p);
+        return item;
     }
 
     /**
@@ -245,46 +334,50 @@
      * introducing race.)
      */
     Node<E> first() {
+        Node<E> h = head;
+        Node<E> p = h;
+        Node<E> result;
         for (;;) {
-            Node<E> h = head;
-            Node<E> t = tail;
-            Node<E> first = h.getNext();
-            if (h == head) {
-                if (h == t) {
-                    if (first == null)
-                        return null;
-                    else
-                        casTail(t, first);
-                } else {
-                    if (first.getItem() != null)
-                        return first;
-                    else // remove deleted node and continue
-                        casHead(h, first);
-                }
+            E item = p.getItem();
+            if (item != null) {
+                result = p;
+                break;
             }
+            Node<E> next = succ(p);
+            if (next == null) {
+                result = null;
+                break;
+            }
+            p = next;
         }
+        updateHead(h, p);
+        return result;
     }
 
-
+    /**
+     * Returns {@code true} if this queue contains no elements.
+     *
+     * @return {@code true} if this queue contains no elements
+     */
     public boolean isEmpty() {
         return first() == null;
     }
 
     /**
      * Returns the number of elements in this queue.  If this queue
-     * contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
-     * <tt>Integer.MAX_VALUE</tt>.
+     * contains more than {@code Integer.MAX_VALUE} elements, returns
+     * {@code Integer.MAX_VALUE}.
      *
      * <p>Beware that, unlike in most collections, this method is
      * <em>NOT</em> a constant-time operation. Because of the
      * asynchronous nature of these queues, determining the current
      * number of elements requires an O(n) traversal.
      *
-     * @return  the number of elements in this queue.
+     * @return the number of elements in this queue
      */
     public int size() {
         int count = 0;
-        for (Node<E> p = first(); p != null; p = p.getNext()) {
+        for (Node<E> p = first(); p != null; p = succ(p)) {
             if (p.getItem() != null) {
                 // Collections.size() spec says to max out
                 if (++count == Integer.MAX_VALUE)
@@ -294,9 +387,17 @@
         return count;
     }
 
+    /**
+     * Returns {@code true} if this queue contains the specified element.
+     * More formally, returns {@code true} if and only if this queue contains
+     * at least one element {@code e} such that {@code o.equals(e)}.
+     *
+     * @param o object to be checked for containment in this queue
+     * @return {@code true} if this queue contains the specified element
+     */
     public boolean contains(Object o) {
         if (o == null) return false;
-        for (Node<E> p = first(); p != null; p = p.getNext()) {
+        for (Node<E> p = first(); p != null; p = succ(p)) {
             E item = p.getItem();
             if (item != null &&
                 o.equals(item))
@@ -305,22 +406,50 @@
         return false;
     }
 
+    /**
+     * Removes a single instance of the specified element from this queue,
+     * if it is present.  More formally, removes an element {@code e} such
+     * that {@code o.equals(e)}, if this queue contains one or more such
+     * elements.
+     * Returns {@code true} if this queue contained the specified element
+     * (or equivalently, if this queue changed as a result of the call).
+     *
+     * @param o element to be removed from this queue, if present
+     * @return {@code true} if this queue changed as a result of the call
+     */
     public boolean remove(Object o) {
         if (o == null) return false;
-        for (Node<E> p = first(); p != null; p = p.getNext()) {
+        Node<E> pred = null;
+        for (Node<E> p = first(); p != null; p = succ(p)) {
             E item = p.getItem();
-            if (item != null &&
-                o.equals(item) &&
-                p.casItem(item, null))
+            if (item != null && o.equals(item) && p.casItem(item, null)) {
+                Node<E> next = succ(p);
+                if (pred != null && next != null)
+                    pred.casNext(p, next);
                 return true;
+            }
+            pred = p;
         }
         return false;
     }
 
+    /**
+     * Returns an array containing all of the elements in this queue, in
+     * proper sequence.
+     *
+     * <p>The returned array will be "safe" in that no references to it are
+     * maintained by this queue.  (In other words, this method must allocate
+     * a new array).  The caller is thus free to modify the returned array.
+     *
+     * <p>This method acts as bridge between array-based and collection-based
+     * APIs.
+     *
+     * @return an array containing all of the elements in this queue
+     */
     public Object[] toArray() {
         // Use ArrayList to deal with resizing.
         ArrayList<E> al = new ArrayList<E>();
-        for (Node<E> p = first(); p != null; p = p.getNext()) {
+        for (Node<E> p = first(); p != null; p = succ(p)) {
             E item = p.getItem();
             if (item != null)
                 al.add(item);
@@ -328,11 +457,48 @@
         return al.toArray();
     }
 
+    /**
+     * Returns an array containing all of the elements in this queue, in
+     * proper sequence; the runtime type of the returned array is that of
+     * the specified array.  If the queue fits in the specified array, it
+     * is returned therein.  Otherwise, a new array is allocated with the
+     * runtime type of the specified array and the size of this queue.
+     *
+     * <p>If this queue fits in the specified array with room to spare
+     * (i.e., the array has more elements than this queue), the element in
+     * the array immediately following the end of the queue is set to
+     * {@code null}.
+     *
+     * <p>Like the {@link #toArray()} method, this method acts as bridge between
+     * array-based and collection-based APIs.  Further, this method allows
+     * precise control over the runtime type of the output array, and may,
+     * under certain circumstances, be used to save allocation costs.
+     *
+     * <p>Suppose {@code x} is a queue known to contain only strings.
+     * The following code can be used to dump the queue into a newly
+     * allocated array of {@code String}:
+     *
+     * <pre>
+     *     String[] y = x.toArray(new String[0]);</pre>
+     *
+     * Note that {@code toArray(new Object[0])} is identical in function to
+     * {@code toArray()}.
+     *
+     * @param a the array into which the elements of the queue are to
+     *          be stored, if it is big enough; otherwise, a new array of the
+     *          same runtime type is allocated for this purpose
+     * @return an array containing all of the elements in this queue
+     * @throws ArrayStoreException if the runtime type of the specified array
+     *         is not a supertype of the runtime type of every element in
+     *         this queue
+     * @throws NullPointerException if the specified array is null
+     */
+    @SuppressWarnings("unchecked")
     public <T> T[] toArray(T[] a) {
         // try to use sent-in array
         int k = 0;
         Node<E> p;
-        for (p = first(); p != null && k < a.length; p = p.getNext()) {
+        for (p = first(); p != null && k < a.length; p = succ(p)) {
             E item = p.getItem();
             if (item != null)
                 a[k++] = (T)item;
@@ -345,23 +511,23 @@
 
         // If won't fit, use ArrayList version
         ArrayList<E> al = new ArrayList<E>();
-        for (Node<E> q = first(); q != null; q = q.getNext()) {
+        for (Node<E> q = first(); q != null; q = succ(q)) {
             E item = q.getItem();
             if (item != null)
                 al.add(item);
         }
-        return (T[])al.toArray(a);
+        return al.toArray(a);
     }
 
     /**
      * Returns an iterator over the elements in this queue in proper sequence.
      * The returned iterator is a "weakly consistent" iterator that
-     * will never throw {@link java.util.ConcurrentModificationException},
+     * will never throw {@link ConcurrentModificationException},
      * and guarantees to traverse elements as they existed upon
      * construction of the iterator, and may (but is not guaranteed to)
      * reflect any modifications subsequent to construction.
      *
-     * @return an iterator over the elements in this queue in proper sequence.
+     * @return an iterator over the elements in this queue in proper sequence
      */
     public Iterator<E> iterator() {
         return new Itr();
@@ -378,7 +544,7 @@
          * that an element exists in hasNext(), we must return it in
          * the following next() call even if it was in the process of
          * being removed when hasNext() was called.
-         **/
+         */
         private E nextItem;
 
         /**
@@ -398,7 +564,15 @@
             lastRet = nextNode;
             E x = nextItem;
 
-            Node<E> p = (nextNode == null)? first() : nextNode.getNext();
+            Node<E> pred, p;
+            if (nextNode == null) {
+                p = first();
+                pred = null;
+            } else {
+                pred = nextNode;
+                p = succ(nextNode);
+            }
+
             for (;;) {
                 if (p == null) {
                     nextNode = null;
@@ -410,8 +584,13 @@
                     nextNode = p;
                     nextItem = item;
                     return x;
-                } else // skip over nulls
-                    p = p.getNext();
+                } else {
+                    // skip over nulls
+                    Node<E> next = succ(p);
+                    if (pred != null && next != null)
+                        pred.casNext(p, next);
+                    p = next;
+                }
             }
         }
 
@@ -436,7 +615,7 @@
     /**
      * Save the state to a stream (that is, serialize it).
      *
-     * @serialData All of the elements (each an <tt>E</tt>) in
+     * @serialData All of the elements (each an {@code E}) in
      * the proper order, followed by a null
      * @param s the stream
      */
@@ -447,7 +626,7 @@
         s.defaultWriteObject();
 
         // Write out all elements in the proper order.
-        for (Node<E> p = first(); p != null; p = p.getNext()) {
+        for (Node<E> p = first(); p != null; p = succ(p)) {
             Object item = p.getItem();
             if (item != null)
                 s.writeObject(item);
@@ -466,10 +645,11 @@
         throws java.io.IOException, ClassNotFoundException {
         // Read in capacity, and any hidden stuff
         s.defaultReadObject();
-        head = new Node<E>(null, null);
+        head = new Node<E>(null);
         tail = head;
         // Read in all elements and place in queue
         for (;;) {
+            @SuppressWarnings("unchecked")
             E item = (E)s.readObject();
             if (item == null)
                 break;
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/ConcurrentMap.java b/libcore/concurrent/src/main/java/java/util/concurrent/ConcurrentMap.java
index 32dc000..2daebc5 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/ConcurrentMap.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/ConcurrentMap.java
@@ -15,10 +15,17 @@
  * A {@link java.util.Map} providing additional atomic
  * <tt>putIfAbsent</tt>, <tt>remove</tt>, and <tt>replace</tt> methods.
  *
+ * <p>Memory consistency effects: As with other concurrent
+ * collections, actions in a thread prior to placing an object into a
+ * {@code ConcurrentMap} as a key or value
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * actions subsequent to the access or removal of that object from
+ * the {@code ConcurrentMap} in another thread.
+ *
  * @since 1.5
  * @author Doug Lea
  * @param <K> the type of keys maintained by this map
- * @param <V> the type of mapped values 
+ * @param <V> the type of mapped values
  */
 public interface ConcurrentMap<K, V> extends Map<K, V> {
     /**
@@ -26,93 +33,102 @@
      * with a value, associate it with the given value.
      * This is equivalent to
      * <pre>
-     *   if (!map.containsKey(key)) 
-     *      return map.put(key, value);
+     *   if (!map.containsKey(key))
+     *       return map.put(key, value);
      *   else
-     *      return map.get(key);
-     * </pre>
-     * Except that the action is performed atomically.
-     * @param key key with which the specified value is to be associated.
-     * @param value value to be associated with the specified key.
-     * @return previous value associated with specified key, or <tt>null</tt>
-     *         if there was no mapping for key.  A <tt>null</tt> return can
-     *         also indicate that the map previously associated <tt>null</tt>
-     *         with the specified key, if the implementation supports
-     *         <tt>null</tt> values.
+     *       return map.get(key);</pre>
+     * except that the action is performed atomically.
      *
-     * @throws UnsupportedOperationException if the <tt>put</tt> operation is
-     *            not supported by this map.
+     * @param key key with which the specified value is to be associated
+     * @param value value to be associated with the specified key
+     * @return the previous value associated with the specified key, or
+     *         <tt>null</tt> if there was no mapping for the key.
+     *         (A <tt>null</tt> return can also indicate that the map
+     *         previously associated <tt>null</tt> with the key,
+     *         if the implementation supports null values.)
+     * @throws UnsupportedOperationException if the <tt>put</tt> operation
+     *         is not supported by this map
      * @throws ClassCastException if the class of the specified key or value
-     *            prevents it from being stored in this map.
-     * @throws IllegalArgumentException if some aspect of this key or value
-     *            prevents it from being stored in this map.
-     * @throws NullPointerException if this map does not permit <tt>null</tt>
-     *            keys or values, and the specified key or value is
-     *            <tt>null</tt>.
+     *         prevents it from being stored in this map
+     * @throws NullPointerException if the specified key or value is null,
+     *         and this map does not permit null keys or values
+     * @throws IllegalArgumentException if some property of the specified key
+     *         or value prevents it from being stored in this map
      *
      */
     V putIfAbsent(K key, V value);
 
     /**
-     * Remove entry for key only if currently mapped to given value.
-     * Acts as
-     * <pre> 
-     *  if ((map.containsKey(key) && map.get(key).equals(value)) {
-     *     map.remove(key);
-     *     return true;
-     * } else return false;
-     * </pre>
+     * Removes the entry for a key only if currently mapped to a given value.
+     * This is equivalent to
+     * <pre>
+     *   if (map.containsKey(key) &amp;&amp; map.get(key).equals(value)) {
+     *       map.remove(key);
+     *       return true;
+     *   } else return false;</pre>
      * except that the action is performed atomically.
-     * @param key key with which the specified value is associated.
-     * @param value value associated with the specified key.
-     * @return true if the value was removed, false otherwise
-     * @throws NullPointerException if this map does not permit <tt>null</tt>
-     *            keys or values, and the specified key or value is
-     *            <tt>null</tt>.
+     *
+     * @param key key with which the specified value is associated
+     * @param value value expected to be associated with the specified key
+     * @return <tt>true</tt> if the value was removed
+     * @throws UnsupportedOperationException if the <tt>remove</tt> operation
+     *         is not supported by this map
+     * @throws ClassCastException if the key or value is of an inappropriate
+     *         type for this map (optional)
+     * @throws NullPointerException if the specified key or value is null,
+     *         and this map does not permit null keys or values (optional)
      */
     boolean remove(Object key, Object value);
 
-
     /**
-     * Replace entry for key only if currently mapped to given value.
-     * Acts as
-     * <pre> 
-     *  if ((map.containsKey(key) && map.get(key).equals(oldValue)) {
-     *     map.put(key, newValue);
-     *     return true;
-     * } else return false;
-     * </pre>
+     * Replaces the entry for a key only if currently mapped to a given value.
+     * This is equivalent to
+     * <pre>
+     *   if (map.containsKey(key) &amp;&amp; map.get(key).equals(oldValue)) {
+     *       map.put(key, newValue);
+     *       return true;
+     *   } else return false;</pre>
      * except that the action is performed atomically.
-     * @param key key with which the specified value is associated.
-     * @param oldValue value expected to be associated with the specified key.
-     * @param newValue value to be associated with the specified key.
-     * @return true if the value was replaced
-     * @throws NullPointerException if this map does not permit <tt>null</tt>
-     *            keys or values, and the specified key or value is
-     *            <tt>null</tt>.
+     *
+     * @param key key with which the specified value is associated
+     * @param oldValue value expected to be associated with the specified key
+     * @param newValue value to be associated with the specified key
+     * @return <tt>true</tt> if the value was replaced
+     * @throws UnsupportedOperationException if the <tt>put</tt> operation
+     *         is not supported by this map
+     * @throws ClassCastException if the class of a specified key or value
+     *         prevents it from being stored in this map
+     * @throws NullPointerException if a specified key or value is null,
+     *         and this map does not permit null keys or values
+     * @throws IllegalArgumentException if some property of a specified key
+     *         or value prevents it from being stored in this map
      */
     boolean replace(K key, V oldValue, V newValue);
 
     /**
-     * Replace entry for key only if currently mapped to some value.
-     * Acts as
-     * <pre> 
-     *  if ((map.containsKey(key)) {
-     *     return map.put(key, value);
-     * } else return null;
-     * </pre>
+     * Replaces the entry for a key only if currently mapped to some value.
+     * This is equivalent to
+     * <pre>
+     *   if (map.containsKey(key)) {
+     *       return map.put(key, value);
+     *   } else return null;</pre>
      * except that the action is performed atomically.
-     * @param key key with which the specified value is associated.
-     * @param value value to be associated with the specified key.
-     * @return previous value associated with specified key, or <tt>null</tt>
-     *         if there was no mapping for key.  A <tt>null</tt> return can
-     *         also indicate that the map previously associated <tt>null</tt>
-     *         with the specified key, if the implementation supports
-     *         <tt>null</tt> values.
-     * @throws NullPointerException if this map does not permit <tt>null</tt>
-     *            keys or values, and the specified key or value is
-     *            <tt>null</tt>.
+     *
+     * @param key key with which the specified value is associated
+     * @param value value to be associated with the specified key
+     * @return the previous value associated with the specified key, or
+     *         <tt>null</tt> if there was no mapping for the key.
+     *         (A <tt>null</tt> return can also indicate that the map
+     *         previously associated <tt>null</tt> with the key,
+     *         if the implementation supports null values.)
+     * @throws UnsupportedOperationException if the <tt>put</tt> operation
+     *         is not supported by this map
+     * @throws ClassCastException if the class of the specified key or value
+     *         prevents it from being stored in this map
+     * @throws NullPointerException if the specified key or value is null,
+     *         and this map does not permit null keys or values
+     * @throws IllegalArgumentException if some property of the specified key
+     *         or value prevents it from being stored in this map
      */
     V replace(K key, V value);
-
 }
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/CopyOnWriteArrayList.java b/libcore/concurrent/src/main/java/java/util/concurrent/CopyOnWriteArrayList.java
index 7274595..f0c8ac6 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/CopyOnWriteArrayList.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/CopyOnWriteArrayList.java
@@ -1,1190 +1,1317 @@
 /*
- * 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.
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group.  Adapted and released, under explicit permission,
+ * from JDK ArrayList.java which carries the following copyright:
+ *
+ * Copyright 1997 by Sun Microsystems, Inc.,
+ * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
+ * All rights reserved.
+ *
+ * This software is the confidential and proprietary information
+ * of Sun Microsystems, Inc. ("Confidential Information").  You
+ * shall not disclose such Confidential Information and shall use
+ * it only in accordance with the terms of the license agreement
+ * you entered into with Sun.
  */
 
 package java.util.concurrent;
-
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Serializable;
+import java.util.*;
+import java.util.concurrent.locks.*;
 import java.lang.reflect.Array;
-import java.util.Collection;
-import java.util.ConcurrentModificationException;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.NoSuchElementException;
-import java.util.RandomAccess;
-import java.util.concurrent.locks.ReentrantLock;
 
-// BEGIN android-added
+import sun.misc.Unsafe;
+
+// BEGIN android-note
+// removed link to collections framework docs
+// END android-note
+
 /**
- * Implements a {@link java.util.ArrayList} variant that is thread-safe. All
- * write operation result in a new copy of the underlying data being created.
- * Iterators reflect the state of the CopyOnWriteArrayList at the time they were
- * created. They are not updated to reflect subsequent changes to the list. In
- * addition, these iterators cannot be used for modifying the underlying
- * CopyOnWriteArrayList.
- * 
- * @param <E> the element type
+ * A thread-safe variant of {@link java.util.ArrayList} in which all mutative
+ * operations (<tt>add</tt>, <tt>set</tt>, and so on) are implemented by
+ * making a fresh copy of the underlying array.
+ *
+ * <p> This is ordinarily too costly, but may be <em>more</em> efficient
+ * than alternatives when traversal operations vastly outnumber
+ * mutations, and is useful when you cannot or don't want to
+ * synchronize traversals, yet need to preclude interference among
+ * concurrent threads.  The "snapshot" style iterator method uses a
+ * reference to the state of the array at the point that the iterator
+ * was created. This array never changes during the lifetime of the
+ * iterator, so interference is impossible and the iterator is
+ * guaranteed not to throw <tt>ConcurrentModificationException</tt>.
+ * The iterator will not reflect additions, removals, or changes to
+ * the list since the iterator was created.  Element-changing
+ * operations on iterators themselves (<tt>remove</tt>, <tt>set</tt>, and
+ * <tt>add</tt>) are not supported. These methods throw
+ * <tt>UnsupportedOperationException</tt>.
+ *
+ * <p>All elements are permitted, including <tt>null</tt>.
+ *
+ * <p>Memory consistency effects: As with other concurrent
+ * collections, actions in a thread prior to placing an object into a
+ * {@code CopyOnWriteArrayList}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * actions subsequent to the access or removal of that element from
+ * the {@code CopyOnWriteArrayList} in another thread.
+ *
+ * @since 1.5
+ * @author Doug Lea
+ * @param <E> the type of elements held in this collection
  */
-// END android-added
-public class CopyOnWriteArrayList<E> implements List<E>, RandomAccess, Cloneable, Serializable {
-
+public class CopyOnWriteArrayList<E>
+    implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
     private static final long serialVersionUID = 8673264195747942595L;
 
-    private transient volatile E[] arr;
+    /** The lock protecting all mutators */
+    transient final ReentrantLock lock = new ReentrantLock();
+
+    /** The array, accessed only via getArray/setArray. */
+    private volatile transient Object[] array;
 
     /**
-     * Lock for the queue write methods
+     * Gets the array.  Non-private so as to also be accessible
+     * from CopyOnWriteArraySet class.
      */
-    private final transient ReentrantLock lock = new ReentrantLock();
+    final Object[] getArray() {
+        return array;
+    }
 
-    // BEGIN android-added
     /**
-     * Creates a new, empty instance of CopyOnWriteArrayList. 
+     * Sets the array.
      */
-    // END android-added
+    final void setArray(Object[] a) {
+        array = a;
+    }
+
+    /**
+     * Creates an empty list.
+     */
     public CopyOnWriteArrayList() {
+        setArray(new Object[0]);
     }
 
-    // BEGIN android-added
     /**
-     * Creates a new instance of CopyOnWriteArrayList and fills it with the
-     * contents of a given Collection.
-     * 
-     * @param c     the collection the elements of which are to be copied into
-     *              the new instance.
+     * Creates a list containing the elements of the specified
+     * collection, in the order they are returned by the collection's
+     * iterator.
+     *
+     * @param c the collection of initially held elements
+     * @throws NullPointerException if the specified collection is null
      */
-    // END android-added
     public CopyOnWriteArrayList(Collection<? extends E> c) {
-        this((E[]) c.toArray());
+        Object[] elements = c.toArray();
+        // c.toArray might (incorrectly) not return Object[] (see 6260652)
+        if (elements.getClass() != Object[].class)
+            elements = Java6Arrays.copyOf(elements, elements.length, Object[].class);
+        setArray(elements);
     }
 
-    // BEGIN android-added
     /**
-     * Creates a new instance of CopyOnWriteArrayList and fills it with the
-     * contents of a given array.
-     * 
-     * @param array the array the elements of which are to be copied into the
-     *              new instance.
+     * Creates a list holding a copy of the given array.
+     *
+     * @param toCopyIn the array (a copy of this array is used as the
+     *        internal array)
+     * @throws NullPointerException if the specified array is null
      */
-    // END android-added
-    public CopyOnWriteArrayList(E[] array) {
-        int size = array.length;
-        E[] data = newElementArray(size);
-        for (int i = 0; i < size; i++) {
-            data[i] = array[i];
-        }
-        arr = data;
+    public CopyOnWriteArrayList(E[] toCopyIn) {
+        setArray(Java6Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class));
     }
 
-    public boolean add(E e) {
-        lock.lock();
-        try {
-            E[] data;
-            E[] old = getData();
-            int size = old.length;
-            data = newElementArray(size + 1);
-            System.arraycopy(old, 0, data, 0, size);
-            data[size] = e;
-            setData(data);
-            return true;
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    public void add(int index, E e) {
-        lock.lock();
-        try {
-            E[] data;
-            E[] old = getData();
-            int size = old.length;
-            checkIndexInclusive(index, size);
-            data = newElementArray(size+1);
-            System.arraycopy(old, 0, data, 0, index);
-            data[index] = e;
-            if (size > index) {
-                System.arraycopy(old, index, data, index + 1, size - index);
-            }
-            setData(data);
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    public boolean addAll(Collection<? extends E> c) {
-        Iterator it = c.iterator();
-        int ssize = c.size();
-        lock.lock();
-        try {
-            int size = size();
-            E[] data;
-            E[] old = getData();
-            int nSize = size + ssize;
-            data = newElementArray(nSize);
-            System.arraycopy(old, 0, data, 0, size);
-            while (it.hasNext()) {
-                data[size++] = (E) it.next();
-            }
-            setData(data);
-        } finally {
-            lock.unlock();
-        }
-        return true;
-    }
-
-    public boolean addAll(int index, Collection<? extends E> c) {
-        Iterator it = c.iterator();
-        int ssize = c.size();
-        lock.lock();
-        try {
-            int size = size();
-            checkIndexInclusive(index, size);
-            E[] data;
-            E[] old = getData();
-            int nSize = size + ssize;
-            data = newElementArray(nSize);
-            System.arraycopy(old, 0, data, 0, index);
-            int i = index;
-            while (it.hasNext()) {
-                data[i++] = (E) it.next();
-            }
-            if (size > index) {
-                System.arraycopy(old, index, data, index + ssize, size - index);
-            }
-            setData(data);
-        } finally {
-            lock.unlock();
-        }
-        return true;
-    }
-
-    // BEGIN android-added
     /**
-     * Adds to this CopyOnWriteArrayList all those elements from a given
-     * collection that are not yet part of the list.
-     * 
-     * @param c     the collection from which the potential new elements are
-     *              taken.
-     * 
-     * @return the number of elements actually added to this list.
+     * Returns the number of elements in this list.
+     *
+     * @return the number of elements in this list
      */
-    // END android-added
-    public int addAllAbsent(Collection<? extends E> c) {
-        if (c.size() == 0) {
-            return 0;
-        }
-        lock.lock();
-        try {
-            E[] old = getData();
-            int size = old.length;
-            E[] toAdd = newElementArray(c.size());
-            int i = 0;
-            for (Iterator it = c.iterator(); it.hasNext();) {
-                E o = (E) it.next();
-                if (indexOf(o) < 0) {
-                    toAdd[i++] = o;
-                }
-            }
-            E[] data = newElementArray(size + i);
-            System.arraycopy(old, 0, data, 0, size);
-            System.arraycopy(toAdd, 0, data, size, i);
-            setData(data);
-            return i;
-        } finally {
-            lock.unlock();
-        }
+    public int size() {
+        return getArray().length;
     }
 
-    // BEGIN android-added
     /**
-     * Adds to this CopyOnWriteArrayList another element, given that this
-     * element is not yet part of the list.
-     * 
-     * @param e     the potential new element.
-     * 
-     * @return true if the element was added, or false otherwise.
+     * Returns <tt>true</tt> if this list contains no elements.
+     *
+     * @return <tt>true</tt> if this list contains no elements
      */
-    // END android-added
-    public boolean addIfAbsent(E e) {
-        lock.lock();
-        try {
-            E[] data;
-            E[] old = getData();
-            int size = old.length;
-            if (size != 0) {
-                if (indexOf(e) >= 0) {
-                    return false;
-                }
-            }
-            data = newElementArray(size + 1);
-            System.arraycopy(old, 0, data, 0, size);
-            data[size] = e;
-            setData(data);
-            return true;
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    public void clear() {
-        lock.lock();
-        try {
-            setData(newElementArray(0));
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    @Override
-    public Object clone() {
-        try {
-            CopyOnWriteArrayList thisClone = (CopyOnWriteArrayList) super.clone();
-            thisClone.setData(this.getData());
-            return thisClone;
-        } catch (CloneNotSupportedException e) {
-            throw new RuntimeException("CloneNotSupportedException is not expected here");
-        }
-    }
-
-    public boolean contains(Object o) {
-        return indexOf(o) >= 0;
-    }
-
-    public boolean containsAll(Collection<?> c) {
-        E[] data = getData();
-        return containsAll(c, data, 0, data.length);
-    }
-
-    public boolean equals(Object o) {
-        if (o == this) {
-            return true;
-        }
-        if (!(o instanceof List)) {
-            return false;
-        }
-        List l = (List) o;
-        Iterator it = l.listIterator();
-        Iterator ourIt = listIterator();
-        while (it.hasNext()) {
-            if (!ourIt.hasNext()) {
-                return false;
-            }
-            Object thisListElem = it.next();
-            Object anotherListElem = ourIt.next();
-            if (!(thisListElem == null ? anotherListElem == null : thisListElem
-                    .equals(anotherListElem))) {
-                return false;
-            }
-        }
-        if (ourIt.hasNext()) {
-            return false;
-        }
-        return true;
-    }
-
-    public E get(int index) {
-        E[] data = getData();
-        return data[index];
-    }
-
-    public int hashCode() {
-        int hashCode = 1;
-        Iterator it = listIterator();
-        while (it.hasNext()) {
-            Object obj = it.next();
-            hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
-        }
-        return hashCode;
-    }
-
-    // BEGIN android-added
-    /**
-     * Returns the index of a given element, starting the search from a given
-     * position in the list. 
-     * 
-     * @param e     the element to search.
-     * @param index the index at which to start the search.
-     * 
-     * @return the index of the element or null, if the element has not been
-     * found at or beyond the given start index.
-     */
-    // END android-added
-    public int indexOf(E e, int index) {
-        E[] data = getData();
-        return indexOf(e, data, index, data.length - index);
-    }
-
-    public int indexOf(Object o) {
-        E[] data = getData();
-        return indexOf(o, data, 0, data.length);
-    }
-
     public boolean isEmpty() {
         return size() == 0;
     }
 
-    public Iterator<E> iterator() {
-        return new ListIteratorImpl(getData(), 0);
-    }
-
-    // BEGIN android-added
     /**
-     * Returns the last index of a given element, starting the search from
-     * a given position in the list and going backwards. 
-     * 
-     * @param e     the element to search.
-     * @param index the index at which to start the search.
-     * 
-     * @return the index of the element or null, if the element has not been
-     * found at or before the given start index.
+     * Test for equality, coping with nulls.
      */
-    // END android-added
-    public int lastIndexOf(E e, int index) {
-        E[] data = getData();
-        return lastIndexOf(e, data, 0, index);
+    private static boolean eq(Object o1, Object o2) {
+        return (o1 == null ? o2 == null : o1.equals(o2));
     }
 
+    /**
+     * static version of indexOf, to allow repeated calls without
+     * needing to re-acquire array each time.
+     * @param o element to search for
+     * @param elements the array
+     * @param index first index to search
+     * @param fence one past last index to search
+     * @return index of element, or -1 if absent
+     */
+    private static int indexOf(Object o, Object[] elements,
+                               int index, int fence) {
+        if (o == null) {
+            for (int i = index; i < fence; i++)
+                if (elements[i] == null)
+                    return i;
+        } else {
+            for (int i = index; i < fence; i++)
+                if (o.equals(elements[i]))
+                    return i;
+        }
+        return -1;
+    }
+
+    /**
+     * static version of lastIndexOf.
+     * @param o element to search for
+     * @param elements the array
+     * @param index first index to search
+     * @return index of element, or -1 if absent
+     */
+    private static int lastIndexOf(Object o, Object[] elements, int index) {
+        if (o == null) {
+            for (int i = index; i >= 0; i--)
+                if (elements[i] == null)
+                    return i;
+        } else {
+            for (int i = index; i >= 0; i--)
+                if (o.equals(elements[i]))
+                    return i;
+        }
+        return -1;
+    }
+
+    /**
+     * Returns <tt>true</tt> if this list contains the specified element.
+     * More formally, returns <tt>true</tt> if and only if this list contains
+     * at least one element <tt>e</tt> such that
+     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
+     *
+     * @param o element whose presence in this list is to be tested
+     * @return <tt>true</tt> if this list contains the specified element
+     */
+    public boolean contains(Object o) {
+        Object[] elements = getArray();
+        return indexOf(o, elements, 0, elements.length) >= 0;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int indexOf(Object o) {
+        Object[] elements = getArray();
+        return indexOf(o, elements, 0, elements.length);
+    }
+
+    /**
+     * Returns the index of the first occurrence of the specified element in
+     * this list, searching forwards from <tt>index</tt>, or returns -1 if
+     * the element is not found.
+     * More formally, returns the lowest index <tt>i</tt> such that
+     * <tt>(i&nbsp;&gt;=&nbsp;index&nbsp;&amp;&amp;&nbsp;(e==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;e.equals(get(i))))</tt>,
+     * or -1 if there is no such index.
+     *
+     * @param e element to search for
+     * @param index index to start searching from
+     * @return the index of the first occurrence of the element in
+     *         this list at position <tt>index</tt> or later in the list;
+     *         <tt>-1</tt> if the element is not found.
+     * @throws IndexOutOfBoundsException if the specified index is negative
+     */
+    public int indexOf(E e, int index) {
+        Object[] elements = getArray();
+        return indexOf(e, elements, index, elements.length);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
     public int lastIndexOf(Object o) {
-        E[] data = getData();
-        return lastIndexOf(o, data, 0, data.length);
+        Object[] elements = getArray();
+        return lastIndexOf(o, elements, elements.length - 1);
     }
 
-    public ListIterator<E> listIterator() {
-        return new ListIteratorImpl(getData(), 0);
+    /**
+     * Returns the index of the last occurrence of the specified element in
+     * this list, searching backwards from <tt>index</tt>, or returns -1 if
+     * the element is not found.
+     * More formally, returns the highest index <tt>i</tt> such that
+     * <tt>(i&nbsp;&lt;=&nbsp;index&nbsp;&amp;&amp;&nbsp;(e==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;e.equals(get(i))))</tt>,
+     * or -1 if there is no such index.
+     *
+     * @param e element to search for
+     * @param index index to start searching backwards from
+     * @return the index of the last occurrence of the element at position
+     *         less than or equal to <tt>index</tt> in this list;
+     *         -1 if the element is not found.
+     * @throws IndexOutOfBoundsException if the specified index is greater
+     *         than or equal to the current size of this list
+     */
+    public int lastIndexOf(E e, int index) {
+        Object[] elements = getArray();
+        return lastIndexOf(e, elements, index);
     }
 
-    public ListIterator<E> listIterator(int index) {
-        E[] data = getData();
-        checkIndexInclusive(index, data.length);
-        return new ListIteratorImpl(data, index);
+    /**
+     * Returns a shallow copy of this list.  (The elements themselves
+     * are not copied.)
+     *
+     * @return a clone of this list
+     */
+    public Object clone() {
+        try {
+            CopyOnWriteArrayList c = (CopyOnWriteArrayList)(super.clone());
+            c.resetLock();
+            return c;
+        } catch (CloneNotSupportedException e) {
+            // this shouldn't happen, since we are Cloneable
+            throw new InternalError();
+        }
     }
 
-    public E remove(int index) {
-        return removeRange(index, 1);
+    /**
+     * Returns an array containing all of the elements in this list
+     * in proper sequence (from first to last element).
+     *
+     * <p>The returned array will be "safe" in that no references to it are
+     * maintained by this list.  (In other words, this method must allocate
+     * a new array).  The caller is thus free to modify the returned array.
+     *
+     * <p>This method acts as bridge between array-based and collection-based
+     * APIs.
+     *
+     * @return an array containing all the elements in this list
+     */
+    public Object[] toArray() {
+        Object[] elements = getArray();
+        return Java6Arrays.copyOf(elements, elements.length);
     }
 
-    public boolean remove(Object o) {
+    /**
+     * Returns an array containing all of the elements in this list in
+     * proper sequence (from first to last element); the runtime type of
+     * the returned array is that of the specified array.  If the list fits
+     * in the specified array, it is returned therein.  Otherwise, a new
+     * array is allocated with the runtime type of the specified array and
+     * the size of this list.
+     *
+     * <p>If this list fits in the specified array with room to spare
+     * (i.e., the array has more elements than this list), the element in
+     * the array immediately following the end of the list is set to
+     * <tt>null</tt>.  (This is useful in determining the length of this
+     * list <i>only</i> if the caller knows that this list does not contain
+     * any null elements.)
+     *
+     * <p>Like the {@link #toArray()} method, this method acts as bridge between
+     * array-based and collection-based APIs.  Further, this method allows
+     * precise control over the runtime type of the output array, and may,
+     * under certain circumstances, be used to save allocation costs.
+     *
+     * <p>Suppose <tt>x</tt> is a list known to contain only strings.
+     * The following code can be used to dump the list into a newly
+     * allocated array of <tt>String</tt>:
+     *
+     * <pre>
+     *     String[] y = x.toArray(new String[0]);</pre>
+     *
+     * Note that <tt>toArray(new Object[0])</tt> is identical in function to
+     * <tt>toArray()</tt>.
+     *
+     * @param a the array into which the elements of the list are to
+     *          be stored, if it is big enough; otherwise, a new array of the
+     *          same runtime type is allocated for this purpose.
+     * @return an array containing all the elements in this list
+     * @throws ArrayStoreException if the runtime type of the specified array
+     *         is not a supertype of the runtime type of every element in
+     *         this list
+     * @throws NullPointerException if the specified array is null
+     */
+    @SuppressWarnings("unchecked")
+    public <T> T[] toArray(T a[]) {
+        Object[] elements = getArray();
+        int len = elements.length;
+        if (a.length < len)
+            return (T[]) Java6Arrays.copyOf(elements, len, a.getClass());
+        else {
+            System.arraycopy(elements, 0, a, 0, len);
+            if (a.length > len)
+                a[len] = null;
+            return a;
+        }
+    }
+
+    // Positional Access Operations
+
+    @SuppressWarnings("unchecked")
+    private E get(Object[] a, int index) {
+        return (E) a[index];
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @throws IndexOutOfBoundsException {@inheritDoc}
+     */
+    public E get(int index) {
+        return get(getArray(), index);
+    }
+
+    /**
+     * Replaces the element at the specified position in this list with the
+     * specified element.
+     *
+     * @throws IndexOutOfBoundsException {@inheritDoc}
+     */
+    public E set(int index, E element) {
+        final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            int index = indexOf(o);
-            if (index == -1) {
-                return false;
+            Object[] elements = getArray();
+            E oldValue = get(elements, index);
+
+            if (oldValue != element) {
+                int len = elements.length;
+                Object[] newElements = Java6Arrays.copyOf(elements, len);
+                newElements[index] = element;
+                setArray(newElements);
+            } else {
+                // Not quite a no-op; ensures volatile write semantics
+                setArray(elements);
             }
-            remove(index);
+            return oldValue;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Appends the specified element to the end of this list.
+     *
+     * @param e element to be appended to this list
+     * @return <tt>true</tt> (as specified by {@link Collection#add})
+     */
+    public boolean add(E e) {
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            Object[] elements = getArray();
+            int len = elements.length;
+            Object[] newElements = Java6Arrays.copyOf(elements, len + 1);
+            newElements[len] = e;
+            setArray(newElements);
             return true;
         } finally {
             lock.unlock();
         }
     }
 
-    public boolean removeAll(Collection<?> c) {
+    /**
+     * Inserts the specified element at the specified position in this
+     * list. Shifts the element currently at that position (if any) and
+     * any subsequent elements to the right (adds one to their indices).
+     *
+     * @throws IndexOutOfBoundsException {@inheritDoc}
+     */
+    public void add(int index, E element) {
+        final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            return removeAll(c, 0, getData().length) != 0;
+            Object[] elements = getArray();
+            int len = elements.length;
+            if (index > len || index < 0)
+                throw new IndexOutOfBoundsException("Index: "+index+
+                                                    ", Size: "+len);
+            Object[] newElements;
+            int numMoved = len - index;
+            if (numMoved == 0)
+                newElements = Java6Arrays.copyOf(elements, len + 1);
+            else {
+                newElements = new Object[len + 1];
+                System.arraycopy(elements, 0, newElements, 0, index);
+                System.arraycopy(elements, index, newElements, index + 1,
+                                 numMoved);
+            }
+            newElements[index] = element;
+            setArray(newElements);
         } finally {
             lock.unlock();
         }
     }
 
-    public boolean retainAll(Collection<?> c) {
-        if (c == null) {
-            throw new NullPointerException();
-        }
+    /**
+     * Removes the element at the specified position in this list.
+     * Shifts any subsequent elements to the left (subtracts one from their
+     * indices).  Returns the element that was removed from the list.
+     *
+     * @throws IndexOutOfBoundsException {@inheritDoc}
+     */
+    public E remove(int index) {
+        final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            return retainAll(c, 0, getData().length) != 0;
+            Object[] elements = getArray();
+            int len = elements.length;
+            E oldValue = get(elements, index);
+            int numMoved = len - index - 1;
+            if (numMoved == 0)
+                setArray(Java6Arrays.copyOf(elements, len - 1));
+            else {
+                Object[] newElements = new Object[len - 1];
+                System.arraycopy(elements, 0, newElements, 0, index);
+                System.arraycopy(elements, index + 1, newElements, index,
+                                 numMoved);
+                setArray(newElements);
+            }
+            return oldValue;
         } finally {
             lock.unlock();
         }
     }
 
-    public E set(int index, E e) {
+    /**
+     * Removes the first occurrence of the specified element from this list,
+     * if it is present.  If this list does not contain the element, it is
+     * unchanged.  More formally, removes the element with the lowest index
+     * <tt>i</tt> such that
+     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>
+     * (if such an element exists).  Returns <tt>true</tt> if this list
+     * contained the specified element (or equivalently, if this list
+     * changed as a result of the call).
+     *
+     * @param o element to be removed from this list, if present
+     * @return <tt>true</tt> if this list contained the specified element
+     */
+    public boolean remove(Object o) {
+        final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            int size = size();
-            checkIndexExlusive(index, size);
-            E[] data;
-            data = newElementArray(size);
-            E[] oldArr = getData();
-            System.arraycopy(oldArr, 0, data, 0, size);
-            E old = data[index];
-            data[index] = e;
-            setData(data);
-            return old;
-        } finally {
-            lock.unlock();
-        }
-    }
+            Object[] elements = getArray();
+            int len = elements.length;
+            if (len != 0) {
+                // Copy while searching for element to remove
+                // This wins in the normal case of element being present
+                int newlen = len - 1;
+                Object[] newElements = new Object[newlen];
 
-    public int size() {
-        return getData().length;
-    }
+                for (int i = 0; i < newlen; ++i) {
+                    if (eq(o, elements[i])) {
+                        // found one;  copy remaining and exit
+                        for (int k = i + 1; k < len; ++k)
+                            newElements[k-1] = elements[k];
+                        setArray(newElements);
+                        return true;
+                    } else
+                        newElements[i] = elements[i];
+                }
 
-    public List<E> subList(int fromIndex, int toIndex) {
-        return new SubList(this, fromIndex, toIndex);
-    }
-
-    public Object[] toArray() {
-        E[] data = getData();
-        return toArray(data, 0, data.length);
-    }
-
-    public <T> T[] toArray(T[] a) {
-        E[] data = getData();
-        return (T[]) toArray(a, data, 0, data.length);
-    }
-
-    @Override
-    public String toString() {
-        StringBuffer sb = new StringBuffer("[");
-
-        Iterator it = listIterator();
-        while (it.hasNext()) {
-            sb.append(String.valueOf(it.next()));
-            sb.append(", ");
-        }
-        if (sb.length() > 1) {
-            sb.setLength(sb.length() - 2);
-        }
-        sb.append("]");
-        return sb.toString();
-    }
-
-    // private and package private methods
-
-    @SuppressWarnings("unchecked")
-    private final E[] newElementArray(int size) {
-        return (E[])new Object[size];
-    }
-
-    /**
-     * sets the internal data array
-     *
-     * @param data array to set
-     */
-    private final void setData(E[] data) {
-        arr = data;
-    }
-
-    /**
-     * gets the internal data array
-     *
-     * @return the data array
-     */
-    final E[] getData() {
-        if (arr == null) {
-            return newElementArray(0);
-        }
-        return arr;
-    }
-
-    /**
-     * Removes from the specified range of this list
-     * all the elements that are contained in the specified collection
-     * <p/>
-     * !should be called under lock
-     *
-     * @return Returns the number of removed elements
-     */
-    final int removeAll(Collection c, int start, int size) {
-        int ssize = c.size();
-        if (ssize == 0) {
-            return 0;
-        }
-        Object[] old = getData();
-        int arrsize = old.length;
-        if (arrsize == 0) {
-            return 0;
-        }
-        Object[] data = new Object[size];
-        int j = 0;
-        for (int i = start; i < (start + size); i++) {
-            if (!c.contains(old[i])) {
-                data[j++] = old[i];
+                // special handling for last cell
+                if (eq(o, elements[newlen])) {
+                    setArray(newElements);
+                    return true;
+                }
             }
-        }
-        if (j != size) {
-            E[] result = newElementArray(arrsize - (size - j));
-            System.arraycopy(old, 0, result, 0, start);
-            System.arraycopy(data, 0, result, start, j);
-            System.arraycopy(old, start + size, result, start + j, arrsize
-                    - (start + size));
-            setData(result);
-            return (size - j);
-        }
-        return 0;
-    }
-
-    /**
-     * Retains only the elements in the specified range of this list
-     * that are contained in the specified collection
-     *
-     * @return Returns the number of removed elements
-     */
-    // should be called under lock
-    int retainAll(Collection c, int start, int size) {
-        Object[] old = getData();
-        if (size == 0) {
-            return 0;
-        }
-        if (c.size() == 0) {
-            E[] data;
-            if (size == old.length) {
-                data = newElementArray(0);
-            } else {
-                data = newElementArray(old.length - size);
-                System.arraycopy(old, 0, data, 0, start);
-                System.arraycopy(old, start + size, data, start, old.length
-                        - start - size);
-            }
-            setData(data);
-            return size;
-        }
-        Object[] temp = new Object[size];
-        int pos = 0;
-        for (int i = start; i < (start + size); i++) {
-            if (c.contains(old[i])) {
-                temp[pos++] = old[i];
-            }
-        }
-        if (pos == size) {
-            return 0;
-        }
-        E[] data = newElementArray(pos + old.length - size);
-        System.arraycopy(old, 0, data, 0, start);
-        System.arraycopy(temp, 0, data, start, pos);
-        System.arraycopy(old, start + size, data, start + pos, old.length
-                - start - size);
-        setData(data);
-        return (size - pos);
-    }
-
-    /**
-     * Removes specified range from this list
-     */
-    E removeRange(int start, int size) {
-        lock.lock();
-        try {
-            int sizeArr = size();
-            checkIndexExlusive(start, sizeArr);
-            checkIndexInclusive(start + size, sizeArr);
-            E[] data;
-            data = newElementArray(sizeArr - size);
-            E[] oldArr = getData();
-            System.arraycopy(oldArr, 0, data, 0, start);
-            E old = oldArr[start];
-            if (sizeArr > (start + size)) {
-                System.arraycopy(oldArr, start + size, data, start, sizeArr
-                        - (start + size));
-            }
-            setData(data);
-            return old;
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    // some util static functions to use by iterators and methods
-    /**
-     * Returns an array containing all of the elements
-     * in the specified range of the array in proper sequence
-     */
-    static Object[] toArray(Object[] data, int start, int size) {
-        Object[] result = new Object[size];
-        System.arraycopy(data, start, result, 0, size);
-        return result;
-    }
-
-    /**
-     * Returns an array containing all of the elements
-     * in the specified range of the array in proper sequence,
-     * stores the result in the array, specified by first parameter
-     * (as for public instance method toArray(Object[] to)
-     */
-    static Object[] toArray(Object[] to, Object[] data, int start, int size) {
-        int l = data.length;
-        if (to.length < l) {
-            to = (Object[]) Array.newInstance(to.getClass().getComponentType(),
-                    l);
-        } else {
-            if (to.length > l) {
-                to[l] = null;
-            }
-        }
-        System.arraycopy(data, start, to, 0, size);
-        return to;
-    }
-
-    /**
-     * Checks if the specified range of the
-     * array contains all of the elements in the collection
-     *
-     * @param c     collection with elements
-     * @param data  array where to search the elements
-     * @param start start index
-     * @param size  size of the range
-     */
-    static final boolean containsAll(Collection c, Object[] data, int start,
-                                     int size) {
-        if (size == 0) {
             return false;
+        } finally {
+            lock.unlock();
         }
-        Iterator it = c.iterator();
-        while (it.hasNext()) {
-            Object next = it.next();
-            if (indexOf(next, data, start, size) < 0) {
-                return false;
+    }
+
+    /**
+     * Removes from this list all of the elements whose index is between
+     * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive.
+     * Shifts any succeeding elements to the left (reduces their index).
+     * This call shortens the list by <tt>(toIndex - fromIndex)</tt> elements.
+     * (If <tt>toIndex==fromIndex</tt>, this operation has no effect.)
+     *
+     * @param fromIndex index of first element to be removed
+     * @param toIndex index after last element to be removed
+     * @throws IndexOutOfBoundsException if fromIndex or toIndex out of range
+     *         (@code{fromIndex < 0 || toIndex > size() || toIndex < fromIndex})
+     */
+    private void removeRange(int fromIndex, int toIndex) {
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            Object[] elements = getArray();
+            int len = elements.length;
+
+            if (fromIndex < 0 || toIndex > len || toIndex < fromIndex)
+                throw new IndexOutOfBoundsException();
+            int newlen = len - (toIndex - fromIndex);
+            int numMoved = len - toIndex;
+            if (numMoved == 0)
+                setArray(Java6Arrays.copyOf(elements, newlen));
+            else {
+                Object[] newElements = new Object[newlen];
+                System.arraycopy(elements, 0, newElements, 0, fromIndex);
+                System.arraycopy(elements, toIndex, newElements,
+                                 fromIndex, numMoved);
+                setArray(newElements);
             }
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Append the element if not present.
+     *
+     * @param e element to be added to this list, if absent
+     * @return <tt>true</tt> if the element was added
+     */
+    public boolean addIfAbsent(E e) {
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            // Copy while checking if already present.
+            // This wins in the most common case where it is not present
+            Object[] elements = getArray();
+            int len = elements.length;
+            Object[] newElements = new Object[len + 1];
+            for (int i = 0; i < len; ++i) {
+                if (eq(e, elements[i]))
+                    return false; // exit, throwing away copy
+                else
+                    newElements[i] = elements[i];
+            }
+            newElements[len] = e;
+            setArray(newElements);
+            return true;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Returns <tt>true</tt> if this list contains all of the elements of the
+     * specified collection.
+     *
+     * @param c collection to be checked for containment in this list
+     * @return <tt>true</tt> if this list contains all of the elements of the
+     *         specified collection
+     * @throws NullPointerException if the specified collection is null
+     * @see #contains(Object)
+     */
+    public boolean containsAll(Collection<?> c) {
+        Object[] elements = getArray();
+        int len = elements.length;
+        for (Object e : c) {
+            if (indexOf(e, elements, 0, len) < 0)
+                return false;
         }
         return true;
     }
 
     /**
-     * Returns the index in the specified range of the data array
-     * of the last occurrence of the specified element
+     * Removes from this list all of its elements that are contained in
+     * the specified collection. This is a particularly expensive operation
+     * in this class because of the need for an internal temporary array.
      *
-     * @param o     element to search
-     * @param data  array where to search
-     * @param start start index
-     * @param size  size of the range
-     * @return
+     * @param c collection containing elements to be removed from this list
+     * @return <tt>true</tt> if this list changed as a result of the call
+     * @throws ClassCastException if the class of an element of this list
+     *         is incompatible with the specified collection (optional)
+     * @throws NullPointerException if this list contains a null element and the
+     *         specified collection does not permit null elements (optional),
+     *         or if the specified collection is null
+     * @see #remove(Object)
      */
-    static final int lastIndexOf(Object o, Object[] data, int start, int size) {
-        if (size == 0) {
-            return -1;
-        }
-        if (o != null) {
-            for (int i = start + size - 1; i > start - 1; i--) {
-                if (o.equals(data[i])) {
-                    return i;
+    public boolean removeAll(Collection<?> c) {
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            Object[] elements = getArray();
+            int len = elements.length;
+            if (len != 0) {
+                // temp array holds those elements we know we want to keep
+                int newlen = 0;
+                Object[] temp = new Object[len];
+                for (int i = 0; i < len; ++i) {
+                    Object element = elements[i];
+                    if (!c.contains(element))
+                        temp[newlen++] = element;
+                }
+                if (newlen != len) {
+                    setArray(Java6Arrays.copyOf(temp, newlen));
+                    return true;
                 }
             }
-        } else {
-            for (int i = start + size - 1; i > start - 1; i--) {
-                if (data[i] == null) {
-                    return i;
-                }
-            }
-        }
-        return -1;
-    }
-
-    /**
-     * Returns the index in the specified range of the data array
-     * of the first occurrence of the specified element
-     *
-     * @param o     element to search
-     * @param data  array where to search
-     * @param start start index
-     * @param size  end index
-     * @return
-     */
-    static final int indexOf(Object o, Object[] data, int start, int size) {
-        if (size == 0) {
-            return -1;
-        }
-        if (o == null) {
-            for (int i = start; i < start + size; i++) {
-                if (data[i] == null) {
-                    return i;
-                }
-            }
-        } else {
-            for (int i = start; i < start + size; i++) {
-                if (o.equals(data[i])) {
-                    return i;
-                }
-            }
-        }
-        return -1;
-    }
-
-    /**
-     * Throws <code>IndexOutOfBoundsException</code> if <code>index</code>
-     * is out of the list bounds.
-     *
-     * @param index element index to check.
-     */
-    static final void checkIndexInclusive(int index, int size) {
-        if (index < 0 || index > size) {
-            throw new IndexOutOfBoundsException("Index is " + index + ", size is " + size);
+            return false;
+        } finally {
+            lock.unlock();
         }
     }
 
     /**
-     * Throws <code>IndexOutOfBoundsException</code> if <code>index</code>
-     * is out of the list bounds. Excluding the last element.
+     * Retains only the elements in this list that are contained in the
+     * specified collection.  In other words, removes from this list all of
+     * its elements that are not contained in the specified collection.
      *
-     * @param index element index to check.
+     * @param c collection containing elements to be retained in this list
+     * @return <tt>true</tt> if this list changed as a result of the call
+     * @throws ClassCastException if the class of an element of this list
+     *         is incompatible with the specified collection (optional)
+     * @throws NullPointerException if this list contains a null element and the
+     *         specified collection does not permit null elements (optional),
+     *         or if the specified collection is null
+     * @see #remove(Object)
      */
-    static final void checkIndexExlusive(int index, int size) {
-        if (index < 0 || index >= size) {
-            throw new IndexOutOfBoundsException("Index is " + index + ", size is " + size);
+    public boolean retainAll(Collection<?> c) {
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            Object[] elements = getArray();
+            int len = elements.length;
+            if (len != 0) {
+                // temp array holds those elements we know we want to keep
+                int newlen = 0;
+                Object[] temp = new Object[len];
+                for (int i = 0; i < len; ++i) {
+                    Object element = elements[i];
+                    if (c.contains(element))
+                        temp[newlen++] = element;
+                }
+                if (newlen != len) {
+                    setArray(Java6Arrays.copyOf(temp, newlen));
+                    return true;
+                }
+            }
+            return false;
+        } finally {
+            lock.unlock();
         }
     }
 
     /**
-     * list iterator implementation,
-     * when created gets snapshot of the list,
-     * so never throws ConcurrentModificationException
+     * Appends all of the elements in the specified collection that
+     * are not already contained in this list, to the end of
+     * this list, in the order that they are returned by the
+     * specified collection's iterator.
+     *
+     * @param c collection containing elements to be added to this list
+     * @return the number of elements added
+     * @throws NullPointerException if the specified collection is null
+     * @see #addIfAbsent(Object)
      */
-    private static class ListIteratorImpl implements ListIterator {
-        private final Object[] arr;
-
-        private int current;
-
-        private final int size;
-
-        final int size() {
-            return size;
+    public int addAllAbsent(Collection<? extends E> c) {
+        Object[] cs = c.toArray();
+        if (cs.length == 0)
+            return 0;
+        Object[] uniq = new Object[cs.length];
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            Object[] elements = getArray();
+            int len = elements.length;
+            int added = 0;
+            for (int i = 0; i < cs.length; ++i) { // scan for duplicates
+                Object e = cs[i];
+                if (indexOf(e, elements, 0, len) < 0 &&
+                    indexOf(e, uniq, 0, added) < 0)
+                    uniq[added++] = e;
+            }
+            if (added > 0) {
+                Object[] newElements = Java6Arrays.copyOf(elements, len + added);
+                System.arraycopy(uniq, 0, newElements, len, added);
+                setArray(newElements);
+            }
+            return added;
+        } finally {
+            lock.unlock();
         }
+    }
 
-        public ListIteratorImpl(Object[] data, int current) {
-            this.current = current;
-            arr = data;
-            size = data.length;
+    /**
+     * Removes all of the elements from this list.
+     * The list will be empty after this call returns.
+     */
+    public void clear() {
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            setArray(new Object[0]);
+        } finally {
+            lock.unlock();
         }
+    }
 
-        public void add(Object o) {
-            throw new UnsupportedOperationException("Unsupported operation add");
+    /**
+     * Appends all of the elements in the specified collection to the end
+     * of this list, in the order that they are returned by the specified
+     * collection's iterator.
+     *
+     * @param c collection containing elements to be added to this list
+     * @return <tt>true</tt> if this list changed as a result of the call
+     * @throws NullPointerException if the specified collection is null
+     * @see #add(Object)
+     */
+    public boolean addAll(Collection<? extends E> c) {
+        Object[] cs = c.toArray();
+        if (cs.length == 0)
+            return false;
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            Object[] elements = getArray();
+            int len = elements.length;
+            Object[] newElements = Java6Arrays.copyOf(elements, len + cs.length);
+            System.arraycopy(cs, 0, newElements, len, cs.length);
+            setArray(newElements);
+            return true;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Inserts all of the elements in the specified collection into this
+     * list, starting at the specified position.  Shifts the element
+     * currently at that position (if any) and any subsequent elements to
+     * the right (increases their indices).  The new elements will appear
+     * in this list in the order that they are returned by the
+     * specified collection's iterator.
+     *
+     * @param index index at which to insert the first element
+     *        from the specified collection
+     * @param c collection containing elements to be added to this list
+     * @return <tt>true</tt> if this list changed as a result of the call
+     * @throws IndexOutOfBoundsException {@inheritDoc}
+     * @throws NullPointerException if the specified collection is null
+     * @see #add(int,Object)
+     */
+    public boolean addAll(int index, Collection<? extends E> c) {
+        Object[] cs = c.toArray();
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            Object[] elements = getArray();
+            int len = elements.length;
+            if (index > len || index < 0)
+                throw new IndexOutOfBoundsException("Index: "+index+
+                                                    ", Size: "+len);
+            if (cs.length == 0)
+                return false;
+            int numMoved = len - index;
+            Object[] newElements;
+            if (numMoved == 0)
+                newElements = Java6Arrays.copyOf(elements, len + cs.length);
+            else {
+                newElements = new Object[len + cs.length];
+                System.arraycopy(elements, 0, newElements, 0, index);
+                System.arraycopy(elements, index,
+                                 newElements, index + cs.length,
+                                 numMoved);
+            }
+            System.arraycopy(cs, 0, newElements, index, cs.length);
+            setArray(newElements);
+            return true;
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Save the state of the list to a stream (i.e., serialize it).
+     *
+     * @serialData The length of the array backing the list is emitted
+     *               (int), followed by all of its elements (each an Object)
+     *               in the proper order.
+     * @param s the stream
+     */
+    private void writeObject(java.io.ObjectOutputStream s)
+        throws java.io.IOException{
+
+        // Write out element count, and any hidden stuff
+        s.defaultWriteObject();
+
+        Object[] elements = getArray();
+        int len = elements.length;
+        // Write out array length
+        s.writeInt(len);
+
+        // Write out all elements in the proper order.
+        for (int i = 0; i < len; i++)
+            s.writeObject(elements[i]);
+    }
+
+    /**
+     * Reconstitute the list from a stream (i.e., deserialize it).
+     * @param s the stream
+     */
+    private void readObject(java.io.ObjectInputStream s)
+        throws java.io.IOException, ClassNotFoundException {
+
+        // Read in size, and any hidden stuff
+        s.defaultReadObject();
+
+        // bind to new lock
+        resetLock();
+
+        // Read in array length and allocate array
+        int len = s.readInt();
+        Object[] elements = new Object[len];
+
+        // Read in all elements in the proper order.
+        for (int i = 0; i < len; i++)
+            elements[i] = s.readObject();
+        setArray(elements);
+    }
+
+    /**
+     * Returns a string representation of this list.  The string
+     * representation consists of the string representations of the list's
+     * elements in the order they are returned by its iterator, enclosed in
+     * square brackets (<tt>"[]"</tt>).  Adjacent elements are separated by
+     * the characters <tt>", "</tt> (comma and space).  Elements are
+     * converted to strings as by {@link String#valueOf(Object)}.
+     *
+     * @return a string representation of this list
+     */
+    public String toString() {
+        return Arrays.toString(getArray());
+    }
+
+    /**
+     * Compares the specified object with this list for equality.
+     * Returns {@code true} if the specified object is the same object
+     * as this object, or if it is also a {@link List} and the sequence
+     * of elements returned by an {@linkplain List#iterator() iterator}
+     * over the specified list is the same as the sequence returned by
+     * an iterator over this list.  The two sequences are considered to
+     * be the same if they have the same length and corresponding
+     * elements at the same position in the sequence are <em>equal</em>.
+     * Two elements {@code e1} and {@code e2} are considered
+     * <em>equal</em> if {@code (e1==null ? e2==null : e1.equals(e2))}.
+     *
+     * @param o the object to be compared for equality with this list
+     * @return {@code true} if the specified object is equal to this list
+     */
+    public boolean equals(Object o) {
+        if (o == this)
+            return true;
+        if (!(o instanceof List))
+            return false;
+
+        List<?> list = (List<?>)(o);
+        Iterator<?> it = list.iterator();
+        Object[] elements = getArray();
+        int len = elements.length;
+        for (int i = 0; i < len; ++i)
+            if (!it.hasNext() || !eq(elements[i], it.next()))
+                return false;
+        if (it.hasNext())
+            return false;
+        return true;
+    }
+
+    /**
+     * Returns the hash code value for this list.
+     *
+     * <p>This implementation uses the definition in {@link List#hashCode}.
+     *
+     * @return the hash code value for this list
+     */
+    public int hashCode() {
+        int hashCode = 1;
+        Object[] elements = getArray();
+        int len = elements.length;
+        for (int i = 0; i < len; ++i) {
+            Object obj = elements[i];
+            hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());
+        }
+        return hashCode;
+    }
+
+    /**
+     * Returns an iterator over the elements in this list in proper sequence.
+     *
+     * <p>The returned iterator provides a snapshot of the state of the list
+     * when the iterator was constructed. No synchronization is needed while
+     * traversing the iterator. The iterator does <em>NOT</em> support the
+     * <tt>remove</tt> method.
+     *
+     * @return an iterator over the elements in this list in proper sequence
+     */
+    public Iterator<E> iterator() {
+        return new COWIterator<E>(getArray(), 0);
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>The returned iterator provides a snapshot of the state of the list
+     * when the iterator was constructed. No synchronization is needed while
+     * traversing the iterator. The iterator does <em>NOT</em> support the
+     * <tt>remove</tt>, <tt>set</tt> or <tt>add</tt> methods.
+     */
+    public ListIterator<E> listIterator() {
+        return new COWIterator<E>(getArray(), 0);
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * <p>The returned iterator provides a snapshot of the state of the list
+     * when the iterator was constructed. No synchronization is needed while
+     * traversing the iterator. The iterator does <em>NOT</em> support the
+     * <tt>remove</tt>, <tt>set</tt> or <tt>add</tt> methods.
+     *
+     * @throws IndexOutOfBoundsException {@inheritDoc}
+     */
+    public ListIterator<E> listIterator(final int index) {
+        Object[] elements = getArray();
+        int len = elements.length;
+        if (index<0 || index>len)
+            throw new IndexOutOfBoundsException("Index: "+index);
+
+        return new COWIterator<E>(elements, index);
+    }
+
+    private static class COWIterator<E> implements ListIterator<E> {
+        /** Snapshot of the array **/
+        private final Object[] snapshot;
+        /** Index of element to be returned by subsequent call to next.  */
+        private int cursor;
+
+        private COWIterator(Object[] elements, int initialCursor) {
+            cursor = initialCursor;
+            snapshot = elements;
         }
 
         public boolean hasNext() {
-            if (current < size) {
-                return true;
-            }
-            return false;
+            return cursor < snapshot.length;
         }
 
         public boolean hasPrevious() {
-            return current > 0;
+            return cursor > 0;
         }
 
-        public Object next() {
-            if (hasNext()) {
-                return arr[current++];
-            }
-            throw new NoSuchElementException("pos is " + current + ", size is " + size);
+        @SuppressWarnings("unchecked")
+        public E next() {
+            if (! hasNext())
+                throw new NoSuchElementException();
+            return (E) snapshot[cursor++];
+        }
+
+        @SuppressWarnings("unchecked")
+        public E previous() {
+            if (! hasPrevious())
+                throw new NoSuchElementException();
+            return (E) snapshot[--cursor];
         }
 
         public int nextIndex() {
-            return current;
-        }
-
-        public Object previous() {
-            if (hasPrevious()) {
-                return arr[--current];
-            }
-            throw new NoSuchElementException("pos is " + (current-1) + ", size is " + size);
+            return cursor;
         }
 
         public int previousIndex() {
-            return current - 1;
+            return cursor-1;
         }
 
+        /**
+         * Not supported. Always throws UnsupportedOperationException.
+         * @throws UnsupportedOperationException always; <tt>remove</tt>
+         *         is not supported by this iterator.
+         */
         public void remove() {
-            throw new UnsupportedOperationException("Unsupported operation remove");
+            throw new UnsupportedOperationException();
         }
 
-        public void set(Object o) {
-            throw new UnsupportedOperationException("Unsupported operation set");
+        /**
+         * Not supported. Always throws UnsupportedOperationException.
+         * @throws UnsupportedOperationException always; <tt>set</tt>
+         *         is not supported by this iterator.
+         */
+        public void set(E e) {
+            throw new UnsupportedOperationException();
         }
 
-    }
-
-    /**
-     * Keeps a state of sublist implementation,
-     * size and array declared as final,
-     * so we'll never get the unconsistent state
-     */
-    static final class SubListReadData {
-        final int size;
-
-        final Object[] data;
-
-        SubListReadData(int size, Object[] data) {
-            this.size = size;
-            this.data = data;
+        /**
+         * Not supported. Always throws UnsupportedOperationException.
+         * @throws UnsupportedOperationException always; <tt>add</tt>
+         *         is not supported by this iterator.
+         */
+        public void add(E e) {
+            throw new UnsupportedOperationException();
         }
     }
 
     /**
-     * Represents a list returned by <code>sublist()</code>.
+     * Returns a view of the portion of this list between
+     * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive.
+     * The returned list is backed by this list, so changes in the
+     * returned list are reflected in this list.
+     *
+     * <p>The semantics of the list returned by this method become
+     * undefined if the backing list (i.e., this list) is modified in
+     * any way other than via the returned list.
+     *
+     * @param fromIndex low endpoint (inclusive) of the subList
+     * @param toIndex high endpoint (exclusive) of the subList
+     * @return a view of the specified range within this list
+     * @throws IndexOutOfBoundsException {@inheritDoc}
      */
-    static class SubList implements List {
-        private final CopyOnWriteArrayList list;
+    public List<E> subList(int fromIndex, int toIndex) {
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            Object[] elements = getArray();
+            int len = elements.length;
+            if (fromIndex < 0 || toIndex > len || fromIndex > toIndex)
+                throw new IndexOutOfBoundsException();
+            return new COWSubList<E>(this, fromIndex, toIndex);
+        } finally {
+            lock.unlock();
+        }
+    }
 
-        private volatile SubListReadData read;
+    /**
+     * Sublist for CopyOnWriteArrayList.
+     * This class extends AbstractList merely for convenience, to
+     * avoid having to define addAll, etc. This doesn't hurt, but
+     * is wasteful.  This class does not need or use modCount
+     * mechanics in AbstractList, but does need to check for
+     * concurrent modification using similar mechanics.  On each
+     * operation, the array that we expect the backing list to use
+     * is checked and updated.  Since we do this for all of the
+     * base operations invoked by those defined in AbstractList,
+     * all is well.  While inefficient, this is not worth
+     * improving.  The kinds of list operations inherited from
+     * AbstractList are already so slow on COW sublists that
+     * adding a bit more space/time doesn't seem even noticeable.
+     */
+    private static class COWSubList<E>
+        extends AbstractList<E>
+        implements RandomAccess
+    {
+        private final CopyOnWriteArrayList<E> l;
+        private final int offset;
+        private int size;
+        private Object[] expectedArray;
 
-        private final int start;
-
-        /**
-         * Sublist constructor.
-         *
-         * @param list    backing list.
-         * @param fromIdx startingIndex, inclusive
-         * @param toIdx   endIndex, exclusive
-         */
-        public SubList(CopyOnWriteArrayList list, int fromIdx, int toIdx) {
-            this.list = list;
-            Object[] data = list.getData();
-            int size = toIdx - fromIdx;
-            checkIndexExlusive(fromIdx, data.length);
-            checkIndexInclusive(toIdx, data.length);
-            read = new SubListReadData(size, list.getData());
-            start = fromIdx;
+        // only call this holding l's lock
+        COWSubList(CopyOnWriteArrayList<E> list,
+                   int fromIndex, int toIndex) {
+            l = list;
+            expectedArray = l.getArray();
+            offset = fromIndex;
+            size = toIndex - fromIndex;
         }
 
-        /**
-         * throws ConcurrentModificationException when the list
-         * is structurally modified in the other way other than via this subList
-         * <p/>
-         * Should be called under lock!
-         */
-        private void checkModifications() {
-            if (read.data != list.getData()) {
+        // only call this holding l's lock
+        private void checkForComodification() {
+            if (l.getArray() != expectedArray)
                 throw new ConcurrentModificationException();
-            }
         }
 
-        /**
-         * @see java.util.List#listIterator(int)
-         */
-        public ListIterator listIterator(int startIdx) {
-            return new SubListIterator(startIdx, read);
+        // only call this holding l's lock
+        private void rangeCheck(int index) {
+            if (index<0 || index>=size)
+                throw new IndexOutOfBoundsException("Index: "+index+
+                                                    ",Size: "+size);
         }
 
-        /**
-         * @see java.util.List#set(int, java.lang.Object)
-         */
-        public Object set(int index, Object obj) {
-            list.lock.lock();
+        public E set(int index, E element) {
+            final ReentrantLock lock = l.lock;
+            lock.lock();
             try {
-                checkIndexExlusive(index, read.size);
-                checkModifications();
-                Object result = list.set(index + start, obj);
-                read = new SubListReadData(read.size, list.getData());
-                return result;
+                rangeCheck(index);
+                checkForComodification();
+                E x = l.set(index+offset, element);
+                expectedArray = l.getArray();
+                return x;
             } finally {
-                list.lock.unlock();
+                lock.unlock();
             }
         }
 
-        /**
-         * @see java.util.List#get(int)
-         */
-        public Object get(int index) {
-            SubListReadData data = read;
-            if (data.data != list.getData()) {
-                list.lock.lock();
-                try {
-                    data = read;
-                    if (data.data != list.getData()) {
-                        throw new ConcurrentModificationException();
-                    }
-                } finally {
-                    list.lock.unlock();
-                }
+        public E get(int index) {
+            final ReentrantLock lock = l.lock;
+            lock.lock();
+            try {
+                rangeCheck(index);
+                checkForComodification();
+                return l.get(index+offset);
+            } finally {
+                lock.unlock();
             }
-            checkIndexExlusive(index, data.size);
-            return data.data[index + start];
         }
 
-        /**
-         * @see java.util.Collection#size()
-         */
         public int size() {
-            return read.size;
-        }
-
-        /**
-         * @see java.util.List#remove(int)
-         */
-        public Object remove(int index) {
-            list.lock.lock();
+            final ReentrantLock lock = l.lock;
+            lock.lock();
             try {
-                checkIndexExlusive(index, read.size);
-                checkModifications();
-                Object obj = list.remove(index + start);
-                read = new SubListReadData(read.size - 1, list.getData());
-                return obj;
+                checkForComodification();
+                return size;
             } finally {
-                list.lock.unlock();
+                lock.unlock();
             }
         }
 
-        /**
-         * @see java.util.List#add(int, java.lang.Object)
-         */
-        public void add(int index, Object object) {
-            list.lock.lock();
+        public void add(int index, E element) {
+            final ReentrantLock lock = l.lock;
+            lock.lock();
             try {
-                checkIndexInclusive(index, read.size);
-                checkModifications();
-                list.add(index + start, object);
-                read = new SubListReadData(read.size + 1, list.getData());
+                checkForComodification();
+                if (index<0 || index>size)
+                    throw new IndexOutOfBoundsException();
+                l.add(index+offset, element);
+                expectedArray = l.getArray();
+                size++;
             } finally {
-                list.lock.unlock();
-            }
-        }
-
-        public boolean add(Object o) {
-            list.lock.lock();
-            try {
-                checkModifications();
-                list.add(start + read.size, o);
-                read = new SubListReadData(read.size + 1, list.getData());
-                return true;
-            } finally {
-                list.lock.unlock();
-            }
-        }
-
-        public boolean addAll(Collection c) {
-            list.lock.lock();
-            try {
-                checkModifications();
-                int d = list.size();
-                list.addAll(start + read.size, c);
-                read = new SubListReadData(read.size + (list.size() - d), list
-                        .getData());
-                return true;
-            } finally {
-                list.lock.unlock();
+                lock.unlock();
             }
         }
 
         public void clear() {
-            list.lock.lock();
+            final ReentrantLock lock = l.lock;
+            lock.lock();
             try {
-                checkModifications();
-                list.removeRange(start, read.size);
-                read = new SubListReadData(0, list.getData());
+                checkForComodification();
+                l.removeRange(offset, offset+size);
+                expectedArray = l.getArray();
+                size = 0;
             } finally {
-                list.lock.unlock();
+                lock.unlock();
             }
         }
 
-        public boolean contains(Object o) {
-            return indexOf(o) != -1;
-        }
-
-        public boolean containsAll(Collection c) {
-            SubListReadData b = read;
-            return CopyOnWriteArrayList.containsAll(c, b.data, start, b.size);
-        }
-
-        public int indexOf(Object o) {
-            SubListReadData b = read;
-            int ind = CopyOnWriteArrayList.indexOf(o, b.data, start, b.size)
-                    - start;
-            return ind < 0 ? -1 : ind;
-        }
-
-        public boolean isEmpty() {
-            return read.size == 0;
-        }
-
-        public Iterator iterator() {
-            return new SubListIterator(0, read);
-        }
-
-        public int lastIndexOf(Object o) {
-            SubListReadData b = read;
-            int ind = CopyOnWriteArrayList
-                    .lastIndexOf(o, b.data, start, b.size)
-                    - start;
-            return ind < 0 ? -1 : ind;
-        }
-
-        public ListIterator listIterator() {
-            return new SubListIterator(0, read);
+        public E remove(int index) {
+            final ReentrantLock lock = l.lock;
+            lock.lock();
+            try {
+                rangeCheck(index);
+                checkForComodification();
+                E result = l.remove(index+offset);
+                expectedArray = l.getArray();
+                size--;
+                return result;
+            } finally {
+                lock.unlock();
+            }
         }
 
         public boolean remove(Object o) {
-            list.lock.lock();
-            try {
-                checkModifications();
-                int i = indexOf(o);
-                if (i == -1) {
-                    return false;
-                }
-                boolean result = list.remove(i + start) != null;
-                if (result) {
-                    read = new SubListReadData(read.size - 1, list.getData());
-                }
-                return result;
-            } finally {
-                list.lock.unlock();
-            }
-        }
-
-        public boolean removeAll(Collection c) {
-            list.lock.lock();
-            try {
-                checkModifications();
-                int removed = list.removeAll(c, start, read.size);
-                if (removed > 0) {
-                    read = new SubListReadData(read.size - removed, list
-                            .getData());
-                    return true;
-                }
-            } finally {
-                list.lock.unlock();
-            }
-            return false;
-        }
-
-        public boolean retainAll(Collection c) {
-            list.lock.lock();
-            try {
-                checkModifications();
-                int removed = list.retainAll(c, start, read.size);
-                if (removed > 0) {
-                    read = new SubListReadData(read.size - removed, list
-                            .getData());
-                    return true;
-                }
+            int index = indexOf(o);
+            if (index == -1)
                 return false;
-            } finally {
-                list.lock.unlock();
-            }
+            remove(index);
+            return true;
         }
 
-        public List subList(int fromIndex, int toIndex) {
-            return new SubList(list, start + fromIndex, start + toIndex);
-        }
-
-        public Object[] toArray() {
-            SubListReadData r = read;
-            return CopyOnWriteArrayList.toArray(r.data, start, r.size);
-        }
-
-        public Object[] toArray(Object[] a) {
-            SubListReadData r = read;
-            return CopyOnWriteArrayList.toArray(a, r.data, start, r.size);
-        }
-
-        /**
-         * @see java.util.List#addAll(int, java.util.Collection)
-         */
-        public boolean addAll(int index, Collection collection) {
-            list.lock.lock();
+        public Iterator<E> iterator() {
+            final ReentrantLock lock = l.lock;
+            lock.lock();
             try {
-                checkIndexInclusive(index, read.size);
-                checkModifications();
-                int d = list.size();
-                boolean rt = list.addAll(index + start, collection);
-                read = new SubListReadData(read.size + list.size() - d, list
-                        .getData());
-                return rt;
+                checkForComodification();
+                return new COWSubListIterator<E>(l, 0, offset, size);
             } finally {
-                list.lock.unlock();
+                lock.unlock();
             }
         }
 
-        /**
-         * Implementation of <code>ListIterator</code> for the
-         * <code>SubList</code>
-         * gets a snapshot of the sublist,
-         * never throws ConcurrentModificationException
-         */
-        private class SubListIterator extends ListIteratorImpl {
-            private final SubListReadData dataR;
-
-            /**
-             * Constructs an iterator starting with the given index
-             *
-             * @param index index of the first element to iterate.
-             */
-            private SubListIterator(int index, SubListReadData d) {
-                super(d.data, index + start);
-                this.dataR = d;
+        public ListIterator<E> listIterator(final int index) {
+            final ReentrantLock lock = l.lock;
+            lock.lock();
+            try {
+                checkForComodification();
+                if (index<0 || index>size)
+                    throw new IndexOutOfBoundsException("Index: "+index+
+                                                        ", Size: "+size);
+                return new COWSubListIterator<E>(l, index, offset, size);
+            } finally {
+                lock.unlock();
             }
+        }
 
-            /**
-             * @see java.util.ListIterator#nextIndex()
-             */
-            public int nextIndex() {
-                return super.nextIndex() - start;
-            }
-
-            /**
-             * @see java.util.ListIterator#previousIndex()
-             */
-            public int previousIndex() {
-                return super.previousIndex() - start;
-            }
-
-            /**
-             * @see java.util.Iterator#hasNext()
-             */
-            public boolean hasNext() {
-                return nextIndex() < dataR.size;
-            }
-
-            /**
-             * @see java.util.ListIterator#hasPrevious()
-             */
-            public boolean hasPrevious() {
-                return previousIndex() > -1;
+        public List<E> subList(int fromIndex, int toIndex) {
+            final ReentrantLock lock = l.lock;
+            lock.lock();
+            try {
+                checkForComodification();
+                if (fromIndex<0 || toIndex>size)
+                    throw new IndexOutOfBoundsException();
+                return new COWSubList<E>(l, fromIndex + offset,
+                                         toIndex + offset);
+            } finally {
+                lock.unlock();
             }
         }
 
     }
 
-    //serialization support
-    /**
-     * Writes the object state to the ObjectOutputStream.
-     *
-     * @param oos ObjectOutputStream to write object to.
-     * @throws IOException if an I/O error occur.
-     */
-    private void writeObject(ObjectOutputStream oos) throws IOException {
-        E[] back = getData();
-        int size = back.length;
-        oos.defaultWriteObject();
-        oos.writeInt(size);
-        for (int i = 0; i < size; i++) {
-            oos.writeObject(back[i]);
+
+    private static class COWSubListIterator<E> implements ListIterator<E> {
+        private final ListIterator<E> i;
+        private final int index;
+        private final int offset;
+        private final int size;
+
+        COWSubListIterator(List<E> l, int index, int offset,
+                           int size) {
+            this.index = index;
+            this.offset = offset;
+            this.size = size;
+            i = l.listIterator(index+offset);
+        }
+
+        public boolean hasNext() {
+            return nextIndex() < size;
+        }
+
+        public E next() {
+            if (hasNext())
+                return i.next();
+            else
+                throw new NoSuchElementException();
+        }
+
+        public boolean hasPrevious() {
+            return previousIndex() >= 0;
+        }
+
+        public E previous() {
+            if (hasPrevious())
+                return i.previous();
+            else
+                throw new NoSuchElementException();
+        }
+
+        public int nextIndex() {
+            return i.nextIndex() - offset;
+        }
+
+        public int previousIndex() {
+            return i.previousIndex() - offset;
+        }
+
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+
+        public void set(E e) {
+            throw new UnsupportedOperationException();
+        }
+
+        public void add(E e) {
+            throw new UnsupportedOperationException();
         }
     }
 
-    /**
-     * Reads the object state from the ObjectOutputStream.
-     *
-     * @param ois ObjectInputStream to read object from.
-     * @throws IOException if an I/O error occur.
-     */
-    private void readObject(ObjectInputStream ois) throws IOException,
-            ClassNotFoundException {
-        ois.defaultReadObject();
-        int length = ois.readInt();
-        if (length == 0) {
-            setData(newElementArray(0));
-        } else {
-            E[] back = newElementArray(length);
-            for (int i = 0; i < back.length; i++) {
-                back[i] = (E) ois.readObject();
-            }
-            setData(back);
-        }
+    // Support for resetting lock while deserializing
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+    private static final long lockOffset;
+    static {
+        try {
+            lockOffset = unsafe.objectFieldOffset
+                (CopyOnWriteArrayList.class.getDeclaredField("lock"));
+            } catch (Exception ex) { throw new Error(ex); }
+    }
+    private void resetLock() {
+        unsafe.putObjectVolatile(this, lockOffset, new ReentrantLock());
     }
 }
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/CopyOnWriteArraySet.java b/libcore/concurrent/src/main/java/java/util/concurrent/CopyOnWriteArraySet.java
index 532952b..65a05de 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/CopyOnWriteArraySet.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/CopyOnWriteArraySet.java
@@ -1,7 +1,7 @@
 /*
  * Written by Doug Lea with assistance from members of JCP JSR-166
- * Expert Group and released to the public domain. Use, modify, and
- * redistribute this code in any way without acknowledgement.
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
  */
 
 package java.util.concurrent;
@@ -9,39 +9,37 @@
 
 // BEGIN android-note
 // removed link to collections framework docs
-// Removed clonable interface to be closer to the RI.
 // END android-note
 
 /**
- * A {@link java.util.Set} that uses {@link
- * java.util.concurrent.CopyOnWriteArrayList} for all of its
- * operations.  Thus, it shares the same basic properties:
+ * A {@link java.util.Set} that uses an internal {@link CopyOnWriteArrayList}
+ * for all of its operations.  Thus, it shares the same basic properties:
  * <ul>
  *  <li>It is best suited for applications in which set sizes generally
  *       stay small, read-only operations
  *       vastly outnumber mutative operations, and you need
  *       to prevent interference among threads during traversal.
- *  <li>Mutative operations(add, set, remove, etc) are expensive
- *      since they usually entail copying the entire underlying array.
- *  <li>Iterators do not support the mutative remove operation
- *  <li>Traversal via iterators is very fast and cannot ever encounter
+ *  <li>It is thread-safe.
+ *  <li>Mutative operations (<tt>add</tt>, <tt>set</tt>, <tt>remove</tt>, etc.)
+ *      are expensive since they usually entail copying the entire underlying
+ *      array.
+ *  <li>Iterators do not support the mutative <tt>remove</tt> operation.
+ *  <li>Traversal via iterators is fast and cannot encounter
  *      interference from other threads. Iterators rely on
  *      unchanging snapshots of the array at the time the iterators were
- *     constructed.
+ *      constructed.
  * </ul>
- * <p>
- * <b>Sample Usage.</b> Probably the main application
- * of copy-on-write sets are classes that maintain
- * sets of Handler objects
- * that must be multicasted to upon an update command. This
- * is a classic case where you do not want to be holding a
- * lock while sending a message, and where traversals normally
- * vastly overwhelm additions.
+ *
+ * <p> <b>Sample Usage.</b> The following code sketch uses a
+ * copy-on-write set to maintain a set of Handler objects that
+ * perform some action upon state updates.
+ *
  * <pre>
  * class Handler { void handle(); ... }
  *
  * class X {
- *    private final CopyOnWriteArraySet&lt;Handler&gt; handlers = new CopyOnWriteArraySet&lt;Handler&gt;();
+ *    private final CopyOnWriteArraySet&lt;Handler&gt; handlers
+ *       = new CopyOnWriteArraySet&lt;Handler&gt;();
  *    public void addHandler(Handler h) { handlers.add(h); }
  *
  *    private long internalState;
@@ -49,14 +47,13 @@
  *
  *    public void update() {
  *       changeState();
- *       Iterator it = handlers.iterator();
- *       while (it.hasNext())
- *          it.next().handle();
+ *       for (Handler handler : handlers)
+ *          handler.handle();
  *    }
  * }
  * </pre>
- * @see CopyOnWriteArrayList
  *
+ * @see CopyOnWriteArrayList
  * @since 1.5
  * @author Doug Lea
  * @param <E> the type of elements held in this collection
@@ -76,27 +73,292 @@
 
     /**
      * Creates a set containing all of the elements of the specified
-     * Collection.
-     * @param c the collection
+     * collection.
+     *
+     * @param c the collection of elements to initially contain
+     * @throws NullPointerException if the specified collection is null
      */
     public CopyOnWriteArraySet(Collection<? extends E> c) {
         al = new CopyOnWriteArrayList<E>();
         al.addAllAbsent(c);
     }
 
+    /**
+     * Returns the number of elements in this set.
+     *
+     * @return the number of elements in this set
+     */
+    public int size() {
+        return al.size();
+    }
 
-    public int      size()                    { return al.size(); }
-    public boolean  isEmpty()                 { return al.isEmpty(); }
-    public boolean  contains(Object o)        { return al.contains(o); }
-    public Object[] toArray()                 { return al.toArray(); }
-    public <T> T[]  toArray(T[] a)            { return al.toArray(a); }
-    public void     clear()                   {        al.clear(); }
-    public Iterator<E>  iterator()            { return al.iterator(); }
-    public boolean  remove(Object o)          { return al.remove(o); }
-    public boolean  add(E o)                  { return al.addIfAbsent(o); }
-    public boolean  containsAll(Collection<?> c)      { return al.containsAll(c); }
-    public boolean  addAll(Collection<? extends E> c) { return al.addAllAbsent(c) > 0; }
-    public boolean  removeAll(Collection<?> c)        { return al.removeAll(c); }
-    public boolean  retainAll(Collection<?> c)        { return al.retainAll(c); }
+    /**
+     * Returns <tt>true</tt> if this set contains no elements.
+     *
+     * @return <tt>true</tt> if this set contains no elements
+     */
+    public boolean isEmpty() {
+        return al.isEmpty();
+    }
 
+    /**
+     * Returns <tt>true</tt> if this set contains the specified element.
+     * More formally, returns <tt>true</tt> if and only if this set
+     * contains an element <tt>e</tt> such that
+     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
+     *
+     * @param o element whose presence in this set is to be tested
+     * @return <tt>true</tt> if this set contains the specified element
+     */
+    public boolean contains(Object o) {
+        return al.contains(o);
+    }
+
+    /**
+     * Returns an array containing all of the elements in this set.
+     * If this set makes any guarantees as to what order its elements
+     * are returned by its iterator, this method must return the
+     * elements in the same order.
+     *
+     * <p>The returned array will be "safe" in that no references to it
+     * are maintained by this set.  (In other words, this method must
+     * allocate a new array even if this set is backed by an array).
+     * The caller is thus free to modify the returned array.
+     *
+     * <p>This method acts as bridge between array-based and collection-based
+     * APIs.
+     *
+     * @return an array containing all the elements in this set
+     */
+    public Object[] toArray() {
+        return al.toArray();
+    }
+
+    /**
+     * Returns an array containing all of the elements in this set; the
+     * runtime type of the returned array is that of the specified array.
+     * If the set fits in the specified array, it is returned therein.
+     * Otherwise, a new array is allocated with the runtime type of the
+     * specified array and the size of this set.
+     *
+     * <p>If this set fits in the specified array with room to spare
+     * (i.e., the array has more elements than this set), the element in
+     * the array immediately following the end of the set is set to
+     * <tt>null</tt>.  (This is useful in determining the length of this
+     * set <i>only</i> if the caller knows that this set does not contain
+     * any null elements.)
+     *
+     * <p>If this set makes any guarantees as to what order its elements
+     * are returned by its iterator, this method must return the elements
+     * in the same order.
+     *
+     * <p>Like the {@link #toArray()} method, this method acts as bridge between
+     * array-based and collection-based APIs.  Further, this method allows
+     * precise control over the runtime type of the output array, and may,
+     * under certain circumstances, be used to save allocation costs.
+     *
+     * <p>Suppose <tt>x</tt> is a set known to contain only strings.
+     * The following code can be used to dump the set into a newly allocated
+     * array of <tt>String</tt>:
+     *
+     * <pre>
+     *     String[] y = x.toArray(new String[0]);</pre>
+     *
+     * Note that <tt>toArray(new Object[0])</tt> is identical in function to
+     * <tt>toArray()</tt>.
+     *
+     * @param a the array into which the elements of this set are to be
+     *        stored, if it is big enough; otherwise, a new array of the same
+     *        runtime type is allocated for this purpose.
+     * @return an array containing all the elements in this set
+     * @throws ArrayStoreException if the runtime type of the specified array
+     *         is not a supertype of the runtime type of every element in this
+     *         set
+     * @throws NullPointerException if the specified array is null
+     */
+    public <T> T[] toArray(T[] a) {
+        return al.toArray(a);
+    }
+
+    /**
+     * Removes all of the elements from this set.
+     * The set will be empty after this call returns.
+     */
+    public void clear() {
+        al.clear();
+    }
+
+    /**
+     * Removes the specified element from this set if it is present.
+     * More formally, removes an element <tt>e</tt> such that
+     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>,
+     * if this set contains such an element.  Returns <tt>true</tt> if
+     * this set contained the element (or equivalently, if this set
+     * changed as a result of the call).  (This set will not contain the
+     * element once the call returns.)
+     *
+     * @param o object to be removed from this set, if present
+     * @return <tt>true</tt> if this set contained the specified element
+     */
+    public boolean remove(Object o) {
+        return al.remove(o);
+    }
+
+    /**
+     * Adds the specified element to this set if it is not already present.
+     * More formally, adds the specified element <tt>e</tt> to this set if
+     * the set contains no element <tt>e2</tt> such that
+     * <tt>(e==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;e.equals(e2))</tt>.
+     * If this set already contains the element, the call leaves the set
+     * unchanged and returns <tt>false</tt>.
+     *
+     * @param e element to be added to this set
+     * @return <tt>true</tt> if this set did not already contain the specified
+     *         element
+     */
+    public boolean add(E e) {
+        return al.addIfAbsent(e);
+    }
+
+    /**
+     * Returns <tt>true</tt> if this set contains all of the elements of the
+     * specified collection.  If the specified collection is also a set, this
+     * method returns <tt>true</tt> if it is a <i>subset</i> of this set.
+     *
+     * @param  c collection to be checked for containment in this set
+     * @return <tt>true</tt> if this set contains all of the elements of the
+     *         specified collection
+     * @throws NullPointerException if the specified collection is null
+     * @see #contains(Object)
+     */
+    public boolean containsAll(Collection<?> c) {
+        return al.containsAll(c);
+    }
+
+    /**
+     * Adds all of the elements in the specified collection to this set if
+     * they're not already present.  If the specified collection is also a
+     * set, the <tt>addAll</tt> operation effectively modifies this set so
+     * that its value is the <i>union</i> of the two sets.  The behavior of
+     * this operation is undefined if the specified collection is modified
+     * while the operation is in progress.
+     *
+     * @param  c collection containing elements to be added to this set
+     * @return <tt>true</tt> if this set changed as a result of the call
+     * @throws NullPointerException if the specified collection is null
+     * @see #add(Object)
+     */
+    public boolean addAll(Collection<? extends E> c) {
+        return al.addAllAbsent(c) > 0;
+    }
+
+    /**
+     * Removes from this set all of its elements that are contained in the
+     * specified collection.  If the specified collection is also a set,
+     * this operation effectively modifies this set so that its value is the
+     * <i>asymmetric set difference</i> of the two sets.
+     *
+     * @param  c collection containing elements to be removed from this set
+     * @return <tt>true</tt> if this set changed as a result of the call
+     * @throws ClassCastException if the class of an element of this set
+     *         is incompatible with the specified collection (optional)
+     * @throws NullPointerException if this set contains a null element and the
+     *         specified collection does not permit null elements (optional),
+     *         or if the specified collection is null
+     * @see #remove(Object)
+     */
+    public boolean removeAll(Collection<?> c) {
+        return al.removeAll(c);
+    }
+
+    /**
+     * Retains only the elements in this set that are contained in the
+     * specified collection.  In other words, removes from this set all of
+     * its elements that are not contained in the specified collection.  If
+     * the specified collection is also a set, this operation effectively
+     * modifies this set so that its value is the <i>intersection</i> of the
+     * two sets.
+     *
+     * @param  c collection containing elements to be retained in this set
+     * @return <tt>true</tt> if this set changed as a result of the call
+     * @throws ClassCastException if the class of an element of this set
+     *         is incompatible with the specified collection (optional)
+     * @throws NullPointerException if this set contains a null element and the
+     *         specified collection does not permit null elements (optional),
+     *         or if the specified collection is null
+     * @see #remove(Object)
+     */
+    public boolean retainAll(Collection<?> c) {
+        return al.retainAll(c);
+    }
+
+    /**
+     * Returns an iterator over the elements contained in this set
+     * in the order in which these elements were added.
+     *
+     * <p>The returned iterator provides a snapshot of the state of the set
+     * when the iterator was constructed. No synchronization is needed while
+     * traversing the iterator. The iterator does <em>NOT</em> support the
+     * <tt>remove</tt> method.
+     *
+     * @return an iterator over the elements in this set
+     */
+    public Iterator<E> iterator() {
+        return al.iterator();
+    }
+
+    /**
+     * Compares the specified object with this set for equality.
+     * Returns {@code true} if the specified object is the same object
+     * as this object, or if it is also a {@link Set} and the elements
+     * returned by an {@linkplain List#iterator() iterator} over the
+     * specified set are the same as the elements returned by an
+     * iterator over this set.  More formally, the two iterators are
+     * considered to return the same elements if they return the same
+     * number of elements and for every element {@code e1} returned by
+     * the iterator over the specified set, there is an element
+     * {@code e2} returned by the iterator over this set such that
+     * {@code (e1==null ? e2==null : e1.equals(e2))}.
+     *
+     * @param o object to be compared for equality with this set
+     * @return {@code true} if the specified object is equal to this set
+     */
+    public boolean equals(Object o) {
+        if (o == this)
+            return true;
+        if (!(o instanceof Set))
+            return false;
+        Set<?> set = (Set<?>)(o);
+        Iterator<?> it = set.iterator();
+
+        // Uses O(n^2) algorithm that is only appropriate
+        // for small sets, which CopyOnWriteArraySets should be.
+
+        //  Use a single snapshot of underlying array
+        Object[] elements = al.getArray();
+        int len = elements.length;
+        // Mark matched elements to avoid re-checking
+        boolean[] matched = new boolean[len];
+        int k = 0;
+        outer: while (it.hasNext()) {
+            if (++k > len)
+                return false;
+            Object x = it.next();
+            for (int i = 0; i < len; ++i) {
+                if (!matched[i] && eq(x, elements[i])) {
+                    matched[i] = true;
+                    continue outer;
+                }
+            }
+            return false;
+        }
+        return k == len;
+    }
+
+    /**
+     * Test for equality, coping with nulls.
+     */
+    private static boolean eq(Object o1, Object o2) {
+        return (o1 == null ? o2 == null : o1.equals(o2));
+    }
 }
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/CountDownLatch.java b/libcore/concurrent/src/main/java/java/util/concurrent/CountDownLatch.java
index 721744c..2b945dd 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/CountDownLatch.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/CountDownLatch.java
@@ -12,25 +12,25 @@
  * A synchronization aid that allows one or more threads to wait until
  * a set of operations being performed in other threads completes.
  *
- * <p>A <tt>CountDownLatch</tt> is initialized with a given
- * <em>count</em>.  The {@link #await await} methods block until the current
- * {@link #getCount count} reaches zero due to invocations of the
- * {@link #countDown} method, after which all waiting threads are
- * released and any subsequent invocations of {@link #await await} return
- * immediately. This is a one-shot phenomenon -- the count cannot be
- * reset.  If you need a version that resets the count, consider using
- * a {@link CyclicBarrier}.
+ * <p>A {@code CountDownLatch} is initialized with a given <em>count</em>.
+ * The {@link #await await} methods block until the current count reaches
+ * zero due to invocations of the {@link #countDown} method, after which
+ * all waiting threads are released and any subsequent invocations of
+ * {@link #await await} return immediately.  This is a one-shot phenomenon
+ * -- the count cannot be reset.  If you need a version that resets the
+ * count, consider using a {@link CyclicBarrier}.
  *
- * <p>A <tt>CountDownLatch</tt> is a versatile synchronization tool
+ * <p>A {@code CountDownLatch} is a versatile synchronization tool
  * and can be used for a number of purposes.  A
- * <tt>CountDownLatch</tt> initialized with a count of one serves as a
+ * {@code CountDownLatch} initialized with a count of one serves as a
  * simple on/off latch, or gate: all threads invoking {@link #await await}
  * wait at the gate until it is opened by a thread invoking {@link
- * #countDown}.  A <tt>CountDownLatch</tt> initialized to <em>N</em>
+ * #countDown}.  A {@code CountDownLatch} initialized to <em>N</em>
  * can be used to make one thread wait until <em>N</em> threads have
  * completed some action, or some action has been completed N times.
- * <p>A useful property of a <tt>CountDownLatch</tt> is that it
- * doesn't require that threads calling <tt>countDown</tt> wait for
+ *
+ * <p>A useful property of a {@code CountDownLatch} is that it
+ * doesn't require that threads calling {@code countDown} wait for
  * the count to reach zero before proceeding, it simply prevents any
  * thread from proceeding past an {@link #await await} until all
  * threads could pass.
@@ -119,6 +119,13 @@
  *
  * </pre>
  *
+ * <p>Memory consistency effects: Until the count reaches
+ * zero, actions in a thread prior to calling
+ * {@code countDown()}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * actions following a successful return from a corresponding
+ * {@code await()} in another thread.
+ *
  * @since 1.5
  * @author Doug Lea
  */
@@ -128,118 +135,120 @@
      * Uses AQS state to represent count.
      */
     private static final class Sync extends AbstractQueuedSynchronizer {
+        private static final long serialVersionUID = 4982264981922014374L;
+
         Sync(int count) {
-            setState(count); 
+            setState(count);
         }
-        
+
         int getCount() {
             return getState();
         }
 
-        public int tryAcquireShared(int acquires) {
+        protected int tryAcquireShared(int acquires) {
             return getState() == 0? 1 : -1;
         }
-        
-        public boolean tryReleaseShared(int releases) {
+
+        protected boolean tryReleaseShared(int releases) {
             // Decrement count; signal when transition to zero
             for (;;) {
                 int c = getState();
                 if (c == 0)
                     return false;
                 int nextc = c-1;
-                if (compareAndSetState(c, nextc)) 
+                if (compareAndSetState(c, nextc))
                     return nextc == 0;
             }
         }
     }
 
     private final Sync sync;
+
     /**
-     * Constructs a <tt>CountDownLatch</tt> initialized with the given
-     * count.
-     * 
-     * @param count the number of times {@link #countDown} must be invoked
-     * before threads can pass through {@link #await}.
+     * Constructs a {@code CountDownLatch} initialized with the given count.
      *
-     * @throws IllegalArgumentException if <tt>count</tt> is less than zero.
+     * @param count the number of times {@link #countDown} must be invoked
+     *        before threads can pass through {@link #await}
+     * @throws IllegalArgumentException if {@code count} is negative
      */
-    public CountDownLatch(int count) { 
+    public CountDownLatch(int count) {
         if (count < 0) throw new IllegalArgumentException("count < 0");
         this.sync = new Sync(count);
     }
 
     /**
-     * Causes the current thread to wait until the latch has counted down to 
-     * zero, unless the thread is {@link Thread#interrupt interrupted}.
+     * Causes the current thread to wait until the latch has counted down to
+     * zero, unless the thread is {@linkplain Thread#interrupt interrupted}.
      *
-     * <p>If the current {@link #getCount count} is zero then this method
-     * returns immediately.
-     * <p>If the current {@link #getCount count} is greater than zero then
-     * the current thread becomes disabled for thread scheduling 
-     * purposes and lies dormant until one of two things happen:
+     * <p>If the current count is zero then this method returns immediately.
+     *
+     * <p>If the current count is greater than zero then the current
+     * thread becomes disabled for thread scheduling purposes and lies
+     * dormant until one of two things happen:
      * <ul>
      * <li>The count reaches zero due to invocations of the
      * {@link #countDown} method; or
-     * <li>Some other thread {@link Thread#interrupt interrupts} the current
-     * thread.
+     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+     * the current thread.
      * </ul>
+     *
      * <p>If the current thread:
      * <ul>
-     * <li>has its interrupted status set on entry to this method; or 
-     * <li>is {@link Thread#interrupt interrupted} while waiting, 
+     * <li>has its interrupted status set on entry to this method; or
+     * <li>is {@linkplain Thread#interrupt interrupted} while waiting,
      * </ul>
-     * then {@link InterruptedException} is thrown and the current thread's 
-     * interrupted status is cleared. 
+     * then {@link InterruptedException} is thrown and the current thread's
+     * interrupted status is cleared.
      *
      * @throws InterruptedException if the current thread is interrupted
-     * while waiting.
+     *         while waiting
      */
     public void await() throws InterruptedException {
         sync.acquireSharedInterruptibly(1);
     }
 
     /**
-     * Causes the current thread to wait until the latch has counted down to 
-     * zero, unless the thread is {@link Thread#interrupt interrupted},
+     * Causes the current thread to wait until the latch has counted down to
+     * zero, unless the thread is {@linkplain Thread#interrupt interrupted},
      * or the specified waiting time elapses.
      *
-     * <p>If the current {@link #getCount count} is zero then this method
-     * returns immediately with the value <tt>true</tt>.
+     * <p>If the current count is zero then this method returns immediately
+     * with the value {@code true}.
      *
-     * <p>If the current {@link #getCount count} is greater than zero then
-     * the current thread becomes disabled for thread scheduling 
-     * purposes and lies dormant until one of three things happen:
+     * <p>If the current count is greater than zero then the current
+     * thread becomes disabled for thread scheduling purposes and lies
+     * dormant until one of three things happen:
      * <ul>
      * <li>The count reaches zero due to invocations of the
      * {@link #countDown} method; or
-     * <li>Some other thread {@link Thread#interrupt interrupts} the current
-     * thread; or
+     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+     * the current thread; or
      * <li>The specified waiting time elapses.
      * </ul>
+     *
      * <p>If the count reaches zero then the method returns with the
-     * value <tt>true</tt>.
+     * value {@code true}.
+     *
      * <p>If the current thread:
      * <ul>
-     * <li>has its interrupted status set on entry to this method; or 
-     * <li>is {@link Thread#interrupt interrupted} while waiting, 
+     * <li>has its interrupted status set on entry to this method; or
+     * <li>is {@linkplain Thread#interrupt interrupted} while waiting,
      * </ul>
-     * then {@link InterruptedException} is thrown and the current thread's 
-     * interrupted status is cleared. 
+     * then {@link InterruptedException} is thrown and the current thread's
+     * interrupted status is cleared.
      *
-     * <p>If the specified waiting time elapses then the value <tt>false</tt>
-     * is returned.
-     * If the time is 
-     * less than or equal to zero, the method will not wait at all.
+     * <p>If the specified waiting time elapses then the value {@code false}
+     * is returned.  If the time is less than or equal to zero, the method
+     * will not wait at all.
      *
      * @param timeout the maximum time to wait
-     * @param unit the time unit of the <tt>timeout</tt> argument.
-     * @return <tt>true</tt> if the count reached zero  and <tt>false</tt>
-     * if the waiting time elapsed before the count reached zero.
-     *
+     * @param unit the time unit of the {@code timeout} argument
+     * @return {@code true} if the count reached zero and {@code false}
+     *         if the waiting time elapsed before the count reached zero
      * @throws InterruptedException if the current thread is interrupted
-     * while waiting.
+     *         while waiting
      */
-    public boolean await(long timeout, TimeUnit unit) 
+    public boolean await(long timeout, TimeUnit unit)
         throws InterruptedException {
         return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
     }
@@ -247,11 +256,12 @@
     /**
      * Decrements the count of the latch, releasing all waiting threads if
      * the count reaches zero.
-     * <p>If the current {@link #getCount count} is greater than zero then
-     * it is decremented. If the new count is zero then all waiting threads
-     * are re-enabled for thread scheduling purposes.
-     * <p>If the current {@link #getCount count} equals zero then nothing
-     * happens.
+     *
+     * <p>If the current count is greater than zero then it is decremented.
+     * If the new count is zero then all waiting threads are re-enabled for
+     * thread scheduling purposes.
+     *
+     * <p>If the current count equals zero then nothing happens.
      */
     public void countDown() {
         sync.releaseShared(1);
@@ -259,8 +269,10 @@
 
     /**
      * Returns the current count.
+     *
      * <p>This method is typically used for debugging and testing purposes.
-     * @return the current count.
+     *
+     * @return the current count
      */
     public long getCount() {
         return sync.getCount();
@@ -268,13 +280,12 @@
 
     /**
      * Returns a string identifying this latch, as well as its state.
-     * The state, in brackets, includes the String 
-     * &quot;Count =&quot; followed by the current count.
-     * @return a string identifying this latch, as well as its
-     * state
+     * The state, in brackets, includes the String {@code "Count ="}
+     * followed by the current count.
+     *
+     * @return a string identifying this latch, as well as its state
      */
     public String toString() {
         return super.toString() + "[Count = " + sync.getCount() + "]";
     }
-
 }
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/CyclicBarrier.java b/libcore/concurrent/src/main/java/java/util/concurrent/CyclicBarrier.java
index d70c4c7..d5738c5 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/CyclicBarrier.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/CyclicBarrier.java
@@ -17,10 +17,10 @@
  *
  * <p>A <tt>CyclicBarrier</tt> supports an optional {@link Runnable} command
  * that is run once per barrier point, after the last thread in the party
- * arrives, but before any threads are released. 
+ * arrives, but before any threads are released.
  * This <em>barrier action</em> is useful
  * for updating shared-state before any of the parties continue.
- * 
+ *
  * <p><b>Sample usage:</b> Here is an example of
  *  using a barrier in a parallel decomposition design:
  * <pre>
@@ -28,7 +28,7 @@
  *   final int N;
  *   final float[][] data;
  *   final CyclicBarrier barrier;
- *   
+ *
  *   class Worker implements Runnable {
  *     int myRow;
  *     Worker(int row) { myRow = row; }
@@ -37,11 +37,11 @@
  *         processRow(myRow);
  *
  *         try {
- *           barrier.await(); 
- *         } catch (InterruptedException ex) { 
- *           return; 
- *         } catch (BrokenBarrierException ex) { 
- *           return; 
+ *           barrier.await();
+ *         } catch (InterruptedException ex) {
+ *           return;
+ *         } catch (BrokenBarrierException ex) {
+ *           return;
  *         }
  *       }
  *     }
@@ -50,22 +50,22 @@
  *   public Solver(float[][] matrix) {
  *     data = matrix;
  *     N = matrix.length;
- *     barrier = new CyclicBarrier(N, 
+ *     barrier = new CyclicBarrier(N,
  *                                 new Runnable() {
- *                                   public void run() { 
- *                                     mergeRows(...); 
+ *                                   public void run() {
+ *                                     mergeRows(...);
  *                                   }
  *                                 });
- *     for (int i = 0; i < N; ++i) 
+ *     for (int i = 0; i < N; ++i)
  *       new Thread(new Worker(i)).start();
  *
  *     waitUntilDone();
  *   }
  * }
  * </pre>
- * Here, each worker thread processes a row of the matrix then waits at the 
+ * Here, each worker thread processes a row of the matrix then waits at the
  * barrier until all rows have been processed. When all rows are processed
- * the supplied {@link Runnable} barrier action is executed and merges the 
+ * the supplied {@link Runnable} barrier action is executed and merges the
  * rows. If the merger
  * determines that a solution has been found then <tt>done()</tt> will return
  * <tt>true</tt> and each worker will terminate.
@@ -74,19 +74,26 @@
  * it is executed, then any of the threads in the party could execute that
  * action when it is released. To facilitate this, each invocation of
  * {@link #await} returns the arrival index of that thread at the barrier.
- * You can then choose which thread should execute the barrier action, for 
+ * You can then choose which thread should execute the barrier action, for
  * example:
  * <pre>  if (barrier.await() == 0) {
  *     // log the completion of this iteration
  *   }</pre>
  *
- * <p>The <tt>CyclicBarrier</tt> uses a fast-fail all-or-none breakage
- * model for failed synchronization attempts: If a thread leaves a
- * barrier point prematurely because of interruption, failure, or
- * timeout, all other threads, even those that have not yet resumed
- * from a previous {@link #await}. will also leave abnormally via
- * {@link BrokenBarrierException} (or <tt>InterruptedException</tt> if
- * they too were interrupted at about the same time).
+ * <p>The <tt>CyclicBarrier</tt> uses an all-or-none breakage model
+ * for failed synchronization attempts: If a thread leaves a barrier
+ * point prematurely because of interruption, failure, or timeout, all
+ * other threads waiting at that barrier point will also leave
+ * abnormally via {@link BrokenBarrierException} (or
+ * {@link InterruptedException} if they too were interrupted at about
+ * the same time).
+ *
+ * <p>Memory consistency effects: Actions in a thread prior to calling
+ * {@code await()}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * actions that are part of the barrier action, which in turn
+ * <i>happen-before</i> actions following a successful return from the
+ * corresponding {@code await()} in other threads.
  *
  * @since 1.5
  * @see CountDownLatch
@@ -94,6 +101,21 @@
  * @author Doug Lea
  */
 public class CyclicBarrier {
+    /**
+     * Each use of the barrier is represented as a generation instance.
+     * The generation changes whenever the barrier is tripped, or
+     * is reset. There can be many generations associated with threads
+     * using the barrier - due to the non-deterministic way the lock
+     * may be allocated to waiting threads - but only one of these
+     * can be active at a time (the one to which <tt>count</tt> applies)
+     * and all the rest are either broken or tripped.
+     * There need not be an active generation if there has been a break
+     * but no subsequent reset.
+     */
+    private static class Generation {
+        boolean broken = false;
+    }
+
     /** The lock for guarding barrier entry */
     private final ReentrantLock lock = new ReentrantLock();
     /** Condition to wait on until tripped */
@@ -102,53 +124,50 @@
     private final int parties;
     /* The command to run when tripped */
     private final Runnable barrierCommand;
-
-    /**
-     * The generation number. Incremented upon barrier trip.
-     * Retracted upon reset.
-     */
-    private long generation; 
-
-    /** 
-     * Breakage indicator.
-     */
-    private boolean broken; 
+    /** The current generation */
+    private Generation generation = new Generation();
 
     /**
      * Number of parties still waiting. Counts down from parties to 0
-     * on each cycle.
+     * on each generation.  It is reset to parties on each new
+     * generation or when broken.
      */
-    private int count; 
+    private int count;
 
     /**
-     * Updates state on barrier trip and wake up everyone.
-     */  
+     * Updates state on barrier trip and wakes up everyone.
+     * Called only while holding lock.
+     */
     private void nextGeneration() {
-        count = parties;
-        ++generation;
+        // signal completion of last generation
         trip.signalAll();
+        // set up next generation
+        count = parties;
+        generation = new Generation();
     }
 
     /**
-     * Sets barrier as broken and wake up everyone
+     * Sets current barrier generation as broken and wakes up everyone.
+     * Called only while holding lock.
      */
     private void breakBarrier() {
-        broken = true;
+        generation.broken = true;
+        count = parties;
         trip.signalAll();
     }
 
     /**
      * Main barrier code, covering the various policies.
      */
-    private int dowait(boolean timed, long nanos) 
-        throws InterruptedException, BrokenBarrierException, TimeoutException {
+    private int dowait(boolean timed, long nanos)
+        throws InterruptedException, BrokenBarrierException,
+               TimeoutException {
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            int index = --count;
-            long g = generation;
+            final Generation g = generation;
 
-            if (broken) 
+            if (g.broken)
                 throw new BrokenBarrierException();
 
             if (Thread.interrupted()) {
@@ -156,37 +175,45 @@
                 throw new InterruptedException();
             }
 
-            if (index == 0) {  // tripped
-                nextGeneration();
-                boolean ranAction = false;
-                try {
-                    Runnable command = barrierCommand;
-                    if (command != null) 
-                        command.run();
-                    ranAction = true;
-                    return 0;
-                } finally {
-                    if (!ranAction)
-                        breakBarrier();
-                }
-            }
+           int index = --count;
+           if (index == 0) {  // tripped
+               boolean ranAction = false;
+               try {
+                   final Runnable command = barrierCommand;
+                   if (command != null)
+                       command.run();
+                   ranAction = true;
+                   nextGeneration();
+                   return 0;
+               } finally {
+                   if (!ranAction)
+                       breakBarrier();
+               }
+           }
 
+            // loop until tripped, broken, interrupted, or timed out
             for (;;) {
                 try {
-                    if (!timed) 
+                    if (!timed)
                         trip.await();
                     else if (nanos > 0L)
                         nanos = trip.awaitNanos(nanos);
                 } catch (InterruptedException ie) {
-                    breakBarrier();
-                    throw ie;
+                    if (g == generation && ! g.broken) {
+                        breakBarrier();
+                        throw ie;
+                    } else {
+                        // We're about to finish waiting even if we had not
+                        // been interrupted, so this interrupt is deemed to
+                        // "belong" to subsequent execution.
+                        Thread.currentThread().interrupt();
+                    }
                 }
-                
-                if (broken || 
-                    g > generation) // true if a reset occurred while waiting
+
+                if (g.broken)
                     throw new BrokenBarrierException();
 
-                if (g < generation)
+                if (g != generation)
                     return index;
 
                 if (timed && nanos <= 0L) {
@@ -194,7 +221,6 @@
                     throw new TimeoutException();
                 }
             }
-
         } finally {
             lock.unlock();
         }
@@ -207,15 +233,14 @@
      * performed by the last thread entering the barrier.
      *
      * @param parties the number of threads that must invoke {@link #await}
-     * before the barrier is tripped.
+     *        before the barrier is tripped
      * @param barrierAction the command to execute when the barrier is
-     * tripped, or <tt>null</tt> if there is no action.
-     *
-     * @throws IllegalArgumentException if <tt>parties</tt> is less than 1.
+     *        tripped, or {@code null} if there is no action
+     * @throws IllegalArgumentException if {@code parties} is less than 1
      */
     public CyclicBarrier(int parties, Runnable barrierAction) {
         if (parties <= 0) throw new IllegalArgumentException();
-        this.parties = parties; 
+        this.parties = parties;
         this.count = parties;
         this.barrierCommand = barrierAction;
     }
@@ -223,12 +248,11 @@
     /**
      * Creates a new <tt>CyclicBarrier</tt> that will trip when the
      * given number of parties (threads) are waiting upon it, and
-     * does not perform a predefined action upon each barrier.
+     * does not perform a predefined action when the barrier is tripped.
      *
      * @param parties the number of threads that must invoke {@link #await}
-     * before the barrier is tripped.
-     *
-     * @throws IllegalArgumentException if <tt>parties</tt> is less than 1.
+     *        before the barrier is tripped
+     * @throws IllegalArgumentException if {@code parties} is less than 1
      */
     public CyclicBarrier(int parties) {
         this(parties, null);
@@ -236,64 +260,66 @@
 
     /**
      * Returns the number of parties required to trip this barrier.
-     * @return the number of parties required to trip this barrier.
-     **/
+     *
+     * @return the number of parties required to trip this barrier
+     */
     public int getParties() {
         return parties;
     }
 
     /**
-     * Waits until all {@link #getParties parties} have invoked <tt>await</tt>
-     * on this barrier.
+     * Waits until all {@linkplain #getParties parties} have invoked
+     * <tt>await</tt> on this barrier.
      *
      * <p>If the current thread is not the last to arrive then it is
      * disabled for thread scheduling purposes and lies dormant until
-     * one of following things happens:
+     * one of the following things happens:
      * <ul>
      * <li>The last thread arrives; or
-     * <li>Some other thread {@link Thread#interrupt interrupts} the current
-     * thread; or
-     * <li>Some other thread  {@link Thread#interrupt interrupts} one of the
-     * other waiting threads; or
+     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+     * the current thread; or
+     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+     * one of the other waiting threads; or
      * <li>Some other thread times out while waiting for barrier; or
      * <li>Some other thread invokes {@link #reset} on this barrier.
      * </ul>
+     *
      * <p>If the current thread:
      * <ul>
      * <li>has its interrupted status set on entry to this method; or
-     * <li>is {@link Thread#interrupt interrupted} while waiting
+     * <li>is {@linkplain Thread#interrupt interrupted} while waiting
      * </ul>
      * then {@link InterruptedException} is thrown and the current thread's
      * interrupted status is cleared.
      *
-     * <p>If the barrier is {@link #reset} while any thread is waiting, or if 
-     * the barrier {@link #isBroken is broken} when <tt>await</tt> is invoked,
-     * or while any thread is waiting,
-     * then {@link BrokenBarrierException} is thrown.
+     * <p>If the barrier is {@link #reset} while any thread is waiting,
+     * or if the barrier {@linkplain #isBroken is broken} when
+     * <tt>await</tt> is invoked, or while any thread is waiting, then
+     * {@link BrokenBarrierException} is thrown.
      *
-     * <p>If any thread is {@link Thread#interrupt interrupted} while waiting,
-     * then all other waiting threads will throw 
+     * <p>If any thread is {@linkplain Thread#interrupt interrupted} while waiting,
+     * then all other waiting threads will throw
      * {@link BrokenBarrierException} and the barrier is placed in the broken
      * state.
      *
      * <p>If the current thread is the last thread to arrive, and a
      * non-null barrier action was supplied in the constructor, then the
-     * current thread runs the action before allowing the other threads to 
+     * current thread runs the action before allowing the other threads to
      * continue.
      * If an exception occurs during the barrier action then that exception
      * will be propagated in the current thread and the barrier is placed in
      * the broken state.
      *
      * @return the arrival index of the current thread, where index
-     *  <tt>{@link #getParties()} - 1</tt> indicates the first to arrive and 
-     * zero indicates the last to arrive.
-     *
-     * @throws InterruptedException if the current thread was interrupted 
-     * while waiting
+     *         <tt>{@link #getParties()} - 1</tt> indicates the first
+     *         to arrive and zero indicates the last to arrive
+     * @throws InterruptedException if the current thread was interrupted
+     *         while waiting
      * @throws BrokenBarrierException if <em>another</em> thread was
-     * interrupted while the current thread was waiting, or the barrier was
-     * reset, or the barrier was broken when <tt>await</tt> was called,
-     * or the barrier action (if present) failed due an exception.
+     *         interrupted or timed out while the current thread was
+     *         waiting, or the barrier was reset, or the barrier was
+     *         broken when {@code await} was called, or the barrier
+     *         action (if present) failed due an exception.
      */
     public int await() throws InterruptedException, BrokenBarrierException {
         try {
@@ -304,8 +330,8 @@
     }
 
     /**
-     * Waits until all {@link #getParties parties} have invoked <tt>await</tt>
-     * on this barrier.
+     * Waits until all {@linkplain #getParties parties} have invoked
+     * <tt>await</tt> on this barrier, or the specified waiting time elapses.
      *
      * <p>If the current thread is not the last to arrive then it is
      * disabled for thread scheduling purposes and lies dormant until
@@ -313,34 +339,39 @@
      * <ul>
      * <li>The last thread arrives; or
      * <li>The specified timeout elapses; or
-     * <li>Some other thread {@link Thread#interrupt interrupts} the current
-     * thread; or
-     * <li>Some other thread  {@link Thread#interrupt interrupts} one of the
-     * other waiting threads; or
+     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+     * the current thread; or
+     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+     * one of the other waiting threads; or
      * <li>Some other thread times out while waiting for barrier; or
      * <li>Some other thread invokes {@link #reset} on this barrier.
      * </ul>
+     *
      * <p>If the current thread:
      * <ul>
      * <li>has its interrupted status set on entry to this method; or
-     * <li>is {@link Thread#interrupt interrupted} while waiting
+     * <li>is {@linkplain Thread#interrupt interrupted} while waiting
      * </ul>
      * then {@link InterruptedException} is thrown and the current thread's
      * interrupted status is cleared.
      *
-     * <p>If the barrier is {@link #reset} while any thread is waiting, or if 
-     * the barrier {@link #isBroken is broken} when <tt>await</tt> is invoked,
-     * or while any thread is waiting,
-     * then {@link BrokenBarrierException} is thrown.
+     * <p>If the specified waiting time elapses then {@link TimeoutException}
+     * is thrown. If the time is less than or equal to zero, the
+     * method will not wait at all.
      *
-     * <p>If any thread is {@link Thread#interrupt interrupted} while waiting,
-     * then all other waiting threads will throw 
-     * {@link BrokenBarrierException} and the barrier is placed in the broken
+     * <p>If the barrier is {@link #reset} while any thread is waiting,
+     * or if the barrier {@linkplain #isBroken is broken} when
+     * <tt>await</tt> is invoked, or while any thread is waiting, then
+     * {@link BrokenBarrierException} is thrown.
+     *
+     * <p>If any thread is {@linkplain Thread#interrupt interrupted} while
+     * waiting, then all other waiting threads will throw {@link
+     * BrokenBarrierException} and the barrier is placed in the broken
      * state.
      *
      * <p>If the current thread is the last thread to arrive, and a
      * non-null barrier action was supplied in the constructor, then the
-     * current thread runs the action before allowing the other threads to 
+     * current thread runs the action before allowing the other threads to
      * continue.
      * If an exception occurs during the barrier action then that exception
      * will be propagated in the current thread and the barrier is placed in
@@ -349,36 +380,37 @@
      * @param timeout the time to wait for the barrier
      * @param unit the time unit of the timeout parameter
      * @return the arrival index of the current thread, where index
-     *  <tt>{@link #getParties()} - 1</tt> indicates the first to arrive and 
-     * zero indicates the last to arrive.
-     *
-     * @throws InterruptedException if the current thread was interrupted 
-     * while waiting
-     * @throws TimeoutException if the specified timeout elapses.
+     *         <tt>{@link #getParties()} - 1</tt> indicates the first
+     *         to arrive and zero indicates the last to arrive
+     * @throws InterruptedException if the current thread was interrupted
+     *         while waiting
+     * @throws TimeoutException if the specified timeout elapses
      * @throws BrokenBarrierException if <em>another</em> thread was
-     * interrupted while the current thread was waiting, or the barrier was
-     * reset, or the barrier was broken when <tt>await</tt> was called,
-     * or the barrier action (if present) failed due an exception.
+     *         interrupted or timed out while the current thread was
+     *         waiting, or the barrier was reset, or the barrier was broken
+     *         when {@code await} was called, or the barrier action (if
+     *         present) failed due an exception
      */
-    public int await(long timeout, TimeUnit unit) 
-        throws InterruptedException, 
-        BrokenBarrierException, 
-        TimeoutException {
+    public int await(long timeout, TimeUnit unit)
+        throws InterruptedException,
+               BrokenBarrierException,
+               TimeoutException {
         return dowait(true, unit.toNanos(timeout));
     }
 
     /**
      * Queries if this barrier is in a broken state.
-     * @return <tt>true</tt> if one or more parties broke out of this
-     * barrier due to interruption or timeout since construction or
-     * the last reset, or a barrier action failed due to an exception; 
-     * and <tt>false</tt> otherwise.
+     *
+     * @return {@code true} if one or more parties broke out of this
+     *         barrier due to interruption or timeout since
+     *         construction or the last reset, or a barrier action
+     *         failed due to an exception; {@code false} otherwise.
      */
     public boolean isBroken() {
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            return broken;
+            return generation.broken;
         } finally {
             lock.unlock();
         }
@@ -397,15 +429,8 @@
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            /*
-             * Retract generation number enough to cover threads
-             * currently waiting on current and still resuming from
-             * previous generation, plus similarly accommodating spans
-             * after the reset.
-             */
-            generation -= 4;
-            broken = false;
-            trip.signalAll();
+            breakBarrier();   // break the current generation
+            nextGeneration(); // start a new generation
         } finally {
             lock.unlock();
         }
@@ -416,7 +441,7 @@
      * This method is primarily useful for debugging and assertions.
      *
      * @return the number of parties currently blocked in {@link #await}
-     **/
+     */
     public int getNumberWaiting() {
         final ReentrantLock lock = this.lock;
         lock.lock();
@@ -426,5 +451,4 @@
             lock.unlock();
         }
     }
-
 }
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/DelayQueue.java b/libcore/concurrent/src/main/java/java/util/concurrent/DelayQueue.java
index 156dc7e..52ac4a0 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/DelayQueue.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/DelayQueue.java
@@ -14,14 +14,22 @@
 // END android-note
 
 /**
- * An unbounded {@linkplain BlockingQueue blocking queue} of <tt>Delayed</tt>
- * elements, in which an element can only be taken when its delay has expired.
- * The <em>head</em> of the queue is that <tt>Delayed</tt> element whose delay
- * expired furthest in the past - if no delay has expired there is no head and
- * <tt>poll</tt> will return <tt>null</tt>.
- * This queue does not permit <tt>null</tt> elements.
- * <p>This class implements all of the <em>optional</em> methods
- * of the {@link Collection} and {@link Iterator} interfaces.
+ * An unbounded {@linkplain BlockingQueue blocking queue} of
+ * <tt>Delayed</tt> elements, in which an element can only be taken
+ * when its delay has expired.  The <em>head</em> of the queue is that
+ * <tt>Delayed</tt> element whose delay expired furthest in the
+ * past.  If no delay has expired there is no head and <tt>poll</tt>
+ * will return <tt>null</tt>. Expiration occurs when an element's
+ * <tt>getDelay(TimeUnit.NANOSECONDS)</tt> method returns a value less
+ * than or equal to zero.  Even though unexpired elements cannot be
+ * removed using <tt>take</tt> or <tt>poll</tt>, they are otherwise
+ * treated as normal elements. For example, the <tt>size</tt> method
+ * returns the count of both expired and unexpired elements.
+ * This queue does not permit null elements.
+ *
+ * <p>This class and its iterator implement all of the
+ * <em>optional</em> methods of the {@link Collection} and {@link
+ * Iterator} interfaces.
  *
  * @since 1.5
  * @author Doug Lea
@@ -32,10 +40,34 @@
     implements BlockingQueue<E> {
 
     private transient final ReentrantLock lock = new ReentrantLock();
-    private transient final Condition available = lock.newCondition();
     private final PriorityQueue<E> q = new PriorityQueue<E>();
 
     /**
+     * Thread designated to wait for the element at the head of
+     * the queue.  This variant of the Leader-Follower pattern
+     * (http://www.cs.wustl.edu/~schmidt/POSA/POSA2/) serves to
+     * minimize unnecessary timed waiting.  When a thread becomes
+     * the leader, it waits only for the next delay to elapse, but
+     * other threads await indefinitely.  The leader thread must
+     * signal some other thread before returning from take() or
+     * poll(...), unless some other thread becomes leader in the
+     * interim.  Whenever the head of the queue is replaced with
+     * an element with an earlier expiration time, the leader
+     * field is invalidated by being reset to null, and some
+     * waiting thread, but not necessarily the current leader, is
+     * signalled.  So waiting threads must be prepared to acquire
+     * and lose leadership while waiting.
+     */
+    private Thread leader = null;
+
+    /**
+     * Condition signalled when a newer element becomes available
+     * at the head of the queue or a new thread may need to
+     * become leader.
+     */
+    private final Condition available = lock.newCondition();
+
+    /**
      * Creates a new <tt>DelayQueue</tt> that is initially empty.
      */
     public DelayQueue() {}
@@ -44,10 +76,9 @@
      * Creates a <tt>DelayQueue</tt> initially containing the elements of the
      * given collection of {@link Delayed} instances.
      *
-     * @param c the collection
-     * @throws NullPointerException if <tt>c</tt> or any element within it
-     * is <tt>null</tt>
-     *
+     * @param c the collection of elements to initially contain
+     * @throws NullPointerException if the specified collection or any
+     *         of its elements are null
      */
     public DelayQueue(Collection<? extends E> c) {
         this.addAll(c);
@@ -56,91 +87,136 @@
     /**
      * Inserts the specified element into this delay queue.
      *
-     * @param o the element to add
-     * @return <tt>true</tt>
-     * @throws NullPointerException if the specified element is <tt>null</tt>.
+     * @param e the element to add
+     * @return <tt>true</tt> (as specified by {@link Collection#add})
+     * @throws NullPointerException if the specified element is null
      */
-    public boolean offer(E o) {
+    public boolean add(E e) {
+        return offer(e);
+    }
+
+    /**
+     * Inserts the specified element into this delay queue.
+     *
+     * @param e the element to add
+     * @return <tt>true</tt>
+     * @throws NullPointerException if the specified element is null
+     */
+    public boolean offer(E e) {
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            E first = q.peek();
-            q.offer(o);
-            if (first == null || o.compareTo(first) < 0)
-                available.signalAll();
+            q.offer(e);
+            if (q.peek() == e) {
+                leader = null;
+                available.signal();
+            }
             return true;
         } finally {
             lock.unlock();
         }
     }
 
-
     /**
-     * Adds the specified element to this delay queue. As the queue is
+     * Inserts the specified element into this delay queue. As the queue is
      * unbounded this method will never block.
-     * @param o the element to add
-     * @throws NullPointerException if the specified element is <tt>null</tt>.
+     *
+     * @param e the element to add
+     * @throws NullPointerException {@inheritDoc}
      */
-    public void put(E o) {
-        offer(o);
+    public void put(E e) {
+        offer(e);
     }
 
     /**
      * Inserts the specified element into this delay queue. As the queue is
      * unbounded this method will never block.
-     * @param o the element to add
+     *
+     * @param e the element to add
      * @param timeout This parameter is ignored as the method never blocks
      * @param unit This parameter is ignored as the method never blocks
      * @return <tt>true</tt>
-     * @throws NullPointerException if the specified element is <tt>null</tt>.
+     * @throws NullPointerException {@inheritDoc}
      */
-    public boolean offer(E o, long timeout, TimeUnit unit) {
-        return offer(o);
+    public boolean offer(E e, long timeout, TimeUnit unit) {
+        return offer(e);
     }
 
     /**
-     * Adds the specified element to this queue.
-     * @param o the element to add
-     * @return <tt>true</tt> (as per the general contract of
-     * <tt>Collection.add</tt>).
+     * Retrieves and removes the head of this queue, or returns <tt>null</tt>
+     * if this queue has no elements with an expired delay.
      *
-     * @throws NullPointerException if the specified element is <tt>null</tt>.
+     * @return the head of this queue, or <tt>null</tt> if this
+     *         queue has no elements with an expired delay
      */
-    public boolean add(E o) {
-        return offer(o);
+    public E poll() {
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            E first = q.peek();
+            if (first == null || first.getDelay(TimeUnit.NANOSECONDS) > 0)
+                return null;
+            else
+                return q.poll();
+        } finally {
+            lock.unlock();
+        }
     }
 
+    /**
+     * Retrieves and removes the head of this queue, waiting if necessary
+     * until an element with an expired delay is available on this queue.
+     *
+     * @return the head of this queue
+     * @throws InterruptedException {@inheritDoc}
+     */
     public E take() throws InterruptedException {
         final ReentrantLock lock = this.lock;
         lock.lockInterruptibly();
         try {
             for (;;) {
                 E first = q.peek();
-                if (first == null) {
+                if (first == null)
                     available.await();
-                } else {
-                    long delay =  first.getDelay(TimeUnit.NANOSECONDS);
-                    if (delay > 0) {
-                        long tl = available.awaitNanos(delay);
-                    } else {
-                        E x = q.poll();
-                        assert x != null;
-                        if (q.size() != 0)
-                            available.signalAll(); // wake up other takers
-                        return x;
-
+                else {
+                    long delay = first.getDelay(TimeUnit.NANOSECONDS);
+                    if (delay <= 0)
+                        return q.poll();
+                    else if (leader != null)
+                        available.await();
+                    else {
+                        Thread thisThread = Thread.currentThread();
+                        leader = thisThread;
+                        try {
+                            available.awaitNanos(delay);
+                        } finally {
+                            if (leader == thisThread)
+                                leader = null;
+                        }
                     }
                 }
             }
         } finally {
+            if (leader == null && q.peek() != null)
+                available.signal();
             lock.unlock();
         }
     }
 
-    public E poll(long time, TimeUnit unit) throws InterruptedException {
+    /**
+     * Retrieves and removes the head of this queue, waiting if necessary
+     * until an element with an expired delay is available on this queue,
+     * or the specified wait time expires.
+     *
+     * @return the head of this queue, or <tt>null</tt> if the
+     *         specified waiting time elapses before an element with
+     *         an expired delay becomes available
+     * @throws InterruptedException {@inheritDoc}
+     */
+    public E poll(long timeout, TimeUnit unit) throws InterruptedException {
+        long nanos = unit.toNanos(timeout);
         final ReentrantLock lock = this.lock;
         lock.lockInterruptibly();
-        long nanos = unit.toNanos(time);
         try {
             for (;;) {
                 E first = q.peek();
@@ -150,46 +226,43 @@
                     else
                         nanos = available.awaitNanos(nanos);
                 } else {
-                    long delay =  first.getDelay(TimeUnit.NANOSECONDS);
-                    if (delay > 0) {
-                        if (delay > nanos)
-                            delay = nanos;
-                        long timeLeft = available.awaitNanos(delay);
-                        nanos -= delay - timeLeft;
-                    } else {
-                        E x = q.poll();
-                        assert x != null;
-                        if (q.size() != 0)
-                            available.signalAll();
-                        return x;
+                    long delay = first.getDelay(TimeUnit.NANOSECONDS);
+                    if (delay <= 0)
+                        return q.poll();
+                    if (nanos <= 0)
+                        return null;
+                    if (nanos < delay || leader != null)
+                        nanos = available.awaitNanos(nanos);
+                    else {
+                        Thread thisThread = Thread.currentThread();
+                        leader = thisThread;
+                        try {
+                            long timeLeft = available.awaitNanos(delay);
+                            nanos -= delay - timeLeft;
+                        } finally {
+                            if (leader == thisThread)
+                                leader = null;
+                        }
                     }
                 }
             }
         } finally {
+            if (leader == null && q.peek() != null)
+                available.signal();
             lock.unlock();
         }
     }
 
-
-    public E poll() {
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
-            E first = q.peek();
-            if (first == null || first.getDelay(TimeUnit.NANOSECONDS) > 0)
-                return null;
-            else {
-                E x = q.poll();
-                assert x != null;
-                if (q.size() != 0)
-                    available.signalAll();
-                return x;
-            }
-        } finally {
-            lock.unlock();
-        }
-    }
-
+    /**
+     * Retrieves, but does not remove, the head of this queue, or
+     * returns <tt>null</tt> if this queue is empty.  Unlike
+     * <tt>poll</tt>, if no expired elements are available in the queue,
+     * this method returns the element that will expire next,
+     * if one exists.
+     *
+     * @return the head of this queue, or <tt>null</tt> if this
+     *         queue is empty.
+     */
     public E peek() {
         final ReentrantLock lock = this.lock;
         lock.lock();
@@ -210,6 +283,12 @@
         }
     }
 
+    /**
+     * @throws UnsupportedOperationException {@inheritDoc}
+     * @throws ClassCastException            {@inheritDoc}
+     * @throws NullPointerException          {@inheritDoc}
+     * @throws IllegalArgumentException      {@inheritDoc}
+     */
     public int drainTo(Collection<? super E> c) {
         if (c == null)
             throw new NullPointerException();
@@ -226,14 +305,18 @@
                 c.add(q.poll());
                 ++n;
             }
-            if (n > 0)
-                available.signalAll();
             return n;
         } finally {
             lock.unlock();
         }
     }
 
+    /**
+     * @throws UnsupportedOperationException {@inheritDoc}
+     * @throws ClassCastException            {@inheritDoc}
+     * @throws NullPointerException          {@inheritDoc}
+     * @throws IllegalArgumentException      {@inheritDoc}
+     */
     public int drainTo(Collection<? super E> c, int maxElements) {
         if (c == null)
             throw new NullPointerException();
@@ -252,8 +335,6 @@
                 c.add(q.poll());
                 ++n;
             }
-            if (n > 0)
-                available.signalAll();
             return n;
         } finally {
             lock.unlock();
@@ -263,6 +344,8 @@
     /**
      * Atomically removes all of the elements from this delay queue.
      * The queue will be empty after this call returns.
+     * Elements with an unexpired delay are not waited for; they are
+     * simply discarded from the queue.
      */
     public void clear() {
         final ReentrantLock lock = this.lock;
@@ -277,12 +360,26 @@
     /**
      * Always returns <tt>Integer.MAX_VALUE</tt> because
      * a <tt>DelayQueue</tt> is not capacity constrained.
+     *
      * @return <tt>Integer.MAX_VALUE</tt>
      */
     public int remainingCapacity() {
         return Integer.MAX_VALUE;
     }
 
+    /**
+     * Returns an array containing all of the elements in this queue.
+     * The returned array elements are in no particular order.
+     *
+     * <p>The returned array will be "safe" in that no references to it are
+     * maintained by this queue.  (In other words, this method must allocate
+     * a new array).  The caller is thus free to modify the returned array.
+     *
+     * <p>This method acts as bridge between array-based and collection-based
+     * APIs.
+     *
+     * @return an array containing all of the elements in this queue
+     */
     public Object[] toArray() {
         final ReentrantLock lock = this.lock;
         lock.lock();
@@ -293,16 +390,56 @@
         }
     }
 
-    public <T> T[] toArray(T[] array) {
+    /**
+     * Returns an array containing all of the elements in this queue; the
+     * runtime type of the returned array is that of the specified array.
+     * The returned array elements are in no particular order.
+     * If the queue fits in the specified array, it is returned therein.
+     * Otherwise, a new array is allocated with the runtime type of the
+     * specified array and the size of this queue.
+     *
+     * <p>If this queue fits in the specified array with room to spare
+     * (i.e., the array has more elements than this queue), the element in
+     * the array immediately following the end of the queue is set to
+     * <tt>null</tt>.
+     *
+     * <p>Like the {@link #toArray()} method, this method acts as bridge between
+     * array-based and collection-based APIs.  Further, this method allows
+     * precise control over the runtime type of the output array, and may,
+     * under certain circumstances, be used to save allocation costs.
+     *
+     * <p>The following code can be used to dump a delay queue into a newly
+     * allocated array of <tt>Delayed</tt>:
+     *
+     * <pre>
+     *     Delayed[] a = q.toArray(new Delayed[0]);</pre>
+     *
+     * Note that <tt>toArray(new Object[0])</tt> is identical in function to
+     * <tt>toArray()</tt>.
+     *
+     * @param a the array into which the elements of the queue are to
+     *          be stored, if it is big enough; otherwise, a new array of the
+     *          same runtime type is allocated for this purpose
+     * @return an array containing all of the elements in this queue
+     * @throws ArrayStoreException if the runtime type of the specified array
+     *         is not a supertype of the runtime type of every element in
+     *         this queue
+     * @throws NullPointerException if the specified array is null
+     */
+    public <T> T[] toArray(T[] a) {
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            return q.toArray(array);
+            return q.toArray(a);
         } finally {
             lock.unlock();
         }
     }
 
+    /**
+     * Removes a single instance of the specified element from this
+     * queue, if it is present, whether or not it has expired.
+     */
     public boolean remove(Object o) {
         final ReentrantLock lock = this.lock;
         lock.lock();
@@ -314,49 +451,61 @@
     }
 
     /**
-     * Returns an iterator over the elements in this queue. The iterator
-     * does not return the elements in any particular order. The
-     * returned iterator is a thread-safe "fast-fail" iterator that will
-     * throw {@link java.util.ConcurrentModificationException}
-     * upon detected interference.
+     * Returns an iterator over all the elements (both expired and
+     * unexpired) in this queue. The iterator does not return the
+     * elements in any particular order.  The returned
+     * <tt>Iterator</tt> is a "weakly consistent" iterator that will
+     * never throw {@link ConcurrentModificationException}, and
+     * guarantees to traverse elements as they existed upon
+     * construction of the iterator, and may (but is not guaranteed
+     * to) reflect any modifications subsequent to construction.
      *
-     * @return an iterator over the elements in this queue.
+     * @return an iterator over the elements in this queue
      */
     public Iterator<E> iterator() {
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
-            return new Itr(q.iterator());
-        } finally {
-            lock.unlock();
-        }
+        return new Itr(toArray());
     }
 
-    private class Itr<E> implements Iterator<E> {
-        private final Iterator<E> iter;
-        Itr(Iterator<E> i) {
-            iter = i;
+    /**
+     * Snapshot iterator that works off copy of underlying q array.
+     */
+    private class Itr implements Iterator<E> {
+        final Object[] array; // Array of all elements
+        int cursor;           // index of next element to return;
+        int lastRet;          // index of last element, or -1 if no such
+
+        Itr(Object[] array) {
+            lastRet = -1;
+            this.array = array;
         }
 
         public boolean hasNext() {
-            return iter.hasNext();
+            return cursor < array.length;
         }
 
+        @SuppressWarnings("unchecked")
         public E next() {
-            final ReentrantLock lock = DelayQueue.this.lock;
-            lock.lock();
-            try {
-                return iter.next();
-            } finally {
-                lock.unlock();
-            }
+            if (cursor >= array.length)
+                throw new NoSuchElementException();
+            lastRet = cursor;
+            return (E)array[cursor++];
         }
 
         public void remove() {
-            final ReentrantLock lock = DelayQueue.this.lock;
+            if (lastRet < 0)
+                throw new IllegalStateException();
+            Object x = array[lastRet];
+            lastRet = -1;
+            // Traverse underlying queue to find == element,
+            // not just a .equals element.
             lock.lock();
             try {
-                iter.remove();
+                for (Iterator it = q.iterator(); it.hasNext(); ) {
+                    if (it.next() == x) {
+                        it.remove();
+                        return;
+                    }
+                }
             } finally {
                 lock.unlock();
             }
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/Delayed.java b/libcore/concurrent/src/main/java/java/util/concurrent/Delayed.java
index bd48292..af41300 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/Delayed.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/Delayed.java
@@ -4,6 +4,11 @@
  * http://creativecommons.org/licenses/publicdomain
  */
 
+/*
+ * Modified in Apache Harmony to comply with Java 5 signature
+ * specification.
+ */
+
 package java.util.concurrent;
 
 import java.util.*;
@@ -26,11 +31,12 @@
 public interface Delayed extends Comparable<Delayed> {
 
     /**
-     * Returns the delay associated with this object, in the given time unit.
+     * Returns the remaining delay associated with this object, in the
+     * given time unit.
      *
      * @param unit the time unit
-     * @return the delay; zero or negative values indicate that the
-     * delay has already elapsed
+     * @return the remaining delay; zero or negative values indicate
+     * that the delay has already elapsed
      */
     long getDelay(TimeUnit unit);
 }
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/Exchanger.java b/libcore/concurrent/src/main/java/java/util/concurrent/Exchanger.java
index da8c815..f67659c 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/Exchanger.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/Exchanger.java
@@ -1,27 +1,31 @@
 /*
- * Written by Doug Lea with assistance from members of JCP JSR-166
- * Expert Group and released to the public domain, as explained at
+ * Written by Doug Lea, Bill Scherer, and Michael Scott with
+ * assistance from members of JCP JSR-166 Expert Group and released to
+ * the public domain, as explained at
  * http://creativecommons.org/licenses/publicdomain
  */
 
 package java.util.concurrent;
-import java.util.concurrent.locks.*;
+import java.util.concurrent.atomic.*;
+import java.util.concurrent.locks.LockSupport;
 
 /**
- * A synchronization point at which two threads can exchange objects.
- * Each thread presents some object on entry to the {@link #exchange
- * exchange} method, and receives the object presented by the other
- * thread on return.
+ * A synchronization point at which threads can pair and swap elements
+ * within pairs.  Each thread presents some object on entry to the
+ * {@link #exchange exchange} method, matches with a partner thread,
+ * and receives its partner's object on return.  An Exchanger may be
+ * viewed as a bidirectional form of a {@link SynchronousQueue}.
+ * Exchangers may be useful in applications such as genetic algorithms
+ * and pipeline designs.
  *
  * <p><b>Sample Usage:</b>
- * Here are the highlights of a class that uses an <tt>Exchanger</tt> to
- * swap buffers between threads so that the thread filling the
- * buffer gets a freshly
- * emptied one when it needs it, handing off the filled one to
- * the thread emptying the buffer.
- * <pre>
+ * Here are the highlights of a class that uses an {@code Exchanger}
+ * to swap buffers between threads so that the thread filling the
+ * buffer gets a freshly emptied one when it needs it, handing off the
+ * filled one to the thread emptying the buffer.
+ * <pre>{@code
  * class FillAndEmpty {
- *   Exchanger&lt;DataBuffer&gt; exchanger = new Exchanger();
+ *   Exchanger<DataBuffer> exchanger = new Exchanger<DataBuffer>();
  *   DataBuffer initialEmptyBuffer = ... a made-up type
  *   DataBuffer initialFullBuffer = ...
  *
@@ -31,7 +35,7 @@
  *       try {
  *         while (currentBuffer != null) {
  *           addToBuffer(currentBuffer);
- *           if (currentBuffer.full())
+ *           if (currentBuffer.isFull())
  *             currentBuffer = exchanger.exchange(currentBuffer);
  *         }
  *       } catch (InterruptedException ex) { ... handle ... }
@@ -44,7 +48,7 @@
  *       try {
  *         while (currentBuffer != null) {
  *           takeFromBuffer(currentBuffer);
- *           if (currentBuffer.empty())
+ *           if (currentBuffer.isEmpty())
  *             currentBuffer = exchanger.exchange(currentBuffer);
  *         }
  *       } catch (InterruptedException ex) { ... handle ...}
@@ -56,192 +60,597 @@
  *     new Thread(new EmptyingLoop()).start();
  *   }
  * }
- * </pre>
+ * }</pre>
+ *
+ * <p>Memory consistency effects: For each pair of threads that
+ * successfully exchange objects via an {@code Exchanger}, actions
+ * prior to the {@code exchange()} in each thread
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * those subsequent to a return from the corresponding {@code exchange()}
+ * in the other thread.
  *
  * @since 1.5
- * @author Doug Lea
+ * @author Doug Lea and Bill Scherer and Michael Scott
  * @param <V> The type of objects that may be exchanged
  */
 public class Exchanger<V> {
-    private final ReentrantLock lock = new ReentrantLock();
-    private final Condition taken = lock.newCondition();
-
-    /** Holder for the item being exchanged */
-    private V item;
-    
-    /**
-     * Arrival count transitions from 0 to 1 to 2 then back to 0
-     * during an exchange.
+    /*
+     * Algorithm Description:
+     *
+     * The basic idea is to maintain a "slot", which is a reference to
+     * a Node containing both an Item to offer and a "hole" waiting to
+     * get filled in.  If an incoming "occupying" thread sees that the
+     * slot is null, it CAS'es (compareAndSets) a Node there and waits
+     * for another to invoke exchange.  That second "fulfilling" thread
+     * sees that the slot is non-null, and so CASes it back to null,
+     * also exchanging items by CASing the hole, plus waking up the
+     * occupying thread if it is blocked.  In each case CAS'es may
+     * fail because a slot at first appears non-null but is null upon
+     * CAS, or vice-versa.  So threads may need to retry these
+     * actions.
+     *
+     * This simple approach works great when there are only a few
+     * threads using an Exchanger, but performance rapidly
+     * deteriorates due to CAS contention on the single slot when
+     * there are lots of threads using an exchanger.  So instead we use
+     * an "arena"; basically a kind of hash table with a dynamically
+     * varying number of slots, any one of which can be used by
+     * threads performing an exchange.  Incoming threads pick slots
+     * based on a hash of their Thread ids.  If an incoming thread
+     * fails to CAS in its chosen slot, it picks an alternative slot
+     * instead.  And similarly from there.  If a thread successfully
+     * CASes into a slot but no other thread arrives, it tries
+     * another, heading toward the zero slot, which always exists even
+     * if the table shrinks.  The particular mechanics controlling this
+     * are as follows:
+     *
+     * Waiting: Slot zero is special in that it is the only slot that
+     * exists when there is no contention.  A thread occupying slot
+     * zero will block if no thread fulfills it after a short spin.
+     * In other cases, occupying threads eventually give up and try
+     * another slot.  Waiting threads spin for a while (a period that
+     * should be a little less than a typical context-switch time)
+     * before either blocking (if slot zero) or giving up (if other
+     * slots) and restarting.  There is no reason for threads to block
+     * unless there are unlikely to be any other threads present.
+     * Occupants are mainly avoiding memory contention so sit there
+     * quietly polling for a shorter period than it would take to
+     * block and then unblock them.  Non-slot-zero waits that elapse
+     * because of lack of other threads waste around one extra
+     * context-switch time per try, which is still on average much
+     * faster than alternative approaches.
+     *
+     * Sizing: Usually, using only a few slots suffices to reduce
+     * contention.  Especially with small numbers of threads, using
+     * too many slots can lead to just as poor performance as using
+     * too few of them, and there's not much room for error.  The
+     * variable "max" maintains the number of slots actually in
+     * use.  It is increased when a thread sees too many CAS
+     * failures.  (This is analogous to resizing a regular hash table
+     * based on a target load factor, except here, growth steps are
+     * just one-by-one rather than proportional.)  Growth requires
+     * contention failures in each of three tried slots.  Requiring
+     * multiple failures for expansion copes with the fact that some
+     * failed CASes are not due to contention but instead to simple
+     * races between two threads or thread pre-emptions occurring
+     * between reading and CASing.  Also, very transient peak
+     * contention can be much higher than the average sustainable
+     * levels.  The max limit is decreased on average 50% of the times
+     * that a non-slot-zero wait elapses without being fulfilled.
+     * Threads experiencing elapsed waits move closer to zero, so
+     * eventually find existing (or future) threads even if the table
+     * has been shrunk due to inactivity.  The chosen mechanics and
+     * thresholds for growing and shrinking are intrinsically
+     * entangled with indexing and hashing inside the exchange code,
+     * and can't be nicely abstracted out.
+     *
+     * Hashing: Each thread picks its initial slot to use in accord
+     * with a simple hashcode.  The sequence is the same on each
+     * encounter by any given thread, but effectively random across
+     * threads.  Using arenas encounters the classic cost vs quality
+     * tradeoffs of all hash tables.  Here, we use a one-step FNV-1a
+     * hash code based on the current thread's Thread.getId(), along
+     * with a cheap approximation to a mod operation to select an
+     * index.  The downside of optimizing index selection in this way
+     * is that the code is hardwired to use a maximum table size of
+     * 32.  But this value more than suffices for known platforms and
+     * applications.
+     *
+     * Probing: On sensed contention of a selected slot, we probe
+     * sequentially through the table, analogously to linear probing
+     * after collision in a hash table.  (We move circularly, in
+     * reverse order, to mesh best with table growth and shrinkage
+     * rules.)  Except that to minimize the effects of false-alarms
+     * and cache thrashing, we try the first selected slot twice
+     * before moving.
+     *
+     * Padding: Even with contention management, slots are heavily
+     * contended, so use cache-padding to avoid poor memory
+     * performance.  Because of this, slots are lazily constructed
+     * only when used, to avoid wasting this space unnecessarily.
+     * While isolation of locations is not much of an issue at first
+     * in an application, as time goes on and garbage-collectors
+     * perform compaction, slots are very likely to be moved adjacent
+     * to each other, which can cause much thrashing of cache lines on
+     * MPs unless padding is employed.
+     *
+     * This is an improvement of the algorithm described in the paper
+     * "A Scalable Elimination-based Exchange Channel" by William
+     * Scherer, Doug Lea, and Michael Scott in Proceedings of SCOOL05
+     * workshop.  Available at: http://hdl.handle.net/1802/2104
      */
-    private int arrivalCount;
+
+    /** The number of CPUs, for sizing and spin control */
+    private static final int NCPU = Runtime.getRuntime().availableProcessors();
 
     /**
-     * Main exchange function, handling the different policy variants.
+     * The capacity of the arena.  Set to a value that provides more
+     * than enough space to handle contention.  On small machines
+     * most slots won't be used, but it is still not wasted because
+     * the extra space provides some machine-level address padding
+     * to minimize interference with heavily CAS'ed Slot locations.
+     * And on very large machines, performance eventually becomes
+     * bounded by memory bandwidth, not numbers of threads/CPUs.
+     * This constant cannot be changed without also modifying
+     * indexing and hashing algorithms.
      */
-    private V doExchange(V x, boolean timed, long nanos) throws InterruptedException, TimeoutException {
-        lock.lock();
-        try {
-            V other;
+    private static final int CAPACITY = 32;
 
-            // If arrival count already at two, we must wait for
-            // a previous pair to finish and reset the count;
-            while (arrivalCount == 2) {
-                if (!timed)
-                    taken.await();
-                else if (nanos > 0) 
-                    nanos = taken.awaitNanos(nanos);
-                else 
-                    throw new TimeoutException();
-            }
+    /**
+     * The value of "max" that will hold all threads without
+     * contention.  When this value is less than CAPACITY, some
+     * otherwise wasted expansion can be avoided.
+     */
+    private static final int FULL =
+        Math.max(0, Math.min(CAPACITY, NCPU / 2) - 1);
 
-            int count = ++arrivalCount;
+    /**
+     * The number of times to spin (doing nothing except polling a
+     * memory location) before blocking or giving up while waiting to
+     * be fulfilled.  Should be zero on uniprocessors.  On
+     * multiprocessors, this value should be large enough so that two
+     * threads exchanging items as fast as possible block only when
+     * one of them is stalled (due to GC or preemption), but not much
+     * longer, to avoid wasting CPU resources.  Seen differently, this
+     * value is a little over half the number of cycles of an average
+     * context switch time on most systems.  The value here is
+     * approximately the average of those across a range of tested
+     * systems.
+     */
+    private static final int SPINS = (NCPU == 1) ? 0 : 2000;
 
-            // If item is already waiting, replace it and signal other thread
-            if (count == 2) { 
-                other = item;
-                item = x;
-                taken.signal();
-                return other;
-            }
+    /**
+     * The number of times to spin before blocking in timed waits.
+     * Timed waits spin more slowly because checking the time takes
+     * time.  The best value relies mainly on the relative rate of
+     * System.nanoTime vs memory accesses.  The value is empirically
+     * derived to work well across a variety of systems.
+     */
+    private static final int TIMED_SPINS = SPINS / 20;
 
-            // Otherwise, set item and wait for another thread to
-            // replace it and signal us.
+    /**
+     * Sentinel item representing cancellation of a wait due to
+     * interruption, timeout, or elapsed spin-waits.  This value is
+     * placed in holes on cancellation, and used as a return value
+     * from waiting methods to indicate failure to set or get hole.
+     */
+    private static final Object CANCEL = new Object();
 
-            item = x;
-            InterruptedException interrupted = null;
-            try { 
-                while (arrivalCount != 2) {
-                    if (!timed)
-                        taken.await();
-                    else if (nanos > 0) 
-                        nanos = taken.awaitNanos(nanos);
-                    else 
-                        break; // timed out
-                }
-            } catch (InterruptedException ie) {
-                interrupted = ie;
-            }
+    /**
+     * Value representing null arguments/returns from public
+     * methods.  This disambiguates from internal requirement that
+     * holes start out as null to mean they are not yet set.
+     */
+    private static final Object NULL_ITEM = new Object();
 
-            // Get and reset item and count after the wait.
-            // (We need to do this even if wait was aborted.)
-            other = item;
-            item = null;
-            count = arrivalCount;
-            arrivalCount = 0; 
-            taken.signal();
-            
-            // If the other thread replaced item, then we must
-            // continue even if cancelled.
-            if (count == 2) {
-                if (interrupted != null)
-                    Thread.currentThread().interrupt();
-                return other;
-            }
+    /**
+     * Nodes hold partially exchanged data.  This class
+     * opportunistically subclasses AtomicReference to represent the
+     * hole.  So get() returns hole, and compareAndSet CAS'es value
+     * into hole.  This class cannot be parameterized as "V" because
+     * of the use of non-V CANCEL sentinels.
+     */
+    private static final class Node extends AtomicReference<Object> {
+        /** The element offered by the Thread creating this node. */
+        public final Object item;
 
-            // If no one is waiting for us, we can back out
-            if (interrupted != null) 
-                throw interrupted;
-            else  // must be timeout
-                throw new TimeoutException();
-        } finally {
-            lock.unlock();
+        /** The Thread waiting to be signalled; null until waiting. */
+        public volatile Thread waiter;
+
+        /**
+         * Creates node with given item and empty hole.
+         * @param item the item
+         */
+        public Node(Object item) {
+            this.item = item;
         }
     }
 
     /**
-     * Create a new Exchanger.
-     **/
+     * A Slot is an AtomicReference with heuristic padding to lessen
+     * cache effects of this heavily CAS'ed location.  While the
+     * padding adds noticeable space, all slots are created only on
+     * demand, and there will be more than one of them only when it
+     * would improve throughput more than enough to outweigh using
+     * extra space.
+     */
+    private static final class Slot extends AtomicReference<Object> {
+        // Improve likelihood of isolation on <= 64 byte cache lines
+        long q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, qa, qb, qc, qd, qe;
+    }
+
+    /**
+     * Slot array.  Elements are lazily initialized when needed.
+     * Declared volatile to enable double-checked lazy construction.
+     */
+    private volatile Slot[] arena = new Slot[CAPACITY];
+
+    /**
+     * The maximum slot index being used.  The value sometimes
+     * increases when a thread experiences too many CAS contentions,
+     * and sometimes decreases when a spin-wait elapses.  Changes
+     * are performed only via compareAndSet, to avoid stale values
+     * when a thread happens to stall right before setting.
+     */
+    private final AtomicInteger max = new AtomicInteger();
+
+    /**
+     * Main exchange function, handling the different policy variants.
+     * Uses Object, not "V" as argument and return value to simplify
+     * handling of sentinel values.  Callers from public methods decode
+     * and cast accordingly.
+     *
+     * @param item the (non-null) item to exchange
+     * @param timed true if the wait is timed
+     * @param nanos if timed, the maximum wait time
+     * @return the other thread's item, or CANCEL if interrupted or timed out
+     */
+    private Object doExchange(Object item, boolean timed, long nanos) {
+        Node me = new Node(item);                 // Create in case occupying
+        int index = hashIndex();                  // Index of current slot
+        int fails = 0;                            // Number of CAS failures
+
+        for (;;) {
+            Object y;                             // Contents of current slot
+            Slot slot = arena[index];
+            if (slot == null)                     // Lazily initialize slots
+                createSlot(index);                // Continue loop to reread
+            else if ((y = slot.get()) != null &&  // Try to fulfill
+                     slot.compareAndSet(y, null)) {
+                Node you = (Node)y;               // Transfer item
+                if (you.compareAndSet(null, item)) {
+                    LockSupport.unpark(you.waiter);
+                    return you.item;
+                }                                 // Else cancelled; continue
+            }
+            else if (y == null &&                 // Try to occupy
+                     slot.compareAndSet(null, me)) {
+                if (index == 0)                   // Blocking wait for slot 0
+                    return timed? awaitNanos(me, slot, nanos): await(me, slot);
+                Object v = spinWait(me, slot);    // Spin wait for non-0
+                if (v != CANCEL)
+                    return v;
+                me = new Node(item);              // Throw away cancelled node
+                int m = max.get();
+                if (m > (index >>>= 1))           // Decrease index
+                    max.compareAndSet(m, m - 1);  // Maybe shrink table
+            }
+            else if (++fails > 1) {               // Allow 2 fails on 1st slot
+                int m = max.get();
+                if (fails > 3 && m < FULL && max.compareAndSet(m, m + 1))
+                    index = m + 1;                // Grow on 3rd failed slot
+                else if (--index < 0)
+                    index = m;                    // Circularly traverse
+            }
+        }
+    }
+
+    /**
+     * Returns a hash index for the current thread.  Uses a one-step
+     * FNV-1a hash code (http://www.isthe.com/chongo/tech/comp/fnv/)
+     * based on the current thread's Thread.getId().  These hash codes
+     * have more uniform distribution properties with respect to small
+     * moduli (here 1-31) than do other simple hashing functions.
+     *
+     * <p>To return an index between 0 and max, we use a cheap
+     * approximation to a mod operation, that also corrects for bias
+     * due to non-power-of-2 remaindering (see {@link
+     * java.util.Random#nextInt}).  Bits of the hashcode are masked
+     * with "nbits", the ceiling power of two of table size (looked up
+     * in a table packed into three ints).  If too large, this is
+     * retried after rotating the hash by nbits bits, while forcing new
+     * top bit to 0, which guarantees eventual termination (although
+     * with a non-random-bias).  This requires an average of less than
+     * 2 tries for all table sizes, and has a maximum 2% difference
+     * from perfectly uniform slot probabilities when applied to all
+     * possible hash codes for sizes less than 32.
+     *
+     * @return a per-thread-random index, 0 <= index < max
+     */
+    private final int hashIndex() {
+        long id = Thread.currentThread().getId();
+        int hash = (((int)(id ^ (id >>> 32))) ^ 0x811c9dc5) * 0x01000193;
+
+        int m = max.get();
+        int nbits = (((0xfffffc00  >> m) & 4) | // Compute ceil(log2(m+1))
+                     ((0x000001f8 >>> m) & 2) | // The constants hold
+                     ((0xffff00f2 >>> m) & 1)); // a lookup table
+        int index;
+        while ((index = hash & ((1 << nbits) - 1)) > m)       // May retry on
+            hash = (hash >>> nbits) | (hash << (33 - nbits)); // non-power-2 m
+        return index;
+    }
+
+    /**
+     * Creates a new slot at given index.  Called only when the slot
+     * appears to be null.  Relies on double-check using builtin
+     * locks, since they rarely contend.  This in turn relies on the
+     * arena array being declared volatile.
+     *
+     * @param index the index to add slot at
+     */
+    private void createSlot(int index) {
+        // Create slot outside of lock to narrow sync region
+        Slot newSlot = new Slot();
+        Slot[] a = arena;
+        synchronized (a) {
+            if (a[index] == null)
+                a[index] = newSlot;
+        }
+    }
+
+    /**
+     * Tries to cancel a wait for the given node waiting in the given
+     * slot, if so, helping clear the node from its slot to avoid
+     * garbage retention.
+     *
+     * @param node the waiting node
+     * @param slot the slot it is waiting in
+     * @return true if successfully cancelled
+     */
+    private static boolean tryCancel(Node node, Slot slot) {
+        if (!node.compareAndSet(null, CANCEL))
+            return false;
+        if (slot.get() == node) // pre-check to minimize contention
+            slot.compareAndSet(node, null);
+        return true;
+    }
+
+    // Three forms of waiting. Each just different enough not to merge
+    // code with others.
+
+    /**
+     * Spin-waits for hole for a non-0 slot.  Fails if spin elapses
+     * before hole filled.  Does not check interrupt, relying on check
+     * in public exchange method to abort if interrupted on entry.
+     *
+     * @param node the waiting node
+     * @return on success, the hole; on failure, CANCEL
+     */
+    private static Object spinWait(Node node, Slot slot) {
+        int spins = SPINS;
+        for (;;) {
+            Object v = node.get();
+            if (v != null)
+                return v;
+            else if (spins > 0)
+                --spins;
+            else
+                tryCancel(node, slot);
+        }
+    }
+
+    /**
+     * Waits for (by spinning and/or blocking) and gets the hole
+     * filled in by another thread.  Fails if interrupted before
+     * hole filled.
+     *
+     * When a node/thread is about to block, it sets its waiter field
+     * and then rechecks state at least one more time before actually
+     * parking, thus covering race vs fulfiller noticing that waiter
+     * is non-null so should be woken.
+     *
+     * Thread interruption status is checked only surrounding calls to
+     * park.  The caller is assumed to have checked interrupt status
+     * on entry.
+     *
+     * @param node the waiting node
+     * @return on success, the hole; on failure, CANCEL
+     */
+    private static Object await(Node node, Slot slot) {
+        Thread w = Thread.currentThread();
+        int spins = SPINS;
+        for (;;) {
+            Object v = node.get();
+            if (v != null)
+                return v;
+            else if (spins > 0)                 // Spin-wait phase
+                --spins;
+            else if (node.waiter == null)       // Set up to block next
+                node.waiter = w;
+            else if (w.isInterrupted())         // Abort on interrupt
+                tryCancel(node, slot);
+            else                                // Block
+                LockSupport.park();
+        }
+    }
+
+    /**
+     * Waits for (at index 0) and gets the hole filled in by another
+     * thread.  Fails if timed out or interrupted before hole filled.
+     * Same basic logic as untimed version, but a bit messier.
+     *
+     * @param node the waiting node
+     * @param nanos the wait time
+     * @return on success, the hole; on failure, CANCEL
+     */
+    private Object awaitNanos(Node node, Slot slot, long nanos) {
+        int spins = TIMED_SPINS;
+        long lastTime = 0;
+        Thread w = null;
+        for (;;) {
+            Object v = node.get();
+            if (v != null)
+                return v;
+            long now = System.nanoTime();
+            if (w == null)
+                w = Thread.currentThread();
+            else
+                nanos -= now - lastTime;
+            lastTime = now;
+            if (nanos > 0) {
+                if (spins > 0)
+                    --spins;
+                else if (node.waiter == null)
+                    node.waiter = w;
+                else if (w.isInterrupted())
+                    tryCancel(node, slot);
+                else
+                    LockSupport.parkNanos(nanos);
+            }
+            else if (tryCancel(node, slot) && !w.isInterrupted())
+                return scanOnTimeout(node);
+        }
+    }
+
+    /**
+     * Sweeps through arena checking for any waiting threads.  Called
+     * only upon return from timeout while waiting in slot 0.  When a
+     * thread gives up on a timed wait, it is possible that a
+     * previously-entered thread is still waiting in some other
+     * slot.  So we scan to check for any.  This is almost always
+     * overkill, but decreases the likelihood of timeouts when there
+     * are other threads present to far less than that in lock-based
+     * exchangers in which earlier-arriving threads may still be
+     * waiting on entry locks.
+     *
+     * @param node the waiting node
+     * @return another thread's item, or CANCEL
+     */
+    private Object scanOnTimeout(Node node) {
+        Object y;
+        for (int j = arena.length - 1; j >= 0; --j) {
+            Slot slot = arena[j];
+            if (slot != null) {
+                while ((y = slot.get()) != null) {
+                    if (slot.compareAndSet(y, null)) {
+                        Node you = (Node)y;
+                        if (you.compareAndSet(null, node.item)) {
+                            LockSupport.unpark(you.waiter);
+                            return you.item;
+                        }
+                    }
+                }
+            }
+        }
+        return CANCEL;
+    }
+
+    /**
+     * Creates a new Exchanger.
+     */
     public Exchanger() {
     }
 
     /**
      * Waits for another thread to arrive at this exchange point (unless
-     * it is {@link Thread#interrupt interrupted}),
+     * the current thread is {@linkplain Thread#interrupt interrupted}),
      * and then transfers the given object to it, receiving its object
      * in return.
+     *
      * <p>If another thread is already waiting at the exchange point then
      * it is resumed for thread scheduling purposes and receives the object
-     * passed in by the current thread. The current thread returns immediately,
+     * passed in by the current thread.  The current thread returns immediately,
      * receiving the object passed to the exchange by that other thread.
-     * <p>If no other thread is already waiting at the exchange then the 
+     *
+     * <p>If no other thread is already waiting at the exchange then the
      * current thread is disabled for thread scheduling purposes and lies
      * dormant until one of two things happens:
      * <ul>
      * <li>Some other thread enters the exchange; or
-     * <li>Some other thread {@link Thread#interrupt interrupts} the current
+     * <li>Some other thread {@linkplain Thread#interrupt interrupts} the current
      * thread.
      * </ul>
      * <p>If the current thread:
      * <ul>
-     * <li>has its interrupted status set on entry to this method; or 
-     * <li>is {@link Thread#interrupt interrupted} while waiting
-     * for the exchange, 
+     * <li>has its interrupted status set on entry to this method; or
+     * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+     * for the exchange,
      * </ul>
-     * then {@link InterruptedException} is thrown and the current thread's 
-     * interrupted status is cleared. 
+     * then {@link InterruptedException} is thrown and the current thread's
+     * interrupted status is cleared.
      *
      * @param x the object to exchange
-     * @return the object provided by the other thread.
-     * @throws InterruptedException if current thread was interrupted 
-     * while waiting
-     **/
+     * @return the object provided by the other thread
+     * @throws InterruptedException if the current thread was
+     *         interrupted while waiting
+     */
     public V exchange(V x) throws InterruptedException {
-        try {
-            return doExchange(x, false, 0);
-        } catch (TimeoutException cannotHappen) { 
-            throw new Error(cannotHappen);
+        if (!Thread.interrupted()) {
+            Object v = doExchange(x == null? NULL_ITEM : x, false, 0);
+            if (v == NULL_ITEM)
+                return null;
+            if (v != CANCEL)
+                return (V)v;
+            Thread.interrupted(); // Clear interrupt status on IE throw
         }
+        throw new InterruptedException();
     }
 
     /**
      * Waits for another thread to arrive at this exchange point (unless
-     * it is {@link Thread#interrupt interrupted}, or the specified waiting
-     * time elapses),
-     * and then transfers the given object to it, receiving its object
-     * in return.
+     * the current thread is {@linkplain Thread#interrupt interrupted} or
+     * the specified waiting time elapses), and then transfers the given
+     * object to it, receiving its object in return.
      *
      * <p>If another thread is already waiting at the exchange point then
      * it is resumed for thread scheduling purposes and receives the object
-     * passed in by the current thread. The current thread returns immediately,
+     * passed in by the current thread.  The current thread returns immediately,
      * receiving the object passed to the exchange by that other thread.
      *
-     * <p>If no other thread is already waiting at the exchange then the 
+     * <p>If no other thread is already waiting at the exchange then the
      * current thread is disabled for thread scheduling purposes and lies
      * dormant until one of three things happens:
      * <ul>
      * <li>Some other thread enters the exchange; or
-     * <li>Some other thread {@link Thread#interrupt interrupts} the current
-     * thread; or
+     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+     * the current thread; or
      * <li>The specified waiting time elapses.
      * </ul>
      * <p>If the current thread:
      * <ul>
-     * <li>has its interrupted status set on entry to this method; or 
-     * <li>is {@link Thread#interrupt interrupted} while waiting
-     * for the exchange, 
+     * <li>has its interrupted status set on entry to this method; or
+     * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+     * for the exchange,
      * </ul>
-     * then {@link InterruptedException} is thrown and the current thread's 
-     * interrupted status is cleared. 
+     * then {@link InterruptedException} is thrown and the current thread's
+     * interrupted status is cleared.
      *
-     * <p>If the specified waiting time elapses then {@link TimeoutException}
-     * is thrown.
-     * If the time is 
-     * less than or equal to zero, the method will not wait at all.
+     * <p>If the specified waiting time elapses then {@link
+     * TimeoutException} is thrown.  If the time is less than or equal
+     * to zero, the method will not wait at all.
      *
      * @param x the object to exchange
      * @param timeout the maximum time to wait
-     * @param unit the time unit of the <tt>timeout</tt> argument.
-     * @return the object provided by the other thread.
-     * @throws InterruptedException if current thread was interrupted
-     * while waiting
-     * @throws TimeoutException if the specified waiting time elapses before
-     * another thread enters the exchange.
-     **/
-    public V exchange(V x, long timeout, TimeUnit unit) 
+     * @param unit the time unit of the <tt>timeout</tt> argument
+     * @return the object provided by the other thread
+     * @throws InterruptedException if the current thread was
+     *         interrupted while waiting
+     * @throws TimeoutException if the specified waiting time elapses
+     *         before another thread enters the exchange
+     */
+    public V exchange(V x, long timeout, TimeUnit unit)
         throws InterruptedException, TimeoutException {
-        return doExchange(x, true, unit.toNanos(timeout));
+        if (!Thread.interrupted()) {
+            Object v = doExchange(x == null? NULL_ITEM : x,
+                                  true, unit.toNanos(timeout));
+            if (v == NULL_ITEM)
+                return null;
+            if (v != CANCEL)
+                return (V)v;
+            if (!Thread.interrupted())
+                throw new TimeoutException();
+        }
+        throw new InterruptedException();
     }
-
 }
-
-
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/ExecutionException.java b/libcore/concurrent/src/main/java/java/util/concurrent/ExecutionException.java
index 8f0e448..bc561e5 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/ExecutionException.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/ExecutionException.java
@@ -19,14 +19,14 @@
     private static final long serialVersionUID = 7830266012832686185L;
 
     /**
-     * Constructs a <tt>ExecutionException</tt> with no detail message.
+     * Constructs an <tt>ExecutionException</tt> with no detail message.
      * The cause is not initialized, and may subsequently be
      * initialized by a call to {@link #initCause(Throwable) initCause}.
      */
     protected ExecutionException() { }
 
     /**
-     * Constructs a <tt>ExecutionException</tt> with the specified detail
+     * Constructs an <tt>ExecutionException</tt> with the specified detail
      * message. The cause is not initialized, and may subsequently be
      * initialized by a call to {@link #initCause(Throwable) initCause}.
      *
@@ -37,7 +37,7 @@
     }
 
     /**
-     * Constructs a <tt>ExecutionException</tt> with the specified detail
+     * Constructs an <tt>ExecutionException</tt> with the specified detail
      * message and cause.
      *
      * @param  message the detail message
@@ -49,7 +49,7 @@
     }
 
     /**
-     * Constructs a <tt>ExecutionException</tt> with the specified cause.
+     * Constructs an <tt>ExecutionException</tt> with the specified cause.
      * The detail message is set to:
      * <pre>
      *  (cause == null ? null : cause.toString())</pre>
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/Executor.java b/libcore/concurrent/src/main/java/java/util/concurrent/Executor.java
index 60fe193..a61e921 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/Executor.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/Executor.java
@@ -21,7 +21,7 @@
  * executor.execute(new RunnableTask2());
  * ...
  * </pre>
- * 
+ *
  * However, the <tt>Executor</tt> interface does not strictly
  * require that execution be asynchronous. In the simplest case, an
  * executor can run the submitted task immediately in the caller's
@@ -52,7 +52,7 @@
  *
  * <pre>
  * class SerialExecutor implements Executor {
- *     final Queue&lt;Runnable&gt; tasks = new LinkedBlockingQueue&lt;Runnable&gt;();
+ *     final Queue&lt;Runnable&gt; tasks = new ArrayDeque&lt;Runnable&gt;();
  *     final Executor executor;
  *     Runnable active;
  *
@@ -88,6 +88,11 @@
  * extensible thread pool implementation. The {@link Executors} class
  * provides convenient factory methods for these Executors.
  *
+ * <p>Memory consistency effects: Actions in a thread prior to
+ * submitting a {@code Runnable} object to an {@code Executor}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * its execution begins, perhaps in another thread.
+ *
  * @since 1.5
  * @author Doug Lea
  */
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/ExecutorCompletionService.java b/libcore/concurrent/src/main/java/java/util/concurrent/ExecutorCompletionService.java
index 4f9c9d9..02606f9 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/ExecutorCompletionService.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/ExecutorCompletionService.java
@@ -6,11 +6,10 @@
 
 package java.util.concurrent;
 
-
 /**
  * A {@link CompletionService} that uses a supplied {@link Executor}
  * to execute tasks.  This class arranges that submitted tasks are,
- * upon completion, placed on a queue accessible using <tt>take</tt>.
+ * upon completion, placed on a queue accessible using {@code take}.
  * The class is lightweight enough to be suitable for transient use
  * when processing groups of tasks.
  *
@@ -19,84 +18,102 @@
  * <b>Usage Examples.</b>
  *
  * Suppose you have a set of solvers for a certain problem, each
- * returning a value of some type <tt>Result</tt>, and would like to
+ * returning a value of some type {@code Result}, and would like to
  * run them concurrently, processing the results of each of them that
- * return a non-null value, in some method <tt>use(Result r)</tt>. You
+ * return a non-null value, in some method {@code use(Result r)}. You
  * could write this as:
  *
- * <pre>
- *    void solve(Executor e, Collection&lt;Callable&lt;Result&gt;&gt; solvers)
- *      throws InterruptedException, ExecutionException {
- *        CompletionService&lt;Result&gt; ecs = new ExecutorCompletionService&lt;Result&gt;(e);
- *        for (Callable&lt;Result&gt; s : solvers)
- *            ecs.submit(s);
- *        int n = solvers.size();
- *        for (int i = 0; i &lt; n; ++i) {
- *            Result r = ecs.take().get();
- *            if (r != null) 
- *                use(r);
- *        }
- *    }
- * </pre>
+ * <pre> {@code
+ * void solve(Executor e,
+ *            Collection<Callable<Result>> solvers)
+ *     throws InterruptedException, ExecutionException {
+ *     CompletionService<Result> ecs
+ *         = new ExecutorCompletionService<Result>(e);
+ *     for (Callable<Result> s : solvers)
+ *         ecs.submit(s);
+ *     int n = solvers.size();
+ *     for (int i = 0; i < n; ++i) {
+ *         Result r = ecs.take().get();
+ *         if (r != null)
+ *             use(r);
+ *     }
+ * }}</pre>
  *
  * Suppose instead that you would like to use the first non-null result
  * of the set of tasks, ignoring any that encounter exceptions,
  * and cancelling all other tasks when the first one is ready:
  *
- * <pre>
- *    void solve(Executor e, Collection&lt;Callable&lt;Result&gt;&gt; solvers) 
- *      throws InterruptedException {
- *        CompletionService&lt;Result&gt; ecs = new ExecutorCompletionService&lt;Result&gt;(e);
- *        int n = solvers.size();
- *        List&lt;Future&lt;Result&gt;&gt; futures = new ArrayList&lt;Future&lt;Result&gt;&gt;(n);
- *        Result result = null;
- *        try {
- *            for (Callable&lt;Result&gt; s : solvers)
- *                futures.add(ecs.submit(s));
- *            for (int i = 0; i &lt; n; ++i) {
- *                try {
- *                    Result r = ecs.take().get();
- *                    if (r != null) {
- *                        result = r;
- *                        break;
- *                    }
- *                } catch(ExecutionException ignore) {}
- *            }
- *        }
- *        finally {
- *            for (Future&lt;Result&gt; f : futures)
- *                f.cancel(true);
- *        }
+ * <pre> {@code
+ * void solve(Executor e,
+ *            Collection<Callable<Result>> solvers)
+ *     throws InterruptedException {
+ *     CompletionService<Result> ecs
+ *         = new ExecutorCompletionService<Result>(e);
+ *     int n = solvers.size();
+ *     List<Future<Result>> futures
+ *         = new ArrayList<Future<Result>>(n);
+ *     Result result = null;
+ *     try {
+ *         for (Callable<Result> s : solvers)
+ *             futures.add(ecs.submit(s));
+ *         for (int i = 0; i < n; ++i) {
+ *             try {
+ *                 Result r = ecs.take().get();
+ *                 if (r != null) {
+ *                     result = r;
+ *                     break;
+ *                 }
+ *             } catch (ExecutionException ignore) {}
+ *         }
+ *     }
+ *     finally {
+ *         for (Future<Result> f : futures)
+ *             f.cancel(true);
+ *     }
  *
- *        if (result != null)
- *            use(result);
- *    }
- * </pre>
+ *     if (result != null)
+ *         use(result);
+ * }}</pre>
  */
 public class ExecutorCompletionService<V> implements CompletionService<V> {
     private final Executor executor;
+    private final AbstractExecutorService aes;
     private final BlockingQueue<Future<V>> completionQueue;
 
     /**
      * FutureTask extension to enqueue upon completion
      */
-    private class QueueingFuture extends FutureTask<V> {
-        QueueingFuture(Callable<V> c) { super(c); }
-        QueueingFuture(Runnable t, V r) { super(t, r); }
-        protected void done() { completionQueue.add(this); }
+    private class QueueingFuture extends FutureTask<Void> {
+        QueueingFuture(FutureTask<V> task) {
+            super(task, null);
+            this.task = task;
+        }
+        protected void done() { completionQueue.add(task); }
+        private final Future<V> task;
+    }
+
+    private FutureTask<V> newTaskFor(Callable<V> task) {
+        return new FutureTask<V>(task);
+    }
+
+    private FutureTask<V> newTaskFor(Runnable task, V result) {
+        return new FutureTask<V>(task, result);
     }
 
     /**
      * Creates an ExecutorCompletionService using the supplied
      * executor for base task execution and a
      * {@link LinkedBlockingQueue} as a completion queue.
+     *
      * @param executor the executor to use
-     * @throws NullPointerException if executor is <tt>null</tt>
+     * @throws NullPointerException if executor is {@code null}
      */
     public ExecutorCompletionService(Executor executor) {
-        if (executor == null) 
+        if (executor == null)
             throw new NullPointerException();
         this.executor = executor;
+        this.aes = (executor instanceof AbstractExecutorService) ?
+            (AbstractExecutorService) executor : null;
         this.completionQueue = new LinkedBlockingQueue<Future<V>>();
     }
 
@@ -104,30 +121,36 @@
      * Creates an ExecutorCompletionService using the supplied
      * executor for base task execution and the supplied queue as its
      * completion queue.
+     *
      * @param executor the executor to use
      * @param completionQueue the queue to use as the completion queue
-     * normally one dedicated for use by this service
-     * @throws NullPointerException if executor or completionQueue are <tt>null</tt>
+     *        normally one dedicated for use by this service. This
+     *        queue is treated as unbounded -- failed attempted
+     *        {@code Queue.add} operations for completed taskes cause
+     *        them not to be retrievable.
+     * @throws NullPointerException if executor or completionQueue are {@code null}
      */
     public ExecutorCompletionService(Executor executor,
                                      BlockingQueue<Future<V>> completionQueue) {
-        if (executor == null || completionQueue == null) 
+        if (executor == null || completionQueue == null)
             throw new NullPointerException();
         this.executor = executor;
+        this.aes = (executor instanceof AbstractExecutorService) ?
+            (AbstractExecutorService) executor : null;
         this.completionQueue = completionQueue;
     }
 
     public Future<V> submit(Callable<V> task) {
         if (task == null) throw new NullPointerException();
-        QueueingFuture f = new QueueingFuture(task);
-        executor.execute(f);
+        FutureTask<V> f = newTaskFor(task);
+        executor.execute(new QueueingFuture(f));
         return f;
     }
 
     public Future<V> submit(Runnable task, V result) {
         if (task == null) throw new NullPointerException();
-        QueueingFuture f = new QueueingFuture(task, result);
-        executor.execute(f);
+        FutureTask<V> f = newTaskFor(task, result);
+        executor.execute(new QueueingFuture(f));
         return f;
     }
 
@@ -144,5 +167,3 @@
     }
 
 }
-
-
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/ExecutorService.java b/libcore/concurrent/src/main/java/java/util/concurrent/ExecutorService.java
index e178eb2..757f7cb 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/ExecutorService.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/ExecutorService.java
@@ -5,7 +5,6 @@
  */
 
 package java.util.concurrent;
-
 import java.util.List;
 import java.util.Collection;
 import java.security.PrivilegedAction;
@@ -14,14 +13,18 @@
 /**
  * An {@link Executor} that provides methods to manage termination and
  * methods that can produce a {@link Future} for tracking progress of
- * one or more asynchronous tasks.  
+ * one or more asynchronous tasks.
  *
- * <p>
- * An <tt>ExecutorService</tt> can be shut down, which will cause it
- * to stop accepting new tasks.  After being shut down, the executor
- * will eventually terminate, at which point no tasks are actively
- * executing, no tasks are awaiting execution, and no new tasks can be
- * submitted.
+ * <p> An <tt>ExecutorService</tt> can be shut down, which will cause
+ * it to reject new tasks.  Two different methods are provided for
+ * shutting down an <tt>ExecutorService</tt>. The {@link #shutdown}
+ * method will allow previously submitted tasks to execute before
+ * terminating, while the {@link #shutdownNow} method prevents waiting
+ * tasks from starting and attempts to stop currently executing tasks.
+ * Upon termination, an executor has no tasks actively executing, no
+ * tasks awaiting execution, and no new tasks can be submitted.  An
+ * unused <tt>ExecutorService</tt> should be shut down to allow
+ * reclamation of its resources.
  *
  * <p> Method <tt>submit</tt> extends base method {@link
  * Executor#execute} by creating and returning a {@link Future} that
@@ -35,41 +38,74 @@
  * <p>The {@link Executors} class provides factory methods for the
  * executor services provided in this package.
  *
- * <h3>Usage Example</h3>
+ * <h3>Usage Examples</h3>
  *
  * Here is a sketch of a network service in which threads in a thread
  * pool service incoming requests. It uses the preconfigured {@link
  * Executors#newFixedThreadPool} factory method:
  *
  * <pre>
- * class NetworkService {
- *    private final ServerSocket serverSocket;
- *    private final ExecutorService pool;
+ * class NetworkService implements Runnable {
+ *   private final ServerSocket serverSocket;
+ *   private final ExecutorService pool;
  *
- *    public NetworkService(int port, int poolSize) throws IOException {
- *      serverSocket = new ServerSocket(port);
- *      pool = Executors.newFixedThreadPool(poolSize);
- *    }
- * 
- *    public void serve() {
- *      try {
- *        for (;;) {
- *          pool.execute(new Handler(serverSocket.accept()));
- *        }
- *      } catch (IOException ex) {
- *        pool.shutdown();
- *      }
- *    }
- *  }
+ *   public NetworkService(int port, int poolSize)
+ *       throws IOException {
+ *     serverSocket = new ServerSocket(port);
+ *     pool = Executors.newFixedThreadPool(poolSize);
+ *   }
  *
- *  class Handler implements Runnable {
- *    private final Socket socket;
- *    Handler(Socket socket) { this.socket = socket; }
- *    public void run() {
- *      // read and service request
- *    }
+ *   public void run() { // run the service
+ *     try {
+ *       for (;;) {
+ *         pool.execute(new Handler(serverSocket.accept()));
+ *       }
+ *     } catch (IOException ex) {
+ *       pool.shutdown();
+ *     }
+ *   }
+ * }
+ *
+ * class Handler implements Runnable {
+ *   private final Socket socket;
+ *   Handler(Socket socket) { this.socket = socket; }
+ *   public void run() {
+ *     // read and service request on socket
+ *   }
  * }
  * </pre>
+ *
+ * The following method shuts down an <tt>ExecutorService</tt> in two phases,
+ * first by calling <tt>shutdown</tt> to reject incoming tasks, and then
+ * calling <tt>shutdownNow</tt>, if necessary, to cancel any lingering tasks:
+ *
+ * <pre>
+ * void shutdownAndAwaitTermination(ExecutorService pool) {
+ *   pool.shutdown(); // Disable new tasks from being submitted
+ *   try {
+ *     // Wait a while for existing tasks to terminate
+ *     if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
+ *       pool.shutdownNow(); // Cancel currently executing tasks
+ *       // Wait a while for tasks to respond to being cancelled
+ *       if (!pool.awaitTermination(60, TimeUnit.SECONDS))
+ *           System.err.println("Pool did not terminate");
+ *     }
+ *   } catch (InterruptedException ie) {
+ *     // (Re-)Cancel if current thread also interrupted
+ *     pool.shutdownNow();
+ *     // Preserve interrupt status
+ *     Thread.currentThread().interrupt();
+ *   }
+ * }
+ * </pre>
+ *
+ * <p>Memory consistency effects: Actions in a thread prior to the
+ * submission of a {@code Runnable} or {@code Callable} task to an
+ * {@code ExecutorService}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * any actions taken by that task, which in turn <i>happen-before</i> the
+ * result is retrieved via {@code Future.get()}.
+ *
  * @since 1.5
  * @author Doug Lea
  */
@@ -77,33 +113,45 @@
 
     /**
      * Initiates an orderly shutdown in which previously submitted
-     * tasks are executed, but no new tasks will be
-     * accepted. Invocation has no additional effect if already shut
-     * down.
+     * tasks are executed, but no new tasks will be accepted.
+     * Invocation has no additional effect if already shut down.
+     *
+     * <p>This method does not wait for previously submitted tasks to
+     * complete execution.  Use {@link #awaitTermination awaitTermination}
+     * to do that.
+     *
      * @throws SecurityException if a security manager exists and
-     * shutting down this ExecutorService may manipulate threads that
-     * the caller is not permitted to modify because it does not hold
-     * {@link java.lang.RuntimePermission}<tt>("modifyThread")</tt>,
-     * or the security manager's <tt>checkAccess</tt>  method denies access.
+     *         shutting down this ExecutorService may manipulate
+     *         threads that the caller is not permitted to modify
+     *         because it does not hold {@link
+     *         java.lang.RuntimePermission}<tt>("modifyThread")</tt>,
+     *         or the security manager's <tt>checkAccess</tt> method
+     *         denies access.
      */
     void shutdown();
 
     /**
      * Attempts to stop all actively executing tasks, halts the
-     * processing of waiting tasks, and returns a list of the tasks that were
-     * awaiting execution. 
-     *  
+     * processing of waiting tasks, and returns a list of the tasks
+     * that were awaiting execution.
+     *
+     * <p>This method does not wait for actively executing tasks to
+     * terminate.  Use {@link #awaitTermination awaitTermination} to
+     * do that.
+     *
      * <p>There are no guarantees beyond best-effort attempts to stop
      * processing actively executing tasks.  For example, typical
-     * implementations will cancel via {@link Thread#interrupt}, so if any
-     * tasks mask or fail to respond to interrupts, they may never terminate.
+     * implementations will cancel via {@link Thread#interrupt}, so any
+     * task that fails to respond to interrupts may never terminate.
      *
      * @return list of tasks that never commenced execution
      * @throws SecurityException if a security manager exists and
-     * shutting down this ExecutorService may manipulate threads that
-     * the caller is not permitted to modify because it does not hold
-     * {@link java.lang.RuntimePermission}<tt>("modifyThread")</tt>,
-     * or the security manager's <tt>checkAccess</tt> method denies access.
+     *         shutting down this ExecutorService may manipulate
+     *         threads that the caller is not permitted to modify
+     *         because it does not hold {@link
+     *         java.lang.RuntimePermission}<tt>("modifyThread")</tt>,
+     *         or the security manager's <tt>checkAccess</tt> method
+     *         denies access.
      */
     List<Runnable> shutdownNow();
 
@@ -130,8 +178,8 @@
      *
      * @param timeout the maximum time to wait
      * @param unit the time unit of the timeout argument
-     * @return <tt>true</tt> if this executor terminated and <tt>false</tt>
-     * if the timeout elapsed before termination
+     * @return <tt>true</tt> if this executor terminated and
+     *         <tt>false</tt> if the timeout elapsed before termination
      * @throws InterruptedException if interrupted while waiting
      */
     boolean awaitTermination(long timeout, TimeUnit unit)
@@ -139,8 +187,10 @@
 
 
     /**
-     * Submits a value-returning task for execution and returns a Future
-     * representing the pending results of the task. 
+     * Submits a value-returning task for execution and returns a
+     * Future representing the pending results of the task. The
+     * Future's <tt>get</tt> method will return the task's result upon
+     * successful completion.
      *
      * <p>
      * If you would like to immediately block waiting
@@ -154,88 +204,92 @@
      *
      * @param task the task to submit
      * @return a Future representing pending completion of the task
-     * @throws RejectedExecutionException if task cannot be scheduled
-     * for execution
-     * @throws NullPointerException if task null
+     * @throws RejectedExecutionException if the task cannot be
+     *         scheduled for execution
+     * @throws NullPointerException if the task is null
      */
     <T> Future<T> submit(Callable<T> task);
 
     /**
-     * Submits a Runnable task for execution and returns a Future 
-     * representing that task that will upon completion return 
-     * the given result
+     * Submits a Runnable task for execution and returns a Future
+     * representing that task. The Future's <tt>get</tt> method will
+     * return the given result upon successful completion.
      *
      * @param task the task to submit
      * @param result the result to return
-     * @return a Future representing pending completion of the task,
-     * and whose <tt>get()</tt> method will return the given result
-     * upon completion.
-     * @throws RejectedExecutionException if task cannot be scheduled
-     * for execution
-     * @throws NullPointerException if task null     
+     * @return a Future representing pending completion of the task
+     * @throws RejectedExecutionException if the task cannot be
+     *         scheduled for execution
+     * @throws NullPointerException if the task is null
      */
     <T> Future<T> submit(Runnable task, T result);
 
     /**
-     * Submits a Runnable task for execution and returns a Future 
-     * representing that task.
+     * Submits a Runnable task for execution and returns a Future
+     * representing that task. The Future's <tt>get</tt> method will
+     * return <tt>null</tt> upon <em>successful</em> completion.
      *
      * @param task the task to submit
-     * @return a Future representing pending completion of the task,
-     * and whose <tt>get()</tt> method will return <tt>null</tt>
-     * upon completion.
-     * @throws RejectedExecutionException if task cannot be scheduled
-     * for execution
-     * @throws NullPointerException if task null
+     * @return a Future representing pending completion of the task
+     * @throws RejectedExecutionException if the task cannot be
+     *         scheduled for execution
+     * @throws NullPointerException if the task is null
      */
     Future<?> submit(Runnable task);
 
     /**
-     * Executes the given tasks, returning their results
-     * when all complete.
+     * Executes the given tasks, returning a list of Futures holding
+     * their status and results when all complete.
+     * {@link Future#isDone} is <tt>true</tt> for each
+     * element of the returned list.
      * Note that a <em>completed</em> task could have
      * terminated either normally or by throwing an exception.
      * The results of this method are undefined if the given
      * collection is modified while this operation is in progress.
+     *
      * @param tasks the collection of tasks
      * @return A list of Futures representing the tasks, in the same
-     * sequential order as produced by the iterator for the given task
-     * list, each of which has completed.
+     *         sequential order as produced by the iterator for the
+     *         given task list, each of which has completed.
      * @throws InterruptedException if interrupted while waiting, in
-     * which case unfinished tasks are cancelled.
+     *         which case unfinished tasks are cancelled.
      * @throws NullPointerException if tasks or any of its elements are <tt>null</tt>
-     * @throws RejectedExecutionException if any task cannot be scheduled
-     * for execution
+     * @throws RejectedExecutionException if any task cannot be
+     *         scheduled for execution
      */
 
     <T> List<Future<T>> invokeAll(Collection<Callable<T>> tasks)
         throws InterruptedException;
 
     /**
-     * Executes the given tasks, returning their results
+     * Executes the given tasks, returning a list of Futures holding
+     * their status and results
      * when all complete or the timeout expires, whichever happens first.
+     * {@link Future#isDone} is <tt>true</tt> for each
+     * element of the returned list.
      * Upon return, tasks that have not completed are cancelled.
      * Note that a <em>completed</em> task could have
      * terminated either normally or by throwing an exception.
      * The results of this method are undefined if the given
      * collection is modified while this operation is in progress.
+     *
      * @param tasks the collection of tasks
      * @param timeout the maximum time to wait
      * @param unit the time unit of the timeout argument
-     * @return A list of Futures representing the tasks, in the same
-     * sequential order as produced by the iterator for the given
-     * task list. If the operation did not time out, each task will
-     * have completed. If it did time out, some of thiese tasks will
-     * not have completed.
+     * @return a list of Futures representing the tasks, in the same
+     *         sequential order as produced by the iterator for the
+     *         given task list. If the operation did not time out,
+     *         each task will have completed. If it did time out, some
+     *         of these tasks will not have completed.
      * @throws InterruptedException if interrupted while waiting, in
-     * which case unfinished tasks are cancelled.
+     *         which case unfinished tasks are cancelled
      * @throws NullPointerException if tasks, any of its elements, or
-     * unit are <tt>null</tt>
+     *         unit are <tt>null</tt>
      * @throws RejectedExecutionException if any task cannot be scheduled
-     * for execution
+     *         for execution
      */
-    <T> List<Future<T>> invokeAll(Collection<Callable<T>> tasks, 
-                                  long timeout, TimeUnit unit) 
+    <T> List<Future<T>> invokeAll(Collection<Callable<T>> tasks,
+                                  long timeout, TimeUnit unit)
         throws InterruptedException;
 
     /**
@@ -245,15 +299,16 @@
      * tasks that have not completed are cancelled.
      * The results of this method are undefined if the given
      * collection is modified while this operation is in progress.
+     *
      * @param tasks the collection of tasks
-     * @return The result returned by one of the tasks.
+     * @return the result returned by one of the tasks
      * @throws InterruptedException if interrupted while waiting
      * @throws NullPointerException if tasks or any of its elements
-     * are <tt>null</tt>
-     * @throws IllegalArgumentException if tasks empty
+     *         are <tt>null</tt>
+     * @throws IllegalArgumentException if tasks is empty
      * @throws ExecutionException if no task successfully completes
      * @throws RejectedExecutionException if tasks cannot be scheduled
-     * for execution
+     *         for execution
      */
     <T> T invokeAny(Collection<Callable<T>> tasks)
         throws InterruptedException, ExecutionException;
@@ -266,21 +321,21 @@
      * completed are cancelled.
      * The results of this method are undefined if the given
      * collection is modified while this operation is in progress.
+     *
      * @param tasks the collection of tasks
      * @param timeout the maximum time to wait
      * @param unit the time unit of the timeout argument
-     * @return The result returned by one of the tasks.
+     * @return the result returned by one of the tasks.
      * @throws InterruptedException if interrupted while waiting
      * @throws NullPointerException if tasks, any of its elements, or
-     * unit are <tt>null</tt>
+     *         unit are <tt>null</tt>
      * @throws TimeoutException if the given timeout elapses before
-     * any task successfully completes
+     *         any task successfully completes
      * @throws ExecutionException if no task successfully completes
      * @throws RejectedExecutionException if tasks cannot be scheduled
-     * for execution
+     *         for execution
      */
-    <T> T invokeAny(Collection<Callable<T>> tasks, 
-                    long timeout, TimeUnit unit) 
+    <T> T invokeAny(Collection<Callable<T>> tasks,
+                    long timeout, TimeUnit unit)
         throws InterruptedException, ExecutionException, TimeoutException;
-
 }
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/Executors.java b/libcore/concurrent/src/main/java/java/util/concurrent/Executors.java
index 23f1b75..a57abe5 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/Executors.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/Executors.java
@@ -11,6 +11,7 @@
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.security.PrivilegedExceptionAction;
+import java.security.PrivilegedActionException;
 import java.security.AccessControlException;
 
 /**
@@ -18,18 +19,18 @@
  * ExecutorService}, {@link ScheduledExecutorService}, {@link
  * ThreadFactory}, and {@link Callable} classes defined in this
  * package. This class supports the following kinds of methods:
- * 
+ *
  * <ul>
- *   <li> Methods that create and return an {@link ExecutorService} 
- *        set up with commonly useful configuration settings. 
- *   <li> Methods that create and return a {@link ScheduledExecutorService} 
- *        set up with commonly useful configuration settings. 
+ *   <li> Methods that create and return an {@link ExecutorService}
+ *        set up with commonly useful configuration settings.
+ *   <li> Methods that create and return a {@link ScheduledExecutorService}
+ *        set up with commonly useful configuration settings.
  *   <li> Methods that create and return a "wrapped" ExecutorService, that
  *        disables reconfiguration by making implementation-specific methods
  *        inaccessible.
  *   <li> Methods that create and return a {@link ThreadFactory}
  *        that sets newly created threads to a known state.
- *   <li> Methods that create and return a {@link Callable} 
+ *   <li> Methods that create and return a {@link Callable}
  *        out of other closure-like forms, so they can be used
  *        in execution methods requiring <tt>Callable</tt>.
  * </ul>
@@ -40,14 +41,19 @@
 public class Executors {
 
     /**
-     * Creates a thread pool that reuses a fixed set of threads
-     * operating off a shared unbounded queue. If any thread
-     * terminates due to a failure during execution prior to shutdown,
-     * a new one will take its place if needed to execute subsequent
-     * tasks.
+     * Creates a thread pool that reuses a fixed number of threads
+     * operating off a shared unbounded queue.  At any point, at most
+     * <tt>nThreads</tt> threads will be active processing tasks.
+     * If additional tasks are submitted when all threads are active,
+     * they will wait in the queue until a thread is available.
+     * If any thread terminates due to a failure during execution
+     * prior to shutdown, a new one will take its place if needed to
+     * execute subsequent tasks.  The threads in the pool will exist
+     * until it is explicitly {@link ExecutorService#shutdown shutdown}.
      *
      * @param nThreads the number of threads in the pool
      * @return the newly created thread pool
+     * @throws IllegalArgumentException if <tt>nThreads &lt;= 0</tt>
      */
     public static ExecutorService newFixedThreadPool(int nThreads) {
         return new ThreadPoolExecutor(nThreads, nThreads,
@@ -56,13 +62,23 @@
     }
 
     /**
-     * Creates a thread pool that reuses a fixed set of threads
+     * Creates a thread pool that reuses a fixed number of threads
      * operating off a shared unbounded queue, using the provided
-     * ThreadFactory to create new threads when needed.
+     * ThreadFactory to create new threads when needed.  At any point,
+     * at most <tt>nThreads</tt> threads will be active processing
+     * tasks.  If additional tasks are submitted when all threads are
+     * active, they will wait in the queue until a thread is
+     * available.  If any thread terminates due to a failure during
+     * execution prior to shutdown, a new one will take its place if
+     * needed to execute subsequent tasks.  The threads in the pool will
+     * exist until it is explicitly {@link ExecutorService#shutdown
+     * shutdown}.
      *
      * @param nThreads the number of threads in the pool
      * @param threadFactory the factory to use when creating new threads
      * @return the newly created thread pool
+     * @throws NullPointerException if threadFactory is null
+     * @throws IllegalArgumentException if <tt>nThreads &lt;= 0</tt>
      */
     public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
         return new ThreadPoolExecutor(nThreads, nThreads,
@@ -85,7 +101,7 @@
      * @return the newly created single-threaded Executor
      */
     public static ExecutorService newSingleThreadExecutor() {
-        return new DelegatedExecutorService
+        return new FinalizableDelegatedExecutorService
             (new ThreadPoolExecutor(1, 1,
                                     0L, TimeUnit.MILLISECONDS,
                                     new LinkedBlockingQueue<Runnable>()));
@@ -95,17 +111,18 @@
      * Creates an Executor that uses a single worker thread operating
      * off an unbounded queue, and uses the provided ThreadFactory to
      * create a new thread when needed. Unlike the otherwise
-     * equivalent <tt>newFixedThreadPool(1, threadFactory)</tt> the returned executor
-     * is guaranteed not to be reconfigurable to use additional
-     * threads.
-     * 
+     * equivalent <tt>newFixedThreadPool(1, threadFactory)</tt> the
+     * returned executor is guaranteed not to be reconfigurable to use
+     * additional threads.
+     *
      * @param threadFactory the factory to use when creating new
      * threads
      *
      * @return the newly created single-threaded Executor
+     * @throws NullPointerException if threadFactory is null
      */
     public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
-        return new DelegatedExecutorService
+        return new FinalizableDelegatedExecutorService
             (new ThreadPoolExecutor(1, 1,
                                     0L, TimeUnit.MILLISECONDS,
                                     new LinkedBlockingQueue<Runnable>(),
@@ -141,6 +158,7 @@
      * ThreadFactory to create new threads when needed.
      * @param threadFactory the factory to use when creating new threads
      * @return the newly created thread pool
+     * @throws NullPointerException if threadFactory is null
      */
     public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
         return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
@@ -148,7 +166,7 @@
                                       new SynchronousQueue<Runnable>(),
                                       threadFactory);
     }
-   
+
     /**
      * Creates a single-threaded executor that can schedule commands
      * to run after a given delay, or to execute periodically.
@@ -181,31 +199,35 @@
      * @param threadFactory the factory to use when creating new
      * threads
      * @return a newly created scheduled executor
+     * @throws NullPointerException if threadFactory is null
      */
     public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) {
         return new DelegatedScheduledExecutorService
             (new ScheduledThreadPoolExecutor(1, threadFactory));
     }
-    
+
     /**
-     * Creates a thread pool that can schedule commands to run after a 
+     * Creates a thread pool that can schedule commands to run after a
      * given delay, or to execute periodically.
      * @param corePoolSize the number of threads to keep in the pool,
      * even if they are idle.
      * @return a newly created scheduled thread pool
+     * @throws IllegalArgumentException if <tt>corePoolSize &lt; 0</tt>
      */
     public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
         return new ScheduledThreadPoolExecutor(corePoolSize);
     }
 
     /**
-     * Creates a thread pool that can schedule commands to run after a 
+     * Creates a thread pool that can schedule commands to run after a
      * given delay, or to execute periodically.
      * @param corePoolSize the number of threads to keep in the pool,
      * even if they are idle.
      * @param threadFactory the factory to use when the executor
-     * creates a new thread. 
+     * creates a new thread.
      * @return a newly created scheduled thread pool
+     * @throws IllegalArgumentException if <tt>corePoolSize &lt; 0</tt>
+     * @throws NullPointerException if threadFactory is null
      */
     public static ScheduledExecutorService newScheduledThreadPool(
             int corePoolSize, ThreadFactory threadFactory) {
@@ -244,7 +266,7 @@
             throw new NullPointerException();
         return new DelegatedScheduledExecutorService(executor);
     }
-        
+
     /**
      * Returns a default thread factory used to create new threads.
      * This factory creates all new threads used by an Executor in the
@@ -252,8 +274,9 @@
      * java.lang.SecurityManager}, it uses the group of {@link
      * System#getSecurityManager}, else the group of the thread
      * invoking this <tt>defaultThreadFactory</tt> method. Each new
-     * thread is created as a non-daemon thread with priority
-     * <tt>Thread.NORM_PRIORITY</tt>. New threads have names
+     * thread is created as a non-daemon thread with priority set to
+     * the smaller of <tt>Thread.NORM_PRIORITY</tt> and the maximum
+     * priority permitted in the thread group.  New threads have names
      * accessible via {@link Thread#getName} of
      * <em>pool-N-thread-M</em>, where <em>N</em> is the sequence
      * number of this factory, and <em>M</em> is the sequence number
@@ -307,8 +330,8 @@
      * <tt>Callable</tt> to an otherwise resultless action.
      * @param task the task to run
      * @param result the result to return
-     * @throws NullPointerException if task null
      * @return a callable object
+     * @throws NullPointerException if task null
      */
     public static <T> Callable<T> callable(Runnable task, T result) {
         if (task == null)
@@ -336,10 +359,11 @@
      * @return a callable object
      * @throws NullPointerException if action null
      */
-    public static Callable<Object> callable(PrivilegedAction action) {
+    public static Callable<Object> callable(final PrivilegedAction action) {
         if (action == null)
             throw new NullPointerException();
-        return new PrivilegedActionAdapter(action);
+        return new Callable<Object>() {
+            public Object call() { return action.run(); }};
     }
 
     /**
@@ -350,10 +374,11 @@
      * @return a callable object
      * @throws NullPointerException if action null
      */
-    public static Callable<Object> callable(PrivilegedExceptionAction action) {
+    public static Callable<Object> callable(final PrivilegedExceptionAction action) {
         if (action == null)
             throw new NullPointerException();
-        return new PrivilegedExceptionActionAdapter(action);
+        return new Callable<Object>() {
+            public Object call() throws Exception { return action.run(); }};
     }
 
     /**
@@ -373,9 +398,9 @@
     public static <T> Callable<T> privilegedCallable(Callable<T> callable) {
         if (callable == null)
             throw new NullPointerException();
-        return new PrivilegedCallable(callable);
+        return new PrivilegedCallable<T>(callable);
     }
-    
+
     /**
      * Returns a {@link Callable} object that will, when
      * called, execute the given <tt>callable</tt> under the current
@@ -397,7 +422,7 @@
     public static <T> Callable<T> privilegedCallableUsingCurrentClassLoader(Callable<T> callable) {
         if (callable == null)
             throw new NullPointerException();
-        return new PrivilegedCallableUsingCurrentClassLoader(callable);
+        return new PrivilegedCallableUsingCurrentClassLoader<T>(callable);
     }
 
     // Non-public classes supporting the public methods
@@ -408,71 +433,39 @@
     static final class RunnableAdapter<T> implements Callable<T> {
         final Runnable task;
         final T result;
-        RunnableAdapter(Runnable  task, T result) {
-            this.task = task; 
+        RunnableAdapter(Runnable task, T result) {
+            this.task = task;
             this.result = result;
         }
-        public T call() { 
-            task.run(); 
-            return result; 
+        public T call() {
+            task.run();
+            return result;
         }
     }
 
     /**
-     * A callable that runs given privileged action and returns its result
-     */
-    static final class PrivilegedActionAdapter implements Callable<Object> {
-        PrivilegedActionAdapter(PrivilegedAction action) {
-            this.action = action;
-        }
-        public Object call () {
-            return action.run();
-        }
-        private final PrivilegedAction action;
-    }
-
-    /**
-     * A callable that runs given privileged exception action and returns its result
-     */
-    static final class PrivilegedExceptionActionAdapter implements Callable<Object> {
-        PrivilegedExceptionActionAdapter(PrivilegedExceptionAction action) {
-            this.action = action;
-        }
-        public Object call () throws Exception {
-            return action.run();
-        }
-        private final PrivilegedExceptionAction action;
-    }
-
-
-    /**
      * A callable that runs under established access control settings
      */
     static final class PrivilegedCallable<T> implements Callable<T> {
-        private final AccessControlContext acc;
         private final Callable<T> task;
-        private T result;
-        private Exception exception;
+        private final AccessControlContext acc;
+
         PrivilegedCallable(Callable<T> task) {
             this.task = task;
             this.acc = AccessController.getContext();
         }
 
         public T call() throws Exception {
-            AccessController.doPrivileged(new PrivilegedAction() {
-                    public Object run() {
-                        try {
-                            result = task.call();
-                        } catch(Exception ex) {
-                            exception = ex;
+            try {
+                return AccessController.doPrivileged(
+                    new PrivilegedExceptionAction<T>() {
+                        public T run() throws Exception {
+                            return task.call();
                         }
-                        return null;
-                    }
-                }, acc);
-            if (exception != null)
-                throw exception;
-            else 
-                return result;
+                    }, acc);
+            } catch (PrivilegedActionException e) {
+                throw e.getException();
+            }
         }
     }
 
@@ -481,44 +474,50 @@
      * current ClassLoader
      */
     static final class PrivilegedCallableUsingCurrentClassLoader<T> implements Callable<T> {
-        private final ClassLoader ccl;
-        private final AccessControlContext acc;
         private final Callable<T> task;
-        private T result;
-        private Exception exception;
+        private final AccessControlContext acc;
+        private final ClassLoader ccl;
+
         PrivilegedCallableUsingCurrentClassLoader(Callable<T> task) {
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                // Calls to getContextClassLoader from this class
+                // never trigger a security check, but we check
+                // whether our callers have this permission anyways.
+                sm.checkPermission(new RuntimePermission("getContextClassLoader"));
+
+                // Whether setContextClassLoader turns out to be necessary
+                // or not, we fail fast if permission is not available.
+                sm.checkPermission(new RuntimePermission("setContextClassLoader"));
+            }
             this.task = task;
-            this.ccl = Thread.currentThread().getContextClassLoader();
             this.acc = AccessController.getContext();
-            acc.checkPermission(new RuntimePermission("getContextClassLoader"));
-            acc.checkPermission(new RuntimePermission("setContextClassLoader"));
+            this.ccl = Thread.currentThread().getContextClassLoader();
         }
 
         public T call() throws Exception {
-            AccessController.doPrivileged(new PrivilegedAction() {
-                    public Object run() {
-                        ClassLoader savedcl = null;
-                        Thread t = Thread.currentThread();
-                        try {
-                            ClassLoader cl = t.getContextClassLoader();
-                            if (ccl != cl) {
-                                t.setContextClassLoader(ccl);
-                                savedcl = cl;
+            try {
+                return AccessController.doPrivileged(
+                    new PrivilegedExceptionAction<T>() {
+                        public T run() throws Exception {
+                            ClassLoader savedcl = null;
+                            Thread t = Thread.currentThread();
+                            try {
+                                ClassLoader cl = t.getContextClassLoader();
+                                if (ccl != cl) {
+                                    t.setContextClassLoader(ccl);
+                                    savedcl = cl;
+                                }
+                                return task.call();
+                            } finally {
+                                if (savedcl != null)
+                                    t.setContextClassLoader(savedcl);
                             }
-                            result = task.call();
-                        } catch(Exception ex) {
-                            exception = ex;
-                        } finally {
-                            if (savedcl != null)
-                                t.setContextClassLoader(savedcl);
                         }
-                        return null;
-                    }
-                }, acc);
-            if (exception != null)
-                throw exception;
-            else 
-                return result;
+                    }, acc);
+            } catch (PrivilegedActionException e) {
+                throw e.getException();
+            }
         }
     }
 
@@ -526,22 +525,22 @@
      * The default thread factory
      */
     static class DefaultThreadFactory implements ThreadFactory {
-        static final AtomicInteger poolNumber = new AtomicInteger(1);
-        final ThreadGroup group;
-        final AtomicInteger threadNumber = new AtomicInteger(1);
-        final String namePrefix;
+        private static final AtomicInteger poolNumber = new AtomicInteger(1);
+        private final ThreadGroup group;
+        private final AtomicInteger threadNumber = new AtomicInteger(1);
+        private final String namePrefix;
 
         DefaultThreadFactory() {
             SecurityManager s = System.getSecurityManager();
             group = (s != null)? s.getThreadGroup() :
                                  Thread.currentThread().getThreadGroup();
-            namePrefix = "pool-" + 
-                          poolNumber.getAndIncrement() + 
+            namePrefix = "pool-" +
+                          poolNumber.getAndIncrement() +
                          "-thread-";
         }
 
         public Thread newThread(Runnable r) {
-            Thread t = new Thread(group, r, 
+            Thread t = new Thread(group, r,
                                   namePrefix + threadNumber.getAndIncrement(),
                                   0);
             if (t.isDaemon())
@@ -553,38 +552,46 @@
     }
 
     /**
-     *  Thread factory capturing access control and class loader
+     * Thread factory capturing access control context and class loader
      */
     static class PrivilegedThreadFactory extends DefaultThreadFactory {
-        private final ClassLoader ccl;
         private final AccessControlContext acc;
+        private final ClassLoader ccl;
 
         PrivilegedThreadFactory() {
             super();
-            this.ccl = Thread.currentThread().getContextClassLoader();
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                // Calls to getContextClassLoader from this class
+                // never trigger a security check, but we check
+                // whether our callers have this permission anyways.
+                sm.checkPermission(new RuntimePermission("getContextClassLoader"));
+
+                // Fail fast
+                sm.checkPermission(new RuntimePermission("setContextClassLoader"));
+            }
             this.acc = AccessController.getContext();
-            acc.checkPermission(new RuntimePermission("setContextClassLoader"));
+            this.ccl = Thread.currentThread().getContextClassLoader();
         }
-        
+
         public Thread newThread(final Runnable r) {
             return super.newThread(new Runnable() {
                 public void run() {
-                    AccessController.doPrivileged(new PrivilegedAction() {
-                        public Object run() { 
+                    AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                        public Void run() {
                             Thread.currentThread().setContextClassLoader(ccl);
                             r.run();
-                            return null; 
+                            return null;
                         }
                     }, acc);
                 }
             });
         }
-        
     }
 
-   /**
+    /**
      * A wrapper class that exposes only the ExecutorService methods
-     * of an implementation.
+     * of an ExecutorService implementation.
      */
     static class DelegatedExecutorService extends AbstractExecutorService {
         private final ExecutorService e;
@@ -611,8 +618,8 @@
             throws InterruptedException {
             return e.invokeAll(tasks);
         }
-        public <T> List<Future<T>> invokeAll(Collection<Callable<T>> tasks, 
-                                             long timeout, TimeUnit unit) 
+        public <T> List<Future<T>> invokeAll(Collection<Callable<T>> tasks,
+                                             long timeout, TimeUnit unit)
             throws InterruptedException {
             return e.invokeAll(tasks, timeout, unit);
         }
@@ -620,19 +627,29 @@
             throws InterruptedException, ExecutionException {
             return e.invokeAny(tasks);
         }
-        public <T> T invokeAny(Collection<Callable<T>> tasks, 
-                               long timeout, TimeUnit unit) 
+        public <T> T invokeAny(Collection<Callable<T>> tasks,
+                               long timeout, TimeUnit unit)
             throws InterruptedException, ExecutionException, TimeoutException {
             return e.invokeAny(tasks, timeout, unit);
         }
     }
-    
+
+    static class FinalizableDelegatedExecutorService
+        extends DelegatedExecutorService {
+        FinalizableDelegatedExecutorService(ExecutorService executor) {
+            super(executor);
+        }
+        protected void finalize()  {
+            super.shutdown();
+        }
+    }
+
     /**
-     * A wrapper class that exposes only the ExecutorService and 
-     * ScheduleExecutor methods of a ScheduledExecutorService implementation.
+     * A wrapper class that exposes only the ScheduledExecutorService
+     * methods of a ScheduledExecutorService implementation.
      */
     static class DelegatedScheduledExecutorService
-            extends DelegatedExecutorService 
+            extends DelegatedExecutorService
             implements ScheduledExecutorService {
         private final ScheduledExecutorService e;
         DelegatedScheduledExecutorService(ScheduledExecutorService executor) {
@@ -653,7 +670,7 @@
         }
     }
 
-        
+
     /** Cannot instantiate. */
     private Executors() {}
 }
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/Future.java b/libcore/concurrent/src/main/java/java/util/concurrent/Future.java
index 38fa8c6..0459ee4 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/Future.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/Future.java
@@ -29,10 +29,13 @@
  * class App {
  *   ExecutorService executor = ...
  *   ArchiveSearcher searcher = ...
- *   void showSearch(final String target) throws InterruptedException {
- *     Future&lt;String&gt; future = executor.submit(new Callable&lt;String&gt;() {
- *         public String call() { return searcher.search(target); }
- *     });
+ *   void showSearch(final String target)
+ *       throws InterruptedException {
+ *     Future&lt;String&gt; future
+ *       = executor.submit(new Callable&lt;String&gt;() {
+ *         public String call() {
+ *             return searcher.search(target);
+ *         }});
  *     displayOtherThings(); // do other things while searching
  *     try {
  *       displayText(future.get()); // use future
@@ -41,8 +44,8 @@
  * }
  * </pre>
  *
- * The {@link FutureTask} class is an implementation of <tt>Future</tt> that 
- * implements <tt>Runnable</tt>, and so may be executed by an <tt>Executor</tt>. 
+ * The {@link FutureTask} class is an implementation of <tt>Future</tt> that
+ * implements <tt>Runnable</tt>, and so may be executed by an <tt>Executor</tt>.
  * For example, the above construction with <tt>submit</tt> could be replaced by:
  * <pre>
  *     FutureTask&lt;String&gt; future =
@@ -52,6 +55,11 @@
  *       }});
  *     executor.execute(future);
  * </pre>
+ *
+ * <p>Memory consistency effects: Actions taken by the asynchronous computation
+ * <a href="package-summary.html#MemoryVisibility"> <i>happen-before</i></a>
+ * actions following the corresponding {@code Future.get()} in another thread.
+ *
  * @see FutureTask
  * @see Executor
  * @since 1.5
@@ -62,7 +70,7 @@
 
     /**
      * Attempts to cancel execution of this task.  This attempt will
-     * fail if the task has already completed, already been cancelled,
+     * fail if the task has already completed, has already been cancelled,
      * or could not be cancelled for some other reason. If successful,
      * and this task has not started when <tt>cancel</tt> is called,
      * this task should never run.  If the task has already started,
@@ -70,6 +78,10 @@
      * whether the thread executing this task should be interrupted in
      * an attempt to stop the task.
      *
+     * <p>After this method returns, subsequent calls to {@link #isDone} will
+     * always return <tt>true</tt>.  Subsequent calls to {@link #isCancelled}
+     * will always return <tt>true</tt> if this method returned <tt>true</tt>.
+     *
      * @param mayInterruptIfRunning <tt>true</tt> if the thread executing this
      * task should be interrupted; otherwise, in-progress tasks are allowed
      * to complete
@@ -83,18 +95,18 @@
      * Returns <tt>true</tt> if this task was cancelled before it completed
      * normally.
      *
-     * @return <tt>true</tt> if task was cancelled before it completed
+     * @return <tt>true</tt> if this task was cancelled before it completed
      */
     boolean isCancelled();
 
     /**
-     * Returns <tt>true</tt> if this task completed.  
+     * Returns <tt>true</tt> if this task completed.
      *
      * Completion may be due to normal termination, an exception, or
      * cancellation -- in all of these cases, this method will return
      * <tt>true</tt>.
-     * 
-     * @return <tt>true</tt> if this task completed.
+     *
+     * @return <tt>true</tt> if this task completed
      */
     boolean isDone();
 
@@ -128,6 +140,3 @@
     V get(long timeout, TimeUnit unit)
         throws InterruptedException, ExecutionException, TimeoutException;
 }
-
-
-
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/FutureTask.java b/libcore/concurrent/src/main/java/java/util/concurrent/FutureTask.java
index 87db1cd..8aa9dd1 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/FutureTask.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/FutureTask.java
@@ -35,7 +35,7 @@
     private final Sync sync;
 
     /**
-     * Creates a <tt>FutureTask</tt> that will upon running, execute the
+     * Creates a <tt>FutureTask</tt> that will, upon running, execute the
      * given <tt>Callable</tt>.
      *
      * @param  callable the callable task
@@ -48,11 +48,11 @@
     }
 
     /**
-     * Creates a <tt>FutureTask</tt> that will upon running, execute the
+     * Creates a <tt>FutureTask</tt> that will, upon running, execute the
      * given <tt>Runnable</tt>, and arrange that <tt>get</tt> will return the
      * given result on successful completion.
      *
-     * @param  runnable the runnable task
+     * @param runnable the runnable task
      * @param result the result to return on successful completion. If
      * you don't need a particular result, consider using
      * constructions of the form:
@@ -66,7 +66,7 @@
     public boolean isCancelled() {
         return sync.innerIsCancelled();
     }
-    
+
     public boolean isDone() {
         return sync.innerIsDone();
     }
@@ -74,11 +74,17 @@
     public boolean cancel(boolean mayInterruptIfRunning) {
         return sync.innerCancel(mayInterruptIfRunning);
     }
-    
+
+    /**
+     * @throws CancellationException {@inheritDoc}
+     */
     public V get() throws InterruptedException, ExecutionException {
         return sync.innerGet();
     }
 
+    /**
+     * @throws CancellationException {@inheritDoc}
+     */
     public V get(long timeout, TimeUnit unit)
         throws InterruptedException, ExecutionException, TimeoutException {
         return sync.innerGet(unit.toNanos(timeout));
@@ -98,8 +104,10 @@
     /**
      * Sets the result of this Future to the given value unless
      * this future has already been set or has been cancelled.
+     * This method is invoked internally by the <tt>run</tt> method
+     * upon successful completion of the computation.
      * @param v the value
-     */ 
+     */
     protected void set(V v) {
         sync.innerSet(v);
     }
@@ -108,15 +116,22 @@
      * Causes this future to report an <tt>ExecutionException</tt>
      * with the given throwable as its cause, unless this Future has
      * already been set or has been cancelled.
-     * @param t the cause of failure.
-     */ 
+     * This method is invoked internally by the <tt>run</tt> method
+     * upon failure of the computation.
+     * @param t the cause of failure
+     */
     protected void setException(Throwable t) {
         sync.innerSetException(t);
     }
-    
+
+    // The following (duplicated) doc comment can be removed once
+    //
+    // 6270645: Javadoc comments should be inherited from most derived
+    //          superinterface or superclass
+    // is fixed.
     /**
-     * Sets this Future to the result of computation unless
-     * it has been cancelled.
+     * Sets this Future to the result of its computation
+     * unless it has been cancelled.
      */
     public void run() {
         sync.innerRun();
@@ -143,6 +158,10 @@
      * Uses AQS sync state to represent run status
      */
     private final class Sync extends AbstractQueuedSynchronizer {
+        private static final long serialVersionUID = -7828117401763700385L;
+
+        /** State value representing that task is ready to run */
+        private static final int READY     = 0;
         /** State value representing that task is running */
         private static final int RUNNING   = 1;
         /** State value representing that task ran */
@@ -157,10 +176,10 @@
         /** The exception to throw from get() */
         private Throwable exception;
 
-        /** 
+        /**
          * The thread running task. When nulled after set/cancel, this
          * indicates that the results are accessible.  Must be
-         * volatile, to serve as write barrier on completion.
+         * volatile, to ensure visibility upon completion.
          */
         private volatile Thread runner;
 
@@ -176,7 +195,7 @@
          * Implements AQS base acquire to succeed if ran or cancelled
          */
         protected int tryAcquireShared(int ignore) {
-            return innerIsDone()? 1 : -1;
+            return innerIsDone() ? 1 : -1;
         }
 
         /**
@@ -185,13 +204,13 @@
          */
         protected boolean tryReleaseShared(int ignore) {
             runner = null;
-            return true; 
+            return true;
         }
 
         boolean innerIsCancelled() {
             return getState() == CANCELLED;
         }
-        
+
         boolean innerIsDone() {
             return ranOrCancelled(getState()) && runner == null;
         }
@@ -207,7 +226,7 @@
 
         V innerGet(long nanosTimeout) throws InterruptedException, ExecutionException, TimeoutException {
             if (!tryAcquireSharedNanos(0, nanosTimeout))
-                throw new TimeoutException();                
+                throw new TimeoutException();
             if (getState() == CANCELLED)
                 throw new CancellationException();
             if (exception != null)
@@ -216,28 +235,55 @@
         }
 
         void innerSet(V v) {
-            int s = getState();
-            if (ranOrCancelled(s) || !compareAndSetState(s, RAN))
-                return;
-            result = v;
-            releaseShared(0);
-            done();
+            for (;;) {
+                int s = getState();
+                if (s == RAN)
+                    return;
+                if (s == CANCELLED) {
+                    // aggressively release to set runner to null,
+                    // in case we are racing with a cancel request
+                    // that will try to interrupt runner
+                    releaseShared(0);
+                    return;
+                }
+                if (compareAndSetState(s, RAN)) {
+                    result = v;
+                    releaseShared(0);
+                    done();
+                    return;
+                }
+            }
         }
 
         void innerSetException(Throwable t) {
-            int s = getState();
-            if (ranOrCancelled(s) || !compareAndSetState(s, RAN)) 
-                return;
-            exception = t;
-            result = null;
-            releaseShared(0);
-            done();
+            for (;;) {
+                int s = getState();
+                if (s == RAN)
+                    return;
+                if (s == CANCELLED) {
+                    // aggressively release to set runner to null,
+                    // in case we are racing with a cancel request
+                    // that will try to interrupt runner
+                    releaseShared(0);
+                    return;
+                }
+                if (compareAndSetState(s, RAN)) {
+                    exception = t;
+                    releaseShared(0);
+                    done();
+                    return;
+                }
+            }
         }
 
         boolean innerCancel(boolean mayInterruptIfRunning) {
-            int s = getState();
-            if (ranOrCancelled(s) || !compareAndSetState(s, CANCELLED)) 
-                return false;
+            for (;;) {
+                int s = getState();
+                if (ranOrCancelled(s))
+                    return false;
+                if (compareAndSetState(s, CANCELLED))
+                    break;
+            }
             if (mayInterruptIfRunning) {
                 Thread r = runner;
                 if (r != null)
@@ -249,28 +295,37 @@
         }
 
         void innerRun() {
-            if (!compareAndSetState(0, RUNNING)) 
+            if (!compareAndSetState(READY, RUNNING))
                 return;
-            try {
-                runner = Thread.currentThread();
-                innerSet(callable.call());
-            } catch(Throwable ex) {
-                innerSetException(ex);
-            } 
+
+            runner = Thread.currentThread();
+            if (getState() == RUNNING) { // recheck after setting thread
+                V result;
+                try {
+                    result = callable.call();
+                } catch (Throwable ex) {
+                    setException(ex);
+                    return;
+                }
+                set(result);
+            } else {
+                releaseShared(0); // cancel
+            }
         }
 
         boolean innerRunAndReset() {
-            if (!compareAndSetState(0, RUNNING)) 
+            if (!compareAndSetState(READY, RUNNING))
                 return false;
             try {
                 runner = Thread.currentThread();
-                callable.call(); // don't set result
+                if (getState() == RUNNING)
+                    callable.call(); // don't set result
                 runner = null;
-                return compareAndSetState(RUNNING, 0);
-            } catch(Throwable ex) {
-                innerSetException(ex);
+                return compareAndSetState(RUNNING, READY);
+            } catch (Throwable ex) {
+                setException(ex);
                 return false;
-            } 
+            }
         }
     }
 }
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/Java6Arrays.java b/libcore/concurrent/src/main/java/java/util/concurrent/Java6Arrays.java
new file mode 100644
index 0000000..6b728be
--- /dev/null
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/Java6Arrays.java
@@ -0,0 +1,77 @@
+/*
+ *  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 java.util.concurrent;
+
+import java.lang.reflect.Array;
+
+/**
+ * Arrays.copyOf and Arrays.copyOfRange backported from Java 6.
+ */
+class Java6Arrays {
+
+    static <T> T[] copyOf(T[] original, int newLength) {
+        if (null == original) {
+            throw new NullPointerException();
+        }
+        if (0 <= newLength) {
+            return copyOfRange(original, 0, newLength);
+        }
+        throw new NegativeArraySizeException();
+    }
+
+    static <T, U> T[] copyOf(U[] original, int newLength,
+            Class<? extends T[]> newType) {
+        if (0 <= newLength) {
+            return copyOfRange(original, 0, newLength, newType);
+        }
+        throw new NegativeArraySizeException();
+    }
+
+    @SuppressWarnings("unchecked")
+    static <T> T[] copyOfRange(T[] original, int start, int end) {
+        if (original.length >= start && 0 <= start) {
+            if (start <= end) {
+                int length = end - start;
+                int copyLength = Math.min(length, original.length - start);
+                T[] copy = (T[]) Array.newInstance(original.getClass().getComponentType(), length);
+                System.arraycopy(original, start, copy, 0, copyLength);
+                return copy;
+            }
+            throw new IllegalArgumentException();
+        }
+        throw new ArrayIndexOutOfBoundsException();
+    }
+
+    @SuppressWarnings("unchecked")
+    static <T, U> T[] copyOfRange(U[] original, int start, int end,
+            Class<? extends T[]> newType) {
+        if (start <= end) {
+            if (original.length >= start && 0 <= start) {
+                int length = end - start;
+                int copyLength = Math.min(length, original.length - start);
+                T[] copy = (T[]) Array.newInstance(newType.getComponentType(),
+                        length);
+                System.arraycopy(original, start, copy, 0, copyLength);
+                return copy;
+            }
+            throw new ArrayIndexOutOfBoundsException();
+        }
+        throw new IllegalArgumentException();
+    }
+
+}
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/LinkedBlockingQueue.java b/libcore/concurrent/src/main/java/java/util/concurrent/LinkedBlockingQueue.java
index 662f63e..e06f7bd 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/LinkedBlockingQueue.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/LinkedBlockingQueue.java
@@ -32,14 +32,15 @@
  * dynamically created upon each insertion unless this would bring the
  * queue above capacity.
  *
- * <p>This class implements all of the <em>optional</em> methods
- * of the {@link Collection} and {@link Iterator} interfaces.
+ * <p>This class and its iterator implement all of the
+ * <em>optional</em> methods of the {@link Collection} and {@link
+ * Iterator} interfaces.
  *
  * @since 1.5
  * @author Doug Lea
  * @param <E> the type of elements held in this collection
  *
- **/
+ */
 public class LinkedBlockingQueue<E> extends AbstractQueue<E>
         implements BlockingQueue<E>, java.io.Serializable {
     private static final long serialVersionUID = -6903933977591709194L;
@@ -56,7 +57,7 @@
      * items have been entered since the signal. And symmetrically for
      * takes signalling puts. Operations such as remove(Object) and
      * iterators acquire both locks.
-    */
+     */
 
     /**
      * Linked list node class
@@ -93,7 +94,7 @@
     private final Condition notFull = putLock.newCondition();
 
     /**
-     * Signal a waiting take. Called only from put/offer (which do not
+     * Signals a waiting take. Called only from put/offer (which do not
      * otherwise ordinarily lock takeLock.)
      */
     private void signalNotEmpty() {
@@ -107,7 +108,7 @@
     }
 
     /**
-     * Signal a waiting put. Called only from take/poll.
+     * Signals a waiting put. Called only from take/poll.
      */
     private void signalNotFull() {
         final ReentrantLock putLock = this.putLock;
@@ -120,7 +121,7 @@
     }
 
     /**
-     * Create a node and link it at end of queue
+     * Creates a node and links it at end of queue.
      * @param x the item
      */
     private void insert(E x) {
@@ -128,11 +129,13 @@
     }
 
     /**
-     * Remove a node from head of queue,
+     * Removes a node from head of queue,
      * @return the node
      */
     private E extract() {
-        Node<E> first = head.next;
+        Node<E> h = head;
+        Node<E> first = h.next;
+        h.next = null; // help GC
         head = first;
         E x = first.item;
         first.item = null;
@@ -167,9 +170,9 @@
     /**
      * Creates a <tt>LinkedBlockingQueue</tt> with the given (fixed) capacity.
      *
-     * @param capacity the capacity of this queue.
+     * @param capacity the capacity of this queue
      * @throws IllegalArgumentException if <tt>capacity</tt> is not greater
-     *         than zero.
+     *         than zero
      */
     public LinkedBlockingQueue(int capacity) {
         if (capacity <= 0) throw new IllegalArgumentException();
@@ -182,14 +185,15 @@
      * {@link Integer#MAX_VALUE}, initially containing the elements of the
      * given collection,
      * added in traversal order of the collection's iterator.
+     *
      * @param c the collection of elements to initially contain
-     * @throws NullPointerException if <tt>c</tt> or any element within it
-     * is <tt>null</tt>
+     * @throws NullPointerException if the specified collection or any
+     *         of its elements are null
      */
     public LinkedBlockingQueue(Collection<? extends E> c) {
         this(Integer.MAX_VALUE);
-        for (Iterator<? extends E> it = c.iterator(); it.hasNext();)
-            add(it.next());
+        for (E e : c)
+            add(e);
     }
 
 
@@ -198,7 +202,7 @@
     /**
      * Returns the number of elements in this queue.
      *
-     * @return  the number of elements in this queue.
+     * @return the number of elements in this queue
      */
     public int size() {
         return count.get();
@@ -207,31 +211,29 @@
     // this doc comment is a modified copy of the inherited doc comment,
     // without the reference to unlimited queues.
     /**
-     * Returns the number of elements that this queue can ideally (in
-     * the absence of memory or resource constraints) accept without
+     * Returns the number of additional elements that this queue can ideally
+     * (in the absence of memory or resource constraints) accept without
      * blocking. This is always equal to the initial capacity of this queue
      * less the current <tt>size</tt> of this queue.
-     * <p>Note that you <em>cannot</em> always tell if
-     * an attempt to <tt>add</tt> an element will succeed by
-     * inspecting <tt>remainingCapacity</tt> because it may be the
-     * case that a waiting consumer is ready to <tt>take</tt> an
-     * element out of an otherwise full queue.
-     * 
-     * @return the remaining capacity
+     *
+     * <p>Note that you <em>cannot</em> always tell if an attempt to insert
+     * an element will succeed by inspecting <tt>remainingCapacity</tt>
+     * because it may be the case that another thread is about to
+     * insert or remove an element.
      */
     public int remainingCapacity() {
         return capacity - count.get();
     }
 
     /**
-     * Adds the specified element to the tail of this queue, waiting if
+     * Inserts the specified element at the tail of this queue, waiting if
      * necessary for space to become available.
-     * @param o the element to add
-     * @throws InterruptedException if interrupted while waiting.
-     * @throws NullPointerException if the specified element is <tt>null</tt>.
+     *
+     * @throws InterruptedException {@inheritDoc}
+     * @throws NullPointerException {@inheritDoc}
      */
-    public void put(E o) throws InterruptedException {
-        if (o == null) throw new NullPointerException();
+    public void put(E e) throws InterruptedException {
+        if (e == null) throw new NullPointerException();
         // Note: convention in all put/take/etc is to preset
         // local var holding count  negative to indicate failure unless set.
         int c = -1;
@@ -255,7 +257,7 @@
                 notFull.signal(); // propagate to a non-interrupted thread
                 throw ie;
             }
-            insert(o);
+            insert(e);
             c = count.getAndIncrement();
             if (c + 1 < capacity)
                 notFull.signal();
@@ -269,20 +271,16 @@
     /**
      * Inserts the specified element at the tail of this queue, waiting if
      * necessary up to the specified wait time for space to become available.
-     * @param o the element to add
-     * @param timeout how long to wait before giving up, in units of
-     * <tt>unit</tt>
-     * @param unit a <tt>TimeUnit</tt> determining how to interpret the
-     * <tt>timeout</tt> parameter
+     *
      * @return <tt>true</tt> if successful, or <tt>false</tt> if
-     * the specified waiting time elapses before space is available.
-     * @throws InterruptedException if interrupted while waiting.
-     * @throws NullPointerException if the specified element is <tt>null</tt>.
+     *         the specified waiting time elapses before space is available.
+     * @throws InterruptedException {@inheritDoc}
+     * @throws NullPointerException {@inheritDoc}
      */
-    public boolean offer(E o, long timeout, TimeUnit unit)
+    public boolean offer(E e, long timeout, TimeUnit unit)
         throws InterruptedException {
 
-        if (o == null) throw new NullPointerException();
+        if (e == null) throw new NullPointerException();
         long nanos = unit.toNanos(timeout);
         int c = -1;
         final ReentrantLock putLock = this.putLock;
@@ -291,7 +289,7 @@
         try {
             for (;;) {
                 if (count.get() < capacity) {
-                    insert(o);
+                    insert(e);
                     c = count.getAndIncrement();
                     if (c + 1 < capacity)
                         notFull.signal();
@@ -315,16 +313,18 @@
     }
 
     /**
-     * Inserts the specified element at the tail of this queue if possible,
-     * returning immediately if this queue is full.
+     * Inserts the specified element at the tail of this queue if it is
+     * possible to do so immediately without exceeding the queue's capacity,
+     * returning <tt>true</tt> upon success and <tt>false</tt> if this queue
+     * is full.
+     * When using a capacity-restricted queue, this method is generally
+     * preferable to method {@link BlockingQueue#add add}, which can fail to
+     * insert an element only by throwing an exception.
      *
-     * @param o the element to add.
-     * @return <tt>true</tt> if it was possible to add the element to
-     *         this queue, else <tt>false</tt>
-     * @throws NullPointerException if the specified element is <tt>null</tt>
+     * @throws NullPointerException if the specified element is null
      */
-    public boolean offer(E o) {
-        if (o == null) throw new NullPointerException();
+    public boolean offer(E e) {
+        if (e == null) throw new NullPointerException();
         final AtomicInteger count = this.count;
         if (count.get() == capacity)
             return false;
@@ -333,7 +333,7 @@
         putLock.lock();
         try {
             if (count.get() < capacity) {
-                insert(o);
+                insert(e);
                 c = count.getAndIncrement();
                 if (c + 1 < capacity)
                     notFull.signal();
@@ -447,6 +447,17 @@
         }
     }
 
+    /**
+     * Removes a single instance of the specified element from this queue,
+     * if it is present.  More formally, removes an element <tt>e</tt> such
+     * that <tt>o.equals(e)</tt>, if this queue contains one or more such
+     * elements.
+     * Returns <tt>true</tt> if this queue contained the specified element
+     * (or equivalently, if this queue changed as a result of the call).
+     *
+     * @param o element to be removed from this queue, if present
+     * @return <tt>true</tt> if this queue changed as a result of the call
+     */
     public boolean remove(Object o) {
         if (o == null) return false;
         boolean removed = false;
@@ -465,6 +476,8 @@
             if (removed) {
                 p.item = null;
                 trail.next = p.next;
+                if (last == p)
+                    last = trail;
                 if (count.getAndDecrement() == capacity)
                     notFull.signalAll();
             }
@@ -474,6 +487,19 @@
         return removed;
     }
 
+    /**
+     * Returns an array containing all of the elements in this queue, in
+     * proper sequence.
+     *
+     * <p>The returned array will be "safe" in that no references to it are
+     * maintained by this queue.  (In other words, this method must allocate
+     * a new array).  The caller is thus free to modify the returned array.
+     *
+     * <p>This method acts as bridge between array-based and collection-based
+     * APIs.
+     *
+     * @return an array containing all of the elements in this queue
+     */
     public Object[] toArray() {
         fullyLock();
         try {
@@ -488,6 +514,42 @@
         }
     }
 
+    /**
+     * Returns an array containing all of the elements in this queue, in
+     * proper sequence; the runtime type of the returned array is that of
+     * the specified array.  If the queue fits in the specified array, it
+     * is returned therein.  Otherwise, a new array is allocated with the
+     * runtime type of the specified array and the size of this queue.
+     *
+     * <p>If this queue fits in the specified array with room to spare
+     * (i.e., the array has more elements than this queue), the element in
+     * the array immediately following the end of the queue is set to
+     * <tt>null</tt>.
+     *
+     * <p>Like the {@link #toArray()} method, this method acts as bridge between
+     * array-based and collection-based APIs.  Further, this method allows
+     * precise control over the runtime type of the output array, and may,
+     * under certain circumstances, be used to save allocation costs.
+     *
+     * <p>Suppose <tt>x</tt> is a queue known to contain only strings.
+     * The following code can be used to dump the queue into a newly
+     * allocated array of <tt>String</tt>:
+     *
+     * <pre>
+     *     String[] y = x.toArray(new String[0]);</pre>
+     *
+     * Note that <tt>toArray(new Object[0])</tt> is identical in function to
+     * <tt>toArray()</tt>.
+     *
+     * @param a the array into which the elements of the queue are to
+     *          be stored, if it is big enough; otherwise, a new array of the
+     *          same runtime type is allocated for this purpose
+     * @return an array containing all of the elements in this queue
+     * @throws ArrayStoreException if the runtime type of the specified array
+     *         is not a supertype of the runtime type of every element in
+     *         this queue
+     * @throws NullPointerException if the specified array is null
+     */
     public <T> T[] toArray(T[] a) {
         fullyLock();
         try {
@@ -499,6 +561,8 @@
             int k = 0;
             for (Node p = head.next; p != null; p = p.next)
                 a[k++] = (T)p.item;
+            if (a.length > k)
+                a[k] = null;
             return a;
         } finally {
             fullyUnlock();
@@ -514,10 +578,16 @@
         }
     }
 
+    /**
+     * Atomically removes all of the elements from this queue.
+     * The queue will be empty after this call returns.
+     */
     public void clear() {
         fullyLock();
         try {
             head.next = null;
+            assert head.item == null;
+            last = head;
             if (count.getAndSet(0) == capacity)
                 notFull.signalAll();
         } finally {
@@ -525,16 +595,24 @@
         }
     }
 
+    /**
+     * @throws UnsupportedOperationException {@inheritDoc}
+     * @throws ClassCastException            {@inheritDoc}
+     * @throws NullPointerException          {@inheritDoc}
+     * @throws IllegalArgumentException      {@inheritDoc}
+     */
     public int drainTo(Collection<? super E> c) {
         if (c == null)
             throw new NullPointerException();
         if (c == this)
             throw new IllegalArgumentException();
-        Node first;
+        Node<E> first;
         fullyLock();
         try {
             first = head.next;
             head.next = null;
+            assert head.item == null;
+            last = head;
             if (count.getAndSet(0) == capacity)
                 notFull.signalAll();
         } finally {
@@ -549,14 +627,18 @@
         }
         return n;
     }
-        
+
+    /**
+     * @throws UnsupportedOperationException {@inheritDoc}
+     * @throws ClassCastException            {@inheritDoc}
+     * @throws NullPointerException          {@inheritDoc}
+     * @throws IllegalArgumentException      {@inheritDoc}
+     */
     public int drainTo(Collection<? super E> c, int maxElements) {
         if (c == null)
             throw new NullPointerException();
         if (c == this)
             throw new IllegalArgumentException();
-        if (maxElements <= 0)
-            return 0;
         fullyLock();
         try {
             int n = 0;
@@ -569,6 +651,9 @@
             }
             if (n != 0) {
                 head.next = p;
+                assert head.item == null;
+                if (p == null)
+                    last = head;
                 if (count.getAndAdd(-n) == capacity)
                     notFull.signalAll();
             }
@@ -581,12 +666,12 @@
     /**
      * Returns an iterator over the elements in this queue in proper sequence.
      * The returned <tt>Iterator</tt> is a "weakly consistent" iterator that
-     * will never throw {@link java.util.ConcurrentModificationException},
+     * will never throw {@link ConcurrentModificationException},
      * and guarantees to traverse elements as they existed upon
      * construction of the iterator, and may (but is not guaranteed to)
      * reflect any modifications subsequent to construction.
      *
-     * @return an iterator over the elements in this queue in proper sequence.
+     * @return an iterator over the elements in this queue in proper sequence
      */
     public Iterator<E> iterator() {
       return new Itr();
@@ -660,6 +745,8 @@
                 if (p == node) {
                     p.item = null;
                     trail.next = p.next;
+                    if (last == p)
+                        last = trail;
                     int c = count.getAndDecrement();
                     if (c == capacity)
                         notFull.signalAll();
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/PriorityBlockingQueue.java b/libcore/concurrent/src/main/java/java/util/concurrent/PriorityBlockingQueue.java
index 83f1040..7a33dc7 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/PriorityBlockingQueue.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/PriorityBlockingQueue.java
@@ -19,16 +19,47 @@
  * blocking retrieval operations.  While this queue is logically
  * unbounded, attempted additions may fail due to resource exhaustion
  * (causing <tt>OutOfMemoryError</tt>). This class does not permit
- * <tt>null</tt> elements.  A priority queue relying on natural
- * ordering also does not permit insertion of non-comparable objects
- * (doing so results in <tt>ClassCastException</tt>).
+ * <tt>null</tt> elements.  A priority queue relying on {@linkplain
+ * Comparable natural ordering} also does not permit insertion of
+ * non-comparable objects (doing so results in
+ * <tt>ClassCastException</tt>).
  *
- * <p>This class implements all of the <em>optional</em> methods
- * of the {@link Collection} and {@link Iterator} interfaces.
- * <p>The Iterator provided in method {@link #iterator()} is
- * <em>not</em> guaranteed to traverse the elements of the
- * PriorityBlockingQueue in any particular order. If you need ordered
- * traversal, consider using <tt>Arrays.sort(pq.toArray())</tt>.
+ * <p>This class and its iterator implement all of the
+ * <em>optional</em> methods of the {@link Collection} and {@link
+ * Iterator} interfaces.  The Iterator provided in method {@link
+ * #iterator()} is <em>not</em> guaranteed to traverse the elements of
+ * the PriorityBlockingQueue in any particular order. If you need
+ * ordered traversal, consider using
+ * <tt>Arrays.sort(pq.toArray())</tt>.  Also, method <tt>drainTo</tt>
+ * can be used to <em>remove</em> some or all elements in priority
+ * order and place them in another collection.
+ *
+ * <p>Operations on this class make no guarantees about the ordering
+ * of elements with equal priority. If you need to enforce an
+ * ordering, you can define custom classes or comparators that use a
+ * secondary key to break ties in primary priority values.  For
+ * example, here is a class that applies first-in-first-out
+ * tie-breaking to comparable elements. To use it, you would insert a
+ * <tt>new FIFOEntry(anEntry)</tt> instead of a plain entry object.
+ *
+ * <pre>
+ * class FIFOEntry&lt;E extends Comparable&lt;? super E&gt;&gt;
+ *     implements Comparable&lt;FIFOEntry&lt;E&gt;&gt; {
+ *   final static AtomicLong seq = new AtomicLong();
+ *   final long seqNum;
+ *   final E entry;
+ *   public FIFOEntry(E entry) {
+ *     seqNum = seq.getAndIncrement();
+ *     this.entry = entry;
+ *   }
+ *   public E getEntry() { return entry; }
+ *   public int compareTo(FIFOEntry&lt;E&gt; other) {
+ *     int res = entry.compareTo(other.entry);
+ *     if (res == 0 &amp;&amp; other.entry != this.entry)
+ *       res = (seqNum &lt; other.seqNum ? -1 : 1);
+ *     return res;
+ *   }
+ * }</pre>
  *
  * @since 1.5
  * @author Doug Lea
@@ -43,24 +74,22 @@
     private final Condition notEmpty = lock.newCondition();
 
     /**
-     * Creates a <tt>PriorityBlockingQueue</tt> with the default initial 
-     * capacity
-     * (11) that orders its elements according to their natural
-     * ordering (using <tt>Comparable</tt>).
+     * Creates a <tt>PriorityBlockingQueue</tt> with the default
+     * initial capacity (11) that orders its elements according to
+     * their {@linkplain Comparable natural ordering}.
      */
     public PriorityBlockingQueue() {
         q = new PriorityQueue<E>();
     }
 
     /**
-     * Creates a <tt>PriorityBlockingQueue</tt> with the specified initial
-     * capacity
-     * that orders its elements according to their natural ordering
-     * (using <tt>Comparable</tt>).
+     * Creates a <tt>PriorityBlockingQueue</tt> with the specified
+     * initial capacity that orders its elements according to their
+     * {@linkplain Comparable natural ordering}.
      *
-     * @param initialCapacity the initial capacity for this priority queue.
+     * @param initialCapacity the initial capacity for this priority queue
      * @throws IllegalArgumentException if <tt>initialCapacity</tt> is less
-     * than 1
+     *         than 1
      */
     public PriorityBlockingQueue(int initialCapacity) {
         q = new PriorityQueue<E>(initialCapacity, null);
@@ -68,15 +97,15 @@
 
     /**
      * Creates a <tt>PriorityBlockingQueue</tt> with the specified initial
-     * capacity
-     * that orders its elements according to the specified comparator.
+     * capacity that orders its elements according to the specified
+     * comparator.
      *
-     * @param initialCapacity the initial capacity for this priority queue.
-     * @param comparator the comparator used to order this priority queue.
-     * If <tt>null</tt> then the order depends on the elements' natural
-     * ordering.
+     * @param initialCapacity the initial capacity for this priority queue
+     * @param  comparator the comparator that will be used to order this
+     *         priority queue.  If {@code null}, the {@linkplain Comparable
+     *         natural ordering} of the elements will be used.
      * @throws IllegalArgumentException if <tt>initialCapacity</tt> is less
-     * than 1
+     *         than 1
      */
     public PriorityBlockingQueue(int initialCapacity,
                                  Comparator<? super E> comparator) {
@@ -85,75 +114,54 @@
 
     /**
      * Creates a <tt>PriorityBlockingQueue</tt> containing the elements
-     * in the specified collection.  The priority queue has an initial
-     * capacity of 110% of the size of the specified collection. If
-     * the specified collection is a {@link SortedSet} or a {@link
-     * PriorityQueue}, this priority queue will be sorted according to
-     * the same comparator, or according to its elements' natural
-     * order if the collection is sorted according to its elements'
-     * natural order.  Otherwise, this priority queue is ordered
-     * according to its elements' natural order.
+     * in the specified collection.  If the specified collection is a
+     * {@link SortedSet} or a {@link PriorityQueue},  this
+     * priority queue will be ordered according to the same ordering.
+     * Otherwise, this priority queue will be ordered according to the
+     * {@linkplain Comparable natural ordering} of its elements.
      *
-     * @param c the collection whose elements are to be placed
-     *        into this priority queue.
+     * @param  c the collection whose elements are to be placed
+     *         into this priority queue
      * @throws ClassCastException if elements of the specified collection
      *         cannot be compared to one another according to the priority
-     *         queue's ordering.
-     * @throws NullPointerException if <tt>c</tt> or any element within it
-     * is <tt>null</tt>
+     *         queue's ordering
+     * @throws NullPointerException if the specified collection or any
+     *         of its elements are null
      */
     public PriorityBlockingQueue(Collection<? extends E> c) {
         q = new PriorityQueue<E>(c);
     }
 
-
-    // these first few override just to update doc comments
-
     /**
-     * Adds the specified element to this queue.
-     * @param o the element to add
-     * @return <tt>true</tt> (as per the general contract of
-     * <tt>Collection.add</tt>).
+     * Inserts the specified element into this priority queue.
      *
-     * @throws NullPointerException if the specified element is <tt>null</tt>.
+     * @param e the element to add
+     * @return <tt>true</tt> (as specified by {@link Collection#add})
      * @throws ClassCastException if the specified element cannot be compared
-     * with elements currently in the priority queue according
-     * to the priority queue's ordering.
+     *         with elements currently in the priority queue according to the
+     *         priority queue's ordering
+     * @throws NullPointerException if the specified element is null
      */
-    public boolean add(E o) {
-        return super.add(o);
+    public boolean add(E e) {
+        return offer(e);
     }
 
     // BEGIN android-changed
     /**
-     * Returns the comparator used to order this collection, or <tt>null</tt>
-     * if this collection is sorted according to its elements natural ordering
-     * (using <tt>Comparable</tt>).
-     *
-     * @return the comparator used to order this collection, or <tt>null</tt>
-     * if this collection is sorted according to its elements natural ordering.
-     */
-    public Comparator<? super E> comparator() {
-        return q.comparator();
-    }
-    // END android-changed
-
-    /**
      * Inserts the specified element into this priority queue.
      *
-     * @param o the element to add
-     * @return <tt>true</tt>
+     * @param e the element to add
+     * @return <tt>true</tt> (as specified by {@link Queue#offer})
      * @throws ClassCastException if the specified element cannot be compared
-     * with elements currently in the priority queue according
-     * to the priority queue's ordering.
-     * @throws NullPointerException if the specified element is <tt>null</tt>.
+     *         with elements currently in the priority queue according to the
+     *         priority queue's ordering
+     * @throws NullPointerException if the specified element is null
      */
-    public boolean offer(E o) {
-        if (o == null) throw new NullPointerException();
+    public boolean offer(E e) {
         final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            boolean ok = q.offer(o);
+            boolean ok = q.offer(e);
             assert ok;
             notEmpty.signal();
             return true;
@@ -163,32 +171,44 @@
     }
 
     /**
-     * Adds the specified element to this priority queue. As the queue is
+     * Inserts the specified element into this priority queue. As the queue is
      * unbounded this method will never block.
-     * @param o the element to add
-     * @throws ClassCastException if the element cannot be compared
-     * with elements currently in the priority queue according
-     * to the priority queue's ordering.
-     * @throws NullPointerException if the specified element is <tt>null</tt>.
+     *
+     * @param e the element to add
+     * @throws ClassCastException if the specified element cannot be compared
+     *         with elements currently in the priority queue according to the
+     *         priority queue's ordering
+     * @throws NullPointerException if the specified element is null
      */
-    public void put(E o) {
-        offer(o); // never need to block
+    public void put(E e) {
+        offer(e); // never need to block
     }
 
     /**
      * Inserts the specified element into this priority queue. As the queue is
      * unbounded this method will never block.
-     * @param o the element to add
+     *
+     * @param e the element to add
      * @param timeout This parameter is ignored as the method never blocks
      * @param unit This parameter is ignored as the method never blocks
      * @return <tt>true</tt>
-     * @throws ClassCastException if the element cannot be compared
-     * with elements currently in the priority queue according
-     * to the priority queue's ordering.
-     * @throws NullPointerException if the specified element is <tt>null</tt>.
+     * @throws ClassCastException if the specified element cannot be compared
+     *         with elements currently in the priority queue according to the
+     *         priority queue's ordering
+     * @throws NullPointerException if the specified element is null
      */
-    public boolean offer(E o, long timeout, TimeUnit unit) {
-        return offer(o); // never need to block
+    public boolean offer(E e, long timeout, TimeUnit unit) {
+        return offer(e); // never need to block
+    }
+
+    public E poll() {
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            return q.poll();
+        } finally {
+            lock.unlock();
+        }
     }
 
     public E take() throws InterruptedException {
@@ -210,17 +230,6 @@
         }
     }
 
-
-    public E poll() {
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
-            return q.poll();
-        } finally {
-            lock.unlock();
-        }
-    }
-
     public E poll(long timeout, TimeUnit unit) throws InterruptedException {
         long nanos = unit.toNanos(timeout);
         final ReentrantLock lock = this.lock;
@@ -254,6 +263,19 @@
         }
     }
 
+    /**
+     * Returns the comparator used to order the elements in this queue,
+     * or <tt>null</tt> if this queue uses the {@linkplain Comparable
+     * natural ordering} of its elements.
+     *
+     * @return the comparator used to order the elements in this queue,
+     *         or <tt>null</tt> if this queue uses the natural
+     *         ordering of its elements
+     */
+    public Comparator<? super E> comparator() {
+        return q.comparator();
+    }
+
     public int size() {
         final ReentrantLock lock = this.lock;
         lock.lock();
@@ -273,6 +295,17 @@
         return Integer.MAX_VALUE;
     }
 
+    /**
+     * Removes a single instance of the specified element from this queue,
+     * if it is present.  More formally, removes an element {@code e} such
+     * that {@code o.equals(e)}, if this queue contains one or more such
+     * elements.  Returns {@code true} if and only if this queue contained
+     * the specified element (or equivalently, if this queue changed as a
+     * result of the call).
+     *
+     * @param o element to be removed from this queue, if present
+     * @return <tt>true</tt> if this queue changed as a result of the call
+     */
     public boolean remove(Object o) {
         final ReentrantLock lock = this.lock;
         lock.lock();
@@ -283,6 +316,14 @@
         }
     }
 
+    /**
+     * Returns {@code true} if this queue contains the specified element.
+     * More formally, returns {@code true} if and only if this queue contains
+     * at least one element {@code e} such that {@code o.equals(e)}.
+     *
+     * @param o object to be checked for containment in this queue
+     * @return <tt>true</tt> if this queue contains the specified element
+     */
     public boolean contains(Object o) {
         final ReentrantLock lock = this.lock;
         lock.lock();
@@ -293,6 +334,19 @@
         }
     }
 
+    /**
+     * Returns an array containing all of the elements in this queue.
+     * The returned array elements are in no particular order.
+     *
+     * <p>The returned array will be "safe" in that no references to it are
+     * maintained by this queue.  (In other words, this method must allocate
+     * a new array).  The caller is thus free to modify the returned array.
+     *
+     * <p>This method acts as bridge between array-based and collection-based
+     * APIs.
+     *
+     * @return an array containing all of the elements in this queue
+     */
     public Object[] toArray() {
         final ReentrantLock lock = this.lock;
         lock.lock();
@@ -314,6 +368,12 @@
         }
     }
 
+    /**
+     * @throws UnsupportedOperationException {@inheritDoc}
+     * @throws ClassCastException            {@inheritDoc}
+     * @throws NullPointerException          {@inheritDoc}
+     * @throws IllegalArgumentException      {@inheritDoc}
+     */
     public int drainTo(Collection<? super E> c) {
         if (c == null)
             throw new NullPointerException();
@@ -334,6 +394,12 @@
         }
     }
 
+    /**
+     * @throws UnsupportedOperationException {@inheritDoc}
+     * @throws ClassCastException            {@inheritDoc}
+     * @throws NullPointerException          {@inheritDoc}
+     * @throws IllegalArgumentException      {@inheritDoc}
+     */
     public int drainTo(Collection<? super E> c, int maxElements) {
         if (c == null)
             throw new NullPointerException();
@@ -357,7 +423,7 @@
     }
 
     /**
-     * Atomically removes all of the elements from this delay queue.
+     * Atomically removes all of the elements from this queue.
      * The queue will be empty after this call returns.
      */
     public void clear() {
@@ -370,6 +436,43 @@
         }
     }
 
+    /**
+     * Returns an array containing all of the elements in this queue; the
+     * runtime type of the returned array is that of the specified array.
+     * The returned array elements are in no particular order.
+     * If the queue fits in the specified array, it is returned therein.
+     * Otherwise, a new array is allocated with the runtime type of the
+     * specified array and the size of this queue.
+     *
+     * <p>If this queue fits in the specified array with room to spare
+     * (i.e., the array has more elements than this queue), the element in
+     * the array immediately following the end of the queue is set to
+     * <tt>null</tt>.
+     *
+     * <p>Like the {@link #toArray()} method, this method acts as bridge between
+     * array-based and collection-based APIs.  Further, this method allows
+     * precise control over the runtime type of the output array, and may,
+     * under certain circumstances, be used to save allocation costs.
+     *
+     * <p>Suppose <tt>x</tt> is a queue known to contain only strings.
+     * The following code can be used to dump the queue into a newly
+     * allocated array of <tt>String</tt>:
+     *
+     * <pre>
+     *     String[] y = x.toArray(new String[0]);</pre>
+     *
+     * Note that <tt>toArray(new Object[0])</tt> is identical in function to
+     * <tt>toArray()</tt>.
+     *
+     * @param a the array into which the elements of the queue are to
+     *          be stored, if it is big enough; otherwise, a new array of the
+     *          same runtime type is allocated for this purpose
+     * @return an array containing all of the elements in this queue
+     * @throws ArrayStoreException if the runtime type of the specified array
+     *         is not a supertype of the runtime type of every element in
+     *         this queue
+     * @throws NullPointerException if the specified array is null
+     */
     public <T> T[] toArray(T[] a) {
         final ReentrantLock lock = this.lock;
         lock.lock();
@@ -383,54 +486,58 @@
     /**
      * Returns an iterator over the elements in this queue. The
      * iterator does not return the elements in any particular order.
-     * The returned iterator is a thread-safe "fast-fail" iterator
-     * that will throw {@link
-     * java.util.ConcurrentModificationException} upon detected
-     * interference.
+     * The returned <tt>Iterator</tt> is a "weakly consistent"
+     * iterator that will never throw {@link
+     * ConcurrentModificationException}, and guarantees to traverse
+     * elements as they existed upon construction of the iterator, and
+     * may (but is not guaranteed to) reflect any modifications
+     * subsequent to construction.
      *
-     * @return an iterator over the elements in this queue.
+     * @return an iterator over the elements in this queue
      */
     public Iterator<E> iterator() {
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
-            return new Itr(q.iterator());
-        } finally {
-            lock.unlock();
-        }
+        return new Itr(toArray());
     }
 
-    private class Itr<E> implements Iterator<E> {
-        private final Iterator<E> iter;
-        Itr(Iterator<E> i) {
-            iter = i;
+    /**
+     * Snapshot iterator that works off copy of underlying q array.
+     */
+    private class Itr implements Iterator<E> {
+        final Object[] array; // Array of all elements
+        int cursor;           // index of next element to return;
+        int lastRet;          // index of last element, or -1 if no such
+
+        Itr(Object[] array) {
+            lastRet = -1;
+            this.array = array;
         }
 
         public boolean hasNext() {
-            /*
-             * No sync -- we rely on underlying hasNext to be
-             * stateless, in which case we can return true by mistake
-             * only when next() will subsequently throw
-             * ConcurrentModificationException.
-             */
-            return iter.hasNext();
+            return cursor < array.length;
         }
 
         public E next() {
-            ReentrantLock lock = PriorityBlockingQueue.this.lock;
-            lock.lock();
-            try {
-                return iter.next();
-            } finally {
-                lock.unlock();
-            }
+            if (cursor >= array.length)
+                throw new NoSuchElementException();
+            lastRet = cursor;
+            return (E)array[cursor++];
         }
 
         public void remove() {
-            ReentrantLock lock = PriorityBlockingQueue.this.lock;
+            if (lastRet < 0)
+                throw new IllegalStateException();
+            Object x = array[lastRet];
+            lastRet = -1;
+            // Traverse underlying queue to find == element,
+            // not just a .equals element.
             lock.lock();
             try {
-                iter.remove();
+                for (Iterator it = q.iterator(); it.hasNext(); ) {
+                    if (it.next() == x) {
+                        it.remove();
+                        return;
+                    }
+                }
             } finally {
                 lock.unlock();
             }
@@ -438,7 +545,7 @@
     }
 
     /**
-     * Save the state to a stream (that is, serialize it).  This
+     * Saves the state to a stream (that is, serializes it).  This
      * merely wraps default serialization within lock.  The
      * serialization strategy for items is left to underlying
      * Queue. Note that locking is not needed on deserialization, so
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/RejectedExecutionException.java b/libcore/concurrent/src/main/java/java/util/concurrent/RejectedExecutionException.java
index 199b9de..30b043d 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/RejectedExecutionException.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/RejectedExecutionException.java
@@ -9,7 +9,7 @@
 /**
  * Exception thrown by an {@link Executor} when a task cannot be
  * accepted for execution.
- * 
+ *
  * @since 1.5
  * @author Doug Lea
  */
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/RejectedExecutionHandler.java b/libcore/concurrent/src/main/java/java/util/concurrent/RejectedExecutionHandler.java
index 4b4bbea..417a27c 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/RejectedExecutionHandler.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/RejectedExecutionHandler.java
@@ -7,8 +7,7 @@
 package java.util.concurrent;
 
 /**
- * A handler for tasks that cannot be executed by a {@link
- * ThreadPoolExecutor}.
+ * A handler for tasks that cannot be executed by a {@link ThreadPoolExecutor}.
  *
  * @since 1.5
  * @author Doug Lea
@@ -17,13 +16,14 @@
 
     /**
      * Method that may be invoked by a {@link ThreadPoolExecutor} when
-     * <tt>execute</tt> cannot accept a task. This may occur when no
-     * more threads or queue slots are available because their bounds
-     * would be exceeded, or upon shutdown of the Executor.
+     * {@link ThreadPoolExecutor#execute execute} cannot accept a
+     * task.  This may occur when no more threads or queue slots are
+     * available because their bounds would be exceeded, or upon
+     * shutdown of the Executor.
      *
-     * In the absence other alternatives, the method may throw an
-     * unchecked {@link RejectedExecutionException}, which will be
-     * propagated to the caller of <tt>execute</tt>.
+     * <p>In the absence of other alternatives, the method may throw
+     * an unchecked {@link RejectedExecutionException}, which will be
+     * propagated to the caller of {@code execute}.
      *
      * @param r the runnable task requested to be executed
      * @param executor the executor attempting to execute this task
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/ScheduledExecutorService.java b/libcore/concurrent/src/main/java/java/util/concurrent/ScheduledExecutorService.java
index 9579fef..c170c4a 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/ScheduledExecutorService.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/ScheduledExecutorService.java
@@ -10,13 +10,13 @@
 
 /**
  * An {@link ExecutorService} that can schedule commands to run after a given
- * delay, or to execute periodically. 
+ * delay, or to execute periodically.
  *
  * <p> The <tt>schedule</tt> methods create tasks with various delays
  * and return a task object that can be used to cancel or check
  * execution. The <tt>scheduleAtFixedRate</tt> and
  * <tt>scheduleWithFixedDelay</tt> methods create and execute tasks
- * that run periodically until cancelled.  
+ * that run periodically until cancelled.
  *
  * <p> Commands submitted using the {@link Executor#execute} and
  * {@link ExecutorService} <tt>submit</tt> methods are scheduled with
@@ -33,27 +33,27 @@
  * TimeUnit.MILLISECONDS)</tt>. Beware however that expiration of a
  * relative delay need not coincide with the current <tt>Date</tt> at
  * which the task is enabled due to network time synchronization
- * protocols, clock drift, or other factors. 
+ * protocols, clock drift, or other factors.
  *
  * The {@link Executors} class provides convenient factory methods for
  * the ScheduledExecutorService implementations provided in this package.
  *
  * <h3>Usage Example</h3>
- * 
+ *
  * Here is a class with a method that sets up a ScheduledExecutorService
  * to beep every ten seconds for an hour:
  *
  * <pre>
- * import static java.util.concurrent.TimeUnit;
+ * import static java.util.concurrent.TimeUnit.*;
  * class BeeperControl {
- *    private final ScheduledExecutorService scheduler = 
+ *    private final ScheduledExecutorService scheduler =
  *       Executors.newScheduledThreadPool(1);
  *
  *    public void beepForAnHour() {
  *        final Runnable beeper = new Runnable() {
  *                public void run() { System.out.println("beep"); }
  *            };
- *        final ScheduledFuture&lt;?&gt; beeperHandle = 
+ *        final ScheduledFuture&lt;?&gt; beeperHandle =
  *            scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS);
  *        scheduler.schedule(new Runnable() {
  *                public void run() { beeperHandle.cancel(true); }
@@ -70,76 +70,90 @@
     /**
      * Creates and executes a one-shot action that becomes enabled
      * after the given delay.
-     * @param command the task to execute.
-     * @param delay the time from now to delay execution.
-     * @param unit the time unit of the delay parameter.
-     * @return a Future representing pending completion of the task,
-     * and whose <tt>get()</tt> method will return <tt>null</tt>
-     * upon completion.
-     * @throws RejectedExecutionException if task cannot be scheduled
-     * for execution.
+     *
+     * @param command the task to execute
+     * @param delay the time from now to delay execution
+     * @param unit the time unit of the delay parameter
+     * @return a ScheduledFuture representing pending completion of
+     *         the task and whose <tt>get()</tt> method will return
+     *         <tt>null</tt> upon completion
+     * @throws RejectedExecutionException if the task cannot be
+     *         scheduled for execution
      * @throws NullPointerException if command is null
      */
-    public ScheduledFuture<?> schedule(Runnable command, long delay,  TimeUnit unit);
+    public ScheduledFuture<?> schedule(Runnable command,
+                                       long delay, TimeUnit unit);
 
     /**
      * Creates and executes a ScheduledFuture that becomes enabled after the
      * given delay.
-     * @param callable the function to execute.
-     * @param delay the time from now to delay execution.
-     * @param unit the time unit of the delay parameter.
-     * @return a ScheduledFuture that can be used to extract result or cancel.
-     * @throws RejectedExecutionException if task cannot be scheduled
-     * for execution.
+     *
+     * @param callable the function to execute
+     * @param delay the time from now to delay execution
+     * @param unit the time unit of the delay parameter
+     * @return a ScheduledFuture that can be used to extract result or cancel
+     * @throws RejectedExecutionException if the task cannot be
+     *         scheduled for execution
      * @throws NullPointerException if callable is null
      */
-    public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit);
+    public <V> ScheduledFuture<V> schedule(Callable<V> callable,
+                                           long delay, TimeUnit unit);
 
     /**
      * Creates and executes a periodic action that becomes enabled first
      * after the given initial delay, and subsequently with the given
      * period; that is executions will commence after
      * <tt>initialDelay</tt> then <tt>initialDelay+period</tt>, then
-     * <tt>initialDelay + 2 * period</tt>, and so on.  
+     * <tt>initialDelay + 2 * period</tt>, and so on.
      * If any execution of the task
      * encounters an exception, subsequent executions are suppressed.
      * Otherwise, the task will only terminate via cancellation or
-     * termination of the executor.
-     * @param command the task to execute.
-     * @param initialDelay the time to delay first execution.
-     * @param period the period between successive executions.
+     * termination of the executor.  If any execution of this task
+     * takes longer than its period, then subsequent executions
+     * may start late, but will not concurrently execute.
+     *
+     * @param command the task to execute
+     * @param initialDelay the time to delay first execution
+     * @param period the period between successive executions
      * @param unit the time unit of the initialDelay and period parameters
-     * @return a Future representing pending completion of the task,
-     * and whose <tt>get()</tt> method will throw an exception upon
-     * cancellation.
-     * @throws RejectedExecutionException if task cannot be scheduled
-     * for execution.
+     * @return a ScheduledFuture representing pending completion of
+     *         the task, and whose <tt>get()</tt> method will throw an
+     *         exception upon cancellation
+     * @throws RejectedExecutionException if the task cannot be
+     *         scheduled for execution
      * @throws NullPointerException if command is null
-     * @throws IllegalArgumentException if period less than or equal to zero.
+     * @throws IllegalArgumentException if period less than or equal to zero
      */
-    public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay,  long period, TimeUnit unit);
-    
+    public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
+                                                  long initialDelay,
+                                                  long period,
+                                                  TimeUnit unit);
+
     /**
      * Creates and executes a periodic action that becomes enabled first
      * after the given initial delay, and subsequently with the
      * given delay between the termination of one execution and the
-     * commencement of the next. If any execution of the task
+     * commencement of the next.  If any execution of the task
      * encounters an exception, subsequent executions are suppressed.
      * Otherwise, the task will only terminate via cancellation or
      * termination of the executor.
-     * @param command the task to execute.
-     * @param initialDelay the time to delay first execution.
+     *
+     * @param command the task to execute
+     * @param initialDelay the time to delay first execution
      * @param delay the delay between the termination of one
-     * execution and the commencement of the next.
+     * execution and the commencement of the next
      * @param unit the time unit of the initialDelay and delay parameters
-     * @return a Future representing pending completion of the task,
-     * and whose <tt>get()</tt> method will throw an exception upon
-     * cancellation.
-     * @throws RejectedExecutionException if task cannot be scheduled
-     * for execution.
+     * @return a ScheduledFuture representing pending completion of
+     *         the task, and whose <tt>get()</tt> method will throw an
+     *         exception upon cancellation
+     * @throws RejectedExecutionException if the task cannot be
+     *         scheduled for execution
      * @throws NullPointerException if command is null
-     * @throws IllegalArgumentException if delay less than or equal to zero.
+     * @throws IllegalArgumentException if delay less than or equal to zero
      */
-    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay,  long delay, TimeUnit unit);
+    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
+                                                     long initialDelay,
+                                                     long delay,
+                                                     TimeUnit unit);
 
 }
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java b/libcore/concurrent/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java
index 09ec681..83ffb99 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java
@@ -4,8 +4,13 @@
  * http://creativecommons.org/licenses/publicdomain
  */
 
+/*
+ * Modified in Apache Harmony.
+ */
+
 package java.util.concurrent;
 import java.util.concurrent.atomic.*;
+import java.util.concurrent.locks.*;
 import java.util.*;
 
 /**
@@ -16,25 +21,60 @@
  * flexibility or capabilities of {@link ThreadPoolExecutor} (which
  * this class extends) are required.
  *
- * <p> Delayed tasks execute no sooner than they are enabled, but
+ * <p>Delayed tasks execute no sooner than they are enabled, but
  * without any real-time guarantees about when, after they are
  * enabled, they will commence. Tasks scheduled for exactly the same
  * execution time are enabled in first-in-first-out (FIFO) order of
  * submission.
  *
+ * <p>Successive executions of a task scheduled via
+ * <code>scheduleAtFixedRate</code> or
+ * <code>scheduleWithFixedDelay</code> do not overlap. While different
+ * executions may be performed by different threads, the effects of
+ * prior executions <a
+ * href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * those of subsequent ones.
+ *
  * <p>While this class inherits from {@link ThreadPoolExecutor}, a few
  * of the inherited tuning methods are not useful for it. In
- * particular, because it acts as a fixed-sized pool using
- * <tt>corePoolSize</tt> threads and an unbounded queue, adjustments
- * to <tt>maximumPoolSize</tt> have no useful effect.
+ * particular, because it acts as a fixed-sized pool using {@code
+ * corePoolSize} threads and an unbounded queue, adjustments to {@code
+ * maximumPoolSize} have no useful effect.
  *
  * @since 1.5
  * @author Doug Lea
  */
-public class ScheduledThreadPoolExecutor 
-        extends ThreadPoolExecutor 
+public class ScheduledThreadPoolExecutor
+        extends ThreadPoolExecutor
         implements ScheduledExecutorService {
 
+    /*
+     * This class specializes ThreadPoolExecutor implementation by
+     *
+     * 1. Using a custom task type, ScheduledFutureTask for
+     *    tasks, even those that don't require scheduling (i.e.,
+     *    those submitted using ExecutorService execute, not
+     *    ScheduledExecutorService methods) which are treated as
+     *    delayed tasks with a delay of zero.
+     *
+     * 2. Using a custom queue (DelayedWorkQueue), a variant of
+     *    unbounded DelayQueue. The lack of capacity constraint and
+     *    the fact that corePoolSize and maximumPoolSize are
+     *    effectively identical simplifies some execution mechanics
+     *    (see delayedExecute) compared to ThreadPoolExecutor.
+     *
+     * 3. Supporting optional run-after-shutdown parameters, which
+     *    leads to overrides of shutdown methods to remove and cancel
+     *    tasks that should NOT be run after shutdown, as well as
+     *    different recheck logic when task (re)submission overlaps
+     *    with a shutdown.
+     *
+     * 4. Task decoration methods to allow interception and
+     *    instrumentation, which are needed because subclasses cannot
+     *    otherwise override submit methods to get this effect. These
+     *    don't have any impact on pool control logic though.
+     */
+
     /**
      * False if should cancel/suppress periodic tasks on shutdown.
      */
@@ -46,28 +86,40 @@
     private volatile boolean executeExistingDelayedTasksAfterShutdown = true;
 
     /**
+     * True if ScheduledFutureTask.cancel should remove from queue
+     */
+    private volatile boolean removeOnCancel = false;
+
+    /**
      * Sequence number to break scheduling ties, and in turn to
      * guarantee FIFO order among tied entries.
      */
     private static final AtomicLong sequencer = new AtomicLong(0);
 
-    /** Base of nanosecond timings, to avoid wrapping */
-    private static final long NANO_ORIGIN = System.nanoTime();
 
     /**
-     * Returns nanosecond time offset by origin
+     * Value of System.nanoTime upon static initialization.  This is
+     * used as an offset by now() to avoid wraparound of time values
+     * that would make them appear negative.
      */
-    final long now() {
-        return System.nanoTime() - NANO_ORIGIN;
+    static final long initialNanoTime = System.nanoTime();
+
+    /**
+     * Returns current nanosecond time.
+     */
+    static long now() {
+        return System.nanoTime() - initialNanoTime;
     }
 
-    private class ScheduledFutureTask<V> 
+    private class ScheduledFutureTask<V>
             extends FutureTask<V> implements ScheduledFuture<V> {
-        
+
         /** Sequence number to break ties FIFO */
         private final long sequenceNumber;
+
         /** The time the task is enabled to execute in nanoTime units */
         private long time;
+
         /**
          * Period in nanoseconds for repeating tasks.  A positive
          * value indicates fixed-rate execution.  A negative value
@@ -76,8 +128,16 @@
          */
         private final long period;
 
+        /** The actual task to be re-enqueued by reExecutePeriodic */
+        ScheduledFutureTask<V> outerTask = this;
+
         /**
-         * Creates a one-shot action with given nanoTime-based trigger time
+         * Index into delay queue, to support faster cancellation.
+         */
+        int heapIndex;
+
+        /**
+         * Creates a one-shot action with given nanoTime-based trigger time.
          */
         ScheduledFutureTask(Runnable r, V result, long ns) {
             super(r, result);
@@ -87,9 +147,9 @@
         }
 
         /**
-         * Creates a periodic action with given nano time and period
+         * Creates a periodic action with given nano time and period.
          */
-        ScheduledFutureTask(Runnable r, V result, long ns,  long period) {
+        ScheduledFutureTask(Runnable r, V result, long ns, long period) {
             super(r, result);
             this.time = ns;
             this.period = period;
@@ -97,7 +157,7 @@
         }
 
         /**
-         * Creates a one-shot action with given nanoTime-based trigger
+         * Creates a one-shot action with given nanoTime-based trigger.
          */
         ScheduledFutureTask(Callable<V> callable, long ns) {
             super(callable);
@@ -107,122 +167,162 @@
         }
 
         public long getDelay(TimeUnit unit) {
-            long d = unit.convert(time - now(), TimeUnit.NANOSECONDS);
-            return d;
+            long d = time - now();
+            return d<=0? 0 : unit.convert(d, TimeUnit.NANOSECONDS);
         }
 
         public int compareTo(Delayed other) {
             if (other == this) // compare zero ONLY if same object
                 return 0;
-            ScheduledFutureTask<?> x = (ScheduledFutureTask<?>)other;
-            long diff = time - x.time;
-            if (diff < 0)
-                return -1;
-            else if (diff > 0)
-                return 1;
-            else if (sequenceNumber < x.sequenceNumber)
-                return -1;
-            else
-                return 1;
+            if (other instanceof ScheduledFutureTask) {
+                ScheduledFutureTask<?> x = (ScheduledFutureTask<?>)other;
+                long diff = time - x.time;
+                if (diff < 0)
+                    return -1;
+                else if (diff > 0)
+                    return 1;
+                else if (sequenceNumber < x.sequenceNumber)
+                    return -1;
+                else
+                    return 1;
+            }
+            long d = (getDelay(TimeUnit.NANOSECONDS) -
+                      other.getDelay(TimeUnit.NANOSECONDS));
+            return (d == 0) ? 0 : ((d < 0) ? -1 : 1);
         }
 
         /**
          * Returns true if this is a periodic (not a one-shot) action.
+         *
          * @return true if periodic
          */
-        boolean isPeriodic() {
+        public boolean isPeriodic() {
             return period != 0;
         }
 
         /**
-         * Run a periodic task
+         * Sets the next time to run for a periodic task.
          */
-        private void runPeriodic() {
-            boolean ok = ScheduledFutureTask.super.runAndReset();
-            boolean down = isShutdown();
-            // Reschedule if not cancelled and not shutdown or policy allows
-            if (ok && (!down ||
-                       (getContinueExistingPeriodicTasksAfterShutdownPolicy() && 
-                        !isTerminating()))) {
-                long p = period;
-                if (p > 0)
-                    time += p;
-                else
-                    time = now() - p;
-                ScheduledThreadPoolExecutor.super.getQueue().add(this);
-            }
-            // This might have been the final executed delayed
-            // task.  Wake up threads to check.
-            else if (down) 
-                interruptIdleWorkers();
+        private void setNextRunTime() {
+            long p = period;
+            if (p > 0)
+                time += p;
+            else
+                time = now() - p;
+        }
+
+        public boolean cancel(boolean mayInterruptIfRunning) {
+            boolean cancelled = super.cancel(mayInterruptIfRunning);
+            if (cancelled && removeOnCancel && heapIndex >= 0)
+                remove(this);
+            return cancelled;
         }
 
         /**
          * Overrides FutureTask version so as to reset/requeue if periodic.
-         */ 
+         */
         public void run() {
-            if (isPeriodic())
-                runPeriodic();
-            else 
+            boolean periodic = isPeriodic();
+            if (!canRunInCurrentRunState(periodic))
+                cancel(false);
+            else if (!periodic)
                 ScheduledFutureTask.super.run();
+            else if (ScheduledFutureTask.super.runAndReset()) {
+                setNextRunTime();
+                reExecutePeriodic(outerTask);
+            }
         }
     }
 
     /**
-     * Specialized variant of ThreadPoolExecutor.execute for delayed tasks.
+     * Returns true if can run a task given current run state
+     * and run-after-shutdown parameters.
+     *
+     * @param periodic true if this task periodic, false if delayed
      */
-    private void delayedExecute(Runnable command) {
-        if (isShutdown()) {
-            reject(command);
-            return;
-        }
-        // Prestart a thread if necessary. We cannot prestart it
-        // running the task because the task (probably) shouldn't be
-        // run yet, so thread will just idle until delay elapses.
-        if (getPoolSize() < getCorePoolSize())
-            prestartCoreThread();
-            
-        super.getQueue().add(command);
+    boolean canRunInCurrentRunState(boolean periodic) {
+        return isRunningOrShutdown(periodic ?
+                                   continueExistingPeriodicTasksAfterShutdown :
+                                   executeExistingDelayedTasksAfterShutdown);
     }
 
     /**
-     * Cancel and clear the queue of all tasks that should not be run
-     * due to shutdown policy.
+     * Main execution method for delayed or periodic tasks.  If pool
+     * is shut down, rejects the task. Otherwise adds task to queue
+     * and starts a thread, if necessary, to run it.  (We cannot
+     * prestart the thread to run the task because the task (probably)
+     * shouldn't be run yet,) If the pool is shut down while the task
+     * is being added, cancel and remove it if required by state and
+     * run-after-shutdown parameters.
+     *
+     * @param task the task
      */
-    private void cancelUnwantedTasks() {
-        boolean keepDelayed = getExecuteExistingDelayedTasksAfterShutdownPolicy();
-        boolean keepPeriodic = getContinueExistingPeriodicTasksAfterShutdownPolicy();
-        if (!keepDelayed && !keepPeriodic) 
-            super.getQueue().clear();
-        else if (keepDelayed || keepPeriodic) {
-            Object[] entries = super.getQueue().toArray();
-            for (int i = 0; i < entries.length; ++i) {
-                Object e = entries[i];
+    private void delayedExecute(ScheduledFutureTask<?> task) {
+        if (isShutdown())
+            reject(task);
+        else {
+            super.getQueue().add(task);
+            if (isShutdown() &&
+                !canRunInCurrentRunState(task.isPeriodic()) &&
+                remove(task))
+                task.cancel(false);
+            else
+                prestartCoreThread();
+        }
+    }
+
+    /**
+     * Requeues a periodic task unless current run state precludes it.
+     * Same idea as delayedExecute except drops task rather than rejecting.
+     *
+     * @param task the task
+     */
+    void reExecutePeriodic(ScheduledFutureTask<?> task) {
+        if (canRunInCurrentRunState(true)) {
+            super.getQueue().add(task);
+            if (!canRunInCurrentRunState(true) && remove(task))
+                task.cancel(false);
+            else
+                prestartCoreThread();
+        }
+    }
+
+    /**
+     * Cancels and clears the queue of all tasks that should not be run
+     * due to shutdown policy.  Invoked within super.shutdown.
+     */
+    @Override void onShutdown() {
+        BlockingQueue<Runnable> q = super.getQueue();
+        boolean keepDelayed =
+            getExecuteExistingDelayedTasksAfterShutdownPolicy();
+        boolean keepPeriodic =
+            getContinueExistingPeriodicTasksAfterShutdownPolicy();
+        if (!keepDelayed && !keepPeriodic)
+            q.clear();
+        else {
+            // Traverse snapshot to avoid iterator exceptions
+            for (Object e : q.toArray()) {
                 if (e instanceof ScheduledFutureTask) {
-                    ScheduledFutureTask<?> t = (ScheduledFutureTask<?>)e;
-                    if (t.isPeriodic()? !keepPeriodic : !keepDelayed)
-                        t.cancel(false);
+                    ScheduledFutureTask<?> t =
+                        (ScheduledFutureTask<?>)e;
+                    if ((t.isPeriodic() ? !keepPeriodic : !keepDelayed) ||
+                        t.isCancelled()) { // also remove if already cancelled
+                        if (q.remove(t))
+                            t.cancel(false);
+                    }
                 }
             }
-            entries = null;
-            purge();
         }
-    }
-
-    public boolean remove(Runnable task) {
-        if (!(task instanceof ScheduledFutureTask))
-            return false;
-        return getQueue().remove(task);
+        tryTerminate();
     }
 
     /**
-     * Creates a new ScheduledThreadPoolExecutor with the given core
-     * pool size.
-     * 
-     * @param corePoolSize the number of threads to keep in the pool,
-     * even if they are idle.
-     * @throws IllegalArgumentException if corePoolSize less than or
-     * equal to zero
+     * Creates a new {@code ScheduledThreadPoolExecutor} with the
+     * given core pool size.
+     *
+     * @param corePoolSize the number of threads to keep in the pool, even
+     *        if they are idle
+     * @throws IllegalArgumentException if {@code corePoolSize < 0}
      */
     public ScheduledThreadPoolExecutor(int corePoolSize) {
         super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
@@ -230,14 +330,15 @@
     }
 
     /**
-     * Creates a new ScheduledThreadPoolExecutor with the given
-     * initial parameters.
-     * 
-     * @param corePoolSize the number of threads to keep in the pool,
-     * even if they are idle.
+     * Creates a new {@code ScheduledThreadPoolExecutor} with the
+     * given initial parameters.
+     *
+     * @param corePoolSize the number of threads to keep in the pool, even
+     *        if they are idle
      * @param threadFactory the factory to use when the executor
-     * creates a new thread. 
-     * @throws NullPointerException if threadFactory is null
+     *        creates a new thread
+     * @throws IllegalArgumentException if {@code corePoolSize < 0}
+     * @throws NullPointerException if {@code threadFactory} is null
      */
     public ScheduledThreadPoolExecutor(int corePoolSize,
                              ThreadFactory threadFactory) {
@@ -248,12 +349,13 @@
     /**
      * Creates a new ScheduledThreadPoolExecutor with the given
      * initial parameters.
-     * 
-     * @param corePoolSize the number of threads to keep in the pool,
-     * even if they are idle.
+     *
+     * @param corePoolSize the number of threads to keep in the pool, even
+     *        if they are idle
      * @param handler the handler to use when execution is blocked
-     * because the thread bounds and queue capacities are reached.
-     * @throws NullPointerException if handler is null
+     *        because the thread bounds and queue capacities are reached
+     * @throws IllegalArgumentException if {@code corePoolSize < 0}
+     * @throws NullPointerException if {@code handler} is null
      */
     public ScheduledThreadPoolExecutor(int corePoolSize,
                               RejectedExecutionHandler handler) {
@@ -264,14 +366,16 @@
     /**
      * Creates a new ScheduledThreadPoolExecutor with the given
      * initial parameters.
-     * 
-     * @param corePoolSize the number of threads to keep in the pool,
-     * even if they are idle.
+     *
+     * @param corePoolSize the number of threads to keep in the pool, even
+     *        if they are idle
      * @param threadFactory the factory to use when the executor
-     * creates a new thread. 
+     *        creates a new thread
      * @param handler the handler to use when execution is blocked
-     * because the thread bounds and queue capacities are reached.
-     * @throws NullPointerException if threadFactory or handler is null
+     *        because the thread bounds and queue capacities are reached
+     * @throws IllegalArgumentException if {@code corePoolSize < 0}
+     * @throws NullPointerException if {@code threadFactory} or
+     *         {@code handler} is null
      */
     public ScheduledThreadPoolExecutor(int corePoolSize,
                               ThreadFactory threadFactory,
@@ -280,128 +384,178 @@
               new DelayedWorkQueue(), threadFactory, handler);
     }
 
-    public ScheduledFuture<?> schedule(Runnable command, 
-                                       long delay, 
+    /**
+     * Returns the trigger time of a delayed action
+     */
+    private static long nextTriggerTime(long delay, TimeUnit unit) {
+        long triggerTime;
+        long now = now();
+        if (delay <= 0)
+            return now;            // avoid negative trigger times
+        else if ((triggerTime = now + unit.toNanos(delay)) < 0)
+            return Long.MAX_VALUE; // avoid numerical overflow
+        else
+            return triggerTime;
+    }
+
+    /**
+     * @throws RejectedExecutionException {@inheritDoc}
+     * @throws NullPointerException       {@inheritDoc}
+     */
+    public ScheduledFuture<?> schedule(Runnable command,
+                                       long delay,
                                        TimeUnit unit) {
         if (command == null || unit == null)
             throw new NullPointerException();
-        long triggerTime = now() + unit.toNanos(delay);
-        ScheduledFutureTask<?> t = 
-            new ScheduledFutureTask<Boolean>(command, null, triggerTime);
+        long triggerTime = nextTriggerTime(delay, unit);
+        ScheduledFutureTask<?> t
+                = new ScheduledFutureTask<Void>(command, null, triggerTime);
         delayedExecute(t);
         return t;
     }
 
-    public <V> ScheduledFuture<V> schedule(Callable<V> callable, 
-                                           long delay, 
+    /**
+     * @throws RejectedExecutionException {@inheritDoc}
+     * @throws NullPointerException       {@inheritDoc}
+     */
+    public <V> ScheduledFuture<V> schedule(Callable<V> callable,
+                                           long delay,
                                            TimeUnit unit) {
         if (callable == null || unit == null)
             throw new NullPointerException();
-        if (delay < 0) delay = 0;
-        long triggerTime = now() + unit.toNanos(delay);
-        ScheduledFutureTask<V> t = 
-            new ScheduledFutureTask<V>(callable, triggerTime);
+        long triggerTime = nextTriggerTime(delay, unit);
+        ScheduledFutureTask<V> t
+                = new ScheduledFutureTask<V>(callable, triggerTime);
         delayedExecute(t);
         return t;
     }
 
-    public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, 
-                                                  long initialDelay,  
-                                                  long period, 
+    /**
+     * @throws RejectedExecutionException {@inheritDoc}
+     * @throws NullPointerException       {@inheritDoc}
+     * @throws IllegalArgumentException   {@inheritDoc}
+     */
+    public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
+                                                  long initialDelay,
+                                                  long period,
                                                   TimeUnit unit) {
         if (command == null || unit == null)
             throw new NullPointerException();
         if (period <= 0)
             throw new IllegalArgumentException();
         if (initialDelay < 0) initialDelay = 0;
-        long triggerTime = now() + unit.toNanos(initialDelay);
-        ScheduledFutureTask<?> t = 
-            new ScheduledFutureTask<Object>(command, 
-                                            null,
-                                            triggerTime,
-                                            unit.toNanos(period));
-        delayedExecute(t);
-        return t;
+        long triggerTime = nextTriggerTime(initialDelay, unit);
+        ScheduledFutureTask<Void> sft =
+            new ScheduledFutureTask<Void>(command,
+                                          null,
+                                          triggerTime,
+                                          unit.toNanos(period));
+        sft.outerTask = sft;
+        delayedExecute(sft);
+        return sft;
     }
-    
-    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, 
-                                                     long initialDelay,  
-                                                     long delay, 
+
+    /**
+     * @throws RejectedExecutionException {@inheritDoc}
+     * @throws NullPointerException       {@inheritDoc}
+     * @throws IllegalArgumentException   {@inheritDoc}
+     */
+    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
+                                                     long initialDelay,
+                                                     long delay,
                                                      TimeUnit unit) {
         if (command == null || unit == null)
             throw new NullPointerException();
         if (delay <= 0)
             throw new IllegalArgumentException();
-        if (initialDelay < 0) initialDelay = 0;
-        long triggerTime = now() + unit.toNanos(initialDelay);
-        ScheduledFutureTask<?> t = 
-            new ScheduledFutureTask<Boolean>(command, 
-                                             null,
-                                             triggerTime,
-                                             unit.toNanos(-delay));
-        delayedExecute(t);
-        return t;
+        long triggerTime = nextTriggerTime(initialDelay, unit);
+        ScheduledFutureTask<Void> sft =
+            new ScheduledFutureTask<Void>(command,
+                                          null,
+                                          triggerTime,
+                                          unit.toNanos(-delay));
+        sft.outerTask = sft;
+        delayedExecute(sft);
+        return sft;
     }
-    
 
     /**
-     * Execute command with zero required delay. This has effect
-     * equivalent to <tt>schedule(command, 0, anyUnit)</tt>.  Note
-     * that inspections of the queue and of the list returned by
-     * <tt>shutdownNow</tt> will access the zero-delayed
-     * {@link ScheduledFuture}, not the <tt>command</tt> itself.
+     * Executes {@code command} with zero required delay.
+     * This has effect equivalent to
+     * {@link #schedule(Runnable,long,TimeUnit) schedule(command, 0, anyUnit)}.
+     * Note that inspections of the queue and of the list returned by
+     * {@code shutdownNow} will access the zero-delayed
+     * {@link ScheduledFuture}, not the {@code command} itself.
      *
-     * @param command the task to execute
+     * <p>A consequence of the use of {@code ScheduledFuture} objects is
+     * that {@link ThreadPoolExecutor#afterExecute afterExecute} is always
+     * called with a null second {@code Throwable} argument, even if the
+     * {@code command} terminated abruptly.  Instead, the {@code Throwable}
+     * thrown by such a task can be obtained via {@link Future#get}.
+     *
      * @throws RejectedExecutionException at discretion of
-     * <tt>RejectedExecutionHandler</tt>, if task cannot be accepted
-     * for execution because the executor has been shut down.
-     * @throws NullPointerException if command is null
+     *         {@code RejectedExecutionHandler}, if the task
+     *         cannot be accepted for execution because the
+     *         executor has been shut down
+     * @throws NullPointerException {@inheritDoc}
      */
     public void execute(Runnable command) {
-        if (command == null)
-            throw new NullPointerException();
         schedule(command, 0, TimeUnit.NANOSECONDS);
     }
 
     // Override AbstractExecutorService methods
 
+    /**
+     * @throws RejectedExecutionException {@inheritDoc}
+     * @throws NullPointerException       {@inheritDoc}
+     */
     public Future<?> submit(Runnable task) {
         return schedule(task, 0, TimeUnit.NANOSECONDS);
     }
 
+    /**
+     * @throws RejectedExecutionException {@inheritDoc}
+     * @throws NullPointerException       {@inheritDoc}
+     */
     public <T> Future<T> submit(Runnable task, T result) {
-        return schedule(Executors.callable(task, result), 
+        return schedule(Executors.callable(task, result),
                         0, TimeUnit.NANOSECONDS);
     }
 
+    /**
+     * @throws RejectedExecutionException {@inheritDoc}
+     * @throws NullPointerException       {@inheritDoc}
+     */
     public <T> Future<T> submit(Callable<T> task) {
         return schedule(task, 0, TimeUnit.NANOSECONDS);
     }
 
     /**
-     * Set policy on whether to continue executing existing periodic
-     * tasks even when this executor has been <tt>shutdown</tt>. In
-     * this case, these tasks will only terminate upon
-     * <tt>shutdownNow</tt>, or after setting the policy to
-     * <tt>false</tt> when already shutdown. This value is by default
-     * false.
-     * @param value if true, continue after shutdown, else don't.
-     * @see #getExecuteExistingDelayedTasksAfterShutdownPolicy
+     * Sets the policy on whether to continue executing existing
+     * periodic tasks even when this executor has been {@code shutdown}.
+     * In this case, these tasks will only terminate upon
+     * {@code shutdownNow} or after setting the policy to
+     * {@code false} when already shutdown.
+     * This value is by default {@code false}.
+     *
+     * @param value if {@code true}, continue after shutdown, else don't.
+     * @see #getContinueExistingPeriodicTasksAfterShutdownPolicy
      */
     public void setContinueExistingPeriodicTasksAfterShutdownPolicy(boolean value) {
         continueExistingPeriodicTasksAfterShutdown = value;
         if (!value && isShutdown())
-            cancelUnwantedTasks();
+            onShutdown();
     }
 
     /**
-     * Get the policy on whether to continue executing existing
-     * periodic tasks even when this executor has been
-     * <tt>shutdown</tt>. In this case, these tasks will only
-     * terminate upon <tt>shutdownNow</tt> or after setting the policy
-     * to <tt>false</tt> when already shutdown. This value is by
-     * default false.
-     * @return true if will continue after shutdown.
+     * Gets the policy on whether to continue executing existing
+     * periodic tasks even when this executor has been {@code shutdown}.
+     * In this case, these tasks will only terminate upon
+     * {@code shutdownNow} or after setting the policy to
+     * {@code false} when already shutdown.
+     * This value is by default {@code false}.
+     *
+     * @return {@code true} if will continue after shutdown
      * @see #setContinueExistingPeriodicTasksAfterShutdownPolicy
      */
     public boolean getContinueExistingPeriodicTasksAfterShutdownPolicy() {
@@ -409,66 +563,79 @@
     }
 
     /**
-     * Set policy on whether to execute existing delayed
-     * tasks even when this executor has been <tt>shutdown</tt>. In
-     * this case, these tasks will only terminate upon
-     * <tt>shutdownNow</tt>, or after setting the policy to
-     * <tt>false</tt> when already shutdown. This value is by default
-     * true.
-     * @param value if true, execute after shutdown, else don't.
+     * Sets the policy on whether to execute existing delayed
+     * tasks even when this executor has been {@code shutdown}.
+     * In this case, these tasks will only terminate upon
+     * {@code shutdownNow}, or after setting the policy to
+     * {@code false} when already shutdown.
+     * This value is by default {@code true}.
+     *
+     * @param value if {@code true}, execute after shutdown, else don't.
      * @see #getExecuteExistingDelayedTasksAfterShutdownPolicy
      */
     public void setExecuteExistingDelayedTasksAfterShutdownPolicy(boolean value) {
         executeExistingDelayedTasksAfterShutdown = value;
         if (!value && isShutdown())
-            cancelUnwantedTasks();
+            onShutdown();
     }
 
     /**
-     * Get policy on whether to execute existing delayed
-     * tasks even when this executor has been <tt>shutdown</tt>. In
-     * this case, these tasks will only terminate upon
-     * <tt>shutdownNow</tt>, or after setting the policy to
-     * <tt>false</tt> when already shutdown. This value is by default
-     * true.
-     * @return true if will execute after shutdown.
+     * Gets the policy on whether to execute existing delayed
+     * tasks even when this executor has been {@code shutdown}.
+     * In this case, these tasks will only terminate upon
+     * {@code shutdownNow}, or after setting the policy to
+     * {@code false} when already shutdown.
+     * This value is by default {@code true}.
+     *
+     * @return {@code true} if will execute after shutdown
      * @see #setExecuteExistingDelayedTasksAfterShutdownPolicy
      */
     public boolean getExecuteExistingDelayedTasksAfterShutdownPolicy() {
         return executeExistingDelayedTasksAfterShutdown;
     }
 
-
     /**
      * Initiates an orderly shutdown in which previously submitted
-     * tasks are executed, but no new tasks will be accepted. If the
-     * <tt>ExecuteExistingDelayedTasksAfterShutdownPolicy</tt> has
-     * been set <tt>false</tt>, existing delayed tasks whose delays
-     * have not yet elapsed are cancelled. And unless the
-     * <tt>ContinueExistingPeriodicTasksAfterShutdownPolicy</tt> has
-     * been set <tt>true</tt>, future executions of existing periodic
-     * tasks will be cancelled.
+     * tasks are executed, but no new tasks will be accepted.
+     * Invocation has no additional effect if already shut down.
+     *
+     * <p>This method does not wait for previously submitted tasks to
+     * complete execution.  Use {@link #awaitTermination awaitTermination}
+     * to do that.
+     *
+     * <p>If the {@code ExecuteExistingDelayedTasksAfterShutdownPolicy}
+     * has been set {@code false}, existing delayed tasks whose delays
+     * have not yet elapsed are cancelled.  And unless the {@code
+     * ContinueExistingPeriodicTasksAfterShutdownPolicy} has been set
+     * {@code true}, future executions of existing periodic tasks will
+     * be cancelled.
+     *
+     * @throws SecurityException {@inheritDoc}
      */
     public void shutdown() {
-        cancelUnwantedTasks();
         super.shutdown();
     }
 
     /**
      * Attempts to stop all actively executing tasks, halts the
-     * processing of waiting tasks, and returns a list of the tasks that were
-     * awaiting execution. 
-     *  
+     * processing of waiting tasks, and returns a list of the tasks
+     * that were awaiting execution.
+     *
+     * <p>This method does not wait for actively executing tasks to
+     * terminate.  Use {@link #awaitTermination awaitTermination} to
+     * do that.
+     *
      * <p>There are no guarantees beyond best-effort attempts to stop
      * processing actively executing tasks.  This implementation
-     * cancels tasks via {@link Thread#interrupt}, so if any tasks mask or
-     * fail to respond to interrupts, they may never terminate.
+     * cancels tasks via {@link Thread#interrupt}, so any task that
+     * fails to respond to interrupts may never terminate.
      *
-     * @return list of tasks that never commenced execution.  Each
-     * element of this list is a {@link ScheduledFuture},
-     * including those tasks submitted using <tt>execute</tt>, which
-     * are for scheduling purposes used as the basis of a zero-delay
-     * <tt>ScheduledFuture</tt>.
+     * @return list of tasks that never commenced execution.
+     *         Each element of this list is a {@link ScheduledFuture},
+     *         including those tasks submitted using {@code execute},
+     *         which are for scheduling purposes used as the basis of a
+     *         zero-delay {@code ScheduledFuture}.
+     * @throws SecurityException {@inheritDoc}
      */
     public List<Runnable> shutdownNow() {
         return super.shutdownNow();
@@ -477,9 +644,9 @@
     /**
      * Returns the task queue used by this executor.  Each element of
      * this queue is a {@link ScheduledFuture}, including those
-     * tasks submitted using <tt>execute</tt> which are for scheduling
+     * tasks submitted using {@code execute} which are for scheduling
      * purposes used as the basis of a zero-delay
-     * <tt>ScheduledFuture</tt>. Iteration over this queue is
+     * {@code ScheduledFuture}.  Iteration over this queue is
      * <em>not</em> guaranteed to traverse tasks in the order in
      * which they will execute.
      *
@@ -490,52 +657,478 @@
     }
 
     /**
-     * An annoying wrapper class to convince generics compiler to
-     * use a DelayQueue<ScheduledFutureTask> as a BlockingQueue<Runnable>
-     */ 
-    private static class DelayedWorkQueue 
-        extends AbstractCollection<Runnable> 
+     * Specialized delay queue. To mesh with TPE declarations, this
+     * class must be declared as a BlockingQueue<Runnable> even though
+     * it can only hold RunnableScheduledFutures.
+     */
+    static class DelayedWorkQueue extends AbstractQueue<Runnable>
         implements BlockingQueue<Runnable> {
-        
-        private final DelayQueue<ScheduledFutureTask> dq = new DelayQueue<ScheduledFutureTask>();
-        public Runnable poll() { return dq.poll(); }
-        public Runnable peek() { return dq.peek(); }
-        public Runnable take() throws InterruptedException { return dq.take(); }
-        public Runnable poll(long timeout, TimeUnit unit) throws InterruptedException {
-            return dq.poll(timeout, unit);
+
+        /*
+         * A DelayedWorkQueue is based on a heap-based data structure
+         * like those in DelayQueue and PriorityQueue, except that
+         * every ScheduledFutureTask also records its index into the
+         * heap array. This eliminates the need to find a task upon
+         * cancellation, greatly speeding up removal (down from O(n)
+         * to O(log n)), and reducing garbage retention that would
+         * otherwise occur by waiting for the element to rise to top
+         * before clearing. But because the queue may also hold
+         * RunnableScheduledFutures that are not ScheduledFutureTasks,
+         * we are not guaranteed to have such indices available, in
+         * which case we fall back to linear search. (We expect that
+         * most tasks will not be decorated, and that the faster cases
+         * will be much more common.)
+         *
+         * All heap operations must record index changes -- mainly
+         * within siftUp and siftDown. Upon removal, a task's
+         * heapIndex is set to -1. Note that ScheduledFutureTasks can
+         * appear at most once in the queue (this need not be true for
+         * other kinds of tasks or work queues), so are uniquely
+         * identified by heapIndex.
+         */
+
+        private static final int INITIAL_CAPACITY = 16;
+        private ScheduledFutureTask[] queue =
+            new ScheduledFutureTask[INITIAL_CAPACITY];
+        private final ReentrantLock lock = new ReentrantLock();
+        private int size = 0;
+
+        /**
+         * Thread designated to wait for the task at the head of the
+         * queue.  This variant of the Leader-Follower pattern
+         * (http://www.cs.wustl.edu/~schmidt/POSA/POSA2/) serves to
+         * minimize unnecessary timed waiting.  When a thread becomes
+         * the leader, it waits only for the next delay to elapse, but
+         * other threads await indefinitely.  The leader thread must
+         * signal some other thread before returning from take() or
+         * poll(...), unless some other thread becomes leader in the
+         * interim.  Whenever the head of the queue is replaced with a
+         * task with an earlier expiration time, the leader field is
+         * invalidated by being reset to null, and some waiting
+         * thread, but not necessarily the current leader, is
+         * signalled.  So waiting threads must be prepared to acquire
+         * and lose leadership while waiting.
+         */
+        private Thread leader = null;
+
+        /**
+         * Condition signalled when a newer task becomes available at the
+         * head of the queue or a new thread may need to become leader.
+         */
+        private final Condition available = lock.newCondition();
+
+        /**
+         * Set f's heapIndex if it is a ScheduledFutureTask.
+         */
+        private void setIndex(ScheduledFutureTask f, int idx) {
+            if (f instanceof ScheduledFutureTask)
+                ((ScheduledFutureTask)f).heapIndex = idx;
         }
 
-        public boolean add(Runnable x) { return dq.add((ScheduledFutureTask)x); }
-        public boolean offer(Runnable x) { return dq.offer((ScheduledFutureTask)x); }
-        public void put(Runnable x)  {
-            dq.put((ScheduledFutureTask)x); 
-        }
-        public boolean offer(Runnable x, long timeout, TimeUnit unit) {
-            return dq.offer((ScheduledFutureTask)x, timeout, unit);
+        /**
+         * Sift element added at bottom up to its heap-ordered spot.
+         * Call only when holding lock.
+         */
+        private void siftUp(int k, ScheduledFutureTask key) {
+            while (k > 0) {
+                int parent = (k - 1) >>> 1;
+                ScheduledFutureTask e = queue[parent];
+                if (key.compareTo(e) >= 0)
+                    break;
+                queue[k] = e;
+                setIndex(e, k);
+                k = parent;
+            }
+            queue[k] = key;
+            setIndex(key, k);
         }
 
-        public Runnable remove() { return dq.remove(); }
-        public Runnable element() { return dq.element(); }
-        public void clear() { dq.clear(); }
-        public int drainTo(Collection<? super Runnable> c) { return dq.drainTo(c); }
-        public int drainTo(Collection<? super Runnable> c, int maxElements) { 
-            return dq.drainTo(c, maxElements); 
+        /**
+         * Sift element added at top down to its heap-ordered spot.
+         * Call only when holding lock.
+         */
+        private void siftDown(int k, ScheduledFutureTask key) {
+            int half = size >>> 1;
+            while (k < half) {
+                int child = (k << 1) + 1;
+                ScheduledFutureTask c = queue[child];
+                int right = child + 1;
+                if (right < size && c.compareTo(queue[right]) > 0)
+                    c = queue[child = right];
+                if (key.compareTo(c) <= 0)
+                    break;
+                queue[k] = c;
+                setIndex(c, k);
+                k = child;
+            }
+            queue[k] = key;
+            setIndex(key, k);
         }
 
-        public int remainingCapacity() { return dq.remainingCapacity(); }
-        public boolean remove(Object x) { return dq.remove(x); }
-        public boolean contains(Object x) { return dq.contains(x); }
-        public int size() { return dq.size(); }
-        public boolean isEmpty() { return dq.isEmpty(); }
-        public Object[] toArray() { return dq.toArray(); }
-        public <T> T[] toArray(T[] array) { return dq.toArray(array); }
-        public Iterator<Runnable> iterator() { 
-            return new Iterator<Runnable>() {
-                private Iterator<ScheduledFutureTask> it = dq.iterator();
-                public boolean hasNext() { return it.hasNext(); }
-                public Runnable next() { return it.next(); }
-                public void remove() {  it.remove(); }
-            };
+        /**
+         * Resize the heap array.  Call only when holding lock.
+         */
+        private void grow() {
+            int oldCapacity = queue.length;
+            int newCapacity = oldCapacity + (oldCapacity >> 1); // grow 50%
+            if (newCapacity < 0) // overflow
+                newCapacity = Integer.MAX_VALUE;
+            queue = Java6Arrays.copyOf(queue, newCapacity);
+        }
+
+        /**
+         * Find index of given object, or -1 if absent
+         */
+        private int indexOf(Object x) {
+            if (x != null) {
+                if (x instanceof ScheduledFutureTask) {
+                    int i = ((ScheduledFutureTask) x).heapIndex;
+                    // Sanity check; x could conceivably be a
+                    // ScheduledFutureTask from some other pool.
+                    if (i >= 0 && i < size && queue[i] == x)
+                        return i;
+                } else {
+                    for (int i = 0; i < size; i++)
+                        if (x.equals(queue[i]))
+                            return i;
+                }
+            }
+            return -1;
+        }
+
+        public boolean contains(Object x) {
+            final ReentrantLock lock = this.lock;
+            lock.lock();
+            try {
+                return indexOf(x) != -1;
+            } finally {
+                lock.unlock();
+            }
+        }
+
+        public boolean remove(Object x) {
+            final ReentrantLock lock = this.lock;
+            lock.lock();
+            try {
+                int i = indexOf(x);
+                if (i < 0)
+                    return false;
+
+                setIndex(queue[i], -1);
+                int s = --size;
+                ScheduledFutureTask replacement = queue[s];
+                queue[s] = null;
+                if (s != i) {
+                    siftDown(i, replacement);
+                    if (queue[i] == replacement)
+                        siftUp(i, replacement);
+                }
+                return true;
+            } finally {
+                lock.unlock();
+            }
+        }
+
+        public int size() {
+            final ReentrantLock lock = this.lock;
+            lock.lock();
+            try {
+                return size;
+            } finally {
+                lock.unlock();
+            }
+        }
+
+        public boolean isEmpty() {
+            return size() == 0;
+        }
+
+        public int remainingCapacity() {
+            return Integer.MAX_VALUE;
+        }
+
+        public ScheduledFutureTask peek() {
+            final ReentrantLock lock = this.lock;
+            lock.lock();
+            try {
+                return queue[0];
+            } finally {
+                lock.unlock();
+            }
+        }
+
+        public boolean offer(Runnable x) {
+            if (x == null)
+                throw new NullPointerException();
+            ScheduledFutureTask e = (ScheduledFutureTask)x;
+            final ReentrantLock lock = this.lock;
+            lock.lock();
+            try {
+                int i = size;
+                if (i >= queue.length)
+                    grow();
+                size = i + 1;
+                if (i == 0) {
+                    queue[0] = e;
+                    setIndex(e, 0);
+                } else {
+                    siftUp(i, e);
+                }
+                if (queue[0] == e) {
+                    leader = null;
+                    available.signal();
+                }
+            } finally {
+                lock.unlock();
+            }
+            return true;
+        }
+
+        public void put(Runnable e) {
+            offer(e);
+        }
+
+        public boolean add(Runnable e) {
+            return offer(e);
+        }
+
+        public boolean offer(Runnable e, long timeout, TimeUnit unit) {
+            return offer(e);
+        }
+
+        /**
+         * Performs common bookkeeping for poll and take: Replaces
+         * first element with last and sifts it down.  Call only when
+         * holding lock.
+         * @param f the task to remove and return
+         */
+        private ScheduledFutureTask finishPoll(ScheduledFutureTask f) {
+            int s = --size;
+            ScheduledFutureTask x = queue[s];
+            queue[s] = null;
+            if (s != 0)
+                siftDown(0, x);
+            setIndex(f, -1);
+            return f;
+        }
+
+        public ScheduledFutureTask poll() {
+            final ReentrantLock lock = this.lock;
+            lock.lock();
+            try {
+                ScheduledFutureTask first = queue[0];
+                if (first == null || first.getDelay(TimeUnit.NANOSECONDS) > 0)
+                    return null;
+                else
+                    return finishPoll(first);
+            } finally {
+                lock.unlock();
+            }
+        }
+
+        public ScheduledFutureTask take() throws InterruptedException {
+            final ReentrantLock lock = this.lock;
+            lock.lockInterruptibly();
+            try {
+                for (;;) {
+                    ScheduledFutureTask first = queue[0];
+                    if (first == null)
+                        available.await();
+                    else {
+                        long delay = first.getDelay(TimeUnit.NANOSECONDS);
+                        if (delay <= 0)
+                            return finishPoll(first);
+                        else if (leader != null)
+                            available.await();
+                        else {
+                            Thread thisThread = Thread.currentThread();
+                            leader = thisThread;
+                            try {
+                                available.awaitNanos(delay);
+                            } finally {
+                                if (leader == thisThread)
+                                    leader = null;
+                            }
+                        }
+                    }
+                }
+            } finally {
+                if (leader == null && queue[0] != null)
+                    available.signal();
+                lock.unlock();
+            }
+        }
+
+        public ScheduledFutureTask poll(long timeout, TimeUnit unit)
+            throws InterruptedException {
+            long nanos = unit.toNanos(timeout);
+            final ReentrantLock lock = this.lock;
+            lock.lockInterruptibly();
+            try {
+                for (;;) {
+                    ScheduledFutureTask first = queue[0];
+                    if (first == null) {
+                        if (nanos <= 0)
+                            return null;
+                        else
+                            nanos = available.awaitNanos(nanos);
+                    } else {
+                        long delay = first.getDelay(TimeUnit.NANOSECONDS);
+                        if (delay <= 0)
+                            return finishPoll(first);
+                        if (nanos <= 0)
+                            return null;
+                        if (nanos < delay || leader != null)
+                            nanos = available.awaitNanos(nanos);
+                        else {
+                            Thread thisThread = Thread.currentThread();
+                            leader = thisThread;
+                            try {
+                                long timeLeft = available.awaitNanos(delay);
+                                nanos -= delay - timeLeft;
+                            } finally {
+                                if (leader == thisThread)
+                                    leader = null;
+                            }
+                        }
+                    }
+                }
+            } finally {
+                if (leader == null && queue[0] != null)
+                    available.signal();
+                lock.unlock();
+            }
+        }
+
+        public void clear() {
+            final ReentrantLock lock = this.lock;
+            lock.lock();
+            try {
+                for (int i = 0; i < size; i++) {
+                    ScheduledFutureTask t = queue[i];
+                    if (t != null) {
+                        queue[i] = null;
+                        setIndex(t, -1);
+                    }
+                }
+                size = 0;
+            } finally {
+                lock.unlock();
+            }
+        }
+
+        /**
+         * Return and remove first element only if it is expired.
+         * Used only by drainTo.  Call only when holding lock.
+         */
+        private ScheduledFutureTask pollExpired() {
+            ScheduledFutureTask first = queue[0];
+            if (first == null || first.getDelay(TimeUnit.NANOSECONDS) > 0)
+                return null;
+            return finishPoll(first);
+        }
+
+        public int drainTo(Collection<? super Runnable> c) {
+            if (c == null)
+                throw new NullPointerException();
+            if (c == this)
+                throw new IllegalArgumentException();
+            final ReentrantLock lock = this.lock;
+            lock.lock();
+            try {
+                ScheduledFutureTask first;
+                int n = 0;
+                while ((first = pollExpired()) != null) {
+                    c.add(first);
+                    ++n;
+                }
+                return n;
+            } finally {
+                lock.unlock();
+            }
+        }
+
+        public int drainTo(Collection<? super Runnable> c, int maxElements) {
+            if (c == null)
+                throw new NullPointerException();
+            if (c == this)
+                throw new IllegalArgumentException();
+            if (maxElements <= 0)
+                return 0;
+            final ReentrantLock lock = this.lock;
+            lock.lock();
+            try {
+                ScheduledFutureTask first;
+                int n = 0;
+                while (n < maxElements && (first = pollExpired()) != null) {
+                    c.add(first);
+                    ++n;
+                }
+                return n;
+            } finally {
+                lock.unlock();
+            }
+        }
+
+        public Object[] toArray() {
+            final ReentrantLock lock = this.lock;
+            lock.lock();
+            try {
+                return Java6Arrays.copyOf(queue, size, Object[].class);
+            } finally {
+                lock.unlock();
+            }
+        }
+
+        @SuppressWarnings("unchecked")
+        public <T> T[] toArray(T[] a) {
+            final ReentrantLock lock = this.lock;
+            lock.lock();
+            try {
+                if (a.length < size)
+                    return (T[]) Java6Arrays.copyOf(queue, size, a.getClass());
+                System.arraycopy(queue, 0, a, 0, size);
+                if (a.length > size)
+                    a[size] = null;
+                return a;
+            } finally {
+                lock.unlock();
+            }
+        }
+
+        public Iterator<Runnable> iterator() {
+            return new Itr(Java6Arrays.copyOf(queue, size));
+        }
+
+        /**
+         * Snapshot iterator that works off copy of underlying q array.
+         */
+        private class Itr implements Iterator<Runnable> {
+            final ScheduledFutureTask[] array;
+            int cursor = 0;     // index of next element to return
+            int lastRet = -1;   // index of last element, or -1 if no such
+
+            Itr(ScheduledFutureTask[] array) {
+                this.array = array;
+            }
+
+            public boolean hasNext() {
+                return cursor < array.length;
+            }
+
+            public Runnable next() {
+                if (cursor >= array.length)
+                    throw new NoSuchElementException();
+                lastRet = cursor;
+                return array[cursor++];
+            }
+
+            public void remove() {
+                if (lastRet < 0)
+                    throw new IllegalStateException();
+                DelayedWorkQueue.this.remove(array[lastRet]);
+                lastRet = -1;
+            }
         }
     }
 }
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/Semaphore.java b/libcore/concurrent/src/main/java/java/util/concurrent/Semaphore.java
index 6eb80bc..1052364 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/Semaphore.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/Semaphore.java
@@ -14,7 +14,7 @@
  * permits.  Each {@link #acquire} blocks if necessary until a permit is
  * available, and then takes it.  Each {@link #release} adds a permit,
  * potentially releasing a blocking acquirer.
- * However, no actual permit objects are used; the <tt>Semaphore</tt> just
+ * However, no actual permit objects are used; the {@code Semaphore} just
  * keeps a count of the number available and acts accordingly.
  *
  * <p>Semaphores are often used to restrict the number of threads than can
@@ -22,7 +22,7 @@
  * a class that uses a semaphore to control access to a pool of items:
  * <pre>
  * class Pool {
- *   private static final MAX_AVAILABLE = 100;
+ *   private static final int MAX_AVAILABLE = 100;
  *   private final Semaphore available = new Semaphore(MAX_AVAILABLE, true);
  *
  *   public Object getItem() throws InterruptedException {
@@ -93,15 +93,19 @@
  * guarantees about the order in which threads acquire permits. In
  * particular, <em>barging</em> is permitted, that is, a thread
  * invoking {@link #acquire} can be allocated a permit ahead of a
- * thread that has been waiting.  When fairness is set true, the
+ * thread that has been waiting - logically the new thread places itself at
+ * the head of the queue of waiting threads. When fairness is set true, the
  * semaphore guarantees that threads invoking any of the {@link
- * #acquire() acquire} methods are allocated permits in the order in
+ * #acquire() acquire} methods are selected to obtain permits in the order in
  * which their invocation of those methods was processed
  * (first-in-first-out; FIFO). Note that FIFO ordering necessarily
  * applies to specific internal points of execution within these
  * methods.  So, it is possible for one thread to invoke
- * <tt>acquire</tt> before another, but reach the ordering point after
+ * {@code acquire} before another, but reach the ordering point after
  * the other, and similarly upon return from the method.
+ * Also note that the untimed {@link #tryAcquire() tryAcquire} methods do not
+ * honor the fairness setting, but will take any permits that are
+ * available.
  *
  * <p>Generally, semaphores used to control resource access should be
  * initialized as fair, to ensure that no thread is starved out from
@@ -114,6 +118,12 @@
  * permits at a time.  Beware of the increased risk of indefinite
  * postponement when these methods are used without fairness set true.
  *
+ * <p>Memory consistency effects: Actions in a thread prior to calling
+ * a "release" method such as {@code release()}
+ * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
+ * actions following a successful "acquire" method such as {@code acquire()}
+ * in another thread.
+ *
  * @since 1.5
  * @author Doug Lea
  *
@@ -130,10 +140,12 @@
      * versions.
      */
     abstract static class Sync extends AbstractQueuedSynchronizer {
+        private static final long serialVersionUID = 1192457210091910933L;
+
         Sync(int permits) {
             setState(permits);
         }
-        
+
         final int getPermits() {
             return getState();
         }
@@ -147,11 +159,11 @@
                     return remaining;
             }
         }
-        
+
         protected final boolean tryReleaseShared(int releases) {
             for (;;) {
                 int p = getState();
-                if (compareAndSetState(p, p + releases)) 
+                if (compareAndSetState(p, p + releases))
                     return true;
             }
         }
@@ -178,10 +190,12 @@
      * NonFair version
      */
     final static class NonfairSync extends Sync {
+        private static final long serialVersionUID = -2694183684443567898L;
+
         NonfairSync(int permits) {
             super(permits);
         }
-       
+
         protected int tryAcquireShared(int acquires) {
             return nonfairTryAcquireShared(acquires);
         }
@@ -191,10 +205,12 @@
      * Fair version
      */
     final static class FairSync extends Sync {
+        private static final long serialVersionUID = 2014338818796000944L;
+
         FairSync(int permits) {
             super(permits);
         }
-        
+
         protected int tryAcquireShared(int acquires) {
             Thread current = Thread.currentThread();
             for (;;) {
@@ -211,57 +227,59 @@
     }
 
     /**
-     * Creates a <tt>Semaphore</tt> with the given number of
+     * Creates a {@code Semaphore} with the given number of
      * permits and nonfair fairness setting.
-     * @param permits the initial number of permits available. This
-     * value may be negative, in which case releases must
-     * occur before any acquires will be granted.
+     *
+     * @param permits the initial number of permits available.
+     *        This value may be negative, in which case releases
+     *        must occur before any acquires will be granted.
      */
-    public Semaphore(int permits) { 
+    public Semaphore(int permits) {
         sync = new NonfairSync(permits);
     }
 
     /**
-     * Creates a <tt>Semaphore</tt> with the given number of
+     * Creates a {@code Semaphore} with the given number of
      * permits and the given fairness setting.
-     * @param permits the initial number of permits available. This
-     * value may be negative, in which case releases must
-     * occur before any acquires will be granted.
-     * @param fair true if this semaphore will guarantee first-in
-     * first-out granting of permits under contention, else false.
+     *
+     * @param permits the initial number of permits available.
+     *        This value may be negative, in which case releases
+     *        must occur before any acquires will be granted.
+     * @param fair {@code true} if this semaphore will guarantee
+     *        first-in first-out granting of permits under contention,
+     *        else {@code false}
      */
-    public Semaphore(int permits, boolean fair) { 
+    public Semaphore(int permits, boolean fair) {
         sync = (fair)? new FairSync(permits) : new NonfairSync(permits);
     }
 
     /**
      * Acquires a permit from this semaphore, blocking until one is
-     * available, or the thread is {@link Thread#interrupt interrupted}.
+     * available, or the thread is {@linkplain Thread#interrupt interrupted}.
      *
      * <p>Acquires a permit, if one is available and returns immediately,
      * reducing the number of available permits by one.
+     *
      * <p>If no permit is available then the current thread becomes
      * disabled for thread scheduling purposes and lies dormant until
      * one of two things happens:
      * <ul>
      * <li>Some other thread invokes the {@link #release} method for this
      * semaphore and the current thread is next to be assigned a permit; or
-     * <li>Some other thread {@link Thread#interrupt interrupts} the current
-     * thread.
+     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+     * the current thread.
      * </ul>
      *
      * <p>If the current thread:
      * <ul>
      * <li>has its interrupted status set on entry to this method; or
-     * <li>is {@link Thread#interrupt interrupted} while waiting
+     * <li>is {@linkplain Thread#interrupt interrupted} while waiting
      * for a permit,
      * </ul>
      * then {@link InterruptedException} is thrown and the current thread's
      * interrupted status is cleared.
      *
      * @throws InterruptedException if the current thread is interrupted
-     *
-     * @see Thread#interrupt
      */
     public void acquire() throws InterruptedException {
         sync.acquireSharedInterruptibly(1);
@@ -273,103 +291,105 @@
      *
      * <p>Acquires a permit, if one is available and returns immediately,
      * reducing the number of available permits by one.
+     *
      * <p>If no permit is available then the current thread becomes
      * disabled for thread scheduling purposes and lies dormant until
      * some other thread invokes the {@link #release} method for this
      * semaphore and the current thread is next to be assigned a permit.
      *
-     * <p>If the current thread
-     * is {@link Thread#interrupt interrupted} while waiting
-     * for a permit then it will continue to wait, but the time at which
-     * the thread is assigned a permit may change compared to the time it
-     * would have received the permit had no interruption occurred. When the
-     * thread does return from this method its interrupt status will be set.
-     *
+     * <p>If the current thread is {@linkplain Thread#interrupt interrupted}
+     * while waiting for a permit then it will continue to wait, but the
+     * time at which the thread is assigned a permit may change compared to
+     * the time it would have received the permit had no interruption
+     * occurred.  When the thread does return from this method its interrupt
+     * status will be set.
      */
     public void acquireUninterruptibly() {
         sync.acquireShared(1);
     }
 
     /**
-     * Acquires a permit from this semaphore, only if one is available at the 
+     * Acquires a permit from this semaphore, only if one is available at the
      * time of invocation.
+     *
      * <p>Acquires a permit, if one is available and returns immediately,
-     * with the value <tt>true</tt>,
+     * with the value {@code true},
      * reducing the number of available permits by one.
      *
      * <p>If no permit is available then this method will return
-     * immediately with the value <tt>false</tt>.
+     * immediately with the value {@code false}.
      *
      * <p>Even when this semaphore has been set to use a
-     * fair ordering policy, a call to <tt>tryAcquire()</tt> <em>will</em>
+     * fair ordering policy, a call to {@code tryAcquire()} <em>will</em>
      * immediately acquire a permit if one is available, whether or not
-     * other threads are currently waiting. 
-     * This &quot;barging&quot; behavior can be useful in certain 
+     * other threads are currently waiting.
+     * This &quot;barging&quot; behavior can be useful in certain
      * circumstances, even though it breaks fairness. If you want to honor
-     * the fairness setting, then use 
+     * the fairness setting, then use
      * {@link #tryAcquire(long, TimeUnit) tryAcquire(0, TimeUnit.SECONDS) }
      * which is almost equivalent (it also detects interruption).
      *
-     * @return <tt>true</tt> if a permit was acquired and <tt>false</tt>
-     * otherwise.
+     * @return {@code true} if a permit was acquired and {@code false}
+     *         otherwise
      */
     public boolean tryAcquire() {
         return sync.nonfairTryAcquireShared(1) >= 0;
     }
 
     /**
-     * Acquires a permit from this semaphore, if one becomes available 
-     * within the given waiting time and the
-     * current thread has not been {@link Thread#interrupt interrupted}.
+     * Acquires a permit from this semaphore, if one becomes available
+     * within the given waiting time and the current thread has not
+     * been {@linkplain Thread#interrupt interrupted}.
+     *
      * <p>Acquires a permit, if one is available and returns immediately,
-     * with the value <tt>true</tt>,
+     * with the value {@code true},
      * reducing the number of available permits by one.
-     * <p>If no permit is available then
-     * the current thread becomes disabled for thread scheduling
-     * purposes and lies dormant until one of three things happens:
+     *
+     * <p>If no permit is available then the current thread becomes
+     * disabled for thread scheduling purposes and lies dormant until
+     * one of three things happens:
      * <ul>
      * <li>Some other thread invokes the {@link #release} method for this
      * semaphore and the current thread is next to be assigned a permit; or
-     * <li>Some other thread {@link Thread#interrupt interrupts} the current
-     * thread; or
+     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+     * the current thread; or
      * <li>The specified waiting time elapses.
      * </ul>
-     * <p>If a permit is acquired then the value <tt>true</tt> is returned.
+     *
+     * <p>If a permit is acquired then the value {@code true} is returned.
+     *
      * <p>If the current thread:
      * <ul>
      * <li>has its interrupted status set on entry to this method; or
-     * <li>is {@link Thread#interrupt interrupted} while waiting to acquire
-     * a permit,
+     * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+     * to acquire a permit,
      * </ul>
      * then {@link InterruptedException} is thrown and the current thread's
      * interrupted status is cleared.
-     * <p>If the specified waiting time elapses then the value <tt>false</tt>
-     * is returned.
-     * If the time is less than or equal to zero, the method will not wait 
-     * at all.
+     *
+     * <p>If the specified waiting time elapses then the value {@code false}
+     * is returned.  If the time is less than or equal to zero, the method
+     * will not wait at all.
      *
      * @param timeout the maximum time to wait for a permit
-     * @param unit the time unit of the <tt>timeout</tt> argument.
-     * @return <tt>true</tt> if a permit was acquired and <tt>false</tt>
-     * if the waiting time elapsed before a permit was acquired.
-     *
+     * @param unit the time unit of the {@code timeout} argument
+     * @return {@code true} if a permit was acquired and {@code false}
+     *         if the waiting time elapsed before a permit was acquired
      * @throws InterruptedException if the current thread is interrupted
-     *
-     * @see Thread#interrupt
-     *
      */
-    public boolean tryAcquire(long timeout, TimeUnit unit) 
+    public boolean tryAcquire(long timeout, TimeUnit unit)
         throws InterruptedException {
         return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
     }
 
     /**
      * Releases a permit, returning it to the semaphore.
-     * <p>Releases a permit, increasing the number of available permits
-     * by one.
-     * If any threads are blocking trying to acquire a permit, then one
-     * is selected and given the permit that was just released.
-     * That thread is re-enabled for thread scheduling purposes.
+     *
+     * <p>Releases a permit, increasing the number of available permits by
+     * one.  If any threads are trying to acquire a permit, then one is
+     * selected and given the permit that was just released.  That thread
+     * is (re)enabled for thread scheduling purposes.
+     *
      * <p>There is no requirement that a thread that releases a permit must
      * have acquired that permit by calling {@link #acquire}.
      * Correct usage of a semaphore is established by programming convention
@@ -378,45 +398,42 @@
     public void release() {
         sync.releaseShared(1);
     }
-       
+
     /**
-     * Acquires the given number of permits from this semaphore, 
-     * blocking until all are available, 
-     * or the thread is {@link Thread#interrupt interrupted}.
+     * Acquires the given number of permits from this semaphore,
+     * blocking until all are available,
+     * or the thread is {@linkplain Thread#interrupt interrupted}.
      *
      * <p>Acquires the given number of permits, if they are available,
-     * and returns immediately,
-     * reducing the number of available permits by the given amount.
+     * and returns immediately, reducing the number of available permits
+     * by the given amount.
      *
      * <p>If insufficient permits are available then the current thread becomes
      * disabled for thread scheduling purposes and lies dormant until
      * one of two things happens:
      * <ul>
-     * <li>Some other thread invokes one of the {@link #release() release} 
+     * <li>Some other thread invokes one of the {@link #release() release}
      * methods for this semaphore, the current thread is next to be assigned
      * permits and the number of available permits satisfies this request; or
-     * <li>Some other thread {@link Thread#interrupt interrupts} the current
-     * thread.
+     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+     * the current thread.
      * </ul>
      *
      * <p>If the current thread:
      * <ul>
      * <li>has its interrupted status set on entry to this method; or
-     * <li>is {@link Thread#interrupt interrupted} while waiting
+     * <li>is {@linkplain Thread#interrupt interrupted} while waiting
      * for a permit,
      * </ul>
      * then {@link InterruptedException} is thrown and the current thread's
-     * interrupted status is cleared. 
-     * Any permits that were to be assigned to this thread are instead 
-     * assigned to the next waiting thread(s), as if
-     * they had been made available by a call to {@link #release()}.
+     * interrupted status is cleared.
+     * Any permits that were to be assigned to this thread are instead
+     * assigned to other threads trying to acquire permits, as if
+     * permits had been made available by a call to {@link #release()}.
      *
      * @param permits the number of permits to acquire
-     *
      * @throws InterruptedException if the current thread is interrupted
-     * @throws IllegalArgumentException if permits less than zero.
-     *
-     * @see Thread#interrupt
+     * @throws IllegalArgumentException if {@code permits} is negative
      */
     public void acquire(int permits) throws InterruptedException {
         if (permits < 0) throw new IllegalArgumentException();
@@ -424,27 +441,26 @@
     }
 
     /**
-     * Acquires the given number of permits from this semaphore, 
+     * Acquires the given number of permits from this semaphore,
      * blocking until all are available.
      *
      * <p>Acquires the given number of permits, if they are available,
-     * and returns immediately,
-     * reducing the number of available permits by the given amount.
+     * and returns immediately, reducing the number of available permits
+     * by the given amount.
      *
      * <p>If insufficient permits are available then the current thread becomes
      * disabled for thread scheduling purposes and lies dormant until
-     * some other thread invokes one of the {@link #release() release} 
+     * some other thread invokes one of the {@link #release() release}
      * methods for this semaphore, the current thread is next to be assigned
      * permits and the number of available permits satisfies this request.
      *
-     * <p>If the current thread
-     * is {@link Thread#interrupt interrupted} while waiting
-     * for permits then it will continue to wait and its position in the
-     * queue is not affected. When the
-     * thread does return from this method its interrupt status will be set.
+     * <p>If the current thread is {@linkplain Thread#interrupt interrupted}
+     * while waiting for permits then it will continue to wait and its
+     * position in the queue is not affected.  When the thread does return
+     * from this method its interrupt status will be set.
      *
      * @param permits the number of permits to acquire
-     * @throws IllegalArgumentException if permits less than zero.
+     * @throws IllegalArgumentException if {@code permits} is negative
      *
      */
     public void acquireUninterruptibly(int permits) {
@@ -456,16 +472,16 @@
      * Acquires the given number of permits from this semaphore, only
      * if all are available at the time of invocation.
      *
-     * <p>Acquires the given number of permits, if they are available, and 
-     * returns immediately, with the value <tt>true</tt>,
+     * <p>Acquires the given number of permits, if they are available, and
+     * returns immediately, with the value {@code true},
      * reducing the number of available permits by the given amount.
      *
      * <p>If insufficient permits are available then this method will return
-     * immediately with the value <tt>false</tt> and the number of available
+     * immediately with the value {@code false} and the number of available
      * permits is unchanged.
      *
      * <p>Even when this semaphore has been set to use a fair ordering
-     * policy, a call to <tt>tryAcquire</tt> <em>will</em>
+     * policy, a call to {@code tryAcquire} <em>will</em>
      * immediately acquire a permit if one is available, whether or
      * not other threads are currently waiting.  This
      * &quot;barging&quot; behavior can be useful in certain
@@ -475,10 +491,9 @@
      * which is almost equivalent (it also detects interruption).
      *
      * @param permits the number of permits to acquire
-     *
-     * @return <tt>true</tt> if the permits were acquired and <tt>false</tt>
-     * otherwise.
-     * @throws IllegalArgumentException if permits less than zero.
+     * @return {@code true} if the permits were acquired and
+     *         {@code false} otherwise
+     * @throws IllegalArgumentException if {@code permits} is negative
      */
     public boolean tryAcquire(int permits) {
         if (permits < 0) throw new IllegalArgumentException();
@@ -486,55 +501,54 @@
     }
 
     /**
-     * Acquires the given number of permits from this semaphore, if all 
-     * become available within the given waiting time and the
-     * current thread has not been {@link Thread#interrupt interrupted}.
-     * <p>Acquires the given number of permits, if they are available and 
-     * returns immediately, with the value <tt>true</tt>,
+     * Acquires the given number of permits from this semaphore, if all
+     * become available within the given waiting time and the current
+     * thread has not been {@linkplain Thread#interrupt interrupted}.
+     *
+     * <p>Acquires the given number of permits, if they are available and
+     * returns immediately, with the value {@code true},
      * reducing the number of available permits by the given amount.
+     *
      * <p>If insufficient permits are available then
      * the current thread becomes disabled for thread scheduling
      * purposes and lies dormant until one of three things happens:
      * <ul>
-     * <li>Some other thread invokes one of the {@link #release() release} 
+     * <li>Some other thread invokes one of the {@link #release() release}
      * methods for this semaphore, the current thread is next to be assigned
      * permits and the number of available permits satisfies this request; or
-     * <li>Some other thread {@link Thread#interrupt interrupts} the current
-     * thread; or
+     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+     * the current thread; or
      * <li>The specified waiting time elapses.
      * </ul>
-     * <p>If the permits are acquired then the value <tt>true</tt> is returned.
+     *
+     * <p>If the permits are acquired then the value {@code true} is returned.
+     *
      * <p>If the current thread:
      * <ul>
      * <li>has its interrupted status set on entry to this method; or
-     * <li>is {@link Thread#interrupt interrupted} while waiting to acquire
-     * the permits,
+     * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+     * to acquire the permits,
      * </ul>
      * then {@link InterruptedException} is thrown and the current thread's
      * interrupted status is cleared.
-     * Any permits that were to be assigned to this thread, are instead 
-     * assigned to the next waiting thread(s), as if
-     * they had been made available by a call to {@link #release()}.
+     * Any permits that were to be assigned to this thread, are instead
+     * assigned to other threads trying to acquire permits, as if
+     * the permits had been made available by a call to {@link #release()}.
      *
-     * <p>If the specified waiting time elapses then the value <tt>false</tt>
-     * is returned.
-     * If the time is
-     * less than or equal to zero, the method will not wait at all.
-     * Any permits that were to be assigned to this thread, are instead 
-     * assigned to the next waiting thread(s), as if
-     * they had been made available by a call to {@link #release()}.
+     * <p>If the specified waiting time elapses then the value {@code false}
+     * is returned.  If the time is less than or equal to zero, the method
+     * will not wait at all.  Any permits that were to be assigned to this
+     * thread, are instead assigned to other threads trying to acquire
+     * permits, as if the permits had been made available by a call to
+     * {@link #release()}.
      *
      * @param permits the number of permits to acquire
      * @param timeout the maximum time to wait for the permits
-     * @param unit the time unit of the <tt>timeout</tt> argument.
-     * @return <tt>true</tt> if all permits were acquired and <tt>false</tt>
-     * if the waiting time elapsed before all permits were acquired.
-     *
+     * @param unit the time unit of the {@code timeout} argument
+     * @return {@code true} if all permits were acquired and {@code false}
+     *         if the waiting time elapsed before all permits were acquired
      * @throws InterruptedException if the current thread is interrupted
-     * @throws IllegalArgumentException if permits less than zero.
-     *
-     * @see Thread#interrupt
-     *
+     * @throws IllegalArgumentException if {@code permits} is negative
      */
     public boolean tryAcquire(int permits, long timeout, TimeUnit unit)
         throws InterruptedException {
@@ -544,19 +558,17 @@
 
     /**
      * Releases the given number of permits, returning them to the semaphore.
-     * <p>Releases the given number of permits, increasing the number of 
+     *
+     * <p>Releases the given number of permits, increasing the number of
      * available permits by that amount.
-     * If any threads are blocking trying to acquire permits, then the
-     * one that has been waiting the longest
+     * If any threads are trying to acquire permits, then one
      * is selected and given the permits that were just released.
      * If the number of available permits satisfies that thread's request
-     * then that thread is re-enabled for thread scheduling purposes; otherwise
-     * the thread continues to wait. If there are still permits available
-     * after the first thread's request has been satisfied, then those permits
-     * are assigned to the next waiting thread. If it is satisfied then it is
-     * re-enabled for thread scheduling purposes. This continues until there
-     * are insufficient permits to satisfy the next waiting thread, or there
-     * are no more waiting threads.
+     * then that thread is (re)enabled for thread scheduling purposes;
+     * otherwise the thread will wait until sufficient permits are available.
+     * If there are still permits available
+     * after this thread's request has been satisfied, then those permits
+     * are assigned in turn to other threads trying to acquire permits.
      *
      * <p>There is no requirement that a thread that releases a permit must
      * have acquired that permit by calling {@link Semaphore#acquire acquire}.
@@ -564,7 +576,7 @@
      * in the application.
      *
      * @param permits the number of permits to release
-     * @throws IllegalArgumentException if permits less than zero.
+     * @throws IllegalArgumentException if {@code permits} is negative
      */
     public void release(int permits) {
         if (permits < 0) throw new IllegalArgumentException();
@@ -573,16 +585,19 @@
 
     /**
      * Returns the current number of permits available in this semaphore.
+     *
      * <p>This method is typically used for debugging and testing purposes.
-     * @return the number of permits available in this semaphore.
+     *
+     * @return the number of permits available in this semaphore
      */
     public int availablePermits() {
         return sync.getPermits();
     }
 
     /**
-     * Acquire and return all permits that are immediately available.
-     * @return the number of permits 
+     * Acquires and returns all permits that are immediately available.
+     *
+     * @return the number of permits acquired
      */
     public int drainPermits() {
         return sync.drainPermits();
@@ -592,19 +607,21 @@
      * Shrinks the number of available permits by the indicated
      * reduction. This method can be useful in subclasses that use
      * semaphores to track resources that become unavailable. This
-     * method differs from <tt>acquire</tt> in that it does not block
+     * method differs from {@code acquire} in that it does not block
      * waiting for permits to become available.
+     *
      * @param reduction the number of permits to remove
-     * @throws IllegalArgumentException if reduction is negative
+     * @throws IllegalArgumentException if {@code reduction} is negative
      */
     protected void reducePermits(int reduction) {
-    if (reduction < 0) throw new IllegalArgumentException();
+        if (reduction < 0) throw new IllegalArgumentException();
         sync.reducePermits(reduction);
     }
 
     /**
-     * Returns true if this semaphore has fairness set true.
-     * @return true if this semaphore has fairness set true.
+     * Returns {@code true} if this semaphore has fairness set true.
+     *
+     * @return {@code true} if this semaphore has fairness set true
      */
     public boolean isFair() {
         return sync instanceof FairSync;
@@ -612,25 +629,25 @@
 
     /**
      * Queries whether any threads are waiting to acquire. Note that
-     * because cancellations may occur at any time, a <tt>true</tt>
+     * because cancellations may occur at any time, a {@code true}
      * return does not guarantee that any other thread will ever
      * acquire.  This method is designed primarily for use in
      * monitoring of the system state.
      *
-     * @return true if there may be other threads waiting to acquire
-     * the lock.
+     * @return {@code true} if there may be other threads waiting to
+     *         acquire the lock
      */
-    public final boolean hasQueuedThreads() { 
+    public final boolean hasQueuedThreads() {
         return sync.hasQueuedThreads();
     }
 
     /**
-     * Returns an estimate of the number of threads waiting to
-     * acquire.  The value is only an estimate because the number of
-     * threads may change dynamically while this method traverses
-     * internal data structures.  This method is designed for use in
-     * monitoring of the system state, not for synchronization
-     * control.
+     * Returns an estimate of the number of threads waiting to acquire.
+     * The value is only an estimate because the number of threads may
+     * change dynamically while this method traverses internal data
+     * structures.  This method is designed for use in monitoring of the
+     * system state, not for synchronization control.
+     *
      * @return the estimated number of threads waiting for this lock
      */
     public final int getQueueLength() {
@@ -638,13 +655,13 @@
     }
 
     /**
-     * Returns a collection containing threads that may be waiting to
-     * acquire.  Because the actual set of threads may change
-     * dynamically while constructing this result, the returned
-     * collection is only a best-effort estimate.  The elements of the
-     * returned collection are in no particular order.  This method is
-     * designed to facilitate construction of subclasses that provide
-     * more extensive monitoring facilities.
+     * Returns a collection containing threads that may be waiting to acquire.
+     * Because the actual set of threads may change dynamically while
+     * constructing this result, the returned collection is only a best-effort
+     * estimate.  The elements of the returned collection are in no particular
+     * order.  This method is designed to facilitate construction of
+     * subclasses that provide more extensive monitoring facilities.
+     *
      * @return the collection of threads
      */
     protected Collection<Thread> getQueuedThreads() {
@@ -653,13 +670,12 @@
 
     /**
      * Returns a string identifying this semaphore, as well as its state.
-     * The state, in brackets, includes the String 
-     * &quot;Permits =&quot; followed by the number of permits.
-     * @return a string identifying this semaphore, as well as its
-     * state
+     * The state, in brackets, includes the String {@code "Permits ="}
+     * followed by the number of permits.
+     *
+     * @return a string identifying this semaphore, as well as its state
      */
     public String toString() {
         return super.toString() + "[Permits = " + sync.getPermits() + "]";
     }
-
 }
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/SynchronousQueue.java b/libcore/concurrent/src/main/java/java/util/concurrent/SynchronousQueue.java
index b8d3536..0d297ff 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/SynchronousQueue.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/SynchronousQueue.java
@@ -1,11 +1,13 @@
 /*
- * Written by Doug Lea with assistance from members of JCP JSR-166
- * Expert Group and released to the public domain, as explained at
+ * Written by Doug Lea, Bill Scherer, and Michael Scott with
+ * assistance from members of JCP JSR-166 Expert Group and released to
+ * the public domain, as explained at
  * http://creativecommons.org/licenses/publicdomain
  */
 
 package java.util.concurrent;
 import java.util.concurrent.locks.*;
+import java.util.concurrent.atomic.*;
 import java.util.*;
 
 // BEGIN android-note
@@ -13,20 +15,21 @@
 // END android-note
 
 /**
- * A {@linkplain BlockingQueue blocking queue} in which each
- * <tt>put</tt> must wait for a <tt>take</tt>, and vice versa.  A
- * synchronous queue does not have any internal capacity, not even a
- * capacity of one. You cannot <tt>peek</tt> at a synchronous queue
- * because an element is only present when you try to take it; you
- * cannot add an element (using any method) unless another thread is
- * trying to remove it; you cannot iterate as there is nothing to
- * iterate.  The <em>head</em> of the queue is the element that the
- * first queued thread is trying to add to the queue; if there are no
- * queued threads then no element is being added and the head is
- * <tt>null</tt>.  For purposes of other <tt>Collection</tt> methods
- * (for example <tt>contains</tt>), a <tt>SynchronousQueue</tt> acts
- * as an empty collection.  This queue does not permit <tt>null</tt>
- * elements.
+ * A {@linkplain BlockingQueue blocking queue} in which each insert
+ * operation must wait for a corresponding remove operation by another
+ * thread, and vice versa.  A synchronous queue does not have any
+ * internal capacity, not even a capacity of one.  You cannot
+ * <tt>peek</tt> at a synchronous queue because an element is only
+ * present when you try to remove it; you cannot insert an element
+ * (using any method) unless another thread is trying to remove it;
+ * you cannot iterate as there is nothing to iterate.  The
+ * <em>head</em> of the queue is the element that the first queued
+ * inserting thread is trying to add to the queue; if there is no such
+ * queued thread then no element is available for removal and
+ * <tt>poll()</tt> will return <tt>null</tt>.  For purposes of other
+ * <tt>Collection</tt> methods (for example <tt>contains</tt>), a
+ * <tt>SynchronousQueue</tt> acts as an empty collection.  This queue
+ * does not permit <tt>null</tt> elements.
  *
  * <p>Synchronous queues are similar to rendezvous channels used in
  * CSP and Ada. They are well suited for handoff designs, in which an
@@ -37,52 +40,746 @@
  * <p> This class supports an optional fairness policy for ordering
  * waiting producer and consumer threads.  By default, this ordering
  * is not guaranteed. However, a queue constructed with fairness set
- * to <tt>true</tt> grants threads access in FIFO order. Fairness
- * generally decreases throughput but reduces variability and avoids
- * starvation.
+ * to <tt>true</tt> grants threads access in FIFO order.
  *
- * <p>This class implements all of the <em>optional</em> methods
- * of the {@link Collection} and {@link Iterator} interfaces.
+ * <p>This class and its iterator implement all of the
+ * <em>optional</em> methods of the {@link Collection} and {@link
+ * Iterator} interfaces.
  *
  * @since 1.5
- * @author Doug Lea
+ * @author Doug Lea and Bill Scherer and Michael Scott
  * @param <E> the type of elements held in this collection
  */
 public class SynchronousQueue<E> extends AbstractQueue<E>
-        implements BlockingQueue<E>, java.io.Serializable {
+    implements BlockingQueue<E>, java.io.Serializable {
     private static final long serialVersionUID = -3223113410248163686L;
 
     /*
-      This implementation divides actions into two cases for puts:
+     * This class implements extensions of the dual stack and dual
+     * queue algorithms described in "Nonblocking Concurrent Objects
+     * with Condition Synchronization", by W. N. Scherer III and
+     * M. L. Scott.  18th Annual Conf. on Distributed Computing,
+     * Oct. 2004 (see also
+     * http://www.cs.rochester.edu/u/scott/synchronization/pseudocode/duals.html).
+     * The (Lifo) stack is used for non-fair mode, and the (Fifo)
+     * queue for fair mode. The performance of the two is generally
+     * similar. Fifo usually supports higher throughput under
+     * contention but Lifo maintains higher thread locality in common
+     * applications.
+     *
+     * A dual queue (and similarly stack) is one that at any given
+     * time either holds "data" -- items provided by put operations,
+     * or "requests" -- slots representing take operations, or is
+     * empty. A call to "fulfill" (i.e., a call requesting an item
+     * from a queue holding data or vice versa) dequeues a
+     * complementary node.  The most interesting feature of these
+     * queues is that any operation can figure out which mode the
+     * queue is in, and act accordingly without needing locks.
+     *
+     * Both the queue and stack extend abstract class Transferer
+     * defining the single method transfer that does a put or a
+     * take. These are unified into a single method because in dual
+     * data structures, the put and take operations are symmetrical,
+     * so nearly all code can be combined. The resulting transfer
+     * methods are on the long side, but are easier to follow than
+     * they would be if broken up into nearly-duplicated parts.
+     *
+     * The queue and stack data structures share many conceptual
+     * similarities but very few concrete details. For simplicity,
+     * they are kept distinct so that they can later evolve
+     * separately.
+     *
+     * The algorithms here differ from the versions in the above paper
+     * in extending them for use in synchronous queues, as well as
+     * dealing with cancellation. The main differences include:
+     *
+     *  1. The original algorithms used bit-marked pointers, but
+     *     the ones here use mode bits in nodes, leading to a number
+     *     of further adaptations.
+     *  2. SynchronousQueues must block threads waiting to become
+     *     fulfilled.
+     *  3. Support for cancellation via timeout and interrupts,
+     *     including cleaning out cancelled nodes/threads
+     *     from lists to avoid garbage retention and memory depletion.
+     *
+     * Blocking is mainly accomplished using LockSupport park/unpark,
+     * except that nodes that appear to be the next ones to become
+     * fulfilled first spin a bit (on multiprocessors only). On very
+     * busy synchronous queues, spinning can dramatically improve
+     * throughput. And on less busy ones, the amount of spinning is
+     * small enough not to be noticeable.
+     *
+     * Cleaning is done in different ways in queues vs stacks.  For
+     * queues, we can almost always remove a node immediately in O(1)
+     * time (modulo retries for consistency checks) when it is
+     * cancelled. But if it may be pinned as the current tail, it must
+     * wait until some subsequent cancellation. For stacks, we need a
+     * potentially O(n) traversal to be sure that we can remove the
+     * node, but this can run concurrently with other threads
+     * accessing the stack.
+     *
+     * While garbage collection takes care of most node reclamation
+     * issues that otherwise complicate nonblocking algorithms, care
+     * is taken to "forget" references to data, other nodes, and
+     * threads that might be held on to long-term by blocked
+     * threads. In cases where setting to null would otherwise
+     * conflict with main algorithms, this is done by changing a
+     * node's link to now point to the node itself. This doesn't arise
+     * much for Stack nodes (because blocked threads do not hang on to
+     * old head pointers), but references in Queue nodes must be
+     * aggressively forgotten to avoid reachability of everything any
+     * node has ever referred to since arrival.
+     */
 
-      * An arriving producer that does not already have a waiting consumer
-      creates a node holding item, and then waits for a consumer to take it.
-      * An arriving producer that does already have a waiting consumer fills
-      the slot node created by the consumer, and notifies it to continue.
+    /**
+     * Shared internal API for dual stacks and queues.
+     */
+    static abstract class Transferer {
+        /**
+         * Performs a put or take.
+         *
+         * @param e if non-null, the item to be handed to a consumer;
+         *          if null, requests that transfer return an item
+         *          offered by producer.
+         * @param timed if this operation should timeout
+         * @param nanos the timeout, in nanoseconds
+         * @return if non-null, the item provided or received; if null,
+         *         the operation failed due to timeout or interrupt --
+         *         the caller can distinguish which of these occurred
+         *         by checking Thread.interrupted.
+         */
+        abstract Object transfer(Object e, boolean timed, long nanos);
+    }
 
-      And symmetrically, two for takes:
+    /** The number of CPUs, for spin control */
+    static final int NCPUS = Runtime.getRuntime().availableProcessors();
 
-      * An arriving consumer that does not already have a waiting producer
-      creates an empty slot node, and then waits for a producer to fill it.
-      * An arriving consumer that does already have a waiting producer takes
-      item from the node created by the producer, and notifies it to continue.
+    /**
+     * The number of times to spin before blocking in timed waits.
+     * The value is empirically derived -- it works well across a
+     * variety of processors and OSes. Empirically, the best value
+     * seems not to vary with number of CPUs (beyond 2) so is just
+     * a constant.
+     */
+    static final int maxTimedSpins = (NCPUS < 2)? 0 : 32;
 
-      When a put or take waiting for the actions of its counterpart
-      aborts due to interruption or timeout, it marks the node
-      it created as "CANCELLED", which causes its counterpart to retry
-      the entire put or take sequence.
+    /**
+     * The number of times to spin before blocking in untimed waits.
+     * This is greater than timed value because untimed waits spin
+     * faster since they don't need to check times on each spin.
+     */
+    static final int maxUntimedSpins = maxTimedSpins * 16;
 
-      This requires keeping two simple queues, waitingProducers and
-      waitingConsumers. Each of these can be FIFO (preserves fairness)
-      or LIFO (improves throughput).
-    */
+    /**
+     * The number of nanoseconds for which it is faster to spin
+     * rather than to use timed park. A rough estimate suffices.
+     */
+    static final long spinForTimeoutThreshold = 1000L;
 
-    /** Lock protecting both wait queues */
-    private final ReentrantLock qlock;
-    /** Queue holding waiting puts */
-    private final WaitQueue waitingProducers;
-    /** Queue holding waiting takes */
-    private final WaitQueue waitingConsumers;
+    /** Dual stack */
+    static final class TransferStack extends Transferer {
+        /*
+         * This extends Scherer-Scott dual stack algorithm, differing,
+         * among other ways, by using "covering" nodes rather than
+         * bit-marked pointers: Fulfilling operations push on marker
+         * nodes (with FULFILLING bit set in mode) to reserve a spot
+         * to match a waiting node.
+         */
+
+        /* Modes for SNodes, ORed together in node fields */
+        /** Node represents an unfulfilled consumer */
+        static final int REQUEST    = 0;
+        /** Node represents an unfulfilled producer */
+        static final int DATA       = 1;
+        /** Node is fulfilling another unfulfilled DATA or REQUEST */
+        static final int FULFILLING = 2;
+
+        /** Return true if m has fulfilling bit set */
+        static boolean isFulfilling(int m) { return (m & FULFILLING) != 0; }
+
+        /** Node class for TransferStacks. */
+        static final class SNode {
+            volatile SNode next;        // next node in stack
+            volatile SNode match;       // the node matched to this
+            volatile Thread waiter;     // to control park/unpark
+            Object item;                // data; or null for REQUESTs
+            int mode;
+            // Note: item and mode fields don't need to be volatile
+            // since they are always written before, and read after,
+            // other volatile/atomic operations.
+
+            SNode(Object item) {
+                this.item = item;
+            }
+
+            static final AtomicReferenceFieldUpdater<SNode, SNode>
+                nextUpdater = AtomicReferenceFieldUpdater.newUpdater
+                (SNode.class, SNode.class, "next");
+
+            boolean casNext(SNode cmp, SNode val) {
+                return (cmp == next &&
+                        nextUpdater.compareAndSet(this, cmp, val));
+            }
+
+            static final AtomicReferenceFieldUpdater<SNode, SNode>
+                matchUpdater = AtomicReferenceFieldUpdater.newUpdater
+                (SNode.class, SNode.class, "match");
+
+            /**
+             * Tries to match node s to this node, if so, waking up thread.
+             * Fulfillers call tryMatch to identify their waiters.
+             * Waiters block until they have been matched.
+             *
+             * @param s the node to match
+             * @return true if successfully matched to s
+             */
+            boolean tryMatch(SNode s) {
+                if (match == null &&
+                    matchUpdater.compareAndSet(this, null, s)) {
+                    Thread w = waiter;
+                    if (w != null) {    // waiters need at most one unpark
+                        waiter = null;
+                        LockSupport.unpark(w);
+                    }
+                    return true;
+                }
+                return match == s;
+            }
+
+            /**
+             * Tries to cancel a wait by matching node to itself.
+             */
+            void tryCancel() {
+                matchUpdater.compareAndSet(this, null, this);
+            }
+
+            boolean isCancelled() {
+                return match == this;
+            }
+        }
+
+        /** The head (top) of the stack */
+        volatile SNode head;
+
+        static final AtomicReferenceFieldUpdater<TransferStack, SNode>
+            headUpdater = AtomicReferenceFieldUpdater.newUpdater
+            (TransferStack.class,  SNode.class, "head");
+
+        boolean casHead(SNode h, SNode nh) {
+            return h == head && headUpdater.compareAndSet(this, h, nh);
+        }
+
+        /**
+         * Creates or resets fields of a node. Called only from transfer
+         * where the node to push on stack is lazily created and
+         * reused when possible to help reduce intervals between reads
+         * and CASes of head and to avoid surges of garbage when CASes
+         * to push nodes fail due to contention.
+         */
+        static SNode snode(SNode s, Object e, SNode next, int mode) {
+            if (s == null) s = new SNode(e);
+            s.mode = mode;
+            s.next = next;
+            return s;
+        }
+
+        /**
+         * Puts or takes an item.
+         */
+        Object transfer(Object e, boolean timed, long nanos) {
+            /*
+             * Basic algorithm is to loop trying one of three actions:
+             *
+             * 1. If apparently empty or already containing nodes of same
+             *    mode, try to push node on stack and wait for a match,
+             *    returning it, or null if cancelled.
+             *
+             * 2. If apparently containing node of complementary mode,
+             *    try to push a fulfilling node on to stack, match
+             *    with corresponding waiting node, pop both from
+             *    stack, and return matched item. The matching or
+             *    unlinking might not actually be necessary because of
+             *    other threads performing action 3:
+             *
+             * 3. If top of stack already holds another fulfilling node,
+             *    help it out by doing its match and/or pop
+             *    operations, and then continue. The code for helping
+             *    is essentially the same as for fulfilling, except
+             *    that it doesn't return the item.
+             */
+
+            SNode s = null; // constructed/reused as needed
+            int mode = (e == null)? REQUEST : DATA;
+
+            for (;;) {
+                SNode h = head;
+                if (h == null || h.mode == mode) {  // empty or same-mode
+                    if (timed && nanos <= 0) {      // can't wait
+                        if (h != null && h.isCancelled())
+                            casHead(h, h.next);     // pop cancelled node
+                        else
+                            return null;
+                    } else if (casHead(h, s = snode(s, e, h, mode))) {
+                        SNode m = awaitFulfill(s, timed, nanos);
+                        if (m == s) {               // wait was cancelled
+                            clean(s);
+                            return null;
+                        }
+                        if ((h = head) != null && h.next == s)
+                            casHead(h, s.next);     // help s's fulfiller
+                        return mode == REQUEST? m.item : s.item;
+                    }
+                } else if (!isFulfilling(h.mode)) { // try to fulfill
+                    if (h.isCancelled())            // already cancelled
+                        casHead(h, h.next);         // pop and retry
+                    else if (casHead(h, s=snode(s, e, h, FULFILLING|mode))) {
+                        for (;;) { // loop until matched or waiters disappear
+                            SNode m = s.next;       // m is s's match
+                            if (m == null) {        // all waiters are gone
+                                casHead(s, null);   // pop fulfill node
+                                s = null;           // use new node next time
+                                break;              // restart main loop
+                            }
+                            SNode mn = m.next;
+                            if (m.tryMatch(s)) {
+                                casHead(s, mn);     // pop both s and m
+                                return (mode == REQUEST)? m.item : s.item;
+                            } else                  // lost match
+                                s.casNext(m, mn);   // help unlink
+                        }
+                    }
+                } else {                            // help a fulfiller
+                    SNode m = h.next;               // m is h's match
+                    if (m == null)                  // waiter is gone
+                        casHead(h, null);           // pop fulfilling node
+                    else {
+                        SNode mn = m.next;
+                        if (m.tryMatch(h))          // help match
+                            casHead(h, mn);         // pop both h and m
+                        else                        // lost match
+                            h.casNext(m, mn);       // help unlink
+                    }
+                }
+            }
+        }
+
+        /**
+         * Spins/blocks until node s is matched by a fulfill operation.
+         *
+         * @param s the waiting node
+         * @param timed true if timed wait
+         * @param nanos timeout value
+         * @return matched node, or s if cancelled
+         */
+        SNode awaitFulfill(SNode s, boolean timed, long nanos) {
+            /*
+             * When a node/thread is about to block, it sets its waiter
+             * field and then rechecks state at least one more time
+             * before actually parking, thus covering race vs
+             * fulfiller noticing that waiter is non-null so should be
+             * woken.
+             *
+             * When invoked by nodes that appear at the point of call
+             * to be at the head of the stack, calls to park are
+             * preceded by spins to avoid blocking when producers and
+             * consumers are arriving very close in time.  This can
+             * happen enough to bother only on multiprocessors.
+             *
+             * The order of checks for returning out of main loop
+             * reflects fact that interrupts have precedence over
+             * normal returns, which have precedence over
+             * timeouts. (So, on timeout, one last check for match is
+             * done before giving up.) Except that calls from untimed
+             * SynchronousQueue.{poll/offer} don't check interrupts
+             * and don't wait at all, so are trapped in transfer
+             * method rather than calling awaitFulfill.
+             */
+            long lastTime = (timed)? System.nanoTime() : 0;
+            Thread w = Thread.currentThread();
+            SNode h = head;
+            int spins = (shouldSpin(s)?
+                         (timed? maxTimedSpins : maxUntimedSpins) : 0);
+            for (;;) {
+                if (w.isInterrupted())
+                    s.tryCancel();
+                SNode m = s.match;
+                if (m != null)
+                    return m;
+                if (timed) {
+                    long now = System.nanoTime();
+                    nanos -= now - lastTime;
+                    lastTime = now;
+                    if (nanos <= 0) {
+                        s.tryCancel();
+                        continue;
+                    }
+                }
+                if (spins > 0)
+                    spins = shouldSpin(s)? (spins-1) : 0;
+                else if (s.waiter == null)
+                    s.waiter = w; // establish waiter so can park next iter
+                else if (!timed)
+                    LockSupport.park();
+                else if (nanos > spinForTimeoutThreshold)
+                    LockSupport.parkNanos(nanos);
+            }
+        }
+
+        /**
+         * Returns true if node s is at head or there is an active
+         * fulfiller.
+         */
+        boolean shouldSpin(SNode s) {
+            SNode h = head;
+            return (h == s || h == null || isFulfilling(h.mode));
+        }
+
+        /**
+         * Unlinks s from the stack.
+         */
+        void clean(SNode s) {
+            s.item = null;   // forget item
+            s.waiter = null; // forget thread
+
+            /*
+             * At worst we may need to traverse entire stack to unlink
+             * s. If there are multiple concurrent calls to clean, we
+             * might not see s if another thread has already removed
+             * it. But we can stop when we see any node known to
+             * follow s. We use s.next unless it too is cancelled, in
+             * which case we try the node one past. We don't check any
+             * further because we don't want to doubly traverse just to
+             * find sentinel.
+             */
+
+            SNode past = s.next;
+            if (past != null && past.isCancelled())
+                past = past.next;
+
+            // Absorb cancelled nodes at head
+            SNode p;
+            while ((p = head) != null && p != past && p.isCancelled())
+                casHead(p, p.next);
+
+            // Unsplice embedded nodes
+            while (p != null && p != past) {
+                SNode n = p.next;
+                if (n != null && n.isCancelled())
+                    p.casNext(n, n.next);
+                else
+                    p = n;
+            }
+        }
+    }
+
+    /** Dual Queue */
+    static final class TransferQueue extends Transferer {
+        /*
+         * This extends Scherer-Scott dual queue algorithm, differing,
+         * among other ways, by using modes within nodes rather than
+         * marked pointers. The algorithm is a little simpler than
+         * that for stacks because fulfillers do not need explicit
+         * nodes, and matching is done by CAS'ing QNode.item field
+         * from non-null to null (for put) or vice versa (for take).
+         */
+
+        /** Node class for TransferQueue. */
+        static final class QNode {
+            volatile QNode next;          // next node in queue
+            volatile Object item;         // CAS'ed to or from null
+            volatile Thread waiter;       // to control park/unpark
+            final boolean isData;
+
+            QNode(Object item, boolean isData) {
+                this.item = item;
+                this.isData = isData;
+            }
+
+            static final AtomicReferenceFieldUpdater<QNode, QNode>
+                nextUpdater = AtomicReferenceFieldUpdater.newUpdater
+                (QNode.class, QNode.class, "next");
+
+            boolean casNext(QNode cmp, QNode val) {
+                return (next == cmp &&
+                        nextUpdater.compareAndSet(this, cmp, val));
+            }
+
+            static final AtomicReferenceFieldUpdater<QNode, Object>
+                itemUpdater = AtomicReferenceFieldUpdater.newUpdater
+                (QNode.class, Object.class, "item");
+
+            boolean casItem(Object cmp, Object val) {
+                return (item == cmp &&
+                        itemUpdater.compareAndSet(this, cmp, val));
+            }
+
+            /**
+             * Tries to cancel by CAS'ing ref to this as item.
+             */
+            void tryCancel(Object cmp) {
+                itemUpdater.compareAndSet(this, cmp, this);
+            }
+
+            boolean isCancelled() {
+                return item == this;
+            }
+
+            /**
+             * Returns true if this node is known to be off the queue
+             * because its next pointer has been forgotten due to
+             * an advanceHead operation.
+             */
+            boolean isOffList() {
+                return next == this;
+            }
+        }
+
+        /** Head of queue */
+        transient volatile QNode head;
+        /** Tail of queue */
+        transient volatile QNode tail;
+        /**
+         * Reference to a cancelled node that might not yet have been
+         * unlinked from queue because it was the last inserted node
+         * when it cancelled.
+         */
+        transient volatile QNode cleanMe;
+
+        TransferQueue() {
+            QNode h = new QNode(null, false); // initialize to dummy node.
+            head = h;
+            tail = h;
+        }
+
+        static final AtomicReferenceFieldUpdater<TransferQueue, QNode>
+            headUpdater = AtomicReferenceFieldUpdater.newUpdater
+            (TransferQueue.class,  QNode.class, "head");
+
+        /**
+         * Tries to cas nh as new head; if successful, unlink
+         * old head's next node to avoid garbage retention.
+         */
+        void advanceHead(QNode h, QNode nh) {
+            if (h == head && headUpdater.compareAndSet(this, h, nh))
+                h.next = h; // forget old next
+        }
+
+        static final AtomicReferenceFieldUpdater<TransferQueue, QNode>
+            tailUpdater = AtomicReferenceFieldUpdater.newUpdater
+            (TransferQueue.class, QNode.class, "tail");
+
+        /**
+         * Tries to cas nt as new tail.
+         */
+        void advanceTail(QNode t, QNode nt) {
+            if (tail == t)
+                tailUpdater.compareAndSet(this, t, nt);
+        }
+
+        static final AtomicReferenceFieldUpdater<TransferQueue, QNode>
+            cleanMeUpdater = AtomicReferenceFieldUpdater.newUpdater
+            (TransferQueue.class, QNode.class, "cleanMe");
+
+        /**
+         * Tries to CAS cleanMe slot.
+         */
+        boolean casCleanMe(QNode cmp, QNode val) {
+            return (cleanMe == cmp &&
+                    cleanMeUpdater.compareAndSet(this, cmp, val));
+        }
+
+        /**
+         * Puts or takes an item.
+         */
+        Object transfer(Object e, boolean timed, long nanos) {
+            /* Basic algorithm is to loop trying to take either of
+             * two actions:
+             *
+             * 1. If queue apparently empty or holding same-mode nodes,
+             *    try to add node to queue of waiters, wait to be
+             *    fulfilled (or cancelled) and return matching item.
+             *
+             * 2. If queue apparently contains waiting items, and this
+             *    call is of complementary mode, try to fulfill by CAS'ing
+             *    item field of waiting node and dequeuing it, and then
+             *    returning matching item.
+             *
+             * In each case, along the way, check for and try to help
+             * advance head and tail on behalf of other stalled/slow
+             * threads.
+             *
+             * The loop starts off with a null check guarding against
+             * seeing uninitialized head or tail values. This never
+             * happens in current SynchronousQueue, but could if
+             * callers held non-volatile/final ref to the
+             * transferer. The check is here anyway because it places
+             * null checks at top of loop, which is usually faster
+             * than having them implicitly interspersed.
+             */
+
+            QNode s = null; // constructed/reused as needed
+            boolean isData = (e != null);
+
+            for (;;) {
+                QNode t = tail;
+                QNode h = head;
+                if (t == null || h == null)         // saw uninitialized value
+                    continue;                       // spin
+
+                if (h == t || t.isData == isData) { // empty or same-mode
+                    QNode tn = t.next;
+                    if (t != tail)                  // inconsistent read
+                        continue;
+                    if (tn != null) {               // lagging tail
+                        advanceTail(t, tn);
+                        continue;
+                    }
+                    if (timed && nanos <= 0)        // can't wait
+                        return null;
+                    if (s == null)
+                        s = new QNode(e, isData);
+                    if (!t.casNext(null, s))        // failed to link in
+                        continue;
+
+                    advanceTail(t, s);              // swing tail and wait
+                    Object x = awaitFulfill(s, e, timed, nanos);
+                    if (x == s) {                   // wait was cancelled
+                        clean(t, s);
+                        return null;
+                    }
+
+                    if (!s.isOffList()) {           // not already unlinked
+                        advanceHead(t, s);          // unlink if head
+                        if (x != null)              // and forget fields
+                            s.item = s;
+                        s.waiter = null;
+                    }
+                    return (x != null)? x : e;
+
+                } else {                            // complementary-mode
+                    QNode m = h.next;               // node to fulfill
+                    if (t != tail || m == null || h != head)
+                        continue;                   // inconsistent read
+
+                    Object x = m.item;
+                    if (isData == (x != null) ||    // m already fulfilled
+                        x == m ||                   // m cancelled
+                        !m.casItem(x, e)) {         // lost CAS
+                        advanceHead(h, m);          // dequeue and retry
+                        continue;
+                    }
+
+                    advanceHead(h, m);              // successfully fulfilled
+                    LockSupport.unpark(m.waiter);
+                    return (x != null)? x : e;
+                }
+            }
+        }
+
+        /**
+         * Spins/blocks until node s is fulfilled.
+         *
+         * @param s the waiting node
+         * @param e the comparison value for checking match
+         * @param timed true if timed wait
+         * @param nanos timeout value
+         * @return matched item, or s if cancelled
+         */
+        Object awaitFulfill(QNode s, Object e, boolean timed, long nanos) {
+            /* Same idea as TransferStack.awaitFulfill */
+            long lastTime = (timed)? System.nanoTime() : 0;
+            Thread w = Thread.currentThread();
+            int spins = ((head.next == s) ?
+                         (timed? maxTimedSpins : maxUntimedSpins) : 0);
+            for (;;) {
+                if (w.isInterrupted())
+                    s.tryCancel(e);
+                Object x = s.item;
+                if (x != e)
+                    return x;
+                if (timed) {
+                    long now = System.nanoTime();
+                    nanos -= now - lastTime;
+                    lastTime = now;
+                    if (nanos <= 0) {
+                        s.tryCancel(e);
+                        continue;
+                    }
+                }
+                if (spins > 0)
+                    --spins;
+                else if (s.waiter == null)
+                    s.waiter = w;
+                else if (!timed)
+                    LockSupport.park();
+                else if (nanos > spinForTimeoutThreshold)
+                    LockSupport.parkNanos(nanos);
+            }
+        }
+
+        /**
+         * Gets rid of cancelled node s with original predecessor pred.
+         */
+        void clean(QNode pred, QNode s) {
+            s.waiter = null; // forget thread
+            /*
+             * At any given time, exactly one node on list cannot be
+             * deleted -- the last inserted node. To accommodate this,
+             * if we cannot delete s, we save its predecessor as
+             * "cleanMe", deleting the previously saved version
+             * first. At least one of node s or the node previously
+             * saved can always be deleted, so this always terminates.
+             */
+            while (pred.next == s) { // Return early if already unlinked
+                QNode h = head;
+                QNode hn = h.next;   // Absorb cancelled first node as head
+                if (hn != null && hn.isCancelled()) {
+                    advanceHead(h, hn);
+                    continue;
+                }
+                QNode t = tail;      // Ensure consistent read for tail
+                if (t == h)
+                    return;
+                QNode tn = t.next;
+                if (t != tail)
+                    continue;
+                if (tn != null) {
+                    advanceTail(t, tn);
+                    continue;
+                }
+                if (s != t) {        // If not tail, try to unsplice
+                    QNode sn = s.next;
+                    if (sn == s || pred.casNext(s, sn))
+                        return;
+                }
+                QNode dp = cleanMe;
+                if (dp != null) {    // Try unlinking previous cancelled node
+                    QNode d = dp.next;
+                    QNode dn;
+                    if (d == null ||               // d is gone or
+                        d == dp ||                 // d is off list or
+                        !d.isCancelled() ||        // d not cancelled or
+                        (d != t &&                 // d not tail and
+                         (dn = d.next) != null &&  //   has successor
+                         dn != d &&                //   that is on list
+                         dp.casNext(d, dn)))       // d unspliced
+                        casCleanMe(dp, null);
+                    if (dp == pred)
+                        return;      // s is already saved node
+                } else if (casCleanMe(null, pred))
+                    return;          // Postpone cleaning s
+            }
+        }
+    }
+
+    /**
+     * The transferer. Set only in constructor, but cannot be declared
+     * as final without further complicating serialization.  Since
+     * this is accessed only at most once per public method, there
+     * isn't a noticeable performance penalty for using volatile
+     * instead of final here.
+     */
+    private transient volatile Transferer transferer;
 
     /**
      * Creates a <tt>SynchronousQueue</tt> with nonfair access policy.
@@ -92,394 +789,92 @@
     }
 
     /**
-     * Creates a <tt>SynchronousQueue</tt> with specified fairness policy.
-     * @param fair if true, threads contend in FIFO order for access;
-     * otherwise the order is unspecified.
+     * Creates a <tt>SynchronousQueue</tt> with the specified fairness policy.
+     *
+     * @param fair if true, waiting threads contend in FIFO order for
+     *        access; otherwise the order is unspecified.
      */
     public SynchronousQueue(boolean fair) {
-        if (fair) {
-            qlock = new ReentrantLock(true);
-            waitingProducers = new FifoWaitQueue();
-            waitingConsumers = new FifoWaitQueue();
-        }
-        else {
-            qlock = new ReentrantLock();
-            waitingProducers = new LifoWaitQueue();
-            waitingConsumers = new LifoWaitQueue();
-        }
-    }
-
-    /**
-     * Queue to hold waiting puts/takes; specialized to Fifo/Lifo below.
-     * These queues have all transient fields, but are serializable
-     * in order to recover fairness settings when deserialized.
-     */
-    static abstract class WaitQueue implements java.io.Serializable {
-        /** Create, add, and return node for x */
-        abstract Node enq(Object x);
-        /** Remove and return node, or null if empty */
-        abstract Node deq();
-    }
-
-    /**
-     * FIFO queue to hold waiting puts/takes.
-     */
-    static final class FifoWaitQueue extends WaitQueue implements java.io.Serializable {
-        private static final long serialVersionUID = -3623113410248163686L;
-        private transient Node head;
-        private transient Node last;
-
-        Node enq(Object x) {
-            Node p = new Node(x);
-            if (last == null)
-                last = head = p;
-            else
-                last = last.next = p;
-            return p;
-        }
-
-        Node deq() {
-            Node p = head;
-            if (p != null) {
-                if ((head = p.next) == null)
-                    last = null;
-                p.next = null;
-            }
-            return p;
-        }
-    }
-
-    /**
-     * LIFO queue to hold waiting puts/takes.
-     */
-    static final class LifoWaitQueue extends WaitQueue implements java.io.Serializable {
-        private static final long serialVersionUID = -3633113410248163686L;
-        private transient Node head;
-
-        Node enq(Object x) {
-            return head = new Node(x, head);
-        }
-
-        Node deq() {
-            Node p = head;
-            if (p != null) {
-                head = p.next;
-                p.next = null;
-            }
-            return p;
-        }
-    }
-
-    /**
-     * Nodes each maintain an item and handle waits and signals for
-     * getting and setting it. The class extends
-     * AbstractQueuedSynchronizer to manage blocking, using AQS state
-     *  0 for waiting, 1 for ack, -1 for cancelled.
-     */
-    static final class Node extends AbstractQueuedSynchronizer {
-        /** Synchronization state value representing that node acked */
-        private static final int ACK    =  1;
-        /** Synchronization state value representing that node cancelled */
-        private static final int CANCEL = -1;
-
-        /** The item being transferred */
-        Object item;
-        /** Next node in wait queue */
-        Node next;
-
-        /** Creates a node with initial item */
-        Node(Object x) { item = x; }
-
-        /** Creates a node with initial item and next */
-        Node(Object x, Node n) { item = x; next = n; }
-
-        /**
-         * Implements AQS base acquire to succeed if not in WAITING state
-         */
-        protected boolean tryAcquire(int ignore) {
-            return getState() != 0;
-        }
-
-        /**
-         * Implements AQS base release to signal if state changed
-         */
-        protected boolean tryRelease(int newState) {
-            return compareAndSetState(0, newState);
-        }
-
-        /**
-         * Takes item and nulls out field (for sake of GC)
-         */
-        private Object extract() {
-            Object x = item;
-            item = null;
-            return x;
-        }
-
-        /**
-         * Tries to cancel on interrupt; if so rethrowing,
-         * else setting interrupt state
-         */
-        private void checkCancellationOnInterrupt(InterruptedException ie) 
-            throws InterruptedException {
-            if (release(CANCEL)) 
-                throw ie;
-            Thread.currentThread().interrupt();
-        }
-
-        /**
-         * Fills in the slot created by the consumer and signal consumer to
-         * continue.
-         */
-        boolean setItem(Object x) {
-            item = x; // can place in slot even if cancelled
-            return release(ACK);
-        }
-
-        /**
-         * Removes item from slot created by producer and signal producer
-         * to continue.
-         */
-        Object getItem() {
-            return (release(ACK))? extract() : null;
-        }
-
-        /**
-         * Waits for a consumer to take item placed by producer.
-         */
-        void waitForTake() throws InterruptedException {
-            try {
-                acquireInterruptibly(0);
-            } catch (InterruptedException ie) {
-                checkCancellationOnInterrupt(ie);
-            }
-        }
-
-        /**
-         * Waits for a producer to put item placed by consumer.
-         */
-        Object waitForPut() throws InterruptedException {
-            try {
-                acquireInterruptibly(0);
-            } catch (InterruptedException ie) {
-                checkCancellationOnInterrupt(ie);
-            }
-            return extract();
-        }
-
-        /**
-         * Waits for a consumer to take item placed by producer or time out.
-         */
-        boolean waitForTake(long nanos) throws InterruptedException {
-            try {
-                if (!tryAcquireNanos(0, nanos) &&
-                    release(CANCEL))
-                    return false;
-            } catch (InterruptedException ie) {
-                checkCancellationOnInterrupt(ie);
-            }
-            return true;
-        }
-
-        /**
-         * Waits for a producer to put item placed by consumer, or time out.
-         */
-        Object waitForPut(long nanos) throws InterruptedException {
-            try {
-                if (!tryAcquireNanos(0, nanos) &&
-                    release(CANCEL))
-                    return null;
-            } catch (InterruptedException ie) {
-                checkCancellationOnInterrupt(ie);
-            }
-            return extract();
-        }
+        transferer = (fair)? new TransferQueue() : new TransferStack();
     }
 
     /**
      * Adds the specified element to this queue, waiting if necessary for
      * another thread to receive it.
-     * @param o the element to add
-     * @throws InterruptedException if interrupted while waiting.
-     * @throws NullPointerException if the specified element is <tt>null</tt>.
+     *
+     * @throws InterruptedException {@inheritDoc}
+     * @throws NullPointerException {@inheritDoc}
      */
     public void put(E o) throws InterruptedException {
         if (o == null) throw new NullPointerException();
-        final ReentrantLock qlock = this.qlock;
-
-        for (;;) {
-            Node node;
-            boolean mustWait;
-            if (Thread.interrupted()) throw new InterruptedException();
-            qlock.lock();
-            try {
-                node = waitingConsumers.deq();
-                if ( (mustWait = (node == null)) )
-                    node = waitingProducers.enq(o);
-            } finally {
-                qlock.unlock();
-            }
-
-            if (mustWait) {
-                node.waitForTake();
-                return;
-            }
-
-            else if (node.setItem(o))
-                return;
-
-            // else consumer cancelled, so retry
+        if (transferer.transfer(o, false, 0) == null) {
+            Thread.interrupted();
+            throw new InterruptedException();
         }
     }
 
     /**
      * Inserts the specified element into this queue, waiting if necessary
      * up to the specified wait time for another thread to receive it.
-     * @param o the element to add
-     * @param timeout how long to wait before giving up, in units of
-     * <tt>unit</tt>
-     * @param unit a <tt>TimeUnit</tt> determining how to interpret the
-     * <tt>timeout</tt> parameter
-     * @return <tt>true</tt> if successful, or <tt>false</tt> if
-     * the specified waiting time elapses before a consumer appears.
-     * @throws InterruptedException if interrupted while waiting.
-     * @throws NullPointerException if the specified element is <tt>null</tt>.
+     *
+     * @return <tt>true</tt> if successful, or <tt>false</tt> if the
+     *         specified waiting time elapses before a consumer appears.
+     * @throws InterruptedException {@inheritDoc}
+     * @throws NullPointerException {@inheritDoc}
      */
-    public boolean offer(E o, long timeout, TimeUnit unit) throws InterruptedException {
+    public boolean offer(E o, long timeout, TimeUnit unit)
+        throws InterruptedException {
         if (o == null) throw new NullPointerException();
-        long nanos = unit.toNanos(timeout);
-        final ReentrantLock qlock = this.qlock;
-        for (;;) {
-            Node node;
-            boolean mustWait;
-            if (Thread.interrupted()) throw new InterruptedException();
-            qlock.lock();
-            try {
-                node = waitingConsumers.deq();
-                if ( (mustWait = (node == null)) )
-                    node = waitingProducers.enq(o);
-            } finally {
-                qlock.unlock();
-            }
+        if (transferer.transfer(o, true, unit.toNanos(timeout)) != null)
+            return true;
+        if (!Thread.interrupted())
+            return false;
+        throw new InterruptedException();
+    }
 
-            if (mustWait) 
-                return node.waitForTake(nanos);
-
-            else if (node.setItem(o))
-                return true;
-
-            // else consumer cancelled, so retry
-        }
+    /**
+     * Inserts the specified element into this queue, if another thread is
+     * waiting to receive it.
+     *
+     * @param e the element to add
+     * @return <tt>true</tt> if the element was added to this queue, else
+     *         <tt>false</tt>
+     * @throws NullPointerException if the specified element is null
+     */
+    public boolean offer(E e) {
+        if (e == null) throw new NullPointerException();
+        return transferer.transfer(e, true, 0) != null;
     }
 
     /**
      * Retrieves and removes the head of this queue, waiting if necessary
      * for another thread to insert it.
-     * @throws InterruptedException if interrupted while waiting.
+     *
      * @return the head of this queue
+     * @throws InterruptedException {@inheritDoc}
      */
     public E take() throws InterruptedException {
-        final ReentrantLock qlock = this.qlock;
-        for (;;) {
-            Node node;
-            boolean mustWait;
-
-            if (Thread.interrupted()) throw new InterruptedException();
-            qlock.lock();
-            try {
-                node = waitingProducers.deq();
-                if ( (mustWait = (node == null)) )
-                    node = waitingConsumers.enq(null);
-            } finally {
-                qlock.unlock();
-            }
-
-            if (mustWait) {
-                Object x = node.waitForPut();
-                return (E)x;
-            }
-            else {
-                Object x = node.getItem();
-                if (x != null)
-                    return (E)x;
-                // else cancelled, so retry
-            }
-        }
+        Object e = transferer.transfer(null, false, 0);
+        if (e != null)
+            return (E)e;
+        Thread.interrupted();
+        throw new InterruptedException();
     }
 
     /**
      * Retrieves and removes the head of this queue, waiting
      * if necessary up to the specified wait time, for another thread
      * to insert it.
-     * @param timeout how long to wait before giving up, in units of
-     * <tt>unit</tt>
-     * @param unit a <tt>TimeUnit</tt> determining how to interpret the
-     * <tt>timeout</tt> parameter
+     *
      * @return the head of this queue, or <tt>null</tt> if the
-     * specified waiting time elapses before an element is present.
-     * @throws InterruptedException if interrupted while waiting.
+     *         specified waiting time elapses before an element is present.
+     * @throws InterruptedException {@inheritDoc}
      */
     public E poll(long timeout, TimeUnit unit) throws InterruptedException {
-        long nanos = unit.toNanos(timeout);
-        final ReentrantLock qlock = this.qlock;
-
-        for (;;) {
-            Node node;
-            boolean mustWait;
-
-            if (Thread.interrupted()) throw new InterruptedException();
-            qlock.lock();
-            try {
-                node = waitingProducers.deq();
-                if ( (mustWait = (node == null)) )
-                    node = waitingConsumers.enq(null);
-            } finally {
-                qlock.unlock();
-            }
-
-            if (mustWait) {
-                Object x = node.waitForPut(nanos);
-                return (E)x;
-            }
-            else {
-                Object x = node.getItem();
-                if (x != null)
-                    return (E)x;
-                // else cancelled, so retry
-            }
-        }
-    }
-
-    // Untimed nonblocking versions
-
-   /**
-    * Inserts the specified element into this queue, if another thread is
-    * waiting to receive it.
-    *
-    * @param o the element to add.
-    * @return <tt>true</tt> if it was possible to add the element to
-    *         this queue, else <tt>false</tt>
-    * @throws NullPointerException if the specified element is <tt>null</tt>
-    */
-    public boolean offer(E o) {
-        if (o == null) throw new NullPointerException();
-        final ReentrantLock qlock = this.qlock;
-
-        for (;;) {
-            Node node;
-            qlock.lock();
-            try {
-                node = waitingConsumers.deq();
-            } finally {
-                qlock.unlock();
-            }
-            if (node == null)
-                return false;
-
-            else if (node.setItem(o))
-                return true;
-            // else retry
-        }
+        Object e = transferer.transfer(null, true, unit.toNanos(timeout));
+        if (e != null || !Thread.interrupted())
+            return (E)e;
+        throw new InterruptedException();
     }
 
     /**
@@ -490,30 +885,13 @@
      *         element is available.
      */
     public E poll() {
-        final ReentrantLock qlock = this.qlock;
-        for (;;) {
-            Node node;
-            qlock.lock();
-            try {
-                node = waitingProducers.deq();
-            } finally {
-                qlock.unlock();
-            }
-            if (node == null)
-                return null;
-
-            else {
-                Object x = node.getItem();
-                if (x != null)
-                    return (E)x;
-                // else retry
-            }
-        }
+        return (E)transferer.transfer(null, true, 0);
     }
 
     /**
-     * Always returns <tt>true</tt>. 
+     * Always returns <tt>true</tt>.
      * A <tt>SynchronousQueue</tt> has no internal capacity.
+     *
      * @return <tt>true</tt>
      */
     public boolean isEmpty() {
@@ -523,6 +901,7 @@
     /**
      * Always returns zero.
      * A <tt>SynchronousQueue</tt> has no internal capacity.
+     *
      * @return zero.
      */
     public int size() {
@@ -532,6 +911,7 @@
     /**
      * Always returns zero.
      * A <tt>SynchronousQueue</tt> has no internal capacity.
+     *
      * @return zero.
      */
     public int remainingCapacity() {
@@ -542,11 +922,13 @@
      * Does nothing.
      * A <tt>SynchronousQueue</tt> has no internal capacity.
      */
-    public void clear() {}
+    public void clear() {
+    }
 
     /**
      * Always returns <tt>false</tt>.
      * A <tt>SynchronousQueue</tt> has no internal capacity.
+     *
      * @param o the element
      * @return <tt>false</tt>
      */
@@ -566,8 +948,9 @@
     }
 
     /**
-     * Returns <tt>false</tt> unless given collection is empty.
+     * Returns <tt>false</tt> unless the given collection is empty.
      * A <tt>SynchronousQueue</tt> has no internal capacity.
+     *
      * @param c the collection
      * @return <tt>false</tt> unless given collection is empty
      */
@@ -578,6 +961,7 @@
     /**
      * Always returns <tt>false</tt>.
      * A <tt>SynchronousQueue</tt> has no internal capacity.
+     *
      * @param c the collection
      * @return <tt>false</tt>
      */
@@ -588,6 +972,7 @@
     /**
      * Always returns <tt>false</tt>.
      * A <tt>SynchronousQueue</tt> has no internal capacity.
+     *
      * @param c the collection
      * @return <tt>false</tt>
      */
@@ -596,9 +981,10 @@
     }
 
     /**
-     * Always returns <tt>null</tt>. 
+     * Always returns <tt>null</tt>.
      * A <tt>SynchronousQueue</tt> does not return elements
      * unless actively waited on.
+     *
      * @return <tt>null</tt>
      */
     public E peek() {
@@ -628,7 +1014,6 @@
         return new EmptyIterator<E>();
     }
 
-
     /**
      * Returns a zero-length array.
      * @return a zero-length array
@@ -640,8 +1025,10 @@
     /**
      * Sets the zeroeth element of the specified array to <tt>null</tt>
      * (if the array has non-zero length) and returns it.
+     *
      * @param a the array
      * @return the specified array
+     * @throws NullPointerException if the specified array is null
      */
     public <T> T[] toArray(T[] a) {
         if (a.length > 0)
@@ -649,7 +1036,12 @@
         return a;
     }
 
-
+    /**
+     * @throws UnsupportedOperationException {@inheritDoc}
+     * @throws ClassCastException            {@inheritDoc}
+     * @throws NullPointerException          {@inheritDoc}
+     * @throws IllegalArgumentException      {@inheritDoc}
+     */
     public int drainTo(Collection<? super E> c) {
         if (c == null)
             throw new NullPointerException();
@@ -664,6 +1056,12 @@
         return n;
     }
 
+    /**
+     * @throws UnsupportedOperationException {@inheritDoc}
+     * @throws ClassCastException            {@inheritDoc}
+     * @throws NullPointerException          {@inheritDoc}
+     * @throws IllegalArgumentException      {@inheritDoc}
+     */
     public int drainTo(Collection<? super E> c, int maxElements) {
         if (c == null)
             throw new NullPointerException();
@@ -677,9 +1075,54 @@
         }
         return n;
     }
+
+    /*
+     * To cope with serialization strategy in the 1.5 version of
+     * SynchronousQueue, we declare some unused classes and fields
+     * that exist solely to enable serializability across versions.
+     * These fields are never used, so are initialized only if this
+     * object is ever serialized or deserialized.
+     */
+
+    static class WaitQueue implements java.io.Serializable { }
+    static class LifoWaitQueue extends WaitQueue {
+        private static final long serialVersionUID = -3633113410248163686L;
+    }
+    static class FifoWaitQueue extends WaitQueue {
+        private static final long serialVersionUID = -3623113410248163686L;
+    }
+    private ReentrantLock qlock;
+    private WaitQueue waitingProducers;
+    private WaitQueue waitingConsumers;
+
+    /**
+     * Save the state to a stream (that is, serialize it).
+     *
+     * @param s the stream
+     */
+    private void writeObject(java.io.ObjectOutputStream s)
+        throws java.io.IOException {
+        boolean fair = transferer instanceof TransferQueue;
+        if (fair) {
+            qlock = new ReentrantLock(true);
+            waitingProducers = new FifoWaitQueue();
+            waitingConsumers = new FifoWaitQueue();
+        }
+        else {
+            qlock = new ReentrantLock();
+            waitingProducers = new LifoWaitQueue();
+            waitingConsumers = new LifoWaitQueue();
+        }
+        s.defaultWriteObject();
+    }
+
+    private void readObject(final java.io.ObjectInputStream s)
+        throws java.io.IOException, ClassNotFoundException {
+        s.defaultReadObject();
+        if (waitingProducers instanceof FifoWaitQueue)
+            transferer = new TransferQueue();
+        else
+            transferer = new TransferStack();
+    }
+
 }
-
-
-
-
-
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/ThreadFactory.java b/libcore/concurrent/src/main/java/java/util/concurrent/ThreadFactory.java
index 04c63e1..2f0fb1a 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/ThreadFactory.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/ThreadFactory.java
@@ -11,7 +11,7 @@
  * removes hardwiring of calls to {@link Thread#Thread(Runnable) new Thread},
  * enabling applications to use special thread subclasses, priorities, etc.
  *
- * <p> 
+ * <p>
  * The simplest implementation of this interface is just:
  * <pre>
  * class SimpleThreadFactory implements ThreadFactory {
@@ -23,18 +23,19 @@
  *
  * The {@link Executors#defaultThreadFactory} method provides a more
  * useful simple implementation, that sets the created thread context
- * to known values before returning it. 
+ * to known values before returning it.
  * @since 1.5
  * @author Doug Lea
  */
-public interface ThreadFactory { 
+public interface ThreadFactory {
 
     /**
-     * Constructs a new <tt>Thread</tt>.  Implementations may also initialize
-     * priority, name, daemon status, <tt>ThreadGroup</tt>, etc.
+     * Constructs a new {@code Thread}.  Implementations may also initialize
+     * priority, name, daemon status, {@code ThreadGroup}, etc.
      *
      * @param r a runnable to be executed by new thread instance
-     * @return constructed thread
+     * @return constructed thread, or {@code null} if the request to
+     *         create a thread is rejected
      */
     Thread newThread(Runnable r);
 }
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/ThreadPoolExecutor.java b/libcore/concurrent/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
index 1aa8e55..d0c934d 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
@@ -6,13 +6,9 @@
 
 package java.util.concurrent;
 import java.util.concurrent.locks.*;
+import java.util.concurrent.atomic.*;
 import java.util.*;
 
-// BEGIN android-note
-// Altered {@link TimeUnit#NANOSECONDS} because our javadoc tool doesn't
-// like it.
-// END android-note
-
 /**
  * An {@link ExecutorService} that executes each submitted task using
  * one of possibly several pooled threads, normally configured
@@ -23,7 +19,7 @@
  * asynchronous tasks, due to reduced per-task invocation overhead,
  * and they provide a means of bounding and managing the resources,
  * including threads, consumed when executing a collection of tasks.
- * Each <tt>ThreadPoolExecutor</tt> also maintains some basic
+ * Each {@code ThreadPoolExecutor} also maintains some basic
  * statistics, such as the number of completed tasks.
  *
  * <p>To be useful across a wide range of contexts, this class
@@ -42,61 +38,63 @@
  *
  * <dt>Core and maximum pool sizes</dt>
  *
- * <dd>A <tt>ThreadPoolExecutor</tt> will automatically adjust the
- * pool size 
- * (see {@link ThreadPoolExecutor#getPoolSize})
- * according to the bounds set by corePoolSize 
- * (see {@link ThreadPoolExecutor#getCorePoolSize})
- * and
- * maximumPoolSize
- * (see {@link ThreadPoolExecutor#getMaximumPoolSize}).
- * When a new task is submitted in method {@link
- * ThreadPoolExecutor#execute}, and fewer than corePoolSize threads
- * are running, a new thread is created to handle the request, even if
- * other worker threads are idle.  If there are more than
- * corePoolSize but less than maximumPoolSize threads running, a new
- * thread will be created only if the queue is full.  By setting
- * corePoolSize and maximumPoolSize the same, you create a fixed-size
- * thread pool. By setting maximumPoolSize to an essentially unbounded
- * value such as <tt>Integer.MAX_VALUE</tt>, you allow the pool to
- * accommodate an arbitrary number of concurrent tasks. Most typically,
- * core and maximum pool sizes are set only upon construction, but they
- * may also be changed dynamically using {@link
- * ThreadPoolExecutor#setCorePoolSize} and {@link
- * ThreadPoolExecutor#setMaximumPoolSize}. <dd>
+ * <dd>A {@code ThreadPoolExecutor} will automatically adjust the
+ * pool size (see {@link #getPoolSize})
+ * according to the bounds set by
+ * corePoolSize (see {@link #getCorePoolSize}) and
+ * maximumPoolSize (see {@link #getMaximumPoolSize}).
  *
- * <dt> On-demand construction
+ * When a new task is submitted in method {@link #execute}, and fewer
+ * than corePoolSize threads are running, a new thread is created to
+ * handle the request, even if other worker threads are idle.  If
+ * there are more than corePoolSize but less than maximumPoolSize
+ * threads running, a new thread will be created only if the queue is
+ * full.  By setting corePoolSize and maximumPoolSize the same, you
+ * create a fixed-size thread pool. By setting maximumPoolSize to an
+ * essentially unbounded value such as {@code Integer.MAX_VALUE}, you
+ * allow the pool to accommodate an arbitrary number of concurrent
+ * tasks. Most typically, core and maximum pool sizes are set only
+ * upon construction, but they may also be changed dynamically using
+ * {@link #setCorePoolSize} and {@link #setMaximumPoolSize}. </dd>
+ *
+ * <dt>On-demand construction</dt>
  *
  * <dd> By default, even core threads are initially created and
- * started only when needed by new tasks, but this can be overridden
- * dynamically using method {@link
- * ThreadPoolExecutor#prestartCoreThread} or
- * {@link ThreadPoolExecutor#prestartAllCoreThreads}.  </dd>
+ * started only when new tasks arrive, but this can be overridden
+ * dynamically using method {@link #prestartCoreThread} or {@link
+ * #prestartAllCoreThreads}.  You probably want to prestart threads if
+ * you construct the pool with a non-empty queue. </dd>
  *
  * <dt>Creating new threads</dt>
  *
- * <dd>New threads are created using a {@link
- * java.util.concurrent.ThreadFactory}.  If not otherwise specified, a
- * {@link Executors#defaultThreadFactory} is used, that creates threads to all
- * be in the same {@link ThreadGroup} and with the same
- * <tt>NORM_PRIORITY</tt> priority and non-daemon status. By supplying
- * a different ThreadFactory, you can alter the thread's name, thread
- * group, priority, daemon status, etc.  </dd>
+ * <dd>New threads are created using a {@link ThreadFactory}.  If not
+ * otherwise specified, a {@link Executors#defaultThreadFactory} is
+ * used, that creates threads to all be in the same {@link
+ * ThreadGroup} and with the same {@code NORM_PRIORITY} priority and
+ * non-daemon status. By supplying a different ThreadFactory, you can
+ * alter the thread's name, thread group, priority, daemon status,
+ * etc. If a {@code ThreadFactory} fails to create a thread when asked
+ * by returning null from {@code newThread}, the executor will
+ * continue, but might not be able to execute any tasks. Threads
+ * should possess the "modifyThread" {@code RuntimePermission}. If
+ * worker threads or other threads using the pool do not possess this
+ * permission, service may be degraded: configuration changes may not
+ * take effect in a timely manner, and a shutdown pool may remain in a
+ * state in which termination is possible but not completed.</dd>
  *
  * <dt>Keep-alive times</dt>
  *
  * <dd>If the pool currently has more than corePoolSize threads,
  * excess threads will be terminated if they have been idle for more
- * than the keepAliveTime (see {@link
- * ThreadPoolExecutor#getKeepAliveTime}). This provides a means of
- * reducing resource consumption when the pool is not being actively
- * used. If the pool becomes more active later, new threads will be
- * constructed. This parameter can also be changed dynamically
- * using method {@link ThreadPoolExecutor#setKeepAliveTime}. Using
- * a value of <tt>Long.MAX_VALUE</tt> <code>TimeUnit.NANOSECONDS</code>
- * effectively disables idle threads from ever terminating prior
- * to shut down.
- * </dd>
+ * than the keepAliveTime (see {@link #getKeepAliveTime}). This
+ * provides a means of reducing resource consumption when the pool is
+ * not being actively used. If the pool becomes more active later, new
+ * threads will be constructed. This parameter can also be changed
+ * dynamically using method {@link #setKeepAliveTime}. Using a value
+ * of {@code Long.MAX_VALUE} {@link TimeUnit#NANOSECONDS} effectively
+ * disables idle threads from ever terminating prior to shut down. The
+ * keep-alive policy applies only when there are more than
+ * corePoolSizeThreads.</dd>
  *
  * <dt>Queuing</dt>
  *
@@ -112,7 +110,7 @@
  * <li> If corePoolSize or more threads are running, the Executor
  * always prefers queuing a request rather than adding a new
  * thread.</li>
- * 
+ *
  * <li> If a request cannot be queued, a new thread is created unless
  * this would exceed maximumPoolSize, in which case, the task will be
  * rejected.</li>
@@ -135,7 +133,7 @@
  *
  * <li><em> Unbounded queues.</em> Using an unbounded queue (for
  * example a {@link LinkedBlockingQueue} without a predefined
- * capacity) will cause new tasks to be queued in cases where all
+ * capacity) will cause new tasks to wait in the queue when all
  * corePoolSize threads are busy. Thus, no more than corePoolSize
  * threads will ever be created. (And the value of the maximumPoolSize
  * therefore doesn't have any effect.)  This may be appropriate when
@@ -165,35 +163,33 @@
  *
  * <dt>Rejected tasks</dt>
  *
- * <dd> New tasks submitted in method {@link
- * ThreadPoolExecutor#execute} will be <em>rejected</em> when the
- * Executor has been shut down, and also when the Executor uses finite
- * bounds for both maximum threads and work queue capacity, and is
- * saturated.  In either case, the <tt>execute</tt> method invokes the
- * {@link RejectedExecutionHandler#rejectedExecution} method of its
- * {@link RejectedExecutionHandler}.  Four predefined handler policies
- * are provided:
+ * <dd> New tasks submitted in method {@link #execute} will be
+ * <em>rejected</em> when the Executor has been shut down, and also
+ * when the Executor uses finite bounds for both maximum threads and
+ * work queue capacity, and is saturated.  In either case, the {@code
+ * execute} method invokes the {@link
+ * RejectedExecutionHandler#rejectedExecution} method of its {@link
+ * RejectedExecutionHandler}.  Four predefined handler policies are
+ * provided:
  *
  * <ol>
  *
- * <li> In the
- * default {@link ThreadPoolExecutor.AbortPolicy}, the handler throws a
- * runtime {@link RejectedExecutionException} upon rejection. </li>
- * 
- * <li> In {@link
- * ThreadPoolExecutor.CallerRunsPolicy}, the thread that invokes
- * <tt>execute</tt> itself runs the task. This provides a simple
- * feedback control mechanism that will slow down the rate that new
- * tasks are submitted. </li>
+ * <li> In the default {@link ThreadPoolExecutor.AbortPolicy}, the
+ * handler throws a runtime {@link RejectedExecutionException} upon
+ * rejection. </li>
  *
- * <li> In {@link ThreadPoolExecutor.DiscardPolicy},
- * a task that cannot be executed is simply dropped.  </li>
+ * <li> In {@link ThreadPoolExecutor.CallerRunsPolicy}, the thread
+ * that invokes {@code execute} itself runs the task. This provides a
+ * simple feedback control mechanism that will slow down the rate that
+ * new tasks are submitted. </li>
  *
- * <li>In {@link
- * ThreadPoolExecutor.DiscardOldestPolicy}, if the executor is not
- * shut down, the task at the head of the work queue is dropped, and
- * then execution is retried (which can fail again, causing this to be
- * repeated.) </li>
+ * <li> In {@link ThreadPoolExecutor.DiscardPolicy}, a task that
+ * cannot be executed is simply dropped.  </li>
+ *
+ * <li>In {@link ThreadPoolExecutor.DiscardOldestPolicy}, if the
+ * executor is not shut down, the task at the head of the work queue
+ * is dropped, and then execution is retried (which can fail again,
+ * causing this to be repeated.) </li>
  *
  * </ol>
  *
@@ -204,50 +200,62 @@
  *
  * <dt>Hook methods</dt>
  *
- * <dd>This class provides <tt>protected</tt> overridable {@link
- * ThreadPoolExecutor#beforeExecute} and {@link
- * ThreadPoolExecutor#afterExecute} methods that are called before and
- * after execution of each task.  These can be used to manipulate the
- * execution environment, for example, reinitializing ThreadLocals,
- * gathering statistics, or adding log entries. Additionally, method
- * {@link ThreadPoolExecutor#terminated} can be overridden to perform
- * any special processing that needs to be done once the Executor has
- * fully terminated.</dd>
+ * <dd>This class provides {@code protected} overridable {@link
+ * #beforeExecute} and {@link #afterExecute} methods that are called
+ * before and after execution of each task.  These can be used to
+ * manipulate the execution environment; for example, reinitializing
+ * ThreadLocals, gathering statistics, or adding log
+ * entries. Additionally, method {@link #terminated} can be overridden
+ * to perform any special processing that needs to be done once the
+ * Executor has fully terminated.
+ *
+ * <p>If hook or callback methods throw exceptions, internal worker
+ * threads may in turn fail and abruptly terminate.</dd>
  *
  * <dt>Queue maintenance</dt>
  *
- * <dd> Method {@link ThreadPoolExecutor#getQueue} allows access to
- * the work queue for purposes of monitoring and debugging.  Use of
- * this method for any other purpose is strongly discouraged.  Two
- * supplied methods, {@link ThreadPoolExecutor#remove} and {@link
- * ThreadPoolExecutor#purge} are available to assist in storage
- * reclamation when large numbers of queued tasks become
- * cancelled.</dd> </dl>
+ * <dd> Method {@link #getQueue} allows access to the work queue for
+ * purposes of monitoring and debugging.  Use of this method for any
+ * other purpose is strongly discouraged.  Two supplied methods,
+ * {@link #remove} and {@link #purge} are available to assist in
+ * storage reclamation when large numbers of queued tasks become
+ * cancelled.</dd>
+ *
+ * <dt>Finalization</dt>
+ *
+ * <dd> A pool that is no longer referenced in a program <em>AND</em>
+ * has no remaining threads will be {@code shutdown} automatically. If
+ * you would like to ensure that unreferenced pools are reclaimed even
+ * if users forget to call {@link #shutdown}, then you must arrange
+ * that unused threads eventually die, by setting appropriate
+ * keep-alive times using a lower bound of zero core threads.  </dd>
+ *
+ * </dl>
  *
  * <p> <b>Extension example</b>. Most extensions of this class
  * override one or more of the protected hook methods. For example,
  * here is a subclass that adds a simple pause/resume feature:
  *
- * <pre>
+ *  <pre> {@code
  * class PausableThreadPoolExecutor extends ThreadPoolExecutor {
  *   private boolean isPaused;
  *   private ReentrantLock pauseLock = new ReentrantLock();
  *   private Condition unpaused = pauseLock.newCondition();
  *
  *   public PausableThreadPoolExecutor(...) { super(...); }
- * 
+ *
  *   protected void beforeExecute(Thread t, Runnable r) {
  *     super.beforeExecute(t, r);
  *     pauseLock.lock();
  *     try {
  *       while (isPaused) unpaused.await();
- *     } catch(InterruptedException ie) {
+ *     } catch (InterruptedException ie) {
  *       t.interrupt();
  *     } finally {
  *       pauseLock.unlock();
  *     }
  *   }
- * 
+ *
  *   public void pause() {
  *     pauseLock.lock();
  *     try {
@@ -256,7 +264,7 @@
  *       pauseLock.unlock();
  *     }
  *   }
- * 
+ *
  *   public void resume() {
  *     pauseLock.lock();
  *     try {
@@ -266,86 +274,196 @@
  *       pauseLock.unlock();
  *     }
  *   }
- * }
- * </pre>
+ * }}</pre>
+ *
  * @since 1.5
  * @author Doug Lea
  */
 public class ThreadPoolExecutor extends AbstractExecutorService {
     /**
-     * Only used to force toArray() to produce a Runnable[].
+     * The main pool control state, ctl, is an atomic integer packing
+     * two conceptual fields
+     *   workerCount, indicating the effective number of threads
+     *   runState,    indicating whether running, shutting down etc
+     *
+     * In order to pack them into one int, we limit workerCount to
+     * (2^29)-1 (about 500 million) threads rather than (2^31)-1 (2
+     * billion) otherwise representable. If this is ever an issue in
+     * the future, the variable can be changed to be an AtomicLong,
+     * and the shift/mask constants below adjusted. But until the need
+     * arises, this code is a bit faster and simpler using an int.
+     *
+     * The workerCount is the number of workers that have been
+     * permitted to start and not permitted to stop.  The value may be
+     * transiently different from the actual number of live threads,
+     * for example when a ThreadFactory fails to create a thread when
+     * asked, and when exiting threads are still performing
+     * bookkeeping before terminating. The user-visible pool size is
+     * reported as the current size of the workers set.
+     *
+     * The runState provides the main lifecyle control, taking on values:
+     *
+     *   RUNNING:  Accept new tasks and process queued tasks
+     *   SHUTDOWN: Don't accept new tasks, but process queued tasks
+     *   STOP:     Don't accept new tasks, don't process queued tasks,
+     *             and interrupt in-progress tasks
+     *   TIDYING:  All tasks have terminated, workerCount is zero,
+     *             the thread transitioning to state TIDYING
+     *             will run the terminated() hook method
+     *   TERMINATED: terminated() has completed
+     *
+     * The numerical order among these values matters, to allow
+     * ordered comparisons. The runState monotonically increases over
+     * time, but need not hit each state. The transitions are:
+     *
+     * RUNNING -> SHUTDOWN
+     *    On invocation of shutdown(), perhaps implicitly in finalize()
+     * (RUNNING or SHUTDOWN) -> STOP
+     *    On invocation of shutdownNow()
+     * SHUTDOWN -> TIDYING
+     *    When both queue and pool are empty
+     * STOP -> TIDYING
+     *    When pool is empty
+     * TIDYING -> TERMINATED
+     *    When the terminated() hook method has completed
+     *
+     * Threads waiting in awaitTermination() will return when the
+     * state reaches TERMINATED.
+     *
+     * Detecting the transition from SHUTDOWN to TIDYING is less
+     * straightforward than you'd like because the queue may become
+     * empty after non-empty and vice versa during SHUTDOWN state, but
+     * we can only terminate if, after seeing that it is empty, we see
+     * that workerCount is 0 (which sometimes entails a recheck -- see
+     * below).
      */
-    private static final Runnable[] EMPTY_RUNNABLE_ARRAY = new Runnable[0];
+    private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
+    private static final int COUNT_BITS = Integer.SIZE - 3;
+    private static final int CAPACITY   = (1 << COUNT_BITS) - 1;
+
+    // runState is stored in the high-order bits
+    private static final int RUNNING    = -1 << COUNT_BITS;
+    private static final int SHUTDOWN   =  0 << COUNT_BITS;
+    private static final int STOP       =  1 << COUNT_BITS;
+    private static final int TIDYING    =  2 << COUNT_BITS;
+    private static final int TERMINATED =  3 << COUNT_BITS;
+
+    // Packing and unpacking ctl
+    private static int runStateOf(int c)     { return c & ~CAPACITY; }
+    private static int workerCountOf(int c)  { return c & CAPACITY; }
+    private static int ctlOf(int rs, int wc) { return rs | wc; }
+
+    /*
+     * Bit field accessors that don't require unpacking ctl.
+     * These depend on the bit layout and on workerCount being never negative.
+     */
+
+    private static boolean runStateLessThan(int c, int s) {
+        return c < s;
+    }
+
+    private static boolean runStateAtLeast(int c, int s) {
+        return c >= s;
+    }
+
+    private static boolean isRunning(int c) {
+        return c < SHUTDOWN;
+    }
 
     /**
-     * Permission for checking shutdown
+     * Attempt to CAS-increment the workerCount field of ctl.
      */
-    private static final RuntimePermission shutdownPerm =
-        new RuntimePermission("modifyThread");
+    private boolean compareAndIncrementWorkerCount(int expect) {
+        return ctl.compareAndSet(expect, expect + 1);
+    }
 
     /**
-     * Queue used for holding tasks and handing off to worker threads.
+     * Attempt to CAS-decrement the workerCount field of ctl.
+     */
+    private boolean compareAndDecrementWorkerCount(int expect) {
+        return ctl.compareAndSet(expect, expect - 1);
+    }
+
+    /**
+     * Decrements the workerCount field of ctl. This is called only on
+     * abrupt termination of a thread (see processWorkerExit). Other
+     * decrements are performed within getTask.
+     */
+    private void decrementWorkerCount() {
+        do {} while (! compareAndDecrementWorkerCount(ctl.get()));
+    }
+
+    /**
+     * The queue used for holding tasks and handing off to worker
+     * threads.  We do not require that workQueue.poll() returning
+     * null necessarily means that workQueue.isEmpty(), so rely
+     * solely on isEmpty to see if the queue is empty (which we must
+     * do for example when deciding whether to transition from
+     * SHUTDOWN to TIDYING).  This accommodates special-purpose
+     * queues such as DelayQueues for which poll() is allowed to
+     * return null even if it may later return non-null when delays
+     * expire.
      */
     private final BlockingQueue<Runnable> workQueue;
 
     /**
-     * Lock held on updates to poolSize, corePoolSize, maximumPoolSize, and
-     * workers set.
+     * Lock held on access to workers set and related bookkeeping.
+     * While we could use a concurrent set of some sort, it turns out
+     * to be generally preferable to use a lock. Among the reasons is
+     * that this serializes interruptIdleWorkers, which avoids
+     * unnecessary interrupt storms, especially during shutdown.
+     * Otherwise exiting threads would concurrently interrupt those
+     * that have not yet interrupted. It also simplifies some of the
+     * associated statistics bookkeeping of largestPoolSize etc. We
+     * also hold mainLock on shutdown and shutdownNow, for the sake of
+     * ensuring workers set is stable while separately checking
+     * permission to interrupt and actually interrupting.
      */
     private final ReentrantLock mainLock = new ReentrantLock();
 
     /**
+     * Set containing all worker threads in pool. Accessed only when
+     * holding mainLock.
+     */
+    private final HashSet<Worker> workers = new HashSet<Worker>();
+
+    /**
      * Wait condition to support awaitTermination
      */
     private final Condition termination = mainLock.newCondition();
 
     /**
-     * Set containing all worker threads in pool.
+     * Tracks largest attained pool size. Accessed only under
+     * mainLock.
      */
-    private final HashSet<Worker> workers = new HashSet<Worker>();
+    private int largestPoolSize;
 
     /**
-     * Timeout in nanoseconds for idle threads waiting for work.
-     * Threads use this timeout only when there are more than
-     * corePoolSize present. Otherwise they wait forever for new work.
+     * Counter for completed tasks. Updated only on termination of
+     * worker threads. Accessed only under mainLock.
      */
-    private volatile long  keepAliveTime;
+    private long completedTaskCount;
+
+    /*
+     * All user control parameters are declared as volatiles so that
+     * ongoing actions are based on freshest values, but without need
+     * for locking, since no internal invariants depend on them
+     * changing synchronously with respect to other actions.
+     */
 
     /**
-     * Core pool size, updated only while holding mainLock,
-     * but volatile to allow concurrent readability even
-     * during updates.
+     * Factory for new threads. All threads are created using this
+     * factory (via method addWorker).  All callers must be prepared
+     * for addWorker to fail, which may reflect a system or user's
+     * policy limiting the number of threads.  Even though it is not
+     * treated as an error, failure to create threads may result in
+     * new tasks being rejected or existing ones remaining stuck in
+     * the queue. On the other hand, no special precautions exist to
+     * handle OutOfMemoryErrors that might be thrown while trying to
+     * create threads, since there is generally no recourse from
+     * within this class.
      */
-    private volatile int   corePoolSize;
-
-    /**
-     * Maximum pool size, updated only while holding mainLock
-     * but volatile to allow concurrent readability even
-     * during updates.
-     */
-    private volatile int   maximumPoolSize;
-
-    /**
-     * Current pool size, updated only while holding mainLock
-     * but volatile to allow concurrent readability even
-     * during updates.
-     */
-    private volatile int   poolSize;
-
-    /**
-     * Lifecycle state
-     */
-    volatile int runState;
-
-    // Special values for runState
-    /** Normal, not-shutdown mode */
-    static final int RUNNING    = 0;
-    /** Controlled shutdown mode */
-    static final int SHUTDOWN   = 1;
-    /** Immediate shutdown mode */
-    static final int STOP       = 2;
-    /** Final state */
-    static final int TERMINATED = 3;
+    private volatile ThreadFactory threadFactory;
 
     /**
      * Handler called when saturated or shutdown in execute.
@@ -353,21 +471,24 @@
     private volatile RejectedExecutionHandler handler;
 
     /**
-     * Factory for new threads.
+     * Timeout in nanoseconds for idle threads waiting for work.
+     * Threads use this timeout when there are more than corePoolSize
+     * present. Otherwise they wait forever for new work.
      */
-    private volatile ThreadFactory threadFactory;
+    private volatile long keepAliveTime;
 
     /**
-     * Tracks largest attained pool size.
+     * Core pool size is the minimum number of workers to keep alive
+     * (and not allow to time out etc).
      */
-    private int largestPoolSize;
+    private volatile int corePoolSize;
 
     /**
-     * Counter for completed tasks. Updated only on termination of
-     * worker threads.
+     * Maximum pool size. Note that the actual maximum is internally
+     * bounded by CAPACITY.
      */
-    private long completedTaskCount;
-    
+    private volatile int maximumPoolSize;
+
     /**
      * The default rejected execution handler
      */
@@ -375,336 +496,622 @@
         new AbortPolicy();
 
     /**
-     * Invoke the rejected execution handler for the given command.
+     * Permission required for callers of shutdown and shutdownNow.
+     * We additionally require (see checkShutdownAccess) that callers
+     * have permission to actually interrupt threads in the worker set
+     * (as governed by Thread.interrupt, which relies on
+     * ThreadGroup.checkAccess, which in turn relies on
+     * SecurityManager.checkAccess). Shutdowns are attempted only if
+     * these checks pass.
+     *
+     * All actual invocations of Thread.interrupt (see
+     * interruptIdleWorkers and interruptWorkers) ignore
+     * SecurityExceptions, meaning that the attempted interrupts
+     * silently fail. In the case of shutdown, they should not fail
+     * unless the SecurityManager has inconsistent policies, sometimes
+     * allowing access to a thread and sometimes not. In such cases,
+     * failure to actually interrupt threads may disable or delay full
+     * termination. Other uses of interruptIdleWorkers are advisory,
+     * and failure to actually interrupt will merely delay response to
+     * configuration changes so is not handled exceptionally.
      */
-    void reject(Runnable command) {
+    private static final RuntimePermission shutdownPerm =
+        new RuntimePermission("modifyThread");
+
+    /**
+     * Class Worker mainly maintains interrupt control state for
+     * threads running tasks, along with other minor bookkeeping.
+     * This class opportunistically extends AbstractQueuedSynchronizer
+     * to simplify acquiring and releasing a lock surrounding each
+     * task execution.  This protects against interrupts that are
+     * intended to wake up a worker thread waiting for a task from
+     * instead interrupting a task being run.  We implement a simple
+     * non-reentrant mutual exclusion lock rather than use ReentrantLock
+     * because we do not want worker tasks to be able to reacquire the
+     * lock when they invoke pool control methods like setCorePoolSize.
+     */
+    private final class Worker
+        extends AbstractQueuedSynchronizer
+        implements Runnable
+    {
+        /**
+         * This class will never be serialized, but we provide a
+         * serialVersionUID to suppress a javac warning.
+         */
+        private static final long serialVersionUID = 6138294804551838833L;
+
+        /** Thread this worker is running in.  Null if factory fails. */
+        final Thread thread;
+        /** Initial task to run.  Possibly null. */
+        Runnable firstTask;
+        /** Per-thread task counter */
+        volatile long completedTasks;
+
+        /**
+         * Creates with given first task and thread from ThreadFactory.
+         * @param firstTask the first task (null if none)
+         */
+        Worker(Runnable firstTask) {
+            this.firstTask = firstTask;
+            this.thread = getThreadFactory().newThread(this);
+        }
+
+        /** Delegates main run loop to outer runWorker  */
+        public void run() {
+            runWorker(this);
+        }
+
+        // Lock methods
+        //
+        // The value 0 represents the unlocked state.
+        // The value 1 represents the locked state.
+
+        protected boolean isHeldExclusively() {
+            return getState() == 1;
+        }
+
+        protected boolean tryAcquire(int unused) {
+            if (compareAndSetState(0, 1)) {
+                setExclusiveOwnerThread(Thread.currentThread());
+                return true;
+            }
+            return false;
+        }
+
+        protected boolean tryRelease(int unused) {
+            setExclusiveOwnerThread(null);
+            setState(0);
+            return true;
+        }
+
+        public void lock()        { acquire(1); }
+        public boolean tryLock()  { return tryAcquire(1); }
+        public void unlock()      { release(1); }
+        public boolean isLocked() { return isHeldExclusively(); }
+    }
+
+    /*
+     * Methods for setting control state
+     */
+
+    /**
+     * Transitions runState to given target, or leaves it alone if
+     * already at least the given target.
+     *
+     * @param targetState the desired state, either SHUTDOWN or STOP
+     *        (but not TIDYING or TERMINATED -- use tryTerminate for that)
+     */
+    private void advanceRunState(int targetState) {
+        for (;;) {
+            int c = ctl.get();
+            if (runStateAtLeast(c, targetState) ||
+                ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))))
+                break;
+        }
+    }
+
+    /**
+     * Transitions to TERMINATED state if either (SHUTDOWN and pool
+     * and queue empty) or (STOP and pool empty).  If otherwise
+     * eligible to terminate but workerCount is nonzero, interrupts an
+     * idle worker to ensure that shutdown signals propagate. This
+     * method must be called following any action that might make
+     * termination possible -- reducing worker count or removing tasks
+     * from the queue during shutdown. The method is non-private to
+     * allow access from ScheduledThreadPoolExecutor.
+     */
+    final void tryTerminate() {
+        for (;;) {
+            int c = ctl.get();
+            if (isRunning(c) ||
+                runStateAtLeast(c, TIDYING) ||
+                (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
+                return;
+            if (workerCountOf(c) != 0) { // Eligible to terminate
+                interruptIdleWorkers(ONLY_ONE);
+                return;
+            }
+
+            final ReentrantLock mainLock = this.mainLock;
+            mainLock.lock();
+            try {
+                if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
+                    try {
+                        terminated();
+                    } finally {
+                        ctl.set(ctlOf(TERMINATED, 0));
+                        termination.signalAll();
+                    }
+                    return;
+                }
+            } finally {
+                mainLock.unlock();
+            }
+            // else retry on failed CAS
+        }
+    }
+
+    /*
+     * Methods for controlling interrupts to worker threads.
+     */
+
+    /**
+     * If there is a security manager, makes sure caller has
+     * permission to shut down threads in general (see shutdownPerm).
+     * If this passes, additionally makes sure the caller is allowed
+     * to interrupt each worker thread. This might not be true even if
+     * first check passed, if the SecurityManager treats some threads
+     * specially.
+     */
+    private void checkShutdownAccess() {
+        SecurityManager security = System.getSecurityManager();
+        if (security != null) {
+            security.checkPermission(shutdownPerm);
+            final ReentrantLock mainLock = this.mainLock;
+            mainLock.lock();
+            try {
+                for (Worker w : workers)
+                    security.checkAccess(w.thread);
+            } finally {
+                mainLock.unlock();
+            }
+        }
+    }
+
+    /**
+     * Interrupts all threads, even if active. Ignores SecurityExceptions
+     * (in which case some threads may remain uninterrupted).
+     */
+    private void interruptWorkers() {
+        final ReentrantLock mainLock = this.mainLock;
+        mainLock.lock();
+        try {
+            for (Worker w : workers) {
+                try {
+                    w.thread.interrupt();
+                } catch (SecurityException ignore) {
+                }
+            }
+        } finally {
+            mainLock.unlock();
+        }
+    }
+
+    /**
+     * Interrupts threads that might be waiting for tasks (as
+     * indicated by not being locked) so they can check for
+     * termination or configuration changes. Ignores
+     * SecurityExceptions (in which case some threads may remain
+     * uninterrupted).
+     *
+     * @param onlyOne If true, interrupt at most one worker. This is
+     * called only from tryTerminate when termination is otherwise
+     * enabled but there are still other workers.  In this case, at
+     * most one waiting worker is interrupted to propagate shutdown
+     * signals in case all threads are currently waiting.
+     * Interrupting any arbitrary thread ensures that newly arriving
+     * workers since shutdown began will also eventually exit.
+     * To guarantee eventual termination, it suffices to always
+     * interrupt only one idle worker, but shutdown() interrupts all
+     * idle workers so that redundant workers exit promptly, not
+     * waiting for a straggler task to finish.
+     */
+    private void interruptIdleWorkers(boolean onlyOne) {
+        final ReentrantLock mainLock = this.mainLock;
+        mainLock.lock();
+        try {
+            for (Worker w : workers) {
+                Thread t = w.thread;
+                if (!t.isInterrupted() && w.tryLock()) {
+                    try {
+                        t.interrupt();
+                    } catch (SecurityException ignore) {
+                    } finally {
+                        w.unlock();
+                    }
+                }
+                if (onlyOne)
+                    break;
+            }
+        } finally {
+            mainLock.unlock();
+        }
+    }
+
+    /**
+     * Common form of interruptIdleWorkers, to avoid having to
+     * remember what the boolean argument means.
+     */
+    private void interruptIdleWorkers() {
+        interruptIdleWorkers(false);
+    }
+
+    private static final boolean ONLY_ONE = true;
+
+    /**
+     * Ensures that unless the pool is stopping, the current thread
+     * does not have its interrupt set. This requires a double-check
+     * of state in case the interrupt was cleared concurrently with a
+     * shutdownNow -- if so, the interrupt is re-enabled.
+     */
+    private void clearInterruptsForTaskRun() {
+        if (runStateLessThan(ctl.get(), STOP) &&
+            Thread.interrupted() &&
+            runStateAtLeast(ctl.get(), STOP))
+            Thread.currentThread().interrupt();
+    }
+
+    /*
+     * Misc utilities, most of which are also exported to
+     * ScheduledThreadPoolExecutor
+     */
+
+    /**
+     * Invokes the rejected execution handler for the given command.
+     * Package-protected for use by ScheduledThreadPoolExecutor.
+     */
+    final void reject(Runnable command) {
         handler.rejectedExecution(command, this);
     }
 
     /**
-     * Create and return a new thread running firstTask as its first
-     * task. Call only while holding mainLock
-     * @param firstTask the task the new thread should run first (or
-     * null if none)
-     * @return the new thread
+     * Performs any further cleanup following run state transition on
+     * invocation of shutdown.  A no-op here, but used by
+     * ScheduledThreadPoolExecutor to cancel delayed tasks.
      */
-    private Thread addThread(Runnable firstTask) {
-        Worker w = new Worker(firstTask);
-        Thread t = threadFactory.newThread(w);
-        w.thread = t;
-        workers.add(w);
-        int nt = ++poolSize;
-        if (nt > largestPoolSize)
-            largestPoolSize = nt;
-        return t;
+    void onShutdown() {
     }
 
     /**
-     * Create and start a new thread running firstTask as its first
-     * task, only if fewer than corePoolSize threads are running.
-     * @param firstTask the task the new thread should run first (or
-     * null if none)
-     * @return true if successful.
+     * State check needed by ScheduledThreadPoolExecutor to
+     * enable running tasks during shutdown.
+     *
+     * @param shutdownOK true if should return true if SHUTDOWN
      */
-    private boolean addIfUnderCorePoolSize(Runnable firstTask) {
-        Thread t = null;
+    final boolean isRunningOrShutdown(boolean shutdownOK) {
+        int rs = runStateOf(ctl.get());
+        return rs == RUNNING || (rs == SHUTDOWN && shutdownOK);
+    }
+
+    /**
+     * Drains the task queue into a new list, normally using
+     * drainTo. But if the queue is a DelayQueue or any other kind of
+     * queue for which poll or drainTo may fail to remove some
+     * elements, it deletes them one by one.
+     */
+    private List<Runnable> drainQueue() {
+        BlockingQueue<Runnable> q = workQueue;
+        List<Runnable> taskList = new ArrayList<Runnable>();
+        q.drainTo(taskList);
+        if (!q.isEmpty()) {
+            for (Runnable r : q.toArray(new Runnable[0])) {
+                if (q.remove(r))
+                    taskList.add(r);
+            }
+        }
+        return taskList;
+    }
+
+    /*
+     * Methods for creating, running and cleaning up after workers
+     */
+
+    /**
+     * Checks if a new worker can be added with respect to current
+     * pool state and the given bound (either core or maximum). If so,
+     * the worker count is adjusted accordingly, and, if possible, a
+     * new worker is created and started running firstTask as its
+     * first task. This method returns false if the pool is stopped or
+     * eligible to shut down. It also returns false if the thread
+     * factory fails to create a thread when asked, which requires a
+     * backout of workerCount, and a recheck for termination, in case
+     * the existence of this worker was holding up termination.
+     *
+     * @param firstTask the task the new thread should run first (or
+     * null if none). Workers are created with an initial first task
+     * (in method execute()) to bypass queuing when there are fewer
+     * than corePoolSize threads (in which case we always start one),
+     * or when the queue is full (in which case we must bypass queue).
+     * Initially idle threads are usually created via
+     * prestartCoreThread or to replace other dying workers.
+     *
+     * @param core if true use corePoolSize as bound, else
+     * maximumPoolSize. (A boolean indicator is used here rather than a
+     * value to ensure reads of fresh values after checking other pool
+     * state).
+     * @return true if successful
+     */
+    private boolean addWorker(Runnable firstTask, boolean core) {
+        retry:
+        for (;;) {
+            int c = ctl.get();
+            int rs = runStateOf(c);
+
+            // Check if queue empty only if necessary.
+            if (rs >= SHUTDOWN &&
+                ! (rs == SHUTDOWN &&
+                   firstTask == null &&
+                   ! workQueue.isEmpty()))
+                return false;
+
+            for (;;) {
+                int wc = workerCountOf(c);
+                if (wc >= CAPACITY ||
+                    wc >= (core ? corePoolSize : maximumPoolSize))
+                    return false;
+                if (compareAndIncrementWorkerCount(c))
+                    break retry;
+                c = ctl.get();  // Re-read ctl
+                if (runStateOf(c) != rs)
+                    continue retry;
+                // else CAS failed due to workerCount change; retry inner loop
+            }
+        }
+
+        Worker w = new Worker(firstTask);
+        Thread t = w.thread;
+
         final ReentrantLock mainLock = this.mainLock;
         mainLock.lock();
         try {
-            if (poolSize < corePoolSize)
-                t = addThread(firstTask);
+            // Recheck while holding lock.
+            // Back out on ThreadFactory failure or if
+            // shut down before lock acquired.
+            int c = ctl.get();
+            int rs = runStateOf(c);
+
+            if (t == null ||
+                (rs >= SHUTDOWN &&
+                 ! (rs == SHUTDOWN &&
+                    firstTask == null))) {
+                decrementWorkerCount();
+                tryTerminate();
+                return false;
+            }
+
+            workers.add(w);
+
+            int s = workers.size();
+            if (s > largestPoolSize)
+                largestPoolSize = s;
         } finally {
             mainLock.unlock();
         }
-        if (t == null)
-            return false;
+
         t.start();
+        // It is possible (but unlikely) for a thread to have been
+        // added to workers, but not yet started, during transition to
+        // STOP, which could result in a rare missed interrupt,
+        // because Thread.interrupt is not guaranteed to have any effect
+        // on a non-yet-started Thread (see Thread#interrupt).
+        if (runStateOf(ctl.get()) == STOP && ! t.isInterrupted())
+            t.interrupt();
+
         return true;
     }
 
     /**
-     * Create and start a new thread only if fewer than maximumPoolSize
-     * threads are running.  The new thread runs as its first task the
-     * next task in queue, or if there is none, the given task.
-     * @param firstTask the task the new thread should run first (or
-     * null if none)
-     * @return null on failure, else the first task to be run by new thread.
-     */
-    private Runnable addIfUnderMaximumPoolSize(Runnable firstTask) {
-        Thread t = null;
-        Runnable next = null;
-        final ReentrantLock mainLock = this.mainLock;
-        mainLock.lock();
-        try {
-            if (poolSize < maximumPoolSize) {
-                next = workQueue.poll();
-                if (next == null)
-                    next = firstTask;
-                t = addThread(next);
-            }
-        } finally {
-            mainLock.unlock();
-        }
-        if (t == null)
-            return null;
-        t.start();
-        return next;
-    }
-
-
-    /**
-     * Get the next task for a worker thread to run.
-     * @return the task
-     * @throws InterruptedException if interrupted while waiting for task
-     */
-    Runnable getTask() throws InterruptedException {
-        for (;;) {
-            switch(runState) {
-            case RUNNING: {
-                if (poolSize <= corePoolSize)   // untimed wait if core
-                    return workQueue.take();
-                
-                long timeout = keepAliveTime;
-                if (timeout <= 0) // die immediately for 0 timeout
-                    return null;
-                Runnable r =  workQueue.poll(timeout, TimeUnit.NANOSECONDS);
-                if (r != null)
-                    return r;
-                if (poolSize > corePoolSize) // timed out
-                    return null;
-                // else, after timeout, pool shrank so shouldn't die, so retry
-                break;
-            }
-
-            case SHUTDOWN: {
-                // Help drain queue 
-                Runnable r = workQueue.poll();
-                if (r != null)
-                    return r;
-                    
-                // Check if can terminate
-                if (workQueue.isEmpty()) {
-                    interruptIdleWorkers();
-                    return null;
-                }
-
-                // There could still be delayed tasks in queue.
-                // Wait for one, re-checking state upon interruption
-                try {
-                    return workQueue.take();
-                } catch(InterruptedException ignore) {}
-                break;
-            }
-
-            case STOP:
-                return null;
-            default:
-                assert false; 
-            }
-        }
-    }
-
-    /**
-     * Wake up all threads that might be waiting for tasks.
-     */
-    void interruptIdleWorkers() {
-        final ReentrantLock mainLock = this.mainLock;
-        mainLock.lock();
-        try {
-            for (Worker w : workers)
-                w.interruptIfIdle();
-        } finally {
-            mainLock.unlock();
-        }
-    }
-
-    /**
-     * Perform bookkeeping for a terminated worker thread.
+     * Performs cleanup and bookkeeping for a dying worker. Called
+     * only from worker threads. Unless completedAbruptly is set,
+     * assumes that workerCount has already been adjusted to account
+     * for exit.  This method removes thread from worker set, and
+     * possibly terminates the pool or replaces the worker if either
+     * it exited due to user task exception or if fewer than
+     * corePoolSize workers are running or queue is non-empty but
+     * there are no workers.
+     *
      * @param w the worker
+     * @param completedAbruptly if the worker died due to user exception
      */
-    void workerDone(Worker w) {
+    private void processWorkerExit(Worker w, boolean completedAbruptly) {
+        if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
+            decrementWorkerCount();
+
         final ReentrantLock mainLock = this.mainLock;
         mainLock.lock();
         try {
             completedTaskCount += w.completedTasks;
             workers.remove(w);
-            if (--poolSize > 0)
-                return;
-
-            // Else, this is the last thread. Deal with potential shutdown.
-
-            int state = runState;
-            assert state != TERMINATED;
-
-            if (state != STOP) {
-                // If there are queued tasks but no threads, create
-                // replacement.
-                Runnable r = workQueue.poll();
-                if (r != null) {
-                    addThread(r).start();
-                    return;
-                }
-
-                // If there are some (presumably delayed) tasks but
-                // none pollable, create an idle replacement to wait.
-                if (!workQueue.isEmpty()) { 
-                    addThread(null).start();
-                    return;
-                }
-
-                // Otherwise, we can exit without replacement
-                if (state == RUNNING)
-                    return;
-            }
-
-            // Either state is STOP, or state is SHUTDOWN and there is
-            // no work to do. So we can terminate.
-            termination.signalAll();
-            runState = TERMINATED;
-            // fall through to call terminate() outside of lock.
         } finally {
             mainLock.unlock();
         }
 
-        assert runState == TERMINATED;
-        terminated(); 
+        tryTerminate();
+
+        int c = ctl.get();
+        if (runStateLessThan(c, STOP)) {
+            if (!completedAbruptly) {
+                int min = corePoolSize;
+                if (min == 0 && ! workQueue.isEmpty())
+                    min = 1;
+                if (workerCountOf(c) >= min)
+                    return; // replacement not needed
+            }
+            addWorker(null, false);
+        }
     }
 
     /**
-     *  Worker threads
-     */
-    private class Worker implements Runnable {
-
-        /**
-         * The runLock is acquired and released surrounding each task
-         * execution. It mainly protects against interrupts that are
-         * intended to cancel the worker thread from instead
-         * interrupting the task being run.
-         */
-        private final ReentrantLock runLock = new ReentrantLock();
-
-        /**
-         * Initial task to run before entering run loop
-         */
-        private Runnable firstTask;
-
-        /**
-         * Per thread completed task counter; accumulated
-         * into completedTaskCount upon termination.
-         */
-        volatile long completedTasks;
-
-        /**
-         * Thread this worker is running in.  Acts as a final field,
-         * but cannot be set until thread is created.
-         */
-        Thread thread;
-
-        Worker(Runnable firstTask) {
-            this.firstTask = firstTask;
-        }
-
-        boolean isActive() {
-            return runLock.isLocked();
-        }
-
-        /**
-         * Interrupt thread if not running a task
-         */
-        void interruptIfIdle() {
-            final ReentrantLock runLock = this.runLock;
-            if (runLock.tryLock()) {
-                try {
-                    thread.interrupt();
-                } finally {
-                    runLock.unlock();
-                }
-            }
-        }
-
-        /**
-         * Cause thread to die even if running a task.
-         */
-        void interruptNow() {
-            thread.interrupt();
-        }
-
-        /**
-         * Run a single task between before/after methods.
-         */
-        private void runTask(Runnable task) {
-            final ReentrantLock runLock = this.runLock;
-            runLock.lock();
-            try {
-                // Abort now if immediate cancel.  Otherwise, we have
-                // committed to run this task.
-                if (runState == STOP)
-                    return;
-
-                Thread.interrupted(); // clear interrupt status on entry
-                boolean ran = false;
-                beforeExecute(thread, task);
-                try {
-                    task.run();
-                    ran = true;
-                    afterExecute(task, null);
-                    ++completedTasks;
-                } catch(RuntimeException ex) {
-                    if (!ran)
-                        afterExecute(task, ex);
-                    // Else the exception occurred within
-                    // afterExecute itself in which case we don't
-                    // want to call it again.
-                    throw ex;
-                }
-            } finally {
-                runLock.unlock();
-            }
-        }
-
-        /**
-         * Main run loop
-         */
-        public void run() {
-            try {
-                Runnable task = firstTask;
-                firstTask = null;
-                while (task != null || (task = getTask()) != null) {
-                    runTask(task);
-                    task = null; // unnecessary but can help GC
-                }
-            } catch(InterruptedException ie) {
-                // fall through
-            } finally {
-                workerDone(this);
-            }
-        }
-    }
-
-    // Public methods
-
-    /**
-     * Creates a new <tt>ThreadPoolExecutor</tt> with the given
-     * initial parameters and default thread factory and handler.  It
-     * may be more convenient to use one of the {@link Executors}
-     * factory methods instead of this general purpose constructor.
+     * Performs blocking or timed wait for a task, depending on
+     * current configuration settings, or returns null if this worker
+     * must exit because of any of:
+     * 1. There are more than maximumPoolSize workers (due to
+     *    a call to setMaximumPoolSize).
+     * 2. The pool is stopped.
+     * 3. The pool is shutdown and the queue is empty.
+     * 4. This worker timed out waiting for a task, and timed-out
+     *    workers are subject to termination (that is,
+     *    {@code workerCount > corePoolSize})
+     *    both before and after the timed wait.
      *
-     * @param corePoolSize the number of threads to keep in the
-     * pool, even if they are idle.
+     * @return task, or null if the worker must exit, in which case
+     *         workerCount is decremented
+     */
+    private Runnable getTask() {
+        boolean timedOut = false; // Did the last poll() time out?
+
+        retry:
+        for (;;) {
+            int c = ctl.get();
+            int rs = runStateOf(c);
+
+            // Check if queue empty only if necessary.
+            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
+                decrementWorkerCount();
+                return null;
+            }
+
+            boolean timed;      // Are workers subject to culling?
+
+            for (;;) {
+                int wc = workerCountOf(c);
+                timed = wc > corePoolSize;
+
+                if (wc <= maximumPoolSize && ! (timedOut && timed))
+                    break;
+                if (compareAndDecrementWorkerCount(c))
+                    return null;
+                c = ctl.get();  // Re-read ctl
+                if (runStateOf(c) != rs)
+                    continue retry;
+                // else CAS failed due to workerCount change; retry inner loop
+            }
+
+            try {
+                Runnable r = timed ?
+                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
+                    workQueue.take();
+                if (r != null)
+                    return r;
+                timedOut = true;
+            } catch (InterruptedException retry) {
+                timedOut = false;
+            }
+        }
+    }
+
+    /**
+     * Main worker run loop.  Repeatedly gets tasks from queue and
+     * executes them, while coping with a number of issues:
+     *
+     * 1. We may start out with an initial task, in which case we
+     * don't need to get the first one. Otherwise, as long as pool is
+     * running, we get tasks from getTask. If it returns null then the
+     * worker exits due to changed pool state or configuration
+     * parameters.  Other exits result from exception throws in
+     * external code, in which case completedAbruptly holds, which
+     * usually leads processWorkerExit to replace this thread.
+     *
+     * 2. Before running any task, the lock is acquired to prevent
+     * other pool interrupts while the task is executing, and
+     * clearInterruptsForTaskRun called to ensure that unless pool is
+     * stopping, this thread does not have its interrupt set.
+     *
+     * 3. Each task run is preceded by a call to beforeExecute, which
+     * might throw an exception, in which case we cause thread to die
+     * (breaking loop with completedAbruptly true) without processing
+     * the task.
+     *
+     * 4. Assuming beforeExecute completes normally, we run the task,
+     * gathering any of its thrown exceptions to send to
+     * afterExecute. We separately handle RuntimeException, Error
+     * (both of which the specs guarantee that we trap) and arbitrary
+     * Throwables.  Because we cannot rethrow Throwables within
+     * Runnable.run, we wrap them within Errors on the way out (to the
+     * thread's UncaughtExceptionHandler).  Any thrown exception also
+     * conservatively causes thread to die.
+     *
+     * 5. After task.run completes, we call afterExecute, which may
+     * also throw an exception, which will also cause thread to
+     * die. According to JLS Sec 14.20, this exception is the one that
+     * will be in effect even if task.run throws.
+     *
+     * The net effect of the exception mechanics is that afterExecute
+     * and the thread's UncaughtExceptionHandler have as accurate
+     * information as we can provide about any problems encountered by
+     * user code.
+     *
+     * @param w the worker
+     */
+    final void runWorker(Worker w) {
+        Runnable task = w.firstTask;
+        w.firstTask = null;
+        boolean completedAbruptly = true;
+        try {
+            while (task != null || (task = getTask()) != null) {
+                w.lock();
+                clearInterruptsForTaskRun();
+                try {
+                    beforeExecute(w.thread, task);
+                    Throwable thrown = null;
+                    try {
+                        task.run();
+                    } catch (RuntimeException x) {
+                        thrown = x; throw x;
+                    } catch (Error x) {
+                        thrown = x; throw x;
+                    } catch (Throwable x) {
+                        thrown = x; throw new Error(x);
+                    } finally {
+                        afterExecute(task, thrown);
+                    }
+                } finally {
+                    task = null;
+                    w.completedTasks++;
+                    w.unlock();
+                }
+            }
+            completedAbruptly = false;
+        } finally {
+            processWorkerExit(w, completedAbruptly);
+        }
+    }
+
+    // Public constructors and methods
+
+    /**
+     * Creates a new {@code ThreadPoolExecutor} with the given initial
+     * parameters and default thread factory and rejected execution handler.
+     * It may be more convenient to use one of the {@link Executors} factory
+     * methods instead of this general purpose constructor.
+     *
+     * @param corePoolSize the number of threads to keep in the pool, even
+     *        if they are idle
      * @param maximumPoolSize the maximum number of threads to allow in the
-     * pool.
+     *        pool
      * @param keepAliveTime when the number of threads is greater than
-     * the core, this is the maximum time that excess idle threads
-     * will wait for new tasks before terminating.
-     * @param unit the time unit for the keepAliveTime
-     * argument.
-     * @param workQueue the queue to use for holding tasks before they
-     * are executed. This queue will hold only the <tt>Runnable</tt>
-     * tasks submitted by the <tt>execute</tt> method.
-     * @throws IllegalArgumentException if corePoolSize, or
-     * keepAliveTime less than zero, or if maximumPoolSize less than or
-     * equal to zero, or if corePoolSize greater than maximumPoolSize.
-     * @throws NullPointerException if <tt>workQueue</tt> is null
+     *        the core, this is the maximum time that excess idle threads
+     *        will wait for new tasks before terminating.
+     * @param unit the time unit for the {@code keepAliveTime} argument
+     * @param workQueue the queue to use for holding tasks before they are
+     *        executed.  This queue will hold only the {@code Runnable}
+     *        tasks submitted by the {@code execute} method.
+     * @throws IllegalArgumentException if one of the following holds:<br>
+     *         {@code corePoolSize < 0}<br>
+     *         {@code keepAliveTime < 0}<br>
+     *         {@code maximumPoolSize <= 0}<br>
+     *         {@code maximumPoolSize < corePoolSize}
+     * @throws NullPointerException if {@code workQueue} is null
      */
     public ThreadPoolExecutor(int corePoolSize,
                               int maximumPoolSize,
@@ -716,28 +1123,29 @@
     }
 
     /**
-     * Creates a new <tt>ThreadPoolExecutor</tt> with the given initial
-     * parameters.
+     * Creates a new {@code ThreadPoolExecutor} with the given initial
+     * parameters and default rejected execution handler.
      *
-     * @param corePoolSize the number of threads to keep in the
-     * pool, even if they are idle.
+     * @param corePoolSize the number of threads to keep in the pool, even
+     *        if they are idle
      * @param maximumPoolSize the maximum number of threads to allow in the
-     * pool.
+     *        pool
      * @param keepAliveTime when the number of threads is greater than
-     * the core, this is the maximum time that excess idle threads
-     * will wait for new tasks before terminating.
-     * @param unit the time unit for the keepAliveTime
-     * argument.
-     * @param workQueue the queue to use for holding tasks before they
-     * are executed. This queue will hold only the <tt>Runnable</tt>
-     * tasks submitted by the <tt>execute</tt> method.
+     *        the core, this is the maximum time that excess idle threads
+     *        will wait for new tasks before terminating.
+     * @param unit the time unit for the {@code keepAliveTime} argument
+     * @param workQueue the queue to use for holding tasks before they are
+     *        executed.  This queue will hold only the {@code Runnable}
+     *        tasks submitted by the {@code execute} method.
      * @param threadFactory the factory to use when the executor
-     * creates a new thread.
-     * @throws IllegalArgumentException if corePoolSize, or
-     * keepAliveTime less than zero, or if maximumPoolSize less than or
-     * equal to zero, or if corePoolSize greater than maximumPoolSize.
-     * @throws NullPointerException if <tt>workQueue</tt>
-     * or <tt>threadFactory</tt> are null.
+     *        creates a new thread
+     * @throws IllegalArgumentException if one of the following holds:<br>
+     *         {@code corePoolSize < 0}<br>
+     *         {@code keepAliveTime < 0}<br>
+     *         {@code maximumPoolSize <= 0}<br>
+     *         {@code maximumPoolSize < corePoolSize}
+     * @throws NullPointerException if {@code workQueue}
+     *         or {@code threadFactory} is null
      */
     public ThreadPoolExecutor(int corePoolSize,
                               int maximumPoolSize,
@@ -750,28 +1158,29 @@
     }
 
     /**
-     * Creates a new <tt>ThreadPoolExecutor</tt> with the given initial
-     * parameters.
+     * Creates a new {@code ThreadPoolExecutor} with the given initial
+     * parameters and default thread factory.
      *
-     * @param corePoolSize the number of threads to keep in the
-     * pool, even if they are idle.
+     * @param corePoolSize the number of threads to keep in the pool, even
+     *        if they are idle
      * @param maximumPoolSize the maximum number of threads to allow in the
-     * pool.
+     *        pool
      * @param keepAliveTime when the number of threads is greater than
-     * the core, this is the maximum time that excess idle threads
-     * will wait for new tasks before terminating.
-     * @param unit the time unit for the keepAliveTime
-     * argument.
-     * @param workQueue the queue to use for holding tasks before they
-     * are executed. This queue will hold only the <tt>Runnable</tt>
-     * tasks submitted by the <tt>execute</tt> method.
+     *        the core, this is the maximum time that excess idle threads
+     *        will wait for new tasks before terminating.
+     * @param unit the time unit for the {@code keepAliveTime} argument
+     * @param workQueue the queue to use for holding tasks before they are
+     *        executed.  This queue will hold only the {@code Runnable}
+     *        tasks submitted by the {@code execute} method.
      * @param handler the handler to use when execution is blocked
-     * because the thread bounds and queue capacities are reached.
-     * @throws IllegalArgumentException if corePoolSize, or
-     * keepAliveTime less than zero, or if maximumPoolSize less than or
-     * equal to zero, or if corePoolSize greater than maximumPoolSize.
-     * @throws NullPointerException if <tt>workQueue</tt>
-     * or  <tt>handler</tt> are null.
+     *        because the thread bounds and queue capacities are reached
+     * @throws IllegalArgumentException if one of the following holds:<br>
+     *         {@code corePoolSize < 0}<br>
+     *         {@code keepAliveTime < 0}<br>
+     *         {@code maximumPoolSize <= 0}<br>
+     *         {@code maximumPoolSize < corePoolSize}
+     * @throws NullPointerException if {@code workQueue}
+     *         or {@code handler} is null
      */
     public ThreadPoolExecutor(int corePoolSize,
                               int maximumPoolSize,
@@ -784,30 +1193,31 @@
     }
 
     /**
-     * Creates a new <tt>ThreadPoolExecutor</tt> with the given initial
+     * Creates a new {@code ThreadPoolExecutor} with the given initial
      * parameters.
      *
-     * @param corePoolSize the number of threads to keep in the
-     * pool, even if they are idle.
+     * @param corePoolSize the number of threads to keep in the pool, even
+     *        if they are idle
      * @param maximumPoolSize the maximum number of threads to allow in the
-     * pool.
+     *        pool
      * @param keepAliveTime when the number of threads is greater than
-     * the core, this is the maximum time that excess idle threads
-     * will wait for new tasks before terminating.
-     * @param unit the time unit for the keepAliveTime
-     * argument.
-     * @param workQueue the queue to use for holding tasks before they
-     * are executed. This queue will hold only the <tt>Runnable</tt>
-     * tasks submitted by the <tt>execute</tt> method.
+     *        the core, this is the maximum time that excess idle threads
+     *        will wait for new tasks before terminating.
+     * @param unit the time unit for the {@code keepAliveTime} argument
+     * @param workQueue the queue to use for holding tasks before they are
+     *        executed.  This queue will hold only the {@code Runnable}
+     *        tasks submitted by the {@code execute} method.
      * @param threadFactory the factory to use when the executor
-     * creates a new thread.
+     *        creates a new thread
      * @param handler the handler to use when execution is blocked
-     * because the thread bounds and queue capacities are reached.
-     * @throws IllegalArgumentException if corePoolSize, or
-     * keepAliveTime less than zero, or if maximumPoolSize less than or
-     * equal to zero, or if corePoolSize greater than maximumPoolSize.
-     * @throws NullPointerException if <tt>workQueue</tt>
-     * or <tt>threadFactory</tt> or <tt>handler</tt> are null.
+     *        because the thread bounds and queue capacities are reached
+     * @throws IllegalArgumentException if one of the following holds:<br>
+     *         {@code corePoolSize < 0}<br>
+     *         {@code keepAliveTime < 0}<br>
+     *         {@code maximumPoolSize <= 0}<br>
+     *         {@code maximumPoolSize < corePoolSize}
+     * @throws NullPointerException if {@code workQueue}
+     *         or {@code threadFactory} or {@code handler} is null
      */
     public ThreadPoolExecutor(int corePoolSize,
                               int maximumPoolSize,
@@ -831,181 +1241,140 @@
         this.handler = handler;
     }
 
-
     /**
      * Executes the given task sometime in the future.  The task
      * may execute in a new thread or in an existing pooled thread.
      *
      * If the task cannot be submitted for execution, either because this
      * executor has been shutdown or because its capacity has been reached,
-     * the task is handled by the current <tt>RejectedExecutionHandler</tt>.
+     * the task is handled by the current {@code RejectedExecutionHandler}.
      *
      * @param command the task to execute
      * @throws RejectedExecutionException at discretion of
-     * <tt>RejectedExecutionHandler</tt>, if task cannot be accepted
-     * for execution
-     * @throws NullPointerException if command is null
+     *         {@code RejectedExecutionHandler}, if the task
+     *         cannot be accepted for execution
+     * @throws NullPointerException if {@code command} is null
      */
     public void execute(Runnable command) {
         if (command == null)
             throw new NullPointerException();
-        for (;;) {
-            if (runState != RUNNING) {
-                reject(command);
+        /*
+         * Proceed in 3 steps:
+         *
+         * 1. If fewer than corePoolSize threads are running, try to
+         * start a new thread with the given command as its first
+         * task.  The call to addWorker atomically checks runState and
+         * workerCount, and so prevents false alarms that would add
+         * threads when it shouldn't, by returning false.
+         *
+         * 2. If a task can be successfully queued, then we still need
+         * to double-check whether we should have added a thread
+         * (because existing ones died since last checking) or that
+         * the pool shut down since entry into this method. So we
+         * recheck state and if necessary roll back the enqueuing if
+         * stopped, or start a new thread if there are none.
+         *
+         * 3. If we cannot queue task, then we try to add a new
+         * thread.  If it fails, we know we are shut down or saturated
+         * and so reject the task.
+         */
+        int c = ctl.get();
+        if (workerCountOf(c) < corePoolSize) {
+            if (addWorker(command, true))
                 return;
-            }
-            if (poolSize < corePoolSize && addIfUnderCorePoolSize(command))
-                return;
-            if (workQueue.offer(command))
-                return;
-            Runnable r = addIfUnderMaximumPoolSize(command);
-            if (r == command)
-                return;
-            if (r == null) {
-                reject(command);
-                return;
-            }
-            // else retry
+            c = ctl.get();
         }
+        if (isRunning(c) && workQueue.offer(command)) {
+            int recheck = ctl.get();
+            if (! isRunning(recheck) && remove(command))
+                reject(command);
+            else if (workerCountOf(recheck) == 0)
+                addWorker(null, false);
+        }
+        else if (!addWorker(command, false))
+            reject(command);
     }
 
     /**
      * Initiates an orderly shutdown in which previously submitted
-     * tasks are executed, but no new tasks will be
-     * accepted. Invocation has no additional effect if already shut
-     * down.
-     * @throws SecurityException if a security manager exists and
-     * shutting down this ExecutorService may manipulate threads that
-     * the caller is not permitted to modify because it does not hold
-     * {@link java.lang.RuntimePermission}<tt>("modifyThread")</tt>,
-     * or the security manager's <tt>checkAccess</tt>  method denies access.
+     * tasks are executed, but no new tasks will be accepted.
+     * Invocation has no additional effect if already shut down.
+     *
+     * <p>This method does not wait for previously submitted tasks to
+     * complete execution.  Use {@link #awaitTermination awaitTermination}
+     * to do that.
+     *
+     * @throws SecurityException {@inheritDoc}
      */
     public void shutdown() {
-        // Fail if caller doesn't have modifyThread permission
-        SecurityManager security = System.getSecurityManager();
-        if (security != null) 
-            java.security.AccessController.checkPermission(shutdownPerm);
-
-        boolean fullyTerminated = false;
         final ReentrantLock mainLock = this.mainLock;
         mainLock.lock();
         try {
-            if (workers.size() > 0) {
-                // Check if caller can modify worker threads.  This
-                // might not be true even if passed above check, if
-                // the SecurityManager treats some threads specially.
-                if (security != null) {
-                    for (Worker w: workers)
-                        security.checkAccess(w.thread);
-                }
-
-                int state = runState;
-                if (state == RUNNING) // don't override shutdownNow
-                    runState = SHUTDOWN;
-
-                try {
-                    for (Worker w: workers)
-                        w.interruptIfIdle();
-                } catch(SecurityException se) {
-                    // If SecurityManager allows above checks, but
-                    // then unexpectedly throws exception when
-                    // interrupting threads (which it ought not do),
-                    // back out as cleanly as we can. Some threads may
-                    // have been killed but we remain in non-shutdown
-                    // state.
-                    runState = state; 
-                    throw se;
-                }
-            }
-            else { // If no workers, trigger full termination now
-                fullyTerminated = true;
-                runState = TERMINATED;
-                termination.signalAll();
-            }
+            checkShutdownAccess();
+            advanceRunState(SHUTDOWN);
+            interruptIdleWorkers();
+            onShutdown(); // hook for ScheduledThreadPoolExecutor
         } finally {
             mainLock.unlock();
         }
-        if (fullyTerminated)
-            terminated();
+        tryTerminate();
     }
 
-
     /**
      * Attempts to stop all actively executing tasks, halts the
-     * processing of waiting tasks, and returns a list of the tasks that were
-     * awaiting execution. 
-     *  
-     * <p>This implementation cancels tasks via {@link
-     * Thread#interrupt}, so if any tasks mask or fail to respond to
-     * interrupts, they may never terminate.
+     * processing of waiting tasks, and returns a list of the tasks
+     * that were awaiting execution. These tasks are drained (removed)
+     * from the task queue upon return from this method.
      *
-     * @return list of tasks that never commenced execution
-     * @throws SecurityException if a security manager exists and
-     * shutting down this ExecutorService may manipulate threads that
-     * the caller is not permitted to modify because it does not hold
-     * {@link java.lang.RuntimePermission}<tt>("modifyThread")</tt>,
-     * or the security manager's <tt>checkAccess</tt> method denies access.
+     * <p>This method does not wait for actively executing tasks to
+     * terminate.  Use {@link #awaitTermination awaitTermination} to
+     * do that.
+     *
+     * <p>There are no guarantees beyond best-effort attempts to stop
+     * processing actively executing tasks.  This implementation
+     * cancels tasks via {@link Thread#interrupt}, so any task that
+     * fails to respond to interrupts may never terminate.
+     *
+     * @throws SecurityException {@inheritDoc}
      */
     public List<Runnable> shutdownNow() {
-        // Almost the same code as shutdown()
-        SecurityManager security = System.getSecurityManager();
-        if (security != null) 
-            java.security.AccessController.checkPermission(shutdownPerm);
-
-        boolean fullyTerminated = false;
+        List<Runnable> tasks;
         final ReentrantLock mainLock = this.mainLock;
         mainLock.lock();
         try {
-            if (workers.size() > 0) {
-                if (security != null) {
-                    for (Worker w: workers)
-                        security.checkAccess(w.thread);
-                }
-
-                int state = runState;
-                if (state != TERMINATED)
-                    runState = STOP;
-                try {
-                    for (Worker w : workers)
-                        w.interruptNow();
-                } catch(SecurityException se) {
-                    runState = state; // back out;
-                    throw se;
-                }
-            }
-            else { // If no workers, trigger full termination now
-                fullyTerminated = true;
-                runState = TERMINATED;
-                termination.signalAll();
-            }
+            checkShutdownAccess();
+            advanceRunState(STOP);
+            interruptWorkers();
+            tasks = drainQueue();
         } finally {
             mainLock.unlock();
         }
-        if (fullyTerminated)
-            terminated();
-        return Arrays.asList(workQueue.toArray(EMPTY_RUNNABLE_ARRAY));
+        tryTerminate();
+        return tasks;
     }
 
     public boolean isShutdown() {
-        return runState != RUNNING;
+        return ! isRunning(ctl.get());
     }
 
-    /** 
+    /**
      * Returns true if this executor is in the process of terminating
-     * after <tt>shutdown</tt> or <tt>shutdownNow</tt> but has not
+     * after {@link #shutdown} or {@link #shutdownNow} but has not
      * completely terminated.  This method may be useful for
-     * debugging. A return of <tt>true</tt> reported a sufficient
+     * debugging. A return of {@code true} reported a sufficient
      * period after shutdown may indicate that submitted tasks have
      * ignored or suppressed interruption, causing this executor not
      * to properly terminate.
-     * @return true if terminating but not yet terminated.
+     *
+     * @return true if terminating but not yet terminated
      */
     public boolean isTerminating() {
-        return runState == STOP;
+        int c = ctl.get();
+        return ! isRunning(c) && runStateLessThan(c, TERMINATED);
     }
 
     public boolean isTerminated() {
-        return runState == TERMINATED;
+        return runStateAtLeast(ctl.get(), TERMINATED);
     }
 
     public boolean awaitTermination(long timeout, TimeUnit unit)
@@ -1015,7 +1384,7 @@
         mainLock.lock();
         try {
             for (;;) {
-                if (runState == TERMINATED) 
+                if (runStateAtLeast(ctl.get(), TERMINATED))
                     return true;
                 if (nanos <= 0)
                     return false;
@@ -1027,10 +1396,10 @@
     }
 
     /**
-     * Invokes <tt>shutdown</tt> when this executor is no longer
-     * referenced.
-     */ 
-    protected void finalize()  {
+     * Invokes {@code shutdown} when this executor is no longer
+     * referenced and it has no threads.
+     */
+    protected void finalize() {
         shutdown();
     }
 
@@ -1081,103 +1450,33 @@
     }
 
     /**
-     * Returns the task queue used by this executor. Access to the
-     * task queue is intended primarily for debugging and monitoring.
-     * This queue may be in active use.  Retrieving the task queue
-     * does not prevent queued tasks from executing.
-     *
-     * @return the task queue
-     */
-    public BlockingQueue<Runnable> getQueue() {
-        return workQueue;
-    }
-
-    /**
-     * Removes this task from the executor's internal queue if it is
-     * present, thus causing it not to be run if it has not already
-     * started.
-     * 
-     * <p> This method may be useful as one part of a cancellation
-     * scheme.  It may fail to remove tasks that have been converted
-     * into other forms before being placed on the internal queue. For
-     * example, a task entered using <tt>submit</tt> might be
-     * converted into a form that maintains <tt>Future</tt> status.
-     * However, in such cases, method {@link ThreadPoolExecutor#purge}
-     * may be used to remove those Futures that have been cancelled.
-     * 
-     *
-     * @param task the task to remove
-     * @return true if the task was removed
-     */
-    public boolean remove(Runnable task) {
-        return getQueue().remove(task);
-    }
-
-
-    /**
-     * Tries to remove from the work queue all {@link Future}
-     * tasks that have been cancelled. This method can be useful as a
-     * storage reclamation operation, that has no other impact on
-     * functionality. Cancelled tasks are never executed, but may
-     * accumulate in work queues until worker threads can actively
-     * remove them. Invoking this method instead tries to remove them now.
-     * However, this method may fail to remove tasks in
-     * the presence of interference by other threads.
-     */
-    public void purge() {
-        // Fail if we encounter interference during traversal
-        try {
-            Iterator<Runnable> it = getQueue().iterator();
-            while (it.hasNext()) {
-                Runnable r = it.next();
-                if (r instanceof Future<?>) {
-                    Future<?> c = (Future<?>)r;
-                    if (c.isCancelled())
-                        it.remove();
-                }
-            }
-        }
-        catch(ConcurrentModificationException ex) {
-            return; 
-        }
-    }
-
-    /**
      * Sets the core number of threads.  This overrides any value set
      * in the constructor.  If the new value is smaller than the
      * current value, excess existing threads will be terminated when
-     * they next become idle. If larger, new threads will, if needed,
+     * they next become idle.  If larger, new threads will, if needed,
      * be started to execute any queued tasks.
      *
      * @param corePoolSize the new core size
-     * @throws IllegalArgumentException if <tt>corePoolSize</tt>
-     * less than zero
+     * @throws IllegalArgumentException if {@code corePoolSize < 0}
      * @see #getCorePoolSize
      */
     public void setCorePoolSize(int corePoolSize) {
         if (corePoolSize < 0)
             throw new IllegalArgumentException();
-        final ReentrantLock mainLock = this.mainLock;
-        mainLock.lock();
-        try {
-            int extra = this.corePoolSize - corePoolSize;
-            this.corePoolSize = corePoolSize;
-            if (extra < 0) {
-                Runnable r;
-                while (extra++ < 0 && poolSize < corePoolSize &&
-                       (r = workQueue.poll()) != null)
-                    addThread(r).start();
+        int delta = corePoolSize - this.corePoolSize;
+        this.corePoolSize = corePoolSize;
+        if (workerCountOf(ctl.get()) > corePoolSize)
+            interruptIdleWorkers();
+        else if (delta > 0) {
+            // We don't really know how many new threads are "needed".
+            // As a heuristic, prestart enough new workers (up to new
+            // core size) to handle the current number of tasks in
+            // queue, but stop if queue becomes empty while doing so.
+            int k = Math.min(delta, workQueue.size());
+            while (k-- > 0 && addWorker(null, true)) {
+                if (workQueue.isEmpty())
+                    break;
             }
-            else if (extra > 0 && poolSize > corePoolSize) {
-                Iterator<Worker> it = workers.iterator();
-                while (it.hasNext() &&
-                       extra-- > 0 &&
-                       poolSize > corePoolSize &&
-                       workQueue.remainingCapacity() == 0) 
-                    it.next().interruptIfIdle();
-            }
-        } finally {
-            mainLock.unlock();
         }
     }
 
@@ -1194,23 +1493,26 @@
     /**
      * Starts a core thread, causing it to idly wait for work. This
      * overrides the default policy of starting core threads only when
-     * new tasks are executed. This method will return <tt>false</tt>
+     * new tasks are executed. This method will return {@code false}
      * if all core threads have already been started.
-     * @return true if a thread was started
-     */ 
+     *
+     * @return {@code true} if a thread was started
+     */
     public boolean prestartCoreThread() {
-        return addIfUnderCorePoolSize(null);
+        return workerCountOf(ctl.get()) < corePoolSize &&
+            addWorker(null, true);
     }
 
     /**
      * Starts all core threads, causing them to idly wait for work. This
      * overrides the default policy of starting core threads only when
-     * new tasks are executed. 
-     * @return the number of threads started.
-     */ 
+     * new tasks are executed.
+     *
+     * @return the number of threads started
+     */
     public int prestartAllCoreThreads() {
         int n = 0;
-        while (addIfUnderCorePoolSize(null))
+        while (addWorker(null, true))
             ++n;
         return n;
     }
@@ -1222,30 +1524,17 @@
      * terminated when they next become idle.
      *
      * @param maximumPoolSize the new maximum
-     * @throws IllegalArgumentException if maximumPoolSize less than zero or
-     * the {@link #getCorePoolSize core pool size}
+     * @throws IllegalArgumentException if the new maximum is
+     *         less than or equal to zero, or
+     *         less than the {@linkplain #getCorePoolSize core pool size}
      * @see #getMaximumPoolSize
      */
     public void setMaximumPoolSize(int maximumPoolSize) {
         if (maximumPoolSize <= 0 || maximumPoolSize < corePoolSize)
             throw new IllegalArgumentException();
-        final ReentrantLock mainLock = this.mainLock;
-        mainLock.lock();
-        try {
-            int extra = this.maximumPoolSize - maximumPoolSize;
-            this.maximumPoolSize = maximumPoolSize;
-            if (extra > 0 && poolSize > maximumPoolSize) {
-                Iterator<Worker> it = workers.iterator();
-                while (it.hasNext() &&
-                       extra > 0 &&
-                       poolSize > maximumPoolSize) {
-                    it.next().interruptIfIdle();
-                    --extra;
-                }
-            }
-        } finally {
-            mainLock.unlock();
-        }
+        this.maximumPoolSize = maximumPoolSize;
+        if (workerCountOf(ctl.get()) > maximumPoolSize)
+            interruptIdleWorkers();
     }
 
     /**
@@ -1264,21 +1553,27 @@
      * threads currently in the pool, after waiting this amount of
      * time without processing a task, excess threads will be
      * terminated.  This overrides any value set in the constructor.
+     *
      * @param time the time to wait.  A time value of zero will cause
-     * excess threads to terminate immediately after executing tasks.
-     * @param unit  the time unit of the time argument
-     * @throws IllegalArgumentException if time less than zero
+     *        excess threads to terminate immediately after executing tasks.
+     * @param unit the time unit of the {@code time} argument
+     * @throws IllegalArgumentException if {@code time} less than zero or
+     *         if {@code time} is zero and {@code allowsCoreThreadTimeOut}
      * @see #getKeepAliveTime
      */
     public void setKeepAliveTime(long time, TimeUnit unit) {
         if (time < 0)
             throw new IllegalArgumentException();
-        this.keepAliveTime = unit.toNanos(time);
+        long keepAliveTime = unit.toNanos(time);
+        long delta = keepAliveTime - this.keepAliveTime;
+        this.keepAliveTime = keepAliveTime;
+        if (delta < 0)
+            interruptIdleWorkers();
     }
 
     /**
      * Returns the thread keep-alive time, which is the amount of time
-     * which threads in excess of the core pool size may remain
+     * that threads in excess of the core pool size may remain
      * idle before being terminated.
      *
      * @param unit the desired time unit of the result
@@ -1289,6 +1584,73 @@
         return unit.convert(keepAliveTime, TimeUnit.NANOSECONDS);
     }
 
+    /* User-level queue utilities */
+
+    /**
+     * Returns the task queue used by this executor. Access to the
+     * task queue is intended primarily for debugging and monitoring.
+     * This queue may be in active use.  Retrieving the task queue
+     * does not prevent queued tasks from executing.
+     *
+     * @return the task queue
+     */
+    public BlockingQueue<Runnable> getQueue() {
+        return workQueue;
+    }
+
+    /**
+     * Removes this task from the executor's internal queue if it is
+     * present, thus causing it not to be run if it has not already
+     * started.
+     *
+     * <p> This method may be useful as one part of a cancellation
+     * scheme.  It may fail to remove tasks that have been converted
+     * into other forms before being placed on the internal queue. For
+     * example, a task entered using {@code submit} might be
+     * converted into a form that maintains {@code Future} status.
+     * However, in such cases, method {@link #purge} may be used to
+     * remove those Futures that have been cancelled.
+     *
+     * @param task the task to remove
+     * @return true if the task was removed
+     */
+    public boolean remove(Runnable task) {
+        boolean removed = workQueue.remove(task);
+        tryTerminate(); // In case SHUTDOWN and now empty
+        return removed;
+    }
+
+    /**
+     * Tries to remove from the work queue all {@link Future}
+     * tasks that have been cancelled. This method can be useful as a
+     * storage reclamation operation, that has no other impact on
+     * functionality. Cancelled tasks are never executed, but may
+     * accumulate in work queues until worker threads can actively
+     * remove them. Invoking this method instead tries to remove them now.
+     * However, this method may fail to remove tasks in
+     * the presence of interference by other threads.
+     */
+    public void purge() {
+        final BlockingQueue<Runnable> q = workQueue;
+        try {
+            Iterator<Runnable> it = q.iterator();
+            while (it.hasNext()) {
+                Runnable r = it.next();
+                if (r instanceof Future<?> && ((Future<?>)r).isCancelled())
+                    it.remove();
+            }
+        } catch (ConcurrentModificationException fallThrough) {
+            // Take slow path if we encounter interference during traversal.
+            // Make copy for traversal and call remove for cancelled entries.
+            // The slow path is more likely to be O(N*N).
+            for (Object r : q.toArray())
+                if (r instanceof Future<?> && ((Future<?>)r).isCancelled())
+                    q.remove(r);
+        }
+
+        tryTerminate(); // In case SHUTDOWN and now empty
+    }
+
     /* Statistics */
 
     /**
@@ -1297,7 +1659,16 @@
      * @return the number of threads
      */
     public int getPoolSize() {
-        return poolSize;
+        final ReentrantLock mainLock = this.mainLock;
+        mainLock.lock();
+        try {
+            // Remove rare and surprising possibility of
+            // isTerminated() && getPoolSize() > 0
+            return runStateAtLeast(ctl.get(), TIDYING) ? 0
+                : workers.size();
+        } finally {
+            mainLock.unlock();
+        }
     }
 
     /**
@@ -1311,10 +1682,9 @@
         mainLock.lock();
         try {
             int n = 0;
-            for (Worker w : workers) {
-                if (w.isActive())
+            for (Worker w : workers)
+                if (w.isLocked())
                     ++n;
-            }
             return n;
         } finally {
             mainLock.unlock();
@@ -1338,11 +1708,10 @@
     }
 
     /**
-     * Returns the approximate total number of tasks that have been
+     * Returns the approximate total number of tasks that have ever been
      * scheduled for execution. Because the states of tasks and
      * threads may change dynamically during computation, the returned
-     * value is only an approximation, but one that does not ever
-     * decrease across successive calls.
+     * value is only an approximation.
      *
      * @return the number of tasks
      */
@@ -1353,7 +1722,7 @@
             long n = completedTaskCount;
             for (Worker w : workers) {
                 n += w.completedTasks;
-                if (w.isActive())
+                if (w.isLocked())
                     ++n;
             }
             return n + workQueue.size();
@@ -1384,30 +1753,69 @@
         }
     }
 
+    /* Extension hooks */
+
     /**
      * Method invoked prior to executing the given Runnable in the
-     * given thread.  This method is invoked by thread <tt>t</tt> that
-     * will execute task <tt>r</tt>, and may be used to re-initialize
-     * ThreadLocals, or to perform logging. Note: To properly nest
-     * multiple overridings, subclasses should generally invoke
-     * <tt>super.beforeExecute</tt> at the end of this method.
+     * given thread.  This method is invoked by thread {@code t} that
+     * will execute task {@code r}, and may be used to re-initialize
+     * ThreadLocals, or to perform logging.
      *
-     * @param t the thread that will run task r.
-     * @param r the task that will be executed.
+     * <p>This implementation does nothing, but may be customized in
+     * subclasses. Note: To properly nest multiple overridings, subclasses
+     * should generally invoke {@code super.beforeExecute} at the end of
+     * this method.
+     *
+     * @param t the thread that will run task {@code r}
+     * @param r the task that will be executed
      */
     protected void beforeExecute(Thread t, Runnable r) { }
 
     /**
-     * Method invoked upon completion of execution of the given
-     * Runnable.  This method is invoked by the thread that executed
-     * the task. If non-null, the Throwable is the uncaught exception
-     * that caused execution to terminate abruptly. Note: To properly
-     * nest multiple overridings, subclasses should generally invoke
-     * <tt>super.afterExecute</tt> at the beginning of this method.
+     * Method invoked upon completion of execution of the given Runnable.
+     * This method is invoked by the thread that executed the task. If
+     * non-null, the Throwable is the uncaught {@code RuntimeException}
+     * or {@code Error} that caused execution to terminate abruptly.
      *
-     * @param r the runnable that has completed.
+     * <p>This implementation does nothing, but may be customized in
+     * subclasses. Note: To properly nest multiple overridings, subclasses
+     * should generally invoke {@code super.afterExecute} at the
+     * beginning of this method.
+     *
+     * <p><b>Note:</b> When actions are enclosed in tasks (such as
+     * {@link FutureTask}) either explicitly or via methods such as
+     * {@code submit}, these task objects catch and maintain
+     * computational exceptions, and so they do not cause abrupt
+     * termination, and the internal exceptions are <em>not</em>
+     * passed to this method. If you would like to trap both kinds of
+     * failures in this method, you can further probe for such cases,
+     * as in this sample subclass that prints either the direct cause
+     * or the underlying exception if a task has been aborted:
+     *
+     *  <pre> {@code
+     * class ExtendedExecutor extends ThreadPoolExecutor {
+     *   // ...
+     *   protected void afterExecute(Runnable r, Throwable t) {
+     *     super.afterExecute(r, t);
+     *     if (t == null && r instanceof Future<?>) {
+     *       try {
+     *         Object result = ((Future<?>) r).get();
+     *       } catch (CancellationException ce) {
+     *           t = ce;
+     *       } catch (ExecutionException ee) {
+     *           t = ee.getCause();
+     *       } catch (InterruptedException ie) {
+     *           Thread.currentThread().interrupt(); // ignore/reset
+     *       }
+     *     }
+     *     if (t != null)
+     *       System.out.println(t);
+     *   }
+     * }}</pre>
+     *
+     * @param r the runnable that has completed
      * @param t the exception that caused termination, or null if
-     * execution completed normally.
+     * execution completed normally
      */
     protected void afterExecute(Runnable r, Throwable t) { }
 
@@ -1415,25 +1823,28 @@
      * Method invoked when the Executor has terminated.  Default
      * implementation does nothing. Note: To properly nest multiple
      * overridings, subclasses should generally invoke
-     * <tt>super.terminated</tt> within this method.
+     * {@code super.terminated} within this method.
      */
     protected void terminated() { }
 
+    /* Predefined RejectedExecutionHandlers */
+
     /**
      * A handler for rejected tasks that runs the rejected task
-     * directly in the calling thread of the <tt>execute</tt> method,
+     * directly in the calling thread of the {@code execute} method,
      * unless the executor has been shut down, in which case the task
      * is discarded.
      */
-   public static class CallerRunsPolicy implements RejectedExecutionHandler {
+    public static class CallerRunsPolicy implements RejectedExecutionHandler {
         /**
-         * Creates a <tt>CallerRunsPolicy</tt>.
+         * Creates a {@code CallerRunsPolicy}.
          */
         public CallerRunsPolicy() { }
 
         /**
          * Executes task r in the caller's thread, unless the executor
          * has been shut down, in which case the task is discarded.
+         *
          * @param r the runnable task requested to be executed
          * @param e the executor attempting to execute this task
          */
@@ -1446,16 +1857,17 @@
 
     /**
      * A handler for rejected tasks that throws a
-     * <tt>RejectedExecutionException</tt>.
+     * {@code RejectedExecutionException}.
      */
     public static class AbortPolicy implements RejectedExecutionHandler {
         /**
-         * Creates an <tt>AbortPolicy</tt>.
+         * Creates an {@code AbortPolicy}.
          */
         public AbortPolicy() { }
 
         /**
          * Always throws RejectedExecutionException.
+         *
          * @param r the runnable task requested to be executed
          * @param e the executor attempting to execute this task
          * @throws RejectedExecutionException always.
@@ -1471,12 +1883,13 @@
      */
     public static class DiscardPolicy implements RejectedExecutionHandler {
         /**
-         * Creates a <tt>DiscardPolicy</tt>.
+         * Creates a {@code DiscardPolicy}.
          */
         public DiscardPolicy() { }
 
         /**
          * Does nothing, which has the effect of discarding task r.
+         *
          * @param r the runnable task requested to be executed
          * @param e the executor attempting to execute this task
          */
@@ -1486,12 +1899,12 @@
 
     /**
      * A handler for rejected tasks that discards the oldest unhandled
-     * request and then retries <tt>execute</tt>, unless the executor
+     * request and then retries {@code execute}, unless the executor
      * is shut down, in which case the task is discarded.
      */
     public static class DiscardOldestPolicy implements RejectedExecutionHandler {
         /**
-         * Creates a <tt>DiscardOldestPolicy</tt> for the given executor.
+         * Creates a {@code DiscardOldestPolicy} for the given executor.
          */
         public DiscardOldestPolicy() { }
 
@@ -1500,6 +1913,7 @@
          * would otherwise execute, if one is immediately available,
          * and then retries execution of task r, unless the executor
          * is shut down, in which case task r is instead discarded.
+         *
          * @param r the runnable task requested to be executed
          * @param e the executor attempting to execute this task
          */
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/TimeUnit.java b/libcore/concurrent/src/main/java/java/util/concurrent/TimeUnit.java
index b186aeb..412d28a 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/TimeUnit.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/TimeUnit.java
@@ -12,7 +12,11 @@
  * and to perform timing and delay operations in these units.  A
  * <tt>TimeUnit</tt> does not maintain time information, but only
  * helps organize and use time representations that may be maintained
- * separately across various contexts.
+ * separately across various contexts.  A nanosecond is defined as one
+ * thousandth of a microsecond, a microsecond as one thousandth of a
+ * millisecond, a millisecond as one thousandth of a second, a minute
+ * as sixty seconds, an hour as sixty minutes, and a day as twenty four
+ * hours.
  *
  * <p>A <tt>TimeUnit</tt> is mainly used to inform time-based methods
  * how a given timing parameter should be interpreted. For example,
@@ -37,61 +41,80 @@
  */
 public enum TimeUnit {
     /** TimeUnit which represents one nanosecond. */
-    NANOSECONDS(0), 
+    NANOSECONDS {
+        public long toNanos(long d)   { return d; }
+        public long toMicros(long d)  { return d/(C1/C0); }
+        public long toMillis(long d)  { return d/(C2/C0); }
+        public long toSeconds(long d) { return d/(C3/C0); }
+        public long toMinutes(long d) { return d/(C4/C0); }
+        public long toHours(long d)   { return d/(C5/C0); }
+        public long toDays(long d)    { return d/(C6/C0); }
+        public long convert(long d, TimeUnit u) { return u.toNanos(d); }
+        int excessNanos(long d, long m) { return (int)(d - (m*C2)); }
+    },
     /** TimeUnit which represents one microsecond. */
-    MICROSECONDS(1), 
+    MICROSECONDS {
+        public long toNanos(long d)   { return x(d, C1/C0, MAX/(C1/C0)); }
+        public long toMicros(long d)  { return d; }
+        public long toMillis(long d)  { return d/(C2/C1); }
+        public long toSeconds(long d) { return d/(C3/C1); }
+        public long toMinutes(long d) { return d/(C4/C1); }
+        public long toHours(long d)   { return d/(C5/C1); }
+        public long toDays(long d)    { return d/(C6/C1); }
+        public long convert(long d, TimeUnit u) { return u.toMicros(d); }
+        int excessNanos(long d, long m) { return (int)((d*C1) - (m*C2)); }
+    },
     /** TimeUnit which represents one millisecond. */
-    MILLISECONDS(2), 
+    MILLISECONDS {
+        public long toNanos(long d)   { return x(d, C2/C0, MAX/(C2/C0)); }
+        public long toMicros(long d)  { return x(d, C2/C1, MAX/(C2/C1)); }
+        public long toMillis(long d)  { return d; }
+        public long toSeconds(long d) { return d/(C3/C2); }
+        public long toMinutes(long d) { return d/(C4/C2); }
+        public long toHours(long d)   { return d/(C5/C2); }
+        public long toDays(long d)    { return d/(C6/C2); }
+        public long convert(long d, TimeUnit u) { return u.toMillis(d); }
+        int excessNanos(long d, long m) { return 0; }
+    },
     /** TimeUnit which represents one second. */
-    SECONDS(3);
-
-    /** the index of this unit */
-    private final int index;
-
-    /** Internal constructor */
-    TimeUnit(int index) { 
-        this.index = index; 
-    }
-
-    /** Lookup table for conversion factors */
-    private static final int[] multipliers = { 
-        1, 
-        1000, 
-        1000 * 1000, 
-        1000 * 1000 * 1000 
+    SECONDS {
+        public long toNanos(long d)   { return x(d, C3/C0, MAX/(C3/C0)); }
+        public long toMicros(long d)  { return x(d, C3/C1, MAX/(C3/C1)); }
+        public long toMillis(long d)  { return x(d, C3/C2, MAX/(C3/C2)); }
+        public long toSeconds(long d) { return d; }
+        public long toMinutes(long d) { return d/(C4/C3); }
+        public long toHours(long d)   { return d/(C5/C3); }
+        public long toDays(long d)    { return d/(C6/C3); }
+        public long convert(long d, TimeUnit u) { return u.toSeconds(d); }
+        int excessNanos(long d, long m) { return 0; }
     };
-    
-    /** 
-     * Lookup table to check saturation.  Note that because we are
-     * dividing these down, we don't have to deal with asymmetry of
-     * MIN/MAX values.
-     */
-    private static final long[] overflows = { 
-        0, // unused
-        Long.MAX_VALUE / 1000,
-        Long.MAX_VALUE / (1000 * 1000),
-        Long.MAX_VALUE / (1000 * 1000 * 1000) 
-    };
+
+    // Handy constants for conversion methods
+    static final long C0 = 1L;
+    static final long C1 = C0 * 1000L;
+    static final long C2 = C1 * 1000L;
+    static final long C3 = C2 * 1000L;
+    static final long C4 = C3 * 60L;
+    static final long C5 = C4 * 60L;
+    static final long C6 = C5 * 24L;
+
+    static final long MAX = Long.MAX_VALUE;
 
     /**
-     * Perform conversion based on given delta representing the
-     * difference between units
-     * @param delta the difference in index values of source and target units
-     * @param duration the duration
-     * @return converted duration or saturated value
+     * Scale d by m, checking for overflow.
+     * This has a short name to make above code more readable.
      */
-    private static long doConvert(int delta, long duration) {
-        if (delta == 0)
-            return duration;
-        if (delta < 0) 
-            return duration / multipliers[-delta];
-        if (duration > overflows[delta])
-            return Long.MAX_VALUE;
-        if (duration < -overflows[delta])
-            return Long.MIN_VALUE;
-        return duration * multipliers[delta];
+    static long x(long d, long m, long over) {
+        if (d >  over) return Long.MAX_VALUE;
+        if (d < -over) return Long.MIN_VALUE;
+        return d * m;
     }
 
+    // To maintain full signature compatibility with 1.5, and to improve the
+    // clarity of the generated javadoc (see 6287639: Abstract methods in
+    // enum classes should not be listed as abstract), method convert
+    // etc. are not declared abstract but otherwise act as abstract methods.
+
     /**
      * Convert the given time duration in the given unit to this
      * unit.  Conversions from finer to coarser granularities
@@ -102,14 +125,17 @@
      * <tt>Long.MIN_VALUE</tt> if negative or <tt>Long.MAX_VALUE</tt>
      * if positive.
      *
-     * @param duration the time duration in the given <tt>unit</tt>
-     * @param unit the unit of the <tt>duration</tt> argument
+     * <p>For example, to convert 10 minutes to milliseconds, use:
+     * <tt>TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)</tt>
+     *
+     * @param sourceDuration the time duration in the given <tt>sourceUnit</tt>
+     * @param sourceUnit the unit of the <tt>sourceDuration</tt> argument
      * @return the converted duration in this unit,
      * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
      * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
      */
-    public long convert(long duration, TimeUnit unit) {
-        return doConvert(unit.index - index, duration);
+    public long convert(long sourceDuration, TimeUnit sourceUnit) {
+        throw new AbstractMethodError();
     }
 
     /**
@@ -121,7 +147,7 @@
      * @see #convert
      */
     public long toNanos(long duration) {
-        return doConvert(index, duration);
+        throw new AbstractMethodError();
     }
 
     /**
@@ -133,7 +159,7 @@
      * @see #convert
      */
     public long toMicros(long duration) {
-        return doConvert(index - MICROSECONDS.index, duration);
+        throw new AbstractMethodError();
     }
 
     /**
@@ -145,34 +171,66 @@
      * @see #convert
      */
     public long toMillis(long duration) {
-        return doConvert(index - MILLISECONDS.index, duration);
+        throw new AbstractMethodError();
     }
 
     /**
      * Equivalent to <tt>SECONDS.convert(duration, this)</tt>.
      * @param duration the duration
-     * @return the converted duration.
+     * @return the converted duration,
+     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
+     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
      * @see #convert
      */
     public long toSeconds(long duration) {
-        return doConvert(index - SECONDS.index, duration);
+        throw new AbstractMethodError();
     }
 
-
     /**
-     * Utility method to compute the excess-nanosecond argument to
-     * wait, sleep, join.
+     * Equivalent to <tt>MINUTES.convert(duration, this)</tt>.
+     * @param duration the duration
+     * @return the converted duration,
+     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
+     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+     * @see #convert
      */
-    private int excessNanos(long time, long ms) {
-        if (this == NANOSECONDS)
-            return (int) (time  - (ms * 1000 * 1000));
-        if (this == MICROSECONDS)
-            return (int) ((time * 1000) - (ms * 1000 * 1000));
-        return 0;
+    long toMinutes(long duration) {
+        throw new AbstractMethodError();
     }
 
     /**
-     * Perform a timed <tt>Object.wait</tt> using this time unit.
+     * Equivalent to <tt>HOURS.convert(duration, this)</tt>.
+     * @param duration the duration
+     * @return the converted duration,
+     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
+     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+     * @see #convert
+     */
+    long toHours(long duration) {
+        throw new AbstractMethodError();
+    }
+
+    /**
+     * Equivalent to <tt>DAYS.convert(duration, this)</tt>.
+     * @param duration the duration
+     * @return the converted duration
+     * @see #convert
+     */
+    long toDays(long duration) {
+        throw new AbstractMethodError();
+    }
+
+    /**
+     * Utility to compute the excess-nanosecond argument to wait,
+     * sleep, join.
+     * @param d the duration
+     * @param m the number of milliseconds
+     * @return the number of nanoseconds
+     */
+    abstract int excessNanos(long d, long m);
+
+    /**
+     * Performs a timed <tt>Object.wait</tt> using this time unit.
      * This is a convenience method that converts timeout arguments
      * into the form required by the <tt>Object.wait</tt> method.
      *
@@ -180,7 +238,7 @@
      * method (see {@link BlockingQueue#poll BlockingQueue.poll})
      * using:
      *
-     * <pre>  public synchronized  Object poll(long timeout, TimeUnit unit) throws InterruptedException {
+     * <pre>  public synchronized Object poll(long timeout, TimeUnit unit) throws InterruptedException {
      *    while (empty) {
      *      unit.timedWait(this, timeout);
      *      ...
@@ -188,12 +246,13 @@
      *  }</pre>
      *
      * @param obj the object to wait on
-     * @param timeout the maximum time to wait. 
+     * @param timeout the maximum time to wait. If less than
+     * or equal to zero, do not wait at all.
      * @throws InterruptedException if interrupted while waiting.
      * @see Object#wait(long, int)
      */
     public void timedWait(Object obj, long timeout)
-        throws InterruptedException {
+    throws InterruptedException {
         if (timeout > 0) {
             long ms = toMillis(timeout);
             int ns = excessNanos(timeout, ms);
@@ -202,16 +261,17 @@
     }
 
     /**
-     * Perform a timed <tt>Thread.join</tt> using this time unit.
+     * Performs a timed <tt>Thread.join</tt> using this time unit.
      * This is a convenience method that converts time arguments into the
      * form required by the <tt>Thread.join</tt> method.
      * @param thread the thread to wait for
-     * @param timeout the maximum time to wait
+     * @param timeout the maximum time to wait. If less than
+     * or equal to zero, do not wait at all.
      * @throws InterruptedException if interrupted while waiting.
      * @see Thread#join(long, int)
      */
     public void timedJoin(Thread thread, long timeout)
-        throws InterruptedException {
+    throws InterruptedException {
         if (timeout > 0) {
             long ms = toMillis(timeout);
             int ns = excessNanos(timeout, ms);
@@ -220,10 +280,11 @@
     }
 
     /**
-     * Perform a <tt>Thread.sleep</tt> using this unit.
+     * Performs a <tt>Thread.sleep</tt> using this unit.
      * This is a convenience method that converts time arguments into the
      * form required by the <tt>Thread.sleep</tt> method.
-     * @param timeout the minimum time to sleep
+     * @param timeout the minimum time to sleep. If less than
+     * or equal to zero, do not sleep at all.
      * @throws InterruptedException if interrupted while sleeping.
      * @see Thread#sleep
      */
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java
index fdd3d49..ba60556 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java
@@ -8,10 +8,10 @@
 import sun.misc.Unsafe;
 
 /**
- * A <tt>boolean</tt> value that may be updated atomically. See the
+ * A {@code boolean} value that may be updated atomically. See the
  * {@link java.util.concurrent.atomic} package specification for
  * description of the properties of atomic variables. An
- * <tt>AtomicBoolean</tt> is used in applications such as atomically
+ * {@code AtomicBoolean} is used in applications such as atomically
  * updated flags, and cannot be used as a replacement for a
  * {@link java.lang.Boolean}.
  *
@@ -37,7 +37,7 @@
     private volatile int value;
 
     /**
-     * Creates a new <tt>AtomicBoolean</tt> with the given initial value.
+     * Creates a new {@code AtomicBoolean} with the given initial value.
      *
      * @param initialValue the initial value
      */
@@ -46,7 +46,7 @@
     }
 
     /**
-     * Creates a new <tt>AtomicBoolean</tt> with initial value <tt>false</tt>.
+     * Creates a new {@code AtomicBoolean} with initial value {@code false}.
      */
     public AtomicBoolean() {
     }
@@ -61,16 +61,13 @@
     }
 
     /**
-     * Atomically sets the value to the given update value if the
-     * current value is equal to the expected value.  Any given
-     * invocation of this operation may fail (return
-     * <tt>false</tt>) spuriously, but repeated invocation when
-     * the current value holds the expected value and no other thread
-     * is also attempting to set the value will eventually succeed.
+     * Atomically sets the value to the given updated value
+     * if the current value {@code ==} the expected value.
      *
      * @param expect the expected value
      * @param update the new value
-     * @return true if successful
+     * @return true if successful. False return indicates that
+     * the actual value was not equal to the expected value.
      */
     public final boolean compareAndSet(boolean expect, boolean update) {
         int e = expect ? 1 : 0;
@@ -79,9 +76,13 @@
     }
 
     /**
-     * Atomically set the value to the given updated value
-     * if the current value <tt>==</tt> the expected value.
-     * May fail spuriously.
+     * Atomically sets the value to the given updated value
+     * if the current value {@code ==} the expected value.
+     *
+     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
+     * and does not provide ordering guarantees, so is only rarely an
+     * appropriate alternative to {@code compareAndSet}.
+     *
      * @param expect the expected value
      * @param update the new value
      * @return true if successful.
@@ -102,7 +103,7 @@
     }
 
     /**
-     * Sets to the given value and returns the previous value.
+     * Atomically sets to the given value and returns the previous value.
      *
      * @param newValue the new value
      * @return the previous value
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicInteger.java b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicInteger.java
index 2b9d15c..1aa32f4 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicInteger.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicInteger.java
@@ -8,20 +8,19 @@
 import sun.misc.Unsafe;
 
 /**
- * An <tt>int</tt> value that may be updated atomically. See the
+ * An {@code int} value that may be updated atomically.  See the
  * {@link java.util.concurrent.atomic} package specification for
  * description of the properties of atomic variables. An
- * <tt>AtomicInteger</tt> is used in applications such as atomically
+ * {@code AtomicInteger} is used in applications such as atomically
  * incremented counters, and cannot be used as a replacement for an
  * {@link java.lang.Integer}. However, this class does extend
- * <tt>Number</tt> to allow uniform access by tools and utilities that
+ * {@code Number} to allow uniform access by tools and utilities that
  * deal with numerically-based classes.
- * 
  *
  * @since 1.5
  * @author Doug Lea
 */
-public class AtomicInteger extends Number implements java.io.Serializable { 
+public class AtomicInteger extends Number implements java.io.Serializable {
     private static final long serialVersionUID = 6214790243416807050L;
 
     // setup to use Unsafe.compareAndSwapInt for updates
@@ -34,13 +33,13 @@
       try {
         valueOffset = unsafe.objectFieldOffset
             (AtomicInteger.class.getDeclaredField("value"));
-      } catch(Exception ex) { throw new Error(ex); }
+      } catch (Exception ex) { throw new Error(ex); }
     }
 
     private volatile int value;
 
     /**
-     * Create a new AtomicInteger with the given initial value.
+     * Creates a new AtomicInteger with the given initial value.
      *
      * @param initialValue the initial value
      */
@@ -49,22 +48,22 @@
     }
 
     /**
-     * Create a new AtomicInteger with initial value <tt>0</tt>.
+     * Creates a new AtomicInteger with initial value {@code 0}.
      */
     public AtomicInteger() {
     }
 
     /**
-     * Get the current value.
+     * Gets the current value.
      *
      * @return the current value
      */
     public final int get() {
         return value;
     }
-  
+
     /**
-     * Set to the given value.
+     * Sets to the given value.
      *
      * @param newValue the new value
      */
@@ -73,7 +72,7 @@
     }
 
     /**
-     * Set to the give value and return the old value.
+     * Atomically sets to the given value and returns the old value.
      *
      * @param newValue the new value
      * @return the previous value
@@ -85,35 +84,39 @@
                 return current;
         }
     }
-  
-  
+
     /**
-     * Atomically set the value to the given updated value
-     * if the current value <tt>==</tt> the expected value.
+     * Atomically sets the value to the given updated value
+     * if the current value {@code ==} the expected value.
+     *
      * @param expect the expected value
      * @param update the new value
      * @return true if successful. False return indicates that
      * the actual value was not equal to the expected value.
      */
     public final boolean compareAndSet(int expect, int update) {
-      return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
+        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
     }
 
     /**
-     * Atomically set the value to the given updated value
-     * if the current value <tt>==</tt> the expected value.
-     * May fail spuriously.
+     * Atomically sets the value to the given updated value
+     * if the current value {@code ==} the expected value.
+     *
+     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
+     * and does not provide ordering guarantees, so is only rarely an
+     * appropriate alternative to {@code compareAndSet}.
+     *
      * @param expect the expected value
      * @param update the new value
      * @return true if successful.
      */
     public final boolean weakCompareAndSet(int expect, int update) {
-      return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
+        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
     }
 
-
     /**
-     * Atomically increment by one the current value.
+     * Atomically increments by one the current value.
+     *
      * @return the previous value
      */
     public final int getAndIncrement() {
@@ -124,10 +127,10 @@
                 return current;
         }
     }
-  
-  
+
     /**
-     * Atomically decrement by one the current value.
+     * Atomically decrements by one the current value.
+     *
      * @return the previous value
      */
     public final int getAndDecrement() {
@@ -138,10 +141,10 @@
                 return current;
         }
     }
-  
-  
+
     /**
-     * Atomically add the given value to current value.
+     * Atomically adds the given value to the current value.
+     *
      * @param delta the value to add
      * @return the previous value
      */
@@ -155,7 +158,8 @@
     }
 
     /**
-     * Atomically increment by one the current value.
+     * Atomically increments by one the current value.
+     *
      * @return the updated value
      */
     public final int incrementAndGet() {
@@ -166,9 +170,10 @@
                 return next;
         }
     }
-    
+
     /**
-     * Atomically decrement by one the current value.
+     * Atomically decrements by one the current value.
+     *
      * @return the updated value
      */
     public final int decrementAndGet() {
@@ -179,10 +184,10 @@
                 return next;
         }
     }
-  
-  
+
     /**
-     * Atomically add the given value to current value.
+     * Atomically adds the given value to the current value.
+     *
      * @param delta the value to add
      * @return the updated value
      */
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 95807f3..ee21b13 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
@@ -9,14 +9,14 @@
 import java.util.*;
 
 /**
- * An <tt>int</tt> array in which elements may be updated atomically.
+ * An {@code int} array in which elements may be updated atomically.
  * See the {@link java.util.concurrent.atomic} package
  * specification for description of the properties of atomic
  * variables.
  * @since 1.5
  * @author Doug Lea
  */
-public class AtomicIntegerArray implements java.io.Serializable { 
+public class AtomicIntegerArray implements java.io.Serializable {
     private static final long serialVersionUID = 2862133569453604235L;
 
    // setup to use Unsafe.compareAndSwapInt for updates
@@ -34,7 +34,7 @@
     }
 
     /**
-     * Create a new AtomicIntegerArray of given length.
+     * Creates a new AtomicIntegerArray of given length.
      *
      * @param length the length of the array
      */
@@ -46,14 +46,14 @@
     }
 
     /**
-     * Create a new AtomicIntegerArray with the same length as, and
+     * Creates a new AtomicIntegerArray with the same length as, and
      * all elements copied from, the given array.
      *
      * @param array the array to copy elements from
      * @throws NullPointerException if array is null
      */
     public AtomicIntegerArray(int[] array) {
-        if (array == null) 
+        if (array == null)
             throw new NullPointerException();
         int length = array.length;
         this.array = new int[length];
@@ -76,7 +76,7 @@
     }
 
     /**
-     * Get the current value at position <tt>i</tt>.
+     * Gets the current value at position {@code i}.
      *
      * @param i the index
      * @return the current value
@@ -84,9 +84,9 @@
     public final int get(int i) {
         return unsafe.getIntVolatile(array, rawIndex(i));
     }
- 
+
     /**
-     * Set the element at position <tt>i</tt> to the given value.
+     * Sets the element at position {@code i} to the given value.
      *
      * @param i the index
      * @param newValue the new value
@@ -94,10 +94,10 @@
     public final void set(int i, int newValue) {
         unsafe.putIntVolatile(array, rawIndex(i), newValue);
     }
-  
+
     /**
-     * Set the element at position <tt>i</tt> to the given value and return the
-     * old value.
+     * Atomically sets the element at position {@code i} to the given
+     * value and returns the old value.
      *
      * @param i the index
      * @param newValue the new value
@@ -110,10 +110,10 @@
                 return current;
         }
     }
-  
+
     /**
-     * Atomically set the value to the given updated value
-     * if the current value <tt>==</tt> the expected value.
+     * Atomically sets the element at position {@code i} to the given
+     * updated value if the current value {@code ==} the expected value.
      *
      * @param i the index
      * @param expect the expected value
@@ -122,14 +122,17 @@
      * the actual value was not equal to the expected value.
      */
     public final boolean compareAndSet(int i, int expect, int update) {
-        return unsafe.compareAndSwapInt(array, rawIndex(i), 
+        return unsafe.compareAndSwapInt(array, rawIndex(i),
                                         expect, update);
     }
 
     /**
-     * Atomically set the value to the given updated value
-     * if the current value <tt>==</tt> the expected value.
-     * May fail spuriously.
+     * Atomically sets the element at position {@code i} to the given
+     * updated value if the current value {@code ==} the expected value.
+     *
+     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
+     * and does not provide ordering guarantees, so is only rarely an
+     * appropriate alternative to {@code compareAndSet}.
      *
      * @param i the index
      * @param expect the expected value
@@ -141,10 +144,10 @@
     }
 
     /**
-     * Atomically increment by one the element at index <tt>i</tt>.
+     * Atomically increments by one the element at index {@code i}.
      *
      * @param i the index
-     * @return the previous value;
+     * @return the previous value
      */
     public final int getAndIncrement(int i) {
         while (true) {
@@ -154,12 +157,12 @@
                 return current;
         }
     }
-  
+
     /**
-     * Atomically decrement by one the element at index <tt>i</tt>.
+     * Atomically decrements by one the element at index {@code i}.
      *
      * @param i the index
-     * @return the previous value;
+     * @return the previous value
      */
     public final int getAndDecrement(int i) {
         while (true) {
@@ -169,13 +172,13 @@
                 return current;
         }
     }
-  
+
     /**
-     * Atomically add the given value to element at index <tt>i</tt>.
+     * Atomically adds the given value to the element at index {@code i}.
      *
      * @param i the index
      * @param delta the value to add
-     * @return the previous value;
+     * @return the previous value
      */
     public final int getAndAdd(int i, int delta) {
         while (true) {
@@ -187,10 +190,10 @@
     }
 
     /**
-     * Atomically increment by one the element at index <tt>i</tt>.
+     * Atomically increments by one the element at index {@code i}.
      *
      * @param i the index
-     * @return the updated value;
+     * @return the updated value
      */
     public final int incrementAndGet(int i) {
         while (true) {
@@ -200,12 +203,12 @@
                 return next;
         }
     }
-  
+
     /**
-     * Atomically decrement by one the element at index <tt>i</tt>.
+     * Atomically decrements by one the element at index {@code i}.
      *
      * @param i the index
-     * @return the updated value;
+     * @return the updated value
      */
     public final int decrementAndGet(int i) {
         while (true) {
@@ -215,13 +218,13 @@
                 return next;
         }
     }
-  
+
     /**
-     * Atomically add the given value to element at index <tt>i</tt>.
+     * Atomically adds the given value to the element at index {@code i}.
      *
      * @param i the index
      * @param delta the value to add
-     * @return the updated value;
+     * @return the updated value
      */
     public final int addAndGet(int i, int delta) {
         while (true) {
@@ -231,7 +234,7 @@
                 return next;
         }
     }
- 
+
     /**
      * Returns the String representation of the current values of array.
      * @return the String representation of the current values of array.
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
index 5f289c2..f8d2c81 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
@@ -8,35 +8,40 @@
 import sun.misc.Unsafe;
 import java.lang.reflect.*;
 
+import org.apache.harmony.kernel.vm.VM;
+import dalvik.system.VMStack;
+
 /**
  * A reflection-based utility that enables atomic updates to
- * designated <tt>volatile int</tt> fields of designated classes.
+ * designated {@code volatile int} fields of designated classes.
  * This class is designed for use in atomic data structures in which
  * several fields of the same node are independently subject to atomic
  * updates.
  *
- * <p> Note that the guarantees of the <tt>compareAndSet</tt> method
- * in this class are weaker than in other atomic classes. Because this
- * class cannot ensure that all uses of the field are appropriate for
- * purposes of atomic access, it can guarantee atomicity and volatile
- * semantics only with respect to other invocations of
- * <tt>compareAndSet</tt> and <tt>set</tt>.
+ * <p>Note that the guarantees of the {@code compareAndSet}
+ * method in this class are weaker than in other atomic classes.
+ * Because this class cannot ensure that all uses of the field
+ * are appropriate for purposes of atomic access, it can
+ * guarantee atomicity only with respect to other invocations of
+ * {@code compareAndSet} and {@code set} on the same updater.
+ *
  * @since 1.5
  * @author Doug Lea
  * @param <T> The type of the object holding the updatable field
  */
 public abstract class  AtomicIntegerFieldUpdater<T>  {
     /**
-     * Creates an updater for objects with the given field.  The Class
-     * argument is needed to check that reflective types and generic
-     * types match.
+     * Creates and returns an updater for objects with the given field.
+     * The Class argument is needed to check that reflective types and
+     * generic types match.
+     *
      * @param tclass the class of the objects holding the field
-     * @param fieldName the name of the field to be updated.
+     * @param fieldName the name of the field to be updated
      * @return the updater
      * @throws IllegalArgumentException if the field is not a
-     * volatile integer type.
+     * volatile integer type
      * @throws RuntimeException with a nested reflection-based
-     * exception if the class does not hold field or is the wrong type.
+     * exception if the class does not hold field or is the wrong type
      */
     public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
         return new AtomicIntegerFieldUpdaterImpl<U>(tclass, fieldName);
@@ -49,57 +54,63 @@
     }
 
     /**
-     * Atomically set the value of the field of the given object managed
-     * by this Updater to the given updated value if the current value
-     * <tt>==</tt> the expected value. This method is guaranteed to be
-     * atomic with respect to other calls to <tt>compareAndSet</tt> and
-     * <tt>set</tt>, but not necessarily with respect to other
-     * changes in the field.
+     * Atomically sets the field of the given object managed by this updater
+     * to the given updated value if the current value {@code ==} the
+     * expected value. This method is guaranteed to be atomic with respect to
+     * other calls to {@code compareAndSet} and {@code set}, but not
+     * necessarily with respect to other changes in the field.
+     *
      * @param obj An object whose field to conditionally set
      * @param expect the expected value
      * @param update the new value
-     * @return true if successful.
-     * @throws ClassCastException if <tt>obj</tt> is not an instance
-     * of the class possessing the field established in the constructor.
+     * @return true if successful
+     * @throws ClassCastException if {@code obj} is not an instance
+     * of the class possessing the field established in the constructor
      */
-
     public abstract boolean compareAndSet(T obj, int expect, int update);
 
     /**
-     * Atomically set the value of the field of the given object managed
-     * by this Updater to the given updated value if the current value
-     * <tt>==</tt> the expected value. This method is guaranteed to be
-     * atomic with respect to other calls to <tt>compareAndSet</tt> and
-     * <tt>set</tt>, but not necessarily with respect to other
-     * changes in the field, and may fail spuriously.
+     * Atomically sets the field of the given object managed by this updater
+     * to the given updated value if the current value {@code ==} the
+     * expected value. This method is guaranteed to be atomic with respect to
+     * other calls to {@code compareAndSet} and {@code set}, but not
+     * necessarily with respect to other changes in the field.
+     *
+     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
+     * and does not provide ordering guarantees, so is only rarely an
+     * appropriate alternative to {@code compareAndSet}.
+     *
      * @param obj An object whose field to conditionally set
      * @param expect the expected value
      * @param update the new value
-     * @return true if successful.
-     * @throws ClassCastException if <tt>obj</tt> is not an instance
-     * of the class possessing the field established in the constructor.
+     * @return true if successful
+     * @throws ClassCastException if {@code obj} is not an instance
+     * of the class possessing the field established in the constructor
      */
-
     public abstract boolean weakCompareAndSet(T obj, int expect, int update);
 
     /**
-     * Set the field of the given object managed by this updater. This
-     * operation is guaranteed to act as a volatile store with respect
-     * to subsequent invocations of <tt>compareAndSet</tt>.
+     * Sets the field of the given object managed by this updater to the
+     * given updated value. This operation is guaranteed to act as a volatile
+     * store with respect to subsequent invocations of {@code compareAndSet}.
+     *
      * @param obj An object whose field to set
      * @param newValue the new value
      */
     public abstract void set(T obj, int newValue);
 
     /**
-     * Get the current value held in the field by the given object.
+     * Gets the current value held in the field of the given object managed
+     * by this updater.
+     *
      * @param obj An object whose field to get
      * @return the current value
      */
     public abstract int get(T obj);
 
     /**
-     * Set to the given value and return the old value.
+     * Atomically sets the field of the given object managed by this updater
+     * to the given value and returns the old value.
      *
      * @param obj An object whose field to get and set
      * @param newValue the new value
@@ -114,9 +125,11 @@
     }
 
     /**
-     * Atomically increment by one the current value.
+     * Atomically increments by one the current value of the field of the
+     * given object managed by this updater.
+     *
      * @param obj An object whose field to get and set
-     * @return the previous value;
+     * @return the previous value
      */
     public int getAndIncrement(T obj) {
         for (;;) {
@@ -127,11 +140,12 @@
         }
     }
 
-
     /**
-     * Atomically decrement by one the current value.
+     * Atomically decrements by one the current value of the field of the
+     * given object managed by this updater.
+     *
      * @param obj An object whose field to get and set
-     * @return the previous value;
+     * @return the previous value
      */
     public int getAndDecrement(T obj) {
         for (;;) {
@@ -142,12 +156,13 @@
         }
     }
 
-
     /**
-     * Atomically add the given value to current value.
+     * Atomically adds the given value to the current value of the field of
+     * the given object managed by this updater.
+     *
      * @param obj An object whose field to get and set
      * @param delta the value to add
-     * @return the previous value;
+     * @return the previous value
      */
     public int getAndAdd(T obj, int delta) {
         for (;;) {
@@ -159,9 +174,11 @@
     }
 
     /**
-     * Atomically increment by one the current value.
+     * Atomically increments by one the current value of the field of the
+     * given object managed by this updater.
+     *
      * @param obj An object whose field to get and set
-     * @return the updated value;
+     * @return the updated value
      */
     public int incrementAndGet(T obj) {
         for (;;) {
@@ -172,11 +189,12 @@
         }
     }
 
-
     /**
-     * Atomically decrement by one the current value.
+     * Atomically decrements by one the current value of the field of the
+     * given object managed by this updater.
+     *
      * @param obj An object whose field to get and set
-     * @return the updated value;
+     * @return the updated value
      */
     public int decrementAndGet(T obj) {
         for (;;) {
@@ -187,12 +205,13 @@
         }
     }
 
-
     /**
-     * Atomically add the given value to current value.
+     * Atomically adds the given value to the current value of the field of
+     * the given object managed by this updater.
+     *
      * @param obj An object whose field to get and set
      * @param delta the value to add
-     * @return the updated value;
+     * @return the updated value
      */
     public int addAndGet(T obj, int delta) {
         for (;;) {
@@ -212,49 +231,83 @@
         // END android-changed
         private final long offset;
         private final Class<T> tclass;
+        private final Class cclass;
 
         AtomicIntegerFieldUpdaterImpl(Class<T> tclass, String fieldName) {
             Field field = null;
+            Class caller = null;
+            int modifiers = 0;
             try {
                 field = tclass.getDeclaredField(fieldName);
-            } catch(Exception ex) {
+                // BEGIN android-changed
+                caller = VMStack.getStackClass2();
+                // END android-changed
+                modifiers = field.getModifiers();
+
+                SecurityManager smgr = System.getSecurityManager();
+                if (smgr != null) {
+                    int type = Modifier.isPublic(modifiers)
+                            ? Member.PUBLIC : Member.DECLARED;
+                    smgr.checkMemberAccess(tclass, type);
+                    smgr.checkPackageAccess(tclass.getPackage().getName());
+                }
+            } catch (Exception ex) {
                 throw new RuntimeException(ex);
             }
-            
+
             Class fieldt = field.getType();
             if (fieldt != int.class)
                 throw new IllegalArgumentException("Must be integer type");
-            
-            if (!Modifier.isVolatile(field.getModifiers()))
+
+            if (!Modifier.isVolatile(modifiers))
                 throw new IllegalArgumentException("Must be volatile type");
-         
+
+            this.cclass = (Modifier.isProtected(modifiers) &&
+                           caller != tclass) ? caller : null;
             this.tclass = tclass;
             offset = unsafe.objectFieldOffset(field);
         }
 
-        public boolean compareAndSet(T obj, int expect, int update) {
+        private void fullCheck(T obj) {
             if (!tclass.isInstance(obj))
                 throw new ClassCastException();
+            if (cclass != null)
+                ensureProtectedAccess(obj);
+        }
+
+        public boolean compareAndSet(T obj, int expect, int update) {
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
             return unsafe.compareAndSwapInt(obj, offset, expect, update);
         }
 
         public boolean weakCompareAndSet(T obj, int expect, int update) {
-            if (!tclass.isInstance(obj))
-                throw new ClassCastException();
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
             return unsafe.compareAndSwapInt(obj, offset, expect, update);
         }
 
         public void set(T obj, int newValue) {
-            if (!tclass.isInstance(obj))
-                throw new ClassCastException();
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
             unsafe.putIntVolatile(obj, offset, newValue);
         }
 
         public final int get(T obj) {
-            if (!tclass.isInstance(obj))
-                throw new ClassCastException();
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
             return unsafe.getIntVolatile(obj, offset);
         }
+
+        private void ensureProtectedAccess(T obj) {
+            if (cclass.isInstance(obj)) {
+                return;
+            }
+            throw new RuntimeException(
+                new IllegalAccessException("Class " +
+                    cclass.getName() +
+                    " can not access a protected member of class " +
+                    tclass.getName() +
+                    " using an instance of " +
+                    obj.getClass().getName()
+                )
+            );
+        }
     }
 }
-
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLong.java b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLong.java
index 7f41364..9b56002 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLong.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLong.java
@@ -8,19 +8,19 @@
 import sun.misc.Unsafe;
 
 /**
- * A <tt>long</tt> value that may be updated atomically.  See the
+ * A {@code long} value that may be updated atomically.  See the
  * {@link java.util.concurrent.atomic} package specification for
  * description of the properties of atomic variables. An
- * <tt>AtomicLong</tt> is used in applications such as atomically
+ * {@code AtomicLong} is used in applications such as atomically
  * incremented sequence numbers, and cannot be used as a replacement
  * for a {@link java.lang.Long}. However, this class does extend
- * <tt>Number</tt> to allow uniform access by tools and utilities that
+ * {@code Number} to allow uniform access by tools and utilities that
  * deal with numerically-based classes.
  *
  * @since 1.5
  * @author Doug Lea
  */
-public class AtomicLong extends Number implements java.io.Serializable { 
+public class AtomicLong extends Number implements java.io.Serializable {
     private static final long serialVersionUID = 1927816293512124184L;
 
     // setup to use Unsafe.compareAndSwapLong for updates
@@ -30,12 +30,14 @@
     private static final long valueOffset;
 
     /**
-     * Record whether the underlying JVM supports lockless
-     * CompareAndSet for longs. While the unsafe.CompareAndSetLong
+     * Records whether the underlying JVM supports lockless
+     * compareAndSwap for longs. While the Unsafe.compareAndSwapLong
      * method works in either case, some constructions should be
      * handled at Java level to avoid locking user-visible locks.
+     *
+     * Initialised in the static block.
      */
-    static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
+    static final boolean VM_SUPPORTS_LONG_CAS;
 
     /**
      * Returns whether underlying JVM supports lockless CompareAndSet
@@ -47,13 +49,22 @@
       try {
         valueOffset = unsafe.objectFieldOffset
             (AtomicLong.class.getDeclaredField("value"));
-      } catch(Exception ex) { throw new Error(ex); }
+      } catch (Exception ex) { throw new Error(ex); }
+
+      boolean longCASSupport;
+      try {
+         longCASSupport = VMSupportsCS8();
+      } catch (UnsatisfiedLinkError e) {
+         // assume there's support if the native isn't provided by the VM
+         longCASSupport = true;
+      }
+      VM_SUPPORTS_LONG_CAS = longCASSupport;
     }
 
     private volatile long value;
 
     /**
-     * Create a new AtomicLong with the given initial value.
+     * Creates a new AtomicLong with the given initial value.
      *
      * @param initialValue the initial value
      */
@@ -62,31 +73,31 @@
     }
 
     /**
-     * Create a new AtomicLong with initial value <tt>0</tt>.
+     * Creates a new AtomicLong with initial value {@code 0}.
      */
     public AtomicLong() {
     }
-  
+
     /**
-     * Get the current value.
+     * Gets the current value.
      *
      * @return the current value
      */
     public final long get() {
         return value;
     }
- 
+
     /**
-     * Set to the given value.
+     * Sets to the given value.
      *
      * @param newValue the new value
      */
     public final void set(long newValue) {
         value = newValue;
     }
-  
+
     /**
-     * Set to the give value and return the old value.
+     * Atomically sets to the given value and returns the old value.
      *
      * @param newValue the new value
      * @return the previous value
@@ -98,33 +109,39 @@
                 return current;
         }
     }
-  
+
     /**
-     * Atomically set the value to the given updated value
-     * if the current value <tt>==</tt> the expected value.
+     * Atomically sets the value to the given updated value
+     * if the current value {@code ==} the expected value.
+     *
      * @param expect the expected value
      * @param update the new value
      * @return true if successful. False return indicates that
      * the actual value was not equal to the expected value.
      */
     public final boolean compareAndSet(long expect, long update) {
-      return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
+        return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
     }
 
     /**
-     * Atomically set the value to the given updated value
-     * if the current value <tt>==</tt> the expected value.
-     * May fail spuriously.
+     * Atomically sets the value to the given updated value
+     * if the current value {@code ==} the expected value.
+     *
+     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
+     * and does not provide ordering guarantees, so is only rarely an
+     * appropriate alternative to {@code compareAndSet}.
+     *
      * @param expect the expected value
      * @param update the new value
      * @return true if successful.
      */
     public final boolean weakCompareAndSet(long expect, long update) {
-      return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
+        return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
     }
-  
+
     /**
-     * Atomically increment by one the current value.
+     * Atomically increments by one the current value.
+     *
      * @return the previous value
      */
     public final long getAndIncrement() {
@@ -135,10 +152,10 @@
                 return current;
         }
     }
-  
-  
+
     /**
-     * Atomically decrement by one the current value.
+     * Atomically decrements by one the current value.
+     *
      * @return the previous value
      */
     public final long getAndDecrement() {
@@ -149,10 +166,10 @@
                 return current;
         }
     }
-  
-  
+
     /**
-     * Atomically add the given value to current value.
+     * Atomically adds the given value to the current value.
+     *
      * @param delta the value to add
      * @return the previous value
      */
@@ -164,9 +181,10 @@
                 return current;
         }
     }
-  
+
     /**
-     * Atomically increment by one the current value.
+     * Atomically increments by one the current value.
+     *
      * @return the updated value
      */
     public final long incrementAndGet() {
@@ -177,9 +195,10 @@
                 return next;
         }
     }
-    
+
     /**
-     * Atomically decrement by one the current value.
+     * Atomically decrements by one the current value.
+     *
      * @return the updated value
      */
     public final long decrementAndGet() {
@@ -190,10 +209,10 @@
                 return next;
         }
     }
-  
-  
+
     /**
-     * Atomically add the given value to current value.
+     * Atomically adds the given value to the current value.
+     *
      * @param delta the value to add
      * @return the updated value
      */
@@ -205,7 +224,7 @@
                 return next;
         }
     }
-  
+
     /**
      * Returns the String representation of the current value.
      * @return the String representation of the current value.
@@ -220,7 +239,7 @@
     }
 
     public long longValue() {
-        return (long)get();
+        return get();
     }
 
     public float floatValue() {
@@ -230,5 +249,5 @@
     public double doubleValue() {
         return (double)get();
     }
-  
+
 }
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 a0e76b4..d96f4c2 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
@@ -9,13 +9,13 @@
 import java.util.*;
 
 /**
- * A <tt>long</tt> array in which elements may be updated atomically.
+ * A {@code long} array in which elements may be updated atomically.
  * See the {@link java.util.concurrent.atomic} package specification
  * for description of the properties of atomic variables.
  * @since 1.5
  * @author Doug Lea
  */
-public class AtomicLongArray implements java.io.Serializable { 
+public class AtomicLongArray implements java.io.Serializable {
     private static final long serialVersionUID = -2308431214976778248L;
 
     // setup to use Unsafe.compareAndSwapInt for updates
@@ -33,25 +33,26 @@
     }
 
     /**
-     * Create a new AtomicLongArray of given length.
+     * Creates a new AtomicLongArray of given length.
+     *
      * @param length the length of the array
      */
     public AtomicLongArray(int length) {
         array = new long[length];
         // must perform at least one volatile write to conform to JMM
-        if (length > 0) 
+        if (length > 0)
             unsafe.putLongVolatile(array, rawIndex(0), 0);
     }
 
     /**
-     * Create a new AtomicLongArray with the same length as, and
+     * Creates a new AtomicLongArray with the same length as, and
      * all elements copied from, the given array.
      *
      * @param array the array to copy elements from
      * @throws NullPointerException if array is null
      */
     public AtomicLongArray(long[] array) {
-        if (array == null) 
+        if (array == null)
             throw new NullPointerException();
         int length = array.length;
         this.array = new long[length];
@@ -74,7 +75,7 @@
     }
 
     /**
-     * Get the current value at position <tt>i</tt>.
+     * Gets the current value at position {@code i}.
      *
      * @param i the index
      * @return the current value
@@ -82,9 +83,9 @@
     public final long get(int i) {
         return unsafe.getLongVolatile(array, rawIndex(i));
     }
- 
+
     /**
-     * Set the element at position <tt>i</tt> to the given value.
+     * Sets the element at position {@code i} to the given value.
      *
      * @param i the index
      * @param newValue the new value
@@ -92,10 +93,10 @@
     public final void set(int i, long newValue) {
         unsafe.putLongVolatile(array, rawIndex(i), newValue);
     }
-  
+
     /**
-     * Set the element at position <tt>i</tt> to the given value and return the
-     * old value.
+     * Atomically sets the element at position {@code i} to the given value
+     * and returns the old value.
      *
      * @param i the index
      * @param newValue the new value
@@ -108,10 +109,11 @@
                 return current;
         }
     }
-  
+
     /**
-     * Atomically set the value to the given updated value
-     * if the current value <tt>==</tt> the expected value.
+     * Atomically sets the value to the given updated value
+     * if the current value {@code ==} the expected value.
+     *
      * @param i the index
      * @param expect the expected value
      * @param update the new value
@@ -119,14 +121,18 @@
      * the actual value was not equal to the expected value.
      */
     public final boolean compareAndSet(int i, long expect, long update) {
-        return unsafe.compareAndSwapLong(array, rawIndex(i), 
+        return unsafe.compareAndSwapLong(array, rawIndex(i),
                                          expect, update);
     }
 
     /**
-     * Atomically set the value to the given updated value
-     * if the current value <tt>==</tt> the expected value.
-     * May fail spuriously.
+     * Atomically sets the value to the given updated value
+     * if the current value {@code ==} the expected value.
+     *
+     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
+     * and does not provide ordering guarantees, so is only rarely an
+     * appropriate alternative to {@code compareAndSet}.
+     *
      * @param i the index
      * @param expect the expected value
      * @param update the new value
@@ -137,10 +143,10 @@
     }
 
     /**
-     * Atomically increment by one the element at index <tt>i</tt>.
+     * Atomically increments by one the element at index {@code i}.
      *
      * @param i the index
-     * @return the previous value;
+     * @return the previous value
      */
     public final long getAndIncrement(int i) {
         while (true) {
@@ -150,12 +156,12 @@
                 return current;
         }
     }
-  
+
     /**
-     * Atomically decrement by one the element at index <tt>i</tt>.
+     * Atomically decrements by one the element at index {@code i}.
      *
      * @param i the index
-     * @return the previous value;
+     * @return the previous value
      */
     public final long getAndDecrement(int i) {
         while (true) {
@@ -165,13 +171,13 @@
                 return current;
         }
     }
-  
+
     /**
-     * Atomically add the given value to element at index <tt>i</tt>.
+     * Atomically adds the given value to the element at index {@code i}.
      *
      * @param i the index
      * @param delta the value to add
-     * @return the previous value;
+     * @return the previous value
      */
     public final long getAndAdd(int i, long delta) {
         while (true) {
@@ -181,13 +187,12 @@
                 return current;
         }
     }
-  
 
     /**
-     * Atomically increment the element at index <tt>i</tt>.
+     * Atomically increments by one the element at index {@code i}.
      *
      * @param i the index
-     * @return the updated value;
+     * @return the updated value
      */
     public final long incrementAndGet(int i) {
         while (true) {
@@ -197,12 +202,12 @@
                 return next;
         }
     }
-  
+
     /**
-     * Atomically decrement the element at index <tt>i</tt>.
+     * Atomically decrements by one the element at index {@code i}.
      *
      * @param i the index
-     * @return the updated value;
+     * @return the updated value
      */
     public final long decrementAndGet(int i) {
         while (true) {
@@ -212,13 +217,13 @@
                 return next;
         }
     }
-  
+
     /**
-     * Atomically add the given value to element at index <tt>i</tt>.
+     * Atomically adds the given value to the element at index {@code i}.
      *
      * @param i the index
      * @param delta the value to add
-     * @return the updated value;
+     * @return the updated value
      */
     public long addAndGet(int i, long delta) {
         while (true) {
@@ -238,5 +243,5 @@
             get(0);
         return Arrays.toString(array);
     }
-  
+
 }
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
index dcb8b2e..d97c2e4 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
@@ -8,19 +8,22 @@
 import sun.misc.Unsafe;
 import java.lang.reflect.*;
 
+import org.apache.harmony.kernel.vm.VM;
+import dalvik.system.VMStack;
+
 /**
  * A reflection-based utility that enables atomic updates to
- * designated <tt>volatile long</tt> fields of designated classes.
+ * designated {@code volatile long} fields of designated classes.
  * This class is designed for use in atomic data structures in which
  * several fields of the same node are independently subject to atomic
  * updates.
  *
- * <p> Note that the guarantees of the <tt>compareAndSet</tt> method
- * in this class are weaker than in other atomic classes. Because this
- * class cannot ensure that all uses of the field are appropriate for
- * purposes of atomic access, it can guarantee atomicity and volatile
- * semantics only with respect to other invocations of
- * <tt>compareAndSet</tt> and <tt>set</tt>.
+ * <p>Note that the guarantees of the {@code compareAndSet}
+ * method in this class are weaker than in other atomic classes.
+ * Because this class cannot ensure that all uses of the field
+ * are appropriate for purposes of atomic access, it can
+ * guarantee atomicity only with respect to other invocations of
+ * {@code compareAndSet} and {@code set} on the same updater.
  *
  * @since 1.5
  * @author Doug Lea
@@ -28,9 +31,10 @@
  */
 public abstract class  AtomicLongFieldUpdater<T>  {
     /**
-     * Creates an updater for objects with the given field.  The Class
-     * argument is needed to check that reflective types and generic
-     * types match.
+     * Creates and returns an updater for objects with the given field.
+     * The Class argument is needed to check that reflective types and
+     * generic types match.
+     *
      * @param tclass the class of the objects holding the field
      * @param fieldName the name of the field to be updated.
      * @return the updater
@@ -53,57 +57,63 @@
     }
 
     /**
-     * Atomically set the value of the field of the given object managed
-     * by this Updater to the given updated value if the current value
-     * <tt>==</tt> the expected value. This method is guaranteed to be
-     * atomic with respect to other calls to <tt>compareAndSet</tt> and
-     * <tt>set</tt>, but not necessarily with respect to other
-     * changes in the field.
+     * Atomically sets the field of the given object managed by this updater
+     * to the given updated value if the current value {@code ==} the
+     * expected value. This method is guaranteed to be atomic with respect to
+     * other calls to {@code compareAndSet} and {@code set}, but not
+     * necessarily with respect to other changes in the field.
+     *
      * @param obj An object whose field to conditionally set
      * @param expect the expected value
      * @param update the new value
      * @return true if successful.
-     * @throws ClassCastException if <tt>obj</tt> is not an instance
+     * @throws ClassCastException if {@code obj} is not an instance
      * of the class possessing the field established in the constructor.
      */
-
     public abstract boolean compareAndSet(T obj, long expect, long update);
 
     /**
-     * Atomically set the value of the field of the given object managed
-     * by this Updater to the given updated value if the current value
-     * <tt>==</tt> the expected value. This method is guaranteed to be
-     * atomic with respect to other calls to <tt>compareAndSet</tt> and
-     * <tt>set</tt>, but not necessarily with respect to other
-     * changes in the field, and may fail spuriously.
+     * Atomically sets the field of the given object managed by this updater
+     * to the given updated value if the current value {@code ==} the
+     * expected value. This method is guaranteed to be atomic with respect to
+     * other calls to {@code compareAndSet} and {@code set}, but not
+     * necessarily with respect to other changes in the field.
+     *
+     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
+     * and does not provide ordering guarantees, so is only rarely an
+     * appropriate alternative to {@code compareAndSet}.
+     *
      * @param obj An object whose field to conditionally set
      * @param expect the expected value
      * @param update the new value
      * @return true if successful.
-     * @throws ClassCastException if <tt>obj</tt> is not an instance
+     * @throws ClassCastException if {@code obj} is not an instance
      * of the class possessing the field established in the constructor.
      */
-
     public abstract boolean weakCompareAndSet(T obj, long expect, long update);
 
     /**
-     * Set the field of the given object managed by this updater. This
-     * operation is guaranteed to act as a volatile store with respect
-     * to subsequent invocations of <tt>compareAndSet</tt>.
+     * Sets the field of the given object managed by this updater to the
+     * given updated value. This operation is guaranteed to act as a volatile
+     * store with respect to subsequent invocations of {@code compareAndSet}.
+     *
      * @param obj An object whose field to set
      * @param newValue the new value
      */
     public abstract void set(T obj, long newValue);
 
     /**
-     * Get the current value held in the field by the given object.
+     * Gets the current value held in the field of the given object managed
+     * by this updater.
+     *
      * @param obj An object whose field to get
      * @return the current value
      */
     public abstract long get(T obj);
 
     /**
-     * Set to the given value and return the old value.
+     * Atomically sets the field of the given object managed by this updater
+     * to the given value and returns the old value.
      *
      * @param obj An object whose field to get and set
      * @param newValue the new value
@@ -118,9 +128,11 @@
     }
 
     /**
-     * Atomically increment by one the current value.
+     * Atomically increments by one the current value of the field of the
+     * given object managed by this updater.
+     *
      * @param obj An object whose field to get and set
-     * @return the previous value;
+     * @return the previous value
      */
     public long getAndIncrement(T obj) {
         for (;;) {
@@ -131,11 +143,12 @@
         }
     }
 
-
     /**
-     * Atomically decrement by one the current value.
+     * Atomically decrements by one the current value of the field of the
+     * given object managed by this updater.
+     *
      * @param obj An object whose field to get and set
-     * @return the previous value;
+     * @return the previous value
      */
     public long getAndDecrement(T obj) {
         for (;;) {
@@ -146,12 +159,13 @@
         }
     }
 
-
     /**
-     * Atomically add the given value to current value.
+     * Atomically adds the given value to the current value of the field of
+     * the given object managed by this updater.
+     *
      * @param obj An object whose field to get and set
      * @param delta the value to add
-     * @return the previous value;
+     * @return the previous value
      */
     public long getAndAdd(T obj, long delta) {
         for (;;) {
@@ -163,9 +177,11 @@
     }
 
     /**
-     * Atomically increment by one the current value.
+     * Atomically increments by one the current value of the field of the
+     * given object managed by this updater.
+     *
      * @param obj An object whose field to get and set
-     * @return the updated value;
+     * @return the updated value
      */
     public long incrementAndGet(T obj) {
         for (;;) {
@@ -176,11 +192,12 @@
         }
     }
 
-
     /**
-     * Atomically decrement by one the current value.
+     * Atomically decrements by one the current value of the field of the
+     * given object managed by this updater.
+     *
      * @param obj An object whose field to get and set
-     * @return the updated value;
+     * @return the updated value
      */
     public long decrementAndGet(T obj) {
         for (;;) {
@@ -191,12 +208,13 @@
         }
     }
 
-
     /**
-     * Atomically add the given value to current value.
+     * Atomically adds the given value to the current value of the field of
+     * the given object managed by this updater.
+     *
      * @param obj An object whose field to get and set
      * @param delta the value to add
-     * @return the updated value;
+     * @return the updated value
      */
     public long addAndGet(T obj, long delta) {
         for (;;) {
@@ -213,49 +231,83 @@
         // END android-changed
         private final long offset;
         private final Class<T> tclass;
+        private final Class cclass;
 
         CASUpdater(Class<T> tclass, String fieldName) {
             Field field = null;
+            Class caller = null;
+            int modifiers = 0;
             try {
                 field = tclass.getDeclaredField(fieldName);
-            } catch(Exception ex) {
+                // BEGIN android-changed
+                caller = VMStack.getStackClass2();
+                // END android-changed
+                modifiers = field.getModifiers();
+                SecurityManager smgr = System.getSecurityManager();
+                if (smgr != null) {
+                    int type = Modifier.isPublic(modifiers)
+                            ? Member.PUBLIC : Member.DECLARED;
+                    smgr.checkMemberAccess(tclass, type);
+                    smgr.checkPackageAccess(tclass.getPackage().getName());
+                }
+            } catch (Exception ex) {
                 throw new RuntimeException(ex);
             }
-            
+
             Class fieldt = field.getType();
             if (fieldt != long.class)
                 throw new IllegalArgumentException("Must be long type");
-            
-            if (!Modifier.isVolatile(field.getModifiers()))
+
+            if (!Modifier.isVolatile(modifiers))
                 throw new IllegalArgumentException("Must be volatile type");
-            
+
+            this.cclass = (Modifier.isProtected(modifiers) &&
+                           caller != tclass) ? caller : null;
             this.tclass = tclass;
             offset = unsafe.objectFieldOffset(field);
         }
 
-        public boolean compareAndSet(T obj, long expect, long update) {
+        private void fullCheck(T obj) {
             if (!tclass.isInstance(obj))
                 throw new ClassCastException();
+            if (cclass != null)
+                ensureProtectedAccess(obj);
+        }
+
+        public boolean compareAndSet(T obj, long expect, long update) {
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
             return unsafe.compareAndSwapLong(obj, offset, expect, update);
         }
 
         public boolean weakCompareAndSet(T obj, long expect, long update) {
-            if (!tclass.isInstance(obj))
-                throw new ClassCastException();
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
             return unsafe.compareAndSwapLong(obj, offset, expect, update);
         }
 
         public void set(T obj, long newValue) {
-            if (!tclass.isInstance(obj))
-                throw new ClassCastException();
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
             unsafe.putLongVolatile(obj, offset, newValue);
         }
 
         public long get(T obj) {
-            if (!tclass.isInstance(obj))
-                throw new ClassCastException();
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
             return unsafe.getLongVolatile(obj, offset);
         }
+
+        private void ensureProtectedAccess(T obj) {
+            if (cclass.isInstance(obj)) {
+                return;
+            }
+            throw new RuntimeException (
+                new IllegalAccessException("Class " +
+                    cclass.getName() +
+                    " can not access a protected member of class " +
+                    tclass.getName() +
+                    " using an instance of " +
+                    obj.getClass().getName()
+                )
+            );
+        }
     }
 
 
@@ -265,32 +317,54 @@
         // END android-changed
         private final long offset;
         private final Class<T> tclass;
+        private final Class cclass;
 
         LockedUpdater(Class<T> tclass, String fieldName) {
             Field field = null;
+            Class caller = null;
+            int modifiers = 0;
             try {
                 field = tclass.getDeclaredField(fieldName);
-            } catch(Exception ex) {
+                // BEGIN android-changed
+                caller = VMStack.getStackClass2();
+                // END android-changed
+                modifiers = field.getModifiers();
+                SecurityManager smgr = System.getSecurityManager();
+                if (smgr != null) {
+                    int type = Modifier.isPublic(modifiers)
+                            ? Member.PUBLIC : Member.DECLARED;
+                    smgr.checkMemberAccess(tclass, type);
+                    smgr.checkPackageAccess(tclass.getPackage().getName());
+                }
+            } catch (Exception ex) {
                 throw new RuntimeException(ex);
             }
-            
+
             Class fieldt = field.getType();
             if (fieldt != long.class)
                 throw new IllegalArgumentException("Must be long type");
-            
-            if (!Modifier.isVolatile(field.getModifiers()))
+
+            if (!Modifier.isVolatile(modifiers))
                 throw new IllegalArgumentException("Must be volatile type");
-            
+
+            this.cclass = (Modifier.isProtected(modifiers) &&
+                           caller != tclass) ? caller : null;
             this.tclass = tclass;
             offset = unsafe.objectFieldOffset(field);
         }
 
-        public boolean compareAndSet(T obj, long expect, long update) {
+        private void fullCheck(T obj) {
             if (!tclass.isInstance(obj))
                 throw new ClassCastException();
+            if (cclass != null)
+                ensureProtectedAccess(obj);
+        }
+
+        public boolean compareAndSet(T obj, long expect, long update) {
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
             synchronized(this) {
                 long v = unsafe.getLong(obj, offset);
-                if (v != expect) 
+                if (v != expect)
                     return false;
                 unsafe.putLong(obj, offset, update);
                 return true;
@@ -302,20 +376,36 @@
         }
 
         public void set(T obj, long newValue) {
-            if (!tclass.isInstance(obj))
-                throw new ClassCastException();
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
             synchronized(this) {
                 unsafe.putLong(obj, offset, newValue);
             }
         }
 
+        public void lazySet(T obj, long newValue) {
+            set(obj, newValue);
+        }
+
         public long get(T obj) {
-            if (!tclass.isInstance(obj))
-                throw new ClassCastException();
+            if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj);
             synchronized(this) {
                 return unsafe.getLong(obj, offset);
             }
         }
+
+        private void ensureProtectedAccess(T obj) {
+            if (cclass.isInstance(obj)) {
+                return;
+            }
+            throw new RuntimeException (
+                new IllegalAccessException("Class " +
+                    cclass.getName() +
+                    " can not access a protected member of class " +
+                    tclass.getName() +
+                    " using an instance of " +
+                    obj.getClass().getName()
+                )
+            );
+        }
     }
 }
-
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicMarkableReference.java b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicMarkableReference.java
index 11c91ba..4877dc4 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicMarkableReference.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicMarkableReference.java
@@ -7,7 +7,7 @@
 package java.util.concurrent.atomic;
 
 /**
- * An <tt>AtomicMarkableReference</tt> maintains an object reference
+ * An {@code AtomicMarkableReference} maintains an object reference
  * along with a mark bit, that can be updated atomically.
  * <p>
  * <p> Implementation note. This implementation maintains markable
@@ -31,7 +31,7 @@
     private final AtomicReference<ReferenceBooleanPair<V>>  atomicRef;
 
     /**
-     * Creates a new <tt>AtomicMarkableReference</tt> with the given
+     * Creates a new {@code AtomicMarkableReference} with the given
      * initial values.
      *
      * @param initialRef the initial reference
@@ -61,10 +61,10 @@
 
     /**
      * Returns the current values of both the reference and the mark.
-     * Typical usage is <tt>boolean[1] holder; ref = v.get(holder); </tt>.
+     * Typical usage is {@code boolean[1] holder; ref = v.get(holder); }.
      *
      * @param markHolder an array of size of at least one. On return,
-     * <tt>markholder[0]</tt> will hold the value of the mark.
+     * {@code markholder[0]} will hold the value of the mark.
      * @return the current value of the reference
      */
     public V get(boolean[] markHolder) {
@@ -76,12 +76,12 @@
     /**
      * Atomically sets the value of both the reference and mark
      * to the given update values if the
-     * current reference is <tt>==</tt> to the expected reference
-     * and the current mark is equal to the expected mark.  Any given
-     * invocation of this operation may fail (return
-     * <tt>false</tt>) spuriously, but repeated invocation when
-     * the current value holds the expected value and no other thread
-     * is also attempting to set the value will eventually succeed.
+     * current reference is {@code ==} to the expected reference
+     * and the current mark is equal to the expected mark.
+     *
+     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
+     * and does not provide ordering guarantees, so is only rarely an
+     * appropriate alternative to {@code compareAndSet}.
      *
      * @param expectedReference the expected value of the reference
      * @param newReference the new value for the reference
@@ -93,7 +93,7 @@
                                      V       newReference,
                                      boolean expectedMark,
                                      boolean newMark) {
-        ReferenceBooleanPair current = atomicRef.get();
+        ReferenceBooleanPair<V> current = atomicRef.get();
         return  expectedReference == current.reference &&
             expectedMark == current.bit &&
             ((newReference == current.reference && newMark == current.bit) ||
@@ -105,8 +105,8 @@
     /**
      * Atomically sets the value of both the reference and mark
      * to the given update values if the
-     * current reference is <tt>==</tt> to the expected reference
-     * and the current mark is equal to the expected mark.  
+     * current reference is {@code ==} to the expected reference
+     * and the current mark is equal to the expected mark.
      *
      * @param expectedReference the expected value of the reference
      * @param newReference the new value for the reference
@@ -118,7 +118,7 @@
                                  V       newReference,
                                  boolean expectedMark,
                                  boolean newMark) {
-        ReferenceBooleanPair current = atomicRef.get();
+        ReferenceBooleanPair<V> current = atomicRef.get();
         return  expectedReference == current.reference &&
             expectedMark == current.bit &&
             ((newReference == current.reference && newMark == current.bit) ||
@@ -134,16 +134,16 @@
      * @param newMark the new value for the mark
      */
     public void set(V newReference, boolean newMark) {
-        ReferenceBooleanPair current = atomicRef.get();
+        ReferenceBooleanPair<V> current = atomicRef.get();
         if (newReference != current.reference || newMark != current.bit)
             atomicRef.set(new ReferenceBooleanPair<V>(newReference, newMark));
     }
 
     /**
      * Atomically sets the value of the mark to the given update value
-     * if the current reference is <tt>==</tt> to the expected
+     * if the current reference is {@code ==} to the expected
      * reference.  Any given invocation of this operation may fail
-     * (return <tt>false</tt>) spuriously, but repeated invocation
+     * (return {@code false}) spuriously, but repeated invocation
      * when the current value holds the expected value and no other
      * thread is also attempting to set the value will eventually
      * succeed.
@@ -153,7 +153,7 @@
      * @return true if successful
      */
     public boolean attemptMark(V expectedReference, boolean newMark) {
-        ReferenceBooleanPair current = atomicRef.get();
+        ReferenceBooleanPair<V> current = atomicRef.get();
         return  expectedReference == current.reference &&
             (newMark == current.bit ||
              atomicRef.compareAndSet
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReference.java b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReference.java
index 89c050c..1de9b1c 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReference.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReference.java
@@ -15,7 +15,7 @@
  * @author Doug Lea
  * @param <V> The type of object referred to by this reference
  */
-public class AtomicReference<V>  implements java.io.Serializable { 
+public class AtomicReference<V>  implements java.io.Serializable {
     private static final long serialVersionUID = -1848883965231344442L;
 
     // BEGIN android-changed
@@ -27,13 +27,13 @@
       try {
         valueOffset = unsafe.objectFieldOffset
             (AtomicReference.class.getDeclaredField("value"));
-      } catch(Exception ex) { throw new Error(ex); }
+      } catch (Exception ex) { throw new Error(ex); }
     }
 
     private volatile V value;
 
     /**
-     * Create a new AtomicReference with the given initial value.
+     * Creates a new AtomicReference with the given initial value.
      *
      * @param initialValue the initial value
      */
@@ -42,55 +42,59 @@
     }
 
     /**
-     * Create a new AtomicReference with null initial value.
+     * Creates a new AtomicReference with null initial value.
      */
     public AtomicReference() {
     }
-  
+
     /**
-     * Get the current value.
+     * Gets the current value.
      *
      * @return the current value
      */
     public final V get() {
         return value;
     }
-  
+
     /**
-     * Set to the given value.
+     * Sets to the given value.
      *
      * @param newValue the new value
      */
     public final void set(V newValue) {
         value = newValue;
     }
-  
+
     /**
-     * Atomically set the value to the given updated value
-     * if the current value <tt>==</tt> the expected value.
+     * Atomically sets the value to the given updated value
+     * if the current value {@code ==} the expected value.
      * @param expect the expected value
      * @param update the new value
      * @return true if successful. False return indicates that
      * the actual value was not equal to the expected value.
      */
     public final boolean compareAndSet(V expect, V update) {
-      return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
+        return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
     }
 
     /**
-     * Atomically set the value to the given updated value
-     * if the current value <tt>==</tt> the expected value.
-     * May fail spuriously.
+     * Atomically sets the value to the given updated value
+     * if the current value {@code ==} the expected value.
+     *
+     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
+     * and does not provide ordering guarantees, so is only rarely an
+     * appropriate alternative to {@code compareAndSet}.
+     *
      * @param expect the expected value
      * @param update the new value
      * @return true if successful.
      */
     public final boolean weakCompareAndSet(V expect, V update) {
-      return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
+        return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
     }
 
     /**
-     * Set to the given value and return the old value.
+     * Atomically sets to the given value and returns the old value.
      *
      * @param newValue the new value
      * @return the previous value
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 9ad800c..9a484e6 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
@@ -17,7 +17,7 @@
  * @author Doug Lea
  * @param <E> The base class of elements held in this array
  */
-public class AtomicReferenceArray<E> implements java.io.Serializable { 
+public class AtomicReferenceArray<E> implements java.io.Serializable {
     private static final long serialVersionUID = -6209656149925076980L;
 
     // BEGIN android-changed
@@ -34,25 +34,25 @@
     }
 
     /**
-     * Create a new AtomicReferenceArray of given length.
+     * Creates a new AtomicReferenceArray of given length.
      * @param length the length of the array
      */
     public AtomicReferenceArray(int length) {
         array = new Object[length];
         // must perform at least one volatile write to conform to JMM
-        if (length > 0) 
+        if (length > 0)
             unsafe.putObjectVolatile(array, rawIndex(0), null);
     }
 
     /**
-     * Create a new AtomicReferenceArray with the same length as, and
+     * Creates a new AtomicReferenceArray with the same length as, and
      * all elements copied from, the given array.
      *
      * @param array the array to copy elements from
      * @throws NullPointerException if array is null
      */
     public AtomicReferenceArray(E[] array) {
-        if (array == null) 
+        if (array == null)
             throw new NullPointerException();
         int length = array.length;
         this.array = new Object[length];
@@ -76,7 +76,7 @@
     }
 
     /**
-     * Get the current value at position <tt>i</tt>.
+     * Gets the current value at position {@code i}.
      *
      * @param i the index
      * @return the current value
@@ -84,9 +84,9 @@
     public final E get(int i) {
         return (E) unsafe.getObjectVolatile(array, rawIndex(i));
     }
- 
+
     /**
-     * Set the element at position <tt>i</tt> to the given value.
+     * Sets the element at position {@code i} to the given value.
      *
      * @param i the index
      * @param newValue the new value
@@ -94,10 +94,10 @@
     public final void set(int i, E newValue) {
         unsafe.putObjectVolatile(array, rawIndex(i), newValue);
     }
-  
+
     /**
-     * Set the element at position <tt>i</tt> to the given value and return the
-     * old value.
+     * Atomically sets the element at position {@code i} to the given
+     * value and returns the old value.
      *
      * @param i the index
      * @param newValue the new value
@@ -110,10 +110,10 @@
                 return current;
         }
     }
-  
+
     /**
-     * Atomically set the value to the given updated value
-     * if the current value <tt>==</tt> the expected value.
+     * Atomically sets the element at position {@code i} to the given
+     * updated value if the current value {@code ==} the expected value.
      * @param i the index
      * @param expect the expected value
      * @param update the new value
@@ -121,14 +121,18 @@
      * the actual value was not equal to the expected value.
      */
     public final boolean compareAndSet(int i, E expect, E update) {
-        return unsafe.compareAndSwapObject(array, rawIndex(i), 
+        return unsafe.compareAndSwapObject(array, rawIndex(i),
                                          expect, update);
     }
 
     /**
-     * Atomically set the value to the given updated value
-     * if the current value <tt>==</tt> the expected value.
-     * May fail spuriously.
+     * Atomically sets the element at position {@code i} to the given
+     * updated value if the current value {@code ==} the expected value.
+     *
+     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
+     * and does not provide ordering guarantees, so is only rarely an
+     * appropriate alternative to {@code compareAndSet}.
+     *
      * @param i the index
      * @param expect the expected value
      * @param update the new value
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
index f20661d..fae134f 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
@@ -8,9 +8,12 @@
 import sun.misc.Unsafe;
 import java.lang.reflect.*;
 
+import org.apache.harmony.kernel.vm.VM;
+import dalvik.system.VMStack;
+
 /**
  * A reflection-based utility that enables atomic updates to
- * designated <tt>volatile</tt> reference fields of designated
+ * designated {@code volatile} reference fields of designated
  * classes.  This class is designed for use in atomic data structures
  * in which several reference fields of the same node are
  * independently subject to atomic updates. For example, a tree node
@@ -33,12 +36,13 @@
  * }
  * </pre>
  *
- * <p> Note that the guarantees of the <tt>compareAndSet</tt>
- * method in this class are weaker than in other atomic classes. Because this
- * class cannot ensure that all uses of the field are appropriate for
- * purposes of atomic access, it can guarantee atomicity and volatile
- * semantics only with respect to other invocations of
- * <tt>compareAndSet</tt> and <tt>set</tt>.
+ * <p>Note that the guarantees of the {@code compareAndSet}
+ * method in this class are weaker than in other atomic classes.
+ * Because this class cannot ensure that all uses of the field
+ * are appropriate for purposes of atomic access, it can
+ * guarantee atomicity only with respect to other invocations of
+ * {@code compareAndSet} and {@code set} on the same updater.
+ *
  * @since 1.5
  * @author Doug Lea
  * @param <T> The type of the object holding the updatable field
@@ -47,9 +51,10 @@
 public abstract class AtomicReferenceFieldUpdater<T, V>  {
 
     /**
-     * Creates an updater for objects with the given field.  The Class
-     * arguments are needed to check that reflective types and generic
-     * types match.
+     * Creates and returns an updater for objects with the given field.
+     * The Class arguments are needed to check that reflective types and
+     * generic types match.
+     *
      * @param tclass the class of the objects holding the field.
      * @param vclass the class of the field
      * @param fieldName the name of the field to be updated.
@@ -59,9 +64,8 @@
      * exception if the class does not hold field or is the wrong type.
      */
     public static <U, W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass, Class<W> vclass, String fieldName) {
-        // Currently rely on standard intrinsics implementation
-        return new AtomicReferenceFieldUpdaterImpl<U,W>(tclass, 
-                                                        vclass, 
+        return new AtomicReferenceFieldUpdaterImpl<U,W>(tclass,
+                                                        vclass,
                                                         fieldName);
     }
 
@@ -72,27 +76,30 @@
     }
 
     /**
-     * Atomically set the value of the field of the given object managed
-     * by this Updater to the given updated value if the current value
-     * <tt>==</tt> the expected value. This method is guaranteed to be
-     * atomic with respect to other calls to <tt>compareAndSet</tt> and
-     * <tt>set</tt>, but not necessarily with respect to other
-     * changes in the field.
+     * Atomically sets the field of the given object managed by this updater
+     * to the given updated value if the current value {@code ==} the
+     * expected value. This method is guaranteed to be atomic with respect to
+     * other calls to {@code compareAndSet} and {@code set}, but not
+     * necessarily with respect to other changes in the field.
+     *
      * @param obj An object whose field to conditionally set
      * @param expect the expected value
      * @param update the new value
      * @return true if successful.
      */
-
     public abstract boolean compareAndSet(T obj, V expect, V update);
 
     /**
-     * Atomically set the value of the field of the given object managed
-     * by this Updater to the given updated value if the current value
-     * <tt>==</tt> the expected value. This method is guaranteed to be
-     * atomic with respect to other calls to <tt>compareAndSet</tt> and
-     * <tt>set</tt>, but not necessarily with respect to other
-     * changes in the field, and may fail spuriously.
+     * Atomically sets the field of the given object managed by this updater
+     * to the given updated value if the current value {@code ==} the
+     * expected value. This method is guaranteed to be atomic with respect to
+     * other calls to {@code compareAndSet} and {@code set}, but not
+     * necessarily with respect to other changes in the field.
+     *
+     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
+     * and does not provide ordering guarantees, so is only rarely an
+     * appropriate alternative to {@code compareAndSet}.
+     *
      * @param obj An object whose field to conditionally set
      * @param expect the expected value
      * @param update the new value
@@ -101,23 +108,27 @@
     public abstract boolean weakCompareAndSet(T obj, V expect, V update);
 
     /**
-     * Set the field of the given object managed by this updater. This
-     * operation is guaranteed to act as a volatile store with respect
-     * to subsequent invocations of <tt>compareAndSet</tt>.
+     * Sets the field of the given object managed by this updater to the
+     * given updated value. This operation is guaranteed to act as a volatile
+     * store with respect to subsequent invocations of {@code compareAndSet}.
+     *
      * @param obj An object whose field to set
      * @param newValue the new value
      */
     public abstract void set(T obj, V newValue);
 
     /**
-     * Get the current value held in the field by the given object.
+     * Gets the current value held in the field of the given object managed
+     * by this updater.
+     *
      * @param obj An object whose field to get
      * @return the current value
      */
     public abstract V get(T obj);
 
     /**
-     * Set to the given value and return the old value.
+     * Atomically sets the field of the given object managed by this updater
+     * to the given value and returns the old value.
      *
      * @param obj An object whose field to get and set
      * @param newValue the new value
@@ -131,67 +142,128 @@
         }
     }
 
-    /**
-     * Standard hotspot implementation using intrinsics
-     */
-    private static class AtomicReferenceFieldUpdaterImpl<T,V> extends AtomicReferenceFieldUpdater<T,V> {
+    private static final class AtomicReferenceFieldUpdaterImpl<T,V>
+        extends AtomicReferenceFieldUpdater<T,V> {
         // BEGIN android-changed
         private static final Unsafe unsafe = UnsafeAccess.THE_ONE;
         // END android-changed
         private final long offset;
         private final Class<T> tclass;
         private final Class<V> vclass;
+        private final Class cclass;
 
-        AtomicReferenceFieldUpdaterImpl(Class<T> tclass, Class<V> vclass, String fieldName) {
+        /*
+         * Internal type checks within all update methods contain
+         * internal inlined optimizations checking for the common
+         * cases where the class is final (in which case a simple
+         * getClass comparison suffices) or is of type Object (in
+         * which case no check is needed because all objects are
+         * instances of Object). The Object case is handled simply by
+         * setting vclass to null in constructor.  The targetCheck and
+         * updateCheck methods are invoked when these faster
+         * screenings fail.
+         */
+
+        AtomicReferenceFieldUpdaterImpl(Class<T> tclass,
+                                        Class<V> vclass,
+                                        String fieldName) {
             Field field = null;
             Class fieldClass = null;
+            Class caller = null;
+            int modifiers = 0;
             try {
                 field = tclass.getDeclaredField(fieldName);
+                // BEGIN android-changed
+                caller = VMStack.getStackClass2();
+                // END android-changed
+                modifiers = field.getModifiers();
+                SecurityManager smgr = System.getSecurityManager();
+                if (smgr != null) {
+                    int type = Modifier.isPublic(modifiers)
+                            ? Member.PUBLIC : Member.DECLARED;
+                    smgr.checkMemberAccess(tclass, type);
+                    smgr.checkPackageAccess(tclass.getPackage().getName());
+                }
                 fieldClass = field.getType();
-            } catch(Exception ex) {
+            } catch (Exception ex) {
                 throw new RuntimeException(ex);
             }
-            
+
             if (vclass != fieldClass)
                 throw new ClassCastException();
-            
-            if (!Modifier.isVolatile(field.getModifiers()))
+
+            if (!Modifier.isVolatile(modifiers))
                 throw new IllegalArgumentException("Must be volatile type");
 
+            this.cclass = (Modifier.isProtected(modifiers) &&
+                           caller != tclass) ? caller : null;
             this.tclass = tclass;
-            this.vclass = vclass;
+            if (vclass == Object.class)
+                this.vclass = null;
+            else
+                this.vclass = vclass;
             offset = unsafe.objectFieldOffset(field);
         }
-        
+
+        void targetCheck(T obj) {
+            if (!tclass.isInstance(obj))
+                throw new ClassCastException();
+            if (cclass != null)
+                ensureProtectedAccess(obj);
+        }
+
+        void updateCheck(T obj, V update) {
+            if (!tclass.isInstance(obj) ||
+                (update != null && vclass != null && !vclass.isInstance(update)))
+                throw new ClassCastException();
+            if (cclass != null)
+                ensureProtectedAccess(obj);
+        }
 
         public boolean compareAndSet(T obj, V expect, V update) {
-            if (!tclass.isInstance(obj) ||
-                (update != null && !vclass.isInstance(update)))
-                throw new ClassCastException();
+            if (obj == null || obj.getClass() != tclass || cclass != null ||
+                (update != null && vclass != null &&
+                 vclass != update.getClass()))
+                updateCheck(obj, update);
             return unsafe.compareAndSwapObject(obj, offset, expect, update);
         }
 
         public boolean weakCompareAndSet(T obj, V expect, V update) {
             // same implementation as strong form for now
-            if (!tclass.isInstance(obj) ||
-                (update != null && !vclass.isInstance(update)))
-                throw new ClassCastException();
+            if (obj == null || obj.getClass() != tclass || cclass != null ||
+                (update != null && vclass != null &&
+                 vclass != update.getClass()))
+                updateCheck(obj, update);
             return unsafe.compareAndSwapObject(obj, offset, expect, update);
         }
 
-
         public void set(T obj, V newValue) {
-            if (!tclass.isInstance(obj) ||
-                (newValue != null && !vclass.isInstance(newValue)))
-                throw new ClassCastException();
+            if (obj == null || obj.getClass() != tclass || cclass != null ||
+                (newValue != null && vclass != null &&
+                 vclass != newValue.getClass()))
+                updateCheck(obj, newValue);
             unsafe.putObjectVolatile(obj, offset, newValue);
         }
 
         public V get(T obj) {
-            if (!tclass.isInstance(obj))
-                throw new ClassCastException();
+            if (obj == null || obj.getClass() != tclass || cclass != null)
+                targetCheck(obj);
             return (V)unsafe.getObjectVolatile(obj, offset);
         }
+
+        private void ensureProtectedAccess(T obj) {
+            if (cclass.isInstance(obj)) {
+                return;
+            }
+            throw new RuntimeException (
+                new IllegalAccessException("Class " +
+                    cclass.getName() +
+                    " can not access a protected member of class " +
+                    tclass.getName() +
+                    " using an instance of " +
+                    obj.getClass().getName()
+                )
+            );
+        }
     }
 }
-
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicStampedReference.java b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicStampedReference.java
index b0a02c2..a1d535f 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicStampedReference.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/AtomicStampedReference.java
@@ -7,8 +7,8 @@
 package java.util.concurrent.atomic;
 
 /**
- * An <tt>AtomicStampedReference</tt> maintains an object reference
- * along with an integer "stamp", that can be updated atomically.  
+ * An {@code AtomicStampedReference} maintains an object reference
+ * along with an integer "stamp", that can be updated atomically.
  *
  * <p> Implementation note. This implementation maintains stamped
  * references by creating internal objects representing "boxed"
@@ -31,7 +31,7 @@
     private final AtomicReference<ReferenceIntegerPair<V>>  atomicRef;
 
     /**
-     * Creates a new <tt>AtomicStampedReference</tt> with the given
+     * Creates a new {@code AtomicStampedReference} with the given
      * initial values.
      *
      * @param initialRef the initial reference
@@ -62,10 +62,10 @@
 
     /**
      * Returns the current values of both the reference and the stamp.
-     * Typical usage is <tt>int[1] holder; ref = v.get(holder); </tt>.
+     * Typical usage is {@code int[1] holder; ref = v.get(holder); }.
      *
      * @param stampHolder an array of size of at least one.  On return,
-     * <tt>stampholder[0]</tt> will hold the value of the stamp.
+     * {@code stampholder[0]} will hold the value of the stamp.
      * @return the current value of the reference
      */
     public V get(int[] stampHolder) {
@@ -77,12 +77,12 @@
     /**
      * Atomically sets the value of both the reference and stamp
      * to the given update values if the
-     * current reference is <tt>==</tt> to the expected reference
-     * and the current stamp is equal to the expected stamp.  Any given
-     * invocation of this operation may fail (return
-     * <tt>false</tt>) spuriously, but repeated invocation when
-     * the current value holds the expected value and no other thread
-     * is also attempting to set the value will eventually succeed.
+     * current reference is {@code ==} to the expected reference
+     * and the current stamp is equal to the expected stamp.
+     *
+     * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
+     * and does not provide ordering guarantees, so is only rarely an
+     * appropriate alternative to {@code compareAndSet}.
      *
      * @param expectedReference the expected value of the reference
      * @param newReference the new value for the reference
@@ -94,7 +94,7 @@
                                      V      newReference,
                                      int    expectedStamp,
                                      int    newStamp) {
-        ReferenceIntegerPair current = atomicRef.get();
+        ReferenceIntegerPair<V> current = atomicRef.get();
         return  expectedReference == current.reference &&
             expectedStamp == current.integer &&
             ((newReference == current.reference &&
@@ -107,8 +107,8 @@
     /**
      * Atomically sets the value of both the reference and stamp
      * to the given update values if the
-     * current reference is <tt>==</tt> to the expected reference
-     * and the current stamp is equal to the expected stamp. 
+     * current reference is {@code ==} to the expected reference
+     * and the current stamp is equal to the expected stamp.
      *
      * @param expectedReference the expected value of the reference
      * @param newReference the new value for the reference
@@ -120,7 +120,7 @@
                                  V      newReference,
                                  int    expectedStamp,
                                  int    newStamp) {
-        ReferenceIntegerPair current = atomicRef.get();
+        ReferenceIntegerPair<V> current = atomicRef.get();
         return  expectedReference == current.reference &&
             expectedStamp == current.integer &&
             ((newReference == current.reference &&
@@ -138,16 +138,16 @@
      * @param newStamp the new value for the stamp
      */
     public void set(V newReference, int newStamp) {
-        ReferenceIntegerPair current = atomicRef.get();
+        ReferenceIntegerPair<V> current = atomicRef.get();
         if (newReference != current.reference || newStamp != current.integer)
             atomicRef.set(new ReferenceIntegerPair<V>(newReference, newStamp));
     }
 
     /**
      * Atomically sets the value of the stamp to the given update value
-     * if the current reference is <tt>==</tt> to the expected
+     * if the current reference is {@code ==} to the expected
      * reference.  Any given invocation of this operation may fail
-     * (return <tt>false</tt>) spuriously, but repeated invocation
+     * (return {@code false}) spuriously, but repeated invocation
      * when the current value holds the expected value and no other
      * thread is also attempting to set the value will eventually
      * succeed.
@@ -157,7 +157,7 @@
      * @return true if successful
      */
     public boolean attemptStamp(V expectedReference, int newStamp) {
-        ReferenceIntegerPair current = atomicRef.get();
+        ReferenceIntegerPair<V> current = atomicRef.get();
         return  expectedReference == current.reference &&
             (newStamp == current.integer ||
              atomicRef.compareAndSet(current,
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/package-info.java b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/package-info.java
new file mode 100644
index 0000000..2252e5c
--- /dev/null
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/package-info.java
@@ -0,0 +1,163 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+/**
+ * A small toolkit of classes that support lock-free thread-safe
+ * programming on single variables.  In essence, the classes in this
+ * package extend the notion of {@code volatile} values, fields, and
+ * array elements to those that also provide an atomic conditional update
+ * operation of the form:
+ *
+ * <pre>
+ *   boolean compareAndSet(expectedValue, updateValue);
+ * </pre>
+ *
+ * <p>This method (which varies in argument types across different
+ * classes) atomically sets a variable to the {@code updateValue} if it
+ * currently holds the {@code expectedValue}, reporting {@code true} on
+ * success.  The classes in this package also contain methods to get and
+ * unconditionally set values, as well as a weaker conditional atomic
+ * update operation {@code weakCompareAndSet} described below.
+ *
+ * <p>The specifications of these methods enable implementations to
+ * employ efficient machine-level atomic instructions that are available
+ * on contemporary processors.  However on some platforms, support may
+ * entail some form of internal locking.  Thus the methods are not
+ * strictly guaranteed to be non-blocking --
+ * a thread may block transiently before performing the operation.
+ *
+ * <p>Instances of classes
+ * {@link java.util.concurrent.atomic.AtomicBoolean},
+ * {@link java.util.concurrent.atomic.AtomicInteger},
+ * {@link java.util.concurrent.atomic.AtomicLong}, and
+ * {@link java.util.concurrent.atomic.AtomicReference}
+ * each provide access and updates to a single variable of the
+ * corresponding type.  Each class also provides appropriate utility
+ * methods for that type.  For example, classes {@code AtomicLong} and
+ * {@code AtomicInteger} provide atomic increment methods.  One
+ * application is to generate sequence numbers, as in:
+ *
+ * <pre>
+ * class Sequencer {
+ *   private final AtomicLong sequenceNumber
+ *     = new AtomicLong(0);
+ *   public long next() {
+ *     return sequenceNumber.getAndIncrement();
+ *   }
+ * }
+ * </pre>
+ *
+ * <p>The memory effects for accesses and updates of atomics generally
+ * follow the rules for volatiles, as stated in
+ * <a href="http://java.sun.com/docs/books/jls/"> The Java Language
+ * Specification, Third Edition (17.4 Memory Model)</a>:
+ *
+ * <ul>
+ *
+ *   <li> {@code get} has the memory effects of reading a
+ * {@code volatile} variable.
+ *
+ *   <li> {@code set} has the memory effects of writing (assigning) a
+ * {@code volatile} variable.
+ *
+ *   <li>{@code weakCompareAndSet} atomically reads and conditionally
+ *   writes a variable but does <em>not</em>
+ *   create any happens-before orderings, so provides no guarantees
+ *   with respect to previous or subsequent reads and writes of any
+ *   variables other than the target of the {@code weakCompareAndSet}.
+ *
+ *   <li> {@code compareAndSet}
+ *   and all other read-and-update operations such as {@code getAndIncrement}
+ *   have the memory effects of both reading and
+ *   writing {@code volatile} variables.
+ * </ul>
+ *
+ * <p>In addition to classes representing single values, this package
+ * contains <em>Updater</em> classes that can be used to obtain
+ * {@code compareAndSet} operations on any selected {@code volatile}
+ * field of any selected class.
+ *
+ * {@link java.util.concurrent.atomic.AtomicReferenceFieldUpdater},
+ * {@link java.util.concurrent.atomic.AtomicIntegerFieldUpdater}, and
+ * {@link java.util.concurrent.atomic.AtomicLongFieldUpdater} are
+ * reflection-based utilities that provide access to the associated
+ * field types.  These are mainly of use in atomic data structures in
+ * which several {@code volatile} fields of the same node (for
+ * example, the links of a tree node) are independently subject to
+ * atomic updates.  These classes enable greater flexibility in how
+ * and when to use atomic updates, at the expense of more awkward
+ * reflection-based setup, less convenient usage, and weaker
+ * guarantees.
+ *
+ * <p>The
+ * {@link java.util.concurrent.atomic.AtomicIntegerArray},
+ * {@link java.util.concurrent.atomic.AtomicLongArray}, and
+ * {@link java.util.concurrent.atomic.AtomicReferenceArray} classes
+ * further extend atomic operation support to arrays of these types.
+ * These classes are also notable in providing {@code volatile} access
+ * semantics for their array elements, which is not supported for
+ * ordinary arrays.
+ *
+ * <a name="Spurious">
+ * <p>The atomic classes also support method {@code weakCompareAndSet},
+ * which has limited applicability.  On some platforms, the weak version
+ * may be more efficient than {@code compareAndSet} in the normal case,
+ * but differs in that any given invocation of the
+ * {@code weakCompareAndSet} method may return {@code false}
+ * <em>spuriously</em> (that is, for no apparent reason)</a>.  A
+ * {@code false} return means only that the operation may be retried if
+ * desired, relying on the guarantee that repeated invocation when the
+ * variable holds {@code expectedValue} and no other thread is also
+ * attempting to set the variable will eventually succeed.  (Such
+ * spurious failures may for example be due to memory contention effects
+ * that are unrelated to whether the expected and current values are
+ * equal.)  Additionally {@code weakCompareAndSet} does not provide
+ * ordering guarantees that are usually needed for synchronization
+ * control.  However, the method may be useful for updating counters and
+ * statistics when such updates are unrelated to the other
+ * happens-before orderings of a program.  When a thread sees an update
+ * to an atomic variable caused by a {@code weakCompareAndSet}, it does
+ * not necessarily see updates to any <em>other</em> variables that
+ * occurred before the {@code weakCompareAndSet}.  This may be
+ * acceptable when, for example, updating performance statistics, but
+ * rarely otherwise.
+ *
+ * <p>The {@link java.util.concurrent.atomic.AtomicMarkableReference}
+ * class associates a single boolean with a reference.  For example, this
+ * bit might be used inside a data structure to mean that the object
+ * being referenced has logically been deleted.
+ *
+ * The {@link java.util.concurrent.atomic.AtomicStampedReference}
+ * class associates an integer value with a reference.  This may be
+ * used for example, to represent version numbers corresponding to
+ * series of updates.
+ *
+ * <p>Atomic classes are designed primarily as building blocks for
+ * implementing non-blocking data structures and related infrastructure
+ * classes.  The {@code compareAndSet} method is not a general
+ * replacement for locking.  It applies only when critical updates for an
+ * object are confined to a <em>single</em> variable.
+ *
+ * <p>Atomic classes are not general purpose replacements for
+ * {@code java.lang.Integer} and related classes.  They do <em>not</em>
+ * define methods such as {@code hashCode} and
+ * {@code compareTo}.  (Because atomic variables are expected to be
+ * mutated, they are poor choices for hash table keys.)  Additionally,
+ * classes are provided only for those types that are commonly useful in
+ * intended applications.  For example, there is no atomic class for
+ * representing {@code byte}.  In those infrequent cases where you would
+ * like to do so, you can use an {@code AtomicInteger} to hold
+ * {@code byte} values, and cast appropriately.
+ *
+ * You can also hold floats using
+ * {@link java.lang.Float#floatToIntBits} and
+ * {@link java.lang.Float#intBitsToFloat} conversions, and doubles using
+ * {@link java.lang.Double#doubleToLongBits} and
+ * {@link java.lang.Double#longBitsToDouble} conversions.
+ *
+ * @since 1.5
+ */
+package java.util.concurrent.atomic;
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/package.html b/libcore/concurrent/src/main/java/java/util/concurrent/atomic/package.html
deleted file mode 100644
index bdb15e8..0000000
--- a/libcore/concurrent/src/main/java/java/util/concurrent/atomic/package.html
+++ /dev/null
@@ -1,132 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html> <head>
-<title>Atomics</title>
-</head>
-
-<body>
-
-A small toolkit of classes that support lock-free thread-safe
-programming on single variables. In essence, the classes in this
-package extend the notion of <tt>volatile</tt> values, fields, and
-array elements to those that also provide an atomic conditional update
-operation of the form:
-
-<pre>
-  boolean compareAndSet(expectedValue, updateValue);
-</pre>
-
-<p> This method (which varies in argument types across different
-classes) atomically sets a variable to the <tt>updateValue</tt> if it
-currently holds the <tt>expectedValue</tt>, reporting <tt>true</tt> on
-success.  The classes in this package also contain methods to get and
-unconditionally set values, as well as a weaker conditional atomic
-update operation <tt> weakCompareAndSet</tt>.  The weak version may be
-more efficient in the normal case, but differs in that any given
-invocation of <tt>weakCompareAndSet</tt> method may fail, even
-spuriously (that is, for no apparent reason). A <tt>false</tt> return
-means only that the operation may be retried if desired, relying on
-the guarantee that repeated invocation when the variable holds
-<tt>expectedValue</tt> and no other thread is also attempting to set
-the variable will eventually succeed.
-
-<p> The specifications of these methods enable implementations to
-employ efficient machine-level atomic instructions that are available
-on contemporary processors. However on some platforms, support may
-entail some form of internal locking. Thus the methods are not
-strictly guaranteed to be non-blocking --
-a thread may block transiently before performing the operation.
-
-<p> Instances of classes {@link
-java.util.concurrent.atomic.AtomicBoolean}, {@link
-java.util.concurrent.atomic.AtomicInteger}, {@link
-java.util.concurrent.atomic.AtomicLong}, and {@link
-java.util.concurrent.atomic.AtomicReference} each provide access and
-updates to a single variable of the corresponding type.  Each class
-also provides appropriate utility methods for that type.  For example,
-classes <tt>AtomicLong</tt> and <tt>AtomicInteger</tt> provide atomic
-increment methods.  One application is to generate sequence numbers,
-as in:
-
-<pre>
-class Sequencer {
-  private AtomicLong sequenceNumber = new AtomicLong(0);
-  public long next() { return sequenceNumber.getAndIncrement(); }
-}
-</pre>
-
-<p>The memory effects for accesses and updates of atomics generally follow the
-rules for volatiles:
-
-<ul>
-
-  <li> <tt>get</tt> has the memory effects of reading a
-<tt>volatile</tt> variable.
-
-  <li> <tt>set</tt> has the memory effects of writing (assigning) a
-<tt>volatile</tt> variable.
-
-  <li><tt>weakCompareAndSet</tt> atomically reads and conditionally
-  writes a variable, is ordered with respect to other
-  memory operations on that variable, but otherwise acts as an
-  ordinary non-volatile memory operation.
-
-  <li> <tt>compareAndSet</tt>
-  and all other read-and-update operations such as <tt>getAndIncrement</tt>
-  have the memory effects of both reading and
-  writing <tt>volatile</tt> variables.
-</ul> 
-
-<p>In addition to classes representing single values, this package
-contains <em>Updater</em> classes that can be used to obtain
-<tt>compareAndSet</tt> operations on any selected <tt>volatile</tt>
-field of any selected class.  {@link
-java.util.concurrent.atomic.AtomicReferenceFieldUpdater}, {@link
-java.util.concurrent.atomic.AtomicIntegerFieldUpdater}, and {@link
-java.util.concurrent.atomic.AtomicLongFieldUpdater} are
-reflection-based utilities that provide access to the associated field
-types. These are mainly of use in atomic data structures in which
-several <tt>volatile</tt> fields of the same node (for example, the
-links of a tree node) are independently subject to atomic
-updates. These classes enable greater flexibility in how and when to
-use atomic updates, at the expense of more awkward reflection-based
-setup, less convenient usage, and weaker guarantees.
-
-<p>The {@link java.util.concurrent.atomic.AtomicIntegerArray}, {@link
-java.util.concurrent.atomic.AtomicLongArray}, and {@link
-java.util.concurrent.atomic.AtomicReferenceArray} classes further
-extend atomic operation support to arrays of these types. These
-classes are also notable in providing <tt>volatile</tt> access
-semantics for their array elements, which is not supported for
-ordinary arrays.
-
-<p> The {@link java.util.concurrent.atomic.AtomicMarkableReference}
-class associates a single boolean with a reference. For example, this
-bit might be used inside a data structure to mean that the object
-being referenced has logically been deleted. The {@link
-java.util.concurrent.atomic.AtomicStampedReference} class associates
-an integer value with a reference. This may be used for example, to
-represent version numbers corresponding to series of updates.
-
-<p> Atomic classes are designed primarily as building blocks for
-implementing non-blocking data structures and related infrastructure
-classes.  The <tt>compareAndSet</tt> method is not a general
-replacement for locking. It applies only when critical updates for an
-object are confined to a <em>single</em> variable.
-
-<p> Atomic classes are not general purpose replacements for
-<tt>java.lang.Integer</tt> and related classes. They do <em>not</em>
-define methods such as <tt>hashCode</tt> and
-<tt>compareTo</tt>. (Because atomic variables are expected to be
-mutated, they are poor choices for hash table keys.)  Additionally,
-classes are provided only for those types that are commonly useful in
-intended applications. For example, there is no atomic class for
-representing <tt>byte</tt>. In those infrequent cases where you would
-like to do so, you can use an <tt>AtomicInteger</tt> to hold
-<tt>byte</tt> values, and cast appropriately. You can also hold floats
-using <tt>Float.floatToIntBits</tt> and <tt>Float.intBitstoFloat</tt>
-conversions, and doubles using <tt>Double.doubleToLongBits</tt> and
-<tt>Double.longBitsToDouble</tt> conversions.
-
-@since Android 1.0
-
-</body> </html>
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/locks/AbstractOwnableSynchronizer.java b/libcore/concurrent/src/main/java/java/util/concurrent/locks/AbstractOwnableSynchronizer.java
new file mode 100644
index 0000000..bf2fe16
--- /dev/null
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/locks/AbstractOwnableSynchronizer.java
@@ -0,0 +1,56 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+package java.util.concurrent.locks;
+
+/**
+ * A synchronizer that may be exclusively owned by a thread.  This
+ * class provides a basis for creating locks and related synchronizers
+ * that may entail a notion of ownership.  The
+ * <tt>AbstractOwnableSynchronizer</tt> class itself does not manage or
+ * use this information. However, subclasses and tools may use
+ * appropriately maintained values to help control and monitor access
+ * and provide diagnostics.
+ *
+ * @author Doug Lea
+ */
+abstract class AbstractOwnableSynchronizer
+        implements java.io.Serializable {
+
+    /** Use serial ID even though all fields transient. */
+    private static final long serialVersionUID = 3737899427754241961L;
+
+    /**
+     * Empty constructor for use by subclasses.
+     */
+    protected AbstractOwnableSynchronizer() { }
+
+    /**
+     * The current owner of exclusive mode synchronization.
+     */
+    private transient Thread exclusiveOwnerThread;
+
+    /**
+     * Sets the thread that currently owns exclusive access. A
+     * <tt>null</tt> argument indicates that no thread owns access.
+     * This method does not otherwise impose any synchronization or
+     * <tt>volatile</tt> field accesses.
+     */
+    protected final void setExclusiveOwnerThread(Thread t) {
+        exclusiveOwnerThread = t;
+    }
+
+    /**
+     * Returns the thread last set by
+     * <tt>setExclusiveOwnerThread</tt>, or <tt>null</tt> if never
+     * set.  This method does not otherwise impose any synchronization
+     * or <tt>volatile</tt> field accesses.
+     * @return the owner thread
+     */
+    protected final Thread getExclusiveOwnerThread() {
+        return exclusiveOwnerThread;
+    }
+}
\ No newline at end of file
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java b/libcore/concurrent/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
index 29e72b5..8b9821e 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
@@ -32,7 +32,7 @@
  * synchronization interface.  Instead it defines methods such as
  * {@link #acquireInterruptibly} that can be invoked as
  * appropriate by concrete locks and related synchronizers to
- * implement their public methods. 
+ * implement their public methods.
  *
  * <p>This class supports either or both a default <em>exclusive</em>
  * mode and a <em>shared</em> mode. When acquired in exclusive mode,
@@ -59,14 +59,14 @@
  * condition, so if this constraint cannot be met, do not use it.  The
  * behavior of {@link ConditionObject} depends of course on the
  * semantics of its synchronizer implementation.
- * 
- * <p> This class provides inspection, instrumentation, and monitoring
+ *
+ * <p>This class provides inspection, instrumentation, and monitoring
  * methods for the internal queue, as well as similar methods for
  * condition objects. These can be exported as desired into classes
  * using an <tt>AbstractQueuedSynchronizer</tt> for their
  * synchronization mechanics.
  *
- * <p> Serialization of this class stores only the underlying atomic
+ * <p>Serialization of this class stores only the underlying atomic
  * integer maintaining state, so deserialized objects have empty
  * thread queues. Typical subclasses requiring serializability will
  * define a <tt>readObject</tt> method that restores this to a known
@@ -74,10 +74,10 @@
  *
  * <h3>Usage</h3>
  *
- * <p> To use this class as the basis of a synchronizer, redefine the
+ * <p>To use this class as the basis of a synchronizer, redefine the
  * following methods, as applicable, by inspecting and/or modifying
  * the synchronization state using {@link #getState}, {@link
- * #setState} and/or {@link #compareAndSetState}: 
+ * #setState} and/or {@link #compareAndSetState}:
  *
  * <ul>
  * <li> {@link #tryAcquire}
@@ -94,7 +94,7 @@
  * means of using this class. All other methods are declared
  * <tt>final</tt> because they cannot be independently varied.
  *
- * <p> Even though this class is based on an internal FIFO queue, it
+ * <p>Even though this class is based on an internal FIFO queue, it
  * does not automatically enforce FIFO acquisition policies.  The core
  * of exclusive synchronization takes the form:
  *
@@ -112,22 +112,17 @@
  *
  * (Shared mode is similar but may involve cascading signals.)
  *
- * <p> Because checks in acquire are invoked before enqueuing, a newly
- * acquiring thread may <em>barge</em> ahead of others that are
- * blocked and queued. However, you can, if desired, define
- * <tt>tryAcquire</tt> and/or <tt>tryAcquireShared</tt> to disable
- * barging by internally invoking one or more of the inspection
- * methods. In particular, a strict FIFO lock can define
- * <tt>tryAcquire</tt> to immediately return <tt>false</tt> if {@link
- * #getFirstQueuedThread} does not return the current thread.  A
- * normally preferable non-strict fair version can immediately return
- * <tt>false</tt> only if {@link #hasQueuedThreads} returns
- * <tt>true</tt> and <tt>getFirstQueuedThread</tt> is not the current
- * thread; or equivalently, that <tt>getFirstQueuedThread</tt> is both
- * non-null and not the current thread.  Further variations are
- * possible.
+ * <p><a name="barging">Because checks in acquire are invoked before
+ * enqueuing, a newly acquiring thread may <em>barge</em> ahead of
+ * others that are blocked and queued.  However, you can, if desired,
+ * define <tt>tryAcquire</tt> and/or <tt>tryAcquireShared</tt> to
+ * disable barging by internally invoking one or more of the inspection
+ * methods, thereby providing a <em>fair</em> FIFO acquisition order.
+ * In particular, most fair synchronizers can define <tt>tryAcquire</tt>
+ * to return <tt>false</tt> if predecessors are queued.  Other variations
+ * are possible.
  *
- * <p> Throughput and scalability are generally highest for the
+ * <p>Throughput and scalability are generally highest for the
  * default barging (also known as <em>greedy</em>,
  * <em>renouncement</em>, and <em>convoy-avoidance</em>) strategy.
  * While this is not guaranteed to be fair or starvation-free, earlier
@@ -144,7 +139,7 @@
  * and/or {@link #hasQueuedThreads} to only do so if the synchronizer
  * is likely not to be contended.
  *
- * <p> This class provides an efficient and scalable basis for
+ * <p>This class provides an efficient and scalable basis for
  * synchronization in part by specializing its range of use to
  * synchronizers that can rely on <tt>int</tt> state, acquire, and
  * release parameters, and an internal FIFO wait queue. When this does
@@ -152,7 +147,7 @@
  * {@link java.util.concurrent.atomic atomic} classes, your own custom
  * {@link java.util.Queue} classes, and {@link LockSupport} blocking
  * support.
- * 
+ *
  * <h3>Usage Examples</h3>
  *
  * <p>Here is a non-reentrant mutual exclusion lock class that uses
@@ -163,56 +158,58 @@
  * <pre>
  * class Mutex implements Lock, java.io.Serializable {
  *
- *    // Our internal helper class
- *    private static class Sync extends AbstractQueuedSynchronizer {
- *      // Report whether in locked state
- *      protected boolean isHeldExclusively() { 
- *        return getState() == 1; 
- *      }
+ *   // Our internal helper class
+ *   private static class Sync extends AbstractQueuedSynchronizer {
+ *     // Report whether in locked state
+ *     protected boolean isHeldExclusively() {
+ *       return getState() == 1;
+ *     }
  *
- *      // Acquire the lock if state is zero
- *      public boolean tryAcquire(int acquires) {
- *        assert acquires == 1; // Otherwise unused
- *        return compareAndSetState(0, 1);
- *      }
+ *     // Acquire the lock if state is zero
+ *     public boolean tryAcquire(int acquires) {
+ *       assert acquires == 1; // Otherwise unused
+ *       return compareAndSetState(0, 1);
+ *     }
  *
- *      // Release the lock by setting state to zero
- *      protected boolean tryRelease(int releases) {
- *        assert releases == 1; // Otherwise unused
- *        if (getState() == 0) throw new IllegalMonitorStateException();
- *        setState(0);
- *        return true;
- *      }
- *       
- *      // Provide a Condition
- *      Condition newCondition() { return new ConditionObject(); }
+ *     // Release the lock by setting state to zero
+ *     protected boolean tryRelease(int releases) {
+ *       assert releases == 1; // Otherwise unused
+ *       if (getState() == 0) throw new IllegalMonitorStateException();
+ *       setState(0);
+ *       return true;
+ *     }
  *
- *      // Deserialize properly
- *      private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
- *        s.defaultReadObject();
- *        setState(0); // reset to unlocked state
- *      }
- *    }
+ *     // Provide a Condition
+ *     Condition newCondition() { return new ConditionObject(); }
  *
- *    // The sync object does all the hard work. We just forward to it.
- *    private final Sync sync = new Sync();
+ *     // Deserialize properly
+ *     private void readObject(ObjectInputStream s)
+ *         throws IOException, ClassNotFoundException {
+ *       s.defaultReadObject();
+ *       setState(0); // reset to unlocked state
+ *     }
+ *   }
  *
- *    public void lock()                { sync.acquire(1); }
- *    public boolean tryLock()          { return sync.tryAcquire(1); }
- *    public void unlock()              { sync.release(1); }
- *    public Condition newCondition()   { return sync.newCondition(); }
- *    public boolean isLocked()         { return sync.isHeldExclusively(); }
- *    public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }
- *    public void lockInterruptibly() throws InterruptedException { 
- *      sync.acquireInterruptibly(1);
- *    }
- *    public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
- *      return sync.tryAcquireNanos(1, unit.toNanos(timeout));
- *    }
+ *   // The sync object does all the hard work. We just forward to it.
+ *   private final Sync sync = new Sync();
+ *
+ *   public void lock()                { sync.acquire(1); }
+ *   public boolean tryLock()          { return sync.tryAcquire(1); }
+ *   public void unlock()              { sync.release(1); }
+ *   public Condition newCondition()   { return sync.newCondition(); }
+ *   public boolean isLocked()         { return sync.isHeldExclusively(); }
+ *   public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }
+ *   public void lockInterruptibly() throws InterruptedException {
+ *     sync.acquireInterruptibly(1);
+ *   }
+ *   public boolean tryLock(long timeout, TimeUnit unit)
+ *       throws InterruptedException {
+ *     return sync.tryAcquireNanos(1, unit.toNanos(timeout));
+ *   }
  * }
  * </pre>
  *
- * <p> Here is a latch class that is like a {@link CountDownLatch}
+ * <p>Here is a latch class that is like a {@link CountDownLatch}
  * except that it only requires a single <tt>signal</tt> to
  * fire. Because a latch is non-exclusive, it uses the <tt>shared</tt>
  * acquire and release methods.
@@ -220,33 +217,35 @@
  * <pre>
  * class BooleanLatch {
  *
- *    private static class Sync extends AbstractQueuedSynchronizer {
- *      boolean isSignalled() { return getState() != 0; }
+ *   private static class Sync extends AbstractQueuedSynchronizer {
+ *     boolean isSignalled() { return getState() != 0; }
  *
- *      protected int tryAcquireShared(int ignore) {
- *        return isSignalled()? 1 : -1;
- *      }
- *        
- *      protected boolean tryReleaseShared(int ignore) {
- *        setState(1);
- *        return true;
- *      }
- *    }
+ *     protected int tryAcquireShared(int ignore) {
+ *       return isSignalled()? 1 : -1;
+ *     }
  *
- *    private final Sync sync = new Sync();
- *    public boolean isSignalled() { return sync.isSignalled(); }
- *    public void signal()         { sync.releaseShared(1); }
- *    public void await() throws InterruptedException {
- *      sync.acquireSharedInterruptibly(1);
- *    }
+ *     protected boolean tryReleaseShared(int ignore) {
+ *       setState(1);
+ *       return true;
+ *     }
+ *   }
+ *
+ *   private final Sync sync = new Sync();
+ *   public boolean isSignalled() { return sync.isSignalled(); }
+ *   public void signal()         { sync.releaseShared(1); }
+ *   public void await() throws InterruptedException {
+ *     sync.acquireSharedInterruptibly(1);
+ *   }
  * }
- *
  * </pre>
  *
  * @since 1.5
  * @author Doug Lea
  */
-public abstract class AbstractQueuedSynchronizer implements java.io.Serializable {
+public abstract class AbstractQueuedSynchronizer
+    extends AbstractOwnableSynchronizer
+    implements java.io.Serializable {
+
     private static final long serialVersionUID = 7373984972572414691L;
 
     /**
@@ -258,7 +257,7 @@
     /**
      * Wait queue node class.
      *
-     * <p> The wait queue is a variant of a "CLH" (Craig, Landin, and
+     * <p>The wait queue is a variant of a "CLH" (Craig, Landin, and
      * Hagersten) lock queue. CLH locks are normally used for
      * spinlocks.  We instead use them for blocking synchronizers, but
      * use the same basic tactic of holding some of the control
@@ -274,7 +273,7 @@
      * contender thread may need to rewait.
      *
      * <p>To enqueue into a CLH lock, you atomically splice it in as new
-     * tail. To dequeue, you just set the head field.  
+     * tail. To dequeue, you just set the head field.
      * <pre>
      *      +------+  prev +-----+       +-----+
      * head |      | <---- |     | <---- |     |  tail
@@ -295,7 +294,7 @@
      * predecessor. For explanation of similar mechanics in the case
      * of spin locks, see the papers by Scott and Scherer at
      * http://www.cs.rochester.edu/u/scott/synchronization/
-     * 
+     *
      * <p>We also use "next" links to implement blocking mechanics.
      * The thread id for each node is kept in its own node, so a
      * predecessor signals the next node to wake up by traversing
@@ -312,7 +311,8 @@
      * nodes, we can miss noticing whether a cancelled node is
      * ahead or behind us. This is dealt with by always unparking
      * successors upon cancellation, allowing them to stabilize on
-     * a new predecessor.
+     * a new predecessor, unless we can identify an uncancelled
+     * predecessor who will carry this responsibility.
      *
      * <p>CLH queues need a dummy header node to get started. But
      * we don't create them on construction, because it would be wasted
@@ -334,34 +334,46 @@
      * on the design of this class.
      */
     static final class Node {
-        /** waitStatus value to indicate thread has cancelled */
-        static final int CANCELLED =  1;
-        /** waitStatus value to indicate thread needs unparking */
-        static final int SIGNAL    = -1;
-        /** waitStatus value to indicate thread is waiting on condition */
-        static final int CONDITION = -2;
         /** Marker to indicate a node is waiting in shared mode */
         static final Node SHARED = new Node();
         /** Marker to indicate a node is waiting in exclusive mode */
         static final Node EXCLUSIVE = null;
 
+        /** waitStatus value to indicate thread has cancelled */
+        static final int CANCELLED =  1;
+        /** waitStatus value to indicate successor's thread needs unparking */
+        static final int SIGNAL    = -1;
+        /** waitStatus value to indicate thread is waiting on condition */
+        static final int CONDITION = -2;
+        /**
+         * waitStatus value to indicate the next acquireShared should
+         * unconditionally propagate
+         */
+        static final int PROPAGATE = -3;
+
         /**
          * Status field, taking on only the values:
-         *   SIGNAL:     The successor of this node is (or will soon be) 
-         *               blocked (via park), so the current node must 
-         *               unpark its successor when it releases or 
+         *   SIGNAL:     The successor of this node is (or will soon be)
+         *               blocked (via park), so the current node must
+         *               unpark its successor when it releases or
          *               cancels. To avoid races, acquire methods must
-         *               first indicate they need a signal, 
-         *               then retry the atomic acquire, and then, 
+         *               first indicate they need a signal,
+         *               then retry the atomic acquire, and then,
          *               on failure, block.
-         *   CANCELLED:  Node is cancelled due to timeout or interrupt
+         *   CANCELLED:  This node is cancelled due to timeout or interrupt.
          *               Nodes never leave this state. In particular,
          *               a thread with cancelled node never again blocks.
-         *   CONDITION:  Node is currently on a condition queue
-         *               It will not be used as a sync queue node until
-         *               transferred. (Use of this value here
-         *               has nothing to do with the other uses
-         *               of the field, but simplifies mechanics.)
+         *   CONDITION:  This node is currently on a condition queue.
+         *               It will not be used as a sync queue node
+         *               until transferred, at which time the status
+         *               will be set to 0. (Use of this value here has
+         *               nothing to do with the other uses of the
+         *               field, but simplifies mechanics.)
+         *   PROPAGATE:  A releaseShared should be propagated to other
+         *               nodes. This is set (for head node only) in
+         *               doReleaseShared to ensure propagation
+         *               continues, even if other operations have
+         *               since intervened.
          *   0:          None of the above
          *
          * The values are arranged numerically to simplify use.
@@ -370,8 +382,8 @@
          * values, just for sign.
          *
          * The field is initialized to 0 for normal sync nodes, and
-         * CONDITION for condition nodes.  It is modified only using
-         * CAS.
+         * CONDITION for condition nodes.  It is modified using CAS
+         * (or when possible, unconditional volatile writes).
          */
         volatile int waitStatus;
 
@@ -390,25 +402,26 @@
 
         /**
          * Link to the successor node that the current node/thread
-         * unparks upon release. Assigned once during enqueuing, and
-         * nulled out (for sake of GC) when no longer needed.  Upon
-         * cancellation, we cannot adjust this field, but can notice
-         * status and bypass the node if cancelled.  The enq operation
-         * does not assign next field of a predecessor until after
-         * attachment, so seeing a null next field does not
-         * necessarily mean that node is at end of queue. However, if
-         * a next field appears to be null, we can scan prev's from
-         * the tail to double-check.
+         * unparks upon release. Assigned during enqueuing, adjusted
+         * when bypassing cancelled predecessors, and nulled out (for
+         * sake of GC) when dequeued.  The enq operation does not
+         * assign next field of a predecessor until after attachment,
+         * so seeing a null next field does not necessarily mean that
+         * node is at end of queue. However, if a next field appears
+         * to be null, we can scan prev's from the tail to
+         * double-check.  The next field of cancelled nodes is set to
+         * point to the node itself instead of null, to make life
+         * easier for isOnSyncQueue.
          */
         volatile Node next;
 
         /**
          * The thread that enqueued this node.  Initialized on
-         * construction and nulled out after use. 
+         * construction and nulled out after use.
          */
         volatile Thread thread;
 
-        /** 
+        /**
          * Link to next node waiting on condition, or the special
          * value SHARED.  Because condition queues are accessed only
          * when holding in exclusive mode, we just need a simple
@@ -428,14 +441,16 @@
         }
 
         /**
-         * Returns previous node, or throws NullPointerException if
-         * null.  Use when predecessor cannot be null.
+         * Returns previous node, or throws NullPointerException if null.
+         * Use when predecessor cannot be null.  The null check could
+         * be elided, but is present to help the VM.
+         *
          * @return the predecessor of this node
          */
         final Node predecessor() throws NullPointerException {
             Node p = prev;
             if (p == null)
-                throw new NullPointerException(); 
+                throw new NullPointerException();
             else
                 return p;
         }
@@ -450,11 +465,11 @@
 
         Node(Thread thread, int waitStatus) { // Used by Condition
             this.waitStatus = waitStatus;
-            this.thread = thread; 
+            this.thread = thread;
         }
     }
 
-    /** 
+    /**
      * Head of the wait queue, lazily initialized.  Except for
      * initialization, it is modified only via method setHead.  Note:
      * If head exists, its waitStatus is guaranteed not to be
@@ -462,11 +477,11 @@
      */
     private transient volatile Node head;
 
-    /** 
+    /**
      * Tail of the wait queue, lazily initialized.  Modified only via
      * method enq to add new wait node.
      */
-    private transient volatile Node tail; 
+    private transient volatile Node tail;
 
     /**
      * The synchronization state.
@@ -496,10 +511,11 @@
      * value if the current state value equals the expected value.
      * This operation has memory semantics of a <tt>volatile</tt> read
      * and write.
+     *
      * @param expect the expected value
      * @param update the new value
-     * @return true if successful. False return indicates that
-     * the actual value was not equal to the expected value.
+     * @return true if successful. False return indicates that the actual
+     *         value was not equal to the expected value.
      */
     protected final boolean compareAndSetState(int expect, int update) {
         // See below for intrinsics setup to support this
@@ -509,7 +525,14 @@
     // Queuing utilities
 
     /**
-     * Insert node into queue, initializing if necessary. See picture above.
+     * The number of nanoseconds for which it is faster to spin
+     * rather than to use timed park. A rough estimate suffices
+     * to improve responsiveness with very short timeouts.
+     */
+    static final long spinForTimeoutThreshold = 1000L;
+
+    /**
+     * Inserts node into queue, initializing if necessary. See picture above.
      * @param node the node to insert
      * @return node's predecessor
      */
@@ -517,27 +540,21 @@
         for (;;) {
             Node t = tail;
             if (t == null) { // Must initialize
-                Node h = new Node(); // Dummy header
-                h.next = node;
-                node.prev = h;
-                if (compareAndSetHead(h)) {
-                    tail = node;
-                    return h;
-                }
-            }
-            else {
-                node.prev = t;     
+                if (compareAndSetHead(new Node()))
+                    tail = head;
+            } else {
+                node.prev = t;
                 if (compareAndSetTail(t, node)) {
-                    t.next = node; 
-                    return t; 
+                    t.next = node;
+                    return t;
                 }
             }
         }
     }
 
     /**
-     * Create and enq node for given thread and mode
-     * @param current the thread
+     * Creates and enqueues node for current thread and given mode.
+     *
      * @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared
      * @return the new node
      */
@@ -546,9 +563,9 @@
         // Try the fast path of enq; backup to full enq on failure
         Node pred = tail;
         if (pred != null) {
-            node.prev = pred;     
+            node.prev = pred;
             if (compareAndSetTail(pred, node)) {
-                pred.next = node; 
+                pred.next = node;
                 return node;
             }
         }
@@ -557,79 +574,166 @@
     }
 
     /**
-     * Set head of queue to be node, thus dequeuing. Called only by
+     * Sets head of queue to be node, thus dequeuing. Called only by
      * acquire methods.  Also nulls out unused fields for sake of GC
      * and to suppress unnecessary signals and traversals.
-     * @param node the node 
+     *
+     * @param node the node
      */
     private void setHead(Node node) {
         head = node;
         node.thread = null;
-        node.prev = null; 
+        node.prev = null;
     }
 
     /**
-     * Wake up node's successor, if one exists.
+     * Wakes up node's successor, if one exists.
+     *
      * @param node the node
      */
     private void unparkSuccessor(Node node) {
         /*
-         * Try to clear status in anticipation of signalling.  It is
-         * OK if this fails or if status is changed by waiting thread.
+         * If status is negative (i.e., possibly needing signal) try
+         * to clear in anticipation of signalling.  It is OK if this
+         * fails or if status is changed by waiting thread.
          */
-        compareAndSetWaitStatus(node, Node.SIGNAL, 0);
-        
+        int ws = node.waitStatus;
+        if (ws < 0)
+            compareAndSetWaitStatus(node, ws, 0);
+
         /*
          * Thread to unpark is held in successor, which is normally
          * just the next node.  But if cancelled or apparently null,
          * traverse backwards from tail to find the actual
          * non-cancelled successor.
          */
-        Thread thread;
         Node s = node.next;
-        if (s != null && s.waitStatus <= 0)
-            thread = s.thread;
-        else {
-            thread = null;
-            for (s = tail; s != null && s != node; s = s.prev) 
-                if (s.waitStatus <= 0)
-                    thread = s.thread;
+        if (s == null || s.waitStatus > 0) {
+            s = null;
+            for (Node t = tail; t != null && t != node; t = t.prev)
+                if (t.waitStatus <= 0)
+                    s = t;
         }
-        LockSupport.unpark(thread);
+        if (s != null)
+            LockSupport.unpark(s.thread);
     }
 
     /**
-     * Set head of queue, and check if successor may be waiting
-     * in shared mode, if so propagating if propagate > 0.
-     * @param pred the node holding waitStatus for node
-     * @param node the node 
+     * Release action for shared mode -- signal successor and ensure
+     * propagation. (Note: For exclusive mode, release just amounts
+     * to calling unparkSuccessor of head if it needs signal.)
+     */
+    private void doReleaseShared() {
+        /*
+         * Ensure that a release propagates, even if there are other
+         * in-progress acquires/releases.  This proceeds in the usual
+         * way of trying to unparkSuccessor of head if it needs
+         * signal. But if it does not, status is set to PROPAGATE to
+         * ensure that upon release, propagation continues.
+         * Additionally, we must loop in case a new node is added
+         * while we are doing this. Also, unlike other uses of
+         * unparkSuccessor, we need to know if CAS to reset status
+         * fails, if so rechecking.
+         */
+        for (;;) {
+            Node h = head;
+            if (h != null && h != tail) {
+                int ws = h.waitStatus;
+                if (ws == Node.SIGNAL) {
+                    if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
+                        continue;            // loop to recheck cases
+                    unparkSuccessor(h);
+                }
+                else if (ws == 0 &&
+                         !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
+                    continue;                // loop on failed CAS
+            }
+            if (h == head)                   // loop if head changed
+                break;
+        }
+    }
+
+    /**
+     * Sets head of queue, and checks if successor may be waiting
+     * in shared mode, if so propagating if either propagate > 0 or
+     * PROPAGATE status was set.
+     *
+     * @param node the node
      * @param propagate the return value from a tryAcquireShared
      */
     private void setHeadAndPropagate(Node node, int propagate) {
+        Node h = head; // Record old head for check below
         setHead(node);
-        if (propagate > 0 && node.waitStatus != 0) {
-            /*
-             * Don't bother fully figuring out successor.  If it
-             * looks null, call unparkSuccessor anyway to be safe.
-             */
-            Node s = node.next; 
+        /*
+         * Try to signal next queued node if:
+         *   Propagation was indicated by caller,
+         *     or was recorded (as h.waitStatus) by a previous operation
+         *     (note: this uses sign-check of waitStatus because
+         *      PROPAGATE status may transition to SIGNAL.)
+         * and
+         *   The next node is waiting in shared mode,
+         *     or we don't know, because it appears null
+         *
+         * The conservatism in both of these checks may cause
+         * unnecessary wake-ups, but only when there are multiple
+         * racing acquires/releases, so most need signals now or soon
+         * anyway.
+         */
+        if (propagate > 0 || h == null || h.waitStatus < 0) {
+            Node s = node.next;
             if (s == null || s.isShared())
-                unparkSuccessor(node);
+                doReleaseShared();
         }
     }
 
     // Utilities for various versions of acquire
 
     /**
-     * Cancel an ongoing attempt to acquire.
+     * Cancels an ongoing attempt to acquire.
+     *
      * @param node the node
      */
     private void cancelAcquire(Node node) {
-        if (node != null) { // Ignore if node doesn't exist
-            node.thread = null;
-            // Can use unconditional write instead of CAS here
-            node.waitStatus = Node.CANCELLED;
-            unparkSuccessor(node);
+        // Ignore if node doesn't exist
+        if (node == null)
+            return;
+
+        node.thread = null;
+
+        // Skip cancelled predecessors
+        Node pred = node.prev;
+        while (pred.waitStatus > 0)
+            node.prev = pred = pred.prev;
+
+        // predNext is the apparent node to unsplice. CASes below will
+        // fail if not, in which case, we lost race vs another cancel
+        // or signal, so no further action is necessary.
+        Node predNext = pred.next;
+
+        // Can use unconditional write instead of CAS here.
+        // After this atomic step, other Nodes can skip past us.
+        // Before, we are free of interference from other threads.
+        node.waitStatus = Node.CANCELLED;
+
+        // If we are the tail, remove ourselves.
+        if (node == tail && compareAndSetTail(node, pred)) {
+            compareAndSetNext(pred, predNext, null);
+        } else {
+            // If successor needs signal, try to set pred's next-link
+            // so it will get one. Otherwise wake it up to propagate.
+            int ws;
+            if (pred != head &&
+                ((ws = pred.waitStatus) == Node.SIGNAL ||
+                 (ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
+                pred.thread != null) {
+                Node next = node.next;
+                if (next != null && next.waitStatus <= 0)
+                    compareAndSetNext(pred, predNext, next);
+            } else {
+                unparkSuccessor(node);
+            }
+
+            node.next = node; // help GC
         }
     }
 
@@ -637,31 +741,36 @@
      * Checks and updates status for a node that failed to acquire.
      * Returns true if thread should block. This is the main signal
      * control in all acquire loops.  Requires that pred == node.prev
+     *
      * @param pred node's predecessor holding status
-     * @param node the node 
-     * @return true if thread should block
+     * @param node the node
+     * @return {@code true} if thread should block
      */
     private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
-        int s = pred.waitStatus;
-        if (s < 0)
+        int ws = pred.waitStatus;
+        if (ws == Node.SIGNAL)
             /*
              * This node has already set status asking a release
-             * to signal it, so it can safely park
+             * to signal it, so it can safely park.
              */
             return true;
-        if (s > 0) 
+        if (ws > 0) {
             /*
-             * Predecessor was cancelled. Move up to its predecessor
-             * and indicate retry.
+             * Predecessor was cancelled. Skip over predecessors and
+             * indicate retry.
              */
-            node.prev = pred.prev;
-        else
+            do {
+                node.prev = pred = pred.prev;
+            } while (pred.waitStatus > 0);
+            pred.next = node;
+        } else {
             /*
-             * Indicate that we need a signal, but don't park yet. Caller
-             * will need to retry to make sure it cannot acquire before
-             * parking.
+             * waitStatus must be 0 or PROPAGATE.  Indicate that we
+             * need a signal, but don't park yet.  Caller will need to
+             * retry to make sure it cannot acquire before parking.
              */
-            compareAndSetWaitStatus(pred, 0, Node.SIGNAL);
+            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
+        }
         return false;
     }
 
@@ -674,9 +783,10 @@
 
     /**
      * Convenience method to park and then check if interrupted
-     * @return true if interrupted
+     *
+     * @return {@code true} if interrupted
      */
-    private static boolean parkAndCheckInterrupt() {
+    private final boolean parkAndCheckInterrupt() {
         LockSupport.park();
         return Thread.interrupted();
     }
@@ -687,17 +797,19 @@
      * different.  Only a little bit of factoring is possible due to
      * interactions of exception mechanics (including ensuring that we
      * cancel if tryAcquire throws exception) and other control, at
-     * least not without hurting performance too much. 
+     * least not without hurting performance too much.
      */
 
     /**
-     * Acquire in exclusive uninterruptible mode for thread already in
+     * Acquires in exclusive uninterruptible mode for thread already in
      * queue. Used by condition wait methods as well as acquire.
+     *
      * @param node the node
      * @param arg the acquire argument
-     * @return true if interrupted while waiting
+     * @return {@code true} if interrupted while waiting
      */
     final boolean acquireQueued(final Node node, int arg) {
+        boolean failed = true;
         try {
             boolean interrupted = false;
             for (;;) {
@@ -705,92 +817,91 @@
                 if (p == head && tryAcquire(arg)) {
                     setHead(node);
                     p.next = null; // help GC
+                    failed = false;
                     return interrupted;
                 }
-                if (shouldParkAfterFailedAcquire(p, node) && 
-                    parkAndCheckInterrupt()) 
+                if (shouldParkAfterFailedAcquire(p, node) &&
+                    parkAndCheckInterrupt())
                     interrupted = true;
             }
-        } catch (RuntimeException ex) {
-            cancelAcquire(node);
-            throw ex;
+        } finally {
+            if (failed)
+                cancelAcquire(node);
         }
     }
 
-    /** 
-     * Acquire in exclusive interruptible mode
+    /**
+     * Acquires in exclusive interruptible mode.
      * @param arg the acquire argument
      */
-    private void doAcquireInterruptibly(int arg) 
+    private void doAcquireInterruptibly(int arg)
         throws InterruptedException {
         final Node node = addWaiter(Node.EXCLUSIVE);
+        boolean failed = true;
         try {
             for (;;) {
                 final Node p = node.predecessor();
                 if (p == head && tryAcquire(arg)) {
                     setHead(node);
                     p.next = null; // help GC
+                    failed = false;
                     return;
                 }
-                if (shouldParkAfterFailedAcquire(p, node) && 
-                    parkAndCheckInterrupt()) 
-                    break;
+                if (shouldParkAfterFailedAcquire(p, node) &&
+                    parkAndCheckInterrupt())
+                    throw new InterruptedException();
             }
-        } catch (RuntimeException ex) {
-            cancelAcquire(node);
-            throw ex;
+        } finally {
+            if (failed)
+                cancelAcquire(node);
         }
-        // Arrive here only if interrupted
-        cancelAcquire(node);
-        throw new InterruptedException();
     }
 
-    /** 
-     * Acquire in exclusive timed mode
+    /**
+     * Acquires in exclusive timed mode.
+     *
      * @param arg the acquire argument
      * @param nanosTimeout max wait time
-     * @return true if acquired
+     * @return {@code true} if acquired
      */
-    private boolean doAcquireNanos(int arg, long nanosTimeout) 
+    private boolean doAcquireNanos(int arg, long nanosTimeout)
         throws InterruptedException {
         long lastTime = System.nanoTime();
         final Node node = addWaiter(Node.EXCLUSIVE);
+        boolean failed = true;
         try {
             for (;;) {
                 final Node p = node.predecessor();
                 if (p == head && tryAcquire(arg)) {
                     setHead(node);
                     p.next = null; // help GC
+                    failed = false;
                     return true;
                 }
-                if (nanosTimeout <= 0) {
-                    cancelAcquire(node);
+                if (nanosTimeout <= 0)
                     return false;
-                }
-                if (shouldParkAfterFailedAcquire(p, node)) {
+                if (shouldParkAfterFailedAcquire(p, node) &&
+                    nanosTimeout > spinForTimeoutThreshold)
                     LockSupport.parkNanos(nanosTimeout);
-                    if (Thread.interrupted()) 
-                        break;
-                    long now = System.nanoTime();
-                    nanosTimeout -= now - lastTime;
-                    lastTime = now;
-                }
+                long now = System.nanoTime();
+                nanosTimeout -= now - lastTime;
+                lastTime = now;
+                if (Thread.interrupted())
+                    throw new InterruptedException();
             }
-        } catch (RuntimeException ex) {
-            cancelAcquire(node);
-            throw ex;
+        } finally {
+            if (failed)
+                cancelAcquire(node);
         }
-        // Arrive here only if interrupted
-        cancelAcquire(node);
-        throw new InterruptedException();
     }
 
-    /** 
-     * Acquire in shared uninterruptible mode
+    /**
+     * Acquires in shared uninterruptible mode.
      * @param arg the acquire argument
      */
     private void doAcquireShared(int arg) {
         final Node node = addWaiter(Node.SHARED);
+        boolean failed = true;
         try {
             boolean interrupted = false;
             for (;;) {
@@ -802,26 +913,28 @@
                         p.next = null; // help GC
                         if (interrupted)
                             selfInterrupt();
+                        failed = false;
                         return;
                     }
                 }
-                if (shouldParkAfterFailedAcquire(p, node) && 
-                    parkAndCheckInterrupt()) 
+                if (shouldParkAfterFailedAcquire(p, node) &&
+                    parkAndCheckInterrupt())
                     interrupted = true;
             }
-        } catch (RuntimeException ex) {
-            cancelAcquire(node);
-            throw ex;
+        } finally {
+            if (failed)
+                cancelAcquire(node);
         }
     }
 
-    /** 
-     * Acquire in shared interruptible mode
+    /**
+     * Acquires in shared interruptible mode.
      * @param arg the acquire argument
      */
-    private void doAcquireSharedInterruptibly(int arg) 
+    private void doAcquireSharedInterruptibly(int arg)
         throws InterruptedException {
         final Node node = addWaiter(Node.SHARED);
+        boolean failed = true;
         try {
             for (;;) {
                 final Node p = node.predecessor();
@@ -830,33 +943,33 @@
                     if (r >= 0) {
                         setHeadAndPropagate(node, r);
                         p.next = null; // help GC
+                        failed = false;
                         return;
                     }
                 }
-                if (shouldParkAfterFailedAcquire(p, node) && 
-                    parkAndCheckInterrupt()) 
-                    break;
+                if (shouldParkAfterFailedAcquire(p, node) &&
+                    parkAndCheckInterrupt())
+                    throw new InterruptedException();
             }
-        } catch (RuntimeException ex) {
-            cancelAcquire(node);
-            throw ex;
+        } finally {
+            if (failed)
+                cancelAcquire(node);
         }
-        // Arrive here only if interrupted
-        cancelAcquire(node);
-        throw new InterruptedException();
     }
 
-    /** 
-     * Acquire in shared timed mode
+    /**
+     * Acquires in shared timed mode.
+     *
      * @param arg the acquire argument
      * @param nanosTimeout max wait time
-     * @return true if acquired
+     * @return {@code true} if acquired
      */
-    private boolean doAcquireSharedNanos(int arg, long nanosTimeout) 
+    private boolean doAcquireSharedNanos(int arg, long nanosTimeout)
         throws InterruptedException {
 
         long lastTime = System.nanoTime();
         final Node node = addWaiter(Node.SHARED);
+        boolean failed = true;
         try {
             for (;;) {
                 final Node p = node.predecessor();
@@ -865,32 +978,28 @@
                     if (r >= 0) {
                         setHeadAndPropagate(node, r);
                         p.next = null; // help GC
+                        failed = false;
                         return true;
                     }
                 }
-                if (nanosTimeout <= 0) {
-                    cancelAcquire(node);
+                if (nanosTimeout <= 0)
                     return false;
-                }
-                if (shouldParkAfterFailedAcquire(p, node)) {
+                if (shouldParkAfterFailedAcquire(p, node) &&
+                    nanosTimeout > spinForTimeoutThreshold)
                     LockSupport.parkNanos(nanosTimeout);
-                    if (Thread.interrupted()) 
-                        break;
-                    long now = System.nanoTime();
-                    nanosTimeout -= now - lastTime;
-                    lastTime = now;
-                }
+                long now = System.nanoTime();
+                nanosTimeout -= now - lastTime;
+                lastTime = now;
+                if (Thread.interrupted())
+                    throw new InterruptedException();
             }
-        } catch (RuntimeException ex) {
-            cancelAcquire(node);
-            throw ex;
+        } finally {
+            if (failed)
+                cancelAcquire(node);
         }
-        // Arrive here only if interrupted
-        cancelAcquire(node);
-        throw new InterruptedException();
     }
 
-    // Main exported methods 
+    // Main exported methods
 
     /**
      * Attempts to acquire in exclusive mode. This method should query
@@ -901,22 +1010,21 @@
      * acquire.  If this method reports failure, the acquire method
      * may queue the thread, if it is not already queued, until it is
      * signalled by a release from some other thread. This can be used
-     * to implement method {@link Lock#tryLock()}. 
+     * to implement method {@link Lock#tryLock()}.
      *
      * <p>The default
-     * implementation throws {@link UnsupportedOperationException}
+     * implementation throws {@link UnsupportedOperationException}.
      *
-     * @param arg the acquire argument. This value
-     * is always the one passed to an acquire method,
-     * or is the value saved on entry to a condition wait.
-     * The value is otherwise uninterpreted and can represent anything
-     * you like.
-     * @return true if successful. Upon success, this object has been
-     * acquired.
-     * @throws IllegalMonitorStateException if acquiring would place
-     * this synchronizer in an illegal state. This exception must be
-     * thrown in a consistent fashion for synchronization to work
-     * correctly.
+     * @param arg the acquire argument. This value is always the one
+     *        passed to an acquire method, or is the value saved on entry
+     *        to a condition wait.  The value is otherwise uninterpreted
+     *        and can represent anything you like.
+     * @return {@code true} if successful. Upon success, this object has
+     *         been acquired.
+     * @throws IllegalMonitorStateException if acquiring would place this
+     *         synchronizer in an illegal state. This exception must be
+     *         thrown in a consistent fashion for synchronization to work
+     *         correctly.
      * @throws UnsupportedOperationException if exclusive mode is not supported
      */
     protected boolean tryAcquire(int arg) {
@@ -925,23 +1033,24 @@
 
     /**
      * Attempts to set the state to reflect a release in exclusive
-     * mode.  <p>This method is always invoked by the thread
-     * performing release.  
+     * mode.
+     *
+     * <p>This method is always invoked by the thread performing release.
      *
      * <p>The default implementation throws
-     * {@link UnsupportedOperationException}
-     * @param arg the release argument. This value
-     * is always the one passed to a release method,
-     * or the current state value upon entry to a condition wait.
-     * The value is otherwise uninterpreted and can represent anything
-     * you like.
-     * @return <tt>true</tt> if this object is now in a fully released state, 
-     * so that any waiting threads may attempt to acquire; and <tt>false</tt>
-     * otherwise.
-     * @throws IllegalMonitorStateException if releasing would place
-     * this synchronizer in an illegal state. This exception must be
-     * thrown in a consistent fashion for synchronization to work
-     * correctly.
+     * {@link UnsupportedOperationException}.
+     *
+     * @param arg the release argument. This value is always the one
+     *        passed to a release method, or the current state value upon
+     *        entry to a condition wait.  The value is otherwise
+     *        uninterpreted and can represent anything you like.
+     * @return {@code true} if this object is now in a fully released
+     *         state, so that any waiting threads may attempt to acquire;
+     *         and {@code false} otherwise.
+     * @throws IllegalMonitorStateException if releasing would place this
+     *         synchronizer in an illegal state. This exception must be
+     *         thrown in a consistent fashion for synchronization to work
+     *         correctly.
      * @throws UnsupportedOperationException if exclusive mode is not supported
      */
     protected boolean tryRelease(int arg) {
@@ -951,7 +1060,7 @@
     /**
      * Attempts to acquire in shared mode. This method should query if
      * the state of the object permits it to be acquired in the shared
-     * mode, and if so to acquire it.  
+     * mode, and if so to acquire it.
      *
      * <p>This method is always invoked by the thread performing
      * acquire.  If this method reports failure, the acquire method
@@ -959,24 +1068,25 @@
      * signalled by a release from some other thread.
      *
      * <p>The default implementation throws {@link
-     * UnsupportedOperationException}
+     * UnsupportedOperationException}.
      *
-     * @param arg the acquire argument. This value
-     * is always the one passed to an acquire method,
-     * or is the value saved on entry to a condition wait.
-     * The value is otherwise uninterpreted and can represent anything
-     * you like.
-     * @return a negative value on failure, zero on exclusive success,
-     * and a positive value if non-exclusively successful, in which
-     * case a subsequent waiting thread must check
-     * availability. (Support for three different return values
-     * enables this method to be used in contexts where acquires only
-     * sometimes act exclusively.)  Upon success, this object has been
-     * acquired.
-     * @throws IllegalMonitorStateException if acquiring would place
-     * this synchronizer in an illegal state. This exception must be
-     * thrown in a consistent fashion for synchronization to work
-     * correctly.
+     * @param arg the acquire argument. This value is always the one
+     *        passed to an acquire method, or is the value saved on entry
+     *        to a condition wait.  The value is otherwise uninterpreted
+     *        and can represent anything you like.
+     * @return a negative value on failure; zero if acquisition in shared
+     *         mode succeeded but no subsequent shared-mode acquire can
+     *         succeed; and a positive value if acquisition in shared
+     *         mode succeeded and subsequent shared-mode acquires might
+     *         also succeed, in which case a subsequent waiting thread
+     *         must check availability. (Support for three different
+     *         return values enables this method to be used in contexts
+     *         where acquires only sometimes act exclusively.)  Upon
+     *         success, this object has been acquired.
+     * @throws IllegalMonitorStateException if acquiring would place this
+     *         synchronizer in an illegal state. This exception must be
+     *         thrown in a consistent fashion for synchronization to work
+     *         correctly.
      * @throws UnsupportedOperationException if shared mode is not supported
      */
     protected int tryAcquireShared(int arg) {
@@ -985,21 +1095,23 @@
 
     /**
      * Attempts to set the state to reflect a release in shared mode.
+     *
      * <p>This method is always invoked by the thread performing release.
-     * <p> The default implementation throws 
-     * {@link UnsupportedOperationException}
-     * @param arg the release argument. This value
-     * is always the one passed to a release method,
-     * or the current state value upon entry to a condition wait.
-     * The value is otherwise uninterpreted and can represent anything
-     * you like.
-     * @return <tt>true</tt> if this object is now in a fully released state, 
-     * so that any waiting threads may attempt to acquire; and <tt>false</tt>
-     * otherwise.
-     * @throws IllegalMonitorStateException if releasing would place
-     * this synchronizer in an illegal state. This exception must be
-     * thrown in a consistent fashion for synchronization to work
-     * correctly.
+     *
+     * <p>The default implementation throws
+     * {@link UnsupportedOperationException}.
+     *
+     * @param arg the release argument. This value is always the one
+     *        passed to a release method, or the current state value upon
+     *        entry to a condition wait.  The value is otherwise
+     *        uninterpreted and can represent anything you like.
+     * @return {@code true} if this release of shared mode may permit a
+     *         waiting acquire (shared or exclusive) to succeed; and
+     *         {@code false} otherwise
+     * @throws IllegalMonitorStateException if releasing would place this
+     *         synchronizer in an illegal state. This exception must be
+     *         thrown in a consistent fashion for synchronization to work
+     *         correctly.
      * @throws UnsupportedOperationException if shared mode is not supported
      */
     protected boolean tryReleaseShared(int arg) {
@@ -1007,17 +1119,18 @@
     }
 
     /**
-     * Returns true if synchronization is held exclusively with respect
-     * to the current (calling) thread.  This method is invoked
+     * Returns {@code true} if synchronization is held exclusively with
+     * respect to the current (calling) thread.  This method is invoked
      * upon each call to a non-waiting {@link ConditionObject} method.
      * (Waiting methods instead invoke {@link #release}.)
+     *
      * <p>The default implementation throws {@link
      * UnsupportedOperationException}. This method is invoked
      * internally only within {@link ConditionObject} methods, so need
      * not be defined if conditions are not used.
      *
-     * @return true if synchronization is held exclusively;
-     * else false
+     * @return {@code true} if synchronization is held exclusively;
+     *         {@code false} otherwise
      * @throws UnsupportedOperationException if conditions are not supported
      */
     protected boolean isHeldExclusively() {
@@ -1030,12 +1143,12 @@
      * returning on success.  Otherwise the thread is queued, possibly
      * repeatedly blocking and unblocking, invoking {@link
      * #tryAcquire} until success.  This method can be used
-     * to implement method {@link Lock#lock}
-     * @param arg the acquire argument.
-     * This value is conveyed to {@link #tryAcquire} but is
-     * otherwise uninterpreted and can represent anything
-     * you like.
-     */ 
+     * to implement method {@link Lock#lock}.
+     *
+     * @param arg the acquire argument.  This value is conveyed to
+     *        {@link #tryAcquire} but is otherwise uninterpreted and
+     *        can represent anything you like.
+     */
     public final void acquire(int arg) {
         if (!tryAcquire(arg) &&
             acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
@@ -1049,11 +1162,11 @@
      * success.  Otherwise the thread is queued, possibly repeatedly
      * blocking and unblocking, invoking {@link #tryAcquire}
      * until success or the thread is interrupted.  This method can be
-     * used to implement method {@link Lock#lockInterruptibly}
-     * @param arg the acquire argument.
-     * This value is conveyed to {@link #tryAcquire} but is
-     * otherwise uninterpreted and can represent anything
-     * you like.
+     * used to implement method {@link Lock#lockInterruptibly}.
+     *
+     * @param arg the acquire argument.  This value is conveyed to
+     *        {@link #tryAcquire} but is otherwise uninterpreted and
+     *        can represent anything you like.
      * @throws InterruptedException if the current thread is interrupted
      */
     public final void acquireInterruptibly(int arg) throws InterruptedException {
@@ -1072,35 +1185,35 @@
      * {@link #tryAcquire} until success or the thread is interrupted
      * or the timeout elapses.  This method can be used to implement
      * method {@link Lock#tryLock(long, TimeUnit)}.
-     * @param arg the acquire argument.
-     * This value is conveyed to {@link #tryAcquire} but is
-     * otherwise uninterpreted and can represent anything
-     * you like.
+     *
+     * @param arg the acquire argument.  This value is conveyed to
+     *        {@link #tryAcquire} but is otherwise uninterpreted and
+     *        can represent anything you like.
      * @param nanosTimeout the maximum number of nanoseconds to wait
-     * @return true if acquired; false if timed out
+     * @return {@code true} if acquired; {@code false} if timed out
      * @throws InterruptedException if the current thread is interrupted
      */
-   public final boolean tryAcquireNanos(int arg, long nanosTimeout) throws InterruptedException {
-       if (Thread.interrupted())
-           throw new InterruptedException();
-       return tryAcquire(arg) ||
-           doAcquireNanos(arg, nanosTimeout);
-   }
+    public final boolean tryAcquireNanos(int arg, long nanosTimeout) throws InterruptedException {
+        if (Thread.interrupted())
+            throw new InterruptedException();
+        return tryAcquire(arg) ||
+            doAcquireNanos(arg, nanosTimeout);
+    }
 
     /**
      * Releases in exclusive mode.  Implemented by unblocking one or
      * more threads if {@link #tryRelease} returns true.
-     * This method can be used to implement method {@link Lock#unlock}
-     * @param arg the release argument.
-     * This value is conveyed to {@link #tryRelease} but is
-     * otherwise uninterpreted and can represent anything
-     * you like.
-     * @return the value returned from {@link #tryRelease} 
+     * This method can be used to implement method {@link Lock#unlock}.
+     *
+     * @param arg the release argument.  This value is conveyed to
+     *        {@link #tryRelease} but is otherwise uninterpreted and
+     *        can represent anything you like.
+     * @return the value returned from {@link #tryRelease}
      */
     public final boolean release(int arg) {
         if (tryRelease(arg)) {
             Node h = head;
-            if (h != null && h.waitStatus != 0) 
+            if (h != null && h.waitStatus != 0)
                 unparkSuccessor(h);
             return true;
         }
@@ -1112,11 +1225,11 @@
      * first invoking at least once {@link #tryAcquireShared},
      * returning on success.  Otherwise the thread is queued, possibly
      * repeatedly blocking and unblocking, invoking {@link
-     * #tryAcquireShared} until success.  
-     * @param arg the acquire argument.
-     * This value is conveyed to {@link #tryAcquireShared} but is
-     * otherwise uninterpreted and can represent anything
-     * you like.
+     * #tryAcquireShared} until success.
+     *
+     * @param arg the acquire argument.  This value is conveyed to
+     *        {@link #tryAcquireShared} but is otherwise uninterpreted
+     *        and can represent anything you like.
      */
     public final void acquireShared(int arg) {
         if (tryAcquireShared(arg) < 0)
@@ -1129,8 +1242,8 @@
      * {@link #tryAcquireShared}, returning on success.  Otherwise the
      * thread is queued, possibly repeatedly blocking and unblocking,
      * invoking {@link #tryAcquireShared} until success or the thread
-     * is interrupted.  
-     * @param arg the acquire argument.
+     * is interrupted.
+     * @param arg the acquire argument
      * This value is conveyed to {@link #tryAcquireShared} but is
      * otherwise uninterpreted and can represent anything
      * you like.
@@ -1141,7 +1254,7 @@
             throw new InterruptedException();
         if (tryAcquireShared(arg) < 0)
             doAcquireSharedInterruptibly(arg);
-   }
+    }
 
     /**
      * Attempts to acquire in shared mode, aborting if interrupted, and
@@ -1151,35 +1264,33 @@
      * thread is queued, possibly repeatedly blocking and unblocking,
      * invoking {@link #tryAcquireShared} until success or the thread
      * is interrupted or the timeout elapses.
-     * @param arg the acquire argument.
-     * This value is conveyed to {@link #tryAcquireShared} but is
-     * otherwise uninterpreted and can represent anything
-     * you like.
+     *
+     * @param arg the acquire argument.  This value is conveyed to
+     *        {@link #tryAcquireShared} but is otherwise uninterpreted
+     *        and can represent anything you like.
      * @param nanosTimeout the maximum number of nanoseconds to wait
-     * @return true if acquired; false if timed out
+     * @return {@code true} if acquired; {@code false} if timed out
      * @throws InterruptedException if the current thread is interrupted
      */
-   public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout) throws InterruptedException {
-       if (Thread.interrupted())
-           throw new InterruptedException();
-       return tryAcquireShared(arg) >= 0 ||
-           doAcquireSharedNanos(arg, nanosTimeout);
-   }
+    public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout) throws InterruptedException {
+        if (Thread.interrupted())
+            throw new InterruptedException();
+        return tryAcquireShared(arg) >= 0 ||
+            doAcquireSharedNanos(arg, nanosTimeout);
+    }
 
     /**
      * Releases in shared mode.  Implemented by unblocking one or more
-     * threads if {@link #tryReleaseShared} returns true. 
-     * @param arg the release argument.
-     * This value is conveyed to {@link #tryReleaseShared} but is
-     * otherwise uninterpreted and can represent anything
-     * you like.
-     * @return the value returned from {@link #tryReleaseShared} 
+     * threads if {@link #tryReleaseShared} returns true.
+     *
+     * @param arg the release argument.  This value is conveyed to
+     *        {@link #tryReleaseShared} but is otherwise uninterpreted
+     *        and can represent anything you like.
+     * @return the value returned from {@link #tryReleaseShared}
      */
     public final boolean releaseShared(int arg) {
         if (tryReleaseShared(arg)) {
-            Node h = head;
-            if (h != null && h.waitStatus != 0) 
-                unparkSuccessor(h);
+            doReleaseShared();
             return true;
         }
         return false;
@@ -1190,16 +1301,15 @@
     /**
      * Queries whether any threads are waiting to acquire. Note that
      * because cancellations due to interrupts and timeouts may occur
-     * at any time, a <tt>true</tt> return does not guarantee that any
+     * at any time, a {@code true} return does not guarantee that any
      * other thread will ever acquire.
      *
-     * <p> In this implementation, this operation returns in
+     * <p>In this implementation, this operation returns in
      * constant time.
      *
-     * @return true if there may be other threads waiting to acquire
-     * the lock.
+     * @return {@code true} if there may be other threads waiting to acquire
      */
-    public final boolean hasQueuedThreads() { 
+    public final boolean hasQueuedThreads() {
         return head != tail;
     }
 
@@ -1207,10 +1317,10 @@
      * Queries whether any threads have ever contended to acquire this
      * synchronizer; that is if an acquire method has ever blocked.
      *
-     * <p> In this implementation, this operation returns in
+     * <p>In this implementation, this operation returns in
      * constant time.
      *
-     * @return true if there has ever been contention
+     * @return {@code true} if there has ever been contention
      */
     public final boolean hasContended() {
         return head != null;
@@ -1218,18 +1328,18 @@
 
     /**
      * Returns the first (longest-waiting) thread in the queue, or
-     * <tt>null</tt> if no threads are currently queued.
+     * {@code null} if no threads are currently queued.
      *
-     * <p> In this implementation, this operation normally returns in
+     * <p>In this implementation, this operation normally returns in
      * constant time, but may iterate upon contention if other threads are
      * concurrently modifying the queue.
      *
      * @return the first (longest-waiting) thread in the queue, or
-     * <tt>null</tt> if no threads are currently queued.
+     *         {@code null} if no threads are currently queued
      */
     public final Thread getFirstQueuedThread() {
         // handle only fast path, else relay
-        return (head == tail)? null : fullGetFirstQueuedThread();
+        return (head == tail) ? null : fullGetFirstQueuedThread();
     }
 
     /**
@@ -1237,57 +1347,49 @@
      */
     private Thread fullGetFirstQueuedThread() {
         /*
-         * This loops only if the queue changes while we read sets of
-         * fields.
+         * The first node is normally head.next. Try to get its
+         * thread field, ensuring consistent reads: If thread
+         * field is nulled out or s.prev is no longer head, then
+         * some other thread(s) concurrently performed setHead in
+         * between some of our reads. We try this twice before
+         * resorting to traversal.
          */
-        for (;;) {
-            Node h = head;
-            if (h == null)                    // No queue
-                return null;
+        Node h, s;
+        Thread st;
+        if (((h = head) != null && (s = h.next) != null &&
+             s.prev == head && (st = s.thread) != null) ||
+            ((h = head) != null && (s = h.next) != null &&
+             s.prev == head && (st = s.thread) != null))
+            return st;
 
-            /*
-             * The first node is normally h.next. Try to get its
-             * thread field, ensuring consistent reads: If thread
-             * field is nulled out or s.prev is no longer head, then
-             * some other thread(s) concurrently performed setHead in
-             * between some of our reads, so we must reread.
-             */
-            Node s = h.next;
-            if (s != null) {
-                Thread st = s.thread;
-                Node sp = s.prev;
-                if (st != null && sp == head)
-                    return st;
-            }
+        /*
+         * Head's next field might not have been set yet, or may have
+         * been unset after setHead. So we must check to see if tail
+         * is actually first node. If not, we continue on, safely
+         * traversing from tail back to head to find first,
+         * guaranteeing termination.
+         */
 
-            /*
-             * Head's next field might not have been set yet, or may
-             * have been unset after setHead. So we must check to see
-             * if tail is actually first node, in almost the same way
-             * as above.
-             */
-            Node t = tail; 
-            if (t == h)                       // Empty queue
-                return null;
-
-            if (t != null) {
-                Thread tt = t.thread;
-                Node tp = t.prev;
-                if (tt != null && tp == head)
-                    return tt;
-            }
+        Node t = tail;
+        Thread firstThread = null;
+        while (t != null && t != head) {
+            Thread tt = t.thread;
+            if (tt != null)
+                firstThread = tt;
+            t = t.prev;
         }
+        return firstThread;
     }
 
     /**
-     * Returns true if the given thread is currently queued. 
+     * Returns true if the given thread is currently queued.
      *
-     * <p> This implementation traverses the queue to determine
+     * <p>This implementation traverses the queue to determine
      * presence of the given thread.
      *
      * @param thread the thread
-     * @return true if the given thread in on the queue
-     * @throws NullPointerException if thread null
+     * @return {@code true} if the given thread is on the queue
+     * @throws NullPointerException if the thread is null
      */
     public final boolean isQueued(Thread thread) {
         if (thread == null)
@@ -1298,6 +1400,77 @@
         return false;
     }
 
+    /**
+     * Returns {@code true} if the apparent first queued thread, if one
+     * exists, is waiting in exclusive mode.  If this method returns
+     * {@code true}, and the current thread is attempting to acquire in
+     * shared mode (that is, this method is invoked from {@link
+     * #tryAcquireShared}) then it is guaranteed that the current thread
+     * is not the first queued thread.  Used only as a heuristic in
+     * ReentrantReadWriteLock.
+     */
+    final boolean apparentlyFirstQueuedIsExclusive() {
+        Node h, s;
+        return (h = head) != null &&
+            (s = h.next)  != null &&
+            !s.isShared()         &&
+            s.thread != null;
+    }
+
+    /**
+     * Queries whether any threads have been waiting to acquire longer
+     * than the current thread.
+     *
+     * <p>An invocation of this method is equivalent to (but may be
+     * more efficient than):
+     *  <pre> {@code
+     * getFirstQueuedThread() != Thread.currentThread() &&
+     * hasQueuedThreads()}</pre>
+     *
+     * <p>Note that because cancellations due to interrupts and
+     * timeouts may occur at any time, a {@code true} return does not
+     * guarantee that some other thread will acquire before the current
+     * thread.  Likewise, it is possible for another thread to win a
+     * race to enqueue after this method has returned {@code false},
+     * due to the queue being empty.
+     *
+     * <p>This method is designed to be used by a fair synchronizer to
+     * avoid <a href="AbstractQueuedSynchronizer#barging">barging</a>.
+     * Such a synchronizer's {@link #tryAcquire} method should return
+     * {@code false}, and its {@link #tryAcquireShared} method should
+     * return a negative value, if this method returns {@code true}
+     * (unless this is a reentrant acquire).  For example, the {@code
+     * tryAcquire} method for a fair, reentrant, exclusive mode
+     * synchronizer might look like this:
+     *
+     *  <pre> {@code
+     * protected boolean tryAcquire(int arg) {
+     *   if (isHeldExclusively()) {
+     *     // A reentrant acquire; increment hold count
+     *     return true;
+     *   } else if (hasQueuedPredecessors()) {
+     *     return false;
+     *   } else {
+     *     // try to acquire normally
+     *   }
+     * }}</pre>
+     *
+     * @return {@code true} if there is a queued thread preceding the
+     *         current thread, and {@code false} if the current thread
+     *         is at the head of the queue or the queue is empty
+     */
+    final boolean hasQueuedPredecessors() {
+        // The correctness of this depends on head being initialized
+        // before tail and on head.next being accurate if the current
+        // thread is first in queue.
+        Node t = tail; // Read fields in reverse initialization order
+        Node h = head;
+        Node s;
+        return h != t &&
+            ((s = h.next) == null || s.thread != Thread.currentThread());
+    }
+
+
     // Instrumentation and monitoring methods
 
     /**
@@ -1308,7 +1481,7 @@
      * monitoring system state, not for synchronization
      * control.
      *
-     * @return the estimated number of threads waiting for this lock
+     * @return the estimated number of threads waiting to acquire
      */
     public final int getQueueLength() {
         int n = 0;
@@ -1327,6 +1500,7 @@
      * returned collection are in no particular order.  This method is
      * designed to facilitate construction of subclasses that provide
      * more extensive monitoring facilities.
+     *
      * @return the collection of threads
      */
     public final Collection<Thread> getQueuedThreads() {
@@ -1344,6 +1518,7 @@
      * acquire in exclusive mode. This has the same properties
      * as {@link #getQueuedThreads} except that it only returns
      * those threads waiting due to an exclusive acquire.
+     *
      * @return the collection of threads
      */
     public final Collection<Thread> getExclusiveQueuedThreads() {
@@ -1363,6 +1538,7 @@
      * acquire in shared mode. This has the same properties
      * as {@link #getQueuedThreads} except that it only returns
      * those threads waiting due to a shared acquire.
+     *
      * @return the collection of threads
      */
     public final Collection<Thread> getSharedQueuedThreads() {
@@ -1378,18 +1554,18 @@
     }
 
     /**
-     * Returns a string identifying this synchronizer, as well as its
-     * state.  The state, in brackets, includes the String &quot;State
-     * =&quot; followed by the current value of {@link #getState}, and
-     * either &quot;nonempty&quot; or &quot;empty&quot; depending on
-     * whether the queue is empty.
+     * Returns a string identifying this synchronizer, as well as its state.
+     * The state, in brackets, includes the String {@code "State ="}
+     * followed by the current value of {@link #getState}, and either
+     * {@code "nonempty"} or {@code "empty"} depending on whether the
+     * queue is empty.
      *
-     * @return a string identifying this synchronizer, as well as its state.
+     * @return a string identifying this synchronizer, as well as its state
      */
     public String toString() {
         int s = getState();
-        String q  = hasQueuedThreads()? "non" : "";
-        return super.toString() + 
+        String q  = hasQueuedThreads() ? "non" : "";
+        return super.toString() +
             "[State = " + s + ", " + q + "empty queue]";
     }
 
@@ -1416,7 +1592,7 @@
          * there, so we hardly ever traverse much.
          */
         return findNodeFromTail(node);
-    } 
+    }
 
     /**
      * Returns true if node is on sync queue by searching backwards from tail.
@@ -1424,7 +1600,7 @@
      * @return true if present
      */
     private boolean findNodeFromTail(Node node) {
-        Node t = tail; 
+        Node t = tail;
         for (;;) {
             if (t == node)
                 return true;
@@ -1435,7 +1611,7 @@
     }
 
     /**
-     * Transfers a node from a condition queue onto sync queue. 
+     * Transfers a node from a condition queue onto sync queue.
      * Returns true if successful.
      * @param node the node
      * @return true if successfully transferred (else the node was
@@ -1455,8 +1631,8 @@
          * case the waitStatus can be transiently and harmlessly wrong).
          */
         Node p = enq(node);
-        int c = p.waitStatus;
-        if (c > 0 || !compareAndSetWaitStatus(p, c, Node.SIGNAL)) 
+        int ws = p.waitStatus;
+        if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
             LockSupport.unpark(node.thread);
         return true;
     }
@@ -1465,9 +1641,8 @@
      * Transfers node, if necessary, to sync queue after a cancelled
      * wait. Returns true if thread was cancelled before being
      * signalled.
-     * @param current the waiting thread
      * @param node its node
-     * @return true if cancelled before the node was signalled.
+     * @return true if cancelled before the node was signalled
      */
     final boolean transferAfterCancelledWait(Node node) {
         if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
@@ -1480,39 +1655,42 @@
          * incomplete transfer is both rare and transient, so just
          * spin.
          */
-        while (!isOnSyncQueue(node)) 
+        while (!isOnSyncQueue(node))
             Thread.yield();
         return false;
     }
 
     /**
-     * Invoke release with current state value; return saved state.
-     * Cancel node and throw exception on failure.
+     * Invokes release with current state value; returns saved state.
+     * Cancels node and throws exception on failure.
      * @param node the condition node for this wait
      * @return previous sync state
      */
     final int fullyRelease(Node node) {
+        boolean failed = true;
         try {
             int savedState = getState();
-            if (release(savedState))
+            if (release(savedState)) {
+                failed = false;
                 return savedState;
-        } catch(RuntimeException ex) {
-            node.waitStatus = Node.CANCELLED;
-            throw ex;
+            } else {
+                throw new IllegalMonitorStateException();
+            }
+        } finally {
+            if (failed)
+                node.waitStatus = Node.CANCELLED;
         }
-        // reach here if release fails
-        node.waitStatus = Node.CANCELLED;
-        throw new IllegalMonitorStateException();
     }
 
     // Instrumentation methods for conditions
 
     /**
-     * Queries whether the given ConditionObject 
+     * Queries whether the given ConditionObject
      * uses this synchronizer as its lock.
+     *
      * @param condition the condition
      * @return <tt>true</tt> if owned
-     * @throws NullPointerException if condition null
+     * @throws NullPointerException if the condition is null
      */
     public final boolean owns(ConditionObject condition) {
         if (condition == null)
@@ -1527,14 +1705,15 @@
      * does not guarantee that a future <tt>signal</tt> will awaken
      * any threads.  This method is designed primarily for use in
      * monitoring of the system state.
+     *
      * @param condition the condition
-     * @return <tt>true</tt> if there are any waiting threads.
-     * @throws IllegalMonitorStateException if exclusive synchronization 
-     * is not held
+     * @return <tt>true</tt> if there are any waiting threads
+     * @throws IllegalMonitorStateException if exclusive synchronization
+     *         is not held
      * @throws IllegalArgumentException if the given condition is
-     * not associated with this synchronizer
-     * @throws NullPointerException if condition null
-     */ 
+     *         not associated with this synchronizer
+     * @throws NullPointerException if the condition is null
+     */
     public final boolean hasWaiters(ConditionObject condition) {
         if (!owns(condition))
             throw new IllegalArgumentException("Not owner");
@@ -1548,14 +1727,15 @@
      * estimate serves only as an upper bound on the actual number of
      * waiters.  This method is designed for use in monitoring of the
      * system state, not for synchronization control.
+     *
      * @param condition the condition
-     * @return the estimated number of waiting threads.
-     * @throws IllegalMonitorStateException if exclusive synchronization 
-     * is not held
+     * @return the estimated number of waiting threads
+     * @throws IllegalMonitorStateException if exclusive synchronization
+     *         is not held
      * @throws IllegalArgumentException if the given condition is
-     * not associated with this synchronizer
-     * @throws NullPointerException if condition null
-     */ 
+     *         not associated with this synchronizer
+     * @throws NullPointerException if the condition is null
+     */
     public final int getWaitQueueLength(ConditionObject condition) {
         if (!owns(condition))
             throw new IllegalArgumentException("Not owner");
@@ -1568,14 +1748,15 @@
      * synchronizer.  Because the actual set of threads may change
      * dynamically while constructing this result, the returned
      * collection is only a best-effort estimate. The elements of the
-     * returned collection are in no particular order.  
+     * returned collection are in no particular order.
+     *
      * @param condition the condition
      * @return the collection of threads
-     * @throws IllegalMonitorStateException if exclusive synchronization 
-     * is not held
+     * @throws IllegalMonitorStateException if exclusive synchronization
+     *         is not held
      * @throws IllegalArgumentException if the given condition is
-     * not associated with this synchronizer
-     * @throws NullPointerException if condition null
+     *         not associated with this synchronizer
+     * @throws NullPointerException if the condition is null
      */
     public final Collection<Thread> getWaitingThreads(ConditionObject condition) {
         if (!owns(condition))
@@ -1588,14 +1769,14 @@
      * AbstractQueuedSynchronizer} serving as the basis of a {@link
      * Lock} implementation.
      *
-     * <p> Method documentation for this class describes mechanics,
+     * <p>Method documentation for this class describes mechanics,
      * not behavioral specifications from the point of view of Lock
      * and Condition users. Exported versions of this class will in
      * general need to be accompanied by documentation describing
      * condition semantics that rely on those of the associated
      * <tt>AbstractQueuedSynchronizer</tt>.
-     * 
-     * <p> This class is Serializable, but all fields are transient,
+     *
+     * <p>This class is Serializable, but all fields are transient,
      * so deserialized conditions have no waiters.
      */
     public class ConditionObject implements Condition, java.io.Serializable {
@@ -1613,29 +1794,34 @@
         // Internal methods
 
         /**
-         * Add a new waiter to wait queue
+         * Adds a new waiter to wait queue.
          * @return its new wait node
          */
         private Node addConditionWaiter() {
-            Node node = new Node(Thread.currentThread(), Node.CONDITION);
             Node t = lastWaiter;
-            if (t == null) 
+            // If lastWaiter is cancelled, clean out.
+            if (t != null && t.waitStatus != Node.CONDITION) {
+                unlinkCancelledWaiters();
+                t = lastWaiter;
+            }
+            Node node = new Node(Thread.currentThread(), Node.CONDITION);
+            if (t == null)
                 firstWaiter = node;
-            else 
+            else
                 t.nextWaiter = node;
             lastWaiter = node;
             return node;
         }
 
         /**
-         * Remove and transfer nodes until hit non-cancelled one or
+         * Removes and transfers nodes until hit non-cancelled one or
          * null. Split out from signal in part to encourage compilers
          * to inline the case of no waiters.
          * @param first (non-null) the first node on condition queue
          */
         private void doSignal(Node first) {
             do {
-                if ( (firstWaiter = first.nextWaiter) == null) 
+                if ( (firstWaiter = first.nextWaiter) == null)
                     lastWaiter = null;
                 first.nextWaiter = null;
             } while (!transferForSignal(first) &&
@@ -1643,11 +1829,11 @@
         }
 
         /**
-         * Remove and transfer all nodes.
+         * Removes and transfers all nodes.
          * @param first (non-null) the first node on condition queue
          */
         private void doSignalAll(Node first) {
-            lastWaiter = firstWaiter  = null;
+            lastWaiter = firstWaiter = null;
             do {
                 Node next = first.nextWaiter;
                 first.nextWaiter = null;
@@ -1656,45 +1842,81 @@
             } while (first != null);
         }
 
+        /**
+         * Unlinks cancelled waiter nodes from condition queue.
+         * Called only while holding lock. This is called when
+         * cancellation occurred during condition wait, and upon
+         * insertion of a new waiter when lastWaiter is seen to have
+         * been cancelled. This method is needed to avoid garbage
+         * retention in the absence of signals. So even though it may
+         * require a full traversal, it comes into play only when
+         * timeouts or cancellations occur in the absence of
+         * signals. It traverses all nodes rather than stopping at a
+         * particular target to unlink all pointers to garbage nodes
+         * without requiring many re-traversals during cancellation
+         * storms.
+         */
+        private void unlinkCancelledWaiters() {
+            Node t = firstWaiter;
+            Node trail = null;
+            while (t != null) {
+                Node next = t.nextWaiter;
+                if (t.waitStatus != Node.CONDITION) {
+                    t.nextWaiter = null;
+                    if (trail == null)
+                        firstWaiter = next;
+                    else
+                        trail.nextWaiter = next;
+                    if (next == null)
+                        lastWaiter = trail;
+                }
+                else
+                    trail = t;
+                t = next;
+            }
+        }
+
         // public methods
 
         /**
          * Moves the longest-waiting thread, if one exists, from the
          * wait queue for this condition to the wait queue for the
          * owning lock.
+         *
          * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
-         * returns false
+         *         returns {@code false}
          */
         public final void signal() {
-            if (!isHeldExclusively()) 
+            if (!isHeldExclusively())
                 throw new IllegalMonitorStateException();
             Node first = firstWaiter;
             if (first != null)
                 doSignal(first);
         }
-         
+
         /**
          * Moves all threads from the wait queue for this condition to
          * the wait queue for the owning lock.
+         *
          * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
-         * returns false
+         *         returns {@code false}
          */
         public final void signalAll() {
-            if (!isHeldExclusively()) 
+            if (!isHeldExclusively())
                 throw new IllegalMonitorStateException();
             Node first = firstWaiter;
-            if (first != null) 
+            if (first != null)
                 doSignalAll(first);
         }
 
         /**
          * Implements uninterruptible condition wait.
          * <ol>
-         * <li> Save lock state returned by {@link #getState} 
-         * <li> Invoke {@link #release} with 
-         *      saved state as argument, throwing 
-         *      IllegalMonitorStateException  if it fails.
-         * <li> Block until signalled
+         * <li> Save lock state returned by {@link #getState}.
+         * <li> Invoke {@link #release} with
+         *      saved state as argument, throwing
+         *      IllegalMonitorStateException if it fails.
+         * <li> Block until signalled.
          * <li> Reacquire by invoking specialized version of
          *      {@link #acquire} with saved state as argument.
          * </ol>
@@ -1705,7 +1927,7 @@
             boolean interrupted = false;
             while (!isOnSyncQueue(node)) {
                 LockSupport.park();
-                if (Thread.interrupted()) 
+                if (Thread.interrupted())
                     interrupted = true;
             }
             if (acquireQueued(node, savedState) || interrupted)
@@ -1725,47 +1947,47 @@
         private static final int THROW_IE    = -1;
 
         /**
-         * Check for interrupt, returning THROW_IE if interrupted
+         * Checks for interrupt, returning THROW_IE if interrupted
          * before signalled, REINTERRUPT if after signalled, or
          * 0 if not interrupted.
          */
         private int checkInterruptWhileWaiting(Node node) {
-            return (Thread.interrupted()) ?
-                ((transferAfterCancelledWait(node))? THROW_IE : REINTERRUPT) :
+            return Thread.interrupted() ?
+                (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :
                 0;
         }
 
         /**
-         * Throw InterruptedException, reinterrupt current thread, or
-         * do nothing, depending on mode.
+         * Throws InterruptedException, reinterrupts current thread, or
+         * does nothing, depending on mode.
          */
-        private void reportInterruptAfterWait(int interruptMode) 
+        private void reportInterruptAfterWait(int interruptMode)
             throws InterruptedException {
             if (interruptMode == THROW_IE)
                 throw new InterruptedException();
             else if (interruptMode == REINTERRUPT)
-                Thread.currentThread().interrupt();
+                selfInterrupt();
         }
 
         /**
          * Implements interruptible condition wait.
          * <ol>
-         * <li> If current thread is interrupted, throw InterruptedException
-         * <li> Save lock state returned by {@link #getState} 
-         * <li> Invoke {@link #release} with 
-         *      saved state as argument, throwing 
-         *      IllegalMonitorStateException  if it fails.
-         * <li> Block until signalled or interrupted
+         * <li> If current thread is interrupted, throw InterruptedException.
+         * <li> Save lock state returned by {@link #getState}.
+         * <li> Invoke {@link #release} with
+         *      saved state as argument, throwing
+         *      IllegalMonitorStateException if it fails.
+         * <li> Block until signalled or interrupted.
          * <li> Reacquire by invoking specialized version of
          *      {@link #acquire} with saved state as argument.
-         * <li> If interrupted while blocked in step 4, throw exception
+         * <li> If interrupted while blocked in step 4, throw InterruptedException.
          * </ol>
-         * 
+         *
          * @throws InterruptedException if the current thread is interrupted (and
          * interruption of thread suspension is supported).
          */
         public final void await() throws InterruptedException {
-            if (Thread.interrupted()) 
+            if (Thread.interrupted())
                 throw new InterruptedException();
             Node node = addConditionWaiter();
             int savedState = fullyRelease(node);
@@ -1777,6 +1999,8 @@
             }
             if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                 interruptMode = REINTERRUPT;
+            if (node.nextWaiter != null) // clean up if cancelled
+                unlinkCancelledWaiters();
             if (interruptMode != 0)
                 reportInterruptAfterWait(interruptMode);
         }
@@ -1784,17 +2008,17 @@
         /**
          * Implements timed condition wait.
          * <ol>
-         * <li> If current thread is interrupted, throw InterruptedException
-         * <li> Save lock state returned by {@link #getState} 
-         * <li> Invoke {@link #release} with 
-         *      saved state as argument, throwing 
-         *      IllegalMonitorStateException  if it fails.
-         * <li> Block until signalled, interrupted, or timed out
+         * <li> If current thread is interrupted, throw InterruptedException.
+         * <li> Save lock state returned by {@link #getState}.
+         * <li> Invoke {@link #release} with
+         *      saved state as argument, throwing
+         *      IllegalMonitorStateException if it fails.
+         * <li> Block until signalled, interrupted, or timed out.
          * <li> Reacquire by invoking specialized version of
          *      {@link #acquire} with saved state as argument.
-         * <li> If interrupted while blocked in step 4, throw InterruptedException
+         * <li> If interrupted while blocked in step 4, throw InterruptedException.
          * </ol>
-         * 
+         *
          * @param nanosTimeout the maximum time to wait, in nanoseconds
          * @return A value less than or equal to zero if the wait has
          * timed out; otherwise an estimate, that
@@ -1805,7 +2029,7 @@
          * interruption of thread suspension is supported).
          */
         public final long awaitNanos(long nanosTimeout) throws InterruptedException {
-            if (Thread.interrupted()) 
+            if (Thread.interrupted())
                 throw new InterruptedException();
             Node node = addConditionWaiter();
             int savedState = fullyRelease(node);
@@ -1813,18 +2037,21 @@
             int interruptMode = 0;
             while (!isOnSyncQueue(node)) {
                 if (nanosTimeout <= 0L) {
-                    transferAfterCancelledWait(node); 
+                    transferAfterCancelledWait(node);
                     break;
                 }
                 LockSupport.parkNanos(nanosTimeout);
                 if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                     break;
+
                 long now = System.nanoTime();
                 nanosTimeout -= now - lastTime;
                 lastTime = now;
             }
             if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                 interruptMode = REINTERRUPT;
+            if (node.nextWaiter != null)
+                unlinkCancelledWaiters();
             if (interruptMode != 0)
                 reportInterruptAfterWait(interruptMode);
             return nanosTimeout - (System.nanoTime() - lastTime);
@@ -1833,18 +2060,18 @@
         /**
          * Implements absolute timed condition wait.
          * <ol>
-         * <li> If current thread is interrupted, throw InterruptedException
-         * <li> Save lock state returned by {@link #getState} 
-         * <li> Invoke {@link #release} with 
-         *      saved state as argument, throwing 
-         *      IllegalMonitorStateException  if it fails.
-         * <li> Block until signalled, interrupted, or timed out
+         * <li> If current thread is interrupted, throw InterruptedException.
+         * <li> Save lock state returned by {@link #getState}.
+         * <li> Invoke {@link #release} with
+         *      saved state as argument, throwing
+         *      IllegalMonitorStateException if it fails.
+         * <li> Block until signalled, interrupted, or timed out.
          * <li> Reacquire by invoking specialized version of
          *      {@link #acquire} with saved state as argument.
-         * <li> If interrupted while blocked in step 4, throw InterruptedException
-         * <li> If timed out while blocked in step 4, return false, else true
+         * <li> If interrupted while blocked in step 4, throw InterruptedException.
+         * <li> If timed out while blocked in step 4, return false, else true.
          * </ol>
-         * 
+         *
          * @param deadline the absolute time to wait until
          * @return <tt>false</tt> if the deadline has
          * elapsed upon return, else <tt>true</tt>.
@@ -1856,7 +2083,7 @@
             if (deadline == null)
                 throw new NullPointerException();
             long abstime = deadline.getTime();
-            if (Thread.interrupted()) 
+            if (Thread.interrupted())
                 throw new InterruptedException();
             Node node = addConditionWaiter();
             int savedState = fullyRelease(node);
@@ -1864,7 +2091,7 @@
             int interruptMode = 0;
             while (!isOnSyncQueue(node)) {
                 if (System.currentTimeMillis() > abstime) {
-                    timedout = transferAfterCancelledWait(node); 
+                    timedout = transferAfterCancelledWait(node);
                     break;
                 }
                 LockSupport.parkUntil(abstime);
@@ -1873,26 +2100,28 @@
             }
             if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                 interruptMode = REINTERRUPT;
+            if (node.nextWaiter != null)
+                unlinkCancelledWaiters();
             if (interruptMode != 0)
                 reportInterruptAfterWait(interruptMode);
             return !timedout;
         }
-        
+
         /**
-         * Implements timed condition wait. 
+         * Implements timed condition wait.
          * <ol>
-         * <li> If current thread is interrupted, throw InterruptedException
-         * <li> Save lock state returned by {@link #getState} 
-         * <li> Invoke {@link #release} with 
-         *      saved state as argument, throwing 
-         *      IllegalMonitorStateException  if it fails.
-         * <li> Block until signalled, interrupted, or timed out
+         * <li> If current thread is interrupted, throw InterruptedException.
+         * <li> Save lock state returned by {@link #getState}.
+         * <li> Invoke {@link #release} with
+         *      saved state as argument, throwing
+         *      IllegalMonitorStateException if it fails.
+         * <li> Block until signalled, interrupted, or timed out.
          * <li> Reacquire by invoking specialized version of
          *      {@link #acquire} with saved state as argument.
-         * <li> If interrupted while blocked in step 4, throw InterruptedException
-         * <li> If timed out while blocked in step 4, return false, else true
+         * <li> If interrupted while blocked in step 4, throw InterruptedException.
+         * <li> If timed out while blocked in step 4, return false, else true.
          * </ol>
-         * 
+         *
          * @param time the maximum time to wait
          * @param unit the time unit of the <tt>time</tt> argument.
          * @return <tt>false</tt> if the waiting time detectably elapsed
@@ -1904,7 +2133,7 @@
             if (unit == null)
                 throw new NullPointerException();
             long nanosTimeout = unit.toNanos(time);
-            if (Thread.interrupted()) 
+            if (Thread.interrupted())
                 throw new InterruptedException();
             Node node = addConditionWaiter();
             int savedState = fullyRelease(node);
@@ -1913,10 +2142,11 @@
             int interruptMode = 0;
             while (!isOnSyncQueue(node)) {
                 if (nanosTimeout <= 0L) {
-                    timedout = transferAfterCancelledWait(node); 
+                    timedout = transferAfterCancelledWait(node);
                     break;
                 }
-                LockSupport.parkNanos(nanosTimeout);
+                if (nanosTimeout >= spinForTimeoutThreshold)
+                    LockSupport.parkNanos(nanosTimeout);
                 if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
                     break;
                 long now = System.nanoTime();
@@ -1925,6 +2155,8 @@
             }
             if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
                 interruptMode = REINTERRUPT;
+            if (node.nextWaiter != null)
+                unlinkCancelledWaiters();
             if (interruptMode != 0)
                 reportInterruptAfterWait(interruptMode);
             return !timedout;
@@ -1934,8 +2166,9 @@
 
         /**
          * Returns true if this condition was created by the given
-         * synchronization object
-         * @return true if owned
+         * synchronization object.
+         *
+         * @return {@code true} if owned
          */
         final boolean isOwnedBy(AbstractQueuedSynchronizer sync) {
             return sync == AbstractQueuedSynchronizer.this;
@@ -1943,13 +2176,14 @@
 
         /**
          * Queries whether any threads are waiting on this condition.
-         * Implements {@link AbstractQueuedSynchronizer#hasWaiters}
-         * @return <tt>true</tt> if there are any waiting threads.
+         * Implements {@link AbstractQueuedSynchronizer#hasWaiters}.
+         *
+         * @return {@code true} if there are any waiting threads
          * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
-         * returns false
-         */ 
+         *         returns {@code false}
+         */
         protected final boolean hasWaiters() {
-            if (!isHeldExclusively()) 
+            if (!isHeldExclusively())
                 throw new IllegalMonitorStateException();
             for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                 if (w.waitStatus == Node.CONDITION)
@@ -1960,14 +2194,15 @@
 
         /**
          * Returns an estimate of the number of threads waiting on
-         * this condition. 
-         * Implements {@link AbstractQueuedSynchronizer#getWaitQueueLength}
-         * @return the estimated number of waiting threads.
+         * this condition.
+         * Implements {@link AbstractQueuedSynchronizer#getWaitQueueLength}.
+         *
+         * @return the estimated number of waiting threads
          * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
-         * returns false
-         */ 
+         *         returns {@code false}
+         */
         protected final int getWaitQueueLength() {
-            if (!isHeldExclusively()) 
+            if (!isHeldExclusively())
                 throw new IllegalMonitorStateException();
             int n = 0;
             for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
@@ -1979,14 +2214,15 @@
 
         /**
          * Returns a collection containing those threads that may be
-         * waiting on this Condition.  
-         * Implements {@link AbstractQueuedSynchronizer#getWaitingThreads}
+         * waiting on this Condition.
+         * Implements {@link AbstractQueuedSynchronizer#getWaitingThreads}.
+         *
          * @return the collection of threads
          * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
-         * returns false
+         *         returns {@code false}
          */
         protected final Collection<Thread> getWaitingThreads() {
-            if (!isHeldExclusively()) 
+            if (!isHeldExclusively())
                 throw new IllegalMonitorStateException();
             ArrayList<Thread> list = new ArrayList<Thread>();
             for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
@@ -2016,6 +2252,7 @@
     private static final long headOffset;
     private static final long tailOffset;
     private static final long waitStatusOffset;
+    private static final long nextOffset;
 
     static {
         try {
@@ -2027,19 +2264,21 @@
                 (AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
             waitStatusOffset = unsafe.objectFieldOffset
                 (Node.class.getDeclaredField("waitStatus"));
-            
-        } catch(Exception ex) { throw new Error(ex); }
+            nextOffset = unsafe.objectFieldOffset
+                (Node.class.getDeclaredField("next"));
+
+        } catch (Exception ex) { throw new Error(ex); }
     }
 
     /**
-     * CAS head field. Used only by enq
+     * CAS head field. Used only by enq.
      */
     private final boolean compareAndSetHead(Node update) {
         return unsafe.compareAndSwapObject(this, headOffset, null, update);
     }
-    
+
     /**
-     * CAS tail field. Used only by enq
+     * CAS tail field. Used only by enq.
      */
     private final boolean compareAndSetTail(Node expect, Node update) {
         return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
@@ -2048,11 +2287,19 @@
     /**
      * CAS waitStatus field of a node.
      */
-    private final static boolean compareAndSetWaitStatus(Node node, 
-                                                         int expect, 
+    private final static boolean compareAndSetWaitStatus(Node node,
+                                                         int expect,
                                                          int update) {
-        return unsafe.compareAndSwapInt(node, waitStatusOffset, 
+        return unsafe.compareAndSwapInt(node, waitStatusOffset,
                                         expect, update);
     }
 
+    /**
+     * CAS next field of a node.
+     */
+    private final static boolean compareAndSetNext(Node node,
+                                                   Node expect,
+                                                   Node update) {
+        return unsafe.compareAndSwapObject(node, nextOffset, expect, update);
+    }
 }
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/locks/Condition.java b/libcore/concurrent/src/main/java/java/util/concurrent/locks/Condition.java
index 7a8ca5b..03be58f 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/locks/Condition.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/locks/Condition.java
@@ -9,13 +9,13 @@
 import java.util.Date;
 
 /**
- * <tt>Condition</tt> factors out the <tt>Object</tt> monitor
+ * {@code Condition} factors out the {@code Object} monitor
  * methods ({@link Object#wait() wait}, {@link Object#notify notify}
  * and {@link Object#notifyAll notifyAll}) into distinct objects to
  * give the effect of having multiple wait-sets per object, by
  * combining them with the use of arbitrary {@link Lock} implementations.
- * Where a <tt>Lock</tt> replaces the use of <tt>synchronized</tt> methods
- * and statements, a <tt>Condition</tt> replaces the use of the Object
+ * Where a {@code Lock} replaces the use of {@code synchronized} methods
+ * and statements, a {@code Condition} replaces the use of the Object
  * monitor methods.
  *
  * <p>Conditions (also known as <em>condition queues</em> or
@@ -26,37 +26,37 @@
  * must be protected, so a lock of some form is associated with the
  * condition. The key property that waiting for a condition provides
  * is that it <em>atomically</em> releases the associated lock and
- * suspends the current thread, just like <tt>Object.wait</tt>.
+ * suspends the current thread, just like {@code Object.wait}.
  *
- * <p>A <tt>Condition</tt> instance is intrinsically bound to a lock.
- * To obtain a <tt>Condition</tt> instance for a particular {@link Lock} 
+ * <p>A {@code Condition} instance is intrinsically bound to a lock.
+ * To obtain a {@code Condition} instance for a particular {@link Lock}
  * instance use its {@link Lock#newCondition newCondition()} method.
  *
  * <p>As an example, suppose we have a bounded buffer which supports
- * <tt>put</tt> and <tt>take</tt> methods.  If a
- * <tt>take</tt> is attempted on an empty buffer, then the thread will block
- * until an item becomes available; if a <tt>put</tt> is attempted on a
+ * {@code put} and {@code take} methods.  If a
+ * {@code take} is attempted on an empty buffer, then the thread will block
+ * until an item becomes available; if a {@code put} is attempted on a
  * full buffer, then the thread will block until a space becomes available.
- * We would like to keep waiting <tt>put</tt> threads and <tt>take</tt>
+ * We would like to keep waiting {@code put} threads and {@code take}
  * threads in separate wait-sets so that we can use the optimization of
  * only notifying a single thread at a time when items or spaces become
- * available in the buffer. This can be achieved using two 
+ * available in the buffer. This can be achieved using two
  * {@link Condition} instances.
  * <pre>
  * class BoundedBuffer {
- *   <b>Lock lock = new ReentrantLock();</b>
+ *   <b>final Lock lock = new ReentrantLock();</b>
  *   final Condition notFull  = <b>lock.newCondition(); </b>
  *   final Condition notEmpty = <b>lock.newCondition(); </b>
  *
- *   Object[] items = new Object[100];
+ *   final Object[] items = new Object[100];
  *   int putptr, takeptr, count;
  *
  *   public void put(Object x) throws InterruptedException {
  *     <b>lock.lock();
  *     try {</b>
- *       while (count == items.length) 
+ *       while (count == items.length)
  *         <b>notFull.await();</b>
- *       items[putptr] = x; 
+ *       items[putptr] = x;
  *       if (++putptr == items.length) putptr = 0;
  *       ++count;
  *       <b>notEmpty.signal();</b>
@@ -68,9 +68,9 @@
  *   public Object take() throws InterruptedException {
  *     <b>lock.lock();
  *     try {</b>
- *       while (count == 0) 
+ *       while (count == 0)
  *         <b>notEmpty.await();</b>
- *       Object x = items[takeptr]; 
+ *       Object x = items[takeptr];
  *       if (++takeptr == items.length) takeptr = 0;
  *       --count;
  *       <b>notFull.signal();</b>
@@ -78,7 +78,7 @@
  *     <b>} finally {
  *       lock.unlock();
  *     }</b>
- *   } 
+ *   }
  * }
  * </pre>
  *
@@ -86,61 +86,63 @@
  * this functionality, so there is no reason to implement this
  * sample usage class.)
  *
- * <p>A <tt>Condition</tt> implementation can provide behavior and semantics 
- * that is 
- * different from that of the <tt>Object</tt> monitor methods, such as 
- * guaranteed ordering for notifications, or not requiring a lock to be held 
+ * <p>A {@code Condition} implementation can provide behavior and semantics
+ * that is
+ * different from that of the {@code Object} monitor methods, such as
+ * guaranteed ordering for notifications, or not requiring a lock to be held
  * when performing notifications.
- * If an implementation provides such specialized semantics then the 
+ * If an implementation provides such specialized semantics then the
  * implementation must document those semantics.
  *
- * <p>Note that <tt>Condition</tt> instances are just normal objects and can 
- * themselves be used as the target in a <tt>synchronized</tt> statement,
+ * <p>Note that {@code Condition} instances are just normal objects and can
+ * themselves be used as the target in a {@code synchronized} statement,
  * and can have their own monitor {@link Object#wait wait} and
  * {@link Object#notify notification} methods invoked.
- * Acquiring the monitor lock of a <tt>Condition</tt> instance, or using its
+ * Acquiring the monitor lock of a {@code Condition} instance, or using its
  * monitor methods, has no specified relationship with acquiring the
- * {@link Lock} associated with that <tt>Condition</tt> or the use of its
- * {@link #await waiting} and {@link #signal signalling} methods.
- * It is recommended that to avoid confusion you never use <tt>Condition</tt>
+ * {@link Lock} associated with that {@code Condition} or the use of its
+ * {@linkplain #await waiting} and {@linkplain #signal signalling} methods.
+ * It is recommended that to avoid confusion you never use {@code Condition}
  * instances in this way, except perhaps within their own implementation.
  *
- * <p>Except where noted, passing a <tt>null</tt> value for any parameter 
+ * <p>Except where noted, passing a {@code null} value for any parameter
  * will result in a {@link NullPointerException} being thrown.
  *
  * <h3>Implementation Considerations</h3>
  *
- * <p>When waiting upon a <tt>Condition</tt>, a &quot;<em>spurious
- * wakeup</em>&quot; is permitted to occur, in 
+ * <p>When waiting upon a {@code Condition}, a &quot;<em>spurious
+ * wakeup</em>&quot; is permitted to occur, in
  * general, as a concession to the underlying platform semantics.
  * This has little practical impact on most application programs as a
- * <tt>Condition</tt> should always be waited upon in a loop, testing
+ * {@code Condition} should always be waited upon in a loop, testing
  * the state predicate that is being waited for.  An implementation is
- * free to remove the possibility of spurious wakeups but it is 
+ * free to remove the possibility of spurious wakeups but it is
  * recommended that applications programmers always assume that they can
  * occur and so always wait in a loop.
  *
- * <p>The three forms of condition waiting 
- * (interruptible, non-interruptible, and timed) may differ in their ease of 
+ * <p>The three forms of condition waiting
+ * (interruptible, non-interruptible, and timed) may differ in their ease of
  * implementation on some platforms and in their performance characteristics.
- * In particular, it may be difficult to provide these features and maintain 
- * specific semantics such as ordering guarantees. 
- * Further, the ability to interrupt the actual suspension of the thread may 
+ * In particular, it may be difficult to provide these features and maintain
+ * specific semantics such as ordering guarantees.
+ * Further, the ability to interrupt the actual suspension of the thread may
  * not always be feasible to implement on all platforms.
- * <p>Consequently, an implementation is not required to define exactly the 
- * same guarantees or semantics for all three forms of waiting, nor is it 
+ *
+ * <p>Consequently, an implementation is not required to define exactly the
+ * same guarantees or semantics for all three forms of waiting, nor is it
  * required to support interruption of the actual suspension of the thread.
+ *
  * <p>An implementation is required to
- * clearly document the semantics and guarantees provided by each of the 
- * waiting methods, and when an implementation does support interruption of 
- * thread suspension then it must obey the interruption semantics as defined 
+ * clearly document the semantics and guarantees provided by each of the
+ * waiting methods, and when an implementation does support interruption of
+ * thread suspension then it must obey the interruption semantics as defined
  * in this interface.
- * <p>As interruption generally implies cancellation, and checks for 
+ *
+ * <p>As interruption generally implies cancellation, and checks for
  * interruption are often infrequent, an implementation can favor responding
  * to an interrupt over normal method return. This is true even if it can be
- * shown that the interrupt occurred after another action may have unblocked
- * the thread. An implementation should document this behavior. 
- *
+ * shown that the interrupt occurred after another action that may have
+ * unblocked the thread. An implementation should document this behavior.
  *
  * @since 1.5
  * @author Doug Lea
@@ -148,21 +150,21 @@
 public interface Condition {
 
     /**
-     * Causes the current thread to wait until it is signalled or 
-     * {@link Thread#interrupt interrupted}.
+     * Causes the current thread to wait until it is signalled or
+     * {@linkplain Thread#interrupt interrupted}.
      *
-     * <p>The lock associated with this <tt>Condition</tt> is atomically 
-     * released and the current thread becomes disabled for thread scheduling 
+     * <p>The lock associated with this {@code Condition} is atomically
+     * released and the current thread becomes disabled for thread scheduling
      * purposes and lies dormant until <em>one</em> of four things happens:
      * <ul>
-     * <li>Some other thread invokes the {@link #signal} method for this 
-     * <tt>Condition</tt> and the current thread happens to be chosen as the 
+     * <li>Some other thread invokes the {@link #signal} method for this
+     * {@code Condition} and the current thread happens to be chosen as the
      * thread to be awakened; or
-     * <li>Some other thread invokes the {@link #signalAll} method for this 
-     * <tt>Condition</tt>; or
-     * <li>Some other thread {@link Thread#interrupt interrupts} the current
-     * thread, and interruption of thread suspension is supported; or
-     * <li>A &quot;<em>spurious wakeup</em>&quot; occurs
+     * <li>Some other thread invokes the {@link #signalAll} method for this
+     * {@code Condition}; or
+     * <li>Some other thread {@linkplain Thread#interrupt interrupts} the
+     * current thread, and interruption of thread suspension is supported; or
+     * <li>A &quot;<em>spurious wakeup</em>&quot; occurs.
      * </ul>
      *
      * <p>In all cases, before this method can return the current thread must
@@ -171,20 +173,21 @@
      *
      * <p>If the current thread:
      * <ul>
-     * <li>has its interrupted status set on entry to this method; or 
-     * <li>is {@link Thread#interrupt interrupted} while waiting 
-     * and interruption of thread suspension is supported, 
+     * <li>has its interrupted status set on entry to this method; or
+     * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+     * and interruption of thread suspension is supported,
      * </ul>
-     * then {@link InterruptedException} is thrown and the current thread's 
+     * then {@link InterruptedException} is thrown and the current thread's
      * interrupted status is cleared. It is not specified, in the first
      * case, whether or not the test for interruption occurs before the lock
      * is released.
-     * 
+     *
      * <p><b>Implementation Considerations</b>
+     *
      * <p>The current thread is assumed to hold the lock associated with this
-     * <tt>Condition</tt> when this method is called.
+     * {@code Condition} when this method is called.
      * It is up to the implementation to determine if this is
-     * the case and if not, how to respond. Typically, an exception will be 
+     * the case and if not, how to respond. Typically, an exception will be
      * thrown (such as {@link IllegalMonitorStateException}) and the
      * implementation must document that fact.
      *
@@ -193,62 +196,62 @@
      * must ensure that the signal is redirected to another waiting thread, if
      * there is one.
      *
-     * @throws InterruptedException if the current thread is interrupted (and
-     * interruption of thread suspension is supported).
-     **/
+     * @throws InterruptedException if the current thread is interrupted
+     *         (and interruption of thread suspension is supported)
+     */
     void await() throws InterruptedException;
 
     /**
      * Causes the current thread to wait until it is signalled.
      *
-     * <p>The lock associated with this condition is atomically 
-     * released and the current thread becomes disabled for thread scheduling 
+     * <p>The lock associated with this condition is atomically
+     * released and the current thread becomes disabled for thread scheduling
      * purposes and lies dormant until <em>one</em> of three things happens:
      * <ul>
-     * <li>Some other thread invokes the {@link #signal} method for this 
-     * <tt>Condition</tt> and the current thread happens to be chosen as the 
+     * <li>Some other thread invokes the {@link #signal} method for this
+     * {@code Condition} and the current thread happens to be chosen as the
      * thread to be awakened; or
-     * <li>Some other thread invokes the {@link #signalAll} method for this 
-     * <tt>Condition</tt>; or
-     * <li>A &quot;<em>spurious wakeup</em>&quot; occurs
+     * <li>Some other thread invokes the {@link #signalAll} method for this
+     * {@code Condition}; or
+     * <li>A &quot;<em>spurious wakeup</em>&quot; occurs.
      * </ul>
      *
      * <p>In all cases, before this method can return the current thread must
      * re-acquire the lock associated with this condition. When the
      * thread returns it is <em>guaranteed</em> to hold this lock.
      *
-     * <p>If the current thread's interrupt status is set when it enters
-     * this method, or it is {@link Thread#interrupt interrupted} 
+     * <p>If the current thread's interrupted status is set when it enters
+     * this method, or it is {@linkplain Thread#interrupt interrupted}
      * while waiting, it will continue to wait until signalled. When it finally
-     * returns from this method its <em>interrupted status</em> will still
+     * returns from this method its interrupted status will still
      * be set.
-     * 
+     *
      * <p><b>Implementation Considerations</b>
+     *
      * <p>The current thread is assumed to hold the lock associated with this
-     * <tt>Condition</tt> when this method is called.
+     * {@code Condition} when this method is called.
      * It is up to the implementation to determine if this is
-     * the case and if not, how to respond. Typically, an exception will be 
+     * the case and if not, how to respond. Typically, an exception will be
      * thrown (such as {@link IllegalMonitorStateException}) and the
      * implementation must document that fact.
-     *
-     **/
+     */
     void awaitUninterruptibly();
 
     /**
      * Causes the current thread to wait until it is signalled or interrupted,
      * or the specified waiting time elapses.
      *
-     * <p>The lock associated with this condition is atomically 
-     * released and the current thread becomes disabled for thread scheduling 
+     * <p>The lock associated with this condition is atomically
+     * released and the current thread becomes disabled for thread scheduling
      * purposes and lies dormant until <em>one</em> of five things happens:
      * <ul>
-     * <li>Some other thread invokes the {@link #signal} method for this 
-     * <tt>Condition</tt> and the current thread happens to be chosen as the 
-     * thread to be awakened; or 
-     * <li>Some other thread invokes the {@link #signalAll} method for this 
-     * <tt>Condition</tt>; or
-     * <li>Some other thread {@link Thread#interrupt interrupts} the current
-     * thread, and interruption of thread suspension is supported; or
+     * <li>Some other thread invokes the {@link #signal} method for this
+     * {@code Condition} and the current thread happens to be chosen as the
+     * thread to be awakened; or
+     * <li>Some other thread invokes the {@link #signalAll} method for this
+     * {@code Condition}; or
+     * <li>Some other thread {@linkplain Thread#interrupt interrupts} the
+     * current thread, and interruption of thread suspension is supported; or
      * <li>The specified waiting time elapses; or
      * <li>A &quot;<em>spurious wakeup</em>&quot; occurs.
      * </ul>
@@ -259,17 +262,17 @@
      *
      * <p>If the current thread:
      * <ul>
-     * <li>has its interrupted status set on entry to this method; or 
-     * <li>is {@link Thread#interrupt interrupted} while waiting 
-     * and interruption of thread suspension is supported, 
+     * <li>has its interrupted status set on entry to this method; or
+     * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+     * and interruption of thread suspension is supported,
      * </ul>
-     * then {@link InterruptedException} is thrown and the current thread's 
+     * then {@link InterruptedException} is thrown and the current thread's
      * interrupted status is cleared. It is not specified, in the first
      * case, whether or not the test for interruption occurs before the lock
      * is released.
      *
      * <p>The method returns an estimate of the number of nanoseconds
-     * remaining to wait given the supplied <tt>nanosTimeout</tt>
+     * remaining to wait given the supplied {@code nanosTimeout}
      * value upon return, or a value less than or equal to zero if it
      * timed out. This value can be used to determine whether and how
      * long to re-wait in cases where the wait returns but an awaited
@@ -285,7 +288,7 @@
      *      else
      *        return false;
      *   }
-     *   // ... 
+     *   // ...
      * }
      * </pre>
      *
@@ -296,10 +299,11 @@
      * than specified when re-waits occur.
      *
      * <p><b>Implementation Considerations</b>
+     *
      * <p>The current thread is assumed to hold the lock associated with this
-     * <tt>Condition</tt> when this method is called.
+     * {@code Condition} when this method is called.
      * It is up to the implementation to determine if this is
-     * the case and if not, how to respond. Typically, an exception will be 
+     * the case and if not, how to respond. Typically, an exception will be
      * thrown (such as {@link IllegalMonitorStateException}) and the
      * implementation must document that fact.
      *
@@ -310,13 +314,14 @@
      * there is one.
      *
      * @param nanosTimeout the maximum time to wait, in nanoseconds
-     * @return A value less than or equal to zero if the wait has
-     * timed out; otherwise an estimate, that
-     * is strictly less than the <tt>nanosTimeout</tt> argument,
-     * of the time still remaining when this method returned.
-     *
-     * @throws InterruptedException if the current thread is interrupted (and
-     * interruption of thread suspension is supported).
+     * @return an estimate of the {@code nanosTimeout} value minus
+     *         the time spent waiting upon return from this method.
+     *         A positive value may be used as the argument to a
+     *         subsequent call to this method to finish waiting out
+     *         the desired time.  A value less than or equal to zero
+     *         indicates that no time remains.
+     * @throws InterruptedException if the current thread is interrupted
+     *         (and interruption of thread suspension is supported)
      */
     long awaitNanos(long nanosTimeout) throws InterruptedException;
 
@@ -328,29 +333,29 @@
      *   awaitNanos(unit.toNanos(time)) &gt; 0
      * </pre>
      * @param time the maximum time to wait
-     * @param unit the time unit of the <tt>time</tt> argument.
-     * @return <tt>false</tt> if the waiting time detectably elapsed
-     * before return from the method, else <tt>true</tt>.
-     * @throws InterruptedException if the current thread is interrupted (and
-     * interruption of thread suspension is supported).
+     * @param unit the time unit of the {@code time} argument
+     * @return {@code false} if the waiting time detectably elapsed
+     *         before return from the method, else {@code true}
+     * @throws InterruptedException if the current thread is interrupted
+     *         (and interruption of thread suspension is supported)
      */
     boolean await(long time, TimeUnit unit) throws InterruptedException;
-    
+
     /**
      * Causes the current thread to wait until it is signalled or interrupted,
      * or the specified deadline elapses.
      *
-     * <p>The lock associated with this condition is atomically 
-     * released and the current thread becomes disabled for thread scheduling 
+     * <p>The lock associated with this condition is atomically
+     * released and the current thread becomes disabled for thread scheduling
      * purposes and lies dormant until <em>one</em> of five things happens:
      * <ul>
-     * <li>Some other thread invokes the {@link #signal} method for this 
-     * <tt>Condition</tt> and the current thread happens to be chosen as the 
-     * thread to be awakened; or 
-     * <li>Some other thread invokes the {@link #signalAll} method for this 
-     * <tt>Condition</tt>; or
-     * <li>Some other thread {@link Thread#interrupt interrupts} the current
-     * thread, and interruption of thread suspension is supported; or
+     * <li>Some other thread invokes the {@link #signal} method for this
+     * {@code Condition} and the current thread happens to be chosen as the
+     * thread to be awakened; or
+     * <li>Some other thread invokes the {@link #signalAll} method for this
+     * {@code Condition}; or
+     * <li>Some other thread {@linkplain Thread#interrupt interrupts} the
+     * current thread, and interruption of thread suspension is supported; or
      * <li>The specified deadline elapses; or
      * <li>A &quot;<em>spurious wakeup</em>&quot; occurs.
      * </ul>
@@ -362,11 +367,11 @@
      *
      * <p>If the current thread:
      * <ul>
-     * <li>has its interrupted status set on entry to this method; or 
-     * <li>is {@link Thread#interrupt interrupted} while waiting 
-     * and interruption of thread suspension is supported, 
+     * <li>has its interrupted status set on entry to this method; or
+     * <li>is {@linkplain Thread#interrupt interrupted} while waiting
+     * and interruption of thread suspension is supported,
      * </ul>
-     * then {@link InterruptedException} is thrown and the current thread's 
+     * then {@link InterruptedException} is thrown and the current thread's
      * interrupted status is cleared. It is not specified, in the first
      * case, whether or not the test for interruption occurs before the lock
      * is released.
@@ -378,20 +383,21 @@
      * synchronized boolean aMethod(Date deadline) {
      *   boolean stillWaiting = true;
      *   while (!conditionBeingWaitedFor) {
-     *     if (stillwaiting)
+     *     if (stillWaiting)
      *         stillWaiting = theCondition.awaitUntil(deadline);
      *      else
      *        return false;
      *   }
-     *   // ... 
+     *   // ...
      * }
      * </pre>
      *
      * <p><b>Implementation Considerations</b>
+     *
      * <p>The current thread is assumed to hold the lock associated with this
-     * <tt>Condition</tt> when this method is called.
+     * {@code Condition} when this method is called.
      * It is up to the implementation to determine if this is
-     * the case and if not, how to respond. Typically, an exception will be 
+     * the case and if not, how to respond. Typically, an exception will be
      * thrown (such as {@link IllegalMonitorStateException}) and the
      * implementation must document that fact.
      *
@@ -401,13 +407,11 @@
      * must ensure that the signal is redirected to another waiting thread, if
      * there is one.
      *
-     *
      * @param deadline the absolute time to wait until
-     * @return <tt>false</tt> if the deadline has
-     * elapsed upon return, else <tt>true</tt>.
-     *
-     * @throws InterruptedException if the current thread is interrupted (and
-     * interruption of thread suspension is supported).
+     * @return {@code false} if the deadline has elapsed upon return, else
+     *         {@code true}
+     * @throws InterruptedException if the current thread is interrupted
+     *         (and interruption of thread suspension is supported)
      */
     boolean awaitUntil(Date deadline) throws InterruptedException;
 
@@ -416,8 +420,8 @@
      *
      * <p>If any threads are waiting on this condition then one
      * is selected for waking up. That thread must then re-acquire the
-     * lock before returning from <tt>await</tt>.
-     **/
+     * lock before returning from {@code await}.
+     */
     void signal();
 
     /**
@@ -425,15 +429,7 @@
      *
      * <p>If any threads are waiting on this condition then they are
      * all woken up. Each thread must re-acquire the lock before it can
-     * return from <tt>await</tt>.
-     **/
+     * return from {@code await}.
+     */
     void signalAll();
-
 }
-
-
-
-
-
-
-
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/locks/Lock.java b/libcore/concurrent/src/main/java/java/util/concurrent/locks/Lock.java
index f07b72e..4b9abd6 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/locks/Lock.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/locks/Lock.java
@@ -8,8 +8,8 @@
 import java.util.concurrent.TimeUnit;
 
 /**
- * <tt>Lock</tt> implementations provide more extensive locking
- * operations than can be obtained using <tt>synchronized</tt> methods
+ * {@code Lock} implementations provide more extensive locking
+ * operations than can be obtained using {@code synchronized} methods
  * and statements.  They allow more flexible structuring, may have
  * quite different properties, and may support multiple associated
  * {@link Condition} objects.
@@ -19,17 +19,16 @@
  * shared resource: only one thread at a time can acquire the lock and
  * all access to the shared resource requires that the lock be
  * acquired first. However, some locks may allow concurrent access to
- * a shared resource, such as the read lock of a {@link
- * ReadWriteLock}.
+ * a shared resource, such as the read lock of a {@link ReadWriteLock}.
  *
- * <p>The use of <tt>synchronized</tt> methods or statements provides 
+ * <p>The use of {@code synchronized} methods or statements provides
  * access to the implicit monitor lock associated with every object, but
  * forces all lock acquisition and release to occur in a block-structured way:
  * when multiple locks are acquired they must be released in the opposite
  * order, and all locks must be released in the same lexical scope in which
  * they were acquired.
  *
- * <p>While the scoping mechanism for <tt>synchronized</tt> methods
+ * <p>While the scoping mechanism for {@code synchronized} methods
  * and statements makes it much easier to program with monitor locks,
  * and helps avoid many common programming errors involving locks,
  * there are occasions where you need to work with locks in a more
@@ -38,18 +37,18 @@
  * &quot;hand-over-hand&quot; or &quot;chain locking&quot;: you
  * acquire the lock of node A, then node B, then release A and acquire
  * C, then release B and acquire D and so on.  Implementations of the
- * <tt>Lock</tt> interface enable the use of such techniques by
+ * {@code Lock} interface enable the use of such techniques by
  * allowing a lock to be acquired and released in different scopes,
  * and allowing multiple locks to be acquired and released in any
  * order.
  *
  * <p>With this increased flexibility comes additional
  * responsibility. The absence of block-structured locking removes the
- * automatic release of locks that occurs with <tt>synchronized</tt>
+ * automatic release of locks that occurs with {@code synchronized}
  * methods and statements. In most cases, the following idiom
  * should be used:
  *
- * <pre><tt>     Lock l = ...; 
+ * <pre><tt>     Lock l = ...;
  *     l.lock();
  *     try {
  *         // access the resource protected by this lock
@@ -63,39 +62,42 @@
  * held is protected by try-finally or try-catch to ensure that the
  * lock is released when necessary.
  *
- * <p><tt>Lock</tt> implementations provide additional functionality
- * over the use of <tt>synchronized</tt> methods and statements by
+ * <p>{@code Lock} implementations provide additional functionality
+ * over the use of {@code synchronized} methods and statements by
  * providing a non-blocking attempt to acquire a lock ({@link
  * #tryLock()}), an attempt to acquire the lock that can be
  * interrupted ({@link #lockInterruptibly}, and an attempt to acquire
  * the lock that can timeout ({@link #tryLock(long, TimeUnit)}).
  *
- * <p>A <tt>Lock</tt> class can also provide behavior and semantics
+ * <p>A {@code Lock} class can also provide behavior and semantics
  * that is quite different from that of the implicit monitor lock,
  * such as guaranteed ordering, non-reentrant usage, or deadlock
  * detection. If an implementation provides such specialized semantics
  * then the implementation must document those semantics.
  *
- * <p>Note that <tt>Lock</tt> instances are just normal objects and can 
- * themselves be used as the target in a <tt>synchronized</tt> statement.
+ * <p>Note that {@code Lock} instances are just normal objects and can
+ * themselves be used as the target in a {@code synchronized} statement.
  * Acquiring the
- * monitor lock of a <tt>Lock</tt> instance has no specified relationship
- * with invoking any of the {@link #lock} methods of that instance. 
- * It is recommended that to avoid confusion you never use <tt>Lock</tt>
+ * monitor lock of a {@code Lock} instance has no specified relationship
+ * with invoking any of the {@link #lock} methods of that instance.
+ * It is recommended that to avoid confusion you never use {@code Lock}
  * instances in this way, except within their own implementation.
  *
- * <p>Except where noted, passing a <tt>null</tt> value for any
+ * <p>Except where noted, passing a {@code null} value for any
  * parameter will result in a {@link NullPointerException} being
  * thrown.
  *
  * <h3>Memory Synchronization</h3>
- * <p>All <tt>Lock</tt> implementations <em>must</em> enforce the same
- * memory synchronization semantics as provided by the built-in monitor lock:
+ *
+ * <p>All {@code Lock} implementations <em>must</em> enforce the same
+ * memory synchronization semantics as provided by the built-in monitor
+ * lock, as described in <a href="http://java.sun.com/docs/books/jls/">
+ * The Java Language Specification, Third Edition (17.4 Memory Model)</a>:
  * <ul>
- * <li>A successful lock operation acts like a successful 
- * <tt>monitorEnter</tt> action
- * <li>A successful <tt>unlock</tt> operation acts like a successful
- * <tt>monitorExit</tt> action
+ * <li>A successful {@code lock} operation has the same memory
+ * synchronization effects as a successful <em>Lock</em> action.
+ * <li>A successful {@code unlock} operation has the same
+ * memory synchronization effects as a successful <em>Unlock</em> action.
  * </ul>
  *
  * Unsuccessful locking and unlocking operations, and reentrant
@@ -108,7 +110,7 @@
  * non-interruptible, and timed) may differ in their performance
  * characteristics, ordering guarantees, or other implementation
  * qualities.  Further, the ability to interrupt the <em>ongoing</em>
- * acquisition of a lock may not be available in a given <tt>Lock</tt>
+ * acquisition of a lock may not be available in a given {@code Lock}
  * class.  Consequently, an implementation is not required to define
  * exactly the same guarantees or semantics for all three forms of
  * lock acquisition, nor is it required to support interruption of an
@@ -119,12 +121,11 @@
  * acquisition is supported: which is either totally, or only on
  * method entry.
  *
- * <p>As interruption generally implies cancellation, and checks for 
+ * <p>As interruption generally implies cancellation, and checks for
  * interruption are often infrequent, an implementation can favor responding
  * to an interrupt over normal method return. This is true even if it can be
  * shown that the interrupt occurred after another action may have unblocked
- * the thread. An implementation should document this behavior. 
- *
+ * the thread. An implementation should document this behavior.
  *
  * @see ReentrantLock
  * @see Condition
@@ -132,45 +133,50 @@
  *
  * @since 1.5
  * @author Doug Lea
- *
- **/
+ */
 public interface Lock {
 
     /**
      * Acquires the lock.
-     * <p>If the lock is not available then
-     * the current thread becomes disabled for thread scheduling 
-     * purposes and lies dormant until the lock has been acquired.
-     * <p><b>Implementation Considerations</b>
-     * <p>A <tt>Lock</tt> implementation may be able to detect 
-     * erroneous use of the lock, such as an invocation that would cause 
-     * deadlock, and may throw an (unchecked) exception in such circumstances. 
-     * The circumstances and the exception type must be documented by that 
-     * <tt>Lock</tt> implementation.
      *
-     **/
+     * <p>If the lock is not available then the current thread becomes
+     * disabled for thread scheduling purposes and lies dormant until the
+     * lock has been acquired.
+     *
+     * <p><b>Implementation Considerations</b>
+     *
+     * <p>A {@code Lock} implementation may be able to detect erroneous use
+     * of the lock, such as an invocation that would cause deadlock, and
+     * may throw an (unchecked) exception in such circumstances.  The
+     * circumstances and the exception type must be documented by that
+     * {@code Lock} implementation.
+     */
     void lock();
 
     /**
-     * Acquires the lock unless the current thread is  
-     * {@link Thread#interrupt interrupted}. 
+     * Acquires the lock unless the current thread is
+     * {@linkplain Thread#interrupt interrupted}.
+     *
      * <p>Acquires the lock if it is available and returns immediately.
-     * <p>If the lock is not available then
-     * the current thread becomes disabled for thread scheduling 
-     * purposes and lies dormant until one of two things happens:
+     *
+     * <p>If the lock is not available then the current thread becomes
+     * disabled for thread scheduling purposes and lies dormant until
+     * one of two things happens:
+     *
      * <ul>
      * <li>The lock is acquired by the current thread; or
-     * <li>Some other thread {@link Thread#interrupt interrupts} the current
-     * thread, and interruption of lock acquisition is supported.
+     * <li>Some other thread {@linkplain Thread#interrupt interrupts} the
+     * current thread, and interruption of lock acquisition is supported.
      * </ul>
+     *
      * <p>If the current thread:
      * <ul>
-     * <li>has its interrupted status set on entry to this method; or 
-     * <li>is {@link Thread#interrupt interrupted} while acquiring 
-     * the lock, and interruption of lock acquisition is supported, 
+     * <li>has its interrupted status set on entry to this method; or
+     * <li>is {@linkplain Thread#interrupt interrupted} while acquiring the
+     * lock, and interruption of lock acquisition is supported,
      * </ul>
-     * then {@link InterruptedException} is thrown and the current thread's 
-     * interrupted status is cleared. 
+     * then {@link InterruptedException} is thrown and the current thread's
+     * interrupted status is cleared.
      *
      * <p><b>Implementation Considerations</b>
      *
@@ -183,28 +189,26 @@
      * <p>An implementation can favor responding to an interrupt over
      * normal method return.
      *
-     * <p>A <tt>Lock</tt> implementation may be able to detect
+     * <p>A {@code Lock} implementation may be able to detect
      * erroneous use of the lock, such as an invocation that would
      * cause deadlock, and may throw an (unchecked) exception in such
      * circumstances.  The circumstances and the exception type must
-     * be documented by that <tt>Lock</tt> implementation.
+     * be documented by that {@code Lock} implementation.
      *
-     * @throws InterruptedException if the current thread is interrupted
-     * while acquiring the lock (and interruption of lock acquisition is 
-     * supported).
-     *
-     * @see Thread#interrupt
-     *
-     **/
+     * @throws InterruptedException if the current thread is
+     *         interrupted while acquiring the lock (and interruption
+     *         of lock acquisition is supported).
+     */
     void lockInterruptibly() throws InterruptedException;
 
-
     /**
      * Acquires the lock only if it is free at the time of invocation.
+     *
      * <p>Acquires the lock if it is available and returns immediately
-     * with the value <tt>true</tt>.
-     * If the lock is not available then this method will return 
-     * immediately with the value <tt>false</tt>.
+     * with the value {@code true}.
+     * If the lock is not available then this method will return
+     * immediately with the value {@code false}.
+     *
      * <p>A typical usage idiom for this method would be:
      * <pre>
      *      Lock lock = ...;
@@ -221,109 +225,103 @@
      * This usage ensures that the lock is unlocked if it was acquired, and
      * doesn't try to unlock if the lock was not acquired.
      *
-     * @return <tt>true</tt> if the lock was acquired and <tt>false</tt>
-     * otherwise.
-     **/
+     * @return {@code true} if the lock was acquired and
+     *         {@code false} otherwise
+     */
     boolean tryLock();
 
     /**
      * Acquires the lock if it is free within the given waiting time and the
-     * current thread has not been {@link Thread#interrupt interrupted}.
+     * current thread has not been {@linkplain Thread#interrupt interrupted}.
      *
      * <p>If the lock is available this method returns immediately
-     * with the value <tt>true</tt>.
+     * with the value {@code true}.
      * If the lock is not available then
-     * the current thread becomes disabled for thread scheduling 
+     * the current thread becomes disabled for thread scheduling
      * purposes and lies dormant until one of three things happens:
      * <ul>
      * <li>The lock is acquired by the current thread; or
-     * <li>Some other thread {@link Thread#interrupt interrupts} the current
-     * thread, and interruption of lock acquisition is supported; or
+     * <li>Some other thread {@linkplain Thread#interrupt interrupts} the
+     * current thread, and interruption of lock acquisition is supported; or
      * <li>The specified waiting time elapses
      * </ul>
-     * <p>If the lock is acquired then the value <tt>true</tt> is returned.
+     *
+     * <p>If the lock is acquired then the value {@code true} is returned.
+     *
      * <p>If the current thread:
      * <ul>
-     * <li>has its interrupted status set on entry to this method; or 
-     * <li>is {@link Thread#interrupt interrupted} while acquiring 
-     * the lock, and interruption of lock acquisition is supported, 
+     * <li>has its interrupted status set on entry to this method; or
+     * <li>is {@linkplain Thread#interrupt interrupted} while acquiring
+     * the lock, and interruption of lock acquisition is supported,
      * </ul>
-     * then {@link InterruptedException} is thrown and the current thread's 
-     * interrupted status is cleared. 
-     * <p>If the specified waiting time elapses then the value <tt>false</tt>
+     * then {@link InterruptedException} is thrown and the current thread's
+     * interrupted status is cleared.
+     *
+     * <p>If the specified waiting time elapses then the value {@code false}
      * is returned.
-     * If the time is 
+     * If the time is
      * less than or equal to zero, the method will not wait at all.
      *
      * <p><b>Implementation Considerations</b>
+     *
      * <p>The ability to interrupt a lock acquisition in some implementations
-     * may not be possible, and if possible may 
-     * be an expensive operation. 
+     * may not be possible, and if possible may
+     * be an expensive operation.
      * The programmer should be aware that this may be the case. An
      * implementation should document when this is the case.
-     * <p>An implementation can favor responding to an interrupt over normal 
+     *
+     * <p>An implementation can favor responding to an interrupt over normal
      * method return, or reporting a timeout.
-     * <p>A <tt>Lock</tt> implementation may be able to detect 
-     * erroneous use of the lock, such as an invocation that would cause 
-     * deadlock, and may throw an (unchecked) exception in such circumstances. 
-     * The circumstances and the exception type must be documented by that 
-     * <tt>Lock</tt> implementation.
+     *
+     * <p>A {@code Lock} implementation may be able to detect
+     * erroneous use of the lock, such as an invocation that would cause
+     * deadlock, and may throw an (unchecked) exception in such circumstances.
+     * The circumstances and the exception type must be documented by that
+     * {@code Lock} implementation.
      *
      * @param time the maximum time to wait for the lock
-     * @param unit the time unit of the <tt>time</tt> argument.
-     * @return <tt>true</tt> if the lock was acquired and <tt>false</tt>
-     * if the waiting time elapsed before the lock was acquired.
+     * @param unit the time unit of the {@code time} argument
+     * @return {@code true} if the lock was acquired and {@code false}
+     *         if the waiting time elapsed before the lock was acquired
      *
      * @throws InterruptedException if the current thread is interrupted
-     * while acquiring the lock (and interruption of lock acquisition is 
-     * supported).
-     *
-     * @see Thread#interrupt
-     *
-     **/
+     *         while acquiring the lock (and interruption of lock
+     *         acquisition is supported)
+     */
     boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
 
     /**
      * Releases the lock.
+     *
      * <p><b>Implementation Considerations</b>
-     * <p>A <tt>Lock</tt> implementation will usually impose
+     *
+     * <p>A {@code Lock} implementation will usually impose
      * restrictions on which thread can release a lock (typically only the
      * holder of the lock can release it) and may throw
      * an (unchecked) exception if the restriction is violated.
      * Any restrictions and the exception
-     * type must be documented by that <tt>Lock</tt> implementation.
-     **/
+     * type must be documented by that {@code Lock} implementation.
+     */
     void unlock();
 
     /**
-     * Returns a new {@link Condition} instance that is bound to this 
-     * <tt>Lock</tt> instance.
-     * <p>Before waiting on the condition the lock must be held by the 
-     * current thread. 
-     * A call to {@link Condition#await()} will atomically release the lock 
+     * Returns a new {@link Condition} instance that is bound to this
+     * {@code Lock} instance.
+     *
+     * <p>Before waiting on the condition the lock must be held by the
+     * current thread.
+     * A call to {@link Condition#await()} will atomically release the lock
      * before waiting and re-acquire the lock before the wait returns.
+     *
      * <p><b>Implementation Considerations</b>
-     * <p>The exact operation of the {@link Condition} instance depends on the
-     * <tt>Lock</tt> implementation and must be documented by that
+     *
+     * <p>The exact operation of the {@link Condition} instance depends on
+     * the {@code Lock} implementation and must be documented by that
      * implementation.
-     * 
-     * @return A new {@link Condition} instance for this <tt>Lock</tt> 
-     * instance.
-     * @throws UnsupportedOperationException if this <tt>Lock</tt> 
-     * implementation does not support conditions.
-     **/
+     *
+     * @return A new {@link Condition} instance for this {@code Lock} instance
+     * @throws UnsupportedOperationException if this {@code Lock}
+     *         implementation does not support conditions
+     */
     Condition newCondition();
-
 }
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/locks/LockSupport.java b/libcore/concurrent/src/main/java/java/util/concurrent/locks/LockSupport.java
index 8603785..b55b874 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/locks/LockSupport.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/locks/LockSupport.java
@@ -13,48 +13,56 @@
  * Basic thread blocking primitives for creating locks and other
  * synchronization classes.
  *
- * <p>This class associates with each thread that uses it, a permit
+ * <p>This class associates, with each thread that uses it, a permit
  * (in the sense of the {@link java.util.concurrent.Semaphore
- * Semaphore} class). A call to <tt>park</tt> will return immediately
+ * Semaphore} class). A call to {@code park} will return immediately
  * if the permit is available, consuming it in the process; otherwise
- * it <em>may</em> block.  A call to <tt>unpark</tt> makes the permit
+ * it <em>may</em> block.  A call to {@code unpark} makes the permit
  * available, if it was not already available. (Unlike with Semaphores
  * though, permits do not accumulate. There is at most one.)
  *
- * <p>Methods <tt>park</tt> and <tt>unpark</tt> provide efficient
+ * <p>Methods {@code park} and {@code unpark} provide efficient
  * means of blocking and unblocking threads that do not encounter the
- * problems that cause the deprecated methods <tt>Thread.suspend</tt>
- * and <tt>Thread.resume</tt> to be unusable for such purposes: Races
- * between one thread invoking <tt>park</tt> and another thread trying
- * to <tt>unpark</tt> it will preserve liveness, due to the
- * permit. Additionally, <tt>park</tt> will return if the caller's
+ * problems that cause the deprecated methods {@code Thread.suspend}
+ * and {@code Thread.resume} to be unusable for such purposes: Races
+ * between one thread invoking {@code park} and another thread trying
+ * to {@code unpark} it will preserve liveness, due to the
+ * permit. Additionally, {@code park} will return if the caller's
  * thread was interrupted, and timeout versions are supported. The
- * <tt>park</tt> method may also return at any other time, for "no
+ * {@code park} method may also return at any other time, for "no
  * reason", so in general must be invoked within a loop that rechecks
- * conditions upon return. In this sense <tt>park</tt> serves as an
+ * conditions upon return. In this sense {@code park} serves as an
  * optimization of a "busy wait" that does not waste as much time
- * spinning, but must be paired with an <tt>unpark</tt> to be
+ * spinning, but must be paired with an {@code unpark} to be
  * effective.
  *
  * <p>These methods are designed to be used as tools for creating
  * higher-level synchronization utilities, and are not in themselves
- * useful for most concurrency control applications.
+ * useful for most concurrency control applications.  The {@code park}
+ * method is designed for use only in constructions of the form:
+ * <pre>while (!canProceed()) { ... LockSupport.park(this); }</pre>
+ * where neither {@code canProceed} nor any other actions prior to the
+ * call to {@code park} entail locking or blocking.  Because only one
+ * permit is associated with each thread, any intermediary uses of
+ * {@code park} could interfere with its intended effects.
  *
- * <p><b>Sample Usage.</b> Here is a sketch of a First-in-first-out
- * non-reentrant lock class.
- * <pre>
- *   private AtomicBoolean locked = new AtomicBoolean(false);
- *   private Queue&lt;Thread&gt; waiters = new ConcurrentLinkedQueue&lt;Thread&gt;();
+ * <p><b>Sample Usage.</b> Here is a sketch of a first-in-first-out
+ * non-reentrant lock class:
+ * <pre>{@code
+ * class FIFOMutex {
+ *   private final AtomicBoolean locked = new AtomicBoolean(false);
+ *   private final Queue<Thread> waiters
+ *     = new ConcurrentLinkedQueue<Thread>();
  *
- *   public void lock() { 
+ *   public void lock() {
  *     boolean wasInterrupted = false;
  *     Thread current = Thread.currentThread();
  *     waiters.add(current);
  *
  *     // Block while not first in queue or cannot acquire lock
- *     while (waiters.peek() != current || 
- *            !locked.compareAndSet(false, true)) { 
- *        LockSupport.park();
+ *     while (waiters.peek() != current ||
+ *            !locked.compareAndSet(false, true)) {
+ *        LockSupport.park(this);
  *        if (Thread.interrupted()) // ignore interrupts while waiting
  *          wasInterrupted = true;
  *     }
@@ -67,9 +75,8 @@
  *   public void unlock() {
  *     locked.set(false);
  *     LockSupport.unpark(waiters.peek());
- *   } 
- * }
- * </pre>
+ *   }
+ * }}</pre>
  */
 @SuppressWarnings("all")
 public class LockSupport {
@@ -80,14 +87,15 @@
     // END android-changed
 
     /**
-     * Make available the permit for the given thread, if it
+     * Makes available the permit for the given thread, if it
      * was not already available.  If the thread was blocked on
-     * <tt>park</tt> then it will unblock.  Otherwise, its next call
-     * to <tt>park</tt> is guaranteed not to block. This operation
+     * {@code park} then it will unblock.  Otherwise, its next call
+     * to {@code park} is guaranteed not to block. This operation
      * is not guaranteed to have any effect at all if the given
      * thread has not been started.
-     * @param thread the thread to unpark, or <tt>null</tt>, in which case
-     * this operation has no effect. 
+     *
+     * @param thread the thread to unpark, or {@code null}, in which case
+     *        this operation has no effect
      */
     public static void unpark(Thread thread) {
         if (thread != null)
@@ -97,20 +105,26 @@
     /**
      * Disables the current thread for thread scheduling purposes unless the
      * permit is available.
-     * <p>If the permit is available then it is consumed and the call returns
-     * immediately; otherwise 
-     * the current thread becomes disabled for thread scheduling 
-     * purposes and lies dormant until one of three things happens:
+     *
+     * <p>If the permit is available then it is consumed and the call
+     * returns immediately; otherwise the current thread becomes disabled
+     * for thread scheduling purposes and lies dormant until one of three
+     * things happens:
+     *
      * <ul>
-     * <li>Some other thread invokes <tt>unpark</tt> with the current thread 
-     * as the target; or
-     * <li>Some other thread {@link Thread#interrupt interrupts} the current
-     * thread; or
+     *
+     * <li>Some other thread invokes {@link #unpark unpark} with the
+     * current thread as the target; or
+     *
+     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+     * the current thread; or
+     *
      * <li>The call spuriously (that is, for no reason) returns.
      * </ul>
-     * <p>This method does <em>not</em> report which of these caused the 
-     * method to return. Callers should re-check the conditions which caused 
-     * the thread to park in the first place. Callers may also determine, 
+     *
+     * <p>This method does <em>not</em> report which of these caused the
+     * method to return. Callers should re-check the conditions which caused
+     * the thread to park in the first place. Callers may also determine,
      * for example, the interrupt status of the thread upon return.
      */
     public static void park() {
@@ -120,21 +134,27 @@
     /**
      * Disables the current thread for thread scheduling purposes, for up to
      * the specified waiting time, unless the permit is available.
-     * <p>If the permit is available then it is consumed and the call returns
-     * immediately; otherwise 
-     * the current thread becomes disabled for thread scheduling 
-     * purposes and lies dormant until one of four things happens:
+     *
+     * <p>If the permit is available then it is consumed and the call
+     * returns immediately; otherwise the current thread becomes disabled
+     * for thread scheduling purposes and lies dormant until one of four
+     * things happens:
+     *
      * <ul>
-     * <li>Some other thread invokes <tt>unpark</tt> with the current thread 
-     * as the target; or
-     * <li>Some other thread {@link Thread#interrupt interrupts} the current
-     * thread; or
+     * <li>Some other thread invokes {@link #unpark unpark} with the
+     * current thread as the target; or
+     *
+     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+     * the current thread; or
+     *
      * <li>The specified waiting time elapses; or
+     *
      * <li>The call spuriously (that is, for no reason) returns.
      * </ul>
-     * <p>This method does <em>not</em> report which of these caused the 
-     * method to return. Callers should re-check the conditions which caused 
-     * the thread to park in the first place. Callers may also determine, 
+     *
+     * <p>This method does <em>not</em> report which of these caused the
+     * method to return. Callers should re-check the conditions which caused
+     * the thread to park in the first place. Callers may also determine,
      * for example, the interrupt status of the thread, or the elapsed time
      * upon return.
      *
@@ -142,37 +162,40 @@
      */
     public static void parkNanos(long nanos) {
         if (nanos > 0)
-            unsafe.park(false, nanos);   
+            unsafe.park(false, nanos);
     }
 
     /**
      * Disables the current thread for thread scheduling purposes, until
      * the specified deadline, unless the permit is available.
-     * <p>If the permit is available then it is consumed and the call returns
-     * immediately; otherwise 
-     * the current thread becomes disabled for thread scheduling 
-     * purposes and lies dormant until one of four things happens:
+     *
+     * <p>If the permit is available then it is consumed and the call
+     * returns immediately; otherwise the current thread becomes disabled
+     * for thread scheduling purposes and lies dormant until one of four
+     * things happens:
+     *
      * <ul>
-     * <li>Some other thread invokes <tt>unpark</tt> with the current thread 
-     * as the target; or
-     * <li>Some other thread {@link Thread#interrupt interrupts} the current
-     * thread; or
+     * <li>Some other thread invokes {@link #unpark unpark} with the
+     * current thread as the target; or
+     *
+     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+     * the current thread; or
+     *
      * <li>The specified deadline passes; or
+     *
      * <li>The call spuriously (that is, for no reason) returns.
      * </ul>
-     * <p>This method does <em>not</em> report which of these caused the 
-     * method to return. Callers should re-check the conditions which caused 
-     * the thread to park in the first place. Callers may also determine, 
+     *
+     * <p>This method does <em>not</em> report which of these caused the
+     * method to return. Callers should re-check the conditions which caused
+     * the thread to park in the first place. Callers may also determine,
      * for example, the interrupt status of the thread, or the current time
      * upon return.
      *
-     * @param deadline the absolute time, in milliseconds from the Epoch, to
-     * wait until
+     * @param deadline the absolute time, in milliseconds from the Epoch,
+     *        to wait until
      */
     public static void parkUntil(long deadline) {
-        unsafe.park(true, deadline);   
+        unsafe.park(true, deadline);
     }
-
 }
-
-
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/locks/ReadWriteLock.java b/libcore/concurrent/src/main/java/java/util/concurrent/locks/ReadWriteLock.java
index c7116d5..484f68d 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/locks/ReadWriteLock.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/locks/ReadWriteLock.java
@@ -12,11 +12,18 @@
  * The {@link #readLock read lock} may be held simultaneously by
  * multiple reader threads, so long as there are no writers.  The
  * {@link #writeLock write lock} is exclusive.
- * 
+ *
+ * <p>All <tt>ReadWriteLock</tt> implementations must guarantee that
+ * the memory synchronization effects of <tt>writeLock</tt> operations
+ * (as specified in the {@link Lock} interface) also hold with respect
+ * to the associated <tt>readLock</tt>. That is, a thread successfully
+ * acquiring the read lock will see all updates made upon previous
+ * release of the write lock.
+ *
  * <p>A read-write lock allows for a greater level of concurrency in
- * accessing shared data, than that permitted by a mutual exclusion lock.
+ * accessing shared data than that permitted by a mutual exclusion lock.
  * It exploits the fact that while only a single thread at a time (a
- * <em>writer</em> thread) can modify the shared data, in many cases any 
+ * <em>writer</em> thread) can modify the shared data, in many cases any
  * number of threads can concurrently read the data (hence <em>reader</em>
  * threads).
  * In theory, the increase in concurrency permitted by the use of a read-write
@@ -27,7 +34,7 @@
  *
  * <p>Whether or not a read-write lock will improve performance over the use
  * of a mutual exclusion lock depends on the frequency that the data is
- * read compared to being modified, the duration of the read and write 
+ * read compared to being modified, the duration of the read and write
  * operations, and the contention for the data - that is, the number of
  * threads that will try to read or write the data at the same time.
  * For example, a collection that is initially populated with data and
@@ -56,14 +63,14 @@
  * lengthy delays for a write if the readers are frequent and long-lived as
  * expected. Fair, or &quot;in-order&quot; implementations are also possible.
  *
- * <li>Determining whether readers that request the read lock while a 
+ * <li>Determining whether readers that request the read lock while a
  * reader is active and a writer is waiting, are granted the read lock.
  * Preference to the reader can delay the writer indefinitely, while
- * preference to the write can reduce the potential for concurrency.
+ * preference to the writer can reduce the potential for concurrency.
  *
  * <li>Determining whether the locks are reentrant: can a thread with the
- * write lock reacquire it? can it acquire a read lock while holding the
- * write lock? is the read lock itself reentrant?
+ * write lock reacquire it? Can it acquire a read lock while holding the
+ * write lock? Is the read lock itself reentrant?
  *
  * <li>Can the write lock be downgraded to a read lock without allowing
  * an intervening writer? Can a read lock be upgraded to a write lock,
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/locks/ReentrantLock.java b/libcore/concurrent/src/main/java/java/util/concurrent/locks/ReentrantLock.java
index bf3d653..bf2ac38 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/locks/ReentrantLock.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/locks/ReentrantLock.java
@@ -12,19 +12,19 @@
 /**
  * A reentrant mutual exclusion {@link Lock} with the same basic
  * behavior and semantics as the implicit monitor lock accessed using
- * <tt>synchronized</tt> methods and statements, but with extended
+ * {@code synchronized} methods and statements, but with extended
  * capabilities.
  *
- * <p> A <tt>ReentrantLock</tt> is <em>owned</em> by the thread last
+ * <p>A {@code ReentrantLock} is <em>owned</em> by the thread last
  * successfully locking, but not yet unlocking it. A thread invoking
- * <tt>lock</tt> will return, successfully acquiring the lock, when
+ * {@code lock} will return, successfully acquiring the lock, when
  * the lock is not owned by another thread. The method will return
  * immediately if the current thread already owns the lock. This can
  * be checked using methods {@link #isHeldByCurrentThread}, and {@link
- * #getHoldCount}.  
+ * #getHoldCount}.
  *
- * <p> The constructor for this class accepts an optional
- * <em>fairness</em> parameter.  When set <tt>true</tt>, under
+ * <p>The constructor for this class accepts an optional
+ * <em>fairness</em> parameter.  When set {@code true}, under
  * contention, locks favor granting access to the longest-waiting
  * thread.  Otherwise this lock does not guarantee any particular
  * access order.  Programs using fair locks accessed by many threads
@@ -36,9 +36,12 @@
  * fair lock may obtain it multiple times in succession while other
  * active threads are not progressing and not currently holding the
  * lock.
+ * Also note that the untimed {@link #tryLock() tryLock} method does not
+ * honor the fairness setting. It will succeed if the lock
+ * is available even if other threads are waiting.
  *
- * <p> It is recommended practice to <em>always</em> immediately
- * follow a call to <tt>lock</tt> with a <tt>try</tt> block, most
+ * <p>It is recommended practice to <em>always</em> immediately
+ * follow a call to {@code lock} with a {@code try} block, most
  * typically in a before/after construction such as:
  *
  * <pre>
@@ -46,7 +49,7 @@
  *   private final ReentrantLock lock = new ReentrantLock();
  *   // ...
  *
- *   public void m() { 
+ *   public void m() {
  *     lock.lock();  // block until condition holds
  *     try {
  *       // ... method body
@@ -58,21 +61,21 @@
  * </pre>
  *
  * <p>In addition to implementing the {@link Lock} interface, this
- * class defines methods <tt>isLocked</tt> and
- * <tt>getLockQueueLength</tt>, as well as some associated
- * <tt>protected</tt> access methods that may be useful for
+ * class defines methods {@code isLocked} and
+ * {@code getLockQueueLength}, as well as some associated
+ * {@code protected} access methods that may be useful for
  * instrumentation and monitoring.
  *
- * <p> Serialization of this class behaves in the same way as built-in
+ * <p>Serialization of this class behaves in the same way as built-in
  * locks: a deserialized lock is in the unlocked state, regardless of
  * its state when serialized.
  *
- * <p> This lock supports a maximum of 2147483648 recursive locks by
- * the same thread. 
+ * <p>This lock supports a maximum of 2147483647 recursive locks by
+ * the same thread. Attempts to exceed this limit result in
+ * {@link Error} throws from locking methods.
  *
  * @since 1.5
  * @author Doug Lea
- * 
  */
 public class ReentrantLock implements Lock, java.io.Serializable {
     private static final long serialVersionUID = 7373984872572414699L;
@@ -84,32 +87,34 @@
      * into fair and nonfair versions below. Uses AQS state to
      * represent the number of holds on the lock.
      */
-    static abstract class Sync  extends AbstractQueuedSynchronizer {
-        /** Current owner thread */
-        transient Thread owner;
+    static abstract class Sync extends AbstractQueuedSynchronizer {
+        private static final long serialVersionUID = -5179523762034025860L;
 
         /**
-         * Perform {@link Lock#lock}. The main reason for subclassing
+         * Performs {@link Lock#lock}. The main reason for subclassing
          * is to allow fast path for nonfair version.
          */
         abstract void lock();
 
-        /** 
-         * Perform non-fair tryLock.  tryAcquire is
+        /**
+         * Performs non-fair tryLock.  tryAcquire is
          * implemented in subclasses, but both need nonfair
-         * try for trylock method
+         * try for trylock method.
          */
-        final boolean nonfairTryAcquire(int acquires) { 
+        final boolean nonfairTryAcquire(int acquires) {
             final Thread current = Thread.currentThread();
             int c = getState();
             if (c == 0) {
                 if (compareAndSetState(0, acquires)) {
-                    owner = current;
+                    setExclusiveOwnerThread(current);
                     return true;
                 }
             }
-            else if (current == owner) {
-                setState(c+acquires);
+            else if (current == getExclusiveOwnerThread()) {
+                int nextc = c + acquires;
+                if (nextc < 0) // overflow
+                    throw new Error("Maximum lock count exceeded");
+                setState(nextc);
                 return true;
             }
             return false;
@@ -117,19 +122,21 @@
 
         protected final boolean tryRelease(int releases) {
             int c = getState() - releases;
-            if (Thread.currentThread() != owner)
+            if (Thread.currentThread() != getExclusiveOwnerThread())
                 throw new IllegalMonitorStateException();
             boolean free = false;
             if (c == 0) {
                 free = true;
-                owner = null;
+                setExclusiveOwnerThread(null);
             }
             setState(c);
             return free;
         }
 
         protected final boolean isHeldExclusively() {
-            return getState() != 0 && owner == Thread.currentThread();
+            // While we must in general read state before owner,
+            // we don't need to do so to check if current thread is owner
+            return getExclusiveOwnerThread() == Thread.currentThread();
         }
 
         final ConditionObject newCondition() {
@@ -139,23 +146,19 @@
         // Methods relayed from outer class
 
         final Thread getOwner() {
-            int c = getState();
-            Thread o = owner;
-            return (c == 0)? null : o;
+            return getState() == 0 ? null : getExclusiveOwnerThread();
         }
-        
+
         final int getHoldCount() {
-            int c = getState();
-            Thread o = owner;
-            return (o == Thread.currentThread())? c : 0;
+            return isHeldExclusively() ? getState() : 0;
         }
-        
+
         final boolean isLocked() {
             return getState() != 0;
         }
 
         /**
-         * Reconstitute this lock instance from a stream
+         * Reconstitutes this lock instance from a stream.
          * @param s the stream
          */
         private void readObject(java.io.ObjectInputStream s)
@@ -169,18 +172,20 @@
      * Sync object for non-fair locks
      */
     final static class NonfairSync extends Sync {
+        private static final long serialVersionUID = 7316153563782823691L;
+
         /**
-         * Perform lock.  Try immediate barge, backing up to normal
+         * Performs lock.  Try immediate barge, backing up to normal
          * acquire on failure.
          */
         final void lock() {
             if (compareAndSetState(0, 1))
-                owner = Thread.currentThread();
+                setExclusiveOwnerThread(Thread.currentThread());
             else
                 acquire(1);
         }
 
-        protected final boolean tryAcquire(int acquires) { 
+        protected final boolean tryAcquire(int acquires) {
             return nonfairTryAcquire(acquires);
         }
     }
@@ -188,28 +193,32 @@
     /**
      * Sync object for fair locks
      */
-    final static class FairSync  extends Sync {
-        final void lock() { 
-            acquire(1); 
+    final static class FairSync extends Sync {
+        private static final long serialVersionUID = -3000897897090466540L;
+
+        final void lock() {
+            acquire(1);
         }
 
         /**
          * Fair version of tryAcquire.  Don't grant access unless
          * recursive call or no waiters or is first.
          */
-        protected final boolean tryAcquire(int acquires) { 
+        protected final boolean tryAcquire(int acquires) {
             final Thread current = Thread.currentThread();
             int c = getState();
             if (c == 0) {
-                Thread first = getFirstQueuedThread();
-                if ((first == null || first == current) && 
+                if (!hasQueuedPredecessors() &&
                     compareAndSetState(0, acquires)) {
-                    owner = current;
+                    setExclusiveOwnerThread(current);
                     return true;
                 }
             }
-            else if (current == owner) {
-                setState(c+acquires);
+            else if (current == getExclusiveOwnerThread()) {
+                int nextc = c + acquires;
+                if (nextc < 0)
+                    throw new Error("Maximum lock count exceeded");
+                setState(nextc);
                 return true;
             }
             return false;
@@ -217,89 +226,88 @@
     }
 
     /**
-     * Creates an instance of <tt>ReentrantLock</tt>.
-     * This is equivalent to using <tt>ReentrantLock(false)</tt>.
+     * Creates an instance of {@code ReentrantLock}.
+     * This is equivalent to using {@code ReentrantLock(false)}.
      */
-    public ReentrantLock() { 
+    public ReentrantLock() {
         sync = new NonfairSync();
     }
 
     /**
-     * Creates an instance of <tt>ReentrantLock</tt> with the
+     * Creates an instance of {@code ReentrantLock} with the
      * given fairness policy.
-     * @param fair true if this lock will be fair; else false
+     *
+     * @param fair {@code true} if this lock should use a fair ordering policy
      */
-    public ReentrantLock(boolean fair) { 
+    public ReentrantLock(boolean fair) {
         sync = (fair)? new FairSync() : new NonfairSync();
     }
 
     /**
-     * Acquires the lock. 
+     * Acquires the lock.
      *
-     * <p>Acquires the lock if it is not held by another thread and returns 
+     * <p>Acquires the lock if it is not held by another thread and returns
      * immediately, setting the lock hold count to one.
      *
-     * <p>If the current thread
-     * already holds the lock then the hold count is incremented by one and
-     * the method returns immediately.
+     * <p>If the current thread already holds the lock then the hold
+     * count is incremented by one and the method returns immediately.
      *
      * <p>If the lock is held by another thread then the
-     * current thread becomes disabled for thread scheduling 
+     * current thread becomes disabled for thread scheduling
      * purposes and lies dormant until the lock has been acquired,
-     * at which time the lock hold count is set to one. 
+     * at which time the lock hold count is set to one.
      */
     public void lock() {
         sync.lock();
     }
 
     /**
-     * Acquires the lock unless the current thread is 
-     * {@link Thread#interrupt interrupted}.
+     * Acquires the lock unless the current thread is
+     * {@linkplain Thread#interrupt interrupted}.
      *
-     * <p>Acquires the lock if it is not held by another thread and returns 
+     * <p>Acquires the lock if it is not held by another thread and returns
      * immediately, setting the lock hold count to one.
      *
-     * <p>If the current thread already holds this lock then the hold count 
+     * <p>If the current thread already holds this lock then the hold count
      * is incremented by one and the method returns immediately.
      *
      * <p>If the lock is held by another thread then the
-     * current thread becomes disabled for thread scheduling 
+     * current thread becomes disabled for thread scheduling
      * purposes and lies dormant until one of two things happens:
      *
      * <ul>
      *
      * <li>The lock is acquired by the current thread; or
      *
-     * <li>Some other thread {@link Thread#interrupt interrupts} the current
-     * thread.
+     * <li>Some other thread {@linkplain Thread#interrupt interrupts} the
+     * current thread.
      *
      * </ul>
      *
-     * <p>If the lock is acquired by the current thread then the lock hold 
+     * <p>If the lock is acquired by the current thread then the lock hold
      * count is set to one.
      *
      * <p>If the current thread:
      *
      * <ul>
      *
-     * <li>has its interrupted status set on entry to this method; or 
+     * <li>has its interrupted status set on entry to this method; or
      *
-     * <li>is {@link Thread#interrupt interrupted} while acquiring 
+     * <li>is {@linkplain Thread#interrupt interrupted} while acquiring
      * the lock,
      *
      * </ul>
      *
-     * then {@link InterruptedException} is thrown and the current thread's 
-     * interrupted status is cleared. 
+     * then {@link InterruptedException} is thrown and the current thread's
+     * interrupted status is cleared.
      *
-     * <p>In this implementation, as this method is an explicit interruption 
-     * point, preference is 
-     * given to responding to the interrupt over normal or reentrant 
-     * acquisition of the lock.
+     * <p>In this implementation, as this method is an explicit
+     * interruption point, preference is given to responding to the
+     * interrupt over normal or reentrant acquisition of the lock.
      *
      * @throws InterruptedException if the current thread is interrupted
      */
-    public void lockInterruptibly() throws InterruptedException { 
+    public void lockInterruptibly() throws InterruptedException {
         sync.acquireInterruptibly(1);
     }
 
@@ -308,43 +316,42 @@
      * of invocation.
      *
      * <p>Acquires the lock if it is not held by another thread and
-     * returns immediately with the value <tt>true</tt>, setting the
+     * returns immediately with the value {@code true}, setting the
      * lock hold count to one. Even when this lock has been set to use a
-     * fair ordering policy, a call to <tt>tryLock()</tt> <em>will</em>
+     * fair ordering policy, a call to {@code tryLock()} <em>will</em>
      * immediately acquire the lock if it is available, whether or not
-     * other threads are currently waiting for the lock. 
-     * This &quot;barging&quot; behavior can be useful in certain 
+     * other threads are currently waiting for the lock.
+     * This &quot;barging&quot; behavior can be useful in certain
      * circumstances, even though it breaks fairness. If you want to honor
-     * the fairness setting for this lock, then use 
+     * the fairness setting for this lock, then use
      * {@link #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }
      * which is almost equivalent (it also detects interruption).
      *
-     * <p> If the current thread
-     * already holds this lock then the hold count is incremented by one and
-     * the method returns <tt>true</tt>.
+     * <p> If the current thread already holds this lock then the hold
+     * count is incremented by one and the method returns {@code true}.
      *
-     * <p>If the lock is held by another thread then this method will return 
-     * immediately with the value <tt>false</tt>.  
+     * <p>If the lock is held by another thread then this method will return
+     * immediately with the value {@code false}.
      *
-     * @return <tt>true</tt> if the lock was free and was acquired by the
-     * current thread, or the lock was already held by the current thread; and
-     * <tt>false</tt> otherwise.
+     * @return {@code true} if the lock was free and was acquired by the
+     *         current thread, or the lock was already held by the current
+     *         thread; and {@code false} otherwise
      */
     public boolean tryLock() {
         return sync.nonfairTryAcquire(1);
     }
 
     /**
-     * Acquires the lock if it is not held by another thread within the given 
-     * waiting time and the current thread has not been 
-     * {@link Thread#interrupt interrupted}.
+     * Acquires the lock if it is not held by another thread within the given
+     * waiting time and the current thread has not been
+     * {@linkplain Thread#interrupt interrupted}.
      *
-     * <p>Acquires the lock if it is not held by another thread and returns 
-     * immediately with the value <tt>true</tt>, setting the lock hold count 
+     * <p>Acquires the lock if it is not held by another thread and returns
+     * immediately with the value {@code true}, setting the lock hold count
      * to one. If this lock has been set to use a fair ordering policy then
      * an available lock <em>will not</em> be acquired if any other threads
      * are waiting for the lock. This is in contrast to the {@link #tryLock()}
-     * method. If you want a timed <tt>tryLock</tt> that does permit barging on
+     * method. If you want a timed {@code tryLock} that does permit barging on
      * a fair lock then combine the timed and un-timed forms together:
      *
      * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
@@ -352,60 +359,56 @@
      *
      * <p>If the current thread
      * already holds this lock then the hold count is incremented by one and
-     * the method returns <tt>true</tt>.
+     * the method returns {@code true}.
      *
      * <p>If the lock is held by another thread then the
-     * current thread becomes disabled for thread scheduling 
+     * current thread becomes disabled for thread scheduling
      * purposes and lies dormant until one of three things happens:
      *
      * <ul>
      *
      * <li>The lock is acquired by the current thread; or
      *
-     * <li>Some other thread {@link Thread#interrupt interrupts} the current
-     * thread; or
+     * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+     * the current thread; or
      *
      * <li>The specified waiting time elapses
      *
      * </ul>
      *
-     * <p>If the lock is acquired then the value <tt>true</tt> is returned and
+     * <p>If the lock is acquired then the value {@code true} is returned and
      * the lock hold count is set to one.
      *
      * <p>If the current thread:
      *
      * <ul>
      *
-     * <li>has its interrupted status set on entry to this method; or 
+     * <li>has its interrupted status set on entry to this method; or
      *
-     * <li>is {@link Thread#interrupt interrupted} while acquiring
-     * the lock,
+     * <li>is {@linkplain Thread#interrupt interrupted} while
+     * acquiring the lock,
      *
      * </ul>
-     * then {@link InterruptedException} is thrown and the current thread's 
-     * interrupted status is cleared. 
+     * then {@link InterruptedException} is thrown and the current thread's
+     * interrupted status is cleared.
      *
-     * <p>If the specified waiting time elapses then the value <tt>false</tt>
-     * is returned.
-     * If the time is 
-     * less than or equal to zero, the method will not wait at all.
+     * <p>If the specified waiting time elapses then the value {@code false}
+     * is returned.  If the time is less than or equal to zero, the method
+     * will not wait at all.
      *
-     * <p>In this implementation, as this method is an explicit interruption 
-     * point, preference is 
-     * given to responding to the interrupt over normal or reentrant 
-     * acquisition of the lock, and over reporting the elapse of the waiting
-     * time.
+     * <p>In this implementation, as this method is an explicit
+     * interruption point, preference is given to responding to the
+     * interrupt over normal or reentrant acquisition of the lock, and
+     * over reporting the elapse of the waiting time.
      *
      * @param timeout the time to wait for the lock
      * @param unit the time unit of the timeout argument
-     *
-     * @return <tt>true</tt> if the lock was free and was acquired by the
-     * current thread, or the lock was already held by the current thread; and
-     * <tt>false</tt> if the waiting time elapsed before the lock could be 
-     * acquired.
-     *
+     * @return {@code true} if the lock was free and was acquired by the
+     *         current thread, or the lock was already held by the current
+     *         thread; and {@code false} if the waiting time elapsed before
+     *         the lock could be acquired
      * @throws InterruptedException if the current thread is interrupted
-     * @throws NullPointerException if unit is null
+     * @throws NullPointerException if the time unit is null
      *
      */
     public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
@@ -413,22 +416,22 @@
     }
 
     /**
-     * Attempts to release this lock.  
+     * Attempts to release this lock.
      *
-     * <p>If the current thread is the
-     * holder of this lock then the hold count is decremented. If the
-     * hold count is now zero then the lock is released.  If the
-     * current thread is not the holder of this lock then {@link
-     * IllegalMonitorStateException} is thrown.
+     * <p>If the current thread is the holder of this lock then the hold
+     * count is decremented.  If the hold count is now zero then the lock
+     * is released.  If the current thread is not the holder of this
+     * lock then {@link IllegalMonitorStateException} is thrown.
+     *
      * @throws IllegalMonitorStateException if the current thread does not
-     * hold this lock.
+     *         hold this lock
      */
     public void unlock() {
         sync.release(1);
     }
 
     /**
-     * Returns a {@link Condition} instance for use with this 
+     * Returns a {@link Condition} instance for use with this
      * {@link Lock} instance.
      *
      * <p>The returned {@link Condition} instance supports the same
@@ -440,28 +443,28 @@
      * <ul>
      *
      * <li>If this lock is not held when any of the {@link Condition}
-     * {@link Condition#await() waiting} or {@link Condition#signal
-     * signalling} methods are called, then an {@link
+     * {@linkplain Condition#await() waiting} or {@linkplain
+     * Condition#signal signalling} methods are called, then an {@link
      * IllegalMonitorStateException} is thrown.
      *
-     * <li>When the condition {@link Condition#await() waiting}
+     * <li>When the condition {@linkplain Condition#await() waiting}
      * methods are called the lock is released and, before they
      * return, the lock is reacquired and the lock hold count restored
      * to what it was when the method was called.
      *
-     * <li>If a thread is {@link Thread#interrupt interrupted} while
-     * waiting then the wait will terminate, an {@link
+     * <li>If a thread is {@linkplain Thread#interrupt interrupted}
+     * while waiting then the wait will terminate, an {@link
      * InterruptedException} will be thrown, and the thread's
      * interrupted status will be cleared.
      *
-     * <li> Waiting threads are signalled in FIFO order
+     * <li> Waiting threads are signalled in FIFO order.
      *
      * <li>The ordering of lock reacquisition for threads returning
      * from waiting methods is the same as for threads initially
      * acquiring the lock, which is in the default case not specified,
      * but for <em>fair</em> locks favors those threads that have been
      * waiting the longest.
-     * 
+     *
      * </ul>
      *
      * @return the Condition object
@@ -473,7 +476,7 @@
     /**
      * Queries the number of holds on this lock by the current thread.
      *
-     * <p>A thread has a hold on a lock for each lock action that is not 
+     * <p>A thread has a hold on a lock for each lock action that is not
      * matched by an unlock action.
      *
      * <p>The hold count information is typically only used for testing and
@@ -484,8 +487,8 @@
      * <pre>
      * class X {
      *   ReentrantLock lock = new ReentrantLock();
-     *   // ...     
-     *   public void m() { 
+     *   // ...
+     *   public void m() {
      *     assert lock.getHoldCount() == 0;
      *     lock.lock();
      *     try {
@@ -498,7 +501,7 @@
      * </pre>
      *
      * @return the number of holds on this lock by the current thread,
-     * or zero if this lock is not held by the current thread.
+     *         or zero if this lock is not held by the current thread
      */
     public int getHoldCount() {
         return sync.getHoldCount();
@@ -517,7 +520,7 @@
      *   ReentrantLock lock = new ReentrantLock();
      *   // ...
      *
-     *   public void m() { 
+     *   public void m() {
      *       assert lock.isHeldByCurrentThread();
      *       // ... method body
      *   }
@@ -532,7 +535,7 @@
      *   ReentrantLock lock = new ReentrantLock();
      *   // ...
      *
-     *   public void m() { 
+     *   public void m() {
      *       assert !lock.isHeldByCurrentThread();
      *       lock.lock();
      *       try {
@@ -543,8 +546,9 @@
      *   }
      * }
      * </pre>
-     * @return <tt>true</tt> if current thread holds this lock and 
-     * <tt>false</tt> otherwise.
+     *
+     * @return {@code true} if current thread holds this lock and
+     *         {@code false} otherwise
      */
     public boolean isHeldByCurrentThread() {
         return sync.isHeldExclusively();
@@ -552,47 +556,53 @@
 
     /**
      * Queries if this lock is held by any thread. This method is
-     * designed for use in monitoring of the system state, 
+     * designed for use in monitoring of the system state,
      * not for synchronization control.
-     * @return <tt>true</tt> if any thread holds this lock and 
-     * <tt>false</tt> otherwise.
+     *
+     * @return {@code true} if any thread holds this lock and
+     *         {@code false} otherwise
      */
     public boolean isLocked() {
         return sync.isLocked();
     }
 
     /**
-     * Returns true if this lock has fairness set true.
-     * @return true if this lock has fairness set true.
+     * Returns {@code true} if this lock has fairness set true.
+     *
+     * @return {@code true} if this lock has fairness set true
      */
     public final boolean isFair() {
         return sync instanceof FairSync;
     }
 
     /**
-     * Returns the thread that currently owns the exclusive lock, or
-     * <tt>null</tt> if not owned. Note that the owner may be
-     * momentarily <tt>null</tt> even if there are threads trying to
-     * acquire the lock but have not yet done so.  This method is
-     * designed to facilitate construction of subclasses that provide
-     * more extensive lock monitoring facilities.
-     * @return the owner, or <tt>null</tt> if not owned.
+     * Returns the thread that currently owns this lock, or
+     * {@code null} if not owned. When this method is called by a
+     * thread that is not the owner, the return value reflects a
+     * best-effort approximation of current lock status. For example,
+     * the owner may be momentarily {@code null} even if there are
+     * threads trying to acquire the lock but have not yet done so.
+     * This method is designed to facilitate construction of
+     * subclasses that provide more extensive lock monitoring
+     * facilities.
+     *
+     * @return the owner, or {@code null} if not owned
      */
     protected Thread getOwner() {
         return sync.getOwner();
     }
 
     /**
-     * Queries whether any threads are waiting to acquire. Note that
-     * because cancellations may occur at any time, a <tt>true</tt>
+     * Queries whether any threads are waiting to acquire this lock. Note that
+     * because cancellations may occur at any time, a {@code true}
      * return does not guarantee that any other thread will ever
-     * acquire.  This method is designed primarily for use in
+     * acquire this lock.  This method is designed primarily for use in
      * monitoring of the system state.
      *
-     * @return true if there may be other threads waiting to acquire
-     * the lock.
+     * @return {@code true} if there may be other threads waiting to
+     *         acquire the lock
      */
-    public final boolean hasQueuedThreads() { 
+    public final boolean hasQueuedThreads() {
         return sync.hasQueuedThreads();
     }
 
@@ -600,26 +610,27 @@
     /**
      * Queries whether the given thread is waiting to acquire this
      * lock. Note that because cancellations may occur at any time, a
-     * <tt>true</tt> return does not guarantee that this thread
-     * will ever acquire.  This method is designed primarily for use
+     * {@code true} return does not guarantee that this thread
+     * will ever acquire this lock.  This method is designed primarily for use
      * in monitoring of the system state.
      *
      * @param thread the thread
-     * @return true if the given thread is queued waiting for this lock.
-     * @throws NullPointerException if thread is null
+     * @return {@code true} if the given thread is queued waiting for this lock
+     * @throws NullPointerException if the thread is null
      */
-    public final boolean hasQueuedThread(Thread thread) { 
+    public final boolean hasQueuedThread(Thread thread) {
         return sync.isQueued(thread);
     }
 
 
     /**
      * Returns an estimate of the number of threads waiting to
-     * acquire.  The value is only an estimate because the number of
+     * acquire this lock.  The value is only an estimate because the number of
      * threads may change dynamically while this method traverses
      * internal data structures.  This method is designed for use in
      * monitoring of the system state, not for synchronization
      * control.
+     *
      * @return the estimated number of threads waiting for this lock
      */
     public final int getQueueLength() {
@@ -628,12 +639,13 @@
 
     /**
      * Returns a collection containing threads that may be waiting to
-     * acquire.  Because the actual set of threads may change
+     * acquire this lock.  Because the actual set of threads may change
      * dynamically while constructing this result, the returned
      * collection is only a best-effort estimate.  The elements of the
      * returned collection are in no particular order.  This method is
      * designed to facilitate construction of subclasses that provide
      * more extensive monitoring facilities.
+     *
      * @return the collection of threads
      */
     protected Collection<Thread> getQueuedThreads() {
@@ -643,18 +655,18 @@
     /**
      * Queries whether any threads are waiting on the given condition
      * associated with this lock. Note that because timeouts and
-     * interrupts may occur at any time, a <tt>true</tt> return does
-     * not guarantee that a future <tt>signal</tt> will awaken any
+     * interrupts may occur at any time, a {@code true} return does
+     * not guarantee that a future {@code signal} will awaken any
      * threads.  This method is designed primarily for use in
      * monitoring of the system state.
+     *
      * @param condition the condition
-     * @return <tt>true</tt> if there are any waiting threads.
-     * @throws IllegalMonitorStateException if this lock 
-     * is not held
+     * @return {@code true} if there are any waiting threads
+     * @throws IllegalMonitorStateException if this lock is not held
      * @throws IllegalArgumentException if the given condition is
-     * not associated with this lock
-     * @throws NullPointerException if condition null
-     */ 
+     *         not associated with this lock
+     * @throws NullPointerException if the condition is null
+     */
     public boolean hasWaiters(Condition condition) {
         if (condition == null)
             throw new NullPointerException();
@@ -670,14 +682,14 @@
      * serves only as an upper bound on the actual number of waiters.
      * This method is designed for use in monitoring of the system
      * state, not for synchronization control.
+     *
      * @param condition the condition
-     * @return the estimated number of waiting threads.
-     * @throws IllegalMonitorStateException if this lock 
-     * is not held
+     * @return the estimated number of waiting threads
+     * @throws IllegalMonitorStateException if this lock is not held
      * @throws IllegalArgumentException if the given condition is
-     * not associated with this lock
-     * @throws NullPointerException if condition null
-     */ 
+     *         not associated with this lock
+     * @throws NullPointerException if the condition is null
+     */
     public int getWaitQueueLength(Condition condition) {
         if (condition == null)
             throw new NullPointerException();
@@ -695,13 +707,13 @@
      * are in no particular order.  This method is designed to
      * facilitate construction of subclasses that provide more
      * extensive condition monitoring facilities.
+     *
      * @param condition the condition
      * @return the collection of threads
-     * @throws IllegalMonitorStateException if this lock 
-     * is not held
+     * @throws IllegalMonitorStateException if this lock is not held
      * @throws IllegalArgumentException if the given condition is
-     * not associated with this lock
-     * @throws NullPointerException if condition null
+     *         not associated with this lock
+     * @throws NullPointerException if the condition is null
      */
     protected Collection<Thread> getWaitingThreads(Condition condition) {
         if (condition == null)
@@ -712,16 +724,17 @@
     }
 
     /**
-     * Returns a string identifying this lock, as well as its lock
-     * state.  The state, in brackets, includes either the String
-     * &quot;Unlocked&quot; or the String &quot;Locked by&quot;
-     * followed by the {@link Thread#getName} of the owning thread.
-     * @return a string identifying this lock, as well as its lock state.
+     * Returns a string identifying this lock, as well as its lock state.
+     * The state, in brackets, includes either the String {@code "Unlocked"}
+     * or the String {@code "Locked by"} followed by the
+     * {@linkplain Thread#getName name} of the owning thread.
+     *
+     * @return a string identifying this lock, as well as its lock state
      */
     public String toString() {
-        Thread owner = sync.getOwner();
-        return super.toString() + ((owner == null) ?
+        Thread o = sync.getOwner();
+        return super.toString() + ((o == null) ?
                                    "[Unlocked]" :
-                                   "[Locked by thread " + owner.getName() + "]");
+                                   "[Locked by thread " + o.getName() + "]");
     }
 }
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java b/libcore/concurrent/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java
index 95fc7af..c923944 100644
--- a/libcore/concurrent/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java
@@ -19,32 +19,60 @@
  *
  * <p> This class does not impose a reader or writer preference
  * ordering for lock access.  However, it does support an optional
- * <em>fairness</em> policy.  When constructed as fair, threads
- * contend for entry using an approximately arrival-order policy. When
- * the write lock is released either the longest-waiting single writer
- * will be assigned the write lock, or if there is a reader waiting
- * longer than any writer, the set of readers will be assigned the
- * read lock.  When constructed as non-fair, the order of entry to the
- * lock need not be in arrival order.  In either case, if readers are
- * active and a writer enters the lock then no subsequent readers will
- * be granted the read lock until after that writer has acquired and
- * released the write lock.
- * 
+ * <em>fairness</em> policy.
+ *
+ * <dl>
+ * <dt><b><i>Non-fair mode (default)</i></b>
+ * <dd>When constructed as non-fair (the default), the order of entry
+ * to the read and write lock is unspecified, subject to reentrancy
+ * constraints.  A nonfair lock that is continuously contended may
+ * indefinitely postpone one or more reader or writer threads, but
+ * will normally have higher throughput than a fair lock.
+ * <p>
+ *
+ * <dt><b><i>Fair mode</i></b>
+ * <dd> When constructed as fair, threads contend for entry using an
+ * approximately arrival-order policy. When the currently held lock
+ * is released either the longest-waiting single writer thread will
+ * be assigned the write lock, or if there is a group of reader threads
+ * waiting longer than all waiting writer threads, that group will be
+ * assigned the read lock.
+ *
+ * <p>A thread that tries to acquire a fair read lock (non-reentrantly)
+ * will block if either the write lock is held, or there is a waiting
+ * writer thread. The thread will not acquire the read lock until
+ * after the oldest currently waiting writer thread has acquired and
+ * released the write lock. Of course, if a waiting writer abandons
+ * its wait, leaving one or more reader threads as the longest waiters
+ * in the queue with the write lock free, then those readers will be
+ * assigned the read lock.
+ *
+ * <p>A thread that tries to acquire a fair write lock (non-reentrantly)
+ * will block unless both the read lock and write lock are free (which
+ * implies there are no waiting threads).  (Note that the non-blocking
+ * {@link ReadLock#tryLock()} and {@link WriteLock#tryLock()} methods
+ * do not honor this fair setting and will acquire the lock if it is
+ * possible, regardless of waiting threads.)
+ * <p>
+ * </dl>
+ *
  * <li><b>Reentrancy</b>
+ *
  * <p>This lock allows both readers and writers to reacquire read or
- * write locks in the style of a {@link ReentrantLock}. Readers are not
- * allowed until all write locks held by the writing thread have been
- * released.  
- * <p>Additionally, a writer can acquire the read lock - but not vice-versa.
- * Among other applications, reentrancy can be useful when
- * write locks are held during calls or callbacks to methods that
- * perform reads under read locks. 
- * If a reader tries to acquire the write lock it will never succeed.
- * 
+ * write locks in the style of a {@link ReentrantLock}. Non-reentrant
+ * readers are not allowed until all write locks held by the writing
+ * thread have been released.
+ *
+ * <p>Additionally, a writer can acquire the read lock, but not
+ * vice-versa.  Among other applications, reentrancy can be useful
+ * when write locks are held during calls or callbacks to methods that
+ * perform reads under read locks.  If a reader tries to acquire the
+ * write lock it will never succeed.
+ *
  * <li><b>Lock downgrading</b>
  * <p>Reentrancy also allows downgrading from the write lock to a read lock,
  * by acquiring the write lock, then the read lock and then releasing the
- * write lock. However, upgrading from a read lock to the write lock, is
+ * write lock. However, upgrading from a read lock to the write lock is
  * <b>not</b> possible.
  *
  * <li><b>Interruption of lock acquisition</b>
@@ -53,96 +81,105 @@
  *
  * <li><b>{@link Condition} support</b>
  * <p>The write lock provides a {@link Condition} implementation that
- * behaves in the same way, with respect to the write lock, as the 
+ * behaves in the same way, with respect to the write lock, as the
  * {@link Condition} implementation provided by
  * {@link ReentrantLock#newCondition} does for {@link ReentrantLock}.
  * This {@link Condition} can, of course, only be used with the write lock.
+ *
  * <p>The read lock does not support a {@link Condition} and
- * <tt>readLock().newCondition()</tt> throws 
- * <tt>UnsupportedOperationException</tt>.
+ * {@code readLock().newCondition()} throws
+ * {@code UnsupportedOperationException}.
  *
  * <li><b>Instrumentation</b>
- * <P> This class supports methods to determine whether locks
+ * <p>This class supports methods to determine whether locks
  * are held or contended. These methods are designed for monitoring
  * system state, not for synchronization control.
  * </ul>
  *
- * <p> Serialization of this class behaves in the same way as built-in
+ * <p>Serialization of this class behaves in the same way as built-in
  * locks: a deserialized lock is in the unlocked state, regardless of
  * its state when serialized.
  *
- * <p><b>Sample usages</b>. Here is a code sketch showing how to exploit
- * reentrancy to perform lock downgrading after updating a cache (exception
- * handling is elided for simplicity):
- * <pre>
+ * <p><b>Sample usages</b>. Here is a code sketch showing how to perform
+ * lock downgrading after updating a cache (exception handling is
+ * particularly tricky when handling multiple locks in a non-nested
+ * fashion):
+ *
+ * <pre> {@code
  * class CachedData {
  *   Object data;
  *   volatile boolean cacheValid;
- *   ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
+ *   final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
  *
  *   void processCachedData() {
  *     rwl.readLock().lock();
  *     if (!cacheValid) {
- *        // upgrade lock manually
- *        rwl.readLock().unlock();   // must unlock first to obtain writelock
+ *        // Must release read lock before acquiring write lock
+ *        rwl.readLock().unlock();
  *        rwl.writeLock().lock();
- *        if (!cacheValid) { // recheck
- *          data = ...
- *          cacheValid = true;
+ *        try {
+ *          // Recheck state because another thread might have
+ *          // acquired write lock and changed state before we did.
+ *          if (!cacheValid) {
+ *            data = ...
+ *            cacheValid = true;
+ *          }
+ *          // Downgrade by acquiring read lock before releasing write lock
+ *          rwl.readLock().lock();
+ *        } finally  {
+ *          rwl.writeLock().unlock(); // Unlock write, still hold read
  *        }
- *        // downgrade lock
- *        rwl.readLock().lock();  // reacquire read without giving up write lock
- *        rwl.writeLock().unlock(); // unlock write, still hold read
  *     }
  *
- *     use(data);
- *     rwl.readLock().unlock();
+ *     try {
+ *       use(data);
+ *     } finally {
+ *       rwl.readLock().unlock();
+ *     }
  *   }
- * }
- * </pre>
+ * }}</pre>
  *
  * ReentrantReadWriteLocks can be used to improve concurrency in some
  * uses of some kinds of Collections. This is typically worthwhile
  * only when the collections are expected to be large, accessed by
  * more reader threads than writer threads, and entail operations with
  * overhead that outweighs synchronization overhead. For example, here
- * is a class using a TreeMap that is expected to be large and 
+ * is a class using a TreeMap that is expected to be large and
  * concurrently accessed.
  *
- * <pre>
+ * <pre>{@code
  * class RWDictionary {
- *    private final Map&lt;String, Data&gt;  m = new TreeMap&lt;String, Data&gt;();
+ *    private final Map<String, Data> m = new TreeMap<String, Data>();
  *    private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
  *    private final Lock r = rwl.readLock();
  *    private final Lock w = rwl.writeLock();
  *
  *    public Data get(String key) {
- *        r.lock(); try { return m.get(key); } finally { r.unlock(); }
+ *        r.lock();
+ *        try { return m.get(key); }
+ *        finally { r.unlock(); }
  *    }
  *    public String[] allKeys() {
- *        r.lock(); try { return m.keySet().toArray(); } finally { r.unlock(); }
+ *        r.lock();
+ *        try { return m.keySet().toArray(); }
+ *        finally { r.unlock(); }
  *    }
  *    public Data put(String key, Data value) {
- *        w.lock(); try { return m.put(key, value); } finally { w.unlock(); }
+ *        w.lock();
+ *        try { return m.put(key, value); }
+ *        finally { w.unlock(); }
  *    }
  *    public void clear() {
- *        w.lock(); try { m.clear(); } finally { w.unlock(); }
+ *        w.lock();
+ *        try { m.clear(); }
+ *        finally { w.unlock(); }
  *    }
- * }
- * </pre>
- * 
+ * }}</pre>
  *
  * <h3>Implementation Notes</h3>
  *
- * <p>A reentrant write lock intrinsically defines an owner and can
- * only be released by the thread that acquired it.  In contrast, in
- * this implementation, the read lock has no concept of ownership, and
- * there is no requirement that the thread releasing a read lock is
- * the same as the one that acquired it.  However, this property is
- * not guaranteed to hold in future implementations of this class.
- *
- * <p> This lock supports a maximum of 65536 recursive write locks
- * and 65536 read locks. Attempts to exceed these limits result in
+ * <p>This lock supports a maximum of 65535 recursive write locks
+ * and 65535 read locks. Attempts to exceed these limits result in
  * {@link Error} throws from locking methods.
  *
  * @since 1.5
@@ -156,26 +193,24 @@
     /** Inner class providing writelock */
     private final ReentrantReadWriteLock.WriteLock writerLock;
     /** Performs all synchronization mechanics */
-    private final Sync sync;
+    final Sync sync;
 
     /**
-     * Creates a new <tt>ReentrantReadWriteLock</tt> with
-     * default ordering properties.
+     * Creates a new {@code ReentrantReadWriteLock} with
+     * default (nonfair) ordering properties.
      */
     public ReentrantReadWriteLock() {
-        sync = new NonfairSync();
-        readerLock = new ReadLock(this);
-        writerLock = new WriteLock(this);
+        this(false);
     }
 
     /**
-     * Creates a new <tt>ReentrantReadWriteLock</tt> with
+     * Creates a new {@code ReentrantReadWriteLock} with
      * the given fairness policy.
      *
-     * @param fair true if this lock should use a fair ordering policy
+     * @param fair {@code true} if this lock should use a fair ordering policy
      */
     public ReentrantReadWriteLock(boolean fair) {
-        sync = (fair)? new FairSync() : new NonfairSync();
+        sync = fair ? new FairSync() : new NonfairSync();
         readerLock = new ReadLock(this);
         writerLock = new WriteLock(this);
     }
@@ -183,129 +218,409 @@
     public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }
     public ReentrantReadWriteLock.ReadLock  readLock()  { return readerLock; }
 
-    /* 
-     * Read vs write count extraction constants and functions.
-     * Lock state is logically divided into two shorts: The lower
-     * one representing the exclusive (writer) lock hold count,
-     * and the upper the shared (reader) hold count.
-     */
-    
-    static final int SHARED_SHIFT   = 16;
-    static final int SHARED_UNIT    = (1 << SHARED_SHIFT);
-    static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
-    
-    /** Returns the number of shared holds represented in count  */
-    static int sharedCount(int c)    { return c >>> SHARED_SHIFT; }
-    /** Returns the number of exclusive holds represented in count  */
-    static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
-
-    /** 
+    /**
      * Synchronization implementation for ReentrantReadWriteLock.
      * Subclassed into fair and nonfair versions.
      */
-    abstract static class Sync extends AbstractQueuedSynchronizer {
-        /** Current (exclusive) owner thread */
-        transient Thread owner;
+    static abstract class Sync extends AbstractQueuedSynchronizer {
+        private static final long serialVersionUID = 6317671515068378041L;
+
+        /*
+         * Read vs write count extraction constants and functions.
+         * Lock state is logically divided into two unsigned shorts:
+         * The lower one representing the exclusive (writer) lock hold count,
+         * and the upper the shared (reader) hold count.
+         */
+
+        static final int SHARED_SHIFT   = 16;
+        static final int SHARED_UNIT    = (1 << SHARED_SHIFT);
+        static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;
+        static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
+
+        /** Returns the number of shared holds represented in count  */
+        static int sharedCount(int c)    { return c >>> SHARED_SHIFT; }
+        /** Returns the number of exclusive holds represented in count  */
+        static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
 
         /**
-         * Perform write lock. Allows fast path in non-fair version.
+         * A counter for per-thread read hold counts.
+         * Maintained as a ThreadLocal; cached in cachedHoldCounter
          */
-        abstract void wlock();
-
-        /** 
-         * Perform non-fair tryLock for write.  tryAcquire is
-         * implemented in subclasses, but both versions need nonfair
-         * try for trylock method
-         */
-        final boolean nonfairTryAcquire(int acquires) {
-            // mask out readlocks if called from condition methods
-            acquires = exclusiveCount(acquires);
-            Thread current = Thread.currentThread();
-            int c = getState();
-            int w = exclusiveCount(c);
-            if (w + acquires >= SHARED_UNIT)
-                throw new Error("Maximum lock count exceeded");
-            if (c != 0 && (w == 0 || current != owner))
-                return false;
-            if (!compareAndSetState(c, c + acquires)) 
-                return false;
-            owner = current;
-            return true;
+        static final class HoldCounter {
+            int count = 0;
+            // Use id, not reference, to avoid garbage retention
+            final long tid = Thread.currentThread().getId();
         }
 
-        /** 
-         * Perform nonfair tryLock for read. 
+        /**
+         * ThreadLocal subclass. Easiest to explicitly define for sake
+         * of deserialization mechanics.
          */
-        final int nonfairTryAcquireShared(int acquires) {
-            for (;;) {
-                int c = getState();
-                int nextc = c + (acquires << SHARED_SHIFT);
-                if (nextc < c)
-                    throw new Error("Maximum lock count exceeded");
-                if (exclusiveCount(c) != 0 && 
-                    owner != Thread.currentThread())
-                    return -1;
-                if (compareAndSetState(c, nextc)) 
-                    return 1;
-                // Recheck count if lost CAS
+        static final class ThreadLocalHoldCounter
+            extends ThreadLocal<HoldCounter> {
+            public HoldCounter initialValue() {
+                return new HoldCounter();
             }
         }
 
+        /**
+         * The number of reentrant read locks held by current thread.
+         * Initialized only in constructor and readObject.
+         * Removed whenever a thread's read hold count drops to 0.
+         */
+        private transient ThreadLocalHoldCounter readHolds;
+
+        /**
+         * The hold count of the last thread to successfully acquire
+         * readLock. This saves ThreadLocal lookup in the common case
+         * where the next thread to release is the last one to
+         * acquire. This is non-volatile since it is just used
+         * as a heuristic, and would be great for threads to cache.
+         *
+         * <p>Can outlive the Thread for which it is caching the read
+         * hold count, but avoids garbage retention by not retaining a
+         * reference to the Thread.
+         *
+         * <p>Accessed via a benign data race; relies on the memory
+         * model's final field and out-of-thin-air guarantees.
+         */
+        private transient HoldCounter cachedHoldCounter;
+
+        /**
+         * firstReader is the first thread to have acquired the read lock.
+         * firstReaderHoldCount is firstReader's hold count.
+         *
+         * <p>More precisely, firstReader is the unique thread that last
+         * changed the shared count from 0 to 1, and has not released the
+         * read lock since then; null if there is no such thread.
+         *
+         * <p>Cannot cause garbage retention unless the thread terminated
+         * without relinquishing its read locks, since tryReleaseShared
+         * sets it to null.
+         *
+         * <p>Accessed via a benign data race; relies on the memory
+         * model's out-of-thin-air guarantees for references.
+         *
+         * <p>This allows tracking of read holds for uncontended read
+         * locks to be very cheap.
+         */
+        private transient Thread firstReader = null;
+        private transient int firstReaderHoldCount;
+
+        Sync() {
+            readHolds = new ThreadLocalHoldCounter();
+            setState(getState()); // ensures visibility of readHolds
+        }
+
+        /*
+         * Acquires and releases use the same code for fair and
+         * nonfair locks, but differ in whether/how they allow barging
+         * when queues are non-empty.
+         */
+
+        /**
+         * Returns true if the current thread, when trying to acquire
+         * the read lock, and otherwise eligible to do so, should block
+         * because of policy for overtaking other waiting threads.
+         */
+        abstract boolean readerShouldBlock();
+
+        /**
+         * Returns true if the current thread, when trying to acquire
+         * the write lock, and otherwise eligible to do so, should block
+         * because of policy for overtaking other waiting threads.
+         */
+        abstract boolean writerShouldBlock();
+
+        /*
+         * Note that tryRelease and tryAcquire can be called by
+         * Conditions. So it is possible that their arguments contain
+         * both read and write holds that are all released during a
+         * condition wait and re-established in tryAcquire.
+         */
+
         protected final boolean tryRelease(int releases) {
-            Thread current = Thread.currentThread();
-            int c = getState();
-            if (owner != current)
+            if (!isHeldExclusively())
                 throw new IllegalMonitorStateException();
-            int nextc = c - releases;
-            boolean free = false;
-            if (exclusiveCount(c) == releases) {
-                free = true;
-                owner = null;
-            }
+            int nextc = getState() - releases;
+            boolean free = exclusiveCount(nextc) == 0;
+            if (free)
+                setExclusiveOwnerThread(null);
             setState(nextc);
             return free;
         }
 
-        protected final boolean tryReleaseShared(int releases) {
+        protected final boolean tryAcquire(int acquires) {
+            /*
+             * Walkthrough:
+             * 1. If read count nonzero or write count nonzero
+             *    and owner is a different thread, fail.
+             * 2. If count would saturate, fail. (This can only
+             *    happen if count is already nonzero.)
+             * 3. Otherwise, this thread is eligible for lock if
+             *    it is either a reentrant acquire or
+             *    queue policy allows it. If so, update state
+             *    and set owner.
+             */
+            Thread current = Thread.currentThread();
+            int c = getState();
+            int w = exclusiveCount(c);
+            if (c != 0) {
+                // (Note: if c != 0 and w == 0 then shared count != 0)
+                if (w == 0 || current != getExclusiveOwnerThread())
+                    return false;
+                if (w + exclusiveCount(acquires) > MAX_COUNT)
+                    throw new Error("Maximum lock count exceeded");
+                // Reentrant acquire
+                setState(c + acquires);
+                return true;
+            }
+            if (writerShouldBlock() ||
+                !compareAndSetState(c, c + acquires))
+                return false;
+            setExclusiveOwnerThread(current);
+            return true;
+        }
+
+        protected final boolean tryReleaseShared(int unused) {
+            Thread current = Thread.currentThread();
+            if (firstReader == current) {
+                // assert firstReaderHoldCount > 0;
+                if (firstReaderHoldCount == 1)
+                    firstReader = null;
+                else
+                    firstReaderHoldCount--;
+            } else {
+                HoldCounter rh = cachedHoldCounter;
+                if (rh == null || rh.tid != current.getId())
+                    rh = readHolds.get();
+                int count = rh.count;
+                if (count <= 1) {
+                    readHolds.remove();
+                    if (count <= 0)
+                        throw unmatchedUnlockException();
+                }
+                --rh.count;
+            }
             for (;;) {
                 int c = getState();
-                int nextc = c - (releases << SHARED_SHIFT);
-                if (nextc < 0)
-                    throw new IllegalMonitorStateException();
-                if (compareAndSetState(c, nextc)) 
+                int nextc = c - SHARED_UNIT;
+                if (compareAndSetState(c, nextc))
+                    // Releasing the read lock has no effect on readers,
+                    // but it may allow waiting writers to proceed if
+                    // both read and write locks are now free.
                     return nextc == 0;
             }
         }
-    
+
+        private IllegalMonitorStateException unmatchedUnlockException() {
+            return new IllegalMonitorStateException(
+                "attempt to unlock read lock, not locked by current thread");
+        }
+
+        protected final int tryAcquireShared(int unused) {
+            /*
+             * Walkthrough:
+             * 1. If write lock held by another thread, fail.
+             * 2. Otherwise, this thread is eligible for
+             *    lock wrt state, so ask if it should block
+             *    because of queue policy. If not, try
+             *    to grant by CASing state and updating count.
+             *    Note that step does not check for reentrant
+             *    acquires, which is postponed to full version
+             *    to avoid having to check hold count in
+             *    the more typical non-reentrant case.
+             * 3. If step 2 fails either because thread
+             *    apparently not eligible or CAS fails or count
+             *    saturated, chain to version with full retry loop.
+             */
+            Thread current = Thread.currentThread();
+            int c = getState();
+            if (exclusiveCount(c) != 0 &&
+                getExclusiveOwnerThread() != current)
+                return -1;
+            int r = sharedCount(c);
+            if (!readerShouldBlock() &&
+                r < MAX_COUNT &&
+                compareAndSetState(c, c + SHARED_UNIT)) {
+                if (r == 0) {
+                    firstReader = current;
+                    firstReaderHoldCount = 1;
+                } else if (firstReader == current) {
+                    firstReaderHoldCount++;
+                } else {
+                    HoldCounter rh = cachedHoldCounter;
+                    if (rh == null || rh.tid != current.getId())
+                        cachedHoldCounter = rh = readHolds.get();
+                    else if (rh.count == 0)
+                        readHolds.set(rh);
+                    rh.count++;
+                }
+                return 1;
+            }
+            return fullTryAcquireShared(current);
+        }
+
+        /**
+         * Full version of acquire for reads, that handles CAS misses
+         * and reentrant reads not dealt with in tryAcquireShared.
+         */
+        final int fullTryAcquireShared(Thread current) {
+            /*
+             * This code is in part redundant with that in
+             * tryAcquireShared but is simpler overall by not
+             * complicating tryAcquireShared with interactions between
+             * retries and lazily reading hold counts.
+             */
+            HoldCounter rh = null;
+            for (;;) {
+                int c = getState();
+                if (exclusiveCount(c) != 0) {
+                    if (getExclusiveOwnerThread() != current)
+                        return -1;
+                    // else we hold the exclusive lock; blocking here
+                    // would cause deadlock.
+                } else if (readerShouldBlock()) {
+                    // Make sure we're not acquiring read lock reentrantly
+                    if (firstReader == current) {
+                        // assert firstReaderHoldCount > 0;
+                    } else {
+                        if (rh == null) {
+                            rh = cachedHoldCounter;
+                            if (rh == null || rh.tid != current.getId()) {
+                                rh = readHolds.get();
+                                if (rh.count == 0)
+                                    readHolds.remove();
+                            }
+                        }
+                        if (rh.count == 0)
+                            return -1;
+                    }
+                }
+                if (sharedCount(c) == MAX_COUNT)
+                    throw new Error("Maximum lock count exceeded");
+                if (compareAndSetState(c, c + SHARED_UNIT)) {
+                    if (sharedCount(c) == 0) {
+                        firstReader = current;
+                        firstReaderHoldCount = 1;
+                    } else if (firstReader == current) {
+                        firstReaderHoldCount++;
+                    } else {
+                        if (rh == null)
+                            rh = cachedHoldCounter;
+                        if (rh == null || rh.tid != current.getId())
+                            rh = readHolds.get();
+                        else if (rh.count == 0)
+                            readHolds.set(rh);
+                        rh.count++;
+                        cachedHoldCounter = rh; // cache for release
+                    }
+                    return 1;
+                }
+            }
+        }
+
+        /**
+         * Performs tryLock for write, enabling barging in both modes.
+         * This is identical in effect to tryAcquire except for lack
+         * of calls to writerShouldBlock.
+         */
+        final boolean tryWriteLock() {
+            Thread current = Thread.currentThread();
+            int c = getState();
+            if (c != 0) {
+                int w = exclusiveCount(c);
+                if (w == 0 || current != getExclusiveOwnerThread())
+                    return false;
+                if (w == MAX_COUNT)
+                    throw new Error("Maximum lock count exceeded");
+            }
+            if (!compareAndSetState(c, c + 1))
+                return false;
+            setExclusiveOwnerThread(current);
+            return true;
+        }
+
+        /**
+         * Performs tryLock for read, enabling barging in both modes.
+         * This is identical in effect to tryAcquireShared except for
+         * lack of calls to readerShouldBlock.
+         */
+        final boolean tryReadLock() {
+            Thread current = Thread.currentThread();
+            for (;;) {
+                int c = getState();
+                if (exclusiveCount(c) != 0 &&
+                    getExclusiveOwnerThread() != current)
+                    return false;
+                int r = sharedCount(c);
+                if (r == MAX_COUNT)
+                    throw new Error("Maximum lock count exceeded");
+                if (compareAndSetState(c, c + SHARED_UNIT)) {
+                    if (r == 0) {
+                        firstReader = current;
+                        firstReaderHoldCount = 1;
+                    } else if (firstReader == current) {
+                        firstReaderHoldCount++;
+                    } else {
+                        HoldCounter rh = cachedHoldCounter;
+                        if (rh == null || rh.tid != current.getId())
+                            cachedHoldCounter = rh = readHolds.get();
+                        else if (rh.count == 0)
+                            readHolds.set(rh);
+                        rh.count++;
+                    }
+                    return true;
+                }
+            }
+        }
+
         protected final boolean isHeldExclusively() {
-            return exclusiveCount(getState()) != 0 && 
-                owner == Thread.currentThread();
+            // While we must in general read state before owner,
+            // we don't need to do so to check if current thread is owner
+            return getExclusiveOwnerThread() == Thread.currentThread();
         }
 
         // Methods relayed to outer class
-        
-        final ConditionObject newCondition() { 
-            return new ConditionObject(); 
+
+        final ConditionObject newCondition() {
+            return new ConditionObject();
         }
 
         final Thread getOwner() {
-            int c = exclusiveCount(getState());
-            Thread o = owner;
-            return (c == 0)? null : o;
+            // Must read state before owner to ensure memory consistency
+            return ((exclusiveCount(getState()) == 0)?
+                    null :
+                    getExclusiveOwnerThread());
         }
-        
+
         final int getReadLockCount() {
             return sharedCount(getState());
         }
-        
+
         final boolean isWriteLocked() {
             return exclusiveCount(getState()) != 0;
         }
 
         final int getWriteHoldCount() {
-            int c = exclusiveCount(getState());
-            Thread o = owner;
-            return (o == Thread.currentThread())? c : 0;
+            return isHeldExclusively() ? exclusiveCount(getState()) : 0;
+        }
+
+        final int getReadHoldCount() {
+            if (getReadLockCount() == 0)
+                return 0;
+
+            Thread current = Thread.currentThread();
+            if (firstReader == current)
+                return firstReaderHoldCount;
+
+            HoldCounter rh = cachedHoldCounter;
+            if (rh != null && rh.tid == current.getId())
+                return rh.count;
+
+            int count = readHolds.get().count;
+            if (count == 0) readHolds.remove();
+            return count;
         }
 
         /**
@@ -315,78 +630,43 @@
         private void readObject(java.io.ObjectInputStream s)
             throws java.io.IOException, ClassNotFoundException {
             s.defaultReadObject();
+            readHolds = new ThreadLocalHoldCounter();
             setState(0); // reset to unlocked state
         }
 
         final int getCount() { return getState(); }
     }
 
-    /** 
+    /**
      * Nonfair version of Sync
      */
     final static class NonfairSync extends Sync {
-        protected final boolean tryAcquire(int acquires) { 
-            return nonfairTryAcquire(acquires);
+        private static final long serialVersionUID = -8159625535654395037L;
+        final boolean writerShouldBlock() {
+            return false; // writers can always barge
         }
-
-        protected final int tryAcquireShared(int acquires) {
-            return nonfairTryAcquireShared(acquires);
-        }
-
-        // Use fastpath for main write lock method
-        final void wlock() {
-            if (compareAndSetState(0, 1))
-                owner = Thread.currentThread();
-            else
-                acquire(1);
+        final boolean readerShouldBlock() {
+            /* As a heuristic to avoid indefinite writer starvation,
+             * block if the thread that momentarily appears to be head
+             * of queue, if one exists, is a waiting writer.  This is
+             * only a probabilistic effect since a new reader will not
+             * block if there is a waiting writer behind other enabled
+             * readers that have not yet drained from the queue.
+             */
+            return apparentlyFirstQueuedIsExclusive();
         }
     }
 
-    /** 
+    /**
      * Fair version of Sync
      */
     final static class FairSync extends Sync {
-        protected final boolean tryAcquire(int acquires) { 
-            // mask out readlocks if called from condition methods
-            acquires = exclusiveCount(acquires);
-            Thread current = Thread.currentThread();
-            Thread first;
-            int c = getState();
-            int w = exclusiveCount(c);
-            if (w + acquires >= SHARED_UNIT)
-                throw new Error("Maximum lock count exceeded");
-            if ((w == 0 || current != owner) &&
-                (c != 0 || 
-                 ((first = getFirstQueuedThread()) != null && 
-                  first != current)))
-                return false;
-            if (!compareAndSetState(c, c + acquires)) 
-                return false;
-            owner = current;
-            return true;
+        private static final long serialVersionUID = -2274990926593161451L;
+        final boolean writerShouldBlock() {
+            return hasQueuedPredecessors();
         }
-
-        protected final int tryAcquireShared(int acquires) {
-            Thread current = Thread.currentThread();
-            for (;;) {
-                Thread first = getFirstQueuedThread();
-                if (first != null && first != current)
-                    return -1;
-                int c = getState();
-                int nextc = c + (acquires << SHARED_SHIFT);
-                if (nextc < c)
-                    throw new Error("Maximum lock count exceeded");
-                if (exclusiveCount(c) != 0 && 
-                    owner != Thread.currentThread())
-                    return -1;
-                if (compareAndSetState(c, nextc)) 
-                    return 1;
-                // Recheck count if lost CAS
-            }
-        }
-
-        final void wlock() { // no fast path
-            acquire(1);
+        final boolean readerShouldBlock() {
+            return hasQueuedPredecessors();
         }
     }
 
@@ -396,46 +676,47 @@
     public static class ReadLock implements Lock, java.io.Serializable  {
         private static final long serialVersionUID = -5992448646407690164L;
         private final Sync sync;
-        
-        /** 
-         * Constructor for use by subclasses.
+
+        /**
+         * Constructor for use by subclasses
+         *
          * @param lock the outer lock object
-         * @throws NullPointerException if lock null
+         * @throws NullPointerException if the lock is null
          */
         protected ReadLock(ReentrantReadWriteLock lock) {
             sync = lock.sync;
         }
 
         /**
-         * Acquires the shared lock. 
+         * Acquires the read lock.
          *
-         * <p>Acquires the lock if it is not held exclusively by
+         * <p>Acquires the read lock if the write lock is not held by
          * another thread and returns immediately.
          *
-         * <p>If the lock is held exclusively by another thread then
+         * <p>If the write lock is held by another thread then
          * the current thread becomes disabled for thread scheduling
-         * purposes and lies dormant until the lock has been acquired.
+         * purposes and lies dormant until the read lock has been acquired.
          */
-        public void lock() { 
+        public void lock() {
             sync.acquireShared(1);
         }
 
         /**
-         * Acquires the shared lock unless the current thread is 
-         * {@link Thread#interrupt interrupted}.
+         * Acquires the read lock unless the current thread is
+         * {@linkplain Thread#interrupt interrupted}.
          *
-         * <p>Acquires the shared lock if it is not held exclusively
+         * <p>Acquires the read lock if the write lock is not held
          * by another thread and returns immediately.
          *
-         * <p>If the lock is held by another thread then the
-         * current thread becomes disabled for thread scheduling 
+         * <p>If the write lock is held by another thread then the
+         * current thread becomes disabled for thread scheduling
          * purposes and lies dormant until one of two things happens:
          *
          * <ul>
          *
-         * <li>The lock is acquired by the current thread; or
+         * <li>The read lock is acquired by the current thread; or
          *
-         * <li>Some other thread {@link Thread#interrupt interrupts}
+         * <li>Some other thread {@linkplain Thread#interrupt interrupts}
          * the current thread.
          *
          * </ul>
@@ -444,10 +725,10 @@
          *
          * <ul>
          *
-         * <li>has its interrupted status set on entry to this method; or 
+         * <li>has its interrupted status set on entry to this method; or
          *
-         * <li>is {@link Thread#interrupt interrupted} while acquiring 
-         * the lock,
+         * <li>is {@linkplain Thread#interrupt interrupted} while
+         * acquiring the read lock,
          *
          * </ul>
          *
@@ -466,83 +747,83 @@
         }
 
         /**
-         * Acquires the shared lock only if it is not held exclusively by
+         * Acquires the read lock only if the write lock is not held by
          * another thread at the time of invocation.
          *
-         * <p>Acquires the lock if it is not held exclusively by
+         * <p>Acquires the read lock if the write lock is not held by
          * another thread and returns immediately with the value
-         * <tt>true</tt>. Even when this lock has been set to use a
-         * fair ordering policy, a call to <tt>tryLock()</tt>
-         * <em>will</em> immediately acquire the lock if it is
+         * {@code true}. Even when this lock has been set to use a
+         * fair ordering policy, a call to {@code tryLock()}
+         * <em>will</em> immediately acquire the read lock if it is
          * available, whether or not other threads are currently
-         * waiting for the lock.  This &quot;barging&quot; behavior
+         * waiting for the read lock.  This &quot;barging&quot; behavior
          * can be useful in certain circumstances, even though it
          * breaks fairness. If you want to honor the fairness setting
          * for this lock, then use {@link #tryLock(long, TimeUnit)
          * tryLock(0, TimeUnit.SECONDS) } which is almost equivalent
          * (it also detects interruption).
          *
-         * <p>If the lock is held exclusively by another thread then
+         * <p>If the write lock is held by another thread then
          * this method will return immediately with the value
-         * <tt>false</tt>.
+         * {@code false}.
          *
-         * @return <tt>true</tt> if the lock was acquired.
+         * @return {@code true} if the read lock was acquired
          */
         public  boolean tryLock() {
-            return sync.nonfairTryAcquireShared(1) >= 0;
+            return sync.tryReadLock();
         }
 
         /**
-         * Acquires the shared lock if it is not held exclusively by
+         * Acquires the read lock if the write lock is not held by
          * another thread within the given waiting time and the
-         * current thread has not been {@link Thread#interrupt
+         * current thread has not been {@linkplain Thread#interrupt
          * interrupted}.
          *
-         * <p>Acquires the lock if it is not held exclusively by
+         * <p>Acquires the read lock if the write lock is not held by
          * another thread and returns immediately with the value
-         * <tt>true</tt>. If this lock has been set to use a fair
+         * {@code true}. If this lock has been set to use a fair
          * ordering policy then an available lock <em>will not</em> be
          * acquired if any other threads are waiting for the
          * lock. This is in contrast to the {@link #tryLock()}
-         * method. If you want a timed <tt>tryLock</tt> that does
+         * method. If you want a timed {@code tryLock} that does
          * permit barging on a fair lock then combine the timed and
          * un-timed forms together:
          *
          * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
          * </pre>
          *
-         * <p>If the lock is held exclusively by another thread then the
-         * current thread becomes disabled for thread scheduling 
+         * <p>If the write lock is held by another thread then the
+         * current thread becomes disabled for thread scheduling
          * purposes and lies dormant until one of three things happens:
          *
          * <ul>
          *
-         * <li>The lock is acquired by the current thread; or
+         * <li>The read lock is acquired by the current thread; or
          *
-         * <li>Some other thread {@link Thread#interrupt interrupts} the current
-         * thread; or
+         * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+         * the current thread; or
          *
-         * <li>The specified waiting time elapses
+         * <li>The specified waiting time elapses.
          *
          * </ul>
          *
-         * <p>If the lock is acquired then the value <tt>true</tt> is
+         * <p>If the read lock is acquired then the value {@code true} is
          * returned.
          *
          * <p>If the current thread:
          *
          * <ul>
          *
-         * <li>has its interrupted status set on entry to this method; or 
+         * <li>has its interrupted status set on entry to this method; or
          *
-         * <li>is {@link Thread#interrupt interrupted} while acquiring
-         * the lock,
+         * <li>is {@linkplain Thread#interrupt interrupted} while
+         * acquiring the read lock,
          *
          * </ul> then {@link InterruptedException} is thrown and the
          * current thread's interrupted status is cleared.
          *
          * <p>If the specified waiting time elapses then the value
-         * <tt>false</tt> is returned.  If the time is less than or
+         * {@code false} is returned.  If the time is less than or
          * equal to zero, the method will not wait at all.
          *
          * <p>In this implementation, as this method is an explicit
@@ -550,13 +831,11 @@
          * the interrupt over normal or reentrant acquisition of the
          * lock, and over reporting the elapse of the waiting time.
          *
-         * @param timeout the time to wait for the lock
+         * @param timeout the time to wait for the read lock
          * @param unit the time unit of the timeout argument
-         *
-         * @return <tt>true</tt> if the lock was acquired.
-         *
+         * @return {@code true} if the read lock was acquired
          * @throws InterruptedException if the current thread is interrupted
-         * @throws NullPointerException if unit is null
+         * @throws NullPointerException if the time unit is null
          *
          */
         public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
@@ -564,20 +843,19 @@
         }
 
         /**
-         * Attempts to release this lock.  
+         * Attempts to release this lock.
          *
          * <p> If the number of readers is now zero then the lock
-         * is made available for other lock attempts.
+         * is made available for write lock attempts.
          */
         public  void unlock() {
             sync.releaseShared(1);
         }
 
         /**
-         * Throws UnsupportedOperationException because ReadLocks
-         * do not support conditions.
-         * @return A new {@link Condition} instance for this <tt>Lock</tt> 
-         * instance.
+         * Throws {@code UnsupportedOperationException} because
+         * {@code ReadLocks} do not support conditions.
+         *
          * @throws UnsupportedOperationException always
          */
         public Condition newCondition() {
@@ -586,17 +864,16 @@
 
         /**
          * Returns a string identifying this lock, as well as its lock state.
-         * The state, in brackets, includes the String 
-         * &quot;Read locks =&quot; followed by the number of held
-         * read locks.
-         * @return a string identifying this lock, as well as its lock state.
+         * The state, in brackets, includes the String {@code "Read locks ="}
+         * followed by the number of held read locks.
+         *
+         * @return a string identifying this lock, as well as its lock state
          */
         public String toString() {
             int r = sync.getReadLockCount();
-            return super.toString() + 
+            return super.toString() +
                 "[Read locks = " + r + "]";
         }
-
     }
 
     /**
@@ -605,42 +882,45 @@
     public static class WriteLock implements Lock, java.io.Serializable  {
         private static final long serialVersionUID = -4992448646407690164L;
         private final Sync sync;
-        
-        /** 
-         * Constructor for use by subclasses.
+
+        /**
+         * Constructor for use by subclasses
+         *
          * @param lock the outer lock object
-         * @throws NullPointerException if lock null
+         * @throws NullPointerException if the lock is null
          */
         protected WriteLock(ReentrantReadWriteLock lock) {
             sync = lock.sync;
         }
 
         /**
-         * Acquire the lock. 
+         * Acquires the write lock.
          *
-         * <p>Acquires the lock if it is not held by another thread
-         * and returns immediately, setting the lock hold count to
+         * <p>Acquires the write lock if neither the read nor write lock
+         * are held by another thread
+         * and returns immediately, setting the write lock hold count to
          * one.
          *
-         * <p>If the current thread already holds the lock then the
+         * <p>If the current thread already holds the write lock then the
          * hold count is incremented by one and the method returns
          * immediately.
          *
          * <p>If the lock is held by another thread then the current
          * thread becomes disabled for thread scheduling purposes and
-         * lies dormant until the lock has been acquired, at which
-         * time the lock hold count is set to one.
+         * lies dormant until the write lock has been acquired, at which
+         * time the write lock hold count is set to one.
          */
         public void lock() {
-            sync.wlock();
+            sync.acquire(1);
         }
 
         /**
-         * Acquires the lock unless the current thread is {@link
-         * Thread#interrupt interrupted}.
+         * Acquires the write lock unless the current thread is
+         * {@linkplain Thread#interrupt interrupted}.
          *
-         * <p>Acquires the lock if it is not held by another thread
-         * and returns immediately, setting the lock hold count to
+         * <p>Acquires the write lock if neither the read nor write lock
+         * are held by another thread
+         * and returns immediately, setting the write lock hold count to
          * one.
          *
          * <p>If the current thread already holds this lock then the
@@ -653,14 +933,14 @@
          *
          * <ul>
          *
-         * <li>The lock is acquired by the current thread; or
+         * <li>The write lock is acquired by the current thread; or
          *
-         * <li>Some other thread {@link Thread#interrupt interrupts}
+         * <li>Some other thread {@linkplain Thread#interrupt interrupts}
          * the current thread.
          *
          * </ul>
          *
-         * <p>If the lock is acquired by the current thread then the
+         * <p>If the write lock is acquired by the current thread then the
          * lock hold count is set to one.
          *
          * <p>If the current thread:
@@ -670,8 +950,8 @@
          * <li>has its interrupted status set on entry to this method;
          * or
          *
-         * <li>is {@link Thread#interrupt interrupted} while acquiring
-         * the lock,
+         * <li>is {@linkplain Thread#interrupt interrupted} while
+         * acquiring the write lock,
          *
          * </ul>
          *
@@ -690,16 +970,17 @@
         }
 
         /**
-         * Acquires the lock only if it is not held by another thread
+         * Acquires the write lock only if it is not held by another thread
          * at the time of invocation.
          *
-         * <p>Acquires the lock if it is not held by another thread
-         * and returns immediately with the value <tt>true</tt>,
-         * setting the lock hold count to one. Even when this lock has
+         * <p>Acquires the write lock if neither the read nor write lock
+         * are held by another thread
+         * and returns immediately with the value {@code true},
+         * setting the write lock hold count to one. Even when this lock has
          * been set to use a fair ordering policy, a call to
-         * <tt>tryLock()</tt> <em>will</em> immediately acquire the
+         * {@code tryLock()} <em>will</em> immediately acquire the
          * lock if it is available, whether or not other threads are
-         * currently waiting for the lock.  This &quot;barging&quot;
+         * currently waiting for the write lock.  This &quot;barging&quot;
          * behavior can be useful in certain circumstances, even
          * though it breaks fairness. If you want to honor the
          * fairness setting for this lock, then use {@link
@@ -708,31 +989,32 @@
          *
          * <p> If the current thread already holds this lock then the
          * hold count is incremented by one and the method returns
-         * <tt>true</tt>.
+         * {@code true}.
          *
          * <p>If the lock is held by another thread then this method
-         * will return immediately with the value <tt>false</tt>.
+         * will return immediately with the value {@code false}.
          *
-         * @return <tt>true</tt> if the lock was free and was acquired by the
-         * current thread, or the lock was already held by the current thread; and
-         * <tt>false</tt> otherwise.
+         * @return {@code true} if the lock was free and was acquired
+         * by the current thread, or the write lock was already held
+         * by the current thread; and {@code false} otherwise.
          */
         public boolean tryLock( ) {
-            return sync.nonfairTryAcquire(1);
+            return sync.tryWriteLock();
         }
 
         /**
-         * Acquires the lock if it is not held by another thread
+         * Acquires the write lock if it is not held by another thread
          * within the given waiting time and the current thread has
-         * not been {@link Thread#interrupt interrupted}.
+         * not been {@linkplain Thread#interrupt interrupted}.
          *
-         * <p>Acquires the lock if it is not held by another thread
-         * and returns immediately with the value <tt>true</tt>,
-         * setting the lock hold count to one. If this lock has been
+         * <p>Acquires the write lock if neither the read nor write lock
+         * are held by another thread
+         * and returns immediately with the value {@code true},
+         * setting the write lock hold count to one. If this lock has been
          * set to use a fair ordering policy then an available lock
          * <em>will not</em> be acquired if any other threads are
-         * waiting for the lock. This is in contrast to the {@link
-         * #tryLock()} method. If you want a timed <tt>tryLock</tt>
+         * waiting for the write lock. This is in contrast to the {@link
+         * #tryLock()} method. If you want a timed {@code tryLock}
          * that does permit barging on a fair lock then combine the
          * timed and un-timed forms together:
          *
@@ -741,7 +1023,7 @@
          *
          * <p>If the current thread already holds this lock then the
          * hold count is incremented by one and the method returns
-         * <tt>true</tt>.
+         * {@code true}.
          *
          * <p>If the lock is held by another thread then the current
          * thread becomes disabled for thread scheduling purposes and
@@ -749,17 +1031,17 @@
          *
          * <ul>
          *
-         * <li>The lock is acquired by the current thread; or
+         * <li>The write lock is acquired by the current thread; or
          *
-         * <li>Some other thread {@link Thread#interrupt interrupts}
+         * <li>Some other thread {@linkplain Thread#interrupt interrupts}
          * the current thread; or
          *
          * <li>The specified waiting time elapses
          *
          * </ul>
          *
-         * <p>If the lock is acquired then the value <tt>true</tt> is
-         * returned and the lock hold count is set to one.
+         * <p>If the write lock is acquired then the value {@code true} is
+         * returned and the write lock hold count is set to one.
          *
          * <p>If the current thread:
          *
@@ -768,16 +1050,16 @@
          * <li>has its interrupted status set on entry to this method;
          * or
          *
-         * <li>is {@link Thread#interrupt interrupted} while acquiring
-         * the lock,
+         * <li>is {@linkplain Thread#interrupt interrupted} while
+         * acquiring the write lock,
          *
-         * </ul> 
+         * </ul>
          *
          * then {@link InterruptedException} is thrown and the current
          * thread's interrupted status is cleared.
          *
          * <p>If the specified waiting time elapses then the value
-         * <tt>false</tt> is returned.  If the time is less than or
+         * {@code false} is returned.  If the time is less than or
          * equal to zero, the method will not wait at all.
          *
          * <p>In this implementation, as this method is an explicit
@@ -785,30 +1067,31 @@
          * the interrupt over normal or reentrant acquisition of the
          * lock, and over reporting the elapse of the waiting time.
          *
-         * @param timeout the time to wait for the lock
+         * @param timeout the time to wait for the write lock
          * @param unit the time unit of the timeout argument
          *
-         * @return <tt>true</tt> if the lock was free and was acquired
-         * by the current thread, or the lock was already held by the
-         * current thread; and <tt>false</tt> if the waiting time
+         * @return {@code true} if the lock was free and was acquired
+         * by the current thread, or the write lock was already held by the
+         * current thread; and {@code false} if the waiting time
          * elapsed before the lock could be acquired.
          *
          * @throws InterruptedException if the current thread is interrupted
-         * @throws NullPointerException if unit is null
+         * @throws NullPointerException if the time unit is null
          *
          */
         public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
             return sync.tryAcquireNanos(1, unit.toNanos(timeout));
         }
-        
+
         /**
-         * Attempts to release this lock.  
+         * Attempts to release this lock.
          *
          * <p>If the current thread is the holder of this lock then
          * the hold count is decremented. If the hold count is now
          * zero then the lock is released.  If the current thread is
          * not the holder of this lock then {@link
          * IllegalMonitorStateException} is thrown.
+         *
          * @throws IllegalMonitorStateException if the current thread does not
          * hold this lock.
          */
@@ -818,7 +1101,7 @@
 
         /**
          * Returns a {@link Condition} instance for use with this
-         * {@link Lock} instance. 
+         * {@link Lock} instance.
          * <p>The returned {@link Condition} instance supports the same
          * usages as do the {@link Object} monitor methods ({@link
          * Object#wait() wait}, {@link Object#notify notify}, and {@link
@@ -834,74 +1117,80 @@
          * affected. However it is essentially always an error to
          * invoke a condition waiting method when the current thread
          * has also acquired read locks, since other threads that
-         * could unblock it will not be able to access the write
+         * could unblock it will not be able to acquire the write
          * lock.)
          *
-         * <li>When the condition {@link Condition#await() waiting}
+         * <li>When the condition {@linkplain Condition#await() waiting}
          * methods are called the write lock is released and, before
          * they return, the write lock is reacquired and the lock hold
          * count restored to what it was when the method was called.
          *
-         * <li>If a thread is {@link Thread#interrupt interrupted} while
+         * <li>If a thread is {@linkplain Thread#interrupt interrupted} while
          * waiting then the wait will terminate, an {@link
          * InterruptedException} will be thrown, and the thread's
          * interrupted status will be cleared.
          *
-         * <li> Waiting threads are signalled in FIFO order
+         * <li> Waiting threads are signalled in FIFO order.
          *
          * <li>The ordering of lock reacquisition for threads returning
          * from waiting methods is the same as for threads initially
          * acquiring the lock, which is in the default case not specified,
          * but for <em>fair</em> locks favors those threads that have been
          * waiting the longest.
-         * 
+         *
          * </ul>
+         *
          * @return the Condition object
          */
-        public Condition newCondition() { 
+        public Condition newCondition() {
             return sync.newCondition();
         }
 
         /**
          * Returns a string identifying this lock, as well as its lock
          * state.  The state, in brackets includes either the String
-         * &quot;Unlocked&quot; or the String &quot;Locked by&quot;
-         * followed by the {@link Thread#getName} of the owning thread.
-         * @return a string identifying this lock, as well as its lock state.
+         * {@code "Unlocked"} or the String {@code "Locked by"}
+         * followed by the {@linkplain Thread#getName name} of the owning thread.
+         *
+         * @return a string identifying this lock, as well as its lock state
          */
         public String toString() {
-            Thread owner = sync.getOwner();
-            return super.toString() + ((owner == null) ?
+            Thread o = sync.getOwner();
+            return super.toString() + ((o == null) ?
                                        "[Unlocked]" :
-                                       "[Locked by thread " + owner.getName() + "]");
+                                       "[Locked by thread " + o.getName() + "]");
         }
 
     }
 
-
     // Instrumentation and status
 
     /**
-     * Returns true if this lock has fairness set true.
-     * @return true if this lock has fairness set true.
+     * Returns {@code true} if this lock has fairness set true.
+     *
+     * @return {@code true} if this lock has fairness set true
      */
     public final boolean isFair() {
         return sync instanceof FairSync;
     }
 
     /**
-     * Returns the thread that currently owns the exclusive lock, or
-     * <tt>null</tt> if not owned. Note that the owner may be
-     * momentarily <tt>null</tt> even if there are threads trying to
-     * acquire the lock but have not yet done so.  This method is
-     * designed to facilitate construction of subclasses that provide
-     * more extensive lock monitoring facilities.
-     * @return the owner, or <tt>null</tt> if not owned.
+     * Returns the thread that currently owns the write lock, or
+     * {@code null} if not owned. When this method is called by a
+     * thread that is not the owner, the return value reflects a
+     * best-effort approximation of current lock status. For example,
+     * the owner may be momentarily {@code null} even if there are
+     * threads trying to acquire the lock but have not yet done so.
+     * This method is designed to facilitate construction of
+     * subclasses that provide more extensive lock monitoring
+     * facilities.
+     *
+     * @return the owner, or {@code null} if not owned
      */
     protected Thread getOwner() {
         return sync.getOwner();
     }
-    
+
     /**
      * Queries the number of read locks held for this lock. This
      * method is designed for use in monitoring system state, not for
@@ -916,17 +1205,19 @@
      * Queries if the write lock is held by any thread. This method is
      * designed for use in monitoring system state, not for
      * synchronization control.
-     * @return <tt>true</tt> if any thread holds write lock and 
-     * <tt>false</tt> otherwise.
+     *
+     * @return {@code true} if any thread holds the write lock and
+     *         {@code false} otherwise
      */
     public boolean isWriteLocked() {
         return sync.isWriteLocked();
     }
 
     /**
-     * Queries if the write lock is held by the current thread. 
-     * @return <tt>true</tt> if current thread holds this lock and 
-     * <tt>false</tt> otherwise.
+     * Queries if the write lock is held by the current thread.
+     *
+     * @return {@code true} if the current thread holds the write lock and
+     *         {@code false} otherwise
      */
     public boolean isWriteLockedByCurrentThread() {
         return sync.isHeldExclusively();
@@ -937,8 +1228,8 @@
      * current thread.  A writer thread has a hold on a lock for
      * each lock action that is not matched by an unlock action.
      *
-     * @return the number of holds on this lock by the current thread,
-     * or zero if this lock is not held by the current thread.
+     * @return the number of holds on the write lock by the current thread,
+     *         or zero if the write lock is not held by the current thread
      */
     public int getWriteHoldCount() {
         return sync.getWriteHoldCount();
@@ -952,6 +1243,7 @@
      * returned collection are in no particular order.  This method is
      * designed to facilitate construction of subclasses that provide
      * more extensive lock monitoring facilities.
+     *
      * @return the collection of threads
      */
     protected Collection<Thread> getQueuedWriterThreads() {
@@ -966,6 +1258,7 @@
      * returned collection are in no particular order.  This method is
      * designed to facilitate construction of subclasses that provide
      * more extensive lock monitoring facilities.
+     *
      * @return the collection of threads
      */
     protected Collection<Thread> getQueuedReaderThreads() {
@@ -973,41 +1266,42 @@
     }
 
     /**
-     * Queries whether any threads are waiting to acquire. Note that
-     * because cancellations may occur at any time, a <tt>true</tt>
-     * return does not guarantee that any other thread will ever
-     * acquire.  This method is designed primarily for use in
-     * monitoring of the system state.
+     * Queries whether any threads are waiting to acquire the read or
+     * write lock. Note that because cancellations may occur at any
+     * time, a {@code true} return does not guarantee that any other
+     * thread will ever acquire a lock.  This method is designed
+     * primarily for use in monitoring of the system state.
      *
-     * @return true if there may be other threads waiting to acquire
-     * the lock.
+     * @return {@code true} if there may be other threads waiting to
+     *         acquire the lock
      */
-    public final boolean hasQueuedThreads() { 
+    public final boolean hasQueuedThreads() {
         return sync.hasQueuedThreads();
     }
 
     /**
-     * Queries whether the given thread is waiting to acquire this
-     * lock. Note that because cancellations may occur at any time, a
-     * <tt>true</tt> return does not guarantee that this thread
-     * will ever acquire.  This method is designed primarily for use
-     * in monitoring of the system state.
+     * Queries whether the given thread is waiting to acquire either
+     * the read or write lock. Note that because cancellations may
+     * occur at any time, a {@code true} return does not guarantee
+     * that this thread will ever acquire a lock.  This method is
+     * designed primarily for use in monitoring of the system state.
      *
      * @param thread the thread
-     * @return true if the given thread is queued waiting for this lock.
-     * @throws NullPointerException if thread is null
+     * @return {@code true} if the given thread is queued waiting for this lock
+     * @throws NullPointerException if the thread is null
      */
-    public final boolean hasQueuedThread(Thread thread) { 
+    public final boolean hasQueuedThread(Thread thread) {
         return sync.isQueued(thread);
     }
 
     /**
-     * Returns an estimate of the number of threads waiting to
-     * acquire.  The value is only an estimate because the number of
-     * threads may change dynamically while this method traverses
-     * internal data structures.  This method is designed for use in
-     * monitoring of the system state, not for synchronization
-     * control.
+     * Returns an estimate of the number of threads waiting to acquire
+     * either the read or write lock.  The value is only an estimate
+     * because the number of threads may change dynamically while this
+     * method traverses internal data structures.  This method is
+     * designed for use in monitoring of the system state, not for
+     * synchronization control.
+     *
      * @return the estimated number of threads waiting for this lock
      */
     public final int getQueueLength() {
@@ -1016,12 +1310,13 @@
 
     /**
      * Returns a collection containing threads that may be waiting to
-     * acquire.  Because the actual set of threads may change
-     * dynamically while constructing this result, the returned
-     * collection is only a best-effort estimate.  The elements of the
-     * returned collection are in no particular order.  This method is
-     * designed to facilitate construction of subclasses that provide
-     * more extensive monitoring facilities.
+     * acquire either the read or write lock.  Because the actual set
+     * of threads may change dynamically while constructing this
+     * result, the returned collection is only a best-effort estimate.
+     * The elements of the returned collection are in no particular
+     * order.  This method is designed to facilitate construction of
+     * subclasses that provide more extensive monitoring facilities.
+     *
      * @return the collection of threads
      */
     protected Collection<Thread> getQueuedThreads() {
@@ -1031,18 +1326,18 @@
     /**
      * Queries whether any threads are waiting on the given condition
      * associated with the write lock. Note that because timeouts and
-     * interrupts may occur at any time, a <tt>true</tt> return does
-     * not guarantee that a future <tt>signal</tt> will awaken any
+     * interrupts may occur at any time, a {@code true} return does
+     * not guarantee that a future {@code signal} will awaken any
      * threads.  This method is designed primarily for use in
      * monitoring of the system state.
+     *
      * @param condition the condition
-     * @return <tt>true</tt> if there are any waiting threads.
-     * @throws IllegalMonitorStateException if this lock 
-     * is not held
+     * @return {@code true} if there are any waiting threads
+     * @throws IllegalMonitorStateException if this lock is not held
      * @throws IllegalArgumentException if the given condition is
-     * not associated with this lock
-     * @throws NullPointerException if condition null
-     */ 
+     *         not associated with this lock
+     * @throws NullPointerException if the condition is null
+     */
     public boolean hasWaiters(Condition condition) {
         if (condition == null)
             throw new NullPointerException();
@@ -1058,14 +1353,14 @@
      * serves only as an upper bound on the actual number of waiters.
      * This method is designed for use in monitoring of the system
      * state, not for synchronization control.
+     *
      * @param condition the condition
-     * @return the estimated number of waiting threads.
-     * @throws IllegalMonitorStateException if this lock 
-     * is not held
+     * @return the estimated number of waiting threads
+     * @throws IllegalMonitorStateException if this lock is not held
      * @throws IllegalArgumentException if the given condition is
-     * not associated with this lock
-     * @throws NullPointerException if condition null
-     */ 
+     *         not associated with this lock
+     * @throws NullPointerException if the condition is null
+     */
     public int getWaitQueueLength(Condition condition) {
         if (condition == null)
             throw new NullPointerException();
@@ -1083,13 +1378,13 @@
      * are in no particular order.  This method is designed to
      * facilitate construction of subclasses that provide more
      * extensive condition monitoring facilities.
+     *
      * @param condition the condition
      * @return the collection of threads
-     * @throws IllegalMonitorStateException if this lock 
-     * is not held
+     * @throws IllegalMonitorStateException if this lock is not held
      * @throws IllegalArgumentException if the given condition is
-     * not associated with this lock
-     * @throws NullPointerException if condition null
+     *         not associated with this lock
+     * @throws NullPointerException if the condition is null
      */
     protected Collection<Thread> getWaitingThreads(Condition condition) {
         if (condition == null)
@@ -1101,18 +1396,19 @@
 
     /**
      * Returns a string identifying this lock, as well as its lock state.
-     * The state, in brackets, includes the String &quot;Write locks =&quot;
-     * follwed by the number of reentrantly held write locks, and the
-     * String &quot;Read locks =&quot; followed by the number of held
+     * The state, in brackets, includes the String {@code "Write locks ="}
+     * followed by the number of reentrantly held write locks, and the
+     * String {@code "Read locks ="} followed by the number of held
      * read locks.
-     * @return a string identifying this lock, as well as its lock state.
+     *
+     * @return a string identifying this lock, as well as its lock state
      */
     public String toString() {
         int c = sync.getCount();
-        int w = exclusiveCount(c);
-        int r = sharedCount(c);
-        
-        return super.toString() + 
+        int w = Sync.exclusiveCount(c);
+        int r = Sync.sharedCount(c);
+
+        return super.toString() +
             "[Write locks = " + w + ", Read locks = " + r + "]";
     }
 
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/locks/package-info.java b/libcore/concurrent/src/main/java/java/util/concurrent/locks/package-info.java
new file mode 100644
index 0000000..801ee9b
--- /dev/null
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/locks/package-info.java
@@ -0,0 +1,44 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+/**
+ * Interfaces and classes providing a framework for locking and waiting
+ * for conditions that is distinct from built-in synchronization and
+ * monitors.  The framework permits much greater flexibility in the use of
+ * locks and conditions, at the expense of more awkward syntax.
+ *
+ * <p>The {@link java.util.concurrent.locks.Lock} interface supports
+ * locking disciplines that differ in semantics (reentrant, fair, etc),
+ * and that can be used in non-block-structured contexts including
+ * hand-over-hand and lock reordering algorithms.  The main implementation
+ * is {@link java.util.concurrent.locks.ReentrantLock}.
+ *
+ * <p>The {@link java.util.concurrent.locks.ReadWriteLock} interface
+ * similarly defines locks that may be shared among readers but are
+ * exclusive to writers.  Only a single implementation, {@link
+ * java.util.concurrent.locks.ReentrantReadWriteLock}, is provided, since
+ * it covers most standard usage contexts.  But programmers may create
+ * their own implementations to cover nonstandard requirements.
+ *
+ * <p>The {@link java.util.concurrent.locks.Condition} interface
+ * describes condition variables that may be associated with Locks.
+ * These are similar in usage to the implicit monitors accessed using
+ * {@code Object.wait}, but offer extended capabilities.
+ * In particular, multiple {@code Condition} objects may be associated
+ * with a single {@code Lock}.  To avoid compatibility issues, the
+ * names of {@code Condition} methods are different from the
+ * corresponding {@code Object} versions.
+ *
+ * <p>The {@link java.util.concurrent.locks.AbstractQueuedSynchronizer}
+ * class serves as a useful superclass for defining locks and other
+ * synchronizers that rely on queuing blocked threads. The
+ * {@link java.util.concurrent.locks.LockSupport} class provides
+ * lower-level blocking and unblocking support that is useful for those
+ * developers implementing their own customized lock classes.
+ *
+ * @since 1.5
+ */
+package java.util.concurrent.locks;
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/locks/package.html b/libcore/concurrent/src/main/java/java/util/concurrent/locks/package.html
deleted file mode 100644
index 1cc156f..0000000
--- a/libcore/concurrent/src/main/java/java/util/concurrent/locks/package.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html> <head>
-<title>Locks</title>
-</head>
-
-<body>
-
-Interfaces and classes providing a framework for locking and waiting
-for conditions that is distinct from built-in synchronization and
-monitors. The framework permits much greater flexibility in the use of
-locks and conditions, at the expense of more awkward syntax.
-
-<p> The {@link java.util.concurrent.locks.Lock} interface supports
-locking disciplines that differ in semantics (reentrant, fair, etc),
-and that can be used in non-block-structured contexts including
-hand-over-hand and lock reordering algorithms. The main implementation
-is {@link java.util.concurrent.locks.ReentrantLock}. 
-
-<p> The {@link java.util.concurrent.locks.ReadWriteLock} interface
-similarly defines locks that may be shared among readers but are
-exclusive to writers.  Only a single implementation, {@link
-java.util.concurrent.locks.ReentrantReadWriteLock}, is provided, since
-it covers most standard usage contexts. But programmers may create
-their own implementations to cover nonstandard requirements.
-
-<p> The {@link java.util.concurrent.locks.Condition} interface
-describes condition variables that may be associated with Locks.
-These are similar in usage to the implicit monitors accessed using
-<tt>Object.wait</tt>, but offer extended capabilities.  In particular,
-multiple <tt>Condition</tt> objects may be associated with a single
-<tt>Lock</tt>.  To avoid compatibility issues, the names of
-<tt>Condition</tt> methods are different than the corresponding
-<tt>Object</tt> versions.
-
-<p> The {@link java.util.concurrent.locks.AbstractQueuedSynchronizer}
-class serves as a useful superclass for defining locks and other
-synchronizers that rely on queuing blocked threads.  The {@link
-java.util.concurrent.locks.LockSupport} class provides lower-level
-blocking and unblocking support that is useful for those developers
-implementing their own customized lock classes.
-
-@since Android 1.0
-
-</body> </html>
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/package-info.java b/libcore/concurrent/src/main/java/java/util/concurrent/package-info.java
new file mode 100644
index 0000000..d49ef25
--- /dev/null
+++ b/libcore/concurrent/src/main/java/java/util/concurrent/package-info.java
@@ -0,0 +1,229 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+/**
+ * Utility classes commonly useful in concurrent programming.  This
+ * package includes a few small standardized extensible frameworks, as
+ * well as some classes that provide useful functionality and are
+ * otherwise tedious or difficult to implement.  Here are brief
+ * descriptions of the main components.  See also the
+ * {@link java.util.concurrent.locks} and
+ * {@link java.util.concurrent.atomic} packages.
+ *
+ * <h2>Executors</h2>
+ *
+ * <b>Interfaces.</b>
+ *
+ * {@link java.util.concurrent.Executor} is a simple standardized
+ * interface for defining custom thread-like subsystems, including
+ * thread pools, asynchronous IO, and lightweight task frameworks.
+ * Depending on which concrete Executor class is being used, tasks may
+ * execute in a newly created thread, an existing task-execution thread,
+ * or the thread calling {@link java.util.concurrent.Executor#execute
+ * execute}, and may execute sequentially or concurrently.
+ *
+ * {@link java.util.concurrent.ExecutorService} provides a more
+ * complete asynchronous task execution framework.  An
+ * ExecutorService manages queuing and scheduling of tasks,
+ * and allows controlled shutdown.
+ *
+ * The {@link java.util.concurrent.ScheduledExecutorService}
+ * subinterface and associated interfaces add support for
+ * delayed and periodic task execution.  ExecutorServices
+ * provide methods arranging asynchronous execution of any
+ * function expressed as {@link java.util.concurrent.Callable},
+ * the result-bearing analog of {@link java.lang.Runnable}.
+ *
+ * A {@link java.util.concurrent.Future} returns the results of
+ * a function, allows determination of whether execution has
+ * completed, and provides a means to cancel execution.
+ *
+ * <p>
+ *
+ * <b>Implementations.</b>
+ *
+ * Classes {@link java.util.concurrent.ThreadPoolExecutor} and
+ * {@link java.util.concurrent.ScheduledThreadPoolExecutor}
+ * provide tunable, flexible thread pools.
+ *
+ * The {@link java.util.concurrent.Executors} class provides
+ * factory methods for the most common kinds and configurations
+ * of Executors, as well as a few utility methods for using
+ * them.  Other utilities based on {@code Executors} include the
+ * concrete class {@link java.util.concurrent.FutureTask}
+ * providing a common extensible implementation of Futures, and
+ * {@link java.util.concurrent.ExecutorCompletionService}, that
+ * assists in coordinating the processing of groups of
+ * asynchronous tasks.
+ *
+ * <h2>Queues</h2>
+ *
+ * The {@link java.util.concurrent.ConcurrentLinkedQueue} class
+ * supplies an efficient scalable thread-safe non-blocking FIFO
+ * queue.
+ *
+ * <p>Five implementations in {@code java.util.concurrent} support
+ * the extended {@link java.util.concurrent.BlockingQueue}
+ * interface, that defines blocking versions of put and take:
+ * {@link java.util.concurrent.LinkedBlockingQueue},
+ * {@link java.util.concurrent.ArrayBlockingQueue},
+ * {@link java.util.concurrent.SynchronousQueue},
+ * {@link java.util.concurrent.PriorityBlockingQueue}, and
+ * {@link java.util.concurrent.DelayQueue}.
+ * The different classes cover the most common usage contexts
+ * for producer-consumer, messaging, parallel tasking, and
+ * related concurrent designs.
+ *
+ * <h2>Timing</h2>
+ *
+ * The {@link java.util.concurrent.TimeUnit} class provides
+ * multiple granularities (including nanoseconds) for
+ * specifying and controlling time-out based operations.  Most
+ * classes in the package contain operations based on time-outs
+ * in addition to indefinite waits.  In all cases that
+ * time-outs are used, the time-out specifies the minimum time
+ * that the method should wait before indicating that it
+ * timed-out.  Implementations make a &quot;best effort&quot;
+ * to detect time-outs as soon as possible after they occur.
+ * However, an indefinite amount of time may elapse between a
+ * time-out being detected and a thread actually executing
+ * again after that time-out.  All methods that accept timeout
+ * parameters treat values less than or equal to zero to mean
+ * not to wait at all.  To wait "forever", you can use a value
+ * of {@code Long.MAX_VALUE}.
+ *
+ * <h2>Synchronizers</h2>
+ *
+ * Four classes aid common special-purpose synchronization idioms.
+ * {@link java.util.concurrent.Semaphore} is a classic concurrency tool.
+ * {@link java.util.concurrent.CountDownLatch} is a very simple yet very
+ * common utility for blocking until a given number of signals, events,
+ * or conditions hold.  A {@link java.util.concurrent.CyclicBarrier} is a
+ * resettable multiway synchronization point useful in some styles of
+ * parallel programming.  An {@link java.util.concurrent.Exchanger} allows
+ * two threads to exchange objects at a rendezvous point, and is useful
+ * in several pipeline designs.
+ *
+ * <h2>Concurrent Collections</h2>
+ *
+ * Besides Queues, this package supplies Collection implementations
+ * designed for use in multithreaded contexts:
+ * {@link java.util.concurrent.ConcurrentHashMap},
+ * {@link java.util.concurrent.CopyOnWriteArrayList}, and
+ * {@link java.util.concurrent.CopyOnWriteArraySet}.
+ * When many threads are expected to access a given collection, a
+ * {@code ConcurrentHashMap} is normally preferable to a synchronized
+ * {@code HashMap}. A {@code CopyOnWriteArrayList} is preferable to a
+ * synchronized {@code ArrayList} when the expected number of reads and
+ * traversals greatly outnumber the number of updates to a list.
+
+ * <p>The "Concurrent" prefix used with some classes in this package
+ * is a shorthand indicating several differences from similar
+ * "synchronized" classes.  For example {@code java.util.Hashtable} and
+ * {@code Collections.synchronizedMap(new HashMap())} are
+ * synchronized.  But {@link
+ * java.util.concurrent.ConcurrentHashMap} is "concurrent".  A
+ * concurrent collection is thread-safe, but not governed by a
+ * single exclusion lock.  In the particular case of
+ * ConcurrentHashMap, it safely permits any number of
+ * concurrent reads as well as a tunable number of concurrent
+ * writes.  "Synchronized" classes can be useful when you need
+ * to prevent all access to a collection via a single lock, at
+ * the expense of poorer scalability.  In other cases in which
+ * multiple threads are expected to access a common collection,
+ * "concurrent" versions are normally preferable.  And
+ * unsynchronized collections are preferable when either
+ * collections are unshared, or are accessible only when
+ * holding other locks.
+ *
+ * <p>Most concurrent Collection implementations (including most
+ * Queues) also differ from the usual java.util conventions in that
+ * their Iterators provide <em>weakly consistent</em> rather than
+ * fast-fail traversal.  A weakly consistent iterator is thread-safe,
+ * but does not necessarily freeze the collection while iterating, so
+ * it may (or may not) reflect any updates since the iterator was
+ * created.
+ *
+ * <h2><a name="MemoryVisibility">Memory Consistency Properties</a></h2>
+ *
+ * <a href="http://java.sun.com/docs/books/jls/third_edition/html/memory.html">
+ * Chapter 17 of the Java Language Specification</a> defines the
+ * <i>happens-before</i> relation on memory operations such as reads and
+ * writes of shared variables.  The results of a write by one thread are
+ * guaranteed to be visible to a read by another thread only if the write
+ * operation <i>happens-before</i> the read operation.  The
+ * {@code synchronized} and {@code volatile} constructs, as well as the
+ * {@code Thread.start()} and {@code Thread.join()} methods, can form
+ * <i>happens-before</i> relationships.  In particular:
+ *
+ * <ul>
+ *   <li>Each action in a thread <i>happens-before</i> every action in that
+ *   thread that comes later in the program's order.
+ *
+ *   <li>An unlock ({@code synchronized} block or method exit) of a
+ *   monitor <i>happens-before</i> every subsequent lock ({@code synchronized}
+ *   block or method entry) of that same monitor.  And because
+ *   the <i>happens-before</i> relation is transitive, all actions
+ *   of a thread prior to unlocking <i>happen-before</i> all actions
+ *   subsequent to any thread locking that monitor.
+ *
+ *   <li>A write to a {@code volatile} field <i>happens-before</i> every
+ *   subsequent read of that same field.  Writes and reads of
+ *   {@code volatile} fields have similar memory consistency effects
+ *   as entering and exiting monitors, but do <em>not</em> entail
+ *   mutual exclusion locking.
+ *
+ *   <li>A call to {@code start} on a thread <i>happens-before</i> any
+ *   action in the started thread.
+ *
+ *   <li>All actions in a thread <i>happen-before</i> any other thread
+ *   successfully returns from a {@code join} on that thread.
+ *
+ * </ul>
+ *
+ *
+ * The methods of all classes in {@code java.util.concurrent} and its
+ * subpackages extend these guarantees to higher-level
+ * synchronization.  In particular:
+ *
+ * <ul>
+ *
+ *   <li>Actions in a thread prior to placing an object into any concurrent
+ *   collection <i>happen-before</i> actions subsequent to the access or
+ *   removal of that element from the collection in another thread.
+ *
+ *   <li>Actions in a thread prior to the submission of a {@code Runnable}
+ *   to an {@code Executor} <i>happen-before</i> its execution begins.
+ *   Similarly for {@code Callables} submitted to an {@code ExecutorService}.
+ *
+ *   <li>Actions taken by the asynchronous computation represented by a
+ *   {@code Future} <i>happen-before</i> actions subsequent to the
+ *   retrieval of the result via {@code Future.get()} in another thread.
+ *
+ *   <li>Actions prior to "releasing" synchronizer methods such as
+ *   {@code Lock.unlock}, {@code Semaphore.release}, and
+ *   {@code CountDownLatch.countDown} <i>happen-before</i> actions
+ *   subsequent to a successful "acquiring" method such as
+ *   {@code Lock.lock}, {@code Semaphore.acquire},
+ *   {@code Condition.await}, and {@code CountDownLatch.await} on the
+ *   same synchronizer object in another thread.
+ *
+ *   <li>For each pair of threads that successfully exchange objects via
+ *   an {@code Exchanger}, actions prior to the {@code exchange()}
+ *   in each thread <i>happen-before</i> those subsequent to the
+ *   corresponding {@code exchange()} in another thread.
+ *
+ *   <li>Actions prior to calling {@code CyclicBarrier.await}
+ *   <i>happen-before</i> actions performed by the barrier action, and
+ *   actions performed by the barrier action <i>happen-before</i> actions
+ *   subsequent to a successful return from the corresponding {@code await}
+ *   in other threads.
+ *
+ * </ul>
+ *
+ * @since 1.5
+ */
+package java.util.concurrent;
diff --git a/libcore/concurrent/src/main/java/java/util/concurrent/package.html b/libcore/concurrent/src/main/java/java/util/concurrent/package.html
deleted file mode 100644
index a5bb8d2..0000000
--- a/libcore/concurrent/src/main/java/java/util/concurrent/package.html
+++ /dev/null
@@ -1,125 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html> <head>
-<title>Concurrency Utilities</title>
-</head>
-
-<body>
-
-<p> Utility classes commonly useful in concurrent programming.  This
-package includes a few small standardized extensible frameworks, as
-well as some classes that provide useful functionality and are
-otherwise tedious or difficult to implement.  Here are brief
-descriptions of the main components. See also the <tt>locks</tt> and
-<tt>atomic</tt> packages.
-
-<h2>Executors</h2>
-
-<b>Interfaces.</b> {@link java.util.concurrent.Executor} is a simple
-standardized interface for defining custom thread-like subsystems,
-including thread pools, asynchronous IO, and lightweight task
-frameworks.  Depending on which concrete Executor class is being used,
-tasks may execute in a newly created thread, an existing
-task-execution thread, or the thread calling <tt>execute()</tt>, and
-may execute sequentially or concurrently.  {@link
-java.util.concurrent.ExecutorService} provides a more complete
-asynchronous task execution framework.  An ExecutorService manages
-queuing and scheduling of tasks, and allows controlled shutdown.  The
-{@link java.util.concurrent.ScheduledExecutorService} subinterface
-adds support for delayed and periodic task execution.
-ExecutorServices provide methods arranging asynchronous execution of
-any function expressed as {@link java.util.concurrent.Callable}, the
-result-bearing analog of {@link java.lang.Runnable}.  A {@link
-java.util.concurrent.Future} returns the results of a function, allows
-determination of whether execution has completed, and provides a means to
-cancel execution.
-
-<p>
-
-<b>Implementations.</b> Classes {@link
-java.util.concurrent.ThreadPoolExecutor} and {@link
-java.util.concurrent.ScheduledThreadPoolExecutor} provide tunable,
-flexible thread pools. The {@link java.util.concurrent.Executors}
-class provides factory methods for the most common kinds and
-configurations of Executors, as well as a few utility methods for
-using them. Other utilities based on Executors include the concrete
-class {@link java.util.concurrent.FutureTask} providing a common
-extensible implementation of Futures, and {@link
-java.util.concurrent.ExecutorCompletionService}, that assists in
-coordinating the processing of groups of asynchronous tasks.
-
-<h2>Queues</h2>
-
-The java.util.concurrent {@link
-java.util.concurrent.ConcurrentLinkedQueue} class supplies an
-efficient scalable thread-safe non-blocking FIFO queue.  Five
-implementations in java.util.concurrent support the extended {@link
-java.util.concurrent.BlockingQueue} interface, that defines blocking
-versions of put and take: {@link
-java.util.concurrent.LinkedBlockingQueue}, {@link
-java.util.concurrent.ArrayBlockingQueue}, {@link
-java.util.concurrent.SynchronousQueue}, {@link
-java.util.concurrent.PriorityBlockingQueue}, and {@link
-java.util.concurrent.DelayQueue}. The different classes cover the most
-common usage contexts for producer-consumer, messaging, parallel
-tasking, and related concurrent designs.
-
-
-<h2>Timing</h2>
-
-The {@link java.util.concurrent.TimeUnit} class provides multiple
-granularities (including nanoseconds) for specifying and controlling
-time-out based operations. Most classes in the package contain
-operations based on time-outs in addition to indefinite waits.  In all
-cases that time-outs are used, the time-out specifies the minimum time
-that the method should wait before indicating that it
-timed-out. Implementations make a &quot;best effort&quot; to detect
-time-outs as soon as possible after they occur. However, an indefinite
-amount of time may elapse between a time-out being detected and a
-thread actually executing again after that time-out.
-
-<h2>Synchronizers</h2>
-
-Four classes aid common special-purpose synchronization idioms.
-{@link java.util.concurrent.Semaphore} is a classic concurrency tool.
-{@link java.util.concurrent.CountDownLatch} is a very simple yet very
-common utility for blocking until a given number of signals, events,
-or conditions hold.  A {@link java.util.concurrent.CyclicBarrier} is a
-resettable multiway synchronization point useful in some styles of
-parallel programming. An {@link java.util.concurrent.Exchanger} allows
-two threads to exchange objects at a rendezvous point, and is useful
-in several pipeline designs.
-
-<h2>Concurrent Collections</h2>
-
-Besides Queues, this package supplies a few Collection implementations
-designed for use in multithreaded contexts: {@link
-java.util.concurrent.ConcurrentHashMap}, {@link
-java.util.concurrent.CopyOnWriteArrayList}, and {@link
-java.util.concurrent.CopyOnWriteArraySet}.
-
-<p>The "Concurrent" prefix used with some classes in this package is a
-shorthand indicating several differences from similar "synchronized"
-classes. For example <tt>java.util.Hashtable</tt> and
-<tt>Collections.synchronizedMap(new HashMap())</tt> are
-synchronized. But {@link java.util.concurrent.ConcurrentHashMap} is
-"concurrent".  A concurrent collection is thread-safe, but not
-governed by a single exclusion lock. In the particular case of
-ConcurrentHashMap, it safely permits any number of concurrent reads as
-well as a tunable number of concurrent writes.  "Synchronized" classes
-can be useful when you need to prevent all access to a collection via
-a single lock, at the expense of poorer scalability. In other cases in
-which multiple threads are expected to access a common collection,
-"concurrent" versions are normally preferable. And unsynchronized
-collections are preferable when either collections are unshared, or
-are accessible only when holding other locks.
-
-<p> Most concurrent Collection implementations (including most Queues)
-also differ from the usual java.util conventions in that their Iterators
-provide <em>weakly consistent</em> rather than fast-fail traversal. A
-weakly consistent iterator is thread-safe, but does not necessarily
-freeze the collection while iterating, so it may (or may not) reflect
-any updates since the iterator was created.
-
-@since Android 1.0
-
-</body> </html>
diff --git a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AbstractQueuedSynchronizerTest.java b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AbstractQueuedSynchronizerTest.java
index 7102c14..db89645 100644
--- a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AbstractQueuedSynchronizerTest.java
+++ b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AbstractQueuedSynchronizerTest.java
@@ -462,7 +462,9 @@
         Thread t = new Thread(new InterruptedSyncRunnable(sync));
         try {
             t.start();
+            Thread.sleep(SHORT_DELAY_MS);
             t.interrupt();
+            Thread.sleep(SHORT_DELAY_MS);
             sync.release(1);
             t.join();
         } catch(Exception e){
@@ -951,7 +953,6 @@
             sync.acquire(1);
             c.signal();
             sync.release(1);
-            assert(t.isInterrupted());
             t.join(SHORT_DELAY_MS);
             assertFalse(t.isAlive());
         }
diff --git a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ArrayBlockingQueueTest.java b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ArrayBlockingQueueTest.java
index da6988f..b650ede 100755
--- a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ArrayBlockingQueueTest.java
+++ b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ArrayBlockingQueueTest.java
@@ -651,6 +651,7 @@
         assertEquals(SIZE, q.remainingCapacity());
         q.add(one);
         assertFalse(q.isEmpty());
+        assertTrue(q.contains(one));
         q.clear();
         assertTrue(q.isEmpty());
     }
@@ -971,6 +972,17 @@
         assertEquals(l.size(), SIZE);
         for (int i = 0; i < SIZE; ++i) 
             assertEquals(l.get(i), new Integer(i));
+        q.add(zero);
+        q.add(one);
+        assertFalse(q.isEmpty());
+        assertTrue(q.contains(zero));
+        assertTrue(q.contains(one));
+        l.clear();
+        q.drainTo(l);
+        assertEquals(q.size(), 0);
+        assertEquals(l.size(), 2);
+        for (int i = 0; i < 2; ++i) 
+            assertEquals(l.get(i), new Integer(i));
     }
 
     /**
@@ -1029,15 +1041,18 @@
      * drainTo(c, n) empties first max {n, size} elements of queue into c
      */ 
     public void testDrainToN() {
+        ArrayBlockingQueue q = new ArrayBlockingQueue(SIZE*2);
         for (int i = 0; i < SIZE + 2; ++i) {
-            ArrayBlockingQueue q = populatedQueue(SIZE);
+            for(int j = 0; j < SIZE; j++)
+                assertTrue(q.offer(new Integer(j)));
             ArrayList l = new ArrayList();
             q.drainTo(l, i);
             int k = (i < SIZE)? i : SIZE;
-            assertEquals(q.size(), SIZE-k);
             assertEquals(l.size(), k);
+            assertEquals(q.size(), SIZE-k);
             for (int j = 0; j < k; ++j) 
                 assertEquals(l.get(j), new Integer(j));
+            while (q.poll() != null) ;
         }
     }
 
diff --git a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicIntegerFieldUpdaterTest.java b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicIntegerFieldUpdaterTest.java
index 03fd2c8..4c3ecb4 100755
--- a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicIntegerFieldUpdaterTest.java
+++ b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicIntegerFieldUpdaterTest.java
@@ -62,6 +62,27 @@
         catch (RuntimeException rt) {}
     }
 
+    static class Base {
+        protected volatile int f = 0;
+    }
+    static class Sub1 extends Base {
+        AtomicIntegerFieldUpdater<Base> fUpdater
+                = AtomicIntegerFieldUpdater.newUpdater(Base.class, "f");
+    }
+    static class Sub2 extends Base {}
+
+    public void testProtectedFieldOnAnotherSubtype() {
+        Sub1 sub1 = new Sub1();
+        Sub2 sub2 = new Sub2();
+
+        sub1.fUpdater.set(sub1, 1);
+        try {
+            sub1.fUpdater.set(sub2, 2);
+            shouldThrow();
+        } 
+        catch (RuntimeException rt) {}
+    }
+
     /**
      *  get returns the last value set or assigned
      */
@@ -80,6 +101,7 @@
         assertEquals(-3,a.get(this));
         
     }
+
     /**
      * compareAndSet succeeds in changing value if equal to expected else fails
      */
diff --git a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicIntegerTest.java b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicIntegerTest.java
index 1771d80..d484785 100755
--- a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicIntegerTest.java
+++ b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicIntegerTest.java
@@ -48,6 +48,7 @@
         assertEquals(-3,ai.get());
         
     }
+
     /**
      * compareAndSet succeeds in changing value if equal to expected else fails
      */
diff --git a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicLongFieldUpdaterTest.java b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicLongFieldUpdaterTest.java
index 8076f7b..9310795 100755
--- a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicLongFieldUpdaterTest.java
+++ b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicLongFieldUpdaterTest.java
@@ -29,7 +29,7 @@
      */
     public void testConstructor(){
         try{
-            AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> 
+            AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest>
                 a = AtomicLongFieldUpdater.newUpdater
                 (AtomicLongFieldUpdaterTest.class, "y");
             shouldThrow();
@@ -42,7 +42,7 @@
      */
     public void testConstructor2(){
         try{
-            AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> 
+            AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest>
                 a = AtomicLongFieldUpdater.newUpdater
                 (AtomicLongFieldUpdaterTest.class, "z");
             shouldThrow();
@@ -55,7 +55,7 @@
      */
     public void testConstructor3(){
         try{
-            AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> 
+            AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest>
                 a = AtomicLongFieldUpdater.newUpdater
                 (AtomicLongFieldUpdaterTest.class, "w");
             shouldThrow();
@@ -64,6 +64,27 @@
         catch (RuntimeException rt) {}
     }
 
+    static class Base {
+        protected volatile long f = 0;
+    }
+    static class Sub1 extends Base {
+        AtomicLongFieldUpdater<Base> fUpdater
+                = AtomicLongFieldUpdater.newUpdater(Base.class, "f");
+    }
+    static class Sub2 extends Base {}
+
+    public void testProtectedFieldOnAnotherSubtype() {
+        Sub1 sub1 = new Sub1();
+        Sub2 sub2 = new Sub2();
+
+        sub1.fUpdater.set(sub1, 1);
+        try {
+            sub1.fUpdater.set(sub2, 2);
+            shouldThrow();
+        }
+        catch (RuntimeException rt) {}
+    }
+
     /**
      *  get returns the last value set or assigned
      */
@@ -75,12 +96,12 @@
             return;
         }
         x = 1;
-        assertEquals(1,a.get(this));
-        a.set(this,2);
-        assertEquals(2,a.get(this));
-        a.set(this,-3);
-        assertEquals(-3,a.get(this));
-        
+	assertEquals(1,a.get(this));
+	a.set(this,2);
+	assertEquals(2,a.get(this));
+	a.set(this,-3);
+	assertEquals(-3,a.get(this));
+
     }
     /**
      * compareAndSet succeeds in changing value if equal to expected else fails
@@ -134,7 +155,7 @@
 
     /**
      * repeated weakCompareAndSet succeeds in changing value when equal
-     * to expected 
+     * to expected
      */
     public void testWeakCompareAndSet(){
         AtomicLongFieldUpdater<AtomicLongFieldUpdaterTest> a;
diff --git a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicLongTest.java b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicLongTest.java
index 55b8a49..143c84a 100755
--- a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicLongTest.java
+++ b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicLongTest.java
@@ -48,6 +48,7 @@
         assertEquals(-3,ai.get());
         
     }
+
     /**
      * compareAndSet succeeds in changing value if equal to expected else fails
      */
diff --git a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicReferenceFieldUpdaterTest.java b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicReferenceFieldUpdaterTest.java
index 183ca21..feddce7 100755
--- a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicReferenceFieldUpdaterTest.java
+++ b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicReferenceFieldUpdaterTest.java
@@ -64,6 +64,27 @@
         catch (RuntimeException rt) {}
     }
 
+    static class Base {
+        protected volatile Object f = null;
+    }
+    static class Sub1 extends Base {
+        AtomicReferenceFieldUpdater<Base, Object> fUpdater
+                = AtomicReferenceFieldUpdater.newUpdater(Base.class, Object.class, "f");
+    }
+    static class Sub2 extends Base {}
+
+    public void testProtectedFieldOnAnotherSubtype() {
+        Sub1 sub1 = new Sub1();
+        Sub2 sub2 = new Sub2();
+
+        sub1.fUpdater.set(sub1, "f");
+        try {
+            sub1.fUpdater.set(sub2, "g");
+            shouldThrow();
+        }
+        catch (RuntimeException rt) {}
+    }
+
     /**
      *  get returns the last value set or assigned
      */
@@ -75,14 +96,11 @@
             return;
         }
         x = one;
-        assertEquals(one,a.get(this));
-        a.set(this,two);
-        assertEquals(two,a.get(this));
-        a.set(this,-3);
-        // BEGIN android-changed
-        assertEquals(new Integer(-3),a.get(this));
-        // END android-changed
-        
+	assertEquals(one,a.get(this));
+	a.set(this,two);
+	assertEquals(two,a.get(this));
+	a.set(this,m3);
+	assertEquals(m3,a.get(this));
     }
     /**
      * compareAndSet succeeds in changing value if equal to expected else fails
@@ -135,7 +153,7 @@
 
     /**
      * repeated weakCompareAndSet succeeds in changing value when equal
-     * to expected 
+     * to expected
      */
     public void testWeakCompareAndSet(){
         AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer>a;
diff --git a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicReferenceTest.java b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicReferenceTest.java
index 0aa48cd..33da30d 100755
--- a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicReferenceTest.java
+++ b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/AtomicReferenceTest.java
@@ -46,7 +46,7 @@
         assertEquals(two,ai.get());
         ai.set(m3);
         assertEquals(m3,ai.get());
-        
+
     }
     /**
      * compareAndSet succeeds in changing value if equal to expected else fails
@@ -86,7 +86,7 @@
 
     /**
      * repeated weakCompareAndSet succeeds in changing value when equal
-     * to expected 
+     * to expected
      */
     public void testWeakCompareAndSet(){
         AtomicReference ai = new AtomicReference(one);
diff --git a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentHashMapTest.java b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentHashMapTest.java
index 9b3ec52..d7f2210 100755
--- a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentHashMapTest.java
+++ b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ConcurrentHashMapTest.java
@@ -16,59 +16,16 @@
 
 public class ConcurrentHashMapTest extends JSR166TestCase{
     public static void main(String[] args) {
-        junit.textui.TestRunner.run (suite());        
+        junit.textui.TestRunner.run (suite());
     }
     public static Test suite() {
         return new TestSuite(ConcurrentHashMapTest.class);
     }
-    // BEGIN android-added
-    static class MyConcurrentHashMap<V, K> extends ConcurrentHashMap<K, V>
-            implements Cloneable {
-
-        public MyConcurrentHashMap() {
-            super();
-        }
-
-        public MyConcurrentHashMap(int initialCapacity, float loadFactor,
-                int concurrencyLevel) {
-            super(initialCapacity, loadFactor, concurrencyLevel);
-        }
-
-        public MyConcurrentHashMap(int initialCapacity) {
-            super(initialCapacity);
-        }
-
-        public MyConcurrentHashMap(Map<? extends K, ? extends V> t) {
-            super(t);
-        }
-
-        @Override
-        protected Object clone() throws CloneNotSupportedException {
-            return super.clone();
-        }
-
-    }
 
     /**
      * Create a map from Integers 1-5 to Strings "A"-"E".
      */
-    private static MyConcurrentHashMap myMap5() {
-        MyConcurrentHashMap map = new MyConcurrentHashMap(5);
-        assertTrue(map.isEmpty());
-        map.put(one, "A");
-        map.put(two, "B");
-        map.put(three, "C");
-        map.put(four, "D");
-        map.put(five, "E");
-        assertFalse(map.isEmpty());
-        assertEquals(5, map.size());
-        return map;
-    }
-    // END android-added
-    /**
-     * Create a map from Integers 1-5 to Strings "A"-"E".
-     */
-    private static ConcurrentHashMap map5() {   
+    private static ConcurrentHashMap map5() {
         ConcurrentHashMap map = new ConcurrentHashMap(5);
         assertTrue(map.isEmpty());
         map.put(one, "A");
@@ -111,7 +68,7 @@
         assertTrue(map.contains("A"));
         assertFalse(map.contains("Z"));
     }
-    
+
     /**
      *  containsKey returns true for contained key
      */
@@ -126,8 +83,8 @@
      */
     public void testContainsValue() {
         ConcurrentHashMap map = map5();
-        assertTrue(map.contains("A"));
-        assertFalse(map.contains("Z"));
+	assertTrue(map.containsValue("A"));
+        assertFalse(map.containsValue("Z"));
     }
 
     /**
@@ -146,21 +103,6 @@
     }
 
     /**
-     *   Clone creates an equal map
-     */
-    public void testClone() {
-        // BEGIN android-changed
-        MyConcurrentHashMap map =myMap5();
-        try {
-            MyConcurrentHashMap m2 = (MyConcurrentHashMap)(map.clone());
-            assertEquals(map, m2);
-        } catch (CloneNotSupportedException e) {
-            fail("clone not supported");
-        }
-        // END android-changed
-    }
-
-    /**
      *  get returns the correct element at the given key,
      *  or null if not present
      */
@@ -210,6 +152,49 @@
     }
 
     /**
+     *  keySet.toArray returns contains all keys
+     */
+    public void testKeySetToArray() {
+        ConcurrentHashMap map = map5();
+	Set s = map.keySet();
+        Object[] ar = s.toArray();
+        assertTrue(s.containsAll(Arrays.asList(ar)));
+	assertEquals(5, ar.length);
+        ar[0] = m10;
+        assertFalse(s.containsAll(Arrays.asList(ar)));
+    }
+
+    /**
+     *  Values.toArray contains all values
+     */
+    public void testValuesToArray() {
+        ConcurrentHashMap map = map5();
+	Collection v = map.values();
+        Object[] ar = v.toArray();
+        ArrayList s = new ArrayList(Arrays.asList(ar));
+	assertEquals(5, ar.length);
+	assertTrue(s.contains("A"));
+	assertTrue(s.contains("B"));
+	assertTrue(s.contains("C"));
+	assertTrue(s.contains("D"));
+	assertTrue(s.contains("E"));
+    }
+
+    /**
+     *  entrySet.toArray contains all entries
+     */
+    public void testEntrySetToArray() {
+        ConcurrentHashMap map = map5();
+	Set s = map.entrySet();
+        Object[] ar = s.toArray();
+        assertEquals(5, ar.length);
+        for (int i = 0; i < 5; ++i) {
+            assertTrue(map.containsKey(((Map.Entry)(ar[i])).getKey()));
+            assertTrue(map.containsValue(((Map.Entry)(ar[i])).getValue()));
+        }
+    }
+
+    /**
      * values collection contains all values
      */
     public void testValues() {
@@ -233,7 +218,7 @@
         Iterator it = s.iterator();
         while (it.hasNext()) {
             Map.Entry e = (Map.Entry) it.next();
-            assertTrue( 
+            assertTrue(
                        (e.getKey().equals(one) && e.getValue().equals("A")) ||
                        (e.getKey().equals(two) && e.getValue().equals("B")) ||
                        (e.getKey().equals(three) && e.getValue().equals("C")) ||
@@ -357,12 +342,12 @@
         for (int i = 1; i <= 5; ++i) {
             assertTrue(s.indexOf(String.valueOf(i)) >= 0);
         }
-    }        
+    }
 
     // Exception tests
-    
+
     /**
-     * Cannot create with negative capacity 
+     * Cannot create with negative capacity
      */
     public void testConstructor1() {
         try {
@@ -561,6 +546,19 @@
     }
 
     /**
+     * remove(x, null) returns false
+     */
+    public void testRemove3() {
+        try {
+            ConcurrentHashMap c = new ConcurrentHashMap(5);
+            c.put("sadsdf", "asdads");
+            assertFalse(c.remove("sadsdf", null));
+        } catch(NullPointerException e){
+            fail();
+        }
+    }
+
+    /**
      * A deserialized map equals original
      */
     public void testSerialization() {
diff --git a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/CyclicBarrierTest.java b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/CyclicBarrierTest.java
index 9eac1a7..ecd6e45 100755
--- a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/CyclicBarrierTest.java
+++ b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/CyclicBarrierTest.java
@@ -11,6 +11,8 @@
 import junit.framework.*;
 import java.util.*;
 import java.util.concurrent.*;
+import java.util.concurrent.locks.*;
+import java.util.concurrent.atomic.*;
 
 public class CyclicBarrierTest extends JSR166TestCase{
     public static void main(String[] args) {
@@ -164,7 +166,7 @@
      * throw BrokenBarrierException
      */
     public void testAwait2_Interrupted_BrokenBarrier() {
-      final CyclicBarrier c = new CyclicBarrier(3);
+        final CyclicBarrier c = new CyclicBarrier(3);
         Thread t1 = new Thread(new Runnable() {
                 public void run() {
                     try {
@@ -229,7 +231,7 @@
      * throw BrokenBarrierException
      */
     public void testAwait4_Timeout_BrokenBarrier() {
-      final CyclicBarrier c = new CyclicBarrier(3);
+        final CyclicBarrier c = new CyclicBarrier(3);
         Thread t1 = new Thread(new Runnable() {
                 public void run() {
                     try {
@@ -267,7 +269,7 @@
      * throw BrokenBarrierException
      */
     public void testAwait5_Timeout_BrokenBarrier() {
-      final CyclicBarrier c = new CyclicBarrier(3);
+        final CyclicBarrier c = new CyclicBarrier(3);
         Thread t1 = new Thread(new Runnable() {
                 public void run() {
                     try {
@@ -376,4 +378,249 @@
         }
     }
 
+    /**
+     * All threads block while a barrier is broken.
+     */
+    public void testReset_Leakage() {
+        try {
+            final CyclicBarrier c = new CyclicBarrier(2);
+            final AtomicBoolean done = new AtomicBoolean();
+            Thread t = new Thread() {
+                    public void run() {
+                        while (!done.get()) {
+                            try {
+                                while (c.isBroken())
+                                    c.reset();
+                                
+                                c.await();
+                                threadFail("await should not return");
+                            }
+                            catch (BrokenBarrierException e) {
+                            }
+                            catch (InterruptedException ie) {
+                            }
+                        }
+                    }
+                };
+            
+            t.start();
+            for( int i = 0; i < 4; i++) {
+                Thread.sleep(SHORT_DELAY_MS);
+                t.interrupt();
+            }
+            done.set(true);
+            t.interrupt();
+        }
+        catch (Exception ex) {
+            unexpectedException();
+        }
+    }
+
+    /**
+     * Reset of a non-broken barrier does not break barrier
+     */
+    public void testResetWithoutBreakage() {
+        try {
+            final CyclicBarrier start = new CyclicBarrier(3);
+            final CyclicBarrier barrier = new CyclicBarrier(3);
+            for (int i = 0; i < 3; i++) {
+                Thread t1 = new Thread(new Runnable() {
+                        public void run() {
+                            try { start.await(); }
+                            catch (Exception ie) { 
+                                threadFail("start barrier"); 
+                            }
+                            try { barrier.await(); }
+                            catch (Throwable thrown) { 
+                                unexpectedException(); 
+                            }}});
+                
+                Thread t2 = new Thread(new Runnable() {
+                        public void run() {
+                            try { start.await(); }
+                            catch (Exception ie) { 
+                                threadFail("start barrier"); 
+                            }
+                            try { barrier.await(); }
+                            catch (Throwable thrown) { 
+                                unexpectedException(); 
+                            }}});
+                
+                
+                t1.start();
+                t2.start();
+                try { start.await(); }
+                catch (Exception ie) { threadFail("start barrier"); }
+                barrier.await();
+                t1.join();
+                t2.join();
+                assertFalse(barrier.isBroken());
+                assertEquals(0, barrier.getNumberWaiting());
+                if (i == 1) barrier.reset();
+                assertFalse(barrier.isBroken());
+                assertEquals(0, barrier.getNumberWaiting());
+            }
+        }
+        catch (Exception ex) {
+            unexpectedException();
+        }
+    }
+        
+    /**
+     * Reset of a barrier after interruption reinitializes it.
+     */
+    public void testResetAfterInterrupt() {
+        try {
+            final CyclicBarrier start = new CyclicBarrier(3);
+            final CyclicBarrier barrier = new CyclicBarrier(3);
+            for (int i = 0; i < 2; i++) {
+                Thread t1 = new Thread(new Runnable() {
+                        public void run() {
+                            try { start.await(); }
+                            catch (Exception ie) { 
+                                threadFail("start barrier"); 
+                            }
+                            try { barrier.await(); }
+                            catch(InterruptedException ok) {}
+                            catch (Throwable thrown) { 
+                                unexpectedException(); 
+                            }}});
+                
+                Thread t2 = new Thread(new Runnable() {
+                        public void run() {
+                            try { start.await(); }
+                            catch (Exception ie) { 
+                                threadFail("start barrier"); 
+                            }
+                            try { barrier.await(); }
+                            catch(BrokenBarrierException ok) {}
+                            catch (Throwable thrown) { 
+                                unexpectedException(); 
+                            }}});
+                
+                t1.start();
+                t2.start();
+                try { start.await(); }
+                catch (Exception ie) { threadFail("start barrier"); }
+                t1.interrupt();
+                t1.join();
+                t2.join();
+                assertTrue(barrier.isBroken());
+                assertEquals(0, barrier.getNumberWaiting());
+                barrier.reset();
+                assertFalse(barrier.isBroken());
+                assertEquals(0, barrier.getNumberWaiting());
+            }
+        }
+        catch (Exception ex) {
+            unexpectedException();
+        }
+    }
+        
+    /**
+     * Reset of a barrier after timeout reinitializes it.
+     */
+    public void testResetAfterTimeout() {
+        try {
+            final CyclicBarrier start = new CyclicBarrier(3);
+            final CyclicBarrier barrier = new CyclicBarrier(3);
+            for (int i = 0; i < 2; i++) {
+                Thread t1 = new Thread(new Runnable() {
+                        public void run() {
+                            try { start.await(); }
+                            catch (Exception ie) { 
+                                threadFail("start barrier"); 
+                            }
+                            try { barrier.await(MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS); }
+                            catch(TimeoutException ok) {}
+                            catch (Throwable thrown) { 
+                                unexpectedException(); 
+                            }}});
+                
+                Thread t2 = new Thread(new Runnable() {
+                        public void run() {
+                            try { start.await(); }
+                            catch (Exception ie) { 
+                                threadFail("start barrier"); 
+                            }
+                            try { barrier.await(); }
+                            catch(BrokenBarrierException ok) {}
+                            catch (Throwable thrown) { 
+                                unexpectedException(); 
+                            }}});
+                
+                t1.start();
+                t2.start();
+                try { start.await(); }
+                catch (Exception ie) { threadFail("start barrier"); }
+                t1.join();
+                t2.join();
+                assertTrue(barrier.isBroken());
+                assertEquals(0, barrier.getNumberWaiting());
+                barrier.reset();
+                assertFalse(barrier.isBroken());
+                assertEquals(0, barrier.getNumberWaiting());
+            }
+        }
+        catch (Exception ex) {
+            unexpectedException();
+        }
+    }
+
+    
+    /**
+     * Reset of a barrier after a failed command reinitializes it.
+     */
+    public void testResetAfterCommandException() {
+        try {
+            final CyclicBarrier start = new CyclicBarrier(3);
+            final CyclicBarrier barrier = 
+                new CyclicBarrier(3, new Runnable() {
+                        public void run() { 
+                            throw new NullPointerException(); }});
+            for (int i = 0; i < 2; i++) {
+                Thread t1 = new Thread(new Runnable() {
+                        public void run() {
+                            try { start.await(); }
+                            catch (Exception ie) { 
+                                threadFail("start barrier"); 
+                            }
+                            try { barrier.await(); }
+                            catch(BrokenBarrierException ok) {}
+                            catch (Throwable thrown) { 
+                                unexpectedException(); 
+                            }}});
+                
+                Thread t2 = new Thread(new Runnable() {
+                        public void run() {
+                            try { start.await(); }
+                            catch (Exception ie) { 
+                                threadFail("start barrier"); 
+                            }
+                            try { barrier.await(); }
+                            catch(BrokenBarrierException ok) {}
+                            catch (Throwable thrown) { 
+                                unexpectedException(); 
+                            }}});
+                
+                t1.start();
+                t2.start();
+                try { start.await(); }
+                catch (Exception ie) { threadFail("start barrier"); }
+                while (barrier.getNumberWaiting() < 2) { Thread.yield(); }
+                try { barrier.await(); }
+                catch (Exception ok) { }
+                t1.join();
+                t2.join();
+                assertTrue(barrier.isBroken());
+                assertEquals(0, barrier.getNumberWaiting());
+                barrier.reset();
+                assertFalse(barrier.isBroken());
+                assertEquals(0, barrier.getNumberWaiting());
+            }
+        }
+        catch (Exception ex) {
+            unexpectedException();
+        }
+    }
 }
diff --git a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/DelayQueueTest.java b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/DelayQueueTest.java
index e332513..978edb4 100755
--- a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/DelayQueueTest.java
+++ b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/DelayQueueTest.java
@@ -14,11 +14,11 @@
 
 public class DelayQueueTest extends JSR166TestCase {
     public static void main(String[] args) {
-        junit.textui.TestRunner.run (suite());        
+	junit.textui.TestRunner.run (suite());
     }
 
     public static Test suite() {
-        return new TestSuite(DelayQueueTest.class);
+	return new TestSuite(DelayQueueTest.class);
     }
 
     private static final int NOCAP = Integer.MAX_VALUE;
@@ -27,20 +27,19 @@
      * A delayed implementation for testing.
      * Most  tests use Pseudodelays, where delays are all elapsed
      * (so, no blocking solely for delays) but are still ordered
-     */ 
-    static class PDelay implements Delayed { 
+     */
+    static class PDelay implements Delayed {
         int pseudodelay;
         PDelay(int i) { pseudodelay = Integer.MIN_VALUE + i; }
-        // BEGIN android-changed
-        public int compareTo(Delayed y) {
+        public int compareTo(PDelay y) {
             int i = pseudodelay;
             int j = ((PDelay)y).pseudodelay;
             if (i < j) return -1;
             if (i > j) return 1;
             return 0;
         }
-        // END android-changed
-        public int compareTo(PDelay y) {
+
+        public int compareTo(Delayed y) {
             int i = pseudodelay;
             int j = ((PDelay)y).pseudodelay;
             if (i < j) return -1;
@@ -72,21 +71,20 @@
     /**
      * Delayed implementation that actually delays
      */
-    static class NanoDelay implements Delayed { 
+    static class NanoDelay implements Delayed {
         long trigger;
-        NanoDelay(long i) { 
+        NanoDelay(long i) {
             trigger = System.nanoTime() + i;
         }
-        // BEGIN android-changed
-        public int compareTo(Delayed y) {
+        public int compareTo(NanoDelay y) {
             long i = trigger;
             long j = ((NanoDelay)y).trigger;
             if (i < j) return -1;
             if (i > j) return 1;
             return 0;
         }
-        // END android-changed
-        public int compareTo(NanoDelay y) {
+
+        public int compareTo(Delayed y) {
             long i = trigger;
             long j = ((NanoDelay)y).trigger;
             if (i < j) return -1;
@@ -123,16 +121,16 @@
     private DelayQueue populatedQueue(int n) {
         DelayQueue q = new DelayQueue();
         assertTrue(q.isEmpty());
-        for(int i = n-1; i >= 0; i-=2)
-            assertTrue(q.offer(new PDelay(i)));
-        for(int i = (n & 1); i < n; i+=2)
-            assertTrue(q.offer(new PDelay(i)));
+	for(int i = n-1; i >= 0; i-=2)
+	    assertTrue(q.offer(new PDelay(i)));
+	for(int i = (n & 1); i < n; i+=2)
+	    assertTrue(q.offer(new PDelay(i)));
         assertFalse(q.isEmpty());
         assertEquals(NOCAP, q.remainingCapacity());
-        assertEquals(n, q.size());
+	assertEquals(n, q.size());
         return q;
     }
- 
+
     /**
      * A new queue has unbounded capacity
      */
@@ -229,22 +227,22 @@
      * offer(null) throws NPE
      */
     public void testOfferNull() {
-        try {
+	try {
             DelayQueue q = new DelayQueue();
             q.offer(null);
             shouldThrow();
-        } catch (NullPointerException success) { }   
+        } catch (NullPointerException success) { }
     }
 
     /**
      * add(null) throws NPE
      */
     public void testAddNull() {
-        try {
+	try {
             DelayQueue q = new DelayQueue();
             q.add(null);
             shouldThrow();
-        } catch (NullPointerException success) { }   
+        } catch (NullPointerException success) { }
     }
 
     /**
@@ -342,13 +340,13 @@
      * put(null) throws NPE
      */
      public void testPutNull() {
-        try {
+	try {
             DelayQueue q = new DelayQueue();
             q.put(null);
             shouldThrow();
-        } 
+        }
         catch (NullPointerException success){
-        }   
+	}
      }
 
     /**
@@ -416,7 +414,7 @@
                     } finally { }
                 }
             });
-        
+
         try {
             t.start();
             Thread.sleep(SMALL_DELAY_MS);
@@ -431,14 +429,14 @@
      * take retrieves elements in priority order
      */
     public void testTake() {
-        try {
+	try {
             DelayQueue q = populatedQueue(SIZE);
             for (int i = 0; i < SIZE; ++i) {
                 assertEquals(new PDelay(i), ((PDelay)q.take()));
             }
         } catch (InterruptedException e){
-            unexpectedException();
-        }   
+	    unexpectedException();
+	}
     }
 
     /**
@@ -450,8 +448,8 @@
                 public void run() {
                     try {
                         q.take();
-                        threadShouldThrow();
-                    } catch (InterruptedException success){ }                
+			threadShouldThrow();
+                    } catch (InterruptedException success){ }
                 }
             });
         try {
@@ -478,16 +476,16 @@
                         q.take();
                         threadShouldThrow();
                     } catch (InterruptedException success){
-                    }   
+                    }
                 }});
         t.start();
-        try { 
-           Thread.sleep(SHORT_DELAY_MS); 
+        try {
+           Thread.sleep(SHORT_DELAY_MS);
            t.interrupt();
            t.join();
         }
         catch (InterruptedException ie) {
-            unexpectedException();
+	    unexpectedException();
         }
     }
 
@@ -500,7 +498,7 @@
         for (int i = 0; i < SIZE; ++i) {
             assertEquals(new PDelay(i), ((PDelay)q.poll()));
         }
-        assertNull(q.poll());
+	assertNull(q.poll());
     }
 
     /**
@@ -514,8 +512,8 @@
             }
             assertNull(q.poll(0, TimeUnit.MILLISECONDS));
         } catch (InterruptedException e){
-            unexpectedException();
-        }   
+	    unexpectedException();
+	}
     }
 
     /**
@@ -529,8 +527,8 @@
             }
             assertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
         } catch (InterruptedException e){
-            unexpectedException();
-        }   
+	    unexpectedException();
+	}
     }
 
     /**
@@ -547,16 +545,16 @@
                         }
                         threadAssertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
                     } catch (InterruptedException success){
-                    }   
+                    }
                 }});
         t.start();
-        try { 
-           Thread.sleep(SHORT_DELAY_MS); 
+        try {
+           Thread.sleep(SHORT_DELAY_MS);
            t.interrupt();
            t.join();
         }
         catch (InterruptedException ie) {
-            unexpectedException();
+	    unexpectedException();
         }
     }
 
@@ -572,8 +570,8 @@
                         threadAssertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
                         q.poll(LONG_DELAY_MS, TimeUnit.MILLISECONDS);
                         q.poll(LONG_DELAY_MS, TimeUnit.MILLISECONDS);
-                        threadFail("Should block");
-                    } catch (InterruptedException success) { }                
+			threadFail("Should block");
+                    } catch (InterruptedException success) { }
                 }
             });
         try {
@@ -585,7 +583,7 @@
         } catch (Exception e){
             unexpectedException();
         }
-    }  
+    }
 
 
     /**
@@ -596,10 +594,12 @@
         for (int i = 0; i < SIZE; ++i) {
             assertEquals(new PDelay(i), ((PDelay)q.peek()));
             q.poll();
-            assertTrue(q.peek() == null ||
-                       i != ((PDelay)q.peek()).intValue());
+            if (q.isEmpty())
+                assertNull(q.peek());
+            else
+                assertTrue(i != ((PDelay)q.peek()).intValue());
         }
-        assertNull(q.peek());
+	assertNull(q.peek());
     }
 
     /**
@@ -630,7 +630,7 @@
             q.remove();
             shouldThrow();
         } catch (NoSuchElementException success){
-        }   
+	}
     }
 
     /**
@@ -647,7 +647,7 @@
         }
         assertTrue(q.isEmpty());
     }
-        
+
     /**
      * contains(x) reports true when elements added but not yet removed
      */
@@ -669,8 +669,10 @@
         assertTrue(q.isEmpty());
         assertEquals(0, q.size());
         assertEquals(NOCAP, q.remainingCapacity());
-        q.add(new PDelay(1));
+        PDelay x = new PDelay(1);
+        q.add(x);
         assertFalse(q.isEmpty());
+        assertTrue(q.contains(x));
         q.clear();
         assertTrue(q.isEmpty());
     }
@@ -729,14 +731,14 @@
      */
     public void testToArray() {
         DelayQueue q = populatedQueue(SIZE);
-        Object[] o = q.toArray();
+	Object[] o = q.toArray();
         Arrays.sort(o);
-        try {
-        for(int i = 0; i < o.length; i++)
-            assertEquals(o[i], q.take());
-        } catch (InterruptedException e){
-            unexpectedException();
-        }    
+	try {
+	for(int i = 0; i < o.length; i++)
+	    assertEquals(o[i], q.take());
+	} catch (InterruptedException e){
+	    unexpectedException();
+	}
     }
 
     /**
@@ -744,15 +746,15 @@
      */
     public void testToArray2() {
         DelayQueue q = populatedQueue(SIZE);
-        PDelay[] ints = new PDelay[SIZE];
-        ints = (PDelay[])q.toArray(ints);
+	PDelay[] ints = new PDelay[SIZE];
+	ints = (PDelay[])q.toArray(ints);
         Arrays.sort(ints);
-        try {
-            for(int i = 0; i < ints.length; i++)
-                assertEquals(ints[i], q.take());
-        } catch (InterruptedException e){
-            unexpectedException();
-        }    
+	try {
+	    for(int i = 0; i < ints.length; i++)
+		assertEquals(ints[i], q.take());
+	} catch (InterruptedException e){
+	    unexpectedException();
+	}
     }
 
 
@@ -760,31 +762,31 @@
      * toArray(null) throws NPE
      */
     public void testToArray_BadArg() {
-        try {
+	try {
             DelayQueue q = populatedQueue(SIZE);
-            Object o[] = q.toArray(null);
-            shouldThrow();
-        } catch(NullPointerException success){}
+	    Object o[] = q.toArray(null);
+	    shouldThrow();
+	} catch(NullPointerException success){}
     }
 
     /**
      * toArray with incompatible array type throws CCE
      */
     public void testToArray1_BadArg() {
-        try {
+	try {
             DelayQueue q = populatedQueue(SIZE);
-            Object o[] = q.toArray(new String[10] );
-            shouldThrow();
-        } catch(ArrayStoreException  success){}
+	    Object o[] = q.toArray(new String[10] );
+	    shouldThrow();
+	} catch(ArrayStoreException  success){}
     }
-    
+
     /**
      * iterator iterates through all elements
      */
     public void testIterator() {
         DelayQueue q = populatedQueue(SIZE);
         int i = 0;
-        Iterator it = q.iterator();
+	Iterator it = q.iterator();
         while(it.hasNext()) {
             assertTrue(q.contains(it.next()));
             ++i;
@@ -819,7 +821,7 @@
         for (int i = 0; i < SIZE; ++i) {
             assertTrue(s.indexOf(String.valueOf(Integer.MIN_VALUE+i)) >= 0);
         }
-    }        
+    }
 
     /**
      * offer transfers elements across Executor tasks
@@ -875,7 +877,7 @@
                 NanoDelay e = (NanoDelay)(q.take());
                 long tt = e.getTriggerTime();
                 assertTrue(tt <= System.nanoTime());
-                if (i != 0) 
+                if (i != 0)
                     assertTrue(tt >= last);
                 last = tt;
             }
@@ -885,10 +887,41 @@
         }
     }
 
+    /**
+     * peek of a non-empty queue returns non-null even if not expired
+     */
+    public void testPeekDelayed() {
+        DelayQueue q = new DelayQueue();
+        q.add(new NanoDelay(Long.MAX_VALUE));
+        assert(q.peek() != null);
+    }
+
+
+    /**
+     * poll of a non-empty queue returns null if no expired elements.
+     */
+    public void testPollDelayed() {
+        DelayQueue q = new DelayQueue();
+        q.add(new NanoDelay(Long.MAX_VALUE));
+        assertNull(q.poll());
+    }
+
+    /**
+     * timed poll of a non-empty queue returns null if no expired elements.
+     */
+    public void testTimedPollDelayed() {
+        DelayQueue q = new DelayQueue();
+        q.add(new NanoDelay(LONG_DELAY_MS * 1000000L));
+        try {
+            assertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
+        } catch (Exception ex) {
+            unexpectedException();
+        }
+    }
 
     /**
      * drainTo(null) throws NPE
-     */ 
+     */
     public void testDrainToNull() {
         DelayQueue q = populatedQueue(SIZE);
         try {
@@ -900,7 +933,7 @@
 
     /**
      * drainTo(this) throws IAE
-     */ 
+     */
     public void testDrainToSelf() {
         DelayQueue q = populatedQueue(SIZE);
         try {
@@ -912,13 +945,30 @@
 
     /**
      * drainTo(c) empties queue into another collection c
-     */ 
+     */
     public void testDrainTo() {
-        DelayQueue q = populatedQueue(SIZE);
+        DelayQueue q = new DelayQueue();
+        PDelay[] elems = new PDelay[SIZE];
+        for (int i = 0; i < SIZE; ++i) {
+            elems[i] = new PDelay(i);
+            q.add(elems[i]);
+        }
         ArrayList l = new ArrayList();
         q.drainTo(l);
         assertEquals(q.size(), 0);
-        assertEquals(l.size(), SIZE);
+        for (int i = 0; i < SIZE; ++i)
+            assertEquals(l.get(i), elems[i]);
+        q.add(elems[0]);
+        q.add(elems[1]);
+        assertFalse(q.isEmpty());
+        assertTrue(q.contains(elems[0]));
+        assertTrue(q.contains(elems[1]));
+        l.clear();
+        q.drainTo(l);
+        assertEquals(q.size(), 0);
+        assertEquals(l.size(), 2);
+        for (int i = 0; i < 2; ++i)
+            assertEquals(l.get(i), elems[i]);
     }
 
     /**
diff --git a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ExecutorCompletionServiceTest.java b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ExecutorCompletionServiceTest.java
index 2e237e2..b1988cc 100644
--- a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ExecutorCompletionServiceTest.java
+++ b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ExecutorCompletionServiceTest.java
@@ -11,6 +11,7 @@
 import junit.framework.*;
 import java.util.*;
 import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
 import java.math.BigInteger;
 import java.security.*;
 
@@ -88,7 +89,7 @@
             Callable c = new StringTask();
             ecs.submit(c);
             Future f = ecs.take();
-            assert(f.isDone());
+            assertTrue(f.isDone());
         } catch (Exception ex) {
             unexpectedException();
         } finally {
@@ -128,7 +129,7 @@
             for (;;) {
                 Future f = ecs.poll();
                 if (f != null) {
-                    assert(f.isDone());
+                    assertTrue(f.isDone());
                     break;
                 }
             }
@@ -151,12 +152,11 @@
             ecs.submit(c);
             Future f = ecs.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
             if (f != null) 
-                assert(f.isDone());
+                assertTrue(f.isDone());
         } catch (Exception ex) {
             unexpectedException();
         } finally {
             joinPool(e);
         }
     }
-
 }
diff --git a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ExecutorsTest.java b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ExecutorsTest.java
index 40e23e4..e8fc7e5 100755
--- a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ExecutorsTest.java
+++ b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ExecutorsTest.java
@@ -16,7 +16,7 @@
 
 public class ExecutorsTest extends JSR166TestCase{
     public static void main(String[] args) {
-        junit.textui.TestRunner.run (suite());  
+        junit.textui.TestRunner.run (suite());
     }
     public static Test suite() {
         return new TestSuite(ExecutorsTest.class);
@@ -26,13 +26,13 @@
         private final ExecutorService exec;
         private final Callable<T> func;
         private final long msecs;
-        
+
         TimedCallable(ExecutorService exec, Callable<T> func, long msecs) {
             this.exec = exec;
             this.func = func;
             this.msecs = msecs;
         }
-        
+
         public T call() throws Exception {
             Future<T> ftask = exec.submit(func);
             try {
@@ -295,13 +295,13 @@
         List<Callable<BigInteger>> tasks = new ArrayList<Callable<BigInteger>>(N);
         try {
             long startTime = System.currentTimeMillis();
-            
+
             long i = 0;
             while (tasks.size() < N) {
                 tasks.add(new TimedCallable<BigInteger>(executor, new Fib(i), 1));
                 i += 10;
             }
-            
+
             int iters = 0;
             BigInteger sum = BigInteger.ZERO;
             for (Iterator<Callable<BigInteger>> it = tasks.iterator(); it.hasNext();) {
@@ -326,7 +326,7 @@
         }
     }
 
-    
+
     /**
      * ThreadPoolExecutor using defaultThreadFactory has
      * specified group, priority, daemon status, and name
@@ -335,31 +335,31 @@
         final ThreadGroup egroup = Thread.currentThread().getThreadGroup();
         Runnable r = new Runnable() {
                 public void run() {
-                    try {
-                        Thread current = Thread.currentThread();
-                        threadAssertTrue(!current.isDaemon());
-                        threadAssertTrue(current.getPriority() == Thread.NORM_PRIORITY);
-                        ThreadGroup g = current.getThreadGroup();
-                        SecurityManager s = System.getSecurityManager();
-                        if (s != null)
-                            threadAssertTrue(g == s.getThreadGroup());
-                        else
-                            threadAssertTrue(g == egroup);
-                        String name = current.getName();
-                        threadAssertTrue(name.endsWith("thread-1"));
-                    } catch (SecurityException ok) {
-                        // Also pass if not allowed to change setting
-                    }
+		    try {
+			Thread current = Thread.currentThread();
+			threadAssertTrue(!current.isDaemon());
+			threadAssertTrue(current.getPriority() <= Thread.NORM_PRIORITY);
+			ThreadGroup g = current.getThreadGroup();
+			SecurityManager s = System.getSecurityManager();
+			if (s != null)
+			    threadAssertTrue(g == s.getThreadGroup());
+			else
+			    threadAssertTrue(g == egroup);
+			String name = current.getName();
+			threadAssertTrue(name.endsWith("thread-1"));
+		    } catch (SecurityException ok) {
+			// Also pass if not allowed to change setting
+		    }
                 }
             };
         ExecutorService e = Executors.newSingleThreadExecutor(Executors.defaultThreadFactory());
-        
+
         e.execute(r);
         try {
             e.shutdown();
         } catch(SecurityException ok) {
         }
-        
+
         try {
             Thread.sleep(SHORT_DELAY_MS);
         } catch (Exception eX) {
@@ -390,27 +390,27 @@
         final AccessControlContext thisacc = AccessController.getContext();
         Runnable r = new Runnable() {
                 public void run() {
-                    try {
-                        Thread current = Thread.currentThread();
-                        threadAssertTrue(!current.isDaemon());
-                        threadAssertTrue(current.getPriority() == Thread.NORM_PRIORITY);
-                        ThreadGroup g = current.getThreadGroup();
-                        SecurityManager s = System.getSecurityManager();
-                        if (s != null)
-                            threadAssertTrue(g == s.getThreadGroup());
-                        else
-                            threadAssertTrue(g == egroup);
-                        String name = current.getName();
-                        threadAssertTrue(name.endsWith("thread-1"));
-                        threadAssertTrue(thisccl == current.getContextClassLoader());
-                        threadAssertTrue(thisacc.equals(AccessController.getContext()));
-                    } catch(SecurityException ok) {
-                        // Also pass if not allowed to change settings
-                    }
+		    try {
+			Thread current = Thread.currentThread();
+			threadAssertTrue(!current.isDaemon());
+			threadAssertTrue(current.getPriority() <= Thread.NORM_PRIORITY);
+			ThreadGroup g = current.getThreadGroup();
+			SecurityManager s = System.getSecurityManager();
+			if (s != null)
+			    threadAssertTrue(g == s.getThreadGroup());
+			else
+			    threadAssertTrue(g == egroup);
+			String name = current.getName();
+			threadAssertTrue(name.endsWith("thread-1"));
+			threadAssertTrue(thisccl == current.getContextClassLoader());
+			threadAssertTrue(thisacc.equals(AccessController.getContext()));
+		    } catch(SecurityException ok) {
+			// Also pass if not allowed to change settings
+		    }
                 }
             };
         ExecutorService e = Executors.newSingleThreadExecutor(Executors.privilegedThreadFactory());
-        
+
         Policy.setPolicy(savedPolicy);
         e.execute(r);
         try {
@@ -460,7 +460,7 @@
             Policy.setPolicy(savedPolicy);
             return;
         } catch(AccessControlException ok) {
-        } 
+        }
 
         try {
             Callable task = Executors.privilegedCallableUsingCurrentClassLoader(new NoOpCallable());
@@ -468,7 +468,7 @@
         } catch(AccessControlException success) {
         } catch(Exception ex) {
             unexpectedException();
-        } 
+        }
         finally {
             Policy.setPolicy(savedPolicy);
         }
@@ -489,13 +489,13 @@
         } catch (AccessControlException ok) {
             return;
         }
-            
+
         try {
             Callable task = Executors.privilegedCallableUsingCurrentClassLoader(new NoOpCallable());
             task.call();
         } catch(Exception ex) {
             unexpectedException();
-        } 
+        }
         finally {
             Policy.setPolicy(savedPolicy);
         }
@@ -520,7 +520,7 @@
             return; // program has too few permissions to set up test
         }
 
-        // Make sure that program doesn't have too many permissions 
+        // Make sure that program doesn't have too many permissions
         try {
             AccessController.doPrivileged(new PrivilegedAction() {
                     public Object run() {
@@ -538,7 +538,7 @@
         } catch(AccessControlException success) {
         } catch(Exception ex) {
             unexpectedException();
-        } 
+        }
     }
 
     /**
diff --git a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/JSR166TestCase.java b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/JSR166TestCase.java
index 70dafbc..c900616 100644
--- a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/JSR166TestCase.java
+++ b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/JSR166TestCase.java
@@ -2,8 +2,8 @@
  * Written by Doug Lea with assistance from members of JCP JSR-166
  * Expert Group and released to the public domain, as explained at
  * http://creativecommons.org/licenses/publicdomain
- * Other contributors include Andrew Wright, Jeffrey Hayes, 
- * Pat Fisher, Mike Judd. 
+ * Other contributors include Andrew Wright, Jeffrey Hayes,
+ * Pat Fisher, Mike Judd.
  */
 
 package tests.api.java.util.concurrent;
@@ -19,13 +19,13 @@
  * utility methods and classes, as well as a simple framework for
  * helping to make sure that assertions failing in generated threads
  * cause the associated test that generated them to itself fail (which
- * JUnit doe not otherwise arrange).  The rules for creating such
+ * JUnit does not otherwise arrange).  The rules for creating such
  * tests are:
  *
  * <ol>
  *
  * <li> All assertions in code running in generated threads must use
- * the forms {@link #threadFail} , {@link #threadAssertTrue} {@link
+ * the forms {@link #threadFail}, {@link #threadAssertTrue}, {@link
  * #threadAssertEquals}, or {@link #threadAssertNull}, (not
  * <tt>fail</tt>, <tt>assertTrue</tt>, etc.) It is OK (but not
  * particularly recommended) for other code to use these forms too.
@@ -46,7 +46,7 @@
  * is always discriminable as larger than SHORT and smaller than
  * MEDIUM.  And so on. These constants are set to conservative values,
  * but even so, if there is ever any doubt, they can all be increased
- * in one spot to rerun tests on slower platforms</li>
+ * in one spot to rerun tests on slower platforms.</li>
  *
  * <li> All threads generated must be joined inside each test case
  * method (or <tt>fail</tt> to do so) before returning from the
@@ -65,7 +65,7 @@
  * "normal" behaviors differ significantly. And sometimes testcases
  * cover multiple methods when they cannot be tested in
  * isolation.</li>
- * 
+ *
  * <li> The documentation style for testcases is to provide as javadoc
  * a simple sentence or two describing the property that the testcase
  * method purports to test. The javadocs do not say anything about how
@@ -90,10 +90,10 @@
 public class JSR166TestCase extends TestCase {
     /**
      * Runs all JSR166 unit tests using junit.textui.TestRunner
-     */ 
+     */
     public static void main (String[] args) {
         int iters = 1;
-        if (args.length > 0) 
+        if (args.length > 0)
             iters = Integer.parseInt(args[0]);
         Test s = suite();
         for (int i = 0; i < iters; ++i) {
@@ -106,7 +106,7 @@
 
     /**
      * Collects all JSR166 unit tests as one suite
-     */ 
+     */
     public static Test suite ( ) {
         TestSuite suite = tests.TestSuiteFactory.createTestSuite("JSR166 Unit Tests");
         // BEGIN android-changed
@@ -114,18 +114,18 @@
         suite.addTest(AbstractQueueTest.suite());
         suite.addTest(AbstractQueuedSynchronizerTest.suite());
         suite.addTest(ArrayBlockingQueueTest.suite());
-        suite.addTest(AtomicBooleanTest.suite()); 
-        suite.addTest(AtomicIntegerArrayTest.suite()); 
-        suite.addTest(AtomicIntegerFieldUpdaterTest.suite()); 
-        suite.addTest(AtomicIntegerTest.suite()); 
-        suite.addTest(AtomicLongArrayTest.suite()); 
-        suite.addTest(AtomicLongFieldUpdaterTest.suite()); 
-        suite.addTest(AtomicLongTest.suite()); 
-        suite.addTest(AtomicMarkableReferenceTest.suite()); 
-        suite.addTest(AtomicReferenceArrayTest.suite()); 
-        suite.addTest(AtomicReferenceFieldUpdaterTest.suite()); 
-        suite.addTest(AtomicReferenceTest.suite()); 
-        suite.addTest(AtomicStampedReferenceTest.suite()); 
+        suite.addTest(AtomicBooleanTest.suite());
+        suite.addTest(AtomicIntegerArrayTest.suite());
+        suite.addTest(AtomicIntegerFieldUpdaterTest.suite());
+        suite.addTest(AtomicIntegerTest.suite());
+        suite.addTest(AtomicLongArrayTest.suite());
+        suite.addTest(AtomicLongFieldUpdaterTest.suite());
+        suite.addTest(AtomicLongTest.suite());
+        suite.addTest(AtomicMarkableReferenceTest.suite());
+        suite.addTest(AtomicReferenceArrayTest.suite());
+        suite.addTest(AtomicReferenceFieldUpdaterTest.suite());
+        suite.addTest(AtomicReferenceTest.suite());
+        suite.addTest(AtomicStampedReferenceTest.suite());
         suite.addTest(ConcurrentHashMapTest.suite());
         suite.addTest(ConcurrentLinkedQueueTest.suite());
         suite.addTest(CopyOnWriteArrayListTest.suite());
@@ -164,16 +164,16 @@
 
 
     /**
-     * Return the shortest timed delay. This could
+     * Returns the shortest timed delay. This could
      * be reimplemented to use for example a Property.
-     */ 
+     */
     protected long getShortDelay() {
         return 50;
     }
 
 
     /**
-     * Set delays as multiples of SHORT_DELAY.
+     * Sets delays as multiples of SHORT_DELAY.
      */
     protected  void setDelays() {
         SHORT_DELAY_MS = getShortDelay();
@@ -188,23 +188,23 @@
     volatile boolean threadFailed;
 
     /**
-     * Initialize test to indicate that no thread assertions have failed
+     * Initializes test to indicate that no thread assertions have failed
      */
-    public void setUp() { 
+    public void setUp() {
         setDelays();
-        threadFailed = false;  
+        threadFailed = false;
     }
 
     /**
-     * Trigger test case failure if any thread assertions have failed
+     * Triggers test case failure if any thread assertions have failed
      */
-    public void tearDown() { 
-        assertFalse(threadFailed);  
+    public void tearDown() {
+        assertFalse(threadFailed);
     }
 
     /**
      * Fail, also setting status to indicate current testcase should fail
-     */ 
+     */
     public void threadFail(String reason) {
         threadFailed = true;
         fail(reason);
@@ -213,7 +213,7 @@
     /**
      * If expression not true, set status to indicate current testcase
      * should fail
-     */ 
+     */
     public void threadAssertTrue(boolean b) {
         if (!b) {
             threadFailed = true;
@@ -224,7 +224,7 @@
     /**
      * If expression not false, set status to indicate current testcase
      * should fail
-     */ 
+     */
     public void threadAssertFalse(boolean b) {
         if (b) {
             threadFailed = true;
@@ -235,7 +235,7 @@
     /**
      * If argument not null, set status to indicate current testcase
      * should fail
-     */ 
+     */
     public void threadAssertNull(Object x) {
         if (x != null) {
             threadFailed = true;
@@ -246,7 +246,7 @@
     /**
      * If arguments not equal, set status to indicate current testcase
      * should fail
-     */ 
+     */
     public void threadAssertEquals(long x, long y) {
         if (x != y) {
             threadFailed = true;
@@ -257,7 +257,7 @@
     /**
      * If arguments not equal, set status to indicate current testcase
      * should fail
-     */ 
+     */
     public void threadAssertEquals(Object x, Object y) {
         if (x != y && (x == null || !x.equals(y))) {
             threadFailed = true;
@@ -267,10 +267,15 @@
 
     /**
      * threadFail with message "should throw exception"
-     */ 
+     */
     public void threadShouldThrow() {
-        threadFailed = true;
-        fail("should throw exception");
+       try {
+           threadFailed = true;
+           fail("should throw exception");
+       } catch (AssertionFailedError e) {
+           e.printStackTrace();
+           throw e;
+       }
     }
 
     /**
@@ -281,6 +286,14 @@
         fail("Unexpected exception");
     }
 
+    /**
+     * threadFail with message "Unexpected exception", with argument
+     */
+    public void threadUnexpectedException(Throwable ex) {
+        threadFailed = true;
+        ex.printStackTrace();
+        fail("Unexpected exception: " + ex);
+    }
 
     /**
      * Wait out termination of a thread pool or fail doing so
@@ -299,7 +312,7 @@
 
     /**
      * fail with message "should throw exception"
-     */ 
+     */
     public void shouldThrow() {
         fail("Should throw exception");
     }
@@ -334,6 +347,7 @@
     static final Integer m3  = new Integer(-3);
     static final Integer m4 = new Integer(-4);
     static final Integer m5 = new Integer(-5);
+    static final Integer m6 = new Integer(-6);
     static final Integer m10 = new Integer(-10);
 
 
@@ -389,7 +403,7 @@
                 Thread.sleep(SHORT_DELAY_MS);
             }
             catch(Exception e) {
-                threadUnexpectedException();
+                threadUnexpectedException(e);
             }
         }
     }
@@ -411,7 +425,7 @@
                 Thread.sleep(SMALL_DELAY_MS);
             }
             catch(Exception e) {
-                threadUnexpectedException();
+                threadUnexpectedException(e);
             }
         }
     }
@@ -432,7 +446,7 @@
                 Thread.sleep(SMALL_DELAY_MS);
             }
             catch(Exception e) {
-                threadUnexpectedException();
+                threadUnexpectedException(e);
             }
             return Boolean.TRUE;
         }
@@ -456,7 +470,7 @@
                 Thread.sleep(MEDIUM_DELAY_MS);
             }
             catch(Exception e) {
-                threadUnexpectedException();
+                threadUnexpectedException(e);
             }
         }
     }
@@ -498,7 +512,7 @@
     static class SimpleThreadFactory implements ThreadFactory{
         public Thread newThread(Runnable r){
             return new Thread(r);
-        }   
+        }
     }
 
     static class TrackedShortRunnable implements Runnable {
@@ -558,8 +572,8 @@
      * For use as RejectedExecutionHandler in constructors
      */
     static class NoOpREHandler implements RejectedExecutionHandler{
-        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor){} 
+        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor){}
     }
- 
-    
+
+
 }
diff --git a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/LinkedBlockingQueueTest.java b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/LinkedBlockingQueueTest.java
index 7496a4a..6648afb 100755
--- a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/LinkedBlockingQueueTest.java
+++ b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/LinkedBlockingQueueTest.java
@@ -16,7 +16,7 @@
 public class LinkedBlockingQueueTest extends JSR166TestCase {
 
     public static void main(String[] args) {
-        junit.textui.TestRunner.run (suite());        
+        junit.textui.TestRunner.run (suite());
     }
 
     public static Test suite() {
@@ -38,7 +38,7 @@
         assertEquals(n, q.size());
         return q;
     }
- 
+
     /**
      * A new queue has the indicated capacity, or Integer.MAX_VALUE if
      * none given
@@ -151,7 +151,7 @@
             LinkedBlockingQueue q = new LinkedBlockingQueue(1);
             q.offer(null);
             shouldThrow();
-        } catch (NullPointerException success) { }   
+        } catch (NullPointerException success) { }
     }
 
     /**
@@ -162,7 +162,7 @@
             LinkedBlockingQueue q = new LinkedBlockingQueue(1);
             q.add(null);
             shouldThrow();
-        } catch (NullPointerException success) { }   
+        } catch (NullPointerException success) { }
     }
 
     /**
@@ -186,7 +186,7 @@
             assertEquals(0, q.remainingCapacity());
             q.add(new Integer(SIZE));
         } catch (IllegalStateException success){
-        }   
+        }
     }
 
     /**
@@ -280,9 +280,9 @@
             LinkedBlockingQueue q = new LinkedBlockingQueue(SIZE);
             q.put(null);
             shouldThrow();
-        } 
+        }
         catch (NullPointerException success){
-        }   
+        }
         catch (InterruptedException ie) {
             unexpectedException();
         }
@@ -323,11 +323,11 @@
                         threadShouldThrow();
                     } catch (InterruptedException ie){
                         threadAssertEquals(added, SIZE);
-                    }   
+                    }
                 }});
         t.start();
-        try { 
-           Thread.sleep(SHORT_DELAY_MS); 
+        try {
+           Thread.sleep(SHORT_DELAY_MS);
            t.interrupt();
            t.join();
         }
@@ -386,7 +386,7 @@
                     } catch (InterruptedException success){}
                 }
             });
-        
+
         try {
             t.start();
             Thread.sleep(SMALL_DELAY_MS);
@@ -408,7 +408,7 @@
             }
         } catch (InterruptedException e){
             unexpectedException();
-        }   
+        }
     }
 
     /**
@@ -421,7 +421,7 @@
                     try {
                         q.take();
                         threadShouldThrow();
-                    } catch (InterruptedException success){ }                
+                    } catch (InterruptedException success){ }
                 }
             });
         try {
@@ -448,11 +448,11 @@
                         q.take();
                         threadShouldThrow();
                     } catch (InterruptedException success){
-                    }   
+                    }
                 }});
         t.start();
-        try { 
-           Thread.sleep(SHORT_DELAY_MS); 
+        try {
+           Thread.sleep(SHORT_DELAY_MS);
            t.interrupt();
            t.join();
         }
@@ -485,7 +485,7 @@
             assertNull(q.poll(0, TimeUnit.MILLISECONDS));
         } catch (InterruptedException e){
             unexpectedException();
-        }   
+        }
     }
 
     /**
@@ -500,7 +500,7 @@
             assertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
         } catch (InterruptedException e){
             unexpectedException();
-        }   
+        }
     }
 
     /**
@@ -517,11 +517,11 @@
                         }
                         threadAssertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
                     } catch (InterruptedException success){
-                    }   
+                    }
                 }});
         t.start();
-        try { 
-           Thread.sleep(SHORT_DELAY_MS); 
+        try {
+           Thread.sleep(SHORT_DELAY_MS);
            t.interrupt();
            t.join();
         }
@@ -543,7 +543,7 @@
                         q.poll(LONG_DELAY_MS, TimeUnit.MILLISECONDS);
                         q.poll(LONG_DELAY_MS, TimeUnit.MILLISECONDS);
                         threadShouldThrow();
-                    } catch (InterruptedException success) { }                
+                    } catch (InterruptedException success) { }
                 }
             });
         try {
@@ -555,7 +555,7 @@
         } catch (Exception e){
             unexpectedException();
         }
-    }  
+    }
 
     /**
      * peek returns next element, or null if empty
@@ -599,7 +599,7 @@
             q.remove();
             shouldThrow();
         } catch (NoSuchElementException success){
-        }   
+        }
     }
 
     /**
@@ -616,7 +616,24 @@
         }
         assertTrue(q.isEmpty());
     }
-        
+
+    /**
+     * An add following remove(x) succeeds
+     */
+    public void testRemoveElementAndAdd() {
+        try {
+            LinkedBlockingQueue q = new LinkedBlockingQueue();
+            assertTrue(q.add(new Integer(1)));
+            assertTrue(q.add(new Integer(2)));
+            assertTrue(q.remove(new Integer(1)));
+            assertTrue(q.remove(new Integer(2)));
+            assertTrue(q.add(new Integer(3)));
+            assertTrue(q.take() != null);
+        } catch (Exception e){
+            unexpectedException();
+        }
+    }
+
     /**
      * contains(x) reports true when elements added but not yet removed
      */
@@ -640,6 +657,7 @@
         assertEquals(SIZE, q.remainingCapacity());
         q.add(one);
         assertFalse(q.isEmpty());
+        assertTrue(q.contains(one));
         q.clear();
         assertTrue(q.isEmpty());
     }
@@ -704,7 +722,7 @@
             assertEquals(o[i], q.take());
         } catch (InterruptedException e){
             unexpectedException();
-        }    
+        }
     }
 
     /**
@@ -719,7 +737,7 @@
                 assertEquals(ints[i], q.take());
         } catch (InterruptedException e){
             unexpectedException();
-        }    
+        }
     }
 
     /**
@@ -744,7 +762,7 @@
         } catch(ArrayStoreException  success){}
     }
 
-    
+
     /**
      * iterator iterates through all elements
      */
@@ -757,7 +775,7 @@
             }
         } catch (InterruptedException e){
             unexpectedException();
-        }    
+        }
     }
 
     /**
@@ -772,7 +790,7 @@
         Iterator it = q.iterator();
         it.next();
         it.remove();
-        
+
         it = q.iterator();
         assertEquals(it.next(), one);
         assertEquals(it.next(), three);
@@ -827,7 +845,7 @@
         for (int i = 0; i < SIZE; ++i) {
             assertTrue(s.indexOf(String.valueOf(i)) >= 0);
         }
-    }        
+    }
 
 
     /**
@@ -862,7 +880,7 @@
                 }
             }
         });
-        
+
         joinPool(executor);
     }
 
@@ -896,7 +914,7 @@
                 }
             }
         });
-        
+
         joinPool(executor);
     }
 
@@ -916,7 +934,7 @@
             ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin));
             LinkedBlockingQueue r = (LinkedBlockingQueue)in.readObject();
             assertEquals(q.size(), r.size());
-            while (!q.isEmpty()) 
+            while (!q.isEmpty())
                 assertEquals(q.remove(), r.remove());
         } catch(Exception e){
             unexpectedException();
@@ -925,7 +943,7 @@
 
     /**
      * drainTo(null) throws NPE
-     */ 
+     */
     public void testDrainToNull() {
         LinkedBlockingQueue q = populatedQueue(SIZE);
         try {
@@ -937,7 +955,7 @@
 
     /**
      * drainTo(this) throws IAE
-     */ 
+     */
     public void testDrainToSelf() {
         LinkedBlockingQueue q = populatedQueue(SIZE);
         try {
@@ -949,27 +967,38 @@
 
     /**
      * drainTo(c) empties queue into another collection c
-     */ 
+     */
     public void testDrainTo() {
         LinkedBlockingQueue q = populatedQueue(SIZE);
         ArrayList l = new ArrayList();
         q.drainTo(l);
         assertEquals(q.size(), 0);
         assertEquals(l.size(), SIZE);
-        for (int i = 0; i < SIZE; ++i) 
+        for (int i = 0; i < SIZE; ++i)
+            assertEquals(l.get(i), new Integer(i));
+        q.add(zero);
+        q.add(one);
+        assertFalse(q.isEmpty());
+        assertTrue(q.contains(zero));
+        assertTrue(q.contains(one));
+        l.clear();
+        q.drainTo(l);
+        assertEquals(q.size(), 0);
+        assertEquals(l.size(), 2);
+        for (int i = 0; i < 2; ++i)
             assertEquals(l.get(i), new Integer(i));
     }
 
     /**
      * drainTo empties full queue, unblocking a waiting put.
-     */ 
+     */
     public void testDrainToWithActivePut() {
         final LinkedBlockingQueue q = populatedQueue(SIZE);
         Thread t = new Thread(new Runnable() {
                 public void run() {
                     try {
                         q.put(new Integer(SIZE+1));
-                    } catch (InterruptedException ie){ 
+                    } catch (InterruptedException ie){
                         threadUnexpectedException();
                     }
                 }
@@ -979,7 +1008,7 @@
             ArrayList l = new ArrayList();
             q.drainTo(l);
             assertTrue(l.size() >= SIZE);
-            for (int i = 0; i < SIZE; ++i) 
+            for (int i = 0; i < SIZE; ++i)
                 assertEquals(l.get(i), new Integer(i));
             t.join();
             assertTrue(q.size() + l.size() >= SIZE);
@@ -990,7 +1019,7 @@
 
     /**
      * drainTo(null, n) throws NPE
-     */ 
+     */
     public void testDrainToNullN() {
         LinkedBlockingQueue q = populatedQueue(SIZE);
         try {
@@ -1002,7 +1031,7 @@
 
     /**
      * drainTo(this, n) throws IAE
-     */ 
+     */
     public void testDrainToSelfN() {
         LinkedBlockingQueue q = populatedQueue(SIZE);
         try {
@@ -1014,17 +1043,20 @@
 
     /**
      * drainTo(c, n) empties first max {n, size} elements of queue into c
-     */ 
+     */
     public void testDrainToN() {
+        LinkedBlockingQueue q = new LinkedBlockingQueue();
         for (int i = 0; i < SIZE + 2; ++i) {
-            LinkedBlockingQueue q = populatedQueue(SIZE);
+            for(int j = 0; j < SIZE; j++)
+                assertTrue(q.offer(new Integer(j)));
             ArrayList l = new ArrayList();
             q.drainTo(l, i);
             int k = (i < SIZE)? i : SIZE;
-            assertEquals(q.size(), SIZE-k);
             assertEquals(l.size(), k);
-            for (int j = 0; j < k; ++j) 
+            assertEquals(q.size(), SIZE-k);
+            for (int j = 0; j < k; ++j)
                 assertEquals(l.get(j), new Integer(j));
+            while (q.poll() != null) ;
         }
     }
 
diff --git a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/LockSupportTest.java b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/LockSupportTest.java
index 8d74a3a..b39db2e 100755
--- a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/LockSupportTest.java
+++ b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/LockSupportTest.java
@@ -15,7 +15,7 @@
 
 public class LockSupportTest extends JSR166TestCase{
     public static void main(String[] args) {
-        junit.textui.TestRunner.run (suite());        
+        junit.textui.TestRunner.run (suite());
     }
     public static Test suite() {
         return new TestSuite(LockSupportTest.class);
@@ -24,7 +24,7 @@
     /**
      * park is released by unpark occurring after park
      */
-    public void testPark() { 
+    public void testPark() {
         Thread t = new Thread(new Runnable() {
                 public void run() {
                     try {
@@ -48,7 +48,7 @@
     /**
      * park is released by unpark occurring before park
      */
-    public void testPark2() { 
+    public void testPark2() {
         Thread t = new Thread(new Runnable() {
                 public void run() {
                     try {
@@ -70,15 +70,14 @@
     }
 
     /**
-     * park is released by interrupt 
+     * park is released by interrupt
      */
-    public void testPark3() { 
-        Thread t = new Thread(new Runnable() {
-                public void run() {
-                    try {
-                        LockSupport.park();
-                        threadAssertTrue(Thread.interrupted());
-                    } catch(Exception e){
+    public void testPark3() {
+	Thread t = new Thread(new Runnable() {
+		public void run() {
+		    try {
+			LockSupport.park();
+		    } catch(Exception e){
                         threadUnexpectedException();
                     }
                 }
@@ -97,7 +96,7 @@
     /**
      * park returns if interrupted before park
      */
-    public void testPark4() { 
+    public void testPark4() {
         final ReentrantLock lock = new ReentrantLock();
         lock.lock();
         Thread t = new Thread(new Runnable() {
@@ -124,7 +123,7 @@
     /**
      * parkNanos times out if not unparked
      */
-    public void testParkNanos() { 
+    public void testParkNanos() {
         Thread t = new Thread(new Runnable() {
                 public void run() {
                     try {
@@ -147,7 +146,7 @@
     /**
      * parkUntil times out if not unparked
      */
-    public void testParkUntil() { 
+    public void testParkUntil() {
         Thread t = new Thread(new Runnable() {
                 public void run() {
                     try {
diff --git a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/PriorityBlockingQueueTest.java b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/PriorityBlockingQueueTest.java
index b258963..3857e0f 100755
--- a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/PriorityBlockingQueueTest.java
+++ b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/PriorityBlockingQueueTest.java
@@ -628,9 +628,9 @@
         q.clear();
         assertTrue(q.isEmpty());
         assertEquals(0, q.size());
-        assertEquals(NOCAP, q.remainingCapacity());
-        q.add(new Integer(1));
+        q.add(one);
         assertFalse(q.isEmpty());
+        assertTrue(q.contains(one));
         q.clear();
         assertTrue(q.isEmpty());
     }
@@ -873,6 +873,17 @@
         assertEquals(l.size(), SIZE);
         for (int i = 0; i < SIZE; ++i) 
             assertEquals(l.get(i), new Integer(i));
+        q.add(zero);
+        q.add(one);
+        assertFalse(q.isEmpty());
+        assertTrue(q.contains(zero));
+        assertTrue(q.contains(one));
+        l.clear();
+        q.drainTo(l);
+        assertEquals(q.size(), 0);
+        assertEquals(l.size(), 2);
+        for (int i = 0; i < 2; ++i) 
+            assertEquals(l.get(i), new Integer(i));
     }
 
     /**
@@ -927,15 +938,18 @@
      * drainTo(c, n) empties first max {n, size} elements of queue into c
      */ 
     public void testDrainToN() {
+        PriorityBlockingQueue q = new PriorityBlockingQueue(SIZE*2);
         for (int i = 0; i < SIZE + 2; ++i) {
-            PriorityBlockingQueue q = populatedQueue(SIZE);
+            for(int j = 0; j < SIZE; j++)
+                assertTrue(q.offer(new Integer(j)));
             ArrayList l = new ArrayList();
             q.drainTo(l, i);
             int k = (i < SIZE)? i : SIZE;
-            assertEquals(q.size(), SIZE-k);
             assertEquals(l.size(), k);
+            assertEquals(q.size(), SIZE-k);
             for (int j = 0; j < k; ++j) 
-                assertTrue(l.contains(new Integer(j)));
+                assertEquals(l.get(j), new Integer(j));
+            while (q.poll() != null) ;
         }
     }
 
diff --git a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ReentrantLockTest.java b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ReentrantLockTest.java
index fdc9f31..c50482d 100755
--- a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ReentrantLockTest.java
+++ b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ReentrantLockTest.java
@@ -16,7 +16,7 @@
 
 public class ReentrantLockTest extends JSR166TestCase {
     public static void main(String[] args) {
-        junit.textui.TestRunner.run (suite());        
+        junit.textui.TestRunner.run (suite());
     }
     public static Test suite() {
         return new TestSuite(ReentrantLockTest.class);
@@ -56,11 +56,11 @@
      */
     static class PublicReentrantLock extends ReentrantLock {
         PublicReentrantLock() { super(); }
-        public Collection<Thread> getQueuedThreads() { 
-            return super.getQueuedThreads(); 
+        public Collection<Thread> getQueuedThreads() {
+            return super.getQueuedThreads();
         }
-        public Collection<Thread> getWaitingThreads(Condition c) { 
-            return super.getWaitingThreads(c); 
+        public Collection<Thread> getWaitingThreads(Condition c) {
+            return super.getWaitingThreads(c);
         }
 
 
@@ -69,7 +69,7 @@
     /**
      * Constructor sets given fairness
      */
-    public void testConstructor() { 
+    public void testConstructor() {
         ReentrantLock rl = new ReentrantLock();
         assertFalse(rl.isFair());
         ReentrantLock r2 = new ReentrantLock(true);
@@ -79,7 +79,7 @@
     /**
      * locking an unlocked lock succeeds
      */
-    public void testLock() { 
+    public void testLock() {
         ReentrantLock rl = new ReentrantLock();
         rl.lock();
         assertTrue(rl.isLocked());
@@ -89,7 +89,7 @@
     /**
      * locking an unlocked fair lock succeeds
      */
-    public void testFairLock() { 
+    public void testFairLock() {
         ReentrantLock rl = new ReentrantLock(true);
         rl.lock();
         assertTrue(rl.isLocked());
@@ -99,7 +99,7 @@
     /**
      * Unlocking an unlocked lock throws IllegalMonitorStateException
      */
-    public void testUnlock_IllegalMonitorStateException() { 
+    public void testUnlock_IllegalMonitorStateException() {
         ReentrantLock rl = new ReentrantLock();
         try {
             rl.unlock();
@@ -111,7 +111,7 @@
     /**
      * tryLock on an unlocked lock succeeds
      */
-    public void testTryLock() { 
+    public void testTryLock() {
         ReentrantLock rl = new ReentrantLock();
         assertTrue(rl.tryLock());
         assertTrue(rl.isLocked());
@@ -122,7 +122,7 @@
     /**
      * hasQueuedThreads reports whether there are waiting threads
      */
-    public void testhasQueuedThreads() { 
+    public void testhasQueuedThreads() {
         final ReentrantLock lock = new ReentrantLock();
         Thread t1 = new Thread(new InterruptedLockRunnable(lock));
         Thread t2 = new Thread(new InterruptibleLockRunnable(lock));
@@ -146,12 +146,12 @@
         } catch(Exception e){
             unexpectedException();
         }
-    } 
+    }
 
     /**
      * getQueueLength reports number of waiting threads
      */
-    public void testGetQueueLength() { 
+    public void testGetQueueLength() {
         final ReentrantLock lock = new ReentrantLock();
         Thread t1 = new Thread(new InterruptedLockRunnable(lock));
         Thread t2 = new Thread(new InterruptibleLockRunnable(lock));
@@ -175,12 +175,12 @@
         } catch(Exception e){
             unexpectedException();
         }
-    } 
+    }
 
     /**
      * getQueueLength reports number of waiting threads
      */
-    public void testGetQueueLength_fair() { 
+    public void testGetQueueLength_fair() {
         final ReentrantLock lock = new ReentrantLock(true);
         Thread t1 = new Thread(new InterruptedLockRunnable(lock));
         Thread t2 = new Thread(new InterruptibleLockRunnable(lock));
@@ -204,12 +204,12 @@
         } catch(Exception e){
             unexpectedException();
         }
-    } 
+    }
 
     /**
      * hasQueuedThread(null) throws NPE
      */
-    public void testHasQueuedThreadNPE() { 
+    public void testHasQueuedThreadNPE() {
         final ReentrantLock sync = new ReentrantLock();
         try {
             sync.hasQueuedThread(null);
@@ -221,7 +221,7 @@
     /**
      * hasQueuedThread reports whether a thread is queued.
      */
-    public void testHasQueuedThread() { 
+    public void testHasQueuedThread() {
         final ReentrantLock sync = new ReentrantLock();
         Thread t1 = new Thread(new InterruptedLockRunnable(sync));
         Thread t2 = new Thread(new InterruptibleLockRunnable(sync));
@@ -250,13 +250,13 @@
         } catch(Exception e){
             unexpectedException();
         }
-    } 
+    }
 
 
     /**
      * getQueuedThreads includes waiting threads
      */
-    public void testGetQueuedThreads() { 
+    public void testGetQueuedThreads() {
         final PublicReentrantLock lock = new PublicReentrantLock();
         Thread t1 = new Thread(new InterruptedLockRunnable(lock));
         Thread t2 = new Thread(new InterruptibleLockRunnable(lock));
@@ -283,13 +283,13 @@
         } catch(Exception e){
             unexpectedException();
         }
-    } 
+    }
 
 
     /**
      * timed tryLock is interruptible.
      */
-    public void testInterruptedException2() { 
+    public void testInterruptedException2() {
         final ReentrantLock lock = new ReentrantLock();
         lock.lock();
         Thread t = new Thread(new Runnable() {
@@ -312,7 +312,7 @@
     /**
      * TryLock on a locked lock fails
      */
-    public void testTryLockWhenLocked() { 
+    public void testTryLockWhenLocked() {
         final ReentrantLock lock = new ReentrantLock();
         lock.lock();
         Thread t = new Thread(new Runnable() {
@@ -327,12 +327,12 @@
         } catch(Exception e){
             unexpectedException();
         }
-    } 
+    }
 
     /**
      * Timed tryLock on a locked lock times out
      */
-    public void testTryLock_Timeout() { 
+    public void testTryLock_Timeout() {
         final ReentrantLock lock = new ReentrantLock();
         lock.lock();
         Thread t = new Thread(new Runnable() {
@@ -351,8 +351,8 @@
         } catch(Exception e){
             unexpectedException();
         }
-    } 
-    
+    }
+
     /**
      * getHoldCount returns number of recursive holds
      */
@@ -367,8 +367,8 @@
             assertEquals(i-1,lock.getHoldCount());
         }
     }
-    
-   
+
+
     /**
      * isLocked is true when locked and false when not
      */
@@ -378,7 +378,7 @@
         assertTrue(lock.isLocked());
         lock.unlock();
         assertFalse(lock.isLocked());
-        Thread t = new Thread(new Runnable() { 
+        Thread t = new Thread(new Runnable() {
                 public void run() {
                     lock.lock();
                     try {
@@ -405,25 +405,27 @@
     /**
      * lockInterruptibly is interruptible.
      */
-    public void testLockInterruptibly1() { 
+    public void testLockInterruptibly1() {
         final ReentrantLock lock = new ReentrantLock();
         lock.lock();
         Thread t = new Thread(new InterruptedLockRunnable(lock));
         try {
             t.start();
+            Thread.sleep(SHORT_DELAY_MS);
             t.interrupt();
+            Thread.sleep(SHORT_DELAY_MS);
             lock.unlock();
             t.join();
         } catch(Exception e){
             unexpectedException();
         }
-    } 
+    }
 
     /**
      * lockInterruptibly succeeds when unlocked, else is interruptible
      */
     public void testLockInterruptibly2() {
-        final ReentrantLock lock = new ReentrantLock();        
+        final ReentrantLock lock = new ReentrantLock();
         try {
             lock.lockInterruptibly();
         } catch(Exception e) {
@@ -445,7 +447,7 @@
      * Calling await without holding lock throws IllegalMonitorStateException
      */
     public void testAwait_IllegalMonitor() {
-        final ReentrantLock lock = new ReentrantLock();        
+        final ReentrantLock lock = new ReentrantLock();
         final Condition c = lock.newCondition();
         try {
             c.await();
@@ -462,7 +464,7 @@
      * Calling signal without holding lock throws IllegalMonitorStateException
      */
     public void testSignal_IllegalMonitor() {
-        final ReentrantLock lock = new ReentrantLock();        
+        final ReentrantLock lock = new ReentrantLock();
         final Condition c = lock.newCondition();
         try {
             c.signal();
@@ -479,7 +481,7 @@
      * awaitNanos without a signal times out
      */
     public void testAwaitNanos_Timeout() {
-        final ReentrantLock lock = new ReentrantLock();        
+        final ReentrantLock lock = new ReentrantLock();
         final Condition c = lock.newCondition();
         try {
             lock.lock();
@@ -496,11 +498,11 @@
      *  timed await without a signal times out
      */
     public void testAwait_Timeout() {
-        final ReentrantLock lock = new ReentrantLock();        
+        final ReentrantLock lock = new ReentrantLock();
         final Condition c = lock.newCondition();
         try {
             lock.lock();
-            assertFalse(c.await(SHORT_DELAY_MS, TimeUnit.MILLISECONDS));
+            c.await(SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
             lock.unlock();
         }
         catch (Exception ex) {
@@ -512,12 +514,12 @@
      * awaitUntil without a signal times out
      */
     public void testAwaitUntil_Timeout() {
-        final ReentrantLock lock = new ReentrantLock();        
+        final ReentrantLock lock = new ReentrantLock();
         final Condition c = lock.newCondition();
         try {
             lock.lock();
             java.util.Date d = new java.util.Date();
-            assertFalse(c.awaitUntil(new java.util.Date(d.getTime() + 10)));
+            c.awaitUntil(new java.util.Date(d.getTime() + 10));
             lock.unlock();
         }
         catch (Exception ex) {
@@ -529,9 +531,9 @@
      * await returns when signalled
      */
     public void testAwait() {
-        final ReentrantLock lock = new ReentrantLock();        
+        final ReentrantLock lock = new ReentrantLock();
         final Condition c = lock.newCondition();
-        Thread t = new Thread(new Runnable() { 
+        Thread t = new Thread(new Runnable() {
                 public void run() {
                     try {
                         lock.lock();
@@ -670,9 +672,9 @@
      * getWaitingThreads throws IAE if not owned
      */
     public void testGetWaitingThreadsIAE() {
-        final PublicReentrantLock lock = new PublicReentrantLock();        
+        final PublicReentrantLock lock = new PublicReentrantLock();
         final Condition c = (lock.newCondition());
-        final PublicReentrantLock lock2 = new PublicReentrantLock();        
+        final PublicReentrantLock lock2 = new PublicReentrantLock();
         try {
             lock2.getWaitingThreads(c);
             shouldThrow();
@@ -686,7 +688,7 @@
      * getWaitingThreads throws IMSE if not locked
      */
     public void testGetWaitingThreadsIMSE() {
-        final PublicReentrantLock lock = new PublicReentrantLock();        
+        final PublicReentrantLock lock = new PublicReentrantLock();
         final Condition c = (lock.newCondition());
         try {
             lock.getWaitingThreads(c);
@@ -703,9 +705,9 @@
      * hasWaiters returns true when a thread is waiting, else false
      */
     public void testHasWaiters() {
-        final ReentrantLock lock = new ReentrantLock();        
+        final ReentrantLock lock = new ReentrantLock();
         final Condition c = lock.newCondition();
-        Thread t = new Thread(new Runnable() { 
+        Thread t = new Thread(new Runnable() {
                 public void run() {
                     try {
                         lock.lock();
@@ -745,9 +747,9 @@
      * getWaitQueueLength returns number of waiting threads
      */
     public void testGetWaitQueueLength() {
-        final ReentrantLock lock = new ReentrantLock();        
+        final ReentrantLock lock = new ReentrantLock();
         final Condition c = lock.newCondition();
-        Thread t1 = new Thread(new Runnable() { 
+        Thread t1 = new Thread(new Runnable() {
                 public void run() {
                     try {
                         lock.lock();
@@ -762,7 +764,7 @@
                 }
             });
 
-        Thread t2 = new Thread(new Runnable() { 
+        Thread t2 = new Thread(new Runnable() {
                 public void run() {
                     try {
                         lock.lock();
@@ -806,9 +808,9 @@
      * getWaitingThreads returns only and all waiting threads
      */
     public void testGetWaitingThreads() {
-        final PublicReentrantLock lock = new PublicReentrantLock();        
+        final PublicReentrantLock lock = new PublicReentrantLock();
         final Condition c = lock.newCondition();
-        Thread t1 = new Thread(new Runnable() { 
+        Thread t1 = new Thread(new Runnable() {
                 public void run() {
                     try {
                         lock.lock();
@@ -822,7 +824,7 @@
                 }
             });
 
-        Thread t2 = new Thread(new Runnable() { 
+        Thread t2 = new Thread(new Runnable() {
                 public void run() {
                     try {
                         lock.lock();
@@ -865,34 +867,61 @@
         }
     }
 
+    /** A helper class for uninterruptible wait tests */
+    class UninterruptableThread extends Thread {
+        private ReentrantLock lock;
+        private Condition c;
 
+        public volatile boolean canAwake = false;
+        public volatile boolean interrupted = false;
+        public volatile boolean lockStarted = false;
+
+        public UninterruptableThread(ReentrantLock lock, Condition c) {
+            this.lock = lock;
+            this.c = c;
+        }
+
+        public synchronized void run() {
+            lock.lock();
+            lockStarted = true;
+
+            while (!canAwake) {
+                c.awaitUninterruptibly();
+            }
+
+            interrupted = isInterrupted();
+            lock.unlock();
+        }
+    }
 
     /**
      * awaitUninterruptibly doesn't abort on interrupt
      */
     public void testAwaitUninterruptibly() {
-        final ReentrantLock lock = new ReentrantLock();        
+        final ReentrantLock lock = new ReentrantLock();
         final Condition c = lock.newCondition();
-        Thread t = new Thread(new Runnable() { 
-                public void run() {
-                    lock.lock();
-                    c.awaitUninterruptibly();
-                    lock.unlock();
-                }
-            });
+        UninterruptableThread thread = new UninterruptableThread(lock, c);
 
         try {
-            t.start();
-            Thread.sleep(SHORT_DELAY_MS);
-            t.interrupt();
+            thread.start();
+
+            while (!thread.lockStarted) {
+                Thread.sleep(100);
+            }
+
             lock.lock();
-            c.signal();
-            lock.unlock();
-            assert(t.isInterrupted());
-            t.join(SHORT_DELAY_MS);
-            assertFalse(t.isAlive());
-        }
-        catch (Exception ex) {
+            try {
+                thread.interrupt();
+                thread.canAwake = true;
+                c.signal();
+            } finally {
+                lock.unlock();
+            }
+
+            thread.join();
+            assertTrue(thread.interrupted);
+            assertFalse(thread.isAlive());
+        } catch (Exception ex) {
             unexpectedException();
         }
     }
@@ -901,9 +930,9 @@
      * await is interruptible
      */
     public void testAwait_Interrupt() {
-        final ReentrantLock lock = new ReentrantLock();        
+        final ReentrantLock lock = new ReentrantLock();
         final Condition c = lock.newCondition();
-        Thread t = new Thread(new Runnable() { 
+        Thread t = new Thread(new Runnable() {
                 public void run() {
                     try {
                         lock.lock();
@@ -932,9 +961,9 @@
      * awaitNanos is interruptible
      */
     public void testAwaitNanos_Interrupt() {
-        final ReentrantLock lock = new ReentrantLock();        
+        final ReentrantLock lock = new ReentrantLock();
         final Condition c = lock.newCondition();
-        Thread t = new Thread(new Runnable() { 
+        Thread t = new Thread(new Runnable() {
                 public void run() {
                     try {
                         lock.lock();
@@ -963,9 +992,9 @@
      * awaitUntil is interruptible
      */
     public void testAwaitUntil_Interrupt() {
-        final ReentrantLock lock = new ReentrantLock();        
+        final ReentrantLock lock = new ReentrantLock();
         final Condition c = lock.newCondition();
-        Thread t = new Thread(new Runnable() { 
+        Thread t = new Thread(new Runnable() {
                 public void run() {
                     try {
                         lock.lock();
@@ -995,9 +1024,9 @@
      * signalAll wakes up all threads
      */
     public void testSignalAll() {
-        final ReentrantLock lock = new ReentrantLock();        
+        final ReentrantLock lock = new ReentrantLock();
         final Condition c = lock.newCondition();
-        Thread t1 = new Thread(new Runnable() { 
+        Thread t1 = new Thread(new Runnable() {
                 public void run() {
                     try {
                         lock.lock();
@@ -1010,7 +1039,7 @@
                 }
             });
 
-        Thread t2 = new Thread(new Runnable() { 
+        Thread t2 = new Thread(new Runnable() {
                 public void run() {
                     try {
                         lock.lock();
@@ -1041,6 +1070,61 @@
     }
 
     /**
+     * await after multiple reentrant locking preserves lock count
+     */
+    public void testAwaitLockCount() {
+	final ReentrantLock lock = new ReentrantLock();
+        final Condition c = lock.newCondition();
+	Thread t1 = new Thread(new Runnable() {
+		public void run() {
+		    try {
+			lock.lock();
+                        threadAssertEquals(1, lock.getHoldCount());
+                        c.await();
+                        threadAssertEquals(1, lock.getHoldCount());
+                        lock.unlock();
+		    }
+		    catch(InterruptedException e) {
+                        threadUnexpectedException();
+                    }
+		}
+	    });
+
+	Thread t2 = new Thread(new Runnable() {
+		public void run() {
+		    try {
+			lock.lock();
+			lock.lock();
+                        threadAssertEquals(2, lock.getHoldCount());
+                        c.await();
+                        threadAssertEquals(2, lock.getHoldCount());
+                        lock.unlock();
+                        lock.unlock();
+		    }
+		    catch(InterruptedException e) {
+                        threadUnexpectedException();
+                    }
+		}
+	    });
+
+        try {
+            t1.start();
+            t2.start();
+            Thread.sleep(SHORT_DELAY_MS);
+            lock.lock();
+            c.signalAll();
+            lock.unlock();
+            t1.join(SHORT_DELAY_MS);
+            t2.join(SHORT_DELAY_MS);
+            assertFalse(t1.isAlive());
+            assertFalse(t2.isAlive());
+        }
+        catch (Exception ex) {
+            unexpectedException();
+        }
+    }
+
+    /**
      * A serialized lock deserializes as unlocked
      */
     public void testSerialization() {
diff --git a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ReentrantReadWriteLockTest.java b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ReentrantReadWriteLockTest.java
index 8925b42..e38165a 100644
--- a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ReentrantReadWriteLockTest.java
+++ b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ReentrantReadWriteLockTest.java
@@ -16,7 +16,7 @@
 
 public class ReentrantReadWriteLockTest extends JSR166TestCase {
     public static void main(String[] args) {
-        junit.textui.TestRunner.run (suite());        
+        junit.textui.TestRunner.run (suite());
     }
     public static Test suite() {
         return new TestSuite(ReentrantReadWriteLockTest.class);
@@ -56,18 +56,18 @@
      */
     static class PublicReentrantReadWriteLock extends ReentrantReadWriteLock {
         PublicReentrantReadWriteLock() { super(); }
-        public Collection<Thread> getQueuedThreads() { 
-            return super.getQueuedThreads(); 
+        public Collection<Thread> getQueuedThreads() {
+            return super.getQueuedThreads();
         }
-        public Collection<Thread> getWaitingThreads(Condition c) { 
-            return super.getWaitingThreads(c); 
+        public Collection<Thread> getWaitingThreads(Condition c) {
+            return super.getWaitingThreads(c);
         }
     }
 
     /**
      * Constructor sets given fairness, and is in unlocked state
      */
-    public void testConstructor() { 
+    public void testConstructor() {
         ReentrantReadWriteLock rl = new ReentrantReadWriteLock();
         assertFalse(rl.isFair());
         assertFalse(rl.isWriteLocked());
@@ -81,7 +81,7 @@
     /**
      * write-locking and read-locking an unlocked lock succeed
      */
-    public void testLock() { 
+    public void testLock() {
         ReentrantReadWriteLock rl = new ReentrantReadWriteLock();
         rl.writeLock().lock();
         assertTrue(rl.isWriteLocked());
@@ -105,7 +105,7 @@
     /**
      * locking an unlocked fair lock succeeds
      */
-    public void testFairLock() { 
+    public void testFairLock() {
         ReentrantReadWriteLock rl = new ReentrantReadWriteLock(true);
         rl.writeLock().lock();
         assertTrue(rl.isWriteLocked());
@@ -128,23 +128,23 @@
     /**
      * getWriteHoldCount returns number of recursive holds
      */
-    public void testGetHoldCount() {
-        ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
-        for(int i = 1; i <= SIZE; i++) {
-            lock.writeLock().lock();
-            assertEquals(i,lock.getWriteHoldCount());
-        }
-        for(int i = SIZE; i > 0; i--) {
-            lock.writeLock().unlock();
-            assertEquals(i-1,lock.getWriteHoldCount());
-        }
+    public void testGetWriteHoldCount() {
+	ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+	for(int i = 1; i <= SIZE; i++) {
+	    lock.writeLock().lock();
+	    assertEquals(i,lock.getWriteHoldCount());
+	}
+	for(int i = SIZE; i > 0; i--) {
+	    lock.writeLock().unlock();
+	    assertEquals(i-1,lock.getWriteHoldCount());
+	}
     }
-    
+
 
     /**
      * write-unlocking an unlocked lock throws IllegalMonitorStateException
      */
-    public void testUnlock_IllegalMonitorStateException() { 
+    public void testUnlock_IllegalMonitorStateException() {
         ReentrantReadWriteLock rl = new ReentrantReadWriteLock();
         try {
             rl.writeLock().unlock();
@@ -156,7 +156,7 @@
     /**
      * write-lockInterruptibly is interruptible
      */
-    public void testWriteLockInterruptibly_Interrupted() { 
+    public void testWriteLockInterruptibly_Interrupted() {
         final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         Thread t = new Thread(new Runnable() {
                 public void run() {
@@ -171,18 +171,20 @@
         try {
             lock.writeLock().lock();
             t.start();
+            Thread.sleep(SHORT_DELAY_MS);
             t.interrupt();
+            Thread.sleep(SHORT_DELAY_MS);
             lock.writeLock().unlock();
             t.join();
         } catch(Exception e){
             unexpectedException();
         }
-    } 
+    }
 
     /**
      * timed write-tryLock is interruptible
      */
-    public void testWriteTryLock_Interrupted() { 
+    public void testWriteTryLock_Interrupted() {
         final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         lock.writeLock().lock();
         Thread t = new Thread(new Runnable() {
@@ -205,7 +207,7 @@
     /**
      * read-lockInterruptibly is interruptible
      */
-    public void testReadLockInterruptibly_Interrupted() { 
+    public void testReadLockInterruptibly_Interrupted() {
         final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         lock.writeLock().lock();
         Thread t = new Thread(new Runnable() {
@@ -217,18 +219,20 @@
             });
         try {
             t.start();
+            Thread.sleep(SHORT_DELAY_MS);
             t.interrupt();
+            Thread.sleep(SHORT_DELAY_MS);
             lock.writeLock().unlock();
             t.join();
         } catch(Exception e){
             unexpectedException();
         }
-    } 
+    }
 
     /**
      * timed read-tryLock is interruptible
      */
-    public void testReadTryLock_Interrupted() { 
+    public void testReadTryLock_Interrupted() {
         final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         lock.writeLock().lock();
         Thread t = new Thread(new Runnable() {
@@ -248,11 +252,11 @@
         }
     }
 
-    
+
     /**
      * write-tryLock fails if locked
      */
-    public void testWriteTryLockWhenLocked() { 
+    public void testWriteTryLockWhenLocked() {
         final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         lock.writeLock().lock();
         Thread t = new Thread(new Runnable() {
@@ -267,12 +271,12 @@
         } catch(Exception e){
             unexpectedException();
         }
-    } 
+    }
 
     /**
      * read-tryLock fails if locked
      */
-    public void testReadTryLockWhenLocked() { 
+    public void testReadTryLockWhenLocked() {
         final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         lock.writeLock().lock();
         Thread t = new Thread(new Runnable() {
@@ -287,12 +291,12 @@
         } catch(Exception e){
             unexpectedException();
         }
-    } 
+    }
 
     /**
      * Multiple threads can hold a read lock when not write-locked
      */
-    public void testMultipleReadLocks() { 
+    public void testMultipleReadLocks() {
         final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         lock.readLock().lock();
         Thread t = new Thread(new Runnable() {
@@ -308,12 +312,12 @@
         } catch(Exception e){
             unexpectedException();
         }
-    } 
+    }
 
     /**
      * A writelock succeeds after reading threads unlock
      */
-    public void testWriteAfterMultipleReadLocks() { 
+    public void testWriteAfterMultipleReadLocks() {
         final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         lock.readLock().lock();
         Thread t1 = new Thread(new Runnable() {
@@ -338,16 +342,16 @@
             t2.join(MEDIUM_DELAY_MS);
             assertTrue(!t1.isAlive());
             assertTrue(!t2.isAlive());
-           
+
         } catch(Exception e){
             unexpectedException();
         }
-    } 
+    }
 
     /**
      * Readlocks succeed after a writing thread unlocks
      */
-    public void testReadAfterWriteLock() { 
+    public void testReadAfterWriteLock() {
         final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         lock.writeLock().lock();
         Thread t1 = new Thread(new Runnable() {
@@ -372,17 +376,280 @@
             t2.join(MEDIUM_DELAY_MS);
             assertTrue(!t1.isAlive());
             assertTrue(!t2.isAlive());
-           
+
         } catch(Exception e){
             unexpectedException();
         }
-    } 
+    }
+
+    /**
+     * Read trylock succeeds if write locked by current thread
+     */
+    public void testReadHoldingWriteLock() {
+	final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+	lock.writeLock().lock();
+        assertTrue(lock.readLock().tryLock());
+        lock.readLock().unlock();
+        lock.writeLock().unlock();
+    }
+
+    /**
+     * Read lock succeeds if write locked by current thread even if
+     * other threads are waiting for readlock
+     */
+    public void testReadHoldingWriteLock2() {
+	final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+	lock.writeLock().lock();
+	Thread t1 = new Thread(new Runnable() {
+                public void run() {
+                    lock.readLock().lock();
+                    lock.readLock().unlock();
+		}
+	    });
+	Thread t2 = new Thread(new Runnable() {
+                public void run() {
+                    lock.readLock().lock();
+                    lock.readLock().unlock();
+		}
+	    });
+
+        try {
+            t1.start();
+            t2.start();
+            lock.readLock().lock();
+            lock.readLock().unlock();
+            Thread.sleep(SHORT_DELAY_MS);
+            lock.readLock().lock();
+            lock.readLock().unlock();
+            lock.writeLock().unlock();
+            t1.join(MEDIUM_DELAY_MS);
+            t2.join(MEDIUM_DELAY_MS);
+            assertTrue(!t1.isAlive());
+            assertTrue(!t2.isAlive());
+
+        } catch(Exception e){
+            unexpectedException();
+        }
+    }
+
+    /**
+     *  Read lock succeeds if write locked by current thread even if
+     * other threads are waiting for writelock
+     */
+    public void testReadHoldingWriteLock3() {
+	final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+	lock.writeLock().lock();
+	Thread t1 = new Thread(new Runnable() {
+                public void run() {
+                    lock.writeLock().lock();
+                    lock.writeLock().unlock();
+		}
+	    });
+	Thread t2 = new Thread(new Runnable() {
+                public void run() {
+                    lock.writeLock().lock();
+                    lock.writeLock().unlock();
+		}
+	    });
+
+        try {
+            t1.start();
+            t2.start();
+            lock.readLock().lock();
+            lock.readLock().unlock();
+            Thread.sleep(SHORT_DELAY_MS);
+            lock.readLock().lock();
+            lock.readLock().unlock();
+            lock.writeLock().unlock();
+            t1.join(MEDIUM_DELAY_MS);
+            t2.join(MEDIUM_DELAY_MS);
+            assertTrue(!t1.isAlive());
+            assertTrue(!t2.isAlive());
+
+        } catch(Exception e){
+            unexpectedException();
+        }
+    }
+
+
+    /**
+     *  Write lock succeeds if write locked by current thread even if
+     * other threads are waiting for writelock
+     */
+    public void testWriteHoldingWriteLock4() {
+	final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+	lock.writeLock().lock();
+	Thread t1 = new Thread(new Runnable() {
+                public void run() {
+                    lock.writeLock().lock();
+                    lock.writeLock().unlock();
+		}
+	    });
+	Thread t2 = new Thread(new Runnable() {
+                public void run() {
+                    lock.writeLock().lock();
+                    lock.writeLock().unlock();
+		}
+	    });
+
+        try {
+            t1.start();
+            t2.start();
+            lock.writeLock().lock();
+            lock.writeLock().unlock();
+            Thread.sleep(SHORT_DELAY_MS);
+            lock.writeLock().lock();
+            lock.writeLock().unlock();
+            lock.writeLock().unlock();
+            t1.join(MEDIUM_DELAY_MS);
+            t2.join(MEDIUM_DELAY_MS);
+            assertTrue(!t1.isAlive());
+            assertTrue(!t2.isAlive());
+
+        } catch(Exception e){
+            unexpectedException();
+        }
+    }
+
+
+    /**
+     * Fair Read trylock succeeds if write locked by current thread
+     */
+    public void testReadHoldingWriteLockFair() {
+	final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
+	lock.writeLock().lock();
+        assertTrue(lock.readLock().tryLock());
+        lock.readLock().unlock();
+        lock.writeLock().unlock();
+    }
+
+    /**
+     * Fair Read lock succeeds if write locked by current thread even if
+     * other threads are waiting for readlock
+     */
+    public void testReadHoldingWriteLockFair2() {
+	final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
+	lock.writeLock().lock();
+	Thread t1 = new Thread(new Runnable() {
+                public void run() {
+                    lock.readLock().lock();
+                    lock.readLock().unlock();
+		}
+	    });
+	Thread t2 = new Thread(new Runnable() {
+                public void run() {
+                    lock.readLock().lock();
+                    lock.readLock().unlock();
+		}
+	    });
+
+        try {
+            t1.start();
+            t2.start();
+            lock.readLock().lock();
+            lock.readLock().unlock();
+            Thread.sleep(SHORT_DELAY_MS);
+            lock.readLock().lock();
+            lock.readLock().unlock();
+            lock.writeLock().unlock();
+            t1.join(MEDIUM_DELAY_MS);
+            t2.join(MEDIUM_DELAY_MS);
+            assertTrue(!t1.isAlive());
+            assertTrue(!t2.isAlive());
+
+        } catch(Exception e){
+            unexpectedException();
+        }
+    }
+
+
+    /**
+     * Fair Read lock succeeds if write locked by current thread even if
+     * other threads are waiting for writelock
+     */
+    public void testReadHoldingWriteLockFair3() {
+	final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
+	lock.writeLock().lock();
+	Thread t1 = new Thread(new Runnable() {
+                public void run() {
+                    lock.writeLock().lock();
+                    lock.writeLock().unlock();
+		}
+	    });
+	Thread t2 = new Thread(new Runnable() {
+                public void run() {
+                    lock.writeLock().lock();
+                    lock.writeLock().unlock();
+		}
+	    });
+
+        try {
+            t1.start();
+            t2.start();
+            lock.readLock().lock();
+            lock.readLock().unlock();
+            Thread.sleep(SHORT_DELAY_MS);
+            lock.readLock().lock();
+            lock.readLock().unlock();
+            lock.writeLock().unlock();
+            t1.join(MEDIUM_DELAY_MS);
+            t2.join(MEDIUM_DELAY_MS);
+            assertTrue(!t1.isAlive());
+            assertTrue(!t2.isAlive());
+
+        } catch(Exception e){
+            unexpectedException();
+        }
+    }
+
+
+    /**
+     * Fair Write lock succeeds if write locked by current thread even if
+     * other threads are waiting for writelock
+     */
+    public void testWriteHoldingWriteLockFair4() {
+	final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
+	lock.writeLock().lock();
+	Thread t1 = new Thread(new Runnable() {
+                public void run() {
+                    lock.writeLock().lock();
+                    lock.writeLock().unlock();
+		}
+	    });
+	Thread t2 = new Thread(new Runnable() {
+                public void run() {
+                    lock.writeLock().lock();
+                    lock.writeLock().unlock();
+		}
+	    });
+
+        try {
+            t1.start();
+            t2.start();
+            Thread.sleep(SHORT_DELAY_MS);
+            assertTrue(lock.isWriteLockedByCurrentThread());
+            assertTrue(lock.getWriteHoldCount() == 1);
+            lock.writeLock().lock();
+            assertTrue(lock.getWriteHoldCount() == 2);
+            lock.writeLock().unlock();
+            lock.writeLock().lock();
+            lock.writeLock().unlock();
+            lock.writeLock().unlock();
+            t1.join(MEDIUM_DELAY_MS);
+            t2.join(MEDIUM_DELAY_MS);
+            assertTrue(!t1.isAlive());
+            assertTrue(!t2.isAlive());
+
+        } catch(Exception e){
+            unexpectedException();
+        }
+    }
 
 
     /**
      * Read tryLock succeeds if readlocked but not writelocked
      */
-    public void testTryLockWhenReadLocked() { 
+    public void testTryLockWhenReadLocked() {
         final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         lock.readLock().lock();
         Thread t = new Thread(new Runnable() {
@@ -398,14 +665,14 @@
         } catch(Exception e){
             unexpectedException();
         }
-    } 
+    }
 
-    
+
 
     /**
      * write tryLock fails when readlocked
      */
-    public void testWriteTryLockWhenReadLocked() { 
+    public void testWriteTryLockWhenReadLocked() {
         final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         lock.readLock().lock();
         Thread t = new Thread(new Runnable() {
@@ -420,14 +687,58 @@
         } catch(Exception e){
             unexpectedException();
         }
-    } 
+    }
 
-    
+
+    /**
+     * Fair Read tryLock succeeds if readlocked but not writelocked
+     */
+    public void testTryLockWhenReadLockedFair() {
+	final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
+	lock.readLock().lock();
+	Thread t = new Thread(new Runnable() {
+                public void run() {
+                    threadAssertTrue(lock.readLock().tryLock());
+                    lock.readLock().unlock();
+		}
+	    });
+        try {
+            t.start();
+            t.join();
+            lock.readLock().unlock();
+        } catch(Exception e){
+            unexpectedException();
+        }
+    }
+
+
+
+    /**
+     * Fair write tryLock fails when readlocked
+     */
+    public void testWriteTryLockWhenReadLockedFair() {
+	final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
+	lock.readLock().lock();
+	Thread t = new Thread(new Runnable() {
+                public void run() {
+                    threadAssertFalse(lock.writeLock().tryLock());
+		}
+	    });
+        try {
+            t.start();
+            t.join();
+            lock.readLock().unlock();
+        } catch(Exception e){
+            unexpectedException();
+        }
+    }
+
+
 
     /**
      * write timed tryLock times out if locked
      */
-    public void testWriteTryLock_Timeout() { 
+    public void testWriteTryLock_Timeout() {
         final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         lock.writeLock().lock();
         Thread t = new Thread(new Runnable() {
@@ -446,12 +757,12 @@
         } catch(Exception e){
             unexpectedException();
         }
-    } 
+    }
 
     /**
      * read timed tryLock times out if write-locked
      */
-    public void testReadTryLock_Timeout() { 
+    public void testReadTryLock_Timeout() {
         final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         lock.writeLock().lock();
         Thread t = new Thread(new Runnable() {
@@ -470,7 +781,7 @@
         } catch(Exception e){
             unexpectedException();
         }
-    } 
+    }
 
 
     /**
@@ -483,7 +794,7 @@
         } catch(Exception e) {
             unexpectedException();
         }
-        Thread t = new Thread(new Runnable() { 
+        Thread t = new Thread(new Runnable() {
                 public void run() {
                     try {
                         lock.writeLock().lockInterruptibly();
@@ -495,7 +806,9 @@
             });
         try {
             t.start();
+            Thread.sleep(SHORT_DELAY_MS);
             t.interrupt();
+            Thread.sleep(SHORT_DELAY_MS);
             t.join();
             lock.writeLock().unlock();
         } catch(Exception e){
@@ -513,7 +826,7 @@
         } catch(Exception e) {
             unexpectedException();
         }
-        Thread t = new Thread(new Runnable() { 
+        Thread t = new Thread(new Runnable() {
                 public void run() {
                     try {
                         lock.readLock().lockInterruptibly();
@@ -525,6 +838,7 @@
             });
         try {
             t.start();
+            Thread.sleep(SHORT_DELAY_MS);
             t.interrupt();
             t.join();
             lock.writeLock().unlock();
@@ -537,7 +851,7 @@
      * Calling await without holding lock throws IllegalMonitorStateException
      */
     public void testAwait_IllegalMonitor() {
-        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();        
+        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         final Condition c = lock.writeLock().newCondition();
         try {
             c.await();
@@ -554,7 +868,7 @@
      * Calling signal without holding lock throws IllegalMonitorStateException
      */
     public void testSignal_IllegalMonitor() {
-        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();        
+        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         final Condition c = lock.writeLock().newCondition();
         try {
             c.signal();
@@ -571,7 +885,7 @@
      * awaitNanos without a signal times out
      */
     public void testAwaitNanos_Timeout() {
-        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();        
+        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         final Condition c = lock.writeLock().newCondition();
         try {
             lock.writeLock().lock();
@@ -589,11 +903,10 @@
      *  timed await without a signal times out
      */
     public void testAwait_Timeout() {
-        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();        
+        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         final Condition c = lock.writeLock().newCondition();
         try {
             lock.writeLock().lock();
-            assertFalse(c.await(10, TimeUnit.MILLISECONDS));
             lock.writeLock().unlock();
         }
         catch (Exception ex) {
@@ -605,12 +918,11 @@
      * awaitUntil without a signal times out
      */
     public void testAwaitUntil_Timeout() {
-        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();        
+        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         final Condition c = lock.writeLock().newCondition();
         try {
             lock.writeLock().lock();
             java.util.Date d = new java.util.Date();
-            assertFalse(c.awaitUntil(new java.util.Date(d.getTime() + 10)));
             lock.writeLock().unlock();
         }
         catch (Exception ex) {
@@ -622,9 +934,9 @@
      * await returns when signalled
      */
     public void testAwait() {
-        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();        
+        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         final Condition c = lock.writeLock().newCondition();
-        Thread t = new Thread(new Runnable() { 
+        Thread t = new Thread(new Runnable() {
                 public void run() {
                     try {
                         lock.writeLock().lock();
@@ -651,32 +963,61 @@
         }
     }
 
+    /** A helper class for uninterruptible wait tests */
+    class UninterruptableThread extends Thread {
+        private Lock lock;
+        private Condition c;
+
+        public volatile boolean canAwake = false;
+        public volatile boolean interrupted = false;
+        public volatile boolean lockStarted = false;
+
+        public UninterruptableThread(Lock lock, Condition c) {
+            this.lock = lock;
+            this.c = c;
+        }
+
+        public synchronized void run() {
+            lock.lock();
+            lockStarted = true;
+
+            while (!canAwake) {
+                c.awaitUninterruptibly();
+            }
+
+            interrupted = isInterrupted();
+            lock.unlock();
+        }
+    }
+
     /**
      * awaitUninterruptibly doesn't abort on interrupt
      */
     public void testAwaitUninterruptibly() {
-        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();        
+        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         final Condition c = lock.writeLock().newCondition();
-        Thread t = new Thread(new Runnable() { 
-                public void run() {
-                    lock.writeLock().lock();
-                    c.awaitUninterruptibly();
-                    lock.writeLock().unlock();
-                }
-            });
+        UninterruptableThread thread = new UninterruptableThread(lock.writeLock(), c);
 
         try {
-            t.start();
-            Thread.sleep(SHORT_DELAY_MS);
-            t.interrupt();
+            thread.start();
+
+            while (!thread.lockStarted) {
+                Thread.sleep(100);
+            }
+
             lock.writeLock().lock();
-            c.signal();
-            lock.writeLock().unlock();
-            assert(t.isInterrupted());
-            t.join(SHORT_DELAY_MS);
-            assertFalse(t.isAlive());
-        }
-        catch (Exception ex) {
+            try {
+                thread.interrupt();
+                thread.canAwake = true;
+                c.signal();
+            } finally {
+                lock.writeLock().unlock();
+            }
+
+            thread.join();
+            assertTrue(thread.interrupted);
+            assertFalse(thread.isAlive());
+        } catch (Exception ex) {
             unexpectedException();
         }
     }
@@ -685,9 +1026,9 @@
      * await is interruptible
      */
     public void testAwait_Interrupt() {
-        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();        
+        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         final Condition c = lock.writeLock().newCondition();
-        Thread t = new Thread(new Runnable() { 
+        Thread t = new Thread(new Runnable() {
                 public void run() {
                     try {
                         lock.writeLock().lock();
@@ -716,9 +1057,9 @@
      * awaitNanos is interruptible
      */
     public void testAwaitNanos_Interrupt() {
-        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();        
+        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         final Condition c = lock.writeLock().newCondition();
-        Thread t = new Thread(new Runnable() { 
+        Thread t = new Thread(new Runnable() {
                 public void run() {
                     try {
                         lock.writeLock().lock();
@@ -747,9 +1088,9 @@
      * awaitUntil is interruptible
      */
     public void testAwaitUntil_Interrupt() {
-        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();        
+        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         final Condition c = lock.writeLock().newCondition();
-        Thread t = new Thread(new Runnable() { 
+        Thread t = new Thread(new Runnable() {
                 public void run() {
                     try {
                         lock.writeLock().lock();
@@ -779,9 +1120,9 @@
      * signalAll wakes up all threads
      */
     public void testSignalAll() {
-        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();        
+        final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         final Condition c = lock.writeLock().newCondition();
-        Thread t1 = new Thread(new Runnable() { 
+        Thread t1 = new Thread(new Runnable() {
                 public void run() {
                     try {
                         lock.writeLock().lock();
@@ -794,7 +1135,7 @@
                 }
             });
 
-        Thread t2 = new Thread(new Runnable() { 
+        Thread t2 = new Thread(new Runnable() {
                 public void run() {
                     try {
                         lock.writeLock().lock();
@@ -852,7 +1193,7 @@
     /**
      * hasQueuedThreads reports whether there are waiting threads
      */
-    public void testhasQueuedThreads() { 
+    public void testhasQueuedThreads() {
         final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         Thread t1 = new Thread(new InterruptedLockRunnable(lock));
         Thread t2 = new Thread(new InterruptibleLockRunnable(lock));
@@ -876,12 +1217,12 @@
         } catch(Exception e){
             unexpectedException();
         }
-    } 
+    }
 
     /**
      * hasQueuedThread(null) throws NPE
      */
-    public void testHasQueuedThreadNPE() { 
+    public void testHasQueuedThreadNPE() {
         final ReentrantReadWriteLock sync = new ReentrantReadWriteLock();
         try {
             sync.hasQueuedThread(null);
@@ -893,7 +1234,7 @@
     /**
      * hasQueuedThread reports whether a thread is queued.
      */
-    public void testHasQueuedThread() { 
+    public void testHasQueuedThread() {
         final ReentrantReadWriteLock sync = new ReentrantReadWriteLock();
         Thread t1 = new Thread(new InterruptedLockRunnable(sync));
         Thread t2 = new Thread(new InterruptibleLockRunnable(sync));
@@ -922,13 +1263,13 @@
         } catch(Exception e){
             unexpectedException();
         }
-    } 
+    }
 
 
     /**
      * getQueueLength reports number of waiting threads
      */
-    public void testGetQueueLength() { 
+    public void testGetQueueLength() {
         final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         Thread t1 = new Thread(new InterruptedLockRunnable(lock));
         Thread t2 = new Thread(new InterruptibleLockRunnable(lock));
@@ -952,12 +1293,12 @@
         } catch(Exception e){
             unexpectedException();
         }
-    } 
+    }
 
     /**
      * getQueuedThreads includes waiting threads
      */
-    public void testGetQueuedThreads() { 
+    public void testGetQueuedThreads() {
         final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
         Thread t1 = new Thread(new InterruptedLockRunnable(lock));
         Thread t2 = new Thread(new InterruptibleLockRunnable(lock));
@@ -984,7 +1325,7 @@
         } catch(Exception e){
             unexpectedException();
         }
-    } 
+    }
 
     /**
      * hasWaiters throws NPE if null
@@ -1097,9 +1438,9 @@
      * getWaitingThreads throws IAE if not owned
      */
     public void testGetWaitingThreadsIAE() {
-        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();        
+        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
         final Condition c = (lock.writeLock().newCondition());
-        final PublicReentrantReadWriteLock lock2 = new PublicReentrantReadWriteLock();        
+        final PublicReentrantReadWriteLock lock2 = new PublicReentrantReadWriteLock();
         try {
             lock2.getWaitingThreads(c);
             shouldThrow();
@@ -1113,7 +1454,7 @@
      * getWaitingThreads throws IMSE if not locked
      */
     public void testGetWaitingThreadsIMSE() {
-        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();        
+        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
         final Condition c = (lock.writeLock().newCondition());
         try {
             lock.getWaitingThreads(c);
@@ -1131,7 +1472,7 @@
     public void testHasWaiters() {
         final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         final Condition c = (lock.writeLock().newCondition());
-        Thread t = new Thread(new Runnable() { 
+        Thread t = new Thread(new Runnable() {
                 public void run() {
                     try {
                         lock.writeLock().lock();
@@ -1173,7 +1514,7 @@
     public void testGetWaitQueueLength() {
         final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
         final Condition c = (lock.writeLock().newCondition());
-        Thread t = new Thread(new Runnable() { 
+        Thread t = new Thread(new Runnable() {
                 public void run() {
                     try {
                         lock.writeLock().lock();
@@ -1214,9 +1555,9 @@
      * getWaitingThreads returns only and all waiting threads
      */
     public void testGetWaitingThreads() {
-        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();        
+        final PublicReentrantReadWriteLock lock = new PublicReentrantReadWriteLock();
         final Condition c = lock.writeLock().newCondition();
-        Thread t1 = new Thread(new Runnable() { 
+        Thread t1 = new Thread(new Runnable() {
                 public void run() {
                     try {
                         lock.writeLock().lock();
@@ -1230,7 +1571,7 @@
                 }
             });
 
-        Thread t2 = new Thread(new Runnable() { 
+        Thread t2 = new Thread(new Runnable() {
                 public void run() {
                     try {
                         lock.writeLock().lock();
diff --git a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/SynchronousQueueTest.java b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/SynchronousQueueTest.java
index 19bdede..debce5d 100755
--- a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/SynchronousQueueTest.java
+++ b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/SynchronousQueueTest.java
@@ -757,6 +757,7 @@
             while (!q.isEmpty()) 
                 assertEquals(q.remove(), r.remove());
         } catch(Exception e){
+            e.printStackTrace();
             unexpectedException();
         }
     }
diff --git a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ThreadPoolExecutorTest.java b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ThreadPoolExecutorTest.java
index ca4ba78..4f7cc46 100755
--- a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ThreadPoolExecutorTest.java
+++ b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/ThreadPoolExecutorTest.java
@@ -9,6 +9,7 @@
 package tests.api.java.util.concurrent;
 
 import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
 import junit.framework.*;
 import java.util.*;
 
@@ -38,6 +39,15 @@
         }
     }
 
+    static class FailingThreadFactory implements ThreadFactory{
+        int calls = 0;
+        public Thread newThread(Runnable r){
+            if (++calls > 1) return null;
+            return new Thread(r);
+        }   
+    }
+    
+
     /**
      *  execute successfully executes a runnable
      */
@@ -342,6 +352,9 @@
             assertSame(q, wq);
             assertFalse(wq.contains(tasks[0]));
             assertTrue(wq.contains(tasks[4]));
+            for (int i = 1; i < 5; ++i)
+                tasks[i].cancel(true);
+            p1.shutdownNow();
         } catch(Exception e) {
             unexpectedException();
         } finally {
@@ -1500,5 +1513,58 @@
         }
     }
 
+    /**
+     * Execution continues if there is at least one thread even if
+     * thread factory fails to create more
+     */
+    public void testFailingThreadFactory() {
+        ExecutorService e = new ThreadPoolExecutor(100, 100, LONG_DELAY_MS, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), new FailingThreadFactory());
+        try {
+            ArrayList<Callable<String>> l = new ArrayList<Callable<String>>();
+            for (int k = 0; k < 100; ++k) {
+                e.execute(new NoOpRunnable());
+            }
+            Thread.sleep(LONG_DELAY_MS);
+        } catch(Exception ex) {
+            unexpectedException();
+        } finally {
+            joinPool(e);
+        }
+    }
 
+    /**
+     * execute allows the same task to be submitted multiple times, even
+     * if rejected
+     */
+    public void testRejectedRecycledTask() {
+        final int nTasks = 1000;
+        final AtomicInteger nRun = new AtomicInteger(0);
+        final Runnable recycledTask = new Runnable() {
+                public void run() {
+                    nRun.getAndIncrement();
+                } };
+        final ThreadPoolExecutor p = 
+            new ThreadPoolExecutor(1, 30, 60, TimeUnit.SECONDS, 
+                                   new ArrayBlockingQueue(30));
+        try {
+            for (int i = 0; i < nTasks; ++i) {
+                for (;;) {
+                    try {
+                        p.execute(recycledTask);
+                        break;
+                    }
+                    catch (RejectedExecutionException ignore) {
+                    }
+                }
+            }
+            Thread.sleep(5000); // enough time to run all tasks
+            assertEquals(nRun.get(), nTasks);
+        } catch(Exception ex) {
+            ex.printStackTrace();
+            unexpectedException();
+        } finally {
+            p.shutdown();
+        }
+    }
+            
 }
diff --git a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/TimeUnitTest.java b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/TimeUnitTest.java
index 1a9a04a..54fdc69 100755
--- a/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/TimeUnitTest.java
+++ b/libcore/concurrent/src/test/java/tests/api/java/util/concurrent/TimeUnitTest.java
@@ -21,54 +21,60 @@
         return new TestSuite(TimeUnitTest.class);
     }
 
+    // (loops to 88888 check increments at all time divisions.)
+
     /**
-     * convert correctly converts sample values across the four units
+     * convert correctly converts sample values across the units
      */
     public void testConvert() {
-        for (long t = 0; t < 10; ++t) {
-            assertEquals(t, 
+        for (long t = 0; t < 88888; ++t) {
+            assertEquals(t,
                          TimeUnit.SECONDS.convert(t, 
                                                   TimeUnit.SECONDS));
             assertEquals(t, 
-                         TimeUnit.SECONDS.convert(1000 * t, 
+                         TimeUnit.SECONDS.convert(1000L*t, 
                                                   TimeUnit.MILLISECONDS));
             assertEquals(t, 
-                         TimeUnit.SECONDS.convert(1000000 * t, 
+                         TimeUnit.SECONDS.convert(1000000L*t, 
                                                   TimeUnit.MICROSECONDS));
             assertEquals(t, 
-                         TimeUnit.SECONDS.convert(1000000000 * t, 
+                         TimeUnit.SECONDS.convert(1000000000L*t, 
                                                   TimeUnit.NANOSECONDS));
-            assertEquals(1000 * t, 
+
+
+            assertEquals(1000L*t,
                          TimeUnit.MILLISECONDS.convert(t, 
                                                   TimeUnit.SECONDS));
             assertEquals(t, 
                          TimeUnit.MILLISECONDS.convert(t, 
                                                   TimeUnit.MILLISECONDS));
             assertEquals(t, 
-                         TimeUnit.MILLISECONDS.convert(1000 * t, 
+                         TimeUnit.MILLISECONDS.convert(1000L*t, 
                                                   TimeUnit.MICROSECONDS));
             assertEquals(t, 
-                         TimeUnit.MILLISECONDS.convert(1000000 * t, 
+                         TimeUnit.MILLISECONDS.convert(1000000L*t, 
                                                   TimeUnit.NANOSECONDS));
-            assertEquals(1000000 * t, 
+
+            assertEquals(1000000L*t,
                          TimeUnit.MICROSECONDS.convert(t, 
                                                   TimeUnit.SECONDS));
-            assertEquals(1000 * t, 
+            assertEquals(1000L*t, 
                          TimeUnit.MICROSECONDS.convert(t, 
                                                   TimeUnit.MILLISECONDS));
             assertEquals(t, 
                          TimeUnit.MICROSECONDS.convert(t, 
                                                   TimeUnit.MICROSECONDS));
             assertEquals(t, 
-                         TimeUnit.MICROSECONDS.convert(1000 * t, 
+                         TimeUnit.MICROSECONDS.convert(1000L*t, 
                                                   TimeUnit.NANOSECONDS));
-            assertEquals(1000000000 * t, 
+
+            assertEquals(1000000000L*t,
                          TimeUnit.NANOSECONDS.convert(t, 
                                                   TimeUnit.SECONDS));
-            assertEquals(1000000 * t, 
+            assertEquals(1000000L*t, 
                          TimeUnit.NANOSECONDS.convert(t, 
                                                   TimeUnit.MILLISECONDS));
-            assertEquals(1000 * t, 
+            assertEquals(1000L*t, 
                          TimeUnit.NANOSECONDS.convert(t, 
                                                   TimeUnit.MICROSECONDS));
             assertEquals(t, 
@@ -82,13 +88,12 @@
      * nanoseconds
      */
     public void testToNanos() {
-        for (long t = 0; t < 10; ++t) {
-            assertEquals(1000000000 * t, 
+        for (long t = 0; t < 88888; ++t) {
+            assertEquals(1000000000L*t,
                          TimeUnit.SECONDS.toNanos(t));
-
-            assertEquals(1000000 * t, 
+            assertEquals(1000000L*t, 
                          TimeUnit.MILLISECONDS.toNanos(t));
-            assertEquals(1000 * t, 
+            assertEquals(1000L*t, 
                          TimeUnit.MICROSECONDS.toNanos(t));
             assertEquals(t, 
                          TimeUnit.NANOSECONDS.toNanos(t));
@@ -100,16 +105,15 @@
      * microseconds
      */
     public void testToMicros() {
-        for (long t = 0; t < 10; ++t) {
-            assertEquals(1000000 * t, 
+        for (long t = 0; t < 88888; ++t) {
+            assertEquals(1000000L*t,
                          TimeUnit.SECONDS.toMicros(t));
-
-            assertEquals(1000 * t, 
+            assertEquals(1000L*t, 
                          TimeUnit.MILLISECONDS.toMicros(t));
             assertEquals(t, 
                          TimeUnit.MICROSECONDS.toMicros(t));
             assertEquals(t, 
-                         TimeUnit.NANOSECONDS.toMicros(t * 1000));
+                         TimeUnit.NANOSECONDS.toMicros(t*1000L));
         }
     }
 
@@ -118,16 +122,15 @@
      * milliseconds
      */
     public void testToMillis() {
-        for (long t = 0; t < 10; ++t) {
-            assertEquals(1000 * t, 
+        for (long t = 0; t < 88888; ++t) {
+            assertEquals(1000L*t,
                          TimeUnit.SECONDS.toMillis(t));
-
             assertEquals(t, 
                          TimeUnit.MILLISECONDS.toMillis(t));
             assertEquals(t, 
-                         TimeUnit.MICROSECONDS.toMillis(t * 1000));
+                         TimeUnit.MICROSECONDS.toMillis(t*1000L));
             assertEquals(t, 
-                         TimeUnit.NANOSECONDS.toMillis(t * 1000000));
+                         TimeUnit.NANOSECONDS.toMillis(t*1000000L));
         }
     }
 
@@ -136,20 +139,18 @@
      * seconds
      */
     public void testToSeconds() {
-        for (long t = 0; t < 10; ++t) {
-            assertEquals(t, 
+        for (long t = 0; t < 88888; ++t) {
+            assertEquals(t,
                          TimeUnit.SECONDS.toSeconds(t));
-
             assertEquals(t, 
-                         TimeUnit.MILLISECONDS.toSeconds(t * 1000));
+                         TimeUnit.MILLISECONDS.toSeconds(t*1000L));
             assertEquals(t, 
-                         TimeUnit.MICROSECONDS.toSeconds(t * 1000000));
+                         TimeUnit.MICROSECONDS.toSeconds(t*1000000L));
             assertEquals(t, 
-                         TimeUnit.NANOSECONDS.toSeconds(t * 1000000000));
+                         TimeUnit.NANOSECONDS.toSeconds(t*1000000000L));
         }
     }
 
-
     /**
      * convert saturates positive too-large values to Long.MAX_VALUE 
      * and negative to LONG.MIN_VALUE
@@ -161,6 +162,7 @@
         assertEquals(Long.MIN_VALUE,
                      TimeUnit.NANOSECONDS.convert(-Long.MAX_VALUE / 4,
                                                   TimeUnit.SECONDS));
+
     }
 
     /**
diff --git a/libcore/crypto/src/main/java/javax/crypto/BadPaddingException.java b/libcore/crypto/src/main/java/javax/crypto/BadPaddingException.java
index 19fdaa8..5e2dd38 100644
--- a/libcore/crypto/src/main/java/javax/crypto/BadPaddingException.java
+++ b/libcore/crypto/src/main/java/javax/crypto/BadPaddingException.java
@@ -22,8 +22,6 @@
 /**
  * The exception that is thrown when a padding mechanism is expected for the
  * input data, but the input data does not have the proper padding bytes.
- * 
- * @since Android 1.0
  */
 public class BadPaddingException extends GeneralSecurityException {
 
@@ -37,7 +35,6 @@
      * 
      * @param msg
      *            the message
-     * @since Android 1.0
      */
     public BadPaddingException(String msg) {
         super(msg);
@@ -45,8 +42,6 @@
 
     /**
      * Creates a new instance of {@code BadPaddingException} with no message.
-     * 
-     * @since Android 1.0
      */
     public BadPaddingException() {
     }
diff --git a/libcore/crypto/src/main/java/javax/crypto/Cipher.java b/libcore/crypto/src/main/java/javax/crypto/Cipher.java
index ae72226..8e084ae 100644
--- a/libcore/crypto/src/main/java/javax/crypto/Cipher.java
+++ b/libcore/crypto/src/main/java/javax/crypto/Cipher.java
@@ -61,58 +61,41 @@
  * to be processed at a time can be optionally specified by appending it to the
  * mode name. e.g. <i>"AES/CFB8/NoPadding"</i>. If no number is specified, a
  * provider specific default value is used.
- * </p>
- * 
- * @since Android 1.0
  */
 public class Cipher {
 
     /**
      * Constant for decryption operation mode.
-     * 
-     * @since Android 1.0
      */
     public static final int DECRYPT_MODE = 2;
 
     /**
      * Constant for encryption operation mode.
-     * 
-     * @since Android 1.0
      */
     public static final int ENCRYPT_MODE = 1;
 
     /**
      * Constant indicating that the key to be unwrapped is a private key.
-     * 
-     * @since Android 1.0
      */
     public static final int PRIVATE_KEY = 2;
 
     /**
      * Constant indicating that the key to be unwrapped is a public key.
-     * 
-     * @since Android 1.0
      */
     public static final int PUBLIC_KEY = 1;
 
     /**
      * Constant indicating that the key to be unwrapped is a secret key.
-     * 
-     * @since Android 1.0
      */
     public static final int SECRET_KEY = 3;
 
     /**
      * Constant for key unwrapping operation mode.
-     * 
-     * @since Android 1.0
      */
     public static final int UNWRAP_MODE = 4;
 
     /**
      * Constant for key wrapping operation mode.
-     * 
-     * @since Android 1.0
      */
     public static final int WRAP_MODE = 3;
 
@@ -147,7 +130,7 @@
 
     /**
      * Creates a new Cipher instance.
-     * 
+     *
      * @param cipherSpi
      *            the implementation delegate of the cipher.
      * @param provider
@@ -157,7 +140,6 @@
      * @throws NullPointerException
      *             if either cipherSpi is {@code null} or provider is {@code
      *             null} and {@code cipherSpi} is a {@code NullCipherSpi}.
-     * @since Android 1.0
      */
     protected Cipher(CipherSpi cipherSpi, Provider provider,
             String transformation) {
@@ -178,7 +160,7 @@
      * transformation. The first found provider providing the transformation is
      * used to create the cipher. If no provider is found an exception is
      * thrown.
-     * 
+     *
      * @param transformation
      *            the name of the transformation to create a cipher for.
      * @return a cipher for the requested transformation.
@@ -189,7 +171,6 @@
      * @throws NoSuchPaddingException
      *             if no installed provider can provide the padding scheme in
      *             the <i>transformation</i>.
-     * @since Android 1.0
      */
     public static final Cipher getInstance(String transformation)
             throws NoSuchAlgorithmException, NoSuchPaddingException {
@@ -199,7 +180,7 @@
     /**
      * Creates a new cipher for the specified transformation provided by the
      * specified provider.
-     * 
+     *
      * @param transformation
      *            the name of the transformation to create a cipher for.
      * @param provider
@@ -216,7 +197,6 @@
      *             is not available.
      * @throws IllegalArgumentException
      *             if the specified provider is {@code null}.
-     * @since Android 1.0
      */
     public static final Cipher getInstance(String transformation,
             String provider) throws NoSuchAlgorithmException,
@@ -235,7 +215,7 @@
 
     /**
      * Creates a new cipher for the specified transformation.
-     * 
+     *
      * @param transformation
      *            the name of the transformation to create a cipher for.
      * @param provider
@@ -250,7 +230,6 @@
      *             is not available.
      * @throws IllegalArgumentException
      *             if the provider is {@code null}.
-     * @since Android 1.0
      */
     public static final Cipher getInstance(String transformation,
             Provider provider) throws NoSuchAlgorithmException,
@@ -373,9 +352,8 @@
 
     /**
      * Returns the provider of this cipher instance.
-     * 
+     *
      * @return the provider of this cipher instance.
-     * @since Android 1.0
      */
     public final Provider getProvider() {
         return provider;
@@ -386,10 +364,8 @@
      * <p>
      * This is the name of the <i>transformation</i> argument used in the
      * {@code getInstance} call creating this object.
-     * </p>
-     * 
+     *
      * @return the name of the algorithm of this cipher instance.
-     * @since Android 1.0.
      */
     public final String getAlgorithm() {
         return transformation;
@@ -397,9 +373,8 @@
 
     /**
      * Returns this ciphers block size (in bytes).
-     * 
+     *
      * @return this ciphers block size.
-     * @since Android 1.0
      */
     public final int getBlockSize() {
         return spiImpl.engineGetBlockSize();
@@ -408,13 +383,12 @@
     /**
      * Returns the length in bytes an output buffer needs to be when this cipher
      * is updated with {@code inputLen} bytes.
-     * 
+     *
      * @param inputLen
      *            the number of bytes of the input.
      * @return the output buffer length for the input length.
      * @throws IllegalStateException
      *             if this cipher instance is in an invalid state.
-     * @since Android 1.0
      */
     public final int getOutputSize(int inputLen) {
         if (mode == 0) {
@@ -426,9 +400,8 @@
 
     /**
      * Returns the <i>initialization vector</i> for this cipher instance.
-     * 
+     *
      * @return the <i>initialization vector</i> for this cipher instance.
-     * @since Android 1.0
      */
     public final byte[] getIV() {
         return spiImpl.engineGetIV();
@@ -440,11 +413,10 @@
      * These may be a the same parameters that were used to create this cipher
      * instance, or may be a combination of default and random parameters,
      * depending on the underlying cipher implementation.
-     * 
+     *
      * @return the parameters that where used to create this cipher instance, or
      *         {@code null} if this cipher instance does not have any
      *         parameters.
-     * @since Android 1.0
      */
     public final AlgorithmParameters getParameters() {
         return spiImpl.engineGetParameters();
@@ -452,9 +424,8 @@
 
     /**
      * Returns the exemption mechanism associated with this cipher.
-     * 
+     *
      * @return currently {@code null}
-     * @since Android 1.0
      */
     public final ExemptionMechanism getExemptionMechanism() {
         //FIXME implement getExemptionMechanism
@@ -473,7 +444,7 @@
      * The cipher is initialized for the specified operational mode (one of:
      * encryption, decryption, key wrapping or key unwrapping) depending on
      * {@code opmode}.
-     * </p>
+     * <p>
      * If this cipher instance needs any algorithm parameters or random values
      * that the specified key can not provide, the underlying implementation of
      * this cipher is supposed to generate the required parameters (using its
@@ -483,8 +454,7 @@
      * init} methods, the state of the instance is overridden, meaning that it
      * is equivalent to creating a new instance and calling its {@code init}
      * method.
-     * </p>
-     * 
+     *
      * @param opmode
      *            the operation this cipher instance should be initialized for
      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
@@ -494,7 +464,6 @@
      * @throws InvalidKeyException
      *             if the specified key can not be used to initialize this
      *             cipher instance.
-     * @since Android 1.0
      */
     public final void init(int opmode, Key key) throws InvalidKeyException {
         if (sec_rand == null) {
@@ -513,7 +482,7 @@
      * The cipher is initialized for the specified operational mode (one of:
      * encryption, decryption, key wrapping or key unwrapping) depending on
      * {@code opmode}.
-     * </p>
+     * <p>
      * If this cipher instance needs any algorithm parameters or random values
      * that the specified key can not provide, the underlying implementation of
      * this cipher is supposed to generate the required parameters (using its
@@ -523,8 +492,7 @@
      * When a cipher instance is initialized by a call to any of the {@code
      * init} methods, the state of the instance is overridden, means it is
      * equivalent to creating a new instance and calling it {@code init} method.
-     * </p>
-     * 
+     *
      * @param opmode
      *            the operation this cipher instance should be initialized for
      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
@@ -538,7 +506,6 @@
      *             cipher instance.
      * @throws InvalidParameterException
      *             if the specified opmode is invalid.
-     * @since Android 1.0
      */
     public final void init(int opmode, Key key, SecureRandom random)
             throws InvalidKeyException {
@@ -559,7 +526,7 @@
      * <p>
      * The cipher is initialized for the specified operational mode (one of:
      * encryption, decryption, key wrapping or key unwrapping).
-     * </p>
+     * <p>
      * If this cipher instance needs any algorithm parameters and {@code params}
      * is {@code null}, the underlying implementation of this cipher is supposed
      * to generate the required parameters (using its provider or random
@@ -568,8 +535,7 @@
      * When a cipher instance is initialized by a call to any of the {@code
      * init} methods, the state of the instance is overridden, means it is
      * equivalent to creating a new instance and calling it {@code init} method.
-     * </p>
-     * 
+     *
      * @param opmode
      *            the operation this cipher instance should be initialized for
      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
@@ -584,7 +550,6 @@
      * @throws InvalidAlgorithmParameterException
      *             it the specified parameters are inappropriate for this
      *             cipher.
-     * @since Android 1.0
      */
     public final void init(int opmode, Key key, AlgorithmParameterSpec params)
             throws InvalidKeyException, InvalidAlgorithmParameterException {
@@ -611,7 +576,7 @@
      * init} methods, the state of the instance is overridden, meaning that it
      * is equivalent to creating a new instance and calling it {@code init}
      * method.
-     * 
+     *
      * @param opmode
      *            the operation this cipher instance should be initialized for
      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
@@ -630,7 +595,6 @@
      *             cipher.
      * @throws InvalidParameterException
      *             if the specified {@code opmode} is invalid.
-     * @since Android 1.0
      */
     public final void init(int opmode, Key key, AlgorithmParameterSpec params,
             SecureRandom random) throws InvalidKeyException,
@@ -656,7 +620,7 @@
      * The cipher is initialized for the specified operation (one of:
      * encryption, decryption, key wrapping or key unwrapping) depending on
      * {@code opmode}.
-     * </p>
+     * <p>
      * If this cipher instance needs any algorithm parameters and {@code params}
      * is {@code null}, the underlying implementation of this cipher is supposed
      * to generate the required parameters (using its provider or random
@@ -666,8 +630,7 @@
      * init} methods, the state of the instance is overridden, meaning that it
      * is equivalent to creating a new instance and calling it {@code init}
      * method.
-     * </p>
-     * 
+     *
      * @param opmode
      *            the operation this cipher instance should be initialized for
      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
@@ -682,7 +645,6 @@
      * @throws InvalidAlgorithmParameterException
      *             it the specified parameters are inappropriate for this
      *             cipher.
-     * @since Android 1.0
      */
     public final void init(int opmode, Key key, AlgorithmParameters params)
             throws InvalidKeyException, InvalidAlgorithmParameterException {
@@ -699,7 +661,7 @@
      * The cipher will be initialized for the specified operation (one of:
      * encryption, decryption, key wrapping or key unwrapping) depending on
      * {@code opmode}.
-     * </p>
+     * <p>
      * If this cipher instance needs any algorithm parameters and {@code params}
      * is {@code null}, the underlying implementation of this cipher is supposed
      * to generate the required parameters (using its provider or random
@@ -708,8 +670,7 @@
      * When a cipher instance is initialized by a call to any of the {@code
      * init} methods, the state of the instance is overridden, means it is
      * equivalent to creating a new instance and calling it {@code init} method.
-     * </p>
-     * 
+     *
      * @param opmode
      *            the operation this cipher instance should be initialized for
      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
@@ -728,7 +689,6 @@
      *             cipher.
      * @throws InvalidParameterException
      *             if the specified {@code opmode} is invalid.
-     * @since Android 1.0
      */
     public final void init(int opmode, Key key, AlgorithmParameters params,
             SecureRandom random) throws InvalidKeyException,
@@ -768,7 +728,7 @@
      * When a cipher instance is initialized by a call to any of the {@code
      * init} methods, the state of the instance is overridden, means it is
      * equivalent to creating a new instance and calling it {@code init} method.
-     * 
+     *
      * @param opmode
      *            the operation this cipher instance should be initialized for
      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
@@ -778,7 +738,6 @@
      * @throws InvalidKeyException
      *             if the public key in the certificate can not be used to
      *             initialize this cipher instance.
-     * @since Android 1.0
      */
     public final void init(int opmode, Certificate certificate)
             throws InvalidKeyException {
@@ -795,7 +754,7 @@
      * The cipher will be initialized for the specified operation (one of:
      * encryption, decryption, key wrapping or key unwrapping) depending on
      * {@code opmode}.
-     * </p>
+     * <p>
      * It the type of the certificate is X.509 and the certificate has a <i>key
      * usage</i> extension field marked as critical, the specified {@code
      * opmode} has the be enabled for this key, otherwise an {@code
@@ -806,11 +765,11 @@
      * cipher is supposed to generate the required parameters (using its
      * provider or random values). Random values are generated using {@code
      * random}.
-     * </p>
+     * <p>
      * When a cipher instance is initialized by a call to any of the {@code
      * init} methods, the state of the instance is overridden, means it is
      * equivalent to creating a new instance and calling it {@code init} method.
-     * 
+     *
      * @param opmode
      *            the operation this cipher instance should be initialized for
      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
@@ -822,7 +781,6 @@
      * @throws InvalidKeyException
      *             if the public key in the certificate can not be used to
      *             initialize this cipher instance.
-     * @since Android 1.0
      */
     public final void init(int opmode, Certificate certificate,
             SecureRandom random) throws InvalidKeyException {
@@ -874,7 +832,7 @@
     /**
      * Continues a multi-part transformation (encryption or decryption). The
      * transformed bytes are returned.
-     * 
+     *
      * @param input
      *            the input bytes to transform.
      * @return the transformed bytes in a new buffer, or {@code null} if the
@@ -884,7 +842,6 @@
      *             decryption.
      * @throws IllegalArgumentException
      *             if the input is {@code null}.
-     * @since Android 1.0
      */
     public final byte[] update(byte[] input) {
         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
@@ -903,7 +860,7 @@
     /**
      * Continues a multi-part transformation (encryption or decryption). The
      * transformed bytes are returned.
-     * 
+     *
      * @param input
      *            the input bytes to transform.
      * @param inputOffset
@@ -919,7 +876,6 @@
      *             if the input is {@code null}, or if {@code inputOffset} and
      *             {@code inputLen} do not specify a valid chunk in the input
      *             buffer.
-     * @since Android 1.0
      */
     public final byte[] update(byte[] input, int inputOffset, int inputLen) {
         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
@@ -949,8 +905,7 @@
      * a {@code ShortBufferException} is thrown. Use
      * {@link Cipher#getOutputSize getOutputSize} to check for the size of the
      * output buffer.
-     * </p>
-     * 
+     *
      * @param input
      *            the input bytes to transform.
      * @param inputOffset
@@ -969,7 +924,6 @@
      *             if the input is {@code null}, the output is {@code null}, or
      *             if {@code inputOffset} and {@code inputLen} do not specify a
      *             valid chunk in the input buffer.
-     * @since Android 1.0
      */
     public final int update(byte[] input, int inputOffset, int inputLen,
             byte[] output) throws ShortBufferException {
@@ -984,8 +938,7 @@
      * a {@code ShortBufferException} is thrown. Use
      * {@link Cipher#getOutputSize getOutputSize} to check for the size of the
      * output buffer.
-     * </p>
-     * 
+     *
      * @param input
      *            the input bytes to transform.
      * @param inputOffset
@@ -1006,7 +959,6 @@
      *             if the input is {@code null}, the output is {@code null}, or
      *             if {@code inputOffset} and {@code inputLen} do not specify a
      *             valid chunk in the input buffer.
-     * @since Android 1.0
      */
     public final int update(byte[] input, int inputOffset, int inputLen,
             byte[] output, int outputOffset) throws ShortBufferException {
@@ -1046,8 +998,7 @@
      * bytes a {@code ShortBufferException} is thrown. Use
      * {@link Cipher#getOutputSize getOutputSize} to check for the size of the
      * output buffer.
-     * </p>
-     * 
+     *
      * @param input
      *            the input buffer to transform.
      * @param output
@@ -1061,7 +1012,6 @@
      * @throws IllegalArgumentException
      *             if the input buffer and the output buffer are the identical
      *             object.
-     * @since Android 1.0
      */
     public final int update(ByteBuffer input, ByteBuffer output)
             throws ShortBufferException {
@@ -1081,8 +1031,7 @@
      * <p>
      * Processes any bytes that may have been buffered in previous {@code
      * update} calls.
-     * </p>
-     * 
+     *
      * @return the final bytes from the transformation.
      * @throws IllegalBlockSizeException
      *             if the size of the resulting bytes is not a multiple of the
@@ -1092,7 +1041,6 @@
      * @throws IllegalStateException
      *             if this cipher instance is not initialized for encryption or
      *             decryption.
-     * @since Android 1.0
      */
     public final byte[] doFinal() throws IllegalBlockSizeException,
             BadPaddingException {
@@ -1108,9 +1056,9 @@
      * <p>
      * Processes any bytes that may have been buffered in previous {@code
      * update} calls.
-     * </p>
+     * <p>
      * The final transformed bytes are stored in the {@code output} buffer.
-     * 
+     *
      * @param output
      *            the output buffer.
      * @param outputOffset
@@ -1126,7 +1074,6 @@
      * @throws IllegalStateException
      *             if this cipher instance is not initialized for encryption or
      *             decryption.
-     * @since Android 1.0
      */
     public final int doFinal(byte[] output, int outputOffset)
             throws IllegalBlockSizeException, ShortBufferException,
@@ -1147,8 +1094,7 @@
      * <p>
      * Processes the bytes in {@code input} buffer, and any bytes that have been
      * buffered in previous {@code update} calls.
-     * </p>
-     * 
+     *
      * @param input
      *            the input buffer.
      * @return the final bytes from the transformation.
@@ -1160,7 +1106,6 @@
      * @throws IllegalStateException
      *             if this cipher instance is not initialized for encryption or
      *             decryption.
-     * @since Android 1.0
      */
     public final byte[] doFinal(byte[] input) throws IllegalBlockSizeException,
             BadPaddingException {
@@ -1177,7 +1122,7 @@
      * Processes the {@code inputLen} bytes in {@code input} buffer at {@code
      * inputOffset}, and any bytes that have been buffered in previous {@code
      * update} calls.
-     * 
+     *
      * @param input
      *            the input buffer.
      * @param inputOffset
@@ -1196,7 +1141,6 @@
      * @throws IllegalArgumentException
      *             if {@code inputOffset} and {@code inputLen} do not specify an
      *             valid chunk in the input buffer.
-     * @since Android 1.0
      */
     public final byte[] doFinal(byte[] input, int inputOffset, int inputLen)
             throws IllegalBlockSizeException, BadPaddingException {
@@ -1218,7 +1162,7 @@
      * Processes the {@code inputLen} bytes in {@code input} buffer at {@code
      * inputOffset}, and any bytes that have been buffered in previous {@code
      * update} calls.
-     * 
+     *
      * @param input
      *            the input buffer.
      * @param inputOffset
@@ -1241,7 +1185,6 @@
      * @throws IllegalArgumentException
      *             if {@code inputOffset} and {@code inputLen} do not specify an
      *             valid chunk in the input buffer.
-     * @since Android 1.0
      */
     public final int doFinal(byte[] input, int inputOffset, int inputLen,
             byte[] output) throws ShortBufferException,
@@ -1255,8 +1198,7 @@
      * Processes the {@code inputLen} bytes in {@code input} buffer at {@code
      * inputOffset}, and any bytes that have been buffered in previous {@code
      * update} calls.
-     * </p>
-     * 
+     *
      * @param input
      *            the input buffer.
      * @param inputOffset
@@ -1281,7 +1223,6 @@
      * @throws IllegalArgumentException
      *             if {@code inputOffset} and {@code inputLen} do not specify an
      *             valid chunk in the input buffer.
-     * @since Android 1.0
      */
     public final int doFinal(byte[] input, int inputOffset, int inputLen,
             byte[] output, int outputOffset) throws ShortBufferException,
@@ -1306,8 +1247,7 @@
      * {@code input.position()}, and any bytes that have been buffered in
      * previous {@code update} calls. The transformed bytes are placed into
      * {@code output} buffer.
-     * </p>
-     * 
+     *
      * @param input
      *            the input buffer.
      * @param output
@@ -1326,7 +1266,6 @@
      * @throws IllegalStateException
      *             if this cipher instance is not initialized for encryption or
      *             decryption.
-     * @since Android 1.0
      */
     public final int doFinal(ByteBuffer input, ByteBuffer output)
             throws ShortBufferException, IllegalBlockSizeException,
@@ -1344,7 +1283,7 @@
 
     /**
      * Wraps a key using this cipher instance.
-     * 
+     *
      * @param key
      *            the key to wrap.
      * @return the wrapped key.
@@ -1355,7 +1294,6 @@
      *             if this cipher instance can not wrap this key.
      * @throws IllegalStateException
      *             if this cipher instance is not initialized for wrapping.
-     * @since Android 1.0
      */
     public final byte[] wrap(Key key) throws IllegalBlockSizeException,
             InvalidKeyException {
@@ -1368,7 +1306,7 @@
 
     /**
      * Unwraps a key using this cipher instance.
-     * 
+     *
      * @param wrappedKey
      *            the wrapped key to unwrap.
      * @param wrappedKeyAlgorithm
@@ -1386,7 +1324,6 @@
      *             {@code wrappedKeyType} for the {@code wrappedKeyAlgorithm}.
      * @throws IllegalStateException
      *             if this cipher instance is not initialized for unwrapping.
-     * @since Android 1.0
      */
     public final Key unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
             int wrappedKeyType) throws InvalidKeyException,
@@ -1401,7 +1338,7 @@
 
     /**
      * Returns the maximum key length for the specified transformation.
-     * 
+     *
      * @param transformation
      *            the transformation name.
      * @return the maximum key length, currently {@code Integer.MAX_VALUE}.
@@ -1410,7 +1347,6 @@
      *             be found.
      * @throws NullPointerException
      *             if {@code transformation} is {@code null}.
-     * @since Android 1.0
      */
     public static final int getMaxAllowedKeyLength(String transformation)
             throws NoSuchAlgorithmException {
@@ -1425,7 +1361,7 @@
     /**
      * Returns the maximum cipher parameter value for the specified
      * transformation. If there is no maximum limit, {@code null} is returned.
-     * 
+     *
      * @param transformation
      *            the transformation name.
      * @return a parameter spec holding the maximum value or {@code null}.
@@ -1435,7 +1371,6 @@
      *             be found.
      * @throws NullPointerException
      *             if {@code transformation} is {@code null}.
-     * @since Android 1.0
      */
     public static final AlgorithmParameterSpec getMaxAllowedParameterSpec(
             String transformation) throws NoSuchAlgorithmException {
diff --git a/libcore/crypto/src/main/java/javax/crypto/CipherInputStream.java b/libcore/crypto/src/main/java/javax/crypto/CipherInputStream.java
index ca64c49..b2c626d 100644
--- a/libcore/crypto/src/main/java/javax/crypto/CipherInputStream.java
+++ b/libcore/crypto/src/main/java/javax/crypto/CipherInputStream.java
@@ -32,9 +32,6 @@
  * by a {@code CipherInputStream}. For example, if a cipher initialized for
  * decryption is used with a {@code CipherInputStream}, the {@code
  * CipherInputStream} tries to read the data an decrypt them before returning.
- * </p>
- * 
- * @since Android 1.0
  */
 public class CipherInputStream extends FilterInputStream {
 
@@ -48,12 +45,11 @@
     /**
      * Creates a new {@code CipherInputStream} instance for an {@code
      * InputStream} and a cipher.
-     * 
+     *
      * @param is
      *            the input stream to read data from.
      * @param c
      *            the cipher to process the data with.
-     * @since Android 1.0
      */
     public CipherInputStream(InputStream is, Cipher c) {
         super(is);
@@ -65,11 +61,9 @@
      * InputStream} without a cipher.
      * <p>
      * A {@code NullCipher} is created and used to process the data.
-     * </p>
-     * 
+     *
      * @param is
      *            the input stream to read data from.
-     * @since Android 1.0
      */
     protected CipherInputStream(InputStream is) {
         this(is, new NullCipher());
@@ -77,11 +71,10 @@
 
     /**
      * Reads the next byte from this cipher input stream.
-     * 
+     *
      * @return the next byte, or {@code -1} if the end of the stream is reached.
      * @throws IOException
      *             if an error occurs.
-     * @since Android 1.0
      */
     @Override
     public int read() throws IOException {
@@ -114,14 +107,13 @@
     /**
      * Reads the next {@code b.length} bytes from this input stream into buffer
      * {@code b}.
-     * 
+     *
      * @param b
      *            the buffer to be filled with data.
      * @return the number of bytes filled into buffer {@code b}, or {@code -1}
      *         if the end of the stream is reached.
      * @throws IOException
      *             if an error occurs.
-     * @since Android 1.0
      */
     @Override
     public int read(byte[] b) throws IOException {
@@ -134,8 +126,7 @@
      * <p>
      * if {@code b} is {@code null}, the next {@code len} bytes are read and
      * discarded.
-     * </p>
-     * 
+     *
      * @param b
      *            the buffer to be filled with data.
      * @param off
@@ -148,7 +139,6 @@
      *             if an error occurs.
      * @throws NullPointerException
      *             if the underlying input stream is {@code null}.
-     * @since Android 1.0
      */
     @Override
     public int read(byte[] b, int off, int len) throws IOException {
@@ -175,15 +165,12 @@
      * The number of bytes skipped depends on the result of a call to
      * {@link CipherInputStream#available() available}. The smaller of n and the
      * result are the number of bytes being skipped.
-     * </p>
-     * Skipping is (currently) not supported in Android.
-     * 
+     *
      * @param n
      *            the number of bytes that should be skipped.
      * @return the number of bytes actually skipped.
      * @throws IOException
      *             if an error occurs
-     * @since Android 1.0
      */
     @Override
     public long skip(long n) throws IOException {
@@ -199,13 +186,11 @@
     }
 
     /**
-     * Returns the number of bytes available without blocking. It (currently)
-     * always returns {@code 0} in Android.
-     * 
+     * Returns the number of bytes available without blocking.
+     *
      * @return the number of bytes available, currently zero.
      * @throws IOException
      *             if an error occurs
-     * @since Android 1.0
      */
     @Override
     public int available() throws IOException {
@@ -215,10 +200,9 @@
     /**
      * Closes this {@code CipherInputStream}, also closes the underlying input
      * stream and call {@code doFinal} on the cipher object.
-     * 
+     *
      * @throws IOException
      *             if an error occurs.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -232,15 +216,15 @@
     }
 
     /**
-     * Returns whether this input stream supports {@code mark} and {@code reset}
-     * , which it does not.
-     * 
+     * Returns whether this input stream supports {@code mark} and
+     * {@code reset}, which it does not.
+     *
      * @return false, since this input stream does not support {@code mark} and
      *         {@code reset}.
-     * @since Android 1.0
      */
     @Override
     public boolean markSupported() {
         return false;
     }
 }
+
diff --git a/libcore/crypto/src/main/java/javax/crypto/CipherOutputStream.java b/libcore/crypto/src/main/java/javax/crypto/CipherOutputStream.java
index 8bce42b..1f95b99 100644
--- a/libcore/crypto/src/main/java/javax/crypto/CipherOutputStream.java
+++ b/libcore/crypto/src/main/java/javax/crypto/CipherOutputStream.java
@@ -31,9 +31,6 @@
  * by a {@code CipherOutputStream}. For example, if a cipher initialized for
  * encryption is used with a {@code CipherOutputStream}, the {@code
  * CipherOutputStream} tries to encrypt the data writing it out.
- * </p>
- * 
- * @since Android 1.0
  */
 public class CipherOutputStream extends FilterOutputStream {
 
@@ -43,12 +40,11 @@
     /**
      * Creates a new {@code CipherOutputStream} instance for an {@code
      * OutputStream} and a {@code Cipher}.
-     * 
+     *
      * @param os
      *            the output stream to write data to.
      * @param c
      *            the cipher to process the data with.
-     * @since Android 1.0
      */
     public CipherOutputStream(OutputStream os, Cipher c) {
         super(os);
@@ -60,11 +56,9 @@
      * OutputStream} without a cipher.
      * <p>
      * A {@code NullCipher} is created to process the data.
-     * </p>
-     * 
+     *
      * @param os
      *            the output stream to write the data to.
-     * @since Android 1.0
      */
     protected CipherOutputStream(OutputStream os) {
         this(os, new NullCipher());
@@ -72,12 +66,11 @@
 
     /**
      * Writes the single byte to this cipher output stream.
-     * 
+     *
      * @param b
      *            the byte to write.
      * @throws IOException
      *             if an error occurs.
-     * @since Android 1.0
      */
     @Override
     public void write(int b) throws IOException {
@@ -91,12 +84,11 @@
 
     /**
      * Writes the buffer of bytes to this cipher output stream.
-     * 
+     *
      * @param b
      *            the buffer of bytes.
      * @throws IOException
      *             if an error occurs.
-     * @since Android 1.0
      */
     @Override
     public void write(byte[] b) throws IOException {
@@ -106,7 +98,7 @@
     /**
      * Writes the {@code len} bytes from buffer {@code b} starting at offset
      * {@code off} to this cipher output stream.
-     * 
+     *
      * @param b
      *            the buffer.
      * @param off
@@ -115,7 +107,6 @@
      *            the number of bytes.
      * @throws IOException
      *             if an error occurs.
-     * @since Android 1.0
      */
     @Override
     public void write(byte[] b, int off, int len) throws IOException {
@@ -130,7 +121,7 @@
 
     /**
      * Flushes this cipher output stream.
-     * 
+     *
      * @throws IOException
      *             if an error occurs
      */
@@ -145,7 +136,7 @@
      * On the underlying cipher {@code doFinal} will be invoked, and any
      * buffered bytes from the cipher are also written out, and the cipher is
      * reset to its initial state. The underlying output stream is also closed.
-     * 
+     *
      * @throws IOException
      *             if an error occurs.
      */
@@ -173,3 +164,4 @@
         }
     }
 }
+
diff --git a/libcore/crypto/src/main/java/javax/crypto/CipherSpi.java b/libcore/crypto/src/main/java/javax/crypto/CipherSpi.java
index f6da929..50fdd49 100644
--- a/libcore/crypto/src/main/java/javax/crypto/CipherSpi.java
+++ b/libcore/crypto/src/main/java/javax/crypto/CipherSpi.java
@@ -44,7 +44,7 @@
  * </ul>
  * The following behavior should be implemented for obtaining {@code Cipher}
  * instances.
- * </p>
+ * <p>
  * When one of the {@link Cipher#getInstance} factory methods is called with a
  * <i>transformation</i> that is only an <i>algorithm</i>, check if the provider
  * defines a {@code CipherSpi} for "algorithm", if so: return it, otherwise
@@ -76,53 +76,46 @@
  * padding name and return it, otherwise throw a
  * {@link NoSuchAlgorithmException}.
  * </ul>
- * </p>
- * 
+ *
  * @see Cipher
- * @since Android 1.0
  */
 public abstract class CipherSpi {
 
     /**
      * Creates a new {@code CipherSpi} instance.
-     * 
-     * @since Android 1.0
      */
     public CipherSpi() {
     }
 
     /**
      * Sets the mode for this cipher.
-     * 
+     *
      * @param mode
      *            the name of the cipher mode.
      * @throws NoSuchAlgorithmException
      *             if the specified cipher mode is not supported by this
      *             provider.
-     * @since Android 1.0
      */
     protected abstract void engineSetMode(String mode)
             throws NoSuchAlgorithmException;
 
     /**
      * Sets the padding method for this cipher.
-     * 
+     *
      * @param padding
      *            the name of the padding method.
      * @throws NoSuchPaddingException
      *             if the specified padding method is not supported by this
      *             cipher.
-     * @since Android 1.0
      */
     protected abstract void engineSetPadding(String padding)
             throws NoSuchPaddingException;
 
     /**
      * Returns the block size of this cipher (in bytes)
-     * 
+     *
      * @return the block size of this cipher, or zero if this cipher is not a
      *         block cipher.
-     * @since Android 1.0
      */
     protected abstract int engineGetBlockSize();
 
@@ -133,21 +126,18 @@
      * <p>
      * The actual output length of the next call to {@code update} or {@code
      * doFinal} may be smaller than the length returned by this method.
-     * </p>
-     * 
+     *
      * @param inputLen
      *            the length of the input (in bytes).
      * @return the size for a buffer (in bytes).
-     * @since Android 1.0
      */
     protected abstract int engineGetOutputSize(int inputLen);
 
     /**
      * Returns the Initialization Vector (IV) that was used to initialize this
      * cipher or {@code null} if none was used.
-     * 
+     *
      * @return the Initialization Vector (IV), or {@code null} if none was used.
-     * @since Android 1.0
      */
     protected abstract byte[] engineGetIV();
 
@@ -157,12 +147,10 @@
      * These may be a the same parameters that were used to create this cipher
      * instance, or may be a combination of default and random parameters,
      * depending on the underlying cipher implementation.
-     * </p>
-     * 
+     *
      * @return the parameters that where used to create this cipher instance, or
      *         {@code null} if this cipher instance does not have any parameters
      *         at all.
-     * @since Android 1.0
      */
     protected abstract AlgorithmParameters engineGetParameters();
 
@@ -173,7 +161,7 @@
      * The cipher will be initialized for the specified operation (one of:
      * encryption, decryption, key wrapping or key unwrapping) depending on
      * {@code opmode}.
-     * </p>
+     * <p>
      * If this cipher instance needs any algorithm parameters or random values
      * that the specified key cannot provide, the underlying implementation of
      * this cipher is supposed to generate the required parameters (using its
@@ -183,8 +171,7 @@
      * When a cipher instance is initialized by a call to any of the {@code
      * init} methods, the state of the instance is overridden, means it is
      * equivalent to creating a new instance and calling it {@code init} method.
-     * </p>
-     * 
+     *
      * @param opmode
      *            the operation this cipher instance should be initialized for
      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
@@ -196,7 +183,6 @@
      * @throws InvalidKeyException
      *             if the specified key cannot be used to initialize this cipher
      *             instance.
-     * @since Android 1.0
      */
     protected abstract void engineInit(int opmode, Key key, SecureRandom random)
             throws InvalidKeyException;
@@ -208,7 +194,7 @@
      * The cipher will be initialized for the specified operation (one of:
      * encryption, decryption, key wrapping or key unwrapping) depending on
      * {@code opmode}.
-     * </p>
+     * <p>
      * If this cipher instance needs any algorithm parameters and {@code params}
      * is {@code null}, the underlying implementation of this cipher is supposed
      * to generate the required parameters (using its provider or random
@@ -217,8 +203,7 @@
      * When a cipher instance is initialized by a call to any of the {@code
      * init} methods, the state of the instance is overridden, means it is
      * equivalent to creating a new instance and calling it {@code init} method.
-     * </p>
-     * 
+     *
      * @param opmode
      *            the operation this cipher instance should be initialized for
      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
@@ -235,7 +220,6 @@
      * @throws InvalidAlgorithmParameterException
      *             it the specified parameters are inappropriate for this
      *             cipher.
-     * @since Android 1.0
      */
     protected abstract void engineInit(int opmode, Key key,
             AlgorithmParameterSpec params, SecureRandom random)
@@ -248,7 +232,7 @@
      * The cipher will be initialized for the specified operation (one of:
      * encryption, decryption, key wrapping or key unwrapping) depending on
      * {@code opmode}.
-     * </p>
+     * <p>
      * If this cipher instance needs any algorithm parameters and {@code params}
      * is {@code null}, the underlying implementation of this cipher is supposed
      * to generate the required parameters (using its provider or random
@@ -257,8 +241,7 @@
      * When a cipher instance is initialized by a call to any of the {@code
      * init} methods, the state of the instance is overridden, means it is
      * equivalent to creating a new instance and calling it {@code init} method.
-     * </p>
-     * 
+     *
      * @param opmode
      *            the operation this cipher instance should be initialized for
      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
@@ -275,7 +258,6 @@
      * @throws InvalidAlgorithmParameterException
      *             if the specified parameters are inappropriate for this
      *             cipher.
-     * @since Android 1.0
      */
     protected abstract void engineInit(int opmode, Key key,
             AlgorithmParameters params, SecureRandom random)
@@ -284,7 +266,7 @@
     /**
      * Continues a multi-part transformation (encryption or decryption). The
      * transformed bytes are returned.
-     * 
+     *
      * @param input
      *            the input bytes to transform.
      * @param inputOffset
@@ -299,7 +281,6 @@
      * @throws IllegalArgumentException
      *             if the input is null, or if {@code inputOffset} and {@code
      *             inputLen} do not specify a valid chunk in the input buffer.
-     * @since Android 1.0
      */
     protected abstract byte[] engineUpdate(byte[] input, int inputOffset,
             int inputLen);
@@ -312,8 +293,7 @@
      * a {@code ShortBufferException} is thrown. Use
      * {@link Cipher#getOutputSize getOutputSize} to check for the size of the
      * output buffer.
-     * </p>
-     * 
+     *
      * @param input
      *            the input bytes to transform.
      * @param inputOffset
@@ -327,7 +307,6 @@
      * @return the number of bytes placed in output.
      * @throws ShortBufferException
      *             if the size of the {@code output} buffer is too small.
-     * @since Android 1.0
      */
     protected abstract int engineUpdate(byte[] input, int inputOffset,
             int inputLen, byte[] output, int outputOffset)
@@ -342,8 +321,7 @@
      * bytes a {@code ShortBufferException} is thrown. Use
      * {@link Cipher#getOutputSize getOutputSize} to check for the size of the
      * output buffer.
-     * </p>
-     * 
+     *
      * @param input
      *            the input buffer to transform.
      * @param output
@@ -351,7 +329,6 @@
      * @return the number of bytes stored in the output buffer.
      * @throws ShortBufferException
      *             if the size of the {@code output} buffer is too small.
-     * @since Android 1.0
      */
     protected int engineUpdate(ByteBuffer input, ByteBuffer output)
             throws ShortBufferException {
@@ -395,8 +372,7 @@
      * Processes the {@code inputLen} bytes in {@code input} buffer at {@code
      * inputOffset}, and any bytes that have been buffered in previous {@code
      * update} calls.
-     * </p>
-     * 
+     *
      * @param input
      *            the input buffer.
      * @param inputOffset
@@ -409,7 +385,6 @@
      *             cipher block size.
      * @throws BadPaddingException
      *             if the padding of the data does not match the padding scheme.
-     * @since Android 1.0
      */
     protected abstract byte[] engineDoFinal(byte[] input, int inputOffset,
             int inputLen) throws IllegalBlockSizeException, BadPaddingException;
@@ -418,10 +393,9 @@
      * Finishes a multi-part transformation (encryption or decryption).
      * <p>
      * Processes the {@code inputLen} bytes in {@code input} buffer at
-     * {@code inputOffset}, and any bytes that have been buffered in previous 
+     * {@code inputOffset}, and any bytes that have been buffered in previous
      * {@code update} calls.
-     * </p>
-     * 
+     *
      * @param input
      *            the input buffer.
      * @param inputOffset
@@ -440,7 +414,6 @@
      *             cipher block size.
      * @throws BadPaddingException
      *             if the padding of the data does not match the padding scheme.
-     * @since Android 1.0
      */
     protected abstract int engineDoFinal(byte[] input, int inputOffset,
             int inputLen, byte[] output, int outputOffset)
@@ -454,8 +427,7 @@
      * {@code input.position()}, and any bytes that have been buffered in
      * previous {@code update} calls. The transformed bytes are placed into
      * {@code output} buffer.
-     * </p>
-     * 
+     *
      * @param input
      *            the input buffer.
      * @param output
@@ -519,7 +491,7 @@
      * this class (for backwards compatibility, it cannot be abstract). If this
      * method is not overridden, it throws an {@code
      * UnsupportedOperationException}.
-     * 
+     *
      * @param key
      *            the key to wrap.
      * @return the wrapped key
@@ -528,7 +500,6 @@
      *             cipher block size.
      * @throws InvalidKeyException
      *             if this cipher instance cannot wrap this key.
-     * @since Android 1.0
      */
     protected byte[] engineWrap(Key key) throws IllegalBlockSizeException,
             InvalidKeyException {
@@ -542,8 +513,7 @@
      * This method has been added to this class (for backwards compatibility, it
      * cannot be abstract). If this method is not overridden, it throws an
      * {@code UnsupportedOperationException}.
-     * </p>
-     * 
+     *
      * @param wrappedKey
      *            the wrapped key to unwrap.
      * @param wrappedKeyAlgorithm
@@ -559,7 +529,6 @@
      * @throws NoSuchAlgorithmException
      *             if no provider can be found that can create a key of type
      *             {@code wrappedKeyType} for the {@code wrappedKeyAlgorithm}.
-     * @since Android 1.0
      */
     protected Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
             int wrappedKeyType) throws InvalidKeyException,
@@ -573,17 +542,16 @@
      * added to this class (for backwards compatibility, it cannot be abstract).
      * If this method is not overridden, it throws an {@code
      * UnsupportedOperationException}.
-     * 
+     *
      * @param key
      *            the key to get the size for.
      * @return the size of a specified key object in bits.
      * @throws InvalidKeyException
      *             if the size of the key cannot be determined by this
      *             implementation.
-     * @since Android 1.0
      */
     protected int engineGetKeySize(Key key) throws InvalidKeyException {
         throw new UnsupportedOperationException(
                 Messages.getString("crypto.12")); //$NON-NLS-1$
     }
-}
+}
\ No newline at end of file
diff --git a/libcore/crypto/src/main/java/javax/crypto/EncryptedPrivateKeyInfo.java b/libcore/crypto/src/main/java/javax/crypto/EncryptedPrivateKeyInfo.java
index 301cd49..2d0fd25 100644
--- a/libcore/crypto/src/main/java/javax/crypto/EncryptedPrivateKeyInfo.java
+++ b/libcore/crypto/src/main/java/javax/crypto/EncryptedPrivateKeyInfo.java
@@ -46,7 +46,6 @@
  * #8 - Private-Key Information Syntax Standard</a>.
  * <p>
  * The definition of ASN.1 is as follows:
- * </p>
  * <dl>
  * EncryptedPrivateKeyInfo ::= SEQUENCE {
  * <dd>encryptionAlgorithm AlgorithmIdentifier,</dd>
@@ -57,8 +56,6 @@
  * <dd>algorithm OBJECT IDENTIFIER,</dd>
  * <dd>parameters ANY DEFINED BY algorithm OPTIONAL }</dd>
  * </dl>
- * 
- * @since Android 1.0
  */
 public class EncryptedPrivateKeyInfo {
     // Encryption algorithm name
@@ -75,14 +72,13 @@
     /**
      * Creates an {@code EncryptedPrivateKeyInfo} instance from its encoded
      * representation by parsing it.
-     * 
+     *
      * @param encoded
      *            the encoded representation of this object
      * @throws IOException
      *             if parsing the encoded representation fails.
      * @throws NullPointerException
      *             if {@code encoded} is {@code null}.
-     * @since Android 1.0
      */
     public EncryptedPrivateKeyInfo(byte[] encoded)
             throws IOException {
@@ -127,7 +123,7 @@
     /**
      * Creates an {@code EncryptedPrivateKeyInfo} instance from an algorithm
      * name and its encrypted data.
-     * 
+     *
      * @param encrAlgName
      *            the name of an algorithm.
      * @param encryptedData
@@ -139,7 +135,6 @@
      *             null}.
      * @throws IllegalArgumentException
      *             if {@code encryptedData} is empty.
-     * @since Android 1.0
      */
     public EncryptedPrivateKeyInfo(String encrAlgName, byte[] encryptedData)
         throws NoSuchAlgorithmException {
@@ -166,7 +161,7 @@
     /**
      * Creates an {@code EncryptedPrivateKeyInfo} instance from the
      * encryption algorithm parameters an its encrypted data.
-     * 
+     *
      * @param algParams
      *            the encryption algorithm parameters.
      * @param encryptedData
@@ -177,7 +172,6 @@
      * @throws NullPointerException
      *             if {@code algParams} or {@code encryptedData} is
      *             {@code null}.
-     * @since Android 1.0
      */
     public EncryptedPrivateKeyInfo(AlgorithmParameters algParams,
             byte[] encryptedData)
@@ -204,9 +198,8 @@
 
     /**
      * Returns the name of the encryption algorithm.
-     * 
+     *
      * @return the name of the encryption algorithm.
-     * @since Android 1.0
      */
     public String getAlgName() {
         return algName;
@@ -214,9 +207,8 @@
 
     /**
      * Returns the parameters used by the encryption algorithm.
-     * 
+     *
      * @return the parameters used by the encryption algorithm.
-     * @since Android 1.0
      */
     public AlgorithmParameters getAlgParameters() {
         return algParameters;
@@ -224,10 +216,9 @@
 
     /**
      * Returns the encrypted data of this key.
-     * 
+     *
      * @return the encrypted data of this key, each time this method is called a
      *         new array is returned.
-     * @since Android 1.0
      */
     public byte[] getEncryptedData() {
         byte[] ret = new byte[encryptedData.length];
@@ -242,8 +233,7 @@
      * The cipher must be initialize in either {@code Cipher.DECRYPT_MODE} or
      * {@code Cipher.UNWRAP_MODE} with the same parameters and key used for
      * encrypting this.
-     * </p>
-     * 
+     *
      * @param cipher
      *            the cipher initialized for decrypting the encrypted data.
      * @return the extracted {@code PKCS8EncodedKeySpec}.
@@ -252,7 +242,6 @@
      *             encrypted data.
      * @throws NullPointerException
      *             if {@code cipher} is {@code null}.
-     * @since Android 1.0
      */
     public PKCS8EncodedKeySpec getKeySpec(Cipher cipher)
         throws InvalidKeySpecException {
@@ -280,7 +269,7 @@
     /**
      * Returns the {@code PKCS8EncodedKeySpec} object extracted from the
      * encrypted data.
-     * 
+     *
      * @param decryptKey
      *            the key to decrypt the encrypted data with.
      * @return the extracted {@code PKCS8EncodedKeySpec}.
@@ -292,7 +281,6 @@
      *             data.
      * @throws NullPointerException
      *             if {@code decryptKey} is {@code null}.
-     * @since Android 1.0
      */
     public PKCS8EncodedKeySpec getKeySpec(Key decryptKey)
         throws NoSuchAlgorithmException,
@@ -331,7 +319,7 @@
     /**
      * Returns the {@code PKCS8EncodedKeySpec} object extracted from the
      * encrypted data.
-     * 
+     *
      * @param decryptKey
      *            the key to decrypt the encrypted data with.
      * @param providerName
@@ -349,7 +337,6 @@
      * @throws NullPointerException
      *             if {@code decryptKey} or {@code providerName} is {@code null}
      *             .
-     * @since Android 1.0
      */
     public PKCS8EncodedKeySpec getKeySpec(Key decryptKey, String providerName)
         throws NoSuchProviderException, 
@@ -393,7 +380,7 @@
     /**
      * Returns the {@code PKCS8EncodedKeySpec} object extracted from the
      * encrypted data.
-     * 
+     *
      * @param decryptKey
      *            the key to decrypt the encrypted data with.
      * @param provider
@@ -407,7 +394,6 @@
      *             data.
      * @throws NullPointerException
      *             if {@code decryptKey} or {@code provider} is {@code null}.
-     * @since Android 1.0
      */
     public PKCS8EncodedKeySpec getKeySpec(Key decryptKey, Provider provider)
         throws NoSuchAlgorithmException,
@@ -448,11 +434,10 @@
 
     /**
      * Returns the ASN.1 encoded representation of this object.
-     * 
+     *
      * @return the ASN.1 encoded representation of this object.
      * @throws IOException
      *             if encoding this object fails.
-     * @since Android 1.0
      */
     public byte[] getEncoded() throws IOException {
         if (encoded == null) {
diff --git a/libcore/crypto/src/main/java/javax/crypto/ExemptionMechanism.java b/libcore/crypto/src/main/java/javax/crypto/ExemptionMechanism.java
index 7c68d28..76c88cb 100644
--- a/libcore/crypto/src/main/java/javax/crypto/ExemptionMechanism.java
+++ b/libcore/crypto/src/main/java/javax/crypto/ExemptionMechanism.java
@@ -34,8 +34,6 @@
 /**
  * This class implements the functionality of an exemption mechanism such as
  * <i>key recovery</i>, <i>key weakening</i>, or <i>key escrow</i>.
- * 
- * @since Android 1.0
  */
 public class ExemptionMechanism {
 
@@ -62,14 +60,13 @@
 
     /**
      * Creates a {@code ExemptionMechanism} instance.
-     * 
+     *
      * @param exmechSpi
      *            the implementation delegate.
      * @param provider
      *            the associated provider.
      * @param mechanism
      *            the name of the mechanism.
-     * @since Android 1.0
      */
     protected ExemptionMechanism(ExemptionMechanismSpi exmechSpi,
             Provider provider, String mechanism) {
@@ -81,9 +78,8 @@
 
     /**
      * Returns the name of this {@code ExemptionMechanism}.
-     * 
+     *
      * @return the name of this {@code ExemptionMechanism}.
-     * @since Android 1.0
      */
     public final String getName() {
         return mechanism;
@@ -92,7 +88,7 @@
     /**
      * Returns a new {@code ExemptionMechanism} instance that provides the
      * specified exemption mechanism algorithm.
-     * 
+     *
      * @param algorithm
      *            the name of the requested exemption mechanism.
      * @return the new {@code ExemptionMechanism} instance.
@@ -100,7 +96,6 @@
      *             if the specified algorithm is not available by any provider.
      * @throws NullPointerException
      *             if the algorithm parameter is {@code null}.
-     * @since Android 1.0
      */
     public static final ExemptionMechanism getInstance(String algorithm)
             throws NoSuchAlgorithmException {
@@ -117,7 +112,7 @@
     /**
      * Returns a new {@code ExemptionMechansm} instance that provides the
      * specified exemption mechanism algorithm from the specified provider.
-     * 
+     *
      * @param algorithm
      *            the name of the requested exemption mechanism.
      * @param provider
@@ -132,7 +127,6 @@
      *             if the algorithm parameter is {@code null}.
      * @throws IllegalArgumentException
      *             if the provider parameter is {@code null}.
-     * @since Android 1.0
      */
     public static final ExemptionMechanism getInstance(String algorithm,
             String provider) throws NoSuchAlgorithmException,
@@ -153,7 +147,7 @@
     /**
      * Returns a new {@code ExemptionMechanism} instance that provides the
      * specified exemption mechanism algorithm from the specified provider.
-     * 
+     *
      * @param algorithm
      *            the name of the requested exemption mechanism.
      * @param provider
@@ -166,7 +160,6 @@
      *             if the algorithm parameter is {@code null}.
      * @throws IllegalArgumentException
      *             if the provider parameter is {@code null}.
-     * @since Android 1.0
      */
     public static final ExemptionMechanism getInstance(String algorithm,
             Provider provider) throws NoSuchAlgorithmException {
@@ -185,9 +178,8 @@
 
     /**
      * Returns the provider of this {@code ExemptionMechanism} instance.
-     * 
+     *
      * @return the provider of this {@code ExemptionMechanism} instance.
-     * @since Android 1.0
      */
     public final Provider getProvider() {
         return provider;
@@ -197,7 +189,7 @@
      * Returns whether the result blob for this {@code ExemptionMechanism}
      * instance has been generated successfully and that the specified key is
      * the same as the one that was used to initialize and generate.
-     * 
+     *
      * @param key
      *            the key to verify.
      * @return whether the result blob for this {@code ExemptionMechanism}
@@ -205,7 +197,6 @@
      * @throws ExemptionMechanismException
      *             if an error occurs while determining whether the result blob
      *             has been generated successfully.
-     * @since Android 1.0
      */
     public final boolean isCryptoAllowed(Key key)
             throws ExemptionMechanismException {
@@ -222,14 +213,13 @@
      * Returns the size in bytes for the output buffer needed to hold the output
      * of the next {@link #genExemptionBlob} call, given the specified {@code
      * inputLen} (in bytes).
-     * 
+     *
      * @param inputLen
      *            the specified input length (in bytes).
      * @return the size in bytes for the output buffer.
      * @throws IllegalStateException
      *             if this {@code ExemptionMechanism} instance is not
      *             initialized.
-     * @since Android 1.0
      */
     public final int getOutputSize(int inputLen) throws IllegalStateException {
         if (!isInit) {
@@ -241,14 +231,13 @@
     /**
      * Initializes this {@code ExemptionMechanism} instance with the
      * specified key.
-     * 
+     *
      * @param key
      *            the key to initialize this instance with.
      * @throws InvalidKeyException
      *             if the key cannot be used to initialize this mechanism.
      * @throws ExemptionMechanismException
      *             if error(s) occur during initialization.
-     * @since Android 1.0
      */
     public final void init(Key key) throws InvalidKeyException,
             ExemptionMechanismException {
@@ -261,7 +250,7 @@
     /**
      * Initializes this {@code ExemptionMechanism} instance with the
      * specified key and algorithm parameters.
-     * 
+     *
      * @param key
      *            the key to initialize this instance with.
      * @param param
@@ -273,7 +262,6 @@
      *             mechanism.
      * @throws ExemptionMechanismException
      *             if error(s) occur during initialization.
-     * @since Android 1.0
      */
     public final void init(Key key, AlgorithmParameters param)
             throws InvalidKeyException, InvalidAlgorithmParameterException,
@@ -287,7 +275,7 @@
     /**
      * Initializes this {@code ExemptionMechanism} instance with the
      * specified key and algorithm parameters.
-     * 
+     *
      * @param key
      *            the key to initialize this instance with.
      * @param param
@@ -299,7 +287,6 @@
      *             mechanism.
      * @throws ExemptionMechanismException
      *             if error(s) occur during initialization.
-     * @since Android 1.0
      */
     public final void init(Key key, AlgorithmParameterSpec param)
             throws InvalidKeyException, InvalidAlgorithmParameterException,
@@ -312,14 +299,13 @@
 
     /**
      * Generates the result key blob for this exemption mechanism.
-     * 
+     *
      * @return the result key blob for this exemption mechanism.
      * @throws IllegalStateException
      *             if this {@code ExemptionMechanism} instance is not
      *             initialized.
      * @throws ExemptionMechanismException
      *             if error(s) occur during generation.
-     * @since Android 1.0
      */
     public final byte[] genExemptionBlob() throws IllegalStateException,
             ExemptionMechanismException {
@@ -335,7 +321,7 @@
     /**
      * Generates the result key blob for this exemption mechanism and stores it
      * into the {@code output} buffer.
-     * 
+     *
      * @param output
      *            the output buffer for the result key blob.
      * @return the number of bytes written to the {@code output} buffer.
@@ -346,7 +332,6 @@
      *             if the provided buffer is too small for the result key blob.
      * @throws ExemptionMechanismException
      *             if error(s) occur during generation.
-     * @since Android 1.0
      */
     public final int genExemptionBlob(byte[] output)
             throws IllegalStateException, ShortBufferException,
@@ -357,7 +342,7 @@
     /**
      * Generates the result key blob for this exemption mechanism and stores it
      * into the {@code output} buffer at offset {@code outputOffset}.
-     * 
+     *
      * @param output
      *            the output buffer for the result key blob.
      * @param outputOffset
@@ -370,7 +355,6 @@
      *             if the provided buffer is too small for the result key blob.
      * @throws ExemptionMechanismException
      *             if error(s) occur during generation.
-     * @since Android 1.0
      */
     public final int genExemptionBlob(byte[] output, int outputOffset)
             throws IllegalStateException, ShortBufferException,
@@ -386,8 +370,6 @@
 
     /**
      * Frees the references to the key used to initialize this instance.
-     * 
-     * @since Android 1.0
      */
     @Override
     protected void finalize() {
diff --git a/libcore/crypto/src/main/java/javax/crypto/ExemptionMechanismException.java b/libcore/crypto/src/main/java/javax/crypto/ExemptionMechanismException.java
index 3af498b..d094ac3 100644
--- a/libcore/crypto/src/main/java/javax/crypto/ExemptionMechanismException.java
+++ b/libcore/crypto/src/main/java/javax/crypto/ExemptionMechanismException.java
@@ -21,8 +21,6 @@
 
 /**
  * This is the base class for {@code ExemptionMechanismException}.
- * 
- * @since Android 1.0
  */
 public class ExemptionMechanismException extends GeneralSecurityException {
 
@@ -37,7 +35,6 @@
      * 
      * @param msg
      *            the exception message.
-     * @since Android 1.0
      */
     public ExemptionMechanismException(String msg) {
         super(msg);
@@ -45,8 +42,6 @@
 
     /**
      * Creates a new {@code ExemptionMechanismException} with no message.
-     * 
-     * @since Android 1.0
      */
     public ExemptionMechanismException() {
     }
diff --git a/libcore/crypto/src/main/java/javax/crypto/ExemptionMechanismSpi.java b/libcore/crypto/src/main/java/javax/crypto/ExemptionMechanismSpi.java
index cef1516..39a27f6 100644
--- a/libcore/crypto/src/main/java/javax/crypto/ExemptionMechanismSpi.java
+++ b/libcore/crypto/src/main/java/javax/crypto/ExemptionMechanismSpi.java
@@ -26,26 +26,21 @@
 /**
  * The <i>Service Provider Interface</i> (<b>SPI</b>) definition for the {@code
  * ExemptionMechanism} class.
- * 
- * @since Android 1.0
  */
 public abstract class ExemptionMechanismSpi {
 
     /**
      * Creates a new {@code ExemptionMechanismSpi} instance.
-     * 
-     * @since Android 1.0
      */
     public ExemptionMechanismSpi() {
     }
 
     /**
      * Generates the result key blob for this exemption mechanism.
-     * 
+     *
      * @return the result key blob for this exemption mechanism.
      * @throws ExemptionMechanismException
      *             if error(s) occur during generation.
-     * @since Android 1.0
      */
     protected abstract byte[] engineGenExemptionBlob()
             throws ExemptionMechanismException;
@@ -53,7 +48,7 @@
     /**
      * Generates the result key blob for this exemption mechanism and stores it
      * into the {@code output} buffer at offset {@code outputOffset}.
-     * 
+     *
      * @param output
      *            the output buffer for the result key blob.
      * @param outputOffset
@@ -63,7 +58,6 @@
      *             if the provided buffer is too small for the result key blob.
      * @throws ExemptionMechanismException
      *             if error(s) occur during generation.
-     * @since Android 1.0
      */
     protected abstract int engineGenExemptionBlob(byte[] output,
             int outputOffset) throws ShortBufferException,
@@ -73,7 +67,7 @@
      * Returns the size in bytes for the output buffer needed to hold the output
      * of the next {@link #engineGenExemptionBlob} call, given the specified
      * {@code inputLen} (in bytes).
-     * 
+     *
      * @param inputLen
      *            the specified input length (in bytes).
      * @return the size in bytes for the output buffer.
@@ -83,14 +77,13 @@
     /**
      * Initializes this {@code ExemptionMechanism} instance with the specified
      * key.
-     * 
+     *
      * @param key
      *            the key to initialize this instance with.
      * @throws InvalidKeyException
      *             if the key cannot be used to initialize this mechanism.
      * @throws ExemptionMechanismException
      *             if error(s) occur during initialization.
-     * @since Android 1.0
      */
     protected abstract void engineInit(Key key) throws InvalidKeyException,
             ExemptionMechanismException;
@@ -98,7 +91,7 @@
     /**
      * Initializes this {@code ExemptionMechanism} instance with the specified
      * key and algorithm parameters.
-     * 
+     *
      * @param key
      *            the key to initialize this instance with.
      * @param params
@@ -110,7 +103,6 @@
      *             mechanism.
      * @throws ExemptionMechanismException
      *             if error(s) occur during initialization.
-     * @since Android 1.0
      */
     protected abstract void engineInit(Key key, AlgorithmParameters params)
             throws InvalidKeyException, InvalidAlgorithmParameterException,
@@ -119,7 +111,7 @@
     /**
      * Initializes this {@code ExemptionMechanism} instance with the specified
      * key and algorithm parameters.
-     * 
+     *
      * @param key
      *            the key to initialize this instance with.
      * @param params
@@ -131,7 +123,6 @@
      *             mechanism.
      * @throws ExemptionMechanismException
      *             if error(s) occur during initialization.
-     * @since Android 1.0
      */
     protected abstract void engineInit(Key key, AlgorithmParameterSpec params)
             throws InvalidKeyException, InvalidAlgorithmParameterException,
diff --git a/libcore/crypto/src/main/java/javax/crypto/IllegalBlockSizeException.java b/libcore/crypto/src/main/java/javax/crypto/IllegalBlockSizeException.java
index e376b85..0766b7c 100644
--- a/libcore/crypto/src/main/java/javax/crypto/IllegalBlockSizeException.java
+++ b/libcore/crypto/src/main/java/javax/crypto/IllegalBlockSizeException.java
@@ -22,8 +22,6 @@
 /**
  * The exception, that is thrown when the data length provided to a block cipher
  * does not match the block size of the cipher.
- * 
- * @since Android 1.0
  */
 public class IllegalBlockSizeException extends GeneralSecurityException {
 
@@ -38,7 +36,6 @@
      * 
      * @param msg
      *            the message
-     * @since Android 1.0
      */
     public IllegalBlockSizeException(String msg) {
         super(msg);
@@ -46,8 +43,6 @@
 
     /**
      * Creates a new {@code IllegalBlockSizeException}.
-     * 
-     * @since Android 1.0
      */
     public IllegalBlockSizeException() {
     }
diff --git a/libcore/crypto/src/main/java/javax/crypto/KeyAgreement.java b/libcore/crypto/src/main/java/javax/crypto/KeyAgreement.java
index ee1f195..593aa37 100644
--- a/libcore/crypto/src/main/java/javax/crypto/KeyAgreement.java
+++ b/libcore/crypto/src/main/java/javax/crypto/KeyAgreement.java
@@ -34,8 +34,6 @@
  * This class provides the functionality for a key exchange protocol. This
  * enables two or more parties to agree on a secret key for symmetric
  * cryptography.
- * 
- * @since Android 1.0
  */
 public class KeyAgreement {
 
@@ -56,14 +54,13 @@
 
     /**
      * Creates a new {@code KeyAgreement} instance.
-     * 
+     *
      * @param keyAgreeSpi
      *            the <b>SPI</b> delegate.
      * @param provider
      *            the provider providing this KeyAgreement.
      * @param algorithm
      *            the name of the key agreement algorithm.
-     * @since Android 1.0
      */
     protected KeyAgreement(KeyAgreementSpi keyAgreeSpi, Provider provider,
             String algorithm) {
@@ -74,9 +71,8 @@
 
     /**
      * Returns the name of the key agreement algorithm.
-     * 
+     *
      * @return the name of the key agreement algorithm.
-     * @since Android 1.0
      */
     public final String getAlgorithm() {
         return algorithm;
@@ -84,9 +80,8 @@
 
     /**
      * Returns the provider for this {@code KeyAgreement} instance.
-     * 
+     *
      * @return the provider for this {@code KeyAgreement} instance.
-     * @since Android 1.0
      */
     public final Provider getProvider() {
         return provider;
@@ -94,7 +89,7 @@
 
     /**
      * Creates a new {@code KeyAgreement} for the specified algorithm.
-     * 
+     *
      * @param algorithm
      *            the name of the key agreement algorithm to create.
      * @return a key agreement for the specified algorithm.
@@ -102,7 +97,6 @@
      *             if no installed provider can provide the requested algorithm.
      * @throws NullPointerException
      *             if the specified algorithm is {@code null}.
-     * @since Android 1.0
      */
     public static final KeyAgreement getInstance(String algorithm)
             throws NoSuchAlgorithmException {
@@ -119,7 +113,7 @@
     /**
      * Creates a new {@code KeyAgreement} for the specified algorithm from the
      * specified provider.
-     * 
+     *
      * @param algorithm
      *            the name of the key agreement algorithm to create.
      * @param provider
@@ -134,7 +128,6 @@
      *             if the specified provider does not exist.
      * @throws IllegalArgumentException
      *             if the specified provider name is {@code null} or empty.
-     * @since Android 1.0
      */
     public static final KeyAgreement getInstance(String algorithm,
             String provider) throws NoSuchAlgorithmException,
@@ -152,7 +145,7 @@
     /**
      * Create a new {@code KeyAgreement} for the specified algorithm from the
      * specified provider.
-     * 
+     *
      * @param algorithm
      *            the name of the key agreement algorithm to create.
      * @param provider
@@ -184,13 +177,12 @@
 
     /**
      * Initializes this {@code KeyAgreement} with the specified key.
-     * 
+     *
      * @param key
      *            the key to initialize this key agreement.
      * @throws InvalidKeyException
      *             if the specified key cannot be used to initialize this key
      *             agreement.
-     * @since Android 1.0
      */
     public final void init(Key key) throws InvalidKeyException {
         spiImpl.engineInit(key, rndm);//new SecureRandom());
@@ -199,7 +191,7 @@
     /**
      * Initializes this {@code KeyAgreement} with the specified key and the
      * specified randomness source.
-     * 
+     *
      * @param key
      *            the key to initialize this key agreement.
      * @param random
@@ -207,7 +199,6 @@
      * @throws InvalidKeyException
      *             if the specified key cannot be used to initialize this key
      *             agreement.
-     * @since Android 1.0
      */
     public final void init(Key key, SecureRandom random)
             throws InvalidKeyException {
@@ -217,7 +208,7 @@
     /**
      * Initializes this {@code KeyAgreement} with the specified key and the
      * algorithm parameters.
-     * 
+     *
      * @param key
      *            the key to initialize this key agreement.
      * @param params
@@ -228,7 +219,6 @@
      * @throws InvalidAlgorithmParameterException
      *             if the specified parameters are invalid for this key
      *             agreement algorithm.
-     * @since Android 1.0
      */
     public final void init(Key key, AlgorithmParameterSpec params)
             throws InvalidKeyException, InvalidAlgorithmParameterException {
@@ -238,7 +228,7 @@
     /**
      * Initializes this {@code KeyAgreement} with the specified key, algorithm
      * parameters and randomness source.
-     * 
+     *
      * @param key
      *            the key to initialize this key agreement.
      * @param params
@@ -251,7 +241,6 @@
      * @throws InvalidAlgorithmParameterException
      *             if the specified parameters are invalid for this key
      *             agreement algorithm.
-     * @since Android 1.0
      */
     public final void init(Key key, AlgorithmParameterSpec params,
             SecureRandom random) throws InvalidKeyException,
@@ -262,7 +251,7 @@
     /**
      * Does the next (or the last) phase of the key agreement, using the
      * specified key.
-     * 
+     *
      * @param key
      *            the key received from the other party for this phase.
      * @param lastPhase
@@ -275,7 +264,6 @@
      *             this phase,
      * @throws IllegalStateException
      *             if this instance has not been initialized.
-     * @since Android 1.0
      */
     public final Key doPhase(Key key, boolean lastPhase)
             throws InvalidKeyException, IllegalStateException {
@@ -284,11 +272,10 @@
 
     /**
      * Generates the shared secret.
-     * 
+     *
      * @return the generated shared secret.
      * @throws IllegalStateException
      *             if this key agreement is not complete.
-     * @since Android 1.0
      */
     public final byte[] generateSecret() throws IllegalStateException {
         return spiImpl.engineGenerateSecret();
@@ -297,7 +284,7 @@
     /**
      * Generates the shared secret and stores it into the buffer {@code
      * sharedSecred} at {@code offset}.
-     * 
+     *
      * @param sharedSecret
      *            the buffer to store the shared secret.
      * @param offset
@@ -307,7 +294,6 @@
      *             if this key agreement is not complete.
      * @throws ShortBufferException
      *             if the specified buffer is too small for the shared secret.
-     * @since Android 1.0
      */
     public final int generateSecret(byte[] sharedSecret, int offset)
             throws IllegalStateException, ShortBufferException {
@@ -316,7 +302,7 @@
 
     /**
      * Generates the shared secret.
-     * 
+     *
      * @param algorithm
      *            the algorithm to for the {@code SecretKey}
      * @return the shared secret as a {@code SecretKey} of the specified
@@ -329,7 +315,6 @@
      * @throws InvalidKeyException
      *             if a {@code SecretKey} with the specified algorithm cannot be
      *             created using the generated shared secret.
-     * @since Android 1.0
      */
     public final SecretKey generateSecret(String algorithm)
             throws IllegalStateException, NoSuchAlgorithmException,
diff --git a/libcore/crypto/src/main/java/javax/crypto/KeyAgreementSpi.java b/libcore/crypto/src/main/java/javax/crypto/KeyAgreementSpi.java
index fa9f377..5011183 100644
--- a/libcore/crypto/src/main/java/javax/crypto/KeyAgreementSpi.java
+++ b/libcore/crypto/src/main/java/javax/crypto/KeyAgreementSpi.java
@@ -27,15 +27,11 @@
 /**
  * The <i>Service Provider Interface</i> (<b>SPI</b>) definition for the
  * {@code KeyAgreement} class.
- * 
- * @since Android 1.0
  */
 public abstract class KeyAgreementSpi {
- 
+
     /**
      * Creates a new {@code KeyAgreementSpi} instance.
-     * 
-     * @since Android 1.0
      */
     public KeyAgreementSpi() {
     }
@@ -43,7 +39,7 @@
     /**
      * Does the next (or the last) phase of the key agreement, using the
      * specified key.
-     * 
+     *
      * @param key
      *            the key received from the other party for this phase.
      * @param lastPhase
@@ -56,18 +52,16 @@
      *             this phase,
      * @throws IllegalStateException
      *             if this instance has not been initialized.
-     * @since Android 1.0
      */
     protected abstract Key engineDoPhase(Key key, boolean lastPhase)
             throws InvalidKeyException, IllegalStateException;
 
     /**
      * Generates the shared secret.
-     * 
+     *
      * @return the generated shared secret.
      * @throws IllegalStateException
      *             if this key agreement is not complete.
-     * @since Android 1.0
      */
     protected abstract byte[] engineGenerateSecret()
             throws IllegalStateException;
@@ -75,7 +69,7 @@
     /**
      * Generates the shared secret and stores it into the buffer {@code
      * sharedSecred} at {@code offset}.
-     * 
+     *
      * @param sharedSecret
      *            the buffer to store the shared secret.
      * @param offset
@@ -85,14 +79,13 @@
      *             if this key agreement is not complete.
      * @throws ShortBufferException
      *             if the specified buffer is too small for the shared secret.
-     * @since Android 1.0
      */
     protected abstract int engineGenerateSecret(byte[] sharedSecret, int offset)
             throws IllegalStateException, ShortBufferException;
 
     /**
      * Generates the shared secret.
-     * 
+     *
      * @param algorithm
      *            the algorithm to for the {@code SecretKey}
      * @return the shared secret as a {@code SecretKey} of the specified
@@ -105,7 +98,6 @@
      * @throws InvalidKeyException
      *             if a {@code SecretKey} with the specified algorithm cannot be
      *             created using the generated shared secret.
-     * @since Android 1.0
      */
     protected abstract SecretKey engineGenerateSecret(String algorithm)
             throws IllegalStateException, NoSuchAlgorithmException,
@@ -114,7 +106,7 @@
     /**
      * Initializes this {@code KeyAgreementSpi} with the specified key and the
      * specified randomness source.
-     * 
+     *
      * @param key
      *            the key to initialize this key agreement.
      * @param random
@@ -122,7 +114,6 @@
      * @throws InvalidKeyException
      *             if the specified key cannot be used to initialize this key
      *             agreement.
-     * @since Android 1.0
      */
     protected abstract void engineInit(Key key, SecureRandom random)
             throws InvalidKeyException;
@@ -130,7 +121,7 @@
     /**
      * Initializes this {@code KeyAgreementSpi} with the specified key,
      * algorithm parameters and randomness source.
-     * 
+     *
      * @param key
      *            the key to initialize this key agreement.
      * @param params
@@ -143,7 +134,6 @@
      * @throws InvalidAlgorithmParameterException
      *             if the specified parameters are invalid for this key
      *             agreement algorithm.
-     * @since Android 1.0
      */
     protected abstract void engineInit(Key key, AlgorithmParameterSpec params,
             SecureRandom random) throws InvalidKeyException,
diff --git a/libcore/crypto/src/main/java/javax/crypto/KeyGenerator.java b/libcore/crypto/src/main/java/javax/crypto/KeyGenerator.java
index 3243b39..f1dd3b2 100644
--- a/libcore/crypto/src/main/java/javax/crypto/KeyGenerator.java
+++ b/libcore/crypto/src/main/java/javax/crypto/KeyGenerator.java
@@ -32,8 +32,6 @@
 /**
  * This class provides the public API for generating symmetric cryptographic
  * keys.
- * 
- * @since Android 1.0
  */
 public class KeyGenerator {
 
@@ -54,14 +52,13 @@
 
     /**
      * Creates a new {@code KeyGenerator} instance.
-     * 
+     *
      * @param keyGenSpi
      *            the implementation delegate.
      * @param provider
      *            the implementation provider.
      * @param algorithm
      *            the name of the algorithm.
-     * @since Android 1.0
      */
     protected KeyGenerator(KeyGeneratorSpi keyGenSpi, Provider provider,
             String algorithm) {
@@ -72,9 +69,8 @@
 
     /**
      * Returns the name of the key generation algorithm.
-     * 
+     *
      * @return the name of the key generation algorithm.
-     * @since Android 1.0
      */
     public final String getAlgorithm() {
         return algorithm;
@@ -82,9 +78,8 @@
 
     /**
      * Returns the provider of this {@code KeyGenerator} instance.
-     * 
+     *
      * @return the provider of this {@code KeyGenerator} instance.
-     * @since Android 1.0
      */
     public final Provider getProvider() {
         return provider;
@@ -93,7 +88,7 @@
     /**
      * Creates a new {@code KeyGenerator} instance that provides the specified
      * key algorithm,
-     * 
+     *
      * @param algorithm
      *            the name of the requested key algorithm
      * @return the new {@code KeyGenerator} instance.
@@ -101,7 +96,6 @@
      *             if the specified algorithm is not available by any provider.
      * @throws NullPointerException
      *             if {@code algorithm} is {@code null}.
-     * @since Android 1.0
      */
     public static final KeyGenerator getInstance(String algorithm)
             throws NoSuchAlgorithmException {
@@ -118,7 +112,7 @@
     /**
      * Creates a new {@code KeyGenerator} instance that provides the specified
      * key algorithm from the specified provider.
-     * 
+     *
      * @param algorithm
      *            the name of the requested key algorithm.
      * @param provider
@@ -133,7 +127,6 @@
      *             if the specified provider is name is {@code null} or empty.
      * @throws NullPointerException
      *             if the specified algorithm name is {@code null}.
-     * @since Android 1.0
      */
     public static final KeyGenerator getInstance(String algorithm,
             String provider) throws NoSuchAlgorithmException,
@@ -151,7 +144,7 @@
     /**
      * Creates a new {@code KeyGenerator} instance that provides the specified
      * key algorithm from the specified provider.
-     * 
+     *
      * @param algorithm
      *            the name of the requested key algorithm.
      * @param provider
@@ -164,7 +157,6 @@
      *             if the specified provider is {@code null}.
      * @throws NullPointerException
      *             if the specified algorithm name is {@code null}.
-     * @since Android 1.0
      */
     public static final KeyGenerator getInstance(String algorithm,
             Provider provider) throws NoSuchAlgorithmException {
@@ -183,9 +175,8 @@
 
     /**
      * Generates a secret key.
-     * 
+     *
      * @return the generated secret key.
-     * @since Android 1.0
      */
     public final SecretKey generateKey() {
         return spiImpl.engineGenerateKey();
@@ -194,13 +185,12 @@
     /**
      * Initializes this {@code KeyGenerator} instance with the specified
      * algorithm parameters.
-     * 
+     *
      * @param params
      *            the parameters for the key generation algorithm.
      * @throws InvalidAlgorithmParameterException
      *             if the parameters cannot be used to initialize this key
      *             generator algorithm.
-     * @since Android 1.0
      */
     public final void init(AlgorithmParameterSpec params)
             throws InvalidAlgorithmParameterException {
@@ -210,7 +200,7 @@
     /**
      * Initializes this {@code KeyGenerator} instance with the specified
      * algorithm parameters and randomness source.
-     * 
+     *
      * @param params
      *            the parameters for the key generation algorithm.
      * @param random
@@ -218,7 +208,6 @@
      * @throws InvalidAlgorithmParameterException
      *             if the parameters cannot be uses to initialize this key
      *             generator algorithm.
-     * @since Android 1.0
      */
     public final void init(AlgorithmParameterSpec params, SecureRandom random)
             throws InvalidAlgorithmParameterException {
@@ -228,10 +217,9 @@
     /**
      * Initializes this {@code KeyGenerator} instance for the specified key size
      * (in bits).
-     * 
+     *
      * @param keysize
      *            the size of the key (in bits).
-     * @since Android 1.0
      */
     public final void init(int keysize) {
         spiImpl.engineInit(keysize, rndm);//new SecureRandom());
@@ -240,12 +228,11 @@
     /**
      * Initializes this {@code KeyGenerator} instance for the specified key size
      * (in bits) using the specified randomness source.
-     * 
+     *
      * @param keysize
      *            the size of the key (in bits).
      * @param random
      *            the randomness source for any random bytes.
-     * @since Android 1.0
      */
     public final void init(int keysize, SecureRandom random) {
         spiImpl.engineInit(keysize, random);
@@ -254,10 +241,9 @@
     /**
      * Initializes this {@code KeyGenerator} with the specified randomness
      * source.
-     * 
+     *
      * @param random
      *            the randomness source for any random bytes.
-     * @since Android 1.0
      */
     public final void init(SecureRandom random) {
         spiImpl.engineInit(random);
diff --git a/libcore/crypto/src/main/java/javax/crypto/KeyGeneratorSpi.java b/libcore/crypto/src/main/java/javax/crypto/KeyGeneratorSpi.java
index 165db69..edbbe43 100644
--- a/libcore/crypto/src/main/java/javax/crypto/KeyGeneratorSpi.java
+++ b/libcore/crypto/src/main/java/javax/crypto/KeyGeneratorSpi.java
@@ -26,30 +26,26 @@
  * {@code KeyGenerator} class.
  * 
  * @see KeyGenerator
- * @since Android 1.0
  */
 public abstract class KeyGeneratorSpi {
 
     /**
      * Creates a new {@code KeyGeneratorSpi} instance.
-     * 
-     * @since Android 1.0
      */
     public KeyGeneratorSpi() {
     }
 
     /**
      * Generates a secret key.
-     * 
+     *
      * @return the generated secret key.
-     * @since Android 1.0
      */
     protected abstract SecretKey engineGenerateKey();
 
     /**
      * Initializes this {@code KeyGeneratorSpi} instance with the specified
      * algorithm parameters and randomness source.
-     * 
+     *
      * @param params
      *            the parameters for the key generation algorithm.
      * @param random
@@ -57,7 +53,6 @@
      * @throws InvalidAlgorithmParameterException
      *             if the parameters cannot be uses to initialize this key
      *             generator algorithm.
-     * @since Android 1.0
      */
     protected abstract void engineInit(AlgorithmParameterSpec params,
             SecureRandom random) throws InvalidAlgorithmParameterException;
@@ -65,22 +60,20 @@
     /**
      * Initializes this {@code KeyGenerator} instance for the specified key
      * size (in bits) using the specified randomness source.
-     * 
+     *
      * @param keysize
      *            the size of the key (in bits).
      * @param random
      *            the randomness source for any random bytes.
-     * @since Android 1.0
      */
     protected abstract void engineInit(int keysize, SecureRandom random);
 
     /**
      * Initializes this {@code KeyGenerator} with the specified randomness
      * source.
-     * 
+     *
      * @param random
      *            the randomness source for any random bytes.
-     * @since Android 1.0
      */
     protected abstract void engineInit(SecureRandom random);
 }
\ No newline at end of file
diff --git a/libcore/crypto/src/main/java/javax/crypto/Mac.java b/libcore/crypto/src/main/java/javax/crypto/Mac.java
index 95f4539..94ea20e 100644
--- a/libcore/crypto/src/main/java/javax/crypto/Mac.java
+++ b/libcore/crypto/src/main/java/javax/crypto/Mac.java
@@ -34,8 +34,6 @@
 /**
  * This class provides the public API for <i>Message Authentication Code</i>
  * (MAC) algorithms.
- * 
- * @since Android 1.0
  */
 public class Mac implements Cloneable {
 
@@ -56,14 +54,13 @@
 
     /**
      * Creates a new {@code Mac} instance.
-     * 
+     *
      * @param macSpi
      *            the implementation delegate.
      * @param provider
      *            the implementation provider.
      * @param algorithm
      *            the name of the MAC algorithm.
-     * @since Android 1.0
      */
     protected Mac(MacSpi macSpi, Provider provider, String algorithm) {
         this.provider = provider;
@@ -76,7 +73,6 @@
      * Returns the name of the MAC algorithm.
      * 
      * @return the name of the MAC algorithm.
-     * @since Android 1.0
      */
     public final String getAlgorithm() {
         return algorithm;
@@ -84,9 +80,8 @@
 
     /**
      * Returns the provider of this {@code Mac} instance.
-     * 
+     *
      * @return the provider of this {@code Mac} instance.
-     * @since Android 1.0
      */
     public final Provider getProvider() {
         return provider;
@@ -102,8 +97,8 @@
      * @throws NoSuchAlgorithmException
      *             if the specified algorithm is not available by any provider.
      * @throws NullPointerException
-     *             if {@code algorithm} is {@code null}.
-     * @since Android 1.0
+     *             if {@code algorithm} is {@code null} (instead of
+     *             NoSuchAlgorithmException as in 1.4 release).
      */
     public static final Mac getInstance(String algorithm)
             throws NoSuchAlgorithmException {
@@ -133,8 +128,8 @@
      * @throws IllegalArgumentException
      *             if the specified provider name is {@code null} or empty.
      * @throws NullPointerException
-     *             if {@code algorithm} is {@code null}
-     * @since Android 1.0.
+     *             if {@code algorithm} is {@code null} (instead of
+     *             NoSuchAlgorithmException as in 1.4 release).
      */
     public static final Mac getInstance(String algorithm, String provider)
             throws NoSuchAlgorithmException, NoSuchProviderException {
@@ -163,8 +158,8 @@
      * @throws IllegalArgumentException
      *             if {@code provider} is {@code null}.
      * @throws NullPointerException
-     *             if {@code algorithm} is {@code null}.
-     * @since Android 1.0
+     *             if {@code algorithm} is {@code null} (instead of
+     *             NoSuchAlgorithmException as in 1.4 release).
      */
     public static final Mac getInstance(String algorithm, Provider provider)
             throws NoSuchAlgorithmException {
@@ -182,7 +177,7 @@
 
     /**
      * Returns the length of this MAC (in bytes).
-     * 
+     *
      * @return the length of this MAC (in bytes).
      */
     public final int getMacLength() {
@@ -192,7 +187,7 @@
     /**
      * Initializes this {@code Mac} instance with the specified key and
      * algorithm parameters.
-     * 
+     *
      * @param key
      *            the key to initialize this algorithm.
      * @param params
@@ -203,7 +198,6 @@
      * @throws InvalidAlgorithmParameterException
      *             if the specified parameters cannot be used to initialize this
      *             algorithm.
-     * @since Android 1.0
      */
     public final void init(Key key, AlgorithmParameterSpec params)
             throws InvalidKeyException, InvalidAlgorithmParameterException {
@@ -216,7 +210,7 @@
 
     /**
      * Initializes this {@code Mac} instance with the specified key.
-     * 
+     *
      * @param key
      *            the key to initialize this algorithm.
      * @throws InvalidKeyException
@@ -225,7 +219,6 @@
      * @throws RuntimeException
      *             if the specified key cannot be used to initialize this
      *             algorithm.
-     * @since Android 1.0
      */
     public final void init(Key key) throws InvalidKeyException {
         if (key == null) {
@@ -241,12 +234,11 @@
 
     /**
      * Updates this {@code Mac} instance with the specified byte.
-     * 
+     *
      * @param input
      *            the byte
      * @throws IllegalStateException
      *             if this MAC is not initialized.
-     * @since Android 1.0
      */
     public final void update(byte input) throws IllegalStateException {
         if (!isInitMac) {
@@ -258,7 +250,7 @@
     /**
      * Updates this {@code Mac} instance with the data from the specified buffer
      * {@code input} from the specified {@code offset} and length {@code len}.
-     * 
+     *
      * @param input
      *            the buffer.
      * @param offset
@@ -270,7 +262,6 @@
      * @throws IllegalArgumentException
      *             if {@code offset} and {@code len} do not specified a valid
      *             chunk in {@code input} buffer.
-     * @since Android 1.0
      */
     public final void update(byte[] input, int offset, int len)
             throws IllegalStateException {
@@ -288,12 +279,11 @@
 
     /**
      * Copies the buffer provided as input for further processing.
-     * 
+     *
      * @param input
      *            the buffer.
      * @throws IllegalStateException
      *             if this MAC is not initialized.
-     * @since Android 1.0
      */
     public final void update(byte[] input) throws IllegalStateException {
         if (!isInitMac) {
@@ -308,12 +298,11 @@
      * Updates this {@code Mac} instance with the data from the specified
      * buffer, starting at {@link ByteBuffer#position()}, including the next
      * {@link ByteBuffer#remaining()} bytes.
-     * 
+     *
      * @param input
      *            the buffer.
      * @throws IllegalStateException
      *             if this MAC is not initialized.
-     * @since Android 1.0
      */
     public final void update(ByteBuffer input) {
         if (!isInitMac) {
@@ -333,12 +322,10 @@
      * This {@code Mac} instance is reverted to its initial state and can be
      * used to start the next MAC computation with the same parameters or
      * initialized with different parameters.
-     * </p>
-     * 
+     *
      * @return the generated digest.
      * @throws IllegalStateException
      *             if this MAC is not initialized.
-     * @since Android 1.0
      */
     public final byte[] doFinal() throws IllegalStateException {
         if (!isInitMac) {
@@ -355,8 +342,7 @@
      * This {@code Mac} instance is reverted to its initial state and can be
      * used to start the next MAC computation with the same parameters or
      * initialized with different parameters.
-     * </p>
-     * 
+     *
      * @param output
      *            the output buffer
      * @param outOffset
@@ -368,7 +354,6 @@
      *             of the output buffer.
      * @throws IllegalStateException
      *             if this MAC is not initialized.
-     * @since Android 1.0
      */
     public final void doFinal(byte[] output, int outOffset)
             throws ShortBufferException, IllegalStateException {
@@ -401,14 +386,12 @@
      * This {@code Mac} instance is reverted to its initial state and can be
      * used to start the next MAC computation with the same parameters or
      * initialized with different parameters.
-     * </p>
-     * 
+     *
      * @param input
      *            the final bytes.
      * @return the generated digest.
      * @throws IllegalStateException
      *             if this MAC is not initialized.
-     * @since Android 1.0
      */
     public final byte[] doFinal(byte[] input) throws IllegalStateException {
         if (!isInitMac) {
@@ -426,9 +409,6 @@
      * This {@code Mac} instance is reverted to its initial state and can be
      * used to start the next MAC computation with the same parameters or
      * initialized with different parameters.
-     * </p>
-     * 
-     * @since Android 1.0
      */
     public final void reset() {
         spiImpl.engineReset();
@@ -436,11 +416,10 @@
 
     /**
      * Clones this {@code Mac} instance and the underlying implementation.
-     * 
+     *
      * @return the cloned instance.
      * @throws CloneNotSupportedException
      *             if the underlying implementation does not support cloning.
-     * @since Android 1.0
      */
     @Override
     public final Object clone() throws CloneNotSupportedException {
@@ -449,4 +428,4 @@
         mac.isInitMac = this.isInitMac; 
         return mac;
     }
-}
+}
\ No newline at end of file
diff --git a/libcore/crypto/src/main/java/javax/crypto/MacSpi.java b/libcore/crypto/src/main/java/javax/crypto/MacSpi.java
index 4756184..b2683d2 100644
--- a/libcore/crypto/src/main/java/javax/crypto/MacSpi.java
+++ b/libcore/crypto/src/main/java/javax/crypto/MacSpi.java
@@ -28,30 +28,26 @@
  * Mac} class.
  * 
  * @see Mac
- * @since Android 1.0
  */
 public abstract class MacSpi {
-    
+
     /**
      * Creates a new {@code MacSpi} instance.
-     * 
-     * @since Android 1.0
      */
     public MacSpi() {
     }
 
     /**
      * Returns the length of this MAC (in bytes).
-     * 
+     *
      * @return the length of this MAC (in bytes).
-     * @since Android 1.0
      */
     protected abstract int engineGetMacLength();
 
     /**
      * Initializes this {@code MacSpi} instance with the specified key and
      * algorithm parameters.
-     * 
+     *
      * @param key
      *            the key to initialize this algorithm.
      * @param params
@@ -62,17 +58,15 @@
      * @throws InvalidAlgorithmParameterException
      *             if the specified parameters cannot be used to initialize this
      *             algorithm.
-     * @since Android 1.0
      */
     protected abstract void engineInit(Key key, AlgorithmParameterSpec params)
             throws InvalidKeyException, InvalidAlgorithmParameterException;
 
     /**
      * Updates this {@code MacSpi} instance with the specified byte.
-     * 
+     *
      * @param input
      *            the byte.
-     * @since Android 1.0
      */
     protected abstract void engineUpdate(byte input);
 
@@ -80,14 +74,13 @@
      * Updates this {@code MacSpi} instance with the data from the specified
      * buffer {@code input} from the specified {@code offset} and length {@code
      * len}.
-     * 
+     *
      * @param input
      *            the buffer.
      * @param offset
      *            the offset in the buffer.
      * @param len
      *            the length of the data in the buffer.
-     * @since Android 1.0
      */
     protected abstract void engineUpdate(byte[] input, int offset, int len);
 
@@ -95,10 +88,9 @@
      * Updates this {@code MacSpi} instance with the data from the specified
      * buffer, starting at {@link ByteBuffer#position()}, including the next
      * {@link ByteBuffer#remaining()} bytes.
-     * 
+     *
      * @param input
      *            the buffer.
-     * @since Android 1.0
      */
     protected void engineUpdate(ByteBuffer input) {
         if (!input.hasRemaining()) {
@@ -126,10 +118,8 @@
      * This {@code MacSpi} instance is reverted to its initial state and
      * can be used to start the next MAC computation with the same parameters or
      * initialized with different parameters.
-     * </p>
-     * 
+     *
      * @return the generated digest.
-     * @since Android 1.0
      */
     protected abstract byte[] engineDoFinal();
 
@@ -139,19 +129,15 @@
      * This {@code MacSpi} instance is reverted to its initial state and can be
      * used to start the next MAC computation with the same parameters or
      * initialized with different parameters.
-     * </p>
-     * 
-     * @since Android 1.0
      */
     protected abstract void engineReset();
 
     /**
      * Clones this {@code MacSpi} instance.
-     * 
+     *
      * @return the cloned instance.
      * @throws CloneNotSupportedException
      *             if cloning is not supported.
-     * @since Android 1.0
      */
     @Override
     public Object clone() throws CloneNotSupportedException {
diff --git a/libcore/crypto/src/main/java/javax/crypto/NoSuchPaddingException.java b/libcore/crypto/src/main/java/javax/crypto/NoSuchPaddingException.java
index 4afb8ab..55e1f1e 100644
--- a/libcore/crypto/src/main/java/javax/crypto/NoSuchPaddingException.java
+++ b/libcore/crypto/src/main/java/javax/crypto/NoSuchPaddingException.java
@@ -22,8 +22,6 @@
 /**
  * The exception that is thrown when the requested padding mechanism is not
  * supported.
- * 
- * @since Android 1.0
  */
 public class NoSuchPaddingException extends GeneralSecurityException {
 
@@ -38,7 +36,6 @@
      * 
      * @param msg
      *            the message.
-     * @since Android 1.0
      */
     public NoSuchPaddingException(String msg) {
         super(msg);
@@ -46,8 +43,6 @@
 
     /**
      * Creates a new {@code NoSuchPaddingException}.
-     * 
-     * @since Android 1.0
      */
     public NoSuchPaddingException() {
     }
diff --git a/libcore/crypto/src/main/java/javax/crypto/NullCipher.java b/libcore/crypto/src/main/java/javax/crypto/NullCipher.java
index 49f96c2..fadf3ae 100644
--- a/libcore/crypto/src/main/java/javax/crypto/NullCipher.java
+++ b/libcore/crypto/src/main/java/javax/crypto/NullCipher.java
@@ -32,8 +32,6 @@
 /**
  * This class provides an identity cipher that does not transform the input data
  * in any way. The <i>encrypted</i> data is identical to the <i>plain text</i>.
- * 
- * @since Android 1.0
  */
 public class NullCipher extends Cipher {
 
diff --git a/libcore/crypto/src/main/java/javax/crypto/SealedObject.java b/libcore/crypto/src/main/java/javax/crypto/SealedObject.java
index 4e71453..bf453db 100644
--- a/libcore/crypto/src/main/java/javax/crypto/SealedObject.java
+++ b/libcore/crypto/src/main/java/javax/crypto/SealedObject.java
@@ -40,19 +40,13 @@
  * <p>
  * Since a {@code SealedObject} instance is a serializable object itself it can
  * either be stored or transmitted over an insecure channel.
- * </p>
+ * <p>
  * The wrapped object can later be decrypted (unsealed) using the corresponding
  * key and then be deserialized to retrieve the original object.The sealed
  * object itself keeps track of the cipher and corresponding parameters.
- * 
- * @since Android 1.0
  */
 public class SealedObject implements Serializable {
 
-    // the value of this field was derived by using serialver utility
-    /**
-     * @com.intel.drl.spec_ref
-     */
     private static final long serialVersionUID = 4482838265551344752L;
 
     /**
@@ -76,8 +70,7 @@
      * and sealing it using the specified cipher.
      * <p>
      * The cipher must be fully initialized.
-     * </p>
-     * 
+     *
      * @param object
      *            the object to seal, can be {@code null}.
      * @param c
@@ -90,7 +83,6 @@
      *             size.
      * @throws NullPointerException
      *             if the cipher is {@code null}.
-     * @since Android 1.0
      */
     public SealedObject(Serializable object, Cipher c)
                 throws IOException, IllegalBlockSizeException {
@@ -117,10 +109,9 @@
     /**
      * Creates a new {@code SealedObject} instance by copying the data from
      * the specified object.
-     * 
+     *
      * @param so
      *            the object to copy.
-     * @since Android 1.0
      */
     protected SealedObject(SealedObject so) {
         if (so == null) {
@@ -134,9 +125,8 @@
 
     /**
      * Returns the algorithm this object was sealed with.
-     * 
+     *
      * @return the algorithm this object was sealed with.
-     * @since Android 1.0
      */
     public final String getAlgorithm() {
         return sealAlg;
@@ -144,7 +134,7 @@
 
     /**
      * Returns the wrapped object, decrypting it using the specified key.
-     * 
+     *
      * @param key
      *            the key to decrypt the data with.
      * @return the encapsulated object.
@@ -156,7 +146,6 @@
      *             if the algorithm to decrypt the data is not available.
      * @throws InvalidKeyException
      *             if the specified key cannot be used to decrypt the data.
-     * @since Android 1.0
      */
     public final Object getObject(Key key)
                 throws IOException, ClassNotFoundException,
@@ -207,7 +196,7 @@
     /**
      * Returns the wrapped object, decrypting it using the specified
      * cipher.
-     * 
+     *
      * @param c
      *            the cipher to decrypt the data.
      * @return the encapsulated object.
@@ -221,7 +210,6 @@
      *             size.
      * @throws BadPaddingException
      *             if the padding of the data does not match the padding scheme.
-     * @since Android 1.0
      */
     public final Object getObject(Cipher c)
                 throws IOException, ClassNotFoundException,
@@ -239,7 +227,7 @@
     /**
      * Returns the wrapped object, decrypting it using the specified key. The
      * specified provider is used to retrieve the cipher algorithm.
-     * 
+     *
      * @param key
      *            the key to decrypt the data.
      * @param provider
@@ -255,7 +243,6 @@
      *             if the specified provider is not available.
      * @throws InvalidKeyException
      *             if the specified key cannot be used to decrypt the data.
-     * @since Android 1.0
      */
     public final Object getObject(Key key, String provider)
                 throws IOException, ClassNotFoundException,
diff --git a/libcore/crypto/src/main/java/javax/crypto/SecretKey.java b/libcore/crypto/src/main/java/javax/crypto/SecretKey.java
index 102f888..ac61074 100644
--- a/libcore/crypto/src/main/java/javax/crypto/SecretKey.java
+++ b/libcore/crypto/src/main/java/javax/crypto/SecretKey.java
@@ -24,21 +24,18 @@
  * <p>
  * This interface is a <i>marker interface</i> to group secret keys and to
  * provide type safety for.
- * </p>
+ * <p>
  * Implementations of this interface have to overwrite the
  * {@link Object#equals(Object) equals} and {@link Object#hashCode() hashCode}
  * from {@link java.lang.Object} so comparison is done using the actual key data
  * and not the object reference.
- * 
- * @since Android 1.0
  */
 public interface SecretKey extends Key {
 
     /**
      * The serialization version identifier.
-     * 
+     *
      * @serial
-     * @since Android 1.0
      */
     public static final long serialVersionUID = -4795878709595146952L;
 }
\ No newline at end of file
diff --git a/libcore/crypto/src/main/java/javax/crypto/SecretKeyFactory.java b/libcore/crypto/src/main/java/javax/crypto/SecretKeyFactory.java
index a420dab..57bca3e 100644
--- a/libcore/crypto/src/main/java/javax/crypto/SecretKeyFactory.java
+++ b/libcore/crypto/src/main/java/javax/crypto/SecretKeyFactory.java
@@ -40,9 +40,6 @@
  * </ul>
  * Which key specifications are supported by the {@link #generateSecret} and
  * {@link #getKeySpec} is provider dependent.
- * </p>
- * 
- * @since Android 1.0
  */
 public class SecretKeyFactory {
 
@@ -60,14 +57,13 @@
 
     /**
      * Creates a new {@code SecretKeyFactory}
-     * 
+     *
      * @param keyFacSpi
      *            the SPI delegate.
      * @param provider
      *            the provider providing this key factory.
      * @param algorithm
      *            the algorithm name for the secret key.
-     * @since Android 1.0
      */
     protected SecretKeyFactory(SecretKeyFactorySpi keyFacSpi,
             Provider provider, String algorithm) {
@@ -78,9 +74,8 @@
 
     /**
      * Returns the name of the secret key algorithm.
-     * 
+     *
      * @return the name of the secret key algorithm.
-     * @since Android 1.0
      */
     public final String getAlgorithm() {
         return algorithm;
@@ -88,9 +83,8 @@
 
     /**
      * Returns the provider for this {@code SecretKeyFactory} instance.
-     * 
+     *
      * @return the provider for this {@code SecretKeyFactory} instance.
-     * @since Android 1.0
      */
     public final Provider getProvider() {
         return provider;
@@ -99,7 +93,7 @@
     /**
      * Creates a new {@code SecretKeyFactory} instance for the specified key
      * algorithm.
-     * 
+     *
      * @param algorithm
      *            the name of the key algorithm.
      * @return a secret key factory for the specified key algorithm.
@@ -107,7 +101,6 @@
      *             if no installed provider can provide the requested algorithm.
      * @throws NullPointerException
      *             if the specified algorithm is {@code null}.
-     * @since Android 1.0
      */
     public static final SecretKeyFactory getInstance(String algorithm)
             throws NoSuchAlgorithmException {
@@ -124,7 +117,7 @@
     /**
      * Creates a new {@code SecretKeyFactory} instance for the specified key
      * algorithm from the specified {@code provider}.
-     * 
+     *
      * @param algorithm
      *            the name of the key algorithm.
      * @param provider
@@ -139,7 +132,6 @@
      *             if the specified provider does not exist.
      * @throws IllegalArgumentException
      *             if the specified provider name is {@code null} or empty.
-     * @since Android 1.0
      */
     public static final SecretKeyFactory getInstance(String algorithm,
             String provider) throws NoSuchAlgorithmException,
@@ -157,7 +149,7 @@
     /**
      * Creates a new {@code SecretKeyFactory} instance for the specified key
      * algorithm from the specified provider.
-     * 
+     *
      * @param algorithm
      *            the name of the key algorithm.
      * @param provider
@@ -171,7 +163,6 @@
      *             if the specified provider is {@code null}.
      * @throws NullPointerException
      *             is the specified algorithm name is {@code null}.
-     * @since Android 1.0
      */
     public static final SecretKeyFactory getInstance(String algorithm,
             Provider provider) throws NoSuchAlgorithmException {
@@ -190,14 +181,13 @@
 
     /**
      * Generate a secret key from the specified key specification.
-     * 
+     *
      * @param keySpec
      *            the key specification.
      * @return a secret key.
      * @throws InvalidKeySpecException
      *             if the specified key specification cannot be used to generate
      *             a secret key.
-     * @since Android 1.0
      */
     public final SecretKey generateSecret(KeySpec keySpec)
             throws InvalidKeySpecException {
@@ -206,7 +196,7 @@
 
     /**
      * Returns the key specification of the specified secret key.
-     * 
+     *
      * @param key
      *            the secret key to get the specification from.
      * @param keySpec
@@ -215,7 +205,6 @@
      * @throws InvalidKeySpecException
      *             if the specified secret key cannot be transformed into the
      *             requested key specification.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public final KeySpec getKeySpec(SecretKey key, Class keySpec)
@@ -226,14 +215,13 @@
     /**
      * Translates the specified secret key into an instance of the corresponding
      * key from the provider of this key factory.
-     * 
+     *
      * @param key
      *            the secret key to translate.
      * @return the corresponding translated key.
      * @throws InvalidKeyException
      *             if the specified key cannot be translated using this key
      *             factory.
-     * @since Android 1.0
      */
     public final SecretKey translateKey(SecretKey key)
             throws InvalidKeyException {
diff --git a/libcore/crypto/src/main/java/javax/crypto/SecretKeyFactorySpi.java b/libcore/crypto/src/main/java/javax/crypto/SecretKeyFactorySpi.java
index f834dbb..5d7764e 100644
--- a/libcore/crypto/src/main/java/javax/crypto/SecretKeyFactorySpi.java
+++ b/libcore/crypto/src/main/java/javax/crypto/SecretKeyFactorySpi.java
@@ -24,35 +24,31 @@
 /**
  * The <i>Service Provider Interface</i> (<b>SPI</b>) definition for the {@code
  * SecretKeyFactory} class.
- * 
- * @since Android 1.0
  */
 public abstract class SecretKeyFactorySpi {
 
     /**
      * Creates a new {@code SecretKeyFactorySpi} instance.
-     * @since Android 1.0
      */
     public SecretKeyFactorySpi() {
     }
 
     /**
      * Generate a secret key from the specified key specification.
-     * 
+     *
      * @param keySpec
      *            the key specification.
      * @return a secret key.
      * @throws InvalidKeySpecException
      *             if the specified key specification cannot be used to generate
      *             a secret key.
-     * @since Android 1.0
      */
     protected abstract SecretKey engineGenerateSecret(KeySpec keySpec)
             throws InvalidKeySpecException;
 
     /**
      * Returns the key specification of the specified secret key.
-     * 
+     *
      * @param key
      *            the secret key to get the specification from.
      * @param keySpec
@@ -61,7 +57,6 @@
      * @throws InvalidKeySpecException
      *             if the specified secret key cannot be transformed into the
      *             requested key specification.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     protected abstract KeySpec engineGetKeySpec(SecretKey key, Class keySpec)
@@ -70,14 +65,13 @@
     /**
      * Translates the specified secret key into an instance of the corresponding
      * key from the provider of this key factory.
-     * 
+     *
      * @param key
      *            the secret key to translate.
      * @return the corresponding translated key.
      * @throws InvalidKeyException
      *             if the specified key cannot be translated using this key
      *             factory.
-     * @since Android 1.0
      */
     protected abstract SecretKey engineTranslateKey(SecretKey key)
             throws InvalidKeyException;
diff --git a/libcore/crypto/src/main/java/javax/crypto/ShortBufferException.java b/libcore/crypto/src/main/java/javax/crypto/ShortBufferException.java
index 593a31e..56480a8 100644
--- a/libcore/crypto/src/main/java/javax/crypto/ShortBufferException.java
+++ b/libcore/crypto/src/main/java/javax/crypto/ShortBufferException.java
@@ -27,8 +27,6 @@
 /**
  * The exception that is thrown when the result of an operation is attempted to
  * store in a user provided buffer that is too small.
- * 
- * @since Android 1.0
  */
 public class ShortBufferException extends GeneralSecurityException {
 
@@ -43,7 +41,6 @@
      * 
      * @param msg
      *            the exception message.
-     * @since Android 1.0
      */
     public ShortBufferException(String msg) {
         super(msg);
@@ -51,8 +48,6 @@
 
     /**
      * Creates a new instance of {@code ShortBufferException}.
-     * 
-     * @since Android 1.0
      */
     public ShortBufferException() {
     }
diff --git a/libcore/crypto/src/main/java/javax/crypto/interfaces/DHKey.java b/libcore/crypto/src/main/java/javax/crypto/interfaces/DHKey.java
index f686844..6ef17d4 100644
--- a/libcore/crypto/src/main/java/javax/crypto/interfaces/DHKey.java
+++ b/libcore/crypto/src/main/java/javax/crypto/interfaces/DHKey.java
@@ -21,14 +21,12 @@
 
 /**
  * The interface for a Diffie-Hellman key.
- * 
- * @since Android 1.0
  */
 public interface DHKey {
 
     /**
      * Returns the parameters for this key.
-     * 
+     *
      * @return the parameters for this key.
      */
     public DHParameterSpec getParams();
diff --git a/libcore/crypto/src/main/java/javax/crypto/interfaces/DHPrivateKey.java b/libcore/crypto/src/main/java/javax/crypto/interfaces/DHPrivateKey.java
index d39268b..f63e0cb 100644
--- a/libcore/crypto/src/main/java/javax/crypto/interfaces/DHPrivateKey.java
+++ b/libcore/crypto/src/main/java/javax/crypto/interfaces/DHPrivateKey.java
@@ -22,8 +22,6 @@
 
 /**
  * The interface for a private key in the Diffie-Hellman key exchange protocol.
- * 
- * @since Android 1.0
  */
 public interface DHPrivateKey extends DHKey, PrivateKey {
 
diff --git a/libcore/crypto/src/main/java/javax/crypto/interfaces/DHPublicKey.java b/libcore/crypto/src/main/java/javax/crypto/interfaces/DHPublicKey.java
index 75201a7..92e8f10 100644
--- a/libcore/crypto/src/main/java/javax/crypto/interfaces/DHPublicKey.java
+++ b/libcore/crypto/src/main/java/javax/crypto/interfaces/DHPublicKey.java
@@ -21,9 +21,7 @@
 import java.security.PublicKey;
 
 /**
- * The interface for a public key in the Diffie-Hellman key exchange protocol. 
- * 
- * @since Android 1.0
+ * The interface for a public key in the Diffie-Hellman key exchange protocol.
  */
 public interface DHPublicKey extends DHKey, PublicKey {
 
diff --git a/libcore/crypto/src/main/java/javax/crypto/interfaces/PBEKey.java b/libcore/crypto/src/main/java/javax/crypto/interfaces/PBEKey.java
index 4612ad2..c718715 100644
--- a/libcore/crypto/src/main/java/javax/crypto/interfaces/PBEKey.java
+++ b/libcore/crypto/src/main/java/javax/crypto/interfaces/PBEKey.java
@@ -21,8 +21,6 @@
 
 /**
  * The interface to a <i>password-based-encryption</i>  key.
- * 
- * @since Android 1.0
  */
 public interface PBEKey extends SecretKey {
 
@@ -33,21 +31,21 @@
 
     /**
      * Returns the iteration count, 0 if not specified.
-     * 
+     *
      * @return the iteration count, 0 if not specified.
      */
     public int getIterationCount();
 
     /**
      * Returns a copy of the salt data or null if not specified.
-     * 
+     *
      * @return a copy of the salt data or null if not specified.
      */
     public byte[] getSalt();
 
     /**
      * Returns a copy to the password.
-     * 
+     *
      * @return a copy to the password.
      */
     public char[] getPassword();
diff --git a/libcore/crypto/src/main/java/javax/crypto/spec/DESKeySpec.java b/libcore/crypto/src/main/java/javax/crypto/spec/DESKeySpec.java
index 2a994d5..372a68d 100644
--- a/libcore/crypto/src/main/java/javax/crypto/spec/DESKeySpec.java
+++ b/libcore/crypto/src/main/java/javax/crypto/spec/DESKeySpec.java
@@ -24,8 +24,6 @@
 
 /**
  * The key specification for a DES key.
- * 
- * @since Android 1.0
  */
 public class DESKeySpec implements KeySpec {
 
@@ -96,7 +94,7 @@
     /**
      * Creates a new <code>DESKeySpec</code> from the first 8 bytes of the
      * specified key data.
-     * 
+     *
      * @param key
      *            the key data.
      * @throws InvalidKeyException
@@ -109,7 +107,7 @@
     /**
      * Creates a new <code>DESKeySpec</code> from the first 8 bytes of the
      * specified key data starting at <code>offset</code>.
-     * 
+     *
      * @param key
      *            the key data
      * @param offset
@@ -133,7 +131,7 @@
 
     /**
      * Returns a copy of the key.
-     * 
+     *
      * @return a copy of the key.
      */
     public byte[] getKey() {
@@ -145,7 +143,7 @@
     /**
      * Returns whether the specified key data starting at <code>offset</code> is
      * <i>parity-adjusted</i>.
-     * 
+     *
      * @param key
      *            the key data.
      * @param offset
@@ -185,7 +183,7 @@
     /**
      * Returns whether the specified key data starting at <code>offset</code> is
      * weak or semi-weak.
-     * 
+     *
      * @param key
      *            the key data.
      * @param offset
diff --git a/libcore/crypto/src/main/java/javax/crypto/spec/DESedeKeySpec.java b/libcore/crypto/src/main/java/javax/crypto/spec/DESedeKeySpec.java
index 186f07d..199eba6 100644
--- a/libcore/crypto/src/main/java/javax/crypto/spec/DESedeKeySpec.java
+++ b/libcore/crypto/src/main/java/javax/crypto/spec/DESedeKeySpec.java
@@ -24,8 +24,6 @@
 
 /**
  * The key specification for a triple-DES (DES-EDE) key.
- * 
- * @since Android 1.0
  */
 public class DESedeKeySpec implements KeySpec {
 
@@ -39,7 +37,7 @@
     /**
      * Creates a new <code>DESedeKeySpec</code> instance from the first 24 (
      * {@link #DES_EDE_KEY_LEN}) bytes of the specified key data.
-     * 
+     *
      * @param key
      *            the key data.
      * @throws InvalidKeyException
@@ -64,7 +62,7 @@
      * Creates a new <code>DESedeKeySpec</code> instance from the first 24 (
      * {@link #DES_EDE_KEY_LEN} ) bytes of the specified key data starting at
      * <code>offset</code>.
-     * 
+     *
      * @param key
      *            the key data
      * @param offset
@@ -90,7 +88,7 @@
 
     /**
      * Returns a copy of the key.
-     * 
+     *
      * @return a copy of the key.
      */
     public byte[] getKey() {
@@ -102,7 +100,7 @@
     /**
      * Returns whether the specified key data starting at <code>offset</code> is
      * <i>parity-adjusted</i>.
-     * 
+     *
      * @param key
      *            the key data.
      * @param offset
diff --git a/libcore/crypto/src/main/java/javax/crypto/spec/DHGenParameterSpec.java b/libcore/crypto/src/main/java/javax/crypto/spec/DHGenParameterSpec.java
index a149318..f6ddc03 100644
--- a/libcore/crypto/src/main/java/javax/crypto/spec/DHGenParameterSpec.java
+++ b/libcore/crypto/src/main/java/javax/crypto/spec/DHGenParameterSpec.java
@@ -22,8 +22,6 @@
 /**
  * The algorithm parameter specification for generating Diffie-Hellman
  * parameters used in Diffie-Hellman key agreement.
- * 
- * @since Android 1.0
  */
 public class DHGenParameterSpec implements AlgorithmParameterSpec {
 
@@ -33,7 +31,7 @@
     /**
      * Creates a new <code>DHGenParameterSpec</code> instance with the specified
      * parameters.
-     * 
+     *
      * @param primeSize
      *            the size of the <i>prime modulus</i> in bits.
      * @param exponentSize
@@ -46,7 +44,7 @@
 
     /**
      * Returns the size of the <i>prime modulus</i> in bits.
-     * 
+     *
      * @return the size of the prime modulus in bits.
      */
     public int getPrimeSize() {
@@ -55,7 +53,7 @@
 
     /**
      * Returns the size of the <i>random exponent</i> in bits.
-     * 
+     *
      * @return the size of the random exponent in bits.
      */
     public int getExponentSize() {
diff --git a/libcore/crypto/src/main/java/javax/crypto/spec/DHParameterSpec.java b/libcore/crypto/src/main/java/javax/crypto/spec/DHParameterSpec.java
index 9bb94b5..6030b40 100644
--- a/libcore/crypto/src/main/java/javax/crypto/spec/DHParameterSpec.java
+++ b/libcore/crypto/src/main/java/javax/crypto/spec/DHParameterSpec.java
@@ -22,8 +22,6 @@
 
 /**
  * The algorithm parameter specification for the Diffie-Hellman algorithm.
- * 
- * @since Android 1.0
  */
 public class DHParameterSpec implements AlgorithmParameterSpec {
 
@@ -34,7 +32,7 @@
     /**
      * Creates a new <code>DHParameterSpec</code> instance with the specified
      * <i>prime modulus</i> and <i>base generator</i>.
-     * 
+     *
      * @param p
      *            the prime modulus.
      * @param g
@@ -50,7 +48,7 @@
      * Creates a new <code>DHParameterSpec</code> instance with the specified
      * <i>prime modulus</i>, <i>base generator</i> and size (in bits) of the
      * <i>random exponent</i>.
-     * 
+     *
      * @param p
      *            the prime modulus.
      * @param g
@@ -66,7 +64,7 @@
 
     /**
      * Returns the <i>prime modulus</i> of this parameter specification.
-     * 
+     *
      * @return the prime modulus.
      */
     public BigInteger getP() {
@@ -75,7 +73,7 @@
 
     /**
      * Returns the <i>base generator</i> of this parameter specification.
-     * 
+     *
      * @return the base generator.
      */
     public BigInteger getG() {
@@ -84,7 +82,7 @@
 
     /**
      * Returns the size (in bits) of the <i>random exponent</i>.
-     * 
+     *
      * @return the size (in bits) of the random exponent.
      */
     public int getL() {
diff --git a/libcore/crypto/src/main/java/javax/crypto/spec/DHPrivateKeySpec.java b/libcore/crypto/src/main/java/javax/crypto/spec/DHPrivateKeySpec.java
index 6652de8..925a003 100644
--- a/libcore/crypto/src/main/java/javax/crypto/spec/DHPrivateKeySpec.java
+++ b/libcore/crypto/src/main/java/javax/crypto/spec/DHPrivateKeySpec.java
@@ -22,8 +22,6 @@
 
 /**
  * The key specification for a Diffie-Hellman private key.
- * 
- * @since Android 1.0
  */
 public class DHPrivateKeySpec implements KeySpec {
 
@@ -35,7 +33,7 @@
      * Creates a new <code>DHPrivateKeySpec</code> with the specified <i>private
      * value</i> <code>x</code>. <i>prime modulus</i> <code>p</code> and <i>base
      * generator</i> <code>g</code>.
-     * 
+     *
      * @param x
      *            the private value.
      * @param p
@@ -51,7 +49,7 @@
 
     /**
      * Returns the <i>private value</i> <code>x</code>.
-     * 
+     *
      * @return the private value <code>x</code>.
      */
     public BigInteger getX() {
@@ -60,7 +58,7 @@
 
     /**
      * Returns the <i>prime modulus</i> <code>p</code>.
-     * 
+     *
      * @return the prime modulus <code>p</code>.
      */
     public BigInteger getP() {
@@ -69,10 +67,11 @@
 
     /**
      * Returns the <i>base generator</i> <code>g</code>.
-     * 
+     *
      * @return the base generator <code>g</code>.
      */
     public BigInteger getG() {
         return g;
     }
 }
+
diff --git a/libcore/crypto/src/main/java/javax/crypto/spec/DHPublicKeySpec.java b/libcore/crypto/src/main/java/javax/crypto/spec/DHPublicKeySpec.java
index 68d3267..a5d4461 100644
--- a/libcore/crypto/src/main/java/javax/crypto/spec/DHPublicKeySpec.java
+++ b/libcore/crypto/src/main/java/javax/crypto/spec/DHPublicKeySpec.java
@@ -22,8 +22,6 @@
 
 /**
  * The key specification for a Diffie-Hellman public key.
- * 
- * @since Android 1.0
  */
 public class DHPublicKeySpec implements KeySpec {
 
@@ -35,7 +33,7 @@
      * Creates a new <code>DHPublicKeySpec</code> instance with the specified
      * <i>public value</i> <code>y</code>, the <i>prime modulus</i>
      * <code>p</code> and the <i>base generator</i> <code>g</code>.
-     * 
+     *
      * @param y
      *            the public value.
      * @param p
@@ -51,7 +49,7 @@
 
     /**
      * Returns the <i>public value</i> <code>y</code>.
-     * 
+     *
      * @return the public value <code>y</code>.
      */
     public BigInteger getY() {
@@ -60,7 +58,7 @@
 
     /**
      * Returns the <i>prime modulus</i> <code>p</code>.
-     * 
+     *
      * @return the prime modulus <code>p</code>.
      */
     public BigInteger getP() {
@@ -69,7 +67,7 @@
 
     /**
      * Returns the <i>base generator</i> <code>g</code>;
-     * 
+     *
      * @return the base generator <code>g</code>;
      */
     public BigInteger getG() {
diff --git a/libcore/crypto/src/main/java/javax/crypto/spec/IvParameterSpec.java b/libcore/crypto/src/main/java/javax/crypto/spec/IvParameterSpec.java
index 2f532a8..ce7f9d3 100644
--- a/libcore/crypto/src/main/java/javax/crypto/spec/IvParameterSpec.java
+++ b/libcore/crypto/src/main/java/javax/crypto/spec/IvParameterSpec.java
@@ -35,7 +35,7 @@
     /**
      * Creates a new <code>IvParameterSpec</code> instance with the bytes from
      * the specified buffer <i>iv</i> used as <i>initialization vector</i>.
-     * 
+     *
      * @param iv
      *            the buffer used as initialization vector.
      * @throws NullPointerException
@@ -53,7 +53,7 @@
      * Creates a new <code>IvParameterSpec</code> instance with <code>len</code>
      * bytes from the specified buffer <code>iv</code> starting at
      * <code>offset</code>.
-     * 
+     *
      * @param iv
      *            the buffer used as initialization vector.
      * @param offset
@@ -81,7 +81,7 @@
 
     /**
      * Returns a copy of the <i>initialization vector</i> data.
-     * 
+     *
      * @return a copy of the initialization vector data.
      */
     public byte[] getIV() {
diff --git a/libcore/crypto/src/main/java/javax/crypto/spec/OAEPParameterSpec.java b/libcore/crypto/src/main/java/javax/crypto/spec/OAEPParameterSpec.java
index ebb6cce..29b572d 100644
--- a/libcore/crypto/src/main/java/javax/crypto/spec/OAEPParameterSpec.java
+++ b/libcore/crypto/src/main/java/javax/crypto/spec/OAEPParameterSpec.java
@@ -26,8 +26,6 @@
  * <p>
  * This padding algorithm is defined in the <a
  * href="http://www.ietf.org/rfc/rfc3447.txt">PKCS #1</a> standard.
- * 
- * @since Android 1.0
  */
 public class OAEPParameterSpec implements AlgorithmParameterSpec {
 
@@ -60,7 +58,7 @@
      * <i>message digest</i> algorithm name, <i>mask generation function</i>
      * (<i>mgf</i>) algorithm name, <i>parameters</i> for the <i>mgf</i>
      * algorithm and the <i>source of the label <code>L</code></i>.
-     * 
+     *
      * @param mdName
      *            the message digest algorithm name.
      * @param mgfName
@@ -87,7 +85,7 @@
 
     /**
      * Returns the algorithm name of the <i>message digest</i>.
-     * 
+     *
      * @return the algorithm name of the message digest.
      */
     public String getDigestAlgorithm() {
@@ -96,7 +94,7 @@
 
     /**
      * Returns the algorithm name of the <i>mask generation function</i>.
-     * 
+     *
      * @return the algorithm name of the mask generation function.
      */
     public String getMGFAlgorithm() {
@@ -106,7 +104,7 @@
     /**
      * Returns the algorithm parameter specification for the mask generation
      * function algorithm.
-     * 
+     *
      * @return the algorithm parameter specification for the mask generation
      *         function algorithm.
      */
@@ -116,7 +114,7 @@
 
     /**
      * Returns the source of the label <code>L</code>.
-     * 
+     *
      * @return the source of the label <code>L</code>.
      */
     public PSource getPSource() {
diff --git a/libcore/crypto/src/main/java/javax/crypto/spec/PBEKeySpec.java b/libcore/crypto/src/main/java/javax/crypto/spec/PBEKeySpec.java
index c46617e..d79fd3c 100644
--- a/libcore/crypto/src/main/java/javax/crypto/spec/PBEKeySpec.java
+++ b/libcore/crypto/src/main/java/javax/crypto/spec/PBEKeySpec.java
@@ -27,8 +27,6 @@
  * <p>
  * Password based encryption is described in <a
  * href="http://www.ietf.org/rfc/rfc2898.txt">PKCS #5</a>.
- * 
- * @since Android 1.0
  */
 public class PBEKeySpec implements KeySpec {
 
@@ -39,7 +37,7 @@
 
     /**
      * Creates a new <code>PBEKeySpec</code> with the specified password.
-     * 
+     *
      * @param password
      *            the password.
      */
@@ -58,7 +56,7 @@
     /**
      * Creates a new <code>PBEKeySpec</code> with the specified password, salt,
      * iteration count and the desired length of the derived key.
-     * 
+     *
      * @param password
      *            the password.
      * @param salt
@@ -104,7 +102,7 @@
     /**
      * Creates a new <code>PBEKeySpec</code> with the specified password, salt
      * and iteration count.
-     * 
+     *
      * @param password
      *            the password.
      * @param salt
@@ -150,7 +148,7 @@
 
     /**
      * Returns a copy of the password of this key specification.
-     * 
+     *
      * @return a copy of the password of this key specification.
      * @throws IllegalStateException
      *             if the password has been cleared before.
@@ -166,7 +164,7 @@
 
     /**
      * Returns a copy of the salt of this key specification.
-     * 
+     *
      * @return a copy of the salt of this key specification or null if none is
      *         specified.
      */
@@ -181,7 +179,7 @@
 
     /**
      * Returns the iteration count of this key specification.
-     * 
+     *
      * @return the iteration count of this key specification.
      */
     public final int getIterationCount() {
@@ -190,7 +188,7 @@
 
     /**
      * Returns the desired key length of the derived key.
-     * 
+     *
      * @return the desired key length of the derived key.
      */
     public final int getKeyLength() {
diff --git a/libcore/crypto/src/main/java/javax/crypto/spec/PBEParameterSpec.java b/libcore/crypto/src/main/java/javax/crypto/spec/PBEParameterSpec.java
index 190986e..cce3832 100644
--- a/libcore/crypto/src/main/java/javax/crypto/spec/PBEParameterSpec.java
+++ b/libcore/crypto/src/main/java/javax/crypto/spec/PBEParameterSpec.java
@@ -23,12 +23,10 @@
 
 /**
  * The algorithm parameter specification for a <i>password based encryption</i>
- * algorithm. 
+ * algorithm.
  * <p>
  * Password based encryption is described in <a
  * href="http://www.ietf.org/rfc/rfc2898.txt">PKCS #5</a>.
- * 
- * @since Android 1.0
  *
  */
 public class PBEParameterSpec implements AlgorithmParameterSpec {
@@ -39,7 +37,7 @@
     /**
      * Creates a new <code>PBEParameterSpec</code> with the specified salt and
      * iteration count.
-     * 
+     *
      * @param salt
      *            the salt.
      * @param iterationCount
@@ -58,7 +56,7 @@
 
     /**
      * Returns a copy to the salt.
-     * 
+     *
      * @return a copy to the salt.
      */
     public byte[] getSalt() {
@@ -69,7 +67,7 @@
 
     /**
      * Returns the iteration count.
-     * 
+     *
      * @return the iteration count.
      */
     public int getIterationCount() {
diff --git a/libcore/crypto/src/main/java/javax/crypto/spec/PSource.java b/libcore/crypto/src/main/java/javax/crypto/spec/PSource.java
index d5bdf1b..30fd8af 100644
--- a/libcore/crypto/src/main/java/javax/crypto/spec/PSource.java
+++ b/libcore/crypto/src/main/java/javax/crypto/spec/PSource.java
@@ -22,8 +22,6 @@
 /**
  * The source of the label <code>L</code> as specified in <a
  * href="http://www.ietf.org/rfc/rfc3447.txt"> PKCS #1</a>.
- * 
- * @since Android 1.0
  */
 public class PSource {
 
@@ -34,7 +32,7 @@
     /**
      * Creates a new <code>PSource</code> instance with the specified source
      * algorithm identifier.
-     * 
+     *
      * @param pSrcName
      *            the source algorithm identifier.
      * @throws NullPointerException
@@ -49,7 +47,7 @@
 
     /**
      * Returns the source algorithm identifier.
-     * 
+     *
      * @return the source algorithm identifier.
      */
     public String getAlgorithm() {
@@ -59,15 +57,14 @@
     /**
      * The explicit specification of the parameter <code>P</code> used in the
      * source algorithm.
-     * 
-     * @since Android 1.0
      */
     public static final class PSpecified extends PSource {
 
         private final byte[] p;
 
         /**
-         * The instance of <code>PSpecified</code> with the default value <code>byte[0]</code> for <code>P</code>
+         * The instance of <code>PSpecified</code> with the default value
+         * <code>byte[0]</code> for <code>P</code>
          */
         public static final PSpecified DEFAULT = new PSpecified();
 
@@ -79,7 +76,7 @@
         /**
          * Creates a new instance of <code>PSpecified</code> with the specified
          * parameter <code>P</code>.
-         * 
+         *
          * @param p
          *            the parameter <code>P</code>.
          * @throws NullPointerException
@@ -98,7 +95,7 @@
 
         /**
          * Returns a copy of the value of the parameter <code>P</code>.
-         * 
+         *
          * @return a copy of the value of the parameter <code>P</code>
          */
         public byte[] getValue() {
diff --git a/libcore/crypto/src/main/java/javax/crypto/spec/RC2ParameterSpec.java b/libcore/crypto/src/main/java/javax/crypto/spec/RC2ParameterSpec.java
index bd76cf4..bc7a39c 100644
--- a/libcore/crypto/src/main/java/javax/crypto/spec/RC2ParameterSpec.java
+++ b/libcore/crypto/src/main/java/javax/crypto/spec/RC2ParameterSpec.java
@@ -25,8 +25,6 @@
 /**
  * The algorithm parameter specification for the <a
  * href="http://www.ietf.org/rfc/rfc2268.txt">RC2</a> algorithm.
- * 
- * @since Android 1.0
  */
 public class RC2ParameterSpec implements AlgorithmParameterSpec {
 
@@ -36,7 +34,7 @@
     /**
      * Creates a new <code>RC2ParameterSpec</code> instance with the specified
      * effective key length (in bits),
-     * 
+     *
      * @param effectiveKeyBits
      *            the effective key length (in bits).
      */
@@ -51,7 +49,7 @@
      * <p>
      * The size of the <i>initialization vector</i> must be at least 8 bytes
      * which are copied to protect them against modification.
-     * 
+     *
      * @param effectiveKeyBits
      *            the effective key length (in bits).
      * @param iv
@@ -78,7 +76,7 @@
      * The size of the <i>initialization vector</i> starting at
      * <code>offset</code> must be at least 8 bytes which are copied to protect
      * them against modification.
-     * 
+     *
      * @param effectiveKeyBits
      *            the effective key length (in bits).
      * @param iv
@@ -103,7 +101,7 @@
 
     /**
      * Returns the effective key length (in bits).
-     * 
+     *
      * @return the effective key length (in bits).
      */
     public int getEffectiveKeyBits() {
@@ -112,7 +110,7 @@
 
     /**
      * Returns a copy of the initialization vector.
-     * 
+     *
      * @return a copy of the initialization vector, or null if none specified.
      */
     public byte[] getIV() {
@@ -127,7 +125,7 @@
     /**
      * Compares the specified object to this <code>RC2ParameterSpec</code>
      * instance.
-     * 
+     *
      * @param obj
      *            the object to compare.
      * @return true if the effective key length and the initialization vector of
@@ -148,7 +146,7 @@
 
     /**
      * Returns the hash code of this <code>RC2ParameterSpec</code> instance.
-     * 
+     *
      * @return the hash code.
      */
     @Override
diff --git a/libcore/crypto/src/main/java/javax/crypto/spec/RC5ParameterSpec.java b/libcore/crypto/src/main/java/javax/crypto/spec/RC5ParameterSpec.java
index f711f41..57010f7 100644
--- a/libcore/crypto/src/main/java/javax/crypto/spec/RC5ParameterSpec.java
+++ b/libcore/crypto/src/main/java/javax/crypto/spec/RC5ParameterSpec.java
@@ -25,8 +25,6 @@
 /**
  * The algorithm parameter specification for the <a
  * href="http://www.ietf.org/rfc/rfc2040.txt">RC5</a> algorithm.
- * 
- * @since Android 1.0
  */
 public class RC5ParameterSpec implements AlgorithmParameterSpec {
 
@@ -38,7 +36,7 @@
     /**
      * Creates a new <code>RC5ParameterSpec</code> instance with the specified
      * version, round count an word size (in bits).
-     * 
+     *
      * @param version
      *            the version.
      * @param rounds
@@ -61,7 +59,7 @@
      * The size of the <i>initialization vector</i> must be at least
      * <code>2 * (wordSize / 8)</code> bytes which are copied to protect them
      * against modification.
-     * 
+     *
      * @param version
      *            the version.
      * @param rounds
@@ -97,7 +95,7 @@
      * The size of the <i>initialization vector</i> must be at least
      * <code>offset + (2 * (wordSize / 8))</code> bytes. The bytes starting at
      * <code>offset</code> are copied to protect them against modification.
-     * 
+     *
      * @param version
      *            the version.
      * @param rounds
@@ -135,7 +133,7 @@
 
     /**
      * Returns the version.
-     * 
+     *
      * @return the version.
      */
     public int getVersion() {
@@ -144,7 +142,7 @@
 
     /**
      * Returns the round count.
-     * 
+     *
      * @return the round count.
      */
     public int getRounds() {
@@ -153,7 +151,7 @@
 
     /**
      * Returns the word size (in bits).
-     * 
+     *
      * @return the word size (in bits).
      */
     public int getWordSize() {
@@ -162,7 +160,7 @@
 
     /**
      * Returns a copy of the initialization vector.
-     * 
+     *
      * @return a copy of the initialization vector, or null if none specified.
      */
     public byte[] getIV() {
@@ -177,7 +175,7 @@
     /**
      * Compares the specified object with this <code>RC5ParameterSpec</code>
      * instance.
-     * 
+     *
      * @param obj
      *            the object to compare.
      * @return true if version, round count, word size and initializaion vector
@@ -200,7 +198,7 @@
 
     /**
      * Returns the hash code of this <code>RC5ParameterSpec</code> instance.
-     * 
+     *
      * @return the hash code.
      */
     @Override
diff --git a/libcore/crypto/src/main/java/javax/crypto/spec/SecretKeySpec.java b/libcore/crypto/src/main/java/javax/crypto/spec/SecretKeySpec.java
index 897948c..d1eba47 100644
--- a/libcore/crypto/src/main/java/javax/crypto/spec/SecretKeySpec.java
+++ b/libcore/crypto/src/main/java/javax/crypto/spec/SecretKeySpec.java
@@ -33,8 +33,6 @@
  * A key specification for a <code>SecretKey</code> and also a secret key
  * implementation that is provider-independent. It can be used for raw secret
  * keys that can be specified as <code>byte[]</code>.
- * 
- * @since Android 1.0
  */
 public class SecretKeySpec implements SecretKey, KeySpec, Serializable {
 
@@ -50,7 +48,7 @@
     /**
      * Creates a new <code>SecretKeySpec</code> for the specified key data and
      * algorithm name.
-     * 
+     *
      * @param key
      *            the key data.
      * @param algorithm
@@ -79,7 +77,7 @@
      * Creates a new <code>SecretKeySpec</code> for the key data from the
      * specified buffer <code>key</code> starting at <code>offset</code> with
      * length <code>len</code> and the specified <code>algorithm</code> name.
-     * 
+     *
      * @param key
      *            the key data.
      * @param offset
@@ -120,7 +118,7 @@
 
     /**
      * Returns the algorithm name.
-     * 
+     *
      * @return the algorithm name.
      */
     public String getAlgorithm() {
@@ -129,7 +127,7 @@
 
     /**
      * Returns the name of the format used to encode the key.
-     * 
+     *
      * @return the format name "RAW".
      */
     public String getFormat() {
@@ -138,7 +136,7 @@
 
     /**
      * Returns the encoded form of this secret key.
-     * 
+     *
      * @return the encoded form of this secret key.
      */
     public byte[] getEncoded() {
@@ -149,7 +147,7 @@
 
     /**
      * Returns the hash code of this <code>SecretKeySpec</code> object.
-     * 
+     *
      * @return the hash code.
      */
     @Override
@@ -164,7 +162,7 @@
     /**
      * Compares the specified object with this <code>SecretKeySpec</code>
      * instance.
-     * 
+     *
      * @param obj
      *            the object to compare.
      * @return true if the algorithm name and key of both object are equal,
diff --git a/libcore/crypto/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/ExemptionMechanismTest.java b/libcore/crypto/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/ExemptionMechanismTest.java
index eb2920e..d93c156 100644
--- a/libcore/crypto/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/ExemptionMechanismTest.java
+++ b/libcore/crypto/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/ExemptionMechanismTest.java
@@ -21,6 +21,7 @@
 import dalvik.annotation.TestTargets;
 import dalvik.annotation.TestLevel;
 import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.SideEffect;
 
 import java.math.BigInteger;
 import java.security.AlgorithmParameters;
@@ -221,6 +222,7 @@
         method = "finalize",
         args = {}
     )
+    @SideEffect("Causes OutOfMemoryError to test finalization")
     public void test_finalize () {
         Mock_ExemptionMechanism mem = new Mock_ExemptionMechanism(null, null, "Name");
         assertNotNull(mem);
diff --git a/libcore/dalvik/src/main/java/dalvik/system/AllocationLimitError.java b/libcore/dalvik/src/main/java/dalvik/system/AllocationLimitError.java
index 85f7de6..9118199 100644
--- a/libcore/dalvik/src/main/java/dalvik/system/AllocationLimitError.java
+++ b/libcore/dalvik/src/main/java/dalvik/system/AllocationLimitError.java
@@ -18,8 +18,9 @@
 
 /**
  * Is thrown when an allocation limit is exceeded.
- * 
- * @since Android 1.0
+ *
+ * @deprecated this is an internal Dalvik class that is not appropriate for
+ *      general use. It will be removed from the public API in a future release.
  */
 public class AllocationLimitError extends VirtualMachineError {
     /**
diff --git a/libcore/dalvik/src/main/java/dalvik/system/DexFile.java b/libcore/dalvik/src/main/java/dalvik/system/DexFile.java
index da51e45..00de314 100644
--- a/libcore/dalvik/src/main/java/dalvik/system/DexFile.java
+++ b/libcore/dalvik/src/main/java/dalvik/system/DexFile.java
@@ -38,11 +38,13 @@
 
     /**
      * Opens a DEX file from a given File object. This will usually be a ZIP/JAR
-     * file with a "classes.dex" inside. The method should not be used for files
-     * inside the Dalvik cache.
-     * 
-     * @cts What will happen if we refer to the Dalvik cache? Should be either
-     *      specified or throw an exception...
+     * file with a "classes.dex" inside.
+     *
+     * The VM will generate the name of the coresponding file in
+     * /data/dalvik-cache and open it, possibly creating or updating
+     * it first if system permissions allow.  Don't pass in the name of
+     * a file in /data/dalvik-cache, as the named file is expected to be
+     * in its original (pre-dexopt) state.
      * 
      * @param file
      *            the File object referencing the actual DEX file
@@ -57,11 +59,13 @@
 
     /**
      * Opens a DEX file from a given filename. This will usually be a ZIP/JAR
-     * file with a "classes.dex" inside. The method should not be used for files
-     * inside the Dalvik cache.
-     * 
-     * @cts What will happen if we refer to the Dalvik cache? Should be either
-     *      specified or throw an exception...
+     * file with a "classes.dex" inside.
+     *
+     * The VM will generate the name of the coresponding file in
+     * /data/dalvik-cache and open it, possibly creating or updating
+     * it first if system permissions allow.  Don't pass in the name of
+     * a file in /data/dalvik-cache, as the named file is expected to be
+     * in its original (pre-dexopt) state.
      * 
      * @param fileName
      *            the filename of the DEX file
@@ -190,11 +194,23 @@
      * @cts Exception comment is a bit cryptic. What exception will be thrown?
      */
     public Class loadClass(String name, ClassLoader loader) {
+        String slashName = name.replace('.', '/');
+        return loadClassBinaryName(slashName, loader);
+    }
+
+    /**
+     * See {@link #loadClass(String, ClassLoader)}.
+     *
+     * This takes a "binary" class name to better match ClassLoader semantics.
+     *
+     * {@hide}
+     */
+    public Class loadClassBinaryName(String name, ClassLoader loader) {
         return defineClass(name, loader, mCookie,
             null);
             //new ProtectionDomain(name) /*DEBUG ONLY*/);
     }
-    
+
     native private static Class defineClass(String name, ClassLoader loader,
         int cookie, ProtectionDomain pd);
 
diff --git a/libcore/dalvik/src/main/java/dalvik/system/PathClassLoader.java b/libcore/dalvik/src/main/java/dalvik/system/PathClassLoader.java
index c80aef8..597eb5b 100644
--- a/libcore/dalvik/src/main/java/dalvik/system/PathClassLoader.java
+++ b/libcore/dalvik/src/main/java/dalvik/system/PathClassLoader.java
@@ -56,8 +56,8 @@
     /**
      * Creates a {@code PathClassLoader} that operates on a given list of files
      * and directories. This method is equivalent to calling
-     * {@link #PathClassLoader(String, String, ClassLoader) with a {@code null}
-     * value for the second argument (see description there).
+     * {@link #PathClassLoader(String, String, ClassLoader)} with a
+     * {@code null} value for the second argument (see description there).
      * 
      * @param path
      *            the list of files and directories
@@ -179,8 +179,9 @@
      * parent ClassLoader has failed to find a loaded class of the same name.
      * 
      * @param name
-     *            The name of the class to search for, in a human-readable form
-     *            like "java.lang.String" or "java.net.URLClassLoader$3$1".
+     *            The "binary name" of the class to search for, in a
+     *            human-readable form like "java.lang.String" or
+     *            "java.net.URLClassLoader$3$1".
      * @return the {@link Class} object representing the class
      * @throws ClassNotFoundException
      *             if the class cannot be found
@@ -199,8 +200,7 @@
             //System.out.println("My path is: " + mPaths[i]);
 
             if (mDexs[i] != null) {
-                String slashName = name.replace('.', '/');
-                Class clazz = mDexs[i].loadClass(slashName, this);
+                Class clazz = mDexs[i].loadClassBinaryName(name, this);
                 if (clazz != null)
                     return clazz;
             } else if (mZips[i] != null) {
diff --git a/libcore/dalvik/src/main/java/dalvik/system/PotentialDeadlockError.java b/libcore/dalvik/src/main/java/dalvik/system/PotentialDeadlockError.java
index c85caee..938a5cd 100644
--- a/libcore/dalvik/src/main/java/dalvik/system/PotentialDeadlockError.java
+++ b/libcore/dalvik/src/main/java/dalvik/system/PotentialDeadlockError.java
@@ -18,8 +18,9 @@
 
 /**
  * Is thrown when the VM identifies a potential deadlock.
- * 
- * @since Android 1.0
+ *
+ * @deprecated this is an internal Dalvik class that is not appropriate for
+ *      general use. It will be removed from the public API in a future release.
  */
 public class PotentialDeadlockError extends VirtualMachineError {
     /**
diff --git a/libcore/dalvik/src/main/java/dalvik/system/SamplingProfiler.java b/libcore/dalvik/src/main/java/dalvik/system/SamplingProfiler.java
new file mode 100644
index 0000000..1d88dd1
--- /dev/null
+++ b/libcore/dalvik/src/main/java/dalvik/system/SamplingProfiler.java
@@ -0,0 +1,346 @@
+/*
+ * 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 dalvik.system;
+
+import java.util.logging.Logger;
+import java.io.DataInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+/**
+ * A sampling profiler.
+ *
+ * @hide
+ */
+public class SamplingProfiler {
+
+    private static final Logger logger = Logger.getLogger(
+            SamplingProfiler.class.getName());
+
+    static final boolean DEBUG = false;
+
+    enum State {
+        /** The sampling thread hasn't started or is waiting to resume. */
+        PAUSED,
+        /** The sampling thread is collecting samples. */
+        RUNNING,
+        /** The sampling thread is shutting down. */
+        SHUTTING_DOWN
+    }
+
+    /** Pointer to native state. */
+    int pointer = 0;
+
+    /** The thread that collects samples. */
+    Thread samplingThread;
+
+    /** Time between samples. */
+    volatile int delay; // ms
+
+    /** Number of samples taken (~samples per second * number of threads). */
+    int totalThreadsSampled = 0;
+
+    /** Total time spent collecting samples. */
+    long totalSampleTime = 0;
+
+    /** The state of the profiler. */
+    volatile State state = State.PAUSED;
+
+    private SamplingProfiler() {}
+
+    /**
+     * Returns true if the profiler is running.
+     */
+    public boolean isRunning() {
+        return state == State.RUNNING;
+    }
+
+    /**
+     * Starts collecting samples.
+     *
+     * @param samplesPerSecond number of times to sample each thread per second
+     * @throws IllegalStateException if the profiler is
+     *  {@linkplain #shutDown()} shutting down}
+     */
+    public synchronized void start(int samplesPerSecond) {
+        if (samplesPerSecond < 1) {
+            throw new IllegalArgumentException("samplesPerSecond < 1");
+        }
+        ensureNotShuttingDown();
+        delay = 1000 / samplesPerSecond;
+        if (!isRunning()) {
+            if (DEBUG) logger.info("Starting profiler...");
+            state = State.RUNNING;
+            if (samplingThread == null) {
+                // TODO: Priority?
+                samplingThread = new Thread(new Sampler(), "SamplingProfiler");
+                samplingThread.setDaemon(true);
+                samplingThread.start();
+            } else {
+                notifyAll();
+            }
+        }
+    }
+
+    /**
+     * Pauses sample collection.
+     */
+    public synchronized void pause() {
+        if (isRunning()) {
+            if (DEBUG) logger.info("Pausing profiler...");
+            state = State.PAUSED;
+        }
+    }
+
+    /**
+     * Captures collected samples and clears the sample set. Returns null
+     * if no data has been captured.
+     *
+     * <p>Note: The exact format is not documented because it's not set in
+     * stone yet.
+     *
+     * @throws IllegalStateException if the profiler is
+     *  {@linkplain #shutDown()} shutting down}
+     */
+    public synchronized byte[] snapshot() {
+        ensureNotShuttingDown();
+        if (pointer == 0 || totalThreadsSampled == 0) {
+            return null;
+        }
+
+        if (DEBUG) {
+            int size = size(pointer);
+            int collisions = collisions(pointer);
+
+            long start = System.nanoTime();
+            byte[] bytes = snapshot(pointer);
+            long elapsed = System.nanoTime() - start;
+
+            /*
+             * We shifted the times by 10 bits in the sampling thread to avoid
+             * overflow. Undo the shift and then convert from ns to us.
+             */
+            long averageSampleTime = ((totalSampleTime / totalThreadsSampled)
+                    << 10) / 1000;
+            logger.info("Grabbed snapshot in " + (elapsed / 1000) + "us."
+                    + " Samples collected: " + totalThreadsSampled
+                    + ", Average sample time (per thread): "
+                            + averageSampleTime + "us"
+                    + ", Set size: " + size
+                    + ", Collisions: " + collisions);
+            totalThreadsSampled = 0;
+            totalSampleTime = 0;
+
+            return bytes;
+        } else {
+            totalThreadsSampled = 0;
+            return snapshot(pointer);
+        }
+    }
+
+    /**
+     * Identifies the "event thread". For a user-facing application, this
+     * might be the UI thread. For a background process, this might be the
+     * thread that processes incoming requests.
+     *
+     * @throws IllegalStateException if the profiler is
+     *  {@linkplain #shutDown()} shutting down}
+     */
+    public synchronized void setEventThread(Thread eventThread) {
+        ensureNotShuttingDown();
+        if (pointer == 0) {
+            pointer = allocate();
+        }
+        setEventThread(pointer, eventThread);
+    }
+
+    private void ensureNotShuttingDown() {
+        if (state == State.SHUTTING_DOWN) {
+            throw new IllegalStateException("Profiler is shutting down.");
+        }
+    }
+
+    /**
+     * Shuts down the profiler thread and frees native memory. The profiler
+     * will recreate the thread the next time {@link #start(int)} is called.
+     *
+     * @throws IllegalStateException if the profiler is already shutting down
+     *  or if it hasn't started yet
+     *
+     */
+    public void shutDown() {
+        Thread toStop;
+        synchronized (this) {
+            ensureNotShuttingDown();
+
+            toStop = samplingThread;
+            if (toStop == null) {
+                throw new IllegalStateException(
+                        "The profiler was never started.");
+            }
+
+            state = State.SHUTTING_DOWN;
+            samplingThread = null;
+            notifyAll();
+        }
+
+        // Release lock to 'this' so background thread can grab it and stop.
+        // Interrupt the thread in case it's sleeping.
+        toStop.interrupt();
+        while (true) {
+            try {
+                toStop.join();
+                break;
+            } catch (InterruptedException e) { /* ignore */ }
+        }
+
+        synchronized (this) {
+            if (pointer != 0) {
+                free(pointer);
+                pointer = 0;
+            }
+
+            totalThreadsSampled = 0;
+            totalSampleTime = 0;
+            state = State.PAUSED;
+        }
+    }
+
+    /** Collects some data. Returns number of threads sampled. */
+    private static native int sample(int pointer);
+
+    /** Allocates native state. */
+    private static native int allocate();
+
+    /** Frees native state. */
+    private static native void free(int pointer);
+
+    /** Gets the number of methods in the sample set. */
+    private static native int size(int pointer);
+
+    /** Gets the number of collisions in the sample set. */
+    private static native int collisions(int pointer);
+
+    /** Captures data. */
+    private static native byte[] snapshot(int pointer);
+
+    /** Identifies the "event thread". */
+    private static native void setEventThread(int pointer, Thread thread);
+
+    /**
+     * Background thread that collects samples.
+     */
+    class Sampler implements Runnable {
+        public void run() {
+            boolean firstSample = true;
+            while (true) {
+                synchronized (SamplingProfiler.this) {
+                    if (!isRunning()) {
+                        if (DEBUG) logger.info("Paused profiler.");
+                        while (!isRunning()) {
+                            if (state == State.SHUTTING_DOWN) {
+                                // Stop thread.
+                                return;
+                            }
+
+                            try {
+                                SamplingProfiler.this.wait();
+                            } catch (InterruptedException e) { /* ignore */ }
+                        }
+                        firstSample = true;
+                    }
+
+                    if (pointer == 0) {
+                        pointer = allocate();
+                    }
+
+                    if (firstSample) {
+                        if (DEBUG) logger.info("Started profiler.");
+                        firstSample = false;
+                    }
+
+                    if (DEBUG) {
+                        long start = System.nanoTime();
+                        int threadsSampled = sample(pointer);
+                        long elapsed = System.nanoTime() - start;
+
+                        totalThreadsSampled += threadsSampled;
+                        totalSampleTime += elapsed >> 10; // avoids overflow.
+                    } else {
+                        totalThreadsSampled += sample(pointer);
+                    }
+                }
+
+                try {
+                    Thread.sleep(delay);
+                } catch (InterruptedException e) { /* ignore */ }
+            }
+        }
+    }
+
+    /**
+     * Dumps a snapshot to the log. Useful for debugging.
+     */
+    public static void logSnapshot(byte[] snapshot) {
+        DataInputStream in = new DataInputStream(
+                new ByteArrayInputStream(snapshot));
+        try {
+            int version = in.readUnsignedShort();
+            int classCount = in.readUnsignedShort();
+            StringBuilder sb = new StringBuilder();
+            sb.append("version=").append(version).append(' ')
+                    .append("classes=").append(classCount).append('\n');
+            logger.info(sb.toString());
+            for (int i = 0; i < classCount; i++) {
+                sb = new StringBuilder();
+                sb.append("class ").append(in.readUTF()).append('\n');
+                int methodCount = in.readUnsignedShort();
+                for (int m = 0; m < methodCount; m++) {
+                    sb.append("  ").append(in.readUTF()).append(":\n");
+                    sb.append("    event:\n");
+                    appendCounts(in, sb);
+                    sb.append("    other:\n");
+                    appendCounts(in, sb);
+                }
+                logger.info(sb.toString());
+            }
+        } catch (IOException e) {
+            logger.warning(e.toString());
+        }
+    }
+
+    private static void appendCounts(DataInputStream in, StringBuilder sb)
+            throws IOException {
+        sb.append("      running:\n");
+        sb.append("        caller: ").append(in.readShort()).append('\n');
+        sb.append("        leaf: ").append(in.readShort()).append('\n');
+        sb.append("      suspended:\n");
+        sb.append("        caller: ").append(in.readShort()).append('\n');
+        sb.append("        leaf: ").append(in.readShort()).append('\n');
+    }
+
+    /** This will be allocated when the user calls getInstance(). */
+    private static final SamplingProfiler instance = new SamplingProfiler();
+
+    /**
+     * Gets the profiler. The profiler is not running by default. Start it
+     * with {@link #start(int)}.
+     */
+    public static synchronized SamplingProfiler getInstance() {
+        return instance;
+    }
+}
diff --git a/libcore/dalvik/src/main/java/dalvik/system/StaleDexCacheError.java b/libcore/dalvik/src/main/java/dalvik/system/StaleDexCacheError.java
index 44a40a5..ffde7cb 100644
--- a/libcore/dalvik/src/main/java/dalvik/system/StaleDexCacheError.java
+++ b/libcore/dalvik/src/main/java/dalvik/system/StaleDexCacheError.java
@@ -19,6 +19,9 @@
 /**
  * Is thrown when the VM determines that a DEX file's cache is out of date, and
  * that there is no way to recreate it.
+ *
+ * @deprecated this is an internal Dalvik class that is not appropriate for
+ *      general use. It will be removed from the public API in a future release.
  */
 public class StaleDexCacheError extends VirtualMachineError {
     /**
diff --git a/libcore/dalvik/src/main/java/dalvik/system/TemporaryDirectory.java b/libcore/dalvik/src/main/java/dalvik/system/TemporaryDirectory.java
index 2f909ac..0e26a70 100644
--- a/libcore/dalvik/src/main/java/dalvik/system/TemporaryDirectory.java
+++ b/libcore/dalvik/src/main/java/dalvik/system/TemporaryDirectory.java
@@ -25,8 +25,9 @@
  * call into this class with an appropriate base directory during its
  * startup, as a reasonably easy way to get the standard property
  * <code>java.io.tmpdir</code> to point at something useful.
- * 
- * @since Android 1.0
+ *
+ * @deprecated this is an internal Dalvik class that is not appropriate for
+ *      general use. It will be removed from the public API in a future release.
  */
 public class TemporaryDirectory {
     /** system property name for the temporary directory */
diff --git a/libcore/dalvik/src/main/java/dalvik/system/TouchDex.java b/libcore/dalvik/src/main/java/dalvik/system/TouchDex.java
index 2dbc3ea..04c6546 100644
--- a/libcore/dalvik/src/main/java/dalvik/system/TouchDex.java
+++ b/libcore/dalvik/src/main/java/dalvik/system/TouchDex.java
@@ -25,13 +25,8 @@
 /**
  * Induces optimization/verification of a set of DEX files.
  *
- * TODO: This class is public, so SystemServer can access it.  This is NOT
- * the correct long-term solution; once we have a real installer and/or
- * dalvik-cache manager, this class should be removed.
- * 
- * @cts See to-do about removing this class...
- * 
- * @since Android 1.0
+ * @deprecated this is an internal Dalvik class that is not appropriate for
+ *      general use. It will be removed from the public API in a future release.
  */
 public class TouchDex {
 
diff --git a/libcore/dalvik/src/main/java/dalvik/system/VMDebug.java b/libcore/dalvik/src/main/java/dalvik/system/VMDebug.java
index efc25d6..365388a 100644
--- a/libcore/dalvik/src/main/java/dalvik/system/VMDebug.java
+++ b/libcore/dalvik/src/main/java/dalvik/system/VMDebug.java
@@ -27,8 +27,9 @@
  * <code>android.os.Debug</code>.
  * 
  * @cts Please complete the spec.
- * 
- * @since Android 1.0
+ *
+ * @deprecated this is an internal Dalvik class that is not appropriate for
+ *      general use. It will be removed from the public API in a future release.
  */
 public final class VMDebug {
     /**
@@ -275,8 +276,22 @@
      */
     public static native void dumpHprofData(String fileName) throws IOException;
 
-    /* don't ask */
-    static native void printThis(Object thisThing, int count, int thing);
+    /**
+     * Primes the register map cache.
+     *
+     * @hide
+     */
+    public static native boolean cacheRegisterMap(String classAndMethodDesc);
+
+    /**
+     * Crashes the VM.  Seriously.  Dumps the stack trace for the current
+     * thread and then aborts the VM so you can see the native stack trace.
+     * Useful for figuring out how you got somewhere when lots of native
+     * code is involved.
+     *
+     * @hide
+     */
+    public static native void crash();
 
     /*
      * Fake method, inserted into dmtrace output when the garbage collector
diff --git a/libcore/dalvik/src/main/java/dalvik/system/VMRuntime.java b/libcore/dalvik/src/main/java/dalvik/system/VMRuntime.java
index 5d5e600..7ac0849 100644
--- a/libcore/dalvik/src/main/java/dalvik/system/VMRuntime.java
+++ b/libcore/dalvik/src/main/java/dalvik/system/VMRuntime.java
@@ -20,7 +20,10 @@
  * Provides an interface to VM-global, Dalvik-specific features.
  * An application cannot create its own Runtime instance, and must obtain
  * one from the getRuntime method.
- * 
+ *
+ * @deprecated this is an internal Dalvik class that is not appropriate for
+ *      general use. It will be removed from the public API in a future release.
+ *
  * @since Android 1.0
  */
 public final class VMRuntime {
@@ -62,6 +65,8 @@
      * be resized so that (size of live objects) / (size of heap) is
      * equal to this number.
      *
+     * <p>This is only a hint to the garbage collector and may be ignored.
+     *
      * @param newTarget the new suggested ideal heap utilization.
      *                  This value may be adjusted internally.
      * @return the previous ideal heap utilization
@@ -98,7 +103,9 @@
      * size, the maximum size will be used.  If size is zero
      * or negative, the minimum size constraint will be removed.
      *
-     * Synchronized to make the order of the exchange reliable.
+     * <p>Synchronized to make the order of the exchange reliable.
+     *
+     * <p>This is only a hint to the garbage collector and may be ignored.
      *
      * @param size the new suggested minimum heap size, in bytes
      * @return the old minimum heap size value
@@ -175,7 +182,7 @@
     /**
      * Returns the number of externally-allocated bytes being tracked by
      * trackExternalAllocation/Free().
-     * 
+     *
      * @return the number of bytes
      */
     public native long getExternalBytesAllocated();
diff --git a/libcore/dalvik/src/main/java/dalvik/system/VMStack.java b/libcore/dalvik/src/main/java/dalvik/system/VMStack.java
index 9330c68..b049962 100644
--- a/libcore/dalvik/src/main/java/dalvik/system/VMStack.java
+++ b/libcore/dalvik/src/main/java/dalvik/system/VMStack.java
@@ -19,8 +19,9 @@
 /**
  * Provides a limited interface to the Dalvik VM stack. This class is mostly
  * used for implementing security checks.
- * 
- * @since Android 1.0
+ *
+ * @deprecated this is an internal Dalvik class that is not appropriate for
+ *      general use. It will be removed from the public API in a future release.
  */
 public final class VMStack {
     /**
@@ -40,6 +41,14 @@
     native public static ClassLoader getCallingClassLoader2();
 
     /**
+     * Returns the class of the caller's caller's caller.
+     *
+     * @hide
+     * @return the requested class, or {@code null}.
+     */
+    native public static Class<?> getStackClass2();
+
+    /**
      * Creates an array of classes from the methods at the top of the stack.
      * We continue until we reach the bottom of the stack or exceed the
      * specified maximum depth.  If stopAtPrivileged is set, the last
diff --git a/libcore/dalvik/src/main/java/dalvik/system/Zygote.java b/libcore/dalvik/src/main/java/dalvik/system/Zygote.java
index 9d98bb2..13e7561 100644
--- a/libcore/dalvik/src/main/java/dalvik/system/Zygote.java
+++ b/libcore/dalvik/src/main/java/dalvik/system/Zygote.java
@@ -20,8 +20,9 @@
  * Provides access to the Dalvik "zygote" feature, which allows a VM instance to
  * be partially initialized and then fork()'d from the partially initialized
  * state.
- * 
- * @since Android 1.0
+ *
+ * @deprecated this is an internal Dalvik class that is not appropriate for
+ *      general use. It will be removed from the public API in a future release.
  */
 public class Zygote {
     /*
diff --git a/libcore/icu/src/main/java/com/ibm/icu4jni/charset/CharsetDecoderICU.java b/libcore/icu/src/main/java/com/ibm/icu4jni/charset/CharsetDecoderICU.java
index 206f0c8..919d865 100644
--- a/libcore/icu/src/main/java/com/ibm/icu4jni/charset/CharsetDecoderICU.java
+++ b/libcore/icu/src/main/java/com/ibm/icu4jni/charset/CharsetDecoderICU.java
@@ -344,18 +344,11 @@
 
         // ok was there input held in the previous invocation of decodeLoop 
         // that resulted in output in this invocation?
-        if(data[OUTPUT_OFFSET]>0 && savedInputHeldLen >0){
-            int len = in.position() + data[INPUT_OFFSET] + savedInputHeldLen;
-            in.position(len);   
-            savedInputHeldLen = data[INPUT_HELD];
-        }else{
-            in.position(in.position() + data[INPUT_OFFSET] + savedInputHeldLen);
-            savedInputHeldLen = data[INPUT_HELD];
-            in.position(in.position() - savedInputHeldLen);
-        }       
-        // BEGIN android-added
+        // BEGIN android-changed
+        in.position(in.position() + data[INPUT_OFFSET] + savedInputHeldLen - data[INPUT_HELD]);
+        savedInputHeldLen = data[INPUT_HELD];
         // release reference to input array, which may not be ours
         input = null;
-        // END android-added
+        // END android-changed
     }
 }
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 85530ac..0460fde 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
@@ -179,20 +179,28 @@
     private static String getDefaultLocaleName() {
         return java.util.Locale.getDefault().toString();
     }
-    
-    /**
-     * Name of default locale at the time this class was initialized.
-     */
-    private static final String initialLocale = getDefaultLocaleName();
 
     /**
-     * Names of time zones for the default locale.
+     * Initialization holder for default time zone names. This class will
+     * be preloaded by the zygote to share the time and space costs of setting
+     * up the list of time zone names, so although it looks like the lazy
+     * initialization idiom, it's actually the opposite.
      */
-    private static String[][] defaultTimezoneNames = null;
+    private static class DefaultTimeZones {
+        /**
+         * Name of default locale at the time this class was initialized.
+         */
+        private static final String locale = getDefaultLocaleName();
+
+        /**
+         * Names of time zones for the default locale.
+         */
+        private static final String[][] names = createTimeZoneNamesFor(locale);
+    }
 
     /**
      * Creates array of time zone names for the given locale. This method takes
-     * about 2s to run on a 400mhz ARM11.
+     * about 2s to run on a 400MHz ARM11.
      */
     private static String[][] createTimeZoneNamesFor(String locale) {
         long start = System.currentTimeMillis();
@@ -252,22 +260,16 @@
      *         the TomeZone class.
      */
     public static String[][] getDisplayTimeZones(String locale) {
-        // Note: Defer loading DefaultTimeZones as long as possible.
-
-        String defaultLocaleName = getDefaultLocaleName();
+        String defaultLocale = getDefaultLocaleName();
         if (locale == null) {
-            locale = defaultLocaleName;
+            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 (defaultLocaleName.equals(locale)
-                && initialLocale.equals(defaultLocaleName)) {
-            if (defaultTimezoneNames == null) {
-                defaultTimezoneNames = createTimeZoneNamesFor(locale);
-            }
-            return defaultTimezoneNames;
+        if (defaultLocale.equals(locale) && DefaultTimeZones.locale.equals(defaultLocale)) {
+            return DefaultTimeZones.names;
         }
         
         return createTimeZoneNamesFor(locale);
diff --git a/libcore/icu/src/main/native/DecimalFormatInterface.cpp b/libcore/icu/src/main/native/DecimalFormatInterface.cpp
index 6221826..7e37d6c 100644
--- a/libcore/icu/src/main/native/DecimalFormatInterface.cpp
+++ b/libcore/icu/src/main/native/DecimalFormatInterface.cpp
@@ -15,6 +15,7 @@
  * the VM-specific behavior isolated in VMThread.
  */
 
+#define LOG_TAG "DecimalFormatInterface"
 #include "JNIHelp.h"
 #include "AndroidSystemNatives.h"
 #include "unicode/unum.h"
@@ -28,7 +29,6 @@
 #include <string.h>
 #include "cutils/log.h"
 
-#define LOG_TAG "DecimalFormatInterface"
 
 static UBool icuError(JNIEnv *env, UErrorCode errorcode)
 {
diff --git a/libcore/icu/src/main/native/ResourceInterface.cpp b/libcore/icu/src/main/native/ResourceInterface.cpp
index 5f9d442..a88e15c 100644
--- a/libcore/icu/src/main/native/ResourceInterface.cpp
+++ b/libcore/icu/src/main/native/ResourceInterface.cpp
@@ -943,7 +943,7 @@
 
 
 
-    jclass obj_class = env->FindClass("java/lang/Object");
+    jclass obj_class = env->FindClass("[Ljava/lang/Object;");
     jclass integer_class = env->FindClass("java/lang/Integer");
     jmethodID integerInit = env->GetMethodID(integer_class, "<init>", "(I)V");
     jobjectArray result;
@@ -1207,7 +1207,8 @@
         intCurrencySymbol = env->NewStringUTF("XXX");
     }
     if(currencySymbol == NULL) {
-        currencySymbol = env->NewStringUTF("\u00a4");
+        // creating a new string explicitly with the UTF-8 encoding of "\u00a4"
+        currencySymbol = env->NewStringUTF("\xc2\xa4");
     }
     counter += 2;
 
diff --git a/libcore/logging/src/main/java/java/util/logging/ConsoleHandler.java b/libcore/logging/src/main/java/java/util/logging/ConsoleHandler.java
index a88cf0c..ef365ca 100644
--- a/libcore/logging/src/main/java/java/util/logging/ConsoleHandler.java
+++ b/libcore/logging/src/main/java/java/util/logging/ConsoleHandler.java
@@ -38,19 +38,13 @@
  * handler will use to encode log messages, defaults to {@code null} if this
  * property is not found or has an invalid value.
  * </ul>
- * </p>
  * <p>
  * This class is not thread-safe.
- * </p>
- * 
- * @since Android 1.0
  */
 public class ConsoleHandler extends StreamHandler {
 
     /**
      * Constructs a {@code ConsoleHandler} object.
-     * 
-     * @since Android 1.0
      */
     public ConsoleHandler() {
         super(System.err);
@@ -58,8 +52,6 @@
 
     /**
      * Closes this handler. The {@code System.err} is flushed but not closed.
-     * 
-     * @since Android 1.0
      */
     @Override
     public void close() {
@@ -68,16 +60,13 @@
 
     /**
      * Logs a record if necessary. A flush operation will be done.
-     * 
+     *
      * @param record
      *            the log record to be logged.
-     * 
-     * @since Android 1.0
      */
     @Override
     public void publish(LogRecord record) {
         super.publish(record);
         super.flush();
-
     }
 }
diff --git a/libcore/logging/src/main/java/java/util/logging/ErrorManager.java b/libcore/logging/src/main/java/java/util/logging/ErrorManager.java
index 6f5084c..708ddfa 100644
--- a/libcore/logging/src/main/java/java/util/logging/ErrorManager.java
+++ b/libcore/logging/src/main/java/java/util/logging/ErrorManager.java
@@ -24,51 +24,37 @@
  * error that may happen during logging. {@code Handlers} should report errors
  * to an {@code ErrorManager}, instead of throwing exceptions, which would
  * interfere with the log issuer's execution.
- * 
- * @since Android 1.0
  */
 public class ErrorManager {
 
     /**
      * The error code indicating a failure that does not fit in any of the
      * specific types of failures that follow.
-     * 
-     * @since Android 1.0
      */
     public static final int GENERIC_FAILURE = 0;
 
     /**
      * The error code indicating a failure when writing to an output stream.
-     * 
-     * @since Android 1.0
      */
     public static final int WRITE_FAILURE = 1;
 
     /**
      * The error code indicating a failure when flushing an output stream.
-     * 
-     * @since Android 1.0
      */
     public static final int FLUSH_FAILURE = 2;
 
     /**
      * The error code indicating a failure when closing an output stream.
-     * 
-     * @since Android 1.0
      */
     public static final int CLOSE_FAILURE = 3;
 
     /**
      * The error code indicating a failure when opening an output stream.
-     * 
-     * @since Android 1.0
      */
     public static final int OPEN_FAILURE = 4;
 
     /**
      * The error code indicating a failure when formatting the error messages.
-     * 
-     * @since Android 1.0
      */
     public static final int FORMAT_FAILURE = 5;
 
@@ -85,20 +71,16 @@
 
     /**
      * Constructs an instance of {@code ErrorManager}.
-     * 
-     * @since Android 1.0
      */
     public ErrorManager() {
         super();
     }
 
     /**
-     * <p>
      * Reports an error using the given message, exception and error code. This
      * implementation will write out the message to {@link System#err} on the
      * first call and all subsequent calls are ignored. A subclass of this class
      * should override this method.
-     * </p>
      * 
      * @param message
      *            the error message, which may be {@code null}.
@@ -108,8 +90,6 @@
      * @param errorCode
      *            the error code that identifies the type of error; see the
      *            constant fields of this class for possible values.
-     *            
-     * @since Android 1.0            
      */
     public void error(String message, Exception exception, int errorCode) {
         synchronized (this) {
@@ -119,7 +99,7 @@
             called = true;
         }
         System.err.println(this.getClass().getName()
-            + ": " + FAILURES[errorCode]); //$NON-NLS-1$
+                + ": " + FAILURES[errorCode]); //$NON-NLS-1$
         if (message != null) {
             // logging.1E=Error message - {0}
             System.err.println(Messages.getString("logging.1E", message)); //$NON-NLS-1$
diff --git a/libcore/logging/src/main/java/java/util/logging/FileHandler.java b/libcore/logging/src/main/java/java/util/logging/FileHandler.java
index af71a6d..e1eba9e 100644
--- a/libcore/logging/src/main/java/java/util/logging/FileHandler.java
+++ b/libcore/logging/src/main/java/java/util/logging/FileHandler.java
@@ -38,48 +38,45 @@
  * When a set of files is used and a given amount of data has been written to
  * one file, then this file is closed and another file is opened. The name of
  * these files are generated by given name pattern, see below for details.
- * </p>
+ * When the files have all been filled the Handler returns to the first and goes
+ * through the set again.
  * <p>
  * By default, the I/O buffering mechanism is enabled, but when each log record
  * is complete, it is flushed out.
- * </p>
  * <p>
  * {@code XMLFormatter} is the default formatter for {@code FileHandler}.
- * </p>
  * <p>
  * {@code FileHandler} reads the following {@code LogManager} properties for
  * initialization; if a property is not defined or has an invalid value, a
  * default value is used.
  * <ul>
- * <li>java.util.logging.FileHandler.level specifies the level for this
- * {@code Handler}, defaults to {@code Level.ALL}.</li>
+ * <li>java.util.logging.FileHandler.append specifies whether this
+ * {@code FileHandler} should append onto existing files, defaults to
+ * {@code false}.</li>
+ * <li>java.util.logging.FileHandler.count specifies how many output files to
+ * rotate, defaults to 1.</li>
  * <li>java.util.logging.FileHandler.filter specifies the {@code Filter} class
  * name, defaults to no {@code Filter}.</li>
  * <li>java.util.logging.FileHandler.formatter specifies the {@code Formatter}
  * class, defaults to {@code java.util.logging.XMLFormatter}.</li>
  * <li>java.util.logging.FileHandler.encoding specifies the character set
  * encoding name, defaults to the default platform encoding.</li>
+ * <li>java.util.logging.FileHandler.level specifies the level for this
+ * {@code Handler}, defaults to {@code Level.ALL}.</li>
  * <li>java.util.logging.FileHandler.limit specifies the maximum number of
  * bytes to write to any one file, defaults to zero, which means no limit.</li>
- * <li>java.util.logging.FileHandler.count specifies how many output files to
- * rotate, defaults to 1.</li>
  * <li>java.util.logging.FileHandler.pattern specifies name pattern for the
  * output files. See below for details. Defaults to "%h/java%u.log".</li>
- * <li>java.util.logging.FileHandler.append specifies whether this
- * {@code FileHandler} should append onto existing files, defaults to
- * {@code false}.</li>
  * </ul>
- * </p>
  * <p>
  * Name pattern is a string that may include some special substrings, which will
  * be replaced to generate output files:
- * </p>
  * <ul>
  * <li>"/" represents the local pathname separator</li>
- * <li>"%t" represents the system's temporary directory</li>
+ * <li>"%g" represents the generation number to distinguish rotated logs</li>
  * <li>"%h" represents the home directory of the current user, which is
  * specified by "user.home" system property</li>
- * <li>"%g" represents the generation number to distinguish rotated logs</li>
+ * <li>"%t" represents the system's temporary directory</li>
  * <li>"%u" represents a unique number to resolve conflicts</li>
  * <li>"%%" represents the percent sign character '%'</li>
  * </ul>
@@ -88,7 +85,6 @@
  * follow the sequence 0, 1, 2.... If the file count is larger than one, but the
  * generation field("%g") has not been specified in the pattern, then the
  * generation number after a dot will be added to the end of the file name.
- * </p>
  * <p>
  * The "%u" unique field is used to avoid conflicts and is set to 0 at first. If
  * one {@code FileHandler} tries to open the filename which is currently in use
@@ -98,8 +94,6 @@
  * value will be added to the end of the filename in question immediately to the
  * right of a dot. The generation of unique IDs for avoiding conflicts is only
  * guaranteed to work reliably when using a local disk file system.
- * </p>
- * @since Android 1.0
  */
 public class FileHandler extends StreamHandler {
 
@@ -150,7 +144,7 @@
     /**
      * Construct a {@code FileHandler} using {@code LogManager} properties or
      * their default value.
-     * 
+     *
      * @throws IOException
      *             if any I/O error occurs.
      * @throws SecurityException
@@ -159,7 +153,6 @@
      *             handler; required permissions include
      *             {@code LogPermission("control")},
      *             {@code FilePermission("write")} etc.
-     * @since Android 1.0
      */
     public FileHandler() throws IOException {
         init(null, null, null, null);
@@ -232,21 +225,22 @@
         setOutputStream(output);
     }
 
+    @SuppressWarnings("nls")
     private void initProperties(String p, Boolean a, Integer l, Integer c) {
-        super.initProperties("ALL", null, "java.util.logging.XMLFormatter", //$NON-NLS-1$//$NON-NLS-2$
+        super.initProperties("ALL", null, "java.util.logging.XMLFormatter",
                 null);
         String className = this.getClass().getName();
-        pattern = (null == p) ? getStringProperty(className + ".pattern", //$NON-NLS-1$
+        pattern = (null == p) ? getStringProperty(className + ".pattern",
                 DEFAULT_PATTERN) : p;
-        if (null == pattern || "".equals(pattern)) { //$NON-NLS-1$
+        if (null == pattern || "".equals(pattern)) {
             // logging.19=Pattern cannot be empty
-            throw new NullPointerException(Messages.getString("logging.19")); //$NON-NLS-1$
+            throw new NullPointerException(Messages.getString("logging.19"));
         }
-        append = (null == a) ? getBooleanProperty(className + ".append", //$NON-NLS-1$
+        append = (null == a) ? getBooleanProperty(className + ".append",
                 DEFAULT_APPEND) : a.booleanValue();
-        count = (null == c) ? getIntProperty(className + ".count", //$NON-NLS-1$
+        count = (null == c) ? getIntProperty(className + ".count",
                 DEFAULT_COUNT) : c.intValue();
-        limit = (null == l) ? getIntProperty(className + ".limit", //$NON-NLS-1$
+        limit = (null == l) ? getIntProperty(className + ".limit",
                 DEFAULT_LIMIT) : l.intValue();
         count = count < 1 ? DEFAULT_COUNT : count;
         limit = limit < 0 ? DEFAULT_LIMIT : limit;
@@ -279,7 +273,7 @@
     /**
      * Transform the pattern to the valid file name, replacing any patterns, and
      * applying generation and uniqueID if present.
-     * 
+     *
      * @param gen
      *            generation of this file
      * @return transformed filename ready for use.
@@ -396,9 +390,9 @@
      * Constructs a new {@code FileHandler}. The given name pattern is used as
      * output filename, the file limit is set to zero (no limit), the file count
      * is set to one; the remaining configuration is done using
-     * {@code LogManager} properties or their default values. This handler write
-     * to only one file without size limit.
-     * 
+     * {@code LogManager} properties or their default values. This handler
+     * writes to only one file with no size limit.
+     *
      * @param pattern
      *            the name pattern for the output file.
      * @throws IOException
@@ -413,7 +407,6 @@
      *             if the pattern is empty.
      * @throws NullPointerException
      *             if the pattern is {@code null}.
-     * @since Android 1.0
      */
     public FileHandler(String pattern) throws IOException {
         if (pattern.equals("")) { //$NON-NLS-1$
@@ -429,9 +422,9 @@
      * output filename, the file limit is set to zero (no limit), the file count
      * is initialized to one and the value of {@code append} becomes the new
      * instance's append mode. The remaining configuration is done using
-     * {@code LogManager} properties. This handler write to only one file
-     * without size limit.
-     * 
+     * {@code LogManager} properties. This handler writes to only one file
+     * with no size limit.
+     *
      * @param pattern
      *            the name pattern for the output file.
      * @param append
@@ -448,11 +441,10 @@
      *             if {@code pattern} is empty.
      * @throws NullPointerException
      *             if {@code pattern} is {@code null}.
-     * @since Android 1.0
      */
     public FileHandler(String pattern, boolean append) throws IOException {
         if (pattern.equals("")) { //$NON-NLS-1$
-            throw new IllegalArgumentException(Messages.getString("logging.19")); //$NON-NLS-1$ 
+            throw new IllegalArgumentException(Messages.getString("logging.19")); //$NON-NLS-1$
         }
 
         init(pattern, Boolean.valueOf(append), Integer.valueOf(DEFAULT_LIMIT),
@@ -466,7 +458,7 @@
      * is done using {@code LogManager} properties. This handler is configured
      * to write to a rotating set of count files, when the limit of bytes has
      * been written to one output file, another file will be opened instead.
-     * 
+     *
      * @param pattern
      *            the name pattern for the output file.
      * @param limit
@@ -487,11 +479,10 @@
      *             {@code count < 1}.
      * @throws NullPointerException
      *             if {@code pattern} is {@code null}.
-     * @since Android 1.0
      */
     public FileHandler(String pattern, int limit, int count) throws IOException {
         if (pattern.equals("")) { //$NON-NLS-1$
-            throw new IllegalArgumentException(Messages.getString("logging.19")); //$NON-NLS-1$ 
+            throw new IllegalArgumentException(Messages.getString("logging.19")); //$NON-NLS-1$
         }
         if (limit < 0 || count < 1) {
             // logging.1B=The limit and count property must be larger than 0 and
@@ -509,7 +500,7 @@
      * {@code LogManager} properties. This handler is configured to write to a
      * rotating set of count files, when the limit of bytes has been written to
      * one output file, another file will be opened instead.
-     * 
+     *
      * @param pattern
      *            the name pattern for the output file.
      * @param limit
@@ -532,12 +523,11 @@
      *             {@code count < 1}.
      * @throws NullPointerException
      *             if {@code pattern} is {@code null}.
-     * @since Android 1.0
      */
     public FileHandler(String pattern, int limit, int count, boolean append)
             throws IOException {
         if (pattern.equals("")) { //$NON-NLS-1$
-            throw new IllegalArgumentException(Messages.getString("logging.19")); //$NON-NLS-1$ 
+            throw new IllegalArgumentException(Messages.getString("logging.19")); //$NON-NLS-1$
         }
         if (limit < 0 || count < 1) {
             // logging.1B=The limit and count property must be larger than 0 and
@@ -550,14 +540,13 @@
 
     /**
      * Flushes and closes all opened files.
-     * 
+     *
      * @throws SecurityException
      *             if a security manager exists and it determines that the
      *             caller does not have the required permissions to control this
      *             handler; required permissions include
      *             {@code LogPermission("control")},
      *             {@code FilePermission("write")} etc.
-     * @since Android 1.0
      */
     @Override
     public void close() {
@@ -577,10 +566,9 @@
 
     /**
      * Publish a {@code LogRecord}.
-     * 
+     *
      * @param record
      *            the log record to publish.
-     * @since Android 1.0
      */
     @Override
     public void publish(LogRecord record) {
diff --git a/libcore/logging/src/main/java/java/util/logging/Filter.java b/libcore/logging/src/main/java/java/util/logging/Filter.java
index e81f216..f5dbd9f 100644
--- a/libcore/logging/src/main/java/java/util/logging/Filter.java
+++ b/libcore/logging/src/main/java/java/util/logging/Filter.java
@@ -20,8 +20,6 @@
 /**
  * A {@code Filter} provides a mechanism for exercising fine-grained control
  * over which records get logged.
- * 
- * @since Android 1.0
  */
 public interface Filter {
 
@@ -32,7 +30,6 @@
      *            the {@link LogRecord} to be checked.
      * @return {@code true} if the supplied log record needs to be logged,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     boolean isLoggable(LogRecord record);
 }
diff --git a/libcore/logging/src/main/java/java/util/logging/Formatter.java b/libcore/logging/src/main/java/java/util/logging/Formatter.java
index 2941c24..f9b0d25 100644
--- a/libcore/logging/src/main/java/java/util/logging/Formatter.java
+++ b/libcore/logging/src/main/java/java/util/logging/Formatter.java
@@ -15,7 +15,6 @@
  * limitations under the License.
  */
 
-
 package java.util.logging;
 
 import java.text.MessageFormat;
@@ -26,41 +25,24 @@
  * string representation. Head and tail strings are sometimes used to wrap a set
  * of records. The {@code getHead} and {@code getTail} methods are used for this
  * purpose.
- * 
- * @since Android 1.0
  */
 public abstract class Formatter {
 
-    /*
-     * -------------------------------------------------------------------
-     * Constructors
-     * -------------------------------------------------------------------
-     */
-
     /**
      * Constructs a {@code Formatter} object.
-     * 
-     * @since Android 1.0
      */
     protected Formatter() {
         super();
     }
 
-    /*
-     * -------------------------------------------------------------------
-     * Methods
-     * -------------------------------------------------------------------
-     */
-
     /**
      * Converts a {@link LogRecord} object into a string representation. The
      * resulted string is usually localized and includes the message field of
      * the record.
-     * 
+     *
      * @param r
      *            the log record to be formatted into a string.
      * @return the formatted string.
-     * @since Android 1.0
      */
     public abstract String format(LogRecord r);
 
@@ -71,16 +53,13 @@
      * <p>
      * The message string is firstly localized using the {@code ResourceBundle}
      * object associated with the supplied {@code LogRecord}.
-     * </p>
      * <p>
      * Notice : if message contains "{0", then java.text.MessageFormat is used.
      * Otherwise no formatting is performed.
-     * </p>
-     * 
+     *
      * @param r
      *            the log record to be formatted.
      * @return the string resulted from the formatting.
-     * @since Android 1.0
      */
     public String formatMessage(LogRecord r) {
         String pattern = r.getMessage();
@@ -114,14 +93,12 @@
     /**
      * Gets the head string used to wrap a set of log records. This base class
      * always returns an empty string.
-     * 
+     *
      * @param h
      *            the target handler.
      * @return the head string used to wrap a set of log records, empty in this
      *         implementation.
-     * @since Android 1.0
      */
-    @SuppressWarnings("unused")
     public String getHead(Handler h) {
         return ""; //$NON-NLS-1$
     }
@@ -129,17 +106,13 @@
     /**
      * Gets the tail string used to wrap a set of log records. This base class
      * always returns the empty string.
-     * 
+     *
      * @param h
      *            the target handler.
      * @return the tail string used to wrap a set of log records, empty in this
      *         implementation.
-     * @since Android 1.0
      */
-    @SuppressWarnings("unused")
     public String getTail(Handler h) {
         return ""; //$NON-NLS-1$
     }
-
 }
-
diff --git a/libcore/logging/src/main/java/java/util/logging/Handler.java b/libcore/logging/src/main/java/java/util/logging/Handler.java
index d28bce0..a5b92a0 100644
--- a/libcore/logging/src/main/java/java/util/logging/Handler.java
+++ b/libcore/logging/src/main/java/java/util/logging/Handler.java
@@ -15,13 +15,12 @@
  * limitations under the License.
  */
 
-
 package java.util.logging;
 
+import java.io.UnsupportedEncodingException;
 import java.nio.charset.Charset;
 import java.security.AccessController;
 import java.security.PrivilegedExceptionAction;
-import java.io.UnsupportedEncodingException;
 
 import org.apache.harmony.logging.internal.nls.Messages;
 
@@ -29,24 +28,11 @@
  * A {@code Handler} object accepts a logging request and exports the desired
  * messages to a target, for example, a file, the console, etc. It can be
  * disabled by setting its logging level to {@code Level.OFF}.
- * 
- * @since Android 1.0
  */
 public abstract class Handler {
 
-    /*
-     * -------------------------------------------------------------------
-     * Constants
-     * -------------------------------------------------------------------
-     */
     private static final Level DEFAULT_LEVEL = Level.ALL;
 
-    /*
-     * -------------------------------------------------------------------
-     * Instance variables
-     * -------------------------------------------------------------------
-     */
-
     // the error manager to report errors during logging
     private ErrorManager errorMan;
 
@@ -65,18 +51,10 @@
     // class name, used for property reading
     private String prefix;
 
-    /*
-     * -------------------------------------------------------------------
-     * Constructors
-     * -------------------------------------------------------------------
-     */
-
     /**
      * Constructs a {@code Handler} object with a default error manager instance
      * {@code ErrorManager}, the default encoding, and the default logging
      * level {@code Level.ALL}. It has no filter and no formatter.
-     * 
-     * @since Android 1.0
      */
     protected Handler() {
         this.errorMan = new ErrorManager();
@@ -87,12 +65,6 @@
         this.prefix = this.getClass().getName();
     }
 
-    /*
-     * -------------------------------------------------------------------
-     * Methods
-     * -------------------------------------------------------------------
-     */
-
     // get a instance from given class name, using Class.forName()
     private Object getDefaultInstance(String className) {
         Object result = null;
@@ -102,7 +74,7 @@
         try {
             result = Class.forName(className).newInstance();
         } catch (Exception e) {
-            //ignore
+            // ignore
         }
         return result;
     }
@@ -110,7 +82,8 @@
     // get a instance from given class name, using context classloader
     private Object getCustomizeInstance(final String className)
             throws Exception {
-        Class<?> c = AccessController.doPrivileged(new PrivilegedExceptionAction<Class<?>>() {
+        Class<?> c = AccessController
+                .doPrivileged(new PrivilegedExceptionAction<Class<?>>() {
                     public Class<?> run() throws Exception {
                         ClassLoader loader = Thread.currentThread()
                                 .getContextClassLoader();
@@ -126,22 +99,22 @@
     // print error message in some format
     void printInvalidPropMessage(String key, String value, Exception e) {
         // logging.12=Invalid property value for
-        String msg = new StringBuilder().append(Messages.getString("logging.12"))  //$NON-NLS-1$
+        String msg = new StringBuilder().append(
+                Messages.getString("logging.12")) //$NON-NLS-1$
                 .append(prefix).append(":").append(key).append("/").append( //$NON-NLS-1$//$NON-NLS-2$
                         value).toString();
         errorMan.error(msg, e, ErrorManager.GENERIC_FAILURE);
     }
 
-    /*
+    /**
      * init the common properties, including filter, level, formatter, and
      * encoding
      */
-    @SuppressWarnings("unused")
     void initProperties(String defaultLevel, String defaultFilter,
             String defaultFormatter, String defaultEncoding) {
         LogManager manager = LogManager.getLogManager();
 
-        //set filter
+        // set filter
         final String filterName = manager.getProperty(prefix + ".filter"); //$NON-NLS-1$
         if (null != filterName) {
             try {
@@ -154,7 +127,7 @@
             filter = (Filter) getDefaultInstance(defaultFilter);
         }
 
-        //set level
+        // set level
         String levelName = manager.getProperty(prefix + ".level"); //$NON-NLS-1$
         if (null != levelName) {
             try {
@@ -167,7 +140,7 @@
             level = Level.parse(defaultLevel);
         }
 
-        //set formatter
+        // set formatter
         final String formatterName = manager.getProperty(prefix + ".formatter"); //$NON-NLS-1$
         if (null != formatterName) {
             try {
@@ -180,7 +153,7 @@
             formatter = (Formatter) getDefaultInstance(defaultFormatter);
         }
 
-        //set encoding
+        // set encoding
         final String encodingName = manager.getProperty(prefix + ".encoding"); //$NON-NLS-1$
         try {
             internalSetEncoding(encodingName);
@@ -193,37 +166,31 @@
      * Closes this handler. A flush operation will be performed and all the
      * associated resources will be freed. Client applications should not use
      * this handler after closing it.
-     * 
+     *
      * @throws SecurityException
      *             if a security manager determines that the caller does not
      *             have the required permission.
-     *
-     * @since Android 1.0             
      */
     public abstract void close();
 
     /**
      * Flushes any buffered output.
-     * 
-     * @since Android 1.0
      */
     public abstract void flush();
 
     /**
      * Accepts a logging request and sends it to the the target.
-     * 
+     *
      * @param record
      *            the log record to be logged; {@code null} records are ignored.
-     * @since Android 1.0
      */
     public abstract void publish(LogRecord record);
 
     /**
      * Gets the character encoding used by this handler, {@code null} for
      * default encoding.
-     * 
+     *
      * @return the character encoding used by this handler.
-     * @since Android 1.0
      */
     public String getEncoding() {
         return this.encoding;
@@ -232,12 +199,11 @@
     /**
      * Gets the error manager used by this handler to report errors during
      * logging.
-     * 
+     *
      * @return the error manager used by this handler.
      * @throws SecurityException
      *             if a security manager determines that the caller does not
      *             have the required permission.
-     * @since Android 1.0            
      */
     public ErrorManager getErrorManager() {
         LogManager.getLogManager().checkAccess();
@@ -246,9 +212,8 @@
 
     /**
      * Gets the filter used by this handler.
-     * 
+     *
      * @return the filter used by this handler (possibly {@code null}).
-     * @since Android 1.0
      */
     public Filter getFilter() {
         return this.filter;
@@ -256,9 +221,8 @@
 
     /**
      * Gets the formatter used by this handler to format the logging messages.
-     * 
+     *
      * @return the formatter used by this handler (possibly {@code null}).
-     * @since Android 1.0
      */
     public Formatter getFormatter() {
         return this.formatter;
@@ -267,9 +231,8 @@
     /**
      * Gets the logging level of this handler, records with levels lower than
      * this value will be dropped.
-     * 
+     *
      * @return the logging level of this handler.
-     * @since Android 1.0
      */
     public Level getLevel() {
         return this.level;
@@ -278,12 +241,11 @@
     /**
      * Determines whether the supplied log record needs to be logged. The
      * logging levels will be checked as well as the filter.
-     * 
+     *
      * @param record
      *            the log record to be checked.
      * @return {@code true} if the supplied log record needs to be logged,
      *         otherwise {@code false}.
-     * @since Android 1.0
      */
     public boolean isLoggable(LogRecord record) {
         if (null == record) {
@@ -302,14 +264,13 @@
      * {@code ErrorManager} is used for that purpose. No security checks are
      * done, therefore this is compatible with environments where the caller
      * is non-privileged.
-     * 
+     *
      * @param msg
      *            the error message, may be {@code null}.
      * @param ex
      *            the associated exception, may be {@code null}.
      * @param code
      *            an {@code ErrorManager} error code.
-     * @since Android 1.0
      */
     protected void reportError(String msg, Exception ex, int code) {
         this.errorMan.error(msg, ex, code);
@@ -319,12 +280,11 @@
      * Sets the character encoding used by this handler. A {@code null} value
      * indicates the use of the default encoding. This internal method does
      * not check security.
-     * 
+     *
      * @param newEncoding
      *            the character encoding to set.
      * @throws UnsupportedEncodingException
      *             if the specified encoding is not supported by the runtime.
-     * @since Android 1.0
      */
     void internalSetEncoding(String newEncoding)
             throws UnsupportedEncodingException {
@@ -347,7 +307,7 @@
     /**
      * Sets the character encoding used by this handler, {@code null} indicates
      * a default encoding.
-     * 
+     *
      * @param encoding
      *            the character encoding to set.
      * @throws SecurityException
@@ -355,7 +315,6 @@
      *             have the required permission.
      * @throws UnsupportedEncodingException
      *             if the specified encoding is not supported by the runtime.
-     * @since Android 1.0             
      */
     public void setEncoding(String encoding) throws SecurityException,
             UnsupportedEncodingException {
@@ -365,7 +324,7 @@
 
     /**
      * Sets the error manager for this handler.
-     * 
+     *
      * @param em
      *            the error manager to set.
      * @throws NullPointerException
@@ -373,7 +332,6 @@
      * @throws SecurityException
      *             if a security manager determines that the caller does not
      *             have the required permission.
-     * @since Android 1.0
      */
     public void setErrorManager(ErrorManager em) {
         LogManager.getLogManager().checkAccess();
@@ -385,13 +343,12 @@
 
     /**
      * Sets the filter to be used by this handler.
-     * 
+     *
      * @param newFilter
      *            the filter to set, may be {@code null}.
      * @throws SecurityException
      *             if a security manager determines that the caller does not
      *             have the required permission.
-     * @since Android 1.0
      */
     public void setFilter(Filter newFilter) {
         LogManager.getLogManager().checkAccess();
@@ -401,7 +358,7 @@
     /**
      * Sets the formatter to be used by this handler. This internal method does
      * not check security.
-     * 
+     *
      * @param newFormatter
      *            the formatter to set.
      */
@@ -414,7 +371,7 @@
 
     /**
      * Sets the formatter to be used by this handler.
-     * 
+     *
      * @param newFormatter
      *            the formatter to set.
      * @throws NullPointerException
@@ -422,7 +379,6 @@
      * @throws SecurityException
      *             if a security manager determines that the caller does not
      *             have the required permission.
-     * @since Android 1.0
      */
     public void setFormatter(Formatter newFormatter) {
         LogManager.getLogManager().checkAccess();
@@ -432,7 +388,7 @@
     /**
      * Sets the logging level of the messages logged by this handler, levels
      * lower than this value will be dropped.
-     * 
+     *
      * @param newLevel
      *            the logging level to set.
      * @throws NullPointerException
@@ -440,7 +396,6 @@
      * @throws SecurityException
      *             if a security manager determines that the caller does not
      *             have the required permission.
-     * @since Android 1.0
      */
     public void setLevel(Level newLevel) {
         if (null == newLevel) {
@@ -450,4 +405,3 @@
         this.level = newLevel;
     }
 }
-
diff --git a/libcore/logging/src/main/java/java/util/logging/Level.java b/libcore/logging/src/main/java/java/util/logging/Level.java
index 32ba017..f988127 100644
--- a/libcore/logging/src/main/java/java/util/logging/Level.java
+++ b/libcore/logging/src/main/java/java/util/logging/Level.java
@@ -41,8 +41,6 @@
  * INFO, WARNING, SEVERE. There are two additional predefined levels, which are
  * ALL and OFF. ALL indicates logging all messages, and OFF indicates logging no
  * messages.
- * </p>
- * @since Android 1.0
  */
 public class Level implements Serializable {
 
@@ -52,70 +50,52 @@
 
     /**
      * The OFF level provides no logging messages.
-     * 
-     * @since Android 1.0
      */
     public static final Level OFF = new Level("OFF", Integer.MAX_VALUE); //$NON-NLS-1$
 
     /**
      * The SEVERE level provides severe failure messages.
-     * 
-     * @since Android 1.0
      */
     public static final Level SEVERE = new Level("SEVERE", 1000); //$NON-NLS-1$
 
     /**
      * The WARNING level provides warnings.
-     * 
-     * @since Android 1.0
      */
     public static final Level WARNING = new Level("WARNING", 900); //$NON-NLS-1$
 
     /**
      * The INFO level provides informative messages.
-     * 
-     * @since Android 1.0
      */
     public static final Level INFO = new Level("INFO", 800); //$NON-NLS-1$
 
     /**
      * The CONFIG level provides static configuration messages.
-     * 
-     * @since Android 1.0
      */
     public static final Level CONFIG = new Level("CONFIG", 700); //$NON-NLS-1$
 
     /**
      * The FINE level provides tracing messages.
-     * 
-     * @since Android 1.0
      */
     public static final Level FINE = new Level("FINE", 500); //$NON-NLS-1$
 
     /**
      * The FINER level provides more detailed tracing messages.
-     * 
-     * @since Android 1.0
      */
     public static final Level FINER = new Level("FINER", 400); //$NON-NLS-1$
 
     /**
      * The FINEST level provides highly detailed tracing messages.
-     * 
-     * @since Android 1.0
      */
     public static final Level FINEST = new Level("FINEST", 300); //$NON-NLS-1$
 
     /**
      * The ALL level provides all logging messages.
-     * 
-     * @since Android 1.0
      */
     public static final Level ALL = new Level("ALL", Integer.MIN_VALUE); //$NON-NLS-1$
 
     /**
      * Parses a level name into a {@code Level} object.
-     * 
+     *
      * @param name
      *            the name of the desired {@code level}, which cannot be
      *            {@code null}.
@@ -124,13 +104,8 @@
      *             if {@code name} is {@code null}.
      * @throws IllegalArgumentException
      *             if {@code name} is not valid.
-     * @since Android 1.0
      */
     public static Level parse(String name) throws IllegalArgumentException {
-        // BEGIN android-note
-        // final modifier removed and IAE added to get closer to the RI
-        // copied from newer version of harmony
-        // END android-note
         if (name == null) {
             // logging.1C=The 'name' parameter is null.
             throw new NullPointerException(Messages.getString("logging.1C")); //$NON-NLS-1$
@@ -155,8 +130,8 @@
 
             if (isNameAnInt) {
                 /*
-                 * Loop through levels a second time, so that the
-                 * returned instance will be passed on the order of construction.
+                 * Loop through levels a second time, so that the returned
+                 * instance will be passed on the order of construction.
                  */
                 for (Level level : levels) {
                     if (nameAsInt == level.intValue()) {
@@ -168,7 +143,8 @@
 
         if (!isNameAnInt) {
             // logging.1D=Cannot parse this name: {0}
-            throw new IllegalArgumentException(Messages.getString("logging.1D", name)); //$NON-NLS-1$
+            throw new IllegalArgumentException(Messages.getString(
+                    "logging.1D", name)); //$NON-NLS-1$
         }
 
         return new Level(name, nameAsInt);
@@ -176,21 +152,21 @@
 
     /**
      * The name of this Level.
-     * 
+     *
      * @serial
      */
     private final String name;
 
     /**
      * The integer value indicating the level.
-     * 
+     *
      * @serial
      */
     private final int value;
 
     /**
      * The name of the resource bundle used to localize the level name.
-     * 
+     *
      * @serial
      */
     private final String resourceBundleName;
@@ -204,14 +180,13 @@
     /**
      * Constructs an instance of {@code Level} taking the supplied name and
      * level value.
-     * 
+     *
      * @param name
      *            the name of the level.
      * @param level
      *            an integer value indicating the level.
      * @throws NullPointerException
      *             if {@code name} is {@code null}.
-     * @since Android 1.0             
      */
     protected Level(String name, int level) {
         this(name, level, null);
@@ -220,7 +195,7 @@
     /**
      * Constructs an instance of {@code Level} taking the supplied name, level
      * value and resource bundle name.
-     * 
+     *
      * @param name
      *            the name of the level.
      * @param level
@@ -229,7 +204,6 @@
      *            the name of the resource bundle to use.
      * @throws NullPointerException
      *             if {@code name} is {@code null}.
-     * @since Android 1.0
      */
     protected Level(String name, int level, String resourceBundleName) {
         if (name == null) {
@@ -256,9 +230,8 @@
 
     /**
      * Gets the name of this level.
-     * 
+     *
      * @return this level's name.
-     * @since Android 1.0
      */
     public String getName() {
         return this.name;
@@ -266,9 +239,8 @@
 
     /**
      * Gets the name of the resource bundle associated with this level.
-     * 
+     *
      * @return the name of this level's resource bundle.
-     * @since Android 1.0
      */
     public String getResourceBundleName() {
         return this.resourceBundleName;
@@ -276,20 +248,17 @@
 
     /**
      * Gets the integer value indicating this level.
-     * 
+     *
      * @return this level's integer value.
-     * @since Android 1.0
      */
     public final int intValue() {
         return this.value;
     }
 
     /**
-     * <p>
      * Serialization helper method to maintain singletons and add any new
      * levels.
-     * </p>
-     * 
+     *
      * @return the resolved instance.
      */
     private Object readResolve() {
@@ -298,7 +267,7 @@
                 if (value != level.value) {
                     continue;
                 }
-                if (!name.equals(name)) {
+                if (!name.equals(level.name)) {
                     continue;
                 }
                 if (resourceBundleName == level.resourceBundleName) {
@@ -316,7 +285,7 @@
 
     /**
      * Serialization helper to setup transient resource bundle instance.
-     * 
+     *
      * @param in
      *            the input stream to read the instance data from.
      * @throws IOException
@@ -324,7 +293,8 @@
      * @throws ClassNotFoundException
      *             if a class is not found.
      */
-    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+    private void readObject(ObjectInputStream in) throws IOException,
+            ClassNotFoundException {
         in.defaultReadObject();
         if (resourceBundleName != null) {
             try {
@@ -339,9 +309,8 @@
      * Gets the localized name of this level. The default locale is used. If no
      * resource bundle is associated with this level then the original level
      * name is returned.
-     * 
+     *
      * @return the localized name of this level.
-     * @since Android 1.0
      */
     public String getLocalizedName() {
         if (rb == null) {
@@ -358,12 +327,11 @@
     /**
      * Compares two {@code Level} objects for equality. They are considered to
      * be equal if they have the same level value.
-     * 
+     *
      * @param o
      *            the other object to compare this level to.
      * @return {@code true} if this object equals to the supplied object,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object o) {
@@ -380,9 +348,8 @@
 
     /**
      * Returns the hash code of this {@code Level} object.
-     * 
+     *
      * @return this level's hash code.
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -392,9 +359,8 @@
     /**
      * Returns the string representation of this {@code Level} object. In
      * this case, it is the level's name.
-     * 
+     *
      * @return the string representation of this level.
-     * @since Android 1.0
      */
     @Override
     public final String toString() {
diff --git a/libcore/logging/src/main/java/java/util/logging/LogManager.java b/libcore/logging/src/main/java/java/util/logging/LogManager.java
index 8409b81..308daaf 100644
--- a/libcore/logging/src/main/java/java/util/logging/LogManager.java
+++ b/libcore/logging/src/main/java/java/util/logging/LogManager.java
@@ -24,6 +24,10 @@
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+// BEGIN android-removed
+//import java.lang.management.ManagementFactory;
+//import java.lang.reflect.Method;
+// END android-removed
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.Collection;
@@ -33,13 +37,11 @@
 import java.util.Properties;
 import java.util.Set;
 import java.util.StringTokenizer;
+
 // BEGIN android-removed
-// import java.lang.management.ManagementFactory;
-// import java.lang.reflect.Method;
-// import javax.management.MBeanServer;
-// import javax.management.ObjectName;
-// import javax.management.ObjectInstance;
-// import javax.management.MalformedObjectNameException;
+//import javax.management.MBeanServer;
+//import javax.management.ObjectInstance;
+//import javax.management.ObjectName;
 // END android-removed
 
 import org.apache.harmony.logging.internal.nls.Messages;
@@ -49,23 +51,19 @@
  * logging framework, and to manage a hierarchical namespace of all named
  * {@code Logger} objects.
  * <p>
- *
  * There is only one global {@code LogManager} instance in the
  * application, which can be get by calling static method
  * {@link #getLogManager()}. This instance is created and
  * initialized during class initialization and cannot be changed.
- * </p>
  * <p>
  * The {@code LogManager} class can be specified by
  * java.util.logging.manager system property, if the property is unavailable or
  * invalid, the default class {@link java.util.logging.LogManager} will
  * be used.
- * </p>
  * <p>
- * When initialization, {@code LogManager} read its configuration from a
+ * On initialization, {@code LogManager} reads its configuration from a
  * properties file, which by default is the "lib/logging.properties" in the JRE
  * directory.
- * </p>
  * <p>
  * However, two optional system properties can be used to customize the initial
  * configuration process of {@code LogManager}.
@@ -73,31 +71,26 @@
  * <li>"java.util.logging.config.class"</li>
  * <li>"java.util.logging.config.file"</li>
  * </ul>
- * </p>
  * <p>
  * These two properties can be set in three ways, by the Preferences API, by the
  * "java" command line property definitions, or by system property definitions
  * passed to JNI_CreateJavaVM.
- * </p>
  * <p>
  * The "java.util.logging.config.class" should specifies a class name. If it is
  * set, this given class will be loaded and instantiated during
  * {@code LogManager} initialization, so that this object's default
  * constructor can read the initial configuration and define properties for
  * {@code LogManager}.
- * </p>
  * <p>
  * If "java.util.logging.config.class" property is not set, or it is invalid, or
  * some exception is thrown during the instantiation, then the
  * "java.util.logging.config.file" system property can be used to specify a
  * properties file. The {@code LogManager} will read initial
  * configuration from this file.
- * </p>
  * <p>
  * If neither of these properties is defined, or some exception is thrown
  * during these two properties using, the {@code LogManager} will read
  * its initial configuration from default properties file, as described above.
- * </p>
  * <p>
  * The global logging properties may include:
  * <ul>
@@ -113,22 +106,18 @@
  * some logger, etc. These classes will be loaded and instantiated during
  * {@code LogManager} configuration</li>
  * </ul>
- * </p>
  * <p>
  * This class, together with any handler and configuration classes associated
  * with it, <b>must</b> be loaded from the system classpath when
  * {@code LogManager} configuration occurs.
- * </p>
  * <p>
  * Besides global properties, the properties for loggers and Handlers can be
  * specified in the property files. The names of these properties will start
  * with the complete dot separated names for the handlers or loggers.
- * </p>
  * <p>
  * In the {@code LogManager}'s hierarchical namespace,
  * {@code Loggers} are organized based on their dot separated names. For
  * example, "x.y.z" is child of "x.y".
- * </p>
  * <p>
  * Levels for {@code Loggers} can be defined by properties whose name end
  * with ".level". Thus "alogger.level" defines a level for the logger named as
@@ -136,23 +125,15 @@
  * properties are read and applied in the same order as they are specified in
  * the property file. The root logger's level can be defined by the property
  * named as ".level".
- * </p>
  * <p>
  * All methods on this type can be taken as being thread safe.
- * </p>
- * 
+ *
  */
 public class LogManager {
-    /*
-     * -------------------------------------------------------------------
-     * Class variables
-     * -------------------------------------------------------------------
-     */
 
     // The line separator of the underlying OS
     // Use privileged code to read the line.separator system property
-    private static final String lineSeparator =
-            getPrivilegedSystemProperty("line.separator"); //$NON-NLS-1$
+    private static final String lineSeparator = getPrivilegedSystemProperty("line.separator"); //$NON-NLS-1$
 
     // The shared logging permission
     private static final LoggingPermission perm = new LoggingPermission(
@@ -160,63 +141,55 @@
 
     // the singleton instance
     static LogManager manager;
-    
+
     /**
      * The {@code String} value of the {@link LoggingMXBean}'s ObjectName.
-     * 
-     * @since Android 1.0
      */
-    public static final String LOGGING_MXBEAN_NAME =
-            "java.util.logging:type=Logging"; //$NON-NLS-1$
+    public static final String LOGGING_MXBEAN_NAME = "java.util.logging:type=Logging"; //$NON-NLS-1$
 
     /**
      * Get the {@code LoggingMXBean} instance. this implementation always throws
      * an UnsupportedOperationException.
-     * 
+     *
      * @return the {@code LoggingMXBean} instance
      */
     public static LoggingMXBean getLoggingMXBean() {
-        // BEGIN android-added
-        throw new UnsupportedOperationException();
-        // END android-added        
-        // BEGIN android-removed
-        // try {
-        //     ObjectName loggingMXBeanName = new ObjectName(LOGGING_MXBEAN_NAME);
-        //     MBeanServer platformBeanServer =
-        //             ManagementFactory.getPlatformMBeanServer();
-        //     Set loggingMXBeanSet = platformBeanServer.queryMBeans(
-        //             loggingMXBeanName, null);
-        // 
-        //     if (loggingMXBeanSet.size() != 1) {
-        //         // logging.21=There Can Be Only One logging MX bean.
-        //         throw new AssertionError(Messages.getString("logging.21"));
-        //     }
-        //
-        //     Iterator i = loggingMXBeanSet.iterator();
-        //     ObjectInstance loggingMXBeanOI = (ObjectInstance) i.next();
-        //     String lmxbcn = loggingMXBeanOI.getClassName();
-        //     Class lmxbc = Class.forName(lmxbcn);
-        //     Method giMethod = lmxbc.getDeclaredMethod("getInstance");
-        //     giMethod.setAccessible(true);
-        //     LoggingMXBean lmxb = (LoggingMXBean)
-        //             giMethod.invoke(null, new Object[] {});
-        //
-        //     return lmxb;
-        // } catch (Exception e) {
-        //     //TODO
-        //     //e.printStackTrace();
-        // }
-        // // logging.22=Exception occurred while getting the logging MX bean.
-        // throw new AssertionError(Messages.getString("logging.22")); //$NON-NLS-1$
-        // END android-removed
-     }
+      // BEGIN android-added
+      throw new UnsupportedOperationException();
+      // END android-added
+      // BEGIN android-removed
+      // try {
+      //     ObjectName loggingMXBeanName = new ObjectName(LOGGING_MXBEAN_NAME);
+      //     MBeanServer platformBeanServer = ManagementFactory
+      //             .getPlatformMBeanServer();
+      //     Set<?> loggingMXBeanSet = platformBeanServer.queryMBeans(
+      //             loggingMXBeanName, null);
+      //
+      //     if (loggingMXBeanSet.size() != 1) {
+      //         // logging.21=There Can Be Only One logging MX bean.
+      //         throw new AssertionError(Messages.getString("logging.21")); //$NON-NLS-1$
+      //     }
+      //
+      //     Iterator<?> i = loggingMXBeanSet.iterator();
+      //     ObjectInstance loggingMXBeanOI = (ObjectInstance) i.next();
+      //     String lmxbcn = loggingMXBeanOI.getClassName();
+      //     Class<?> lmxbc = Class.forName(lmxbcn);
+      //     Method giMethod = lmxbc.getDeclaredMethod("getInstance"); //$NON-NLS-1$
+      //     giMethod.setAccessible(true);
+      //     LoggingMXBean lmxb = (LoggingMXBean) giMethod.invoke(null,
+      //             new Object[] {});
+      //
+      //     return lmxb;
+      // } catch (Exception e) {
+      //     // TODO
+      //     // e.printStackTrace();
+      // }
+      // // logging.22=Exception occurred while getting the logging MX bean.
+      // throw new AssertionError(Messages.getString("logging.22")); //$NON-NLS-1$
+      // END android-removed
+    }
 
-    /*
-     * -------------------------------------------------------------------
-     * Instance variables
-     * -------------------------------------------------------------------
-     */
-    //FIXME: use weak reference to avoid heap memory leak    
+    // FIXME: use weak reference to avoid heap memory leak
     private Hashtable<String, Logger> loggers;
 
     // the configuration properties
@@ -225,19 +198,13 @@
     // the property change listener
     private PropertyChangeSupport listeners;
 
-    /*
-     * -------------------------------------------------------------------
-     * Global initialization
-     * -------------------------------------------------------------------
-     */
-
     static {
         // init LogManager singleton instance
         AccessController.doPrivileged(new PrivilegedAction<Object>() {
             public Object run() {
-                String className = System.getProperty(
-                        "java.util.logging.manager"); //$NON-NLS-1$
-                
+                String className = System
+                        .getProperty("java.util.logging.manager"); //$NON-NLS-1$
+
                 if (null != className) {
                     manager = (LogManager) getInstanceByClass(className);
                 }
@@ -256,7 +223,7 @@
                 Logger root = new Logger("", null); //$NON-NLS-1$
                 root.setLevel(Level.INFO);
                 Logger.global.setParent(root);
-                
+
                 manager.addLogger(root);
                 manager.addLogger(Logger.global);
                 return null;
@@ -290,11 +257,6 @@
     }
 
     /*
-     * -------------------------------------------------------------------
-     * Methods
-     * -------------------------------------------------------------------
-     */
-    /*
      * Package private utilities Returns the line separator of the underlying
      * OS.
      */
@@ -307,7 +269,7 @@
      * that it is trusted to modify the configuration for logging framework. If
      * the check passes, just return, otherwise {@code SecurityException}
      * will be thrown.
-     * 
+     *
      * @throws SecurityException
      *             if there is a security manager in operation and the invoker
      *             of this method does not have the required security permission
@@ -330,7 +292,7 @@
      * unexpectedly garbage collected it is necessary for <i>applications</i>
      * to maintain references to them.
      * </p>
-     * 
+     *
      * @param logger
      *            the logger to be added.
      * @return true if the given logger is added into the namespace
@@ -347,7 +309,6 @@
         return true;
     }
 
-
     private void addToFamilyTree(Logger logger, String name) {
         Logger parent = null;
         // find parent
@@ -359,8 +320,8 @@
             if (parent != null) {
                 logger.internalSetParent(parent);
                 break;
-            } else if (getProperty(parentName+".level") != null || //$NON-NLS-1$
-                    getProperty(parentName+".handlers") != null) { //$NON-NLS-1$
+            } else if (getProperty(parentName + ".level") != null || //$NON-NLS-1$
+                    getProperty(parentName + ".handlers") != null) { //$NON-NLS-1$
                 parent = Logger.getLogger(parentName);
                 logger.internalSetParent(parent);
                 break;
@@ -371,16 +332,22 @@
         }
 
         // find children
-        //TODO: performance can be improved here?
+        // TODO: performance can be improved here?
         Collection<Logger> allLoggers = loggers.values();
-        for (Logger child : allLoggers) {
+        for (final Logger child : allLoggers) {
             Logger oldParent = child.getParent();
             if (parent == oldParent
                     && (name.length() == 0 || child.getName().startsWith(
                             name + '.'))) {
-                child.setParent(logger);
+                final Logger thisLogger = logger;
+                AccessController.doPrivileged(new PrivilegedAction<Object>() {
+                    public Object run() {
+                        child.setParent(thisLogger);
+                        return null;
+                    }
+                });
                 if (null != oldParent) {
-                    //-- remove from old parent as the parent has been changed
+                    // -- remove from old parent as the parent has been changed
                     oldParent.removeChild(child);
                 }
             }
@@ -389,7 +356,7 @@
 
     /**
      * Get the logger with the given name.
-     * 
+     *
      * @param name
      *            name of logger
      * @return logger with given name, or {@code null} if nothing is found.
@@ -400,7 +367,7 @@
 
     /**
      * Get a {@code Enumeration} of all registered logger names.
-     * 
+     *
      * @return enumeration of registered logger names
      */
     public synchronized Enumeration<String> getLoggerNames() {
@@ -409,7 +376,7 @@
 
     /**
      * Get the global {@code LogManager} instance.
-     * 
+     *
      * @return the global {@code LogManager} instance
      */
     public static LogManager getLogManager() {
@@ -418,7 +385,7 @@
 
     /**
      * Get the value of property with given name.
-     * 
+     *
      * @param name
      *            the name of property
      * @return the value of property
@@ -433,7 +400,7 @@
      * <p>
      * Notice : No {@code PropertyChangeEvent} are fired.
      * </p>
-     * 
+     *
      * @throws IOException
      *             if any IO related problems happened.
      * @throws SecurityException
@@ -443,19 +410,20 @@
     public void readConfiguration() throws IOException {
         checkAccess();
         // check config class
-        String configClassName = System.getProperty(
-                "java.util.logging.config.class"); //$NON-NLS-1$
-        if (null == configClassName || null == getInstanceByClass(configClassName)) {
-            // if config class failed, check config file       
-            String configFile = System.getProperty(
-                    "java.util.logging.config.file"); //$NON-NLS-1$
+        String configClassName = System
+                .getProperty("java.util.logging.config.class"); //$NON-NLS-1$
+        if (null == configClassName
+                || null == getInstanceByClass(configClassName)) {
+            // if config class failed, check config file
+            String configFile = System
+                    .getProperty("java.util.logging.config.file"); //$NON-NLS-1$
 
             if (null == configFile) {
                 // if cannot find configFile, use default logging.properties
                 configFile = new StringBuilder().append(
                         System.getProperty("java.home")).append(File.separator) //$NON-NLS-1$
                         .append("lib").append(File.separator).append( //$NON-NLS-1$
-                        "logging.properties").toString(); //$NON-NLS-1$
+                                "logging.properties").toString(); //$NON-NLS-1$
             }
 
             InputStream input = null;
@@ -463,7 +431,7 @@
                 // BEGIN android-removed
                 // input = new BufferedInputStream(new FileInputStream(configFile));
                 // END android-removed
-                
+
                 // BEGIN android-added
                 try {
                     input = new BufferedInputStream(
@@ -504,13 +472,12 @@
             return clazz.newInstance();
         } catch (Exception e) {
             try {
-                Class<?> clazz = Thread.currentThread()
-                        .getContextClassLoader().loadClass(className);
+                Class<?> clazz = Thread.currentThread().getContextClassLoader()
+                        .loadClass(className);
                 return clazz.newInstance();
             } catch (Exception innerE) {
-                //logging.20=Loading class "{0}" failed
-                System.err.println(Messages.getString(
-                        "logging.20", className)); //$NON-NLS-1$
+                // logging.20=Loading class "{0}" failed
+                System.err.println(Messages.getString("logging.20", className)); //$NON-NLS-1$
                 System.err.println(innerE);
                 return null;
             }
@@ -523,7 +490,7 @@
             throws IOException {
         reset();
         props.load(ins);
-        
+
         // parse property "config" and apply setting
         String configs = props.getProperty("config"); //$NON-NLS-1$
         if (null != configs) {
@@ -533,27 +500,25 @@
                 getInstanceByClass(configerName);
             }
         }
-        
+
         // set levels for logger
         Collection<Logger> allLoggers = loggers.values();
-        for(Logger logger : allLoggers){
-            String property = props.getProperty(
-                    logger.getName()+".level"); //$NON-NLS-1$
-            if(null != property){
+        for (Logger logger : allLoggers) {
+            String property = props.getProperty(logger.getName() + ".level"); //$NON-NLS-1$
+            if (null != property) {
                 logger.setLevel(Level.parse(property));
             }
         }
         listeners.firePropertyChange(null, null, null);
     }
 
-
     /**
      * Re-initialize the properties and configuration from the given
      * {@code InputStream}
      * <p>
      * Notice : No {@code PropertyChangeEvent} are fired.
      * </p>
-     * 
+     *
      * @param ins
      *            the input stream
      * @throws IOException
@@ -574,7 +539,7 @@
      * level is set to null, except the root logger's level is set to
      * {@code Level.INFO}.
      * </p>
-     * 
+     *
      * @throws SecurityException
      *             if security manager exists and it determines that caller does
      *             not have the required permissions to perform this action.
@@ -583,10 +548,10 @@
         checkAccess();
         props = new Properties();
         Enumeration<String> names = getLoggerNames();
-        while(names.hasMoreElements()){
+        while (names.hasMoreElements()) {
             String name = names.nextElement();
             Logger logger = getLogger(name);
-            if(logger != null){
+            if (logger != null) {
                 logger.reset();
             }
         }
@@ -599,7 +564,7 @@
     /**
      * Add a {@code PropertyChangeListener}, which will be invoked when
      * the properties are reread.
-     * 
+     *
      * @param l
      *            the {@code PropertyChangeListener} to be added.
      * @throws SecurityException
@@ -607,7 +572,7 @@
      *             not have the required permissions to perform this action.
      */
     public void addPropertyChangeListener(PropertyChangeListener l) {
-        if(l == null){
+        if (l == null) {
             throw new NullPointerException();
         }
         checkAccess();
@@ -617,7 +582,7 @@
     /**
      * Remove a {@code PropertyChangeListener}, do nothing if the given
      * listener is not found.
-     * 
+     *
      * @param l
      *            the {@code PropertyChangeListener} to be removed.
      * @throws SecurityException
diff --git a/libcore/logging/src/main/java/java/util/logging/LogRecord.java b/libcore/logging/src/main/java/java/util/logging/LogRecord.java
index b8a98ef..0a8e257 100644
--- a/libcore/logging/src/main/java/java/util/logging/LogRecord.java
+++ b/libcore/logging/src/main/java/java/util/logging/LogRecord.java
@@ -40,9 +40,6 @@
  * {@code getSourceClassName} or {@code getSourceMethodName} if they expect to
  * use them after passing the {@code LogRecord} object to another thread or
  * transmitting it over RMI.
- * </p>
- * 
- * @since Android 1.0
  */
 public class LogRecord implements Serializable {
 
@@ -65,70 +62,70 @@
 
     /**
      * The logging level.
-     * 
+     *
      * @serial
      */
     private Level level;
 
     /**
      * The sequence number.
-     * 
+     *
      * @serial
      */
     private long sequenceNumber;
 
     /**
      * The name of the class that issued the logging call.
-     * 
+     *
      * @serial
      */
     private String sourceClassName;
 
     /**
      * The name of the method that issued the logging call.
-     * 
+     *
      * @serial
      */
     private String sourceMethodName;
 
     /**
      * The original message text.
-     * 
+     *
      * @serial
      */
     private String message;
 
     /**
      * The ID of the thread that issued the logging call.
-     * 
+     *
      * @serial
      */
     private int threadID;
 
     /**
      * The time that the event occurred, in milliseconds since 1970.
-     * 
+     *
      * @serial
      */
     private long millis;
 
     /**
      * The associated {@code Throwable} object if any.
-     * 
+     *
      * @serial
      */
     private Throwable thrown;
 
     /**
      * The name of the source logger.
-     * 
+     *
      * @serial
      */
     private String loggerName;
 
     /**
      * The name of the resource bundle used to localize the log message.
-     * 
+     *
      * @serial
      */
     private String resourceBundleName;
@@ -148,14 +145,13 @@
      * sequence property is set to a new unique value, allocated in increasing
      * order within the virtual machine. The thread ID is set to a unique value
      * for the current thread. All other properties are set to {@code null}.
-     * 
+     *
      * @param level
      *            the logging level, may not be {@code null}.
      * @param msg
      *            the raw message.
      * @throws NullPointerException
      *             if {@code level} is {@code null}.
-     * @since Android 1.0
      */
     public LogRecord(Level level, String msg) {
         if (null == level) {
@@ -188,9 +184,8 @@
 
     /**
      * Gets the logging level.
-     * 
+     *
      * @return the logging level.
-     * @since Android 1.0
      */
     public Level getLevel() {
         return level;
@@ -198,12 +193,11 @@
 
     /**
      * Sets the logging level.
-     * 
+     *
      * @param level
      *            the level to set.
      * @throws NullPointerException
      *             if {@code level} is {@code null}.
-     * @since Android 1.0
      */
     public void setLevel(Level level) {
         if (null == level) {
@@ -215,9 +209,8 @@
 
     /**
      * Gets the name of the logger.
-     * 
+     *
      * @return the logger name.
-     * @since Android 1.0
      */
     public String getLoggerName() {
         return loggerName;
@@ -225,10 +218,9 @@
 
     /**
      * Sets the name of the logger.
-     * 
+     *
      * @param loggerName
      *            the logger name to set.
-     * @since Android 1.0
      */
     public void setLoggerName(String loggerName) {
         this.loggerName = loggerName;
@@ -236,9 +228,8 @@
 
     /**
      * Gets the raw message.
-     * 
+     *
      * @return the raw message, may be {@code null}.
-     * @since Android 1.0
      */
     public String getMessage() {
         return message;
@@ -248,10 +239,9 @@
      * Sets the raw message. When this record is formatted by a logger that has
      * a localization resource bundle that contains an entry for {@code message},
      * then the raw message is replaced with its localized version.
-     * 
+     *
      * @param message
      *            the raw message to set, may be {@code null}.
-     * @since Android 1.0
      */
     public void setMessage(String message) {
         this.message = message;
@@ -259,9 +249,8 @@
 
     /**
      * Gets the time when this event occurred, in milliseconds since 1970.
-     * 
+     *
      * @return the time when this event occurred, in milliseconds since 1970.
-     * @since Android 1.0
      */
     public long getMillis() {
         return millis;
@@ -269,10 +258,9 @@
 
     /**
      * Sets the time when this event occurred, in milliseconds since 1970.
-     * 
+     *
      * @param millis
      *            the time when this event occurred, in milliseconds since 1970.
-     * @since Android 1.0
      */
     public void setMillis(long millis) {
         this.millis = millis;
@@ -280,10 +268,9 @@
 
     /**
      * Gets the parameters.
-     * 
+     *
      * @return the array of parameters or {@code null} if there are no
      *         parameters.
-     * @since Android 1.0
      */
     public Object[] getParameters() {
         return parameters;
@@ -291,10 +278,9 @@
 
     /**
      * Sets the parameters.
-     * 
+     *
      * @param parameters
      *            the array of parameters to set, may be {@code null}.
-     * @since Android 1.0
      */
     public void setParameters(Object[] parameters) {
         this.parameters = parameters;
@@ -303,21 +289,20 @@
     /**
      * Gets the resource bundle used to localize the raw message during
      * formatting.
-     * 
+     *
      * @return the associated resource bundle, {@code null} if none is
      *         available or the message is not localizable.
-     * @since Android 1.0
      */
     public ResourceBundle getResourceBundle() {
         return resourceBundle;
     }
 
     /**
-     * Sets the resource bundle. 
-     * 
+     * Sets the resource bundle used to localize the raw message during
+     * formatting.
+     *
      * @param resourceBundle
      *            the resource bundle to set, may be {@code null}.
-     * @since Android 1.0            
      */
     public void setResourceBundle(ResourceBundle resourceBundle) {
         this.resourceBundle = resourceBundle;
@@ -325,10 +310,9 @@
 
     /**
      * Gets the name of the resource bundle.
-     * 
+     *
      * @return the name of the resource bundle, {@code null} if none is
      *         available or the message is not localizable.
-     * @since Android 1.0
      */
     public String getResourceBundleName() {
         return resourceBundleName;
@@ -336,10 +320,9 @@
 
     /**
      * Sets the name of the resource bundle.
-     * 
+     *
      * @param resourceBundleName
      *            the name of the resource bundle to set.
-     * @since Android 1.0            
      */
     public void setResourceBundleName(String resourceBundleName) {
         this.resourceBundleName = resourceBundleName;
@@ -347,9 +330,8 @@
 
     /**
      * Gets the sequence number.
-     * 
+     *
      * @return the sequence number.
-     * @since Android 1.0
      */
     public long getSequenceNumber() {
         return sequenceNumber;
@@ -359,10 +341,9 @@
      * Sets the sequence number. It is usually not necessary to call this method
      * to change the sequence number because the number is allocated when this
      * instance is constructed.
-     * 
+     *
      * @param sequenceNumber
      *            the sequence number to set.
-     * @since Android 1.0
      */
     public void setSequenceNumber(long sequenceNumber) {
         this.sequenceNumber = sequenceNumber;
@@ -371,9 +352,8 @@
     /**
      * Gets the name of the class that is the source of this log record. This
      * information can be changed, may be {@code null} and is untrusted.
-     * 
+     *
      * @return the name of the source class of this log record (possiblity {@code null})
-     * @since Android 1.0
      */
     public String getSourceClassName() {
         initSource();
@@ -394,7 +374,8 @@
                     break FINDLOG;
                 }
             }
-            while(++i<elements.length && elements[i].getClassName().equals(current)) {
+            while (++i < elements.length
+                    && elements[i].getClassName().equals(current)) {
                 // do nothing
             }
             if (i < elements.length) {
@@ -407,11 +388,10 @@
 
     /**
      * Sets the name of the class that is the source of this log record.
-     * 
+     *
      * @param sourceClassName
      *            the name of the source class of this log record, may be
      *            {@code null}.
-     * @since Android 1.0
      */
     public void setSourceClassName(String sourceClassName) {
         sourceInited = true;
@@ -420,9 +400,8 @@
 
     /**
      * Gets the name of the method that is the source of this log record.
-     * 
+     *
      * @return the name of the source method of this log record.
-     * @since Android 1.0
      */
     public String getSourceMethodName() {
         initSource();
@@ -431,11 +410,10 @@
 
     /**
      * Sets the name of the method that is the source of this log record.
-     * 
+     *
      * @param sourceMethodName
      *            the name of the source method of this log record, may be
      *            {@code null}.
-     * @since Android 1.0
      */
     public void setSourceMethodName(String sourceMethodName) {
         sourceInited = true;
@@ -448,9 +426,8 @@
      * <p>
      * Notice : the ID doesn't necessary map the OS thread ID
      * </p>
-     * 
+     *
      * @return the ID of the thread originating this log record.
-     * @since Android 1.0
      */
     public int getThreadID() {
         return threadID;
@@ -458,10 +435,9 @@
 
     /**
      * Sets the ID of the thread originating this log record.
-     * 
+     *
      * @param threadID
      *            the new ID of the thread originating this log record.
-     * @since Android 1.0
      */
     public void setThreadID(int threadID) {
         this.threadID = threadID;
@@ -469,9 +445,8 @@
 
     /**
      * Gets the {@code Throwable} object associated with this log record.
-     * 
+     *
      * @return the {@code Throwable} object associated with this log record.
-     * @since Android 1.0
      */
     public Throwable getThrown() {
         return thrown;
@@ -479,11 +454,10 @@
 
     /**
      * Sets the {@code Throwable} object associated with this log record.
-     * 
+     *
      * @param thrown
      *            the new {@code Throwable} object to associate with this log
      *            record.
-     * @since Android 1.0
      */
     public void setThrown(Throwable thrown) {
         this.thrown = thrown;
@@ -514,12 +488,13 @@
         in.defaultReadObject();
         byte major = in.readByte();
         byte minor = in.readByte();
-        //only check MAJOR version
+        // only check MAJOR version
         if (major != MAJOR) {
             // logging.5=Different version - {0}.{1}
-            throw new IOException(Messages.getString("logging.5", major, minor)); //$NON-NLS-1$ 
+            throw new IOException(Messages.getString("logging.5", //$NON-NLS-1$
+                    Byte.valueOf(major), Byte.valueOf(minor)));
         }
-        
+
         int length = in.readInt();
         if (length >= 0) {
             parameters = new Object[length];
diff --git a/libcore/logging/src/main/java/java/util/logging/Logger.java b/libcore/logging/src/main/java/java/util/logging/Logger.java
index cd88ca0..fe124d3 100644
--- a/libcore/logging/src/main/java/java/util/logging/Logger.java
+++ b/libcore/logging/src/main/java/java/util/logging/Logger.java
@@ -24,7 +24,6 @@
 import java.util.Locale;
 import java.util.MissingResourceException;
 import java.util.ResourceBundle;
-import java.util.StringTokenizer;
 
 import org.apache.harmony.logging.internal.nls.Messages;
 
@@ -39,7 +38,6 @@
  * namespace hierarchy managed by a log manager. The naming convention is
  * usually the same as java package's naming convention, that is using
  * dot-separated strings. Anonymous loggers do not belong to any namespace.
- * </p>
  * <p>
  * Loggers "inherit" log level setting from their parent if their own level is
  * set to {@code null}. This is also true for the resource bundle. The logger's
@@ -49,36 +47,28 @@
  * context, "inherit" only means that "behavior" is inherited. The internal
  * field values will not change, for example, {@code getLevel()} still returns
  * {@code null}.
- * </p>
  * <p>
  * When loading a given resource bundle, the logger first tries to use the
  * context classloader. If that fails, it tries the system classloader. And if
  * that still fails, it searches up the class stack and uses each class's
  * classloader to try to locate the resource bundle.
- * </p>
  * <p>
  * Some log methods accept log requests that do not specify the source class and
  * source method. In these cases, the logging framework will automatically infer
  * the calling class and method, but this is not guaranteed to be accurate.
- * </p>
  * <p>
  * Once a {@code LogRecord} object has been passed into the logging framework,
  * it is owned by the logging framework and the client applications should not
  * use it any longer.
- * </p>
  * <p>
  * All methods of this class are thread-safe.
- * </p>
- * 
+ *
  * @see LogManager
- * @since Android 1.0
  */
 public class Logger {
 
     /**
      * The global logger is provided as convenience for casual use.
-     * 
-     * @since Android 1.0
      */
     public final static Logger global = new Logger("global", null); //$NON-NLS-1$
 
@@ -116,27 +106,19 @@
     private boolean isNamed;
 
     private List<Logger> childs;
-    
+
     private LogManager manager;
 
     // BEGIN android-changed
     private volatile boolean handlerInited;
     // END android-changed
 
-
-    /*
-     * -------------------------------------------------------------------
-     * Constructors
-     * -------------------------------------------------------------------
-     */
-
     /**
      * Constructs a {@code Logger} object with the supplied name and resource
      * bundle name; {@code notifiyParentHandlers} is set to {@code true}.
      * <p>
-     * Notice : Loggers use a naming hierarchy. Thus "z.x.y" is a child of "z.x". 
-     * </p>
-     * 
+     * Notice : Loggers use a naming hierarchy. Thus "z.x.y" is a child of "z.x".
+     *
      * @param name
      *            the name of this logger, may be {@code null} for anonymous
      *            loggers.
@@ -145,7 +127,6 @@
      *            messages, may be {@code null}.
      * @throws MissingResourceException
      *             if the specified resource bundle can not be loaded.
-     * @since Android 1.0
      */
     protected Logger(String name, String resourceBundleName) {
         // try to load the specified resource bundle first
@@ -164,24 +145,24 @@
         // any logger is not anonymous by default
         this.isNamed = true;
 
-        //-- 'null' means that level will be inherited from parent (see getLevel)
-        //-- Level.INFO is default level if we don't set it. It will be
-        //-- changed to parent level or to configLevel after adding to the
-        //-- family tree. As of this, actually, setting to Level.INFO is
-        //-- not needed here.
+        // -- 'null' means that level will be inherited from parent (see
+        // getLevel)
+        // -- Level.INFO is default level if we don't set it. It will be
+        // -- changed to parent level or to configLevel after adding to the
+        // -- family tree. As of this, actually, setting to Level.INFO is
+        // -- not needed here.
         this.levelObjVal = null;
         this.levelIntVal = Level.INFO.intValue();
     }
 
-    //-- should be called under the lm lock
+    // -- should be called under the lm lock
     private void setLevelImpl(Level newLevel) {
         // update levels for the whole hierarchy
         int oldVal = levelIntVal;
         levelObjVal = newLevel;
         if (null == newLevel) {
-            levelIntVal = null != parent
-                    ? parent.levelIntVal
-                    : Level.INFO.intValue();
+            levelIntVal = null != parent ? parent.levelIntVal : Level.INFO
+                    .intValue();
         } else {
             levelIntVal = newLevel.intValue();
         }
@@ -190,7 +171,7 @@
         }
     }
 
-    //-- should be called under the lm lock
+    // -- should be called under the lm lock
     private void forceChildsToInherit() {
         for (Logger child : childs) {
             if (null == child.levelObjVal) { // should inherit
@@ -199,15 +180,9 @@
         }
     }
 
-    /*
-     * -------------------------------------------------------------------
-     * Methods
-     * -------------------------------------------------------------------
-     */
-
     /**
      * Load the specified resource bundle, use privileged code.
-     * 
+     *
      * @param resourceBundleName
      *            the name of the resource bundle to load, cannot be {@code null}.
      * @return the loaded resource bundle.
@@ -216,8 +191,8 @@
      */
     static ResourceBundle loadResourceBundle(String resourceBundleName) {
         // try context class loader to load the resource
-        ClassLoader cl = AccessController.doPrivileged(
-                new PrivilegedAction<ClassLoader>() {
+        ClassLoader cl = AccessController
+                .doPrivileged(new PrivilegedAction<ClassLoader>() {
                     public ClassLoader run() {
                         return Thread.currentThread().getContextClassLoader();
                     }
@@ -231,12 +206,11 @@
             }
         }
         // try system class loader to load the resource
-        cl = AccessController.doPrivileged(
-                new PrivilegedAction<ClassLoader>() {
-                    public ClassLoader run() {
-                        return ClassLoader.getSystemClassLoader();
-                    }
-                });
+        cl = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+            public ClassLoader run() {
+                return ClassLoader.getSystemClassLoader();
+            }
+        });
         if (null != cl) {
             try {
                 return ResourceBundle.getBundle(resourceBundleName, Locale
@@ -257,8 +231,8 @@
         for (int i = 1; i < classes.length; i++) {
             final int index = i;
             try {
-                cl = AccessController.doPrivileged(
-                        new PrivilegedAction<ClassLoader>() {
+                cl = AccessController
+                        .doPrivileged(new PrivilegedAction<ClassLoader>() {
                             public ClassLoader run() {
                                 return classes[index].getClassLoader();
                             }
@@ -274,7 +248,7 @@
         }
         // logging.8=Failed to load the specified resource bundle "{0}".
         throw new MissingResourceException(Messages.getString("logging.8", //$NON-NLS-1$
-                resourceBundleName), resourceBundleName, null);  
+                resourceBundleName), resourceBundleName, null);
     }
 
     /**
@@ -284,10 +258,8 @@
      * <p>
      * The anonymous loggers' parent is set to be the root logger. This way it
      * inherits the default logging level and handlers from the root logger.
-     * </p>
-     * 
+     *
      * @return a new instance of anonymous logger.
-     * @since Android 1.0
      */
     public static Logger getAnonymousLogger() {
         return getAnonymousLogger(null);
@@ -300,14 +272,12 @@
      * <p>
      * The anonymous loggers' parent is set to be the root logger. This way it
      * inherits default logging level and handlers from the root logger.
-     * </p>
-     * 
+     *
      * @param resourceBundleName
      *            the name of the resource bundle used to localize log messages.
      * @return a new instance of anonymous logger.
      * @throws MissingResourceException
      *             if the specified resource bundle can not be loaded.
-     * @since Android 1.0
      */
     public static Logger getAnonymousLogger(String resourceBundleName) {
         final Logger l = new Logger(null, resourceBundleName);
@@ -324,26 +294,24 @@
     private static void updateResourceBundle(Logger l, String resourceBundleName) {
         synchronized (l) {
             if (null == l.getResourceBundleName()) {
-                if(null == resourceBundleName){
+                if (null == resourceBundleName) {
                     return;
                 }
                 /*
-                 * load the resource bundle if none is specified
-                 * before
+                 * load the resource bundle if none is specified before
                  */
                 l.resBundle = loadResourceBundle(resourceBundleName);
                 l.resBundleName = resourceBundleName;
             } else if (!l.getResourceBundleName().equals(resourceBundleName)) {
                 /*
-                 * throw exception if the specified resource bundles
-                 * are inconsistent with each other, i.e., different
-                 * names
+                 * throw exception if the specified resource bundles are
+                 * inconsistent with each other, i.e., different names
                  */
-                // logging.9=The specified resource bundle name "{0}" is 
+                // logging.9=The specified resource bundle name "{0}" is
                 // inconsistent with the existing one "{1}".
                 throw new IllegalArgumentException(Messages.getString(
                         "logging.9", //$NON-NLS-1$
-                        resourceBundleName, l.getResourceBundleName())); 
+                        resourceBundleName, l.getResourceBundleName()));
             }
         }
     }
@@ -378,11 +346,12 @@
      * Gets a named logger. The returned logger may already exist or may be
      * newly created. In the latter case, its level will be set to the
      * configured level according to the {@code LogManager}'s properties.
-     * 
+     *
      * @param name
      *            the name of the logger to get, cannot be {@code null}.
      * @return a named logger.
-     * @since Android 1.0
+     * @throws MissingResourceException
+     *             If the specified resource bundle can not be loaded.
      */
     public static Logger getLogger(String name) {
         return getLoggerWithRes(name, null, false);
@@ -391,7 +360,7 @@
     /**
      * Gets a named logger associated with the supplied resource bundle. The
      * resource bundle will be used to localize logging messages.
-     * 
+     *
      * @param name
      *            the name of the logger to get, cannot be {@code null}.
      * @param resourceBundleName
@@ -403,7 +372,6 @@
      * @throws MissingResourceException
      *             if the name of the resource bundle cannot be found.
      * @return a named logger.
-     * @since Android 1.0
      */
     public static Logger getLogger(String name, String resourceBundleName) {
         return getLoggerWithRes(name, resourceBundleName, true);
@@ -412,13 +380,12 @@
     /**
      * Adds a handler to this logger. The {@code name} will be fed with log
      * records received by this logger.
-     * 
+     *
      * @param handler
      *            the handler object to add, cannot be {@code null}.
      * @throws SecurityException
      *             if a security manager determines that the caller does not
      *             have the required permission.
-     * @since Android 1.0
      */
     public void addHandler(Handler handler) {
         if (null == handler) {
@@ -430,25 +397,25 @@
             LogManager.getLogManager().checkAccess();
         }
         initHandler();
-        synchronized(this){
+        synchronized (this) {
             this.handlers.add(handler);
         }
     }
-    
+
     /*
-     * Be cautious to avoid deadlock when using this method, it gets lock on manager 
-     * at first, and then gets lock on this Logger, so any methods should not hold 
-     * lock on this Logger when invoking this method. 
+     * Be cautious to avoid deadlock when using this method, it gets lock on manager
+     * at first, and then gets lock on this Logger, so any methods should not hold
+     * lock on this Logger when invoking this method.
      */
     private void initHandler() {
-        if(!handlerInited){
+        if (!handlerInited) {
             synchronized (this) {
                 if (!handlerInited) {
                     // BEGIN android-added
                     /*
                      * Force LogManager to be initialized, since its
                      * class init code performs necessary one-time setup.
-                     */ 
+                     */
                     LogManager.getLogManager();
                     // END android-added
                     if (handlers == null) {
@@ -463,26 +430,27 @@
                     if (null == handlerStr) {
                         return;
                     }
-                    StringTokenizer st = new StringTokenizer(handlerStr, " "); //$NON-NLS-1$
-                    while (st.hasMoreTokens()) {
-                        String handlerName = st.nextToken();
-                        // BEGIN android-changed
-                        // deal with non-existing handler
-                        try {
-                            Handler handler = (Handler) LogManager
-                                    .getInstanceByClass(handlerName);
-                            handlers.add(handler);
-                            String level = manager.getProperty(handlerName
-                                    + ".level"); //$NON-NLS-1$
-                            if (null != level) {
-                                handler.setLevel(Level.parse(level));
-                            }
-                        } catch (Exception ex) {
-                            ex.printStackTrace();
-                        }
-                        // END android-changed
+                  String[] strs = handlerStr.split(",|\\s"); //$NON-NLS-1$
+                  for (int i = 0; i < strs.length; i++) {
+                    String handlerName = strs[i];
+                    if (handlerName.equals("")) { //$NON-NLS-1$
+                      continue;
                     }
-                    handlerInited = true;
+                    // BEGIN android-changed
+                    // deal with non-existing handler
+                    try {
+                      Handler handler = (Handler) LogManager.getInstanceByClass(handlerName);
+                      handlers.add(handler);
+                      String level = manager.getProperty(handlerName + ".level"); //$NON-NLS-1$
+                      if (null != level) {
+                        handler.setLevel(Level.parse(level));
+                      }
+                    } catch (Exception ex) {
+                      ex.printStackTrace();
+                    }
+                    // END android-changed
+                  }
+                  handlerInited = true;
                 }
             }
         }
@@ -490,13 +458,12 @@
 
     /**
      * Gets all the handlers associated with this logger.
-     * 
+     *
      * @return an array of all the handlers associated with this logger.
-     * @since Android 1.0
      */
     public Handler[] getHandlers() {
         initHandler();
-        synchronized(this){
+        synchronized (this) {
             return handlers.toArray(new Handler[handlers.size()]);
         }
     }
@@ -504,13 +471,12 @@
     /**
      * Removes a handler from this logger. If the specified handler does not
      * exist then this method has no effect.
-     * 
+     *
      * @param handler
      *            the handler to be removed.
      * @throws SecurityException
      *             if a security manager determines that the caller does not
      *             have the required permission.
-     * @since Android 1.0
      */
     public void removeHandler(Handler handler) {
         // Anonymous loggers can always remove handlers
@@ -521,16 +487,15 @@
             return;
         }
         initHandler();
-        synchronized(this){
+        synchronized (this) {
             this.handlers.remove(handler);
         }
     }
 
     /**
      * Gets the filter used by this logger.
-     * 
+     *
      * @return the filter used by this logger, may be {@code null}.
-     * @since Android 1.0
      */
     public Filter getFilter() {
         return this.filter;
@@ -538,13 +503,12 @@
 
     /**
      * Sets the filter used by this logger.
-     * 
+     *
      * @param newFilter
      *            the filter to set, may be {@code null}.
      * @throws SecurityException
      *             if a security manager determines that the caller does not
      *             have the required permission.
-     * @since Android 1.0
      */
     public void setFilter(Filter newFilter) {
         // Anonymous loggers can always set the filter
@@ -557,9 +521,8 @@
     /**
      * Gets the logging level of this logger. A {@code null} level indicates
      * that this logger inherits its parent's level.
-     * 
+     *
      * @return the logging level of this logger.
-     * @since Android 1.0
      */
     public Level getLevel() {
         return levelObjVal;
@@ -568,13 +531,12 @@
     /**
      * Sets the logging level for this logger. A {@code null} level indicates
      * that this logger will inherit its parent's level.
-     * 
+     *
      * @param newLevel
      *            the logging level to set.
      * @throws SecurityException
      *             if a security manager determines that the caller does not
      *             have the required permission.
-     * @since Android 1.0
      */
     public void setLevel(Level newLevel) {
         // Anonymous loggers can always set the level
@@ -590,10 +552,9 @@
      * Gets the flag which indicates whether to use the handlers of this
      * logger's parent to publish incoming log records, potentially recursively
      * up the namespace.
-     * 
+     *
      * @return {@code true} if set to use parent's handlers, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public boolean getUseParentHandlers() {
         return this.notifyParentHandlers;
@@ -602,13 +563,12 @@
     /**
      * Sets the flag which indicates whether to use the handlers of this
      * logger's parent, potentially recursively up the namespace.
-     * 
+     *
      * @param notifyParentHandlers
      *            the new flag indicating whether to use the parent's handlers.
      * @throws SecurityException
      *             if a security manager determines that the caller does not
      *             have the required permission.
-     * @since Android 1.0
      */
     public void setUseParentHandlers(boolean notifyParentHandlers) {
         // Anonymous loggers can always set the useParentHandlers flag
@@ -621,9 +581,8 @@
     /**
      * Gets the nearest parent of this logger in the namespace, a {@code null}
      * value will be returned if called on the root logger.
-     * 
+     *
      * @return the parent of this logger in the namespace.
-     * @since Android 1.0
      */
     public Logger getParent() {
         return parent;
@@ -633,14 +592,14 @@
      * Sets the parent of this logger in the namespace. This method should
      * usually be used by the {@code LogManager} object only. This method does
      * not check security.
-     * 
+     *
      * @param newParent
      *            the parent logger to set.
-     * @since Android 1.0
      */
     void internalSetParent(Logger newParent) {
-        //All hierarchy related modifications should get LogManager lock at first
-        synchronized(LogManager.getLogManager()){
+        // All hierarchy related modifications should get LogManager lock at
+        // first
+        synchronized (LogManager.getLogManager()) {
             parent = newParent;
             // -- update level after setting a parent.
             // -- if level == null we should inherit the parent's level
@@ -654,13 +613,12 @@
     /**
      * Sets the parent of this logger in the namespace. This method should be
      * used by the {@code LogManager} object only.
-     * 
+     *
      * @param parent
      *            the parent logger to set.
      * @throws SecurityException
      *             if a security manager determines that the caller does not
      *             have the required permission.
-     * @since Android 1.0            
      */
     public void setParent(Logger parent) {
         if (null == parent) {
@@ -680,12 +638,10 @@
         childs.remove(child);
     }
 
-
     /**
      * Gets the name of this logger, {@code null} for anonymous loggers.
-     * 
+     *
      * @return the name of this logger.
-     * @since Android 1.0
      */
     public String getName() {
         return this.name;
@@ -695,9 +651,8 @@
      * Gets the loaded resource bundle used by this logger to localize logging
      * messages. If the value is {@code null}, the parent's resource bundle will be
      * inherited.
-     * 
+     *
      * @return the loaded resource bundle used by this logger.
-     * @since Android 1.0
      */
     public ResourceBundle getResourceBundle() {
         return this.resBundle;
@@ -707,9 +662,8 @@
      * Gets the name of the loaded resource bundle used by this logger to
      * localize logging messages. If the value is {@code null}, the parent's resource
      * bundle name will be inherited.
-     * 
+     *
      * @return the name of the loaded resource bundle used by this logger.
-     * @since Android 1.0
      */
     public String getResourceBundleName() {
         return this.resBundleName;
@@ -734,12 +688,11 @@
      * Determines whether this logger will actually log messages of the
      * specified level. The effective level used to do the determination may be
      * inherited from its parent. The default level is {@code Level.INFO}.
-     * 
+     *
      * @param l
      *            the level to check.
      * @return {@code true} if this logger will actually log this level,
      *         otherwise {@code false}.
-     * @since Android 1.0
      */
     public boolean isLoggable(Level l) {
         return internalIsLoggable(l);
@@ -775,12 +728,11 @@
      * Logs a message indicating that a method has been entered. A log record
      * with log level {@code Level.FINER}, log message "ENTRY", the specified
      * source class name and source method name is submitted for logging.
-     * 
+     *
      * @param sourceClass
      *            the calling class name.
      * @param sourceMethod
      *            the method name.
-     * @since Android 1.0
      */
     public void entering(String sourceClass, String sourceMethod) {
         if (internalIsLoggable(Level.FINER)) {
@@ -798,14 +750,13 @@
      * with log level {@code Level.FINER}, log message "ENTRY", the specified
      * source class name, source method name and one parameter is submitted for
      * logging.
-     * 
+     *
      * @param sourceClass
      *            the source class name.
      * @param sourceMethod
      *            the source method name.
      * @param param
      *            the parameter for the method call.
-     * @since Android 1.0
      */
     public void entering(String sourceClass, String sourceMethod, Object param) {
         if (internalIsLoggable(Level.FINER)) {
@@ -824,14 +775,13 @@
      * with log level {@code Level.FINER}, log message "ENTRY", the specified
      * source class name, source method name and array of parameters is
      * submitted for logging.
-     * 
+     *
      * @param sourceClass
      *            the source class name.
      * @param sourceMethod
      *            the source method name.
      * @param params
      *            an array of parameters for the method call.
-     * @since Android 1.0
      */
     public void entering(String sourceClass, String sourceMethod,
             Object[] params) {
@@ -858,12 +808,11 @@
      * Logs a message indicating that a method is exited. A log record with log
      * level {@code Level.FINER}, log message "RETURN", the specified source
      * class name and source method name is submitted for logging.
-     * 
+     *
      * @param sourceClass
      *            the calling class name.
      * @param sourceMethod
      *            the method name.
-     * @since Android 1.0
      */
     public void exiting(String sourceClass, String sourceMethod) {
         if (internalIsLoggable(Level.FINER)) {
@@ -880,14 +829,13 @@
      * Logs a message indicating that a method is exited. A log record with log
      * level {@code Level.FINER}, log message "RETURN", the specified source
      * class name, source method name and return value is submitted for logging.
-     * 
+     *
      * @param sourceClass
      *            the source class name.
      * @param sourceMethod
      *            the source method name.
      * @param result
      *            the return value of the method call.
-     * @since Android 1.0
      */
     public void exiting(String sourceClass, String sourceMethod, Object result) {
         if (internalIsLoggable(Level.FINER)) {
@@ -906,14 +854,13 @@
      * log level {@code Level.FINER}, log message "THROW", the specified source
      * class name, source method name and the {@code Throwable} object is
      * submitted for logging.
-     * 
+     *
      * @param sourceClass
      *            the source class name.
      * @param sourceMethod
      *            the source method name.
      * @param thrown
      *            the {@code Throwable} object.
-     * @since Android 1.0
      */
     public void throwing(String sourceClass, String sourceMethod,
             Throwable thrown) {
@@ -931,10 +878,9 @@
     /**
      * Logs a message of level {@code Level.SEVERE}; the message is transmitted
      * to all subscribed handlers.
-     * 
+     *
      * @param msg
      *            the message to log.
-     * @since Android 1.0
      */
     public void severe(String msg) {
         if (internalIsLoggable(Level.SEVERE)) {
@@ -948,10 +894,9 @@
     /**
      * Logs a message of level {@code Level.WARNING}; the message is
      * transmitted to all subscribed handlers.
-     * 
+     *
      * @param msg
      *            the message to log.
-     * @since Android 1.0           
      */
     public void warning(String msg) {
         if (internalIsLoggable(Level.WARNING)) {
@@ -965,10 +910,9 @@
     /**
      * Logs a message of level {@code Level.INFO}; the message is transmitted
      * to all subscribed handlers.
-     * 
+     *
      * @param msg
      *            the message to log.
-     * @since Android 1.0           
      */
     public void info(String msg) {
         if (internalIsLoggable(Level.INFO)) {
@@ -982,10 +926,9 @@
     /**
      * Logs a message of level {@code Level.CONFIG}; the message is transmitted
      * to all subscribed handlers.
-     * 
+     *
      * @param msg
      *            the message to log.
-     * @since Android 1.0           
      */
     public void config(String msg) {
         if (internalIsLoggable(Level.CONFIG)) {
@@ -999,10 +942,9 @@
     /**
      * Logs a message of level {@code Level.FINE}; the message is transmitted
      * to all subscribed handlers.
-     * 
+     *
      * @param msg
      *            the message to log.
-     * @since Android 1.0           
      */
     public void fine(String msg) {
         if (internalIsLoggable(Level.FINE)) {
@@ -1016,10 +958,9 @@
     /**
      * Logs a message of level {@code Level.FINER}; the message is transmitted
      * to all subscribed handlers.
-     * 
+     *
      * @param msg
      *            the message to log.
-     * @since Android 1.0           
      */
     public void finer(String msg) {
         if (internalIsLoggable(Level.FINER)) {
@@ -1033,10 +974,9 @@
     /**
      * Logs a message of level {@code Level.FINEST}; the message is transmitted
      * to all subscribed handlers.
-     * 
+     *
      * @param msg
      *            the message to log.
-     * @since Android 1.0
      */
     public void finest(String msg) {
         if (internalIsLoggable(Level.FINEST)) {
@@ -1050,12 +990,11 @@
     /**
      * Logs a message of the specified level. The message is transmitted to all
      * subscribed handlers.
-     * 
+     *
      * @param logLevel
      *            the level of the specified message.
      * @param msg
      *            the message to log.
-     * @since Android 1.0
      */
     public void log(Level logLevel, String msg) {
         if (internalIsLoggable(logLevel)) {
@@ -1069,14 +1008,13 @@
     /**
      * Logs a message of the specified level with the supplied parameter. The
      * message is then transmitted to all subscribed handlers.
-     * 
+     *
      * @param logLevel
      *            the level of the given message.
      * @param msg
      *            the message to log.
      * @param param
      *            the parameter associated with the event that is logged.
-     * @since Android 1.0
      */
     public void log(Level logLevel, String msg, Object param) {
         if (internalIsLoggable(logLevel)) {
@@ -1091,14 +1029,13 @@
     /**
      * Logs a message of the specified level with the supplied parameter array.
      * The message is then transmitted to all subscribed handlers.
-     * 
+     *
      * @param logLevel
      *            the level of the given message
      * @param msg
      *            the message to log.
      * @param params
      *            the parameter array associated with the event that is logged.
-     * @since Android 1.0
      */
     public void log(Level logLevel, String msg, Object[] params) {
         if (internalIsLoggable(logLevel)) {
@@ -1113,7 +1050,7 @@
     /**
      * Logs a message of the specified level with the supplied {@code Throwable}
      * object. The message is then transmitted to all subscribed handlers.
-     * 
+     *
      * @param logLevel
      *            the level of the given message.
      * @param msg
@@ -1121,7 +1058,6 @@
      * @param thrown
      *            the {@code Throwable} object associated with the event that is
      *            logged.
-     * @since Android 1.0
      */
     public void log(Level logLevel, String msg, Throwable thrown) {
         if (internalIsLoggable(logLevel)) {
@@ -1144,10 +1080,9 @@
      * logging action, subclasses of this class can override this method to
      * catch all logging activities.
      * </p>
-     * 
+     *
      * @param record
      *            the log record to be logged.
-     * @since Android 1.0
      */
     public void log(LogRecord record) {
         if (internalIsLoggable(record.getLevel())) {
@@ -1158,8 +1093,7 @@
             }
             initHandler();
             /*
-             * call the handlers of this logger, throw any exception that
-             * occurs
+             * call the handlers of this logger, throw any exception that occurs
              */
             Handler[] allHandlers = getHandlers();
             for (Handler element : allHandlers) {
@@ -1182,7 +1116,7 @@
     /**
      * Logs a message of the given level with the specified source class name
      * and source method name.
-     * 
+     *
      * @param logLevel
      *            the level of the given message.
      * @param sourceClass
@@ -1191,7 +1125,6 @@
      *            the source method name.
      * @param msg
      *            the message to be logged.
-     * @since Android 1.0
      */
     public void logp(Level logLevel, String sourceClass, String sourceMethod,
             String msg) {
@@ -1208,7 +1141,7 @@
     /**
      * Logs a message of the given level with the specified source class name,
      * source method name and parameter.
-     * 
+     *
      * @param logLevel
      *            the level of the given message
      * @param sourceClass
@@ -1219,7 +1152,6 @@
      *            the message to be logged
      * @param param
      *            the parameter associated with the event that is logged.
-     * @since Android 1.0
      */
     public void logp(Level logLevel, String sourceClass, String sourceMethod,
             String msg, Object param) {
@@ -1237,7 +1169,7 @@
     /**
      * Logs a message of the given level with the specified source class name,
      * source method name and parameter array.
-     * 
+     *
      * @param logLevel
      *            the level of the given message.
      * @param sourceClass
@@ -1248,7 +1180,6 @@
      *            the message to be logged.
      * @param params
      *            the parameter array associated with the event that is logged.
-     * @since Android 1.0
      */
     public void logp(Level logLevel, String sourceClass, String sourceMethod,
             String msg, Object[] params) {
@@ -1266,7 +1197,7 @@
     /**
      * Logs a message of the given level with the specified source class name,
      * source method name and {@code Throwable} object.
-     * 
+     *
      * @param logLevel
      *            the level of the given message.
      * @param sourceClass
@@ -1277,7 +1208,6 @@
      *            the message to be logged.
      * @param thrown
      *            the {@code Throwable} object.
-     * @since Android 1.0
      */
     public void logp(Level logLevel, String sourceClass, String sourceMethod,
             String msg, Throwable thrown) {
@@ -1297,7 +1227,7 @@
      * and source method name, using the given resource bundle to localize the
      * message. If {@code bundleName} is null, the empty string or not valid then
      * the message is not localized.
-     * 
+     *
      * @param logLevel
      *            the level of the given message.
      * @param sourceClass
@@ -1308,7 +1238,6 @@
      *            the name of the resource bundle used to localize the message.
      * @param msg
      *            the message to be logged.
-     * @since Android 1.0
      */
     public void logrb(Level logLevel, String sourceClass, String sourceMethod,
             String bundleName, String msg) {
@@ -1334,7 +1263,7 @@
      * source method name and parameter, using the given resource bundle to
      * localize the message. If {@code bundleName} is null, the empty string
      * or not valid then the message is not localized.
-     * 
+     *
      * @param logLevel
      *            the level of the given message.
      * @param sourceClass
@@ -1347,7 +1276,6 @@
      *            the message to be logged.
      * @param param
      *            the parameter associated with the event that is logged.
-     * @since Android 1.0
      */
     public void logrb(Level logLevel, String sourceClass, String sourceMethod,
             String bundleName, String msg, Object param) {
@@ -1374,7 +1302,7 @@
      * source method name and parameter array, using the given resource bundle
      * to localize the message. If {@code bundleName} is null, the empty string
      * or not valid then the message is not localized.
-     * 
+     *
      * @param logLevel
      *            the level of the given message.
      * @param sourceClass
@@ -1387,7 +1315,6 @@
      *            the message to be logged.
      * @param params
      *            the parameter array associated with the event that is logged.
-     * @since Android 1.0
      */
     public void logrb(Level logLevel, String sourceClass, String sourceMethod,
             String bundleName, String msg, Object[] params) {
@@ -1414,7 +1341,7 @@
      * source method name and {@code Throwable} object, using the given resource
      * bundle to localize the message. If {@code bundleName} is null, the empty
      * string or not valid then the message is not localized.
-     * 
+     *
      * @param logLevel
      *            the level of the given message
      * @param sourceClass
@@ -1427,7 +1354,6 @@
      *            the message to be logged.
      * @param thrown
      *            the {@code Throwable} object.
-     * @since Android 1.0
      */
     public void logrb(Level logLevel, String sourceClass, String sourceMethod,
             String bundleName, String msg, Throwable thrown) {
@@ -1459,25 +1385,30 @@
     }
 
     void setManager(LogManager manager) {
-        if(this.manager != manager){
+        if (this.manager != manager) {
             this.manager = manager;
-            handlerInited  = false;
+            handlerInited = false;
         }
-        //init level here, but let handlers be for lazy loading
-        String configedLevel = manager.getProperty(name+ ".level"); //$NON-NLS-1$
+        // init level here, but let handlers be for lazy loading
+        final String configedLevel = manager.getProperty(name + ".level"); //$NON-NLS-1$
         if (null != configedLevel) {
             try {
-                setLevel(Level.parse(configedLevel));
+                AccessController.doPrivileged(new PrivilegedAction<Object>() {
+                    public Object run() {
+                        setLevel(Level.parse(configedLevel));
+                        return null;
+                    }
+                });
             } catch (IllegalArgumentException e) {
-                //ignore
+                // ignore
             }
-        }        
+        }
     }
 
     synchronized void reset() {
         levelObjVal = null;
         levelIntVal = Level.INFO.intValue();
-        if(handlers != null){
+        if (handlers != null) {
             for (Handler element : handlers) {
                 // close all handlers, when unknown exceptions happen,
                 // ignore them and go on
@@ -1492,4 +1423,3 @@
         handlerInited = false;
     }
 }
-
diff --git a/libcore/logging/src/main/java/java/util/logging/LoggingMXBean.java b/libcore/logging/src/main/java/java/util/logging/LoggingMXBean.java
index f6b49a6..18cc4cc 100644
--- a/libcore/logging/src/main/java/java/util/logging/LoggingMXBean.java
+++ b/libcore/logging/src/main/java/java/util/logging/LoggingMXBean.java
@@ -25,29 +25,28 @@
  * The ObjectName for identifying the {@code LoggingMXBean} in a bean server is
  * {@link LogManager#LOGGING_MXBEAN_NAME}.
  * </p>
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public interface LoggingMXBean {
+
     /**
      * Gets the string value of the logging level of a logger. An empty string
      * is returned when the logger's level is defined by its parent. A
      * {@code null} is returned if the specified logger does not exist.
-     * 
+     *
      * @param loggerName
      *            the name of the logger lookup.
      * @return a {@code String} if the logger is found, otherwise {@code null}.
      * @see Level#getName()
-     * @since Android 1.0
      */
     String getLoggerLevel(String loggerName);
 
     /**
      * Gets a list of all currently registered logger names. This is performed
      * using the {@link LogManager#getLoggerNames()}.
-     * 
+     *
      * @return a list of logger names.
-     * @since Android 1.0
      */
     List<String> getLoggerNames();
 
@@ -55,18 +54,17 @@
      * Gets the name of the parent logger of a logger. If the logger doesn't
      * exist then {@code null} is returned. If the logger is the root logger,
      * then an empty {@code String} is returned.
-     * 
+     *
      * @param loggerName
      *            the name of the logger to lookup.
      * @return a {@code String} if the logger was found, otherwise {@code null}.
-     * @since Android 1.0
      */
     String getParentLoggerName(String loggerName);
 
     /**
      * Sets the log level of a logger. LevelName set to {@code null} means the
      * level is inherited from the nearest non-null ancestor.
-     * 
+     *
      * @param loggerName
      *            the name of the logger to set the level on, which must not be
      *            {@code null}.
@@ -79,7 +77,6 @@
      *             if a security manager exists and the caller doesn't have
      *             LoggingPermission("control").
      * @see Level#parse(String)
-     * @since Android 1.0
      */
     void setLoggerLevel(String loggerName, String levelName);
 }
diff --git a/libcore/logging/src/main/java/java/util/logging/LoggingPermission.java b/libcore/logging/src/main/java/java/util/logging/LoggingPermission.java
index fb6d4f8..aa41a2c 100644
--- a/libcore/logging/src/main/java/java/util/logging/LoggingPermission.java
+++ b/libcore/logging/src/main/java/java/util/logging/LoggingPermission.java
@@ -15,7 +15,6 @@
  * limitations under the License.
  */
 
-
 package java.util.logging;
 
 import java.io.Serializable;
@@ -27,20 +26,12 @@
 /**
  * The permission required to control the logging when run with a
  * {@code SecurityManager}.
- * 
  */
 public final class LoggingPermission extends BasicPermission implements Guard,
         Serializable {
 
-    //for serialization compatibility with J2SE 1.4.2
-    private static final long serialVersionUID =63564341580231582L;
-    
-    
-    /*
-     * -------------------------------------------------------------------
-     * Constructors
-     * -------------------------------------------------------------------
-     */
+    // for serialization compatibility with J2SE 1.4.2
+    private static final long serialVersionUID = 63564341580231582L;
 
     /**
      * Constructs a {@code LoggingPermission} object required to control the
@@ -50,7 +41,7 @@
      * and depends on the security policy file, therefore programmers shouldn't
      * normally use them directly.
      * </p>
-     * 
+     *
      * @param name
      *            currently must be "control".
      * @param actions
@@ -71,4 +62,3 @@
     }
 
 }
-
diff --git a/libcore/logging/src/main/java/java/util/logging/MemoryHandler.java b/libcore/logging/src/main/java/java/util/logging/MemoryHandler.java
index c1e8670..3312083 100644
--- a/libcore/logging/src/main/java/java/util/logging/MemoryHandler.java
+++ b/libcore/logging/src/main/java/java/util/logging/MemoryHandler.java
@@ -22,7 +22,6 @@
 
 import org.apache.harmony.logging.internal.nls.Messages;
 
-
 /**
  * A {@code Handler} put the description of log events into a cycled memory
  * buffer.
@@ -30,68 +29,61 @@
  * Mostly this {@code MemoryHandler} just puts the given {@code LogRecord} into
  * the internal buffer and doesn't perform any formatting or any other process.
  * When the buffer is full, the earliest buffered records will be discarded.
- * </p>
  * <p>
  * Every {@code MemoryHandler} has a target handler, and push action can be
  * triggered so that all buffered records will be output to the target handler
  * and normally the latter will publish the records. After the push action, the
  * buffer will be cleared.
- * </p>
  * <p>
- * The push action can be triggered in three ways:
- * <ul>
- * <li>The push method is called explicitly</li>
- * <li>When a new {@code LogRecord} is put into the internal buffer, and it has
- * a level which is not less than the specified push level.</li>
- * <li>A subclass extends this {@code MemoryHandler} and call push method
- * implicitly according to some criteria.</li>
- * </ul>
- * </p>
+ * The push method can be called directly, but will also be called automatically
+ * if a new <code>LogRecord</code> is added that has a level greater than or
+ * equal to than the value defined for the property
+ * java.util.logging.MemoryHandler.push.
  * <p>
  * {@code MemoryHandler} will read following {@code LogManager} properties for
  * initialization, if given properties are not defined or has invalid values,
  * default value will be used.
  * <ul>
- * <li>java.util.logging.MemoryHandler.level specifies the level for this
- * {@code Handler}, defaults to {@code Level.ALL}.</li>
  * <li>java.util.logging.MemoryHandler.filter specifies the {@code Filter}
  * class name, defaults to no {@code Filter}.</li>
- * <li>java.util.logging.MemoryHandler.size specifies the buffer size in number
- * of {@code LogRecord}, defaults to 1000.</li>
+ * <li>java.util.logging.MemoryHandler.level specifies the level for this
+ * {@code Handler}, defaults to {@code Level.ALL}.</li>
  * <li>java.util.logging.MemoryHandler.push specifies the push level, defaults
  * to level.SEVERE.</li>
+ * <li>java.util.logging.MemoryHandler.size specifies the buffer size in number
+ * of {@code LogRecord}, defaults to 1000.</li>
  * <li>java.util.logging.MemoryHandler.target specifies the class of the target
  * {@code Handler}, no default value, which means this property must be
  * specified either by property setting or by constructor.</li>
  * </ul>
- * </p>
  */
 public class MemoryHandler extends Handler {
 
-    //default maximum buffered number of LogRecord 
+    // default maximum buffered number of LogRecord
     private static final int DEFAULT_SIZE = 1000;
-    //target handler
+
+    // target handler
     private Handler target;
-    
-    //buffer size
+
+    // buffer size
     private int size = DEFAULT_SIZE;
-    
-    //push level
+
+    // push level
     private Level push = Level.SEVERE;
 
-    //LogManager instance for convenience
+    // LogManager instance for convenience
     private final LogManager manager = LogManager.getLogManager();
-    
-    //buffer
+
+    // buffer
     private LogRecord[] buffer;
-    
-    //current position in buffer
+
+    // current position in buffer
     private int cursor;
-    
+
     /**
      * Default constructor, construct and init a {@code MemoryHandler} using
      * {@code LogManager} properties or default values.
-     * 
+     *
      * @throws RuntimeException
      *             if property value are invalid and no default value could be
      *             used.
@@ -99,55 +91,57 @@
     public MemoryHandler() {
         super();
         String className = this.getClass().getName();
-        //init target
-        final String targetName = manager.getProperty(className+".target"); //$NON-NLS-1$
+        // init target
+        final String targetName = manager.getProperty(className + ".target"); //$NON-NLS-1$
         try {
-            Class<?> targetClass = AccessController.doPrivileged(new PrivilegedExceptionAction<Class<?>>(){
-                public Class<?> run() throws Exception{
-                    ClassLoader loader = Thread.currentThread().getContextClassLoader();
-                    if(loader == null){
-                        loader = ClassLoader.getSystemClassLoader();
-                    }
-                    return loader.loadClass(targetName);
-                }
-            });
+            Class<?> targetClass = AccessController
+                    .doPrivileged(new PrivilegedExceptionAction<Class<?>>() {
+                        public Class<?> run() throws Exception {
+                            ClassLoader loader = Thread.currentThread()
+                                    .getContextClassLoader();
+                            if (loader == null) {
+                                loader = ClassLoader.getSystemClassLoader();
+                            }
+                            return loader.loadClass(targetName);
+                        }
+                    });
             target = (Handler) targetClass.newInstance();
         } catch (Exception e) {
             // logging.10=Cannot load target handler:{0}
             throw new RuntimeException(Messages.getString("logging.10", //$NON-NLS-1$
                     targetName));
         }
-        //init size
-        String sizeString = manager.getProperty(className+".size"); //$NON-NLS-1$
+        // init size
+        String sizeString = manager.getProperty(className + ".size"); //$NON-NLS-1$
         if (null != sizeString) {
             try {
                 size = Integer.parseInt(sizeString);
-                if(size <= 0){
+                if (size <= 0) {
                     size = DEFAULT_SIZE;
                 }
             } catch (Exception e) {
-                printInvalidPropMessage(className+".size", sizeString, e); //$NON-NLS-1$
+                printInvalidPropMessage(className + ".size", sizeString, e); //$NON-NLS-1$
             }
         }
-        //init push level
-        String pushName = manager.getProperty(className+".push"); //$NON-NLS-1$
+        // init push level
+        String pushName = manager.getProperty(className + ".push"); //$NON-NLS-1$
         if (null != pushName) {
             try {
                 push = Level.parse(pushName);
             } catch (Exception e) {
-                printInvalidPropMessage(className+".push", pushName, e); //$NON-NLS-1$
+                printInvalidPropMessage(className + ".push", pushName, e); //$NON-NLS-1$
             }
         }
-        //init other properties which are common for all Handler
-        initProperties("ALL", null, "java.util.logging.SimpleFormatter", null);  //$NON-NLS-1$//$NON-NLS-2$
+        // init other properties which are common for all Handler
+        initProperties("ALL", null, "java.util.logging.SimpleFormatter", null); //$NON-NLS-1$//$NON-NLS-2$
         buffer = new LogRecord[size];
     }
-    
+
     /**
      * Construct and init a {@code MemoryHandler} using given target, size and
      * push level, other properties using {@code LogManager} properties or
      * default values.
-     * 
+     *
      * @param target
      *            the given {@code Handler} to output
      * @param size
@@ -156,7 +150,7 @@
      * @param pushLevel
      *            the push level
      * @throws IllegalArgumentException
-     *             if {@code size}<=0
+     *             if {@code size <= 0}
      * @throws RuntimeException
      *             if property value are invalid and no default value could be
      *             used.
@@ -171,13 +165,13 @@
         this.target = target;
         this.size = size;
         this.push = pushLevel;
-        initProperties("ALL", null, "java.util.logging.SimpleFormatter", null);  //$NON-NLS-1$//$NON-NLS-2$
+        initProperties("ALL", null, "java.util.logging.SimpleFormatter", null); //$NON-NLS-1$//$NON-NLS-2$
         buffer = new LogRecord[size];
     }
-    
+
     /**
      * Close this handler and target handler, free all associated resources.
-     * 
+     *
      * @throws SecurityException
      *             if security manager exists and it determines that caller does
      *             not have the required permissions to control this handler.
@@ -204,7 +198,7 @@
      * Furthermore if the record's level is not less than the push level, the
      * push action is triggered to output all the buffered records to the target
      * handler, and the target handler will publish them.
-     * 
+     *
      * @param record
      *            the log record
      */
@@ -225,7 +219,7 @@
 
     /**
      * Return the push level.
-     * 
+     *
      * @return the push level
      */
     public Level getPushLevel() {
@@ -233,18 +227,14 @@
     }
 
     /**
-     * <p>
      * Check if given {@code LogRecord} would be put into this
      * {@code MemoryHandler}'s internal buffer.
-     * </p>
      * <p>
      * The given {@code LogRecord} is loggable if and only if it has appropriate
      * level and it pass any associated filter's check.
-     * </p>
      * <p>
      * Note that the push level is not used for this check.
-     * </p>
-     * 
+     *
      * @param record
      *            the given {@code LogRecord}
      * @return the given {@code LogRecord} if it should be logged, {@code false}
@@ -261,13 +251,13 @@
      */
     public void push() {
         for (int i = cursor; i < size; i++) {
-            if(null != buffer[i]) {
+            if (null != buffer[i]) {
                 target.publish(buffer[i]);
             }
             buffer[i] = null;
         }
         for (int i = 0; i < cursor; i++) {
-            if(null != buffer[i]) {
+            if (null != buffer[i]) {
                 target.publish(buffer[i]);
             }
             buffer[i] = null;
@@ -276,15 +266,15 @@
     }
 
     /**
-     * Set the push level. The push level is used to check the push action 
+     * Set the push level. The push level is used to check the push action
      * triggering. When a new {@code LogRecord} is put into the internal
-     * buffer and its level is not less than the push level, the push action 
+     * buffer and its level is not less than the push level, the push action
      * will be triggered. Note that set new push level won't trigger push action.
-     * 
+     *
      * @param newLevel
      *                 the new level to set.
      * @throws SecurityException
-     *                 if security manager exists and it determines that caller 
+     *                 if security manager exists and it determines that caller
      *                 does not have the required permissions to control this handler.
      */
     public void setPushLevel(Level newLevel) {
diff --git a/libcore/logging/src/main/java/java/util/logging/SimpleFormatter.java b/libcore/logging/src/main/java/java/util/logging/SimpleFormatter.java
index 1595796..def4ad3 100644
--- a/libcore/logging/src/main/java/java/util/logging/SimpleFormatter.java
+++ b/libcore/logging/src/main/java/java/util/logging/SimpleFormatter.java
@@ -15,7 +15,6 @@
  * limitations under the License.
  */
 
-
 package java.util.logging;
 
 import java.io.PrintWriter;
@@ -26,13 +25,10 @@
 /**
  * {@code SimpleFormatter} can be used to print a summary of the information
  * contained in a {@code LogRecord} object in a human readable format.
- * @since Android 1.0
  */
 public class SimpleFormatter extends Formatter {
     /**
      * Constructs a new {@code SimpleFormatter}.
-     * 
-     * @since Android 1.0
      */
     public SimpleFormatter() {
         super();
@@ -41,11 +37,10 @@
     /**
      * Converts a {@link LogRecord} object into a human readable string
      * representation.
-     * 
+     *
      * @param r
      *            the log record to be formatted into a string.
      * @return the formatted string.
-     * @since Android 1.0
      */
     @Override
     public String format(LogRecord r) {
@@ -53,7 +48,8 @@
         sb.append(MessageFormat.format("{0, date} {0, time} ", //$NON-NLS-1$
                 new Object[] { new Date(r.getMillis()) }));
         sb.append(r.getSourceClassName()).append(" "); //$NON-NLS-1$
-        sb.append(r.getSourceMethodName()).append(LogManager.getSystemLineSeparator()); //$NON-NLS-1$
+        sb.append(r.getSourceMethodName()).append(
+                LogManager.getSystemLineSeparator());
         sb.append(r.getLevel().getName()).append(": "); //$NON-NLS-1$
         sb.append(formatMessage(r)).append(LogManager.getSystemLineSeparator());
         if (null != r.getThrown()) {
@@ -66,7 +62,7 @@
                 t.printStackTrace(pw);
                 sb.append(sw.toString());
             } finally {
-                if(pw != null){
+                if (pw != null) {
                     try {
                         pw.close();
                     } catch (Exception e) {
@@ -78,4 +74,3 @@
         return sb.toString();
     }
 }
-
diff --git a/libcore/logging/src/main/java/java/util/logging/SocketHandler.java b/libcore/logging/src/main/java/java/util/logging/SocketHandler.java
index 8626007..38cfd64 100644
--- a/libcore/logging/src/main/java/java/util/logging/SocketHandler.java
+++ b/libcore/logging/src/main/java/java/util/logging/SocketHandler.java
@@ -15,12 +15,11 @@
  * limitations under the License.
  */
 
-
 package java.util.logging;
 
-import java.net.Socket;
 import java.io.BufferedOutputStream;
 import java.io.IOException;
+import java.net.Socket;
 
 import org.apache.harmony.logging.internal.nls.Messages;
 
@@ -48,16 +47,14 @@
  * <li>java.util.logging.SocketHandler.encoding specifies the port number that
  * this handler should connect to. There's no default value for this property.
  * </ul>
- * </p>
  * <p>
  * This handler buffers the outgoing messages, but flushes each time a log
  * record has been published.
- * </p>
  * <p>
  * This class is not thread-safe.
- * </p>
  */
 public class SocketHandler extends StreamHandler {
+
     // default level
     private static final String DEFAULT_LEVEL = "ALL"; //$NON-NLS-1$
 
@@ -71,7 +68,7 @@
      * Constructs a {@code SocketHandler} object using the properties read by
      * the log manager, including the host name and port number. Default
      * formatting uses the XMLFormatter class and level is set to ALL.
-     * 
+     *
      * @throws IOException
      *             if failed to connect to the specified host and port.
      * @throws IllegalArgumentException
@@ -92,7 +89,7 @@
      * Constructs a {@code SocketHandler} object using the specified host name
      * and port number together with other properties read by the log manager.
      * Default formatting uses the XMLFormatter class and level is set to ALL.
-     * 
+     *
      * @param host
      *            the host name
      * @param port
@@ -146,7 +143,7 @@
 
     /**
      * Closes this handler. The network connection to the host is also closed.
-     * 
+     *
      * @throws SecurityException
      *             If a security manager determines that the caller does not
      *             have the required permission to control this handler.
@@ -168,7 +165,7 @@
 
     /**
      * Logs a record if necessary. A flush operation will be done afterwards.
-     * 
+     *
      * @param record
      *            the log record to be logged.
      */
@@ -177,5 +174,4 @@
         super.publish(record);
         super.flush();
     }
-
 }
diff --git a/libcore/logging/src/main/java/java/util/logging/StreamHandler.java b/libcore/logging/src/main/java/java/util/logging/StreamHandler.java
index ee12190..7049d45 100644
--- a/libcore/logging/src/main/java/java/util/logging/StreamHandler.java
+++ b/libcore/logging/src/main/java/java/util/logging/StreamHandler.java
@@ -15,7 +15,6 @@
  * limitations under the License.
  */
 
-
 package java.util.logging;
 
 import java.io.OutputStream;
@@ -30,30 +29,26 @@
  * is, objects of the class {@link java.io.OutputStream}.
  * <p>
  * A {@code StreamHandler} object reads the following properties from the log
- * manager to initialize itself:
+ * manager to initialize itself. A default value will be used if a property is
+ * not found or has an invalid value.
  * <ul>
- * <li>java.util.logging.StreamHandler.level specifies the logging level,
- * defaults to {@code Level.INFO} if this property is not found or has an
- * invalid value.
- * <li>java.util.logging.StreamHandler.filter specifies the name of the filter
- * class to be associated with this handler, defaults to {@code null} if this
- * property is not found or has an invalid value.
- * <li>java.util.logging.StreamHandler.formatter specifies the name of the
- * formatter class to be associated with this handler, defaults to
- * {@code java.util.logging.SimpleFormatter} if this property is not found or
- * has an invalid value.
  * <li>java.util.logging.StreamHandler.encoding specifies the encoding this
- * handler will use to encode log messages, defaults to {@code null} if this
- * property is not found or has an invalid value.
+ * handler will use to encode log messages. Default is the encoding used by the
+ * current platform.
+ * <li>java.util.logging.StreamHandler.filter specifies the name of the filter
+ * class to be associated with this handler. No <code>Filter</code> is used by
+ * default.
+ * <li>java.util.logging.StreamHandler.formatter specifies the name of the
+ * formatter class to be associated with this handler. Default is
+ * {@code java.util.logging.SimpleFormatter}.
+ * <li>java.util.logging.StreamHandler.level specifies the logging level.
+ * Defaults is {@code Level.INFO}.
  * </ul>
- * </p>
  * <p>
  * This class is not thread-safe.
- * </p>
- * 
- * @since Android 1.0
  */
 public class StreamHandler extends Handler {
+
     // the output stream this handler writes to
     private OutputStream os;
 
@@ -66,11 +61,9 @@
     /**
      * Constructs a {@code StreamHandler} object. The new stream handler
      * does not have an associated output stream.
-     * 
-     * @since Android 1.0
      */
     public StreamHandler() {
-        initProperties("INFO", null, "java.util.logging.SimpleFormatter",  //$NON-NLS-1$//$NON-NLS-2$
+        initProperties("INFO", null, "java.util.logging.SimpleFormatter", //$NON-NLS-1$//$NON-NLS-2$
                 null);
         this.os = null;
         this.writer = null;
@@ -80,7 +73,7 @@
     /**
      * Constructs a {@code StreamHandler} object with the supplied output
      * stream. Default properties are read.
-     * 
+     *
      * @param os
      *            the output stream this handler writes to.
      */
@@ -106,14 +99,13 @@
     /**
      * Constructs a {@code StreamHandler} object with the supplied output stream
      * and formatter.
-     * 
+     *
      * @param os
      *            the output stream this handler writes to.
      * @param formatter
      *            the formatter this handler uses to format the output.
      * @throws NullPointerException
      *             if {@code os} or {@code formatter} is {@code null}.
-     * @since Android 1.0
      */
     public StreamHandler(OutputStream os, Formatter formatter) {
         this();
@@ -160,7 +152,7 @@
 
     /**
      * Sets the output stream this handler writes to. Note it does nothing else.
-     * 
+     *
      * @param newOs
      *            the new output stream
      */
@@ -168,13 +160,12 @@
         this.os = newOs;
     }
 
-    
     /**
      * Sets the output stream this handler writes to. If there's an existing
      * output stream, the tail string of the associated formatter will be
-     * written to it. Then it will be flushed, closed and replaced with 
+     * written to it. Then it will be flushed, closed and replaced with
      * {@code os}.
-     * 
+     *
      * @param os
      *            the new output stream.
      * @throws SecurityException
@@ -197,7 +188,7 @@
     /**
      * Sets the character encoding used by this handler. A {@code null} value
      * indicates that the default encoding should be used.
-     * 
+     *
      * @param encoding
      *            the character encoding to set.
      * @throws SecurityException
@@ -205,12 +196,11 @@
      *             have the required permission.
      * @throws UnsupportedEncodingException
      *             if the specified encoding is not supported by the runtime.
-     * @since Android 1.0
      */
     @Override
     public void setEncoding(String encoding) throws SecurityException,
             UnsupportedEncodingException {
-        //flush first before set new encoding
+        // flush first before set new encoding
         this.flush();
         super.setEncoding(encoding);
         // renew writer only if the writer exists
@@ -234,7 +224,7 @@
     /**
      * Closes this handler, but the underlying output stream is only closed if
      * {@code closeStream} is {@code true}. Security is not checked.
-     * 
+     *
      * @param closeStream
      *            whether to close the underlying output stream.
      */
@@ -264,11 +254,10 @@
      * this handler is written out. A flush operation and a subsequent close
      * operation is then performed upon the output stream. Client applications
      * should not use a handler after closing it.
-     * 
+     *
      * @throws SecurityException
      *             if a security manager determines that the caller does not
      *             have the required permission.
-     * @since Android 1.0
      */
     @Override
     public void close() {
@@ -278,8 +267,6 @@
 
     /**
      * Flushes any buffered output.
-     * 
-     * @since Android 1.0
      */
     @Override
     public void flush() {
@@ -291,7 +278,8 @@
                     this.os.flush();
                 }
             } catch (Exception e) {
-                // logging.16=Exception occurred while flushing the output stream.
+                // logging.16=Exception occurred while flushing the output
+                // stream.
                 getErrorManager().error(Messages.getString("logging.16"), //$NON-NLS-1$
                         e, ErrorManager.FLUSH_FAILURE);
             }
@@ -309,10 +297,9 @@
      * </ul>
      * If it is the first time a log record is written out, the head string of
      * the formatter associated with this handler is written out first.
-     * 
+     *
      * @param record
      *            the log record to be logged.
-     * @since Android 1.0
      */
     @Override
     public synchronized void publish(LogRecord record) {
@@ -325,7 +312,8 @@
                 try {
                     msg = getFormatter().format(record);
                 } catch (Exception e) {
-                    // logging.17=Exception occurred while formatting the log record.
+                    // logging.17=Exception occurred while formatting the log
+                    // record.
                     getErrorManager().error(Messages.getString("logging.17"), //$NON-NLS-1$
                             e, ErrorManager.FORMAT_FAILURE);
                 }
@@ -345,13 +333,11 @@
      * {@code false}.
      * <p>
      * Notice : Case of no output stream will return {@code false}.
-     * </p>
-     * 
+     *
      * @param record
      *            the log record to be checked.
      * @return {@code true} if {@code record} needs to be logged, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isLoggable(LogRecord record) {
@@ -363,5 +349,4 @@
         }
         return false;
     }
-
 }
diff --git a/libcore/logging/src/main/java/java/util/logging/XMLFormatter.java b/libcore/logging/src/main/java/java/util/logging/XMLFormatter.java
index 6279d8c..ff96813 100644
--- a/libcore/logging/src/main/java/java/util/logging/XMLFormatter.java
+++ b/libcore/logging/src/main/java/java/util/logging/XMLFormatter.java
@@ -15,7 +15,6 @@
  * limitations under the License.
  */
 
-
 package java.util.logging;
 
 import java.security.AccessController;
@@ -30,8 +29,6 @@
  * {@code XMLFormatter} uses the output handler's encoding if it is specified,
  * otherwise the default platform encoding is used instead. UTF-8 is the
  * recommended encoding.
- * 
- * @since Android 1.0
  */
 public class XMLFormatter extends Formatter {
 
@@ -42,8 +39,6 @@
 
     /**
      * Constructs a new {@code XMLFormatter}.
-     * 
-     * @since Android 1.0
      */
     public XMLFormatter() {
         super();
@@ -51,61 +46,63 @@
 
     /**
      * Converts a {@code LogRecord} into an XML string.
-     * 
+     *
      * @param r
      *            the log record to be formatted.
      * @return the log record formatted as an XML string.
-     * @since Android 1.0
      */
+    @SuppressWarnings("nls")
     @Override
     public String format(LogRecord r) {
-        //call a method of LogRecord to ensure not null
+        // call a method of LogRecord to ensure not null
         long time = r.getMillis();
-        //format to date
-        String date = MessageFormat.format("{0, date} {0, time}", //$NON-NLS-1$
+        // format to date
+        String date = MessageFormat.format("{0, date} {0, time}",
                 new Object[] { new Date(time) });
 
         StringBuilder sb = new StringBuilder();
-        sb.append(("<record>")).append(lineSeperator); //$NON-NLS-1$
-        sb.append(indent).append(("<date>")).append(date).append(("</date>")) //$NON-NLS-1$ //$NON-NLS-2$
+        sb.append(("<record>")).append(lineSeperator);
+        sb.append(indent).append(("<date>")).append(date).append(("</date>"))
                 .append(lineSeperator);
-        sb.append(indent).append(("<millis>")).append(time).append( //$NON-NLS-1$
-                ("</millis>")).append(lineSeperator); //$NON-NLS-1$
-        sb.append(indent).append(("<sequence>")).append(r.getSequenceNumber()) //$NON-NLS-1$
-                .append(("</sequence>")).append(lineSeperator); //$NON-NLS-1$
+        sb.append(indent).append(("<millis>")).append(time).append(
+                ("</millis>")).append(lineSeperator);
+        sb.append(indent).append(("<sequence>")).append(r.getSequenceNumber())
+                .append(("</sequence>")).append(lineSeperator);
         if (null != r.getLoggerName()) {
-            sb.append(indent).append(("<logger>")).append(r.getLoggerName()) //$NON-NLS-1$
-                    .append(("</logger>")).append(lineSeperator); //$NON-NLS-1$
+            sb.append(indent).append(("<logger>")).append(r.getLoggerName())
+                    .append(("</logger>")).append(lineSeperator);
         }
-        sb.append(indent).append(("<level>")).append(r.getLevel().getName()) //$NON-NLS-1$
-                .append(("</level>")).append(lineSeperator); //$NON-NLS-1$
+        sb.append(indent).append(("<level>")).append(r.getLevel().getName())
+                .append(("</level>")).append(lineSeperator);
         if (null != r.getSourceClassName()) {
-            sb.append(indent).append(("<class>")) //$NON-NLS-1$
-                    .append(r.getSourceClassName()).append(("</class>")) //$NON-NLS-1$
+            sb.append(indent).append(("<class>"))
+                    .append(r.getSourceClassName()).append(("</class>"))
                     .append(lineSeperator);
         }
         if (null != r.getSourceMethodName()) {
-            sb.append(indent).append(("<method>")).append( //$NON-NLS-1$
-                    r.getSourceMethodName()).append(("</method>")).append( //$NON-NLS-1$
+            sb.append(indent).append(("<method>")).append(
+                    r.getSourceMethodName()).append(("</method>")).append(
                     lineSeperator);
         }
-        sb.append(indent).append(("<thread>")).append(r.getThreadID()).append( //$NON-NLS-1$
-                ("</thread>")).append(lineSeperator); //$NON-NLS-1$
+        sb.append(indent).append(("<thread>")).append(r.getThreadID()).append(
+                ("</thread>")).append(lineSeperator);
         formatMessages(r, sb);
         Object[] params;
         if ((params = r.getParameters()) != null) {
             for (Object element : params) {
-                sb.append(indent).append(("<param>")).append(element).append( //$NON-NLS-1$
-                        ("</param>")).append(lineSeperator); //$NON-NLS-1$
+                sb.append(indent).append(("<param>")).append(element).append(
+                        ("</param>")).append(lineSeperator);
             }
         }
         formatThrowable(r, sb);
-        sb.append(("</record>")).append(lineSeperator); //$NON-NLS-1$
+        sb.append(("</record>")).append(lineSeperator);
         return sb.toString();
     }
 
+    @SuppressWarnings("nls")
     private void formatMessages(LogRecord r, StringBuilder sb) {
-        //get localized message if has, but don't call Formatter.formatMessage to parse pattern string
+        // get localized message if has, but don't call Formatter.formatMessage
+        // to parse pattern string
         ResourceBundle rb = r.getResourceBundle();
         String pattern = r.getMessage();
         if (null != rb && null != pattern) {
@@ -118,49 +115,50 @@
 
             if (message == null) {
                 message = pattern;
-                sb.append(indent).append(("<message>")).append(message).append( //$NON-NLS-1$
-                        ("</message>")).append(lineSeperator); //$NON-NLS-1$
+                sb.append(indent).append(("<message>")).append(message).append(
+                        ("</message>")).append(lineSeperator);
             } else {
-                sb.append(indent).append(("<message>")).append(message).append( //$NON-NLS-1$
-                        ("</message>")).append(lineSeperator); //$NON-NLS-1$
-                sb.append(indent).append(("<key>")).append(pattern).append( //$NON-NLS-1$
-                        ("</key>")).append(lineSeperator); //$NON-NLS-1$
-                sb.append(indent).append(("<catalog>")).append( //$NON-NLS-1$
-                        r.getResourceBundleName()).append(("</catalog>")) //$NON-NLS-1$
+                sb.append(indent).append(("<message>")).append(message).append(
+                        ("</message>")).append(lineSeperator);
+                sb.append(indent).append(("<key>")).append(pattern).append(
+                        ("</key>")).append(lineSeperator);
+                sb.append(indent).append(("<catalog>")).append(
+                        r.getResourceBundleName()).append(("</catalog>"))
                         .append(lineSeperator);
             }
-        } else if(null != pattern){
-            sb.append(indent).append(("<message>")).append(pattern).append( //$NON-NLS-1$
-                    ("</message>")).append(lineSeperator); //$NON-NLS-1$
-        } else{
-            sb.append(indent).append(("<message/>")); //$NON-NLS-1$
+        } else if (null != pattern) {
+            sb.append(indent).append(("<message>")).append(pattern).append(
+                    ("</message>")).append(lineSeperator);
+        } else {
+            sb.append(indent).append(("<message/>"));
         }
     }
 
+    @SuppressWarnings("nls")
     private void formatThrowable(LogRecord r, StringBuilder sb) {
         Throwable t;
         if ((t = r.getThrown()) != null) {
-            sb.append(indent).append("<exception>").append(lineSeperator); //$NON-NLS-1$
-            sb.append(indent).append(indent).append("<message>").append( //$NON-NLS-1$
-                    t.toString()).append("</message>").append(lineSeperator); //$NON-NLS-1$
-            //format throwable's stack trace
+            sb.append(indent).append("<exception>").append(lineSeperator);
+            sb.append(indent).append(indent).append("<message>").append(
+                    t.toString()).append("</message>").append(lineSeperator);
+            // format throwable's stack trace
             StackTraceElement[] elements = t.getStackTrace();
             for (StackTraceElement e : elements) {
-                sb.append(indent).append(indent).append("<frame>").append( //$NON-NLS-1$
+                sb.append(indent).append(indent).append("<frame>").append(
                         lineSeperator);
                 sb.append(indent).append(indent).append(indent).append(
-                        "<class>").append(e.getClassName()).append("</class>")  //$NON-NLS-1$//$NON-NLS-2$
+                        "<class>").append(e.getClassName()).append("</class>")
                         .append(lineSeperator);
                 sb.append(indent).append(indent).append(indent).append(
-                        "<method>").append(e.getMethodName()).append( //$NON-NLS-1$
-                        "</method>").append(lineSeperator); //$NON-NLS-1$
+                        "<method>").append(e.getMethodName()).append(
+                        "</method>").append(lineSeperator);
                 sb.append(indent).append(indent).append(indent)
-                        .append("<line>").append(e.getLineNumber()).append( //$NON-NLS-1$
-                                "</line>").append(lineSeperator); //$NON-NLS-1$
-                sb.append(indent).append(indent).append("</frame>").append( //$NON-NLS-1$
+                        .append("<line>").append(e.getLineNumber()).append(
+                                "</line>").append(lineSeperator);
+                sb.append(indent).append(indent).append("</frame>").append(
                         lineSeperator);
             }
-            sb.append(indent).append("</exception>").append(lineSeperator); //$NON-NLS-1$
+            sb.append(indent).append("</exception>").append(lineSeperator);
         }
     }
 
@@ -168,54 +166,48 @@
      * Returns the header string for a set of log records formatted as XML
      * strings, using the output handler's encoding if it is defined, otherwise
      * using the default platform encoding.
-     * 
+     *
      * @param h
      *            the output handler, may be {@code null}.
      * @return the header string for log records formatted as XML strings.
-     * @since Android 1.0
      */
+    @SuppressWarnings("nls")
     @Override
     public String getHead(Handler h) {
         String encoding = null;
-        if(null != h) {
+        if (null != h) {
             encoding = h.getEncoding();
         }
         if (null == encoding) {
-            encoding = getSystemProperty("file.encoding"); //$NON-NLS-1$
+            encoding = getSystemProperty("file.encoding");
         }
         StringBuilder sb = new StringBuilder();
-        sb.append("<?xml version=\"1.0\" encoding=\"").append(encoding).append( //$NON-NLS-1$
-                "\" standalone=\"no\"?>").append(lineSeperator); //$NON-NLS-1$
-        sb.append("<!DOCTYPE log SYSTEM \"logger.dtd\">").append(lineSeperator); //$NON-NLS-1$
-        sb.append(("<log>")); //$NON-NLS-1$
+        sb.append("<?xml version=\"1.0\" encoding=\"").append(encoding).append(
+                "\" standalone=\"no\"?>").append(lineSeperator);
+        sb.append("<!DOCTYPE log SYSTEM \"logger.dtd\">").append(lineSeperator);
+        sb.append(("<log>"));
         return sb.toString();
     }
 
     /**
      * Returns the tail string for a set of log records formatted as XML
      * strings.
-     * 
+     *
      * @param h
      *            the output handler, may be {@code null}.
      * @return the tail string for log records formatted as XML strings.
-     * @since Android 1.0
      */
     @Override
-    @SuppressWarnings("unused")
     public String getTail(Handler h) {
         return "</log>"; //$NON-NLS-1$
     }
 
-    //use privilege code to get system property
+    // use privilege code to get system property
     private static String getSystemProperty(final String key) {
-        return AccessController.doPrivileged(
-          new PrivilegedAction<String>() {
+        return AccessController.doPrivileged(new PrivilegedAction<String>() {
             public String run() {
                 return System.getProperty(key);
             }
         });
     }
-
 }
-
-
diff --git a/libcore/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LoggerTest.java b/libcore/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LoggerTest.java
index 3a06078..8a981bb 100644
--- a/libcore/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LoggerTest.java
+++ b/libcore/logging/src/test/java/org/apache/harmony/logging/tests/java/util/logging/LoggerTest.java
@@ -29,12 +29,15 @@
 import java.util.logging.LogRecord;
 import java.util.logging.Logger;
 import java.util.logging.LoggingPermission;
+import java.io.File;
+import java.io.FileInputStream;
 
 import junit.framework.TestCase;
 
 import org.apache.harmony.logging.tests.java.util.logging.util.EnvironmentHelper;
 
 import tests.util.CallVerificationStack;
+import dalvik.annotation.KnownFailure;
 import dalvik.annotation.SideEffect;
 import dalvik.annotation.TestLevel;
 import dalvik.annotation.TestTargetClass;
@@ -4628,6 +4631,27 @@
         }
     }
 
+    /*
+     * test initHandler
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "",
+        method = "initHandler",
+        args = {}
+    )
+    @KnownFailure(value="bug 2002061O")
+    public void test_initHandler() throws Exception {
+        File logProps = new File(LOGGING_CONFIG_FILE);
+        LogManager lm = LogManager.getLogManager();
+        lm.readConfiguration(new FileInputStream(logProps));
+
+        Logger log = Logger.getLogger("");
+        // can log properly
+        Handler[] handlers = log.getHandlers();
+        assertEquals(2, handlers.length);
+    }
+
 
     /*
      * A mock logger, used to test the protected constructors and fields.
diff --git a/libcore/logging/src/test/resources/config/java/util/logging/logging.config b/libcore/logging/src/test/resources/config/java/util/logging/logging.config
index f4c5146..6e7394b 100644
--- a/libcore/logging/src/test/resources/config/java/util/logging/logging.config
+++ b/libcore/logging/src/test/resources/config/java/util/logging/logging.config
@@ -1,3 +1,3 @@
-handlers=org.apache.harmony.logging.tests.java.util.logging.LogManagerTest$MockHandler java.util.logging.ConsoleHandler
+handlers=org.apache.harmony.logging.tests.java.util.logging.LogManagerTest$MockHandler ,  java.util.logging.ConsoleHandler
 .level=ALL
 org.apache.harmony.logging.tests.java.util.logging.LogManagerTest$MockHandler.level=OFF
\ No newline at end of file
diff --git a/libcore/luni-kernel/src/main/java/java/lang/Class.java b/libcore/luni-kernel/src/main/java/java/lang/Class.java
index 70ae3c1..b8e3903 100644
--- a/libcore/luni-kernel/src/main/java/java/lang/Class.java
+++ b/libcore/luni-kernel/src/main/java/java/lang/Class.java
@@ -440,7 +440,8 @@
      * @see ClassLoader#isSystemClassLoader()
      */
     ClassLoader getClassLoaderImpl() {
-        return getClassLoader(this);
+        ClassLoader loader = getClassLoader(this);
+        return loader == null ? BootClassLoader.getInstance() : loader;
     }
 
     /*
@@ -468,6 +469,7 @@
      * 
      * @param parameterTypes
      *            the parameter types of the requested constructor.
+     *            {@code (Class[]) null} is equivalent to the empty array.
      * @return the constructor described by {@code parameterTypes}.
      * @throws NoSuchMethodException
      *             if the constructor can not be found.
@@ -586,6 +588,7 @@
      * 
      * @param parameterTypes
      *            the parameter types of the requested constructor.
+     *            {@code (Class[]) null} is equivalent to the empty array.
      * @return the constructor described by {@code parameterTypes}.
      * @throws NoSuchMethodException
      *             if the requested constructor can not be found.
@@ -658,12 +661,14 @@
         sb.append(getSimpleName());
         sb.append('(');
         boolean first = true;
-        for (Class<?> p : parameterTypes) {
-            if (!first) {
-                sb.append(',');
+        if (parameterTypes != null) {
+            for (Class<?> p : parameterTypes) {
+                if (!first) {
+                    sb.append(',');
+                }
+                first = false;
+                sb.append(p.getSimpleName());
             }
-            first = false;
-            sb.append(p.getSimpleName());
         }
         sb.append(')');
         throw new NoSuchMethodException(sb.toString());
@@ -740,6 +745,7 @@
      *            the requested method's name.
      * @param parameterTypes
      *            the parameter types of the requested method.
+     *            {@code (Class[]) null} is equivalent to the empty array.
      * @return the method described by {@code name} and {@code parameterTypes}.
      * @throws NoSuchMethodException
      *             if the requested constructor can not be found.
@@ -990,6 +996,7 @@
      *            the requested method's name.
      * @param parameterTypes
      *            the parameter types of the requested method.
+     *            {@code (Class[]) null} is equivalent to the empty array.
      * @return the public field specified by {@code name}.
      * @throws NoSuchMethodException
      *             if the method can not be found.
diff --git a/libcore/luni-kernel/src/main/java/java/lang/Thread.java b/libcore/luni-kernel/src/main/java/java/lang/Thread.java
index 3cde7e1..4f9f988 100644
--- a/libcore/luni-kernel/src/main/java/java/lang/Thread.java
+++ b/libcore/luni-kernel/src/main/java/java/lang/Thread.java
@@ -73,14 +73,16 @@
  */
 public class Thread implements Runnable {
 
+    private static final int NANOS_PER_MILLI = 1000000;
+
     /** Park states */
     private static class ParkState {
         /** park state indicating unparked */
         private static final int UNPARKED = 1;
-    
+
         /** park state indicating preemptively unparked */
         private static final int PREEMPTIVELY_UNPARKED = 2;
-    
+
         /** park state indicating parked */
         private static final int PARKED = 3;
     }
@@ -120,21 +122,21 @@
 
     /**
      * The maximum priority value allowed for a thread.
-     * 
+     *
      * @since Android 1.0
      */
     public final static int MAX_PRIORITY = 10;
 
     /**
      * The minimum priority value allowed for a thread.
-     * 
+     *
      * @since Android 1.0
      */
     public final static int MIN_PRIORITY = 1;
 
     /**
      * The normal (default) priority value assigned to threads.
-     * 
+     *
      * @since Android 1.0
      */
     public final static int NORM_PRIORITY = 5;
@@ -198,7 +200,7 @@
 
     /** the park state of the thread */
     private int parkState = ParkState.UNPARKED;
-        
+
     /**
      * Constructs a new {@code Thread} with no {@code Runnable} object and a
      * newly generated name. The new {@code Thread} will belong to the same
@@ -206,7 +208,7 @@
      *
      * @see java.lang.ThreadGroup
      * @see java.lang.Runnable
-     * 
+     *
      * @since Android 1.0
      */
     public Thread() {
@@ -217,14 +219,14 @@
      * Constructs a new {@code Thread} with a {@code Runnable} object and a
      * newly generated name. The new {@code Thread} will belong to the same
      * {@code ThreadGroup} as the {@code Thread} calling this constructor.
-     * 
+     *
      * @param runnable
      *            a {@code Runnable} whose method <code>run</code> will be
      *            executed by the new {@code Thread}
      *
      * @see java.lang.ThreadGroup
      * @see java.lang.Runnable
-     * 
+     *
      * @since Android 1.0
      */
     public Thread(Runnable runnable) {
@@ -235,13 +237,13 @@
      * Constructs a new {@code Thread} with a {@code Runnable} object and name
      * provided. The new {@code Thread} will belong to the same {@code
      * ThreadGroup} as the {@code Thread} calling this constructor.
-     * 
+     *
      * @param runnable
      *            a {@code Runnable} whose method <code>run</code> will be
      *            executed by the new {@code Thread}
      * @param threadName
      *            the name for the {@code Thread} being created
-     * 
+     *
      * @see java.lang.ThreadGroup
      * @see java.lang.Runnable
      *
@@ -259,10 +261,10 @@
      * Constructs a new {@code Thread} with no {@code Runnable} object and the
      * name provided. The new {@code Thread} will belong to the same {@code
      * ThreadGroup} as the {@code Thread} calling this constructor.
-     * 
+     *
      * @param threadName
      *            the name for the {@code Thread} being created
-     * 
+     *
      * @see java.lang.ThreadGroup
      * @see java.lang.Runnable
      *
@@ -280,7 +282,7 @@
      * Constructs a new {@code Thread} with a {@code Runnable} object and a
      * newly generated name. The new {@code Thread} will belong to the {@code
      * ThreadGroup} passed as parameter.
-     * 
+     *
      * @param group
      *            {@code ThreadGroup} to which the new {@code Thread} will
      *            belong
@@ -296,7 +298,7 @@
      * @see java.lang.Runnable
      * @see java.lang.SecurityException
      * @see java.lang.SecurityManager
-     * 
+     *
      * @since Android 1.0
      */
     public Thread(ThreadGroup group, Runnable runnable) {
@@ -306,7 +308,7 @@
     /**
      * Constructs a new {@code Thread} with a {@code Runnable} object, the given
      * name and belonging to the {@code ThreadGroup} passed as parameter.
-     * 
+     *
      * @param group
      *            ThreadGroup to which the new {@code Thread} will belong
      * @param runnable
@@ -323,7 +325,7 @@
      * @see java.lang.Runnable
      * @see java.lang.SecurityException
      * @see java.lang.SecurityManager
-     * 
+     *
      * @since Android 1.0
      */
     public Thread(ThreadGroup group, Runnable runnable, String threadName) {
@@ -337,7 +339,7 @@
     /**
      * Constructs a new {@code Thread} with no {@code Runnable} object, the
      * given name and belonging to the {@code ThreadGroup} passed as parameter.
-     * 
+     *
      * @param group
      *            {@code ThreadGroup} to which the new {@code Thread} will belong
      * @param threadName
@@ -351,7 +353,7 @@
      * @see java.lang.Runnable
      * @see java.lang.SecurityException
      * @see java.lang.SecurityManager
-     * 
+     *
      * @since Android 1.0
      */
     public Thread(ThreadGroup group, String threadName) {
@@ -365,7 +367,7 @@
     /**
      * Constructs a new {@code Thread} with a {@code Runnable} object, the given
      * name and belonging to the {@code ThreadGroup} passed as parameter.
-     * 
+     *
      * @param group
      *            {@code ThreadGroup} to which the new {@code Thread} will
      *            belong
@@ -387,7 +389,7 @@
      * @see java.lang.Runnable
      * @see java.lang.SecurityException
      * @see java.lang.SecurityManager
-     * 
+     *
      * @since Android 1.0
      */
     public Thread(ThreadGroup group, Runnable runnable, String threadName, long stackSize) {
@@ -526,9 +528,9 @@
     /**
      * Returns the number of active {@code Thread}s in the running {@code
      * Thread}'s group and its subgroups.
-     * 
+     *
      * @return the number of {@code Thread}s
-     * 
+     *
      * @since Android 1.0
      */
     public static int activeCount() {
@@ -540,14 +542,14 @@
      * there's none installed, this method is a no-op. If there's a
      * SecurityManager installed, {@link SecurityManager#checkAccess(Thread)} is
      * called for that SecurityManager.
-     * 
+     *
      * @throws SecurityException
      *             if a SecurityManager is installed and it does not allow
      *             access to the Thread.
-     * 
+     *
      * @see java.lang.SecurityException
      * @see java.lang.SecurityManager
-     * 
+     *
      * @since Android 1.0
      */
     public final void checkAccess() {
@@ -562,12 +564,12 @@
 
     /**
      * Returns the number of stack frames in this thread.
-     * 
+     *
      * @return Number of stack frames
      * @deprecated The results of this call were never well defined. To make
      *             things worse, it would depend on whether the Thread was
      *             suspended or not, and suspend was deprecated too.
-     * 
+     *
      * @since Android 1.0
      */
     @Deprecated
@@ -579,7 +581,7 @@
      * Returns the Thread of the caller, that is, the current Thread.
      *
      * @return the current Thread.
-     * 
+     *
      * @since Android 1.0
      */
     public static Thread currentThread() {
@@ -590,7 +592,7 @@
      * Destroys the receiver without any monitor cleanup.
      *
      * @deprecated Not implemented.
-     * 
+     *
      * @since Android 1.0
      */
     @Deprecated
@@ -601,9 +603,9 @@
     /**
      * Prints to the standard error stream a text representation of the current
      * stack for this Thread.
-     * 
+     *
      * @see Throwable#printStackTrace()
-     * 
+     *
      * @since Android 1.0
      */
     public static void dumpStack() {
@@ -615,7 +617,7 @@
      * receiver - and subgroups - into the array <code>threads</code> passed as
      * parameter. If the array passed as parameter is too small no exception is
      * thrown - the extra elements are simply not copied.
-     * 
+     *
      * @param threads
      *            array into which the Threads will be copied
      * @return How many Threads were copied over
@@ -624,7 +626,7 @@
      *             {@link SecurityManager#checkAccess(Thread)}
      * @see java.lang.SecurityException
      * @see java.lang.SecurityManager
-     * 
+     *
      * @since Android 1.0
      */
     public static int enumerate(Thread[] threads) {
@@ -638,13 +640,13 @@
      * Returns the stack traces of all the currently live threads and puts them
      * into the given map.
      * </p>
-     * 
+     *
      * @return A Map of current Threads to StackTraceElement arrays.
      * @throws SecurityException
      *             if the current SecurityManager fails the
      *             {@link SecurityManager#checkPermission(java.security.Permission)}
      *             call.
-     * 
+     *
      * @since Android 1.0
      */
     public static Map<Thread, StackTraceElement[]> getAllStackTraces() {
@@ -682,14 +684,14 @@
      * </ol>
      * are satisfied, a security check for
      * <code>RuntimePermission("getClassLoader")</code> is performed first.
-     * 
+     *
      * @return ClassLoader The context ClassLoader
      * @see java.lang.ClassLoader
      * @see #getContextClassLoader()
-     * 
+     *
      * @throws SecurityException
      *             if the aforementioned security check fails.
-     *             
+     *
      * @since Android 1.0
      */
     public ClassLoader getContextClassLoader() {
@@ -717,7 +719,7 @@
      *
      * @return an {@link UncaughtExceptionHandler} or <code>null</code> if
      *         none exists.
-     * 
+     *
      * @since Android 1.0
      */
     public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() {
@@ -729,9 +731,9 @@
      * generated on thread creation, is unique to the thread, and doesn't change
      * during the lifetime of the thread; the ID may be reused after the thread
      * has been terminated.
-     * 
+     *
      * @return the thread's ID.
-     * 
+     *
      * @since Android 1.0
      */
     public long getId() {
@@ -742,7 +744,7 @@
      * Returns the name of the Thread.
      *
      * @return the Thread's name
-     * 
+     *
      * @since Android 1.0
      */
     public final String getName() {
@@ -754,7 +756,7 @@
      *
      * @return the Thread's priority
      * @see Thread#setPriority
-     * 
+     *
      * @since Android 1.0
      */
     public final int getPriority() {
@@ -768,13 +770,13 @@
      * The <code>RuntimePermission("getStackTrace")</code> is checked before
      * returning a result.
      * </p>
-     * 
+     *
      * @return an array of StackTraceElements.
      * @throws SecurityException
      *             if the current SecurityManager fails the
      *             {@link SecurityManager#checkPermission(java.security.Permission)}
      *             call.
-     * 
+     *
      * @since Android 1.0
      */
     public StackTraceElement[] getStackTrace() {
@@ -790,9 +792,9 @@
     /**
      * Returns the current state of the Thread. This method is useful for
      * monitoring purposes.
-     * 
+     *
      * @return a {@link State} value.
-     * 
+     *
      * @since Android 1.0
      */
     public State getState() {
@@ -803,7 +805,7 @@
         // deletes the reference we won't run into a null reference later.
         VMThread thread = vmThread;
         if (thread != null) {
-            // If the Thread Object became invalid or was not yet started,  
+            // If the Thread Object became invalid or was not yet started,
             // getStatus() will return -1.
             int state = thread.getStatus();
             if(state != -1) {
@@ -812,12 +814,12 @@
         }
         return hasBeenStarted ? Thread.State.TERMINATED : Thread.State.NEW;
     }
-    
+
     /**
      * Returns the ThreadGroup to which this Thread belongs.
-     * 
+     *
      * @return the Thread's ThreadGroup
-     * 
+     *
      * @since Android 1.0
      */
     public final ThreadGroup getThreadGroup() {
@@ -833,9 +835,9 @@
      * Returns the thread's uncaught exception handler. If not explicitly set,
      * then the ThreadGroup's handler is returned. If the thread is terminated,
      * then <code>null</code> is returned.
-     * 
+     *
      * @return an {@link UncaughtExceptionHandler} instance or {@code null}.
-     * 
+     *
      * @since Android 1.0
      */
     public UncaughtExceptionHandler getUncaughtExceptionHandler() {
@@ -868,14 +870,14 @@
      * their interrupt status set and return immediately. They don't receive an
      * exception in this case.
      * <ul>
-     * 
+     *
      * @throws SecurityException
      *             if <code>checkAccess()</code> fails with a SecurityException
      * @see java.lang.SecurityException
      * @see java.lang.SecurityManager
      * @see Thread#interrupted
      * @see Thread#isInterrupted
-     * 
+     *
      * @since Android 1.0
      */
     public void interrupt() {
@@ -896,12 +898,12 @@
      * <code>currentThread()</code>) has a pending interrupt request (<code>
      * true</code>) or not (<code>false</code>). It also has the side-effect of
      * clearing the flag.
-     * 
+     *
      * @return a <code>boolean</code> indicating the interrupt status
      * @see Thread#currentThread
      * @see Thread#interrupt
      * @see Thread#isInterrupted
-     * 
+     *
      * @since Android 1.0
      */
     public static boolean interrupted() {
@@ -913,16 +915,14 @@
      * still runs code (hasn't died yet). Returns <code>false</code> either if
      * the receiver hasn't been started yet or if it has already started and run
      * to completion and died.
-     * 
+     *
      * @return a <code>boolean</code> indicating the lifeness of the Thread
      * @see Thread#start
-     * 
+     *
      * @since Android 1.0
      */
     public final boolean isAlive() {
-        Thread.State state = getState();
-
-        return (state != Thread.State.TERMINATED && state != Thread.State.NEW);
+        return (vmThread != null);
     }
 
     /**
@@ -934,7 +934,7 @@
      *
      * @return a <code>boolean</code> indicating whether the Thread is a daemon
      * @see Thread#setDaemon
-     * 
+     *
      * @since Android 1.0
      */
     public final boolean isDaemon() {
@@ -949,7 +949,7 @@
      * @return a <code>boolean</code> indicating the interrupt status
      * @see Thread#interrupt
      * @see Thread#interrupted
-     * 
+     *
      * @since Android 1.0
      */
     public boolean isInterrupted() {
@@ -969,11 +969,20 @@
      *         the receiver while it was in the <code>join()</code> call
      * @see Object#notifyAll
      * @see java.lang.ThreadDeath
-     * 
+     *
      * @since Android 1.0
      */
     public final void join() throws InterruptedException {
-        join(0, 0);
+        VMThread t = vmThread;
+        if (t == null) {
+            return;
+        }
+
+        synchronized (t) {
+            while (isAlive()) {
+                t.wait();
+            }
+        }
     }
 
     /**
@@ -986,7 +995,7 @@
      *         the receiver while it was in the <code>join()</code> call
      * @see Object#notifyAll
      * @see java.lang.ThreadDeath
-     * 
+     *
      * @since Android 1.0
      */
     public final void join(long millis) throws InterruptedException {
@@ -1004,22 +1013,49 @@
      *         the receiver while it was in the <code>join()</code> call
      * @see Object#notifyAll
      * @see java.lang.ThreadDeath
-     * 
+     *
      * @since Android 1.0
      */
     public final void join(long millis, int nanos) throws InterruptedException {
-        if (millis < 0 || nanos < 0 || nanos > 999999) {
+        if (millis < 0 || nanos < 0 || nanos >= NANOS_PER_MILLI) {
             throw new IllegalArgumentException();
         }
 
-        VMThread t;
+        // avoid overflow: if total > 292,277 years, just wait forever
+        boolean overflow = millis >= (Long.MAX_VALUE - nanos) / NANOS_PER_MILLI;
+        boolean forever = (millis | nanos) == 0;
+        if (forever | overflow) {
+            join();
+            return;
+        }
 
-        t = this.vmThread;
+        VMThread t = vmThread;
+        if (t == null) {
+            return;
+        }
 
-        if (t != null) {
-            synchronized (t) {
-                if (isAlive())
-                    t.wait(millis, nanos);
+        synchronized (t) {
+            if (!isAlive()) {
+                return;
+            }
+
+            // guaranteed not to overflow
+            long nanosToWait = millis * NANOS_PER_MILLI + nanos;
+
+            // wait until this thread completes or the timeout has elapsed
+            long start = System.nanoTime();
+            while (true) {
+                t.wait(millis, nanos);
+                if (!isAlive()) {
+                    break;
+                }
+                long nanosElapsed = System.nanoTime() - start;
+                long nanosRemaining = nanosToWait - nanosElapsed;
+                if (nanosRemaining <= 0) {
+                    break;
+                }
+                millis = nanosRemaining / NANOS_PER_MILLI;
+                nanos = (int) (nanosRemaining - millis * NANOS_PER_MILLI);
             }
         }
     }
@@ -1029,12 +1065,12 @@
      * suspended, or suspended and already resumed. If the receiver is
      * suspended, however, makes it resume to the point where it was when it was
      * suspended.
-     * 
+     *
      * @throws SecurityException
      *             if <code>checkAccess()</code> fails with a SecurityException
      * @see Thread#suspend()
      * @deprecated Used with deprecated method {@link Thread#suspend}
-     * 
+     *
      * @since Android 1.0
      */
     @Deprecated
@@ -1052,7 +1088,7 @@
      * holds. If no Runnable is set, does nothing.
      *
      * @see Thread#start
-     * 
+     *
      * @since Android 1.0
      */
     public void run() {
@@ -1073,7 +1109,7 @@
      *         checkPermission call.
      * @see java.lang.ClassLoader
      * @see #getContextClassLoader()
-     * 
+     *
      * @since Android 1.0
      */
     public void setContextClassLoader(ClassLoader cl) {
@@ -1088,13 +1124,13 @@
     /**
      * Set if the receiver is a daemon Thread or not. This can only be done
      * before the Thread starts running.
-     * 
+     *
      * @param isDaemon
      *            indicates whether the Thread should be daemon or not
      * @throws SecurityException
      *             if <code>checkAccess()</code> fails with a SecurityException
      * @see Thread#isDaemon
-     * 
+     *
      * @since Android 1.0
      */
     public final void setDaemon(boolean isDaemon) {
@@ -1118,13 +1154,13 @@
      * The <code>RuntimePermission("setDefaultUncaughtExceptionHandler")</code>
      * is checked prior to setting the handler.
      * </p>
-     * 
+     *
      * @param handler
      *            The handler to set or <code>null</code>.
      * @throws SecurityException
      *             if the current SecurityManager fails the checkPermission
      *             call.
-     * 
+     *
      * @since Android 1.0
      */
     public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler handler) {
@@ -1159,7 +1195,7 @@
      * @throws SecurityException if <code>checkAccess()</code> fails with a
      *         SecurityException
      * @see Thread#getName
-     * 
+     *
      * @since Android 1.0
      */
     public final void setName(String threadName) {
@@ -1182,7 +1218,7 @@
      * be the parameter that was passed - it will depend on the receiver's
      * ThreadGroup. The priority cannot be set to be higher than the receiver's
      * ThreadGroup's maxPriority().
-     * 
+     *
      * @param priority
      *            new priority for the Thread
      * @throws SecurityException
@@ -1191,7 +1227,7 @@
      *             if the new priority is greater than Thread.MAX_PRIORITY or
      *             less than Thread.MIN_PRIORITY
      * @see Thread#getPriority
-     * 
+     *
      * @since Android 1.0
      */
     public final void setPriority(int priority) {
@@ -1218,12 +1254,12 @@
      * Sets the uncaught exception handler. This handler is invoked in case this
      * Thread dies due to an unhandled exception.
      * </p>
-     * 
+     *
      * @param handler
      *            The handler to set or <code>null</code>.
      * @throws SecurityException
      *             if the current SecurityManager fails the checkAccess call.
-     * 
+     *
      * @since Android 1.0
      */
     public void setUncaughtExceptionHandler(UncaughtExceptionHandler handler) {
@@ -1236,14 +1272,14 @@
      * Causes the thread which sent this message to sleep for the given interval
      * of time (given in milliseconds). The precision is not guaranteed - the
      * Thread may sleep more or less than requested.
-     * 
+     *
      * @param time
      *            The time to sleep in milliseconds.
      * @throws InterruptedException
      *             if <code>interrupt()</code> was called for this Thread while
      *             it was sleeping
      * @see Thread#interrupt()
-     * 
+     *
      * @since Android 1.0
      */
     public static void sleep(long time) throws InterruptedException {
@@ -1254,7 +1290,7 @@
      * Causes the thread which sent this message to sleep for the given interval
      * of time (given in milliseconds and nanoseconds). The precision is not
      * guaranteed - the Thread may sleep more or less than requested.
-     * 
+     *
      * @param millis
      *            The time to sleep in milliseconds.
      * @param nanos
@@ -1263,7 +1299,7 @@
      *             if <code>interrupt()</code> was called for this Thread while
      *             it was sleeping
      * @see Thread#interrupt()
-     * 
+     *
      * @since Android 1.0
      */
     public static void sleep(long millis, int nanos) throws InterruptedException {
@@ -1276,9 +1312,9 @@
      * Thread calling <code>start()</code>).
      *
      * @throws IllegalThreadStateException if the Thread has been started before
-     * 
+     *
      * @see Thread#run
-     * 
+     *
      * @since Android 1.0
      */
     public synchronized void start() {
@@ -1300,7 +1336,7 @@
      *         SecurityException
      * @deprecated because stopping a thread in this manner is unsafe and can
      * leave your application and the VM in an unpredictable state.
-     * 
+     *
      * @since Android 1.0
      */
     @Deprecated
@@ -1321,7 +1357,7 @@
      *         <code>null</code>
      * @deprecated because stopping a thread in this manner is unsafe and can
      * leave your application and the VM in an unpredictable state.
-     * 
+     *
      * @since Android 1.0
      */
     @Deprecated
@@ -1350,12 +1386,12 @@
      * resume()</code> is sent to it. Suspend requests are not queued, which
      * means that N requests are equivalent to just one - only one resume
      * request is needed in this case.
-     * 
+     *
      * @throws SecurityException
      *             if <code>checkAccess()</code> fails with a SecurityException
      * @see Thread#resume()
      * @deprecated May cause deadlocks.
-     * 
+     *
      * @since Android 1.0
      */
     @Deprecated
@@ -1371,9 +1407,9 @@
     /**
      * Returns a string containing a concise, human-readable description of the
      * Thread. It includes the Thread's name, priority, and group name.
-     * 
+     *
      * @return a printable representation for the receiver.
-     * 
+     *
      * @since Android 1.0
      */
     @Override
@@ -1384,7 +1420,7 @@
     /**
      * Causes the calling Thread to yield execution time to another Thread that
      * is ready to run. The actual scheduling is implementation-dependent.
-     * 
+     *
      * @since Android 1.0
      */
     public static void yield() {
@@ -1398,7 +1434,7 @@
      * @param object the object to test for the monitor lock
      * @return true if the current thread has a monitor lock on the specified
      *         object; false otherwise
-     *         
+     *
      * @since Android 1.0
      */
     public static boolean holdsLock(Object object) {
@@ -1410,7 +1446,7 @@
      * terminated by an uncaught exception. Upon such termination, the handler
      * is notified of the terminating thread and causal exception. If there is
      * no explicit handler set then the thread's group is the default handler.
-     * 
+     *
      * @since Android 1.0
      */
     public static interface UncaughtExceptionHandler {
@@ -1421,7 +1457,7 @@
          *
          * @param thread the thread that has an uncaught exception
          * @param ex the exception that was thrown
-         * 
+         *
          * @since Android 1.0
          */
         void uncaughtException(Thread thread, Throwable ex);
@@ -1444,7 +1480,7 @@
             parkState = ParkState.PREEMPTIVELY_UNPARKED;
             return;
         }
-        
+
         synchronized (vmt) {
             switch (parkState) {
                 case ParkState.PREEMPTIVELY_UNPARKED: {
@@ -1468,12 +1504,12 @@
             }
         }
     }
-    
+
     /**
      * Implementation of <code>parkFor()</code>. See {@link LangAccessImpl}.
      * This method must only be called when <code>this</code> is the current
      * thread.
-     * 
+     *
      * @param nanos number of nanoseconds to park for
      */
     /*package*/ void parkFor(long nanos) {
@@ -1483,7 +1519,7 @@
             // Running threads should always have an associated vmThread.
             throw new AssertionError();
         }
-        
+
         synchronized (vmt) {
             switch (parkState) {
                 case ParkState.PREEMPTIVELY_UNPARKED: {
@@ -1491,8 +1527,8 @@
                     break;
                 }
                 case ParkState.UNPARKED: {
-                    long millis = nanos / 1000000;
-                    nanos %= 1000000;
+                    long millis = nanos / NANOS_PER_MILLI;
+                    nanos %= NANOS_PER_MILLI;
 
                     parkState = ParkState.PARKED;
                     try {
@@ -1507,7 +1543,7 @@
                          */
                         if (parkState == ParkState.PARKED) {
                             parkState = ParkState.UNPARKED;
-                        }                            
+                        }
                     }
                     break;
                 }
@@ -1515,7 +1551,7 @@
                     throw new AssertionError(
                             "shouldn't happen: attempt to repark");
                 }
-            }       
+            }
         }
     }
 
@@ -1523,7 +1559,7 @@
      * Implementation of <code>parkUntil()</code>. See {@link LangAccessImpl}.
      * This method must only be called when <code>this</code> is the current
      * thread.
-     * 
+     *
      * @param time absolute milliseconds since the epoch to park until
      */
     /*package*/ void parkUntil(long time) {
@@ -1533,7 +1569,7 @@
             // Running threads should always have an associated vmThread.
             throw new AssertionError();
         }
-        
+
         synchronized (vmt) {
             /*
              * Note: This conflates the two time bases of "wall clock"
@@ -1554,7 +1590,7 @@
             if (delayMillis <= 0) {
                 parkState = ParkState.UNPARKED;
             } else {
-                parkFor(delayMillis * 1000000);
+                parkFor(delayMillis * NANOS_PER_MILLI);
             }
         }
     }
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 fcff1df..eaefc9f 100644
--- a/libcore/luni-kernel/src/main/native/java_lang_ProcessManager.c
+++ b/libcore/luni-kernel/src/main/native/java_lang_ProcessManager.c
@@ -91,7 +91,8 @@
     while (1) {
         int status;
 
-        pid_t pid = wait(&status);
+        /* wait for children in our process group */
+        pid_t pid = waitpid(0, &status, 0);
 
         if (pid >= 0) {
             // Extract real status.
diff --git a/libcore/luni/src/main/java/java/io/BufferedInputStream.java b/libcore/luni/src/main/java/java/io/BufferedInputStream.java
index 0b9afc3..22379dd 100644
--- a/libcore/luni/src/main/java/java/io/BufferedInputStream.java
+++ b/libcore/luni/src/main/java/java/io/BufferedInputStream.java
@@ -30,68 +30,49 @@
  * drawback is that some extra space is required to hold the buffer and that
  * copying takes place when filling that buffer, but this is usually outweighed
  * by the performance benefits.
- * 
+ *
  * <p/>A typical application pattern for the class looks like this:<p/>
- * 
+ *
  * <pre>
  * BufferedInputStream buf = new BufferedInputStream(new FileInputStream(&quot;file.java&quot;));
  * </pre>
- * 
+ *
  * @see BufferedOutputStream
- * 
- * @since Android 1.0
  */
 public class BufferedInputStream extends FilterInputStream {
-    // BEGIN android-changed
-    // The address of the buffer should not be cached in a register.
-    // This was changed to be more close to the RI.
     /**
      * The buffer containing the current bytes read from the target InputStream.
-     * 
-     * @since Android 1.0
      */
     protected volatile byte[] buf;
-    // END android-changed
 
     /**
      * The total number of bytes inside the byte array {@code buf}.
-     * 
-     * @since Android 1.0
      */
     protected int count;
 
     /**
      * The current limit, which when passed, invalidates the current mark.
-     * 
-     * @since Android 1.0
      */
     protected int marklimit;
 
     /**
      * The currently marked position. -1 indicates no mark has been set or the
      * mark has been invalidated.
-     * 
-     * @since Android 1.0
      */
     protected int markpos = -1;
 
     /**
      * The current position within the byte array {@code buf}.
-     * 
-     * @since Android 1.0
      */
     protected int pos;
 
-    private boolean closed = false;
-
     /**
      * Constructs a new {@code BufferedInputStream} on the {@link InputStream}
      * {@code in}. The default buffer size (8 KB) is allocated and all reads
      * can now be filtered through this stream.
-     * 
+     *
      * @param in
      *            the InputStream the buffer reads from.
-     * @since Android 1.0
      */
     public BufferedInputStream(InputStream in) {
         super(in);
@@ -116,14 +97,13 @@
      * Constructs a new {@code BufferedInputStream} on the {@link InputStream}
      * {@code in}. The buffer size is specified by the parameter {@code size}
      * and all reads are now filtered through this stream.
-     * 
+     *
      * @param in
      *            the input stream the buffer reads from.
      * @param size
      *            the size of buffer to allocate.
      * @throws IllegalArgumentException
      *             if {@code size < 0}.
-     * @since Android 1.0
      */
     public BufferedInputStream(InputStream in, int size) {
         super(in);
@@ -138,43 +118,43 @@
      * Returns the number of bytes that are available before this stream will
      * block. This method returns the number of bytes available in the buffer
      * plus those available in the source stream.
-     * 
+     *
      * @return the number of bytes available before blocking.
      * @throws IOException
      *             if this stream is closed.
-     * @since Android 1.0
      */
     @Override
     public synchronized int available() throws IOException {
-        if (buf == null) {
+        InputStream localIn = in; // 'in' could be invalidated by close()
+        if (buf == null || localIn == null) {
             // K0059=Stream is closed
             throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
         }
-        return count - pos + in.available();
+        return count - pos + localIn.available();
     }
 
     /**
      * Closes this stream. The source stream is closed and any resources
      * associated with it are released.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this stream.
-     * @since Android 1.0
      */
     @Override
-    public synchronized void close() throws IOException {
-        if (null != in) {
-            super.close();
-            in = null;
-        }
+    public void close() throws IOException {
         buf = null;
-        closed = true;
+        InputStream localIn = in;
+        in = null;
+        if (localIn != null) {
+            localIn.close();
+        }
     }
 
-    private int fillbuf() throws IOException {
+    private int fillbuf(InputStream localIn, byte[] localBuf)
+            throws IOException {
         if (markpos == -1 || (pos - markpos >= marklimit)) {
             /* Mark position not set or exceeded readlimit */
-            int result = in.read(buf);
+            int result = localIn.read(localBuf);
             if (result > 0) {
                 markpos = -1;
                 pos = 0;
@@ -182,22 +162,25 @@
             }
             return result;
         }
-        if (markpos == 0 && marklimit > buf.length) {
-            /* Increase buffer size to accomodate the readlimit */
-            int newLength = buf.length * 2;
+        if (markpos == 0 && marklimit > localBuf.length) {
+            /* Increase buffer size to accommodate the readlimit */
+            int newLength = localBuf.length * 2;
             if (newLength > marklimit) {
                 newLength = marklimit;
             }
             byte[] newbuf = new byte[newLength];
-            System.arraycopy(buf, 0, newbuf, 0, buf.length);
-            buf = newbuf;
+            System.arraycopy(localBuf, 0, newbuf, 0, localBuf.length);
+            // Reassign buf, which will invalidate any local references
+            // FIXME: what if buf was null?
+            localBuf = buf = newbuf;
         } else if (markpos > 0) {
-            System.arraycopy(buf, markpos, buf, 0, buf.length - markpos);
+            System.arraycopy(localBuf, markpos, localBuf, 0, localBuf.length
+                    - markpos);
         }
         /* Set the new position and mark position */
         pos -= markpos;
         count = markpos = 0;
-        int bytesread = in.read(buf, pos, buf.length - pos);
+        int bytesread = localIn.read(localBuf, pos, localBuf.length - pos);
         count = bytesread <= 0 ? pos : pos + bytesread;
         return bytesread;
     }
@@ -209,12 +192,11 @@
      * position if {@code readlimit} has not been surpassed. The underlying
      * buffer may be increased in size to allow {@code readlimit} number of
      * bytes to be supported.
-     * 
+     *
      * @param readlimit
      *            the number of bytes that can be read before the mark is
      *            invalidated.
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public synchronized void mark(int readlimit) {
@@ -225,11 +207,10 @@
     /**
      * Indicates whether {@code BufferedInputStream} supports the {@code mark()}
      * and {@code reset()} methods.
-     * 
+     *
      * @return {@code true} for BufferedInputStreams.
      * @see #mark(int)
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public boolean markSupported() {
@@ -241,28 +222,39 @@
      * range from 0 to 255. Returns -1 if the end of the source string has been
      * reached. If the internal buffer does not contain any available bytes then
      * it is filled from the source stream and the first byte is returned.
-     * 
+     *
      * @return the byte read or -1 if the end of the source stream has been
      *         reached.
      * @throws IOException
      *             if this stream is closed or another IOException occurs.
-     * @since Android 1.0
      */
     @Override
     public synchronized int read() throws IOException {
-        if (in == null) {
+        // Use local refs since buf and in may be invalidated by an
+        // unsynchronized close()
+        byte[] localBuf = buf;
+        InputStream localIn = in;
+        if (localBuf == null || localIn == null) {
             // K0059=Stream is closed
             throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
         }
 
         /* Are there buffered bytes available? */
-        if (pos >= count && fillbuf() == -1) {
+        if (pos >= count && fillbuf(localIn, localBuf) == -1) {
             return -1; /* no, fill buffer */
         }
+        // localBuf may have been invalidated by fillbuf
+        if (localBuf != buf) {
+            localBuf = buf;
+            if (localBuf == null) {
+                // K0059=Stream is closed
+                throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
+            }
+        }
 
         /* Did filling the buffer fail with -1 (EOF)? */
         if (count - pos > 0) {
-            return buf[pos++] & 0xFF;
+            return localBuf[pos++] & 0xFF;
         }
         return -1;
     }
@@ -275,7 +267,7 @@
      * mark has not been set and the requested number of bytes is larger than
      * the receiver's buffer size, this implementation bypasses the buffer and
      * simply places the results directly into {@code buffer}.
-     * 
+     *
      * @param buffer
      *            the byte array in which to store the bytes read.
      * @param offset
@@ -291,12 +283,14 @@
      * @throws IOException
      *             if the stream is already closed or another IOException
      *             occurs.
-     * @since Android 1.0
      */
     @Override
     public synchronized int read(byte[] buffer, int offset, int length)
             throws IOException {
-        if (closed) {
+        // Use local ref since buf may be invalidated by an unsynchronized
+        // close()
+        byte[] localBuf = buf;
+        if (localBuf == null) {
             // K0059=Stream is closed
             throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
         }
@@ -316,7 +310,9 @@
         if (length == 0) {
             return 0;
         }
-        if (null == buf) {
+        InputStream localIn = in;
+        if (localIn == null) {
+            // K0059=Stream is closed
             throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
         }
 
@@ -324,9 +320,9 @@
         if (pos < count) {
             /* There are bytes available in the buffer. */
             int copylength = count - pos >= length ? length : count - pos;
-            System.arraycopy(buf, pos, buffer, offset, copylength);
+            System.arraycopy(localBuf, pos, buffer, offset, copylength);
             pos += copylength;
-            if (copylength == length || in.available() == 0) {
+            if (copylength == length || localIn.available() == 0) {
                 return copylength;
             }
             offset += copylength;
@@ -341,24 +337,33 @@
              * If we're not marked and the required size is greater than the
              * buffer, simply read the bytes directly bypassing the buffer.
              */
-            if (markpos == -1 && required >= buf.length) {
-                read = in.read(buffer, offset, required);
+            if (markpos == -1 && required >= localBuf.length) {
+                read = localIn.read(buffer, offset, required);
                 if (read == -1) {
                     return required == length ? -1 : length - required;
                 }
             } else {
-                if (fillbuf() == -1) {
+                if (fillbuf(localIn, localBuf) == -1) {
                     return required == length ? -1 : length - required;
                 }
+                // localBuf may have been invalidated by fillbuf
+                if (localBuf != buf) {
+                    localBuf = buf;
+                    if (localBuf == null) {
+                        // K0059=Stream is closed
+                        throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
+                    }
+                }
+
                 read = count - pos >= required ? required : count - pos;
-                System.arraycopy(buf, pos, buffer, offset, read);
+                System.arraycopy(localBuf, pos, buffer, offset, read);
                 pos += read;
             }
             required -= read;
             if (required == 0) {
                 return length;
             }
-            if (in.available() == 0) {
+            if (localIn.available() == 0) {
                 return length - required;
             }
             offset += read;
@@ -367,13 +372,12 @@
 
     /**
      * Resets this stream to the last marked location.
-     * 
+     *
      * @throws IOException
      *             if this stream is closed, no mark has been set or the mark is
      *             no longer valid because more than {@code readlimit} bytes
      *             have been read since setting the mark.
      * @see #mark(int)
-     * @since Android 1.0
      */
     @Override
     public synchronized void reset() throws IOException {
@@ -383,7 +387,7 @@
          * so it is preferable to avoid loading up the whole big set of
          * messages just for these cases.
          */
-        if (closed) {
+        if (buf == null) {
             throw new IOException("Stream is closed");
         }
         if (-1 == markpos) {
@@ -397,24 +401,31 @@
      * Skips {@code amount} number of bytes in this stream. Subsequent
      * {@code read()}'s will not return these bytes unless {@code reset()} is
      * used.
-     * 
+     *
      * @param amount
      *            the number of bytes to skip. {@code skip} does nothing and
      *            returns 0 if {@code amount} is less than zero.
      * @return the number of bytes actually skipped.
      * @throws IOException
      *             if this stream is closed or another IOException occurs.
-     * @since Android 1.0
      */
     @Override
     public synchronized long skip(long amount) throws IOException {
-        if (null == in) {
+        // Use local refs since buf and in may be invalidated by an
+        // unsynchronized close()
+        byte[] localBuf = buf;
+        InputStream localIn = in;
+        if (localBuf == null) {
             // K0059=Stream is closed
             throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
         }
         if (amount < 1) {
             return 0;
         }
+        if (localIn == null) {
+            // K0059=Stream is closed
+            throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
+        }
 
         if (count - pos >= amount) {
             pos += amount;
@@ -425,7 +436,7 @@
 
         if (markpos != -1) {
             if (amount <= marklimit) {
-                if (fillbuf() == -1) {
+                if (fillbuf(localIn, localBuf) == -1) {
                     return read;
                 }
                 if (count - pos >= amount - read) {
@@ -437,9 +448,7 @@
                 pos = count;
                 return read;
             }
-            markpos = -1;
         }
-        return read + in.skip(amount - read);
+        return read + localIn.skip(amount - read);
     }
 }
-
diff --git a/libcore/luni/src/main/java/java/io/BufferedOutputStream.java b/libcore/luni/src/main/java/java/io/BufferedOutputStream.java
index 835d13f..6d52dee 100644
--- a/libcore/luni/src/main/java/java/io/BufferedOutputStream.java
+++ b/libcore/luni/src/main/java/java/io/BufferedOutputStream.java
@@ -30,40 +30,33 @@
  * drawback is that some extra space is required to hold the buffer and that
  * copying takes place when flushing that buffer, but this is usually outweighed
  * by the performance benefits.
- * 
+ *
  * <p/>A typical application pattern for the class looks like this:<p/>
- * 
+ *
  * <pre>
  * BufferedOutputStream buf = new BufferedOutputStream(new FileOutputStream(&quot;file.java&quot;));
  * </pre>
- * 
+ *
  * @see BufferedInputStream
- * 
- * @since Android 1.0
  */
 public class BufferedOutputStream extends FilterOutputStream {
     /**
      * The buffer containing the bytes to be written to the target stream.
-     * 
-     * @since Android 1.0
      */
     protected byte[] buf;
 
     /**
      * The total number of bytes inside the byte array {@code buf}.
-     * 
-     * @since Android 1.0
      */
     protected int count;
 
     /**
      * Constructs a new {@code BufferedOutputStream} on the {@link OutputStream}
      * {@code out}. The buffer size is set to the default value of 8 KB.
-     * 
+     *
      * @param out
      *            the {@code OutputStream} for which write operations are
      *            buffered.
-     * @since Android 1.0
      */
     public BufferedOutputStream(OutputStream out) {
         super(out);
@@ -87,14 +80,13 @@
     /**
      * Constructs a new {@code BufferedOutputStream} on the {@link OutputStream}
      * {@code out}. The buffer size is set to {@code size}.
-     * 
+     *
      * @param out
      *            the output stream for which write operations are buffered.
      * @param size
      *            the size of the buffer in bytes.
      * @throws IllegalArgumentException
      *             if {@code size <= 0}.
-     * @since Android 1.0
      */
     public BufferedOutputStream(OutputStream out, int size) {
         super(out);
@@ -108,17 +100,13 @@
     /**
      * Flushes this stream to ensure all pending data is written out to the
      * target stream. In addition, the target stream is flushed.
-     * 
+     *
      * @throws IOException
      *             if an error occurs attempting to flush this stream.
-     * @since Android 1.0
      */
     @Override
     public synchronized void flush() throws IOException {
-        if (count > 0) {
-            out.write(buf, 0, count);
-        }
-        count = 0;
+        flushInternal();
         out.flush();
     }
 
@@ -128,7 +116,7 @@
      * bytes, they are copied in. If not, the buffered bytes plus the bytes in
      * {@code buffer} are written to the target stream, the target is flushed,
      * and the buffer is cleared.
-     * 
+     *
      * @param buffer
      *            the buffer to be written.
      * @param offset
@@ -144,7 +132,8 @@
      *             if an error occurs attempting to write to this stream.
      * @throws NullPointerException
      *             if {@code buffer} is {@code null}.
-     * @since Android 1.0
+     * @throws ArrayIndexOutOfBoundsException
+     *             If offset or count is outside of bounds.
      */
     @Override
     public synchronized void write(byte[] buffer, int offset, int length)
@@ -153,6 +142,13 @@
             // K0047=buffer is null
             throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
         }
+
+        if (length >= buf.length) {
+            flushInternal();
+            out.write(buffer, offset, length);
+            return;
+        }
+
         // BEGIN android-changed
         // Exception priorities (in case of multiple errors) differ from
         // RI, but are spec-compliant.
@@ -163,32 +159,15 @@
             throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
         }
         // END android-changed
-        if (count == 0 && length >= buf.length) {
-            out.write(buffer, offset, length);
-            return;
+
+        // flush the internal buffer first if we have not enough space left
+        if (length >= (buf.length - count)) {
+            flushInternal();
         }
-        int available = buf.length - count;
-        if (length < available) {
-            available = length;
-        }
-        if (available > 0) {
-            System.arraycopy(buffer, offset, buf, count, available);
-            count += available;
-        }
-        if (count == buf.length) {
-            out.write(buf, 0, buf.length);
-            count = 0;
-            if (length > available) {
-                offset += available;
-                available = length - available;
-                if (available >= buf.length) {
-                    out.write(buffer, offset, available);
-                } else {
-                    System.arraycopy(buffer, offset, buf, count, available);
-                    count += available;
-                }
-            }
-        }
+
+        // the length is always less than (buf.length - count) here so arraycopy is safe
+        System.arraycopy(buffer, offset, buf, count, length);
+        count += length;
     }
 
     /**
@@ -197,12 +176,11 @@
      * copied into the buffer and the count incremented. Otherwise, the buffer
      * plus {@code oneByte} are written to the target stream, the target is
      * flushed, and the buffer is reset.
-     * 
+     *
      * @param oneByte
      *            the byte to be written.
      * @throws IOException
      *             if an error occurs attempting to write to this stream.
-     * @since Android 1.0
      */
     @Override
     public synchronized void write(int oneByte) throws IOException {
@@ -212,4 +190,14 @@
         }
         buf[count++] = (byte) oneByte;
     }
+
+    /**
+     * Flushes only internal buffer.
+     */
+    private void flushInternal() throws IOException {
+        if (count > 0) {
+            out.write(buf, 0, count);
+        }
+        count = 0;
+    }
 }
diff --git a/libcore/luni/src/main/java/java/io/BufferedReader.java b/libcore/luni/src/main/java/java/io/BufferedReader.java
index e82e538..77f1975 100644
--- a/libcore/luni/src/main/java/java/io/BufferedReader.java
+++ b/libcore/luni/src/main/java/java/io/BufferedReader.java
@@ -32,14 +32,13 @@
  * benefits.
  * 
  * <p/>A typical application pattern for the class looks like this:<p/>
- * 
+ *
  * <pre>
  * BufferedReader buf = new BufferedReader(new FileReader(&quot;file.java&quot;));
  * </pre>
  * 
  * @see BufferedWriter
- * 
- * @since Android 1.0
+ * @since 1.1
  */
 public class BufferedReader extends Reader {
 
@@ -61,7 +60,6 @@
      * 
      * @param in
      *            the Reader that is buffered.
-     * @since Android 1.0
      */
     public BufferedReader(Reader in) {
         super(in);
@@ -94,7 +92,6 @@
      *            the size of the buffer to allocate.
      * @throws IllegalArgumentException
      *             if {@code size <= 0}.
-     * @since Android 1.0
      */
     public BufferedReader(Reader in, int size) {
         super(in);
@@ -112,7 +109,6 @@
      * 
      * @throws IOException
      *             if an error occurs while closing this reader.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -181,7 +177,6 @@
      *             if an error occurs while setting a mark in this reader.
      * @see #markSupported()
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public void mark(int readlimit) throws IOException {
@@ -204,7 +199,6 @@
      * @return {@code true} for {@code BufferedReader}.
      * @see #mark(int)
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public boolean markSupported() {
@@ -217,12 +211,11 @@
      * character from the buffer. If there are no characters available in the
      * buffer, it fills the buffer and then returns a character. It returns -1
      * if there are no more characters in the source reader.
-     * 
+     *
      * @return the character read or -1 if the end of the source reader has been
      *         reached.
      * @throws IOException
      *             if this reader is closed or some other I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public int read() throws IOException {
@@ -234,6 +227,7 @@
             if (pos < count || fillbuf() != -1) {
                 return buf[pos++];
             }
+            markpos = -1;
             return -1;
         }
     }
@@ -263,7 +257,6 @@
      *             {@code buffer}.
      * @throws IOException
      *             if this reader is closed or some other I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public int read(char[] buffer, int offset, int length) throws IOException {
@@ -342,7 +335,6 @@
      *         read before the end of the reader has been reached.
      * @throws IOException
      *             if this reader is closed or some other I/O error occurs.
-     * @since Android 1.0
      */
     public String readLine() throws IOException {
         synchronized (lock) {
@@ -355,6 +347,9 @@
             }
             for (int charPos = pos; charPos < count; charPos++) {
                 char ch = buf[charPos];
+                // BEGIN android-note
+                // a switch statement may be more efficient
+                // END android-note
                 if (ch > '\r') {
                     continue;
                 }
@@ -393,6 +388,9 @@
                     }
                 }
                 for (int charPos = pos; charPos < count; charPos++) {
+                    // BEGIN android-note
+                    // use a local variable for buf[charPos] and a switch statement
+                    // END android-note
                     if (eol == '\0') {
                         if ((buf[charPos] == '\n' || buf[charPos] == '\r')) {
                             eol = buf[charPos];
@@ -403,7 +401,7 @@
                         }
                         pos = charPos + 1;
                         return result.toString();
-                    } else if (eol != '\0') {
+                    } else {
                         if (charPos > pos) {
                             result.append(buf, pos, charPos - pos - 1);
                         }
@@ -424,7 +422,7 @@
 
     /**
      * Indicates whether this reader is ready to be read without blocking.
-     * 
+     *
      * @return {@code true} if this reader will not block when {@code read} is
      *         called, {@code false} if unknown or blocking will occur.
      * @throws IOException
@@ -432,7 +430,6 @@
      * @see #read()
      * @see #read(char[], int, int)
      * @see #readLine()
-     * @since Android 1.0
      */
     @Override
     public boolean ready() throws IOException {
@@ -453,7 +450,6 @@
      *             if this reader is closed or no mark has been set.
      * @see #mark(int)
      * @see #markSupported()
-     * @since Android 1.0
      */
     @Override
     public void reset() throws IOException {
@@ -484,7 +480,6 @@
      * @see #mark(int)
      * @see #markSupported()
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public long skip(long amount) throws IOException {
diff --git a/libcore/luni/src/main/java/java/io/BufferedWriter.java b/libcore/luni/src/main/java/java/io/BufferedWriter.java
index 761b9c5..86949fa 100644
--- a/libcore/luni/src/main/java/java/io/BufferedWriter.java
+++ b/libcore/luni/src/main/java/java/io/BufferedWriter.java
@@ -33,16 +33,14 @@
  * some extra space is required to hold the buffer and that copying takes place
  * when filling that buffer, but this is usually outweighed by the performance
  * benefits.
- * 
+ *
  * <p/>A typical application pattern for the class looks like this:<p/>
- * 
+ *
  * <pre>
  * BufferedWriter buf = new BufferedWriter(new FileWriter(&quot;file.java&quot;));
  * </pre>
- * 
+ *
  * @see BufferedReader
- * 
- * @since Android 1.0
  */
 public class BufferedWriter extends Writer {
 
@@ -59,10 +57,9 @@
      * Constructs a new {@code BufferedWriter} with {@code out} as the writer
      * for which to buffer write operations. The buffer size is set to the
      * default value of 8 KB.
-     * 
+     *
      * @param out
      *            the writer for which character writing is buffered.
-     * @since Android 1.0
      */
     public BufferedWriter(Writer out) {
         super(out);
@@ -88,14 +85,13 @@
      * Constructs a new {@code BufferedWriter} with {@code out} as the writer
      * for which to buffer write operations. The buffer size is set to {@code
      * size}.
-     * 
+     *
      * @param out
      *            the writer for which character writing is buffered.
      * @param size
      *            the size of the buffer in bytes.
      * @throws IllegalArgumentException
      *             if {@code size <= 0}.
-     * @since Android 1.0
      */
     public BufferedWriter(Writer out, int size) {
         super(out);
@@ -110,16 +106,15 @@
      * Closes this writer. The contents of the buffer are flushed, the target
      * writer is closed, and the buffer is released. Only the first invocation
      * of close has any effect.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this writer.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
         synchronized (lock) {
             if (!isClosed()) {
-                flush();
+                flushInternal();
                 out.close();
                 buf = null;
                 out = null;
@@ -130,10 +125,9 @@
     /**
      * Flushes this writer. The contents of the buffer are committed to the
      * target writer and it is then flushed.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while flushing this writer.
-     * @since Android 1.0
      */
     @Override
     public void flush() throws IOException {
@@ -141,17 +135,24 @@
             if (isClosed()) {
                 throw new IOException(Msg.getString("K005d")); //$NON-NLS-1$
             }
-            if (pos > 0) {
-                out.write(buf, 0, pos);
-            }
-            pos = 0;
+            flushInternal();
             out.flush();
         }
     }
 
     /**
+     * Flushes the internal buffer.
+     */
+    private void flushInternal() throws IOException {
+        if (pos > 0) {
+            out.write(buf, 0, pos);
+        }
+        pos = 0;
+    }
+
+    /**
      * Indicates whether this writer is closed.
-     * 
+     *
      * @return {@code true} if this writer is closed, {@code false} otherwise.
      */
     private boolean isClosed() {
@@ -162,10 +163,9 @@
      * Writes a newline to this writer. A newline is determined by the System
      * property "line.separator". The target writer may or may not be flushed
      * when a newline is written.
-     * 
+     *
      * @throws IOException
      *             if an error occurs attempting to write to this writer.
-     * @since Android 1.0
      */
     public void newLine() throws IOException {
         write(lineSeparator, 0, lineSeparator.length());
@@ -176,7 +176,7 @@
      * {@code cbuf} to this writer. If {@code count} is greater than this
      * writer's buffer, then the buffer is flushed and the characters are
      * written directly to the target writer.
-     * 
+     *
      * @param cbuf
      *            the array containing characters to write.
      * @param offset
@@ -189,7 +189,6 @@
      *             {@code cbuf}.
      * @throws IOException
      *             if this writer is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public void write(char[] cbuf, int offset, int count) throws IOException {
@@ -243,12 +242,11 @@
      * Writes the character {@code oneChar} to this writer. If the buffer
      * gets full by writing this character, this writer is flushed. Only the
      * lower two bytes of the integer {@code oneChar} are written.
-     * 
+     *
      * @param oneChar
      *            the character to write.
      * @throws IOException
      *             if this writer is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public void write(int oneChar) throws IOException {
@@ -270,7 +268,7 @@
      * then this writer is flushed and the remaining characters are written
      * directly to the target writer. If count is negative no characters are
      * written to the buffer. This differs from the behavior of the superclass.
-     * 
+     *
      * @param str
      *            the non-null String containing characters to write.
      * @param offset
@@ -283,7 +281,6 @@
      * @throws IndexOutOfBoundsException
      *             if {@code offset < 0} or {@code offset + count} is greater
      *             than the length of {@code str}.
-     * @since Android 1.0
      */
     @Override
     public void write(String str, int offset, int count) throws IOException {
diff --git a/libcore/luni/src/main/java/java/io/ByteArrayInputStream.java b/libcore/luni/src/main/java/java/io/ByteArrayInputStream.java
index 1564ca5..f0b7219 100644
--- a/libcore/luni/src/main/java/java/io/ByteArrayInputStream.java
+++ b/libcore/luni/src/main/java/java/io/ByteArrayInputStream.java
@@ -23,48 +23,38 @@
 
 /**
  * A specialized {@link InputStream } for reading the contents of a byte array.
- * 
+ *
  * @see ByteArrayOutputStream
- * 
- * @since Android 1.0
  */
 public class ByteArrayInputStream extends InputStream {
     /**
      * The {@code byte} array containing the bytes to stream over.
-     * 
-     * @since Android 1.0
      */
     protected byte[] buf;
 
     /**
      * The current position within the byte array.
-     * 
-     * @since Android 1.0
      */
     protected int pos;
 
     /**
-     * The current mark position.
-     * 
-     * @since Android 1.0
+     * The current mark position. Initially set to 0 or the <code>offset</code>
+     * parameter within the constructor.
      */
     protected int mark;
 
     /**
      * The total number of bytes initially available in the byte array
      * {@code buf}.
-     * 
-     * @since Android 1.0
      */
     protected int count;
 
     /**
      * Constructs a new {@code ByteArrayInputStream} on the byte array
      * {@code buf}.
-     * 
+     *
      * @param buf
      *            the byte array to stream over.
-     * @since Android 1.0
      */
     public ByteArrayInputStream(byte buf[]) {
         this.mark = 0;
@@ -76,14 +66,13 @@
      * Constructs a new {@code ByteArrayInputStream} on the byte array
      * {@code buf} with the initial position set to {@code offset} and the
      * number of bytes available set to {@code offset} + {@code length}.
-     * 
+     *
      * @param buf
      *            the byte array to stream over.
      * @param offset
      *            the initial position in {@code buf} to start streaming from.
      * @param length
      *            the number of bytes available for streaming.
-     * @since Android 1.0
      */
     public ByteArrayInputStream(byte[] buf, int offset, int length) {
         // BEGIN android-note
@@ -99,9 +88,8 @@
      * Returns the number of bytes that are available before this stream will
      * block. This method returns the number of bytes yet to be read from the
      * source byte array.
-     * 
+     *
      * @return the number of bytes available before blocking.
-     * @since Android 1.0
      */
     @Override
     public synchronized int available() {
@@ -110,10 +98,9 @@
 
     /**
      * Closes this stream and frees resources associated with this stream.
-     * 
+     *
      * @throws IOException
      *             if an I/O error occurs while closing this stream.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -124,12 +111,11 @@
      * Sets a mark position in this ByteArrayInputStream. The parameter
      * {@code readlimit} is ignored. Sending {@code reset()} will reposition the
      * stream back to the marked position.
-     * 
+     *
      * @param readlimit
      *            ignored.
      * @see #markSupported()
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public synchronized void mark(int readlimit) {
@@ -140,11 +126,10 @@
      * Indicates whether this stream supports the {@code mark()} and
      * {@code reset()} methods. Returns {@code true} since this class supports
      * these methods.
-     * 
+     *
      * @return always {@code true}.
      * @see #mark(int)
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public boolean markSupported() {
@@ -155,9 +140,8 @@
      * Reads a single byte from the source byte array and returns it as an
      * integer in the range from 0 to 255. Returns -1 if the end of the source
      * array has been reached.
-     * 
+     *
      * @return the byte read or -1 if the end of this stream has been reached.
-     * @since Android 1.0
      */
     @Override
     public synchronized int read() {
@@ -168,7 +152,7 @@
      * Reads at most {@code len} bytes from this stream and stores
      * them in byte array {@code b} starting at {@code offset}. This
      * implementation reads bytes from the source byte array.
-     * 
+     *
      * @param b
      *            the byte array in which to store the bytes read.
      * @param offset
@@ -183,8 +167,7 @@
      *             {@code offset + length} is greater than the size of
      *             {@code b}.
      * @throws NullPointerException
-     *             if {@code b} is null.
-     * @since Android 1.0
+     *             if {@code b} is {@code null}.
      */
     @Override
     public synchronized int read(byte[] b, int offset, int length) {
@@ -222,9 +205,8 @@
      * Resets this stream to the last marked location. This implementation
      * resets the position to either the marked position, the start position
      * supplied in the constructor or 0 if neither has been provided.
-     * 
+     *
      * @see #mark(int)
-     * @since Android 1.0
      */
     @Override
     public synchronized void reset() {
@@ -236,11 +218,10 @@
      * {@code read()}s will not return these bytes unless {@code reset()} is
      * used. This implementation skips {@code count} number of bytes in the
      * target stream. It does nothing and returns 0 if {@code n} is negative.
-     * 
+     *
      * @param n
      *            the number of bytes to skip.
      * @return the number of bytes actually skipped.
-     * @since Android 1.0
      */
     @Override
     public synchronized long skip(long n) {
diff --git a/libcore/luni/src/main/java/java/io/ByteArrayOutputStream.java b/libcore/luni/src/main/java/java/io/ByteArrayOutputStream.java
index 8c6fa05..4d5a738 100644
--- a/libcore/luni/src/main/java/java/io/ByteArrayOutputStream.java
+++ b/libcore/luni/src/main/java/java/io/ByteArrayOutputStream.java
@@ -24,23 +24,17 @@
  * (internal) byte array. As bytes are written to this stream, the byte array
  * may be expanded to hold more bytes. When the writing is considered to be
  * finished, a copy of the byte array can be requested from the class.
- * 
+ *
  * @see ByteArrayInputStream
- * 
- * @since Android 1.0
  */
 public class ByteArrayOutputStream extends OutputStream {
     /**
      * The byte array containing the bytes written.
-     * 
-     * @since Android 1.0
      */
     protected byte[] buf;
 
     /**
      * The number of bytes written.
-     * 
-     * @since Android 1.0
      */
     protected int count;
 
@@ -48,8 +42,6 @@
      * Constructs a new ByteArrayOutputStream with a default size of 32 bytes.
      * If more than 32 bytes are written to this instance, the underlying byte
      * array will expand.
-     * 
-     * @since Android 1.0
      */
     public ByteArrayOutputStream() {
         super();
@@ -60,13 +52,12 @@
      * Constructs a new {@code ByteArrayOutputStream} with a default size of
      * {@code size} bytes. If more than {@code size} bytes are written to this
      * instance, the underlying byte array will expand.
-     * 
+     *
      * @param size
      *            initial size for the underlying byte array, must be
      *            non-negative.
      * @throws IllegalArgumentException
      *             if {@code size} < 0.
-     * @since Android 1.0
      */
     public ByteArrayOutputStream(int size) {
         super();
@@ -79,10 +70,9 @@
 
     /**
      * Closes this stream. This releases system resources used for this stream.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while attempting to close this stream.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -109,8 +99,6 @@
      * Resets this stream to the beginning of the underlying byte array. All
      * subsequent writes will overwrite any bytes previously stored in this
      * stream.
-     * 
-     * @since Android 1.0
      */
     public synchronized void reset() {
         count = 0;
@@ -118,9 +106,8 @@
 
     /**
      * Returns the total number of bytes written to this stream so far.
-     * 
+     *
      * @return the number of bytes written to this stream.
-     * @since Android 1.0
      */
     public int size() {
         return count;
@@ -130,9 +117,8 @@
      * Returns the contents of this ByteArrayOutputStream as a byte array. Any
      * changes made to the receiver after returning will not be reflected in the
      * byte array returned to the caller.
-     * 
+     *
      * @return this stream's current contents as a byte array.
-     * @since Android 1.0
      */
     public synchronized byte[] toByteArray() {
         byte[] newArray = new byte[count];
@@ -144,9 +130,8 @@
      * Returns the contents of this ByteArrayOutputStream as a string. Any
      * changes made to the receiver after returning will not be reflected in the
      * string returned to the caller.
-     * 
+     *
      * @return this stream's current contents as a string.
-     * @since Android 1.0
      */
 
     @Override
@@ -161,13 +146,12 @@
      * {@code c == (char)(((hibyte & 0xff) << 8) | (b & 0xff))}. This method is
      * deprecated and either {@link #toString()} or {@link #toString(String)}
      * should be used.
-     * 
+     *
      * @param hibyte
      *            the high byte of each resulting Unicode character.
      * @return this stream's current contents as a string with the high byte set
      *         to {@code hibyte}.
      * @deprecated Use {@link #toString()}.
-     * @since Android 1.0
      */
     @Deprecated
     public String toString(int hibyte) {
@@ -181,14 +165,13 @@
     /**
      * Returns the contents of this ByteArrayOutputStream as a string converted
      * according to the encoding declared in {@code enc}.
-     * 
+     *
      * @param enc
      *            a string representing the encoding to use when translating
      *            this stream to a string.
      * @return this stream's current contents as an encoded string.
      * @throws UnsupportedEncodingException
      *             if the provided encoding is not supported.
-     * @since Android 1.0
      */
     public String toString(String enc) throws UnsupportedEncodingException {
         return new String(buf, 0, count, enc);
@@ -197,18 +180,19 @@
     /**
      * Writes {@code count} bytes from the byte array {@code buffer} starting at
      * offset {@code index} to this stream.
-     * 
+     *
      * @param buffer
      *            the buffer to be written.
      * @param offset
      *            the initial position in {@code buffer} to retrieve bytes.
      * @param len
      *            the number of bytes of {@code buffer} to write.
+     * @throws NullPointerException
+     *             if {@code buffer} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code offset < 0} or {@code len < 0}, or if
      *             {@code offset + len} is greater than the length of
      *             {@code buffer}.
-     * @since Android 1.0
      */
     @Override
     public synchronized void write(byte[] buffer, int offset, int len) {
@@ -239,28 +223,26 @@
     /**
      * Writes the specified byte {@code oneByte} to the OutputStream. Only the
      * low order byte of {@code oneByte} is written.
-     * 
+     *
      * @param oneByte
      *            the byte to be written.
-     * @since Android 1.0
      */
     @Override
     public synchronized void write(int oneByte) {
         if (count == buf.length) {
             expand(1);
         }
-        buf[count++] = (byte)oneByte;
+        buf[count++] = (byte) oneByte;
     }
 
     /**
      * Takes the contents of this stream and writes it to the output stream
      * {@code out}.
-     * 
+     *
      * @param out
      *            an OutputStream on which to write the contents of this stream.
      * @throws IOException
      *             if an error occurs while writing to {@code out}.
-     * @since Android 1.0
      */
     public synchronized void writeTo(OutputStream out) throws IOException {
         out.write(buf, 0, count);
diff --git a/libcore/luni/src/main/java/java/io/CharArrayReader.java b/libcore/luni/src/main/java/java/io/CharArrayReader.java
index 95a8826..d2757f6 100644
--- a/libcore/luni/src/main/java/java/io/CharArrayReader.java
+++ b/libcore/luni/src/main/java/java/io/CharArrayReader.java
@@ -21,37 +21,27 @@
 
 /**
  * A specialized {@link Reader} for reading the contents of a char array.
- * 
+ *
  * @see CharArrayWriter
- * 
- * @since Android 1.0
  */
 public class CharArrayReader extends Reader {
     /**
      * The buffer for characters.
-     * 
-     * @since Android 1.0 
      */
     protected char buf[];
 
     /**
      * The current buffer position.
-     * 
-     * @since Android 1.0 
      */
     protected int pos;
 
     /**
      * The current mark position.
-     * 
-     * @since Android 1.0
      */
     protected int markedPos = -1;
 
     /**
      * The ending index of the buffer.
-     *
-     * @since Android 1.0 
      */
     protected int count;
 
@@ -59,10 +49,9 @@
      * Constructs a CharArrayReader on the char array {@code buf}. The size of
      * the reader is set to the length of the buffer and the object to to read
      * from is set to {@code buf}.
-     * 
+     *
      * @param buf
      *            the char array from which to read.
-     * @since Android 1.0
      */
     public CharArrayReader(char[] buf) {
         super(buf);
@@ -74,7 +63,7 @@
      * Constructs a CharArrayReader on the char array {@code buf}. The size of
      * the reader is set to {@code length} and the start position from which to
      * read the buffer is set to {@code offset}.
-     * 
+     *
      * @param buf
      *            the char array from which to read.
      * @param offset
@@ -84,7 +73,6 @@
      * @throws IllegalArgumentException
      *             if {@code offset < 0} or {@code length < 0}, or if
      *             {@code offset} is greater than the size of {@code buf} .
-     * @since Android 1.0
      */
     public CharArrayReader(char[] buf, int offset, int length) {
         super(buf);
@@ -92,7 +80,7 @@
         // Exception priorities (in case of multiple errors) differ from
         // RI, but are spec-compliant.
         // made implicit null check explicit,
-        // removed redundant check, used (offset | length) < 0 instead of 
+        // removed redundant check, used (offset | length) < 0 instead of
         // (offset < 0) || (length < 0) to safe one operation
         if (buf == null) {
             throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
@@ -103,6 +91,7 @@
         // END android-changed
         this.buf = buf;
         this.pos = offset;
+        this.markedPos = offset;
 
         /* This is according to spec */
         this.count = this.pos + length < buf.length ? length : buf.length;
@@ -112,8 +101,6 @@
      * This method closes this CharArrayReader. Once it is closed, you can no
      * longer read from it. Only the first invocation of this method has any
      * effect.
-     * 
-     * @since Android 1.0
      */
     @Override
     public void close() {
@@ -126,7 +113,7 @@
 
     /**
      * Indicates whether this reader is open.
-     * 
+     *
      * @return {@code true} if the reader is open, {@code false} otherwise.
      */
     private boolean isOpen() {
@@ -135,7 +122,7 @@
 
     /**
      * Indicates whether this reader is closed.
-     * 
+     *
      * @return {@code true} if the reader is closed, {@code false} otherwise.
      */
     private boolean isClosed() {
@@ -147,12 +134,11 @@
      * ignored for CharArrayReaders. Calling {@code reset()} will reposition the
      * reader back to the marked position provided the mark has not been
      * invalidated.
-     * 
+     *
      * @param readLimit
      *            ignored for CharArrayReaders.
      * @throws IOException
      *             if this reader is closed.
-     * @since Android 1.0
      */
     @Override
     public void mark(int readLimit) throws IOException {
@@ -167,11 +153,10 @@
     /**
      * Indicates whether this reader supports the {@code mark()} and
      * {@code reset()} methods.
-     * 
+     *
      * @return {@code true} for CharArrayReader.
      * @see #mark(int)
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public boolean markSupported() {
@@ -182,12 +167,11 @@
      * Reads a single character from this reader and returns it as an integer
      * with the two higher-order bytes set to 0. Returns -1 if no more
      * characters are available from this reader.
-     * 
+     *
      * @return the character read as an int or -1 if the end of the reader has
      *         been reached.
      * @throws IOException
      *             if this reader is closed.
-     * @since Android 1.0
      */
     @Override
     public int read() throws IOException {
@@ -207,7 +191,7 @@
      * stores them at {@code offset} in the character array {@code buf}.
      * Returns the number of characters actually read or -1 if the end of reader
      * was encountered.
-     * 
+     *
      * @param buffer
      *            the character array to store the characters read.
      * @param offset
@@ -223,7 +207,6 @@
      *             {@code buffer}.
      * @throws IOException
      *             if this reader is closed.
-     * @since Android 1.0
      */
     @Override
     public int read(char[] buffer, int offset, int len) throws IOException {
@@ -264,12 +247,11 @@
      * {@code false} if this reader may or may not block when {@code read} is
      * called. The implementation in CharArrayReader always returns {@code true}
      * even when it has been closed.
-     * 
+     *
      * @return {@code true} if this reader will not block when {@code read} is
      *         called, {@code false} if unknown or blocking will occur.
      * @throws IOException
      *             if this reader is closed.
-     * @since Android 1.0
      */
     @Override
     public boolean ready() throws IOException {
@@ -286,10 +268,9 @@
      * Invocations of {@code read()} and {@code skip()} will occur from this new
      * location. If this reader has not been marked, it is reset to the
      * beginning of the string.
-     * 
+     *
      * @throws IOException
      *             if this reader is closed.
-     * @since Android 1.0
      */
     @Override
     public void reset() throws IOException {
@@ -305,13 +286,12 @@
      * Skips {@code count} number of characters in this reader. Subsequent
      * {@code read()}s will not return these characters unless {@code reset()}
      * is used. This method does nothing and returns 0 if {@code n} is negative.
-     * 
+     *
      * @param n
      *            the number of characters to skip.
      * @return the number of characters actually skipped.
      * @throws IOException
      *             if this reader is closed.
-     * @since Android 1.0
      */
     @Override
     public long skip(long n) throws IOException {
diff --git a/libcore/luni/src/main/java/java/io/CharArrayWriter.java b/libcore/luni/src/main/java/java/io/CharArrayWriter.java
index 7e58b2b..6b3fa39 100644
--- a/libcore/luni/src/main/java/java/io/CharArrayWriter.java
+++ b/libcore/luni/src/main/java/java/io/CharArrayWriter.java
@@ -24,33 +24,25 @@
  * char array. As bytes are written to this writer, the char array may be
  * expanded to hold more characters. When the writing is considered to be
  * finished, a copy of the char array can be requested from the class.
- * 
+ *
  * @see CharArrayReader
- * 
- * @since Android 1.0
  */
 public class CharArrayWriter extends Writer {
 
     /**
      * The buffer for characters.
-     * 
-     * @since Android 1.0
      */
     protected char[] buf;
 
     /**
      * The ending index of the buffer.
-     * 
-     * @since Android 1.0
      */
     protected int count;
 
     /**
-     * Constructs a new CharArrayWriter which has a buffer allocated with the
-     * default size of 32 characters. This buffer is also used as the
+     * Constructs a new {@code CharArrayWriter} which has a buffer allocated
+     * with the default size of 32 characters. This buffer is also used as the
      * {@code lock} to synchronize access to this writer.
-     * 
-     * @since Android 1.0
      */
     public CharArrayWriter() {
         super();
@@ -59,15 +51,14 @@
     }
 
     /**
-     * Constructs a new CharArrayWriter which has a buffer allocated with the
-     * size of {@code initialSize} characters. The buffer is also used as the
-     * {@code lock} to synchronize access to this writer.
-     * 
+     * Constructs a new {@code CharArrayWriter} which has a buffer allocated
+     * with the size of {@code initialSize} characters. The buffer is also used
+     * as the {@code lock} to synchronize access to this writer.
+     *
      * @param initialSize
      *            the initial size of this CharArrayWriters buffer.
      * @throws IllegalArgumentException
      *             if {@code initialSize < 0}.
-     * @since Android 1.0
      */
     public CharArrayWriter(int initialSize) {
         super();
@@ -79,9 +70,7 @@
     }
 
     /**
-     * Closes this writer. The implementation in CharArrayWriter does nothing.
-     * 
-     * @since Android 1.0
+     * Closes this writer. The implementation in {@code CharArrayWriter} does nothing.
      */
     @Override
     public void close() {
@@ -94,15 +83,14 @@
             return;
         }
 
-        char[] newbuf = new char[buf.length + (2 * i)];
+        int newLen = Math.max(2 * buf.length, count + i);
+        char[] newbuf = new char[newLen];
         System.arraycopy(buf, 0, newbuf, 0, count);
         buf = newbuf;
     }
 
     /**
-     * Flushes this writer. The implementation in CharArrayWriter does nothing.
-     * 
-     * @since Android 1.0
+     * Flushes this writer. The implementation in {@code CharArrayWriter} does nothing.
      */
     @Override
     public void flush() {
@@ -113,8 +101,6 @@
      * Resets this writer. The current write position is reset to the beginning
      * of the buffer. All written characters are lost and the size of this
      * writer is set to 0.
-     * 
-     * @since Android 1.0
      */
     public void reset() {
         synchronized (lock) {
@@ -126,9 +112,8 @@
      * Returns the size of this writer, that is the number of characters it
      * stores. This number changes if this writer is reset or when more
      * characters are written to it.
-     * 
+     *
      * @return this CharArrayWriter's current size in characters.
-     * @since Android 1.0
      */
     public int size() {
         synchronized (lock) {
@@ -140,9 +125,8 @@
      * Returns the contents of the receiver as a char array. The array returned
      * is a copy and any modifications made to this writer after calling this
      * method are not reflected in the result.
-     * 
+     *
      * @return this CharArrayWriter's contents as a new char array.
-     * @since Android 1.0
      */
     public char[] toCharArray() {
         synchronized (lock) {
@@ -153,12 +137,11 @@
     }
 
     /**
-     * Returns the contents of this CharArrayWriter as a string. The string
-     * returned is a copy and any modifications made to this writer after
+     * Returns the contents of this {@code CharArrayWriter} as a string. The
+     * string returned is a copy and any modifications made to this writer after
      * calling this method are not reflected in the result.
-     * 
+     *
      * @return this CharArrayWriters contents as a new string.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -170,7 +153,7 @@
     /**
      * Writes {@code count} characters starting at {@code offset} in {@code c}
      * to this writer.
-     * 
+     *
      * @param c
      *            the non-null array containing characters to write.
      * @param offset
@@ -180,7 +163,6 @@
      * @throws IndexOutOfBoundsException
      *             if {@code offset < 0} or {@code len < 0}, or if
      *             {@code offset + len} is bigger than the size of {@code c}.
-     * @since Android 1.0
      */
     @Override
     public void write(char[] c, int offset, int len) {
@@ -210,10 +192,9 @@
      * Writes the specified character {@code oneChar} to this writer.
      * This implementation writes the two low order bytes of the integer
      * {@code oneChar} to the buffer.
-     * 
+     *
      * @param oneChar
      *            the character to write.
-     * @since Android 1.0
      */
     @Override
     public void write(int oneChar) {
@@ -226,7 +207,7 @@
     /**
      * Writes {@code count} number of characters starting at {@code offset} from
      * the string {@code str} to this CharArrayWriter.
-     * 
+     *
      * @param str
      *            the non-null string containing the characters to write.
      * @param offset
@@ -234,12 +215,11 @@
      * @param len
      *            the number of characters to retrieve and write.
      * @throws NullPointerException
-     *             if {@code str} is null.
+     *             if {@code str} is {@code null}.
      * @throws StringIndexOutOfBoundsException
      *             if {@code offset < 0} or {@code len < 0}, or if
      *             {@code offset + len} is bigger than the length of
      *             {@code str}.
-     * @since Android 1.0
      */
     @Override
     public void write(String str, int offset, int len) {
@@ -264,17 +244,16 @@
     }
 
     /**
-     * Writes the contents of this CharArrayWriter to another Writer. The output
-     * is all the characters that have been written to the receiver since the
-     * last reset or since it was created.
-     * 
+     * Writes the contents of this {@code CharArrayWriter} to another {@code
+     * Writer}. The output is all the characters that have been written to the
+     * receiver since the last reset or since it was created.
+     *
      * @param out
-     *            the non-null Writer on which to write the contents.
+     *            the non-null {@code Writer} on which to write the contents.
      * @throws NullPointerException
-     *             if {@code out} is null.
+     *             if {@code out} is {@code null}.
      * @throws IOException
      *             if an error occurs attempting to write out the contents.
-     * @since Android 1.0
      */
     public void writeTo(Writer out) throws IOException {
         synchronized (lock) {
@@ -283,13 +262,12 @@
     }
 
     /**
-     * Appends a char {@code c} to the CharArrayWriter. The method works the
-     * same way as {@code write(c)}.
-     * 
+     * Appends a char {@code c} to the {@code CharArrayWriter}. The method works
+     * the same way as {@code write(c)}.
+     *
      * @param c
      *            the character appended to the CharArrayWriter.
      * @return this CharArrayWriter.
-     * @since Android 1.0
      */
     @Override
     public CharArrayWriter append(char c) {
@@ -298,14 +276,14 @@
     }
 
     /**
-     * Appends a CharSequence {@code csq} to the CharArrayWriter. The method
+     * Appends a {@code CharSequence} to the {@code CharArrayWriter}. The method
      * works the same way as {@code write(csq.toString())}. If {@code csq} is
-     * null, then it will be substituted with the string "null".
-     * 
+     * {@code null}, then it will be substituted with the string {@code "null"}.
+     *
      * @param csq
-     *            the CharSequence appended to the CharArrayWriter, may be null.
+     *            the {@code CharSequence} appended to the {@code
+     *            CharArrayWriter}, may be {@code null}.
      * @return this CharArrayWriter.
-     * @since Android 1.0
      */
     @Override
     public CharArrayWriter append(CharSequence csq) {
@@ -318,26 +296,27 @@
     }
 
     /**
-     * Append a subsequence of a CharSequence {@code csq} to the
-     * CharArrayWriter. The first and last characters of the subsequence are
-     * specified by the parameters {@code start} and {@code end}. The
-     * CharArrayWriter.append({@code csq}) works the same way as
-     * {@code CharArrayWriter.write(csq.subSequence(start, end).toString)}. If
-     * {@code csq} is null, then it will be substituted with the string "null".
-     * 
+     * Append a subsequence of a {@code CharSequence} to the {@code
+     * CharArrayWriter}. The first and last characters of the subsequence are
+     * specified by the parameters {@code start} and {@code end}. A call to
+     * {@code CharArrayWriter.append(csq)} works the same way as {@code
+     * CharArrayWriter.write(csq.subSequence(start, end).toString)}. If {@code
+     * csq} is {@code null}, then it will be substituted with the string {@code
+     * "null"}.
+     *
      * @param csq
-     *            the CharSequence appended to the CharArrayWriter, may be null.
+     *            the {@code CharSequence} appended to the {@code
+     *            CharArrayWriter}, may be {@code null}.
      * @param start
-     *            the index of the first character in the CharSequence appended
-     *            to the CharArrayWriter.
+     *            the index of the first character in the {@code CharSequence}
+     *            appended to the {@code CharArrayWriter}.
      * @param end
-     *            the index of the character after the last one in the
-     *            CharSequence appended to the CharArrayWriter.
+     *            the index of the character after the last one in the {@code
+     *            CharSequence} appended to the {@code CharArrayWriter}.
      * @return this CharArrayWriter.
      * @throws IndexOutOfBoundsException
      *             if {@code start < 0}, {@code end < 0}, {@code start > end},
      *             or if {@code end} is greater than the length of {@code csq}.
-     * @since Android 1.0
      */
     @Override
     public CharArrayWriter append(CharSequence csq, int start, int end) {
diff --git a/libcore/luni/src/main/java/java/io/CharConversionException.java b/libcore/luni/src/main/java/java/io/CharConversionException.java
index 2247527..97dc186 100644
--- a/libcore/luni/src/main/java/java/io/CharConversionException.java
+++ b/libcore/luni/src/main/java/java/io/CharConversionException.java
@@ -19,8 +19,6 @@
 
 /**
  * The top level class for character conversion exceptions.
- * 
- * @since Android 1.0
  */
 public class CharConversionException extends IOException {
 
@@ -29,8 +27,6 @@
     /**
      * Constructs a new {@code CharConversionException} with its stack trace
      * filled in.
-     * 
-     * @since Android 1.0
      */
     public CharConversionException() {
         super();
@@ -39,10 +35,9 @@
     /**
      * Constructs a new {@code CharConversionException} with its stack trace and
      * detail message filled in.
-     * 
+     *
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public CharConversionException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/io/Closeable.java b/libcore/luni/src/main/java/java/io/Closeable.java
index 015b39a..94b6bd8 100644
--- a/libcore/luni/src/main/java/java/io/Closeable.java
+++ b/libcore/luni/src/main/java/java/io/Closeable.java
@@ -21,18 +21,15 @@
  * are not used any longer. This usually includes all sorts of
  * {@link InputStream}s and {@link OutputStream}s. Calling the {@code close}
  * method releases resources that the object holds.
- * 
- * @since Android 1.0
  */
 public interface Closeable {
 
     /**
      * Closes the object and release any system resources it holds. If the
      * object has already been closed, then invoking this method has no effect.
-     * 
+     *
      * @throws IOException
      *             if any error occurs when closing the object.
-     * @since Android 1.0
      */
     public void close() throws IOException;
 }
\ No newline at end of file
diff --git a/libcore/luni/src/main/java/java/io/DataInput.java b/libcore/luni/src/main/java/java/io/DataInput.java
index a199d2f..02a28d9 100644
--- a/libcore/luni/src/main/java/java/io/DataInput.java
+++ b/libcore/luni/src/main/java/java/io/DataInput.java
@@ -23,13 +23,12 @@
  * {@link DataOutput}. Types that can be read include byte, 16-bit short, 32-bit
  * int, 32-bit float, 64-bit long, 64-bit double, byte strings, and MUTF-8
  * strings.
- *  
+ *
  * <h3>MUTF-8 (Modified UTF-8) Encoding</h3>
  * <p>
  * When encoding strings as UTF, implementations of {@code DataInput} and
  * {@code DataOutput} use a slightly modified form of UTF-8, hereafter referred
  * to as MUTF-8. This form is identical to standard UTF-8, except:
- * </p>
  * <ul>
  * <li>Only the one-, two-, and three-byte encodings are used.</li>
  * <li>Code points in the range <code>U+10000</code> &hellip;
@@ -42,12 +41,9 @@
  * further information about character encoding. MUTF-8 is actually closer to
  * the (relatively less well-known) encoding <a
  * href="http://www.unicode.org/reports/tr26/">CESU-8</a> than to UTF-8 per se.
- * </p>
- * 
+ *
  * @see DataInputStream
  * @see RandomAccessFile
- * 
- * @since Android 1.0
  */
 public interface DataInput {
     /**
@@ -59,7 +55,6 @@
      * @throws IOException
      *             if an I/O error occurs while reading.
      * @see DataOutput#writeBoolean(boolean)
-     * @since Android 1.0
      */
     public abstract boolean readBoolean() throws IOException;
 
@@ -72,7 +67,6 @@
      * @throws IOException
      *             if an I/O error occurs while reading.
      * @see DataOutput#writeByte(int)
-     * @since Android 1.0
      */
     public abstract byte readByte() throws IOException;
 
@@ -85,7 +79,6 @@
      * @throws IOException
      *             if an I/O error occurs while reading.
      * @see DataOutput#writeChar(int)
-     * @since Android 1.0
      */
     public abstract char readChar() throws IOException;
 
@@ -98,7 +91,6 @@
      * @throws IOException
      *             if an I/O error occurs while reading.
      * @see DataOutput#writeDouble(double)
-     * @since Android 1.0
      */
     public abstract double readDouble() throws IOException;
 
@@ -111,7 +103,6 @@
      * @throws IOException
      *             if an I/O error occurs while reading.
      * @see DataOutput#writeFloat(float)
-     * @since Android 1.0
      */
     public abstract float readFloat() throws IOException;
 
@@ -127,7 +118,6 @@
      *             if an I/O error occurs while reading.
      * @see DataOutput#write(byte[])
      * @see DataOutput#write(byte[], int, int)
-     * @since Android 1.0
      */
     public abstract void readFully(byte[] buffer) throws IOException;
 
@@ -149,7 +139,6 @@
      *             if an I/O error occurs while reading.
      * @see DataOutput#write(byte[])
      * @see DataOutput#write(byte[], int, int)
-     * @since Android 1.0
      */
     public abstract void readFully(byte[] buffer, int offset, int count)
             throws IOException;
@@ -163,7 +152,6 @@
      * @throws IOException
      *             if an I/O error occurs while reading.
      * @see DataOutput#writeInt(int)
-     * @since Android 1.0
      */
     public abstract int readInt() throws IOException;
 
@@ -179,7 +167,6 @@
      *         request can be satisfied.
      * @throws IOException
      *             if an I/O error occurs while reading.
-     * @since Android 1.0
      */
     public abstract String readLine() throws IOException;
 
@@ -192,7 +179,6 @@
      * @throws IOException
      *             if an I/O error occurs while reading.
      * @see DataOutput#writeLong(long)
-     * @since Android 1.0
      */
     public abstract long readLong() throws IOException;
 
@@ -205,7 +191,6 @@
      * @throws IOException
      *             if an I/O error occurs while reading.
      * @see DataOutput#writeShort(int)
-     * @since Android 1.0
      */
     public abstract short readShort() throws IOException;
 
@@ -218,7 +203,6 @@
      * @throws IOException
      *             if an I/O error occurs while reading.
      * @see DataOutput#writeByte(int)
-     * @since Android 1.0
      */
     public abstract int readUnsignedByte() throws IOException;
 
@@ -231,7 +215,6 @@
      * @throws IOException
      *             if an I/O error occurs while reading.
      * @see DataOutput#writeShort(int)
-     * @since Android 1.0
      */
     public abstract int readUnsignedShort() throws IOException;
 
@@ -244,7 +227,6 @@
      * @throws IOException
      *             if an I/O error occurs while reading.
      * @see DataOutput#writeUTF(java.lang.String)
-     * @since Android 1.0
      */
     public abstract String readUTF() throws IOException;
 
@@ -258,7 +240,6 @@
      * @return the number of bytes actually skipped.
      * @throws IOException
      *             if a problem occurs during skipping.
-     * @since Android 1.0
      */
     public abstract int skipBytes(int count) throws IOException;
 }
diff --git a/libcore/luni/src/main/java/java/io/DataInputStream.java b/libcore/luni/src/main/java/java/io/DataInputStream.java
index 88b10a5..cb21986 100644
--- a/libcore/luni/src/main/java/java/io/DataInputStream.java
+++ b/libcore/luni/src/main/java/java/io/DataInputStream.java
@@ -21,38 +21,38 @@
 import org.apache.harmony.luni.util.Util;
 
 /**
- * Wraps an existing {@link InputStream} and reads typed data from it. 
+ * Wraps an existing {@link InputStream} and reads typed data from it.
  * Typically, this stream has been written by a DataOutputStream. Types that can
  * be read include byte, 16-bit short, 32-bit int, 32-bit float, 64-bit long,
  * 64-bit double, byte strings, and strings encoded in
  * {@link DataInput modified UTF-8}.
- * 
+ *
  * @see DataOutputStream
- * 
- * @since Android 1.0
  */
 public class DataInputStream extends FilterInputStream implements DataInput {
 
+    byte[] buff;
+
     /**
      * Constructs a new DataInputStream on the InputStream {@code in}. All
      * reads are then filtered through this stream. Note that data read by this
      * stream is not in a human readable format and was most likely created by a
      * DataOutputStream.
-     * 
+     *
      * @param in
      *            the source InputStream the filter reads from.
      * @see DataOutputStream
      * @see RandomAccessFile
-     * @since Android 1.0
      */
     public DataInputStream(InputStream in) {
         super(in);
+        buff = new byte[8];
     }
 
     /**
      * Reads bytes from this stream into the byte array {@code buffer}. Returns
      * the number of bytes that have been read.
-     * 
+     *
      * @param buffer
      *            the buffer to read bytes into.
      * @return the number of bytes that have been read or -1 if the end of the
@@ -61,7 +61,6 @@
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#write(byte[])
      * @see DataOutput#write(byte[], int, int)
-     * @since Android 1.0
      */
     @Override
     public final int read(byte[] buffer) throws IOException {
@@ -73,7 +72,7 @@
      * the byte array {@code buffer} starting at {@code offset}. Returns the
      * number of bytes that have been read or -1 if no bytes have been read and
      * the end of the stream has been reached.
-     * 
+     *
      * @param buffer
      *            the byte array in which to store the bytes read.
      * @param offset
@@ -87,7 +86,6 @@
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#write(byte[])
      * @see DataOutput#write(byte[], int, int)
-     * @since Android 1.0
      */
     @Override
     public final int read(byte[] buffer, int offset, int length)
@@ -97,7 +95,7 @@
 
     /**
      * Reads a boolean from this stream.
-     * 
+     *
      * @return the next boolean value from the source stream.
      * @throws EOFException
      *             if the end of the filtered stream is reached before one byte
@@ -105,7 +103,6 @@
      * @throws IOException
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#writeBoolean(boolean)
-     * @since Android 1.0
      */
     public final boolean readBoolean() throws IOException {
         int temp = in.read();
@@ -117,7 +114,7 @@
 
     /**
      * Reads an 8-bit byte value from this stream.
-     * 
+     *
      * @return the next byte value from the source stream.
      * @throws EOFException
      *             if the end of the filtered stream is reached before one byte
@@ -125,7 +122,6 @@
      * @throws IOException
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#writeByte(int)
-     * @since Android 1.0
      */
     public final byte readByte() throws IOException {
         int temp = in.read();
@@ -137,7 +133,7 @@
 
     /**
      * Reads a 16-bit character value from this stream.
-     * 
+     *
      * @return the next char value from the source stream.
      * @throws EOFException
      *             if the end of the filtered stream is reached before two bytes
@@ -145,20 +141,29 @@
      * @throws IOException
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#writeChar(int)
-     * @since Android 1.0
      */
     public final char readChar() throws IOException {
-        int b1 = in.read();
-        int b2 = in.read();
-        if ((b1 | b2) < 0) {
+        if (readToBuff(2) < 0){
             throw new EOFException();
         }
-        return (char) ((b1 << 8) + b2);
+        return (char) (((buff[0] & 0xff) << 8) | (buff[1] & 0xff));
+
+    }
+
+    private int readToBuff(int count) throws IOException {
+        int offset = 0;
+
+        while(offset < count) {
+            int bytesRead = in.read(buff, offset, count - offset);
+            if(bytesRead == -1) return bytesRead;
+            offset += bytesRead;
+        }
+        return offset;
     }
 
     /**
      * Reads a 64-bit double value from this stream.
-     * 
+     *
      * @return the next double value from the source stream.
      * @throws EOFException
      *             if the end of the filtered stream is reached before eight
@@ -166,7 +171,6 @@
      * @throws IOException
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#writeDouble(double)
-     * @since Android 1.0
      */
     public final double readDouble() throws IOException {
         return Double.longBitsToDouble(readLong());
@@ -174,7 +178,7 @@
 
     /**
      * Reads a 32-bit float value from this stream.
-     * 
+     *
      * @return the next float value from the source stream.
      * @throws EOFException
      *             if the end of the filtered stream is reached before four
@@ -182,7 +186,6 @@
      * @throws IOException
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#writeFloat(float)
-     * @since Android 1.0
      */
     public final float readFloat() throws IOException {
         return Float.intBitsToFloat(readInt());
@@ -192,7 +195,7 @@
      * Reads bytes from this stream into the byte array {@code buffer}. This
      * method will block until {@code buffer.length} number of bytes have been
      * read.
-     * 
+     *
      * @param buffer
      *            to read bytes into.
      * @throws EOFException
@@ -202,7 +205,6 @@
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#write(byte[])
      * @see DataOutput#write(byte[], int, int)
-     * @since Android 1.0
      */
     public final void readFully(byte[] buffer) throws IOException {
         readFully(buffer, 0, buffer.length);
@@ -213,7 +215,7 @@
      * buffer} starting at the position {@code offset}. This method blocks until
      * {@code length} bytes have been read. If {@code length} is zero, then this
      * method returns without reading any bytes.
-     * 
+     *
      * @param buffer
      *            the byte array into which the data is read.
      * @param offset
@@ -232,7 +234,6 @@
      * @throws NullPointerException
      *             if {@code buffer} or the source stream are null.
      * @see java.io.DataInput#readFully(byte[], int, int)
-     * @since Android 1.0
      */
     public final void readFully(byte[] buffer, int offset, int length)
             throws IOException {
@@ -271,7 +272,7 @@
 
     /**
      * Reads a 32-bit integer value from this stream.
-     * 
+     *
      * @return the next int value from the source stream.
      * @throws EOFException
      *             if the end of the filtered stream is reached before four
@@ -279,25 +280,13 @@
      * @throws IOException
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#writeInt(int)
-     * @since Android 1.0
      */
     public final int readInt() throws IOException {
-        // BEGIN android-changed
-        byte[] buf = new byte[4];
-        int nread = 0;
-        while (nread < 4) {
-          int nbytes = in.read(buf, nread, 4 - nread);
-          if (nbytes == -1) {
-              throw new EOFException();
-          }
-          nread += nbytes;
+        if (readToBuff(4) < 0){
+            throw new EOFException();
         }
-        int b1 = buf[0] & 0xff;
-        int b2 = buf[1] & 0xff;
-        int b3 = buf[2] & 0xff;
-        int b4 = buf[3] & 0xff;
-        return ((b1 << 24) + (b2 << 16) + (b3 << 8) + b4);
-        // END android-changed
+        return ((buff[0] & 0xff) << 24) | ((buff[1] & 0xff) << 16) |
+            ((buff[2] & 0xff) << 8) | (buff[3] & 0xff);
     }
 
     /**
@@ -305,17 +294,16 @@
      * source stream. A line is represented by zero or more characters followed
      * by {@code '\n'}, {@code '\r'}, {@code "\r\n"} or the end of the stream.
      * The string does not include the newline sequence.
-     * 
+     *
      * @return the contents of the line or {@code null} if no characters were
      *         read before the end of the source stream has been reached.
      * @throws IOException
      *             if a problem occurs while reading from this stream.
      * @deprecated Use {@link BufferedReader}
-     * @since Android 1.0
      */
     @Deprecated
     public final String readLine() throws IOException {
-        StringBuffer line = new StringBuffer(80); // Typical line length
+        StringBuilder line = new StringBuilder(80); // Typical line length
         boolean foundTerminator = false;
         while (true) {
             int nextByte = in.read();
@@ -350,7 +338,7 @@
 
     /**
      * Reads a 64-bit long value from this stream.
-     * 
+     *
      * @return the next long value from the source stream.
      * @throws EOFException
      *             if the end of the filtered stream is reached before eight
@@ -358,24 +346,22 @@
      * @throws IOException
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#writeLong(long)
-     * @since Android 1.0
      */
     public final long readLong() throws IOException {
-        int i1 = readInt();
-        int b1 = in.read();
-        int b2 = in.read();
-        int b3 = in.read();
-        int b4 = in.read();
-        if ((b1 | b2 | b3 | b4) < 0) {
+        if (readToBuff(8) < 0){
             throw new EOFException();
         }
-        return (((long) i1) << 32) + ((long) b1 << 24) + (b2 << 16) + (b3 << 8)
-                + b4;
+        int i1 = ((buff[0] & 0xff) << 24) | ((buff[1] & 0xff) << 16) |
+            ((buff[2] & 0xff) << 8) | (buff[3] & 0xff);
+        int i2 = ((buff[4] & 0xff) << 24) | ((buff[5] & 0xff) << 16) |
+            ((buff[6] & 0xff) << 8) | (buff[7] & 0xff);
+
+        return ((i1 & 0xffffffffL) << 32) | (i2 & 0xffffffffL);
     }
 
     /**
      * Reads a 16-bit short value from this stream.
-     * 
+     *
      * @return the next short value from the source stream.
      * @throws EOFException
      *             if the end of the filtered stream is reached before two bytes
@@ -383,29 +369,18 @@
      * @throws IOException
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#writeShort(int)
-     * @since Android 1.0
      */
     public final short readShort() throws IOException {
-        // BEGIN android-changed
-        byte[] buf = new byte[2];
-        int nread = 0;
-        while (nread < 2) {
-          int nbytes = in.read(buf, nread, 2 - nread);
-          if (nbytes == -1) {
-              throw new EOFException();
-          }
-          nread += nbytes;
+        if (readToBuff(2) < 0){
+            throw new EOFException();
         }
-        int b1 = buf[0] & 0xff;
-        int b2 = buf[1] & 0xff;
-        return (short) ((b1 << 8) + b2);
-        // END android-changed
+        return (short) (((buff[0] & 0xff) << 8) | (buff[1] & 0xff));
     }
 
     /**
      * Reads an unsigned 8-bit byte value from this stream and returns it as an
      * int.
-     * 
+     *
      * @return the next unsigned byte value from the source stream.
      * @throws EOFException
      *             if the end of the filtered stream has been reached before one
@@ -413,7 +388,6 @@
      * @throws IOException
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#writeByte(int)
-     * @since Android 1.0
      */
     public final int readUnsignedByte() throws IOException {
         int temp = in.read();
@@ -426,7 +400,7 @@
     /**
      * Reads a 16-bit unsigned short value from this stream and returns it as an
      * int.
-     * 
+     *
      * @return the next unsigned short value from the source stream.
      * @throws EOFException
      *             if the end of the filtered stream is reached before two bytes
@@ -434,21 +408,18 @@
      * @throws IOException
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#writeShort(int)
-     * @since Android 1.0
      */
     public final int readUnsignedShort() throws IOException {
-        int b1 = in.read();
-        int b2 = in.read();
-        if ((b1 | b2) < 0) {
+        if (readToBuff(2) < 0){
             throw new EOFException();
         }
-        return ((b1 << 8) + b2);
+        return (char) (((buff[0] & 0xff) << 8) | (buff[1] & 0xff));
     }
 
     /**
      * Reads an string encoded in {@link DataInput modified UTF-8} from this
      * stream.
-     * 
+     *
      * @return the next {@link DataInput MUTF-8} encoded string read from the
      *         source stream.
      * @throws EOFException if the end of the input is reached before the read
@@ -456,90 +427,28 @@
      * @throws IOException
      *             if a problem occurs while reading from this stream.
      * @see DataOutput#writeUTF(java.lang.String)
-     * @since Android 1.0
      */
     public final String readUTF() throws IOException {
-        int utfSize = readUnsignedShort();
-        return decodeUTF(utfSize);
+        return decodeUTF(readUnsignedShort());
     }
 
-    // BEGIN android-removed
-    // static final int MAX_BUF_SIZE = 8192;
-    //
-    // private static class CacheLock {
-    // }
-    //
-    // static final Object cacheLock = new CacheLock();
-    //
-    // static boolean useShared = true;
-    //
-    // static byte[] byteBuf = new byte[0];
-    //
-    // static char[] charBuf = new char[0];
-    // END android-removed
 
     String decodeUTF(int utfSize) throws IOException {
-        // BEGIN android-removed
-        // byte[] buf;
-        // char[] out = null;
-        // boolean makeBuf = true;
-        //
-        // /*
-        //  * Try to avoid the synchronization -- if we get a stale value for
-        //  * useShared then there is no foul below, but those that sync on the
-        //  * lock must see the right value.
-        //  */
-        // if (utfSize <= MAX_BUF_SIZE && useShared) {
-        //     synchronized (cacheLock) {
-        //         if (useShared) {
-        //             useShared = false;
-        //             makeBuf = false;
-        //         }
-        //     }
-        // }
-        // if (makeBuf) {
-        //     buf = new byte[utfSize];
-        //     out = new char[utfSize];
-        // } else {
-        //     /*
-        //      * Need to 'sample' byteBuf and charBuf before using them because
-        //      * they are not protected by the cacheLock. They may get out of sync
-        //      * with the static and one another, but that is ok because we
-        //      * explicitly check and fix their length after sampling.
-        //      */
-        //     buf = byteBuf;
-        //     if (buf.length < utfSize) {
-        //         buf = byteBuf = new byte[utfSize];
-        //     }
-        //     out = charBuf;
-        //     if (out.length < utfSize) {
-        //         out = charBuf = new char[utfSize];
-        //     }
-        // }
-        // END android-removed
-        // BEGIN android-added
+        return decodeUTF(utfSize, this);
+    }
+
+    private static String decodeUTF(int utfSize, DataInput in) throws IOException {
         byte[] buf = new byte[utfSize];
         char[] out = new char[utfSize];
-        // END android-added
-        readFully(buf, 0, utfSize);
-        String result;
-        result = Util.convertUTF8WithBuf(buf, out, 0, utfSize);
-        // BEGIN android-removed
-        // if (!makeBuf) {
-        //     /*
-        //      * Do not synchronize useShared on cacheLock, it will make it back
-        //      * to main storage at some point, and no harm until it does.
-        //      */
-        //     useShared = true;
-        // }
-        //END android-removed
-        return result;
+        in.readFully(buf, 0, utfSize);
+
+        return Util.convertUTF8WithBuf(buf, out, 0, utfSize);
     }
 
     /**
      * Reads a string encoded in {@link DataInput modified UTF-8} from the
      * {@code DataInput} stream {@code in}.
-     * 
+     *
      * @param in
      *            the input stream to read from.
      * @return the next {@link DataInput MUTF-8} encoded string from the source
@@ -547,19 +456,18 @@
      * @throws IOException
      *             if a problem occurs while reading from this stream.
      * @see DataOutputStream#writeUTF(java.lang.String)
-     * @since Android 1.0
      */
     public static final String readUTF(DataInput in) throws IOException {
-        return in.readUTF();
+        return decodeUTF(in.readUnsignedShort(), in);
     }
 
     /**
      * 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 will not throw an {@link EOFException} if the end of the
      * input is reached before {@code count} bytes where skipped.
-     * 
+     *
      * @param count
      *            the number of bytes to skip.
      * @return the number of bytes actually skipped.
@@ -567,7 +475,6 @@
      *             if a problem occurs during skipping.
      * @see #mark(int)
      * @see #reset()
-     * @since Android 1.0
      */
     public final int skipBytes(int count) throws IOException {
         int skipped = 0;
diff --git a/libcore/luni/src/main/java/java/io/DataOutput.java b/libcore/luni/src/main/java/java/io/DataOutput.java
index d028a18..8275958 100644
--- a/libcore/luni/src/main/java/java/io/DataOutput.java
+++ b/libcore/luni/src/main/java/java/io/DataOutput.java
@@ -23,35 +23,29 @@
  * DataInput. Types that can be written include byte, 16-bit short, 32-bit int,
  * 32-bit float, 64-bit long, 64-bit double, byte strings, and {@link DataInput
  * MUTF-8} encoded strings.
- * 
+ *
  * @see DataOutputStream
  * @see RandomAccessFile
- * 
- * @since Android 1.0
  */
 public interface DataOutput {
 
     /**
      * Writes the entire contents of the byte array {@code buffer} to this
      * stream.
-     * 
+     *
      * @param buffer
      *            the buffer to write.
      * @throws IOException
      *             if an I/O error occurs while writing.
      * @see DataInput#readFully(byte[])
      * @see DataInput#readFully(byte[], int, int)
-     * @since Android 1.0
      */
     public abstract void write(byte[] buffer) throws IOException;
-    // BEGIN android-note
-    // changed array notation to be consistent with the rest of harmony
-    // END android-note
 
     /**
      * Writes {@code count} bytes from the byte array {@code buffer} starting at
      * offset {@code index}.
-     * 
+     *
      * @param buffer
      *            the buffer to write.
      * @param offset
@@ -62,7 +56,6 @@
      *             if an I/O error occurs while writing.
      * @see DataInput#readFully(byte[])
      * @see DataInput#readFully(byte[], int, int)
-     * @since Android 1.0
      */
     public abstract void write(byte[] buffer, int offset, int count) throws IOException;
     // BEGIN android-note
@@ -71,51 +64,47 @@
 
     /**
      * Writes the specified 8-bit byte.
-     * 
+     *
      * @param oneByte
      *            the byte to write.
      * @throws IOException
      *             if an I/O error occurs while writing.
      * @see DataInput#readByte()
-     * @since Android 1.0
      */
     public abstract void write(int oneByte) throws IOException;
 
     /**
      * Writes the specified boolean.
-     * 
+     *
      * @param val
      *            the boolean value to write.
      * @throws IOException
      *             if an I/O error occurs while writing.
      * @see DataInput#readBoolean()
-     * @since Android 1.0
      */
     public abstract void writeBoolean(boolean val) throws IOException;
 
     /**
      * Writes the specified 8-bit byte.
-     * 
+     *
      * @param val
      *            the byte value to write.
      * @throws IOException
      *             if an I/O error occurs while writing.
      * @see DataInput#readByte()
      * @see DataInput#readUnsignedByte()
-     * @since Android 1.0
      */
     public abstract void writeByte(int val) throws IOException;
 
     /**
      * Writes the low order 8-bit bytes from the specified string.
-     * 
+     *
      * @param str
      *            the string containing the bytes to write.
      * @throws IOException
      *             if an I/O error occurs while writing.
      * @see DataInput#readFully(byte[])
      * @see DataInput#readFully(byte[],int,int)
-     * @since Android 1.0
      */
     public abstract void writeBytes(String str) throws IOException;
 
@@ -123,106 +112,95 @@
      * Writes the specified 16-bit character. Only the two least significant
      * bytes of the integer {@code oneByte} are written, with the higher one
      * written first. This represents the Unicode value of the char.
-     * 
+     *
      * @param val
      *            the character to write.
      * @throws IOException
      *             if an I/O error occurs while writing.
      * @see DataInput#readChar()
-     * @since Android 1.0
      */
     public abstract void writeChar(int val) throws IOException;
-    // BEGIN android-note
-    // renamed parameter because it was misleading
-    // END android-note
 
     /**
      * Writes the 16-bit characters contained in {@code str}.
-     * 
+     *
      * @param str
      *            the string that contains the characters to write.
      * @throws IOException
      *             if an I/O error occurs while writing.
      * @see DataInput#readChar()
-     * @since Android 1.0
      */
     public abstract void writeChars(String str) throws IOException;
 
     /**
      * Writes the specified 64-bit double. The resulting output is the eight
      * bytes returned by {@link Double#doubleToLongBits(double)}.
-     * 
+     *
      * @param val
      *            the double to write.
      * @throws IOException
      *             if an I/O error occurs while writing.
      * @see DataInput#readDouble()
-     * @since Android 1.0
      */
     public abstract void writeDouble(double val) throws IOException;
 
     /**
      * Writes the specified 32-bit float. The resulting output is the four bytes
      * returned by {@link Float#floatToIntBits(float)}.
-     * 
+     *
      * @param val
      *            the float to write.
      * @throws IOException
      *             if an I/O error occurs while writing.
      * @see DataInput#readFloat()
-     * @since Android 1.0
      */
     public abstract void writeFloat(float val) throws IOException;
 
     /**
      * Writes the specified 32-bit int. The resulting output is the four bytes,
      * highest order first, of {@code val}.
-     * 
+     *
      * @param val
      *            the int to write.
      * @throws IOException
      *             if an I/O error occurs while writing.
      * @see DataInput#readInt()
-     * @since Android 1.0
      */
     public abstract void writeInt(int val) throws IOException;
 
     /**
      * Writes the specified 64-bit long. The resulting output is the eight
      * bytes, highest order first, of {@code val}.
-     * 
+     *
      * @param val
      *            the long to write.
      * @throws IOException
      *             if an I/O error occurs while writing.
      * @see DataInput#readLong()
-     * @since Android 1.0
      */
     public abstract void writeLong(long val) throws IOException;
 
     /**
      * Writes the specified 16-bit short. Only the lower two bytes of {@code
      * val} are written with the higher one written first.
-     * 
+     *
      * @param val
      *            the short to write.
      * @throws IOException
      *             if an I/O error occurs while writing.
      * @see DataInput#readShort()
      * @see DataInput#readUnsignedShort()
-     * @since Android 1.0
      */
     public abstract void writeShort(int val) throws IOException;
 
     /**
      * Writes the specified string encoded in {@link DataInput modified UTF-8}.
-     * 
+     *
      * @param str
      *            the string to write encoded in {@link DataInput modified UTF-8}.
      * @throws IOException
      *             if an I/O error occurs while writing.
      * @see DataInput#readUTF()
-     * @since Android 1.0
      */
     public abstract void writeUTF(String str) throws IOException;
 }
diff --git a/libcore/luni/src/main/java/java/io/DataOutputStream.java b/libcore/luni/src/main/java/java/io/DataOutputStream.java
index 7f45c58..18e04a5 100644
--- a/libcore/luni/src/main/java/java/io/DataOutputStream.java
+++ b/libcore/luni/src/main/java/java/io/DataOutputStream.java
@@ -24,41 +24,37 @@
  * Typically, this stream can be read in by DataInputStream. Types that can be
  * written include byte, 16-bit short, 32-bit int, 32-bit float, 64-bit long,
  * 64-bit double, byte strings, and {@link DataInput MUTF-8} encoded strings.
- * 
+ *
  * @see DataInputStream
- * 
- * @since Android 1.0
  */
 public class DataOutputStream extends FilterOutputStream implements DataOutput {
 
     /**
      * The number of bytes written out so far.
-     * 
-     * @since Android 1.0
      */
     protected int written;
+    byte buff[];
 
     /**
      * Constructs a new {@code DataOutputStream} on the {@code OutputStream}
      * {@code out}. Note that data written by this stream is not in a human
      * readable form but can be reconstructed by using a {@link DataInputStream}
      * on the resulting output.
-     * 
+     *
      * @param out
      *            the target stream for writing.
-     * @since Android 1.0
      */
     public DataOutputStream(OutputStream out) {
         super(out);
+        buff = new byte[8];
     }
 
     /**
      * Flushes this stream to ensure all pending data is sent out to the target
      * stream. This implementation then also flushes the target stream.
-     * 
+     *
      * @throws IOException
      *             if an error occurs attempting to flush this stream.
-     * @since Android 1.0
      */
     @Override
     public void flush() throws IOException {
@@ -67,9 +63,8 @@
 
     /**
      * Returns the total number of bytes written to the target stream so far.
-     * 
+     *
      * @return the number of bytes written to the target stream.
-     * @since Android 1.0
      */
     public final int size() {
         if (written < 0) {
@@ -81,7 +76,7 @@
     /**
      * Writes {@code count} bytes from the byte array {@code buffer} starting at
      * {@code offset} to the target stream.
-     * 
+     *
      * @param buffer
      *            the buffer to write to the target stream.
      * @param offset
@@ -94,7 +89,6 @@
      *             if {@code buffer} is {@code null}.
      * @see DataInputStream#readFully(byte[])
      * @see DataInputStream#readFully(byte[], int, int)
-     * @since Android 1.0
      */
     @Override
     public void write(byte[] buffer, int offset, int count) throws IOException {
@@ -111,13 +105,12 @@
     /**
      * Writes a byte to the target stream. Only the least significant byte of
      * the integer {@code oneByte} is written.
-     * 
+     *
      * @param oneByte
      *            the byte to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see DataInputStream#readByte()
-     * @since Android 1.0
      */
     @Override
     public void write(int oneByte) throws IOException {
@@ -127,13 +120,12 @@
 
     /**
      * Writes a boolean to the target stream.
-     * 
+     *
      * @param val
      *            the boolean value to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see DataInputStream#readBoolean()
-     * @since Android 1.0
      */
     public final void writeBoolean(boolean val) throws IOException {
         out.write(val ? 1 : 0);
@@ -143,14 +135,13 @@
     /**
      * Writes an 8-bit byte to the target stream. Only the least significant
      * byte of the integer {@code val} is written.
-     * 
+     *
      * @param val
      *            the byte value to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see DataInputStream#readByte()
      * @see DataInputStream#readUnsignedByte()
-     * @since Android 1.0
      */
     public final void writeByte(int val) throws IOException {
         out.write(val);
@@ -159,14 +150,13 @@
 
     /**
      * Writes the low order bytes from a string to the target stream.
-     * 
+     *
      * @param str
      *            the string containing the bytes to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see DataInputStream#readFully(byte[])
      * @see DataInputStream#readFully(byte[],int,int)
-     * @since Android 1.0
      */
     public final void writeBytes(String str) throws IOException {
         if (str.length() == 0) {
@@ -184,31 +174,30 @@
      * Writes a 16-bit character to the target stream. Only the two lower bytes
      * of the integer {@code val} are written, with the higher one written
      * first. This corresponds to the Unicode value of {@code val}.
-     * 
+     *
      * @param val
      *            the character to write to the target stream
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see DataInputStream#readChar()
-     * @since Android 1.0
      */
     public final void writeChar(int val) throws IOException {
-        out.write(val >> 8);
-        out.write(val);
+        buff[0] = (byte) (val >> 8);
+        buff[1] = (byte) val;
+        out.write(buff, 0, 2);
         written += 2;
     }
 
     /**
      * Writes the 16-bit characters contained in {@code str} to the target
      * stream.
-     * 
+     *
      * @param str
      *            the string that contains the characters to write to this
      *            stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see DataInputStream#readChar()
-     * @since Android 1.0
      */
     public final void writeChars(String str) throws IOException {
         byte newBytes[] = new byte[str.length() * 2];
@@ -224,13 +213,12 @@
     /**
      * Writes a 64-bit double to the target stream. The resulting output is the
      * eight bytes resulting from calling Double.doubleToLongBits().
-     * 
+     *
      * @param val
      *            the double to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see DataInputStream#readDouble()
-     * @since Android 1.0
      */
     public final void writeDouble(double val) throws IOException {
         writeLong(Double.doubleToLongBits(val));
@@ -239,13 +227,12 @@
     /**
      * Writes a 32-bit float to the target stream. The resulting output is the
      * four bytes resulting from calling Float.floatToIntBits().
-     * 
+     *
      * @param val
      *            the float to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see DataInputStream#readFloat()
-     * @since Android 1.0
      */
     public final void writeFloat(float val) throws IOException {
         writeInt(Float.floatToIntBits(val));
@@ -254,63 +241,68 @@
     /**
      * Writes a 32-bit int to the target stream. The resulting output is the
      * four bytes, highest order first, of {@code val}.
-     * 
+     *
      * @param val
      *            the int to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see DataInputStream#readInt()
-     * @since Android 1.0
      */
     public final void writeInt(int val) throws IOException {
-        out.write(val >> 24);
-        out.write(val >> 16);
-        out.write(val >> 8);
-        out.write(val);
+        buff[0] = (byte) (val >> 24);
+        buff[1] = (byte) (val >> 16);
+        buff[2] = (byte) (val >> 8);
+        buff[3] = (byte) val;
+        out.write(buff, 0, 4);
         written += 4;
     }
 
     /**
      * Writes a 64-bit long to the target stream. The resulting output is the
      * eight bytes, highest order first, of {@code val}.
-     * 
+     *
      * @param val
      *            the long to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see DataInputStream#readLong()
-     * @since Android 1.0
      */
     public final void writeLong(long val) throws IOException {
-        writeInt((int) (val >> 32));
-        writeInt((int) val);
+        buff[0] = (byte) (val >> 56);
+        buff[1] = (byte) (val >> 48);
+        buff[2] = (byte) (val >> 40);
+        buff[3] = (byte) (val >> 32);
+        buff[4] = (byte) (val >> 24);
+        buff[5] = (byte) (val >> 16);
+        buff[6] = (byte) (val >> 8);
+        buff[7] = (byte) val;
+        out.write(buff, 0, 8);
+        written += 8;
     }
 
     /**
      * 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
      * written first.
-     * 
+     *
      * @param val
      *            the short to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see DataInputStream#readShort()
      * @see DataInputStream#readUnsignedShort()
-     * @since Android 1.0
      */
     public final void writeShort(int val) throws IOException {
-        writeChar(val);
+        buff[0] = (byte) (val >> 8);
+        buff[1] = (byte) val;
+        out.write(buff, 0, 2);
+        written += 2;
     }
-    
-    // BEGIN android-added
-    static final int MAX_BUF_SIZE = 8192;
-    // END android-added
-    
+
     /**
      * Writes the specified encoded in {@link DataInput modified UTF-8} to this
      * stream.
-     * 
+     *
      * @param str
      *            the string to write to the target stream encoded in
      *            {@link DataInput modified UTF-8}.
@@ -319,58 +311,14 @@
      * @throws UTFDataFormatException
      *             if the encoded string is longer than 65535 bytes.
      * @see DataInputStream#readUTF()
-     * @since Android 1.0
      */
     public final void writeUTF(String str) throws IOException {
-        int length = str.length();
-        // BEGIN android-changed
-        if (length <= MAX_BUF_SIZE / 3) {
-            int size = length * 3;
-            byte[] utfBytes = new byte[size];
-            // boolean makeBuf = true;
-            // synchronized (DataInputStream.byteBuf) {
-            //     if (DataInputStream.useShared) {
-            //         DataInputStream.useShared = false;
-            //         makeBuf = false;
-            //     }
-            // }
-            // if (makeBuf) {
-            //     utfBytes = new byte[size];
-            // } else {
-            //     if (DataInputStream.byteBuf.length < size) {
-            //         DataInputStream.byteBuf = new byte[size];
-            //     }
-            //     utfBytes = DataInputStream.byteBuf;
-            // }
-            int utfIndex = 0;
-            for (int i = 0; i < length; i++) {
-                int charValue = str.charAt(i);
-                if (charValue > 0 && charValue <= 127) {
-                    utfBytes[utfIndex++] = (byte) charValue;
-                } else if (charValue <= 2047) {
-                    utfBytes[utfIndex++] = (byte) (0xc0 | (0x1f & (charValue >> 6)));
-                    utfBytes[utfIndex++] = (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));
-                }
-            }
-            writeShort(utfIndex);
-            write(utfBytes, 0, utfIndex);
-            // if (!makeBuf) {
-            //     DataInputStream.useShared = true;
-            // }
-        } else {
-            long utfCount;
-            if (length <= 65535 && (utfCount = countUTFBytes(str)) <= 65535) {
-                writeShort((int) utfCount);
-                writeUTFBytes(str, utfCount);
-            } else {
-                throw new UTFDataFormatException(Msg.getString("K0068")); //$NON-NLS-1$
-            }
+        long utfCount = countUTFBytes(str);
+        if (utfCount > 65535) {
+            throw new UTFDataFormatException(Msg.getString("K0068")); //$NON-NLS-1$
         }
-        // END android-changed
+        writeShort((int) utfCount);
+        writeUTFBytes(str, utfCount);
     }
 
     long countUTFBytes(String str) {
@@ -389,76 +337,23 @@
     }
 
     void writeUTFBytes(String str, long count) throws IOException {
-        boolean single = true;
         int size = (int) count;
-        // BEGIN android-changed
-        if (count > MAX_BUF_SIZE) {
-            single = false;
-            size = MAX_BUF_SIZE;
-        }
+        int length = str.length();
         byte[] utfBytes = new byte[size];
-        // END android-changed
-        // BEGIN android-removed
-        // boolean makeBuf = true;
-        // if (DataInputStream.useShared) {
-        //     synchronized (DataInputStream.cacheLock) {
-        //         if (DataInputStream.useShared) {
-        //             DataInputStream.useShared = false;
-        //             makeBuf = false;
-        //         }
-        //     }
-        // }
-        // if (makeBuf) {
-        //     utfBytes = new byte[size];
-        // } else {
-        //     // byteBuf is not protected by the cacheLock, so sample it first
-        //     utfBytes = DataInputStream.byteBuf;
-        //     if (utfBytes.length < size) {
-        //         utfBytes = DataInputStream.byteBuf = new byte[size];
-        //     }
-        // }
-        // END android-removed
-
-        int utfIndex = 0, i = 0, length = str.length();
-        int end = length;
-        while (i < length) {
-            if (!single) {
-                end = i + ((utfBytes.length - utfIndex) / 3);
-                if (end > length) {
-                    end = length;
-                }
-            }
-            for (int j = i; j < end; j++) {
-                int charValue = str.charAt(j);
-                if (charValue > 0 && charValue <= 127) {
-                    utfBytes[utfIndex++] = (byte) charValue;
-                } else if (charValue <= 2047) {
-                    utfBytes[utfIndex++] = (byte) (0xc0 | (0x1f & (charValue >> 6)));
-                    utfBytes[utfIndex++] = (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));
-                }
-            }
-            if (single || utfIndex > utfBytes.length - 300) {
-                write(utfBytes, 0, utfIndex);
-                if (single) {
-                    return;
-                }
-                utfIndex = 0;
-            }
-            i = end;
+        int utfIndex = 0;
+        for (int i = 0; i < length; i++) {
+            int charValue = str.charAt(i);
+            if (charValue > 0 && charValue <= 127) {
+                utfBytes[utfIndex++] = (byte) charValue;
+            } else if (charValue <= 2047) {
+                utfBytes[utfIndex++] = (byte) (0xc0 | (0x1f & (charValue >> 6)));
+                utfBytes[utfIndex++] = (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));
+             }
         }
-        if (utfIndex > 0) {
-            write(utfBytes, 0, utfIndex);
-        }
-        // BEGIN android-removed
-        // if (!makeBuf) {
-        //     // Update the useShared flag optimistically (see DataInputStream
-        //     // equivalent)
-        //     DataInputStream.useShared = true;
-        // }
-        // END android-removed
+        write(utfBytes, 0, utfIndex);
     }
 }
diff --git a/libcore/luni/src/main/java/java/io/EOFException.java b/libcore/luni/src/main/java/java/io/EOFException.java
index 40beadd..7999f43 100644
--- a/libcore/luni/src/main/java/java/io/EOFException.java
+++ b/libcore/luni/src/main/java/java/io/EOFException.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when a program encounters the end of a file or stream during an input
  * operation.
- * 
- * @since Android 1.0
  */
 public class EOFException extends IOException {
 
@@ -29,8 +27,6 @@
 
     /**
      * Constructs a new {@code EOFException} with its stack trace filled in.
-     * 
-     * @since Android 1.0
      */
     public EOFException() {
         super();
@@ -42,7 +38,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public EOFException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/io/EmulatedFields.java b/libcore/luni/src/main/java/java/io/EmulatedFields.java
index 4ef241d..a947a52 100644
--- a/libcore/luni/src/main/java/java/io/EmulatedFields.java
+++ b/libcore/luni/src/main/java/java/io/EmulatedFields.java
@@ -103,17 +103,18 @@
     }
 
     /**
-     * Return a boolean indicating if the field named <code>name</code> has
-     * been assigned a value explicitly (false) or if it still holds a default
-     * value for the type (true) because it hasn't been assigned to yet.
+     * Returns {@code true} indicating the field called {@code name} has not had
+     * a value explicitly assigned and that it still holds a default value for
+     * its type, or {@code false} indicating that the field named has been
+     * assigned a value explicitly.
      * 
      * @param name
-     *            a String, the name of the field to test
-     * @return <code>true</code> if <code>name</code> still holds its
-     *         default value, <code>false</code> otherwise
+     *            the name of the field to test.
+     * @return {@code true} if {@code name} still holds its default value,
+     *         {@code false} otherwise
      * 
      * @throws IllegalArgumentException
-     *             If <code>name</code> is null
+     *             if {@code name} is {@code null}
      */
     public boolean defaulted(String name) throws IllegalArgumentException {
         ObjectSlot slot = findSlot(name, null);
@@ -124,23 +125,23 @@
     }
 
     /**
-     * Find and return an ObjectSlot that corresponds to a field named
-     * <code>fieldName</code> and type <code>fieldType</code>. If the field
-     * type <code>fieldType</code> corresponds to a primitive type, the field
-     * type has to match exactly or <code>null</code> is returned. If the
-     * field type <code>fieldType</code> corresponds to an object type, the
-     * field type has to be compatible in terms of assignment, or null is
-     * returned. If <code>fieldType</code> is <code>null</code>, no such
-     * compatibility checking is performed and the slot is returned.
+     * Finds and returns an ObjectSlot that corresponds to a field named {@code
+     * fieldName} and type {@code fieldType}. If the field type {@code
+     * fieldType} corresponds to a primitive type, the field type has to match
+     * exactly or {@code null} is returned. If the field type {@code fieldType}
+     * corresponds to an object type, the field type has to be compatible in
+     * terms of assignment, or null is returned. If {@code fieldType} is {@code
+     * null}, no such compatibility checking is performed and the slot is
+     * returned.
      * 
      * @param fieldName
-     *            A String, the name of the field to find
+     *            the name of the field to find
      * @param fieldType
-     *            A Class, the type of the field. This will be used to test
-     *            compatibility. If null, no testing is done, the corresponding
-     *            slot is returned.
-     * @return If there is no field with that name, or no compatible field
-     *         (relative to <code>fieldType</code>)
+     *            the type of the field. This will be used to test
+     *            compatibility. If {@code null}, no testing is done, the
+     *            corresponding slot is returned.
+     * @return the object slot, or {@code null} if there is no field with that
+     *         name, or no compatible field (relative to {@code fieldType})
      */
     private ObjectSlot findSlot(String fieldName, Class<?> fieldType) {
         boolean isPrimitive = fieldType != null && fieldType.isPrimitive();
@@ -187,19 +188,19 @@
     }
 
     /**
-     * Find and return the byte value of a given field named <code>name</code>
+     * Finds and returns the byte value of a given field named {@code name}
      * in the receiver. If the field has not been assigned any value yet, the
-     * default value <code>defaultValue</code> is returned instead.
+     * default value {@code defaultValue} is returned instead.
      * 
      * @param name
-     *            A String, the name of the field to find
+     *            the name of the field to find.
      * @param defaultValue
-     *            Return value in case the field has not been assigned to yet.
+     *            return value in case the field has not been assigned to yet.
      * @return the value of the given field if it has been assigned, the default
-     *         value otherwise
+     *         value otherwise.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public byte get(String name, byte defaultValue)
             throws IllegalArgumentException {
@@ -213,19 +214,19 @@
     }
 
     /**
-     * Find and return the char value of a given field named <code>name</code>
-     * in the receiver. If the field has not been assigned any value yet, the
-     * default value <code>defaultValue</code> is returned instead.
+     * Finds and returns the char value of a given field named {@code name} in the
+     * receiver. If the field has not been assigned any value yet, the default
+     * value {@code defaultValue} is returned instead.
      * 
      * @param name
-     *            A String, the name of the field to find
+     *            the name of the field to find.
      * @param defaultValue
-     *            Return value in case the field has not been assigned to yet.
+     *            return value in case the field has not been assigned to yet.
      * @return the value of the given field if it has been assigned, the default
-     *         value otherwise
+     *         value otherwise.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public char get(String name, char defaultValue)
             throws IllegalArgumentException {
@@ -239,19 +240,19 @@
     }
 
     /**
-     * Find and return the double value of a given field named <code>name</code>
+     * Finds and returns the double value of a given field named {@code name}
      * in the receiver. If the field has not been assigned any value yet, the
-     * default value <code>defaultValue</code> is returned instead.
+     * default value {@code defaultValue} is returned instead.
      * 
      * @param name
-     *            A String, the name of the field to find
+     *            the name of the field to find.
      * @param defaultValue
-     *            Return value in case the field has not been assigned to yet.
+     *            return value in case the field has not been assigned to yet.
      * @return the value of the given field if it has been assigned, the default
-     *         value otherwise
+     *         value otherwise.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public double get(String name, double defaultValue)
             throws IllegalArgumentException {
@@ -265,19 +266,19 @@
     }
 
     /**
-     * Find and return the float value of a given field named <code>name</code>
-     * in the receiver. If the field has not been assigned any value yet, the
-     * default value <code>defaultValue</code> is returned instead.
+     * Finds and returns the float value of a given field named {@code name} in
+     * the receiver. If the field has not been assigned any value yet, the
+     * default value {@code defaultValue} is returned instead.
      * 
      * @param name
-     *            A String, the name of the field to find
+     *            the name of the field to find.
      * @param defaultValue
-     *            Return value in case the field has not been assigned to yet.
+     *            return value in case the field has not been assigned to yet.
      * @return the value of the given field if it has been assigned, the default
-     *         value otherwise
+     *         value otherwise.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public float get(String name, float defaultValue)
             throws IllegalArgumentException {
@@ -291,19 +292,19 @@
     }
 
     /**
-     * Find and return the int value of a given field named <code>name</code>
-     * in the receiver. If the field has not been assigned any value yet, the
-     * default value <code>defaultValue</code> is returned instead.
+     * Finds and returns the int value of a given field named {@code name} in the
+     * receiver. If the field has not been assigned any value yet, the default
+     * value {@code defaultValue} is returned instead.
      * 
      * @param name
-     *            A String, the name of the field to find
+     *            the name of the field to find.
      * @param defaultValue
-     *            Return value in case the field has not been assigned to yet.
+     *            return value in case the field has not been assigned to yet.
      * @return the value of the given field if it has been assigned, the default
-     *         value otherwise
+     *         value otherwise.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public int get(String name, int defaultValue)
             throws IllegalArgumentException {
@@ -317,19 +318,19 @@
     }
 
     /**
-     * Find and return the long value of a given field named <code>name</code>
-     * in the receiver. If the field has not been assigned any value yet, the
-     * default value <code>defaultValue</code> is returned instead.
+     * Finds and returns the long value of a given field named {@code name} in the
+     * receiver. If the field has not been assigned any value yet, the default
+     * value {@code defaultValue} is returned instead.
      * 
      * @param name
-     *            A String, the name of the field to find
+     *            the name of the field to find.
      * @param defaultValue
-     *            Return value in case the field has not been assigned to yet.
+     *            return value in case the field has not been assigned to yet.
      * @return the value of the given field if it has been assigned, the default
-     *         value otherwise
+     *         value otherwise.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public long get(String name, long defaultValue)
             throws IllegalArgumentException {
@@ -343,19 +344,19 @@
     }
 
     /**
-     * Find and return the Object value of a given field named <code>name</code>
-     * in the receiver. If the field has not been assigned any value yet, the
-     * default value <code>defaultValue</code> is returned instead.
+     * Finds and returns the Object value of a given field named {@code name} in
+     * the receiver. If the field has not been assigned any value yet, the
+     * default value {@code defaultValue} is returned instead.
      * 
      * @param name
-     *            A String, the name of the field to find
+     *            the name of the field to find.
      * @param defaultValue
-     *            Return value in case the field has not been assigned to yet.
+     *            return value in case the field has not been assigned to yet.
      * @return the value of the given field if it has been assigned, the default
-     *         value otherwise
+     *         value otherwise.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public Object get(String name, Object defaultValue)
             throws IllegalArgumentException {
@@ -368,19 +369,19 @@
     }
 
     /**
-     * Find and return the short value of a given field named <code>name</code>
-     * in the receiver. If the field has not been assigned any value yet, the
-     * default value <code>defaultValue</code> is returned instead.
+     * Finds and returns the short value of a given field named {@code name} in
+     * the receiver. If the field has not been assigned any value yet, the
+     * default value {@code defaultValue} is returned instead.
      * 
      * @param name
-     *            A String, the name of the field to find
+     *            the name of the field to find.
      * @param defaultValue
-     *            Return value in case the field has not been assigned to yet.
+     *            return value in case the field has not been assigned to yet.
      * @return the value of the given field if it has been assigned, the default
-     *         value otherwise
+     *         value otherwise.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public short get(String name, short defaultValue)
             throws IllegalArgumentException {
@@ -394,20 +395,19 @@
     }
 
     /**
-     * Find and return the boolean value of a given field named
-     * <code>name</code> in the receiver. If the field has not been assigned
-     * any value yet, the default value <code>defaultValue</code> is returned
-     * instead.
+     * Finds and returns the boolean value of a given field named {@code name} in
+     * the receiver. If the field has not been assigned any value yet, the
+     * default value {@code defaultValue} is returned instead.
      * 
      * @param name
-     *            A String, the name of the field to find
+     *            the name of the field to find.
      * @param defaultValue
-     *            Return value in case the field has not been assigned to yet.
+     *            return value in case the field has not been assigned to yet.
      * @return the value of the given field if it has been assigned, the default
-     *         value otherwise
+     *         value otherwise.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public boolean get(String name, boolean defaultValue)
             throws IllegalArgumentException {
@@ -421,16 +421,16 @@
     }
 
     /**
-     * Find and set the byte value of a given field named <code>name</code> in
-     * the receiver.
+     * Find and set the byte value of a given field named {@code name} in the
+     * receiver.
      * 
      * @param name
-     *            A String, the name of the field to set
+     *            the name of the field to set.
      * @param value
-     *            New value for the field.
+     *            new value for the field.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public void put(String name, byte value) throws IllegalArgumentException {
         ObjectSlot slot = findSlot(name, Byte.TYPE);
@@ -442,16 +442,16 @@
     }
 
     /**
-     * Find and set the char value of a given field named <code>name</code> in
-     * the receiver.
+     * Find and set the char value of a given field named {@code name} in the
+     * receiver.
      * 
      * @param name
-     *            A String, the name of the field to set
+     *            the name of the field to set.
      * @param value
-     *            New value for the field.
+     *            new value for the field.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public void put(String name, char value) throws IllegalArgumentException {
         ObjectSlot slot = findSlot(name, Character.TYPE);
@@ -463,16 +463,16 @@
     }
 
     /**
-     * Find and set the double value of a given field named <code>name</code>
-     * in the receiver.
+     * Find and set the double value of a given field named {@code name} in the
+     * receiver.
      * 
      * @param name
-     *            A String, the name of the field to set
+     *            the name of the field to set.
      * @param value
-     *            New value for the field.
+     *            new value for the field.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public void put(String name, double value) throws IllegalArgumentException {
         ObjectSlot slot = findSlot(name, Double.TYPE);
@@ -484,16 +484,16 @@
     }
 
     /**
-     * Find and set the float value of a given field named <code>name</code>
-     * in the receiver.
+     * Find and set the float value of a given field named {@code name} in the
+     * receiver.
      * 
      * @param name
-     *            A String, the name of the field to set
+     *            the name of the field to set.
      * @param value
-     *            New value for the field.
+     *            new value for the field.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public void put(String name, float value) throws IllegalArgumentException {
         ObjectSlot slot = findSlot(name, Float.TYPE);
@@ -505,16 +505,16 @@
     }
 
     /**
-     * Find and set the int value of a given field named <code>name</code> in
-     * the receiver.
+     * Find and set the int value of a given field named {@code name} in the
+     * receiver.
      * 
      * @param name
-     *            A String, the name of the field to set
+     *            the name of the field to set.
      * @param value
-     *            New value for the field.
+     *            new value for the field.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public void put(String name, int value) throws IllegalArgumentException {
         ObjectSlot slot = findSlot(name, Integer.TYPE);
@@ -526,16 +526,16 @@
     }
 
     /**
-     * Find and set the long value of a given field named <code>name</code> in
-     * the receiver.
+     * Find and set the long value of a given field named {@code name} in the
+     * receiver.
      * 
      * @param name
-     *            A String, the name of the field to set
+     *            the name of the field to set.
      * @param value
-     *            New value for the field.
+     *            new value for the field.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public void put(String name, long value) throws IllegalArgumentException {
         ObjectSlot slot = findSlot(name, Long.TYPE);
@@ -547,16 +547,16 @@
     }
 
     /**
-     * Find and set the Object value of a given field named <code>name</code>
-     * in the receiver.
+     * Find and set the Object value of a given field named {@code name} in the
+     * receiver.
      * 
      * @param name
-     *            A String, the name of the field to set
+     *            the name of the field to set.
      * @param value
-     *            New value for the field.
+     *            new value for the field.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public void put(String name, Object value) throws IllegalArgumentException {
         Class<?> valueClass = null;
@@ -572,16 +572,16 @@
     }
 
     /**
-     * Find and set the short value of a given field named <code>name</code>
-     * in the receiver.
+     * Find and set the short value of a given field named {@code name} in the
+     * receiver.
      * 
      * @param name
-     *            A String, the name of the field to set
+     *            the name of the field to set.
      * @param value
-     *            New value for the field.
+     *            new value for the field.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public void put(String name, short value) throws IllegalArgumentException {
         ObjectSlot slot = findSlot(name, Short.TYPE);
@@ -593,16 +593,16 @@
     }
 
     /**
-     * Find and set the boolean value of a given field named <code>name</code>
-     * in the receiver.
+     * Find and set the boolean value of a given field named {@code name} in the
+     * receiver.
      * 
      * @param name
-     *            A String, the name of the field to set
+     *            the name of the field to set.
      * @param value
-     *            New value for the field.
+     *            new value for the field.
      * 
      * @throws IllegalArgumentException
-     *             If the corresponding field can not be found.
+     *             if the corresponding field can not be found.
      */
     public void put(String name, boolean value) throws IllegalArgumentException {
         ObjectSlot slot = findSlot(name, Boolean.TYPE);
diff --git a/libcore/luni/src/main/java/java/io/Externalizable.java b/libcore/luni/src/main/java/java/io/Externalizable.java
index 03049eb..d07f0b7 100644
--- a/libcore/luni/src/main/java/java/io/Externalizable.java
+++ b/libcore/luni/src/main/java/java/io/Externalizable.java
@@ -20,8 +20,6 @@
 /**
  * Defines an interface for classes that want to be serializable, but have their
  * own binary representation.
- * 
- * @since Android 1.0
  */
 public interface Externalizable extends Serializable {
     /**
@@ -33,7 +31,6 @@
      *             if an error occurs attempting to read from {@code input}.
      * @throws ClassNotFoundException
      *             if the class of the instance being loaded cannot be found.
-     * @since Android 1.0
      */
     public void readExternal(ObjectInput input) throws IOException,
             ClassNotFoundException;
@@ -45,7 +42,6 @@
      *            the ObjectOutput to write the object to.
      * @throws IOException
      *             if an error occurs attempting to write to {@code output}.
-     * @since Android 1.0
      */
     public void writeExternal(ObjectOutput output) throws IOException;
 }
diff --git a/libcore/luni/src/main/java/java/io/File.java b/libcore/luni/src/main/java/java/io/File.java
index f4e8623..c802995 100644
--- a/libcore/luni/src/main/java/java/io/File.java
+++ b/libcore/luni/src/main/java/java/io/File.java
@@ -21,15 +21,12 @@
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.security.AccessController;
+import java.security.SecureRandom;
 import java.util.ArrayList;
-// BEGIN android-added
-import java.util.Collections;
-// END android-added
 import java.util.List;
 
-// BEGIN android-removed
-// import org.apache.harmony.luni.util.DeleteOnExit;
-// END android-removed
+import org.apache.harmony.luni.internal.io.FileCanonPathCache;
+import org.apache.harmony.luni.util.DeleteOnExit;
 import org.apache.harmony.luni.util.Msg;
 import org.apache.harmony.luni.util.PriviAction;
 import org.apache.harmony.luni.util.Util;
@@ -45,50 +42,39 @@
  * <p>
  * When manipulating file paths, the static fields of this class may be used to
  * determine the platform specific separators.
- * 
+ *
  * @see java.io.Serializable
  * @see java.lang.Comparable
- * 
- * @since Android 1.0
  */
 public class File implements Serializable, Comparable<File> {
+
     private static final long serialVersionUID = 301077366599181567L;
 
+    private static final String EMPTY_STRING = ""; //$NON-NLS-1$
+
     private String path;
 
     transient byte[] properPath;
 
     /**
-     * The system dependent file separator character. Since Android is a Unix-
-     * based system, this defaults to '/'.
-     * 
-     * @since Android 1.0
+     * The system dependent file separator character.
      */
     public static final char separatorChar;
 
     /**
      * The system dependent file separator string. The initial value of this
-     * field is the system property "file.separator". Since Android is a Unix-
-     * based system, this defaults to "/".
-     * 
-     * @since Android 1.0
+     * field is the system property "file.separator".
      */
     public static final String separator;
 
     /**
-     * The system dependent path separator character. Since Android is a Unix-
-     * based system, this defaults to ':'.
-     * 
-     * @since Android 1.0
+     * The system dependent path separator character.
      */
     public static final char pathSeparatorChar;
 
     /**
      * The system dependent path separator string. The initial value of this
-     * field is the system property "path.separator". Since Android is a Unix-
-     * based system, this defaults to ':'.
-     * 
-     * @since Android 1.0
+     * field is the system property "path.separator".
      */
     public static final String pathSeparator;
 
@@ -115,14 +101,13 @@
 
     /**
      * Constructs a new file using the specified directory and name.
-     * 
+     *
      * @param dir
      *            the directory where the file is stored.
      * @param name
      *            the file's name.
      * @throws NullPointerException
-     *             if {@code name} is null.
-     * @since Android 1.0
+     *             if {@code name} is {@code null}.
      */
     public File(File dir, String name) {
         if (name == null) {
@@ -137,10 +122,9 @@
 
     /**
      * Constructs a new file using the specified path.
-     * 
+     *
      * @param path
      *            the path to be used for the file.
-     * @since Android 1.0
      */
     public File(String path) {
         // path == null check & NullPointerException thrown by fixSlashes
@@ -150,14 +134,13 @@
     /**
      * Constructs a new File using the specified directory path and file name,
      * placing a path separator between the two.
-     * 
+     *
      * @param dirPath
      *            the path to the directory where the file is stored.
      * @param name
      *            the file's name.
      * @throws NullPointerException
-     *             if {@code name} is null.
-     * @since Android 1.0
+     *             if {@code name} is {@code null}.
      */
     public File(String dirPath, String name) {
         if (name == null) {
@@ -175,7 +158,7 @@
      * needs to be an absolute and hierarchical Unified Resource Identifier with
      * file scheme and non-empty path component, but with undefined authority,
      * query or fragment components.
-     * 
+     *
      * @param uri
      *            the Unified Resource Identifier that is used to construct this
      *            file.
@@ -183,7 +166,6 @@
      *             if {@code uri} does not comply with the conditions above.
      * @see #toURI
      * @see java.net.URI
-     * @since Android 1.0
      */
     public File(URI uri) {
         // check pre-conditions
@@ -193,7 +175,7 @@
 
     private String calculatePath(String dirPath, String name) {
         dirPath = fixSlashes(dirPath);
-        if (!name.equals("")) { //$NON-NLS-1$
+        if (!name.equals(EMPTY_STRING) || dirPath.equals(EMPTY_STRING)) {
             // Remove all the proceeding separator chars from name
             name = fixSlashes(name);
 
@@ -217,36 +199,37 @@
         return dirPath;
     }
 
+    @SuppressWarnings("nls")
     private void checkURI(URI uri) {
         if (!uri.isAbsolute()) {
-            throw new IllegalArgumentException(Msg.getString("K031a", uri)); //$NON-NLS-1$
-        } else if (!uri.getRawSchemeSpecificPart().startsWith("/")) { //$NON-NLS-1$
-            throw new IllegalArgumentException(Msg.getString("K031b", uri)); //$NON-NLS-1$
+            throw new IllegalArgumentException(Msg.getString("K031a", uri));
+        } else if (!uri.getRawSchemeSpecificPart().startsWith("/")) {
+            throw new IllegalArgumentException(Msg.getString("K031b", uri));
         }
 
         String temp = uri.getScheme();
-        if (temp == null || !temp.equals("file")) { //$NON-NLS-1$
-            throw new IllegalArgumentException(Msg.getString("K031c", uri)); //$NON-NLS-1$
+        if (temp == null || !temp.equals("file")) {
+            throw new IllegalArgumentException(Msg.getString("K031c", uri));
         }
 
         temp = uri.getRawPath();
         if (temp == null || temp.length() == 0) {
-            throw new IllegalArgumentException(Msg.getString("K031d", uri)); //$NON-NLS-1$
+            throw new IllegalArgumentException(Msg.getString("K031d", uri));
         }
 
         if (uri.getRawAuthority() != null) {
-            throw new IllegalArgumentException(Msg.getString(
-                    "K031e", new String[] { "authority", uri.toString() })); //$NON-NLS-1$ //$NON-NLS-2$
+            throw new IllegalArgumentException(Msg.getString("K031e",
+                    new String[] { "authority", uri.toString() }));
         }
 
         if (uri.getRawQuery() != null) {
-            throw new IllegalArgumentException(Msg.getString(
-                    "K031e", new String[] { "query", uri.toString() })); //$NON-NLS-1$//$NON-NLS-2$
+            throw new IllegalArgumentException(Msg.getString("K031e",
+                    new String[] { "query", uri.toString() }));
         }
 
         if (uri.getRawFragment() != null) {
-            throw new IllegalArgumentException(Msg.getString(
-                    "K031e", new String[] { "fragment", uri.toString() })); //$NON-NLS-1$ //$NON-NLS-2$
+            throw new IllegalArgumentException(Msg.getString("K031e",
+                    new String[] { "fragment", uri.toString() }));
         }
     }
 
@@ -259,9 +242,8 @@
      * file systems, each with its own platform-dependent root. Further, the
      * canonical pathname of any file on the system will always begin with one
      * of the returned file system roots.
-     * 
+     *
      * @return the array of file system roots.
-     * @since Android 1.0
      */
     public static File[] listRoots() {
         byte[][] rootsList = rootsImpl();
@@ -293,7 +275,8 @@
         char newPath[] = origPath.toCharArray();
         for (int i = 0; i < length; i++) {
             char pathChar = newPath[i];
-            if (pathChar == '\\' || pathChar == '/') {
+            if ((separatorChar == '\\' && pathChar == '\\')
+                || pathChar == '/') {
                 /* UNC Name requires 2 leading slashes */
                 if ((foundSlash && i == uncIndex) || !foundSlash) {
                     newPath[newLength++] = separatorChar;
@@ -319,42 +302,40 @@
                 && (newLength > (uncIndex + 1) || (newLength == 2 && newPath[0] != separatorChar))) {
             newLength--;
         }
-        String tempPath = new String(newPath, 0, newLength);
-        // If it's the same keep it identical for SecurityManager purposes
-        if (!tempPath.equals(origPath)) {
-            return tempPath;
-        }
-        return origPath;
+
+        return new String(newPath, 0, newLength);
     }
 
     /**
      * Indicates whether the current context is allowed to read from this file.
-     * 
+     *
      * @return {@code true} if this file can be read, {@code false} otherwise.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies the
      *             read request.
-     * @since Android 1.0
      */
     public boolean canRead() {
+        if (path.length() == 0) {
+            return false;
+        }
         SecurityManager security = System.getSecurityManager();
         if (security != null) {
             security.checkRead(path);
         }
+        byte[] pp = properPath(true);
         // BEGIN android-changed
-        return exists() && isReadableImpl(properPath(true));
+        return exists() && isReadableImpl(pp);
         // END android-changed
     }
 
     /**
      * Indicates whether the current context is allowed to write to this file.
-     * 
+     *
      * @return {@code true} if this file can be written, {@code false}
      *         otherwise.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies the
      *             write request.
-     * @since Android 1.0
      */
     public boolean canWrite() {
         SecurityManager security = System.getSecurityManager();
@@ -375,13 +356,12 @@
     /**
      * Returns the relative sort ordering of the paths for this file and the
      * file {@code another}. The ordering is platform dependent.
-     * 
+     *
      * @param another
      *            a file to compare this file to
      * @return an int determined by comparing the two paths. Possible values are
      *         described in the Comparable interface.
      * @see Comparable
-     * @since Android 1.0
      */
     public int compareTo(File another) {
         if (caseSensitive) {
@@ -392,13 +372,12 @@
 
     /**
      * Deletes this file. Directories must be empty before they will be deleted.
-     * 
+     *
      * @return {@code true} if this file was deleted, {@code false} otherwise.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies the
      *             request.
      * @see java.lang.SecurityManager#checkDelete
-     * @since Android 1.0
      */
     public boolean delete() {
         SecurityManager security = System.getSecurityManager();
@@ -418,13 +397,12 @@
 
     /**
      * Schedules this file to be automatically deleted once the virtual machine
-     * terminates. This will only happen when the virtual machine terminates 
+     * terminates. This will only happen when the virtual machine terminates
      * normally as described by the Java Language Specification section 12.9.
-     * 
+     *
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies the
      *             request.
-     * @since Android 1.0
      */
     public void deleteOnExit() {
         SecurityManager security = System.getSecurityManager();
@@ -439,12 +417,11 @@
     /**
      * Compares {@code obj} to this file and returns {@code true} if they
      * represent the <em>same</em> object using a path specific comparison.
-     * 
+     *
      * @param obj
      *            the object to compare this file with.
      * @return {@code true} if {@code obj} is the same as this object,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object obj) {
@@ -460,13 +437,13 @@
     /**
      * Returns a boolean indicating whether this file can be found on the
      * underlying file system.
-     * 
+     *
      * @return {@code true} if this file exists, {@code false} otherwise.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies read
      *             access to this file.
      * @see #getPath
-     * @since Android 1.0
+     * @see java.lang.SecurityManager#checkRead(FileDescriptor)
      */
     public boolean exists() {
         if (path.length() == 0) {
@@ -483,22 +460,20 @@
 
     /**
      * Returns the absolute path of this file.
-     * 
+     *
      * @return the absolute file path.
      * @see java.lang.SecurityManager#checkPropertyAccess
-     * @since Android 1.0
      */
     public String getAbsolutePath() {
         byte[] absolute = properPath(false);
-        return Util.toString(absolute);
+        return Util.toUTF8String(absolute);
     }
 
     /**
      * Returns a new file constructed using the absolute path of this file.
-     * 
+     *
      * @return a new file from this file's absolute path.
      * @see java.lang.SecurityManager#checkPropertyAccess
-     * @since Android 1.0
      */
     public File getAbsoluteFile() {
         return new File(this.getAbsolutePath());
@@ -513,42 +488,26 @@
      * with a direct directory reference. If the file does not exist,
      * getCanonicalPath() may not resolve any references and simply returns an
      * absolute path name or throws an IOException.
-     * 
+     *
      * @return the canonical path of this file.
      * @throws IOException
      *             if an I/O error occurs.
      * @see java.lang.SecurityManager#checkPropertyAccess
-     * @since Android 1.0
      */
     public String getCanonicalPath() throws IOException {
         byte[] result = properPath(false);
+        String absPath = Util.toUTF8String(result);
+        String canonPath = FileCanonPathCache.get(absPath);
 
-        boolean exists = false;
-        byte[] pathBytes = result;
-        do {
-            byte[] linkBytes = getLinkImpl(pathBytes);
-            if (linkBytes == pathBytes) {
-                break;
-            }
-            if (linkBytes[0] == separatorChar) {
-                pathBytes = linkBytes;
-            } else {
-                int index = pathBytes.length - 1;
-                while (pathBytes[index] != separatorChar) {
-                    index--;
-                }
-                byte[] temp = new byte[index + 1 + linkBytes.length];
-                System.arraycopy(pathBytes, 0, temp, 0, index + 1);
-                System.arraycopy(linkBytes, 0, temp, index + 1,
-                        linkBytes.length);
-                pathBytes = temp;
-            }
-            exists = existsImpl(pathBytes);
-        } while (exists);
-        if (exists) {
-            result = pathBytes;
+        if (canonPath != null) {
+            return canonPath;
         }
-
+        if(separatorChar == '/') {
+            // resolve the full path first
+            result = resolveLink(result, result.length, false);
+            // resolve the parent directories
+            result = resolve(result);
+        }
         int numSeparators = 1;
         for (int i = 0; i < result.length; i++) {
             if (result[i] == separatorChar) {
@@ -614,18 +573,106 @@
         newResult[newLength] = 0;
         newResult = getCanonImpl(newResult);
         newLength = newResult.length;
-        return Util.toString(newResult, 0, newLength);
+        canonPath = Util.toUTF8String(newResult, 0, newLength);
+        FileCanonPathCache.put(absPath, canonPath);
+        return canonPath;
+    }
+
+    /*
+     * Resolve symbolic links in the parent directories.
+     */
+    private byte[] resolve(byte[] newResult) throws IOException {
+        int last = 1, nextSize, linkSize;
+        byte[] linkPath = newResult, bytes;
+        boolean done, inPlace;
+        for (int i = 1; i <= newResult.length; i++) {
+            if (i == newResult.length || newResult[i] == separatorChar) {
+                done = i >= newResult.length - 1;
+                // if there is only one segment, do nothing
+                if (done && linkPath.length == 1) {
+                    return newResult;
+                }
+                inPlace = false;
+                if (linkPath == newResult) {
+                    bytes = newResult;
+                    // if there are no symbolic links, terminate the C string
+                    // instead of copying
+                    if (!done) {
+                        inPlace = true;
+                        newResult[i] = '\0';
+                    }
+                } else {
+                    nextSize = i - last + 1;
+                    linkSize = linkPath.length;
+                    if (linkPath[linkSize - 1] == separatorChar) {
+                        linkSize--;
+                    }
+                    bytes = new byte[linkSize + nextSize];
+                    System.arraycopy(linkPath, 0, bytes, 0, linkSize);
+                    System.arraycopy(newResult, last - 1, bytes, linkSize,
+                            nextSize);
+                    // the full path has already been resolved
+                }
+                if (done) {
+                    return bytes;
+                }
+                linkPath = resolveLink(bytes, inPlace ? i : bytes.length, true);
+                if (inPlace) {
+                    newResult[i] = '/';
+                }
+                last = i + 1;
+            }
+        }
+        throw new InternalError();
+    }
+
+    /*
+     * Resolve a symbolic link. While the path resolves to an existing path,
+     * keep resolving. If an absolute link is found, resolve the parent
+     * directories if resolveAbsolute is true.
+     */
+    private byte[] resolveLink(byte[] pathBytes, int length,
+            boolean resolveAbsolute) throws IOException {
+        boolean restart = false;
+        byte[] linkBytes, temp;
+        do {
+            linkBytes = getLinkImpl(pathBytes);
+            if (linkBytes == pathBytes) {
+                break;
+            }
+            if (linkBytes[0] == separatorChar) {
+                // link to an absolute path, if resolving absolute paths,
+                // resolve the parent dirs again
+                restart = resolveAbsolute;
+                pathBytes = linkBytes;
+            } else {
+                int last = length - 1;
+                while (pathBytes[last] != separatorChar) {
+                    last--;
+                }
+                last++;
+                temp = new byte[last + linkBytes.length];
+                System.arraycopy(pathBytes, 0, temp, 0, last);
+                System.arraycopy(linkBytes, 0, temp, last, linkBytes.length);
+                pathBytes = temp;
+            }
+            length = pathBytes.length;
+        } while (existsImpl(pathBytes));
+        // resolve the parent directories
+        if (restart) {
+            return resolve(pathBytes);
+        }
+        return pathBytes;
     }
 
     /**
      * Returns a new file created using the canonical path of this file.
      * Equivalent to {@code new File(this.getCanonicalPath())}.
-     * 
+     *
      * @return the new file constructed from this file's canonical path.
      * @throws IOException
      *             if an I/O error occurs.
      * @see java.lang.SecurityManager#checkPropertyAccess
-     * @since Android 1.0
      */
     public File getCanonicalFile() throws IOException {
         return new File(getCanonicalPath());
@@ -635,10 +682,9 @@
 
     /**
      * Returns the name of the file or directory represented by this file.
-     * 
+     *
      * @return this file's name or an empty string if there is no name part in
      *         the file's path.
-     * @since Android 1.0
      */
     public String getName() {
         int separatorIndex = path.lastIndexOf(separator);
@@ -650,9 +696,8 @@
      * Returns the pathname of the parent of this file. This is the path up to
      * but not including the last name. {@code null} is returned if there is no
      * parent.
-     * 
+     *
      * @return this file's parent pathname or {@code null}.
-     * @since Android 1.0
      */
     public String getParent() {
         int length = path.length(), firstInPath = 0;
@@ -677,9 +722,8 @@
      * Returns a new file made from the pathname of the parent of this file.
      * This is the path up to but not including the last name. {@code null} is
      * returned when there is no parent.
-     * 
+     *
      * @return a new file representing this file's parent or {@code null}.
-     * @since Android 1.0
      */
     public File getParentFile() {
         String tempParent = getParent();
@@ -691,9 +735,8 @@
 
     /**
      * Returns the path of this file.
-     * 
+     *
      * @return this file's path.
-     * @since Android 1.0
      */
     public String getPath() {
         return path;
@@ -702,10 +745,9 @@
     /**
      * Returns an integer hash code for the receiver. Any two objects for which
      * {@code equals} returns {@code true} must return the same hash code.
-     * 
+     *
      * @return this files's hash value.
      * @see #equals
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -721,11 +763,10 @@
      * the character '/'; on Windows it is absolute if either it starts with
      * '\', '/', '\\' (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
-     * @since Android 1.0
      */
     public boolean isAbsolute() {
         // BEGIN android-changed
@@ -741,13 +782,12 @@
     /**
      * Indicates if this file represents a <em>directory</em> on the
      * underlying file system.
-     * 
+     *
      * @return {@code true} if this file is a directory, {@code false}
      *         otherwise.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies read
      *             access to this file.
-     * @since Android 1.0
      */
     public boolean isDirectory() {
         if (path.length() == 0) {
@@ -765,12 +805,11 @@
     /**
      * Indicates if this file represents a <em>file</em> on the underlying
      * file system.
-     * 
+     *
      * @return {@code true} if this file is a file, {@code false} otherwise.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies read
      *             access to this file.
-     * @since Android 1.0
      */
     public boolean isFile() {
         if (path.length() == 0) {
@@ -787,16 +826,15 @@
 
     /**
      * Returns whether or not this file is a hidden file as defined by the
-     * operating system. The notion of "hidden" is system-dependent. For
-     * Unix systems (like Android) a file is considered hidden if its name
-     * starts with a ".". For Windows systems there is an explicit flag in the
-     * file system for this purpose.
-     * 
+     * operating system. The notion of "hidden" is system-dependent. For Unix
+     * systems a file is considered hidden if its name starts with a ".". For
+     * Windows systems there is an explicit flag in the file system for this
+     * purpose.
+     *
      * @return {@code true} if the file is hidden, {@code false} otherwise.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies read
      *             access to this file.
-     * @since Android 1.0
      */
     public boolean isHidden() {
         if (path.length() == 0) {
@@ -822,12 +860,11 @@
     /**
      * Returns the time when this file was last modified, measured in
      * milliseconds since January 1st, 1970, midnight.
-     * 
+     *
      * @return the time when this file was last modified.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies read
      *             access to this file.
-     * @since Android 1.0
      */
     public long lastModified() {
         SecurityManager security = System.getSecurityManager();
@@ -847,7 +884,7 @@
     /**
      * Sets the time this file was last modified, measured in milliseconds since
      * January 1st, 1970, midnight.
-     * 
+     *
      * @param time
      *            the last modification time for this file.
      * @return {@code true} if the operation is successful, {@code false}
@@ -857,7 +894,6 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies write
      *             access to this file.
-     * @since Android 1.0
      */
     public boolean setLastModified(long time) {
         if (time < 0) {
@@ -875,13 +911,12 @@
     /**
      * Marks this file or directory to be read-only as defined by the operating
      * system.
-     * 
+     *
      * @return {@code true} if the operation is successful, {@code false}
      *         otherwise.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies write
      *             access to this file.
-     * @since Android 1.0
      */
     public boolean setReadOnly() {
         SecurityManager security = System.getSecurityManager();
@@ -895,12 +930,11 @@
 
     /**
      * Returns the length of this file in bytes.
-     * 
+     *
      * @return the number of bytes in this file.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies read
      *             access to this file.
-     * @since Android 1.0
      */
     public long length() {
         SecurityManager security = System.getSecurityManager();
@@ -914,35 +948,42 @@
 
     /**
      * Returns an array of strings with the file names in the directory
-     * represented by this file. The result is {@ null} if this file is not a
-     * directory.
+     * represented by this file. The result is {@code null} if this file is not
+     * a directory.
      * <p>
      * The entries {@code .} and {@code ..} representing the current and parent
      * directory are not returned as part of the list.
-     * </p>
-     * 
+     *
      * @return an array of strings with file names or {@code null}.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies read
      *             access to this file.
      * @see #isDirectory
-     * @since Android 1.0
+     * @see java.lang.SecurityManager#checkRead(FileDescriptor)
      */
     public java.lang.String[] list() {
         SecurityManager security = System.getSecurityManager();
         if (security != null) {
             security.checkRead(path);
         }
-        if (!isDirectory()) {
+
+        if (path.length() == 0) {
             return null;
         }
-        byte[][] implList = listImpl(properPath(true));
+
+        byte[] bs = properPath(true);
+        if (!isDirectoryImpl(bs) || !existsImpl(bs) || !isReadableImpl(bs)) {
+            return null;
+        }
+
+        byte[][] implList = listImpl(bs);
         if (implList == null) {
+            // empty list
             return new String[0];
         }
         String result[] = new String[implList.length];
         for (int index = 0; index < implList.length; index++) {
-            result[index] = Util.toString(implList[index]);
+            result[index] = Util.toUTF8String(implList[index]);
         }
         return result;
     }
@@ -952,13 +993,13 @@
      * file. The result is {@code null} if this file is not a directory. The
      * paths of the files in the array are absolute if the path of this file is
      * absolute, they are relative otherwise.
-     * 
+     *
      * @return an array of files or {@code null}.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies read
      *             access to this file.
      * @see #list
-     * @since Android 1.0
+     * @see #isDirectory
      */
     public File[] listFiles() {
         String[] tempNames = list();
@@ -982,8 +1023,7 @@
      * <p>
      * The entries {@code .} and {@code ..} representing the current and parent
      * directories are not returned as part of the list.
-     * </p>
-     * 
+     *
      * @param filter
      *            the filter to match names against, may be {@code null}.
      * @return an array of files or {@code null}.
@@ -991,7 +1031,9 @@
      *             if a {@code SecurityManager} is installed and it denies read
      *             access to this file.
      * @see #list(FilenameFilter filter)
-     * @since Android 1.0
+     * @see #getPath
+     * @see #isDirectory
+     * @see java.lang.SecurityManager#checkRead(FileDescriptor)
      */
     public File[] listFiles(FilenameFilter filter) {
         String[] tempNames = list(filter);
@@ -1014,25 +1056,33 @@
      * <p>
      * The entries {@code .} and {@code ..} representing the current and parent
      * directories are not returned as part of the list.
-     * </p>
-     * 
+     *
      * @param filter
      *            the filter to match names against, may be {@code null}.
      * @return an array of files or {@code null}.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies read
      *             access to this file.
-     * @since Android 1.0
+     * @see #getPath
+     * @see #isDirectory
+     * @see java.lang.SecurityManager#checkRead(FileDescriptor)
      */
     public File[] listFiles(FileFilter filter) {
         SecurityManager security = System.getSecurityManager();
         if (security != null) {
             security.checkRead(path);
         }
-        if (!isDirectory()) {
+
+        if (path.length() == 0) {
             return null;
         }
-        byte[][] implList = listImpl(properPath(true));
+
+        byte[] bs = properPath(true);
+        if (!isDirectoryImpl(bs) || !existsImpl(bs) || !isReadableImpl(bs)) {
+            return null;
+        }
+
+        byte[][] implList = listImpl(bs);
         if (implList == null) {
             return new File[0];
         }
@@ -1056,38 +1106,46 @@
      * <p>
      * The entries {@code .} and {@code ..} representing the current and parent
      * directories are not returned as part of the list.
-     * </p>
-     * 
+     *
      * @param filter
      *            the filter to match names against, may be {@code null}.
      * @return an array of files or {@code null}.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies read
      *             access to this file.
-     * @since Android 1.0
+     * @see #getPath
+     * @see #isDirectory
+     * @see java.lang.SecurityManager#checkRead(FileDescriptor)
      */
     public java.lang.String[] list(FilenameFilter filter) {
         SecurityManager security = System.getSecurityManager();
         if (security != null) {
             security.checkRead(path);
         }
-        if (!isDirectory()) {
+
+        if (path.length() == 0) {
             return null;
         }
-        byte[][] implList = listImpl(properPath(true));
+
+        byte[] bs = properPath(true);
+        if (!isDirectoryImpl(bs) || !existsImpl(bs) || !isReadableImpl(bs)) {
+            return null;
+        }
+
+        byte[][] implList = listImpl(bs);
         if (implList == null) {
+            // empty list
             return new String[0];
         }
-        java.util.Vector<String> tempResult = new java.util.Vector<String>();
+        List<String> tempResult = new ArrayList<String>();
         for (int index = 0; index < implList.length; index++) {
             String aName = Util.toString(implList[index]);
             if (filter == null || filter.accept(this, aName)) {
-                tempResult.addElement(aName);
+                tempResult.add(aName);
             }
         }
-        String[] result = new String[tempResult.size()];
-        tempResult.copyInto(result);
-        return result;
+
+        return tempResult.toArray(new String[tempResult.size()]);
     }
 
     private synchronized static native byte[][] listImpl(byte[] path);
@@ -1095,14 +1153,13 @@
     /**
      * Creates the directory named by the trailing filename of this file. Does
      * not create the complete path required to create this directory.
-     * 
+     *
      * @return {@code true} if the directory has been created, {@code false}
      *         otherwise.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies write
      *             access for this file.
      * @see #mkdirs
-     * @since Android 1.0
      */
     public boolean mkdir() {
         SecurityManager security = System.getSecurityManager();
@@ -1117,7 +1174,7 @@
     /**
      * Creates the directory named by the trailing filename of this file,
      * including the complete directory path required to create this directory.
-     * 
+     *
      * @return {@code true} if the necessary directories have been created,
      *         {@code false} if the target directory already exists or one of
      *         the directories can not be created.
@@ -1125,7 +1182,6 @@
      *             if a {@code SecurityManager} is installed and it denies write
      *             access for this file.
      * @see #mkdir
-     * @since Android 1.0
      */
     public boolean mkdirs() {
         /* If the terminal directory already exists, answer false */
@@ -1151,7 +1207,7 @@
     /**
      * Creates a new, empty file on the file system according to the path
      * information stored in this file.
-     * 
+     *
      * @return {@code true} if the file has been created, {@code false} if it
      *         already exists.
      * @throws IOException
@@ -1160,7 +1216,6 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies write
      *             access for this file.
-     * @since Android 1.0
      */
     public boolean createNewFile() throws IOException {
         SecurityManager security = System.getSecurityManager();
@@ -1215,10 +1270,11 @@
 
     /**
      * Creates an empty temporary file using the given prefix and suffix as part
-     * of the file name. If suffix is null, {@code .tmp} is used. This method
-     * is a convenience method that calls {@link #createTempFile(String, String,
-     * File)} with the third argument being {@code null}.
-     * 
+     * of the file name. If suffix is {@code null}, {@code .tmp} is used. This
+     * method is a convenience method that calls
+     * {@link #createTempFile(String, String, File)} with the third argument
+     * being {@code null}.
+     *
      * @param prefix
      *            the prefix to the temp file name.
      * @param suffix
@@ -1226,7 +1282,6 @@
      * @return the temporary file.
      * @throws IOException
      *             if an error occurs when writing the file.
-     * @since Android 1.0
      */
     public static File createTempFile(String prefix, String suffix)
             throws IOException {
@@ -1236,7 +1291,7 @@
     /**
      * Creates an empty temporary file in the given directory using the given
      * prefix and suffix as part of the file name.
-     * 
+     *
      * @param prefix
      *            the prefix to the temp file name.
      * @param suffix
@@ -1246,26 +1301,30 @@
      *            {@code null} for the default location for temporary files,
      *            which is taken from the "java.io.tmpdir" system property. It
      *            may be necessary to set this property to an existing, writable
-     *            directory for this method to work properly. 
+     *            directory for this method to work properly.
      * @return the temporary file.
      * @throws IllegalArgumentException
      *             if the length of {@code prefix} is less than 3.
      * @throws IOException
      *             if an error occurs when writing the file.
-     * @since Android 1.0
      */
+    @SuppressWarnings("nls")
     public static File createTempFile(String prefix, String suffix,
             File directory) throws IOException {
         // Force a prefix null check first
         if (prefix.length() < 3) {
-            throw new IllegalArgumentException(Msg.getString("K006b")); //$NON-NLS-1$
+            throw new IllegalArgumentException(Msg.getString("K006b"));
         }
-        String newSuffix = suffix == null ? ".tmp" : suffix; //$NON-NLS-1$
-        String tmpDir = "."; //$NON-NLS-1$
-        tmpDir = AccessController.doPrivileged(new PriviAction<String>(
-                "java.io.tmpdir", ".")); //$NON-NLS-1$//$NON-NLS-2$
-        File result, tmpDirFile = directory == null ? new File(tmpDir)
-                : directory;
+        String newSuffix = suffix == null ? ".tmp" : suffix;
+        File tmpDirFile;
+        if (directory == null) {
+            String tmpDir = AccessController.doPrivileged(
+                new PriviAction<String>("java.io.tmpdir", "."));
+            tmpDirFile = new File(tmpDir);
+        } else {
+            tmpDirFile = directory;
+        }
+        File result;
         do {
             result = genTempFile(prefix, newSuffix, tmpDirFile);
         } while (!result.createNewFile());
@@ -1274,7 +1333,7 @@
 
     private static File genTempFile(String prefix, String suffix, File directory) {
         if (counter == 0) {
-            int newInt = new java.util.Random().nextInt();
+            int newInt = new SecureRandom().nextInt();
             counter = ((newInt / 65535) & 0xFFFF) + 0x2710;
         }
         StringBuilder newName = new StringBuilder();
@@ -1290,7 +1349,7 @@
      * Returns a string representing the proper path for this file. If this file
      * path is absolute, the user.dir property is not prepended, otherwise it
      * is.
-     * 
+     *
      * @param internal
      *            is user.dir internal.
      * @return the proper path.
@@ -1311,7 +1370,7 @@
             userdir = System.getProperty("user.dir"); //$NON-NLS-1$
         }
         if (path.length() == 0) {
-            return properPath = Util.getBytes(userdir);
+            return properPath = Util.getUTF8Bytes(userdir);
         }
         int length = userdir.length();
         if (length > 0 && userdir.charAt(length - 1) == separatorChar) {
@@ -1328,14 +1387,13 @@
     /**
      * Renames this file to the name represented by the {@code dest} file. This
      * works for both normal files and directories.
-     * 
+     *
      * @param dest
      *            the file containing the new name.
      * @return {@code true} if the File was renamed, {@code false} otherwise.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies write
      *             access for this file or the {@code dest} file.
-     * @since Android 1.0
      */
     public boolean renameTo(java.io.File dest) {
         SecurityManager security = System.getSecurityManager();
@@ -1351,9 +1409,8 @@
     /**
      * Returns a string containing a concise, human-readable description of this
      * file.
-     * 
+     *
      * @return a printable representation of this file.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -1364,22 +1421,22 @@
      * Returns a Uniform Resource Identifier for this file. The URI is system
      * dependent and may not be transferable between different operating / file
      * systems.
-     * 
+     *
      * @return an URI for this file.
-     * @since Android 1.0
      */
+    @SuppressWarnings("nls")
     public URI toURI() {
         String name = getAbsoluteName();
         try {
-            if (!name.startsWith("/")) { //$NON-NLS-1$
+            if (!name.startsWith("/")) {
                 // start with sep.
-                return new URI("file", null, //$NON-NLS-1$
-                        new StringBuilder(name.length() + 1).append('/')
-                                .append(name).toString(), null, null);
-            } else if (name.startsWith("//")) { //$NON-NLS-1$
-                return new URI("file", name, null); // UNC path //$NON-NLS-1$
+                return new URI("file", null, new StringBuilder(
+                        name.length() + 1).append('/').append(name).toString(),
+                        null, null);
+            } else if (name.startsWith("//")) {
+                return new URI("file", "", name, null); // UNC path
             }
-            return new URI("file", null, name, null, null); //$NON-NLS-1$
+            return new URI("file", null, name, null, null);
         } catch (URISyntaxException e) {
             // this should never happen
             return null;
@@ -1390,22 +1447,23 @@
      * Returns a Uniform Resource Locator for this file. The URL is system
      * dependent and may not be transferable between different operating / file
      * systems.
-     * 
-     * @return an URL for this file.
+     *
+     * @return a URL for this file.
      * @throws java.net.MalformedURLException
-     *             if the path cannot be transformed into an URL.
-     * @since Android 1.0
+     *             if the path cannot be transformed into a URL.
      */
+    @SuppressWarnings("nls")
     public URL toURL() throws java.net.MalformedURLException {
         String name = getAbsoluteName();
-        if (!name.startsWith("/")) { //$NON-NLS-1$
+        if (!name.startsWith("/")) {
             // start with sep.
-            return new URL("file", "", -1, new StringBuilder(name.length() + 1) //$NON-NLS-1$ //$NON-NLS-2$
-                    .append('/').append(name).toString(), null);
-        } else if (name.startsWith("//")) { //$NON-NLS-1$
-            return new URL("file:" + name); // UNC path //$NON-NLS-1$
+            return new URL(
+                    "file", EMPTY_STRING, -1, new StringBuilder(name.length() + 1) //$NON-NLS-1$
+                            .append('/').append(name).toString(), null);
+        } else if (name.startsWith("//")) {
+            return new URL("file:" + name); // UNC path
         }
-        return new URL("file", "", -1, name, null); //$NON-NLS-1$ //$NON-NLS-2$
+        return new URL("file", EMPTY_STRING, -1, name, null);
     }
 
     private String getAbsoluteName() {
@@ -1436,60 +1494,3 @@
         path = path.replace(inSeparator, separatorChar);
     }
 }
-
-// BEGIN android-added
-/**
- * Implements the actual DeleteOnExit mechanism. Is registered as a shutdown
- * hook in the Runtime, once it is actually being used.
- */
-class DeleteOnExit extends Thread {
-    
-    /**
-     * Our singleton instance.
-     */
-    private static DeleteOnExit instance;
-    
-    /**
-     * Our list of files scheduled for deletion.
-     */
-    private ArrayList<String> files = new ArrayList<String>();
-    
-    /**
-     * Returns our singleton instance, creating it if necessary.
-     */
-    public static synchronized DeleteOnExit getInstance() {
-        if (instance == null) {
-            instance = new DeleteOnExit();
-            Runtime.getRuntime().addShutdownHook(instance);
-        }
-        
-        return instance;
-    }
-    
-    /**
-     * Schedules a file for deletion.
-     * 
-     * @param filename The file to delete.
-     */
-    public void addFile(String filename) {
-        synchronized(files) {
-            if (!files.contains(filename)) {
-                files.add(filename);
-            }
-        }
-    }
-    
-    /**
-     * Does the actual work. Note we (a) first sort the files lexicographically
-     * and then (b) delete them in reverse order. This is to make sure files
-     * get deleted before their parent directories.
-     */
-    @Override
-    public void run() {
-        Collections.sort(files);
-        for (int i = files.size() - 1; i >= 0; i--) {
-            new File(files.get(i)).delete();
-        }
-    }
-}
-// END android-added
diff --git a/libcore/luni/src/main/java/java/io/FileDescriptor.java b/libcore/luni/src/main/java/java/io/FileDescriptor.java
index e131c88..15eb983 100644
--- a/libcore/luni/src/main/java/java/io/FileDescriptor.java
+++ b/libcore/luni/src/main/java/java/io/FileDescriptor.java
@@ -30,33 +30,25 @@
  * System.err streams respectively.
  * <p>
  * Applications should not create new FileDescriptors.
- * 
+ *
  * @see FileInputStream#getFD()
  * @see FileOutputStream#getFD()
  * @see RandomAccessFile#getFD()
- * 
- * @since Android 1.0
  */
 public final class FileDescriptor {
 
     /**
      * The FileDescriptor representing standard input.
-     * 
-     * @since Android 1.0
      */
     public static final FileDescriptor in = new FileDescriptor();
 
     /**
      * FileDescriptor representing standard out.
-     * 
-     * @since Android 1.0
      */
     public static final FileDescriptor out = new FileDescriptor();
 
     /**
      * FileDescriptor representing standard error.
-     * 
-     * @since Android 1.0
      */
     public static final FileDescriptor err = new FileDescriptor();
 
@@ -68,8 +60,8 @@
      */
     int descriptor = -1;
     // END android-changed
-    
-    boolean readOnly = false; 
+
+    boolean readOnly = false;
 
     private static native void oneTimeInitialization();
 
@@ -84,8 +76,6 @@
     /**
      * Constructs a new FileDescriptor containing an invalid handle. The
      * contained handle is usually modified by native code at a later point.
-     * 
-     * @since Android 1.0
      */
     public FileDescriptor() {
         super();
@@ -94,10 +84,9 @@
     /**
      * Ensures that data which is buffered within the underlying implementation
      * is written out to the appropriate device before returning.
-     * 
+     *
      * @throws SyncFailedException
      *             when the operation fails.
-     * @since Android 1.0
      */
     public void sync() throws SyncFailedException {
         // if the descriptor is a read-only one, do nothing
@@ -105,15 +94,16 @@
             syncImpl();
         }
     }
-    
+
     private native void syncImpl() throws SyncFailedException;
 
     /**
      * Indicates whether this FileDescriptor is valid.
-     * 
+     *
      * @return {@code true} if this FileDescriptor is valid, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
-    public native boolean valid();
+    public boolean valid() {
+        return descriptor != -1;
+    }
 }
diff --git a/libcore/luni/src/main/java/java/io/FileFilter.java b/libcore/luni/src/main/java/java/io/FileFilter.java
index 674ce13..5638dd9 100644
--- a/libcore/luni/src/main/java/java/io/FileFilter.java
+++ b/libcore/luni/src/main/java/java/io/FileFilter.java
@@ -24,21 +24,18 @@
 /**
  * An interface for filtering {@link File} objects based on their names
  * or other information.
- * 
+ *
  * @see File#listFiles(FileFilter)
- * 
- * @since Android 1.0
  */
 public interface FileFilter {
 
     /**
      * Indicating whether a specific file should be included in a pathname list.
-     * 
+     *
      * @param pathname
      *            the abstract file to check.
      * @return {@code true} if the file should be included, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public abstract boolean accept(File pathname);
 }
diff --git a/libcore/luni/src/main/java/java/io/FileInputStream.java b/libcore/luni/src/main/java/java/io/FileInputStream.java
index c39d1e7..1243262 100644
--- a/libcore/luni/src/main/java/java/io/FileInputStream.java
+++ b/libcore/luni/src/main/java/java/io/FileInputStream.java
@@ -31,11 +31,9 @@
  * Since this may induce some performance penalty, in particular if many small
  * read requests are made, a FileInputStream is often wrapped by a
  * BufferedInputStream.
- * 
+ *
  * @see BufferedInputStream
  * @see FileOutputStream
- * 
- * @since Android 1.0
  */
 public class FileInputStream extends InputStream implements Closeable {
     /**
@@ -58,7 +56,7 @@
 
     /**
      * Constructs a new {@code FileInputStream} based on {@code file}.
-     * 
+     *
      * @param file
      *            the file from which this stream reads.
      * @throws FileNotFoundException
@@ -66,7 +64,6 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies the
      *             read request.
-     * @since Android 1.0
      */
     public FileInputStream(File file) throws FileNotFoundException {
         super();
@@ -90,7 +87,7 @@
      * Constructs a new {@code FileInputStream} on the {@link FileDescriptor}
      * {@code fd}. The file must already be open, therefore no
      * {@code FileNotFoundException} will be thrown.
-     * 
+     *
      * @param fd
      *            the FileDescriptor from which this stream reads.
      * @throws NullPointerException
@@ -98,7 +95,6 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies the
      *             read request.
-     * @since Android 1.0
      */
     public FileInputStream(FileDescriptor fd) {
         super();
@@ -121,7 +117,7 @@
      * Constructs a new {@code FileInputStream} on the file named
      * {@code fileName}. The path of {@code fileName} may be absolute or
      * relative to the system property {@code "user.dir"}.
-     * 
+     *
      * @param fileName
      *            the path and name of the file from which this stream reads.
      * @throws FileNotFoundException
@@ -129,7 +125,6 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies the
      *             read request.
-     * @since Android 1.0
      */
     public FileInputStream(String fileName) throws FileNotFoundException {
         this(null == fileName ? (File) null : new File(fileName));
@@ -139,11 +134,10 @@
      * Returns the number of bytes that are available before this stream will
      * block. This method always returns the size of the file minus the current
      * position.
-     * 
+     *
      * @return the number of bytes available before blocking.
      * @throws IOException
      *             if an error occurs in this stream.
-     * @since Android 1.0
      */
     @Override
     public int available() throws IOException {
@@ -157,7 +151,7 @@
         // use.
 
         return fileSystem.ioctlAvailable(fd.descriptor);
-        // END android-added 
+        // END android-added
 
         // BEGIN android-deleted
         // synchronized (repositioningLock) {
@@ -179,10 +173,9 @@
 
     /**
      * Closes this stream.
-     * 
+     *
      * @throws IOException
      *             if an error occurs attempting to close this stream.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -203,10 +196,9 @@
     /**
      * Ensures that all resources for this stream are released when it is about
      * to be garbage collected.
-     * 
+     *
      * @throws IOException
      *             if an error occurs attempting to finalize this stream.
-     * @since Android 1.0
      */
     @Override
     protected void finalize() throws IOException {
@@ -220,10 +212,8 @@
      * that is the same as the current position of this stream within the file.
      * All changes made to the underlying file descriptor state via the channel
      * are visible by the input stream and vice versa.
-     * </p>
-     * 
+     *
      * @return the file channel for this stream.
-     * @since Android 1.0
      */
     public FileChannel getChannel() {
         // BEGIN android-changed
@@ -240,12 +230,11 @@
     /**
      * Returns the {@link FileDescriptor} representing the operating system
      * resource for this stream.
-     * 
+     *
      * @return the {@code FileDescriptor} for this stream.
      * @throws IOException
      *             if an error occurs while getting this stream's
      *             {@code FileDescriptor}.
-     * @since Android 1.0
      */
     public final FileDescriptor getFD() throws IOException {
         return fd;
@@ -255,11 +244,10 @@
      * Reads a single byte from this stream and returns it as an integer in the
      * range from 0 to 255. Returns -1 if the end of this stream has been
      * reached.
-     * 
+     *
      * @return the byte read or -1 if the end of this stream has been reached.
      * @throws IOException
      *             if this stream is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public int read() throws IOException {
@@ -271,14 +259,13 @@
     /**
      * Reads bytes from this stream and stores them in the byte array
      * {@code buffer}.
-     * 
+     *
      * @param buffer
      *            the byte array in which to store the bytes read.
      * @return the number of bytes actually read or -1 if the end of the stream
      *         has been reached.
      * @throws IOException
      *             if this stream is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public int read(byte[] buffer) throws IOException {
@@ -288,7 +275,7 @@
     /**
      * Reads at most {@code count} bytes from this stream and stores them in the
      * byte array {@code buffer} starting at {@code offset}.
-     * 
+     *
      * @param buffer
      *            the byte array in which to store the bytes read.
      * @param offset
@@ -304,7 +291,6 @@
      *             {@code buffer}.
      * @throws IOException
      *             if the stream is closed or another IOException occurs.
-     * @since Android 1.0
      */
     @Override
     public int read(byte[] buffer, int offset, int count) throws IOException {
@@ -338,14 +324,13 @@
      * 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.
-     * 
+     *
      * @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.
-     * @since Android 1.0
      */
     @Override
     public long skip(long count) throws IOException {
diff --git a/libcore/luni/src/main/java/java/io/FileNotFoundException.java b/libcore/luni/src/main/java/java/io/FileNotFoundException.java
index a0f5bc6..2ab9e89 100644
--- a/libcore/luni/src/main/java/java/io/FileNotFoundException.java
+++ b/libcore/luni/src/main/java/java/io/FileNotFoundException.java
@@ -19,8 +19,6 @@
 
 /**
  * Thrown when a file specified by a program cannot be found.
- * 
- * @since Android 1.0
  */
 public class FileNotFoundException extends IOException {
 
@@ -29,8 +27,6 @@
     /**
      * Constructs a new {@code FileNotFoundException} with its stack trace
      * filled in.
-     * 
-     * @since Android 1.0
      */
     public FileNotFoundException() {
         super();
@@ -42,7 +38,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public FileNotFoundException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/io/FileOutputStream.java b/libcore/luni/src/main/java/java/io/FileOutputStream.java
index 00ae5d8..f0b25c9 100644
--- a/libcore/luni/src/main/java/java/io/FileOutputStream.java
+++ b/libcore/luni/src/main/java/java/io/FileOutputStream.java
@@ -31,10 +31,10 @@
  * Since this may induce some performance penalty, in particular if many small
  * write requests are made, a FileOutputStream is often wrapped by a
  * BufferedOutputStream.
- * 
+ *
  * @see BufferedOutputStream
  * @see FileInputStream
- * 
+ *
  * @since Android 1.0
  */
 public class FileOutputStream extends OutputStream implements Closeable {
@@ -55,7 +55,7 @@
     /**
      * Constructs a new FileOutputStream on the File {@code file}. If the file
      * exists, it is overwritten.
-     * 
+     *
      * @param file
      *            the file to which this stream writes.
      * @throws FileNotFoundException
@@ -63,7 +63,7 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies the
      *             write request.
-     * @since Android 1.0            
+     * @see java.lang.SecurityManager#checkWrite(FileDescriptor)
      */
     public FileOutputStream(File file) throws FileNotFoundException {
         this(file, false);
@@ -73,7 +73,7 @@
      * Constructs a new FileOutputStream on the File {@code file}. The
      * parameter {@code append} determines whether or not the file is opened and
      * appended to or just opened and overwritten.
-     * 
+     *
      * @param file
      *            the file to which this stream writes.
      * @param append
@@ -83,7 +83,8 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies the
      *             write request.
-     * @since Android 1.0
+     * @see java.lang.SecurityManager#checkWrite(FileDescriptor)
+     * @see java.lang.SecurityManager#checkWrite(String)
      */
     public FileOutputStream(File file, boolean append)
             throws FileNotFoundException {
@@ -104,7 +105,7 @@
      * Constructs a new FileOutputStream on the FileDescriptor {@code fd}. The
      * file must already be open, therefore no {@code FileNotFoundException}
      * will be thrown.
-     * 
+     *
      * @param fd
      *            the FileDescriptor to which this stream writes.
      * @throws NullPointerException
@@ -112,7 +113,7 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies the
      *             write request.
-     * @since Android 1.0
+     * @see java.lang.SecurityManager#checkWrite(FileDescriptor)
      */
     public FileOutputStream(FileDescriptor fd) {
         super();
@@ -133,7 +134,7 @@
      * Constructs a new FileOutputStream on the file named {@code filename}. If
      * the file exists, it is overwritten. The {@code filename} may be absolute
      * or relative to the system property {@code "user.dir"}.
-     * 
+     *
      * @param filename
      *            the name of the file to which this stream writes.
      * @throws FileNotFoundException
@@ -141,7 +142,6 @@
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies the
      *             write request.
-     * @since Android 1.0
      */
     public FileOutputStream(String filename) throws FileNotFoundException {
         this(filename, false);
@@ -152,17 +152,16 @@
      * The parameter {@code append} determines whether or not the file is opened
      * and appended to or just opened and overwritten. The {@code filename} may
      * be absolute or relative to the system property {@code "user.dir"}.
-     * 
-     * @param append
-     *            indicates whether or not to append to an existing file.
+     *
      * @param filename
      *            the name of the file to which this stream writes.
+     * @param append
+     *            indicates whether or not to append to an existing file.
      * @throws FileNotFoundException
      *             if the file cannot be opened for writing.
      * @throws SecurityException
      *             if a {@code SecurityManager} is installed and it denies the
      *             write request.
-     * @since Android 1.0
      */
     public FileOutputStream(String filename, boolean append)
             throws FileNotFoundException {
@@ -172,10 +171,9 @@
     /**
      * Closes this stream. This implementation closes the underlying operating
      * system resources allocated to represent this stream.
-     * 
+     *
      * @throws IOException
      *             if an error occurs attempting to close this stream.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -204,10 +202,9 @@
     /**
      * Frees any resources allocated for this stream before it is garbage
      * collected. This method is called from the Java Virtual Machine.
-     * 
+     *
      * @throws IOException
      *             if an error occurs attempting to finalize this stream.
-     * @since Android 1.0
      */
     @Override
     protected void finalize() throws IOException {
@@ -221,10 +218,8 @@
      * file that is the same as the current position of this stream within the
      * file. All changes made to the underlying file descriptor state via the
      * channel are visible by the output stream and vice versa.
-     * </p>
-     * 
+     *
      * @return the file channel representation for this stream.
-     * @since Android 1.0
      */
     public FileChannel getChannel() {
         return channel;
@@ -233,12 +228,11 @@
     /**
      * Returns a FileDescriptor which represents the lowest level representation
      * of an operating system stream resource.
-     * 
+     *
      * @return a FileDescriptor representing this stream.
      * @throws IOException
      *             if an error occurs attempting to get the FileDescriptor of
      *             this stream.
-     * @since Android 1.0
      */
     public final FileDescriptor getFD() throws IOException {
         return fd;
@@ -247,13 +241,12 @@
     /**
      * Writes the entire contents of the byte array {@code buffer} to this
      * stream.
-     * 
+     *
      * @param buffer
      *            the buffer to be written to the file.
      * @throws IOException
      *             if this stream is closed or an error occurs attempting to
      *             write to this stream.
-     * @since Android 1.0
      */
     @Override
     public void write(byte[] buffer) throws IOException {
@@ -263,7 +256,7 @@
     /**
      * Writes {@code count} bytes from the byte array {@code buffer} starting at
      * {@code offset} to this stream.
-     * 
+     *
      * @param buffer
      *            the buffer to write to this stream.
      * @param offset
@@ -279,7 +272,6 @@
      *             write to this stream.
      * @throws NullPointerException
      *             if {@code buffer} is {@code null}.
-     * @since Android 1.0
      */
     @Override
     public void write(byte[] buffer, int offset, int count) throws IOException {
@@ -308,13 +300,12 @@
     /**
      * Writes the specified byte {@code oneByte} to this stream. Only the low
      * order byte of the integer {@code oneByte} is written.
-     * 
+     *
      * @param oneByte
      *            the byte to be written.
      * @throws IOException
      *             if this stream is closed an error occurs attempting to write
      *             to this stream.
-     * @since Android 1.0
      */
     @Override
     public void write(int oneByte) throws IOException {
diff --git a/libcore/luni/src/main/java/java/io/FilePermission.java b/libcore/luni/src/main/java/java/io/FilePermission.java
index 3702ac7..610adee 100644
--- a/libcore/luni/src/main/java/java/io/FilePermission.java
+++ b/libcore/luni/src/main/java/java/io/FilePermission.java
@@ -34,7 +34,6 @@
  * and directories contained in that directory. If the pathname
  * ends in {@code /-}, it includes all the files and directories in that
  * directory <i>recursively</i>. The following pathnames have a special meaning:
- * </p>
  * <ul>
  *   <li>
  *     "*": all files in the current directory;
@@ -46,8 +45,6 @@
  *     "&lt;&lt;ALL FILES&gt;&gt;": any file and directory in the file system.
  *   </li>
  * </ul>
- * 
- * @since Android 1.0
  */
 public final class FilePermission extends Permission implements Serializable {
     
@@ -87,8 +84,7 @@
      *             it contains a string other than "read", "write", "execute"
      *             and "delete".
      * @throws NullPointerException
-     *             if {@code path} is null.
-     * @since Android 1.0
+     *             if {@code path} is {@code null}.
      */
     public FilePermission(String path, String actions) {
         super(path);
@@ -197,7 +193,6 @@
      * Returns the actions associated with this file permission.
      * 
      * @return the actions associated with this file permission.
-     * @since Android 1.0
      */
     @Override
     public String getActions() {
@@ -213,7 +208,6 @@
      *            the object to check equality with.
      * @return {@code true} if this file permission is equal to {@code obj},
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object obj) {
@@ -245,7 +239,6 @@
      *            the permission to check.
      * @return {@code true} if the argument permission is implied by the
      *         receiver, and {@code false} if it is not.
-     * @since Android 1.0
      */
     @Override
     public boolean implies(Permission p) {
@@ -361,7 +354,6 @@
      * 
      * @return A new PermissionCollection object suitable for storing
      *         FilePermission objects.
-     * @since Android 1.0
      */
     @Override
     public PermissionCollection newPermissionCollection() {
@@ -372,7 +364,6 @@
      * Calculates the hash code value for this file permission.
      * 
      * @return the hash code value for this file permission.
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
diff --git a/libcore/luni/src/main/java/java/io/FilePermissionCollection.java b/libcore/luni/src/main/java/java/io/FilePermissionCollection.java
index 9d49b79..3049442 100644
--- a/libcore/luni/src/main/java/java/io/FilePermissionCollection.java
+++ b/libcore/luni/src/main/java/java/io/FilePermissionCollection.java
@@ -25,8 +25,6 @@
 /**
  * Collects {@link FilePermission} objects and allows to query whether a
  * particular permission is implied by it.
- * 
- * @since Android 1.0
  */
 final class FilePermissionCollection extends PermissionCollection implements
         Serializable {
diff --git a/libcore/luni/src/main/java/java/io/FileReader.java b/libcore/luni/src/main/java/java/io/FileReader.java
index 90cd454..c62fdeb 100644
--- a/libcore/luni/src/main/java/java/io/FileReader.java
+++ b/libcore/luni/src/main/java/java/io/FileReader.java
@@ -27,8 +27,6 @@
  * 
  * @see BufferedReader
  * @see FileWriter
- *
- * @since Android 1.0
  */
 public class FileReader extends InputStreamReader {
 
@@ -39,7 +37,6 @@
      *            a File to be opened for reading characters from.
      * @throws FileNotFoundException
      *             if {@code file} does not exist.
-     * @since Android 1.0             
      */
     public FileReader(File file) throws FileNotFoundException {
         super(new FileInputStream(file));
@@ -52,7 +49,6 @@
      * 
      * @param fd
      *            the previously opened file descriptor.
-     * @since Android 1.0
      */
     public FileReader(FileDescriptor fd) {
         super(new FileInputStream(fd));
@@ -65,7 +61,6 @@
      *            an absolute or relative path specifying the file to open.
      * @throws FileNotFoundException
      *             if there is no file named {@code filename}.
-     * @since Android 1.0
      */
     public FileReader(String filename) throws FileNotFoundException {
         super(new FileInputStream(filename));
diff --git a/libcore/luni/src/main/java/java/io/FileWriter.java b/libcore/luni/src/main/java/java/io/FileWriter.java
index 63aee88..86a9af8 100644
--- a/libcore/luni/src/main/java/java/io/FileWriter.java
+++ b/libcore/luni/src/main/java/java/io/FileWriter.java
@@ -27,8 +27,6 @@
  * 
  * @see BufferedWriter
  * @see FileReader
- *
- * @since Android 1.0
  */
 public class FileWriter extends OutputStreamWriter {
 
@@ -39,7 +37,6 @@
      *            the non-null File to write bytes to.
      * @throws IOException
      *             if {@code file} cannot be opened for writing.
-     * @since Android 1.0
      */
     public FileWriter(File file) throws IOException {
         super(new FileOutputStream(file));
@@ -56,7 +53,6 @@
      *            indicates whether or not to append to an existing file.
      * @throws IOException
      *             if the {@code file} cannot be opened for writing.
-     * @since Android 1.0
      */
     public FileWriter(File file, boolean append) throws IOException {
         super(new FileOutputStream(file, append));
@@ -67,7 +63,6 @@
      * 
      * @param fd
      *            the non-null FileDescriptor to write bytes to.
-     * @since Android 1.0
      */
     public FileWriter(FileDescriptor fd) {
         super(new FileOutputStream(fd));
@@ -80,7 +75,6 @@
      *            the non-null name of the file to write bytes to.
      * @throws IOException
      *             if the file cannot be opened for writing.
-     * @since Android 1.0
      */
     public FileWriter(String filename) throws IOException {
         super(new FileOutputStream(new File(filename)));
@@ -97,7 +91,6 @@
      *            indicates whether or not to append to an existing file.
      * @throws IOException
      *             if the {@code file} cannot be opened for writing.
-     * @since Android 1.0
      */
     public FileWriter(String filename, boolean append) throws IOException {
         super(new FileOutputStream(filename, append));
diff --git a/libcore/luni/src/main/java/java/io/FilenameFilter.java b/libcore/luni/src/main/java/java/io/FilenameFilter.java
index 40a6cca..a51bcc6 100644
--- a/libcore/luni/src/main/java/java/io/FilenameFilter.java
+++ b/libcore/luni/src/main/java/java/io/FilenameFilter.java
@@ -21,9 +21,8 @@
  * An interface for filtering {@link File} objects based on their names
  * or the directory they reside in.
  * 
+ * @see File
  * @see File#list(FilenameFilter)
- * 
- * @since Android 1.0
  */
 public interface FilenameFilter {
 
@@ -34,10 +33,9 @@
      *            the directory in which the {@code filename} was found.
      * @param filename
      *            the name of the file in {@code dir} to test.
-     * @return  {@code true} if the filename matches the filter 
-     *            and can be included in the list, {@code false} 
+     * @return  {@code true} if the filename matches the filter
+     *            and can be included in the list, {@code false}
      *            otherwise.
-     * @since Android 1.0
      */
     public abstract boolean accept(File dir, String filename);
 }
diff --git a/libcore/luni/src/main/java/java/io/FilterInputStream.java b/libcore/luni/src/main/java/java/io/FilterInputStream.java
index 5110060..0baa409 100644
--- a/libcore/luni/src/main/java/java/io/FilterInputStream.java
+++ b/libcore/luni/src/main/java/java/io/FilterInputStream.java
@@ -26,21 +26,13 @@
  * from this class.
  * 
  * @see FilterOutputStream
- * 
- * @since Android 1.0
  */
 public class FilterInputStream extends InputStream {
 
-    // BEGIN android-changed
-    // The underlying input stream address should not be cached in a register.
-    // This was changed to be more close to the RI.
     /**
      * The source input stream that is filtered.
-     * 
-     * @since Android 1.0
      */
     protected volatile InputStream in;
-    // END android-changed
 
     /**
      * Constructs a new {@code FilterInputStream} with the specified input
@@ -48,7 +40,6 @@
      * 
      * @param in
      *            the non-null InputStream to filter reads on.
-     * @since Android 1.0
      */
     protected FilterInputStream(InputStream in) {
         super();
@@ -57,12 +48,11 @@
 
     /**
      * Returns the number of bytes that are available before this stream will
-     * block. 
-     *  
+     * block.
+     *
      * @return the number of bytes available before blocking.
      * @throws IOException
      *             if an error occurs in this stream.
-     * @since Android 1.0
      */
     @Override
     public int available() throws IOException {
@@ -74,7 +64,6 @@
      * 
      * @throws IOException
      *             if an error occurs while closing this stream.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -88,14 +77,12 @@
      * position, provided that {@code readlimit} has not been surpassed.
      * <p>
      * This implementation sets a mark in the filtered stream.
-     * </p>
-     * 
+     *
      * @param readlimit
      *            the number of bytes that can be read from this stream before
      *            the mark is invalidated.
      * @see #markSupported()
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public synchronized void mark(int readlimit) {
@@ -112,7 +99,6 @@
      * @see #mark(int)
      * @see #reset()
      * @see #skip(long)
-     * @since Android 1.0
      */
     @Override
     public boolean markSupported() {
@@ -128,7 +114,6 @@
      *         reached.
      * @throws IOException
      *             if the stream is closed or another IOException occurs.
-     * @since Android 1.0
      */
     @Override
     public int read() throws IOException {
@@ -147,7 +132,6 @@
      *         filtered stream has been reached while reading.
      * @throws IOException
      *             if this stream is closed or another IOException occurs.
-     * @since Android 1.0
      */
     @Override
     public int read(byte[] buffer) throws IOException {
@@ -172,7 +156,6 @@
      *         filtered stream has been reached while reading.
      * @throws IOException
      *             if this stream is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public int read(byte[] buffer, int offset, int count) throws IOException {
@@ -189,7 +172,6 @@
      *             bytes have been read since setting the mark.
      * @see #mark(int)
      * @see #markSupported()
-     * @since Android 1.0
      */
     @Override
     public synchronized void reset() throws IOException {
@@ -208,12 +190,10 @@
      * @throws IOException
      *             if this stream is closed or another IOException occurs.
      * @see #mark(int)
-     * @see #reset()  
-     * @since Android 1.0          
+     * @see #reset()
      */
     @Override
     public long skip(long count) throws IOException {
         return in.skip(count);
     }
 }
-
diff --git a/libcore/luni/src/main/java/java/io/FilterOutputStream.java b/libcore/luni/src/main/java/java/io/FilterOutputStream.java
index 212b22e..66765f9 100644
--- a/libcore/luni/src/main/java/java/io/FilterOutputStream.java
+++ b/libcore/luni/src/main/java/java/io/FilterOutputStream.java
@@ -26,27 +26,22 @@
  * decompression of the underlying stream. Output streams that wrap another
  * output stream and provide some additional functionality on top of it usually
  * inherit from this class.
- * 
+ *
  * @see FilterOutputStream
- * 
- * @since Android 1.0
  */
 public class FilterOutputStream extends OutputStream {
 
     /**
      * The target output stream for this filter stream.
-     * 
-     * @since Android 1.0
      */
     protected OutputStream out;
 
     /**
      * Constructs a new {@code FilterOutputStream} with {@code out} as its
      * target stream.
-     * 
+     *
      * @param out
      *            the target stream that this stream writes to.
-     * @since Android 1.0
      */
     public FilterOutputStream(OutputStream out) {
         this.out = out;
@@ -54,10 +49,9 @@
 
     /**
      * Closes this stream. This implementation closes the target stream.
-     * 
+     *
      * @throws IOException
      *             if an error occurs attempting to close this stream.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -73,10 +67,9 @@
     /**
      * Ensures that all pending data is sent out to the target stream. This
      * implementation flushes the target stream.
-     * 
+     *
      * @throws IOException
      *             if an error occurs attempting to flush this stream.
-     * @since Android 1.0
      */
     @Override
     public void flush() throws IOException {
@@ -87,12 +80,11 @@
      * Writes the entire contents of the byte array {@code buffer} to this
      * stream. This implementation writes the {@code buffer} to the target
      * stream.
-     * 
+     *
      * @param buffer
      *            the buffer to be written.
      * @throws IOException
      *             if an I/O error occurs while writing to this stream.
-     * @since Android 1.0
      */
     @Override
     public void write(byte[] buffer) throws IOException {
@@ -105,7 +97,7 @@
     /**
      * Writes {@code count} bytes from the byte array {@code buffer} starting at
      * {@code offset} to the target stream.
-     * 
+     *
      * @param buffer
      *            the buffer to write.
      * @param offset
@@ -118,7 +110,6 @@
      *             {@code buffer}.
      * @throws IOException
      *             if an I/O error occurs while writing to this stream.
-     * @since Android 1.0
      */
     @Override
     public void write(byte[] buffer, int offset, int count) throws IOException {
@@ -149,12 +140,11 @@
     /**
      * Writes one byte to the target stream. Only the low order byte of the
      * integer {@code oneByte} is written.
-     * 
+     *
      * @param oneByte
      *            the byte to be written.
      * @throws IOException
      *             if an I/O error occurs while writing to this stream.
-     * @since Android 1.0
      */
     @Override
     public void write(int oneByte) throws IOException {
diff --git a/libcore/luni/src/main/java/java/io/FilterReader.java b/libcore/luni/src/main/java/java/io/FilterReader.java
index 7fa96b5..e8e06dd 100644
--- a/libcore/luni/src/main/java/java/io/FilterReader.java
+++ b/libcore/luni/src/main/java/java/io/FilterReader.java
@@ -26,15 +26,11 @@
  * class.
  * 
  * @see FilterWriter
- * 
- * @since Android 1.0
  */
 public abstract class FilterReader extends Reader {
 
     /**
      * The target Reader which is being filtered.
-     * 
-     * @since Android 1.0
      */
     protected Reader in;
 
@@ -43,7 +39,6 @@
      * 
      * @param in
      *            The non-null Reader to filter reads on.
-     * @since Android 1.0
      */
     protected FilterReader(Reader in) {
         super(in);
@@ -55,7 +50,6 @@
      * 
      * @throws IOException
      *             if an error occurs while closing this reader.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -71,7 +65,6 @@
      * position, provided that {@code readlimit} has not been surpassed.
      * <p>
      * This implementation sets a mark in the filtered reader.
-     * </p>
      * 
      * @param readlimit
      *            the number of bytes that can be read from this reader before
@@ -80,7 +73,6 @@
      *             if an error occurs while marking this reader.
      * @see #markSupported()
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public synchronized void mark(int readlimit) throws IOException {
@@ -98,7 +90,6 @@
      * @see #mark(int)
      * @see #reset()
      * @see #skip(long)
-     * @since Android 1.0
      */
     @Override
     public boolean markSupported() {
@@ -116,7 +107,6 @@
      *         been reached.
      * @throws IOException
      *             if an error occurs while reading from this reader.
-     * @since Android 1.0
      */
     @Override
     public int read() throws IOException {
@@ -142,7 +132,6 @@
      *         filtered reader has been reached while reading.
      * @throws IOException
      *             if an error occurs while reading from this reader.
-     * @since Android 1.0
      */
     @Override
     public int read(char[] buffer, int offset, int count) throws IOException {
@@ -161,7 +150,6 @@
      *         is called, {@code false} if unknown or blocking will occur.
      * @throws IOException
      *             if the reader is closed or some other I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public boolean ready() throws IOException {
@@ -182,7 +170,6 @@
      *             {@code mark()} and {@code reset()}.
      * @see #mark(int)
      * @see #markSupported()
-     * @since Android 1.0
      */
     @Override
     public void reset() throws IOException {
@@ -205,7 +192,6 @@
      * @see #mark(int)
      * @see #markSupported()
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public long skip(long count) throws IOException {
diff --git a/libcore/luni/src/main/java/java/io/FilterWriter.java b/libcore/luni/src/main/java/java/io/FilterWriter.java
index 66c1d34..cd48f64 100644
--- a/libcore/luni/src/main/java/java/io/FilterWriter.java
+++ b/libcore/luni/src/main/java/java/io/FilterWriter.java
@@ -24,26 +24,22 @@
  * decompression of the underlying writer. Writers that wrap another writer and
  * provide some additional functionality on top of it usually inherit from this
  * class.
- * 
+ *
  * @see FilterReader
- * 
- * @since Android 1.0
  */
 public abstract class FilterWriter extends Writer {
 
     /**
      * The Writer being filtered.
-     * @since Android 1.0
      */
     protected Writer out;
 
     /**
      * Constructs a new FilterWriter on the Writer {@code out}. All writes are
      * now filtered through this writer.
-     * 
+     *
      * @param out
      *            the target Writer to filter writes on.
-     * @since Android 1.0
      */
     protected FilterWriter(Writer out) {
         super(out);
@@ -52,10 +48,9 @@
 
     /**
      * Closes this writer. This implementation closes the target writer.
-     * 
+     *
      * @throws IOException
      *             if an error occurs attempting to close this writer.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -67,10 +62,9 @@
     /**
      * Flushes this writer to ensure all pending data is sent out to the target
      * writer. This implementation flushes the target writer.
-     * 
+     *
      * @throws IOException
      *             if an error occurs attempting to flush this writer.
-     * @since Android 1.0
      */
     @Override
     public void flush() throws IOException {
@@ -82,7 +76,7 @@
     /**
      * Writes {@code count} characters from the char array {@code buffer}
      * starting at position {@code offset} to the target writer.
-     * 
+     *
      * @param buffer
      *            the buffer to write.
      * @param offset
@@ -91,7 +85,6 @@
      *            the number of characters in {@code buffer} to write.
      * @throws IOException
      *             if an error occurs while writing to this writer.
-     * @since Android 1.0
      */
     @Override
     public void write(char[] buffer, int offset, int count) throws IOException {
@@ -106,12 +99,11 @@
     /**
      * Writes the specified character {@code oneChar} to the target writer. Only the
      * two least significant bytes of the integer {@code oneChar} are written.
-     * 
+     *
      * @param oneChar
      *            the char to write to the target writer.
      * @throws IOException
      *             if an error occurs while writing to this writer.
-     * @since Android 1.0
      */
     @Override
     public void write(int oneChar) throws IOException {
@@ -124,7 +116,7 @@
      * Writes {@code count} characters from the string {@code str} starting at
      * position {@code index} to this writer. This implementation writes
      * {@code str} to the target writer.
-     * 
+     *
      * @param str
      *            the string to be written.
      * @param offset
@@ -133,7 +125,6 @@
      *            the number of chars in {@code str} to write.
      * @throws IOException
      *             if an error occurs while writing to this writer.
-     * @since Android 1.0
      */
     @Override
     public void write(String str, int offset, int count) throws IOException {
diff --git a/libcore/luni/src/main/java/java/io/Flushable.java b/libcore/luni/src/main/java/java/io/Flushable.java
index 55fcc92..c36de30 100644
--- a/libcore/luni/src/main/java/java/io/Flushable.java
+++ b/libcore/luni/src/main/java/java/io/Flushable.java
@@ -20,17 +20,14 @@
  * Defines an interface for classes that can (or need to) be flushed, typically
  * before some output processing is considered to be finished and the object
  * gets closed.
- * 
- * @since Android 1.0
  */
 public interface Flushable {
     /**
      * Flushes the object by writing out any buffered data to the underlying
      * output.
-     * 
+     *
      * @throws IOException
      *             if there are any issues writing the data.
-     * @since Android 1.0
      */
     void flush() throws IOException;
 }
diff --git a/libcore/luni/src/main/java/java/io/IOException.java b/libcore/luni/src/main/java/java/io/IOException.java
index 869a6d0..24cea9f 100644
--- a/libcore/luni/src/main/java/java/io/IOException.java
+++ b/libcore/luni/src/main/java/java/io/IOException.java
@@ -22,8 +22,6 @@
  * calling the constructor, as usual. Note there are also several subclasses of
  * this class for more specific error situations, such as
  * {@link FileNotFoundException} or {@link EOFException}.
- * 
- * @since Android 1.0
  */
 public class IOException extends Exception {
 
@@ -31,8 +29,6 @@
 
     /**
      * Constructs a new {@code IOException} with its stack trace filled in.
-     * 
-     * @since Android 1.0
      */
     public IOException() {
         super();
@@ -44,7 +40,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public IOException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/io/InputStream.java b/libcore/luni/src/main/java/java/io/InputStream.java
index 23fd89c..f20ce7d 100644
--- a/libcore/luni/src/main/java/java/io/InputStream.java
+++ b/libcore/luni/src/main/java/java/io/InputStream.java
@@ -34,10 +34,8 @@
  * <p>
  * Many specialized input streams for purposes like reading from a file already
  * exist in this package.
- * 
+ *
  * @see OutputStream
- * 
- * @since Android 1.0
  */
 public abstract class InputStream extends Object implements Closeable {
 
@@ -46,8 +44,6 @@
     /**
      * This constructor does nothing. It is provided for signature
      * compatibility.
-     * 
-     * @since Android 1.0
      */
     public InputStream() {
         /* empty */
@@ -57,11 +53,10 @@
      * Returns the number of bytes that are available before this stream will
      * block. This implementation always returns 0. Subclasses should override
      * and indicate the correct number of bytes available.
-     * 
+     *
      * @return the number of bytes available before blocking.
      * @throws IOException
      *             if an error occurs in this stream.
-     * @since Android 1.0
      */
     public int available() throws IOException {
         return 0;
@@ -70,10 +65,9 @@
     /**
      * Closes this stream. Concrete implementations of this class should free
      * any resources during close. This implementation does nothing.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this stream.
-     * @since Android 1.0
      */
     public void close() throws IOException {
         /* empty */
@@ -87,14 +81,12 @@
      * <p>
      * This default implementation does nothing and concrete subclasses must
      * provide their own implementation.
-     * </p>
-     * 
+     *
      * @param readlimit
      *            the number of bytes that can be read from this stream before
      *            the mark is invalidated.
      * @see #markSupported()
      * @see #reset()
-     * @since Android 1.0
      */
     public void mark(int readlimit) {
         /* empty */
@@ -103,11 +95,10 @@
     /**
      * Indicates whether this stream supports the {@code mark()} and
      * {@code reset()} methods. The default implementation returns {@code false}.
-     * 
+     *
      * @return always {@code false}.
      * @see #mark(int)
      * @see #reset()
-     * @since Android 1.0
      */
     public boolean markSupported() {
         return false;
@@ -118,24 +109,22 @@
      * range from 0 to 255. Returns -1 if the end of the stream has been
      * reached. Blocks until one byte has been read, the end of the source
      * stream is detected or an exception is thrown.
-     * 
+     *
      * @return the byte read or -1 if the end of stream has been reached.
      * @throws IOException
      *             if the stream is closed or another IOException occurs.
-     * @since Android 1.0
      */
     public abstract int read() throws IOException;
 
     /**
      * Reads bytes from this stream and stores them in the byte array {@code b}.
-     * 
+     *
      * @param b
      *            the byte array in which to store the bytes read.
      * @return the number of bytes actually read or -1 if the end of the stream
      *         has been reached.
      * @throws IOException
      *             if this stream is closed or another IOException occurs.
-     * @since Android 1.0
      */
     public int read(byte[] b) throws IOException {
         // BEGIN android-note
@@ -147,7 +136,7 @@
     /**
      * Reads at most {@code length} bytes from this stream and stores them in
      * the byte array {@code b} starting at {@code offset}.
-     * 
+     *
      * @param b
      *            the byte array in which to store the bytes read.
      * @param offset
@@ -163,7 +152,6 @@
      *             {@code b}.
      * @throws IOException
      *             if the stream is closed or another IOException occurs.
-     * @since Android 1.0
      */
     public int read(byte[] b, int offset, int length) throws IOException {
         // BEGIN android-note
@@ -195,7 +183,7 @@
                 }
                 throw e;
             }
-            b[offset + i] = (byte)c;
+            b[offset + i] = (byte) c;
         }
         return length;
     }
@@ -208,11 +196,9 @@
      * <p>
      * This implementation always throws an {@code IOException} and concrete
      * subclasses should provide the proper implementation.
-     * </p>
-     * 
+     *
      * @throws IOException
      *             if this stream is closed or another IOException occurs.
-     * @since Android 1.0
      */
     public synchronized void reset() throws IOException {
         throw new IOException();
@@ -225,14 +211,12 @@
      * <p>
      * This default implementation reads {@code n} bytes into a temporary
      * buffer. Concrete subclasses should provide their own implementation.
-     * </p>
-     * 
+     *
      * @param n
      *            the number of bytes to skip.
      * @return the number of bytes actually skipped.
      * @throws IOException
      *             if this stream is closed or another IOException occurs.
-     * @since Android 1.0
      */
     public long skip(long n) throws IOException {
         if (n <= 0) {
diff --git a/libcore/luni/src/main/java/java/io/InputStreamReader.java b/libcore/luni/src/main/java/java/io/InputStreamReader.java
index 0f74b14..0fdcb9a 100644
--- a/libcore/luni/src/main/java/java/io/InputStreamReader.java
+++ b/libcore/luni/src/main/java/java/io/InputStreamReader.java
@@ -26,15 +26,11 @@
 import java.nio.charset.MalformedInputException;
 import java.nio.charset.UnmappableCharacterException;
 import java.security.AccessController;
-import java.util.HashMap;
 
+import org.apache.harmony.luni.util.HistoricalNamesUtil;
 import org.apache.harmony.luni.util.Msg;
 import org.apache.harmony.luni.util.PriviAction;
 
-// BEGIN android-note
-// Later changes from Harmony have been integrated into this version.
-// END android-note
-
 /**
  * A class for turning a byte stream into a character stream. Data read from the
  * source input stream is converted into characters by either a default or a
@@ -42,10 +38,8 @@
  * "file.encoding" system property. {@code InputStreamReader} contains a buffer
  * of bytes read from the source stream and converts these into characters as
  * needed. The buffer size is 8K.
- * 
+ *
  * @see OutputStreamWriter
- * 
- * @since Android 1.0
  */
 public class InputStreamReader extends Reader {
     private InputStream in;
@@ -63,10 +57,9 @@
      * {@code in}. This constructor sets the character converter to the encoding
      * specified in the "file.encoding" property and falls back to ISO 8859_1
      * (ISO-Latin-1) if the property doesn't exist.
-     * 
+     *
      * @param in
      *            the input stream from which to read characters.
-     * @since Android 1.0
      */
     public InputStreamReader(InputStream in) {
         super(in);
@@ -85,7 +78,7 @@
      * character converter that is used to decode bytes into characters is
      * identified by name by {@code enc}. If the encoding cannot be found, an
      * UnsupportedEncodingException error is thrown.
-     * 
+     *
      * @param in
      *            the InputStream from which to read characters.
      * @param enc
@@ -94,7 +87,6 @@
      *             if {@code enc} is {@code null}.
      * @throws UnsupportedEncodingException
      *             if the encoding specified by {@code enc} cannot be found.
-     * @since Android 1.0
      */
     public InputStreamReader(InputStream in, final String enc)
             throws UnsupportedEncodingException {
@@ -117,12 +109,11 @@
     /**
      * Constructs a new InputStreamReader on the InputStream {@code in} and
      * CharsetDecoder {@code dec}.
-     * 
+     *
      * @param in
      *            the source InputStream from which to read characters.
      * @param dec
      *            the CharsetDecoder used by the character conversion.
-     * @since Android 1.0
      */
     public InputStreamReader(InputStream in, CharsetDecoder dec) {
         super(in);
@@ -135,12 +126,11 @@
     /**
      * Constructs a new InputStreamReader on the InputStream {@code in} and
      * Charset {@code charset}.
-     * 
+     *
      * @param in
      *            the source InputStream from which to read characters.
      * @param charset
      *            the Charset that defines the character converter
-     * @since Android 1.0
      */
     public InputStreamReader(InputStream in, Charset charset) {
         super(in);
@@ -154,10 +144,9 @@
     /**
      * Closes this reader. This implementation closes the source InputStream and
      * releases all local storage.
-     * 
+     *
      * @throws IOException
      *             if an error occurs attempting to close this reader.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -178,10 +167,9 @@
     /**
      * Returns the name of the encoding used to convert bytes into characters.
      * The value {@code null} is returned if this reader has been closed.
-     * 
+     *
      * @return the name of the character converter or {@code null} if this
      *         reader is closed.
-     * @since Android 1.0
      */
     public String getEncoding() {
         if (!isOpen()) {
@@ -190,172 +178,17 @@
         return HistoricalNamesUtil.getHistoricalName(decoder.charset().name());
     }
 
-    /*
-     * helper for getEncoding()
-     */
-    @SuppressWarnings("nls")
-    static class HistoricalNamesUtil {
-        private static HashMap<String, String> historicalNames = new HashMap<String, String>();
-        static {
-            historicalNames.put("Big5-HKSCS", "Big5_HKSCS");
-            historicalNames.put("EUC-JP", "EUC_JP");
-            historicalNames.put("EUC-KR", "EUC_KR");
-            historicalNames.put("GB2312", "EUC_CN");
-            historicalNames.put("IBM-Thai", "Cp838");
-            historicalNames.put("IBM00858", "Cp858");
-            historicalNames.put("IBM01140", "Cp1140");
-            historicalNames.put("IBM01141", "Cp1141");
-            historicalNames.put("IBM01142", "Cp1142");
-            historicalNames.put("IBM01143", "Cp1143");
-            historicalNames.put("IBM01144", "Cp1144");
-            historicalNames.put("IBM01145", "Cp1145");
-            historicalNames.put("IBM01146", "Cp1146");
-            historicalNames.put("IBM01147", "Cp1147");
-            historicalNames.put("IBM01148", "Cp1148");
-            historicalNames.put("IBM01149", "Cp1149");
-            historicalNames.put("IBM037", "Cp037");
-            historicalNames.put("IBM1026", "Cp1026");
-            historicalNames.put("IBM1047", "Cp1047");
-            historicalNames.put("IBM273", "Cp273");
-            historicalNames.put("IBM277", "Cp277");
-            historicalNames.put("IBM278", "Cp278");
-            historicalNames.put("IBM280", "Cp280");
-            historicalNames.put("IBM284", "Cp284");
-            historicalNames.put("IBM285", "Cp285");
-            historicalNames.put("IBM297", "Cp297");
-            historicalNames.put("IBM420", "Cp420");
-            historicalNames.put("IBM424", "Cp424");
-            historicalNames.put("IBM437", "Cp437");
-            historicalNames.put("IBM500", "Cp500");
-            historicalNames.put("IBM775", "Cp775");
-            historicalNames.put("IBM850", "Cp850");
-            historicalNames.put("IBM852", "Cp852");
-            historicalNames.put("IBM855", "Cp855");
-            historicalNames.put("IBM857", "Cp857");
-            historicalNames.put("IBM860", "Cp860");
-            historicalNames.put("IBM861", "Cp861");
-            historicalNames.put("IBM862", "Cp862");
-            historicalNames.put("IBM863", "Cp863");
-            historicalNames.put("IBM864", "Cp864");
-            historicalNames.put("IBM865", "Cp865");
-            historicalNames.put("IBM866", "Cp866");
-            historicalNames.put("IBM868", "Cp868");
-            historicalNames.put("IBM869", "Cp869");
-            historicalNames.put("IBM870", "Cp870");
-            historicalNames.put("IBM871", "Cp871");
-            historicalNames.put("IBM918", "Cp918");
-            historicalNames.put("ISO-2022-CN", "ISO2022CN");
-            historicalNames.put("ISO-2022-JP", "ISO2022JP");
-            historicalNames.put("ISO-2022-KR", "ISO2022KR");
-            historicalNames.put("ISO-8859-1", "ISO8859_1");
-            historicalNames.put("ISO-8859-13", "ISO8859_13");
-            historicalNames.put("ISO-8859-15", "ISO8859_15");
-            historicalNames.put("ISO-8859-2", "ISO8859_2");
-            historicalNames.put("ISO-8859-3", "ISO8859_3");
-            historicalNames.put("ISO-8859-4", "ISO8859_4");
-            historicalNames.put("ISO-8859-5", "ISO8859_5");
-            historicalNames.put("ISO-8859-6", "ISO8859_6");
-            historicalNames.put("ISO-8859-7", "ISO8859_7");
-            historicalNames.put("ISO-8859-8", "ISO8859_8");
-            historicalNames.put("ISO-8859-9", "ISO8859_9");
-            historicalNames.put("KOI8-R", "KOI8_R");
-            historicalNames.put("Shift_JIS", "SJIS");
-            historicalNames.put("TIS-620", "TIS620");
-            historicalNames.put("US-ASCII", "ASCII");
-            historicalNames.put("UTF-16BE", "UnicodeBigUnmarked");
-            historicalNames.put("UTF-16LE", "UnicodeLittleUnmarked");
-            historicalNames.put("UTF-8", "UTF8");
-            historicalNames.put("windows-1250", "Cp1250");
-            historicalNames.put("windows-1251", "Cp1251");
-            historicalNames.put("windows-1252", "Cp1252");
-            historicalNames.put("windows-1253", "Cp1253");
-            historicalNames.put("windows-1254", "Cp1254");
-            historicalNames.put("windows-1255", "Cp1255");
-            historicalNames.put("windows-1256", "Cp1256");
-            historicalNames.put("windows-1257", "Cp1257");
-            historicalNames.put("windows-1258", "Cp1258");
-            historicalNames.put("windows-31j", "MS932");
-            historicalNames.put("x-Big5-Solaris", "Big5_Solaris");
-            historicalNames.put("x-euc-jp-linux", "EUC_JP_LINUX");
-            historicalNames.put("x-EUC-TW", "EUC_TW");
-            historicalNames.put("x-eucJP-Open", "EUC_JP_Solaris");
-            historicalNames.put("x-IBM1006", "Cp1006");
-            historicalNames.put("x-IBM1025", "Cp1025");
-            historicalNames.put("x-IBM1046", "Cp1046");
-            historicalNames.put("x-IBM1097", "Cp1097");
-            historicalNames.put("x-IBM1098", "Cp1098");
-            historicalNames.put("x-IBM1112", "Cp1112");
-            historicalNames.put("x-IBM1122", "Cp1122");
-            historicalNames.put("x-IBM1123", "Cp1123");
-            historicalNames.put("x-IBM1124", "Cp1124");
-            historicalNames.put("x-IBM1381", "Cp1381");
-            historicalNames.put("x-IBM1383", "Cp1383");
-            historicalNames.put("x-IBM33722", "Cp33722");
-            historicalNames.put("x-IBM737", "Cp737");
-            historicalNames.put("x-IBM856", "Cp856");
-            historicalNames.put("x-IBM874", "Cp874");
-            historicalNames.put("x-IBM875", "Cp875");
-            historicalNames.put("x-IBM921", "Cp921");
-            historicalNames.put("x-IBM922", "Cp922");
-            historicalNames.put("x-IBM930", "Cp930");
-            historicalNames.put("x-IBM933", "Cp933");
-            historicalNames.put("x-IBM935", "Cp935");
-            historicalNames.put("x-IBM937", "Cp937");
-            historicalNames.put("x-IBM939", "Cp939");
-            historicalNames.put("x-IBM942", "Cp942");
-            historicalNames.put("x-IBM942C", "Cp942C");
-            historicalNames.put("x-IBM943", "Cp943");
-            historicalNames.put("x-IBM943C", "Cp943C");
-            historicalNames.put("x-IBM948", "Cp948");
-            historicalNames.put("x-IBM949", "Cp949");
-            historicalNames.put("x-IBM949C", "Cp949C");
-            historicalNames.put("x-IBM950", "Cp950");
-            historicalNames.put("x-IBM964", "Cp964");
-            historicalNames.put("x-IBM970", "Cp970");
-            historicalNames.put("x-ISCII91", "ISCII91");
-            historicalNames.put("x-ISO-2022-CN-CNS", "ISO2022CN");
-            historicalNames.put("x-ISO-2022-CN-GB", "ISO2022CN");
-            historicalNames.put("x-JISAutoDetect", "JISAutoDetect");
-            historicalNames.put("x-MacArabic", "MacArabic");
-            historicalNames.put("x-MacCentralEurope", "MacCentralEurope");
-            historicalNames.put("x-MacCroatian", "MacCroatian");
-            historicalNames.put("x-MacCyrillic", "MacCyrillic");
-            historicalNames.put("x-MacDingbat", "MacDingbat");
-            historicalNames.put("x-MacGreek", "MacGreek");
-            historicalNames.put("x-MacHebrew", "MacHebrew");
-            historicalNames.put("x-MacIceland", "MacIceland");
-            historicalNames.put("x-MacRoman", "MacRoman");
-            historicalNames.put("x-MacRomania", "MacRomania");
-            historicalNames.put("x-MacSymbol", "MacSymbol");
-            historicalNames.put("x-MacThai", "MacThai");
-            historicalNames.put("x-MacTurkish", "MacTurkish");
-            historicalNames.put("x-MacUkraine", "MacUkraine");
-            historicalNames.put("x-MS950-HKSCS", "MS950_HKSCS");
-            historicalNames.put("x-mswin-936", "MS936");
-            historicalNames.put("x-PCK", "PCK");
-            historicalNames.put("x-windows-874", "MS874");
-            historicalNames.put("x-windows-949", "MS949");
-            historicalNames.put("x-windows-950", "MS950");
-        }
-
-        public static String getHistoricalName(String name) {
-            return (!historicalNames.containsKey(name) ? name : historicalNames
-                    .get(name));
-        }
-    }
-
     /**
      * Reads a single character from this reader and returns it as an integer
      * with the two higher-order bytes set to 0. Returns -1 if the end of the
      * reader has been reached. The byte value is either obtained from
      * converting bytes in this reader's buffer or by first filling the buffer
      * from the source InputStream and then reading from the buffer.
-     * 
+     *
      * @return the character read or -1 if the end of the reader has been
      *         reached.
      * @throws IOException
      *             if this reader is closed or some other I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public int read() throws IOException {
@@ -377,7 +210,7 @@
      * been reached. The bytes are either obtained from converting bytes in this
      * reader's buffer or by first filling the buffer from the source
      * InputStream and then reading from the buffer.
-     * 
+     *
      * @param buf
      *            the array to store the characters read.
      * @param offset
@@ -393,7 +226,6 @@
      *             {@code buf}.
      * @throws IOException
      *             if this reader is closed or some other I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public int read(char[] buf, int offset, int length) throws IOException {
@@ -465,10 +297,7 @@
 
             if (result == CoderResult.UNDERFLOW && endOfInput) {
                 result = decoder.decode(bytes, out, true);
-                // FIXME: should flush at first, but seems ICU has a bug that it
-                // will throw IAE if some malform/unmappable bytes found during
-                // decoding
-                // result = decoder.flush(out);
+                decoder.flush(out);
                 decoder.reset();
             }
             if (result.isMalformed()) {
@@ -496,12 +325,11 @@
      * {@code read()} is called. This implementation returns {@code true} if
      * there are bytes available in the buffer or the source stream has bytes
      * available.
-     * 
+     *
      * @return {@code true} if the receiver will not block when {@code read()}
      *         is called, {@code false} if unknown or blocking will occur.
      * @throws IOException
      *             if this reader is closed or some other I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public boolean ready() throws IOException {
diff --git a/libcore/luni/src/main/java/java/io/InterruptedIOException.java b/libcore/luni/src/main/java/java/io/InterruptedIOException.java
index de11d28..4d537fc 100644
--- a/libcore/luni/src/main/java/java/io/InterruptedIOException.java
+++ b/libcore/luni/src/main/java/java/io/InterruptedIOException.java
@@ -21,8 +21,6 @@
  * Signals that a blocking I/O operation has been interrupted. The number of
  * bytes that were transferred successfully before the interruption took place
  * is stored in a field of the exception.
- * 
- * @since Android 1.0
  */
 public class InterruptedIOException extends IOException {
 
@@ -30,16 +28,12 @@
 
     /**
      * The number of bytes transferred before the I/O interrupt occurred.
-     * 
-     * @since Android 1.0
      */
     public int bytesTransferred;
 
     /**
      * Constructs a new {@code InterruptedIOException} with its stack trace
      * filled in.
-     * 
-     * @since Android 1.0
      */
     public InterruptedIOException() {
         super();
@@ -51,7 +45,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public InterruptedIOException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/io/InvalidClassException.java b/libcore/luni/src/main/java/java/io/InvalidClassException.java
index 10764b5..4712bb6 100644
--- a/libcore/luni/src/main/java/java/io/InvalidClassException.java
+++ b/libcore/luni/src/main/java/java/io/InvalidClassException.java
@@ -30,8 +30,6 @@
  * 
  * @see ObjectInputStream #readObject()
  * @see ObjectInputValidation#validateObject()
- * 
- * @since Android 1.0
  */
 public class InvalidClassException extends ObjectStreamException {
 
@@ -39,8 +37,6 @@
 
     /**
      * The fully qualified name of the class that caused the problem.
-     * 
-     * @since Android 1.0
      */
     public String classname;
 
@@ -50,7 +46,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public InvalidClassException(String detailMessage) {
         super(detailMessage);
@@ -65,7 +60,6 @@
      *            the name of the class that caused the exception.
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public InvalidClassException(String className, String detailMessage) {
         super(detailMessage);
@@ -80,7 +74,6 @@
      * 
      * @return the detail message, possibly concatenated with the name of the
      *         class that caused the problem.
-     * @since Android 1.0
      */
     @Override
     public String getMessage() {
diff --git a/libcore/luni/src/main/java/java/io/InvalidObjectException.java b/libcore/luni/src/main/java/java/io/InvalidObjectException.java
index a2bb5df..365209d 100644
--- a/libcore/luni/src/main/java/java/io/InvalidObjectException.java
+++ b/libcore/luni/src/main/java/java/io/InvalidObjectException.java
@@ -22,8 +22,6 @@
  * 
  * @see ObjectInputStream#registerValidation(ObjectInputValidation, int)
  * @see ObjectInputValidation#validateObject()
- * 
- * @since Android 1.0
  */
 public class InvalidObjectException extends ObjectStreamException {
 
@@ -35,7 +33,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public InvalidObjectException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/io/LineNumberInputStream.java b/libcore/luni/src/main/java/java/io/LineNumberInputStream.java
index 3bb3997..1a40177 100644
--- a/libcore/luni/src/main/java/java/io/LineNumberInputStream.java
+++ b/libcore/luni/src/main/java/java/io/LineNumberInputStream.java
@@ -27,10 +27,8 @@
  * line terminator sequences are {@code '\r'}, {@code '\n'} and {@code "\r\n"}.
  * When using {@code read}, line terminator sequences are always translated into
  * {@code '\n'}.
- * 
+ *
  * @deprecated Use {@link LineNumberReader}
- * 
- * @since Android 1.0
  */
 @Deprecated
 public class LineNumberInputStream extends FilterInputStream {
@@ -46,10 +44,9 @@
     /**
      * Constructs a new {@code LineNumberInputStream} on the {@link InputStream}
      * {@code in}. Line numbers are counted for all data read from this stream.
-     * 
+     *
      * @param in
      *            The non-null input stream to count line numbers.
-     * @since Android 1.0
      */
     public LineNumberInputStream(InputStream in) {
         super(in);
@@ -63,12 +60,10 @@
      * which are converted into {@code '\n'} by this stream. Therefore,
      * {@code available} returns only {@code in.available() / 2} bytes as
      * result.
-     * </p>
-     * 
+     *
      * @return the guaranteed number of bytes available before blocking.
      * @throws IOException
      *             if an error occurs in this stream.
-     * @since Android 1.0
      */
     @Override
     public int available() throws IOException {
@@ -77,9 +72,8 @@
 
     /**
      * Returns the current line number for this stream. Numbering starts at 0.
-     * 
+     *
      * @return the current line number.
-     * @since Android 1.0
      */
     public int getLineNumber() {
         return lineNumber;
@@ -94,14 +88,12 @@
      * line number count.
      * <p>
      * This implementation sets a mark in the filtered stream.
-     * </p>
-     * 
+     *
      * @param readlimit
      *            the number of bytes that can be read from this stream before
      *            the mark is invalidated.
      * @see #markSupported()
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public void mark(int readlimit) {
@@ -119,14 +111,13 @@
      * Recognized line terminator sequences are {@code '\r'}, {@code '\n'} and
      * {@code "\r\n"}. Line terminator sequences are always translated into
      * {@code '\n'}.
-     * </p>
-     * 
+     *
      * @return the byte read or -1 if the end of the filtered stream has been
      *         reached.
      * @throws IOException
      *             if the stream is closed or another IOException occurs.
-     * @since Android 1.0
      */
+    @SuppressWarnings("fallthrough")
     @Override
     public int read() throws IOException {
         int currentChar = lastChar;
@@ -159,8 +150,7 @@
      * Recognized line terminator sequences are {@code '\r'}, {@code '\n'} and
      * {@code "\r\n"}. Line terminator sequences are always translated into
      * {@code '\n'}.
-     * </p>
-     * 
+     *
      * @param buffer
      *            the array in which to store the bytes read.
      * @param offset
@@ -178,7 +168,6 @@
      *             if this stream is closed or another IOException occurs.
      * @throws NullPointerException
      *             if {@code buffer} is {@code null}.
-     * @since Android 1.0
      */
     @Override
     public int read(byte[] buffer, int offset, int length) throws IOException {
@@ -217,14 +206,13 @@
     /**
      * Resets this stream to the last marked location. It also resets the line
      * count to what is was when this stream was marked.
-     * 
+     *
      * @throws IOException
      *             if this stream is already closed, no mark has been set or the
      *             mark is no longer valid because more than {@code readlimit}
      *             bytes have been read since setting the mark.
      * @see #mark(int)
      * @see #markSupported()
-     * @since Android 1.0
      */
     @Override
     public void reset() throws IOException {
@@ -237,12 +225,11 @@
      * Sets the line number of this stream to the specified
      * {@code lineNumber}. Note that this may have side effects on the
      * line number associated with the last marked position.
-     * 
+     *
      * @param lineNumber
      *            the new lineNumber value.
      * @see #mark(int)
      * @see #reset()
-     * @since Android 1.0
      */
     public void setLineNumber(int lineNumber) {
         this.lineNumber = lineNumber;
@@ -254,7 +241,7 @@
      * used. This implementation skips {@code count} number of bytes in the
      * filtered stream and increments the line number count whenever line
      * terminator sequences are skipped.
-     * 
+     *
      * @param count
      *            the number of bytes to skip.
      * @return the number of bytes actually skipped.
@@ -263,7 +250,6 @@
      * @see #mark(int)
      * @see #read()
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public long skip(long count) throws IOException {
diff --git a/libcore/luni/src/main/java/java/io/LineNumberReader.java b/libcore/luni/src/main/java/java/io/LineNumberReader.java
index 8110426..8ecdd95 100644
--- a/libcore/luni/src/main/java/java/io/LineNumberReader.java
+++ b/libcore/luni/src/main/java/java/io/LineNumberReader.java
@@ -22,8 +22,6 @@
  * while reading the data. The line number starts at 0 and is incremented any
  * time {@code '\r'}, {@code '\n'} or {@code "\r\n"} is read. The class has an
  * internal buffer for its data. The size of the buffer defaults to 8 KB.
- * 
- * @since Android 1.0
  */
 public class LineNumberReader extends BufferedReader {
 
@@ -38,10 +36,9 @@
     /**
      * Constructs a new LineNumberReader on the Reader {@code in}. The internal
      * buffer gets the default size (8 KB).
-     * 
+     *
      * @param in
      *            the Reader that is buffered.
-     * @since Android 1.0
      */
     public LineNumberReader(Reader in) {
         super(in);
@@ -50,14 +47,13 @@
     /**
      * Constructs a new LineNumberReader on the Reader {@code in}. The size of
      * the internal buffer is specified by the parameter {@code size}.
-     * 
+     *
      * @param in
      *            the Reader that is buffered.
      * @param size
      *            the size of the buffer to allocate.
      * @throws IllegalArgumentException
      *             if {@code size <= 0}.
-     * @since Android 1.0
      */
     public LineNumberReader(Reader in, int size) {
         super(in, size);
@@ -65,9 +61,8 @@
 
     /**
      * Returns the current line number for this reader. Numbering starts at 0.
-     * 
+     *
      * @return the current line number.
-     * @since Android 1.0
      */
     public int getLineNumber() {
         synchronized (lock) {
@@ -82,7 +77,7 @@
      * position, provided that {@code readlimit} has not been surpassed. The
      * line number associated with this marked position is also stored so that
      * it can be restored when {@code reset()} is called.
-     * 
+     *
      * @param readlimit
      *            the number of characters that can be read from this stream
      *            before the mark is invalidated.
@@ -90,7 +85,6 @@
      *             if an error occurs while setting the mark in this reader.
      * @see #markSupported()
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public void mark(int readlimit) throws IOException {
@@ -110,14 +104,13 @@
      * Recognized line terminator sequences are {@code '\r'}, {@code '\n'} and
      * {@code "\r\n"}. Line terminator sequences are always translated into
      * {@code '\n'}.
-     * </p>
-     * 
+     *
      * @return the character read or -1 if the end of the source reader has been
      *         reached.
      * @throws IOException
      *             if the reader is closed or another IOException occurs.
-     * @since Android 1.0
      */
+    @SuppressWarnings("fallthrough")
     @Override
     public int read() throws IOException {
         synchronized (lock) {
@@ -148,8 +141,7 @@
      * Recognized line terminator sequences are {@code '\r'}, {@code '\n'} and
      * {@code "\r\n"}. Line terminator sequences are always translated into
      * {@code '\n'}.
-     * </p>
-     * 
+     *
      * @param buffer
      *            the array in which to store the characters read.
      * @param offset
@@ -161,7 +153,6 @@
      *         source reader has been reached while reading.
      * @throws IOException
      *             if this reader is closed or another IOException occurs.
-     * @since Android 1.0
      */
     @Override
     public int read(char[] buffer, int offset, int count) throws IOException {
@@ -193,28 +184,17 @@
      * represented by 0 or more characters followed by {@code '\r'},
      * {@code '\n'}, {@code "\r\n"} or the end of the stream. The returned
      * string does not include the newline sequence.
-     * 
+     *
      * @return the contents of the line or {@code null} if no characters have
      *         been read before the end of the stream has been reached.
      * @throws IOException
      *             if this reader is closed or another IOException occurs.
-     * @since Android 1.0
      */
     @Override
     public String readLine() throws IOException {
         synchronized (lock) {
-            /* Typical Line Length */
-            StringBuilder result = new StringBuilder(80);
-            while (true) {
-                int character = read();
-                if (character == -1) {
-                    return result.length() != 0 ? result.toString() : null;
-                }
-                if (character == '\n') {
-                    return result.toString();
-                }
-                result.append((char) character);
-            }
+            lineNumber++;
+            return super.readLine();
         }
     }
 
@@ -222,14 +202,13 @@
      * Resets this reader to the last marked location. It also resets the line
      * count to what is was when this reader was marked. This implementation
      * resets the source reader.
-     * 
+     *
      * @throws IOException
      *             if this reader is already closed, no mark has been set or the
      *             mark is no longer valid because more than {@code readlimit}
      *             bytes have been read since setting the mark.
      * @see #mark(int)
      * @see #markSupported()
-     * @since Android 1.0
      */
     @Override
     public void reset() throws IOException {
@@ -244,12 +223,11 @@
      * Sets the line number of this reader to the specified {@code lineNumber}.
      * Note that this may have side effects on the line number associated with
      * the last marked position.
-     * 
+     *
      * @param lineNumber
      *            the new line number value.
      * @see #mark(int)
      * @see #reset()
-     * @since Android 1.0
      */
     public void setLineNumber(int lineNumber) {
         synchronized (lock) {
@@ -263,7 +241,7 @@
      * is used. This implementation skips {@code count} number of characters in
      * the source reader and increments the line number count whenever line
      * terminator sequences are skipped.
-     * 
+     *
      * @param count
      *            the number of characters to skip.
      * @return the number of characters actually skipped.
@@ -274,7 +252,6 @@
      * @see #mark(int)
      * @see #read()
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public long skip(long count) throws IOException {
diff --git a/libcore/luni/src/main/java/java/io/NotActiveException.java b/libcore/luni/src/main/java/java/io/NotActiveException.java
index 402eabe..51f4d3f 100644
--- a/libcore/luni/src/main/java/java/io/NotActiveException.java
+++ b/libcore/luni/src/main/java/java/io/NotActiveException.java
@@ -29,8 +29,6 @@
  * <li>{@link ObjectInputStream#registerValidation(ObjectInputValidation, int)}</li>
  * <li>{@link ObjectOutputStream#defaultWriteObject()}</li>
  * </ul>
- * 
- * @since Android 1.0
  */
 public class NotActiveException extends ObjectStreamException {
 
@@ -39,8 +37,6 @@
     /**
      * Constructs a new {@code NotActiveException} with its stack trace filled
      * in.
-     * 
-     * @since Android 1.0
      */
     public NotActiveException() {
         super();
@@ -52,7 +48,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public NotActiveException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/io/NotSerializableException.java b/libcore/luni/src/main/java/java/io/NotSerializableException.java
index ac57a76..f6e93a7 100644
--- a/libcore/luni/src/main/java/java/io/NotSerializableException.java
+++ b/libcore/luni/src/main/java/java/io/NotSerializableException.java
@@ -26,8 +26,6 @@
  * 
  * @see ObjectOutput#writeObject(Object)
  * @see ObjectOutputStream#writeObject(Object)
- * 
- * @since Android 1.0
  */
 public class NotSerializableException extends ObjectStreamException {
 
@@ -36,8 +34,6 @@
     /**
      * Constructs a new {@code NotSerializableException} with its stack trace
      * filled in.
-     * 
-     * @since Android 1.0
      */
     public NotSerializableException() {
         super();
@@ -49,7 +45,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public NotSerializableException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/io/ObjectInput.java b/libcore/luni/src/main/java/java/io/ObjectInput.java
index 7ca3cbe..3b32553 100644
--- a/libcore/luni/src/main/java/java/io/ObjectInput.java
+++ b/libcore/luni/src/main/java/java/io/ObjectInput.java
@@ -22,8 +22,6 @@
  * 
  * @see ObjectInputStream
  * @see ObjectOutput
- * 
- * @since Android 1.0
  */
 public interface ObjectInput extends DataInput {
     /**
@@ -33,7 +31,6 @@
      * @return the number of bytes available.
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
     public int available() throws IOException;
 
@@ -43,7 +40,6 @@
      * 
      * @throws IOException
      *             if an I/O error occurs while closing the input stream.
-     * @since Android 1.0
      */
     public void close() throws IOException;
 
@@ -55,7 +51,6 @@
      * @return the byte read or -1 if the end of this stream has been reached.
      * @throws IOException
      *             if this stream is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public int read() throws IOException;
 
@@ -69,7 +64,6 @@
      *         reached.
      * @throws IOException
      *             if this stream is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public int read(byte[] buffer) throws IOException;
 
@@ -89,7 +83,6 @@
      *         reached.
      * @throws IOException
      *             if this stream is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public int read(byte[] buffer, int offset, int count) throws IOException;
 
@@ -102,7 +95,6 @@
      *             if the object's class cannot be found.
      * @throws IOException
      *             if this stream is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public Object readObject() throws ClassNotFoundException, IOException;
 
@@ -117,7 +109,6 @@
      * 
      * @throws IOException
      *             if this stream is closed or another I/O error occurs.
-     * @since Android 1.0             
      */
     public long skip(long toSkip) throws IOException;
 }
diff --git a/libcore/luni/src/main/java/java/io/ObjectInputStream.java b/libcore/luni/src/main/java/java/io/ObjectInputStream.java
index 9483ab0..6d24eb2 100644
--- a/libcore/luni/src/main/java/java/io/ObjectInputStream.java
+++ b/libcore/luni/src/main/java/java/io/ObjectInputStream.java
@@ -17,6 +17,11 @@
 
 package java.io;
 
+// BEGIN android-note
+// Harmony uses ObjectAccessors to access fields through JNI. Android has not
+// yet migrated that API. As a consequence, there's a lot of changes here...
+// END android-note
+
 import java.io.EmulatedFields.ObjectSlot;
 import java.lang.reflect.Array;
 import java.lang.reflect.Constructor;
@@ -27,14 +32,20 @@
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
-import java.util.Hashtable;
-import java.util.IdentityHashMap;
+import java.util.HashMap;
 import java.util.Iterator;
 
 // BEGIN android-added
 import dalvik.system.VMStack;
 // END android-added
 
+// BEGIN android-removed
+// import org.apache.harmony.misc.accessors.ObjectAccessor;
+// import org.apache.harmony.misc.accessors.AccessorFactory;
+// END android-removed
+
+import org.apache.harmony.kernel.vm.VM;
+import org.apache.harmony.luni.internal.nls.Messages;
 import org.apache.harmony.luni.util.Msg;
 import org.apache.harmony.luni.util.PriviAction;
 
@@ -42,18 +53,19 @@
  * A specialized {@link InputStream} that is able to read (deserialize) Java
  * objects as well as primitive data types (int, byte, char etc.). The data has
  * typically been saved using an ObjectOutputStream.
- * 
+ *
  * @see ObjectOutputStream
  * @see ObjectInput
  * @see Serializable
  * @see Externalizable
- * 
- * @since Android 1.0
  */
 public class ObjectInputStream extends InputStream implements ObjectInput,
         ObjectStreamConstants {
 
-    private static InputStream emptyStream = new ByteArrayInputStream(
+    // BEGIN android-note
+    // this is non-static to avoid sync contention. Would static be faster?
+    // END android-note
+    private InputStream emptyStream = new ByteArrayInputStream(
             new byte[0]);
 
     // To put into objectsRead when reading unsharedObject
@@ -85,7 +97,7 @@
     private boolean enableResolve;
 
     // Table mapping Integer (handle) -> Object
-    private Hashtable<Integer, Object> objectsRead;
+    private HashMap<Integer, Object> objectsRead;
 
     // Used by defaultReadObject
     private Object currentObject;
@@ -109,10 +121,8 @@
     // Handle for the current class descriptor
     private Integer descriptorHandle;
 
-    // cache for readResolve methods
-    private IdentityHashMap<Class<?>, Object> readResolveCache;
-
-    private static final Hashtable<String, Class<?>> PRIMITIVE_CLASSES = new Hashtable<String, Class<?>>();
+    private static final HashMap<String, Class<?>> PRIMITIVE_CLASSES =
+        new HashMap<String, Class<?>>();
 
     static {
         PRIMITIVE_CLASSES.put("byte", byte.class); //$NON-NLS-1$
@@ -125,6 +135,10 @@
         PRIMITIVE_CLASSES.put("double", double.class); //$NON-NLS-1$
     }
 
+    // BEGIN android-removed
+    // private ObjectAccessor accessor = AccessorFactory.getObjectAccessor();
+    // END android-removed
+
     // Internal type used to keep track of validators & corresponding priority
     static class InputValidationDesc {
         ObjectInputValidation validator;
@@ -135,22 +149,19 @@
     /**
      * GetField is an inner class that provides access to the persistent fields
      * read from the source stream.
-     * 
-     * @since Android 1.0
      */
     public abstract static class GetField {
         /**
          * Gets the ObjectStreamClass that describes a field.
-         * 
+         *
          * @return the descriptor class for a serialized field.
-         * @since Android 1.0
          */
         public abstract ObjectStreamClass getObjectStreamClass();
 
         /**
          * Indicates if the field identified by {@code name} is defaulted. This
          * means that it has no value in this stream.
-         * 
+         *
          * @param name
          *            the name of the field to check.
          * @return {@code true} if the field is defaulted, {@code false}
@@ -160,7 +171,6 @@
          * @throws IOException
          *             if an error occurs while reading from the source input
          *             stream.
-         * @since Android 1.0
          */
         public abstract boolean defaulted(String name) throws IOException,
                 IllegalArgumentException;
@@ -168,7 +178,7 @@
         /**
          * Gets the value of the boolean field identified by {@code name} from
          * the persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to get.
          * @param defaultValue
@@ -181,7 +191,6 @@
          * @throws IllegalArgumentException
          *             if the type of the field identified by {@code name} is
          *             not {@code boolean}.
-         * @since Android 1.0
          */
         public abstract boolean get(String name, boolean defaultValue)
                 throws IOException, IllegalArgumentException;
@@ -189,7 +198,7 @@
         /**
          * Gets the value of the character field identified by {@code name} from
          * the persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to get.
          * @param defaultValue
@@ -202,7 +211,6 @@
          * @throws IllegalArgumentException
          *             if the type of the field identified by {@code name} is
          *             not {@code char}.
-         * @since Android 1.0
          */
         public abstract char get(String name, char defaultValue)
                 throws IOException, IllegalArgumentException;
@@ -210,7 +218,7 @@
         /**
          * Gets the value of the byte field identified by {@code name} from the
          * persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to get.
          * @param defaultValue
@@ -223,7 +231,6 @@
          * @throws IllegalArgumentException
          *             if the type of the field identified by {@code name} is
          *             not {@code byte}.
-         * @since Android 1.0
          */
         public abstract byte get(String name, byte defaultValue)
                 throws IOException, IllegalArgumentException;
@@ -231,7 +238,7 @@
         /**
          * Gets the value of the short field identified by {@code name} from the
          * persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to get.
          * @param defaultValue
@@ -244,7 +251,6 @@
          * @throws IllegalArgumentException
          *             if the type of the field identified by {@code name} is
          *             not {@code short}.
-         * @since Android 1.0
          */
         public abstract short get(String name, short defaultValue)
                 throws IOException, IllegalArgumentException;
@@ -252,7 +258,7 @@
         /**
          * Gets the value of the integer field identified by {@code name} from
          * the persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to get.
          * @param defaultValue
@@ -265,15 +271,14 @@
          * @throws IllegalArgumentException
          *             if the type of the field identified by {@code name} is
          *             not {@code int}.
-         * @since Android 1.0
          */
         public abstract int get(String name, int defaultValue)
                 throws IOException, IllegalArgumentException;
 
-       /**
+        /**
          * Gets the value of the long field identified by {@code name} from the
          * persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to get.
          * @param defaultValue
@@ -286,7 +291,6 @@
          * @throws IllegalArgumentException
          *             if the type of the field identified by {@code name} is
          *             not {@code long}.
-         * @since Android 1.0
          */
         public abstract long get(String name, long defaultValue)
                 throws IOException, IllegalArgumentException;
@@ -294,7 +298,7 @@
         /**
          * Gets the value of the float field identified by {@code name} from the
          * persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to get.
          * @param defaultValue
@@ -307,7 +311,6 @@
          * @throws IllegalArgumentException
          *             if the type of the field identified by {@code float} is
          *             not {@code char}.
-         * @since Android 1.0
          */
         public abstract float get(String name, float defaultValue)
                 throws IOException, IllegalArgumentException;
@@ -315,7 +318,7 @@
         /**
          * Gets the value of the double field identified by {@code name} from
          * the persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to get.
          * @param defaultValue
@@ -328,7 +331,6 @@
          * @throws IllegalArgumentException
          *             if the type of the field identified by {@code name} is
          *             not {@code double}.
-         * @since Android 1.0
          */
         public abstract double get(String name, double defaultValue)
                 throws IOException, IllegalArgumentException;
@@ -336,7 +338,7 @@
         /**
          * Gets the value of the object field identified by {@code name} from
          * the persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to get.
          * @param defaultValue
@@ -349,7 +351,6 @@
          * @throws IllegalArgumentException
          *             if the type of the field identified by {@code name} is
          *             not {@code Object}.
-         * @since Android 1.0
          */
         public abstract Object get(String name, Object defaultValue)
                 throws IOException, IllegalArgumentException;
@@ -359,14 +360,13 @@
      * Constructs a new ObjectInputStream. This default constructor can be used
      * by subclasses that do not want to use the public constructor if it
      * allocates unneeded data.
-     * 
+     *
      * @throws IOException
      *             if an error occurs when creating this stream.
      * @throws SecurityException
      *             if a security manager is installed and it denies subclassing
      *             this class.
      * @see SecurityManager#checkPermission(java.security.Permission)
-     * @since Android 1.0
      */
     protected ObjectInputStream() throws IOException, SecurityException {
         super();
@@ -382,7 +382,7 @@
     /**
      * Constructs a new ObjectInputStream that reads from the InputStream
      * {@code input}.
-     * 
+     *
      * @param input
      *            the non-null source InputStream to filter reads on.
      * @throws IOException
@@ -393,7 +393,6 @@
      * @throws SecurityException
      *             if a security manager is installed and it denies subclassing
      *             this class.
-     * @since Android 1.0
      */
     public ObjectInputStream(InputStream input)
             throws StreamCorruptedException, IOException {
@@ -437,7 +436,6 @@
         primitiveTypes = new DataInputStream(this);
         enableResolve = false;
         this.subclassOverridingImplementation = false;
-        this.readResolveCache = new IdentityHashMap<Class<?>, Object>();
         resetState();
         nestedLevels = 0;
         // So read...() methods can be used by
@@ -452,12 +450,11 @@
      * Returns the number of bytes of primitive data that can be read from this
      * stream without blocking. This method should not be used at any arbitrary
      * position; just when reading primitive data types (int, char etc).
-     * 
+     *
      * @return the number of available primitive data bytes.
      * @throws IOException
      *             if any I/O problem occurs while computing the available
      *             bytes.
-     * @since Android 1.0
      */
     @Override
     public int available() throws IOException {
@@ -470,7 +467,7 @@
      * Checks to if it is ok to read primitive types from this stream at
      * this point. One is not supposed to read primitive types when about to
      * read an object, for example, so an exception has to be thrown.
-     * 
+     *
      * @throws IOException
      *             If any IO problem occurred when trying to read primitive type
      *             or if it is illegal to read primitive types
@@ -514,10 +511,9 @@
 
     /**
      * Closes this stream. This implementation closes the source stream.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this stream.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -528,7 +524,7 @@
      * Default method to read objects from this stream. Serializable fields
      * defined in the object's class and superclasses are read from the source
      * stream.
-     * 
+     *
      * @throws ClassNotFoundException
      *             if the object's class cannot be found.
      * @throws IOException
@@ -536,7 +532,6 @@
      * @throws NotActiveException
      *             if this method is not called from {@code readObject()}.
      * @see ObjectOutputStream#defaultWriteObject
-     * @since Android 1.0
      */
     public void defaultReadObject() throws IOException, ClassNotFoundException,
             NotActiveException {
@@ -552,7 +547,7 @@
      * Enables object replacement for this stream. By default this is not
      * enabled. Only trusted subclasses (loaded with system class loader) are
      * allowed to change this status.
-     * 
+     *
      * @param enable
      *            {@code true} to enable object replacement; {@code false} to
      *            disable it.
@@ -562,7 +557,6 @@
      *             object replacement for this stream.
      * @see #resolveObject
      * @see ObjectOutputStream#enableReplaceObject
-     * @since Android 1.0
      */
     protected boolean enableResolveObject(boolean enable)
             throws SecurityException {
@@ -581,7 +575,7 @@
 
     /**
      * Checks if two classes belong to the same package.
-     * 
+     *
      * @param c1
      *            one of the classes to test.
      * @param c2
@@ -594,12 +588,9 @@
         String nameC2 = c2.getName();
         int indexDotC1 = nameC1.lastIndexOf('.');
         int indexDotC2 = nameC2.lastIndexOf('.');
-        // BEGIN android-changed
-        // copied from newer version of harmony
         if (indexDotC1 != indexDotC2) {
             return false; // cannot be in the same package if indices are not
         }
-        // END android-changed
         // the same
         if (indexDotC1 < 0) {
             return true; // both of them are in default package
@@ -608,16 +599,17 @@
                 nameC2.substring(0, indexDotC2));
     }
 
+    // BEGIN android-added
     /**
      * Create and return a new instance of class {@code instantiationClass}
      * but running the constructor defined in class
      * {@code constructorClass} (same as {@code instantiationClass}
      * or a superclass).
-     * 
+     *
      * Has to be native to avoid visibility rules and to be able to have
      * {@code instantiationClass} not the same as
      * {@code constructorClass} (no such API in java.lang.reflect).
-     * 
+     *
      * @param instantiationClass
      *            The new object will be an instance of this class
      * @param constructorClass
@@ -626,26 +618,27 @@
      */
     private static native Object newInstance(Class<?> instantiationClass,
             Class<?> constructorClass);
+    // END android-added
 
     /**
      * Return the next {@code int} handle to be used to indicate cyclic
      * references being loaded from the stream.
-     * 
+     *
      * @return the next handle to represent the next cyclic reference
      */
-    private int nextHandle() {
-        return this.currentHandle++;
+    private Integer nextHandle() {
+        return Integer.valueOf(this.currentHandle++);
     }
 
     /**
      * Return the next token code (TC) from the receiver, which indicates what
      * kind of object follows
-     * 
+     *
      * @return the next TC from the receiver
-     * 
+     *
      * @throws IOException
      *             If an IO error occurs
-     * 
+     *
      * @see ObjectStreamConstants
      */
     private byte nextTC() throws IOException {
@@ -670,12 +663,11 @@
      * Reads a single byte from the source stream and returns it as an integer
      * in the range from 0 to 255. Returns -1 if the end of the source stream
      * has been reached. Blocks if no input is available.
-     * 
+     *
      * @return the byte read or -1 if the end of the source stream has been
      *         reached.
      * @throws IOException
      *             if an error occurs while reading from this stream.
-     * @since Android 1.0
      */
     @Override
     public int read() throws IOException {
@@ -688,7 +680,7 @@
      * in byte array {@code buffer} starting at offset {@code count}. Blocks
      * until {@code count} bytes have been read, the end of the source stream is
      * detected or an exception is thrown.
-     * 
+     *
      * @param buffer
      *            the array in which to store the bytes read.
      * @param offset
@@ -706,7 +698,6 @@
      *             if an error occurs while reading from this stream.
      * @throws NullPointerException
      *             if {@code buffer} is {@code null}.
-     * @since Android 1.0
      */
     @Override
     public int read(byte[] buffer, int offset, int length) throws IOException {
@@ -734,9 +725,9 @@
      * Reads and returns an array of raw bytes with primitive data. The array
      * will have up to 255 bytes. The primitive data will be in the format
      * described by {@code DataOutputStream}.
-     * 
+     *
      * @return The primitive data read, as raw bytes
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the primitive data.
      */
@@ -750,9 +741,9 @@
      * Reads and returns an array of raw bytes with primitive data. The array
      * will have more than 255 bytes. The primitive data will be in the format
      * described by {@code DataOutputStream}.
-     * 
+     *
      * @return The primitive data read, as raw bytes
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the primitive data.
      */
@@ -764,14 +755,13 @@
 
     /**
      * Reads a boolean from the source stream.
-     * 
+     *
      * @return the boolean value read from the source stream.
      * @throws EOFException
      *             if the end of the input is reached before the read
      *             request can be satisfied.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     public boolean readBoolean() throws IOException {
         return primitiveTypes.readBoolean();
@@ -779,14 +769,13 @@
 
     /**
      * Reads a byte (8 bit) from the source stream.
-     * 
+     *
      * @return the byte value read from the source stream.
      * @throws EOFException
      *             if the end of the input is reached before the read
      *             request can be satisfied.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     public byte readByte() throws IOException {
         return primitiveTypes.readByte();
@@ -794,14 +783,13 @@
 
     /**
      * Reads a character (16 bit) from the source stream.
-     * 
+     *
      * @return the char value read from the source stream.
      * @throws EOFException
      *             if the end of the input is reached before the read
      *             request can be satisfied.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     public char readChar() throws IOException {
         return primitiveTypes.readChar();
@@ -809,7 +797,7 @@
 
     /**
      * Reads and discards block data and objects until TC_ENDBLOCKDATA is found.
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the optional class
      *             annotation.
@@ -834,9 +822,9 @@
     /**
      * Reads a class descriptor (an {@code ObjectStreamClass}) from the
      * stream.
-     * 
+     *
      * @return the class descriptor read from the stream
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the class
      *             descriptor.
@@ -855,8 +843,7 @@
                 ObjectStreamClass streamClass = ObjectStreamClass
                         .lookup(proxyClass);
                 streamClass.setLoadFields(new ObjectStreamField[0]);
-                registerObjectRead(streamClass, Integer.valueOf(nextHandle()),
-                        false);
+                registerObjectRead(streamClass, nextHandle(), false);
                 checkedSetSuperClassDesc(streamClass, readClassDesc());
                 return streamClass;
             case TC_REFERENCE:
@@ -872,11 +859,11 @@
     /**
      * Reads the content of the receiver based on the previously read token
      * {@code tc}.
-     * 
+     *
      * @param tc
      *            The token code for the next item in the stream
      * @return the object read from the stream
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the class
      *             descriptor.
@@ -922,11 +909,11 @@
     /**
      * Reads the content of the receiver based on the previously read token
      * {@code tc}. Primitive data content is considered an error.
-     * 
+     *
      * @param unshared
      *            read the object unshared
      * @return the object read from the stream
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the class
      *             descriptor.
@@ -990,9 +977,9 @@
     /**
      * Reads the next item from the stream assuming it is a cyclic reference to
      * an object previously read. Return the actual object previously read.
-     * 
+     *
      * @return the object previously read from the stream
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the class
      *             descriptor.
@@ -1006,14 +993,13 @@
 
     /**
      * Reads a double (64 bit) from the source stream.
-     * 
+     *
      * @return the double value read from the source stream.
      * @throws EOFException
      *             if the end of the input is reached before the read
      *             request can be satisfied.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     public double readDouble() throws IOException {
         return primitiveTypes.readDouble();
@@ -1029,9 +1015,9 @@
      * When exceptions are found normally in the object graph, they are loaded
      * as a regular object, and not by this method. In that case, the set of
      * "known objects" is not reset.
-     * 
+     *
      * @return the exception read
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the exception
      *             object.
@@ -1064,17 +1050,17 @@
     /**
      * Reads a collection of field descriptors (name, type name, etc) for the
      * class descriptor {@code cDesc} (an {@code ObjectStreamClass})
-     * 
+     *
      * @param cDesc
      *            The class descriptor (an {@code ObjectStreamClass})
      *            for which to write field information
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the field
      *             descriptors.
      * @throws ClassNotFoundException
      *             If a class for one of the field types could not be found
-     * 
+     *
      * @see #readObject()
      */
     private void readFieldDescriptors(ObjectStreamClass cDesc)
@@ -1109,17 +1095,45 @@
                     enableResolve = old;
                 }
             }
+
+            classSig = formatClassSig(classSig);
             ObjectStreamField f = new ObjectStreamField(classSig, fieldName);
             fields[i] = f;
         }
     }
 
+    /*
+     * Format the class signature for ObjectStreamField, for example,
+     * "[L[Ljava.lang.String;;" is converted to "[Ljava.lang.String;"
+     */
+    private static String formatClassSig(String classSig) {
+        int start = 0;
+        int end = classSig.length();
+
+        if (end <= 0) {
+            return classSig;
+        }
+
+        while (classSig.startsWith("[L", start) //$NON-NLS-1$
+                && classSig.charAt(end - 1) == ';') {
+            start += 2;
+            end--;
+        }
+
+        if (start > 0) {
+            start -= 2;
+            end++;
+            return classSig.substring(start, end);
+        }
+        return classSig;
+    }
+
     /**
      * Reads the persistent fields of the object that is currently being read
      * from the source stream. The values read are stored in a GetField object
      * that provides access to the persistent fields. This GetField object is
      * then returned.
-     * 
+     *
      * @return the GetField object from which persistent fields can be accessed
      *         by name.
      * @throws ClassNotFoundException
@@ -1129,7 +1143,6 @@
      *             if an error occurs while reading from this stream.
      * @throws NotActiveException
      *             if this stream is currently not reading an object.
-     * @since Android 1.0
      */
     public GetField readFields() throws IOException, ClassNotFoundException,
             NotActiveException {
@@ -1146,11 +1159,11 @@
     /**
      * Reads a collection of field values for the emulated fields
      * {@code emulatedFields}
-     * 
+     *
      * @param emulatedFields
      *            an {@code EmulatedFieldsForLoading}, concrete subclass
      *            of {@code GetField}
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the field values.
      * @throws InvalidClassException
@@ -1159,7 +1172,7 @@
      * @throws OptionalDataException
      *             If optional data could not be found when reading the
      *             exception graph
-     * 
+     *
      * @see #readFields
      * @see #readObject()
      */
@@ -1206,13 +1219,13 @@
      * This is the default mechanism, when emulated fields (an
      * {@code GetField}) are not used. Actual values to load are stored
      * directly into the object {@code obj}.
-     * 
+     *
      * @param obj
      *            Instance in which the fields will be set.
      * @param classDesc
      *            A class descriptor (an {@code ObjectStreamClass})
      *            defining which fields should be loaded.
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the field values.
      * @throws InvalidClassException
@@ -1223,7 +1236,7 @@
      *             exception graph
      * @throws ClassNotFoundException
      *             If a class of an object being de-serialized can not be found
-     * 
+     *
      * @see #readFields
      * @see #readObject()
      */
@@ -1238,9 +1251,16 @@
         }
 
         for (ObjectStreamField fieldDesc : fields) {
+
+            // BEGIN android-removed
+            // // get associated Field
+            // long fieldID = fieldDesc.getFieldID(accessor, declaringClass);
+            // END android-removed
+
             // Code duplication starts, just because Java is typed
             if (fieldDesc.isPrimitive()) {
                 try {
+                    // BEGIN android-changed
                     switch (fieldDesc.getTypeCode()) {
                         case 'B':
                             setField(obj, declaringClass, fieldDesc.getName(),
@@ -1278,19 +1298,22 @@
                             throw new StreamCorruptedException(Msg.getString(
                                     "K00d5", fieldDesc.getTypeCode())); //$NON-NLS-1$
                     }
+                    // END android-changed
                 } catch (NoSuchFieldError err) {
                 }
             } else {
                 // Object type (array included).
                 String fieldName = fieldDesc.getName();
                 boolean setBack = false;
+                // BEGIN android-added
                 ObjectStreamField field = classDesc.getField(fieldName);
-                if (mustResolve && field == null) {
+                // END android-added
+                if (mustResolve && fieldDesc == null) {
                     setBack = true;
                     mustResolve = false;
                 }
                 Object toSet;
-                if (field != null && field.isUnshared()) {
+                if (fieldDesc != null && fieldDesc.isUnshared()) {
                     toSet = readUnshared();
                 } else {
                     toSet = readObject();
@@ -1298,18 +1321,15 @@
                 if (setBack) {
                     mustResolve = true;
                 }
-                if (field != null) {
+                if (fieldDesc != null) {
                     if (toSet != null) {
-                        // BEGIN android-removed
-                        // Class<?> fieldType = field.getType();
-                        // END android-removed
-                        // BEGIN android-added
-                        // Originally getTypeInternal() was called getType().
-                        // After the semantics of getType() changed inside
-                        // Harmony, the check below wasn't adjusted and didn't
-                        // work anymore.
+                        // BEGIN android-changed
+                        // Get the field type from the local field rather than
+                        // from the stream's supplied data. That's the field
+                        // we'll be setting, so that's the one that needs to be
+                        // validated.
                         Class<?> fieldType = field.getTypeInternal();
-                        // END android-added                        
+                        // END android-added
                         Class<?> valueType = toSet.getClass();
                         if (!fieldType.isAssignableFrom(valueType)) {
                             throw new ClassCastException(Msg.getString(
@@ -1319,8 +1339,10 @@
                                                     + fieldName }));
                         }
                         try {
+                            // BEGIN android-changed
                             objSetField(obj, declaringClass, fieldName, field
                                     .getTypeString(), toSet);
+                            // END android-changed
                         } catch (NoSuchFieldError e) {
                             // Ignored
                         }
@@ -1332,14 +1354,13 @@
 
     /**
      * Reads a float (32 bit) from the source stream.
-     * 
+     *
      * @return the float value read from the source stream.
      * @throws EOFException
      *             if the end of the input is reached before the read
      *             request can be satisfied.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     public float readFloat() throws IOException {
         return primitiveTypes.readFloat();
@@ -1348,7 +1369,7 @@
     /**
      * Reads bytes from the source stream into the byte array {@code buffer}.
      * This method will block until {@code buffer.length} bytes have been read.
-     * 
+     *
      * @param buffer
      *            the array in which to store the bytes read.
      * @throws EOFException
@@ -1356,7 +1377,6 @@
      *             request can be satisfied.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     public void readFully(byte[] buffer) throws IOException {
         primitiveTypes.readFully(buffer);
@@ -1366,7 +1386,7 @@
      * Reads bytes from the source stream into the byte array {@code buffer}.
      * This method will block until {@code length} number of bytes have been
      * read.
-     * 
+     *
      * @param buffer
      *            the byte array in which to store the bytes read.
      * @param offset
@@ -1379,7 +1399,6 @@
      *             request can be satisfied.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     public void readFully(byte[] buffer, int offset, int length)
             throws IOException {
@@ -1394,13 +1413,13 @@
      * (corresponding to class descriptor {@code classDesc}) defines
      * private instance method {@code readObject} it will be used to load
      * field values.
-     * 
+     *
      * @param object
      *            Instance into which stored field values loaded.
      * @param classDesc
      *            A class descriptor (an {@code ObjectStreamClass})
      *            defining which fields should be loaded.
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the field values in
      *             the hierarchy.
@@ -1409,7 +1428,7 @@
      * @throws NotActiveException
      *             If {@code defaultReadObject} is called from the wrong
      *             context.
-     * 
+     *
      * @see #defaultReadObject
      * @see #readObject()
      */
@@ -1449,7 +1468,7 @@
                 int index = findStreamSuperclass(superclass, streamClassList,
                         lastIndex);
                 if (index == -1) {
-                    readObjectNoData(object, superclass);
+                    readObjectNoData(object, superclass, ObjectStreamClass.lookupStreamClass(superclass));
                 } else {
                     for (int j = lastIndex; j <= index; j++) {
                         readObjectForClass(object, streamClassList.get(j));
@@ -1483,16 +1502,13 @@
         return -1;
     }
 
-    private void readObjectNoData(Object object, Class<?> cl)
+    private void readObjectNoData(Object object, Class<?> cl, ObjectStreamClass classDesc)
             throws ObjectStreamException {
-        if (!ObjectStreamClass.isSerializable(cl)) {
+        if (!classDesc.isSerializable()) {
             return;
         }
-
-        final Method readMethod = ObjectStreamClass
-                .getPrivateReadObjectNoDataMethod(cl);
-        if (readMethod != null) {
-            AccessController.doPrivileged(new PriviAction<Object>(readMethod));
+        if (classDesc.hasMethodReadObjectNoData()){
+            final Method readMethod = classDesc.getMethodReadObjectNoData();
             try {
                 readMethod.invoke(object, new Object[0]);
             } catch (InvocationTargetException e) {
@@ -1507,6 +1523,7 @@
                 throw new RuntimeException(e.toString());
             }
         }
+
     }
 
     private void readObjectForClass(Object object, ObjectStreamClass classDesc)
@@ -1518,12 +1535,12 @@
 
         boolean hadWriteMethod = (classDesc.getFlags() & SC_WRITE_METHOD) > 0;
         Class<?> targetClass = classDesc.forClass();
+
         final Method readMethod;
         if (targetClass == null || !mustResolve) {
             readMethod = null;
         } else {
-            readMethod = ObjectStreamClass
-                    .getPrivateReadObjectMethod(targetClass);
+            readMethod = classDesc.getMethodReadObject();
         }
         try {
             if (readMethod != null) {
@@ -1562,30 +1579,27 @@
 
     /**
      * Reads an integer (32 bit) from the source stream.
-     * 
+     *
      * @return the integer value read from the source stream.
      * @throws EOFException
      *             if the end of the input is reached before the read
      *             request can be satisfied.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     public int readInt() throws IOException {
         return primitiveTypes.readInt();
     }
 
     /**
-     * Reads the next line from the source stream. Lines are terminated by 
+     * Reads the next line from the source stream. Lines are terminated by
      * {@code '\r'}, {@code '\n'}, {@code "\r\n"} or an {@code EOF}.
-     * 
+     *
      * @return the string read from the source stream.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
      * @deprecated Use {@link BufferedReader}
-     * @since Android 1.0
      */
-    @SuppressWarnings("deprecation")
     @Deprecated
     public String readLine() throws IOException {
         return primitiveTypes.readLine();
@@ -1593,14 +1607,13 @@
 
     /**
      * Reads a long (64 bit) from the source stream.
-     * 
+     *
      * @return the long value read from the source stream.
      * @throws EOFException
      *             if the end of the input is reached before the read
      *             request can be satisfied.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     public long readLong() throws IOException {
         return primitiveTypes.readLong();
@@ -1609,11 +1622,11 @@
     /**
      * Read a new array from the receiver. It is assumed the array has not been
      * read yet (not a cyclic reference). Return the array read.
-     * 
+     *
      * @param unshared
      *            read the object unshared
      * @return the array read
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the array.
      * @throws ClassNotFoundException
@@ -1629,7 +1642,7 @@
             throw new InvalidClassException(Msg.getString("K00d1")); //$NON-NLS-1$
         }
 
-        Integer newHandle = Integer.valueOf(nextHandle());
+        Integer newHandle = nextHandle();
 
         // Array size
         int size = input.readInt();
@@ -1690,6 +1703,10 @@
             // Array of Objects
             Object[] objectArray = (Object[]) result;
             for (int i = 0; i < size; i++) {
+                // TODO: This place is the opportunity for enhancement
+                //      We can implement writing elements through fast-path,
+                //      without setting up the context (see readObject()) for
+                //      each element with public API
                 objectArray[i] = readObject();
             }
         }
@@ -1703,11 +1720,11 @@
     /**
      * Reads a new class from the receiver. It is assumed the class has not been
      * read yet (not a cyclic reference). Return the class read.
-     * 
+     *
      * @param unshared
      *            read the object unshared
      * @return The {@code java.lang.Class} read from the stream.
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the class.
      * @throws ClassNotFoundException
@@ -1718,10 +1735,9 @@
         ObjectStreamClass classDesc = readClassDesc();
 
         if (classDesc != null) {
-            Integer newHandle = Integer.valueOf(nextHandle());
             Class<?> localClass = classDesc.forClass();
             if (localClass != null) {
-                registerObjectRead(localClass, newHandle, unshared);
+                registerObjectRead(localClass, nextHandle(), unshared);
             }
             return localClass;
         }
@@ -1753,11 +1769,9 @@
         ObjectStreamClass classDesc;
         primitiveData = input;
         Integer oldHandle = descriptorHandle;
-        descriptorHandle = Integer.valueOf(nextHandle());
+        descriptorHandle = nextHandle();
         classDesc = readClassDescriptor();
-        if (descriptorHandle != null) {
-            registerObjectRead(classDesc, descriptorHandle, false);
-        }
+        registerObjectRead(classDesc, descriptorHandle, false);
         descriptorHandle = oldHandle;
         primitiveData = emptyStream;
         classDesc.setClass(resolveClass(classDesc));
@@ -1789,7 +1803,7 @@
             ClassNotFoundException, IOException {
         // read classdesc for Enum first
         ObjectStreamClass classDesc = readEnumDesc();
-        Integer newHandle = Integer.valueOf(nextHandle());
+        Integer newHandle = nextHandle();
         // read name after class desc
         String name;
         byte tc = nextTC();
@@ -1818,11 +1832,11 @@
      * Reads a new class descriptor from the receiver. It is assumed the class
      * descriptor has not been read yet (not a cyclic reference). Return the
      * class descriptor read.
-     * 
+     *
      * @param unshared
      *            read the object unshared
      * @return The {@code ObjectStreamClass} read from the stream.
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the class
      *             descriptor.
@@ -1835,21 +1849,17 @@
         // subclasses during readClassDescriptor()
         primitiveData = input;
         Integer oldHandle = descriptorHandle;
-        descriptorHandle = Integer.valueOf(nextHandle());
+        descriptorHandle = nextHandle();
         ObjectStreamClass newClassDesc = readClassDescriptor();
-        if (descriptorHandle != null) {
-            registerObjectRead(newClassDesc, descriptorHandle, unshared);
-        }
+        registerObjectRead(newClassDesc, descriptorHandle, unshared);
         descriptorHandle = oldHandle;
         primitiveData = emptyStream;
 
         // We need to map classDesc to class.
         try {
             newClassDesc.setClass(resolveClass(newClassDesc));
-            // Check SUIDs
-            verifySUID(newClassDesc);
-            // Check base name of the class
-            verifyBaseName(newClassDesc);
+            // Check SUIDs & base name of the class
+            verifyAndInit(newClassDesc);
         } catch (ClassNotFoundException e) {
             if (mustResolve) {
                 throw e;
@@ -1877,9 +1887,9 @@
      * Reads a new proxy class descriptor from the receiver. It is assumed the
      * proxy class descriptor has not been read yet (not a cyclic reference).
      * Return the proxy class descriptor read.
-     * 
+     *
      * @return The {@code Class} read from the stream.
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the class
      *             descriptor.
@@ -1901,33 +1911,33 @@
 
     /**
      * Reads a class descriptor from the source stream.
-     * 
+     *
      * @return the class descriptor read from the source stream.
      * @throws ClassNotFoundException
      *             if a class for one of the objects cannot be found.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     protected ObjectStreamClass readClassDescriptor() throws IOException,
             ClassNotFoundException {
 
         ObjectStreamClass newClassDesc = new ObjectStreamClass();
         String name = input.readUTF();
-        if ("".equals(name)) {
-            throw new IOException("The stream is corrupted.");
+        if (name.length() == 0) {
+            // luni.07 = The stream is corrupted
+            throw new IOException(Messages.getString("luni.07")); //$NON-NLS-1$
         }
         newClassDesc.setName(name);
         newClassDesc.setSerialVersionUID(input.readLong());
         newClassDesc.setFlags(input.readByte());
 
-        // We must register the class descriptor before reading field
-        // descriptors.
-        // if called outside of readObject, the descriptorHandle might be null
-        descriptorHandle = (null == descriptorHandle ? Integer
-                .valueOf(nextHandle()) : descriptorHandle);
+        /*
+         * We must register the class descriptor before reading field
+         * descriptors. If called outside of readObject, the descriptorHandle
+         * might be null.
+         */
+        descriptorHandle = (null == descriptorHandle ? nextHandle() : descriptorHandle);
         registerObjectRead(newClassDesc, descriptorHandle, false);
-        descriptorHandle = null;
 
         readFieldDescriptors(newClassDesc);
         return newClassDesc;
@@ -1936,7 +1946,7 @@
     /**
      * Creates the proxy class that implements the interfaces specified in
      * {@code interfaceNames}.
-     * 
+     *
      * @param interfaceNames
      *            the interfaces used to create the proxy class.
      * @return the proxy class.
@@ -1946,16 +1956,15 @@
      * @throws IOException
      *             if an error occurs while reading from the source stream.
      * @see ObjectOutputStream#annotateProxyClass(Class)
-     * @since Android 1.0
      */
     protected Class<?> resolveProxyClass(String[] interfaceNames)
             throws IOException, ClassNotFoundException {
-        // BEGIN android-removed
+        // TODO: This method is opportunity for performance enhancement
+        //       We can cache the classloader and recently used interfaces.
+        // BEGIN android-changed
         // ClassLoader loader = VM.getNonBootstrapClassLoader();
-        // END android-removed
-        // BEGIN android-added
         ClassLoader loader = ClassLoader.getSystemClassLoader();
-        // END android-added
+        // END android-changed
         Class<?>[] interfaces = new Class<?>[interfaceNames.length];
         for (int i = 0; i < interfaceNames.length; i++) {
             interfaces[i] = Class.forName(interfaceNames[i], false, loader);
@@ -1969,61 +1978,19 @@
 
     /**
      * Write a new handle describing a cyclic reference from the stream.
-     * 
+     *
      * @return the handle read
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the handle
      */
-    private Integer readNewHandle() throws IOException {
-        return Integer.valueOf(input.readInt());
+    private int readNewHandle() throws IOException {
+        return input.readInt();
     }
 
-    /**
-     * Read a new object from the stream. It is assumed the object has not been
-     * loaded yet (not a cyclic reference). Return the object read.
-     * 
-     * If the object implements {@code Externalizable} its
-     * {@code readExternal} is called. Otherwise, all fields described by
-     * the class hierarchy are loaded. Each class can define how its declared
-     * instance fields are loaded by defining a private method
-     * {@code readObject}
-     * 
-     * @param unshared
-     *            read the object unshared
-     * @return the object read
-     * 
-     * @throws IOException
-     *             If an IO exception happened when reading the object.
-     * @throws OptionalDataException
-     *             If optional data could not be found when reading the object
-     *             graph
-     * @throws ClassNotFoundException
-     *             If a class for one of the objects could not be found
-     */
-    private Object readNewObject(boolean unshared)
-            throws OptionalDataException, ClassNotFoundException, IOException {
-        ObjectStreamClass classDesc = readClassDesc();
+    private Class<?> resolveConstructorClass(Class<?> objectClass, boolean wasSerializable, boolean wasExternalizable)
+        throws OptionalDataException, ClassNotFoundException, IOException {
 
-        if (classDesc == null) {
-            throw new InvalidClassException(Msg.getString("K00d1")); //$NON-NLS-1$
-        }
-
-        Integer newHandle = Integer.valueOf(nextHandle());
-
-        // Note that these values come from the Stream, and in fact it could be
-        // that the classes have been changed so that the info below now
-        // conflicts with the newer class
-        boolean wasExternalizable = (classDesc.getFlags() & SC_EXTERNALIZABLE) > 0;
-        boolean wasSerializable = (classDesc.getFlags() & SC_SERIALIZABLE) > 0;
-
-        // Maybe we should cache the values above in classDesc ? It may be the
-        // case that when reading classDesc we may need to read more stuff
-        // depending on the values above
-        Class<?> objectClass = classDesc.forClass();
-
-        Object result, registeredResult = null;
-        if (objectClass != null) {
             // The class of the instance may not be the same as the class of the
             // constructor to run
             // This is the constructor to run if Externalizable
@@ -2083,9 +2050,71 @@
                 }
             }
 
+            return constructorClass;
+    }
+
+    /**
+     * Read a new object from the stream. It is assumed the object has not been
+     * loaded yet (not a cyclic reference). Return the object read.
+     *
+     * If the object implements <code>Externalizable</code> its
+     * <code>readExternal</code> is called. Otherwise, all fields described by
+     * the class hierarchy are loaded. Each class can define how its declared
+     * instance fields are loaded by defining a private method
+     * <code>readObject</code>
+     *
+     * @param unshared
+     *            read the object unshared
+     * @return the object read
+     *
+     * @throws IOException
+     *             If an IO exception happened when reading the object.
+     * @throws OptionalDataException
+     *             If optional data could not be found when reading the object
+     *             graph
+     * @throws ClassNotFoundException
+     *             If a class for one of the objects could not be found
+     */
+    private Object readNewObject(boolean unshared)
+            throws OptionalDataException, ClassNotFoundException, IOException {
+        ObjectStreamClass classDesc = readClassDesc();
+
+        if (classDesc == null) {
+            throw new InvalidClassException(Msg.getString("K00d1")); //$NON-NLS-1$
+        }
+
+        Integer newHandle = nextHandle();
+
+        // Note that these values come from the Stream, and in fact it could be
+        // that the classes have been changed so that the info below now
+        // conflicts with the newer class
+        boolean wasExternalizable = (classDesc.getFlags() & SC_EXTERNALIZABLE) > 0;
+        boolean wasSerializable = (classDesc.getFlags() & SC_SERIALIZABLE) > 0;
+
+
+        // Maybe we should cache the values above in classDesc ? It may be the
+        // case that when reading classDesc we may need to read more stuff
+        // depending on the values above
+        Class<?> objectClass = classDesc.forClass();
+
+        Object result, registeredResult = null;
+        if (objectClass != null) {
+
+            // BEGIN android-changed
+            // long constructor = classDesc.getConstructor();
+            // if (constructor == ObjectStreamClass.CONSTRUCTOR_IS_NOT_RESOLVED) {
+            //     constructor = accessor.getMethodID(resolveConstructorClass(objectClass, wasSerializable, wasExternalizable), null, new Class[0]);
+            //     classDesc.setConstructor(constructor);
+            // }
+            Class constructorClass = resolveConstructorClass(objectClass, wasSerializable, wasExternalizable);
+            // END android-changed
+
             // Now we know which class to instantiate and which constructor to
             // run. We are allowed to run the constructor.
+            // BEGIN android-changed
+            // result = accessor.newInstance(objectClass, constructor, null);
             result = newInstance(objectClass, constructorClass);
+            // END android-changed
             registerObjectRead(result, newHandle, unshared);
 
             registeredResult = result;
@@ -2131,38 +2160,23 @@
         }
 
         if (objectClass != null) {
-            Object readResolveMethod = readResolveCache.get(objectClass);
-            if (readResolveMethod != this) {
-                if (readResolveMethod == null) {
-                    final Method readResolve = ObjectStreamClass
-                            .methodReadResolve(objectClass);
-                    if (readResolve == null) {
-                        readResolveCache.put(objectClass, this);
-                        readResolveMethod = null;
+
+            if (classDesc.hasMethodReadResolve()){
+                Method methodReadResolve = classDesc.getMethodReadResolve();
+                try {
+                    result = methodReadResolve.invoke(result, (Object[]) null);
+                } catch (IllegalAccessException iae) {
+                } catch (InvocationTargetException ite) {
+                    Throwable target = ite.getTargetException();
+                    if (target instanceof ObjectStreamException) {
+                        throw (ObjectStreamException) target;
+                    } else if (target instanceof Error) {
+                        throw (Error) target;
                     } else {
-                        // Has replacement method
-                        AccessController.doPrivileged(new PriviAction<Object>(
-                                readResolve));
-                        readResolveCache.put(objectClass, readResolve);
-                        readResolveMethod = readResolve;
+                        throw (RuntimeException) target;
                     }
                 }
-                if (readResolveMethod != null) {
-                    try {
-                        result = ((Method) readResolveMethod).invoke(result,
-                                (Object[]) null);
-                    } catch (IllegalAccessException iae) {
-                    } catch (InvocationTargetException ite) {
-                        Throwable target = ite.getTargetException();
-                        if (target instanceof ObjectStreamException) {
-                            throw (ObjectStreamException) target;
-                        } else if (target instanceof Error) {
-                            throw (Error) target;
-                        } else {
-                            throw (RuntimeException) target;
-                        }
-                    }
-                }
+
             }
         }
         // We get here either if class-based replacement was not needed or if it
@@ -2183,7 +2197,7 @@
     /**
      * Read a string encoded in {@link DataInput modified UTF-8} from the
      * receiver. Return the string read.
-     * 
+     *
      * @param unshared
      *            read the object unshared
      * @return the string just read.
@@ -2195,8 +2209,7 @@
         if (enableResolve) {
             result = resolveObject(result);
         }
-        int newHandle = nextHandle();
-        registerObjectRead(result, Integer.valueOf(newHandle), unshared);
+		registerObjectRead(result, nextHandle(), unshared);
 
         return result;
     }
@@ -2204,11 +2217,11 @@
     /**
      * Read a new String in UTF format from the receiver. Return the string
      * read.
-     * 
+     *
      * @param unshared
      *            read the object unshared
      * @return the string just read.
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when reading the String.
      */
@@ -2218,15 +2231,14 @@
         if (enableResolve) {
             result = resolveObject(result);
         }
-        int newHandle = nextHandle();
-        registerObjectRead(result, Integer.valueOf(newHandle), unshared);
+        registerObjectRead(result, nextHandle(), unshared);
 
         return result;
     }
 
     /**
      * Reads the next object from the source stream.
-     * 
+     *
      * @return the object read from the source stream.
      * @throws ClassNotFoundException
      *             if the class of one of the objects in the object graph cannot
@@ -2236,7 +2248,6 @@
      * @throws OptionalDataException
      *             if primitive data types were found instead of an object.
      * @see ObjectOutputStream#writeObject(Object)
-     * @since Android 1.0
      */
     public final Object readObject() throws OptionalDataException,
             ClassNotFoundException, IOException {
@@ -2245,7 +2256,7 @@
 
     /**
      * Reads the next unshared object from the source stream.
-     * 
+     *
      * @return the new object read.
      * @throws ClassNotFoundException
      *             if the class of one of the objects in the object graph cannot
@@ -2253,7 +2264,6 @@
      * @throws IOException
      *             if an error occurs while reading from the source stream.
      * @see ObjectOutputStream#writeUnshared
-     * @since Android 1.0
      */
     public Object readUnshared() throws IOException, ClassNotFoundException {
         return readObject(true);
@@ -2347,7 +2357,7 @@
     /**
      * Method to be overriden by subclasses to read the next object from the
      * source stream.
-     * 
+     *
      * @return the object read from the source stream.
      * @throws ClassNotFoundException
      *             if the class of one of the objects in the object graph cannot
@@ -2357,7 +2367,6 @@
      * @throws OptionalDataException
      *             if primitive data types were found instead of an object.
      * @see ObjectOutputStream#writeObjectOverride
-     * @since Android 1.0
      */
     protected Object readObjectOverride() throws OptionalDataException,
             ClassNotFoundException, IOException {
@@ -2370,11 +2379,10 @@
 
     /**
      * Reads a short (16 bit) from the source stream.
-     * 
+     *
      * @return the short value read from the source stream.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     public short readShort() throws IOException {
         return primitiveTypes.readShort();
@@ -2382,13 +2390,12 @@
 
     /**
      * Reads and validates the ObjectInputStream header from the source stream.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while reading from the source stream.
      * @throws StreamCorruptedException
      *             if the source stream does not contain readable serialized
      *             objects.
-     * @since Android 1.0
      */
     protected void readStreamHeader() throws IOException,
             StreamCorruptedException {
@@ -2401,7 +2408,7 @@
 
     /**
      * Reads an unsigned byte (8 bit) from the source stream.
-     * 
+     *
      * @return the unsigned byte value read from the source stream packaged in
      *         an integer.
      * @throws EOFException
@@ -2409,7 +2416,6 @@
      *             request can be satisfied.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     public int readUnsignedByte() throws IOException {
         return primitiveTypes.readUnsignedByte();
@@ -2417,7 +2423,7 @@
 
     /**
      * Reads an unsigned short (16 bit) from the source stream.
-     * 
+     *
      * @return the unsigned short value read from the source stream packaged in
      *         an integer.
      * @throws EOFException
@@ -2425,7 +2431,6 @@
      *             request can be satisfied.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     public int readUnsignedShort() throws IOException {
         return primitiveTypes.readUnsignedShort();
@@ -2434,7 +2439,7 @@
     /**
      * Reads a string encoded in {@link DataInput modified UTF-8} from the
      * source stream.
-     * 
+     *
      * @return the string encoded in {@link DataInput modified UTF-8} read from
      *         the source stream.
      * @throws EOFException
@@ -2442,7 +2447,6 @@
      *             request can be satisfied.
      * @throws IOException
      *             if an error occurs while reading from the source stream.
-     * @since Android 1.0
      */
     public String readUTF() throws IOException {
         return primitiveTypes.readUTF();
@@ -2450,11 +2454,11 @@
 
     /**
      * Return the object previously read tagged with handle {@code handle}.
-     * 
+     *
      * @param handle
      *            The handle that this object was assigned when it was read.
      * @return the object previously read.
-     * 
+     *
      * @throws InvalidObjectException
      *             If there is no previously read object with this handle
      */
@@ -2472,14 +2476,14 @@
     /**
      * Assume object {@code obj} has been read, and assign a handle to
      * it, {@code handle}.
-     * 
+     *
      * @param obj
      *            Non-null object being loaded.
      * @param handle
      *            An Integer, the handle to this object
      * @param unshared
      *            Boolean, indicates that caller is reading in unshared mode
-     * 
+     *
      * @see #nextHandle
      */
     private void registerObjectRead(Object obj, Integer handle, boolean unshared) {
@@ -2494,7 +2498,7 @@
      * a class that implements "special" deserialization rules. It can be called
      * multiple times. Validation callbacks are then done in order of decreasing
      * priority, defined by {@code priority}.
-     * 
+     *
      * @param object
      *            an object that can validate itself by receiving a callback.
      * @param priority
@@ -2512,7 +2516,7 @@
         Object instanceBeingRead = this.currentObject;
 
         // We can't be called from just anywhere. There are rules.
-        if (instanceBeingRead == null) {
+        if (instanceBeingRead == null && nestedLevels == 0) {
             throw new NotActiveException();
         }
         if (object == null) {
@@ -2552,7 +2556,7 @@
      * Reset the collection of objects already loaded by the receiver.
      */
     private void resetSeenObjects() {
-        objectsRead = new Hashtable<Integer, Object>();
+        objectsRead = new HashMap<Integer, Object>();
         currentHandle = baseWireHandle;
         primitiveData = emptyStream;
     }
@@ -2572,7 +2576,7 @@
     /**
      * Loads the Java class corresponding to the class descriptor {@code
      * osClass} that has just been read from the source stream.
-     * 
+     *
      * @param osClass
      *            an ObjectStreamClass read from the source stream.
      * @return a Class corresponding to the descriptor {@code osClass}.
@@ -2581,18 +2585,24 @@
      * @throws IOException
      *             if an I/O error occurs while creating the class.
      * @see ObjectOutputStream#annotateClass(Class)
-     * @since Android 1.0
      */
     protected Class<?> resolveClass(ObjectStreamClass osClass)
             throws IOException, ClassNotFoundException {
-        String className = osClass.getName();
-        // if it is primitive class, for example, long.class
-        Class<?> cls = PRIMITIVE_CLASSES.get(className);
+        // fastpath: obtain cached value
+        Class<?> cls = osClass.forClass();
         if (null == cls) {
-            // not primitive class
-            // Use the first non-null ClassLoader on the stack. If null, use the
-            // system class loader
-            return Class.forName(className, true, callerClassLoader);
+            // slowpath: resolve the class
+            String className = osClass.getName();
+
+            // if it is primitive class, for example, long.class
+            cls = PRIMITIVE_CLASSES.get(className);
+
+            if (null == cls) {
+                // not primitive class
+                // Use the first non-null ClassLoader on the stack. If null, use
+                // the system class loader
+                cls = Class.forName(className, true, callerClassLoader);
+            }
         }
         return cls;
     }
@@ -2602,7 +2612,7 @@
      * object} with a new object. Object substitution has to be activated first
      * with calling {@code enableResolveObject(true)}. This implementation just
      * returns {@code object}.
-     * 
+     *
      * @param object
      *            the original object for which a replacement may be defined.
      * @return the replacement object for {@code object}.
@@ -2612,262 +2622,71 @@
      * @see #enableResolveObject
      * @see ObjectOutputStream#enableReplaceObject
      * @see ObjectOutputStream#replaceObject
-     * @since Android 1.0
      */
     protected Object resolveObject(Object object) throws IOException {
         // By default no object replacement. Subclasses can override
         return object;
     }
 
-    /**
-     * Set a given declared field named {@code fieldName} of
-     * {@code instance} to the new {@code byte} value
-     * {@code value}.
-     * 
-     * This method could be implemented non-natively on top of java.lang.reflect
-     * implementations that support the {@code setAccessible} API, at the
-     * expense of extra object creation (java.lang.reflect.Field). Otherwise
-     * Serialization could not set private fields, except by the use of a native
-     * method like this one.
-     * 
-     * @param instance
-     *            Object whose field to set
-     * @param declaringClass
-     *            {@code instance}'s declaring class
-     * @param fieldName
-     *            Name of the field to set
-     * @param value
-     *            New value for the field
-     * 
-     * @throws NoSuchFieldError
-     *             If the field does not exist.
+    // BEGIN android-added
+
+    /*
+     * These methods set the value of a field named fieldName of instance. The
+     * field is declared by declaringClass. The field is the same type as the
+     * value parameter.
+     *
+     * these methods could be implemented non-natively on top of
+     * java.lang.reflect at the expense of extra object creation
+     * (java.lang.reflect.Field). Otherwise Serialization could not fetch
+     * private fields, except by the use of a native method like this one.
+     *
+     * @throws NoSuchFieldError If the field does not exist.
      */
     private static native void setField(Object instance,
             Class<?> declaringClass, String fieldName, byte value)
             throws NoSuchFieldError;
 
-    /**
-     * Set a given declared field named {@code fieldName} of
-     * {@code instance} to the new {@code char} value
-     * {@code value}.
-     * 
-     * This method could be implemented non-natively on top of java.lang.reflect
-     * implementations that support the {@code setAccessible} API, at the
-     * expense of extra object creation (java.lang.reflect.Field). Otherwise
-     * Serialization could not set private fields, except by the use of a native
-     * method like this one.
-     * 
-     * @param instance
-     *            Object whose field to set
-     * @param declaringClass
-     *            {@code instance}'s declaring class
-     * @param fieldName
-     *            Name of the field to set
-     * @param value
-     *            New value for the field
-     * 
-     * @throws NoSuchFieldError
-     *             If the field does not exist.
-     */
+
     private static native void setField(Object instance,
             Class<?> declaringClass, String fieldName, char value)
             throws NoSuchFieldError;
 
-    /**
-     * Set a given declared field named {@code fieldName} of
-     * {@code instance} to the new {@code double} value
-     * {@code value}.
-     * 
-     * This method could be implemented non-natively on top of java.lang.reflect
-     * implementations that support the {@code setAccessible} API, at the
-     * expense of extra object creation (java.lang.reflect.Field). Otherwise
-     * Serialization could not set private fields, except by the use of a native
-     * method like this one.
-     * 
-     * @param instance
-     *            Object whose field to set
-     * @param declaringClass
-     *            {@code instance}'s declaring class
-     * @param fieldName
-     *            Name of the field to set
-     * @param value
-     *            New value for the field
-     * 
-     * @throws NoSuchFieldError
-     *             If the field does not exist.
-     */
+
     private static native void setField(Object instance,
             Class<?> declaringClass, String fieldName, double value)
             throws NoSuchFieldError;
 
-    /**
-     * Set a given declared field named {@code fieldName} of
-     * {@code instance} to the new {@code float} value
-     * {@code value}.
-     * 
-     * This method could be implemented non-natively on top of java.lang.reflect
-     * implementations that support the {@code setAccessible} API, at the
-     * expense of extra object creation (java.lang.reflect.Field). Otherwise
-     * Serialization could not set private fields, except by the use of a native
-     * method like this one.
-     * 
-     * @param instance
-     *            Object whose field to set
-     * @param declaringClass
-     *            {@code instance}'s declaring class
-     * @param fieldName
-     *            Name of the field to set
-     * @param value
-     *            New value for the field
-     * 
-     * @throws NoSuchFieldError
-     *             If the field does not exist.
-     */
     private static native void setField(Object instance,
             Class<?> declaringClass, String fieldName, float value)
             throws NoSuchFieldError;
 
-    /**
-     * Set a given declared field named {@code fieldName} of
-     * {@code instance} to the new {@code int} value
-     * {@code value}.
-     * 
-     * This method could be implemented non-natively on top of java.lang.reflect
-     * implementations that support the {@code setAccessible} API, at the
-     * expense of extra object creation (java.lang.reflect.Field). Otherwise
-     * Serialization could not set private fields, except by the use of a native
-     * method like this one.
-     * 
-     * @param instance
-     *            Object whose field to set
-     * @param declaringClass
-     *            {@code instance}'s declaring class
-     * @param fieldName
-     *            Name of the field to set
-     * @param value
-     *            New value for the field
-     * 
-     * @throws NoSuchFieldError
-     *             If the field does not exist.
-     */
     private static native void setField(Object instance,
             Class<?> declaringClass, String fieldName, int value)
             throws NoSuchFieldError;
 
-    /**
-     * Set a given declared field named {@code fieldName} of
-     * {@code instance} to the new {@code long} value
-     * {@code value}.
-     * 
-     * This method could be implemented non-natively on top of java.lang.reflect
-     * implementations that support the {@code setAccessible} API, at the
-     * expense of extra object creation (java.lang.reflect.Field). Otherwise
-     * Serialization could not set private fields, except by the use of a native
-     * method like this one.
-     * 
-     * @param instance
-     *            Object whose field to set
-     * @param declaringClass
-     *            {@code instance}'s declaring class
-     * @param fieldName
-     *            Name of the field to set
-     * @param value
-     *            New value for the field
-     * 
-     * @throws NoSuchFieldError
-     *             If the field does not exist.
-     */
     private static native void setField(Object instance,
             Class<?> declaringClass, String fieldName, long value)
             throws NoSuchFieldError;
 
-    /**
-     * Set a given declared field named {@code fieldName} of
-     * {@code instance} to the new value {@code value}.
-     * 
-     * This method could be implemented non-natively on top of java.lang.reflect
-     * implementations that support the {@code setAccessible} API, at the
-     * expense of extra object creation (java.lang.reflect.Field). Otherwise
-     * Serialization could not set private fields, except by the use of a native
-     * method like this one.
-     * 
-     * @param instance
-     *            Object whose field to set
-     * @param declaringClass
-     *            Class which declares the field
-     * @param fieldName
-     *            Name of the field to set
-     * @param fieldTypeName
-     *            Name of the class defining the type of the field
-     * @param value
-     *            New value for the field
-     * 
-     * @throws NoSuchFieldError
-     *             If the field does not exist.
-     */
     private static native void objSetField(Object instance,
             Class<?> declaringClass, String fieldName, String fieldTypeName,
             Object value) throws NoSuchFieldError;
 
-    /**
-     * Set a given declared field named {@code fieldName} of
-     * {@code instance} to the new {@code short} value
-     * {@code value}.
-     * 
-     * This method could be implemented non-natively on top of java.lang.reflect
-     * implementations that support the {@code setAccessible} API, at the
-     * expense of extra object creation (java.lang.reflect.Field). Otherwise
-     * Serialization could not set private fields, except by the use of a native
-     * method like this one.
-     * 
-     * @param instance
-     *            Object whose field to set
-     * @param declaringClass
-     *            {@code instance}'s declaring class
-     * @param fieldName
-     *            Name of the field to set
-     * @param value
-     *            New value for the field
-     * 
-     * @throws NoSuchFieldError
-     *             If the field does not exist.
-     */
     private static native void setField(Object instance,
             Class<?> declaringClass, String fieldName, short value)
             throws NoSuchFieldError;
 
-    /**
-     * Set a given declared field named {@code fieldName} of
-     * {@code instance} to the new {@code boolean} value
-     * {@code value}.
-     * 
-     * This method could be implemented non-natively on top of java.lang.reflect
-     * implementations that support the {@code setAccessible} API, at the
-     * expense of extra object creation (java.lang.reflect.Field). Otherwise
-     * Serialization could not set private fields, except by the use of a native
-     * method like this one.
-     * 
-     * @param instance
-     *            Object whose field to set
-     * @param declaringClass
-     *            {@code instance}'s declaring class
-     * @param fieldName
-     *            Name of the field to set
-     * @param value
-     *            New value for the field
-     * 
-     * @throws NoSuchFieldError
-     *             If the field does not exist.
-     */
     private static native void setField(Object instance,
             Class<?> declaringClass, String fieldName, boolean value)
             throws NoSuchFieldError;
 
+    // END android-added
+
     /**
      * Skips {@code length} bytes on the source stream. This method should not
      * be used to skip bytes at any arbitrary position, just when reading
      * primitive data types (int, char etc).
-     * 
+     *
      * @param length
      *            the number of bytes to skip.
      * @return the number of bytes actually skipped.
@@ -2875,7 +2694,6 @@
      *             if an error occurs while skipping bytes on the source stream.
      * @throws NullPointerException
      *             if the source stream is {@code null}.
-     * @since Android 1.0
      */
     public int skipBytes(int length) throws IOException {
         // To be used with available. Ok to call if reading primitive buffer
@@ -2896,50 +2714,31 @@
     }
 
     /**
-     * Verify if the SUID for descriptor {@code loadedStreamClass}matches
-     * the SUID of the corresponding loaded class.
-     * 
+     * Verify if the SUID & the base name for descriptor
+     * <code>loadedStreamClass</code>matches
+     * the SUID & the base name of the corresponding loaded class and
+     * init private fields.
+     *
      * @param loadedStreamClass
      *            An ObjectStreamClass that was loaded from the stream.
-     * 
+     *
      * @throws InvalidClassException
      *             If the SUID of the stream class does not match the VM class
      */
-    private void verifySUID(ObjectStreamClass loadedStreamClass)
+    private void verifyAndInit(ObjectStreamClass loadedStreamClass)
             throws InvalidClassException {
+
         Class<?> localClass = loadedStreamClass.forClass();
-        // Instances of java.lang.Class are always Serializable, even if their
-        // instances aren't (e.g. java.lang.Object.class). We cannot call lookup
-        // because it returns null if the parameter represents instances that
-        // cannot be serialized, and that is not what we want. If we are loading
-        // an instance of java.lang.Class, we better have the corresponding
-        // ObjectStreamClass.
         ObjectStreamClass localStreamClass = ObjectStreamClass
                 .lookupStreamClass(localClass);
+
         if (loadedStreamClass.getSerialVersionUID() != localStreamClass
                 .getSerialVersionUID()) {
             throw new InvalidClassException(loadedStreamClass.getName(), Msg
                     .getString("K00da", loadedStreamClass, //$NON-NLS-1$
                             localStreamClass));
         }
-    }
 
-    /**
-     * Verify if the base name for descriptor {@code loadedStreamClass}
-     * matches the base name of the corresponding loaded class.
-     * 
-     * @param loadedStreamClass
-     *            An ObjectStreamClass that was loaded from the stream.
-     * 
-     * @throws InvalidClassException
-     *             If the base name of the stream class does not match the VM
-     *             class
-     */
-    private void verifyBaseName(ObjectStreamClass loadedStreamClass)
-            throws InvalidClassException {
-        Class<?> localClass = loadedStreamClass.forClass();
-        ObjectStreamClass localStreamClass = ObjectStreamClass
-                .lookupStreamClass(localClass);
         String loadedClassBaseName = getBaseName(loadedStreamClass.getName());
         String localClassBaseName = getBaseName(localStreamClass.getName());
 
@@ -2948,10 +2747,12 @@
                     .getString("KA015", loadedClassBaseName, //$NON-NLS-1$
                             localClassBaseName));
         }
+
+        loadedStreamClass.initPrivateFields(localStreamClass);
     }
 
     private static String getBaseName(String fullName) {
-        int k = fullName.lastIndexOf("."); //$NON-NLS-1$
+        int k = fullName.lastIndexOf('.');
 
         if (k == -1 || k == (fullName.length() - 1)) {
             return fullName;
diff --git a/libcore/luni/src/main/java/java/io/ObjectInputValidation.java b/libcore/luni/src/main/java/java/io/ObjectInputValidation.java
index f1cae74..3dce15e 100644
--- a/libcore/luni/src/main/java/java/io/ObjectInputValidation.java
+++ b/libcore/luni/src/main/java/java/io/ObjectInputValidation.java
@@ -22,10 +22,7 @@
  * example, the validation of a whole graph of objects after all of them have
  * been loaded.
  * 
- * @see ObjectInputStream
  * @see ObjectInputStream#registerValidation(ObjectInputValidation, int)
- * 
- * @since Android 1.0
  */
 public interface ObjectInputValidation {
     /**
@@ -33,7 +30,6 @@
      * 
      * @throws InvalidObjectException
      *             if this object fails to validate itself.
-     * @since Android 1.0
      */
     public void validateObject() throws InvalidObjectException;
 }
diff --git a/libcore/luni/src/main/java/java/io/ObjectOutput.java b/libcore/luni/src/main/java/java/io/ObjectOutput.java
index cd68439..6680457 100644
--- a/libcore/luni/src/main/java/java/io/ObjectOutput.java
+++ b/libcore/luni/src/main/java/java/io/ObjectOutput.java
@@ -22,8 +22,6 @@
  * 
  * @see ObjectOutputStream
  * @see ObjectInput
- * 
- * @since Android 1.0
  */
 public interface ObjectOutput extends DataOutput {
     /**
@@ -32,7 +30,6 @@
      * 
      * @throws IOException
      *             if an error occurs while closing the target stream.
-     * @since Android 1.0
      */
     public void close() throws IOException;
 
@@ -42,7 +39,6 @@
      * 
      * @throws IOException
      *             if an error occurs while flushing the target stream.
-     * @since Android 1.0
      */
     public void flush() throws IOException;
 
@@ -54,7 +50,6 @@
      *            the buffer to write.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void write(byte[] buffer) throws IOException;
 
@@ -72,7 +67,6 @@
      *            stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void write(byte[] buffer, int offset, int count) throws IOException;
 
@@ -85,7 +79,6 @@
      *            the byte to write.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void write(int value) throws IOException;
 
@@ -96,7 +89,6 @@
      *            the object to write.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void writeObject(Object obj) throws IOException;
 }
diff --git a/libcore/luni/src/main/java/java/io/ObjectOutputStream.java b/libcore/luni/src/main/java/java/io/ObjectOutputStream.java
index 5da4950..e3c1471 100644
--- a/libcore/luni/src/main/java/java/io/ObjectOutputStream.java
+++ b/libcore/luni/src/main/java/java/io/ObjectOutputStream.java
@@ -20,27 +20,40 @@
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
-import java.security.AccessController;
 import java.util.IdentityHashMap;
 
-import org.apache.harmony.luni.util.PriviAction;
+
+// BEGIN android-note
+// Harmony uses ObjectAccessors to access fields through JNI. Android has not
+// yet migrated that API. As a consequence, there's a lot of changes here...
+// END android-note
+
+// BEGIN android-removed
+// import org.apache.harmony.misc.accessors.ObjectAccessor;
+// import org.apache.harmony.misc.accessors.AccessorFactory;
+// END android-removed
+
+import org.apache.harmony.luni.util.Msg;
 
 /**
  * A specialized {@link OutputStream} that is able to write (serialize) Java
  * objects as well as primitive data types (int, byte, char etc.). The data can
  * later be loaded using an ObjectInputStream.
- * 
+ *
  * @see ObjectInputStream
  * @see ObjectOutput
  * @see Serializable
  * @see Externalizable
- * 
- * @since Android 1.0
  */
 public class ObjectOutputStream extends OutputStream implements ObjectOutput,
         ObjectStreamConstants {
 
     /*
+     * Mask to zero SC_BLOC_DATA bit.
+     */
+    private static final byte NOT_SC_BLOCK_DATA = (byte) (SC_BLOCK_DATA ^ 0xFF);
+
+    /*
      * How many nested levels to writeObject. We may not need this.
      */
     private int nestedLevels;
@@ -107,136 +120,129 @@
      */
     private boolean subclassOverridingImplementation;
 
+
+    // BEGIN android-removed
+    // private ObjectAccessor accessor = AccessorFactory.getObjectAccessor();
+    // END android-removed
+
     /*
-     * cache for writeReplace methods
+     * Descriptor for java.lang.reflect.Proxy
      */
-    private IdentityHashMap<Class<?>, Object> writeReplaceCache;
+    private final ObjectStreamClass proxyClassDesc = ObjectStreamClass.lookup(Proxy.class);
 
     /**
      * PutField is an inner class to provide access to the persistent fields
      * that are written to the target stream.
-     * 
-     * @since Android 1.0
      */
     public static abstract class PutField {
         /**
          * Puts the value of the boolean field identified by {@code name} to the
          * persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to serialize.
          * @param value
          *            the value that is put to the persistent field.
-         * @since Android 1.0
          */
         public abstract void put(String name, boolean value);
 
         /**
          * Puts the value of the character field identified by {@code name} to
          * the persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to serialize.
          * @param value
          *            the value that is put to the persistent field.
-         * @since Android 1.0
          */
         public abstract void put(String name, char value);
 
         /**
          * Puts the value of the byte field identified by {@code name} to the
          * persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to serialize.
          * @param value
          *            the value that is put to the persistent field.
-         * @since Android 1.0
          */
         public abstract void put(String name, byte value);
 
         /**
          * Puts the value of the short field identified by {@code name} to the
          * persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to serialize.
          * @param value
          *            the value that is put to the persistent field.
-         * @since Android 1.0
          */
         public abstract void put(String name, short value);
 
         /**
          * Puts the value of the integer field identified by {@code name} to the
          * persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to serialize.
          * @param value
          *            the value that is put to the persistent field.
-         * @since Android 1.0
          */
         public abstract void put(String name, int value);
 
         /**
          * Puts the value of the long field identified by {@code name} to the
          * persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to serialize.
          * @param value
          *            the value that is put to the persistent field.
-         * @since Android 1.0
          */
         public abstract void put(String name, long value);
 
         /**
          * Puts the value of the float field identified by {@code name} to the
          * persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to serialize.
          * @param value
          *            the value that is put to the persistent field.
-         * @since Android 1.0
          */
         public abstract void put(String name, float value);
 
         /**
          * Puts the value of the double field identified by {@code name} to the
          * persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to serialize.
          * @param value
          *            the value that is put to the persistent field.
-         * @since Android 1.0
          */
         public abstract void put(String name, double value);
 
         /**
          * Puts the value of the Object field identified by {@code name} to the
          * persistent field.
-         * 
+         *
          * @param name
          *            the name of the field to serialize.
          * @param value
          *            the value that is put to the persistent field.
-         * @since Android 1.0
          */
         public abstract void put(String name, Object value);
 
         /**
          * Writes the fields to the target stream {@code out}.
-         * 
+         *
          * @param out
          *            the target stream
          * @throws IOException
          *             if an error occurs while writing to the target stream.
          * @deprecated This method is unsafe and may corrupt the target stream.
          *             Use ObjectOutputStream#writeFields() instead.
-         * @since Android 1.0
          */
         @Deprecated
         public abstract void write(ObjectOutput out) throws IOException;
@@ -246,14 +252,13 @@
      * Constructs a new {@code ObjectOutputStream}. This default constructor can
      * be used by subclasses that do not want to use the public constructor if
      * it allocates unneeded data.
-     * 
+     *
      * @throws IOException
      *             if an error occurs when creating this stream.
      * @throws SecurityException
      *             if a security manager is installed and it denies subclassing
      *             this class.
      * @see SecurityManager#checkPermission(java.security.Permission)
-     * @since Android 1.0
      */
     protected ObjectOutputStream() throws IOException, SecurityException {
         super();
@@ -271,17 +276,16 @@
     /**
      * Constructs a new ObjectOutputStream that writes to the OutputStream
      * {@code output}.
-     * 
+     *
      * @param output
      *            the non-null OutputStream to filter writes on.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while writing the object stream
      *             header
      * @throws SecurityException
      *             if a security manager is installed and it denies subclassing
      *             this class.
-     * @since Android 1.0
      */
     public ObjectOutputStream(OutputStream output) throws IOException {
         Class<?> implementationClass = getClass();
@@ -316,7 +320,6 @@
         this.enableReplace = false;
         this.protocolVersion = PROTOCOL_VERSION_2;
         this.subclassOverridingImplementation = false;
-        this.writeReplaceCache = new IdentityHashMap<Class<?>, Object>();
 
         resetState();
         this.nestedException = new StreamCorruptedException();
@@ -333,13 +336,12 @@
      * stream. This optional data can be read when deserializing the class
      * descriptor (ObjectStreamClass) for this class from an input stream. By
      * default, no extra data is saved.
-     * 
+     *
      * @param aClass
      *            the class to annotate.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see ObjectInputStream#resolveClass(ObjectStreamClass)
-     * @since Android 1.0
      */
     protected void annotateClass(Class<?> aClass) throws IOException {
         // By default no extra info is saved. Subclasses can override
@@ -349,13 +351,12 @@
      * Writes optional information for a proxy class to the target stream. This
      * optional data can be read when deserializing the proxy class from an
      * input stream. By default, no extra data is saved.
-     * 
+     *
      * @param aClass
      *            the proxy class to annotate.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see ObjectInputStream#resolveProxyClass(String[])
-     * @since Android 1.0
      */
     protected void annotateProxyClass(Class<?> aClass) throws IOException {
         // By default no extra info is saved. Subclasses can override
@@ -377,10 +378,9 @@
     /**
      * Closes this stream. Any buffered data is flushed. This implementation
      * closes the target stream.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this stream.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -393,7 +393,7 @@
      * Computes the collection of emulated fields that users can manipulate to
      * store a representation different than the one declared by the class of
      * the object being dumped.
-     * 
+     *
      * @see #writeFields
      * @see #writeFieldValues(EmulatedFieldsForDumping)
      */
@@ -405,13 +405,12 @@
      * Default method to write objects to this stream. Serializable fields
      * defined in the object's class and superclasses are written to the output
      * stream.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @throws NotActiveException
      *             if this method is not called from {@code writeObject()}.
      * @see ObjectInputStream#defaultReadObject
-     * @since Android 1.0
      */
     public void defaultWriteObject() throws IOException {
         // We can't be called from just anywhere. There are rules.
@@ -424,13 +423,12 @@
     /**
      * Writes buffered data to the target stream. This is similar to {@code
      * flush} but the flush is not propagated to the target stream.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     protected void drain() throws IOException {
-        if (primitiveTypes == null) {
+        if (primitiveTypes == null || primitiveTypesBuffer == null) {
             return;
         }
 
@@ -462,7 +460,7 @@
     /**
      * Dumps the parameter {@code obj} only if it is {@code null}
      * or an object that has already been dumped previously.
-     * 
+     *
      * @param obj
      *            Object to check if an instance previously dumped by this
      *            stream.
@@ -470,14 +468,14 @@
      *         method does nothing). Integer, if {@code obj} is an
      *         instance which has been dumped already. In this case this method
      *         saves the cyclic reference.
-     * 
+     *
      * @throws IOException
      *             If an error occurs attempting to save {@code null} or
      *             a cyclic reference.
      */
     private Integer dumpCycle(Object obj) throws IOException {
         // If the object has been saved already, save its handle only
-        Integer handle = registeredObjectHandleFor(obj);
+        Integer handle = objectsWritten.get(obj);
         if (handle != null) {
             writeCyclicReference(handle);
             return handle;
@@ -489,7 +487,7 @@
      * Enables object replacement for this stream. By default this is not
      * enabled. Only trusted subclasses (loaded with system class loader) are
      * allowed to change this status.
-     * 
+     *
      * @param enable
      *            {@code true} to enable object replacement; {@code false} to
      *            disable it.
@@ -499,7 +497,6 @@
      *             object replacement for this stream.
      * @see #replaceObject
      * @see ObjectInputStream#enableResolveObject
-     * @since Android 1.0
      */
     protected boolean enableReplaceObject(boolean enable)
             throws SecurityException {
@@ -519,11 +516,10 @@
     /**
      * Writes buffered data to the target stream and calls the {@code flush}
      * method of the target stream.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while writing to or flushing the output
      *             stream.
-     * @since Android 1.0
      */
     @Override
     public void flush() throws IOException {
@@ -531,212 +527,64 @@
         output.flush();
     }
 
-    /**
-     * Get the value of field named
-     * {@code fieldName<code> of object <code>instance}. The
-     * field is declared by class {@code declaringClass}. The field is supposed to be
-     * a boolean.
+    // BEGIN android-added
+    /*
+     * These methods get the value of a field named fieldName of object
+     * instance. The field is declared by declaringClass. The field is the same
+     * type as the method return value.
      *
-     * This method could be implemented non-natively on top of java.lang.reflect implementations
-     * that support the {@code setAccessible} API, at the expense of extra object creation
-     * (java.lang.reflect.Field). Otherwise Serialization could not fetch private fields, except
-     * by the use of a native method like this one.
-     *
-     * @param instance Object whose field value we want to fetch
-     * @param declaringClass The class that declares the field
-     * @param fieldName Name of the field we want to fetch
-     * @return the value of the field
+     * these methods could be implemented non-natively on top of
+     * java.lang.reflect at the expense of extra object creation
+     * (java.lang.reflect.Field). Otherwise Serialization could not fetch
+     * private fields, except by the use of a native method like this one.
      *
      * @throws NoSuchFieldError If the field does not exist.
      */
+
     private static native boolean getFieldBool(Object instance,
             Class<?> declaringClass, String fieldName);
 
-    /**
-     * Get the value of field named
-     * {@code fieldName<code> of object <code>instance}. The
-     * field is declared by class {@code declaringClass}. The field is supposed to be
-     * a byte
-     *
-     * This method could be implemented non-natively on top of java.lang.reflect implementations
-     * that support the {@code setAccessible} API, at the expense of extra object creation
-     * (java.lang.reflect.Field). Otherwise Serialization could not fetch private fields, except
-     * by the use of a native method like this one.
-     *
-     * @param instance Object whose field value we want to fetch
-     * @param declaringClass The class that declares the field
-     * @param fieldName Name of the field we want to fetch
-     * @return the value of the field
-     *
-     * @throws NoSuchFieldError If the field does not exist.
-     */
     private static native byte getFieldByte(Object instance,
             Class<?> declaringClass, String fieldName);
 
-    /**
-     * Get the value of field named
-     * {@code fieldName<code> of object <code>instance}. The
-     * field is declared by class {@code declaringClass}. The field is supposed to be
-     * a char.
-     *
-     * This method could be implemented non-natively on top of java.lang.reflect implementations
-     * that support the {@code setAccessible} API, at the expense of extra object creation
-     * (java.lang.reflect.Field). Otherwise Serialization could not fetch private fields, except
-     * by the use of a native method like this one.
-     *
-     * @param instance Object whose field value we want to fetch
-     * @param declaringClass The class that declares the field
-     * @param fieldName Name of the field we want to fetch
-     * @return the value of the field
-     *
-     * @throws NoSuchFieldError If the field does not exist.
-     */
     private static native char getFieldChar(Object instance,
             Class<?> declaringClass, String fieldName);
 
-    /**
-     * Get the value of field named
-     * {@code fieldName<code> of object <code>instance}. The
-     * field is declared by class {@code declaringClass}. The field is supposed to be
-     * a double.
-     *
-     * This method could be implemented non-natively on top of java.lang.reflect implementations
-     * that support the {@code setAccessible} API, at the expense of extra object creation
-     * (java.lang.reflect.Field). Otherwise Serialization could not fetch private fields, except
-     * by the use of a native method like this one.
-     *
-     * @param instance Object whose field value we want to fetch
-     * @param declaringClass The class that declares the field
-     * @param fieldName Name of the field we want to fetch
-     * @return the value of the field
-     *
-     * @throws NoSuchFieldError If the field does not exist.
-     */
     private static native double getFieldDouble(Object instance,
             Class<?> declaringClass, String fieldName);
 
-    /**
-     * Get the value of field named
-     * {@code fieldName<code> of object <code>instance}. The
-     * field is declared by class {@code declaringClass}. The field is supposed to be
-     * a float.
-     *
-     * This method could be implemented non-natively on top of java.lang.reflect implementations
-     * that support the {@code setAccessible} API, at the expense of extra object creation
-     * (java.lang.reflect.Field). Otherwise Serialization could not fetch private fields, except
-     * by the use of a native method like this one.
-     *
-     * @param instance Object whose field value we want to fetch
-     * @param declaringClass The class that declares the field
-     * @param fieldName Name of the field we want to fetch
-     * @return the value of the field
-     *
-     * @throws NoSuchFieldError If the field does not exist.
-     */
     private static native float getFieldFloat(Object instance,
             Class<?> declaringClass, String fieldName);
 
-    /**
-     * Get the value of field named
-     * {@code fieldName<code> of object <code>instance}. The
-     * field is declared by class {@code declaringClass}. The field is supposed to be
-     * an int.
-     *
-     * This method could be implemented non-natively on top of java.lang.reflect implementations
-     * that support the {@code setAccessible} API, at the expense of extra object creation
-     * (java.lang.reflect.Field). Otherwise Serialization could not fetch private fields, except
-     * by the use of a native method like this one.
-     *
-     * @param instance Object whose field value we want to fetch
-     * @param declaringClass The class that declares the field
-     * @param fieldName Name of the field we want to fetch
-     * @return the value of the field
-     *
-     * @throws NoSuchFieldError If the field does not exist.
-     */
     private static native int getFieldInt(Object instance,
             Class<?> declaringClass, String fieldName);
 
-    /**
-     * Get the value of field named
-     * {@code fieldName<code> of object <code>instance}. The
-     * field is declared by class {@code declaringClass}. The field is supposed to be
-     * a long.
-     *
-     * This method could be implemented non-natively on top of java.lang.reflect implementations
-     * that support the {@code setAccessible} API, at the expense of extra object creation
-     * (java.lang.reflect.Field). Otherwise Serialization could not fetch private fields, except
-     * by the use of a native method like this one.
-     *
-     * @param instance Object whose field value we want to fetch
-     * @param declaringClass The class that declares the field
-     * @param fieldName Name of the field we want to fetch
-     * @return the value of the field
-     *
-     * @throws NoSuchFieldError If the field does not exist.
-     */
     private static native long getFieldLong(Object instance,
             Class<?> declaringClass, String fieldName);
 
-    /**
-     * Get the value of field named
-     * {@code fieldName<code> of object <code>instance}. The
-     * field is declared by class {@code declaringClass}. The field is supposed to be
-     * an Object type whose name is {@code fieldTypeName}.
-     *
-     * This method could be implemented non-natively on top of java.lang.reflect implementations
-     * that support the {@code setAccessible} API, at the expense of extra object creation
-     * (java.lang.reflect.Field). Otherwise Serialization could not fetch private fields, except
-     * by the use of a native method like this one.
-     *
-     * @param instance Object whose field value we want to fetch
-     * @param declaringClass The class that declares the field
-     * @param fieldName Name of the field we want to fetch
-     * @param fieldTypeName Name of the class that defines the type of this field
-     * @return the value of the field
-     *
-     * @throws NoSuchFieldError If the field does not exist.
-     */
     private static native Object getFieldObj(Object instance,
             Class<?> declaringClass, String fieldName, String fieldTypeName);
 
-    /**
-     * Get the value of field named
-     * {@code fieldName<code> of object <code>instance}. The
-     * field is declared by class {@code declaringClass}. The field is supposed to be
-     * a short.
-     *
-     * This method could be implemented non-natively on top of java.lang.reflect implementations
-     * that support the {@code setAccessible} API, at the expense of extra object creation
-     * (java.lang.reflect.Field). Otherwise Serialization could not fetch private fields, except
-     * by the use of a native method like this one.
-     *
-     * @param instance Object whose field value we want to fetch
-     * @param declaringClass The class that declares the field
-     * @param fieldName Name of the field we want to fetch
-     * @return the value of the field
-     *
-     * @throws NoSuchFieldError If the field does not exist.
-     */
     private static native short getFieldShort(Object instance,
             Class<?> declaringClass, String fieldName);
+    // END android-added
 
     /**
-     * Return the next {@code int} handle to be used to indicate cyclic
+     * Return the next <code>Integer</code> handle to be used to indicate cyclic
      * references being saved to the stream.
-     * 
-     * @return int, the next handle to represent the next cyclic reference
+     *
+     * @return the next handle to represent the next cyclic reference
      */
-    private int nextHandle() {
-        return this.currentHandle++;
+    private Integer nextHandle() {
+        return Integer.valueOf(this.currentHandle++);
     }
 
     /**
      * Gets this stream's {@code PutField} object. This object provides access
      * to the persistent fields that are eventually written to the output
      * stream. It is used to transfer the values from the fields of the object
-     * that is currently being written to the persistent fields. 
-     * 
+     * that is currently being written to the persistent fields.
+     *
      * @return the PutField object from which persistent fields can be accessed
      *         by name.
      * @throws IOException
@@ -744,7 +592,6 @@
      * @throws NotActiveException
      *             if this method is not called from {@code writeObject()}.
      * @see ObjectInputStream#defaultReadObject
-     * @since Android 1.0
      */
     public PutField putFields() throws IOException {
         // We can't be called from just anywhere. There are rules.
@@ -758,39 +605,25 @@
     }
 
     /**
-     * Return the {@code Integer} handle used to tag object
-     * {@code obj} as an instance that has been dumped already. Return
-     * {@code null} if object {@code obj} has not been saved yet.
-     * 
-     * @param obj
-     *            the object
-     * @return null if object {@code obj} has not been saved yet. Integer
-     *         The handle that this object was assigned when it was saved.
-     */
-    private Integer registeredObjectHandleFor(Object obj) {
-        return objectsWritten.get(obj);
-    }
-
-    /**
      * Assume object {@code obj} has not been dumped yet, and assign a
      * handle to it
-     * 
+     *
      * @param obj
      *            Non-null object being dumped.
      * @return the handle that this object is being assigned.
-     * 
+     *
      * @see #nextHandle
      */
     private Integer registerObjectWritten(Object obj) {
-        Integer handle = Integer.valueOf(nextHandle());
-        registerObjectWritten(obj, handle);
+        Integer handle = nextHandle();
+        objectsWritten.put(obj, handle);
         return handle;
     }
 
     /**
      * Remove the unshared object from the table, and restore any previous
      * handle.
-     * 
+     *
      * @param obj
      *            Non-null object being dumped.
      * @param previousHandle
@@ -798,33 +631,18 @@
      */
     private void removeUnsharedReference(Object obj, Integer previousHandle) {
         if (previousHandle != null) {
-            registerObjectWritten(obj, previousHandle);
+            objectsWritten.put(obj, previousHandle);
         } else {
             objectsWritten.remove(obj);
         }
     }
 
     /**
-     * Assume object {@code obj} has not been dumped yet, and assign a
-     * handle to it, {@code handle}.
-     * 
-     * @param obj
-     *            Non-null object being dumped.
-     * @param handle
-     *            An Integer, the handle to this object
-     * 
-     * @see #nextHandle
-     */
-    private void registerObjectWritten(Object obj, Integer handle) {
-        objectsWritten.put(obj, handle);
-    }
-
-    /**
      * Allows trusted subclasses to substitute the specified original {@code
      * object} with a new object. Object substitution has to be activated first
      * with calling {@code enableReplaceObject(true)}. This implementation just
      * returns {@code object}.
-     * 
+     *
      * @param object
      *            the original object for which a replacement may be defined.
      * @return the replacement object for {@code object}.
@@ -834,7 +652,6 @@
      * @see #enableReplaceObject
      * @see ObjectInputStream#enableResolveObject
      * @see ObjectInputStream#resolveObject
-     * @since Android 1.0
      */
     protected Object replaceObject(Object object) throws IOException {
         // By default no object replacement. Subclasses can override
@@ -847,11 +664,10 @@
      * point. Objects previously written are no longer remembered, so they will
      * be written again (instead of a cyclical reference) if found in the object
      * graph.
-     * 
+     *
      * @throws IOException
      *             if {@code reset()} is called during the serialization of an
      *             object.
-     * @since Android 1.0
      */
     public void reset() throws IOException {
         // First we flush what we have
@@ -869,7 +685,7 @@
      * Reset the collection of objects already dumped by the receiver. If the
      * objects are found again in the object graph, the receiver will dump them
      * again, instead of a handle (cyclic reference).
-     * 
+     *
      */
     private void resetSeenObjects() {
         objectsWritten = new IdentityHashMap<Object, Integer>();
@@ -880,7 +696,7 @@
      * Reset the receiver. The collection of objects already dumped by the
      * receiver is reset, and internal structures are also reset so that the
      * receiver knows it is in a fresh clean state.
-     * 
+     *
      */
     private void resetState() {
         resetSeenObjects();
@@ -889,7 +705,7 @@
 
     /**
      * Sets the specified protocol version to be used by this stream.
-     * 
+     *
      * @param version
      *            the protocol version to be used. Use a {@code
      *            PROTOCOL_VERSION_x} constant from {@code
@@ -900,13 +716,16 @@
      *             if an I/O error occurs.
      * @see ObjectStreamConstants#PROTOCOL_VERSION_1
      * @see ObjectStreamConstants#PROTOCOL_VERSION_2
-     * @since Android 1.0
      */
     public void useProtocolVersion(int version) throws IOException {
+        if (!objectsWritten.isEmpty()) {
+            // KA028=Cannot set protocol version when stream in use
+            throw new IllegalStateException(Msg.getString("KA028")); //$NON-NLS-1$
+        }
         if (version != ObjectStreamConstants.PROTOCOL_VERSION_1
                 && version != ObjectStreamConstants.PROTOCOL_VERSION_2) {
-            throw new IllegalArgumentException(org.apache.harmony.luni.util.Msg
-                    .getString("K00b3", version)); //$NON-NLS-1$
+            // K00b3=Unknown protocol\: {0}
+            throw new IllegalArgumentException(Msg.getString("K00b3", version)); //$NON-NLS-1$
         }
         protocolVersion = version;
     }
@@ -914,12 +733,11 @@
     /**
      * Writes the entire contents of the byte array {@code buffer} to the output
      * stream. Blocks until all bytes are written.
-     * 
+     *
      * @param buffer
      *            the buffer to write.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     @Override
     public void write(byte[] buffer) throws IOException {
@@ -931,7 +749,7 @@
      * Writes {@code count} bytes from the byte array {@code buffer} starting at
      * offset {@code index} to the target stream. Blocks until all bytes are
      * written.
-     * 
+     *
      * @param buffer
      *            the buffer to write.
      * @param offset
@@ -941,7 +759,6 @@
      *            stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     @Override
     public void write(byte[] buffer, int offset, int length) throws IOException {
@@ -953,12 +770,11 @@
      * Writes a single byte to the target stream. Only the least significant
      * byte of the integer {@code value} is written to the stream. Blocks until
      * the byte is actually written.
-     * 
+     *
      * @param value
      *            the byte to write.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     @Override
     public void write(int value) throws IOException {
@@ -968,12 +784,11 @@
 
     /**
      * Writes a boolean to the target stream.
-     * 
+     *
      * @param value
      *            the boolean value to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void writeBoolean(boolean value) throws IOException {
         checkWritePrimitiveTypes();
@@ -982,12 +797,11 @@
 
     /**
      * Writes a byte (8 bit) to the target stream.
-     * 
+     *
      * @param value
      *            the byte to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void writeByte(int value) throws IOException {
         checkWritePrimitiveTypes();
@@ -998,12 +812,11 @@
      * Writes the string {@code value} as a sequence of bytes to the target
      * stream. Only the least significant byte of each character in the string
      * is written.
-     * 
+     *
      * @param value
      *            the string to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void writeBytes(String value) throws IOException {
         checkWritePrimitiveTypes();
@@ -1012,12 +825,11 @@
 
     /**
      * Writes a character (16 bit) to the target stream.
-     * 
+     *
      * @param value
      *            the character to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void writeChar(int value) throws IOException {
         checkWritePrimitiveTypes();
@@ -1027,12 +839,11 @@
     /**
      * Writes the string {@code value} as a sequence of characters to the target
      * stream.
-     * 
+     *
      * @param value
      *            the string to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void writeChars(String value) throws IOException {
         checkWritePrimitiveTypes();
@@ -1042,14 +853,14 @@
     /**
      * Write a class descriptor {@code classDesc} (an
      * {@code ObjectStreamClass}) to the stream.
-     * 
+     *
      * @param classDesc
      *            The class descriptor (an {@code ObjectStreamClass}) to
      *            be dumped
      * @param unshared
      *            Write the object unshared
      * @return the handle assigned to the class descriptor
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the class
      *             descriptor.
@@ -1066,12 +877,16 @@
         }
         if (handle == null) {
             Class<?> classToWrite = classDesc.forClass();
-            Integer previousHandle = objectsWritten.get(classDesc);
+            Integer previousHandle = null;
+            if (unshared) {
+                previousHandle = objectsWritten.get(classDesc);
+            }
             // If we got here, it is a new (non-null) classDesc that will have
             // to be registered as well
-            handle = registerObjectWritten(classDesc);
+            handle = nextHandle();
+            objectsWritten.put(classDesc, handle);
 
-            if (Proxy.isProxyClass(classToWrite)) {
+            if (classDesc.isProxy()) {
                 output.writeByte(TC_PROXYCLASSDESC);
                 Class<?>[] interfaces = classToWrite.getInterfaces();
                 output.writeInt(interfaces.length);
@@ -1080,7 +895,7 @@
                 }
                 annotateProxyClass(classToWrite);
                 output.writeByte(TC_ENDBLOCKDATA);
-                writeClassDescForClass(Proxy.class);
+                writeClassDesc(proxyClassDesc, false);
                 if (unshared) {
                     // remove reference to unshared object
                     removeUnsharedReference(classDesc, previousHandle);
@@ -1112,31 +927,12 @@
     }
 
     /**
-     * Writes a class descriptor (an {@code ObjectStreamClass}) that
-     * corresponds to the {@code java.lang.Class objClass} to the stream.
-     * 
-     * @param objClass
-     *            The class for which a class descriptor (an
-     *            {@code ObjectStreamClass}) will be dumped.
-     * @return the handle assigned to the class descriptor
-     * 
-     * @throws IOException
-     *             If an IO exception happened when writing the class
-     *             descriptor.
-     * 
-     */
-    private Integer writeClassDescForClass(Class<?> objClass)
-            throws IOException {
-        return writeClassDesc(ObjectStreamClass.lookup(objClass), false);
-    }
-
-    /**
      * Writes a handle representing a cyclic reference (object previously
      * dumped).
-     * 
+     *
      * @param handle
      *            The Integer handle that represents an object previously seen
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the cyclic
      *             reference.
@@ -1148,12 +944,11 @@
 
     /**
      * Writes a double (64 bit) to the target stream.
-     * 
+     *
      * @param value
      *            the double to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void writeDouble(double value) throws IOException {
         checkWritePrimitiveTypes();
@@ -1164,17 +959,17 @@
      * Writes a collection of field descriptors (name, type name, etc) for the
      * class descriptor {@code classDesc} (an
      * {@code ObjectStreamClass})
-     * 
+     *
      * @param classDesc
      *            The class descriptor (an {@code ObjectStreamClass})
      *            for which to write field information
      * @param externalizable
      *            true if the descriptors are externalizable
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the field
      *             descriptors.
-     * 
+     *
      * @see #writeObject(Object)
      */
     private void writeFieldDescriptors(ObjectStreamClass classDesc,
@@ -1207,13 +1002,12 @@
      * Writes the fields of the object currently being written to the target
      * stream. The field values are buffered in the currently active {@code
      * PutField} object, which can be accessed by calling {@code putFields()}.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @throws NotActiveException
      *             if there are no fields to write to the target stream.
      * @see #putFields
-     * @since Android 1.0
      */
     public void writeFields() throws IOException {
         // Has to have fields to write
@@ -1226,14 +1020,14 @@
     /**
      * Writes a collection of field values for the emulated fields
      * {@code emulatedFields}
-     * 
+     *
      * @param emulatedFields
      *            an {@code EmulatedFieldsForDumping}, concrete subclass
      *            of {@code PutField}
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the field values.
-     * 
+     *
      * @see #writeFields
      * @see #writeObject(Object)
      */
@@ -1279,32 +1073,37 @@
         }
     }
 
+
     /**
      * Writes a collection of field values for the fields described by class
      * descriptor {@code classDesc} (an {@code ObjectStreamClass}).
      * This is the default mechanism, when emulated fields (an
      * {@code PutField}) are not used. Actual values to dump are fetched
      * directly from object {@code obj}.
-     * 
+     *
      * @param obj
      *            Instance from which to fetch field values to dump.
      * @param classDesc
      *            A class descriptor (an {@code ObjectStreamClass})
      *            defining which fields should be dumped.
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the field values.
-     * 
+     *
      * @see #writeObject(Object)
      */
     private void writeFieldValues(Object obj, ObjectStreamClass classDesc)
             throws IOException {
         ObjectStreamField[] fields = classDesc.fields();
         Class<?> declaringClass = classDesc.forClass();
-        for (int i = 0; i < fields.length; i++) {
+        for(ObjectStreamField fieldDesc : fields) {
             try {
+
+                // BEGIN android-changed
+                // // get associated Field
+                // long fieldID = fieldDesc.getFieldID(accessor, declaringClass);
+
                 // Code duplication starts, just because Java is typed
-                ObjectStreamField fieldDesc = fields[i];
                 if (fieldDesc.isPrimitive()) {
                     switch (fieldDesc.getTypeCode()) {
                         case 'B':
@@ -1346,14 +1145,15 @@
                     }
                 } else {
                     // Object type (array included).
-                    Object field = getFieldObj(obj, declaringClass, fieldDesc
+                    Object objField = getFieldObj(obj, declaringClass, fieldDesc
                             .getName(), fieldDesc.getTypeString());
                     if (fieldDesc.isUnshared()) {
-                        writeUnshared(field);
+                        writeUnshared(objField);
                     } else {
-                        writeObject(field);
+                        writeObject(objField);
                     }
                 }
+                // END android-changed
             } catch (NoSuchFieldError nsf) {
                 // The user defined serialPersistentFields but did not provide
                 // the glue to transfer values,
@@ -1366,12 +1166,11 @@
 
     /**
      * Writes a float (32 bit) to the target stream.
-     * 
+     *
      * @param value
      *            the float to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void writeFloat(float value) throws IOException {
         checkWritePrimitiveTypes();
@@ -1386,19 +1185,19 @@
      * (corresponding to class descriptor {@code classDesc}) defines
      * private instance method {@code writeObject} it will be used to
      * dump field values.
-     * 
+     *
      * @param object
      *            Instance from which to fetch field values to dump.
      * @param classDesc
      *            A class descriptor (an {@code ObjectStreamClass})
      *            defining which fields should be dumped.
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the field values in
      *             the hierarchy.
      * @throws NotActiveException
      *             If the given object is not active
-     * 
+     *
      * @see #defaultWriteObject
      * @see #writeObject(Object)
      */
@@ -1423,14 +1222,9 @@
 
         // See if the object has a writeObject method. If so, run it
         boolean executed = false;
-        Class<?> targetClass = classDesc.forClass();
         try {
-            final Method method = ObjectStreamClass
-                    .getPrivateWriteObjectMethod(targetClass);
-            if (method != null) {
-                // We have to be able to fetch its value, even if it is
-                // private
-                AccessController.doPrivileged(new PriviAction<Object>(method));
+            if (classDesc.hasMethodWriteObject()){
+                final Method method = classDesc.getMethodWriteObject();
                 try {
                     method.invoke(object, new Object[] { this });
                     executed = true;
@@ -1447,6 +1241,7 @@
                 }
             }
 
+
             if (executed) {
                 drain();
                 output.writeByte(TC_ENDBLOCKDATA);
@@ -1466,12 +1261,11 @@
 
     /**
      * Writes an integer (32 bit) to the target stream.
-     * 
+     *
      * @param value
      *            the integer to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void writeInt(int value) throws IOException {
         checkWritePrimitiveTypes();
@@ -1480,12 +1274,11 @@
 
     /**
      * Writes a long (64 bit) to the target stream.
-     * 
+     *
      * @param value
      *            the long to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void writeLong(long value) throws IOException {
         checkWritePrimitiveTypes();
@@ -1497,7 +1290,7 @@
      * component type {@code componentType} into the receiver. It is
      * assumed the array has not been dumped yet. Return an {@code Integer}
      * that represents the handle for this object (array) which is dumped here.
-     * 
+     *
      * @param array
      *            The array object to dump
      * @param arrayClass
@@ -1507,20 +1300,19 @@
      *            A {@code java.lang.Class} representing the array
      *            component type
      * @return the handle assigned to the array
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the array.
      */
-    private Integer writeNewArray(Object array, Class<?> arrayClass,
+    private Integer writeNewArray(Object array, Class<?> arrayClass, ObjectStreamClass arrayClDesc,
             Class<?> componentType, boolean unshared) throws IOException {
         output.writeByte(TC_ARRAY);
-        writeClassDescForClass(arrayClass);
+        writeClassDesc(arrayClDesc, false);
 
-        Integer previousHandle = objectsWritten.get(array);
-        Integer handle = registerObjectWritten(array);
-        if (unshared) {
-            // remove reference to unshared object
-            removeUnsharedReference(array, previousHandle);
+        Integer handle = nextHandle();
+
+        if (!unshared) {
+            objectsWritten.put(array, handle);
         }
 
         // Now we have code duplication just because Java is typed. We have to
@@ -1585,6 +1377,10 @@
             Object[] objectArray = (Object[]) array;
             output.writeInt(objectArray.length);
             for (int i = 0; i < objectArray.length; i++) {
+                // TODO: This place is the opportunity for enhancement
+                //      We can implement writing elements through fast-path,
+                //      without setting up the context (see writeObject()) for
+                //      each element with public API
                 writeObject(objectArray[i]);
             }
         }
@@ -1597,11 +1393,11 @@
      * descriptor ({@code ObjectStreamClass}) that corresponds to them.
      * Return an {@code Integer} that represents the handle for this
      * object (class) which is dumped here.
-     * 
+     *
      * @param object
      *            The {@code java.lang.Class} object to dump
      * @return the handle assigned to the class being dumped
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the class.
      */
@@ -1614,21 +1410,20 @@
         // We cannot call lookup because it returns null if the parameter
         // represents instances that cannot be serialized, and that is not what
         // we want.
+        ObjectStreamClass clDesc = ObjectStreamClass.lookupStreamClass(object);
 
         // The handle for the classDesc is NOT the handle for the class object
         // being dumped. We must allocate a new handle and return it.
-        if (object.isEnum()) {
-            writeEnumDesc(object, unshared);
+        if (clDesc.isEnum()) {
+            writeEnumDesc(object, clDesc, unshared);
         } else {
-            writeClassDesc(ObjectStreamClass.lookupStreamClass(object),
-                    unshared);
+            writeClassDesc(clDesc, unshared);
         }
 
-        Integer previousHandle = objectsWritten.get(object);
-        Integer handle = registerObjectWritten(object);
-        if (unshared) {
-            // remove reference to unshared object
-            removeUnsharedReference(object, previousHandle);
+        Integer handle = nextHandle();
+
+        if (!unshared) {
+            objectsWritten.put(object, handle);
         }
 
         return handle;
@@ -1640,10 +1435,10 @@
      * descriptors for the superclass chain will be dumped as well. Return an
      * {@code Integer} that represents the handle for this object (class
      * descriptor) which is dumped here.
-     * 
+     *
      * @param classDesc
      *            The {@code ObjectStreamClass} object to dump
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the class
      *             descriptor.
@@ -1653,15 +1448,15 @@
         output.writeUTF(classDesc.getName());
         output.writeLong(classDesc.getSerialVersionUID());
         byte flags = classDesc.getFlags();
-        boolean externalizable = false;
-        externalizable = ObjectStreamClass.isExternalizable(classDesc
-                .forClass());
-        if (protocolVersion != PROTOCOL_VERSION_1) {
-            // Change for 1.2. Objects can be saved in old format
-            // (PROTOCOL_VERSION_1) or in the 1.2 format (PROTOCOL_VERSION_2).
-            // Nested "if" check to optimize checking. Second check is more
-            // expensive.
-            if (externalizable) {
+
+        boolean externalizable = classDesc.isExternalizable();
+
+        if (externalizable) {
+            if (protocolVersion == PROTOCOL_VERSION_1) {
+                flags &= NOT_SC_BLOCK_DATA;
+            } else {
+                // Change for 1.2. Objects can be saved in old format
+                // (PROTOCOL_VERSION_1) or in the 1.2 format (PROTOCOL_VERSION_2).
                 flags |= SC_BLOCK_DATA;
             }
         }
@@ -1676,12 +1471,11 @@
 
     /**
      * Writes a class descriptor to the target stream.
-     * 
+     *
      * @param classDesc
      *            the class descriptor to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     protected void writeClassDescriptor(ObjectStreamClass classDesc)
             throws IOException {
@@ -1695,14 +1489,14 @@
      * This is used to dump the exception instance that happened (if any) when
      * dumping the original object graph. The set of seen objects will be reset
      * just before and just after dumping this exception object.
-     * 
+     *
      * When exceptions are found normally in the object graph, they are dumped
      * as a regular object, and not by this method. In that case, the set of
      * "known objects" is not reset.
-     * 
+     *
      * @param ex
      *            Exception object to dump
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the exception
      *             object.
@@ -1719,13 +1513,13 @@
      * the receiver. It is assumed the object has not been dumped yet. Return an
      * {@code Integer} that represents the handle for this object which
      * is dumped here.
-     * 
+     *
      * If the object implements {@code Externalizable} its
      * {@code writeExternal} is called. Otherwise, all fields described
      * by the class hierarchy is dumped. Each class can define how its declared
      * instance fields are dumped by defining a private method
      * {@code writeObject}
-     * 
+     *
      * @param object
      *            The object to dump
      * @param theClass
@@ -1734,11 +1528,11 @@
      * @param unshared
      *            Write the object unshared
      * @return the handle assigned to the object
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the object.
      */
-    private Integer writeNewObject(Object object, Class<?> theClass,
+    private Integer writeNewObject(Object object, Class<?> theClass, ObjectStreamClass clDesc,
             boolean unshared) throws IOException {
         // Not String, not null, not array, not cyclic reference
 
@@ -1746,8 +1540,8 @@
         currentPutField = null; // null it, to make sure one will be computed if
         // needed
 
-        boolean externalizable = ObjectStreamClass.isExternalizable(theClass);
-        boolean serializable = ObjectStreamClass.isSerializable(theClass);
+        boolean externalizable = clDesc.isExternalizable();
+        boolean serializable = clDesc.isSerializable();
         if (!externalizable && !serializable) {
             // Object is neither externalizable nor serializable. Error
             throw new NotSerializableException(theClass.getName());
@@ -1755,16 +1549,20 @@
 
         // Either serializable or externalizable, now we can save info
         output.writeByte(TC_OBJECT);
-        writeClassDescForClass(theClass);
-        Integer previousHandle = objectsWritten.get(object);
-        Integer handle = registerObjectWritten(object);
+        writeClassDesc(clDesc, false);
+        Integer previousHandle = null;
+        if (unshared) {
+            previousHandle = objectsWritten.get(object);
+        }
+        Integer handle = nextHandle();
+        objectsWritten.put(object, handle);
 
         // This is how we know what to do in defaultWriteObject. And it is also
         // used by defaultWriteObject to check if it was called from an invalid
         // place.
         // It allows writeExternal to call defaultWriteObject and have it work.
         currentObject = object;
-        currentClass = ObjectStreamClass.lookup(theClass);
+        currentClass = clDesc;
         try {
             if (externalizable) {
                 boolean noBlockData = protocolVersion == PROTOCOL_VERSION_1;
@@ -1808,11 +1606,11 @@
      * String has not been dumped yet. Return an {@code Integer} that
      * represents the handle for this object (String) which is dumped here.
      * Strings are saved encoded with {@link DataInput modified UTF-8}.
-     * 
+     *
      * @param object
      *            the string to dump.
      * @return the handle assigned to the String being dumped
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the String.
      */
@@ -1828,19 +1626,19 @@
         }
         output.writeUTFBytes(object, count);
 
-        Integer previousHandle = objectsWritten.get(object);
-        Integer handle = registerObjectWritten(object);
-        if (unshared) {
-            // remove reference to unshared object
-            removeUnsharedReference(object, previousHandle);
+        Integer handle = nextHandle();
+
+        if (!unshared) {
+            objectsWritten.put(object, handle);
         }
+
         return handle;
     }
 
     /**
      * Write a special tag that indicates the value {@code null} into the
      * receiver.
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the tag for
      *             {@code null}.
@@ -1851,13 +1649,12 @@
 
     /**
      * Writes an object to the target stream.
-     * 
+     *
      * @param object
      *            the object to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see ObjectInputStream#readObject()
-     * @since Android 1.0
      */
     public final void writeObject(Object object) throws IOException {
         writeObject(object, false);
@@ -1868,13 +1665,12 @@
      * to {@code writeObject}, except that it always writes a new object to the
      * stream versus the use of back-referencing for identical objects by
      * {@code writeObject}.
-     * 
+     *
      * @param object
      *            the object to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
      * @see ObjectInputStream#readUnshared()
-     * @since Android 1.0
      */
     public void writeUnshared(Object object) throws IOException {
         writeObject(object, true);
@@ -1919,7 +1715,7 @@
 
     /**
      * Write object {@code object} into the receiver's underlying stream.
-     * 
+     *
      * @param object
      *            The object to write
      * @param unshared
@@ -1931,10 +1727,10 @@
      *            A boolean indicating if stream-based replacement should be
      *            computed (if supported) for the object.
      * @return the handle assigned to the final object being dumped
-     * 
+     *
      * @throws IOException
      *             If an IO exception happened when writing the object
-     * 
+     *
      * @see ObjectInputStream#readObject()
      */
     private Integer writeObjectInternal(Object object, boolean unshared,
@@ -1955,6 +1751,8 @@
 
         // Non-null object, first time seen...
         Class<?> objClass = object.getClass();
+        ObjectStreamClass clDesc = ObjectStreamClass.lookupStreamClass(objClass);
+
         nestedLevels++;
         try {
 
@@ -1969,58 +1767,41 @@
                 }
             }
 
-            if (ObjectStreamClass.isSerializable(object.getClass())
+            if (clDesc.isSerializable()
                     && computeClassBasedReplacement) {
-                Object writeReplaceMethod = writeReplaceCache.get(objClass);
-                if (writeReplaceMethod != this) {
-                    if (writeReplaceMethod == null) {
-                        final Method writeReplace = ObjectStreamClass
-                                .methodWriteReplace(objClass);
-                        if (writeReplace == null) {
-                            writeReplaceCache.put(objClass, this);
-                            writeReplaceMethod = null;
+                if(clDesc.hasMethodWriteReplace()){
+                    Method methodWriteReplace = clDesc.getMethodWriteReplace();
+                    Object replObj = null;
+                    try {
+                        replObj = methodWriteReplace.invoke(object, (Object[]) null);
+                    } catch (IllegalAccessException iae) {
+                        replObj = object;
+                    } catch (InvocationTargetException ite) {
+                        // WARNING - Not sure this is the right thing to do
+                        // if we can't run the method
+                        Throwable target = ite.getTargetException();
+                        if (target instanceof ObjectStreamException) {
+                            throw (ObjectStreamException) target;
+                        } else if (target instanceof Error) {
+                            throw (Error) target;
                         } else {
-                            // Has replacement method
-                            AccessController
-                                    .doPrivileged(new PriviAction<Object>(
-                                            writeReplace));
-                            writeReplaceCache.put(objClass, writeReplace);
-                            writeReplaceMethod = writeReplace;
+                            throw (RuntimeException) target;
                         }
                     }
-                    if (writeReplaceMethod != null) {
-                        Object classBasedReplacement;
-                        try {
-                            classBasedReplacement = ((Method) writeReplaceMethod)
-                                    .invoke(object, (Object[]) null);
-                        } catch (IllegalAccessException iae) {
-                            classBasedReplacement = object;
-                        } catch (InvocationTargetException ite) {
-                            // WARNING - Not sure this is the right thing to do
-                            // if we can't run the method
-                            Throwable target = ite.getTargetException();
-                            if (target instanceof ObjectStreamException) {
-                                throw (ObjectStreamException) target;
-                            } else if (target instanceof Error) {
-                                throw (Error) target;
-                            } else {
-                                throw (RuntimeException) target;
-                            }
+                    if (replObj != object) {
+                        // All over, class-based replacement off this time.
+                        Integer replacementHandle = writeObjectInternal(
+                                replObj, false, false,
+                                computeStreamReplacement);
+                        // Make the original object also map to the same
+                        // handle.
+                        if (replacementHandle != null) {
+                            objectsWritten.put(object, replacementHandle);
                         }
-                        if (classBasedReplacement != object) {
-                            // All over, class-based replacement off this time.
-                            Integer replacementHandle = writeObjectInternal(
-                                    classBasedReplacement, false, false,
-                                    computeStreamReplacement);
-                            // Make the original object also map to the same
-                            // handle.
-                            if (replacementHandle != null) {
-                                registerObjectWritten(object, replacementHandle);
-                            }
-                            return replacementHandle;
-                        }
+                        return replacementHandle;
                     }
                 }
+
             }
 
             // We get here either if class-based replacement was not needed or
@@ -2036,7 +1817,7 @@
                             computeClassBasedReplacement, false);
                     // Make the original object also map to the same handle.
                     if (replacementHandle != null) {
-                        registerObjectWritten(object, replacementHandle);
+                        objectsWritten.put(object, replacementHandle);
                     }
                     return replacementHandle;
                 }
@@ -2061,7 +1842,7 @@
 
             // Is it an Array ?
             if (objClass.isArray()) {
-                return writeNewArray(object, objClass, objClass
+                return writeNewArray(object, objClass, clDesc, objClass
                         .getComponentType(), unshared);
             }
 
@@ -2070,20 +1851,23 @@
             }
 
             // Not a String or Class or Array. Default procedure.
-            return writeNewObject(object, objClass, unshared);
+            return writeNewObject(object, objClass, clDesc, unshared);
         } finally {
             nestedLevels--;
         }
     }
 
     // write for Enum Class Desc only, which is different from other classes
-    private ObjectStreamClass writeEnumDesc(Class<?> theClass, boolean unshared)
+    private ObjectStreamClass writeEnumDesc(Class<?> theClass, ObjectStreamClass classDesc, boolean unshared)
             throws IOException {
         // write classDesc, classDesc for enum is different
-        ObjectStreamClass classDesc = ObjectStreamClass.lookup(theClass);
+
         // set flag for enum, the flag is (SC_SERIALIZABLE | SC_ENUM)
         classDesc.setFlags((byte) (SC_SERIALIZABLE | SC_ENUM));
-        Integer previousHandle = objectsWritten.get(classDesc);
+        Integer previousHandle = null;
+        if (unshared) {
+            previousHandle = objectsWritten.get(classDesc);
+        }
         Integer handle = null;
         if (!unshared) {
             handle = dumpCycle(classDesc);
@@ -2092,7 +1876,7 @@
             Class<?> classToWrite = classDesc.forClass();
             // If we got here, it is a new (non-null) classDesc that will have
             // to be registered as well
-            registerObjectWritten(classDesc);
+            objectsWritten.put(classDesc, nextHandle());
 
             output.writeByte(TC_CLASSDESC);
             if (protocolVersion == PROTOCOL_VERSION_1) {
@@ -2109,11 +1893,11 @@
             drain(); // flush primitive types in the annotation
             output.writeByte(TC_ENDBLOCKDATA);
             // write super class
-            ObjectStreamClass superClass = classDesc.getSuperclass();
-            if (null != superClass) {
+            ObjectStreamClass superClassDesc = classDesc.getSuperclass();
+            if (null != superClassDesc) {
                 // super class is also enum
-                superClass.setFlags((byte) (SC_SERIALIZABLE | SC_ENUM));
-                writeEnumDesc(superClass.forClass(), unshared);
+                superClassDesc.setFlags((byte) (SC_SERIALIZABLE | SC_ENUM));
+                writeEnumDesc(superClassDesc.forClass(), superClassDesc, unshared);
             } else {
                 output.writeByte(TC_NULL);
             }
@@ -2137,18 +1921,26 @@
             // write enum only
             theClass = theClass.getSuperclass();
         }
-        ObjectStreamClass classDesc = writeEnumDesc(theClass, unshared);
+        ObjectStreamClass classDesc = ObjectStreamClass.lookup(theClass);
+        writeEnumDesc(theClass, classDesc, unshared);
 
-        Integer previousHandle = objectsWritten.get(object);
-        Integer handle = registerObjectWritten(object);
+        Integer previousHandle = null;
+        if (unshared) {
+            previousHandle = objectsWritten.get(object);
+        }
+        Integer handle = nextHandle();
+        objectsWritten.put(object, handle);
 
         ObjectStreamField[] fields = classDesc.getSuperclass().fields();
         Class<?> declaringClass = classDesc.getSuperclass().forClass();
         // Only write field "name" for enum class, which is the second field of
         // enum, that is fields[1]. Ignore all non-fields and fields.length < 2
         if (null != fields && fields.length > 1) {
+            // BEGIN android-changed
             String str = (String) getFieldObj(object, declaringClass, fields[1]
                     .getName(), fields[1].getTypeString());
+            // END android-changed
+
             Integer strhandle = null;
             if (!unshared) {
                 strhandle = dumpCycle(str);
@@ -2169,31 +1961,26 @@
     /**
      * Method to be overridden by subclasses to write {@code object} to the
      * target stream.
-     * 
+     *
      * @param object
      *            the object to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     protected void writeObjectOverride(Object object) throws IOException {
-        // BEGIN android-changed
-        // copied from newer version of harmony
         if (!subclassOverridingImplementation) {
             // Subclasses must override.
             throw new IOException();
         }
-        // END android-changed
     }
 
     /**
      * Writes a short (16 bit) to the target stream.
-     * 
+     *
      * @param value
      *            the short to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void writeShort(int value) throws IOException {
         checkWritePrimitiveTypes();
@@ -2202,10 +1989,9 @@
 
     /**
      * Writes the {@link ObjectOutputStream} header to the target stream.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     protected void writeStreamHeader() throws IOException {
         output.writeShort(STREAM_MAGIC);
@@ -2215,12 +2001,11 @@
     /**
      * Writes a string encoded with {@link DataInput modified UTF-8} to the
      * target stream.
-     * 
+     *
      * @param value
      *            the string to write to the target stream.
      * @throws IOException
      *             if an error occurs while writing to the target stream.
-     * @since Android 1.0
      */
     public void writeUTF(String value) throws IOException {
         checkWritePrimitiveTypes();
diff --git a/libcore/luni/src/main/java/java/io/ObjectStreamClass.java b/libcore/luni/src/main/java/java/io/ObjectStreamClass.java
index 37b1f17..ac356ea 100644
--- a/libcore/luni/src/main/java/java/io/ObjectStreamClass.java
+++ b/libcore/luni/src/main/java/java/io/ObjectStreamClass.java
@@ -22,6 +22,7 @@
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
 import java.security.AccessController;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
@@ -33,18 +34,17 @@
 
 import org.apache.harmony.luni.util.Msg;
 import org.apache.harmony.luni.util.PriviAction;
+import org.apache.harmony.luni.util.ThreadLocalCache;
 
 /**
  * Represents a descriptor for identifying a class during serialization and
  * deserialization. Information contained in the descriptor includes the name
  * and SUID of the class as well as field names and types. Information inherited
  * from the superclasses is also taken into account.
- * 
+ *
  * @see ObjectOutputStream
  * @see ObjectInputStream
  * @see java.lang.Class
- * 
- * @since Android 1.0
  */
 public class ObjectStreamClass implements Serializable {
 
@@ -55,6 +55,8 @@
     // Name of the field that contains the SUID value (if present)
     private static final String UID_FIELD_NAME = "serialVersionUID"; //$NON-NLS-1$
 
+    static final long CONSTRUCTOR_IS_NOT_RESOLVED = -1;
+
     private static final int CLASS_MODIFIERS_MASK;
 
     private static final int FIELD_MODIFIERS_MASK;
@@ -98,8 +100,6 @@
 
     /**
      * Constant indicating that the class has no Serializable fields.
-     * 
-     * @since Android 1.0
      */
     public static final ObjectStreamField[] NO_FIELDS = new ObjectStreamField[0];
 
@@ -135,9 +135,36 @@
 
     static final Class<ObjectStreamClass> OBJECTSTREAMCLASSCLASS = ObjectStreamClass.class;
 
-    // Table mapping instances of java.lang.Class to to corresponding instances
-    // of ObjectStreamClass
-    private static final WeakHashMap<Class<?>, ObjectStreamClass> classesAndDescriptors = new WeakHashMap<Class<?>, ObjectStreamClass>();
+    private transient Method methodWriteReplace;
+
+    private transient Method methodReadResolve;
+
+    private transient Method methodWriteObject;
+
+    private transient Method methodReadObject;
+
+    private transient Method methodReadObjectNoData;
+
+    /**
+     * Indicates whether the class properties resolved
+     *
+     * @see #resolveProperties()
+     */
+    private transient boolean arePropertiesResolved;
+
+    /**
+     * Cached class properties
+     *
+     * @see #resolveProperties()
+     * @see #isSerializable()
+     * @see #isExternalizable()
+     * @see #isProxy()
+     * @see #isEnum()
+     */
+    private transient boolean isSerializable;
+    private transient boolean isExternalizable;
+    private transient boolean isProxy;
+    private transient boolean isEnum;
 
     // ClassDesc //
 
@@ -167,6 +194,17 @@
     // Array of ObjectStreamField describing the serialized fields of this class
     private transient ObjectStreamField[] loadFields;
 
+    // MethodID for deserialization constructor
+    private transient long constructor = CONSTRUCTOR_IS_NOT_RESOLVED;
+
+    void setConstructor(long newConstructor) {
+        constructor = newConstructor;
+    }
+
+    long getConstructor() {
+        return constructor;
+    }
+
     /*
      * If an ObjectStreamClass describes an Externalizable class, it (the
      * descriptor) should not have field descriptors (ObjectStreamField) at all.
@@ -183,22 +221,24 @@
     }
 
     /**
-     * Adds an extra entry mapping a given class {@code cl} to its class
-     * descriptor, which will be computed (an ObjectStreamClass). If
-     * {@code computeSUID} is true, this method will compute the SUID for
-     * this class.
-     * 
+     * Compute class descriptor for a given class <code>cl</code>.
+     *
      * @param cl
      *            a java.langClass for which to compute the corresponding
      *            descriptor
-     * @param computeSUID
-     *            a boolean indicating if SUID should be computed or not.
      * @return the computer class descriptor
      */
-    private static ObjectStreamClass addToCache(Class<?> cl, boolean computeSUID) {
+    private static ObjectStreamClass createClassDesc(Class<?> cl) {
 
         ObjectStreamClass result = new ObjectStreamClass();
 
+        boolean isArray = cl.isArray();
+        boolean serializable = isSerializable(cl);
+        boolean externalizable = isExternalizable(cl);
+
+        result.isSerializable = serializable;
+        result.isExternalizable = externalizable;
+
         // Now we fill in the values
         result.setName(cl.getName());
         result.setClass(cl);
@@ -208,45 +248,73 @@
         }
 
         Field[] declaredFields = null;
-        if (computeSUID) {
-            // Lazy computation, to save speed & space
-            declaredFields = cl.getDeclaredFields();
-            result.setSerialVersionUID((cl.isEnum() || (cl == Enum.class)) ? 0
-                    : computeSerialVersionUID(cl, declaredFields));
+
+        // Compute the SUID
+        if(serializable || externalizable) {
+            if (result.isEnum() || result.isProxy()) {
+                result.setSerialVersionUID(0L);
+            } else {
+                declaredFields = cl.getDeclaredFields();
+                result.setSerialVersionUID(computeSerialVersionUID(cl,
+                        declaredFields));
+            }
         }
 
-        boolean serializable = isSerializable(cl);
         // Serializables need field descriptors
-        if (serializable && !cl.isArray()) {
+        if (serializable && !isArray) {
             if (declaredFields == null) {
-
                 declaredFields = cl.getDeclaredFields();
             }
             result.buildFieldDescriptors(declaredFields);
         } else {
             // Externalizables or arrays do not need FieldDesc info
-            result.setFields(new ObjectStreamField[0]);
+            result.setFields(NO_FIELDS);
+        }
+
+        // Copy all fields to loadFields - they should be read by default in
+        // ObjectInputStream.defaultReadObject() method
+        ObjectStreamField[] fields = result.getFields();
+
+        if (fields != null) {
+            ObjectStreamField[] loadFields = new ObjectStreamField[fields.length];
+
+            for (int i = 0; i < fields.length; ++i) {
+                loadFields[i] = new ObjectStreamField(fields[i].getName(),
+                        fields[i].getType(), fields[i].isUnshared());
+
+                // resolve type string to init typeString field in
+                // ObjectStreamField
+                loadFields[i].getTypeString();
+            }
+            result.setLoadFields(loadFields);
         }
 
         byte flags = 0;
-        boolean externalizable = isExternalizable(cl);
         if (externalizable) {
             flags |= ObjectStreamConstants.SC_EXTERNALIZABLE;
+            flags |= ObjectStreamConstants.SC_BLOCK_DATA; // use protocol version 2 by default
         } else if (serializable) {
             flags |= ObjectStreamConstants.SC_SERIALIZABLE;
         }
-        if (getPrivateWriteObjectMethod(cl) != null) {
+        result.methodWriteReplace = findMethod(cl, "writeReplace"); //$NON-NLS-1$
+        result.methodReadResolve = findMethod(cl, "readResolve"); //$NON-NLS-1$
+        result.methodWriteObject = findPrivateMethod(cl, "writeObject", //$NON-NLS-1$
+                WRITE_PARAM_TYPES);
+        result.methodReadObject = findPrivateMethod(cl, "readObject", //$NON-NLS-1$
+                READ_PARAM_TYPES);
+        result.methodReadObjectNoData = findPrivateMethod(cl,
+                "readObjectNoData", EMPTY_CONSTRUCTOR_PARAM_TYPES); //$NON-NLS-1$
+        if (result.hasMethodWriteObject()) {
             flags |= ObjectStreamConstants.SC_WRITE_METHOD;
         }
         result.setFlags(flags);
-        classesAndDescriptors.put(cl, result);
 
         return result;
     }
 
     /**
      * Builds the collection of field descriptors for the receiver
-     * 
+     *
      * @param declaredFields
      *            collection of java.lang.reflect.Field for which to compute
      *            field descriptors
@@ -315,12 +383,12 @@
         }
         fields = _fields;
     }
-    
+
     /**
      * Compute and return the Serial Version UID of the class {@code cl}.
      * The value is computed based on the class name, superclass chain, field
      * names, method names, modifiers, etc.
-     * 
+     *
      * @param cl
      *            a java.lang.Class for which to compute the SUID
      * @param fields
@@ -477,7 +545,7 @@
                     /*
                      * write name, modifier & "descriptor" of all but private
                      * ones
-                     * 
+                     *
                      * constructor.getName() returns the constructor name as
                      * typed, not the VM name
                      */
@@ -534,7 +602,7 @@
     /**
      * Returns what the serializaton specification calls "descriptor" given a
      * field signature.
-     * 
+     *
      * @param signature
      *            a field signature
      * @return containing the descriptor
@@ -546,7 +614,7 @@
     /**
      * Return what the serializaton specification calls "descriptor" given a
      * method/constructor signature.
-     * 
+     *
      * @param signature
      *            a method or constructor signature
      * @return containing the descriptor
@@ -558,7 +626,7 @@
     /**
      * Return the java.lang.reflect.Field {@code serialPersistentFields}
      * if class {@code cl} implements it. Return null otherwise.
-     * 
+     *
      * @param cl
      *            a java.lang.Class which to test
      * @return {@code java.lang.reflect.Field} if the class has
@@ -583,10 +651,9 @@
 
     /**
      * Returns the class (java.lang.Class) for this descriptor.
-     * 
+     *
      * @return the class in the local VM that this descriptor represents;
      *         {@code null} if there is no corresponding class.
-     * @since Android 1.0
      */
     public Class<?> forClass() {
         if (resolvedClass != null) {
@@ -597,7 +664,7 @@
 
     /**
      * Return a String representing the signature for a Constructor {@code c}.
-     * 
+     *
      * @param c
      *            a java.lang.reflect.Constructor for which to compute the
      *            signature
@@ -608,12 +675,11 @@
     /**
      * Gets a field descriptor of the class represented by this class
      * descriptor.
-     * 
+     *
      * @param name
      *            the name of the desired field.
      * @return the field identified by {@code name} or {@code null} if there is
      *         no such field.
-     * @since Android 1.0
      */
     public ObjectStreamField getField(String name) {
         ObjectStreamField[] allFields = getFields();
@@ -629,20 +695,18 @@
     /**
      * Returns the collection of field descriptors for the fields of the
      * corresponding class
-     * 
+     *
      * @return the receiver's collection of declared fields for the class it
      *         represents
      */
     ObjectStreamField[] fields() {
         if (fields == null) {
-            synchronized(this){ 
-                Class<?> forCl = forClass();
-                if (forCl != null && isSerializable(forCl) && !forCl.isArray()) {
-                    buildFieldDescriptors(forCl.getDeclaredFields());
-                } else {
-                    // Externalizables or arrays do not need FieldDesc info
-                    setFields(new ObjectStreamField[0]);
-                }
+            Class<?> forCl = forClass();
+            if (forCl != null && isSerializable() && !forCl.isArray()) {
+                buildFieldDescriptors(forCl.getDeclaredFields());
+            } else {
+                // Externalizables or arrays do not need FieldDesc info
+                setFields(NO_FIELDS);
             }
         }
         return fields;
@@ -651,10 +715,9 @@
     /**
      * Returns a collection of field descriptors for the serialized fields of
      * the class represented by this class descriptor.
-     * 
+     *
      * @return an array of field descriptors or an array of length zero if there
      *         are no fields in this descriptor's class.
-     * @since Android 1.0
      */
     public ObjectStreamField[] getFields() {
         copyFieldAttributes();
@@ -662,9 +725,9 @@
     }
 
     /**
-     * If a Class uses "serialPersistentFields" to define the serialized fields, 
+     * If a Class uses "serialPersistentFields" to define the serialized fields,
      * this.loadFields cannot get the "unshared" information when deserializing
-     * fields using current implementation of ObjectInputStream. This method 
+     * fields using current implementation of ObjectInputStream. This method
      * provides a way to copy the "unshared" attribute from this.fields.
      *
      */
@@ -672,7 +735,7 @@
         if ((loadFields == null) || fields == null) {
             return;
         }
-        
+
         for (int i = 0; i < loadFields.length; i++) {
             ObjectStreamField loadField = loadFields[i];
             String name = loadField.getName();
@@ -690,7 +753,7 @@
     /**
      * Returns the collection of field descriptors for the input fields of the
      * corresponding class
-     * 
+     *
      * @return the receiver's collection of input fields for the class it
      *         represents
      */
@@ -700,7 +763,7 @@
 
     /**
      * Return a String representing the signature for a field {@code f}.
-     * 
+     *
      * @param f
      *            a java.lang.reflect.Field for which to compute the signature
      * @return the field's signature
@@ -709,11 +772,11 @@
 
     /**
      * Returns the flags for this descriptor, where possible combined values are
-     * 
+     *
      * ObjectStreamConstants.SC_WRITE_METHOD
      * ObjectStreamConstants.SC_SERIALIZABLE
      * ObjectStreamConstants.SC_EXTERNALIZABLE
-     * 
+     *
      * @return byte the receiver's flags for the class it represents
      */
     byte getFlags() {
@@ -722,7 +785,7 @@
 
     /**
      * Return a String representing the signature for a method {@code m}.
-     * 
+     *
      * @param m
      *            a java.lang.reflect.Method for which to compute the signature
      * @return the method's signature
@@ -731,9 +794,8 @@
 
     /**
      * Returns the name of the class represented by this descriptor.
-     * 
+     *
      * @return the fully qualified name of the class this descriptor represents.
-     * @since Android 1.0
      */
     public String getName() {
         return className;
@@ -742,9 +804,8 @@
     /**
      * Returns the Serial Version User ID of the class represented by this
      * descriptor.
-     * 
+     *
      * @return the SUID for the class represented by this descriptor.
-     * @since Android 1.0
      */
     public long getSerialVersionUID() {
         return svUID;
@@ -753,7 +814,7 @@
     /**
      * Returns the descriptor (ObjectStreamClass) of the superclass of the class
      * represented by the receiver.
-     * 
+     *
      * @return an ObjectStreamClass representing the superclass of the class
      *         represented by the receiver.
      */
@@ -767,7 +828,7 @@
      * compiler-generated, it is used by the serialization code to compute SUID.
      * This is unfortunate, since it may depend on compiler optimizations in
      * some cases.
-     * 
+     *
      * @param cl
      *            a java.lang.Class which to test
      * @return {@code true} if the class has <clinit> {@code false}
@@ -776,84 +837,15 @@
     private static native boolean hasClinit(Class<?> cl);
 
     /**
-     * Return true if the given class {@code cl} implements private
-     * method {@code readObject()}.
-     * 
-     * @param cl
-     *            a java.lang.Class which to test
-     * @return {@code true} if the class implements readObject
-     *         {@code false} if the class does not implement readObject
-     */
-    static Method getPrivateReadObjectMethod(Class<?> cl) {
-        try {
-            Method method = cl
-                    .getDeclaredMethod("readObject", READ_PARAM_TYPES); //$NON-NLS-1$
-            if (Modifier.isPrivate(method.getModifiers())
-                    && method.getReturnType() == VOID_CLASS) {
-                return method;
-            }
-        } catch (NoSuchMethodException nsm) {
-            // Ignored
-        }
-        return null;
-    }
-
-    /**
-     * Return true if the given class {@code cl} implements private
-     * method {@code readObject()}.
-     * 
-     * @param cl
-     *            a java.lang.Class which to test
-     * @return {@code true} if the class implements readObject
-     *         {@code false} if the class does not implement readObject
-     */
-    static Method getPrivateReadObjectNoDataMethod(Class<?> cl) {
-        try {
-            Method method = cl.getDeclaredMethod("readObjectNoData", //$NON-NLS-1$
-                    EMPTY_CONSTRUCTOR_PARAM_TYPES);
-            if (Modifier.isPrivate(method.getModifiers())
-                    && method.getReturnType() == VOID_CLASS) {
-                return method;
-            }
-        } catch (NoSuchMethodException nsm) {
-            // Ignored
-        }
-        return null;
-    }
-
-    /**
-     * Return true if the given class {@code cl} implements private
-     * method {@code writeObject()}.
-     * 
-     * @param cl
-     *            a java.lang.Class which to test
-     * @return {@code true} if the class implements writeObject
-     *         {@code false} if the class does not implement writeObject
-     */
-    static Method getPrivateWriteObjectMethod(Class<?> cl) {
-        try {
-            Method method = cl.getDeclaredMethod("writeObject", //$NON-NLS-1$
-                    WRITE_PARAM_TYPES);
-            if (Modifier.isPrivate(method.getModifiers())
-                    && method.getReturnType() == VOID_CLASS) {
-                return method;
-            }
-        } catch (NoSuchMethodException nsm) {
-            // Ignored
-        }
-        return null;
-    }
-
-    /**
      * Return true if instances of class {@code cl} are Externalizable,
      * false otherwise.
-     * 
+     *
      * @param cl
      *            a java.lang.Class which to test
      * @return {@code true} if instances of the class are Externalizable
      *         {@code false} if instances of the class are not
      *         Externalizable
-     * 
+     *
      * @see Object#hashCode
      */
     static boolean isExternalizable(Class<?> cl) {
@@ -865,7 +857,7 @@
      * <code>typecode<code> describes a primitive type
      *
      * @param typecode a char describing the typecode
-     * @return {@code true} if the typecode represents a primitive type 
+     * @return {@code true} if the typecode represents a primitive type
      * {@code false} if the typecode represents an Object type (including arrays)
      *
      * @see Object#hashCode
@@ -877,13 +869,13 @@
     /**
      * Return true if instances of class {@code cl} are Serializable,
      * false otherwise.
-     * 
+     *
      * @param cl
      *            a java.lang.Class which to test
      * @return {@code true} if instances of the class are Serializable
      *         {@code false} if instances of the class are not
      *         Serializable
-     * 
+     *
      * @see Object#hashCode
      */
     static boolean isSerializable(Class<?> cl) {
@@ -891,8 +883,65 @@
     }
 
     /**
+     * Resolves the class properties, if they weren't already
+     */
+    private void resolveProperties() {
+        if (arePropertiesResolved) {
+            return;
+        }
+
+        Class<?> cl = forClass();
+        isProxy = Proxy.isProxyClass(cl);
+        isEnum = Enum.class.isAssignableFrom(cl);
+        isSerializable = isSerializable(cl);
+        isExternalizable = isExternalizable(cl);
+
+        arePropertiesResolved = true;
+    }
+
+    /**
+     * Answers whether the class for this descriptor is serializable
+     *
+     * @return true if class implements Serializable
+     */
+    boolean isSerializable() {
+        resolveProperties();
+        return isSerializable;
+    }
+
+    /**
+     * Answers whether the class for this descriptor is serializable
+     *
+     * @return true if class implements Serializable
+     */
+    boolean isExternalizable() {
+        resolveProperties();
+        return isExternalizable;
+    }
+
+    /**
+     * Answers whether the class for this descriptor is proxied class
+     *
+     * @return true if class is proxied
+     */
+    boolean isProxy() {
+        resolveProperties();
+        return isProxy;
+    }
+
+    /**
+     * Answers whether the class for this descriptor is subclass of Enum
+     *
+     * @return true if class is subclass of Enum
+     */
+    boolean isEnum() {
+        resolveProperties();
+        return isEnum;
+    }
+
+    /**
      * Return a little endian long stored in a given position of the buffer
-     * 
+     *
      * @param buffer
      *            a byte array with the byte representation of the number
      * @param position
@@ -911,83 +960,67 @@
      * Returns the descriptor corresponding to the class {@code cl}. If the
      * class is not serializable or externalizable then {@code null} is
      * returned.
-     * 
+     *
      * @param cl
      *            a java.langClass for which to obtain the corresponding
      *            descriptor
      * @return the corresponding descriptor if the {@code cl} is serializable or
      *         externalizable; {@code null} otherwise.
-     * @since Android 1.0
      */
     public static ObjectStreamClass lookup(Class<?> cl) {
-        boolean serializable = isSerializable(cl);
-        boolean externalizable = isExternalizable(cl);
+        ObjectStreamClass osc = lookupStreamClass(cl);
 
-        // Has to be either Serializable or Externalizable
-        if (!serializable && !externalizable) {
-            return null;
+        if (osc.isSerializable() || osc.isExternalizable()) {
+            return osc;
         }
 
-        return lookupStreamClass(cl, true);
+        return null;
     }
 
     /**
      * Return the descriptor (ObjectStreamClass) corresponding to the class
      * {@code cl}. Returns an ObjectStreamClass even if instances of the
      * class cannot be serialized
-     * 
+     *
      * @param cl
      *            a java.langClass for which to obtain the corresponding
      *            descriptor
      * @return the corresponding descriptor
      */
     static ObjectStreamClass lookupStreamClass(Class<?> cl) {
-        return lookupStreamClass(cl, isSerializable(cl) || isExternalizable(cl));
-    }
 
-    /**
-     * Return the descriptor (ObjectStreamClass) corresponding to the class
-     * {@code cl}. Returns an ObjectStreamClass even if instances of the
-     * class cannot be serialized
-     * 
-     * @param cl
-     *            a {@code java.langClass} for which to obtain the
-     *            corresponding descriptor
-     * @param computeSUID
-     *            a boolean indicating if SUID should be computed or not.
-     * @return the corresponding descriptor
-     */
-    private static synchronized ObjectStreamClass lookupStreamClass(
-            Class<?> cl, boolean computeSUID) {
-        // Synchronized because of the lookup table 'classesAndDescriptors'
-        ObjectStreamClass cachedValue = classesAndDescriptors.get(cl);
-        if (cachedValue != null) {
-            return cachedValue;
+        WeakHashMap<Class<?>,ObjectStreamClass> tlc = OSCThreadLocalCache.oscWeakHashMap.get();
+
+        ObjectStreamClass cachedValue = tlc.get(cl);
+        if (cachedValue == null) {
+            cachedValue = createClassDesc(cl);
+            tlc.put(cl, cachedValue);
         }
-        return addToCache(cl, computeSUID);
+        return cachedValue;
+
     }
 
     /**
-     * Return the java.lang.reflect.Method {@code readResolve} if class
-     * {@code cl} implements it. Return null otherwise.
-     * 
+     * Return the java.lang.reflect.Method if class <code>cl</code> implements
+     * <code>methodName</code> . Return null otherwise.
+     *
      * @param cl
      *            a java.lang.Class which to test
-     * @return {@code java.lang.reflect.Method} if the class implements
-     *         readResolve {@code null} if the class does not implement
-     *         readResolve
+     * @return <code>java.lang.reflect.Method</code> if the class implements
+     *         writeReplace <code>null</code> if the class does not implement
+     *         writeReplace
      */
-    static Method methodReadResolve(Class<?> cl) {
+    static Method findMethod(Class<?> cl, String methodName) {
         Class<?> search = cl;
+        Method method = null;
         while (search != null) {
             try {
-                Method method = search.getDeclaredMethod(
-                        "readResolve", (Class[]) null); //$NON-NLS-1$
+                method = search.getDeclaredMethod(methodName, (Class[]) null);
                 if (search == cl
                         || (method.getModifiers() & Modifier.PRIVATE) == 0) {
+                    method.setAccessible(true);
                     return method;
                 }
-                return null;
             } catch (NoSuchMethodException nsm) {
             }
             search = search.getSuperclass();
@@ -996,37 +1029,81 @@
     }
 
     /**
-     * Return the java.lang.reflect.Method {@code writeReplace} if class
-     * {@code cl} implements it. Return null otherwise.
-     * 
+     * Return the java.lang.reflect.Method if class <code>cl</code> implements
+     * private <code>methodName</code> . Return null otherwise.
+     *
      * @param cl
      *            a java.lang.Class which to test
      * @return {@code java.lang.reflect.Method} if the class implements
      *         writeReplace {@code null} if the class does not implement
      *         writeReplace
      */
-    static Method methodWriteReplace(Class<?> cl) {
-        Class<?> search = cl;
-        while (search != null) {
-            try {
-                Method method = search.getDeclaredMethod(
-                        "writeReplace", (Class[]) null); //$NON-NLS-1$
-                if (search == cl
-                        || (method.getModifiers() & Modifier.PRIVATE) == 0) {
-                    return method;
-                }
-                return null;
-            } catch (NoSuchMethodException nsm) {
-                // Ignored
+    static Method findPrivateMethod(Class<?> cl, String methodName,
+            Class<?>[] param) {
+        try {
+            Method method = cl.getDeclaredMethod(methodName, param);
+            if (Modifier.isPrivate(method.getModifiers())
+                    && method.getReturnType() == VOID_CLASS) {
+                method.setAccessible(true);
+                return method;
             }
-            search = search.getSuperclass();
+        } catch (NoSuchMethodException nsm) {
+            // Ignored
         }
         return null;
     }
 
+    boolean hasMethodWriteReplace() {
+        return (methodWriteReplace != null);
+    }
+
+    Method getMethodWriteReplace() {
+        return methodWriteReplace;
+    }
+
+    boolean hasMethodReadResolve() {
+        return (methodReadResolve != null);
+    }
+
+    Method getMethodReadResolve() {
+        return methodReadResolve;
+    }
+
+    boolean hasMethodWriteObject() {
+        return (methodWriteObject != null);
+    }
+
+    Method getMethodWriteObject() {
+        return methodWriteObject;
+    }
+
+    boolean hasMethodReadObject() {
+        return (methodReadObject != null);
+    }
+
+    Method getMethodReadObject() {
+        return methodReadObject;
+    }
+
+    boolean hasMethodReadObjectNoData() {
+        return (methodReadObjectNoData != null);
+    }
+
+    Method getMethodReadObjectNoData() {
+        return methodReadObjectNoData;
+    }
+
+    void initPrivateFields(ObjectStreamClass desc) {
+        methodWriteReplace = desc.methodWriteReplace;
+        methodReadResolve = desc.methodReadResolve;
+        methodWriteObject = desc.methodWriteObject;
+        methodReadObject = desc.methodReadObject;
+        methodReadObjectNoData = desc.methodReadObjectNoData;
+    }
+
     /**
      * Set the class (java.lang.Class) that the receiver represents
-     * 
+     *
      * @param c
      *            aClass, the new class that the receiver describes
      */
@@ -1037,7 +1114,7 @@
     /**
      * Set the collection of field descriptors for the fields of the
      * corresponding class
-     * 
+     *
      * @param f
      *            ObjectStreamField[], the receiver's new collection of declared
      *            fields for the class it represents
@@ -1049,7 +1126,7 @@
     /**
      * Set the collection of field descriptors for the input fields of the
      * corresponding class
-     * 
+     *
      * @param f
      *            ObjectStreamField[], the receiver's new collection of input
      *            fields for the class it represents
@@ -1060,11 +1137,11 @@
 
     /**
      * Set the flags for this descriptor, where possible combined values are
-     * 
+     *
      * ObjectStreamConstants.SC_WRITE_METHOD
      * ObjectStreamConstants.SC_SERIALIZABLE
      * ObjectStreamConstants.SC_EXTERNALIZABLE
-     * 
+     *
      * @param b
      *            byte, the receiver's new flags for the class it represents
      */
@@ -1074,7 +1151,7 @@
 
     /**
      * Set the name of the class represented by the receiver
-     * 
+     *
      * @param newName
      *            a String, the new fully qualified name of the class the
      *            receiver represents
@@ -1085,7 +1162,7 @@
 
     /**
      * Set the Serial Version User ID of the class represented by the receiver
-     * 
+     *
      * @param l
      *            a long, the new SUID for the class represented by the receiver
      */
@@ -1096,7 +1173,7 @@
     /**
      * Set the descriptor for the superclass of the class described by the
      * receiver
-     * 
+     *
      * @param c
      *            an ObjectStreamClass, the new ObjectStreamClass for the
      *            superclass of the class represented by the receiver
@@ -1124,13 +1201,24 @@
     /**
      * Returns a string containing a concise, human-readable description of this
      * descriptor.
-     * 
+     *
      * @return a printable representation of this descriptor.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
         return getName() + ": static final long serialVersionUID =" //$NON-NLS-1$
                 + getSerialVersionUID() + "L;"; //$NON-NLS-1$
     }
+
+    static class OSCThreadLocalCache extends ThreadLocalCache {
+
+        // thread-local cache for ObjectStreamClass.lookup
+        public static ThreadLocalCache<WeakHashMap<Class<?>,ObjectStreamClass>> oscWeakHashMap = new ThreadLocalCache<WeakHashMap<Class<?>,ObjectStreamClass>>() {
+            protected WeakHashMap<Class<?>,ObjectStreamClass> initialValue() {
+                return new WeakHashMap<Class<?>,ObjectStreamClass>();
+            }
+        };
+
+    }
+
 }
diff --git a/libcore/luni/src/main/java/java/io/ObjectStreamConstants.java b/libcore/luni/src/main/java/java/io/ObjectStreamConstants.java
index 8f7ad66..01b0109 100644
--- a/libcore/luni/src/main/java/java/io/ObjectStreamConstants.java
+++ b/libcore/luni/src/main/java/java/io/ObjectStreamConstants.java
@@ -19,168 +19,122 @@
 
 /**
  * A helper interface with constants used by the serialization implementation.
- * 
- * @since Android 1.0
  */
 public abstract interface ObjectStreamConstants {
 
     /**
      * The stream header's magic number.
-     * 
-     * @since Android 1.0
      */
     public static final short STREAM_MAGIC = (short) 0xaced;
 
     /**
      * The stream header's version number.
-     * 
-     * @since Android 1.0
      */
     public static final short STREAM_VERSION = 5;
 
     // These are tags to indicate the stream contents
-    
+
     /**
      * The minimum tag value.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_BASE = 0x70;
 
     /**
      * Tag to mark a {@code null} object reference.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_NULL = (byte) 0x70;
 
     /**
      * Tag to mark a reference to an object that has already been written to the
      * stream.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_REFERENCE = (byte) 0x71;
 
     /**
      * Tag to mark a new class descriptor.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_CLASSDESC = (byte) 0x72;
 
     /**
      * Tag to mark a new object.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_OBJECT = (byte) 0x73;
 
     /**
      * Tag to mark a new string.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_STRING = (byte) 0x74;
 
     /**
      * Tag to mark a new array.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_ARRAY = (byte) 0x75;
 
     /**
      * Tag to mark a reference to a class.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_CLASS = (byte) 0x76;
 
     /**
      * Tag to mark a block of optional data. The byte following this tag
      * indicates the size of the block.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_BLOCKDATA = (byte) 0x77;
 
     /**
      * Tag to mark the end of block data blocks for an object.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_ENDBLOCKDATA = (byte) 0x78;
 
     /**
      * Tag to mark a stream reset.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_RESET = (byte) 0x79;
 
     /**
      * Tag to mark a long block of data. The long following this tag
      * indicates the size of the block.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_BLOCKDATALONG = (byte) 0x7A;
 
     /**
      * Tag to mark an exception.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_EXCEPTION = (byte) 0x7B;
 
     /**
      * Tag to mark a long string.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_LONGSTRING = (byte) 0x7C;
 
     /**
      * Tag to mark a new proxy class descriptor.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_PROXYCLASSDESC = (byte) 0x7D;
 
     /**
      * The maximum tag value.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_MAX = 0x7E;
 
     /**
      * Handle for the first object that gets serialized.
-     * 
-     * @since Android 1.0
      */
     public static final int baseWireHandle = 0x007e0000;
 
     /**
      * Stream protocol version 1.
-     * 
-     * @since Android 1.0
      */
     public static final int PROTOCOL_VERSION_1 = 1;
 
     /**
      * Stream protocol version 2.
-     * 
-     * @since Android 1.0
      */
     public static final int PROTOCOL_VERSION_2 = 2;
 
     /**
      * Permission constant to enable subclassing of ObjectInputStream and
      * ObjectOutputStream.
-     * 
-     * @since Android 1.0
      */
     public static final SerializablePermission SUBCLASS_IMPLEMENTATION_PERMISSION = new SerializablePermission(
             "enableSubclassImplementation"); //$NON-NLS-1$
@@ -188,8 +142,6 @@
     /**
      * Permission constant to enable object substitution during serialization
      * and deserialization.
-     * 
-     * @since Android 1.0
      */
     public static final SerializablePermission SUBSTITUTION_PERMISSION = new SerializablePermission(
             "enableSubstitution"); //$NON-NLS-1$
@@ -199,47 +151,35 @@
     /**
      * Bit mask for the {@code flag} field in ObjectStreamClass. Indicates
      * that a serializable class has its own {@code writeObject} method.
-     * 
-     * @since Android 1.0
      */
     public static final byte SC_WRITE_METHOD = 0x01; // If SC_SERIALIZABLE
 
     /**
      * Bit mask for the {@code flag} field in ObjectStreamClass. Indicates
      * that a class is serializable.
-     * 
-     * @since Android 1.0
      */
     public static final byte SC_SERIALIZABLE = 0x02;
 
     /**
      * Bit mask for the {@code flag} field in ObjectStreamClass. Indicates
      * that a class is externalizable.
-     * 
-     * @since Android 1.0
      */
     public static final byte SC_EXTERNALIZABLE = 0x04;
 
     /**
      * Bit mask for the {@code flag} field in ObjectStreamClass. Indicates
      * that an externalizable class is written in block data mode.
-     * 
-     * @since Android 1.0
      */
     public static final byte SC_BLOCK_DATA = 0x08; // If SC_EXTERNALIZABLE
 
     /**
      * Tag to mark a new enum.
-     * 
-     * @since Android 1.0
      */
     public static final byte TC_ENUM = 0x7E;
 
     /**
      * Bit mask for the {@code flag} field in ObjectStreamClass. Indicates
      * that a class is an enum type.
-     * 
-     * @since Android 1.0
      */
     public static final byte SC_ENUM = 0x10;
 }
diff --git a/libcore/luni/src/main/java/java/io/ObjectStreamException.java b/libcore/luni/src/main/java/java/io/ObjectStreamException.java
index a06b102..c3ad7dc 100644
--- a/libcore/luni/src/main/java/java/io/ObjectStreamException.java
+++ b/libcore/luni/src/main/java/java/io/ObjectStreamException.java
@@ -28,8 +28,6 @@
  * @see OptionalDataException
  * @see StreamCorruptedException
  * @see WriteAbortedException
- * 
- * @since Android 1.0
  */
 public abstract class ObjectStreamException extends IOException {
 
@@ -38,8 +36,6 @@
     /**
      * Constructs a new {@code ObjectStreamException} with its stack trace
      * filled in.
-     * 
-     * @since Android 1.0
      */
     protected ObjectStreamException() {
         super();
@@ -51,7 +47,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     protected ObjectStreamException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/io/ObjectStreamField.java b/libcore/luni/src/main/java/java/io/ObjectStreamField.java
index 95deb7b..3baebf7 100644
--- a/libcore/luni/src/main/java/java/io/ObjectStreamField.java
+++ b/libcore/luni/src/main/java/java/io/ObjectStreamField.java
@@ -17,22 +17,32 @@
 
 package java.io;
 
+// BEGIN android-note
+// Harmony uses ObjectAccessors to access fields through JNI. Android has not
+// yet migrated that API.
+// END android-note
+
 import java.lang.ref.WeakReference;
 import java.util.Arrays;
 import java.util.Comparator;
 
+// BEGIN android-removed
+// import org.apache.harmony.misc.accessors.ObjectAccessor;
+// END android-removed
+
 /**
  * Describes a field for the purpose of serialization. Classes can define the
  * collection of fields that are serialized, which may be different from the set
  * of all declared fields.
- * 
+ *
  * @see ObjectOutputStream#writeFields()
  * @see ObjectInputStream#readFields()
- * 
- * @since Android 1.0
  */
 public class ObjectStreamField implements Comparable<Object> {
 
+    static final int FIELD_IS_NOT_RESOLVED = -1;
+    static final int FIELD_IS_ABSENT = -2;
+
     // Declared name of the field
     private String name;
 
@@ -49,16 +59,32 @@
 
     private boolean isDeserialized;
 
+    private long assocFieldID = FIELD_IS_NOT_RESOLVED;
+
+    // BEGIN android-removed
+    // long getFieldID(ObjectAccessor accessor, Class<?> declaringClass) {
+    //     if (assocFieldID != FIELD_IS_NOT_RESOLVED) {
+    //         return assocFieldID;
+    //     } else {
+    //         try {
+    //             assocFieldID = accessor.getFieldID(declaringClass, name);
+    //         } catch(NoSuchFieldError e) {
+    //             assocFieldID = FIELD_IS_ABSENT;
+    //         }
+    //         return assocFieldID;
+    //     }
+    // }
+    // END android-removed
+
     /**
      * Constructs an ObjectStreamField with the specified name and type.
-     * 
+     *
      * @param name
      *            the name of the field.
      * @param cl
      *            the type of the field.
      * @throws NullPointerException
      *             if {@code name} or {@code cl} is {@code null}.
-     * @since Android 1.0
      */
     public ObjectStreamField(String name, Class<?> cl) {
         if (name == null || cl == null) {
@@ -71,7 +97,7 @@
     /**
      * Constructs an ObjectStreamField with the specified name, type and the
      * indication if it is unshared.
-     * 
+     *
      * @param name
      *            the name of the field.
      * @param cl
@@ -82,7 +108,6 @@
      * @throws NullPointerException
      *             if {@code name} or {@code cl} is {@code null}.
      * @see ObjectOutputStream#writeUnshared(Object)
-     * @since Android 1.0
      */
     public ObjectStreamField(String name, Class<?> cl, boolean unshared) {
         if (name == null || cl == null) {
@@ -97,7 +122,7 @@
     /**
      * Constructs an ObjectStreamField with the given name and the given type.
      * The type may be null.
-     * 
+     *
      * @param signature
      *            A String representing the type of the field
      * @param name
@@ -117,13 +142,12 @@
      * of the compared fields has a primitive type and the other one not. If so,
      * the field with the primitive type is considered to be "smaller". If both
      * fields are equal, their names are compared.
-     * 
+     *
      * @param o
      *            the object to compare with.
      * @return -1 if this field is "smaller" than field {@code o}, 0 if both
      *         fields are equal; 1 if this field is "greater" than field {@code
      *         o}.
-     * @since Android 1.0
      */
     public int compareTo(Object o) {
         ObjectStreamField f = (ObjectStreamField) o;
@@ -139,34 +163,14 @@
         // Either both primitives or both not primitives. Compare based on name.
         return this.getName().compareTo(f.getName());
     }
-    
+
     // BEGIN android-removed
     // There shouldn't be an implementation of these methods.
-    // /**
-    //  * Indicates if this field descriptor is equal to {@code arg0}. Field
-    //  * descriptors are equal if their name is equal.
-    //  * 
-    //  * @param arg0
-    //  *            the object to check equality with.
-    //  * @return {@code true} if the name of this field descriptor is equal to the
-    //  *         name of {@code arg0}, {@code false} otherwise.
-    //  * @since Android 1.0
-    //  */
     // @Override
     // public boolean equals(Object arg0) {
-    //     // BEGIN android-changed
-    //     // copied from newer harmony version
-    //     return (arg0 instanceof ObjectStreamField) && compareTo(arg0) == 0;
-    //     // END android-changed
+    //     return (arg0 instanceof ObjectStreamField) && (compareTo(arg0) == 0);
     // }
-    // 
-    // /**
-    //  * Returns a hash code for this field descriptor. The hash code of this
-    //  * field's name is returned.
-    //  * 
-    //  * @return the field's hash code.
-    //  * @since Android 1.0
-    //  */
+    //
     // @Override
     // public int hashCode() {
     //     return getName().hashCode();
@@ -175,9 +179,8 @@
 
     /**
      * Gets the name of this field.
-     * 
+     *
      * @return the field's name.
-     * @since Android 1.0
      */
     public String getName() {
         return name;
@@ -185,9 +188,8 @@
 
     /**
      * Gets the offset of this field in the object.
-     * 
+     *
      * @return this field's offset.
-     * @since Android 1.0
      */
     public int getOffset() {
         return offset;
@@ -196,7 +198,7 @@
     /**
      * Return the type of the field the receiver represents, this is an internal
      * method
-     * 
+     *
      * @return A Class object representing the type of the field
      */
     // BEGIN android-note
@@ -211,9 +213,8 @@
 
     /**
      * Gets the type of this field.
-     * 
+     *
      * @return a {@code Class} object representing the type of the field.
-     * @since Android 1.0
      */
     public Class<?> getType() {
         Class<?> cl = getTypeInternal();
@@ -226,7 +227,7 @@
     /**
      * Gets a character code for the type of this field. The following codes are
      * used:
-     * 
+     *
      * <pre>
      * B     byte
      * C     char
@@ -239,9 +240,8 @@
      * Z     boolean
      * [     array
      * </pre>
-     * 
+     *
      * @return the field's type code.
-     * @since Android 1.0
      */
     public char getTypeCode() {
         Class<?> t = getTypeInternal();
@@ -278,10 +278,9 @@
     /**
      * Gets the type signature used by the VM to represent the type of this
      * field.
-     * 
+     *
      * @return the signature of this field's class or {@code null} if this
      *         field's type is primitive.
-     * @since Android 1.0
      */
     public String getTypeString() {
         if (isPrimitive()) {
@@ -298,10 +297,9 @@
 
     /**
      * Indicates whether this field's type is a primitive type.
-     * 
+     *
      * @return {@code true} if this field's type is primitive; {@code false} if
      *         the type of this field is a regular class.
-     * @since Android 1.0
      */
     public boolean isPrimitive() {
         Class<?> t = getTypeInternal();
@@ -310,10 +308,9 @@
 
     /**
      * Sets this field's offset in the object.
-     * 
+     *
      * @param newValue
      *            the field's new offset.
-     * @since Android 1.0
      */
     protected void setOffset(int newValue) {
         this.offset = newValue;
@@ -322,9 +319,8 @@
     /**
      * Returns a string containing a concise, human-readable description of this
      * field descriptor.
-     * 
+     *
      * @return a printable representation of this descriptor.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -335,7 +331,7 @@
     /**
      * Sorts the fields for dumping. Primitive types come first, then regular
      * types.
-     * 
+     *
      * @param fields
      *            ObjectStreamField[] fields to be sorted
      */
@@ -396,9 +392,8 @@
 
     /**
      * Indicats whether this field is unshared.
-     * 
+     *
      * @return {@code true} if this field is unshared, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isUnshared() {
         return unshared;
diff --git a/libcore/luni/src/main/java/java/io/OptionalDataException.java b/libcore/luni/src/main/java/java/io/OptionalDataException.java
index 891bfdd..39d3d5d 100644
--- a/libcore/luni/src/main/java/java/io/OptionalDataException.java
+++ b/libcore/luni/src/main/java/java/io/OptionalDataException.java
@@ -25,8 +25,6 @@
  * @see ObjectInputStream#available()
  * @see ObjectInputStream#readObject()
  * @see ObjectInputStream#skipBytes(int)
- * 
- * @since Android 1.0
  */
 public class OptionalDataException extends ObjectStreamException {
 
@@ -34,24 +32,18 @@
 
     /**
      * {@code true} indicates that there is no more primitive data available.
-     * 
-     * @since Android 1.0
      */
     public boolean eof;
 
     /**
      * The number of bytes of primitive data (int, char, long etc.) that are
      * available.
-     * 
-     * @since Android 1.0
      */
     public int length;
 
     /**
      * Constructs a new {@code OptionalDataException} with its stack trace
      * filled in.
-     * 
-     * @since Android 1.0
      */
     OptionalDataException() {
         super();
@@ -63,7 +55,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     OptionalDataException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/io/OutputStream.java b/libcore/luni/src/main/java/java/io/OutputStream.java
index 5531ab5..2172411 100644
--- a/libcore/luni/src/main/java/java/io/OutputStream.java
+++ b/libcore/luni/src/main/java/java/io/OutputStream.java
@@ -32,17 +32,13 @@
  * <p>
  * Many specialized output streams for purposes like writing to a file already
  * exist in this package.
- * 
+ *
  * @see InputStream
- * 
- * @since Android 1.0
  */
 public abstract class OutputStream implements Closeable, Flushable {
 
     /**
      * Default constructor.
-     * 
-     * @since Android 1.0
      */
     public OutputStream() {
         super();
@@ -51,10 +47,9 @@
     /**
      * Closes this stream. Implementations of this method should free any
      * resources used by the stream. This implementation does nothing.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this stream.
-     * @since Android 1.0
      */
     public void close() throws IOException {
         /* empty */
@@ -63,10 +58,9 @@
     /**
      * Flushes this stream. Implementations of this method should ensure that
      * any buffered data is written out. This implementation does nothing.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while flushing this stream.
-     * @since Android 1.0
      */
     public void flush() throws IOException {
         /* empty */
@@ -75,12 +69,11 @@
     /**
      * Writes the entire contents of the byte array {@code buffer} to this
      * stream.
-     * 
+     *
      * @param buffer
      *            the buffer to be written.
      * @throws IOException
      *             if an error occurs while writing to this stream.
-     * @since Android 1.0
      */
     public void write(byte[] buffer) throws IOException {
         // BEGIN android-note
@@ -92,7 +85,7 @@
     /**
      * Writes {@code count} bytes from the byte array {@code buffer} starting at
      * position {@code offset} to this stream.
-     * 
+     *
      * @param buffer
      *            the buffer to be written.
      * @param offset
@@ -106,7 +99,6 @@
      *             if {@code offset < 0} or {@code count < 0}, or if
      *             {@code offset + count} is bigger than the length of
      *             {@code buffer}.
-     * @since Android 1.0
      */
     public void write(byte[] buffer, int offset, int count) throws IOException {
         // BEGIN android-note
@@ -134,12 +126,11 @@
     /**
      * Writes a single byte to this stream. Only the least significant byte of
      * the integer {@code oneByte} is written to the stream.
-     * 
+     *
      * @param oneByte
      *            the byte to be written.
      * @throws IOException
      *             if an error occurs while writing to this stream.
-     * @since Android 1.0
      */
     public abstract void write(int oneByte) throws IOException;
 }
diff --git a/libcore/luni/src/main/java/java/io/OutputStreamWriter.java b/libcore/luni/src/main/java/java/io/OutputStreamWriter.java
index d6cc91e..6e6cc50 100644
--- a/libcore/luni/src/main/java/java/io/OutputStreamWriter.java
+++ b/libcore/luni/src/main/java/java/io/OutputStreamWriter.java
@@ -25,6 +25,7 @@
 import java.nio.charset.CodingErrorAction;
 import java.security.AccessController;
 
+import org.apache.harmony.luni.util.HistoricalNamesUtil;
 import org.apache.harmony.luni.util.Msg;
 import org.apache.harmony.luni.util.PriviAction;
 
@@ -35,10 +36,8 @@
  * "file.encoding" system property. {@code OutputStreamWriter} contains a buffer
  * of bytes to be written to target stream and converts these into characters as
  * needed. The buffer size is 8K.
- * 
+ *
  * @see InputStreamReader
- * 
- * @since Android 1.0
  */
 public class OutputStreamWriter extends Writer {
 
@@ -52,10 +51,9 @@
      * Constructs a new OutputStreamWriter using {@code out} as the target
      * stream to write converted characters to. The default character encoding
      * is used.
-     * 
+     *
      * @param out
      *            the non-null target stream to write converted bytes to.
-     * @since Android 1.0
      */
     public OutputStreamWriter(OutputStream out) {
         super(out);
@@ -73,7 +71,7 @@
      * stream to write converted characters to and {@code enc} as the character
      * encoding. If the encoding cannot be found, an
      * UnsupportedEncodingException error is thrown.
-     * 
+     *
      * @param out
      *            the target stream to write converted bytes to.
      * @param enc
@@ -82,7 +80,6 @@
      *             if {@code enc} is {@code null}.
      * @throws UnsupportedEncodingException
      *             if the encoding specified by {@code enc} cannot be found.
-     * @since Android 1.0
      */
     public OutputStreamWriter(OutputStream out, final String enc)
             throws UnsupportedEncodingException {
@@ -104,12 +101,11 @@
      * Constructs a new OutputStreamWriter using {@code out} as the target
      * stream to write converted characters to and {@code cs} as the character
      * encoding.
-     * 
+     *
      * @param out
      *            the target stream to write converted bytes to.
      * @param cs
      *            the {@code Charset} that specifies the character encoding.
-     * @since Android 1.0
      */
     public OutputStreamWriter(OutputStream out, Charset cs) {
         super(out);
@@ -123,12 +119,11 @@
      * Constructs a new OutputStreamWriter using {@code out} as the target
      * stream to write converted characters to and {@code enc} as the character
      * encoder.
-     * 
+     *
      * @param out
      *            the target stream to write converted bytes to.
      * @param enc
      *            the character encoder used for character conversion.
-     * @since Android 1.0
      */
     public OutputStreamWriter(OutputStream out, CharsetEncoder enc) {
         super(out);
@@ -144,11 +139,9 @@
      * <p>
      * Only the first invocation of this method has any effect. Subsequent calls
      * do nothing.
-     * </p>
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this writer.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -168,10 +161,9 @@
      * Flushes this writer. This implementation ensures that all buffered bytes
      * are written to the target stream. After writing the bytes, the target
      * stream is flushed as well.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while flushing this writer.
-     * @since Android 1.0
      */
     @Override
     public void flush() throws IOException {
@@ -197,17 +189,15 @@
     /**
      * Gets the name of the encoding that is used to convert characters to
      * bytes.
-     * 
+     *
      * @return the string describing the converter or {@code null} if this
      *         writer is closed.
-     * @since Android 1.0
      */
     public String getEncoding() {
         if (encoder == null) {
             return null;
         }
-        return InputStreamReader.HistoricalNamesUtil.getHistoricalName(encoder
-                .charset().name());
+        return HistoricalNamesUtil.getHistoricalName(encoder.charset().name());
     }
 
     /**
@@ -215,7 +205,7 @@
      * to this writer. The characters are immediately converted to bytes by the
      * character converter and stored in a local buffer. If the buffer gets full
      * as a result of the conversion, this writer is flushed.
-     * 
+     *
      * @param buf
      *            the array containing characters to write.
      * @param offset
@@ -229,7 +219,6 @@
      * @throws IOException
      *             if this writer has already been closed or another I/O error
      *             occurs.
-     * @since Android 1.0
      */
     @Override
     public void write(char[] buf, int offset, int count) throws IOException {
@@ -273,12 +262,11 @@
      * of the integer {@code oneChar} are immediately converted to bytes by the
      * character converter and stored in a local buffer. If the buffer gets full
      * by converting this character, this writer is flushed.
-     * 
+     *
      * @param oneChar
      *            the character to write.
      * @throws IOException
      *             if this writer is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public void write(int oneChar) throws IOException {
@@ -294,7 +282,7 @@
      * to this writer. The characters are immediately converted to bytes by the
      * character converter and stored in a local buffer. If the buffer gets full
      * as a result of the conversion, this writer is flushed.
-     * 
+     *
      * @param str
      *            the string containing characters to write.
      * @param offset
@@ -308,7 +296,6 @@
      *             if {@code offset < 0} or {@code count < 0}, or if
      *             {@code offset + count} is bigger than the length of
      *             {@code str}.
-     * @since Android 1.0
      */
     @Override
     public void write(String str, int offset, int count) throws IOException {
diff --git a/libcore/luni/src/main/java/java/io/PipedInputStream.java b/libcore/luni/src/main/java/java/io/PipedInputStream.java
index 5562c58..a6b0336 100644
--- a/libcore/luni/src/main/java/java/io/PipedInputStream.java
+++ b/libcore/luni/src/main/java/java/io/PipedInputStream.java
@@ -23,10 +23,8 @@
  * Receives information from a communications pipe. When two threads want to
  * pass data back and forth, one creates a piped output stream and the other one
  * creates a piped input stream.
- * 
+ *
  * @see PipedOutputStream
- * 
- * @since Android 1.0
  */
 public class PipedInputStream extends InputStream {
 
@@ -35,30 +33,37 @@
     private boolean isClosed = false;
 
     /**
-     * The circular buffer through which data is passed.
-     * 
-     * @since Android 1.0
+     * The circular buffer through which data is passed. Data is read from the
+     * range {@code [out, in)} and written to the range {@code [in, out)}.
+     * Data in the buffer is either sequential: <pre>
+     *     { - - - X X X X X X X - - - - - }
+     *             ^             ^
+     *             |             |
+     *            out           in</pre>
+     * ...or wrapped around the buffer's end: <pre>
+     *     { X X X X - - - - - - - - X X X }
+     *               ^               ^
+     *               |               |
+     *              in              out</pre>
+     * When the buffer is empty, {@code in == -1}. Reading when the buffer is
+     * empty will block until data is available. When the buffer is full,
+     * {@code in == out}. Writing when the buffer is full will block until free
+     * space is available.
      */
     protected byte buffer[];
 
     /**
      * The index in {@code buffer} where the next byte will be written.
-     * 
-     * @since Android 1.0
      */
     protected int in = -1;
 
     /**
      * The index in {@code buffer} where the next byte will be read.
-     * 
-     * @since Android 1.0
      */
     protected int out = 0;
 
     /**
      * The size of the default pipe in bytes.
-     * 
-     * @since Android 1.0
      */
     protected static final int PIPE_SIZE = 1024;
 
@@ -71,8 +76,6 @@
      * Constructs a new unconnected {@code PipedInputStream}. The resulting
      * stream must be connected to a {@link PipedOutputStream} before data may
      * be read from it.
-     * 
-     * @since Android 1.0
      */
     public PipedInputStream() {
         /* empty */
@@ -82,12 +85,11 @@
      * Constructs a new {@code PipedInputStream} connected to the
      * {@link PipedOutputStream} {@code out}. Any data written to the output
      * stream can be read from the this input stream.
-     * 
+     *
      * @param out
      *            the piped output stream to connect to.
      * @throws IOException
      *             if this stream or {@code out} are already connected.
-     * @since Android 1.0
      */
     public PipedInputStream(PipedOutputStream out) throws IOException {
         connect(out);
@@ -97,11 +99,10 @@
      * Returns the number of bytes that are available before this stream will
      * block. This implementation returns the number of bytes written to this
      * pipe that have not been read yet.
-     * 
+     *
      * @return the number of bytes available before blocking.
      * @throws IOException
      *             if an error occurs in this stream.
-     * @since Android 1.0
      */
     @Override
     public synchronized int available() throws IOException {
@@ -114,10 +115,9 @@
     /**
      * Closes this stream. This implementation releases the buffer used for the
      * pipe and notifies all threads waiting to read or write.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this stream.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -134,12 +134,11 @@
      * Connects this {@code PipedInputStream} to a {@link PipedOutputStream}.
      * Any data written to the output stream becomes readable in this input
      * stream.
-     * 
+     *
      * @param src
      *            the source output stream.
      * @throws IOException
      *             if either stream is already connected.
-     * @since Android 1.0
      */
     public void connect(PipedOutputStream src) throws IOException {
         src.connect(this);
@@ -155,24 +154,33 @@
      * Separate threads should be used to read from a {@code PipedInputStream}
      * and to write to the connected {@link PipedOutputStream}. If the same
      * thread is used, a deadlock may occur.
-     * </p>
-     * 
+     *
      * @return the byte read or -1 if the end of the source stream has been
      *         reached.
      * @throws IOException
      *             if this stream is closed or not connected to an output
      *             stream, or if the thread writing to the connected output
      *             stream is no longer alive.
-     * @since Android 1.0
      */
     @Override
     public synchronized int read() throws IOException {
         if (!isConnected) {
+            // K0074=Not connected
             throw new IOException(Msg.getString("K0074")); //$NON-NLS-1$
         }
         if (buffer == null) {
+            // K0075=InputStream is closed
             throw new IOException(Msg.getString("K0075")); //$NON-NLS-1$
         }
+
+        // BEGIN android-removed
+        // eagerly throwing prevents checking isClosed and returning normally
+        // if (lastWriter != null && !lastWriter.isAlive() && (in < 0)) {
+        //     // KA030=Write end dead
+        //     throw new IOException(Msg.getString("KA030")); //$NON-NLS-1$
+        // }
+        // END android-removed
+
         /**
          * Set the last thread to be reading on this PipedInputStream. If
          * lastReader dies while someone is waiting to write an IOException of
@@ -180,16 +188,16 @@
          */
         lastReader = Thread.currentThread();
         try {
-            boolean first = true;
+            int attempts = 3;
             while (in == -1) {
                 // Are we at end of stream?
                 if (isClosed) {
                     return -1;
                 }
-                if (!first && lastWriter != null && !lastWriter.isAlive()) {
+                if ((attempts-- <= 0) && lastWriter != null && !lastWriter.isAlive()) {
+                    // K0076=Pipe broken
                     throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
                 }
-                first = false;
                 // Notify callers of receive()
                 notifyAll();
                 wait(1000);
@@ -198,7 +206,8 @@
             throw new InterruptedIOException();
         }
 
-        byte result = buffer[out++];
+        // BEGIN android-changed
+        int result = buffer[out++] & 0xff;
         if (out == buffer.length) {
             out = 0;
         }
@@ -207,7 +216,12 @@
             in = -1;
             out = 0;
         }
-        return result & 0xff;
+
+        // let blocked writers write to the newly available buffer space
+        notifyAll();
+
+        return result;
+        // END android-changed
     }
 
     /**
@@ -219,8 +233,7 @@
      * Separate threads should be used to read from a {@code PipedInputStream}
      * and to write to the connected {@link PipedOutputStream}. If the same
      * thread is used, a deadlock may occur.
-     * </p>
-     * 
+     *
      * @param bytes
      *            the array in which to store the bytes read.
      * @param offset
@@ -264,13 +277,23 @@
         }
 
         if (!isConnected) {
+            // K0074=Not connected
             throw new IOException(Msg.getString("K0074")); //$NON-NLS-1$
         }
 
         if (buffer == null) {
+            // K0075=InputStream is closed
             throw new IOException(Msg.getString("K0075")); //$NON-NLS-1$
         }
 
+        // BEGIN android-removed
+        // eagerly throwing prevents checking isClosed and returning normally
+        // if (lastWriter != null && !lastWriter.isAlive() && (in < 0)) {
+        //     // KA030=Write end dead
+        //     throw new IOException(Msg.getString("KA030")); //$NON-NLS-1$
+        // }
+        // END android-removed
+
         /**
          * Set the last thread to be reading on this PipedInputStream. If
          * lastReader dies while someone is waiting to write an IOException of
@@ -278,16 +301,16 @@
          */
         lastReader = Thread.currentThread();
         try {
-            boolean first = true;
+            int attempts = 3;
             while (in == -1) {
                 // Are we at end of stream?
                 if (isClosed) {
                     return -1;
                 }
-                if (!first && lastWriter != null && !lastWriter.isAlive()) {
+                if ((attempts-- <= 0) && lastWriter != null && !lastWriter.isAlive()) {
+                    // K0076=Pipe broken
                     throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
                 }
-                first = false;
                 // Notify callers of receive()
                 notifyAll();
                 wait(1000);
@@ -296,13 +319,15 @@
             throw new InterruptedIOException();
         }
 
-        int copyLength = 0;
-        /* Copy bytes from out to end of buffer first */
+        // BEGIN android-changed
+        int totalCopied = 0;
+
+        // copy bytes from out thru the end of buffer
         if (out >= in) {
-            copyLength = count > (buffer.length - out) ? buffer.length - out
-                    : count;
-            System.arraycopy(buffer, out, bytes, offset, copyLength);
-            out += copyLength;
+            int leftInBuffer = buffer.length - out;
+            int length = leftInBuffer < count ? leftInBuffer : count;
+            System.arraycopy(buffer, out, bytes, offset, length);
+            out += length;
             if (out == buffer.length) {
                 out = 0;
             }
@@ -311,28 +336,29 @@
                 in = -1;
                 out = 0;
             }
+            totalCopied += length;
         }
 
-        /*
-         * Did the read fully succeed in the previous copy or is the buffer
-         * empty?
-         */
-        if (copyLength == count || in == -1) {
-            return copyLength;
+        // copy bytes from out thru in
+        if (totalCopied < count && in != -1) {
+            int leftInBuffer = in - out;
+            int leftToCopy = count - totalCopied;
+            int length = leftToCopy < leftInBuffer ? leftToCopy : leftInBuffer;
+            System.arraycopy(buffer, out, bytes, offset + totalCopied, length);
+            out += length;
+            if (out == in) {
+                // empty buffer
+                in = -1;
+                out = 0;
+            }
+            totalCopied += length;
         }
 
-        int bytesCopied = copyLength;
-        /* Copy bytes from 0 to the number of available bytes */
-        copyLength = in - out > (count - bytesCopied) ? count - bytesCopied
-                : in - out;
-        System.arraycopy(buffer, out, bytes, offset + bytesCopied, copyLength);
-        out += copyLength;
-        if (out == in) {
-            // empty buffer
-            in = -1;
-            out = 0;
-        }
-        return bytesCopied + copyLength;
+        // let blocked writers write to the newly available buffer space
+        notifyAll();
+
+        return totalCopied;
+        // END android-changed
     }
 
     /**
@@ -342,8 +368,7 @@
      * {@code in} in the {@code buffer}.
      * <p>
      * This method blocks as long as {@code buffer} is full.
-     * </p>
-     * 
+     *
      * @param oneByte
      *            the byte to store in this pipe.
      * @throws InterruptedIOException
@@ -357,9 +382,12 @@
         if (buffer == null || isClosed) {
             throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
         }
-        if (lastReader != null && !lastReader.isAlive()) {
-            throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
-        }
+        // BEGIN android-removed
+        // eagerly throwing causes us to fail even if the buffer's not full
+        // if (lastReader != null && !lastReader.isAlive()) {
+        //     throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
+        // }
+        // END android-removed
         /**
          * Set the last thread to be writing on this PipedInputStream. If
          * lastWriter dies while someone is waiting to read an IOException of
@@ -368,11 +396,14 @@
         lastWriter = Thread.currentThread();
         try {
             while (buffer != null && out == in) {
-                notifyAll();
-                wait(1000);
+                // BEGIN android-changed
+                // moved has-last-reader-died check to be before wait()
                 if (lastReader != null && !lastReader.isAlive()) {
                     throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
                 }
+                notifyAll();
+                wait(1000);
+                // END android-changed
             }
         } catch (InterruptedException e) {
             throw new InterruptedIOException();
@@ -385,7 +416,11 @@
             if (in == buffer.length) {
                 in = 0;
             }
-            return;
+
+            // BEGIN android-added
+            // let blocked readers read the newly available data
+            notifyAll();
+            // END android-added
         }
     }
 
diff --git a/libcore/luni/src/main/java/java/io/PipedOutputStream.java b/libcore/luni/src/main/java/java/io/PipedOutputStream.java
index 3041f70..15ee930 100644
--- a/libcore/luni/src/main/java/java/io/PipedOutputStream.java
+++ b/libcore/luni/src/main/java/java/io/PipedOutputStream.java
@@ -23,10 +23,8 @@
  * Places information on a communications pipe. When two threads want to pass
  * data back and forth, one creates a piped output stream and the other one
  * creates a piped input stream.
- * 
+ *
  * @see PipedInputStream
- * 
- * @since Android 1.0
  */
 public class PipedOutputStream extends OutputStream {
 
@@ -39,8 +37,6 @@
      * Constructs a new unconnected {@code PipedOutputStream}. The resulting
      * stream must be connected to a {@link PipedInputStream} before data can be
      * written to it.
-     * 
-     * @since Android 1.0
      */
     public PipedOutputStream() {
         super();
@@ -50,12 +46,11 @@
      * Constructs a new {@code PipedOutputStream} connected to the
      * {@link PipedInputStream} {@code dest}. Any data written to this stream
      * can be read from the target stream.
-     * 
+     *
      * @param dest
      *            the piped input stream to connect to.
      * @throws IOException
      *             if this stream or {@code dest} are already connected.
-     * @since Android 1.0
      */
     public PipedOutputStream(PipedInputStream dest) throws IOException {
         super();
@@ -65,10 +60,9 @@
     /**
      * Closes this stream. If this stream is connected to an input stream, the
      * input stream is closed and the pipe is disconnected.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this stream.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -82,12 +76,11 @@
     /**
      * Connects this stream to a {@link PipedInputStream}. Any data written to
      * this output stream becomes readable in the input stream.
-     * 
+     *
      * @param stream
      *            the destination input stream.
      * @throws IOException
      *             if either stream is already connected.
-     * @since Android 1.0
      */
     public void connect(PipedInputStream stream) throws IOException {
         if (null == stream) {
@@ -109,10 +102,9 @@
     /**
      * Notifies the readers of this {@link PipedInputStream} that bytes can be
      * read. This method does nothing if this stream is not connected.
-     * 
+     *
      * @throws IOException
      *             if an I/O error occurs while flushing this stream.
-     * @since Android 1.0
      */
     @Override
     public void flush() throws IOException {
@@ -131,8 +123,7 @@
      * Separate threads should be used to write to a {@code PipedOutputStream}
      * and to read from the connected {@link PipedInputStream}. If the same
      * thread is used, a deadlock may occur.
-     * </p>
-     * 
+     *
      * @param buffer
      *            the buffer to write.
      * @param offset
@@ -151,7 +142,6 @@
      *             if this stream is not connected, if the target stream is
      *             closed or if the thread reading from the target stream is no
      *             longer alive. This case is currently not handled correctly.
-     * @since Android 1.0
      */
     @Override
     public void write(byte[] buffer, int offset, int count) throws IOException {
@@ -173,8 +163,7 @@
      * Separate threads should be used to write to a {@code PipedOutputStream}
      * and to read from the connected {@link PipedInputStream}. If the same
      * thread is used, a deadlock may occur.
-     * </p>
-     * 
+     *
      * @param oneByte
      *            the byte to write.
      * @throws InterruptedIOException
@@ -185,7 +174,6 @@
      *             if this stream is not connected, if the target stream is
      *             closed or if the thread reading from the target stream is no
      *             longer alive. This case is currently not handled correctly.
-     * @since Android 1.0
      */
     @Override
     public void write(int oneByte) throws IOException {
diff --git a/libcore/luni/src/main/java/java/io/PipedReader.java b/libcore/luni/src/main/java/java/io/PipedReader.java
index a0af9a5..251ac90 100644
--- a/libcore/luni/src/main/java/java/io/PipedReader.java
+++ b/libcore/luni/src/main/java/java/io/PipedReader.java
@@ -23,10 +23,8 @@
  * Receives information on a communications pipe. When two threads want to pass
  * data back and forth, one creates a piped writer and the other creates a piped
  * reader.
- * 
+ *
  * @see PipedWriter
- * 
- * @since Android 1.0
  */
 public class PipedReader extends Reader {
 
@@ -66,9 +64,8 @@
      * Constructs a new unconnected {@code PipedReader}. The resulting reader
      * must be connected to a {@code PipedWriter} before data may be read from
      * it.
-     * 
+     *
      * @see PipedWriter
-     * @since Android 1.0
      */
     public PipedReader() {
         data = new char[PIPE_SIZE];
@@ -78,12 +75,11 @@
      * Constructs a new {@code PipedReader} connected to the {@link PipedWriter}
      * {@code out}. Any data written to the writer can be read from the this
      * reader.
-     * 
+     *
      * @param out
      *            the {@code PipedWriter} to connect to.
      * @throws IOException
      *             if {@code out} is already connected.
-     * @since Android 1.0
      */
     public PipedReader(PipedWriter out) throws IOException {
         this();
@@ -93,10 +89,9 @@
     /**
      * Closes this reader. This implementation releases the buffer used for
      * the pipe and notifies all threads waiting to read or write.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this reader.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -112,13 +107,12 @@
     /**
      * Connects this {@code PipedReader} to a {@link PipedWriter}. Any data
      * written to the writer becomes readable in this reader.
-     * 
+     *
      * @param src
      *            the writer to connect to.
      * @throws IOException
      *             if this reader is closed or already connected, or if {@code
      *             src} is already connected.
-     * @since Android 1.0
      */
     public void connect(PipedWriter src) throws IOException {
         synchronized (lock) {
@@ -128,7 +122,7 @@
 
     /**
      * Establishes the connection to the PipedWriter.
-     * 
+     *
      * @throws IOException
      *             If this Reader is already connected.
      */
@@ -154,13 +148,11 @@
      * Separate threads should be used to read from a {@code PipedReader} and to
      * write to the connected {@link PipedWriter}. If the same thread is used,
      * a deadlock may occur.
-     * </p>
-     * 
+     *
      * @return the character read or -1 if the end of the reader has been
      *         reached.
      * @throws IOException
      *             if this reader is closed or some other I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public int read() throws IOException {
@@ -179,8 +171,7 @@
      * Separate threads should be used to read from a {@code PipedReader} and to
      * write to the connected {@link PipedWriter}. If the same thread is used, a
      * deadlock may occur.
-     * </p>
-     * 
+     *
      * @param buffer
      *            the character array in which to store the characters read.
      * @param offset
@@ -298,14 +289,13 @@
      * called, {@code false} if unknown or blocking will occur. This
      * implementation returns {@code true} if the internal buffer contains
      * characters that can be read.
-     * 
+     *
      * @return always {@code false}.
      * @throws IOException
      *             if this reader is closed or not connected, or if some other
      *             I/O error occurs.
      * @see #read()
      * @see #read(char[], int, int)
-     * @since Android 1.0
      */
     @Override
     public boolean ready() throws IOException {
@@ -326,10 +316,10 @@
      * <P>
      * If the buffer is full and the thread sending #receive is interrupted, the
      * InterruptedIOException will be thrown.
-     * 
+     *
      * @param oneChar
      *            the char to store into the pipe.
-     * 
+     *
      * @throws IOException
      *             If the stream is already closed or another IOException
      *             occurs.
@@ -380,14 +370,14 @@
      * <P>
      * If the buffer is full and the thread sending #receive is interrupted, the
      * InterruptedIOException will be thrown.
-     * 
+     *
      * @param chars
      *            the char array to store into the pipe.
      * @param offset
      *            offset to start reading from
      * @param count
      *            total characters to read
-     * 
+     *
      * @throws IOException
      *             If the stream is already closed or another IOException
      *             occurs.
diff --git a/libcore/luni/src/main/java/java/io/PipedWriter.java b/libcore/luni/src/main/java/java/io/PipedWriter.java
index 98a73c9..5fc968d 100644
--- a/libcore/luni/src/main/java/java/io/PipedWriter.java
+++ b/libcore/luni/src/main/java/java/io/PipedWriter.java
@@ -23,10 +23,8 @@
  * Places information on a communications pipe. When two threads want to pass
  * data back and forth, one creates a piped writer and the other creates a piped
  * reader.
- * 
+ *
  * @see PipedReader
- * 
- * @since Android 1.0
  */
 public class PipedWriter extends Writer {
     /**
@@ -40,9 +38,8 @@
      * Constructs a new unconnected {@code PipedWriter}. The resulting writer
      * must be connected to a {@code PipedReader} before data may be written to
      * it.
-     * 
+     *
      * @see PipedReader
-     * @since Android 1.0
      */
     public PipedWriter() {
         super();
@@ -52,12 +49,11 @@
      * Constructs a new {@code PipedWriter} connected to the {@link PipedReader}
      * {@code dest}. Any data written to this writer can be read from {@code
      * dest}.
-     * 
+     *
      * @param dest
      *            the {@code PipedReader} to connect to.
      * @throws IOException
      *             if {@code dest} is already connected.
-     * @since Android 1.0
      */
     public PipedWriter(PipedReader dest) throws IOException {
         super(dest);
@@ -68,10 +64,9 @@
      * Closes this writer. If a {@link PipedReader} is connected to this writer,
      * it is closed as well and the pipe is disconnected. Any data buffered in
      * the reader can still be read.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this writer.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -88,13 +83,12 @@
     /**
      * Connects this {@code PipedWriter} to a {@link PipedReader}. Any data
      * written to this writer becomes readable in the reader.
-     * 
+     *
      * @param stream
      *            the reader to connect to.
      * @throws IOException
      *             if this writer is closed or already connected, or if {@code
      *             stream} is already connected.
-     * @since Android 1.0
      */
     public void connect(PipedReader stream) throws IOException {
         synchronized (lock) {
@@ -112,10 +106,9 @@
     /**
      * Notifies the readers of this {@code PipedReader} that characters can be read. This
      * method does nothing if this Writer is not connected.
-     * 
+     *
      * @throws IOException
      *             if an I/O error occurs while flushing this writer.
-     * @since Android 1.0
      */
     @Override
     public void flush() throws IOException {
@@ -132,8 +125,7 @@
      * Separate threads should be used to write to a {@code PipedWriter} and to
      * read from the connected {@code PipedReader}. If the same thread is used,
      * a deadlock may occur.
-     * </p>
-     * 
+     *
      * @param buffer
      *            the buffer to write.
      * @param offset
@@ -155,7 +147,6 @@
      *             correctly.
      * @throws NullPointerException
      *             if {@code buffer} is {@code null}.
-     * @since Android 1.0
      */
     @Override
     public void write(char[] buffer, int offset, int count) throws IOException {
@@ -194,8 +185,7 @@
      * Separate threads should be used to write to a {@code PipedWriter} and to
      * read from the connected {@code PipedReader}. If the same thread is used,
      * a deadlock may occur.
-     * </p>
-     * 
+     *
      * @param c
      *            the character to write.
      * @throws InterruptedIOException
@@ -207,7 +197,6 @@
      *             reader is closed or if the thread reading from the target
      *             reader is no longer alive. This case is currently not handled
      *             correctly.
-     * @since Android 1.0
      */
     @Override
     public void write(int c) throws IOException {
diff --git a/libcore/luni/src/main/java/java/io/PrintStream.java b/libcore/luni/src/main/java/java/io/PrintStream.java
index 0aae645..29d460e 100644
--- a/libcore/luni/src/main/java/java/io/PrintStream.java
+++ b/libcore/luni/src/main/java/java/io/PrintStream.java
@@ -18,6 +18,7 @@
 package java.io;
 
 import java.nio.charset.Charset;
+import java.nio.charset.IllegalCharsetNameException;
 import java.security.AccessController;
 import java.util.Formatter;
 import java.util.IllegalFormatException;
@@ -33,8 +34,6 @@
  * so that they can be read back in. No {@code IOException} is thrown by this
  * class. Instead, callers should use {@link #checkError()} to see if a problem
  * has occurred in this stream.
- * 
- * @since Android 1.0
  */
 public class PrintStream extends FilterOutputStream implements Appendable,
         Closeable {
@@ -63,12 +62,11 @@
      * Constructs a new {@code PrintStream} with {@code out} as its target
      * stream. By default, the new print stream does not automatically flush its
      * contents to the target stream when a newline is encountered.
-     * 
+     *
      * @param out
      *            the target output stream.
      * @throws NullPointerException
      *             if {@code out} is {@code null}.
-     * @since Android 1.0
      */
     public PrintStream(OutputStream out) {
         super(out);
@@ -82,7 +80,7 @@
      * stream. The parameter {@code autoflush} determines if the print stream
      * automatically flushes its contents to the target stream when a newline is
      * encountered.
-     * 
+     *
      * @param out
      *            the target output stream.
      * @param autoflush
@@ -90,7 +88,6 @@
      *            newline sequence.
      * @throws NullPointerException
      *             if {@code out} is {@code null}.
-     * @since Android 1.0
      */
     public PrintStream(OutputStream out, boolean autoflush) {
         super(out);
@@ -105,7 +102,7 @@
      * stream and using the character encoding {@code enc} while writing. The
      * parameter {@code autoflush} determines if the print stream automatically
      * flushes its contents to the target stream when a newline is encountered.
-     * 
+     *
      * @param out
      *            the target output stream.
      * @param autoflush
@@ -117,7 +114,6 @@
      *             if {@code out} or {@code enc} are {@code null}.
      * @throws UnsupportedEncodingException
      *             if the encoding specified by {@code enc} is not supported.
-     * @since Android 1.0
      */
     public PrintStream(OutputStream out, boolean autoflush, String enc)
             throws UnsupportedEncodingException {
@@ -126,7 +122,11 @@
             throw new NullPointerException();
         }
         this.autoflush = autoflush;
-        if (!Charset.isSupported(enc)) {
+        try {
+            if (!Charset.isSupported(enc)) {
+                throw new UnsupportedEncodingException(enc);
+            }
+        } catch (IllegalCharsetNameException e) {
             throw new UnsupportedEncodingException(enc);
         }
         encoding = enc;
@@ -135,7 +135,7 @@
     /**
      * Constructs a new {@code PrintStream} with {@code file} as its target. The
      * virtual machine's default character set is used for character encoding.
-     * 
+     *
      * @param file
      *            the target file. If the file already exists, its contents are
      *            removed, otherwise a new file is created.
@@ -144,7 +144,6 @@
      * @throws SecurityException
      *             if a security manager exists and it denies writing to the
      *             target file.
-     * @since Android 1.0
      */
     public PrintStream(File file) throws FileNotFoundException {
         super(new FileOutputStream(file));
@@ -153,7 +152,7 @@
     /**
      * Constructs a new {@code PrintStream} with {@code file} as its target. The
      * character set named {@code csn} is used for character encoding.
-     * 
+     *
      * @param file
      *            the target file. If the file already exists, its contents are
      *            removed, otherwise a new file is created.
@@ -168,7 +167,6 @@
      *             target file.
      * @throws UnsupportedEncodingException
      *             if the encoding specified by {@code csn} is not supported.
-     * @since Android 1.0
      */
     public PrintStream(File file, String csn) throws FileNotFoundException,
             UnsupportedEncodingException {
@@ -186,7 +184,7 @@
      * Constructs a new {@code PrintStream} with the file identified by
      * {@code fileName} as its target. The virtual machine's default character
      * set is used for character encoding.
-     * 
+     *
      * @param fileName
      *            the target file's name. If the file already exists, its
      *            contents are removed, otherwise a new file is created.
@@ -195,7 +193,6 @@
      * @throws SecurityException
      *             if a security manager exists and it denies writing to the
      *             target file.
-     * @since Android 1.0
      */
     public PrintStream(String fileName) throws FileNotFoundException {
         this(new File(fileName));
@@ -205,7 +202,7 @@
      * Constructs a new {@code PrintStream} with the file identified by
      * {@code fileName} as its target. The character set named {@code csn} is
      * used for character encoding.
-     * 
+     *
      * @param fileName
      *            the target file's name. If the file already exists, its
      *            contents are removed, otherwise a new file is created.
@@ -220,7 +217,6 @@
      *             target file.
      * @throws UnsupportedEncodingException
      *             if the encoding specified by {@code csn} is not supported.
-     * @since Android 1.0
      */
     public PrintStream(String fileName, String csn)
             throws FileNotFoundException, UnsupportedEncodingException {
@@ -229,12 +225,11 @@
 
     /**
      * Flushes this stream and returns the value of the error flag.
-     * 
+     *
      * @return {@code true} if either an {@code IOException} has been thrown
      *         previously or if {@code setError()} has been called;
      *         {@code false} otherwise.
-     * @see #setError()         
-     * @since Android 1.0
+     * @see #setError()
      */
     public boolean checkError() {
         if (out != null) {
@@ -247,8 +242,6 @@
      * Closes this print stream. Flushes this stream and then closes the target
      * stream. If an I/O error occurs, this stream's error state is set to
      * {@code true}.
-     * 
-     * @since Android 1.0
      */
     @Override
     public synchronized void close() {
@@ -267,8 +260,6 @@
      * Ensures that all pending data is sent out to the target stream. It also
      * flushes the target stream. If an I/O error occurs, this stream's error
      * state is set to {@code true}.
-     * 
-     * @since Android 1.0
      */
     @Override
     public synchronized void flush() {
@@ -288,7 +279,7 @@
      * target stream using the specified format string and arguments. For the
      * locale, the default value of the current virtual machine instance is
      * used.
-     * 
+     *
      * @param format
      *            the format string used for {@link java.util.Formatter#format}.
      * @param args
@@ -302,7 +293,6 @@
      *             error regarding the format string or arguments is detected.
      * @throws NullPointerException
      *             if {@code format} is {@code null}.
-     * @since Android 1.0
      */
     public PrintStream format(String format, Object... args) {
         return format(Locale.getDefault(), format, args);
@@ -311,7 +301,7 @@
     /**
      * Writes a string formatted by an intermediate {@link Formatter} to this
      * stream using the specified locale, format string and arguments.
-     * 
+     *
      * @param l
      *            the locale used in the method. No localization will be applied
      *            if {@code l} is {@code null}.
@@ -328,7 +318,6 @@
      *             error regarding the format string or arguments is detected.
      * @throws NullPointerException
      *             if {@code format} is {@code null}.
-     * @since Android 1.0
      */
     public PrintStream format(Locale l, String format, Object... args) {
         if (format == null) {
@@ -342,7 +331,7 @@
      * Prints a formatted string. The behavior of this method is the same as
      * this stream's {@code #format(String, Object...)} method. For the locale,
      * the default value of the current virtual machine instance is used.
-     * 
+     *
      * @param format
      *            the format string used for
      *            {@link java.util.Formatter#format}.
@@ -357,7 +346,6 @@
      *             error regarding the format string or arguments is detected.
      * @throws NullPointerException
      *             if {@code format} is {@code null}.
-     * @since Android 1.0
      */
     public PrintStream printf(String format, Object... args) {
         return format(format, args);
@@ -366,7 +354,7 @@
     /**
      * Prints a formatted string. The behavior of this method is the same as
      * this stream's {@code #format(Locale, String, Object...)} method.
-     * 
+     *
      * @param l
      *            the locale used in the method. No localization will be applied
      *            if {@code l} is {@code null}.
@@ -383,7 +371,6 @@
      *             error regarding the format string or arguments is detected.
      * @throws NullPointerException
      *             if {@code format} is {@code null}.
-     * @since Android 1.0
      */
     public PrintStream printf(Locale l, String format, Object... args) {
         return format(l, format, args);
@@ -399,11 +386,10 @@
     /**
      * Prints the string representation of the specified character array
      * to the target stream.
-     * 
+     *
      * @param charArray
      *            the character array to print to the target stream.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void print(char[] charArray) {
         print(new String(charArray, 0, charArray.length));
@@ -412,11 +398,10 @@
     /**
      * Prints the string representation of the specified character to the target
      * stream.
-     * 
+     *
      * @param ch
      *            the character to print to the target stream.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void print(char ch) {
         print(String.valueOf(ch));
@@ -425,11 +410,10 @@
     /**
      * Prints the string representation of the specified double to the target
      * stream.
-     * 
+     *
      * @param dnum
      *            the double value to print to the target stream.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void print(double dnum) {
         print(String.valueOf(dnum));
@@ -438,12 +422,11 @@
     /**
      * Prints the string representation of the specified float to the target
      * stream.
-     * 
+     *
      * @param fnum
      *            the float value to print to the target stream.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void print(float fnum) {
         print(String.valueOf(fnum));
     }
@@ -451,12 +434,11 @@
     /**
      * Prints the string representation of the specified integer to the target
      * stream.
-     * 
+     *
      * @param inum
      *            the integer value to print to the target stream.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void print(int inum) {
         print(String.valueOf(inum));
     }
@@ -464,12 +446,11 @@
     /**
      * Prints the string representation of the specified long to the target
      * stream.
-     * 
+     *
      * @param lnum
      *            the long value to print to the target stream.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void print(long lnum) {
         print(String.valueOf(lnum));
     }
@@ -477,12 +458,11 @@
     /**
      * Prints the string representation of the specified object to the target
      * stream.
-     * 
+     *
      * @param obj
      *            the object to print to the target stream.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void print(Object obj) {
         print(String.valueOf(obj));
     }
@@ -494,12 +474,10 @@
      * {@code write(int)}.
      * <p>
      * If an I/O error occurs, this stream's error state is set to {@code true}.
-     * </p>
-     * 
+     *
      * @param str
      *            the string to print to the target stream.
      * @see #write(int)
-     * @since Android 1.0
      */
     public synchronized void print(String str) {
         if (out == null) {
@@ -525,12 +503,11 @@
     /**
      * Prints the string representation of the specified boolean to the target
      * stream.
-     * 
+     *
      * @param bool
      *            the boolean value to print the target stream.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void print(boolean bool) {
         print(String.valueOf(bool));
     }
@@ -538,8 +515,6 @@
     /**
      * Prints the string representation of the system property
      * {@code "line.separator"} to the target stream.
-     * 
-     * @since Android 1.0
      */
     public void println() {
         newline();
@@ -549,11 +524,10 @@
      * Prints the string representation of the specified character array
      * followed by the system property {@code "line.separator"} to the target
      * stream.
-     * 
+     *
      * @param charArray
      *            the character array to print to the target stream.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void println(char[] charArray) {
         println(new String(charArray, 0, charArray.length));
@@ -562,11 +536,10 @@
     /**
      * Prints the string representation of the specified character followed by
      * the system property {@code "line.separator"} to the target stream.
-     * 
+     *
      * @param ch
      *            the character to print to the target stream.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void println(char ch) {
         println(String.valueOf(ch));
@@ -575,11 +548,10 @@
     /**
      * Prints the string representation of the specified double followed by the
      * system property {@code "line.separator"} to the target stream.
-     * 
+     *
      * @param dnum
      *            the double value to print to the target stream.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void println(double dnum) {
         println(String.valueOf(dnum));
@@ -588,12 +560,11 @@
     /**
      * Prints the string representation of the specified float followed by the
      * system property {@code "line.separator"} to the target stream.
-     * 
+     *
      * @param fnum
      *            the float value to print to the target stream.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
    public void println(float fnum) {
         println(String.valueOf(fnum));
     }
@@ -601,12 +572,12 @@
    /**
      * Prints the string representation of the specified integer followed by the
      * system property {@code "line.separator"} to the target stream.
-     * 
+     *
      * @param inum
      *            the integer value to print to the target stream.
      * @see #print(String)
      * @since Android 1.0
-     */   
+     */
     public void println(int inum) {
         println(String.valueOf(inum));
     }
@@ -614,12 +585,12 @@
     /**
      * Prints the string representation of the specified long followed by the
      * system property {@code "line.separator"} to the target stream.
-     * 
+     *
      * @param lnum
      *            the long value to print to the target stream.
      * @see #print(String)
      * @since Android 1.0
-     */   
+     */
     public void println(long lnum) {
         println(String.valueOf(lnum));
     }
@@ -627,12 +598,12 @@
     /**
      * Prints the string representation of the specified object followed by the
      * system property {@code "line.separator"} to the target stream.
-     * 
+     *
      * @param obj
      *            the object to print to the target stream.
      * @see #print(String)
      * @since Android 1.0
-     */   
+     */
     public void println(Object obj) {
         println(String.valueOf(obj));
     }
@@ -645,7 +616,7 @@
      * <p>
      * If an I/O error occurs, this stream's error state is set to {@code true}.
      * </p>
-     * 
+     *
      * @param str
      *            the string to print to the target stream.
      * @see #write(int)
@@ -659,20 +630,17 @@
     /**
      * Prints the string representation of the specified boolean followed by the
      * system property {@code "line.separator"} to the target stream.
-     * 
+     *
      * @param bool
      *            the boolean value to print to the target stream.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void println(boolean bool) {
         println(String.valueOf(bool));
     }
 
     /**
      * Sets the error flag of this print stream to {@code true}.
-     * 
-     * @since Android 1.0
      */
     protected void setError() {
         ioError = true;
@@ -685,8 +653,7 @@
      * <p>
      * This stream's error flag is set to {@code true} if this stream is closed
      * or an I/O error occurs.
-     * </p>
-     * 
+     *
      * @param buffer
      *            the buffer to be written.
      * @param offset
@@ -697,7 +664,6 @@
      *             if {@code offset < 0} or {@code count < 0}, or if {@code
      *             offset + count} is bigger than the length of {@code buffer}.
      * @see #flush()
-     * @since Android 1.0
      */
     @Override
     public void write(byte[] buffer, int offset, int count) {
@@ -738,11 +704,9 @@
      * <p>
      * This stream's error flag is set to {@code true} if it is closed or an I/O
      * error occurs.
-     * </p>
-     * 
+     *
      * @param oneByte
      *            the byte to be written
-     * @since Android 1.0
      */
     @Override
     public synchronized void write(int oneByte) {
@@ -763,11 +727,10 @@
     /**
      * Appends the character {@code c} to the target stream. This method works
      * the same way as {@link #print(char)}.
-     * 
+     *
      * @param c
      *            the character to append to the target stream.
      * @return this stream.
-     * @since Android 1.0
      */
     public PrintStream append(char c) {
         print(c);
@@ -779,11 +742,10 @@
      * method works the same way as {@code PrintStream.print(csq.toString())}.
      * If {@code csq} is {@code null}, then the string "null" is written to the
      * target stream.
-     * 
+     *
      * @param csq
      *            the character sequence appended to the target stream.
      * @return this stream.
-     * @since Android 1.0
      */
     public PrintStream append(CharSequence csq) {
         if (null == csq) {
@@ -800,7 +762,7 @@
      * PrintStream.print(csq.subsequence(start, end).toString())}. If {@code
      * csq} is {@code null}, then the specified subsequence of the string "null"
      * will be written to the target stream.
-     * 
+     *
      * @param csq
      *            the character sequence appended to the target stream.
      * @param start
@@ -814,7 +776,6 @@
      *             if {@code start > end}, {@code start < 0}, {@code end < 0} or
      *             either {@code start} or {@code end} are greater or equal than
      *             the length of {@code csq}.
-     * @since Android 1.0
      */
     public PrintStream append(CharSequence csq, int start, int end) {
         if (null == csq) {
diff --git a/libcore/luni/src/main/java/java/io/PrintWriter.java b/libcore/luni/src/main/java/java/io/PrintWriter.java
index 0c5189d..f87707d 100644
--- a/libcore/luni/src/main/java/java/io/PrintWriter.java
+++ b/libcore/luni/src/main/java/java/io/PrintWriter.java
@@ -25,24 +25,16 @@
 import org.apache.harmony.luni.util.Msg;
 import org.apache.harmony.luni.util.PriviAction;
 
-// BEGIN android-note
-// added @return comment to #printf(Locale l, String format, Object... args)
-// END android-note
-
 /**
  * Wraps either an existing {@link OutputStream} or an existing {@link Writer}
  * and provides convenience methods for printing common data types in a human
  * readable format. No {@code IOException} is thrown by this class. Instead,
  * callers should use {@link #checkError()} to see if a problem has occurred in
  * this writer.
- * 
- * @since Android 1.0
  */
 public class PrintWriter extends Writer {
     /**
      * The writer to print data to.
-     * 
-     * @since Android 1.0
      */
     protected Writer out;
 
@@ -64,12 +56,11 @@
      * Constructs a new {@code PrintWriter} with {@code out} as its target
      * stream. By default, the new print writer does not automatically flush its
      * contents to the target stream when a newline is encountered.
-     * 
+     *
      * @param out
      *            the target output stream.
      * @throws NullPointerException
      *             if {@code out} is {@code null}.
-     * @since Android 1.0
      */
     public PrintWriter(OutputStream out) {
         this(new OutputStreamWriter(out), false);
@@ -80,7 +71,7 @@
      * stream. The parameter {@code autoflush} determines if the print writer
      * automatically flushes its contents to the target stream when a newline is
      * encountered.
-     * 
+     *
      * @param out
      *            the target output stream.
      * @param autoflush
@@ -88,7 +79,6 @@
      *            newline sequence.
      * @throws NullPointerException
      *             if {@code out} is {@code null}.
-     * @since Android 1.0
      */
     public PrintWriter(OutputStream out, boolean autoflush) {
         this(new OutputStreamWriter(out), autoflush);
@@ -98,12 +88,11 @@
      * Constructs a new {@code PrintWriter} with {@code wr} as its target
      * writer. By default, the new print writer does not automatically flush its
      * contents to the target writer when a newline is encountered.
-     * 
+     *
      * @param wr
      *            the target writer.
      * @throws NullPointerException
      *             if {@code wr} is {@code null}.
-     * @since Android 1.0
      */
     public PrintWriter(Writer wr) {
         this(wr, false);
@@ -114,7 +103,7 @@
      * writer. The parameter {@code autoflush} determines if the print writer
      * automatically flushes its contents to the target writer when a newline is
      * encountered.
-     * 
+     *
      * @param wr
      *            the target writer.
      * @param autoflush
@@ -122,7 +111,6 @@
      *            newline sequence.
      * @throws NullPointerException
      *             if {@code out} is {@code null}.
-     * @since Android 1.0
      */
     public PrintWriter(Writer wr, boolean autoflush) {
         super(wr);
@@ -135,7 +123,7 @@
      * virtual machine's default character set is used for character encoding.
      * The print writer does not automatically flush its contents to the target
      * file when a newline is encountered. The output to the file is buffered.
-     * 
+     *
      * @param file
      *            the target file. If the file already exists, its contents are
      *            removed, otherwise a new file is created.
@@ -144,7 +132,6 @@
      * @throws SecurityException
      *             if a security manager exists and it denies writing to the
      *             target file.
-     * @since Android 1.0
      */
     public PrintWriter(File file) throws FileNotFoundException {
         // BEGIN android-modified
@@ -160,7 +147,7 @@
      * character set named {@code csn} is used for character encoding.
      * The print writer does not automatically flush its contents to the target
      * file when a newline is encountered. The output to the file is buffered.
-     * 
+     *
      * @param file
      *            the target file. If the file already exists, its contents are
      *            removed, otherwise a new file is created.
@@ -175,7 +162,6 @@
      *             target file.
      * @throws UnsupportedEncodingException
      *             if the encoding specified by {@code csn} is not supported.
-     * @since Android 1.0
      */
     public PrintWriter(File file, String csn) throws FileNotFoundException,
             UnsupportedEncodingException {
@@ -193,7 +179,7 @@
      * used for character encoding. The print writer does not automatically
      * flush its contents to the target file when a newline is encountered. The
      * output to the file is buffered.
-     * 
+     *
      * @param fileName
      *            the target file's name. If the file already exists, its
      *            contents are removed, otherwise a new file is created.
@@ -202,7 +188,6 @@
      * @throws SecurityException
      *             if a security manager exists and it denies writing to the
      *             target file.
-     * @since Android 1.0
      */
     public PrintWriter(String fileName) throws FileNotFoundException {
         // BEGIN android-modified
@@ -219,7 +204,7 @@
      * character encoding. The print writer does not automatically flush its
      * contents to the target file when a newline is encountered. The output to
      * the file is buffered.
-     * 
+     *
      * @param fileName
      *            the target file's name. If the file already exists, its
      *            contents are removed, otherwise a new file is created.
@@ -234,7 +219,6 @@
      *             target file.
      * @throws UnsupportedEncodingException
      *             if the encoding specified by {@code csn} is not supported.
-     * @since Android 1.0
      */
     public PrintWriter(String fileName, String csn)
             throws FileNotFoundException, UnsupportedEncodingException {
@@ -248,12 +232,11 @@
 
     /**
      * Flushes this writer and returns the value of the error flag.
-     * 
+     *
      * @return {@code true} if either an {@code IOException} has been thrown
      *         previously or if {@code setError()} has been called;
      *         {@code false} otherwise.
-     * @see #setError()         
-     * @since Android 1.0
+     * @see #setError()
      */
     public boolean checkError() {
         if (out != null) {
@@ -265,8 +248,6 @@
     /**
      * Closes this print writer. Flushes this writer and then closes the target.
      * If an I/O error occurs, this writer's error flag is set to {@code true}.
-     * 
-     * @since Android 1.0
      */
     @Override
     public void close() {
@@ -286,8 +267,6 @@
      * Ensures that all pending data is sent out to the target. It also
      * flushes the target. If an I/O error occurs, this writer's error
      * state is set to {@code true}.
-     * 
-     * @since Android 1.0
      */
     @Override
     public void flush() {
@@ -309,7 +288,7 @@
      * target using the specified format string and arguments. For the locale,
      * the default value of the current virtual machine instance is used. If
      * automatic flushing is enabled then the buffer is flushed as well.
-     * 
+     *
      * @param format
      *            the format string used for {@link java.util.Formatter#format}.
      * @param args
@@ -323,7 +302,6 @@
      *             error regarding the format string or arguments is detected.
      * @throws NullPointerException
      *             if {@code format} is {@code null}.
-     * @since Android 1.0
      */
     public PrintWriter format(String format, Object... args) {
         return format(Locale.getDefault(), format, args);
@@ -333,7 +311,7 @@
      * Writes a string formatted by an intermediate {@code Formatter} to the
      * target using the specified locale, format string and arguments. If
      * automatic flushing is enabled then this writer is flushed.
-     * 
+     *
      * @param l
      *            the locale used in the method. No localization will be applied
      *            if {@code l} is {@code null}.
@@ -350,7 +328,6 @@
      *             error regarding the format string or arguments is detected.
      * @throws NullPointerException
      *             if {@code format} is {@code null}.
-     * @since Android 1.0
      */
     public PrintWriter format(Locale l, String format, Object... args) {
         if (format == null) {
@@ -367,7 +344,7 @@
      * Prints a formatted string. The behavior of this method is the same as
      * this writer's {@code #format(String, Object...)} method. For the locale,
      * the default value of the current virtual machine instance is used.
-     * 
+     *
      * @param format
      *            the format string used for {@link java.util.Formatter#format}.
      * @param args
@@ -381,7 +358,6 @@
      *             error regarding the format string or arguments is detected.
      * @throws NullPointerException
      *             if {@code format} is {@code null}.
-     * @since Android 1.0
      */
     public PrintWriter printf(String format, Object... args) {
         return format(format, args);
@@ -390,7 +366,7 @@
     /**
      * Prints a formatted string. The behavior of this method is the same as
      * this writer's {@code #format(Locale, String, Object...)} method.
-     * 
+     *
      * @param l
      *            the locale used in the method. No localization will be applied
      *            if {@code l} is {@code null}.
@@ -407,7 +383,6 @@
      *             error regarding the format string or arguments is detected.
      * @throws NullPointerException
      *             if {@code format} is {@code null}.
-     * @since Android 1.0
      */
     public PrintWriter printf(Locale l, String format, Object... args) {
         return format(l, format, args);
@@ -426,11 +401,10 @@
     /**
      * Prints the string representation of the specified character array
      * to the target.
-     * 
+     *
      * @param charArray
      *            the character array to print to the target.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void print(char[] charArray) {
         print(new String(charArray, 0, charArray.length));
@@ -439,11 +413,10 @@
     /**
      * Prints the string representation of the specified character to the
      * target.
-     * 
+     *
      * @param ch
      *            the character to print to the target.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void print(char ch) {
         print(String.valueOf(ch));
@@ -451,23 +424,21 @@
 
     /**
      * Prints the string representation of the specified double to the target.
-     * 
+     *
      * @param dnum
      *            the double value to print to the target.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void print(double dnum) {
         print(String.valueOf(dnum));
     }
 
-   /**
+    /**
      * Prints the string representation of the specified float to the target.
-     * 
+     *
      * @param fnum
      *            the float value to print to the target.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void print(float fnum) {
         print(String.valueOf(fnum));
@@ -475,23 +446,21 @@
 
     /**
      * Prints the string representation of the specified integer to the target.
-     * 
+     *
      * @param inum
      *            the integer value to print to the target.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void print(int inum) {
         print(String.valueOf(inum));
     }
 
     /**
      * Prints the string representation of the specified long to the target.
-     * 
+     *
      * @param lnum
      *            the long value to print to the target.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void print(long lnum) {
         print(String.valueOf(lnum));
@@ -499,12 +468,11 @@
 
     /**
      * Prints the string representation of the specified object to the target.
-     * 
+     *
      * @param obj
      *            the object to print to the target.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void print(Object obj) {
         print(String.valueOf(obj));
     }
@@ -515,12 +483,10 @@
      * The bytes are then written to the target with {@code write(int)}.
      * <p>
      * If an I/O error occurs, this writer's error flag is set to {@code true}.
-     * </p>
-     * 
+     *
      * @param str
      *            the string to print to the target.
      * @see #write(int)
-     * @since Android 1.0
      */
     public void print(String str) {
         write(str != null ? str : String.valueOf((Object) null));
@@ -528,12 +494,11 @@
 
     /**
      * Prints the string representation of the specified boolean to the target.
-     * 
+     *
      * @param bool
      *            the boolean value to print the target.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void print(boolean bool) {
         print(String.valueOf(bool));
     }
@@ -542,8 +507,6 @@
      * Prints the string representation of the system property {@code
      * "line.separator"} to the target. Flushes this writer if the autoflush
      * flag is set to {@code true}.
-     * 
-     * @since Android 1.0
      */
     public void println() {
         synchronized (lock) {
@@ -555,11 +518,10 @@
      * Prints the string representation of the specified character array
      * followed by the system property {@code "line.separator"} to the target.
      * Flushes this writer if the autoflush flag is set to {@code true}.
-     * 
+     *
      * @param charArray
      *            the character array to print to the target.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void println(char[] charArray) {
         println(new String(charArray, 0, charArray.length));
@@ -569,11 +531,10 @@
      * Prints the string representation of the specified character followed by
      * the system property {@code "line.separator"} to the target. Flushes this
      * writer if the autoflush flag is set to {@code true}.
-     * 
+     *
      * @param ch
      *            the character to print to the target.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void println(char ch) {
         println(String.valueOf(ch));
@@ -583,11 +544,10 @@
      * Prints the string representation of the specified double followed by the
      * system property {@code "line.separator"} to the target. Flushes this
      * writer if the autoflush flag is set to {@code true}.
-     * 
+     *
      * @param dnum
      *            the double value to print to the target.
      * @see #print(String)
-     * @since Android 1.0
      */
     public void println(double dnum) {
         println(String.valueOf(dnum));
@@ -597,12 +557,11 @@
      * Prints the string representation of the specified float followed by the
      * system property {@code "line.separator"} to the target. Flushes this
      * writer if the autoflush flag is set to {@code true}.
-     * 
+     *
      * @param fnum
      *            the float value to print to the target.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void println(float fnum) {
         println(String.valueOf(fnum));
     }
@@ -611,12 +570,11 @@
      * Prints the string representation of the specified integer followed by the
      * system property {@code "line.separator"} to the target. Flushes this
      * writer if the autoflush flag is set to {@code true}.
-     * 
+     *
      * @param inum
      *            the integer value to print to the target.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void println(int inum) {
         println(String.valueOf(inum));
     }
@@ -625,12 +583,11 @@
      * Prints the string representation of the specified long followed by the
      * system property {@code "line.separator"} to the target. Flushes this
      * writer if the autoflush flag is set to {@code true}.
-     * 
+     *
      * @param lnum
      *            the long value to print to the target.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void println(long lnum) {
         println(String.valueOf(lnum));
     }
@@ -639,12 +596,11 @@
      * Prints the string representation of the specified object followed by the
      * system property {@code "line.separator"} to the target. Flushes this
      * writer if the autoflush flag is set to {@code true}.
-     * 
+     *
      * @param obj
      *            the object to print to the target.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void println(Object obj) {
         println(String.valueOf(obj));
     }
@@ -657,12 +613,10 @@
      * is flushed if the autoflush flag is set to {@code true}.
      * <p>
      * If an I/O error occurs, this writer's error flag is set to {@code true}.
-     * </p>
-     * 
+     *
      * @param str
      *            the string to print to the target.
      * @see #write(int)
-     * @since Android 1.0
      */
     public void println(String str) {
         synchronized (lock) {
@@ -675,20 +629,17 @@
      * Prints the string representation of the specified boolean followed by the
      * system property {@code "line.separator"} to the target. Flushes this
      * writer if the autoflush flag is set to {@code true}.
-     * 
+     *
      * @param bool
      *            the boolean value to print to the target.
      * @see #print(String)
-     * @since Android 1.0
-     */   
+     */
     public void println(boolean bool) {
         println(String.valueOf(bool));
     }
 
     /**
      * Sets the error flag of this writer to {@code true}.
-     * 
-     * @since Android 1.0
      */
     protected void setError() {
         synchronized (lock) {
@@ -698,10 +649,9 @@
 
     /**
      * Writes the character buffer {@code buf} to the target.
-     * 
+     *
      * @param buf
      *            the non-null array containing characters to write.
-     * @since Android 1.0
      */
     @Override
     public void write(char[] buf) {
@@ -717,8 +667,7 @@
      * <p>
      * This writer's error flag is set to {@code true} if this writer is closed
      * or an I/O error occurs.
-     * </p>
-     * 
+     *
      * @param buf
      *            the buffer to write to the target.
      * @param offset
@@ -728,7 +677,6 @@
      * @throws IndexOutOfBoundsException
      *             if {@code offset < 0} or {@code count < 0}, or if {@code
      *             offset + count} is greater than the length of {@code buf}.
-     * @since Android 1.0
      */
     @Override
     public void write(char[] buf, int offset, int count) {
@@ -744,11 +692,9 @@
      * <p>
      * This writer's error flag is set to {@code true} if this writer is closed
      * or an I/O error occurs.
-     * </p>
-     * 
+     *
      * @param oneChar
      *            the character to write to the target.
-     * @since Android 1.0
      */
     @Override
     public void write(int oneChar) {
@@ -774,10 +720,9 @@
 
     /**
      * Writes the characters from the specified string to the target.
-     * 
+     *
      * @param str
      *            the non-null string containing the characters to write.
-     * @since Android 1.0
      */
     @Override
     public void write(String str) {
@@ -787,7 +732,7 @@
     /**
      * Writes {@code count} characters from {@code str} starting at {@code
      * offset} to the target.
-     * 
+     *
      * @param str
      *            the non-null string containing the characters to write.
      * @param offset
@@ -797,7 +742,6 @@
      * @throws IndexOutOfBoundsException
      *             if {@code offset < 0} or {@code count < 0}, or if {@code
      *             offset + count} is greater than the length of {@code str}.
-     * @since Android 1.0
      */
     @Override
     public void write(String str, int offset, int count) {
@@ -805,12 +749,11 @@
     }
 
     /**
-     * Appends the character {@code c} to the target. 
-     * 
+     * Appends the character {@code c} to the target.
+     *
      * @param c
      *            the character to append to the target.
      * @return this writer.
-     * @since Android 1.0
      */
     @Override
     public PrintWriter append(char c) {
@@ -823,11 +766,10 @@
      * method works the same way as {@code PrintWriter.print(csq.toString())}.
      * If {@code csq} is {@code null}, then the string "null" is written
      * to the target.
-     * 
+     *
      * @param csq
      *            the character sequence appended to the target.
      * @return this writer.
-     * @since Android 1.0
      */
     @Override
     public PrintWriter append(CharSequence csq) {
@@ -845,7 +787,7 @@
      * PrintWriter.print(csq.subsequence(start, end).toString())}. If {@code
      * csq} is {@code null}, then the specified subsequence of the string "null"
      * will be written to the target.
-     * 
+     *
      * @param csq
      *            the character sequence appended to the target.
      * @param start
@@ -859,7 +801,6 @@
      *             if {@code start > end}, {@code start < 0}, {@code end < 0} or
      *             either {@code start} or {@code end} are greater or equal than
      *             the length of {@code csq}.
-     * @since Android 1.0
      */
     @Override
     public PrintWriter append(CharSequence csq, int start, int end) {
diff --git a/libcore/luni/src/main/java/java/io/PushbackInputStream.java b/libcore/luni/src/main/java/java/io/PushbackInputStream.java
index c397c86..4600fa2 100644
--- a/libcore/luni/src/main/java/java/io/PushbackInputStream.java
+++ b/libcore/luni/src/main/java/java/io/PushbackInputStream.java
@@ -25,14 +25,10 @@
  * this useful. The number of bytes which may be pushed back can be specified
  * during construction. If the buffer of pushed back bytes is empty, bytes are
  * read from the underlying input stream.
- * 
- * @since Android 1.0
  */
 public class PushbackInputStream extends FilterInputStream {
     /**
      * The buffer that contains pushed-back bytes.
-     * 
-     * @since Android 1.0
      */
     protected byte[] buf;
 
@@ -40,8 +36,6 @@
      * The current position within {@code buf}. A value equal to
      * {@code buf.length} indicates that no bytes are available. A value of 0
      * indicates that the buffer is full.
-     * 
-     * @since Android 1.0
      */
     protected int pos;
 
@@ -49,10 +43,9 @@
      * Constructs a new {@code PushbackInputStream} with the specified input
      * stream as source. The size of the pushback buffer is set to the default
      * value of 1 byte.
-     * 
+     *
      * @param in
      *            the source input stream.
-     * @since Android 1.0
      */
     public PushbackInputStream(InputStream in) {
         super(in);
@@ -63,14 +56,13 @@
     /**
      * Constructs a new {@code PushbackInputStream} with {@code in} as source
      * input stream. The size of the pushback buffer is set to {@code size}.
-     * 
+     *
      * @param in
      *            the source input stream.
      * @param size
      *            the size of the pushback buffer.
      * @throws IllegalArgumentException
      *             if {@code size} is negative.
-     * @since Android 1.0
      */
     public PushbackInputStream(InputStream in, int size) {
         super(in);
@@ -85,12 +77,11 @@
      * Returns the number of bytes that are available before this stream will
      * block. This is the sum of the bytes available in the pushback buffer and
      * those available from the source stream.
-     * 
+     *
      * @return the number of bytes available before blocking.
      * @throws IOException
      *             if this stream is closed or an I/O error occurs in the source
      *             stream.
-     * @since Android 1.0
      */
     @Override
     public int available() throws IOException {
@@ -103,10 +94,9 @@
     /**
      * Closes this stream. This implementation closes the source stream
      * and releases the pushback buffer.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this stream.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -121,11 +111,10 @@
      * Indicates whether this stream supports the {@code mark(int)} and
      * {@code reset()} methods. {@code PushbackInputStream} does not support
      * them, so it returns {@code false}.
-     * 
+     *
      * @return always {@code false}.
      * @see #mark(int)
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public boolean markSupported() {
@@ -138,13 +127,12 @@
      * available bytes then a byte from the source input stream is returned.
      * Blocks until one byte has been read, the end of the source stream is
      * detected or an exception is thrown.
-     * 
+     *
      * @return the byte read or -1 if the end of the source stream has been
      *         reached.
      * @throws IOException
      *             if this stream is closed or an I/O error occurs while reading
      *             from this stream.
-     * @since Android 1.0
      */
     @Override
     public int read() throws IOException {
@@ -166,7 +154,7 @@
      * from the pushback buffer first, then from the source stream if more bytes
      * are required. Blocks until {@code count} bytes have been read, the end of
      * the source stream is detected or an exception is thrown.
-     * 
+     *
      * @param buffer
      *            the array in which to store the bytes read from this stream.
      * @param offset
@@ -185,7 +173,6 @@
      *             reading from this stream.
      * @throws NullPointerException
      *             if {@code buffer} is {@code null}.
-     * @since Android 1.0
      */
     @Override
     public int read(byte[] buffer, int offset, int length) throws IOException {
@@ -234,13 +221,12 @@
     /**
      * Skips {@code count} bytes in this stream. This implementation skips bytes
      * in the pushback buffer first and then in the source stream if necessary.
-     * 
+     *
      * @param count
      *            the number of bytes to skip.
      * @return the number of bytes actually skipped.
      * @throws IOException
      *             if this stream is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public long skip(long count) throws IOException {
@@ -270,14 +256,12 @@
      * contents of {@code buffer}, an {@code IOException} is thrown. Parts of
      * {@code buffer} may have already been copied to the pushback buffer when
      * the exception is thrown.
-     * </p>
-     * 
+     *
      * @param buffer
      *            the buffer containing the bytes to push back to this stream.
      * @throws IOException
      *             if the free space in the internal pushback buffer is not
      *             sufficient to store the contents of {@code buffer}.
-     * @since Android 1.0
      */
     public void unread(byte[] buffer) throws IOException {
         unread(buffer, 0, buffer.length);
@@ -294,8 +278,7 @@
      * subset of {@code buffer}, an {@code IOException} is thrown. Parts of
      * {@code buffer} may have already been copied to the pushback buffer when
      * the exception is thrown.
-     * </p>
-     * 
+     *
      * @param buffer
      *            the buffer containing the bytes to push back to this stream.
      * @param offset
@@ -309,7 +292,6 @@
      * @throws IOException
      *             if the free space in the internal pushback buffer is not
      *             sufficient to store the selected contents of {@code buffer}.
-     * @since Android 1.0
      */
     public void unread(byte[] buffer, int offset, int length)
             throws IOException {
@@ -332,9 +314,11 @@
         }
         // END android-changed
 
-        for (int i = offset + length - 1; i >= offset; i--) {
-            unread(buffer[i]);
+        if (buf == null) {
+            throw new IOException();
         }
+        System.arraycopy(buffer, offset, buf, pos - length, length);
+        pos = pos - length;
     }
 
     /**
@@ -345,14 +329,12 @@
      * <p>
      * If this stream's internal pushback buffer cannot store the byte, an
      * {@code IOException} is thrown.
-     * </p>
-     * 
+     *
      * @param oneByte
      *            the byte to push back to this stream.
      * @throws IOException
      *             if this stream is closed or the internal pushback buffer is
      *             full.
-     * @since Android 1.0
      */
     public void unread(int oneByte) throws IOException {
         if (buf == null) {
@@ -367,11 +349,10 @@
     /**
      * Marks the current position in this stream. Setting a mark is not
      * supported in this class; this implementation does nothing.
-     * 
+     *
      * @param readlimit
      *            the number of bytes that can be read from this stream before
      *            the mark is invalidated; this parameter is ignored.
-     * @since Android 1.0
      */
     @Override
     public void mark(int readlimit) {
@@ -382,10 +363,9 @@
      * Resets this stream to the last marked position. Resetting the stream is
      * not supported in this class; this implementation always throws an
      * {@code IOException}.
-     * 
+     *
      * @throws IOException
      *             if this method is called.
-     * @since Android 1.0
      */
     @Override
     public void reset() throws IOException {
diff --git a/libcore/luni/src/main/java/java/io/PushbackReader.java b/libcore/luni/src/main/java/java/io/PushbackReader.java
index 484caf3..606ecb4 100644
--- a/libcore/luni/src/main/java/java/io/PushbackReader.java
+++ b/libcore/luni/src/main/java/java/io/PushbackReader.java
@@ -25,8 +25,6 @@
  * find this useful. The number of characters which may be pushed back can be
  * specified during construction. If the buffer of pushed back bytes is empty,
  * characters are read from the underlying reader.
- * 
- * @since Android 1.0
  */
 public class PushbackReader extends FilterReader {
     /**
@@ -45,10 +43,9 @@
      * Constructs a new {@code PushbackReader} with the specified reader as
      * source. The size of the pushback buffer is set to the default value of 1
      * character.
-     * 
+     *
      * @param in
      *            the source reader.
-     * @since Android 1.0
      */
     public PushbackReader(Reader in) {
         super(in);
@@ -59,14 +56,13 @@
     /**
      * Constructs a new {@code PushbackReader} with {@code in} as source reader.
      * The size of the pushback buffer is set to {@code size}.
-     * 
+     *
      * @param in
      *            the source reader.
      * @param size
      *            the size of the pushback buffer.
      * @throws IllegalArgumentException
      *             if {@code size} is negative.
-     * @since Android 1.0
      */
     public PushbackReader(Reader in, int size) {
         super(in);
@@ -80,10 +76,9 @@
     /**
      * Closes this reader. This implementation closes the source reader
      * and releases the pushback buffer.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this reader.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -97,13 +92,12 @@
      * Marks the current position in this stream. Setting a mark is not
      * supported in this class; this implementation always throws an
      * {@code IOException}.
-     * 
+     *
      * @param readAheadLimit
      *            the number of character that can be read from this reader
      *            before the mark is invalidated; this parameter is ignored.
      * @throws IOException
      *             if this method is called.
-     * @since Android 1.0
      */
     @Override
     public void mark(int readAheadLimit) throws IOException {
@@ -114,11 +108,10 @@
      * Indicates whether this reader supports the {@code mark(int)} and
      * {@code reset()} methods. {@code PushbackReader} does not support them, so
      * it returns {@code false}.
-     * 
+     *
      * @return always {@code false}.
      * @see #mark(int)
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public boolean markSupported() {
@@ -132,13 +125,12 @@
      * available characters then a character from the source reader is returned.
      * Blocks until one character has been read, the end of the source reader is
      * detected or an exception is thrown.
-     * 
+     *
      * @return the character read or -1 if the end of the source reader has been
      *         reached.
      * @throws IOException
      *             if this reader is closed or an I/O error occurs while reading
      *             from this reader.
-     * @since Android 1.0
      */
     @Override
     public int read() throws IOException {
@@ -164,7 +156,7 @@
      * read from the pushback buffer first, then from the source reader if more
      * bytes are required. Blocks until {@code count} characters have been read,
      * the end of the source reader is detected or an exception is thrown.
-     * 
+     *
      * @param buffer
      *            the array in which to store the characters read from this
      *            reader.
@@ -182,7 +174,6 @@
      * @throws IOException
      *             if this reader is closed or another I/O error occurs while
      *             reading from this reader.
-     * @since Android 1.0
      */
     @Override
     public int read(char[] buffer, int offset, int count) throws IOException {
@@ -236,7 +227,7 @@
      * Indicates whether this reader is ready to be read without blocking.
      * Returns {@code true} if this reader will not block when {@code read} is
      * called, {@code false} if unknown or blocking will occur.
-     * 
+     *
      * @return {@code true} if the receiver will not block when
      *         {@code read()} is called, {@code false} if unknown
      *         or blocking will occur.
@@ -244,7 +235,6 @@
      *             if this reader is closed or some other I/O error occurs.
      * @see #read()
      * @see #read(char[], int, int)
-     * @since Android 1.0
      */
     @Override
     public boolean ready() throws IOException {
@@ -260,10 +250,9 @@
      * Resets this reader to the last marked position. Resetting the reader is
      * not supported in this class; this implementation always throws an
      * {@code IOException}.
-     * 
+     *
      * @throws IOException
      *             if this method is called.
-     * @since Android 1.0
      */
     @Override
     public void reset() throws IOException {
@@ -279,8 +268,7 @@
      * contents of {@code buffer}, an {@code IOException} is thrown. Parts of
      * {@code buffer} may have already been copied to the pushback buffer when
      * the exception is thrown.
-     * </p>
-     * 
+     *
      * @param buffer
      *            the buffer containing the characters to push back to this
      *            reader.
@@ -288,7 +276,6 @@
      *             if this reader is closed or the free space in the internal
      *             pushback buffer is not sufficient to store the contents of
      *             {@code buffer}.
-     * @since Android 1.0
      */
     public void unread(char[] buffer) throws IOException {
         unread(buffer, 0, buffer.length);
@@ -305,8 +292,7 @@
      * subset of {@code buffer}, an {@code IOException} is thrown. Parts of
      * {@code buffer} may have already been copied to the pushback buffer when
      * the exception is thrown.
-     * </p>
-     * 
+     *
      * @param buffer
      *            the buffer containing the characters to push back to this
      *            reader.
@@ -324,7 +310,6 @@
      *             contents of {@code buffer}.
      * @throws NullPointerException
      *             if {@code buffer} is {@code null}.
-     * @since Android 1.0
      */
     public void unread(char[] buffer, int offset, int count) throws IOException {
         synchronized (lock) {
@@ -361,14 +346,12 @@
      * <p>
      * If this reader's internal pushback buffer cannot store the character, an
      * {@code IOException} is thrown.
-     * </p>
-     * 
+     *
      * @param oneChar
      *            the character to push back to this stream.
      * @throws IOException
      *             if this reader is closed or the internal pushback buffer is
      *             full.
-     * @since Android 1.0
      */
     public void unread(int oneChar) throws IOException {
         synchronized (lock) {
@@ -386,14 +369,13 @@
      * Skips {@code count} characters in this reader. This implementation skips
      * characters in the pushback buffer first and then in the source reader if
      * necessary.
-     * 
+     *
      * @param count
      *            the number of characters to skip.
      * @return the number of characters actually skipped.
      * @throws IllegalArgumentException if {@code count < 0}.
      * @throws IOException
      *             if this reader is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     @Override
     public long skip(long count) throws IOException {
diff --git a/libcore/luni/src/main/java/java/io/RandomAccessFile.java b/libcore/luni/src/main/java/java/io/RandomAccessFile.java
index 7152116..37d77f5 100644
--- a/libcore/luni/src/main/java/java/io/RandomAccessFile.java
+++ b/libcore/luni/src/main/java/java/io/RandomAccessFile.java
@@ -33,8 +33,6 @@
  * opened in read/write mode, write operations are available as well. The
  * position of the next read or write operation can be moved forwards and
  * backwards after every operation.
- * 
- * @since Android 1.0
  */
 public class RandomAccessFile implements DataInput, DataOutput, Closeable {
     /**
@@ -51,7 +49,7 @@
     private IFileSystem fileSystem = Platform.getFileSystem();
 
     private boolean isReadOnly;
-    
+
     // BEGIN android-added
     private int options;
     // END android-added
@@ -61,12 +59,11 @@
 
     private Object repositionLock = new RepositionLock();
 
-    // BEGIN android-changed
     /**
      * Constructs a new {@code RandomAccessFile} based on {@code file} and opens
-     * it according to the access string in {@code mode}. 
+     * it according to the access string in {@code mode}.
      * <p><a id="accessmode"/>
-     * {@code mode} may have one of following values: 
+     * {@code mode} may have one of following values:
      * <table border="0">
      * <tr>
      * <td>{@code "r"}</td>
@@ -90,7 +87,7 @@
      * file's content must be written synchronously to the target device.</td>
      * </tr>
      * </table>
-     * </p>
+     *
      * @param file
      *            the file to open.
      * @param mode
@@ -107,16 +104,17 @@
      *             access request according to {@code mode}.
      * @see java.lang.SecurityManager#checkRead(FileDescriptor)
      * @see java.lang.SecurityManager#checkWrite(FileDescriptor)
-     * @since Android 1.0
      */
     public RandomAccessFile(File file, String mode)
             throws FileNotFoundException {
         super();
 
+        // BEGIN android-changed
         options = 0;
-        
+        // END android-changed
+
         fd = new FileDescriptor();
-       
+
         if (mode.equals("r")) { //$NON-NLS-1$
             isReadOnly = true;
             fd.readOnly = true;
@@ -143,8 +141,12 @@
                 security.checkWrite(file.getPath());
             }
         }
-        
+
         fd.descriptor = fileSystem.open(file.properPath(true), options);
+        // BEGIN android-removed
+        // channel = FileChannelFactory.getFileChannel(this, fd.descriptor,
+        //         options);
+        // END android-removed
 
         // if we are in "rws" mode, attempt to sync file+metadata
         if (syncMetadata) {
@@ -155,14 +157,13 @@
             }
         }
     }
-    // END android-changed
 
     /**
      * Constructs a new {@code RandomAccessFile} based on the file named {@code
      * fileName} and opens it according to the access string in {@code mode}.
      * The file path may be specified absolutely or relative to the system
      * property {@code "user.dir"}.
-     * 
+     *
      * @param fileName
      *            the name of the file to open.
      * @param mode
@@ -179,7 +180,6 @@
      *             access request according to {@code mode}.
      * @see java.lang.SecurityManager#checkRead(FileDescriptor)
      * @see java.lang.SecurityManager#checkWrite(FileDescriptor)
-     * @since Android 1.0
      */
     public RandomAccessFile(String fileName, String mode)
             throws FileNotFoundException {
@@ -188,10 +188,9 @@
 
     /**
      * Closes this file.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this file.
-     * @since Android 1.0
      */
     public void close() throws IOException {
         // BEGIN android-changed
@@ -208,39 +207,34 @@
         // END android-changed
     }
 
-    // BEGIN android-changed
     /**
      * Gets this file's {@link FileChannel} object.
      * <p>
-     * The file channel's {@link FileChannel.#position() position} is the same
+     * The file channel's {@link FileChannel#position() position} is the same
      * as this file's file pointer offset (see {@link #getFilePointer()}). Any
      * changes made to this file's file pointer offset are also visible in the
      * file channel's position and vice versa.
-     * </p>
-     * 
+     *
      * @return this file's file channel instance.
-     * @since Android 1.0
      */
-    public final FileChannel getChannel() {
-        synchronized(this) {
-            if(channel == null) {
-                channel = FileChannelFactory.getFileChannel(this, fd.descriptor,
-                        options);
-            }
-            return channel;
+    public final synchronized FileChannel getChannel() {
+        // BEGIN android-added
+        if(channel == null) {
+            channel = FileChannelFactory.getFileChannel(this, fd.descriptor,
+                    options);
         }
+        // END android-added
+        return channel;
     }
-    // END android-changed
 
     /**
      * Gets this file's {@link FileDescriptor}. This represents the operating
      * system resource for this random access file.
-     * 
+     *
      * @return this file's file descriptor object.
      * @throws IOException
      *             if an error occurs while getting the file descriptor of this
      *             file.
-     * @since Android 1.0
      */
     public final FileDescriptor getFD() throws IOException {
         return fd;
@@ -249,13 +243,12 @@
     /**
      * Gets the current position within this file. All reads and
      * writes take place at the current file pointer position.
-     * 
+     *
      * @return the current offset in bytes from the beginning of the file.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while getting the file pointer of this
      *             file.
-     * @since Android 1.0
      */
     public long getFilePointer() throws IOException {
         openCheck();
@@ -265,7 +258,7 @@
     /**
      * Checks to see if the file is currently open. Returns silently if it is,
      * and throws an exception if it is not.
-     * 
+     *
      * @throws IOException
      *             the receiver is closed.
      */
@@ -277,11 +270,10 @@
 
     /**
      * Returns the length of this file in bytes.
-     * 
+     *
      * @return the file's length in bytes.
      * @throws IOException
      *             if this file is closed or some other I/O error occurs.
-     * @since Android 1.0
      */
     public long length() throws IOException {
         openCheck();
@@ -301,11 +293,10 @@
      * as an integer in the range from 0 to 255. Returns -1 if the end of the
      * file has been reached. Blocks until one byte has been read, the end of
      * the file is detected or an exception is thrown.
-     * 
+     *
      * @return the byte read or -1 if the end of the file has been reached.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public int read() throws IOException {
         openCheck();
@@ -321,14 +312,13 @@
      * byte array {@code buffer}. The maximum number of bytes read corresponds
      * to the size of {@code buffer}. Blocks until at least one byte has been
      * read.
-     * 
+     *
      * @param buffer
      *            the byte array in which to store the bytes read.
      * @return the number of bytes actually read or -1 if the end of the file
      *         has been reached.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public int read(byte[] buffer) throws IOException {
         return read(buffer, 0, buffer.length);
@@ -339,7 +329,7 @@
      * and stores them in the byte array {@code buffer} starting at {@code
      * offset}. Blocks until {@code count} bytes have been read, the end of the
      * file is reached or an exception is thrown.
-     * 
+     *
      * @param buffer
      *            the array in which to store the bytes read from this file.
      * @param offset
@@ -354,7 +344,6 @@
      *             offset + count} is greater than the size of {@code buffer}.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public int read(byte[] buffer, int offset, int count) throws IOException {
         // have to have four comparisions to not miss integer overflow cases
@@ -383,14 +372,13 @@
      * Reads a boolean from the current position in this file. Blocks until one
      * byte has been read, the end of the file is reached or an exception is
      * thrown.
-     * 
+     *
      * @return the next boolean value from this file.
      * @throws EOFException
      *             if the end of this file is detected.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      * @see #writeBoolean(boolean)
-     * @since Android 1.0
      */
     public final boolean readBoolean() throws IOException {
         int temp = this.read();
@@ -404,14 +392,13 @@
      * Reads an 8-bit byte from the current position in this file. Blocks until
      * one byte has been read, the end of the file is reached or an exception is
      * thrown.
-     * 
+     *
      * @return the next signed 8-bit byte value from this file.
      * @throws EOFException
      *             if the end of this file is detected.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      * @see #writeBoolean(boolean)
-     * @since Android 1.0
      */
     public final byte readByte() throws IOException {
         int temp = this.read();
@@ -425,15 +412,14 @@
      * Reads a 16-bit character from the current position in this file. Blocks until
      * two bytes have been read, the end of the file is reached or an exception is
      * thrown.
-     * 
+     *
      * @return the next char value from this file.
      * @throws EOFException
      *             if the end of this file is detected.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      * @see #writeChar(int)
-     * @since Android 1.0
-     */    
+     */
     public final char readChar() throws IOException {
         byte[] buffer = new byte[2];
         if (read(buffer, 0, buffer.length) != buffer.length) {
@@ -446,14 +432,13 @@
      * Reads a 64-bit double from the current position in this file. Blocks
      * until eight bytes have been read, the end of the file is reached or an
      * exception is thrown.
-     * 
+     *
      * @return the next double value from this file.
      * @throws EOFException
      *             if the end of this file is detected.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      * @see #writeDouble(double)
-     * @since Android 1.0
      */
     public final double readDouble() throws IOException {
         return Double.longBitsToDouble(readLong());
@@ -463,14 +448,13 @@
      * Reads a 32-bit float from the current position in this file. Blocks
      * until four bytes have been read, the end of the file is reached or an
      * exception is thrown.
-     * 
+     *
      * @return the next float value from this file.
      * @throws EOFException
      *             if the end of this file is detected.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      * @see #writeFloat(float)
-     * @since Android 1.0
      */
     public final float readFloat() throws IOException {
         return Float.intBitsToFloat(readInt());
@@ -480,7 +464,7 @@
      * Reads bytes from this file into {@code buffer}. Blocks until {@code
      * buffer.length} number of bytes have been read, the end of the file is
      * reached or an exception is thrown.
-     * 
+     *
      * @param buffer
      *            the buffer to read bytes into.
      * @throws EOFException
@@ -489,7 +473,6 @@
      *             if this file is closed or another I/O error occurs.
      * @throws NullPointerException
      *             if {@code buffer} is {@code null}.
-     * @since Android 1.0             
      */
     public final void readFully(byte[] buffer) throws IOException {
         readFully(buffer, 0, buffer.length);
@@ -499,7 +482,7 @@
      * Read bytes from this file into {@code buffer} starting at offset {@code
      * offset}. This method blocks until {@code count} number of bytes have been
      * read.
-     * 
+     *
      * @param buffer
      *            the buffer to read bytes into.
      * @param offset
@@ -516,7 +499,6 @@
      *             if this file is closed or another I/O error occurs.
      * @throws NullPointerException
      *             if {@code buffer} is {@code null}.
-     * @since Android 1.0
      */
     public final void readFully(byte[] buffer, int offset, int count)
             throws IOException {
@@ -547,14 +529,13 @@
      * Reads a 32-bit integer from the current position in this file. Blocks
      * until four bytes have been read, the end of the file is reached or an
      * exception is thrown.
-     * 
+     *
      * @return the next int value from this file.
      * @throws EOFException
      *             if the end of this file is detected.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      * @see #writeInt(int)
-     * @since Android 1.0
      */
     public final int readInt() throws IOException {
         byte[] buffer = new byte[4];
@@ -573,13 +554,11 @@
      * <p>
      * Blocks until a line terminating sequence has been read, the end of the
      * file is reached or an exception is thrown.
-     * </p>
-     * 
+     *
      * @return the contents of the line or {@code null} if no characters have
      *         been read before the end of the file has been reached.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public final String readLine() throws IOException {
         StringBuilder line = new StringBuilder(80); // Typical line length
@@ -615,14 +594,13 @@
      * Reads a 64-bit long from the current position in this file. Blocks until
      * eight bytes have been read, the end of the file is reached or an
      * exception is thrown.
-     * 
+     *
      * @return the next long value from this file.
      * @throws EOFException
      *             if the end of this file is detected.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      * @see #writeLong(long)
-     * @since Android 1.0
      */
     public final long readLong() throws IOException {
         byte[] buffer = new byte[8];
@@ -641,14 +619,13 @@
      * Reads a 16-bit short from the current position in this file. Blocks until
      * two bytes have been read, the end of the file is reached or an exception
      * is thrown.
-     * 
+     *
      * @return the next short value from this file.
      * @throws EOFException
      *             if the end of this file is detected.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      * @see #writeShort(int)
-     * @since Android 1.0
      */
     public final short readShort() throws IOException {
         byte[] buffer = new byte[2];
@@ -662,14 +639,13 @@
      * Reads an unsigned 8-bit byte from the current position in this file and
      * returns it as an integer. Blocks until one byte has been read, the end of
      * the file is reached or an exception is thrown.
-     * 
+     *
      * @return the next unsigned byte value from this file as an int.
      * @throws EOFException
      *             if the end of this file is detected.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      * @see #writeByte(int)
-     * @since Android 1.0
      */
     public final int readUnsignedByte() throws IOException {
         int temp = this.read();
@@ -683,14 +659,13 @@
      * Reads an unsigned 16-bit short from the current position in this file and
      * returns it as an integer. Blocks until two bytes have been read, the end of
      * the file is reached or an exception is thrown.
-     * 
+     *
      * @return the next unsigned short value from this file as an int.
      * @throws EOFException
      *             if the end of this file is detected.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      * @see #writeShort(int)
-     * @since Android 1.0
      */
     public final int readUnsignedShort() throws IOException {
         byte[] buffer = new byte[2];
@@ -706,7 +681,7 @@
      * is determined by the first two bytes read from the file. Blocks until all
      * required bytes have been read, the end of the file is reached or an
      * exception is thrown.
-     * 
+     *
      * @return the next string encoded in {@link DataInput modified UTF-8} from
      *         this file.
      * @throws EOFException
@@ -716,7 +691,6 @@
      * @throws UTFDataFormatException
      *             if the bytes read cannot be decoded into a character string.
      * @see #writeUTF(String)
-     * @since Android 1.0
      */
     public final String readUTF() throws IOException {
         int utfSize = readUnsignedShort();
@@ -736,13 +710,12 @@
      * position may be greater than the current length of the file, but the
      * file's length will only change if the moving of the pointer is followed
      * by a {@code write} operation.
-     * 
+     *
      * @param pos
      *            the new file pointer position.
      * @throws IOException
      *             if this file is closed, {@code pos < 0} or another I/O error
      *             occurs.
-     * @since Android 1.0
      */
     public void seek(long pos) throws IOException {
         if (pos < 0) {
@@ -761,14 +734,13 @@
      * file to the new end are undefined. The file is truncated if its current
      * size is bigger than {@code newLength}. If the current file pointer
      * position is in the truncated part, it is set to the end of the file.
-     * 
+     *
      * @param newLength
      *            the new file length in bytes.
      * @throws IllegalArgumentException
      *             if {@code newLength < 0}.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public void setLength(long newLength) throws IOException {
         openCheck();
@@ -793,13 +765,12 @@
      * bytes are skipped if the end of the file is reached or an exception is
      * thrown during the operation. Nothing is done if {@code count} is
      * negative.
-     * 
+     *
      * @param count
      *            the number of bytes to skip.
      * @return the number of bytes actually skipped.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public int skipBytes(int count) throws IOException {
         if (count > 0) {
@@ -815,7 +786,7 @@
     /**
      * Writes the entire contents of the byte array {@code buffer} to this file,
      * starting at the current file pointer.
-     * 
+     *
      * @param buffer
      *            the buffer to write.
      * @throws IOException
@@ -824,7 +795,6 @@
      * @see #read(byte[],int,int)
      * @see #readFully(byte[])
      * @see #readFully(byte[],int,int)
-     * @since Android 1.0
      */
     public void write(byte[] buffer) throws IOException {
         write(buffer, 0, buffer.length);
@@ -834,7 +804,7 @@
      * Writes {@code count} bytes from the byte array {@code buffer} to this
      * file, starting at the current file pointer and using {@code offset} as
      * the first position within {@code buffer} to get bytes.
-     * 
+     *
      * @param buffer
      *            the buffer to write to this file.
      * @param offset
@@ -848,7 +818,6 @@
      *             if an I/O error occurs while writing to this file.
      * @see #read(byte[], int, int)
      * @see #readFully(byte[], int, int)
-     * @since Android 1.0
      */
     public void write(byte[] buffer, int offset, int count) throws IOException {
         // BEGIN android-changed
@@ -883,13 +852,12 @@
     /**
      * Writes a byte to this file, starting at the current file pointer. Only
      * the least significant byte of the integer {@code oneByte} is written.
-     * 
+     *
      * @param oneByte
      *            the byte to write to this file.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      * @see #read()
-     * @since Android 1.0
      */
     public void write(int oneByte) throws IOException {
         openCheck();
@@ -907,13 +875,12 @@
 
     /**
      * Writes a boolean to this file, starting at the current file pointer.
-     * 
+     *
      * @param val
      *            the boolean to write to this file.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      * @see #readBoolean()
-     * @since Android 1.0
      */
     public final void writeBoolean(boolean val) throws IOException {
         write(val ? 1 : 0);
@@ -922,14 +889,13 @@
     /**
      * Writes an 8-bit byte to this file, starting at the current file pointer.
      * Only the least significant byte of the integer {@code val} is written.
-     * 
+     *
      * @param val
      *            the byte to write to this file.
      * @throws IOException
      *             if this file is closed or another I/O error occurs.
      * @see #readByte()
      * @see #readUnsignedByte()
-     * @since Android 1.0
      */
     public final void writeByte(int val) throws IOException {
         write(val & 0xFF);
@@ -938,7 +904,7 @@
     /**
      * Writes the low order 8-bit bytes from a string to this file, starting at
      * the current file pointer.
-     * 
+     *
      * @param str
      *            the string containing the bytes to write to this file
      * @throws IOException
@@ -947,7 +913,6 @@
      * @see #read(byte[],int,int)
      * @see #readFully(byte[])
      * @see #readFully(byte[],int,int)
-     * @since Android 1.0
      */
     public final void writeBytes(String str) throws IOException {
         byte bytes[] = new byte[str.length()];
@@ -957,18 +922,16 @@
         write(bytes);
     }
 
-
     /**
      * Writes a 16-bit character to this file, starting at the current file
      * pointer. Only the two least significant bytes of the integer {@code val}
      * are written, with the high byte first.
-     * 
+     *
      * @param val
      *            the char to write to this file.
      * @throws IOException
      *             if an I/O error occurs while writing to this file.
      * @see #readChar()
-     * @since Android 1.0
      */
     public final void writeChar(int val) throws IOException {
         byte[] buffer = new byte[2];
@@ -981,13 +944,12 @@
      * Writes the 16-bit characters from a string to this file, starting at the
      * current file pointer. Each character is written in the same way as with
      * {@link #writeChar(int)}, with its high byte first.
-     * 
+     *
      * @param str
      *            the string to write to this file.
      * @throws IOException
      *             if an I/O error occurs while writing to this file.
      * @see #readChar()
-     * @since Android 1.0
      */
     public final void writeChars(String str) throws IOException {
         byte newBytes[] = new byte[str.length() * 2];
@@ -1003,13 +965,12 @@
      * Writes a 64-bit double to this file, starting at the current file
      * pointer. The eight bytes returned by
      * {@link Double#doubleToLongBits(double)} are written to this file.
-     * 
+     *
      * @param val
      *            the double to write to this file.
      * @throws IOException
      *             if an I/O error occurs while writing to this file.
      * @see #readDouble()
-     * @since Android 1.0
      */
     public final void writeDouble(double val) throws IOException {
         writeLong(Double.doubleToLongBits(val));
@@ -1019,13 +980,12 @@
      * Writes a 32-bit float to this file, starting at the current file pointer.
      * The four bytes returned by {@link Float#floatToIntBits(float)} are
      * written to this file.
-     * 
+     *
      * @param val
      *            the float to write to this file.
      * @throws IOException
      *             if an I/O error occurs while writing to this file.
      * @see #readFloat()
-     * @since Android 1.0
      */
     public final void writeFloat(float val) throws IOException {
         writeInt(Float.floatToIntBits(val));
@@ -1035,13 +995,12 @@
      * Writes a 32-bit integer to this file, starting at the current file
      * pointer. The four bytes of the integer are written with the highest byte
      * first.
-     * 
+     *
      * @param val
      *            the int to write to this file.
      * @throws IOException
      *             if an I/O error occurs while writing to this file.
      * @see #readInt()
-     * @since Android 1.0
      */
     public final void writeInt(int val) throws IOException {
         byte[] buffer = new byte[4];
@@ -1056,13 +1015,12 @@
      * Writes a 64-bit long to this file, starting at the current file
      * pointer. The eight bytes of the long are written with the highest byte
      * first.
-     * 
+     *
      * @param val
      *            the long to write to this file.
      * @throws IOException
      *             if an I/O error occurs while writing to this file.
      * @see #readLong()
-     * @since Android 1.0
      */
     public final void writeLong(long val) throws IOException {
         byte[] buffer = new byte[8];
@@ -1082,13 +1040,13 @@
      * Writes a 16-bit short to this file, starting at the current file
      * pointer. Only the two least significant bytes of the integer {@code val}
      * are written, with the high byte first.
-     * 
+     *
      * @param val
      *            the short to write to this file.
      * @throws IOException
      *             if an I/O error occurs while writing to this file.
      * @see #readShort()
-     * @since Android 1.0
+     * @see DataInput#readUnsignedShort()
      */
     public final void writeShort(int val) throws IOException {
         writeChar(val);
@@ -1097,7 +1055,7 @@
     /**
      * Writes a string encoded with {@link DataInput modified UTF-8} to this
      * file, starting at the current file pointer.
-     * 
+     *
      * @param str
      *            the string to write in {@link DataInput modified UTF-8}
      *            format.
@@ -1106,7 +1064,6 @@
      * @throws UTFDataFormatException
      *             if the encoded string is longer than 65535 bytes.
      * @see #readUTF()
-     * @since Android 1.0
      */
     public final void writeUTF(String str) throws IOException {
         int utfCount = 0, length = str.length();
diff --git a/libcore/luni/src/main/java/java/io/Reader.java b/libcore/luni/src/main/java/java/io/Reader.java
index 42fb9ee..1f78f5a 100644
--- a/libcore/luni/src/main/java/java/io/Reader.java
+++ b/libcore/luni/src/main/java/java/io/Reader.java
@@ -33,24 +33,18 @@
  * <p>
  * Many specialized readers for purposes like reading from a file already exist
  * in this package.
- * 
+ *
  * @see Writer
- * 
- * @since Android 1.0
  */
 public abstract class Reader implements Readable, Closeable {
     /**
      * The object used to synchronize access to the reader.
-     * 
-     * @since Android 1.0
      */
     protected Object lock;
 
     /**
      * Constructs a new {@code Reader} with {@code this} as the object used to
      * synchronize critical sections.
-     * 
-     * @since Android 1.0
      */
     protected Reader() {
         super();
@@ -60,12 +54,11 @@
     /**
      * Constructs a new {@code Reader} with {@code lock} used to synchronize
      * critical sections.
-     * 
+     *
      * @param lock
      *            the {@code Object} used to synchronize critical sections.
      * @throws NullPointerException
      *             if {@code lock} is {@code null}.
-     * @since Android 1.0
      */
     protected Reader(Object lock) {
         if (lock == null) {
@@ -77,10 +70,9 @@
     /**
      * Closes this reader. Implementations of this method should free any
      * resources associated with the reader.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this reader.
-     * @since Android 1.0
      */
     public abstract void close() throws IOException;
 
@@ -92,8 +84,7 @@
      * <p>
      * This default implementation simply throws an {@code IOException};
      * subclasses must provide their own implementation.
-     * </p>
-     * 
+     *
      * @param readLimit
      *            the number of characters that can be read before the mark is
      *            invalidated.
@@ -103,7 +94,6 @@
      *             if an error occurs while setting a mark in this reader.
      * @see #markSupported()
      * @see #reset()
-     * @since Android 1.0
      */
     public void mark(int readLimit) throws IOException {
         throw new IOException();
@@ -113,9 +103,8 @@
      * Indicates whether this reader supports the {@code mark()} and
      * {@code reset()} methods. This default implementation returns
      * {@code false}.
-     * 
+     *
      * @return always {@code false}.
-     * @since Android 1.0
      */
     public boolean markSupported() {
         return false;
@@ -125,12 +114,11 @@
      * Reads a single character from this reader and returns it as an integer
      * with the two higher-order bytes set to 0. Returns -1 if the end of the
      * reader has been reached.
-     * 
+     *
      * @return the character read or -1 if the end of the reader has been
      *         reached.
      * @throws IOException
      *             if this reader is closed or some other I/O error occurs.
-     * @since Android 1.0
      */
     public int read() throws IOException {
         synchronized (lock) {
@@ -146,14 +134,13 @@
      * Reads characters from this reader and stores them in the character array
      * {@code buf} starting at offset 0. Returns the number of characters
      * actually read or -1 if the end of the reader has been reached.
-     * 
+     *
      * @param buf
      *            character array to store the characters read.
      * @return the number of characters read or -1 if the end of the reader has
      *         been reached.
      * @throws IOException
      *             if this reader is closed or some other I/O error occurs.
-     * @since Android 1.0
      */
     public int read(char[] buf) throws IOException {
         // BEGIN android-note
@@ -167,7 +154,7 @@
      * at {@code offset} in the character array {@code buf}. Returns the number
      * of characters actually read or -1 if the end of the reader has been
      * reached.
-     * 
+     *
      * @param buf
      *            the character array to store the characters read.
      * @param offset
@@ -179,7 +166,6 @@
      *         been reached.
      * @throws IOException
      *             if this reader is closed or some other I/O error occurs.
-     * @since Android 1.0
      */
     public abstract int read(char[] buf, int offset, int count)
             throws IOException;
@@ -192,14 +178,13 @@
      * Returns {@code true} if this reader will not block when {@code read} is
      * called, {@code false} if unknown or blocking will occur. This default
      * implementation always returns {@code false}.
-     * 
+     *
      * @return always {@code false}.
      * @throws IOException
      *             if this reader is closed or some other I/O error occurs.
      * @see #read()
      * @see #read(char[])
      * @see #read(char[], int, int)
-     * @since Android 1.0
      */
     public boolean ready() throws IOException {
         return false;
@@ -211,12 +196,11 @@
      * location. If this reader has not been marked, the behavior of
      * {@code reset()} is implementation specific. This default
      * implementation throws an {@code IOException}.
-     * 
+     *
      * @throws IOException
      *             always thrown in this default implementation.
      * @see #mark(int)
      * @see #markSupported()
-     * @since Android 1.0
      */
     public void reset() throws IOException {
         throw new IOException();
@@ -227,7 +211,7 @@
      * {@code read} methods will not return these characters unless {@code
      * reset()} is used. This method may perform multiple reads to read {@code
      * count} characters.
-     * 
+     *
      * @param count
      *            the maximum number of characters to skip.
      * @return the number of characters actually skipped.
@@ -238,7 +222,6 @@
      * @see #mark(int)
      * @see #markSupported()
      * @see #reset()
-     * @since Android 1.0
      */
     public long skip(long count) throws IOException {
         if (count < 0) {
@@ -267,7 +250,7 @@
 
     /**
      * Reads characters and puts them into the {@code target} character buffer.
-     * 
+     *
      * @param target
      *            the destination character buffer.
      * @return the number of characters put into {@code target} or -1 if the end
@@ -278,7 +261,6 @@
      *             if {@code target} is {@code null}.
      * @throws ReadOnlyBufferException
      *             if {@code target} is read-only.
-     * @since Android 1.0
      */
     public int read(CharBuffer target) throws IOException {
         if (null == target) {
diff --git a/libcore/luni/src/main/java/java/io/SequenceInputStream.java b/libcore/luni/src/main/java/java/io/SequenceInputStream.java
index 1b946b5..3719021 100644
--- a/libcore/luni/src/main/java/java/io/SequenceInputStream.java
+++ b/libcore/luni/src/main/java/java/io/SequenceInputStream.java
@@ -28,8 +28,6 @@
  * Concatenates two or more existing {@link InputStream}s. Reads are taken from
  * the first stream until it ends, then the next stream is used, until the last
  * stream returns end of file.
- * 
- * @since Android 1.0
  */
 public class SequenceInputStream extends InputStream {
     /**
@@ -45,14 +43,13 @@
     /**
      * Constructs a new {@code SequenceInputStream} using the two streams
      * {@code s1} and {@code s2} as the sequence of streams to read from.
-     * 
+     *
      * @param s1
      *            the first stream to get bytes from.
      * @param s2
      *            the second stream to get bytes from.
      * @throws NullPointerException
      *             if {@code s1} is {@code null}.
-     * @since Android 1.0
      */
     public SequenceInputStream(InputStream s1, InputStream s2) {
         if (s1 == null) {
@@ -68,12 +65,11 @@
      * Constructs a new SequenceInputStream using the elements returned from
      * Enumeration {@code e} as the stream sequence. The instances returned by
      * {@code e.nextElement()} must be of type {@link InputStream}.
-     * 
+     *
      * @param e
      *            the enumeration of {@code InputStreams} to get bytes from.
      * @throws NullPointerException
      *             if any of the elements in {@code e} is {@code null}.
-     * @since Android 1.0
      */
     public SequenceInputStream(Enumeration<? extends InputStream> e) {
         this.e = e;
@@ -87,12 +83,11 @@
 
     /**
      * Returns the number of bytes that are available before the current input stream will
-     * block. 
-     * 
+     * block.
+     *
      * @return the number of bytes available in the current input stream before blocking.
      * @throws IOException
      *             if an I/O error occurs in the current input stream.
-     * @since Android 1.0
      */
     @Override
     public int available() throws IOException {
@@ -103,11 +98,10 @@
     }
 
     /**
-     * Closes all streams in this sequence of input stream. 
-     * 
+     * Closes all streams in this sequence of input stream.
+     *
      * @throws IOException
      *             if an error occurs while closing any of the input streams.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -119,7 +113,7 @@
 
     /**
      * Sets up the next InputStream or leaves it alone if there are none left.
-     * 
+     *
      * @throws IOException
      */
     private void nextStream() throws IOException {
@@ -142,14 +136,13 @@
      * stream first; if the end of this stream has been reached, it reads from
      * the next one. Blocks until one byte has been read, the end of the last
      * input stream in the sequence has been reached, or an exception is thrown.
-     * 
+     *
      * @return the byte read or -1 if either the end of the last stream in the
      *         sequence has been reached or this input stream sequence is
      *         closed.
      * @throws IOException
      *             if an error occurs while reading the current source input
      *             stream.
-     * @since Android 1.0
      */
     @Override
     public int read() throws IOException {
@@ -179,7 +172,7 @@
      * If a substream has already reached the end when this call is made, it
      * will close that substream and start with the next one. If there are no
      * more substreams it will return -1.
-     * 
+     *
      * @param buffer
      *            the array in which to store the bytes read.
      * @param offset
@@ -197,7 +190,6 @@
      *             if an I/O error occurs.
      * @throws NullPointerException
      *             if {@code buffer} is {@code null}.
-     * @since Android 1.0
      */
     @Override
     public int read(byte[] buffer, int offset, int count) throws IOException {
diff --git a/libcore/luni/src/main/java/java/io/Serializable.java b/libcore/luni/src/main/java/java/io/Serializable.java
index 17690e3..9cd7816 100644
--- a/libcore/luni/src/main/java/java/io/Serializable.java
+++ b/libcore/luni/src/main/java/java/io/Serializable.java
@@ -28,13 +28,9 @@
  * <p>
  * {@code private void writeObject(java.io.ObjectOutputStream out) throws
  * IOException}
- * </p>
  * <p>
  * {@code private void readObject(java.io.ObjectInputStream in) throws
  * IOException, ClassNotFoundException}
- * </p>
- * 
- * @since Android 1.0
  */
 public interface Serializable {
     /* empty */
diff --git a/libcore/luni/src/main/java/java/io/StreamCorruptedException.java b/libcore/luni/src/main/java/java/io/StreamCorruptedException.java
index 1181507..9d25727 100644
--- a/libcore/luni/src/main/java/java/io/StreamCorruptedException.java
+++ b/libcore/luni/src/main/java/java/io/StreamCorruptedException.java
@@ -25,8 +25,6 @@
  * 
  * @see ObjectInputStream
  * @see OptionalDataException
- * 
- * @since Android 1.0
  */
 public class StreamCorruptedException extends ObjectStreamException {
 
@@ -35,8 +33,6 @@
     /**
      * Constructs a new {@code StreamCorruptedException} with its stack trace
      * filled in.
-     * 
-     * @since Android 1.0
      */
     public StreamCorruptedException() {
         super();
@@ -48,7 +44,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public StreamCorruptedException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/io/StreamTokenizer.java b/libcore/luni/src/main/java/java/io/StreamTokenizer.java
index 391fca8..c87a053 100644
--- a/libcore/luni/src/main/java/java/io/StreamTokenizer.java
+++ b/libcore/luni/src/main/java/java/io/StreamTokenizer.java
@@ -23,51 +23,37 @@
  * and different comment styles. The class can be used for limited processing
  * of source code of programming languages like Java, although it is nowhere
  * near a full parser.
- * 
- * @since Android 1.0
  */
 public class StreamTokenizer {
     /**
      * Contains a number if the current token is a number ({@code ttype} ==
      * {@code TT_NUMBER}).
-     * 
-     * @since Android 1.0
      */
     public double nval;
 
     /**
      * Contains a string if the current token is a word ({@code ttype} ==
      * {@code TT_WORD}).
-     * 
-     * @since Android 1.0
      */
     public String sval;
 
     /**
      * The constant representing the end of the stream.
-     * 
-     * @since Android 1.0
      */
     public static final int TT_EOF = -1;
 
     /**
      * The constant representing the end of the line.
-     * 
-     * @since Android 1.0
      */
     public static final int TT_EOL = '\n';
 
     /**
      * The constant representing a number token.
-     * 
-     * @since Android 1.0
      */
     public static final int TT_NUMBER = -2;
 
     /**
      * The constant representing a word token.
-     * 
-     * @since Android 1.0
      */
     public static final int TT_WORD = -3;
 
@@ -89,8 +75,6 @@
      * whether {@code eolIsSignificant} is {@code true}.</li>
      * <li> {@code TT_EOF} - the end of the stream has been reached.</li>
      * </ul>
-     * 
-     * @since Android 1.0
      */
     public int ttype = TT_UNKNOWN;
 
@@ -135,7 +119,7 @@
      * specification.
      */
     private StreamTokenizer() {
-        /**
+        /*
          * Initialize the default state per specification. All byte values 'A'
          * through 'Z', 'a' through 'z', and '\u00A0' through '\u00FF' are
          * considered to be alphabetic.
@@ -176,7 +160,6 @@
      * @throws NullPointerException
      *             if {@code is} is {@code null}.
      * @deprecated Use {@link #StreamTokenizer(Reader)}
-     * @since Android 1.0
      */
     @Deprecated
     public StreamTokenizer(InputStream is) {
@@ -205,7 +188,6 @@
      * 
      * @param r
      *            the source reader from which to parse tokens.
-     * @since Android 1.0
      */
     public StreamTokenizer(Reader r) {
         this();
@@ -221,7 +203,6 @@
      * 
      * @param ch
      *            the character to be considered a comment character.
-     * @since Android 1.0
      */
     public void commentChar(int ch) {
         if (0 <= ch && ch < tokenTypes.length) {
@@ -235,7 +216,6 @@
      * 
      * @param flag
      *            {@code true} if EOL is significant, {@code false} otherwise.
-     * @since Android 1.0
      */
     public void eolIsSignificant(boolean flag) {
         isEOLSignificant = flag;
@@ -245,7 +225,6 @@
      * Returns the current line number.
      * 
      * @return this tokenizer's current line number.
-     * @since Android 1.0
      */
     public int lineno() {
         return lineNumber;
@@ -258,7 +237,6 @@
      * @param flag
      *            {@code true} if {@code sval} should be converted to lower
      *            case, {@code false} otherwise.
-     * @since Android 1.0
      */
     public void lowerCaseMode(boolean flag) {
         forceLowercase = flag;
@@ -272,7 +250,6 @@
      * @return the value of {@code ttype}.
      * @throws IOException
      *             if an I/O error occurs while parsing the next token.
-     * @since Android 1.0             
      */
     public int nextToken() throws IOException {
         if (pushBackToken) {
@@ -359,7 +336,7 @@
         }
         // Check for words
         if ((currentType & TOKEN_WORD) != 0) {
-            StringBuffer word = new StringBuffer(20);
+            StringBuilder word = new StringBuilder(20);
             while (true) {
                 word.append((char) currentChar);
                 currentChar = read();
@@ -376,7 +353,7 @@
         // Check for quoted character
         if (currentType == TOKEN_QUOTE) {
             int matchQuote = currentChar;
-            StringBuffer quoteString = new StringBuffer();
+            StringBuilder quoteString = new StringBuilder();
             int peekOne = read();
             while (peekOne >= 0 && peekOne != matchQuote && peekOne != '\r'
                     && peekOne != '\n') {
@@ -507,7 +484,6 @@
      * 
      * @param ch
      *            the character to be considered an ordinary character.
-     * @since Android 1.0
      */
     public void ordinaryChar(int ch) {
         if (0 <= ch && ch < tokenTypes.length) {
@@ -525,7 +501,6 @@
      *            the first character in the range of ordinary characters.
      * @param hi
      *            the last character in the range of ordinary characters.
-     * @since Android 1.0
      */
     public void ordinaryChars(int low, int hi) {
         if (low < 0) {
@@ -541,8 +516,6 @@
 
     /**
      * Specifies that this tokenizer shall parse numbers.
-     * 
-     * @since Android 1.0
      */
     public void parseNumbers() {
         for (int i = '0'; i <= '9'; i++) {
@@ -555,8 +528,6 @@
     /**
      * Indicates that the current token should be pushed back and returned again
      * the next time {@code nextToken()} is called.
-     * 
-     * @since Android 1.0
      */
     public void pushBack() {
         pushBackToken = true;
@@ -568,7 +539,6 @@
      * 
      * @param ch
      *            the character to be considered a quote character.
-     * @since Android 1.0
      */
     public void quoteChar(int ch) {
         if (0 <= ch && ch < tokenTypes.length) {
@@ -586,8 +556,6 @@
 
     /**
      * Specifies that all characters shall be treated as ordinary characters.
-     * 
-     * @since Android 1.0
      */
     public void resetSyntax() {
         for (int i = 0; i < 256; i++) {
@@ -602,7 +570,6 @@
      * @param flag
      *            {@code true} if {@code //} should be recognized as the start
      *            of a comment, {@code false} otherwise.
-     * @since Android 1.0
      */
     public void slashSlashComments(boolean flag) {
         slashSlashComments = flag;
@@ -616,7 +583,6 @@
      * @param flag
      *            {@code true} if {@code /*} should be recognized as the start
      *            of a comment, {@code false} otherwise.
-     * @since Android 1.0
      */
     public void slashStarComments(boolean flag) {
         slashStarComments = flag;
@@ -626,7 +592,6 @@
      * Returns the state of this tokenizer in a readable format.
      * 
      * @return the current state of this tokenizer.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -648,8 +613,6 @@
                 result.append(sval);
                 break;
             default:
-                // BEGIN android-changed
-                // copied from a newer version of harmony
                 if (ttype == TT_UNKNOWN || tokenTypes[ttype] == TOKEN_QUOTE) {
                     result.append(sval);
                 } else {
@@ -657,7 +620,6 @@
                     result.append((char) ttype);
                     result.append('\'');
                 }
-                // END android-changed
         }
         result.append("], line "); //$NON-NLS-1$
         result.append(lineNumber);
@@ -672,7 +634,6 @@
      *            the first character in the range of whitespace characters.
      * @param hi
      *            the last character in the range of whitespace characters.
-     * @since Android 1.0
      */
     public void whitespaceChars(int low, int hi) {
         if (low < 0) {
@@ -695,7 +656,6 @@
      *            the first character in the range of word characters.
      * @param hi
      *            the last character in the range of word characters.
-     * @since Android 1.0
      */
     public void wordChars(int low, int hi) {
         if (low < 0) {
diff --git a/libcore/luni/src/main/java/java/io/StringBufferInputStream.java b/libcore/luni/src/main/java/java/io/StringBufferInputStream.java
index 6e20ab6..cc4ab81 100644
--- a/libcore/luni/src/main/java/java/io/StringBufferInputStream.java
+++ b/libcore/luni/src/main/java/java/io/StringBufferInputStream.java
@@ -22,31 +22,23 @@
 /**
  * A specialized {@link InputStream} that reads bytes from a {@code String} in
  * a sequential manner.
- * 
+ *
  * @deprecated Use {@link StringReader}
- * 
- * @since Android 1.0
  */
 @Deprecated
 public class StringBufferInputStream extends InputStream {
     /**
      * The source string containing the data to read.
-     * 
-     * @since Android 1.0
      */
     protected String buffer;
 
     /**
      * The total number of characters in the source string.
-     * 
-     * @since Android 1.0
      */
     protected int count;
 
     /**
      * The current position within the source string.
-     * 
-     * @since Android 1.0
      */
     protected int pos;
 
@@ -54,12 +46,11 @@
      * Construct a new {@code StringBufferInputStream} with {@code str} as
      * source. The size of the stream is set to the {@code length()} of the
      * string.
-     * 
+     *
      * @param str
      *            the source string for this stream.
      * @throws NullPointerException
      *             if {@code str} is {@code null}.
-     * @since Android 1.0
      */
     public StringBufferInputStream(String str) {
         if (str == null) {
@@ -72,9 +63,8 @@
     /**
      * Returns the number of bytes that are available before this stream will
      * block.
-     * 
+     *
      * @return the number of bytes available before blocking.
-     * @since Android 1.0
      */
     @Override
     public synchronized int available() {
@@ -85,10 +75,9 @@
      * Reads a single byte from the source string and returns it as an integer
      * in the range from 0 to 255. Returns -1 if the end of the source string
      * has been reached.
-     * 
+     *
      * @return the byte read or -1 if the end of the source string has been
      *         reached.
-     * @since Android 1.0
      */
     @Override
     public synchronized int read() {
@@ -98,7 +87,7 @@
     /**
      * Reads at most {@code length} bytes from the source string and stores them
      * in the byte array {@code b} starting at {@code offset}.
-     * 
+     *
      * @param b
      *            the byte array in which to store the bytes read.
      * @param offset
@@ -114,7 +103,6 @@
      *             {@code b}.
      * @throws NullPointerException
      *             if {@code b} is {@code null}.
-     * @since Android 1.0
      */
     @Override
     public synchronized int read(byte[] b, int offset, int length) {
@@ -153,8 +141,6 @@
 
     /**
      * Resets this stream to the beginning of the source string.
-     * 
-     * @since Android 1.0
      */
     @Override
     public synchronized void reset() {
@@ -166,11 +152,10 @@
      * returns 0 if {@code n} is negative. Less than {@code n} characters are
      * skipped if the end of the source string is reached before the operation
      * completes.
-     * 
+     *
      * @param n
      *            the number of characters to skip.
      * @return the number of characters actually skipped.
-     * @since Android 1.0
      */
     @Override
     public synchronized long skip(long n) {
diff --git a/libcore/luni/src/main/java/java/io/StringReader.java b/libcore/luni/src/main/java/java/io/StringReader.java
index 3a19429..0a9e9bb 100644
--- a/libcore/luni/src/main/java/java/io/StringReader.java
+++ b/libcore/luni/src/main/java/java/io/StringReader.java
@@ -22,10 +22,8 @@
 /**
  * A specialized {@link Reader} that reads characters from a {@code String} in
  * a sequential manner.
- * 
+ *
  * @see StringWriter
- * 
- * @since Android 1.0
  */
 public class StringReader extends Reader {
     private String str;
@@ -40,13 +38,12 @@
      * Construct a new {@code StringReader} with {@code str} as source. The size
      * of the reader is set to the {@code length()} of the string and the Object
      * to synchronize access through is set to {@code str}.
-     * 
+     *
      * @param str
      *            the source string for this reader.
-     * @since Android 1.0
      */
     public StringReader(String str) {
-        super(str);
+        super();
         this.str = str;
         this.count = str.length();
     }
@@ -55,22 +52,15 @@
      * Closes this reader. Once it is closed, read operations on this reader
      * will throw an {@code IOException}. Only the first invocation of this
      * method has any effect.
-     * 
-     * @since Android 1.0
      */
     @Override
     public void close() {
-        synchronized (lock) {
-            if (isClosed()) {
-                return;
-            }
-            str = null;
-        }
+        str = null;
     }
 
     /**
      * Returns a boolean indicating whether this reader is closed.
-     * 
+     *
      * @return {@code true} if closed, otherwise {@code false}.
      */
     private boolean isClosed() {
@@ -81,7 +71,7 @@
      * Sets a mark position in this reader. The parameter {@code readLimit} is
      * ignored for this class. Calling {@code reset()} will reposition the
      * reader back to the marked position.
-     * 
+     *
      * @param readLimit
      *            ignored for {@code StringReader} instances.
      * @throws IllegalArgumentException
@@ -90,7 +80,6 @@
      *             if this reader is closed.
      * @see #markSupported()
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public void mark(int readLimit) throws IOException {
@@ -109,9 +98,8 @@
     /**
      * Indicates whether this reader supports the {@code mark()} and {@code
      * reset()} methods. This implementation returns {@code true}.
-     * 
+     *
      * @return always {@code true}.
-     * @since Android 1.0
      */
     @Override
     public boolean markSupported() {
@@ -122,12 +110,11 @@
      * Reads a single character from the source string and returns it as an
      * integer with the two higher-order bytes set to 0. Returns -1 if the end
      * of the source string has been reached.
-     * 
+     *
      * @return the character read or -1 if the end of the source string has been
      *         reached.
      * @throws IOException
      *             if this reader is closed.
-     * @since Android 1.0
      */
     @Override
     public int read() throws IOException {
@@ -147,7 +134,7 @@
      * them at {@code offset} in the character array {@code buf}. Returns the
      * number of characters actually read or -1 if the end of the source string
      * has been reached.
-     * 
+     *
      * @param buf
      *            the character array to store the characters read.
      * @param offset
@@ -162,14 +149,12 @@
      *             {@code offset + len} is greater than the size of {@code buf}.
      * @throws IOException
      *             if this reader is closed.
-     * @since Android 1.0
      */
     @Override
     public int read(char[] buf, int offset, int len) throws IOException {
         // 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.
@@ -178,14 +163,18 @@
         if (buf == null) {
             throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
         }
-        if ((offset | len) < 0 || len > buf.length - offset) {
-            throw new ArrayIndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
-        }
-        // END android-changed
         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()) {
                 throw new IOException(Msg.getString("K0083")); //$NON-NLS-1$
             }
+            if (len == 0) {
+                return 0;
+            }
             if (pos == this.count) {
                 return -1;
             }
@@ -200,13 +189,12 @@
     /**
      * Indicates whether this reader is ready to be read without blocking. This
      * implementation always returns {@code true}.
-     * 
+     *
      * @return always {@code true}.
      * @throws IOException
      *             if this reader is closed.
      * @see #read()
      * @see #read(char[], int, int)
-     * @since Android 1.0
      */
     @Override
     public boolean ready() throws IOException {
@@ -223,12 +211,11 @@
      * Invocations of {@code read()} and {@code skip()} will occur from this new
      * location. If this reader has not been marked, it is reset to the
      * beginning of the source string.
-     * 
+     *
      * @throws IOException
      *             if this reader is closed.
      * @see #mark(int)
      * @see #markSupported()
-     * @since Android 1.0
      */
     @Override
     public void reset() throws IOException {
@@ -244,7 +231,7 @@
      * Skips {@code amount} characters in the source string. Subsequent calls of
      * {@code read} methods will not return these characters unless {@code
      * reset()} is used.
-     * 
+     *
      * @param ns
      *            the maximum number of characters to skip.
      * @return the number of characters actually skipped or 0 if {@code ns < 0}.
@@ -253,7 +240,6 @@
      * @see #mark(int)
      * @see #markSupported()
      * @see #reset()
-     * @since Android 1.0
      */
     @Override
     public long skip(long ns) throws IOException {
diff --git a/libcore/luni/src/main/java/java/io/StringWriter.java b/libcore/luni/src/main/java/java/io/StringWriter.java
index 01a6db8..45f6c16 100644
--- a/libcore/luni/src/main/java/java/io/StringWriter.java
+++ b/libcore/luni/src/main/java/java/io/StringWriter.java
@@ -26,10 +26,8 @@
  * in a sequential manner, appending them in the process. The result can later
  * be queried using the {@link #StringWriter(int)} or {@link #toString()}
  * methods.
- * 
+ *
  * @see StringReader
- * 
- * @since Android 1.0
  */
 public class StringWriter extends Writer {
 
@@ -40,8 +38,6 @@
      * allocated with the default size of 16 characters. The {@code
      * StringBuffer} is also the {@code lock} used to synchronize access to this
      * writer.
-     * 
-     * @since Android 1.0
      */
     public StringWriter() {
         super();
@@ -54,10 +50,9 @@
      * allocated with a size of {@code initialSize} characters. The {@code
      * StringBuffer} is also the {@code lock} used to synchronize access to this
      * writer.
-     * 
+     *
      * @param initialSize
      *            the intial size of the target string buffer.
-     * @since Android 1.0
      */
     public StringWriter(int initialSize) {
         if (initialSize < 0) {
@@ -71,10 +66,9 @@
      * Calling this method has no effect. In contrast to most {@code Writer} subclasses,
      * the other methods in {@code StringWriter} do not throw an {@code IOException} if
      * {@code close()} has been called.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this writer.
-     * @since Android 1.0
      */
     @Override
     public void close() throws IOException {
@@ -83,8 +77,6 @@
 
     /**
      * Calling this method has no effect.
-     * 
-     * @since Android 1.0
      */
     @Override
     public void flush() {
@@ -94,33 +86,27 @@
     /**
      * Gets a reference to this writer's internal {@link StringBuffer}. Any
      * changes made to the returned buffer are reflected in this writer.
-     * 
+     *
      * @return a reference to this writer's internal {@code StringBuffer}.
-     * @since Android 1.0
      */
     public StringBuffer getBuffer() {
-        synchronized (lock) {
-            return buf;
-        }
+        return buf;
     }
 
     /**
      * Gets a copy of the contents of this writer as a string.
-     * 
+     *
      * @return this writer's contents as a string.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
-        synchronized (lock) {
-            return buf.toString();
-        }
+        return buf.toString();
     }
 
     /**
      * Writes {@code count} characters starting at {@code offset} in {@code buf}
      * to this writer's {@code StringBuffer}.
-     * 
+     *
      * @param cbuf
      *            the non-null character array to write.
      * @param offset
@@ -130,7 +116,6 @@
      * @throws IndexOutOfBoundsException
      *             if {@code offset < 0} or {@code count < 0}, or if {@code
      *             offset + count} is greater than the size of {@code buf}.
-     * @since Android 1.0
      */
     @Override
     public void write(char[] cbuf, int offset, int count) {
@@ -147,45 +132,40 @@
             throw new IndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
         }
         // END android-changed
-        synchronized (lock) {
-            this.buf.append(cbuf, offset, count);
+        if (count == 0) {
+            return;
         }
+        buf.append(cbuf, offset, count);
     }
 
     /**
      * Writes one character to this writer's {@code StringBuffer}. Only the two
      * least significant bytes of the integer {@code oneChar} are written.
-     * 
+     *
      * @param oneChar
      *            the character to write to this writer's {@code StringBuffer}.
-     * @since Android 1.0
      */
     @Override
     public void write(int oneChar) {
-        synchronized (lock) {
-            buf.append((char) oneChar);
-        }
+        buf.append((char) oneChar);
     }
 
     /**
      * Writes the characters from the specified string to this writer's {@code
      * StringBuffer}.
-     * 
+     *
      * @param str
      *            the non-null string containing the characters to write.
-     * @since Android 1.0
      */
     @Override
     public void write(String str) {
-        synchronized (lock) {
-            buf.append(str);
-        }
+        buf.append(str);
     }
 
     /**
      * Writes {@code count} characters from {@code str} starting at {@code
      * offset} to this writer's {@code StringBuffer}.
-     * 
+     *
      * @param str
      *            the non-null string containing the characters to write.
      * @param offset
@@ -195,24 +175,20 @@
      * @throws StringIndexOutOfBoundsException
      *             if {@code offset < 0} or {@code count < 0}, or if {@code
      *             offset + count} is greater than the length of {@code str}.
-     * @since Android 1.0
      */
     @Override
     public void write(String str, int offset, int count) {
         String sub = str.substring(offset, offset + count);
-        synchronized (lock) {
-            buf.append(sub);
-        }
+        buf.append(sub);
     }
 
     /**
      * Appends the character {@code c} to this writer's {@code StringBuffer}.
      * This method works the same way as {@link #write(int)}.
-     * 
+     *
      * @param c
      *            the character to append to the target stream.
      * @return this writer.
-     * @since Android 1.0
      */
     @Override
     public StringWriter append(char c) {
@@ -225,18 +201,17 @@
      * StringBuffer}. This method works the same way as {@code
      * StringWriter.write(csq.toString())}. If {@code csq} is {@code null}, then
      * the string "null" is written to the target stream.
-     * 
+     *
      * @param csq
      *            the character sequence appended to the target.
      * @return this writer.
-     * @since Android 1.0
      */
     @Override
     public StringWriter append(CharSequence csq) {
         if (null == csq) {
-            append(TOKEN_NULL, 0, TOKEN_NULL.length());
+            write(TOKEN_NULL);
         } else {
-            append(csq, 0, csq.length());
+            write(csq.toString());
         }
         return this;
     }
@@ -247,7 +222,7 @@
      * StringWriter.writer(csq.subsequence(start, end).toString())}. If {@code
      * csq} is {@code null}, then the specified subsequence of the string "null"
      * will be written to the target.
-     * 
+     *
      * @param csq
      *            the character sequence appended to the target.
      * @param start
@@ -261,7 +236,6 @@
      *             if {@code start > end}, {@code start < 0}, {@code end < 0} or
      *             either {@code start} or {@code end} are greater or equal than
      *             the length of {@code csq}.
-     * @since Android 1.0
      */
     @Override
     public StringWriter append(CharSequence csq, int start, int end) {
diff --git a/libcore/luni/src/main/java/java/io/SyncFailedException.java b/libcore/luni/src/main/java/java/io/SyncFailedException.java
index 2f8d9c7..c4f7340 100644
--- a/libcore/luni/src/main/java/java/io/SyncFailedException.java
+++ b/libcore/luni/src/main/java/java/io/SyncFailedException.java
@@ -20,8 +20,6 @@
 /**
  * Signals that the {@link FileDescriptor#sync()} method has failed to
  * complete.
- * 
- * @since Android 1.0
  */
 public class SyncFailedException extends IOException {
 
@@ -33,7 +31,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public SyncFailedException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/io/UTFDataFormatException.java b/libcore/luni/src/main/java/java/io/UTFDataFormatException.java
index 20a7abe..215e3e2 100644
--- a/libcore/luni/src/main/java/java/io/UTFDataFormatException.java
+++ b/libcore/luni/src/main/java/java/io/UTFDataFormatException.java
@@ -22,9 +22,7 @@
  * likely while reading some {@link DataInputStream}.
  * 
  * @see DataInputStream#readUTF()
-  * 
- * @since Android 1.0
-*/
+ */
 public class UTFDataFormatException extends IOException {
 
     private static final long serialVersionUID = 420743449228280612L;
@@ -32,8 +30,6 @@
     /**
      * Constructs a new {@code UTFDataFormatException} with its stack trace
      * filled in.
-     * 
-     * @since Android 1.0
      */
     public UTFDataFormatException() {
         super();
@@ -45,7 +41,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public UTFDataFormatException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/io/UnsupportedEncodingException.java b/libcore/luni/src/main/java/java/io/UnsupportedEncodingException.java
index deeab29..eca6c81 100644
--- a/libcore/luni/src/main/java/java/io/UnsupportedEncodingException.java
+++ b/libcore/luni/src/main/java/java/io/UnsupportedEncodingException.java
@@ -18,11 +18,8 @@
 package java.io;
 
 /**
- * Signals that a requested character encoding is not available, either because
- * it is not included a specific Android system, or because the encoding name
- * is simply incorrect.
- * 
- * @since Android 1.0
+ * Thrown when a program asks for a particular character converter that is
+ * unavailable.
  */
 public class UnsupportedEncodingException extends IOException {
 
@@ -31,8 +28,6 @@
     /**
      * Constructs a new {@code UnsupportedEncodingException} with its stack
      * trace filled in.
-     * 
-     * @since Android 1.0
      */
     public UnsupportedEncodingException() {
         super();
@@ -44,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public UnsupportedEncodingException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/io/WriteAbortedException.java b/libcore/luni/src/main/java/java/io/WriteAbortedException.java
index 02c2f70..11ee1fe 100644
--- a/libcore/luni/src/main/java/java/io/WriteAbortedException.java
+++ b/libcore/luni/src/main/java/java/io/WriteAbortedException.java
@@ -26,8 +26,6 @@
  * object.
  * 
  * @see ObjectInputStream#readObject()
- * 
- * @since Android 1.0
  */
 public class WriteAbortedException extends ObjectStreamException {
 
@@ -36,8 +34,6 @@
     /**
      * The exception that occured when writeObject() was attempting to serialize
      * the object.
-     * 
-     * @since Android 1.0
      */
     public Exception detail;
 
@@ -50,7 +46,6 @@
      *            the detail message for this exception.
      * @param rootCause
      *            the exception that was thrown when serializing the object.
-     * @since Android 1.0
      */
     public WriteAbortedException(String detailMessage, Exception rootCause) {
         super(detailMessage);
@@ -64,7 +59,6 @@
      * time.
      * 
      * @return the exception message.
-     * @since Android 1.0
      */
     @Override
     public String getMessage() {
@@ -79,7 +73,6 @@
      * Gets the cause of this exception or {@code null} if there is no cause.
      * 
      * @return the exception cause.
-     * @since Android 1.0
      */
     @Override
     public Throwable getCause() {
diff --git a/libcore/luni/src/main/java/java/io/Writer.java b/libcore/luni/src/main/java/java/io/Writer.java
index 5505e80..dfb37c5 100644
--- a/libcore/luni/src/main/java/java/io/Writer.java
+++ b/libcore/luni/src/main/java/java/io/Writer.java
@@ -31,10 +31,8 @@
  * <p>
  * Many specialized readers for purposes like reading from a file already exist
  * in this package.
- * 
+ *
  * @see Reader
- * 
- * @since Android 1.0
  */
 public abstract class Writer implements Appendable, Closeable, Flushable {
 
@@ -42,16 +40,12 @@
 
     /**
      * The object used to synchronize access to the writer.
-     * 
-     * @since Android 1.0
      */
     protected Object lock;
 
     /**
      * Constructs a new {@code Writer} with {@code this} as the object used to
      * synchronize critical sections.
-     * 
-     * @since Android 1.0
      */
     protected Writer() {
         super();
@@ -61,12 +55,11 @@
     /**
      * Constructs a new {@code Writer} with {@code lock} used to synchronize
      * critical sections.
-     * 
+     *
      * @param lock
      *            the {@code Object} used to synchronize critical sections.
      * @throws NullPointerException
      *             if {@code lock} is {@code null}.
-     * @since Android 1.0
      */
     protected Writer(Object lock) {
         if (lock == null) {
@@ -78,31 +71,28 @@
     /**
      * Closes this writer. Implementations of this method should free any
      * resources associated with the writer.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this writer.
-     * @since Android 1.0
      */
     public abstract void close() throws IOException;
 
     /**
      * Flushes this writer. Implementations of this method should ensure that
      * all buffered characters are written to the target.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while flushing this writer.
-     * @since Android 1.0
      */
     public abstract void flush() throws IOException;
 
     /**
      * Writes the entire character buffer {@code buf} to the target.
-     * 
+     *
      * @param buf
      *            the non-null array containing characters to write.
      * @throws IOException
      *             if this writer is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public void write(char[] buf) throws IOException {
         // BEGIN android-note
@@ -114,7 +104,7 @@
     /**
      * Writes {@code count} characters starting at {@code offset} in {@code buf}
      * to the target.
-     * 
+     *
      * @param buf
      *            the non-null character array to write.
      * @param offset
@@ -126,7 +116,6 @@
      *             offset + count} is greater than the size of {@code buf}.
      * @throws IOException
      *             if this writer is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public abstract void write(char[] buf, int offset, int count)
             throws IOException;
@@ -137,12 +126,11 @@
     /**
      * Writes one character to the target. Only the two least significant bytes
      * of the integer {@code oneChar} are written.
-     * 
+     *
      * @param oneChar
      *            the character to write to the target.
      * @throws IOException
      *             if this writer is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public void write(int oneChar) throws IOException {
         synchronized (lock) {
@@ -154,12 +142,11 @@
 
     /**
      * Writes the characters from the specified string to the target.
-     * 
+     *
      * @param str
      *            the non-null string containing the characters to write.
      * @throws IOException
      *             if this writer is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public void write(String str) throws IOException {
         char buf[] = new char[str.length()];
@@ -172,7 +159,7 @@
     /**
      * Writes {@code count} characters from {@code str} starting at {@code
      * offset} to the target.
-     * 
+     *
      * @param str
      *            the non-null string containing the characters to write.
      * @param offset
@@ -184,7 +171,6 @@
      * @throws IndexOutOfBoundsException
      *             if {@code offset < 0} or {@code count < 0}, or if {@code
      *             offset + count} is greater than the length of {@code str}.
-     * @since Android 1.0
      */
     public void write(String str, int offset, int count) throws IOException {
         if (count < 0) { // other cases tested by getChars()
@@ -201,13 +187,12 @@
     /**
      * Appends the character {@code c} to the target. This method works the same
      * way as {@link #write(int)}.
-     * 
+     *
      * @param c
      *            the character to append to the target stream.
      * @return this writer.
      * @throws IOException
      *             if this writer is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public Writer append(char c) throws IOException {
         write(c);
@@ -219,13 +204,12 @@
      * works the same way as {@code Writer.write(csq.toString())}. If {@code
      * csq} is {@code null}, then the string "null" is written to the target
      * stream.
-     * 
+     *
      * @param csq
      *            the character sequence appended to the target.
      * @return this writer.
      * @throws IOException
      *             if this writer is closed or another I/O error occurs.
-     * @since Android 1.0
      */
     public Writer append(CharSequence csq) throws IOException {
         if (null == csq) {
@@ -242,7 +226,7 @@
      * Writer.writer(csq.subsequence(start, end).toString())}. If {@code
      * csq} is {@code null}, then the specified subsequence of the string "null"
      * will be written to the target.
-     * 
+     *
      * @param csq
      *            the character sequence appended to the target.
      * @param start
@@ -258,7 +242,6 @@
      *             if {@code start > end}, {@code start < 0}, {@code end < 0} or
      *             either {@code start} or {@code end} are greater or equal than
      *             the length of {@code csq}.
-     * @since Android 1.0
      */
     public Writer append(CharSequence csq, int start, int end)
             throws IOException {
diff --git a/libcore/luni/src/main/java/java/lang/AbstractMethodError.java b/libcore/luni/src/main/java/java/lang/AbstractMethodError.java
index cdfa0ec..4d5238a 100644
--- a/libcore/luni/src/main/java/java/lang/AbstractMethodError.java
+++ b/libcore/luni/src/main/java/java/lang/AbstractMethodError.java
@@ -22,8 +22,6 @@
  * <p>
  * Note that this can only occur when inconsistent class files have been loaded,
  * since invoking an abstract method is a compile time error.
- * </p>
- * @since Android 1.0
  */
 public class AbstractMethodError extends IncompatibleClassChangeError {
 
@@ -32,8 +30,6 @@
     /**
      * Constructs a new {@code AbstractMethodError} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public AbstractMethodError() {
         super();
@@ -42,10 +38,9 @@
     /**
      * Constructs a new {@code AbstractMethodError} with the current stack trace
      * and the specified detail message.
-     * 
+     *
      * @param detailMessage
      *            the detail message for this error.
-     * @since Android 1.0
      */
     public AbstractMethodError(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/AbstractStringBuilder.java b/libcore/luni/src/main/java/java/lang/AbstractStringBuilder.java
index 39459a0..c481e11 100644
--- a/libcore/luni/src/main/java/java/lang/AbstractStringBuilder.java
+++ b/libcore/luni/src/main/java/java/lang/AbstractStringBuilder.java
@@ -23,15 +23,13 @@
 import org.apache.harmony.luni.util.Msg;
 
 /**
- * <p>
  * A modifiable {@link CharSequence sequence of characters} for use in creating
  * and modifying Strings. This class is intended as a base class for
  * {@link StringBuffer} and {@link StringBuilder}.
- * </p>
  *
  * @see StringBuffer
  * @see StringBuilder
- * @since Android 1.0
+ * @since 1.5
  */
 abstract class AbstractStringBuilder {
 
@@ -95,8 +93,8 @@
     }
 
     private void enlargeBuffer(int min) {
-        int twice = (value.length << 1) + 2;
-        char[] newData = new char[min > twice ? min : twice];
+        int newSize = ((value.length >> 1) + value.length) + 2;
+        char[] newData = new char[min > newSize ? min : newSize];
         System.arraycopy(value, 0, newData, 0, count);
         value = newData;
         shared = false;
@@ -106,9 +104,6 @@
         int newSize = count + 4;
         if (newSize > value.length) {
             enlargeBuffer(newSize);
-        } else if (shared) {
-            value = value.clone();
-            shared = false;
         }
         value[count++] = 'n';
         value[count++] = 'u';
@@ -120,9 +115,6 @@
         int newSize = count + chars.length;
         if (newSize > value.length) {
             enlargeBuffer(newSize);
-        } else if (shared) {
-            value = value.clone();
-            shared = false;
         }
         System.arraycopy(chars, 0, value, count, chars.length);
         count = newSize;
@@ -137,9 +129,6 @@
             int newSize = count + length;
             if (newSize > value.length) {
                 enlargeBuffer(newSize);
-            } else if (shared) {
-                value = value.clone();
-                shared = false;
             }
             System.arraycopy(chars, start, value, count, length);
             count = newSize;
@@ -152,10 +141,6 @@
         if (count == value.length) {
             enlargeBuffer(count + 1);
         }
-        if (shared) {
-            value = value.clone();
-            shared = false;
-        }
         value[count++] = ch;
     }
 
@@ -168,9 +153,6 @@
         int newSize = count + adding;
         if (newSize > value.length) {
             enlargeBuffer(newSize);
-        } else if (shared) {
-            value = value.clone();
-            shared = false;
         }
         // BEGIN android-changed
         string._getChars(0, adding, value, count);
@@ -213,7 +195,7 @@
 
     /**
      * Returns the number of characters that can be held without growing.
-     * 
+     *
      * @return the capacity
      * @see #ensureCapacity
      * @see #length
@@ -224,7 +206,7 @@
 
     /**
      * Retrieves the character at the {@code index}.
-     * 
+     *
      * @param index
      *            the index of the character to retrieve.
      * @return the char value.
@@ -249,7 +231,7 @@
             }
             if (end > start) {
                 int length = count - end;
-                if (length > 0) {
+                if (length >= 0) {
                     if (!shared) {
                         System.arraycopy(value, end, value, start, length);
                     } else {
@@ -296,20 +278,21 @@
      * value of either the {@code minimumCapacity} or the current capacity
      * multiplied by two plus two. Although this is the general policy, there is
      * no guarantee that the capacity will change.
-     * 
+     *
      * @param min
      *            the new minimum capacity to set.
      */
     public void ensureCapacity(int min) {
         if (min > value.length) {
-            enlargeBuffer(min);
+            int twice = (value.length << 1) + 2;
+            enlargeBuffer(twice > min ? twice : min);
         }
     }
 
     /**
      * Copies the requested sequence of characters to the {@code char[]} passed
      * starting at {@code destStart}.
-     * 
+     *
      * @param start
      *            the inclusive start index of the characters to copy.
      * @param end
@@ -343,7 +326,7 @@
         }
     }
 
-    final void insert0(int index, char chars[], int start, int length) {
+    final void insert0(int index, char[] chars, int start, int length) {
         if (0 <= index && index <= count) {
             // start + length could overflow, start/length maybe MaxInt
             if (start >= 0 && 0 <= length && length <= chars.length - start) {
@@ -354,8 +337,9 @@
                 }
                 return;
             }
-            throw new StringIndexOutOfBoundsException("offset " + start
-                    + ", len " + length + ", array.length " + chars.length);
+            throw new StringIndexOutOfBoundsException("offset " + start //$NON-NLS-1$
+                    + ", length " + length //$NON-NLS-1$
+                    + ", char[].length " + chars.length); //$NON-NLS-1$
         }
         throw new StringIndexOutOfBoundsException(index);
     }
@@ -401,7 +385,7 @@
 
     /**
      * The current length.
-     * 
+     *
      * @return the number of characters contained in this instance.
      */
     public int length() {
@@ -481,15 +465,72 @@
             return;
         }
         if (!shared) {
-            for (int i = 0, end = count, mid = count / 2; i < mid; i++) {
-                char temp = value[--end];
-                value[end] = value[i];
-                value[i] = temp;
+            int end = count - 1;
+            char frontHigh = value[0];
+            char endLow = value[end];
+            boolean allowFrontSur = true, allowEndSur = true;
+            for (int i = 0, mid = count / 2; i < mid; i++, --end) {
+                char frontLow = value[i + 1];
+                char endHigh = value[end - 1];
+                boolean surAtFront = allowFrontSur && frontLow >= 0xdc00
+                        && frontLow <= 0xdfff && frontHigh >= 0xd800
+                        && frontHigh <= 0xdbff;
+                if (surAtFront && (count < 3)) {
+                    return;
+                }
+                boolean surAtEnd = allowEndSur && endHigh >= 0xd800
+                        && endHigh <= 0xdbff && endLow >= 0xdc00
+                        && endLow <= 0xdfff;
+                allowFrontSur = allowEndSur = true;
+                if (surAtFront == surAtEnd) {
+                    if (surAtFront) {
+                        // both surrogates
+                        value[end] = frontLow;
+                        value[end - 1] = frontHigh;
+                        value[i] = endHigh;
+                        value[i + 1] = endLow;
+                        frontHigh = value[i + 2];
+                        endLow = value[end - 2];
+                        i++;
+                        end--;
+                    } else {
+                        // neither surrogates
+                        value[end] = frontHigh;
+                        value[i] = endLow;
+                        frontHigh = frontLow;
+                        endLow = endHigh;
+                    }
+                } else {
+                    if (surAtFront) {
+                        // surrogate only at the front
+                        value[end] = frontLow;
+                        value[i] = endLow;
+                        endLow = endHigh;
+                        allowFrontSur = false;
+                    } else {
+                        // surrogate only at the end
+                        value[end] = frontHigh;
+                        value[i] = endHigh;
+                        frontHigh = frontLow;
+                        allowEndSur = false;
+                    }
+                }
+            }
+            if ((count & 1) == 1 && (!allowFrontSur || !allowEndSur)) {
+                value[end] = allowFrontSur ? endLow : frontHigh;
             }
         } else {
             char[] newData = new char[value.length];
             for (int i = 0, end = count; i < count; i++) {
-                newData[--end] = value[i];
+                char high = value[i];
+                if ((i + 1) < count && high >= 0xd800 && high <= 0xdbff) {
+                    char low = value[i + 1];
+                    if (low >= 0xdc00 && low <= 0xdfff) {
+                        newData[--end] = low;
+                        i++;
+                    }
+                }
+                newData[--end] = high;
             }
             value = newData;
             shared = false;
@@ -498,7 +539,7 @@
 
     /**
      * Sets the character at the {@code index}.
-     * 
+     *
      * @param index
      *            the zero-based index of the character to replace.
      * @param ch
@@ -522,7 +563,7 @@
      * Sets the current length to a new value. If the new length is larger than
      * the current length, then the new characters at the end of this object
      * will contain the {@code char} value of {@code \u0000}.
-     * 
+     *
      * @param length
      *            the new length of this StringBuffer.
      * @exception IndexOutOfBoundsException
@@ -533,16 +574,16 @@
         if (length < 0) {
             throw new StringIndexOutOfBoundsException(length);
         }
-        if (count < length) {
-            if (length > value.length) {
-                enlargeBuffer(length);
+        if (length > value.length) {
+            enlargeBuffer(length);
+        } else {
+            if (shared) {
+                char[] newData = new char[value.length];
+                System.arraycopy(value, 0, newData, 0, count);
+                value = newData;
+                shared = false;
             } else {
-                if (shared) {
-                    char[] newData = new char[value.length];
-                    System.arraycopy(value, 0, newData, 0, count);
-                    value = newData;
-                    shared = false;
-                } else {
+                if (count < length) {
                     Arrays.fill(value, count, length, (char) 0);
                 }
             }
@@ -553,7 +594,7 @@
     /**
      * Returns the String value of the subsequence from the {@code start} index
      * to the current end.
-     * 
+     *
      * @param start
      *            the inclusive start index to begin the subsequence.
      * @return a String containing the subsequence.
@@ -567,8 +608,8 @@
                 return ""; //$NON-NLS-1$
             }
 
-            shared = true;
-            return new String(start, count - start, value);
+            // Remove String sharing for more performance
+            return new String(value, start, count - start);
         }
         throw new StringIndexOutOfBoundsException(start);
     }
@@ -576,7 +617,7 @@
     /**
      * Returns the String value of the subsequence from the {@code start} index
      * to the {@code end} index.
-     * 
+     *
      * @param start
      *            the inclusive start index to begin the subsequence.
      * @param end
@@ -592,7 +633,7 @@
                 return ""; //$NON-NLS-1$
             }
 
-            shared = true;
+            // Remove String sharing for more performance
             return new String(value, start, end - start);
         }
         throw new StringIndexOutOfBoundsException();
@@ -600,7 +641,7 @@
 
     /**
      * Returns the current String representation.
-     * 
+     *
      * @return a String containing the characters in this instance.
      */
     @Override
@@ -608,8 +649,10 @@
         if (count == 0) {
             return ""; //$NON-NLS-1$
         }
-
-        if (count >= 256 && count <= (value.length >> 1)) {
+        // Optimize String sharing for more performance
+        int wasted = value.length - count;
+        if (wasted >= 256
+                || (wasted >= INITIAL_CAPACITY && wasted >= (count >> 1))) {
             return new String(value, 0, count);
         }
         shared = true;
@@ -619,7 +662,7 @@
     /**
      * Returns a {@code CharSequence} of the subsequence from the {@code start}
      * index to the {@code end} index.
-     * 
+     *
      * @param start
      *            the inclusive start index to begin the subsequence.
      * @param end
@@ -628,6 +671,7 @@
      * @throws IndexOutOfBoundsException
      *             if {@code start} is negative, greater than {@code end} or if
      *             {@code end} is greater than the current {@link #length()}.
+     * @since 1.4
      */
     public CharSequence subSequence(int start, int end) {
         return substring(start, end);
@@ -636,12 +680,13 @@
     /**
      * Searches for the first index of the specified character. The search for
      * the character starts at the beginning and moves towards the end.
-     * 
+     *
      * @param string
      *            the string to find.
      * @return the index of the specified character, -1 if the character isn't
      *         found.
      * @see #lastIndexOf(String)
+     * @since 1.4
      */
     public int indexOf(String string) {
         return indexOf(string, 0);
@@ -650,7 +695,7 @@
     /**
      * Searches for the index of the specified character. The search for the
      * character starts at the specified offset and moves towards the end.
-     * 
+     *
      * @param subString
      *            the string to find.
      * @param start
@@ -658,6 +703,7 @@
      * @return the index of the specified character, -1 if the character isn't
      *         found
      * @see #lastIndexOf(String,int)
+     * @since 1.4
      */
     public int indexOf(String subString, int start) {
         if (start < 0) {
@@ -698,12 +744,15 @@
     /**
      * Searches for the last index of the specified character. The search for
      * the character starts at the end and moves towards the beginning.
-     * 
+     *
      * @param string
      *            the string to find.
      * @return the index of the specified character, -1 if the character isn't
      *         found.
-     * @see String#lastIndexOf(String)
+     * @throws NullPointerException
+     *             if {@code string} is {@code null}.
+     * @see String#lastIndexOf(java.lang.String)
+     * @since 1.4
      */
     public int lastIndexOf(String string) {
         return lastIndexOf(string, count);
@@ -712,14 +761,17 @@
     /**
      * Searches for the index of the specified character. The search for the
      * character starts at the specified offset and moves towards the beginning.
-     * 
+     *
      * @param subString
      *            the string to find.
      * @param start
      *            the starting offset.
      * @return the index of the specified character, -1 if the character isn't
      *         found.
+     * @throws NullPointerException
+     *             if {@code subString} is {@code null}.
      * @see String#lastIndexOf(String,int)
+     * @since 1.4
      */
     public int lastIndexOf(String subString, int start) {
         int subCount = subString.length();
@@ -762,6 +814,8 @@
     /**
      * Trims off any extra capacity beyond the current length. Note, this method
      * is NOT guaranteed to change the capacity of this object.
+     *
+     * @since 1.5
      */
     public void trimToSize() {
         if (count < value.length) {
@@ -774,7 +828,7 @@
 
     /**
      * Retrieves the Unicode code point value at the {@code index}.
-     * 
+     *
      * @param index
      *            the index to the {@code char} code unit.
      * @return the Unicode code point value.
@@ -783,6 +837,7 @@
      *             {@link #length()}.
      * @see Character
      * @see Character#codePointAt(char[], int, int)
+     * @since 1.5
      */
     public int codePointAt(int index) {
         if (index < 0 || index >= count) {
@@ -793,7 +848,7 @@
 
     /**
      * Retrieves the Unicode code point value that precedes the {@code index}.
-     * 
+     *
      * @param index
      *            the index to the {@code char} code unit within this object.
      * @return the Unicode code point value.
@@ -801,7 +856,8 @@
      *             if {@code index} is less than 1 or greater than
      *             {@link #length()}.
      * @see Character
-     * @see Character#codePointBefore(char[], int)
+     * @see Character#codePointBefore(char[], int, int)
+     * @since 1.5
      */
     public int codePointBefore(int index) {
         if (index < 1 || index > count) {
@@ -811,11 +867,9 @@
     }
 
     /**
-     * <p>
      * Calculates the number of Unicode code points between {@code beginIndex}
      * and {@code endIndex}.
-     * </p>
-     * 
+     *
      * @param beginIndex
      *            the inclusive beginning index of the subsequence.
      * @param endIndex
@@ -827,6 +881,7 @@
      *             {@link #length()}.
      * @see Character
      * @see Character#codePointCount(char[], int, int)
+     * @since 1.5
      */
     public int codePointCount(int beginIndex, int endIndex) {
         if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) {
@@ -837,11 +892,9 @@
     }
 
     /**
-     * <p>
      * Returns the index that is offset {@code codePointOffset} code points from
      * {@code index}.
-     * </p>
-     * 
+     *
      * @param index
      *            the index to calculate the offset from.
      * @param codePointOffset
@@ -855,6 +908,7 @@
      *             {@code codePointOffset}.
      * @see Character
      * @see Character#offsetByCodePoints(char[], int, int, int, int)
+     * @since 1.5
      */
     public int offsetByCodePoints(int index, int codePointOffset) {
         return Character.offsetByCodePoints(value, 0, count, index,
diff --git a/libcore/luni/src/main/java/java/lang/Appendable.java b/libcore/luni/src/main/java/java/lang/Appendable.java
index 1b4e702..ca4b532 100644
--- a/libcore/luni/src/main/java/java/lang/Appendable.java
+++ b/libcore/luni/src/main/java/java/lang/Appendable.java
@@ -27,16 +27,13 @@
  * <p>
  * {@code Appendable} itself does not guarantee thread safety. This
  * responsibility is up to the implementing class.
- * </p>
  * <p>
  * Implementing classes can choose different exception handling mechanism. They
  * can choose to throw exceptions other than {@code IOException} or they do not
  * throw any exceptions at all and use error codes instead.
- * </p>
- * @since Android 1.0
  */
 public interface Appendable {
-    
+
     /**
      * Appends the specified character.
      * 
@@ -45,7 +42,6 @@
      * @return this {@code Appendable}.
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
     Appendable append(char c) throws IOException;
 
@@ -55,14 +51,12 @@
      * limited size.
      * <p>
      * If {@code csq} is {@code null}, the characters "null" are appended.
-     * </p>
-     * 
+     *
      * @param csq
      *            the character sequence to append.
      * @return this {@code Appendable}.
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
     Appendable append(CharSequence csq) throws IOException;
 
@@ -73,7 +67,6 @@
      * to calling {@code append(csq.subSequence(start, end))}.
      * <p>
      * If {@code csq} is {@code null}, the characters "null" are appended.
-     * </p>
      * 
      * @param csq
      *            the character sequence to append.
@@ -89,7 +82,6 @@
      *             or {@code end} is greater than the length of {@code csq}.
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
     Appendable append(CharSequence csq, int start, int end) throws IOException;
 }
diff --git a/libcore/luni/src/main/java/java/lang/ArithmeticException.java b/libcore/luni/src/main/java/java/lang/ArithmeticException.java
index 74671fc..a6ab2a0 100644
--- a/libcore/luni/src/main/java/java/lang/ArithmeticException.java
+++ b/libcore/luni/src/main/java/java/lang/ArithmeticException.java
@@ -19,8 +19,6 @@
 
 /**
  * Thrown when the an invalid arithmetic operation is attempted.
- * 
- * @since Android 1.0
  */
 public class ArithmeticException extends RuntimeException {
 
@@ -29,8 +27,6 @@
     /**
      * Constructs a new {@code ArithmeticException} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public ArithmeticException() {
         super();
@@ -39,10 +35,9 @@
     /**
      * Constructs a new {@code ArithmeticException} with the current stack trace
      * and the specified detail message.
-     * 
+     *
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public ArithmeticException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java b/libcore/luni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java
index 0f231d3..d43a7e6 100644
--- a/libcore/luni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java
+++ b/libcore/luni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java
@@ -22,8 +22,6 @@
 /**
  * Thrown when the an array is indexed with a value less than zero, or greater
  * than or equal to the size of the array.
- * 
- * @since Android 1.0
  */
 public class ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException {
 
@@ -32,8 +30,6 @@
     /**
      * Constructs a new {@code ArrayIndexOutOfBoundsException} that includes the
      * current stack trace.
-     * 
-     * @since Android 1.0
      */
     public ArrayIndexOutOfBoundsException() {
         super();
@@ -46,7 +42,6 @@
      * 
      * @param index
      *            the invalid index.
-     * @since Android 1.0
      */
     public ArrayIndexOutOfBoundsException(int index) {
         super(Msg.getString("K0052", index)); //$NON-NLS-1$
@@ -55,10 +50,9 @@
     /**
      * Constructs a new {@code ArrayIndexOutOfBoundsException} with the current
      * stack trace and the specified detail message.
-     * 
+     *
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public ArrayIndexOutOfBoundsException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/ArrayStoreException.java b/libcore/luni/src/main/java/java/lang/ArrayStoreException.java
index b69697a..6cb9c8f 100644
--- a/libcore/luni/src/main/java/java/lang/ArrayStoreException.java
+++ b/libcore/luni/src/main/java/java/lang/ArrayStoreException.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when a program attempts to store an element of an incompatible type in
  * an array.
- * 
- * @since Android 1.0
  */
 public class ArrayStoreException extends RuntimeException {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code ArrayStoreException} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public ArrayStoreException() {
         super();
@@ -40,10 +36,9 @@
     /**
      * Constructs a new {@code ArrayStoreException} with the current stack trace
      * and the specified detail message.
-     * 
+     *
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public ArrayStoreException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/AssertionError.java b/libcore/luni/src/main/java/java/lang/AssertionError.java
index 8d3368b..e4d4ed0 100644
--- a/libcore/luni/src/main/java/java/lang/AssertionError.java
+++ b/libcore/luni/src/main/java/java/lang/AssertionError.java
@@ -19,8 +19,8 @@
 
 /**
  * Thrown when an assertion has failed.
- * 
- * @since Android 1.0
+ *
+ * @since 1.4
  */
 public class AssertionError extends Error {
 
@@ -28,8 +28,6 @@
 
     /**
      * Constructs a new {@code AssertionError} with no message.
-     * 
-     * @since Android 1.0
      */
     public AssertionError() {
         super();
@@ -44,7 +42,6 @@
      * @param detailMessage
      *            the object to be converted into the detail message and
      *            optionally the cause.
-     * @since Android 1.0
      */
     public AssertionError(Object detailMessage) {
         super(String.valueOf(detailMessage),
@@ -58,7 +55,6 @@
      * 
      * @param detailMessage
      *            the value to be converted into the message.
-     * @since Android 1.0
      */
     public AssertionError(boolean detailMessage) {
         this(String.valueOf(detailMessage));
@@ -70,7 +66,6 @@
      * 
      * @param detailMessage
      *            the value to be converted into the message.
-     * @since Android 1.0
      */
     public AssertionError(char detailMessage) {
         this(String.valueOf(detailMessage));
@@ -82,7 +77,6 @@
      * 
      * @param detailMessage
      *            the value to be converted into the message.
-     * @since Android 1.0
      */
     public AssertionError(int detailMessage) {
         this(Integer.toString(detailMessage));
@@ -94,7 +88,6 @@
      * 
      * @param detailMessage
      *            the value to be converted into the message.
-     * @since Android 1.0
      */
     public AssertionError(long detailMessage) {
         this(Long.toString(detailMessage));
@@ -106,7 +99,6 @@
      * 
      * @param detailMessage
      *            the value to be converted into the message.
-     * @since Android 1.0
      */
     public AssertionError(float detailMessage) {
         this(Float.toString(detailMessage));
@@ -118,7 +110,6 @@
      * 
      * @param detailMessage
      *            the value to be converted into the message.
-     * @since Android 1.0
      */
     public AssertionError(double detailMessage) {
         this(Double.toString(detailMessage));
diff --git a/libcore/luni/src/main/java/java/lang/Boolean.java b/libcore/luni/src/main/java/java/lang/Boolean.java
index c49c384..9c476a4 100644
--- a/libcore/luni/src/main/java/java/lang/Boolean.java
+++ b/libcore/luni/src/main/java/java/lang/Boolean.java
@@ -21,8 +21,8 @@
 
 /**
  * The wrapper for the primitive type {@code boolean}.
- * 
- * @since Android 1.0
+ *
+ * @since 1.0
  */
 public final class Boolean implements Serializable, Comparable<Boolean> {
 
@@ -36,8 +36,6 @@
     /**
      * The {@link Class} object that represents the primitive type {@code
      * boolean}.
-     * 
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static final Class<Boolean> TYPE = (Class<Boolean>) new boolean[0]
@@ -49,16 +47,12 @@
     /**
      * The {@code Boolean} object that represents the primitive value
      * {@code true}.
-     * 
-     * @since Android 1.0
      */
     public static final Boolean TRUE = new Boolean(true);
 
     /**
      * The {@code Boolean} object that represents the primitive value
      * {@code false}.
-     * 
-     * @since Android 1.0
      */
     public static final Boolean FALSE = new Boolean(false);
 
@@ -68,10 +62,9 @@
      * "true" using a non-case sensitive comparison, the result will be a
      * Boolean representing the primitive value {@code true}, otherwise it will
      * be a Boolean representing the primitive value {@code false}.
-     * 
+     *
      * @param string
      *            the string representing a boolean value.
-     * @since Android 1.0
      */
     public Boolean(String string) {
         this(parseBoolean(string));
@@ -80,10 +73,9 @@
     /**
      * Constructs a new {@code Boolean} with the specified primitive boolean
      * value.
-     * 
+     *
      * @param value
      *            the primitive boolean value, {@code true} or {@code false}.
-     * @since Android 1.0
      */
     public Boolean(boolean value) {
         this.value = value;
@@ -92,9 +84,8 @@
     /**
      * Gets the primitive value of this boolean, either {@code true} or
      * {@code false}.
-     * 
+     *
      * @return this object's primitive value, {@code true} or {@code false}.
-     * @since Android 1.0
      */
     public boolean booleanValue() {
         return value;
@@ -104,12 +95,11 @@
      * Compares this instance with the specified object and indicates if they
      * are equal. In order to be equal, {@code o} must be an instance of
      * {@code Boolean} and have the same boolean value as this object.
-     * 
+     *
      * @param o
      *            the object to compare this boolean with.
      * @return {@code true} if the specified object is equal to this
      *         {@code Boolean}; {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object o) {
@@ -120,7 +110,7 @@
     /**
      * Compares this object to the specified boolean object to determine their
      * relative order.
-     * 
+     *
      * @param that
      *            the boolean object to compare this object to.
      * @return 0 if the value of this boolean and the value of {@code that} are
@@ -129,7 +119,7 @@
      *         negative value if the value if this boolean is {@code false} and
      *         the value of {@code that} is {@code true}.
      * @see java.lang.Comparable
-     * @since Android 1.0
+     * @since 1.5
      */
     public int compareTo(Boolean that) {
         if (that == null) {
@@ -145,10 +135,9 @@
 
     /**
      * Returns an integer hash code for this boolean.
-     * 
+     *
      * @return this boolean's hash code, which is {@code 1231} for {@code true}
      *         values and {@code 1237} for {@code false} values.
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -158,10 +147,9 @@
     /**
      * Returns a string containing a concise, human-readable description of this
      * boolean.
-     * 
+     *
      * @return "true" if the value of this boolean is {@code true}, "false"
      *         otherwise.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -171,14 +159,13 @@
     /**
      * Returns the {@code boolean} value of the system property identified by
      * {@code string}.
-     * 
+     *
      * @param string
      *            the name of the requested system property.
      * @return {@code true} if the system property named by {@code string}
      *         exists and it is equal to "true" using case insensitive
      *         comparison, {@code false} otherwise.
      * @see System#getProperty(String)
-     * @since Android 1.0
      */
     public static boolean getBoolean(String string) {
         if (string == null || string.length() == 0) {
@@ -189,25 +176,24 @@
 
     /**
      * Parses the specified string as a {@code boolean}.
-     * 
+     *
      * @param s
      *            the string representation of a boolean value.
      * @return {@code true} if {@code s} is not {@code null} and is equal to
      *         {@code "true"} using case insensitive comparison, {@code false}
      *         otherwise.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static boolean parseBoolean(String s) {
         return "true".equalsIgnoreCase(s); //$NON-NLS-1$
     }
 
     /**
-     * Converts the specified boolean to its string representation. 
-     * 
+     * Converts the specified boolean to its string representation.
+     *
      * @param value
      *            the boolean to convert.
      * @return "true" if {@code value} is {@code true}, "false" otherwise.
-     * @since Android 1.0
      */
     public static String toString(boolean value) {
         return String.valueOf(value);
@@ -215,13 +201,12 @@
 
     /**
      * Parses the specified string as a boolean value.
-     * 
+     *
      * @param string
      *            the string representation of a boolean value.
      * @return {@code Boolean.TRUE} if {@code string} is equal to "true" using
      *         case insensitive comparison, {@code Boolean.FALSE} otherwise.
      * @see #parseBoolean(String)
-     * @since Android 1.0
      */
     public static Boolean valueOf(String string) {
         return parseBoolean(string) ? Boolean.TRUE : Boolean.FALSE;
@@ -233,13 +218,11 @@
      * If it is not necessary to get a new {@code Boolean} instance, it is
      * recommended to use this method instead of the constructor, since it
      * returns its static instances, which results in better performance.
-     * </p>
-     * 
+     *
      * @param b
      *            the boolean to convert to a {@code Boolean}.
      * @return {@code Boolean.TRUE} if {@code b} is equal to {@code true},
      *         {@code Boolean.FALSE} otherwise.
-     * @since Android 1.0
      */
     public static Boolean valueOf(boolean b) {
         return b ? Boolean.TRUE : Boolean.FALSE;
diff --git a/libcore/luni/src/main/java/java/lang/Byte.java b/libcore/luni/src/main/java/java/lang/Byte.java
index a74b539..7e20493 100644
--- a/libcore/luni/src/main/java/java/lang/Byte.java
+++ b/libcore/luni/src/main/java/java/lang/Byte.java
@@ -19,10 +19,11 @@
 
 /**
  * The wrapper for the primitive type {@code byte}.
- * 
- * @since Android 1.0
+ *
+ * @since 1.1
  */
-public final class Byte extends Number implements Comparable<Byte> {    
+public final class Byte extends Number implements Comparable<Byte> {
+
     private static final long serialVersionUID = -7183698231559129828L;
 
     /**
@@ -32,30 +33,24 @@
 
     /**
      * The maximum {@code Byte} value, 2<sup>7</sup>-1.
-     * 
-     * @since Android 1.0
      */
     public static final byte MAX_VALUE = (byte) 0x7F;
 
     /**
      * The minimum {@code Byte} value, -2<sup>7</sup>.
-     * 
-     * @since Android 1.0
      */
     public static final byte MIN_VALUE = (byte) 0x80;
-    
+
     /**
      * The number of bits needed to represent a {@code Byte} value in two's
      * complement form.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final int SIZE = 8;
 
     /**
      * The {@link Class} object that represents the primitive type {@code byte}.
-     * 
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static final Class<Byte> TYPE = (Class<Byte>) new byte[0].getClass()
@@ -63,7 +58,7 @@
 
     // Note: This can't be set to "byte.class", since *that* is
     // defined to be "java.lang.Byte.TYPE";
-    
+
     /**
      * A cache of instances used by {@link #valueOf(byte)} and auto-boxing.
      */
@@ -71,10 +66,9 @@
 
     /**
      * Constructs a new {@code Byte} with the specified primitive byte value.
-     * 
+     *
      * @param value
      *            the primitive byte value to store in the new instance.
-     * @since Android 1.0
      */
     public Byte(byte value) {
         this.value = value;
@@ -82,13 +76,12 @@
 
     /**
      * Constructs a new {@code Byte} from the specified string.
-     * 
+     *
      * @param string
      *            the string representation of a single byte value.
      * @throws NumberFormatException
      *             if {@code string} can not be decoded into a byte value.
      * @see #parseByte(String)
-     * @since Android 1.0
      */
     public Byte(String string) throws NumberFormatException {
         this(parseByte(string));
@@ -96,9 +89,8 @@
 
     /**
      * Gets the primitive value of this byte.
-     * 
+     *
      * @return this object's primitive value.
-     * @since Android 1.0
      */
     @Override
     public byte byteValue() {
@@ -108,7 +100,7 @@
     /**
      * Compares this object to the specified byte object to determine their
      * relative order.
-     * 
+     *
      * @param object
      *            the byte object to compare this object to.
      * @return a negative value if the value of this byte is less than the value
@@ -116,7 +108,7 @@
      *         {@code object} are equal; a positive value if the value of this
      *         byte is greater than the value of {@code object}.
      * @see java.lang.Comparable
-     * @since Android 1.0
+     * @since 1.2
      */
     public int compareTo(Byte object) {
         return value > object.value ? 1 : (value < object.value ? -1 : 0);
@@ -127,13 +119,12 @@
      * string can be decoded into a single byte value. The string may be an
      * optional minus sign "-" followed by a hexadecimal ("0x..." or "#..."),
      * octal ("0..."), or decimal ("...") representation of a byte.
-     * 
+     *
      * @param string
      *            a string representation of a single byte value.
      * @return a {@code Byte} containing the value represented by {@code string}.
      * @throws NumberFormatException
      *             if {@code string} can not be parsed as a byte value.
-     * @since Android 1.0
      */
     public static Byte decode(String string) throws NumberFormatException {
         int intValue = Integer.decode(string).intValue();
@@ -153,12 +144,11 @@
      * Compares this object with the specified object and indicates if they are
      * equal. In order to be equal, {@code object} must be an instance of
      * {@code Byte} and have the same byte value as this object.
-     * 
+     *
      * @param object
      *            the object to compare this byte with.
      * @return {@code true} if the specified object is equal to this
      *         {@code Byte}; {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -189,14 +179,13 @@
     /**
      * Parses the specified string as a signed decimal byte value. The ASCII
      * character \u002d ('-') is recognized as the minus sign.
-     * 
+     *
      * @param string
      *            the string representation of a single byte value.
      * @return the primitive byte value represented by {@code string}.
      * @throws NumberFormatException
      *             if {@code string} is {@code null}, has a length of zero or
      *             can not be parsed as a byte value.
-     * @since Android 1.0
      */
     public static byte parseByte(String string) throws NumberFormatException {
         int intValue = Integer.parseInt(string);
@@ -210,7 +199,7 @@
     /**
      * Parses the specified string as a signed byte value using the specified
      * radix. The ASCII character \u002d ('-') is recognized as the minus sign.
-     * 
+     *
      * @param string
      *            the string representation of a single byte value.
      * @param radix
@@ -222,7 +211,6 @@
      *             {@code radix < Character.MIN_RADIX},
      *             {@code radix > Character.MAX_RADIX}, or if {@code string}
      *             can not be parsed as a byte value.
-     * @since Android 1.0
      */
     public static byte parseByte(String string, int radix)
             throws NumberFormatException {
@@ -247,11 +235,10 @@
     /**
      * Returns a string containing a concise, human-readable description of the
      * specified byte value.
-     * 
+     *
      * @param value
      *            the byte to convert to a string.
      * @return a printable representation of {@code value}.
-     * @since Android 1.0
      */
     public static String toString(byte value) {
         return Integer.toString(value);
@@ -259,7 +246,7 @@
 
     /**
      * Parses the specified string as a signed decimal byte value.
-     * 
+     *
      * @param string
      *            the string representation of a single byte value.
      * @return a {@code Byte} instance containing the byte value represented by
@@ -268,7 +255,6 @@
      *             if {@code string} is {@code null}, has a length of zero or
      *             can not be parsed as a byte value.
      * @see #parseByte(String)
-     * @since Android 1.0
      */
     public static Byte valueOf(String string) throws NumberFormatException {
         return valueOf(parseByte(string));
@@ -277,7 +263,7 @@
     /**
      * Parses the specified string as a signed byte value using the specified
      * radix.
-     * 
+     *
      * @param string
      *            the string representation of a single byte value.
      * @param radix
@@ -290,25 +276,23 @@
      *             {@code radix > Character.MAX_RADIX}, or if {@code string}
      *             can not be parsed as a byte value.
      * @see #parseByte(String, int)
-     * @since Android 1.0
      */
     public static Byte valueOf(String string, int radix)
             throws NumberFormatException {
         return valueOf(parseByte(string, radix));
     }
-    
+
     /**
      * Returns a {@code Byte} instance for the specified byte value.
      * <p>
      * If it is not necessary to get a new {@code Byte} instance, it is
      * recommended to use this method instead of the constructor, since it
      * maintains a cache of instances which may result in better performance.
-     * </p>
-     * 
+     *
      * @param b
      *            the byte value to store in the instance.
      * @return a {@code Byte} instance containing {@code b}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static Byte valueOf(byte b) {
         synchronized (CACHE) {
diff --git a/libcore/luni/src/main/java/java/lang/CharSequence.java b/libcore/luni/src/main/java/java/lang/CharSequence.java
index 1901192..fc1ecd3 100644
--- a/libcore/luni/src/main/java/java/lang/CharSequence.java
+++ b/libcore/luni/src/main/java/java/lang/CharSequence.java
@@ -21,37 +21,33 @@
 /**
  * This interface represents an ordered set of characters and defines the
  * methods to probe them.
- * 
- * @since Android 1.0
  */
 public interface CharSequence {
 
     /**
      * Returns the number of characters in this sequence.
-     * 
+     *
      * @return the number of characters.
-     * @since Android 1.0
      */
     public int length();
 
     /**
      * Returns the character at the specified index, with the first character
      * having index zero.
-     * 
+     *
      * @param index
      *            the index of the character to return.
      * @return the requested character.
      * @throws IndexOutOfBoundsException
      *             if {@code index < 0} or {@code index} is greater than the
      *             length of this sequence.
-     * @since Android 1.0
      */
     public char charAt(int index);
 
     /**
      * Returns a {@code CharSequence} from the {@code start} index (inclusive)
      * to the {@code end} index (exclusive) of this sequence.
-     * 
+     *
      * @param start
      *            the start offset of the sub-sequence. It is inclusive, that
      *            is, the index of the first character that is included in the
@@ -65,16 +61,14 @@
      *             if {@code start < 0}, {@code end < 0}, {@code start > end},
      *             or if {@code start} or {@code end} are greater than the
      *             length of this sequence.
-     * @since Android 1.0
      */
     public CharSequence subSequence(int start, int end);
 
     /**
      * Returns a string with the same characters in the same order as in this
      * sequence.
-     * 
+     *
      * @return a string based on this sequence.
-     * @since Android 1.0
      */
     public String toString();
 }
diff --git a/libcore/luni/src/main/java/java/lang/Character.java b/libcore/luni/src/main/java/java/lang/Character.java
index 564e37a..8e83b48 100644
--- a/libcore/luni/src/main/java/java/lang/Character.java
+++ b/libcore/luni/src/main/java/java/lang/Character.java
@@ -21,7 +21,7 @@
 // BEGIN android-removed
 // import java.util.SortedMap;
 // import java.util.TreeMap;
-// 
+//
 // import org.apache.harmony.luni.util.BinarySearch;
 // END android-removed
 
@@ -36,7 +36,6 @@
  * Character data is based upon the Unicode Standard, 4.0. The Unicode
  * specification, character tables and other information are available at <a
  * href="http://www.unicode.org/">http://www.unicode.org/</a>.
- * </p>
  * <p>
  * Unicode characters are referred to as <i>code points</i>. The range of valid
  * code points is U+0000 to U+10FFFF. The <i>Basic Multilingual Plane (BMP)</i>
@@ -47,14 +46,12 @@
  * supplementary character are made up of a <i>high surrogate</i> with a value
  * range of 0xD800 to 0xDBFF and a <i>low surrogate</i> with a value range of
  * 0xDC00 to 0xDFFF.
- * </p>
  * <p>
  * On the Java platform a {@code char} value represents either a single BMP code
  * point or a UTF-16 unit that's part of a surrogate pair. The {@code int} type
  * is used to represent all Unicode code points.
- * </p>
- * 
- * @since Android 1.0
+ *
+ * @since 1.0
  */
 public final class Character implements Serializable, Comparable<Character> {
     private static final long serialVersionUID = 3786198910865385080L;
@@ -63,36 +60,26 @@
 
     /**
      * The minimum {@code Character} value.
-     * 
-     * @since Android 1.0
      */
     public static final char MIN_VALUE = '\u0000';
 
     /**
      * The maximum {@code Character} value.
-     * 
-     * @since Android 1.0
      */
     public static final char MAX_VALUE = '\uffff';
 
     /**
      * The minimum radix used for conversions between characters and integers.
-     * 
-     * @since Android 1.0
      */
     public static final int MIN_RADIX = 2;
 
     /**
      * The maximum radix used for conversions between characters and integers.
-     * 
-     * @since Android 1.0
      */
     public static final int MAX_RADIX = 36;
 
     /**
      * The {@link Class} object that represents the primitive type {@code char}.
-     * 
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static final Class<Character> TYPE = (Class<Character>) new char[0]
@@ -103,437 +90,415 @@
 
     /**
      * Unicode category constant Cn.
-     * 
-     * @since Android 1.0
      */
     public static final byte UNASSIGNED = 0;
 
     /**
      * Unicode category constant Lu.
-     * 
-     * @since Android 1.0
      */
     public static final byte UPPERCASE_LETTER = 1;
 
     /**
      * Unicode category constant Ll.
-     * 
-     * @since Android 1.0
      */
     public static final byte LOWERCASE_LETTER = 2;
 
     /**
      * Unicode category constant Lt.
-     * 
-     * @since Android 1.0
      */
     public static final byte TITLECASE_LETTER = 3;
 
     /**
      * Unicode category constant Lm.
-     * 
-     * @since Android 1.0
      */
     public static final byte MODIFIER_LETTER = 4;
 
     /**
      * Unicode category constant Lo.
-     * 
-     * @since Android 1.0
      */
     public static final byte OTHER_LETTER = 5;
 
     /**
      * Unicode category constant Mn.
-     * 
-     * @since Android 1.0
      */
     public static final byte NON_SPACING_MARK = 6;
 
     /**
      * Unicode category constant Me.
-     * 
-     * @since Android 1.0
      */
     public static final byte ENCLOSING_MARK = 7;
 
     /**
      * Unicode category constant Mc.
-     * 
-     * @since Android 1.0
      */
     public static final byte COMBINING_SPACING_MARK = 8;
 
     /**
      * Unicode category constant Nd.
-     * 
-     * @since Android 1.0
      */
     public static final byte DECIMAL_DIGIT_NUMBER = 9;
 
     /**
      * Unicode category constant Nl.
-     * 
-     * @since Android 1.0
      */
     public static final byte LETTER_NUMBER = 10;
 
     /**
      * Unicode category constant No.
-     * 
-     * @since Android 1.0
      */
     public static final byte OTHER_NUMBER = 11;
 
     /**
      * Unicode category constant Zs.
-     * 
-     * @since Android 1.0
      */
     public static final byte SPACE_SEPARATOR = 12;
 
     /**
      * Unicode category constant Zl.
-     * 
-     * @since Android 1.0
      */
     public static final byte LINE_SEPARATOR = 13;
 
     /**
      * Unicode category constant Zp.
-     * 
-     * @since Android 1.0
      */
     public static final byte PARAGRAPH_SEPARATOR = 14;
 
     /**
      * Unicode category constant Cc.
-     * 
-     * @since Android 1.0
      */
     public static final byte CONTROL = 15;
 
     /**
      * Unicode category constant Cf.
-     * 
-     * @since Android 1.0
      */
     public static final byte FORMAT = 16;
 
     /**
      * Unicode category constant Co.
-     * 
-     * @since Android 1.0
      */
     public static final byte PRIVATE_USE = 18;
 
     /**
      * Unicode category constant Cs.
-     * 
-     * @since Android 1.0
      */
     public static final byte SURROGATE = 19;
 
     /**
      * Unicode category constant Pd.
-     * 
-     * @since Android 1.0
      */
     public static final byte DASH_PUNCTUATION = 20;
 
     /**
      * Unicode category constant Ps.
-     * 
-     * @since Android 1.0
      */
     public static final byte START_PUNCTUATION = 21;
 
     /**
      * Unicode category constant Pe.
-     * 
-     * @since Android 1.0
      */
     public static final byte END_PUNCTUATION = 22;
 
     /**
      * Unicode category constant Pc.
-     * 
-     * @since Android 1.0
      */
     public static final byte CONNECTOR_PUNCTUATION = 23;
 
     /**
      * Unicode category constant Po.
-     * 
-     * @since Android 1.0
      */
     public static final byte OTHER_PUNCTUATION = 24;
 
     /**
      * Unicode category constant Sm.
-     * 
-     * @since Android 1.0
      */
     public static final byte MATH_SYMBOL = 25;
 
     /**
      * Unicode category constant Sc.
-     * 
-     * @since Android 1.0
      */
     public static final byte CURRENCY_SYMBOL = 26;
 
     /**
      * Unicode category constant Sk.
-     * 
-     * @since Android 1.0
      */
     public static final byte MODIFIER_SYMBOL = 27;
 
     /**
      * Unicode category constant So.
-     * 
-     * @since Android 1.0
      */
     public static final byte OTHER_SYMBOL = 28;
 
     /**
      * Unicode category constant Pi.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte INITIAL_QUOTE_PUNCTUATION = 29;
 
     /**
      * Unicode category constant Pf.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte FINAL_QUOTE_PUNCTUATION = 30;
 
     /**
      * Unicode bidirectional constant.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_UNDEFINED = -1;
 
     /**
      * Unicode bidirectional constant L.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_LEFT_TO_RIGHT = 0;
 
     /**
      * Unicode bidirectional constant R.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_RIGHT_TO_LEFT = 1;
 
     /**
      * Unicode bidirectional constant AL.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC = 2;
 
     /**
      * Unicode bidirectional constant EN.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_EUROPEAN_NUMBER = 3;
 
     /**
      * Unicode bidirectional constant ES.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR = 4;
 
     /**
      * Unicode bidirectional constant ET.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR = 5;
 
     /**
      * Unicode bidirectional constant AN.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_ARABIC_NUMBER = 6;
 
     /**
      * Unicode bidirectional constant CS.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_COMMON_NUMBER_SEPARATOR = 7;
 
     /**
      * Unicode bidirectional constant NSM.
      *
-     * @since Android 1.0
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_NONSPACING_MARK = 8;
 
     /**
      * Unicode bidirectional constant BN.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_BOUNDARY_NEUTRAL = 9;
 
     /**
      * Unicode bidirectional constant B.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_PARAGRAPH_SEPARATOR = 10;
 
     /**
      * Unicode bidirectional constant S.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_SEGMENT_SEPARATOR = 11;
 
     /**
      * Unicode bidirectional constant WS.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_WHITESPACE = 12;
 
     /**
      * Unicode bidirectional constant ON.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_OTHER_NEUTRALS = 13;
 
     /**
      * Unicode bidirectional constant LRE.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING = 14;
 
     /**
      * Unicode bidirectional constant LRO.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE = 15;
 
     /**
      * Unicode bidirectional constant RLE.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING = 16;
 
     /**
      * Unicode bidirectional constant RLO.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE = 17;
 
     /**
      * Unicode bidirectional constant PDF.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.4
      */
     public static final byte DIRECTIONALITY_POP_DIRECTIONAL_FORMAT = 18;
-    
+
     /**
      * The minimum value of a high surrogate or leading surrogate unit in UTF-16
      * encoding, {@code '\uD800'}.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final char MIN_HIGH_SURROGATE = '\uD800';
 
     /**
      * The maximum value of a high surrogate or leading surrogate unit in UTF-16
      * encoding, {@code '\uDBFF'}.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final char MAX_HIGH_SURROGATE = '\uDBFF';
 
     /**
      * The minimum value of a low surrogate or trailing surrogate unit in UTF-16
      * encoding, {@code '\uDC00'}.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final char MIN_LOW_SURROGATE = '\uDC00';
 
     /**
      * The maximum value of a low surrogate or trailing surrogate unit in UTF-16
      * encoding, {@code '\uDFFF'}.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final char MAX_LOW_SURROGATE = '\uDFFF';
 
     /**
      * The minimum value of a surrogate unit in UTF-16 encoding, {@code '\uD800'}.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final char MIN_SURROGATE = '\uD800';
 
     /**
      * The maximum value of a surrogate unit in UTF-16 encoding, {@code '\uDFFF'}.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final char MAX_SURROGATE = '\uDFFF';
 
     /**
      * The minimum value of a supplementary code point, {@code U+010000}.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final int MIN_SUPPLEMENTARY_CODE_POINT = 0x10000;
 
     /**
      * The minimum code point value, {@code U+0000}.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final int MIN_CODE_POINT = 0x000000;
 
     /**
      * The maximum code point value, {@code U+10FFFF}.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final int MAX_CODE_POINT = 0x10FFFF;
 
     /**
-     * The number of bits required to represent a {@code Character} value in
-     * two's compliment form.
-     * 
-     * @since Android 1.0
+     * The number of bits required to represent a {@code Character} value
+     * unsigned form.
+     *
+     * @since 1.5
      */
     public static final int SIZE = 16;
 
     // BEGIN android-removed
-    // removed strings containing information about chars that now are read from
-    // icu data.
+    // Unicode 3.0.1 (same as Unicode 3.0.0)
+    // private static final String bidiKeys = ...
+
+    // private static final char[] bidiValues = ...
+
+    // private static final char[] mirrored = ...
+
+    // Unicode 3.0.1 (same as Unicode 3.0.0)
+    // private static final String typeKeys = ...
+
+    // private static final char[] typeValues = ...
+
+    // private static final int[] typeValuesCache = ...
+
+    // Unicode 3.0.1 (same as Unicode 3.0.0)
+    // private static final String uppercaseKeys = ...
+
+    // private static final char[] uppercaseValues = ...
+
+    // private static final int[] uppercaseValuesCache = ...
+
+    // private static final String lowercaseKeys = ...
+
+    // private static final char[] lowercaseValues = ...
+
+    // private static final int[] lowercaseValuesCache = ...
+
+    // private static final String digitKeys = ...
+
+    // private static final char[] digitValues = ...
     // END android-removed
-    
+
+    // BEGIN android-note
+    // put this in a helper class so that it's only initialized on demand?
+    // END android-note
     private static final char[] typeTags = "\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0000\u0000\u0000\u0000\u0000\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0003\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0002\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0000\u0000\u0000\u0000\u0003\u0000\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0000\u0000\u0000\u0000\u0002"
             .getValue();
-    
+
+    // BEGIN android-note
+    // put this in a helper class so that it's only initialized on demand?
+    // END android-note
     private static final byte[] DIRECTIONALITY = new byte[] {
             DIRECTIONALITY_LEFT_TO_RIGHT, DIRECTIONALITY_RIGHT_TO_LEFT,
             DIRECTIONALITY_EUROPEAN_NUMBER,
@@ -557,24 +522,28 @@
     private static final int ISJAVAPART = 2;
 
     // BEGIN android-removed
-    // removed strings containing information about chars that now are read from
-    // icu data.
+    // Unicode 3.0.1 (same as Unicode 3.0.0)
+    // private static final String titlecaseKeys = ...
+
+    // private static final char[] titlecaseValues = ...
+
+    // Unicode 3.0.0 (NOT the same as Unicode 3.0.1)
+    // private static final String numericKeys = ...
+
+    // private static final char[] numericValues = ...
     // END android-removed
-    
-    /**
+
+    /*
      * Represents a subset of the Unicode character set.
-     * 
-     * @since Android 1.0
      */
     public static class Subset {
         String name;
 
         /**
          * Constructs a new {@code Subset}.
-         * 
+         *
          * @param string
          *            this subset's name.
-         * @since Android 1.0
          */
         protected Subset(String string) {
             if (string == null) {
@@ -586,12 +555,11 @@
         /**
          * Compares this character subset with the specified object. Uses
          * {@link java.lang.Object#equals(Object)} to do the comparison.
-         * 
+         *
          * @param object
          *            the object to compare this character subset with.
          * @return {@code true} if {@code object} is this subset, that is, if
          *         {@code object == this}; {@code false} otherwise.
-         * @since Android 1.0
          */
         @Override
         public final boolean equals(Object object) {
@@ -600,10 +568,9 @@
 
         /**
          * Returns the integer hash code for this character subset.
-         * 
+         *
          * @return this subset's hash code, which is the hash code computed by
          *         {@link java.lang.Object#hashCode()}.
-         * @since Android 1.0
          */
         @Override
         public final int hashCode() {
@@ -612,9 +579,8 @@
 
         /**
          * Returns the string representation of this subset.
-         * 
+         *
          * @return this subset's name.
-         * @since Android 1.0
          */
         @Override
         public final String toString() {
@@ -622,799 +588,796 @@
         }
     }
 
-    // BEGIN android-changed
-    
     /**
      * Represents a block of Unicode characters, as defined by the Unicode 4.0.1
      * specification.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.2
      */
     public static final class UnicodeBlock extends Subset {
         /**
          * The &quot;Surrogates Area&quot; Unicode Block.
-         * 
+         *
          * @deprecated As of Java 5, this block has been replaced by
          *             {@link #HIGH_SURROGATES},
          *             {@link #HIGH_PRIVATE_USE_SURROGATES} and
          *             {@link #LOW_SURROGATES}.
-         * @since Android 1.0
          */
         @Deprecated
-        public static final UnicodeBlock SURROGATES_AREA = new UnicodeBlock("SURROGATES_AREA");
+        public static final UnicodeBlock SURROGATES_AREA = new UnicodeBlock("SURROGATES_AREA", 0x0, 0x0);
         /**
-         * The &quot;Basic Latin&quot; Unicode Block. 
+         * The &quot;Basic Latin&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock BASIC_LATIN = new UnicodeBlock("BASIC_LATIN");
+        public static final UnicodeBlock BASIC_LATIN = new UnicodeBlock("BASIC_LATIN", 0x0, 0x7f);
         /**
-         * The &quot;Latin-1 Supplement&quot; Unicode Block. 
+         * The &quot;Latin-1 Supplement&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock LATIN_1_SUPPLEMENT = new UnicodeBlock("LATIN_1_SUPPLEMENT");
+        public static final UnicodeBlock LATIN_1_SUPPLEMENT = new UnicodeBlock("LATIN_1_SUPPLEMENT", 0x80, 0xff);
         /**
-         * The &quot;Latin Extended-A&quot; Unicode Block. 
+         * The &quot;Latin Extended-A&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock LATIN_EXTENDED_A = new UnicodeBlock("LATIN_EXTENDED_A");
+        public static final UnicodeBlock LATIN_EXTENDED_A = new UnicodeBlock("LATIN_EXTENDED_A", 0x100, 0x17f);
         /**
-         * The &quot;Latin Extended-B&quot; Unicode Block. 
+         * The &quot;Latin Extended-B&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock LATIN_EXTENDED_B = new UnicodeBlock("LATIN_EXTENDED_B");
+        public static final UnicodeBlock LATIN_EXTENDED_B = new UnicodeBlock("LATIN_EXTENDED_B", 0x180, 0x24f);
         /**
-         * The &quot;IPA Extensions&quot; Unicode Block. 
+         * The &quot;IPA Extensions&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock IPA_EXTENSIONS = new UnicodeBlock("IPA_EXTENSIONS");
+        public static final UnicodeBlock IPA_EXTENSIONS = new UnicodeBlock("IPA_EXTENSIONS", 0x250, 0x2af);
         /**
-         * The &quot;Spacing Modifier Letters&quot; Unicode Block. 
+         * The &quot;Spacing Modifier Letters&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock SPACING_MODIFIER_LETTERS = new UnicodeBlock("SPACING_MODIFIER_LETTERS");
+        public static final UnicodeBlock SPACING_MODIFIER_LETTERS = new UnicodeBlock("SPACING_MODIFIER_LETTERS", 0x2b0, 0x2ff);
         /**
-         * The &quot;Combining Diacritical Marks&quot; Unicode Block. 
+         * The &quot;Combining Diacritical Marks&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock COMBINING_DIACRITICAL_MARKS = new UnicodeBlock("COMBINING_DIACRITICAL_MARKS");
+        public static final UnicodeBlock COMBINING_DIACRITICAL_MARKS = new UnicodeBlock("COMBINING_DIACRITICAL_MARKS", 0x300, 0x36f);
         /**
          * The &quot;Greek and Coptic&quot; Unicode Block. Previously referred
          * to as &quot;Greek&quot;.
-         * 
-         * @since Android 1.0
-         */
-        public static final UnicodeBlock GREEK = new UnicodeBlock("GREEK");
-        /**
-         * The &quot;Cyrillic&quot; Unicode Block. 
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock CYRILLIC = new UnicodeBlock("CYRILLIC");
+        public static final UnicodeBlock GREEK = new UnicodeBlock("GREEK", 0x370, 0x3ff);
+        /**
+         * The &quot;Cyrillic&quot; Unicode Block.
+         *
+         * @since 1.2
+         */
+        public static final UnicodeBlock CYRILLIC = new UnicodeBlock("CYRILLIC", 0x400, 0x4ff);
         /**
          * The &quot;Cyrillic Supplement&quot; Unicode Block. Previously
          * referred to as &quot;Cyrillic Supplementary&quot;.
-         * 
-         * @since Android 1.0
-         */
-        public static final UnicodeBlock CYRILLIC_SUPPLEMENTARY = new UnicodeBlock("CYRILLIC_SUPPLEMENTARY");
-        /**
-         * The &quot;Armenian&quot; Unicode Block. 
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock ARMENIAN = new UnicodeBlock("ARMENIAN");
+        public static final UnicodeBlock CYRILLIC_SUPPLEMENTARY = new UnicodeBlock("CYRILLIC_SUPPLEMENTARY", 0x500, 0x52f);
         /**
-         * The &quot;Hebrew&quot; Unicode Block. 
+         * The &quot;Armenian&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock HEBREW = new UnicodeBlock("HEBREW");
+        public static final UnicodeBlock ARMENIAN = new UnicodeBlock("ARMENIAN", 0x530, 0x58f);
         /**
-         * The &quot;Arabic&quot; Unicode Block. 
+         * The &quot;Hebrew&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock ARABIC = new UnicodeBlock("ARABIC");
+        public static final UnicodeBlock HEBREW = new UnicodeBlock("HEBREW", 0x590, 0x5ff);
         /**
-         * The &quot;Syriac&quot; Unicode Block. 
+         * The &quot;Arabic&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock SYRIAC = new UnicodeBlock("SYRIAC");
+        public static final UnicodeBlock ARABIC = new UnicodeBlock("ARABIC", 0x600, 0x6ff);
         /**
-         * The &quot;Thaana&quot; Unicode Block. 
+         * The &quot;Syriac&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock THAANA = new UnicodeBlock("THAANA");
+        public static final UnicodeBlock SYRIAC = new UnicodeBlock("SYRIAC", 0x700, 0x74f);
         /**
-         * The &quot;Devanagari&quot; Unicode Block. 
+         * The &quot;Thaana&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock DEVANAGARI = new UnicodeBlock("DEVANAGARI");
+        public static final UnicodeBlock THAANA = new UnicodeBlock("THAANA", 0x780, 0x7bf);
         /**
-         * The &quot;Bengali&quot; Unicode Block. 
+         * The &quot;Devanagari&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock BENGALI = new UnicodeBlock("BENGALI");
+        public static final UnicodeBlock DEVANAGARI = new UnicodeBlock("DEVANAGARI", 0x900, 0x97f);
         /**
-         * The &quot;Gurmukhi&quot; Unicode Block. 
+         * The &quot;Bengali&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock GURMUKHI = new UnicodeBlock("GURMUKHI");
+        public static final UnicodeBlock BENGALI = new UnicodeBlock("BENGALI", 0x980, 0x9ff);
         /**
-         * The &quot;Gujarati&quot; Unicode Block. 
+         * The &quot;Gurmukhi&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock GUJARATI = new UnicodeBlock("GUJARATI");
+        public static final UnicodeBlock GURMUKHI = new UnicodeBlock("GURMUKHI", 0xa00, 0xa7f);
         /**
-         * The &quot;Oriya&quot; Unicode Block. 
+         * The &quot;Gujarati&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock ORIYA = new UnicodeBlock("ORIYA");
+        public static final UnicodeBlock GUJARATI = new UnicodeBlock("GUJARATI", 0xa80, 0xaff);
         /**
-         * The &quot;Tamil&quot; Unicode Block. 
+         * The &quot;Oriya&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock TAMIL = new UnicodeBlock("TAMIL");
+        public static final UnicodeBlock ORIYA = new UnicodeBlock("ORIYA", 0xb00, 0xb7f);
         /**
-         * The &quot;Telugu&quot; Unicode Block. 
+         * The &quot;Tamil&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock TELUGU = new UnicodeBlock("TELUGU");
+        public static final UnicodeBlock TAMIL = new UnicodeBlock("TAMIL", 0xb80, 0xbff);
         /**
-         * The &quot;Kannada&quot; Unicode Block. 
+         * The &quot;Telugu&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock KANNADA = new UnicodeBlock("KANNADA");
+        public static final UnicodeBlock TELUGU = new UnicodeBlock("TELUGU", 0xc00, 0xc7f);
         /**
-         * The &quot;Malayalam&quot; Unicode Block. 
+         * The &quot;Kannada&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock MALAYALAM = new UnicodeBlock("MALAYALAM");
+        public static final UnicodeBlock KANNADA = new UnicodeBlock("KANNADA", 0xc80, 0xcff);
         /**
-         * The &quot;Sinhala&quot; Unicode Block. 
+         * The &quot;Malayalam&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock SINHALA = new UnicodeBlock("SINHALA");
+        public static final UnicodeBlock MALAYALAM = new UnicodeBlock("MALAYALAM", 0xd00, 0xd7f);
         /**
-         * The &quot;Thai&quot; Unicode Block. 
+         * The &quot;Sinhala&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock THAI = new UnicodeBlock("THAI");
+        public static final UnicodeBlock SINHALA = new UnicodeBlock("SINHALA", 0xd80, 0xdff);
         /**
-         * The &quot;Lao&quot; Unicode Block. 
+         * The &quot;Thai&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock LAO = new UnicodeBlock("LAO");
+        public static final UnicodeBlock THAI = new UnicodeBlock("THAI", 0xe00, 0xe7f);
         /**
-         * The &quot;Tibetan&quot; Unicode Block. 
+         * The &quot;Lao&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock TIBETAN = new UnicodeBlock("TIBETAN");
+        public static final UnicodeBlock LAO = new UnicodeBlock("LAO", 0xe80, 0xeff);
         /**
-         * The &quot;Myanmar&quot; Unicode Block. 
+         * The &quot;Tibetan&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock MYANMAR = new UnicodeBlock("MYANMAR");
+        public static final UnicodeBlock TIBETAN = new UnicodeBlock("TIBETAN", 0xf00, 0xfff);
         /**
-         * The &quot;Georgian&quot; Unicode Block. 
+         * The &quot;Myanmar&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock GEORGIAN = new UnicodeBlock("GEORGIAN");
+        public static final UnicodeBlock MYANMAR = new UnicodeBlock("MYANMAR", 0x1000, 0x109f);
         /**
-         * The &quot;Hangul Jamo&quot; Unicode Block. 
+         * The &quot;Georgian&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock HANGUL_JAMO = new UnicodeBlock("HANGUL_JAMO");
+        public static final UnicodeBlock GEORGIAN = new UnicodeBlock("GEORGIAN", 0x10a0, 0x10ff);
         /**
-         * The &quot;Ethiopic&quot; Unicode Block. 
+         * The &quot;Hangul Jamo&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock ETHIOPIC = new UnicodeBlock("ETHIOPIC");
+        public static final UnicodeBlock HANGUL_JAMO = new UnicodeBlock("HANGUL_JAMO", 0x1100, 0x11ff);
         /**
-         * The &quot;Cherokee&quot; Unicode Block. 
+         * The &quot;Ethiopic&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock CHEROKEE = new UnicodeBlock("CHEROKEE");
+        public static final UnicodeBlock ETHIOPIC = new UnicodeBlock("ETHIOPIC", 0x1200, 0x137f);
         /**
-         * The &quot;Unified Canadian Aboriginal Syllabics&quot; Unicode Block. 
+         * The &quot;Cherokee&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS = new UnicodeBlock("UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS");
+        public static final UnicodeBlock CHEROKEE = new UnicodeBlock("CHEROKEE", 0x13a0, 0x13ff);
         /**
-         * The &quot;Ogham&quot; Unicode Block. 
+         * The &quot;Unified Canadian Aboriginal Syllabics&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock OGHAM = new UnicodeBlock("OGHAM");
+        public static final UnicodeBlock UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS = new UnicodeBlock("UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS", 0x1400, 0x167f);
         /**
-         * The &quot;Runic&quot; Unicode Block. 
+         * The &quot;Ogham&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock RUNIC = new UnicodeBlock("RUNIC");
+        public static final UnicodeBlock OGHAM = new UnicodeBlock("OGHAM", 0x1680, 0x169f);
         /**
-         * The &quot;Tagalog&quot; Unicode Block. 
+         * The &quot;Runic&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock TAGALOG = new UnicodeBlock("TAGALOG");
+        public static final UnicodeBlock RUNIC = new UnicodeBlock("RUNIC", 0x16a0, 0x16ff);
         /**
-         * The &quot;Hanunoo&quot; Unicode Block. 
+         * The &quot;Tagalog&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock HANUNOO = new UnicodeBlock("HANUNOO");
+        public static final UnicodeBlock TAGALOG = new UnicodeBlock("TAGALOG", 0x1700, 0x171f);
         /**
-         * The &quot;Buhid&quot; Unicode Block. 
+         * The &quot;Hanunoo&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock BUHID = new UnicodeBlock("BUHID");
+        public static final UnicodeBlock HANUNOO = new UnicodeBlock("HANUNOO", 0x1720, 0x173f);
         /**
-         * The &quot;Tagbanwa&quot; Unicode Block. 
+         * The &quot;Buhid&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock TAGBANWA = new UnicodeBlock("TAGBANWA");
+        public static final UnicodeBlock BUHID = new UnicodeBlock("BUHID", 0x1740, 0x175f);
         /**
-         * The &quot;Khmer&quot; Unicode Block. 
+         * The &quot;Tagbanwa&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock KHMER = new UnicodeBlock("KHMER");
+        public static final UnicodeBlock TAGBANWA = new UnicodeBlock("TAGBANWA", 0x1760, 0x177f);
         /**
-         * The &quot;Mongolian&quot; Unicode Block. 
+         * The &quot;Khmer&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock MONGOLIAN = new UnicodeBlock("MONGOLIAN");
+        public static final UnicodeBlock KHMER = new UnicodeBlock("KHMER", 0x1780, 0x17ff);
         /**
-         * The &quot;Limbu&quot; Unicode Block. 
+         * The &quot;Mongolian&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock LIMBU = new UnicodeBlock("LIMBU");
+        public static final UnicodeBlock MONGOLIAN = new UnicodeBlock("MONGOLIAN", 0x1800, 0x18af);
         /**
-         * The &quot;Tai Le&quot; Unicode Block. 
+         * The &quot;Limbu&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock TAI_LE = new UnicodeBlock("TAI_LE");
+        public static final UnicodeBlock LIMBU = new UnicodeBlock("LIMBU", 0x1900, 0x194f);
         /**
-         * The &quot;Khmer Symbols&quot; Unicode Block. 
+         * The &quot;Tai Le&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock KHMER_SYMBOLS = new UnicodeBlock("KHMER_SYMBOLS");
+        public static final UnicodeBlock TAI_LE = new UnicodeBlock("TAI_LE", 0x1950, 0x197f);
         /**
-         * The &quot;Phonetic Extensions&quot; Unicode Block. 
+         * The &quot;Khmer Symbols&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock PHONETIC_EXTENSIONS = new UnicodeBlock("PHONETIC_EXTENSIONS");
+        public static final UnicodeBlock KHMER_SYMBOLS = new UnicodeBlock("KHMER_SYMBOLS", 0x19e0, 0x19ff);
         /**
-         * The &quot;Latin Extended Additional&quot; Unicode Block. 
+         * The &quot;Phonetic Extensions&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock LATIN_EXTENDED_ADDITIONAL = new UnicodeBlock("LATIN_EXTENDED_ADDITIONAL");
+        public static final UnicodeBlock PHONETIC_EXTENSIONS = new UnicodeBlock("PHONETIC_EXTENSIONS", 0x1d00, 0x1d7f);
         /**
-         * The &quot;Greek Extended&quot; Unicode Block. 
+         * The &quot;Latin Extended Additional&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock GREEK_EXTENDED = new UnicodeBlock("GREEK_EXTENDED");
+        public static final UnicodeBlock LATIN_EXTENDED_ADDITIONAL = new UnicodeBlock("LATIN_EXTENDED_ADDITIONAL", 0x1e00, 0x1eff);
         /**
-         * The &quot;General Punctuation&quot; Unicode Block. 
+         * The &quot;Greek Extended&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock GENERAL_PUNCTUATION = new UnicodeBlock("GENERAL_PUNCTUATION");
+        public static final UnicodeBlock GREEK_EXTENDED = new UnicodeBlock("GREEK_EXTENDED", 0x1f00, 0x1fff);
         /**
-         * The &quot;Superscripts and Subscripts&quot; Unicode Block. 
+         * The &quot;General Punctuation&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock SUPERSCRIPTS_AND_SUBSCRIPTS = new UnicodeBlock("SUPERSCRIPTS_AND_SUBSCRIPTS");
+        public static final UnicodeBlock GENERAL_PUNCTUATION = new UnicodeBlock("GENERAL_PUNCTUATION", 0x2000, 0x206f);
         /**
-         * The &quot;Currency Symbols&quot; Unicode Block. 
+         * The &quot;Superscripts and Subscripts&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock CURRENCY_SYMBOLS = new UnicodeBlock("CURRENCY_SYMBOLS");
+        public static final UnicodeBlock SUPERSCRIPTS_AND_SUBSCRIPTS = new UnicodeBlock("SUPERSCRIPTS_AND_SUBSCRIPTS", 0x2070, 0x209f);
+        /**
+         * The &quot;Currency Symbols&quot; Unicode Block.
+         *
+         * @since 1.2
+         */
+        public static final UnicodeBlock CURRENCY_SYMBOLS = new UnicodeBlock("CURRENCY_SYMBOLS", 0x20a0, 0x20cf);
         /**
          * The &quot;Combining Diacritical Marks for Symbols&quot; Unicode
          * Block. Previously referred to as &quot;Combining Marks for
          * Symbols&quot;.
-         * 
-         * @since Android 1.0
-         */
-        public static final UnicodeBlock COMBINING_MARKS_FOR_SYMBOLS = new UnicodeBlock("COMBINING_MARKS_FOR_SYMBOLS");
-        /**
-         * The &quot;Letterlike Symbols&quot; Unicode Block. 
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock LETTERLIKE_SYMBOLS = new UnicodeBlock("LETTERLIKE_SYMBOLS");
+        public static final UnicodeBlock COMBINING_MARKS_FOR_SYMBOLS = new UnicodeBlock("COMBINING_MARKS_FOR_SYMBOLS", 0x20d0, 0x20ff);
         /**
-         * The &quot;Number Forms&quot; Unicode Block. 
+         * The &quot;Letterlike Symbols&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock NUMBER_FORMS = new UnicodeBlock("NUMBER_FORMS");
+        public static final UnicodeBlock LETTERLIKE_SYMBOLS = new UnicodeBlock("LETTERLIKE_SYMBOLS", 0x2100, 0x214f);
         /**
-         * The &quot;Arrows&quot; Unicode Block. 
+         * The &quot;Number Forms&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock ARROWS = new UnicodeBlock("ARROWS");
+        public static final UnicodeBlock NUMBER_FORMS = new UnicodeBlock("NUMBER_FORMS", 0x2150, 0x218f);
         /**
-         * The &quot;Mathematical Operators&quot; Unicode Block. 
+         * The &quot;Arrows&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock MATHEMATICAL_OPERATORS = new UnicodeBlock("MATHEMATICAL_OPERATORS");
+        public static final UnicodeBlock ARROWS = new UnicodeBlock("ARROWS", 0x2190, 0x21ff);
         /**
-         * The &quot;Miscellaneous Technical&quot; Unicode Block. 
+         * The &quot;Mathematical Operators&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock MISCELLANEOUS_TECHNICAL = new UnicodeBlock("MISCELLANEOUS_TECHNICAL");
+        public static final UnicodeBlock MATHEMATICAL_OPERATORS = new UnicodeBlock("MATHEMATICAL_OPERATORS", 0x2200, 0x22ff);
         /**
-         * The &quot;Control Pictures&quot; Unicode Block. 
+         * The &quot;Miscellaneous Technical&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock CONTROL_PICTURES = new UnicodeBlock("CONTROL_PICTURES");
+        public static final UnicodeBlock MISCELLANEOUS_TECHNICAL = new UnicodeBlock("MISCELLANEOUS_TECHNICAL", 0x2300, 0x23ff);
         /**
-         * The &quot;Optical Character Recognition&quot; Unicode Block. 
+         * The &quot;Control Pictures&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock OPTICAL_CHARACTER_RECOGNITION = new UnicodeBlock("OPTICAL_CHARACTER_RECOGNITION");
+        public static final UnicodeBlock CONTROL_PICTURES = new UnicodeBlock("CONTROL_PICTURES", 0x2400, 0x243f);
         /**
-         * The &quot;Enclosed Alphanumerics&quot; Unicode Block. 
+         * The &quot;Optical Character Recognition&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock ENCLOSED_ALPHANUMERICS = new UnicodeBlock("ENCLOSED_ALPHANUMERICS");
+        public static final UnicodeBlock OPTICAL_CHARACTER_RECOGNITION = new UnicodeBlock("OPTICAL_CHARACTER_RECOGNITION", 0x2440, 0x245f);
         /**
-         * The &quot;Box Drawing&quot; Unicode Block. 
+         * The &quot;Enclosed Alphanumerics&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock BOX_DRAWING = new UnicodeBlock("BOX_DRAWING");
+        public static final UnicodeBlock ENCLOSED_ALPHANUMERICS = new UnicodeBlock("ENCLOSED_ALPHANUMERICS", 0x2460, 0x24ff);
         /**
-         * The &quot;Block Elements&quot; Unicode Block. 
+         * The &quot;Box Drawing&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock BLOCK_ELEMENTS = new UnicodeBlock("BLOCK_ELEMENTS");
+        public static final UnicodeBlock BOX_DRAWING = new UnicodeBlock("BOX_DRAWING", 0x2500, 0x257f);
         /**
-         * The &quot;Geometric Shapes&quot; Unicode Block. 
+         * The &quot;Block Elements&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock GEOMETRIC_SHAPES = new UnicodeBlock("GEOMETRIC_SHAPES");
+        public static final UnicodeBlock BLOCK_ELEMENTS = new UnicodeBlock("BLOCK_ELEMENTS", 0x2580, 0x259f);
         /**
-         * The &quot;Miscellaneous Symbols&quot; Unicode Block. 
+         * The &quot;Geometric Shapes&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock MISCELLANEOUS_SYMBOLS = new UnicodeBlock("MISCELLANEOUS_SYMBOLS");
+        public static final UnicodeBlock GEOMETRIC_SHAPES = new UnicodeBlock("GEOMETRIC_SHAPES", 0x25a0, 0x25ff);
         /**
-         * The &quot;Dingbats&quot; Unicode Block. 
+         * The &quot;Miscellaneous Symbols&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock DINGBATS = new UnicodeBlock("DINGBATS");
+        public static final UnicodeBlock MISCELLANEOUS_SYMBOLS = new UnicodeBlock("MISCELLANEOUS_SYMBOLS", 0x2600, 0x26ff);
         /**
-         * The &quot;Miscellaneous Mathematical Symbols-A&quot; Unicode Block. 
+         * The &quot;Dingbats&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A = new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A");
+        public static final UnicodeBlock DINGBATS = new UnicodeBlock("DINGBATS", 0x2700, 0x27bf);
         /**
-         * The &quot;Supplemental Arrows-A&quot; Unicode Block. 
+         * The &quot;Miscellaneous Mathematical Symbols-A&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock SUPPLEMENTAL_ARROWS_A = new UnicodeBlock("SUPPLEMENTAL_ARROWS_A");
+        public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A = new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A", 0x27c0, 0x27ef);
         /**
-         * The &quot;Braille Patterns&quot; Unicode Block. 
+         * The &quot;Supplemental Arrows-A&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock BRAILLE_PATTERNS = new UnicodeBlock("BRAILLE_PATTERNS");
+        public static final UnicodeBlock SUPPLEMENTAL_ARROWS_A = new UnicodeBlock("SUPPLEMENTAL_ARROWS_A", 0x27f0, 0x27ff);
         /**
-         * The &quot;Supplemental Arrows-B&quot; Unicode Block. 
+         * The &quot;Braille Patterns&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock SUPPLEMENTAL_ARROWS_B = new UnicodeBlock("SUPPLEMENTAL_ARROWS_B");
+        public static final UnicodeBlock BRAILLE_PATTERNS = new UnicodeBlock("BRAILLE_PATTERNS", 0x2800, 0x28ff);
         /**
-         * The &quot;Miscellaneous Mathematical Symbols-B&quot; Unicode Block. 
+         * The &quot;Supplemental Arrows-B&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B = new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B");
+        public static final UnicodeBlock SUPPLEMENTAL_ARROWS_B = new UnicodeBlock("SUPPLEMENTAL_ARROWS_B", 0x2900, 0x297f);
         /**
-         * The &quot;Supplemental Mathematical Operators&quot; Unicode Block. 
+         * The &quot;Miscellaneous Mathematical Symbols-B&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock SUPPLEMENTAL_MATHEMATICAL_OPERATORS = new UnicodeBlock("SUPPLEMENTAL_MATHEMATICAL_OPERATORS");
+        public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B = new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B", 0x2980, 0x29ff);
         /**
-         * The &quot;Miscellaneous Symbols and Arrows&quot; Unicode Block. 
+         * The &quot;Supplemental Mathematical Operators&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock MISCELLANEOUS_SYMBOLS_AND_ARROWS = new UnicodeBlock("MISCELLANEOUS_SYMBOLS_AND_ARROWS");
+        public static final UnicodeBlock SUPPLEMENTAL_MATHEMATICAL_OPERATORS = new UnicodeBlock("SUPPLEMENTAL_MATHEMATICAL_OPERATORS", 0x2a00, 0x2aff);
         /**
-         * The &quot;CJK Radicals Supplement&quot; Unicode Block. 
+         * The &quot;Miscellaneous Symbols and Arrows&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock CJK_RADICALS_SUPPLEMENT = new UnicodeBlock("CJK_RADICALS_SUPPLEMENT");
+        public static final UnicodeBlock MISCELLANEOUS_SYMBOLS_AND_ARROWS = new UnicodeBlock("MISCELLANEOUS_SYMBOLS_AND_ARROWS", 0x2b00, 0x2bff);
         /**
-         * The &quot;Kangxi Radicals&quot; Unicode Block. 
+         * The &quot;CJK Radicals Supplement&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock KANGXI_RADICALS = new UnicodeBlock("KANGXI_RADICALS");
+        public static final UnicodeBlock CJK_RADICALS_SUPPLEMENT = new UnicodeBlock("CJK_RADICALS_SUPPLEMENT", 0x2e80, 0x2eff);
         /**
-         * The &quot;Ideographic Description Characters&quot; Unicode Block. 
+         * The &quot;Kangxi Radicals&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock IDEOGRAPHIC_DESCRIPTION_CHARACTERS = new UnicodeBlock("IDEOGRAPHIC_DESCRIPTION_CHARACTERS");
+        public static final UnicodeBlock KANGXI_RADICALS = new UnicodeBlock("KANGXI_RADICALS", 0x2f00, 0x2fdf);
         /**
-         * The &quot;CJK Symbols and Punctuation&quot; Unicode Block. 
+         * The &quot;Ideographic Description Characters&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock CJK_SYMBOLS_AND_PUNCTUATION = new UnicodeBlock("CJK_SYMBOLS_AND_PUNCTUATION");
+        public static final UnicodeBlock IDEOGRAPHIC_DESCRIPTION_CHARACTERS = new UnicodeBlock("IDEOGRAPHIC_DESCRIPTION_CHARACTERS", 0x2ff0, 0x2fff);
         /**
-         * The &quot;Hiragana&quot; Unicode Block. 
+         * The &quot;CJK Symbols and Punctuation&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock HIRAGANA = new UnicodeBlock("HIRAGANA");
+        public static final UnicodeBlock CJK_SYMBOLS_AND_PUNCTUATION = new UnicodeBlock("CJK_SYMBOLS_AND_PUNCTUATION", 0x3000, 0x303f);
         /**
-         * The &quot;Katakana&quot; Unicode Block. 
+         * The &quot;Hiragana&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock KATAKANA = new UnicodeBlock("KATAKANA");
+        public static final UnicodeBlock HIRAGANA = new UnicodeBlock("HIRAGANA", 0x3040, 0x309f);
         /**
-         * The &quot;Bopomofo&quot; Unicode Block. 
+         * The &quot;Katakana&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock BOPOMOFO = new UnicodeBlock("BOPOMOFO");
+        public static final UnicodeBlock KATAKANA = new UnicodeBlock("KATAKANA", 0x30a0, 0x30ff);
         /**
-         * The &quot;Hangul Compatibility Jamo&quot; Unicode Block. 
+         * The &quot;Bopomofo&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock HANGUL_COMPATIBILITY_JAMO = new UnicodeBlock("HANGUL_COMPATIBILITY_JAMO");
+        public static final UnicodeBlock BOPOMOFO = new UnicodeBlock("BOPOMOFO", 0x3100, 0x312f);
         /**
-         * The &quot;Kanbun&quot; Unicode Block. 
+         * The &quot;Hangul Compatibility Jamo&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock KANBUN = new UnicodeBlock("KANBUN");
+        public static final UnicodeBlock HANGUL_COMPATIBILITY_JAMO = new UnicodeBlock("HANGUL_COMPATIBILITY_JAMO", 0x3130, 0x318f);
         /**
-         * The &quot;Bopomofo Extended&quot; Unicode Block. 
+         * The &quot;Kanbun&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock BOPOMOFO_EXTENDED = new UnicodeBlock("BOPOMOFO_EXTENDED");
+        public static final UnicodeBlock KANBUN = new UnicodeBlock("KANBUN", 0x3190, 0x319f);
         /**
-         * The &quot;Katakana Phonetic Extensions&quot; Unicode Block. 
+         * The &quot;Bopomofo Extended&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock KATAKANA_PHONETIC_EXTENSIONS = new UnicodeBlock("KATAKANA_PHONETIC_EXTENSIONS");
+        public static final UnicodeBlock BOPOMOFO_EXTENDED = new UnicodeBlock("BOPOMOFO_EXTENDED", 0x31a0, 0x31bf);
         /**
-         * The &quot;Enclosed CJK Letters and Months&quot; Unicode Block. 
+         * The &quot;Katakana Phonetic Extensions&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock ENCLOSED_CJK_LETTERS_AND_MONTHS = new UnicodeBlock("ENCLOSED_CJK_LETTERS_AND_MONTHS");
+        public static final UnicodeBlock KATAKANA_PHONETIC_EXTENSIONS = new UnicodeBlock("KATAKANA_PHONETIC_EXTENSIONS", 0x31f0, 0x31ff);
         /**
-         * The &quot;CJK Compatibility&quot; Unicode Block. 
+         * The &quot;Enclosed CJK Letters and Months&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock CJK_COMPATIBILITY = new UnicodeBlock("CJK_COMPATIBILITY");
+        public static final UnicodeBlock ENCLOSED_CJK_LETTERS_AND_MONTHS = new UnicodeBlock("ENCLOSED_CJK_LETTERS_AND_MONTHS", 0x3200, 0x32ff);
         /**
-         * The &quot;CJK Unified Ideographs Extension A&quot; Unicode Block. 
+         * The &quot;CJK Compatibility&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A");
+        public static final UnicodeBlock CJK_COMPATIBILITY = new UnicodeBlock("CJK_COMPATIBILITY", 0x3300, 0x33ff);
         /**
-         * The &quot;Yijing Hexagram Symbols&quot; Unicode Block. 
+         * The &quot;CJK Unified Ideographs Extension A&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock YIJING_HEXAGRAM_SYMBOLS = new UnicodeBlock("YIJING_HEXAGRAM_SYMBOLS");
+        public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A", 0x3400, 0x4dbf);
         /**
-         * The &quot;CJK Unified Ideographs&quot; Unicode Block. 
+         * The &quot;Yijing Hexagram Symbols&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS");
+        public static final UnicodeBlock YIJING_HEXAGRAM_SYMBOLS = new UnicodeBlock("YIJING_HEXAGRAM_SYMBOLS", 0x4dc0, 0x4dff);
         /**
-         * The &quot;Yi Syllables&quot; Unicode Block. 
+         * The &quot;CJK Unified Ideographs&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock YI_SYLLABLES = new UnicodeBlock("YI_SYLLABLES");
+        public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS", 0x4e00, 0x9fff);
         /**
-         * The &quot;Yi Radicals&quot; Unicode Block. 
+         * The &quot;Yi Syllables&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock YI_RADICALS = new UnicodeBlock("YI_RADICALS");
+        public static final UnicodeBlock YI_SYLLABLES = new UnicodeBlock("YI_SYLLABLES", 0xa000, 0xa48f);
         /**
-         * The &quot;Hangul Syllables&quot; Unicode Block. 
+         * The &quot;Yi Radicals&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.4
          */
-        public static final UnicodeBlock HANGUL_SYLLABLES = new UnicodeBlock("HANGUL_SYLLABLES");
+        public static final UnicodeBlock YI_RADICALS = new UnicodeBlock("YI_RADICALS", 0xa490, 0xa4cf);
+        /**
+         * The &quot;Hangul Syllables&quot; Unicode Block.
+         *
+         * @since 1.2
+         */
+        public static final UnicodeBlock HANGUL_SYLLABLES = new UnicodeBlock("HANGUL_SYLLABLES", 0xac00, 0xd7af);
         /**
          * The &quot;High Surrogates&quot; Unicode Block. This block represents
          * code point values in the high surrogate range 0xD800 to 0xDB7F
-         * 
-         * @since Android 1.0
          */
-        public static final UnicodeBlock HIGH_SURROGATES = new UnicodeBlock("HIGH_SURROGATES");
+        public static final UnicodeBlock HIGH_SURROGATES = new UnicodeBlock("HIGH_SURROGATES", 0xd800, 0xdb7f);
         /**
          * The &quot;High Private Use Surrogates&quot; Unicode Block. This block
          * represents code point values in the high surrogate range 0xDB80 to
          * 0xDBFF
-         * 
-         * @since Android 1.0
          */
-        public static final UnicodeBlock HIGH_PRIVATE_USE_SURROGATES = new UnicodeBlock("HIGH_PRIVATE_USE_SURROGATES");
+        public static final UnicodeBlock HIGH_PRIVATE_USE_SURROGATES = new UnicodeBlock("HIGH_PRIVATE_USE_SURROGATES", 0xdb80, 0xdbff);
         /**
          * The &quot;Low Surrogates&quot; Unicode Block. This block represents
          * code point values in the low surrogate range 0xDC00 to 0xDFFF
-         * 
-         * @since Android 1.0
          */
-        public static final UnicodeBlock LOW_SURROGATES = new UnicodeBlock("LOW_SURROGATES");
+        public static final UnicodeBlock LOW_SURROGATES = new UnicodeBlock("LOW_SURROGATES", 0xdc00, 0xdfff);
         /**
-         * The &quot;Private Use Area&quot; Unicode Block. 
+         * The &quot;Private Use Area&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock PRIVATE_USE_AREA = new UnicodeBlock("PRIVATE_USE_AREA");
+        public static final UnicodeBlock PRIVATE_USE_AREA = new UnicodeBlock("PRIVATE_USE_AREA", 0xe000, 0xf8ff);
         /**
-         * The &quot;CJK Compatibility Ideographs&quot; Unicode Block. 
+         * The &quot;CJK Compatibility Ideographs&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS = new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS");
+        public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS = new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS", 0xf900, 0xfaff);
         /**
-         * The &quot;Alphabetic Presentation Forms&quot; Unicode Block. 
+         * The &quot;Alphabetic Presentation Forms&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock ALPHABETIC_PRESENTATION_FORMS = new UnicodeBlock("ALPHABETIC_PRESENTATION_FORMS");
+        public static final UnicodeBlock ALPHABETIC_PRESENTATION_FORMS = new UnicodeBlock("ALPHABETIC_PRESENTATION_FORMS", 0xfb00, 0xfb4f);
         /**
-         * The &quot;Arabic Presentation Forms-A&quot; Unicode Block. 
+         * The &quot;Arabic Presentation Forms-A&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_A = new UnicodeBlock("ARABIC_PRESENTATION_FORMS_A");
+        public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_A = new UnicodeBlock("ARABIC_PRESENTATION_FORMS_A", 0xfb50, 0xfdff);
         /**
-         * The &quot;Variation Selectors&quot; Unicode Block. 
+         * The &quot;Variation Selectors&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock VARIATION_SELECTORS = new UnicodeBlock("VARIATION_SELECTORS");
+        public static final UnicodeBlock VARIATION_SELECTORS = new UnicodeBlock("VARIATION_SELECTORS", 0xfe00, 0xfe0f);
         /**
-         * The &quot;Combining Half Marks&quot; Unicode Block. 
+         * The &quot;Combining Half Marks&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock COMBINING_HALF_MARKS = new UnicodeBlock("COMBINING_HALF_MARKS");
+        public static final UnicodeBlock COMBINING_HALF_MARKS = new UnicodeBlock("COMBINING_HALF_MARKS", 0xfe20, 0xfe2f);
         /**
-         * The &quot;CJK Compatibility Forms&quot; Unicode Block. 
+         * The &quot;CJK Compatibility Forms&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock CJK_COMPATIBILITY_FORMS = new UnicodeBlock("CJK_COMPATIBILITY_FORMS");
+        public static final UnicodeBlock CJK_COMPATIBILITY_FORMS = new UnicodeBlock("CJK_COMPATIBILITY_FORMS", 0xfe30, 0xfe4f);
         /**
-         * The &quot;Small Form Variants&quot; Unicode Block. 
+         * The &quot;Small Form Variants&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock SMALL_FORM_VARIANTS = new UnicodeBlock("SMALL_FORM_VARIANTS");
+        public static final UnicodeBlock SMALL_FORM_VARIANTS = new UnicodeBlock("SMALL_FORM_VARIANTS", 0xfe50, 0xfe6f);
         /**
-         * The &quot;Arabic Presentation Forms-B&quot; Unicode Block. 
+         * The &quot;Arabic Presentation Forms-B&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_B = new UnicodeBlock("ARABIC_PRESENTATION_FORMS_B");
+        public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_B = new UnicodeBlock("ARABIC_PRESENTATION_FORMS_B", 0xfe70, 0xfeff);
         /**
-         * The &quot;Halfwidth and Fullwidth Forms&quot; Unicode Block. 
+         * The &quot;Halfwidth and Fullwidth Forms&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock HALFWIDTH_AND_FULLWIDTH_FORMS = new UnicodeBlock("HALFWIDTH_AND_FULLWIDTH_FORMS");
+        public static final UnicodeBlock HALFWIDTH_AND_FULLWIDTH_FORMS = new UnicodeBlock("HALFWIDTH_AND_FULLWIDTH_FORMS", 0xff00, 0xffef);
         /**
-         * The &quot;Specials&quot; Unicode Block. 
+         * The &quot;Specials&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock SPECIALS = new UnicodeBlock("SPECIALS");
+        public static final UnicodeBlock SPECIALS = new UnicodeBlock("SPECIALS", 0xfff0, 0xffff);
         /**
-         * The &quot;Linear B Syllabary&quot; Unicode Block. 
+         * The &quot;Linear B Syllabary&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.2
          */
-        public static final UnicodeBlock LINEAR_B_SYLLABARY = new UnicodeBlock("LINEAR_B_SYLLABARY");
+        public static final UnicodeBlock LINEAR_B_SYLLABARY = new UnicodeBlock("LINEAR_B_SYLLABARY", 0x10000, 0x1007f);
         /**
-         * The &quot;Linear B Ideograms&quot; Unicode Block. 
+         * The &quot;Linear B Ideograms&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock LINEAR_B_IDEOGRAMS = new UnicodeBlock("LINEAR_B_IDEOGRAMS");
+        public static final UnicodeBlock LINEAR_B_IDEOGRAMS = new UnicodeBlock("LINEAR_B_IDEOGRAMS", 0x10080, 0x100ff);
         /**
-         * The &quot;Aegean Numbers&quot; Unicode Block. 
+         * The &quot;Aegean Numbers&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock AEGEAN_NUMBERS = new UnicodeBlock("AEGEAN_NUMBERS");
+        public static final UnicodeBlock AEGEAN_NUMBERS = new UnicodeBlock("AEGEAN_NUMBERS", 0x10100, 0x1013f);
         /**
-         * The &quot;Old Italic&quot; Unicode Block. 
+         * The &quot;Old Italic&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock OLD_ITALIC = new UnicodeBlock("OLD_ITALIC");
+        public static final UnicodeBlock OLD_ITALIC = new UnicodeBlock("OLD_ITALIC", 0x10300, 0x1032f);
         /**
-         * The &quot;Gothic&quot; Unicode Block. 
+         * The &quot;Gothic&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock GOTHIC = new UnicodeBlock("GOTHIC");
+        public static final UnicodeBlock GOTHIC = new UnicodeBlock("GOTHIC", 0x10330, 0x1034f);
         /**
-         * The &quot;Ugaritic&quot; Unicode Block. 
+         * The &quot;Ugaritic&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock UGARITIC = new UnicodeBlock("UGARITIC");
+        public static final UnicodeBlock UGARITIC = new UnicodeBlock("UGARITIC", 0x10380, 0x1039f);
         /**
-         * The &quot;Deseret&quot; Unicode Block. 
+         * The &quot;Deseret&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock DESERET = new UnicodeBlock("DESERET");
+        public static final UnicodeBlock DESERET = new UnicodeBlock("DESERET", 0x10400, 0x1044f);
         /**
-         * The &quot;Shavian&quot; Unicode Block. 
+         * The &quot;Shavian&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock SHAVIAN = new UnicodeBlock("SHAVIAN");
+        public static final UnicodeBlock SHAVIAN = new UnicodeBlock("SHAVIAN", 0x10450, 0x1047f);
         /**
-         * The &quot;Osmanya&quot; Unicode Block. 
+         * The &quot;Osmanya&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock OSMANYA = new UnicodeBlock("OSMANYA");
+        public static final UnicodeBlock OSMANYA = new UnicodeBlock("OSMANYA", 0x10480, 0x104af);
         /**
-         * The &quot;Cypriot Syllabary&quot; Unicode Block. 
+         * The &quot;Cypriot Syllabary&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock CYPRIOT_SYLLABARY = new UnicodeBlock("CYPRIOT_SYLLABARY");
+        public static final UnicodeBlock CYPRIOT_SYLLABARY = new UnicodeBlock("CYPRIOT_SYLLABARY", 0x10800, 0x1083f);
         /**
-         * The &quot;Byzantine Musical Symbols&quot; Unicode Block. 
+         * The &quot;Byzantine Musical Symbols&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock BYZANTINE_MUSICAL_SYMBOLS = new UnicodeBlock("BYZANTINE_MUSICAL_SYMBOLS");
+        public static final UnicodeBlock BYZANTINE_MUSICAL_SYMBOLS = new UnicodeBlock("BYZANTINE_MUSICAL_SYMBOLS", 0x1d000, 0x1d0ff);
         /**
-         * The &quot;Musical Symbols&quot; Unicode Block. 
+         * The &quot;Musical Symbols&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock MUSICAL_SYMBOLS = new UnicodeBlock("MUSICAL_SYMBOLS");
+        public static final UnicodeBlock MUSICAL_SYMBOLS = new UnicodeBlock("MUSICAL_SYMBOLS", 0x1d100, 0x1d1ff);
         /**
-         * The &quot;Tai Xuan Jing Symbols&quot; Unicode Block. 
+         * The &quot;Tai Xuan Jing Symbols&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock TAI_XUAN_JING_SYMBOLS = new UnicodeBlock("TAI_XUAN_JING_SYMBOLS");
+        public static final UnicodeBlock TAI_XUAN_JING_SYMBOLS = new UnicodeBlock("TAI_XUAN_JING_SYMBOLS", 0x1d300, 0x1d35f);
         /**
-         * The &quot;Mathematical Alphanumeric Symbols&quot; Unicode Block. 
+         * The &quot;Mathematical Alphanumeric Symbols&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock MATHEMATICAL_ALPHANUMERIC_SYMBOLS = new UnicodeBlock("MATHEMATICAL_ALPHANUMERIC_SYMBOLS");
+        public static final UnicodeBlock MATHEMATICAL_ALPHANUMERIC_SYMBOLS = new UnicodeBlock("MATHEMATICAL_ALPHANUMERIC_SYMBOLS", 0x1d400, 0x1d7ff);
         /**
-         * The &quot;CJK Unified Ideographs Extension B&quot; Unicode Block. 
+         * The &quot;CJK Unified Ideographs Extension B&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B");
+        public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B", 0x20000, 0x2a6df);
         /**
-         * The &quot;CJK Compatibility Ideographs Supplement&quot; Unicode Block. 
+         * The &quot;CJK Compatibility Ideographs Supplement&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT = new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT");
+        public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT = new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT", 0x2f800, 0x2fa1f);
         /**
-         * The &quot;Tags&quot; Unicode Block. 
+         * The &quot;Tags&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock TAGS = new UnicodeBlock("TAGS");
+        public static final UnicodeBlock TAGS = new UnicodeBlock("TAGS", 0xe0000, 0xe007f);
         /**
-         * The &quot;Variation Selectors Supplement&quot; Unicode Block. 
+         * The &quot;Variation Selectors Supplement&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock VARIATION_SELECTORS_SUPPLEMENT = new UnicodeBlock("VARIATION_SELECTORS_SUPPLEMENT");
+        public static final UnicodeBlock VARIATION_SELECTORS_SUPPLEMENT = new UnicodeBlock("VARIATION_SELECTORS_SUPPLEMENT", 0xe0100, 0xe01ef);
         /**
-         * The &quot;Supplementary Private Use Area-A&quot; Unicode Block. 
+         * The &quot;Supplementary Private Use Area-A&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_A = new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_A");
+        public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_A = new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_A", 0xf0000, 0xfffff);
         /**
-         * The &quot;Supplementary Private Use Area-B&quot; Unicode Block. 
+         * The &quot;Supplementary Private Use Area-B&quot; Unicode Block.
          *
-         * @since Android 1.0
+         * @since 1.5
          */
-        public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_B = new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_B");
+        public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_B = new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_B", 0x100000, 0x10ffff);
 
         /*
          * All of the UnicodeBlocks with valid ranges in ascending order.
          */
         private static UnicodeBlock[] BLOCKS;
 
+        // BEGIN android-changed
+        // /*
+        //  * A SortedMap (String.CASE_INSENSITIVE_ORDER) with keys that represents
+        //  * valid block names and values of the UnicodeBlock constant they map
+        //  * to.
+        //  */
+        // private static final SortedMap<String, UnicodeBlock> BLOCKS_BY_NAME = ...;
         // END android-changed
-        
+
         /**
          * Retrieves the constant that corresponds to the specified block name.
          * The block names are defined by the Unicode 4.0.1 specification in the
          * {@code Blocks-4.0.1.txt} file.
          * <p>
          * Block names may be one of the following:
-         * </p>
          * <ul>
          * <li>Canonical block name, as defined by the Unicode specification;
          * case-insensitive.</li>
@@ -1424,13 +1387,15 @@
          * uppercasing the canonical name and replacing all spaces and hyphens
          * with underscores.</li>
          * </ul>
-         * 
+         *
          * @param blockName
          *            the name of the block to retrieve.
          * @return the UnicodeBlock constant corresponding to {@code blockName}.
+         * @throws NullPointerException
+         *             if {@code blockName} is {@code null}.
          * @throws IllegalArgumentException
          *             if {@code blockName} is not a valid block name.
-         * @since Android 1.0
+         * @since 1.5
          */
         public static final UnicodeBlock forName(String blockName) {
             // BEGIN android-note
@@ -1449,7 +1414,7 @@
                     return SURROGATES_AREA;
                 } else if(blockName.equalsIgnoreCase("greek")) {
                     return GREEK;
-                } else if(blockName.equals("COMBINING_MARKS_FOR_SYMBOLS") || 
+                } else if(blockName.equals("COMBINING_MARKS_FOR_SYMBOLS") ||
                         blockName.equals("Combining Marks for Symbols") ||
                         blockName.equals("CombiningMarksforSymbols")) {
                     return COMBINING_MARKS_FOR_SYMBOLS;
@@ -1459,27 +1424,26 @@
             return BLOCKS[block];
             // END android-changed
         }
-        
+
         /**
          * Gets the constant for the Unicode block that contains the specified
          * character.
-         * 
+         *
          * @param c
          *            the character for which to get the {@code UnicodeBlock}
          *            constant.
          * @return the {@code UnicodeBlock} constant for the block that contains
          *         {@code c}, or {@code null} if {@code c} does not belong to
          *         any defined block.
-         * @since Android 1.0
          */
         public static UnicodeBlock of(char c) {
             return of((int) c);
         }
-        
+
         /**
          * Gets the constant for the Unicode block that contains the specified
          * Unicode code point.
-         * 
+         *
          * @param codePoint
          *            the Unicode code point for which to get the
          *            {@code UnicodeBlock} constant.
@@ -1488,7 +1452,7 @@
          *         not belong to any defined block.
          * @throws IllegalArgumentException
          *             if {@code codePoint} is not a valid Unicode code point.
-         * @since Android 1.0
+         * @since 1.5
          */
         public static UnicodeBlock of(int codePoint) {
             if (!isValidCodePoint(codePoint)) {
@@ -1505,9 +1469,9 @@
             return BLOCKS[block];
             // END android-changed
         }
-        
+
         // BEGIN android-changed
-        private UnicodeBlock(String blockName) {
+        private UnicodeBlock(String blockName, int start, int end) {
             super(blockName);
         }
         // END android-changed
@@ -1516,10 +1480,9 @@
     /**
      * Constructs a new {@code Character} with the specified primitive char
      * value.
-     * 
+     *
      * @param value
      *            the primitive char value to store in the new instance.
-     * @since Android 1.0
      */
     public Character(char value) {
         this.value = value;
@@ -1527,9 +1490,8 @@
 
     /**
      * Gets the primitive value of this character.
-     * 
+     *
      * @return this object's primitive value.
-     * @since Android 1.0
      */
     public char charValue() {
         return value;
@@ -1538,7 +1500,7 @@
     /**
      * Compares this object to the specified character object to determine their
      * relative order.
-     * 
+     *
      * @param c
      *            the character object to compare this object to.
      * @return {@code 0} if the value of this character and the value of
@@ -1547,22 +1509,22 @@
      *         value if the value of this character is less than the value of
      *         {@code c}.
      * @see java.lang.Comparable
-     * @since Android 1.0
+     * @since 1.2
      */
     public int compareTo(Character c) {
         return value - c.value;
     }
-    
+
     /**
      * Returns a {@code Character} instance for the {@code char} value passed.
      * For ASCII/Latin-1 characters (and generally all characters with a Unicode
      * value up to 512), this method should be used instead of the constructor,
      * as it maintains a cache of corresponding {@code Character} instances.
-     * 
+     *
      * @param c
      *            the char value for which to get a {@code Character} instance.
      * @return the {@code Character} instance for {@code c}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static Character valueOf(char c) {
         if (c >= CACHE_LEN ) {
@@ -1589,12 +1551,12 @@
     }
     /**
      * Indicates whether {@code codePoint} is a valid Unicode code point.
-     * 
+     *
      * @param codePoint
      *            the code point to test.
      * @return {@code true} if {@code codePoint} is a valid Unicode code point;
      *         {@code false} otherwise.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static boolean isValidCodePoint(int codePoint) {
         return (MIN_CODE_POINT <= codePoint && MAX_CODE_POINT >= codePoint);
@@ -1603,12 +1565,12 @@
     /**
      * Indicates whether {@code codePoint} is within the supplementary code
      * point range.
-     * 
+     *
      * @param codePoint
      *            the code point to test.
      * @return {@code true} if {@code codePoint} is within the supplementary
      *         code point range; {@code false} otherwise.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static boolean isSupplementaryCodePoint(int codePoint) {
         return (MIN_SUPPLEMENTARY_CODE_POINT <= codePoint && MAX_CODE_POINT >= codePoint);
@@ -1618,13 +1580,13 @@
      * Indicates whether {@code ch} is a high- (or leading-) surrogate code unit
      * that is used for representing supplementary characters in UTF-16
      * encoding.
-     * 
+     *
      * @param ch
      *            the character to test.
      * @return {@code true} if {@code ch} is a high-surrogate code unit;
      *         {@code false} otherwise.
      * @see #isLowSurrogate(char)
-     * @since Android 1.0
+     * @since 1.5
      */
     public static boolean isHighSurrogate(char ch) {
         return (MIN_HIGH_SURROGATE <= ch && MAX_HIGH_SURROGATE >= ch);
@@ -1634,21 +1596,21 @@
      * Indicates whether {@code ch} is a low- (or trailing-) surrogate code unit
      * that is used for representing supplementary characters in UTF-16
      * encoding.
-     * 
+     *
      * @param ch
      *            the character to test.
      * @return {@code true} if {@code ch} is a low-surrogate code unit;
      *         {@code false} otherwise.
      * @see #isHighSurrogate(char)
-     * @since Android 1.0
-     */    
+     * @since 1.5
+     */
     public static boolean isLowSurrogate(char ch) {
         return (MIN_LOW_SURROGATE <= ch && MAX_LOW_SURROGATE >= ch);
     }
 
     /**
      * Indicates whether the specified character pair is a valid surrogate pair.
-     * 
+     *
      * @param high
      *            the high surrogate unit to test.
      * @param low
@@ -1658,7 +1620,7 @@
      *         otherwise.
      * @see #isHighSurrogate(char)
      * @see #isLowSurrogate(char)
-     * @since Android 1.0
+     * @since 1.5
      */
     public static boolean isSurrogatePair(char high, char low) {
         return (isHighSurrogate(high) && isLowSurrogate(low));
@@ -1670,12 +1632,14 @@
      * is greater than or equal to {@code 0x10000}, in which case {@code 2} is
      * returned, otherwise {@code 1}. To test if the code point is valid, use
      * the {@link #isValidCodePoint(int)} method.
-     * 
+     *
      * @param codePoint
      *            the code point for which to calculate the number of required
      *            chars.
      * @return {@code 2} if {@code codePoint >= 0x10000}; {@code 1} otherwise.
-     * @since Android 1.0
+     * @see #isValidCodePoint(int)
+     * @see #isSupplementaryCodePoint(int)
+     * @since 1.5
      */
     public static int charCount(int codePoint) {
         return (codePoint >= 0x10000 ? 2 : 1);
@@ -1687,14 +1651,14 @@
      * surrogates, then the result is indeterminate. The
      * {@link #isSurrogatePair(char, char)} method should be used prior to this
      * method to validate the pair.
-     * 
+     *
      * @param high
      *            the high surrogate unit.
      * @param low
      *            the low surrogate unit.
      * @return the Unicode code point corresponding to the surrogate unit pair.
      * @see #isSurrogatePair(char, char)
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int toCodePoint(char high, char low) {
         // See RFC 2781, Section 2.2
@@ -1711,7 +1675,7 @@
      * {@code index + 1} is a low-surrogate unit, then the supplementary code
      * point represented by the pair is returned; otherwise the {@code char}
      * value at {@code index} is returned.
-     * 
+     *
      * @param seq
      *            the source sequence of {@code char} units.
      * @param index
@@ -1719,10 +1683,12 @@
      *            point.
      * @return the Unicode code point or {@code char} value at {@code index} in
      *         {@code seq}.
+     * @throws NullPointerException
+     *             if {@code seq} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if the {@code index} is negative or greater than or equal to
      *             the length of {@code seq}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int codePointAt(CharSequence seq, int index) {
         if (seq == null) {
@@ -1751,7 +1717,7 @@
      * {@code index + 1} is a low-surrogate unit, then the supplementary code
      * point represented by the pair is returned; otherwise the {@code char}
      * value at {@code index} is returned.
-     * 
+     *
      * @param seq
      *            the source array of {@code char} units.
      * @param index
@@ -1759,10 +1725,12 @@
      *            point.
      * @return the Unicode code point or {@code char} value at {@code index} in
      *         {@code seq}.
+     * @throws NullPointerException
+     *             if {@code seq} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if the {@code index} is negative or greater than or equal to
      *             the length of {@code seq}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int codePointAt(char[] seq, int index) {
         if (seq == null) {
@@ -1792,7 +1760,7 @@
      * low-surrogate unit, then the supplementary code point represented by the
      * pair is returned; otherwise the {@code char} value at {@code index} is
      * returned.
-     * 
+     *
      * @param seq
      *            the source array of {@code char} units.
      * @param index
@@ -1801,16 +1769,18 @@
      *            the index after the last unit in {@code seq} that can be used.
      * @return the Unicode code point or {@code char} value at {@code index} in
      *         {@code seq}.
+     * @throws NullPointerException
+     *             if {@code seq} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code index < 0}, {@code index >= limit},
      *             {@code limit < 0} or if {@code limit} is greater than the
      *             length of {@code seq}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int codePointAt(char[] seq, int index, int limit) {
         if (index < 0 || index >= limit || limit < 0 || limit > seq.length) {
             throw new IndexOutOfBoundsException();
-        }       
+        }
 
         char high = seq[index++];
         if (index >= limit) {
@@ -1830,7 +1800,7 @@
      * {@code index - 2} is a high-surrogate unit, then the supplementary code
      * point represented by the pair is returned; otherwise the {@code char}
      * value at {@code index - 1} is returned.
-     * 
+     *
      * @param seq
      *            the source sequence of {@code char} units.
      * @param index
@@ -1838,10 +1808,12 @@
      *            point that should be returned.
      * @return the Unicode code point or {@code char} value before {@code index}
      *         in {@code seq}.
+     * @throws NullPointerException
+     *             if {@code seq} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if the {@code index} is less than 1 or greater than the
      *             length of {@code seq}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int codePointBefore(CharSequence seq, int index) {
         if (seq == null) {
@@ -1870,7 +1842,7 @@
      * {@code index - 2} is a high-surrogate unit, then the supplementary code
      * point represented by the pair is returned; otherwise the {@code char}
      * value at {@code index - 1} is returned.
-     * 
+     *
      * @param seq
      *            the source array of {@code char} units.
      * @param index
@@ -1878,10 +1850,12 @@
      *            point that should be returned.
      * @return the Unicode code point or {@code char} value before {@code index}
      *         in {@code seq}.
+     * @throws NullPointerException
+     *             if {@code seq} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if the {@code index} is less than 1 or greater than the
      *             length of {@code seq}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int codePointBefore(char[] seq, int index) {
         if (seq == null) {
@@ -1911,7 +1885,7 @@
      * high-surrogate unit, then the supplementary code point represented by the
      * pair is returned; otherwise the {@code char} value at {@code index - 1}
      * is returned.
-     * 
+     *
      * @param seq
      *            the source array of {@code char} units.
      * @param index
@@ -1921,12 +1895,14 @@
      *            the index of the first element in {@code seq}.
      * @return the Unicode code point or {@code char} value before {@code index}
      *         in {@code seq}.
+     * @throws NullPointerException
+     *             if {@code seq} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if the {@code index <= start}, {@code start < 0},
      *             {@code index} is greater than the length of {@code seq}, or
      *             if {@code start} is equal or greater than the length of
      *             {@code seq}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int codePointBefore(char[] seq, int index, int start) {
         if (seq == null) {
@@ -1952,7 +1928,7 @@
      * Converts the specified Unicode code point into a UTF-16 encoded sequence
      * and copies the value(s) into the char array {@code dst}, starting at
      * index {@code dstIndex}.
-     * 
+     *
      * @param codePoint
      *            the Unicode code point to encode.
      * @param dst
@@ -1962,12 +1938,14 @@
      * @return the number of {@code char} value units copied into {@code dst}.
      * @throws IllegalArgumentException
      *             if {@code codePoint} is not a valid Unicode code point.
+     * @throws NullPointerException
+     *             if {@code dst} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code dstIndex} is negative, greater than or equal to
      *             {@code dst.length} or equals {@code dst.length - 1} when
      *             {@code codePoint} is a
      *             {@link #isSupplementaryCodePoint(int) supplementary code point}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int toChars(int codePoint, char[] dst, int dstIndex) {
         if (!isValidCodePoint(codePoint)) {
@@ -2001,7 +1979,7 @@
     /**
      * Converts the specified Unicode code point into a UTF-16 encoded sequence
      * and returns it as a char array.
-     * 
+     *
      * @param codePoint
      *            the Unicode code point to encode.
      * @return the UTF-16 encoded char sequence. If {@code codePoint} is a
@@ -2010,7 +1988,7 @@
      *         contains just one character.
      * @throws IllegalArgumentException
      *             if {@code codePoint} is not a valid Unicode code point.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static char[] toChars(int codePoint) {
         if (!isValidCodePoint(codePoint)) {
@@ -2031,7 +2009,7 @@
      * specified character sequence, as delineated by {@code beginIndex} and
      * {@code endIndex}. Any surrogate values with missing pair values will be
      * counted as one code point.
-     * 
+     *
      * @param seq
      *            the {@code CharSequence} to look through.
      * @param beginIndex
@@ -2039,10 +2017,12 @@
      * @param endIndex
      *            the exclusive index to stop counting at.
      * @return the number of Unicode code points.
+     * @throws NullPointerException
+     *             if {@code seq} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code beginIndex < 0}, {@code beginIndex > endIndex} or
      *             if {@code endIndex} is greater than the length of {@code seq}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int codePointCount(CharSequence seq, int beginIndex,
             int endIndex) {
@@ -2075,7 +2055,7 @@
      * specified char array, as delineated by {@code offset} and {@code count}.
      * Any surrogate values with missing pair values will be counted as one code
      * point.
-     * 
+     *
      * @param seq
      *            the char array to look through
      * @param offset
@@ -2084,11 +2064,13 @@
      *            the number of {@code char} values to look through in
      *            {@code seq}.
      * @return the number of Unicode code points.
+     * @throws NullPointerException
+     *             if {@code seq} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code offset < 0}, {@code count < 0} or if
      *             {@code offset + count} is greater than the length of
      *             {@code seq}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int codePointCount(char[] seq, int offset, int count) {
         if (seq == null) {
@@ -2119,7 +2101,7 @@
     /**
      * Determines the index in the specified character sequence that is offset
      * {@code codePointOffset} code points from {@code index}.
-     * 
+     *
      * @param seq
      *            the character sequence to find the index in.
      * @param index
@@ -2129,13 +2111,15 @@
      *            be a negative or positive value.
      * @return the index in {@code seq} that is {@code codePointOffset} code
      *         points away from {@code index}.
+     * @throws NullPointerException
+     *             if {@code seq} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code index < 0}, {@code index} is greater than the
      *             length of {@code seq}, or if there are not enough values in
      *             {@code seq} to skip {@code codePointOffset} code points
      *             forwards or backwards (if {@code codePointOffset} is
      *             negative) from {@code index}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int offsetByCodePoints(CharSequence seq, int index,
             int codePointOffset) {
@@ -2193,7 +2177,7 @@
      * Determines the index in a subsequence of the specified character array
      * that is offset {@code codePointOffset} code points from {@code index}.
      * The subsequence is delineated by {@code start} and {@code count}.
-     * 
+     *
      * @param seq
      *            the character array to find the index in.
      * @param start
@@ -2209,6 +2193,8 @@
      *            be a negative or positive value.
      * @return the index in {@code seq} that is {@code codePointOffset} code
      *         points away from {@code index}.
+     * @throws NullPointerException
+     *             if {@code seq} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code start < 0}, {@code count < 0},
      *             {@code index < start}, {@code index > start + count},
@@ -2217,7 +2203,7 @@
      *             {@code seq} to skip {@code codePointOffset} code points
      *             forward or backward (if {@code codePointOffset} is
      *             negative) from {@code index}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int offsetByCodePoints(char[] seq, int start, int count,
             int index, int codePointOffset) {
@@ -2276,14 +2262,13 @@
      * Convenience method to determine the value of the specified character
      * {@code c} in the supplied radix. The value of {@code radix} must be
      * between MIN_RADIX and MAX_RADIX.
-     * 
+     *
      * @param c
      *            the character to determine the value of.
      * @param radix
      *            the radix.
      * @return the value of {@code c} in {@code radix} if {@code radix} lies
      *         between {@link #MIN_RADIX} and {@link #MAX_RADIX}; -1 otherwise.
-     * @since Android 1.0
      */
     public static int digit(char c, int radix) {
         // BEGIN android-changed
@@ -2313,12 +2298,12 @@
         return UCharacter.digit(c, radix);
         // ENd android-changed
     }
-    
+
     /**
      * Convenience method to determine the value of the character
      * {@code codePoint} in the supplied radix. The value of {@code radix} must
      * be between MIN_RADIX and MAX_RADIX.
-     * 
+     *
      * @param codePoint
      *            the character, including supplementary characters.
      * @param radix
@@ -2326,7 +2311,6 @@
      * @return if {@code radix} lies between {@link #MIN_RADIX} and
      *         {@link #MAX_RADIX} then the value of the character in the radix;
      *         -1 otherwise.
-     * @since Android 1.0
      */
     public static int digit(int codePoint, int radix) {
         return UCharacter.digit(codePoint, radix);
@@ -2336,12 +2320,11 @@
      * Compares this object with the specified object and indicates if they are
      * equal. In order to be equal, {@code object} must be an instance of
      * {@code Character} and have the same char value as this object.
-     * 
+     *
      * @param object
      *            the object to compare this double with.
      * @return {@code true} if the specified object is equal to this
      *         {@code Character}; {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -2355,14 +2338,13 @@
      * {@code MAX_RADIX} inclusive; {@code digit} must not be negative and
      * smaller than {@code radix}. If any of these conditions does not hold, 0
      * is returned.
-     * 
+     *
      * @param digit
      *            the integer value.
      * @param radix
      *            the radix.
      * @return the character which represents the {@code digit} in the
      *         {@code radix}.
-     * @since Android 1.0
      */
     public static char forDigit(int digit, int radix) {
         if (MIN_RADIX <= radix && radix <= MAX_RADIX) {
@@ -2375,13 +2357,12 @@
 
     /**
      * Gets the numeric value of the specified Unicode character.
-     * 
+     *
      * @param c
      *            the Unicode character to get the numeric value of.
      * @return a non-negative numeric integer value if a numeric value for
      *         {@code c} exists, -1 if there is no numeric value for {@code c},
      *         -2 if the numeric value can not be represented with an integer.
-     * @since Android 1.0
      */
     public static int getNumericValue(char c) {
         // BEGIN android-changed
@@ -2414,19 +2395,18 @@
         return UCharacter.getNumericValue(c);
         // END android-changed
     }
-    
+
     /**
      * Gets the numeric value of the specified Unicode code point. For example,
      * the code point '\u216B' stands for the Roman number XII, which has the
      * numeric value 12.
-     * 
+     *
      * @param codePoint
      *            the Unicode code point to get the numeric value of.
      * @return a non-negative numeric integer value if a numeric value for
      *         {@code codePoint} exists, -1 if there is no numeric value for
      *         {@code codePoint}, -2 if the numeric value can not be
      *         represented with an integer.
-     * @since Android 1.0
      */
     public static int getNumericValue(int codePoint) {
         return UCharacter.getNumericValue(codePoint);
@@ -2434,14 +2414,16 @@
 
     /**
      * Gets the general Unicode category of the specified character.
-     * 
+     *
      * @param c
      *            the character to get the category of.
      * @return the Unicode category of {@code c}.
-     * @since Android 1.0
      */
     public static int getType(char c) {
         // BEGIN android-changed
+        // if(c < 1000) {
+        //     return typeValuesCache[(int)c];
+        // }
         // int result = BinarySearch.binarySearchRange(typeKeys, c);
         // int high = typeValues[result * 2];
         // if (c <= high) {
@@ -2452,19 +2434,23 @@
         //     return (c & 1) == 1 ? code >> 8 : code & 0xff;
         // }
         // return UNASSIGNED;
-        return getType((int)c);
+        return getType((int) c);
         // END android-changed
     }
-    
+
     /**
      * Gets the general Unicode category of the specified code point.
-     * 
+     *
      * @param codePoint
      *            the Unicode code point to get the category of.
      * @return the Unicode category of {@code codePoint}.
-     * @since Android 1.0
      */
     public static int getType(int codePoint) {
+        // BEGIN android-changed
+    	// if (codePoint < 1000 && codePoint > 0) {
+    	//     return typeValuesCache[codePoint];
+    	// }
+        // END android-changed
         int type = UCharacter.getType(codePoint);
 
         // the type values returned by UCharacter are not compatible with what
@@ -2477,11 +2463,10 @@
 
     /**
      * Gets the Unicode directionality of the specified character.
-     * 
+     *
      * @param c
      *            the character to get the directionality of.
      * @return the Unicode directionality of {@code c}.
-     * @since Android 1.0
      */
     public static byte getDirectionality(char c) {
         // BEGIN android-changed
@@ -2498,21 +2483,20 @@
         return getDirectionality((int)c);
         // END android-changed
     }
-    
+
     /**
      * Gets the Unicode directionality of the specified character.
-     * 
+     *
      * @param codePoint
      *            the Unicode code point to get the directionality of.
      * @return the Unicode directionality of {@code codePoint}.
-     * @since Android 1.0
      */
     public static byte getDirectionality(int codePoint) {
         if (getType(codePoint) == Character.UNASSIGNED) {
             return Character.DIRECTIONALITY_UNDEFINED;
         }
-        
-        byte UCDirectionality = UCharacter.getDirectionality(codePoint);       
+
+        byte UCDirectionality = UCharacter.getDirectionality(codePoint);
         if (UCDirectionality == -1) {
             return -1;
         }
@@ -2521,12 +2505,11 @@
 
     /**
      * Indicates whether the specified character is mirrored.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is mirrored; {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public static boolean isMirrored(char c) {
         // BEGIN android-changed
@@ -2539,15 +2522,14 @@
         return isMirrored((int)c);
         // ENd android-changed
     }
-    
+
     /**
      * Indicates whether the specified code point is mirrored.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if {@code codePoint} is mirrored, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public static boolean isMirrored(int codePoint) {
         return UCharacter.isMirrored(codePoint);
@@ -2561,12 +2543,11 @@
     /**
      * Indicates whether the specified character is defined in the Unicode
      * specification.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if the general Unicode category of the character is
      *         not {@code UNASSIGNED}; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isDefined(char c) {
         // BEGIN android-changed
@@ -2574,16 +2555,15 @@
         return UCharacter.isDefined(c);
         // END android-changed
     }
-    
+
     /**
      * Indicates whether the specified code point is defined in the Unicode
      * specification.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if the general Unicode category of the code point is
      *         not {@code UNASSIGNED}; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isDefined(int codePoint) {
         return UCharacter.isDefined(codePoint);
@@ -2591,12 +2571,11 @@
 
     /**
      * Indicates whether the specified character is a digit.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is a digit; {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public static boolean isDigit(char c) {
         // BEGIN android-changed
@@ -2611,15 +2590,14 @@
         return UCharacter.isDigit(c);
         // END android-changed
     }
-    
+
     /**
      * Indicates whether the specified code point is a digit.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if {@code codePoint} is a digit; {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public static boolean isDigit(int codePoint) {
         return UCharacter.isDigit(codePoint);
@@ -2628,11 +2606,10 @@
     /**
      * Indicates whether the specified character is ignorable in a Java or
      * Unicode identifier.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is ignorable; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isIdentifierIgnorable(char c) {
         // BEGIN android-changed
@@ -2641,16 +2618,15 @@
         return UCharacter.isIdentifierIgnorable(c);
         // END android-changed
     }
-    
+
     /**
      * Indicates whether the specified code point is ignorable in a Java or
      * Unicode identifier.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if {@code codePoint} is ignorable; {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public static boolean isIdentifierIgnorable(int codePoint) {
         return UCharacter.isIdentifierIgnorable(codePoint);
@@ -2658,12 +2634,11 @@
 
     /**
      * Indicates whether the specified character is an ISO control character.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is an ISO control character;
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isISOControl(char c) {
         return isISOControl((int)c);
@@ -2671,12 +2646,11 @@
 
     /**
      * Indicates whether the specified code point is an ISO control character.
-     * 
+     *
      * @param c
      *            the code point to check.
      * @return {@code true} if {@code c} is an ISO control character;
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isISOControl(int c) {
         return (c >= 0 && c <= 0x1f) || (c >= 0x7f && c <= 0x9f);
@@ -2685,12 +2659,11 @@
     /**
      * Indicates whether the specified character is a valid part of a Java
      * identifier other than the first character.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is valid as part of a Java identifier;
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isJavaIdentifierPart(char c) {
         // Optimized case for ASCII
@@ -2709,31 +2682,29 @@
     /**
      * Indicates whether the specified code point is a valid part of a Java
      * identifier other than the first character.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if {@code c} is valid as part of a Java identifier;
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isJavaIdentifierPart(int codePoint) {
         int type = getType(codePoint);
         return (type >= UPPERCASE_LETTER && type <= OTHER_LETTER)
                 || type == CURRENCY_SYMBOL || type == CONNECTOR_PUNCTUATION
                 || (type >= DECIMAL_DIGIT_NUMBER && type <= LETTER_NUMBER)
-                || type == COMBINING_SPACING_MARK || type == NON_SPACING_MARK 
+                || type == COMBINING_SPACING_MARK || type == NON_SPACING_MARK
                 || isIdentifierIgnorable(codePoint);
     }
 
     /**
      * Indicates whether the specified character is a valid first character for
      * a Java identifier.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is a valid first character of a Java
      *         identifier; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isJavaIdentifierStart(char c) {
         // Optimized case for ASCII
@@ -2746,16 +2717,15 @@
                 || type == CURRENCY_SYMBOL || type == CONNECTOR_PUNCTUATION
                 || type == LETTER_NUMBER;
     }
-    
+
     /**
      * Indicates whether the specified code point is a valid start for a Java
      * identifier.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if {@code codePoint} is a valid start of a Java
      *         identifier; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isJavaIdentifierStart(int codePoint) {
         int type = getType(codePoint);
@@ -2765,13 +2735,12 @@
 
     /**
      * Indicates whether the specified character is a Java letter.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is a Java letter; {@code false}
      *         otherwise.
      * @deprecated Use {@link #isJavaIdentifierStart(char)}
-     * @since Android 1.0
      */
     @Deprecated
     public static boolean isJavaLetter(char c) {
@@ -2781,13 +2750,12 @@
     /**
      * Indicates whether the specified character is a Java letter or digit
      * character.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is a Java letter or digit;
      *         {@code false} otherwise.
      * @deprecated Use {@link #isJavaIdentifierPart(char)}
-     * @since Android 1.0
      */
     @Deprecated
     public static boolean isJavaLetterOrDigit(char c) {
@@ -2796,11 +2764,10 @@
 
     /**
      * Indicates whether the specified character is a letter.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is a letter; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isLetter(char c) {
         // BEGIN android-changed
@@ -2815,15 +2782,14 @@
         return UCharacter.isLetter(c);
         // END android-changed
     }
-    
+
     /**
      * Indicates whether the specified code point is a letter.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if {@code codePoint} is a letter; {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public static boolean isLetter(int codePoint) {
         return UCharacter.isLetter(codePoint);
@@ -2831,12 +2797,11 @@
 
     /**
      * Indicates whether the specified character is a letter or a digit.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is a letter or a digit; {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public static boolean isLetterOrDigit(char c) {
         // BEGIN android-changed
@@ -2846,15 +2811,14 @@
         return UCharacter.isLetterOrDigit(c);
         // END andorid-changed
     }
-    
+
     /**
      * Indicates whether the specified code point is a letter or a digit.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if {@code codePoint} is a letter or a digit;
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isLetterOrDigit(int codePoint) {
         return UCharacter.isLetterOrDigit(codePoint);
@@ -2862,12 +2826,11 @@
 
     /**
      * Indicates whether the specified character is a lower case letter.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is a lower case letter; {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public static boolean isLowerCase(char c) {
         // BEGIN android-changed
@@ -2878,20 +2841,19 @@
         // if (c < 128) {
         //     return false;
         // }
-        // 
+        //
         // return getType(c) == LOWERCASE_LETTER;
         return UCharacter.isLowerCase(c);
         // END android-changed
     }
-    
+
     /**
      * Indicates whether the specified code point is a lower case letter.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if {@code codePoint} is a lower case letter;
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isLowerCase(int codePoint) {
         return UCharacter.isLowerCase(codePoint);
@@ -2899,13 +2861,12 @@
 
     /**
      * Indicates whether the specified character is a Java space.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is a Java space; {@code false}
      *         otherwise.
      * @deprecated Use {@link #isWhitespace(char)}
-     * @since Android 1.0
      */
     @Deprecated
     public static boolean isSpace(char c) {
@@ -2916,12 +2877,11 @@
      * Indicates whether the specified character is a Unicode space character.
      * That is, if it is a member of one of the Unicode categories Space
      * Separator, Line Separator, or Paragraph Separator.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is a Unicode space character,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isSpaceChar(char c) {
         // BEGIN android-changed
@@ -2936,17 +2896,16 @@
         return UCharacter.isSpaceChar(c);
         // END android-changed
     }
-    
+
     /**
      * Indicates whether the specified code point is a Unicode space character.
      * That is, if it is a member of one of the Unicode categories Space
      * Separator, Line Separator, or Paragraph Separator.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if {@code codePoint} is a Unicode space character,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isSpaceChar(int codePoint) {
         return UCharacter.isSpaceChar(codePoint);
@@ -2954,12 +2913,11 @@
 
     /**
      * Indicates whether the specified character is a titlecase character.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is a titlecase character, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public static boolean isTitleCase(char c) {
         // BEGIN android-changed
@@ -2978,15 +2936,14 @@
         return UCharacter.isTitleCase(c);
         // END android-changed
     }
-    
+
     /**
      * Indicates whether the specified code point is a titlecase character.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if {@code codePoint} is a titlecase character,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isTitleCase(int codePoint) {
         return UCharacter.isTitleCase(codePoint);
@@ -2995,12 +2952,11 @@
     /**
      * Indicates whether the specified character is valid as part of a Unicode
      * identifier other than the first character.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is valid as part of a Unicode
      *         identifier; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isUnicodeIdentifierPart(char c) {
         // BEGIN android-changed
@@ -3013,16 +2969,15 @@
         return UCharacter.isUnicodeIdentifierPart(c);
         // END android-changed
     }
-    
+
     /**
      * Indicates whether the specified code point is valid as part of a Unicode
      * identifier other than the first character.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if {@code codePoint} is valid as part of a Unicode
      *         identifier; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isUnicodeIdentifierPart(int codePoint) {
         return UCharacter.isUnicodeIdentifierPart(codePoint);
@@ -3031,12 +2986,11 @@
     /**
      * Indicates whether the specified character is a valid initial character
      * for a Unicode identifier.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is a valid first character for a
      *         Unicode identifier; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isUnicodeIdentifierStart(char c) {
         // BEGIN android-changed
@@ -3046,16 +3000,15 @@
         return UCharacter.isUnicodeIdentifierStart(c);
         // END android-changed
     }
-    
+
     /**
      * Indicates whether the specified code point is a valid initial character
      * for a Unicode identifier.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if {@code codePoint} is a valid first character for
      *         a Unicode identifier; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isUnicodeIdentifierStart(int codePoint) {
         return UCharacter.isUnicodeIdentifierStart(codePoint);
@@ -3063,12 +3016,11 @@
 
     /**
      * Indicates whether the specified character is an upper case letter.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if {@code c} is a upper case letter; {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public static boolean isUpperCase(char c) {
         // BEGIN android-changed
@@ -3079,20 +3031,19 @@
         // if (c < 128) {
         //     return false;
         // }
-        // 
+        //
         // return getType(c) == UPPERCASE_LETTER;
         return UCharacter.isUpperCase(c);
         // END android-changed
     }
-    
+
     /**
      * Indicates whether the specified code point is an upper case letter.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if {@code codePoint} is a upper case letter;
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isUpperCase(int codePoint) {
         return UCharacter.isUpperCase(codePoint);
@@ -3101,12 +3052,11 @@
     /**
      * Indicates whether the specified character is a whitespace character in
      * Java.
-     * 
+     *
      * @param c
      *            the character to check.
      * @return {@code true} if the supplied {@code c} is a whitespace character
      *         in Java; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isWhitespace(char c) {
         // BEGIN android-changed
@@ -3124,30 +3074,29 @@
         return UCharacter.isWhitespace(c);
         // END android-changed
     }
-    
+
     /**
      * Indicates whether the specified code point is a whitespace character in
      * Java.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return {@code true} if the supplied {@code c} is a whitespace character
      *         in Java; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isWhitespace(int codePoint) {
         //FIXME depends on ICU when the codePoint is '\u2007'
         return UCharacter.isWhitespace(codePoint);
+
     }
 
     /**
      * Reverses the order of the first and second byte in the specified
      * character.
-     * 
+     *
      * @param c
      *            the character to reverse.
      * @return the character with reordered bytes.
-     * @since Android 1.0
      */
     public static char reverseBytes(char c) {
         return (char)((c<<8) | (c>>8));
@@ -3157,12 +3106,11 @@
      * Returns the lower case equivalent for the specified character if the
      * character is an upper case letter. Otherwise, the specified character is
      * returned unchanged.
-     * 
+     *
      * @param c
      *            the character
      * @return if {@code c} is an upper case character then its lower case
      *         counterpart, otherwise just {@code c}.
-     * @since Android 1.0
      */
     public static char toLowerCase(char c) {
         // BEGIN android-changed
@@ -3170,10 +3118,13 @@
         // if ('A' <= c && c <= 'Z') {
         //     return (char) (c + ('a' - 'A'));
         // }
-        // if (c < 128) {
+        // if (c < 192) {// || c == 215 || (c > 222 && c < 256)) {
         //     return c;
         // }
-        // 
+        // if (c<1000) {
+        //     return (char)lowercaseValuesCache[c-192];
+        // }
+        //
         // int result = BinarySearch.binarySearchRange(lowercaseKeys, c);
         // if (result >= 0) {
         //     boolean by2 = false;
@@ -3195,17 +3146,16 @@
         return (char)UCharacter.toLowerCase(c);
         // END android-changed
     }
-    
+
     /**
      * Returns the lower case equivalent for the specified code point if it is
      * an upper case letter. Otherwise, the specified code point is returned
      * unchanged.
-     * 
+     *
      * @param codePoint
      *            the code point to check.
      * @return if {@code codePoint} is an upper case character then its lower
      *         case counterpart, otherwise just {@code codePoint}.
-     * @since Android 1.0
      */
     public static int toLowerCase(int codePoint) {
         return UCharacter.toLowerCase(codePoint);
@@ -3218,11 +3168,10 @@
 
     /**
      * Converts the specified character to its string representation.
-     * 
+     *
      * @param value
      *            the character to convert.
      * @return the character converted to a string.
-     * @since Android 1.0
      */
     public static String toString(char value) {
         return String.valueOf(value);
@@ -3231,12 +3180,11 @@
     /**
      * Returns the title case equivalent for the specified character if it
      * exists. Otherwise, the specified character is returned unchanged.
-     * 
+     *
      * @param c
      *            the character to convert.
      * @return the title case equivalent of {@code c} if it exists, otherwise
      *         {@code c}.
-     * @since Android 1.0
      */
     public static char toTitleCase(char c) {
         // BEGIN android-changed
@@ -3251,16 +3199,15 @@
         return (char)UCharacter.toTitleCase(c);
         // ENd android-changed
     }
-    
+
     /**
      * Returns the title case equivalent for the specified code point if it
      * exists. Otherwise, the specified code point is returned unchanged.
-     * 
+     *
      * @param codePoint
      *            the code point to convert.
      * @return the title case equivalent of {@code codePoint} if it exists,
      *         otherwise {@code codePoint}.
-     * @since Android 1.0
      */
     public static int toTitleCase(int codePoint) {
         return UCharacter.toTitleCase(codePoint);
@@ -3270,12 +3217,11 @@
      * Returns the upper case equivalent for the specified character if the
      * character is a lower case letter. Otherwise, the specified character is
      * returned unchanged.
-     * 
+     *
      * @param c
      *            the character to convert.
      * @return if {@code c} is a lower case character then its upper case
      *         counterpart, otherwise just {@code c}.
-     * @since Android 1.0
      */
     public static char toUpperCase(char c) {
         // BEGIN android-changed
@@ -3283,10 +3229,12 @@
         // if ('a' <= c && c <= 'z') {
         //     return (char) (c - ('a' - 'A'));
         // }
-        // if (c < 128) {
+        // if (c < 181) {
         //     return c;
         // }
-        // 
+        // if (c<1000) {
+        //     return (char)uppercaseValuesCache[(int)c-181];
+        // }
         // int result = BinarySearch.binarySearchRange(uppercaseKeys, c);
         // if (result >= 0) {
         //     boolean by2 = false;
@@ -3308,17 +3256,16 @@
         return (char)UCharacter.toUpperCase(c);
         // END android-changed
     }
-    
+
     /**
      * Returns the upper case equivalent for the specified code point if the
      * code point is a lower case letter. Otherwise, the specified code point is
      * returned unchanged.
-     * 
+     *
      * @param codePoint
      *            the code point to convert.
      * @return if {@code codePoint} is a lower case character then its upper
      *         case counterpart, otherwise just {@code codePoint}.
-     * @since Android 1.0
      */
     public static int toUpperCase(int codePoint) {
         return UCharacter.toUpperCase(codePoint);
diff --git a/libcore/luni/src/main/java/java/lang/ClassCastException.java b/libcore/luni/src/main/java/java/lang/ClassCastException.java
index 1482b21..b33efcf 100644
--- a/libcore/luni/src/main/java/java/lang/ClassCastException.java
+++ b/libcore/luni/src/main/java/java/lang/ClassCastException.java
@@ -22,8 +22,6 @@
 /**
  * Thrown when a program attempts to cast a an object to a type with which it is
  * not compatible.
- * 
- * @since Android 1.0
  */
 public class ClassCastException extends RuntimeException {
     private static final long serialVersionUID = -9223365651070458532L;
@@ -31,8 +29,6 @@
     /**
      * Constructs a new {@code ClassCastException} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public ClassCastException() {
         super();
@@ -41,10 +37,9 @@
     /**
      * Constructs a new {@code ClassCastException} with the current stack trace
      * and the specified detail message.
-     * 
+     *
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public ClassCastException(String detailMessage) {
         super(detailMessage);
@@ -53,12 +48,11 @@
     /**
      * Constructs a new {@code ClassCastException} with the current stack trace
      * and a detail message based on the source and target class.
-     * 
+     *
      * @param instanceClass
      *            the class being cast from.
      * @param castClass
      *            the class being cast to.
-     * @since Android 1.0
      */
     ClassCastException(Class<?> instanceClass, Class<?> castClass) {
         super(Msg.getString("K0340", instanceClass.getName(), castClass //$NON-NLS-1$
diff --git a/libcore/luni/src/main/java/java/lang/ClassCircularityError.java b/libcore/luni/src/main/java/java/lang/ClassCircularityError.java
index 6dd1c8e..07bf339 100644
--- a/libcore/luni/src/main/java/java/lang/ClassCircularityError.java
+++ b/libcore/luni/src/main/java/java/lang/ClassCircularityError.java
@@ -24,9 +24,6 @@
  * <p>
  * Note that this error can only occur when inconsistent class files are loaded,
  * since it would normally be detected at compile time.
- * </p>
- * 
- * @since Android 1.0
  */
 public class ClassCircularityError extends LinkageError {
 
@@ -35,8 +32,6 @@
     /**
      * Constructs a new {@code ClassCircularityError} that include the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public ClassCircularityError() {
         super();
@@ -45,10 +40,9 @@
     /**
      * Constructs a new {@code ClassCircularityError} with the current stack
      * trace and the specified detail message.
-     * 
+     *
      * @param detailMessage
      *            the detail message for this error.
-     * @since Android 1.0
      */
     public ClassCircularityError(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/ClassFormatError.java b/libcore/luni/src/main/java/java/lang/ClassFormatError.java
index 282ed70..009f44a 100644
--- a/libcore/luni/src/main/java/java/lang/ClassFormatError.java
+++ b/libcore/luni/src/main/java/java/lang/ClassFormatError.java
@@ -20,8 +20,6 @@
 /**
  * Thrown by a class loader when a class file has an illegal format or if the
  * data that it contains can not be interpreted as a class.
- * 
- * @since Android 1.0
  */
 public class ClassFormatError extends LinkageError {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code ClassFormatError} that includes the current stack
      * trace.
-     * 
-     * @since Android 1.0
      */
     public ClassFormatError() {
         super();
@@ -40,10 +36,9 @@
     /**
      * Constructs a new {@code ClassFormatError} with the current stack trace
      * and the specified detail message.
-     * 
+     *
      * @param detailMessage
      *            the detail message for this error.
-     * @since Android 1.0
      */
     public ClassFormatError(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/ClassNotFoundException.java b/libcore/luni/src/main/java/java/lang/ClassNotFoundException.java
index 26bdbf7..2ac3b49 100644
--- a/libcore/luni/src/main/java/java/lang/ClassNotFoundException.java
+++ b/libcore/luni/src/main/java/java/lang/ClassNotFoundException.java
@@ -19,8 +19,6 @@
 
 /**
  * Thrown when a class loader is unable to find a class.
- * 
- * @since Android 1.0
  */
 public class ClassNotFoundException extends Exception {
 
@@ -31,8 +29,6 @@
     /**
      * Constructs a new {@code ClassNotFoundException} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public ClassNotFoundException() {
         super((Throwable) null);
@@ -41,10 +37,9 @@
     /**
      * Constructs a new {@code ClassNotFoundException} with the current stack
      * trace and the specified detail message.
-     * 
+     *
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public ClassNotFoundException(String detailMessage) {
         super(detailMessage, null);
@@ -54,12 +49,11 @@
      * Constructs a new {@code ClassNotFoundException} with the current stack
      * trace, the specified detail message and the exception that occurred when
      * loading the class.
-     * 
+     *
      * @param detailMessage
      *            the detail message for this exception.
      * @param exception
      *            the exception which occurred while loading the class.
-     * @since Android 1.0
      */
     public ClassNotFoundException(String detailMessage, Throwable exception) {
         super(detailMessage);
@@ -68,7 +62,7 @@
 
     /**
      * Returns the exception which occurred when loading the class.
-     * 
+     *
      * @return Throwable the exception which occurred while loading the class.
      */
     public Throwable getException() {
@@ -78,7 +72,7 @@
     /**
      * Returns the cause of this Throwable, or {@code null} if there is no
      * cause.
-     * 
+     *
      * @return Throwable the receiver's cause.
      */
     @Override
diff --git a/libcore/luni/src/main/java/java/lang/CloneNotSupportedException.java b/libcore/luni/src/main/java/java/lang/CloneNotSupportedException.java
index b484e08..2f4f11c 100644
--- a/libcore/luni/src/main/java/java/lang/CloneNotSupportedException.java
+++ b/libcore/luni/src/main/java/java/lang/CloneNotSupportedException.java
@@ -20,9 +20,8 @@
 /**
  * Thrown when a program attempts to clone an object which does not support the
  * {@link Cloneable} interface.
- * 
+ *
  * @see Cloneable
- * @since Android 1.0
  */
 public class CloneNotSupportedException extends Exception {
 
@@ -31,8 +30,6 @@
     /**
      * Constructs a new {@code CloneNotSupportedException} that includes the
      * current stack trace.
-     * 
-     * @since Android 1.0
      */
     public CloneNotSupportedException() {
         super();
@@ -41,10 +38,9 @@
     /**
      * Constructs a new {@code CloneNotSupportedException} with the current
      * stack trace and the specified detail message.
-     * 
+     *
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public CloneNotSupportedException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/Comparable.java b/libcore/luni/src/main/java/java/lang/Comparable.java
index c50f112..df10416 100644
--- a/libcore/luni/src/main/java/java/lang/Comparable.java
+++ b/libcore/luni/src/main/java/java/lang/Comparable.java
@@ -28,21 +28,17 @@
  * invertible (the sign of the result of x.compareTo(y) must be equal to the
  * negation of the sign of the result of y.compareTo(x) for all combinations of
  * x and y).
- * </p>
  * <p>
  * In addition, it is recommended (but not required) that if and only if the
  * result of x.compareTo(y) is zero, then the result of x.equals(y) should be
  * {@code true}.
- * </p>
- * 
- * @since Android 1.0
  */
 public interface Comparable<T> {
-    
+
     /**
      * Compares this object to the specified object to determine their relative
      * order.
-     * 
+     *
      * @param another
      *            the object to compare to this instance.
      * @return a negative integer if this instance is less than {@code another};
@@ -52,7 +48,6 @@
      * @throws ClassCastException
      *             if {@code another} cannot be converted into something
      *             comparable to {@code this} instance.
-     * @since Android 1.0
      */
     int compareTo(T another);
 }
diff --git a/libcore/luni/src/main/java/java/lang/Deprecated.java b/libcore/luni/src/main/java/java/lang/Deprecated.java
index eb356c2..047a6be 100644
--- a/libcore/luni/src/main/java/java/lang/Deprecated.java
+++ b/libcore/luni/src/main/java/java/lang/Deprecated.java
@@ -1,11 +1,11 @@
-/*
- * 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,
@@ -18,17 +18,16 @@
 
 import java.lang.annotation.Documented;
 import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 
 /**
  * Annotation type used to mark program elements that should no longer be used
  * by programmers. Compilers produce a warning if a deprecated program element
  * is used.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 @Documented
-@Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME)
-public @interface Deprecated
-{
-
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Deprecated {
 }
diff --git a/libcore/luni/src/main/java/java/lang/Double.java b/libcore/luni/src/main/java/java/lang/Double.java
index c50b27d..bc0c380 100644
--- a/libcore/luni/src/main/java/java/lang/Double.java
+++ b/libcore/luni/src/main/java/java/lang/Double.java
@@ -19,9 +19,9 @@
 
 /**
  * The wrapper for the primitive type {@code double}.
- * 
+ *
  * @see java.lang.Number
- * @since Android 1.0
+ * @since 1.0
  */
 public final class Double extends Number implements Comparable<Double> {
 
@@ -35,15 +35,11 @@
     /**
      * Constant for the maximum {@code double} value, (2 - 2<sup>-52</sup>) *
      * 2<sup>1023</sup>.
-     * 
-     * @since Android 1.0
      */
     public static final double MAX_VALUE = 1.79769313486231570e+308;
 
     /**
      * Constant for the minimum {@code double} value, 2<sup>-1074</sup>.
-     * 
-     * @since Android 1.0
      */
     public static final double MIN_VALUE = 5e-324;
 
@@ -51,30 +47,24 @@
 
     /**
      * Constant for the Not-a-Number (NaN) value of the {@code double} type.
-     * 
-     * @since Android 1.0
      */
     public static final double NaN = 0.0 / 0.0;
 
     /**
      * Constant for the Positive Infinity value of the {@code double} type.
-     * 
-     * @since Android 1.0
      */
     public static final double POSITIVE_INFINITY = 1.0 / 0.0;
 
     /**
      * Constant for the Negative Infinity value of the {@code double} type.
-     * 
-     * @since Android 1.0
      */
     public static final double NEGATIVE_INFINITY = -1.0 / 0.0;
 
     /**
      * The {@link Class} object that represents the primitive type {@code
      * double}.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.1
      */
     @SuppressWarnings("unchecked")
     public static final Class<Double> TYPE = (Class<Double>) new double[0]
@@ -86,18 +76,17 @@
     /**
      * Constant for the number of bits needed to represent a {@code double} in
      * two's complement form.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final int SIZE = 64;
 
     /**
      * Constructs a new {@code Double} with the specified primitive double
      * value.
-     * 
+     *
      * @param value
      *            the primitive double value to store in the new instance.
-     * @since Android 1.0
      */
     public Double(double value) {
         this.value = value;
@@ -105,13 +94,12 @@
 
     /**
      * Constructs a new {@code Double} from the specified string.
-     * 
+     *
      * @param string
      *            the string representation of a double value.
      * @throws NumberFormatException
      *             if {@code string} can not be decoded into a double value.
      * @see #parseDouble(String)
-     * @since Android 1.0
      */
     public Double(String string) throws NumberFormatException {
         this(parseDouble(string));
@@ -125,36 +113,20 @@
      * than any other double value, including {@code Double.POSITIVE_INFINITY};</li>
      * <li>+0.0d is greater than -0.0d</li>
      * </ul>
-     * 
+     *
      * @param object
      *            the double object to compare this object to.
      * @return a negative value if the value of this double is less than the
      *         value of {@code object}; 0 if the value of this double and the
      *         value of {@code object} are equal; a positive value if the value
      *         of this double is greater than the value of {@code object}.
+     * @throws NullPointerException
+     *             if {@code object} is {@code null}.
      * @see java.lang.Comparable
-     * @since Android 1.0
+     * @since 1.2
      */
     public int compareTo(Double object) {
-        long d1, d2;
-        long NaNbits = Double.doubleToLongBits(Double.NaN);
-        if ((d1 = Double.doubleToLongBits(value)) == NaNbits) {
-            if (Double.doubleToLongBits(object.value) == NaNbits) {
-                return 0;
-            }
-            return 1;
-        }
-        if ((d2 = Double.doubleToLongBits(object.value)) == NaNbits) {
-            return -1;
-        }
-        if (value == object.value) {
-            if (d1 == d2) {
-                return 0;
-            }
-            // check for -0
-            return d1 > d2 ? 1 : -1;
-        }
-        return value > object.value ? 1 : -1;
+        return compare(value, object.value);
     }
 
     @Override
@@ -167,14 +139,13 @@
      * to the IEEE 754 floating-point double precision bit layout. All
      * <em>Not-a-Number (NaN)</em> values are converted to a single NaN
      * representation ({@code 0x7ff8000000000000L}).
-     * 
+     *
      * @param value
      *            the double value to convert.
      * @return the IEEE 754 floating-point double precision representation of
      *         {@code value}.
      * @see #doubleToRawLongBits(double)
      * @see #longBitsToDouble(long)
-     * @since Android 1.0
      */
     public static native long doubleToLongBits(double value);
 
@@ -182,22 +153,20 @@
      * Converts the specified double value to a binary representation conforming
      * to the IEEE 754 floating-point double precision bit layout.
      * <em>Not-a-Number (NaN)</em> values are preserved.
-     * 
+     *
      * @param value
      *            the double value to convert.
      * @return the IEEE 754 floating-point double precision representation of
      *         {@code value}.
      * @see #doubleToLongBits(double)
      * @see #longBitsToDouble(long)
-     * @since Android 1.0
      */
     public static native long doubleToRawLongBits(double value);
 
     /**
      * Gets the primitive value of this double.
-     * 
+     *
      * @return this object's primitive value.
-     * @since Android 1.0
      */
     @Override
     public double doubleValue() {
@@ -209,12 +178,11 @@
      * equal. In order to be equal, {@code object} must be an instance of
      * {@code Double} and the bit pattern of its double value is the same as
      * this object's.
-     * 
+     *
      * @param object
      *            the object to compare this double with.
      * @return {@code true} if the specified object is equal to this
      *         {@code Double}; {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -241,10 +209,9 @@
 
     /**
      * Indicates whether this object represents an infinite value.
-     * 
+     *
      * @return {@code true} if the value of this double is positive or negative
      *         infinity; {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isInfinite() {
         return isInfinite(value);
@@ -252,12 +219,11 @@
 
     /**
      * Indicates whether the specified double represents an infinite value.
-     * 
+     *
      * @param d
      *            the double to check.
      * @return {@code true} if the value of {@code d} is positive or negative
      *         infinity; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isInfinite(double d) {
         return (d == POSITIVE_INFINITY) || (d == NEGATIVE_INFINITY);
@@ -265,10 +231,9 @@
 
     /**
      * Indicates whether this object is a <em>Not-a-Number (NaN)</em> value.
-     * 
+     *
      * @return {@code true} if this double is <em>Not-a-Number</em>;
      *         {@code false} if it is a (potentially infinite) double number.
-     * @since Android 1.0
      */
     public boolean isNaN() {
         return isNaN(value);
@@ -277,12 +242,11 @@
     /**
      * Indicates whether the specified double is a <em>Not-a-Number (NaN)</em>
      * value.
-     * 
+     *
      * @param d
      *            the double value to check.
      * @return {@code true} if {@code d} is <em>Not-a-Number</em>;
      *         {@code false} if it is a (potentially infinite) double number.
-     * @since Android 1.0
      */
     public static boolean isNaN(double d) {
         return d != d;
@@ -291,14 +255,13 @@
     /**
      * Converts the specified IEEE 754 floating-point double precision bit
      * pattern to a Java double value.
-     * 
+     *
      * @param bits
      *            the IEEE 754 floating-point double precision representation of
      *            a double value.
      * @return the double value converted from {@code bits}.
      * @see #doubleToLongBits(double)
      * @see #doubleToRawLongBits(double)
-     * @since Android 1.0
      */
     public static native double longBitsToDouble(long bits);
 
@@ -309,14 +272,13 @@
 
     /**
      * Parses the specified string as a double value.
-     * 
+     *
      * @param string
      *            the string representation of a double value.
      * @return the primitive double value represented by {@code string}.
      * @throws NumberFormatException
      *             if {@code string} is {@code null}, has a length of zero or
      *             can not be parsed as a double value.
-     * @since Android 1.0
      */
     public static double parseDouble(String string)
             throws NumberFormatException {
@@ -337,11 +299,10 @@
     /**
      * Returns a string containing a concise, human-readable description of the
      * specified double value.
-     * 
+     *
      * @param d
      *             the double to convert to a string.
      * @return a printable representation of {@code d}.
-     * @since Android 1.0
      */
     public static String toString(double d) {
         return org.apache.harmony.luni.util.NumberConverter.convert(d);
@@ -349,7 +310,7 @@
 
     /**
      * Parses the specified string as a double value.
-     * 
+     *
      * @param string
      *            the string representation of a double value.
      * @return a {@code Double} instance containing the double value represented
@@ -358,7 +319,6 @@
      *             if {@code string} is {@code null}, has a length of zero or
      *             can not be parsed as a double value.
      * @see #parseDouble(String)
-     * @since Android 1.0
      */
     public static Double valueOf(String string) throws NumberFormatException {
         return new Double(parseDouble(string));
@@ -371,7 +331,7 @@
      * than any other double value, including {@code Double.POSITIVE_INFINITY};</li>
      * <li>+0.0d is greater than -0.0d</li>
      * </ul>
-     * 
+     *
      * @param double1
      *            the first value to compare.
      * @param double2
@@ -379,37 +339,44 @@
      * @return a negative value if {@code double1} is less than {@code double2};
      *         0 if {@code double1} and {@code double2} are equal; a positive
      *         value if {@code double1} is greater than {@code double2}.
-     * @since Android 1.0         
      */
     public static int compare(double double1, double double2) {
-        long d1, d2;
-        long NaNbits = Double.doubleToLongBits(Double.NaN);
-        if ((d1 = Double.doubleToLongBits(double1)) == NaNbits) {
-            if (Double.doubleToLongBits(double2) == NaNbits) {
+        // Non-zero, non-NaN checking.
+        if (double1 > double2) {
+            return 1;
+        }
+        if (double2 > double1) {
+            return -1;
+        }
+        if (double1 == double2 && 0.0d != double1) {
+            return 0;
+        }
+
+        // NaNs are equal to other NaNs and larger than any other double
+        if (isNaN(double1)) {
+            if (isNaN(double2)) {
                 return 0;
             }
             return 1;
-        }
-        if ((d2 = Double.doubleToLongBits(double2)) == NaNbits) {
+        } else if (isNaN(double2)) {
             return -1;
         }
-        if (double1 == double2) {
-            if (d1 == d2) {
-                return 0;
-            }
-            // check for -0
-            return d1 > d2 ? 1 : -1;
-        }
-        return double1 > double2 ? 1 : -1;
+
+        // Deal with +0.0 and -0.0
+        long d1 = doubleToRawLongBits(double1);
+        long d2 = doubleToRawLongBits(double2);
+        // The below expression is equivalent to:
+        // (d1 == d2) ? 0 : (d1 < d2) ? -1 : 1
+        return (int) ((d1 >> 63) - (d2 >> 63));
     }
 
     /**
      * Returns a {@code Double} instance for the specified double value.
-     * 
+     *
      * @param d
      *            the double value to store in the instance.
      * @return a {@code Double} instance containing {@code d}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static Double valueOf(double d) {
         return new Double(d);
@@ -417,11 +384,11 @@
 
     /**
      * Converts the specified double into its hexadecimal string representation.
-     * 
+     *
      * @param d
      *            the double to convert.
      * @return the hexadecimal string representation of {@code d}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String toHexString(double d) {
         /*
diff --git a/libcore/luni/src/main/java/java/lang/Enum.java b/libcore/luni/src/main/java/java/lang/Enum.java
index 0aa15dd..395c825 100644
--- a/libcore/luni/src/main/java/java/lang/Enum.java
+++ b/libcore/luni/src/main/java/java/lang/Enum.java
@@ -27,8 +27,6 @@
  * The superclass of all enumerated types. Actual enumeration types inherit from
  * this class, but extending this class does not make a class an enumration
  * type, since the compiler needs to generate special information for it.
- * 
- * @since Android 1.0
  */
 public abstract class Enum<E extends Enum<E>> implements Serializable,
         Comparable<E> {
@@ -41,13 +39,12 @@
 
     /**
      * Constructor for constants of enum subtypes.
-     * 
+     *
      * @param name
      *            the enum constant's declared name.
      * @param ordinal
      *            the enum constant's ordinal, which corresponds to its position
      *            in the enum declaration, starting at zero.
-     * @since Android 1.0
      */
     protected Enum(String name, int ordinal) {
         this.name = name;
@@ -57,10 +54,9 @@
     /**
      * Returns the name of this enum constant. The name is the field as it
      * appears in the {@code enum} declaration.
-     * 
+     *
      * @return the name of this enum constant.
      * @see #toString()
-     * @since Android 1.0
      */
     public final String name() {
         return name;
@@ -69,9 +65,8 @@
     /**
      * Returns the position of the enum constant in the declaration. The first
      * constant has an ordinal value of zero.
-     * 
+     *
      * @return the ordinal value of this enum constant.
-     * @since Android 1.0
      */
     public final int ordinal() {
         return ordinal;
@@ -80,9 +75,8 @@
     /**
      * Returns a string containing a concise, human-readable description of this
      * object. In this case, the enum constant's name is returned.
-     * 
+     *
      * @return a printable representation of this object.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -93,12 +87,11 @@
      * Compares this object with the specified object and indicates if they are
      * equal. In order to be equal, {@code object} must be identical to this
      * enum constant.
-     * 
+     *
      * @param other
      *            the object to compare this enum constant with.
      * @return {@code true} if the specified object is equal to this
      *         {@code Enum}; {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public final boolean equals(Object other) {
@@ -113,11 +106,10 @@
     /**
      * {@code Enum} objects are singletons, they may not be cloned. This method
      * always throws a {@code CloneNotSupportedException}.
-     * 
+     *
      * @return does not return.
      * @throws CloneNotSupportedException
      *             is always thrown.
-     * @since Android 1.0
      */
     @Override
     protected final Object clone() throws CloneNotSupportedException {
@@ -129,7 +121,7 @@
      * Compares this object to the specified enum object to determine their
      * relative order. This method compares the object's ordinal values, that
      * is, their position in the enum declaration.
-     * 
+     *
      * @param o
      *            the enum object to compare this object to.
      * @return a negative value if the ordinal value of this enum constant is
@@ -138,7 +130,6 @@
      *         value if the ordinal value of this enum constant is greater than
      *         the ordinal value of {@code o}.
      * @see java.lang.Comparable
-     * @since Android 1.0
      */
     public final int compareTo(E o) {
         return ordinal - o.ordinal;
@@ -146,9 +137,8 @@
 
     /**
      * Returns the enum constant's declaring class.
-     * 
+     *
      * @return the class object representing the constant's enum type.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public final Class<E> getDeclaringClass() {
@@ -162,7 +152,7 @@
 
     /**
      * Returns the constant with the specified name of the specified enum type.
-     * 
+     *
      * @param enumType
      *            the class of the enumerated type to search for the constant
      *            value.
@@ -174,7 +164,6 @@
      * @throws IllegalArgumentException
      *             if {@code enumType} is not an enumerated type or does not
      *             have a constant value called {@code name}.
-     * @since Android 1.0
      */
     public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) {
         if ((enumType == null) || (name == null)) {
diff --git a/libcore/luni/src/main/java/java/lang/EnumConstantNotPresentException.java b/libcore/luni/src/main/java/java/lang/EnumConstantNotPresentException.java
index 0416703..aec32d0 100644
--- a/libcore/luni/src/main/java/java/lang/EnumConstantNotPresentException.java
+++ b/libcore/luni/src/main/java/java/lang/EnumConstantNotPresentException.java
@@ -20,8 +20,8 @@
 
 /**
  * Thrown if an {@code enum} constant does not exist for a particular name.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public class EnumConstantNotPresentException extends RuntimeException {
 
@@ -36,12 +36,11 @@
      * Constructs a new {@code EnumConstantNotPresentException} with the current
      * stack trace and a detail message based on the specified enum type and
      * missing constant name.
-     * 
+     *
      * @param enumType
      *            the enum type.
      * @param constantName
      *            the missing constant name.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public EnumConstantNotPresentException(Class<? extends Enum> enumType,
@@ -54,9 +53,8 @@
 
     /**
      * Gets the enum type for which the constant name is missing.
-     * 
+     *
      * @return the enum type for which a constant name has not been found.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public Class<? extends Enum> enumType() {
@@ -68,7 +66,6 @@
      * 
      * @return the name of the constant that has not been found in the enum
      *         type.
-     * @since Android 1.0
      */
     public String constantName() {
         return constantName;
diff --git a/libcore/luni/src/main/java/java/lang/Error.java b/libcore/luni/src/main/java/java/lang/Error.java
index 3bce72c..dd284ae 100644
--- a/libcore/luni/src/main/java/java/lang/Error.java
+++ b/libcore/luni/src/main/java/java/lang/Error.java
@@ -26,7 +26,6 @@
  * @see Throwable
  * @see Exception
  * @see RuntimeException
- * @since Android 1.0
  */
 public class Error extends Throwable {
 
@@ -34,8 +33,6 @@
 
     /**
      * Constructs a new {@code Error} that includes the current stack trace.
-     * 
-     * @since Android 1.0
      */
     public Error() {
         super();
@@ -47,7 +44,6 @@
      * 
      * @param detailMessage
      *            the detail message for this error.
-     * @since Android 1.0
      */
     public Error(String detailMessage) {
         super(detailMessage);
@@ -61,7 +57,6 @@
      *            the detail message for this error.
      * @param throwable
      *            the cause of this error.
-     * @since Android 1.0
      */
     public Error(String detailMessage, Throwable throwable) {
         super(detailMessage, throwable);
@@ -73,7 +68,6 @@
      * 
      * @param throwable
      *            the cause of this error.
-     * @since Android 1.0
      */
     public Error(Throwable throwable) {
         super(throwable);
diff --git a/libcore/luni/src/main/java/java/lang/Exception.java b/libcore/luni/src/main/java/java/lang/Exception.java
index 010cea4..7921edd 100644
--- a/libcore/luni/src/main/java/java/lang/Exception.java
+++ b/libcore/luni/src/main/java/java/lang/Exception.java
@@ -26,15 +26,12 @@
  * @see Throwable
  * @see Error
  * @see RuntimeException
- * @since Android 1.0
  */
 public class Exception extends Throwable {
     private static final long serialVersionUID = -3387516993124229948L;
 
     /**
      * Constructs a new {@code Exception} that includes the current stack trace.
-     * 
-     * @since Android 1.0
      */
     public Exception() {
         super();
@@ -46,7 +43,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public Exception(String detailMessage) {
         super(detailMessage);
@@ -60,7 +56,6 @@
      *            the detail message for this exception.
      * @param throwable
      *            the cause of this exception.
-     * @since Android 1.0
      */
     public Exception(String detailMessage, Throwable throwable) {
         super(detailMessage, throwable);
@@ -72,7 +67,6 @@
      * 
      * @param throwable
      *            the cause of this exception.
-     * @since Android 1.0
      */
     public Exception(Throwable throwable) {
         super(throwable);
diff --git a/libcore/luni/src/main/java/java/lang/ExceptionInInitializerError.java b/libcore/luni/src/main/java/java/lang/ExceptionInInitializerError.java
index 6096f08..3767488 100644
--- a/libcore/luni/src/main/java/java/lang/ExceptionInInitializerError.java
+++ b/libcore/luni/src/main/java/java/lang/ExceptionInInitializerError.java
@@ -19,8 +19,6 @@
 
 /**
  * Thrown when an exception occurs during class initialization.
- * 
- * @since Android 1.0
  */
 public class ExceptionInInitializerError extends LinkageError {
 
@@ -31,8 +29,6 @@
     /**
      * Constructs a new {@code ExceptionInInitializerError} that includes the
      * current stack trace.
-     * 
-     * @since Android 1.0
      */
     public ExceptionInInitializerError() {
         super();
@@ -45,7 +41,6 @@
      * 
      * @param detailMessage
      *            the detail message for this error.
-     * @since Android 1.0
      */
     public ExceptionInInitializerError(String detailMessage) {
         super(detailMessage);
@@ -70,7 +65,6 @@
      * Returns the exception that is the cause of this error.
      * 
      * @return the exception that caused this error.
-     * @since Android 1.0
      */
     public Throwable getException() {
         return exception;
@@ -80,7 +74,6 @@
      * Returns the cause of this error, or {@code null} if there is no cause.
      * 
      * @return the exception that caused this error.
-     * @since Android 1.0
      */
     @Override
     public Throwable getCause() {
diff --git a/libcore/luni/src/main/java/java/lang/Float.java b/libcore/luni/src/main/java/java/lang/Float.java
index 69f91c5..067149d 100644
--- a/libcore/luni/src/main/java/java/lang/Float.java
+++ b/libcore/luni/src/main/java/java/lang/Float.java
@@ -19,9 +19,9 @@
 
 /**
  * The wrapper for the primitive type {@code float}.
- * 
+ *
  * @see java.lang.Number
- * @since Android 1.0
+ * @since 1.0
  */
 public final class Float extends Number implements Comparable<Float> {
 
@@ -34,44 +34,34 @@
 
     /**
      * Constant for the maximum {@code float} value, (2 - 2<sup>-23</sup>) * 2<sup>127</sup>.
-     * 
-     * @since Android 1.0
      */
     public static final float MAX_VALUE = 3.40282346638528860e+38f;
 
     /**
      * Constant for the minimum {@code float} value, 2<sup>-149</sup>.
-     * 
-     * @since Android 1.0
      */
     public static final float MIN_VALUE = 1.40129846432481707e-45f;
 
     /**
      * Constant for the Not-a-Number (NaN) value of the {@code float} type.
-     * 
-     * @since Android 1.0
      */
     public static final float NaN = 0.0f / 0.0f;
 
     /**
      * Constant for the Positive Infinity value of the {@code float} type.
-     * 
-     * @since Android 1.0
      */
     public static final float POSITIVE_INFINITY = 1.0f / 0.0f;
 
     /**
      * Constant for the Negative Infinity value of the {@code float} type.
-     * 
-     * @since Android 1.0
      */
     public static final float NEGATIVE_INFINITY = -1.0f / 0.0f;
 
     /**
-     * The {@link Class} object that represents the primitive type {@code 
+     * The {@link Class} object that represents the primitive type {@code
      * float}.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.1
      */
     @SuppressWarnings("unchecked")
     public static final Class<Float> TYPE = (Class<Float>) new float[0]
@@ -83,17 +73,16 @@
     /**
      * Constant for the number of bits needed to represent a {@code float} in
      * two's complement form.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final int SIZE = 32;
 
     /**
      * Constructs a new {@code Float} with the specified primitive float value.
-     * 
+     *
      * @param value
      *            the primitive float value to store in the new instance.
-     * @since Android 1.0
      */
     public Float(float value) {
         this.value = value;
@@ -101,10 +90,9 @@
 
     /**
      * Constructs a new {@code Float} with the specified primitive double value.
-     * 
+     *
      * @param value
      *            the primitive double value to store in the new instance.
-     * @since Android 1.0
      */
     public Float(double value) {
         this.value = (float) value;
@@ -112,13 +100,12 @@
 
     /**
      * Constructs a new {@code Float} from the specified string.
-     * 
+     *
      * @param string
      *            the string representation of a float value.
      * @throws NumberFormatException
      *             if {@code string} can not be decoded into a float value.
      * @see #parseFloat(String)
-     * @since Android 1.0
      */
     public Float(String string) throws NumberFormatException {
         this(parseFloat(string));
@@ -132,7 +119,7 @@
      * than any other float value, including {@code Float.POSITIVE_INFINITY};</li>
      * <li>+0.0f is greater than -0.0f</li>
      * </ul>
-     * 
+     *
      * @param object
      *            the float object to compare this object to.
      * @return a negative value if the value of this float is less than the
@@ -140,28 +127,10 @@
      *         value of {@code object} are equal; a positive value if the value
      *         of this float is greater than the value of {@code object}.
      * @see java.lang.Comparable
-     * @since Android 1.0
+     * @since 1.2
      */
     public int compareTo(Float object) {
-        int f1, f2;
-        int NaNbits = Float.floatToIntBits(Float.NaN);
-        if ((f1 = Float.floatToIntBits(value)) == NaNbits) {
-            if (Float.floatToIntBits(object.value) == NaNbits) {
-                return 0;
-            }
-            return 1;
-        }
-        if ((f2 = Float.floatToIntBits(object.value)) == NaNbits) {
-            return -1;
-        }
-        if (value == object.value) {
-            if (f1 == f2) {
-                return 0;
-            }
-            // check for -0
-            return f1 > f2 ? 1 : -1;
-        }
-        return value > object.value ? 1 : -1;
+        return compare(value, object.value);
     }
 
     @Override
@@ -178,12 +147,11 @@
      * Compares this instance with the specified object and indicates if they
      * are equal. In order to be equal, {@code object} must be an instance of
      * {@code Float} and have the same float value as this object.
-     * 
+     *
      * @param object
      *            the object to compare this float with.
      * @return {@code true} if the specified object is equal to this
      *         {@code Float}; {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -197,14 +165,13 @@
      * to the IEEE 754 floating-point single precision bit layout. All
      * <em>Not-a-Number (NaN)</em> values are converted to a single NaN
      * representation ({@code 0x7ff8000000000000L}).
-     * 
+     *
      * @param value
      *            the float value to convert.
      * @return the IEEE 754 floating-point single precision representation of
      *         {@code value}.
      * @see #floatToRawIntBits(float)
      * @see #intBitsToFloat(int)
-     * @since Android 1.0
      */
     public static native int floatToIntBits(float value);
 
@@ -212,22 +179,20 @@
      * Converts the specified float value to a binary representation conforming
      * to the IEEE 754 floating-point single precision bit layout.
      * <em>Not-a-Number (NaN)</em> values are preserved.
-     * 
+     *
      * @param value
      *            the float value to convert.
      * @return the IEEE 754 floating-point single precision representation of
      *         {@code value}.
      * @see #floatToIntBits(float)
      * @see #intBitsToFloat(int)
-     * @since Android 1.0
      */
     public static native int floatToRawIntBits(float value);
 
     /**
      * Gets the primitive value of this float.
-     * 
+     *
      * @return this object's primitive value.
-     * @since Android 1.0
      */
     @Override
     public float floatValue() {
@@ -242,14 +207,13 @@
     /**
      * Converts the specified IEEE 754 floating-point single precision bit
      * pattern to a Java float value.
-     * 
+     *
      * @param bits
      *            the IEEE 754 floating-point single precision representation of
      *            a float value.
      * @return the float value converted from {@code bits}.
      * @see #floatToIntBits(float)
      * @see #floatToRawIntBits(float)
-     * @since Android 1.0
      */
     public static native float intBitsToFloat(int bits);
 
@@ -260,10 +224,9 @@
 
     /**
      * Indicates whether this object represents an infinite value.
-     * 
+     *
      * @return {@code true} if the value of this float is positive or negative
      *         infinity; {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isInfinite() {
         return isInfinite(value);
@@ -271,12 +234,11 @@
 
     /**
      * Indicates whether the specified float represents an infinite value.
-     * 
+     *
      * @param f
      *            the float to check.
      * @return {@code true} if the value of {@code f} is positive or negative
      *         infinity; {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean isInfinite(float f) {
         return (f == POSITIVE_INFINITY) || (f == NEGATIVE_INFINITY);
@@ -284,10 +246,9 @@
 
     /**
      * Indicates whether this object is a <em>Not-a-Number (NaN)</em> value.
-     * 
+     *
      * @return {@code true} if this float is <em>Not-a-Number</em>;
      *         {@code false} if it is a (potentially infinite) float number.
-     * @since Android 1.0
      */
     public boolean isNaN() {
         return isNaN(value);
@@ -296,12 +257,11 @@
     /**
      * Indicates whether the specified float is a <em>Not-a-Number (NaN)</em>
      * value.
-     * 
+     *
      * @param f
      *            the float value to check.
      * @return {@code true} if {@code f} is <em>Not-a-Number</em>;
      *         {@code false} if it is a (potentially infinite) float number.
-     * @since Android 1.0
      */
     public static boolean isNaN(float f) {
         return f != f;
@@ -314,14 +274,15 @@
 
     /**
      * Parses the specified string as a float value.
-     * 
+     *
      * @param string
      *            the string representation of a float value.
      * @return the primitive float value represented by {@code string}.
      * @throws NumberFormatException
      *             if {@code string} is {@code null}, has a length of zero or
      *             can not be parsed as a float value.
-     * @since Android 1.0
+     * @see #valueOf(String)
+     * @since 1.2
      */
     public static float parseFloat(String string) throws NumberFormatException {
         return org.apache.harmony.luni.util.FloatingPointParser
@@ -341,11 +302,10 @@
     /**
      * Returns a string containing a concise, human-readable description of the
      * specified float value.
-     * 
+     *
      * @param f
      *             the float to convert to a string.
      * @return a printable representation of {@code f}.
-     * @since Android 1.0
      */
     public static String toString(float f) {
         return org.apache.harmony.luni.util.NumberConverter.convert(f);
@@ -353,7 +313,7 @@
 
     /**
      * Parses the specified string as a float value.
-     * 
+     *
      * @param string
      *            the string representation of a float value.
      * @return a {@code Float} instance containing the float value represented
@@ -362,7 +322,6 @@
      *             if {@code string} is {@code null}, has a length of zero or
      *             can not be parsed as a float value.
      * @see #parseFloat(String)
-     * @since Android 1.0
      */
     public static Float valueOf(String string) throws NumberFormatException {
         return valueOf(parseFloat(string));
@@ -375,7 +334,7 @@
      * than any other float value, including {@code Float.POSITIVE_INFINITY};</li>
      * <li>+0.0f is greater than -0.0f</li>
      * </ul>
-     * 
+     *
      * @param float1
      *            the first value to compare.
      * @param float2
@@ -383,37 +342,46 @@
      * @return a negative value if {@code float1} is less than {@code float2};
      *         0 if {@code float1} and {@code float2} are equal; a positive
      *         value if {@code float1} is greater than {@code float2}.
-     * @since Android 1.0
+     * @since 1.4
      */
     public static int compare(float float1, float float2) {
-        int f1, f2;
-        int NaNbits = Float.floatToIntBits(Float.NaN);
-        if ((f1 = Float.floatToIntBits(float1)) == NaNbits) {
-            if (Float.floatToIntBits(float2) == NaNbits) {
+        // Non-zero, non-NaN checking.
+        if (float1 > float2) {
+            return 1;
+        }
+        if (float2 > float1) {
+            return -1;
+        }
+        if (float1 == float2 && 0.0f != float1) {
+            return 0;
+        }
+
+        // NaNs are equal to other NaNs and larger than any other float
+        if (isNaN(float1)) {
+            if (isNaN(float2)) {
                 return 0;
             }
             return 1;
-        }
-        if ((f2 = Float.floatToIntBits(float2)) == NaNbits) {
+        } else if (isNaN(float2)) {
             return -1;
         }
-        if (float1 == float2) {
-            if (f1 == f2) {
-                return 0;
-            }
-            // check for -0
-            return f1 > f2 ? 1 : -1;
-        }
-        return float1 > float2 ? 1 : -1;
+
+        // Deal with +0.0 and -0.0
+        int f1 = floatToRawIntBits(float1);
+        int f2 = floatToRawIntBits(float2);
+        // The below expression is equivalent to:
+        // (f1 == f2) ? 0 : (f1 < f2) ? -1 : 1
+        // because f1 and f2 are either 0 or Integer.MIN_VALUE
+        return (f1 >> 31) - (f2 >> 31);
     }
 
     /**
      * Returns a {@code Float} instance for the specified float value.
-     * 
+     *
      * @param f
      *            the float value to store in the instance.
      * @return a {@code Float} instance containing {@code f}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static Float valueOf(float f) {
         return new Float(f);
@@ -421,11 +389,11 @@
 
     /**
      * Converts the specified float into its hexadecimal string representation.
-     * 
+     *
      * @param f
      *            the float to convert.
      * @return the hexadecimal string representation of {@code f}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String toHexString(float f) {
         /*
diff --git a/libcore/luni/src/main/java/java/lang/IllegalAccessError.java b/libcore/luni/src/main/java/java/lang/IllegalAccessError.java
index 7f87afd..7fcef85 100644
--- a/libcore/luni/src/main/java/java/lang/IllegalAccessError.java
+++ b/libcore/luni/src/main/java/java/lang/IllegalAccessError.java
@@ -22,9 +22,6 @@
  * which is not accessible from where it is referenced.
  * <p>
  * Note that this can only occur when inconsistent class files have been loaded.
- * </p>
- * 
- * @since Android 1.0
  */
 public class IllegalAccessError extends IncompatibleClassChangeError {
 
@@ -33,8 +30,6 @@
     /**
      * Constructs a new {@code IllegalAccessError} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public IllegalAccessError() {
         super();
@@ -46,7 +41,6 @@
      * 
      * @param detailMessage
      *            the detail message for this error.
-     * @since Android 1.0
      */
     public IllegalAccessError(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/IllegalAccessException.java b/libcore/luni/src/main/java/java/lang/IllegalAccessException.java
index b9d2d69..d96fd56 100644
--- a/libcore/luni/src/main/java/java/lang/IllegalAccessException.java
+++ b/libcore/luni/src/main/java/java/lang/IllegalAccessException.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when a program attempts to access a field or method which is not
  * accessible from the location where the reference is made.
- * 
- * @since Android 1.0
  */
 public class IllegalAccessException extends Exception {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code IllegalAccessException} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public IllegalAccessException() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public IllegalAccessException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/IllegalArgumentException.java b/libcore/luni/src/main/java/java/lang/IllegalArgumentException.java
index 6f8dcf6..eb2ad91 100644
--- a/libcore/luni/src/main/java/java/lang/IllegalArgumentException.java
+++ b/libcore/luni/src/main/java/java/lang/IllegalArgumentException.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when a method is invoked with an argument which it can not reasonably
  * deal with.
- * 
- * @since Android 1.0
  */
 public class IllegalArgumentException extends RuntimeException {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code IllegalArgumentException} that includes the
      * current stack trace.
-     * 
-     * @since Android 1.0
      */
     public IllegalArgumentException() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public IllegalArgumentException(String detailMessage) {
         super(detailMessage);
@@ -57,7 +52,7 @@
      *            the detail message for this exception.
      * @param cause
      *            the cause of this exception, may be {@code null}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public IllegalArgumentException(String message, Throwable cause) {
         super(message, cause);
@@ -69,8 +64,8 @@
      * 
      * @param cause
      *            the cause of this exception, may be {@code null}.
-     * @since Android 1.0
-     */    
+     * @since 1.5
+     */
     public IllegalArgumentException(Throwable cause) {
         super((cause == null ? null : cause.toString()), cause);
     }
diff --git a/libcore/luni/src/main/java/java/lang/IllegalMonitorStateException.java b/libcore/luni/src/main/java/java/lang/IllegalMonitorStateException.java
index e570bfd..a0b8a75 100644
--- a/libcore/luni/src/main/java/java/lang/IllegalMonitorStateException.java
+++ b/libcore/luni/src/main/java/java/lang/IllegalMonitorStateException.java
@@ -21,8 +21,6 @@
  * Thrown when a monitor operation is attempted when the monitor is not in the
  * correct state, for example when a thread attempts to exit a monitor which it
  * does not own.
- * 
- * @since Android 1.0
  */
 public class IllegalMonitorStateException extends RuntimeException {
 
@@ -31,8 +29,6 @@
     /**
      * Constructs a new {@code IllegalMonitorStateException} that includes the
      * current stack trace.
-     * 
-     * @since Android 1.0
      */
     public IllegalMonitorStateException() {
         super();
@@ -44,7 +40,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public IllegalMonitorStateException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/IllegalStateException.java b/libcore/luni/src/main/java/java/lang/IllegalStateException.java
index 427aaf4..28db2de 100644
--- a/libcore/luni/src/main/java/java/lang/IllegalStateException.java
+++ b/libcore/luni/src/main/java/java/lang/IllegalStateException.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when an action is attempted at a time when the virtual machine is not
  * in the correct state.
- * 
- * @since Android 1.0
  */
 public class IllegalStateException extends RuntimeException {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code IllegalStateException} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public IllegalStateException() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public IllegalStateException(String detailMessage) {
         super(detailMessage);
@@ -57,7 +52,7 @@
      *            the detail message for this exception.
      * @param cause
      *            the cause of this exception.
-     * @since Android 1.0
+     * @since 1.5
      */
     public IllegalStateException(String message, Throwable cause) {
         super(message, cause);
@@ -69,7 +64,7 @@
      * 
      * @param cause
      *            the cause of this exception, may be {@code null}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public IllegalStateException(Throwable cause) {
         super((cause == null ? null : cause.toString()), cause);
diff --git a/libcore/luni/src/main/java/java/lang/IllegalThreadStateException.java b/libcore/luni/src/main/java/java/lang/IllegalThreadStateException.java
index 82eccbb..f1e99a8 100644
--- a/libcore/luni/src/main/java/java/lang/IllegalThreadStateException.java
+++ b/libcore/luni/src/main/java/java/lang/IllegalThreadStateException.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when an operation is attempted which is not possible given the state
  * that the executing thread is in.
- * 
- * @since Android 1.0
  */
 public class IllegalThreadStateException extends IllegalArgumentException {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code IllegalThreadStateException} that includes the
      * current stack trace.
-     * 
-     * @since Android 1.0
      */
     public IllegalThreadStateException() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public IllegalThreadStateException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/IncompatibleClassChangeError.java b/libcore/luni/src/main/java/java/lang/IncompatibleClassChangeError.java
index 83950fd..2155a28 100644
--- a/libcore/luni/src/main/java/java/lang/IncompatibleClassChangeError.java
+++ b/libcore/luni/src/main/java/java/lang/IncompatibleClassChangeError.java
@@ -24,7 +24,6 @@
  * the same running image.
  * 
  * @see Error
- * @since Android 1.0
  */
 public class IncompatibleClassChangeError extends LinkageError {
 
@@ -33,8 +32,6 @@
     /**
      * Constructs a new {@code IncompatibleClassChangeError} that includes the
      * current stack trace.
-     * 
-     * @since Android 1.0
      */
     public IncompatibleClassChangeError() {
         super();
@@ -46,7 +43,6 @@
      * 
      * @param detailMessage
      *            the detail message for this error.
-     * @since Android 1.0
      */
     public IncompatibleClassChangeError(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/IndexOutOfBoundsException.java b/libcore/luni/src/main/java/java/lang/IndexOutOfBoundsException.java
index a4dc282..f26fcbf 100644
--- a/libcore/luni/src/main/java/java/lang/IndexOutOfBoundsException.java
+++ b/libcore/luni/src/main/java/java/lang/IndexOutOfBoundsException.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when a program attempts to access a value in an indexable collection
  * using a value which is outside of the range of valid indices.
- * 
- * @since Android 1.0
  */
 public class IndexOutOfBoundsException extends RuntimeException {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code IndexOutOfBoundsException} that includes the
      * current stack trace.
-     * 
-     * @since Android 1.0
      */
     public IndexOutOfBoundsException() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public IndexOutOfBoundsException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/InheritableThreadLocal.java b/libcore/luni/src/main/java/java/lang/InheritableThreadLocal.java
index 41e0d82..7e12ac2 100644
--- a/libcore/luni/src/main/java/java/lang/InheritableThreadLocal.java
+++ b/libcore/luni/src/main/java/java/lang/InheritableThreadLocal.java
@@ -1,17 +1,18 @@
 /*
- * Copyright (C) 2008 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.lang;
@@ -24,36 +25,33 @@
  * creation time. However, subclasses may override {code #childValue(Object)}
  * to provide an arbitrary function for passing the value of a parent's
  * thread-local variable to the child's thread-local variable.
- * 
+ *
  * @see java.lang.Thread
  * @see java.lang.ThreadLocal
- * 
- * @since Android 1.0
  */
 public class InheritableThreadLocal<T> extends ThreadLocal<T> {
 
     /**
      * Creates a new inheritable thread-local variable.
-     * 
-     * @since Android 1.0
      */
-    public InheritableThreadLocal() {}
+    public InheritableThreadLocal() {
+        super();
+    }
 
     /**
      * Computes the initial value of this thread-local variable for the child
-     * thread given the parent thread's value. Called from the parent thread
-     * when creating a child thread. The default implementation returns the
-     * parent thread's value.
-     * 
-     * @param parentValue
-     *            the value of the variable in the parent thread.
+     * thread given the parent thread's value. Called from the parent thread when
+     * creating a child thread. The default implementation returns the parent
+     * thread's value.
+     *
+     * @param parentValue the value of the variable in the parent thread.
      * @return the initial value of the variable for the child thread.
-     * @since Android 1.0
      */
     protected T childValue(T parentValue) {
         return parentValue;
     }
 
+    // BEGIN android-added
     @Override
     Values values(Thread current) {
         return current.inheritableValues;
@@ -63,4 +61,5 @@
     Values initializeValues(Thread current) {
         return current.inheritableValues = new Values();
     }
+    // END android-added
 }
diff --git a/libcore/luni/src/main/java/java/lang/InstantiationError.java b/libcore/luni/src/main/java/java/lang/InstantiationError.java
index 0d387c6..9ad1ed6 100644
--- a/libcore/luni/src/main/java/java/lang/InstantiationError.java
+++ b/libcore/luni/src/main/java/java/lang/InstantiationError.java
@@ -23,9 +23,6 @@
  * {@code new} is invoked.
  * <p>
  * Note that this can only occur when inconsistent class files are being loaded.
- * </p>
- * 
- * @since Android 1.0
  */
 public class InstantiationError extends IncompatibleClassChangeError {
     private static final long serialVersionUID = -4885810657349421204L;
@@ -33,8 +30,6 @@
     /**
      * Constructs a new {@code InstantiationError} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public InstantiationError() {
         super();
@@ -46,7 +41,6 @@
      * 
      * @param detailMessage
      *            the detail message for this error.
-     * @since Android 1.0
      */
     public InstantiationError(String detailMessage) {
         super(detailMessage);
@@ -58,7 +52,6 @@
      * 
      * @param clazz
      *            the class that can not be instantiated.
-     * @since Android 1.0
      */
     InstantiationError(Class<?> clazz) {
         super(clazz.getName());
diff --git a/libcore/luni/src/main/java/java/lang/InstantiationException.java b/libcore/luni/src/main/java/java/lang/InstantiationException.java
index cc8b556..fe68345 100644
--- a/libcore/luni/src/main/java/java/lang/InstantiationException.java
+++ b/libcore/luni/src/main/java/java/lang/InstantiationException.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when a program attempts to access a constructor which is not
  * accessible from the location where the reference is made.
- * 
- * @since Android 1.0
  */
 public class InstantiationException extends Exception {
     private static final long serialVersionUID = -8441929162975509110L;
@@ -29,8 +27,6 @@
     /**
      * Constructs a new {@code InstantiationException} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public InstantiationException() {
         super();
@@ -42,7 +38,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public InstantiationException(String detailMessage) {
         super(detailMessage);
@@ -54,7 +49,6 @@
      * 
      * @param clazz
      *            the class that can not be instantiated.
-     * @since Android 1.0
      */
     InstantiationException(Class<?> clazz) {
         super(clazz.getName());
diff --git a/libcore/luni/src/main/java/java/lang/Integer.java b/libcore/luni/src/main/java/java/lang/Integer.java
index 3a98872..570120b 100644
--- a/libcore/luni/src/main/java/java/lang/Integer.java
+++ b/libcore/luni/src/main/java/java/lang/Integer.java
@@ -24,10 +24,9 @@
  * href="http://www.hackersdelight.org/">Henry S. Warren, Jr.'s Hacker's
  * Delight, (Addison Wesley, 2002)</a> as well as <a
  * href="http://aggregate.org/MAGIC/">The Aggregate's Magic Algorithms</a>.
- * </p>
- * 
+ *
  * @see java.lang.Number
- * @since Android 1.0
+ * @since 1.1
  */
 public final class Integer extends Number implements Comparable<Integer> {
 
@@ -40,30 +39,32 @@
 
     /**
      * Constant for the maximum {@code int} value, 2<sup>31</sup>-1.
-     * 
-     * @since Android 1.0
      */
     public static final int MAX_VALUE = 0x7FFFFFFF;
 
     /**
      * Constant for the minimum {@code int} value, -2<sup>31</sup>.
-     * 
-     * @since Android 1.0
      */
     public static final int MIN_VALUE = 0x80000000;
 
     /**
      * Constant for the number of bits needed to represent an {@code int} in
      * two's complement form.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final int SIZE = 32;
 
+    /*
+     * Progressively smaller decimal order of magnitude that can be represented
+     * by an instance of Integer. Used to help compute the String
+     * representation.
+     */
+    private static final int[] decimalScale = new int[] { 1000000000, 100000000,
+            10000000, 1000000, 100000, 10000, 1000, 100, 10, 1 };
+
     /**
      * The {@link Class} object that represents the primitive type {@code int}.
-     * 
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static final Class<Integer> TYPE = (Class<Integer>) new int[0]
@@ -75,10 +76,9 @@
     /**
      * Constructs a new {@code Integer} with the specified primitive integer
      * value.
-     * 
+     *
      * @param value
      *            the primitive integer value to store in the new instance.
-     * @since Android 1.0
      */
     public Integer(int value) {
         this.value = value;
@@ -86,13 +86,12 @@
 
     /**
      * Constructs a new {@code Integer} from the specified string.
-     * 
+     *
      * @param string
      *            the string representation of an integer value.
      * @throws NumberFormatException
      *             if {@code string} can not be decoded into an integer value.
      * @see #parseInt(String)
-     * @since Android 1.0
      */
     public Integer(String string) throws NumberFormatException {
         this(parseInt(string));
@@ -106,7 +105,7 @@
     /**
      * Compares this object to the specified integer object to determine their
      * relative order.
-     * 
+     *
      * @param object
      *            the integer object to compare this object to.
      * @return a negative value if the value of this integer is less than the
@@ -114,7 +113,7 @@
      *         value of {@code object} are equal; a positive value if the value
      *         of this integer is greater than the value of {@code object}.
      * @see java.lang.Comparable
-     * @since Android 1.0
+     * @since 1.2
      */
     public int compareTo(Integer object) {
         return value > object.value ? 1 : (value < object.value ? -1 : 0);
@@ -125,14 +124,13 @@
      * string can be decoded into an integer value. The string may be an
      * optional minus sign "-" followed by a hexadecimal ("0x..." or "#..."),
      * octal ("0..."), or decimal ("...") representation of an integer.
-     * 
+     *
      * @param string
      *            a string representation of an integer value.
      * @return an {@code Integer} containing the value represented by
      *         {@code string}.
      * @throws NumberFormatException
      *             if {@code string} can not be parsed as an integer value.
-     * @since Android 1.0
      */
     public static Integer decode(String string) throws NumberFormatException {
         int length = string.length(), i = 0;
@@ -158,23 +156,21 @@
                 return valueOf(0);
             }
             if ((firstDigit = string.charAt(i)) == 'x' || firstDigit == 'X') {
-                if (i == length) {
+                if (++i == length) {
                     // BEGIN android-changed
                     throw new NumberFormatException("unable to parse '"+string+"' as integer");
                     // END android-changed
                 }
-                i++;
                 base = 16;
             } else {
                 base = 8;
             }
         } else if (firstDigit == '#') {
-            if (i == length) {
+            if (++i == length) {
                 // BEGIN android-changed
                 throw new NumberFormatException("unable to parse '"+string+"' as integer");
                 // END android-changed
             }
-            i++;
             base = 16;
         }
 
@@ -191,12 +187,11 @@
      * Compares this instance with the specified object and indicates if they
      * are equal. In order to be equal, {@code o} must be an instance of
      * {@code Integer} and have the same integer value as this object.
-     * 
+     *
      * @param o
      *            the object to compare this integer with.
      * @return {@code true} if the specified object is equal to this
      *         {@code Integer}; {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object o) {
@@ -214,12 +209,11 @@
      * {@code string}. Returns {@code null} if {@code string} is {@code null}
      * or empty, if the property can not be found or if its value can not be
      * parsed as an integer.
-     * 
+     *
      * @param string
      *            the name of the requested system property.
      * @return the requested property's value as an {@code Integer} or
      *         {@code null}.
-     * @since Android 1.0        
      */
     public static Integer getInteger(String string) {
         if (string == null || string.length() == 0) {
@@ -241,7 +235,7 @@
      * {@code string}. Returns the specified default value if {@code string} is
      * {@code null} or empty, if the property can not be found or if its value
      * can not be parsed as an integer.
-     * 
+     *
      * @param string
      *            the name of the requested system property.
      * @param defaultValue
@@ -249,7 +243,6 @@
      *            system property with the requested name.
      * @return the requested property's value as an {@code Integer} or the
      *         default value.
-     * @since Android 1.0        
      */
     public static Integer getInteger(String string, int defaultValue) {
         if (string == null || string.length() == 0) {
@@ -271,7 +264,7 @@
      * {@code string}. Returns the specified default value if {@code string} is
      * {@code null} or empty, if the property can not be found or if its value
      * can not be parsed as an integer.
-     * 
+     *
      * @param string
      *            the name of the requested system property.
      * @param defaultValue
@@ -279,7 +272,6 @@
      *            system property with the requested name.
      * @return the requested property's value as an {@code Integer} or the
      *         default value.
-     * @since Android 1.0        
      */
     public static Integer getInteger(String string, Integer defaultValue) {
         if (string == null || string.length() == 0) {
@@ -303,9 +295,8 @@
 
     /**
      * Gets the primitive value of this int.
-     * 
+     *
      * @return this object's primitive value.
-     * @since Android 1.0
      */
     @Override
     public int intValue() {
@@ -320,14 +311,13 @@
     /**
      * Parses the specified string as a signed decimal integer value. The ASCII
      * character \u002d ('-') is recognized as the minus sign.
-     * 
+     *
      * @param string
      *            the string representation of an integer value.
      * @return the primitive integer value represented by {@code string}.
      * @throws NumberFormatException
      *             if {@code string} is {@code null}, has a length of zero or
      *             can not be parsed as an integer value.
-     * @since Android 1.0
      */
     public static int parseInt(String string) throws NumberFormatException {
         return parseInt(string, 10);
@@ -336,7 +326,7 @@
     /**
      * Parses the specified string as a signed integer value using the specified
      * radix. The ASCII character \u002d ('-') is recognized as the minus sign.
-     * 
+     *
      * @param string
      *            the string representation of an integer value.
      * @param radix
@@ -348,7 +338,6 @@
      *             {@code radix < Character.MIN_RADIX},
      *             {@code radix > Character.MAX_RADIX}, or if {@code string}
      *             can not be parsed as an integer value.
-     * @since Android 1.0
      */
     public static int parseInt(String string, int radix)
             throws NumberFormatException {
@@ -417,11 +406,10 @@
     /**
      * Converts the specified integer into its binary string representation. The
      * returned string is a concatenation of '0' and '1' characters.
-     * 
+     *
      * @param i
      *            the integer to convert.
      * @return the binary string representation of {@code i}.
-     * @since Android 1.0
      */
     public static String toBinaryString(int i) {
         int count = 1, j = i;
@@ -446,12 +434,11 @@
      * Converts the specified integer into its hexadecimal string
      * representation. The returned string is a concatenation of characters from
      * '0' to '9' and 'a' to 'f'.
-     * 
+     *
      * @param i
      *            the integer to convert.
      * @return the hexadecimal string representation of {@code i}.
-     * @since Android 1.0
-     */    
+     */
     public static String toHexString(int i) {
         int count = 1, j = i;
 
@@ -480,12 +467,11 @@
     /**
      * Converts the specified integer into its octal string representation. The
      * returned string is a concatenation of characters from '0' to '7'.
-     * 
+     *
      * @param i
      *            the integer to convert.
      * @return the octal string representation of {@code i}.
-     * @since Android 1.0
-     */    
+     */
     public static String toOctalString(int i) {
         int count = 1, j = i;
 
@@ -514,14 +500,102 @@
      * Converts the specified integer into its decimal string representation.
      * The returned string is a concatenation of a minus sign if the number is
      * negative and characters from '0' to '9'.
-     * 
-     * @param i
+     *
+     * @param value
      *            the integer to convert.
-     * @return the decimal string representation of {@code i}.
-     * @since Android 1.0
-     */    
-    public static String toString(int i) {
-        return toString(i, 10);
+     * @return the decimal string representation of {@code value}.
+     */
+    public static String toString(int value) {
+        // BEGIN android-note
+        // cache the strings in the range 0..99 to save allocations?
+        // END android-note
+        if (value == 0) {
+            return "0"; //$NON-NLS-1$
+        }
+
+        // Faster algorithm for smaller Integers
+        if (value < 1000 && value > -1000) {
+            char[] buffer = new char[4];
+            int positive_value = value < 0 ? -value : value;
+            int first_digit = 0;
+            if (value < 0) {
+                buffer[0] = '-';
+                first_digit++;
+            }
+            int last_digit = first_digit;
+            int quot = positive_value;
+            do {
+                int res = quot / 10;
+                int digit_value = quot - (res * 10);
+                digit_value += '0';
+                buffer[last_digit++] = (char) digit_value;
+                quot = res;
+            } while (quot != 0);
+
+            int count = last_digit--;
+            do {
+                char tmp = buffer[last_digit];
+                buffer[last_digit--] = buffer[first_digit];
+                buffer[first_digit++] = tmp;
+            } while (first_digit < last_digit);
+            return new String(0, count, buffer);
+        }
+        if (value == MIN_VALUE) {
+            return "-2147483648";//$NON-NLS-1$
+        }
+
+        char[] buffer = new char[11];
+        int positive_value = value < 0 ? -value : value;
+        byte first_digit = 0;
+        if (value < 0) {
+            buffer[0] = '-';
+            first_digit++;
+        }
+        byte last_digit = first_digit;
+        byte count;
+        int number;
+        boolean start = false;
+        for (int i = 0; i < 9; i++) {
+            count = 0;
+            if (positive_value < (number = decimalScale[i])) {
+                if (start) {
+                    buffer[last_digit++] = '0';
+                }
+                continue;
+            }
+
+            if (i > 0) {
+                number = (decimalScale[i] << 3);
+                if (positive_value >= number) {
+                    positive_value -= number;
+                    count += 8;
+                }
+                number = (decimalScale[i] << 2);
+                if (positive_value >= number) {
+                    positive_value -= number;
+                    count += 4;
+                }
+            }
+            number = (decimalScale[i] << 1);
+            if (positive_value >= number) {
+                positive_value -= number;
+                count += 2;
+            }
+            if (positive_value >= decimalScale[i]) {
+                positive_value -= decimalScale[i];
+                count++;
+            }
+            if (count > 0 && !start) {
+                start = true;
+            }
+            if (start) {
+                buffer[last_digit++] = (char) (count + '0');
+            }
+        }
+
+        buffer[last_digit++] = (char) (positive_value + '0');
+        count = last_digit--;
+        return new String(0, count, buffer);
     }
 
     /**
@@ -531,15 +605,18 @@
      * depending on the radix. If {@code radix} is not in the interval defined
      * by {@code Character.MIN_RADIX} and {@code Character.MAX_RADIX} then 10 is
      * used as the base for the conversion.
-     * 
+     *
      * @param i
      *            the integer to convert.
      * @param radix
      *            the base to use for the conversion.
      * @return the string representation of {@code i}.
-     * @since Android 1.0
-     */    
+     */
     public static String toString(int i, int radix) {
+        // BEGIN android-note
+        // if radix==10, call thru to faster Integer.toString(int) ?
+        // only worthwhile if 10 is a popular parameter
+        // END android-note
         if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
             radix = 10;
         }
@@ -575,7 +652,7 @@
 
     /**
      * Parses the specified string as a signed decimal integer value.
-     * 
+     *
      * @param string
      *            the string representation of an integer value.
      * @return an {@code Integer} instance containing the integer value
@@ -584,7 +661,6 @@
      *             if {@code string} is {@code null}, has a length of zero or
      *             can not be parsed as an integer value.
      * @see #parseInt(String)
-     * @since Android 1.0
      */
     public static Integer valueOf(String string) throws NumberFormatException {
         return valueOf(parseInt(string));
@@ -593,7 +669,7 @@
     /**
      * Parses the specified string as a signed integer value using the specified
      * radix.
-     * 
+     *
      * @param string
      *            the string representation of an integer value.
      * @param radix
@@ -606,7 +682,6 @@
      *             {@code radix > Character.MAX_RADIX}, or if {@code string}
      *             can not be parsed as an integer value.
      * @see #parseInt(String, int)
-     * @since Android 1.0
      */
     public static Integer valueOf(String string, int radix)
             throws NumberFormatException {
@@ -618,11 +693,11 @@
      * and returns the bit mask value for that bit. This is also referred to as
      * the Most Significant 1 Bit. Returns zero if the specified integer is
      * zero.
-     * 
+     *
      * @param i
      *            the integer to examine.
      * @return the bit mask indicating the highest 1 bit in {@code i}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int highestOneBit(int i) {
         i |= (i >> 1);
@@ -638,11 +713,11 @@
      * and returns the bit mask value for that bit. This is also referred
      * to as the Least Significant 1 Bit. Returns zero if the specified integer
      * is zero.
-     * 
+     *
      * @param i
      *            the integer to examine.
      * @return the bit mask indicating the lowest 1 bit in {@code i}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int lowestOneBit(int i) {
         return (i & (-i));
@@ -651,11 +726,11 @@
     /**
      * Determines the number of leading zeros in the specified integer prior to
      * the {@link #highestOneBit(int) highest one bit}.
-     * 
+     *
      * @param i
      *            the integer to examine.
      * @return the number of leading zeros in {@code i}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int numberOfLeadingZeros(int i) {
         i |= i >> 1;
@@ -669,11 +744,11 @@
     /**
      * Determines the number of trailing zeros in the specified integer after
      * the {@link #lowestOneBit(int) lowest one bit}.
-     * 
+     *
      * @param i
      *            the integer to examine.
      * @return the number of trailing zeros in {@code i}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int numberOfTrailingZeros(int i) {
         return bitCount((i & -i) - 1);
@@ -682,11 +757,11 @@
     /**
      * Counts the number of 1 bits in the specified integer; this is also
      * referred to as population count.
-     * 
+     *
      * @param i
      *            the integer to examine.
      * @return the number of 1 bits in {@code i}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int bitCount(int i) {
         i -= ((i >> 1) & 0x55555555);
@@ -700,13 +775,13 @@
     /**
      * Rotates the bits of the specified integer to the left by the specified
      * number of bits.
-     * 
+     *
      * @param i
      *            the integer value to rotate left.
      * @param distance
      *            the number of bits to rotate.
      * @return the rotated value.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int rotateLeft(int i, int distance) {
         if (distance == 0) {
@@ -723,13 +798,13 @@
     /**
      * Rotates the bits of the specified integer to the right by the specified
      * number of bits.
-     * 
+     *
      * @param i
      *            the integer value to rotate right.
      * @param distance
      *            the number of bits to rotate.
      * @return the rotated value.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int rotateRight(int i, int distance) {
         if (distance == 0) {
@@ -745,11 +820,11 @@
 
     /**
      * Reverses the order of the bytes of the specified integer.
-     * 
+     *
      * @param i
      *            the integer value for which to reverse the byte order.
      * @return the reversed value.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int reverseBytes(int i) {
         int b3 = i >>> 24;
@@ -761,11 +836,11 @@
 
     /**
      * Reverses the order of the bits of the specified integer.
-     * 
+     *
      * @param i
      *            the integer value for which to reverse the bit order.
      * @return the reversed value.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int reverse(int i) {
         // From Hacker's Delight, 7-1, Figure 7-1
@@ -778,12 +853,12 @@
     /**
      * Returns the value of the {@code signum} function for the specified
      * integer.
-     * 
+     *
      * @param i
      *            the integer value to check.
      * @return -1 if {@code i} is negative, 1 if {@code i} is positive, 0 if
      *         {@code i} is zero.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int signum(int i) {
         return (i == 0 ? 0 : (i < 0 ? -1 : 1));
@@ -795,12 +870,11 @@
      * If it is not necessary to get a new {@code Integer} instance, it is
      * recommended to use this method instead of the constructor, since it
      * maintains a cache of instances which may result in better performance.
-     * </p>
-     * 
+     *
      * @param i
      *            the integer value to store in the instance.
      * @return a {@code Integer} instance containing {@code i}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static Integer valueOf(int i) {
         if (i < -128 || i > 127) {
@@ -814,7 +888,6 @@
         /**
          * <p>
          * A cache of instances used by {@link Integer#valueOf(int)} and auto-boxing.
-         * </p>
          */
         static final Integer[] CACHE = new Integer[256];
 
diff --git a/libcore/luni/src/main/java/java/lang/InternalError.java b/libcore/luni/src/main/java/java/lang/InternalError.java
index 9082cd8..d4748af 100644
--- a/libcore/luni/src/main/java/java/lang/InternalError.java
+++ b/libcore/luni/src/main/java/java/lang/InternalError.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when the virtual machine notices that it has gotten into an undefined
  * state.
- * 
- * @since Android 1.0
  */
 public class InternalError extends VirtualMachineError {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code InternalError} that includes the current stack
      * trace.
-     * 
-     * @since Android 1.0
      */
     public InternalError() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this error.
-     * @since Android 1.0
      */
     public InternalError(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/InterruptedException.java b/libcore/luni/src/main/java/java/lang/InterruptedException.java
index b014559..0e099c3 100644
--- a/libcore/luni/src/main/java/java/lang/InterruptedException.java
+++ b/libcore/luni/src/main/java/java/lang/InterruptedException.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when a waiting thread is activated before the condition it was waiting
  * for has been satisfied.
- * 
- * @since Android 1.0
  */
 public class InterruptedException extends Exception {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code InterruptedException} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public InterruptedException() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public InterruptedException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/Iterable.java b/libcore/luni/src/main/java/java/lang/Iterable.java
index d12f0a6..31883fb 100644
--- a/libcore/luni/src/main/java/java/lang/Iterable.java
+++ b/libcore/luni/src/main/java/java/lang/Iterable.java
@@ -21,8 +21,8 @@
 /**
  * Objects of classes that implement this interface can be used within a
  * {@code foreach} statement.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public interface Iterable<T> {
 
@@ -30,7 +30,6 @@
      * Returns an {@link Iterator} for the elements in this object.
      * 
      * @return An {@code Iterator} instance.
-     * @since Android 1.0
      */
     Iterator<T> iterator();
 }
diff --git a/libcore/luni/src/main/java/java/lang/LinkageError.java b/libcore/luni/src/main/java/java/lang/LinkageError.java
index 9bba54b..061f3dc 100644
--- a/libcore/luni/src/main/java/java/lang/LinkageError.java
+++ b/libcore/luni/src/main/java/java/lang/LinkageError.java
@@ -23,7 +23,6 @@
  * loading and linking class files.
  * 
  * @see Error
- * @since Android 1.0
  */
 public class LinkageError extends Error {
 
@@ -32,8 +31,6 @@
     /**
      * Constructs a new {@code LinkageError} that includes the current stack
      * trace.
-     * 
-     * @since Android 1.0
      */
     public LinkageError() {
         super();
@@ -45,7 +42,6 @@
      * 
      * @param detailMessage
      *            the detail message for this error.
-     * @since Android 1.0
      */
     public LinkageError(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/Long.java b/libcore/luni/src/main/java/java/lang/Long.java
index 00b56ae..2746424 100644
--- a/libcore/luni/src/main/java/java/lang/Long.java
+++ b/libcore/luni/src/main/java/java/lang/Long.java
@@ -24,10 +24,9 @@
  * href="http://www.hackersdelight.org/">Henry S. Warren, Jr.'s Hacker's
  * Delight, (Addison Wesley, 2002)</a> as well as <a
  * href="http://aggregate.org/MAGIC/">The Aggregate's Magic Algorithms</a>.
- * </p>
- * 
+ *
  * @see java.lang.Number
- * @since Android 1.0
+ * @since 1.0
  */
 public final class Long extends Number implements Comparable<Long> {
 
@@ -40,22 +39,16 @@
 
     /**
      * Constant for the maximum {@code long} value, 2<sup>63</sup>-1.
-     * 
-     * @since Android 1.0
      */
     public static final long MAX_VALUE = 0x7FFFFFFFFFFFFFFFL;
 
     /**
      * Constant for the minimum {@code long} value, -2<sup>63</sup>.
-     * 
-     * @since Android 1.0
      */
     public static final long MIN_VALUE = 0x8000000000000000L;
 
     /**
      * The {@link Class} object that represents the primitive type {@code long}.
-     * 
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static final Class<Long> TYPE = (Class<Long>) new long[0].getClass()
@@ -67,8 +60,8 @@
     /**
      * Constant for the number of bits needed to represent a {@code long} in
      * two's complement form.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final int SIZE = 64;
 
@@ -78,7 +71,6 @@
      * 
      * @param value
      *            the primitive long value to store in the new instance.
-     * @since Android 1.0
      */
     public Long(long value) {
         this.value = value;
@@ -92,7 +84,6 @@
      * @throws NumberFormatException
      *             if {@code string} can not be decoded into a long value.
      * @see #parseLong(String)
-     * @since Android 1.0
      */
     public Long(String string) throws NumberFormatException {
         this(parseLong(string));
@@ -114,7 +105,7 @@
      *         {@code object} are equal; a positive value if the value of this
      *         long is greater than the value of {@code object}.
      * @see java.lang.Comparable
-     * @since Android 1.0
+     * @since 1.2
      */
     public int compareTo(Long object) {
         return value > object.value ? 1 : (value < object.value ? -1 : 0);
@@ -131,7 +122,6 @@
      * @return a {@code Long} containing the value represented by {@code string}.
      * @throws NumberFormatException
      *             if {@code string} can not be parsed as a long value.
-     * @since Android 1.0
      */
     public static Long decode(String string) throws NumberFormatException {
         int length = string.length(), i = 0;
@@ -187,7 +177,6 @@
      *            the object to compare this long with.
      * @return {@code true} if the specified object is equal to this
      *         {@code Long}; {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object o) {
@@ -209,7 +198,6 @@
      * @param string
      *            the name of the requested system property.
      * @return the requested property's value as a {@code Long} or {@code null}.
-     * @since Android 1.0
      */
     public static Long getLong(String string) {
         if (string == null || string.length() == 0) {
@@ -239,7 +227,6 @@
      *            property with the requested name.
      * @return the requested property's value as a {@code Long} or the default
      *         value.
-     * @since Android 1.0
      */
     public static Long getLong(String string, long defaultValue) {
         if (string == null || string.length() == 0) {
@@ -269,7 +256,6 @@
      *            property with the requested name.
      * @return the requested property's value as a {@code Long} or the default
      *         value.
-     * @since Android 1.0
      */
     public static Long getLong(String string, Long defaultValue) {
         if (string == null || string.length() == 0) {
@@ -300,7 +286,6 @@
      * Gets the primitive value of this long.
      * 
      * @return this object's primitive value.
-     * @since Android 1.0
      */
     @Override
     public long longValue() {
@@ -317,7 +302,6 @@
      * @throws NumberFormatException
      *             if {@code string} is {@code null}, has a length of zero or
      *             can not be parsed as a long value.
-     * @since Android 1.0
      */
     public static long parseLong(String string) throws NumberFormatException {
         return parseLong(string, 10);
@@ -338,7 +322,6 @@
      *             {@code radix < Character.MIN_RADIX},
      *             {@code radix > Character.MAX_RADIX}, or if {@code string}
      *             can not be parsed as a long value.
-     * @since Android 1.0
      */
     public static long parseLong(String string, int radix)
             throws NumberFormatException {
@@ -397,7 +380,6 @@
      * @param l
      *            the long value to convert.
      * @return the binary string representation of {@code l}.
-     * @since Android 1.0
      */
     public static String toBinaryString(long l) {
         int count = 1;
@@ -427,7 +409,6 @@
      * @param l
      *            the long value to convert.
      * @return the hexadecimal string representation of {@code l}.
-     * @since Android 1.0
      */
     public static String toHexString(long l) {
         int count = 1;
@@ -462,7 +443,6 @@
      * @param l
      *            the long value to convert.
      * @return the octal string representation of {@code l}.
-     * @since Android 1.0
      */
     public static String toOctalString(long l) {
         int count = 1;
@@ -497,8 +477,7 @@
      * @param l
      *            the long to convert.
      * @return the decimal string representation of {@code l}.
-     * @since Android 1.0
-     */    
+     */
     public static String toString(long l) {
         return toString(l, 10);
     }
@@ -516,7 +495,6 @@
      * @param radix
      *            the base to use for the conversion.
      * @return the string representation of {@code l}.
-     * @since Android 1.0
      */
     public static String toString(long l, int radix) {
         if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
@@ -564,7 +542,6 @@
      *             if {@code string} is {@code null}, has a length of zero or
      *             can not be parsed as a long value.
      * @see #parseLong(String)
-     * @since Android 1.0
      */
     public static Long valueOf(String string) throws NumberFormatException {
         return valueOf(parseLong(string));
@@ -586,7 +563,6 @@
      *             {@code radix > Character.MAX_RADIX}, or if {@code string}
      *             can not be parsed as a long value.
      * @see #parseLong(String, int)
-     * @since Android 1.0
      */
     public static Long valueOf(String string, int radix)
             throws NumberFormatException {
@@ -602,7 +578,7 @@
      * @param lng
      *            the long to examine.
      * @return the bit mask indicating the highest 1 bit in {@code lng}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static long highestOneBit(long lng) {
         lng |= (lng >> 1);
@@ -623,7 +599,7 @@
      * @param lng
      *            the long to examine.
      * @return the bit mask indicating the lowest 1 bit in {@code lng}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static long lowestOneBit(long lng) {
         return (lng & (-lng));
@@ -632,11 +608,11 @@
     /**
      * Determines the number of leading zeros in the specified long value prior
      * to the {@link #highestOneBit(long) highest one bit}.
-     * 
+     *
      * @param lng
      *            the long to examine.
      * @return the number of leading zeros in {@code lng}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int numberOfLeadingZeros(long lng) {
         lng |= lng >> 1;
@@ -651,11 +627,11 @@
     /**
      * Determines the number of trailing zeros in the specified long value after
      * the {@link #lowestOneBit(long) lowest one bit}.
-     * 
+     *
      * @param lng
      *            the long to examine.
      * @return the number of trailing zeros in {@code lng}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int numberOfTrailingZeros(long lng) {
         return bitCount((lng & -lng) - 1);
@@ -664,11 +640,11 @@
     /**
      * Counts the number of 1 bits in the specified long value; this is also
      * referred to as population count.
-     * 
+     *
      * @param lng
      *            the long to examine.
      * @return the number of 1 bits in {@code lng}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int bitCount(long lng) {
         lng = (lng & 0x5555555555555555L) + ((lng >> 1) & 0x5555555555555555L);
@@ -684,13 +660,13 @@
     /**
      * Rotates the bits of the specified long value to the left by the specified
      * number of bits.
-     * 
+     *
      * @param lng
      *            the long value to rotate left.
      * @param distance
      *            the number of bits to rotate.
      * @return the rotated value.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static long rotateLeft(long lng, int distance) {
         if (distance == 0) {
@@ -705,15 +681,16 @@
     }
 
     /**
+     * <p>
      * Rotates the bits of the specified long value to the right by the
      * specified number of bits.
-     * 
+     *
      * @param lng
      *            the long value to rotate right.
      * @param distance
      *            the number of bits to rotate.
      * @return the rotated value.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static long rotateRight(long lng, int distance) {
         if (distance == 0) {
@@ -733,7 +710,7 @@
      * @param lng
      *            the long value for which to reverse the byte order.
      * @return the reversed value.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static long reverseBytes(long lng) {
         long b7 = lng >>> 56;
@@ -753,7 +730,7 @@
      * @param lng
      *            the long value for which to reverse the bit order.
      * @return the reversed value.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static long reverse(long lng) {
         // From Hacker's Delight, 7-1, Figure 7-1
@@ -774,7 +751,7 @@
      *            the long value to check.
      * @return -1 if {@code lng} is negative, 1 if {@code lng} is positive, 0 if
      *         {@code lng} is zero.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int signum(long lng) {
         return (lng == 0 ? 0 : (lng < 0 ? -1 : 1));
@@ -786,12 +763,11 @@
      * If it is not necessary to get a new {@code Long} instance, it is
      * recommended to use this method instead of the constructor, since it
      * maintains a cache of instances which may result in better performance.
-     * </p>
-     * 
+     *
      * @param lng
      *            the long value to store in the instance.
      * @return a {@code Long} instance containing {@code lng}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static Long valueOf(long lng) {
         if (lng < -128 || lng > 127) {
@@ -804,7 +780,6 @@
         /**
          * <p>
          * A cache of instances used by {@link Long#valueOf(long)} and auto-boxing.
-         * </p>
          */
         static final Long[] CACHE = new Long[256];
 
diff --git a/libcore/luni/src/main/java/java/lang/Math.java b/libcore/luni/src/main/java/java/lang/Math.java
index f18f40f..d06e6e4 100644
--- a/libcore/luni/src/main/java/java/lang/Math.java
+++ b/libcore/luni/src/main/java/java/lang/Math.java
@@ -20,23 +20,17 @@
 /**
  * Class Math provides basic math constants and operations such as trigonometric
  * functions, hyperbolic functions, exponential, logarithms, etc.
- * 
- * @since Android 1.0
  */
 public final class Math {
 
     /**
      * The double value closest to e, the base of the natural logarithm.
-     * 
-     * @since Android 1.0
      */
     public static final double E = 2.718281828459045;
 
     /**
      * The double value closest to pi, the ratio of a circle's circumference to
      * its diameter.
-     * 
-     * @since Android 1.0
      */
     public static final double PI = 3.141592653589793;
 
@@ -58,12 +52,10 @@
      * <li>{@code abs(-infinity) = +infinity}</li>
      * <li>{@code abs(NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param d
      *            the value whose absolute value has to be computed.
      * @return the absolute value of the argument.
-     * @since Android 1.0
      */
     public static double abs(double d) {
         long bits = Double.doubleToLongBits(d);
@@ -81,13 +73,11 @@
      * <li>{@code abs(-infinity) = +infinity}</li>
      * <li>{@code abs(NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param f
      *            the value whose absolute value has to be computed.
      * @return the argument if it is positive, otherwise the negation of the
      *         argument.
-     * @since Android 1.0
      */
     public static float abs(float f) {
         int bits = Float.floatToIntBits(f);
@@ -100,13 +90,11 @@
      * <p>
      * If the argument is {@code Integer.MIN_VALUE}, {@code Integer.MIN_VALUE}
      * is returned.
-     * </p>
      * 
      * @param i
      *            the value whose absolute value has to be computed.
      * @return the argument if it is positive, otherwise the negation of the
      *         argument.
-     * @since Android 1.0
      */
     public static int abs(int i) {
         return i >= 0 ? i : -i;
@@ -120,7 +108,6 @@
      *            the value whose absolute value has to be computed.
      * @return the argument if it is positive, otherwise the negation of the
      *         argument.
-     * @since Android 1.0
      */
     public static long abs(long l) {
         return l >= 0 ? l : -l;
@@ -137,12 +124,10 @@
      * <li>{@code acos((anything < -1) = NaN}</li>
      * <li>{@code acos(NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param d
      *            the value to compute arc cosine of.
      * @return the arc cosine of the argument.
-     * @since Android 1.0
      */
     public static native double acos(double d);
 
@@ -157,12 +142,10 @@
      * <li>{@code asin((anything < -1)) = NaN}</li>
      * <li>{@code asin(NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param d
      *            the value whose arc sine has to be computed.
      * @return the arc sine of the argument.
-     * @since Android 1.0
      */
     public static native double asin(double d);
 
@@ -179,20 +162,18 @@
      * <li>{@code atan(-infinity) = -pi/2}</li>
      * <li>{@code atan(NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param d
      *            the value whose arc tangent has to be computed.
      * @return the arc tangent of the argument.
-     * @since Android 1.0
      */
     public static native double atan(double d);
 
     /**
-     * Returns the closest double approximation of the arc tangent of
-     * {@code y/x} within the range {@code [-pi..pi]}. This is the angle of the
-     * polar representation of the rectangular coordinates (x,y). The returned
-     * result is within 2 ulps (units in the last place) of the real result.
+     * Returns the closest double approximation of the arc tangent of {@code
+     * y/x} within the range {@code [-pi..pi]}. This is the angle of the polar
+     * representation of the rectangular coordinates (x,y). The returned result
+     * is within 2 ulps (units in the last place) of the real result.
      * <p>
      * Special cases:
      * <ul>
@@ -214,24 +195,19 @@
      * <li>{@code atan2(-infinity, +infinity ) = -pi/4}</li>
      * <li>{@code atan2(+infinity, -infinity ) = +3pi/4}</li>
      * <li>{@code atan2(-infinity, -infinity ) = -3pi/4}</li>
-     * <li>{@code atan2(+infinity, (anything but,0, NaN, and infinity))}
-     * {@code =} {@code +pi/2}</li>
-     * <li>{@code atan2(-infinity, (anything but,0, NaN, and infinity))}
-     * {@code =} {@code -pi/2}</li>
+     * <li>{@code atan2(+infinity, (anything but,0, NaN, and infinity))} {@code
+     * =} {@code +pi/2}</li>
+     * <li>{@code atan2(-infinity, (anything but,0, NaN, and infinity))} {@code
+     * =} {@code -pi/2}</li>
      * </ul>
-     * </p>
      * 
      * @param y
      *            the numerator of the value whose atan has to be computed.
      * @param x
      *            the denominator of the value whose atan has to be computed.
      * @return the arc tangent of {@code y/x}.
-     * @since Android 1.0
      */
-    public static native double atan2(double y, double x);
-    // BEGIN android-note
-    // parameter names changed from d1 / d2 to x / y
-    // END android-note
+    public static native double atan2(double x, double y);
 
     /**
      * Returns the closest double approximation of the cube root of the
@@ -245,18 +221,16 @@
      * <li>{@code cbrt(-infinity) = -infinity}</li>
      * <li>{@code cbrt(NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param d
      *            the value whose cube root has to be computed.
      * @return the cube root of the argument.
-     * @since Android 1.0
      */
     public static native double cbrt(double d);
 
     /**
-     * Returns the double conversion of the most negative (closest to
-     * negative infinity) integer value which is greater than the argument.
+     * Returns the double conversion of the most negative (closest to negative
+     * infinity) integer value which is greater than the argument.
      * <p>
      * Special cases:
      * <ul>
@@ -267,14 +241,14 @@
      * <li>{@code ceil(-infinity) = -infinity}</li>
      * <li>{@code ceil(NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param d
      *            the value whose closest integer value has to be computed.
      * @return the ceiling of the argument.
-     * @since Android 1.0
      */
+    // BEGIN android-changed
     public static native double ceil(double d);
+    // END android-changed
 
     /**
      * Returns the closest double approximation of the cosine of the argument.
@@ -287,15 +261,13 @@
      * <li>{@code cos(-infinity) = NaN}</li>
      * <li>{@code cos(NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param d
      *            the angle whose cosine has to be computed, in radians.
      * @return the cosine of the argument.
-     * @since Android 1.0
      */
     public static native double cos(double d);
-    
+
     /**
      * Returns the closest double approximation of the hyperbolic cosine of the
      * argument. The returned result is within 2.5 ulps (units in the last
@@ -307,12 +279,10 @@
      * <li>{@code cosh(-infinity) = +infinity}</li>
      * <li>{@code cosh(NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param d
      *            the value whose hyperbolic cosine has to be computed.
      * @return the hyperbolic cosine of the argument.
-     * @since Android 1.0
      */
     public static native double cosh(double d);
 
@@ -327,19 +297,17 @@
      * <li>{@code exp(-infinity) = +0.0}</li>
      * <li>{@code exp(NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param d
      *            the value whose exponential has to be computed.
      * @return the exponential of the argument.
-     * @since Android 1.0
      */
     public static native double exp(double d);
-    
+
     /**
-     * Returns the closest double approximation of <i>{@code e}</i><sup>
-     * {@code d}</sup>{@code - 1}. If the argument is very close to 0, it is
-     * much more accurate to use {@code expm1(d)+1} than {@code exp(d)} (due to
+     * Returns the closest double approximation of <i>{@code e}</i><sup> {@code
+     * d}</sup>{@code - 1}. If the argument is very close to 0, it is much more
+     * accurate to use {@code expm1(d)+1} than {@code exp(d)} (due to
      * cancellation of significant digits). The returned result is within 1 ulp
      * (unit in the last place) of the real result.
      * <p>
@@ -354,14 +322,12 @@
      * <li>{@code expm1(-infinity) = -1.0}</li>
      * <li>{@code expm1(NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param d
-     *            the value to compute the <i>{@code e}</i><sup>{@code d}
-     *            </sup>{@code - 1} of.
-     * @return the <i>{@code e}</i><sup>{@code d}</sup>{@code - 1} value
-     *         of the argument.
-     * @since Android 1.0
+     *            the value to compute the <i>{@code e}</i><sup>{@code d} </sup>
+     *            {@code - 1} of.
+     * @return the <i>{@code e}</i><sup>{@code d}</sup>{@code - 1} value of the
+     *         argument.
      */
     public static native double expm1(double d);
 
@@ -377,20 +343,21 @@
      * <li>{@code floor(-infinity) = -infinity}</li>
      * <li>{@code floor(NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param d
      *            the value whose closest integer value has to be computed.
      * @return the floor of the argument.
-     * @since Android 1.0
      */
+    // 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> {@code y}</i><sup>{@code 2}</sup>{@code )}. The final result is
-     * without medium underflow or overflow. The returned result is within 1 ulp
-     * (unit in the last place) of the real result.
+     * Returns {@code sqrt(}<i>{@code x}</i><sup>{@code 2}</sup>{@code +} <i>
+     * {@code y}</i><sup>{@code 2}</sup>{@code )}. The final result is without
+     * medium underflow or overflow. The returned result is within 1 ulp (unit
+     * in the last place) of the real result. If one parameter remains constant,
+     * the result should be semi-monotonic.
      * <p>
      * Special cases:
      * <ul>
@@ -400,7 +367,6 @@
      * <li>{@code hypot((anything including NaN), -infinity) = +infinity}</li>
      * <li>{@code hypot(NaN, NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param x
      *            a double number.
@@ -409,7 +375,6 @@
      * @return the {@code sqrt(}<i>{@code x}</i><sup>{@code 2}</sup>{@code +}
      *         <i> {@code y}</i><sup>{@code 2}</sup>{@code )} value of the
      *         arguments.
-     * @since Android 1.0
      */
     public static native double hypot(double x, double y);
 
@@ -431,19 +396,14 @@
      * <li>{@code IEEEremainder(x, -infinity) = x } where x is anything but
      * +/-infinity</li>
      * </ul>
-     * </p>
      * 
      * @param x
      *            the numerator of the operation.
      * @param y
      *            the denominator of the operation.
      * @return the IEEE754 floating point reminder of of {@code x/y}.
-     * @since Android 1.0
      */
     public static native double IEEEremainder(double x, double y);
-    // BEGIN android-note
-    // parameter names changed from d1 / d2 to x / y
-    // END android-note
 
     /**
      * Returns the closest double approximation of the natural logarithm of the
@@ -459,12 +419,10 @@
      * <li>{@code log(-infinity) = NaN}</li>
      * <li>{@code log(NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param d
      *            the value whose log has to be computed.
      * @return the natural logarithm of the argument.
-     * @since Android 1.0
      */
     public static native double log(double d);
 
@@ -482,21 +440,19 @@
      * <li>{@code log10(-infinity) = NaN}</li>
      * <li>{@code log10(NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param d
      *            the value whose base 10 log has to be computed.
      * @return the natural logarithm of the argument.
-     * @since Android 1.0
      */
     public static native double log10(double d);
-    
+
     /**
      * Returns the closest double approximation of the natural logarithm of the
      * sum of the argument and 1. If the argument is very close to 0, it is much
      * more accurate to use {@code log1p(d)} than {@code log(1.0+d)} (due to
      * numerical cancellation). The returned result is within 1 ulp (unit in the
-     * last place) of the real result.
+     * last place) of the real result and is semi-monotonic.
      * <p>
      * Special cases:
      * <ul>
@@ -508,12 +464,10 @@
      * <li>{@code log1p(-infinity) = NaN}</li>
      * <li>{@code log1p(NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param d
      *            the value to compute the {@code ln(1+d)} of.
      * @return the natural logarithm of the sum of the argument and 1.
-     * @since Android 1.0
      */
     public static native double log1p(double d);
 
@@ -528,28 +482,30 @@
      * <li>{@code max(+0.0, -0.0) = +0.0}</li>
      * <li>{@code max(-0.0, +0.0) = +0.0}</li>
      * </ul>
-     * </p>
      * 
      * @param d1
      *            the first argument.
      * @param d2
      *            the second argument.
      * @return the larger of {@code d1} and {@code d2}.
-     * @since Android 1.0
      */
     public static double max(double d1, double d2) {
-        if (d1 > d2)
+        if (d1 > d2) {
             return d1;
-        if (d1 < d2)
+        }
+        if (d1 < d2) {
             return d2;
+        }
         /* if either arg is NaN, return NaN */
-        if (d1 != d2)
+        if (d1 != d2) {
             return Double.NaN;
-        /* max( +0.0,-0.0) == +0.0 */
-        if (d1 == 0.0
-                && ((Double.doubleToLongBits(d1) & Double.doubleToLongBits(d2)) & 0x8000000000000000L) == 0)
-            return 0.0;
-        return d1;
+        }
+        /* max(+0.0,-0.0) == +0.0 */
+        /* 0 == Double.doubleToRawLongBits(0.0d) */
+        if (Double.doubleToRawLongBits(d1) != 0) {
+            return d2;
+        }
+        return 0.0d;
     }
 
     /**
@@ -563,28 +519,30 @@
      * <li>{@code max(+0.0, -0.0) = +0.0}</li>
      * <li>{@code max(-0.0, +0.0) = +0.0}</li>
      * </ul>
-     * </p>
      * 
      * @param f1
      *            the first argument.
      * @param f2
      *            the second argument.
      * @return the larger of {@code f1} and {@code f2}.
-     * @since Android 1.0
      */
     public static float max(float f1, float f2) {
-        if (f1 > f2)
+        if (f1 > f2) {
             return f1;
-        if (f1 < f2)
+        }
+        if (f1 < f2) {
             return f2;
+        }
         /* if either arg is NaN, return NaN */
-        if (f1 != f2)
+        if (f1 != f2) {
             return Float.NaN;
-        /* max( +0.0,-0.0) == +0.0 */
-        if (f1 == 0.0f
-                && ((Float.floatToIntBits(f1) & Float.floatToIntBits(f2)) & 0x80000000) == 0)
-            return 0.0f;
-        return f1;
+        }
+        /* max(+0.0,-0.0) == +0.0 */
+        /* 0 == Float.floatToRawIntBits(0.0f) */
+        if (Float.floatToRawIntBits(f1) != 0) {
+            return f2;
+        }
+        return 0.0f;
     }
 
     /**
@@ -596,7 +554,6 @@
      * @param i2
      *            the second argument.
      * @return the larger of {@code i1} and {@code i2}.
-     * @since Android 1.0
      */
     public static int max(int i1, int i2) {
         return i1 > i2 ? i1 : i2;
@@ -611,7 +568,6 @@
      * @param l2
      *            the second argument.
      * @return the larger of {@code l1} and {@code l2}.
-     * @since Android 1.0
      */
     public static long max(long l1, long l2) {
         return l1 > l2 ? l1 : l2;
@@ -628,28 +584,30 @@
      * <li>{@code min(+0.0, -0.0) = -0.0}</li>
      * <li>{@code min(-0.0, +0.0) = -0.0}</li>
      * </ul>
-     * </p>
      * 
      * @param d1
      *            the first argument.
      * @param d2
      *            the second argument.
      * @return the smaller of {@code d1} and {@code d2}.
-     * @since Android 1.0
      */
     public static double min(double d1, double d2) {
-        if (d1 > d2)
+        if (d1 > d2) {
             return d2;
-        if (d1 < d2)
+        }
+        if (d1 < d2) {
             return d1;
+        }
         /* if either arg is NaN, return NaN */
-        if (d1 != d2)
+        if (d1 != d2) {
             return Double.NaN;
-        /* min( +0.0,-0.0) == -0.0 */
-        if (d1 == 0.0
-                && ((Double.doubleToLongBits(d1) | Double.doubleToLongBits(d2)) & 0x8000000000000000l) != 0)
-            return 0.0 * (-1.0);
-        return d1;
+        }
+        /* min(+0.0,-0.0) == -0.0 */
+        /* 0x8000000000000000L == Double.doubleToRawLongBits(-0.0d) */
+        if (Double.doubleToRawLongBits(d1) == 0x8000000000000000L) {
+            return -0.0d;
+        }
+        return d2;
     }
 
     /**
@@ -663,28 +621,30 @@
      * <li>{@code min(+0.0, -0.0) = -0.0}</li>
      * <li>{@code min(-0.0, +0.0) = -0.0}</li>
      * </ul>
-     * </p>
      * 
      * @param f1
      *            the first argument.
      * @param f2
      *            the second argument.
      * @return the smaller of {@code f1} and {@code f2}.
-     * @since Android 1.0
      */
     public static float min(float f1, float f2) {
-        if (f1 > f2)
+        if (f1 > f2) {
             return f2;
-        if (f1 < f2)
+        }
+        if (f1 < f2) {
             return f1;
+        }
         /* if either arg is NaN, return NaN */
-        if (f1 != f2)
+        if (f1 != f2) {
             return Float.NaN;
-        /* min( +0.0,-0.0) == -0.0 */
-        if (f1 == 0.0f
-                && ((Float.floatToIntBits(f1) | Float.floatToIntBits(f2)) & 0x80000000) != 0)
-            return 0.0f * (-1.0f);
-        return f1;
+        }
+        /* min(+0.0,-0.0) == -0.0 */
+        /* 0x80000000 == Float.floatToRawIntBits(-0.0f) */
+        if (Float.floatToRawIntBits(f1) == 0x80000000) {
+            return -0.0f;
+        }
+        return f2;
     }
 
     /**
@@ -696,7 +656,6 @@
      * @param i2
      *            the second argument.
      * @return the smaller of {@code i1} and {@code i2}.
-     * @since Android 1.0
      */
     public static int min(int i1, int i2) {
         return i1 < i2 ? i1 : i2;
@@ -711,15 +670,14 @@
      * @param l2
      *            the second argument.
      * @return the smaller of {@code l1} and {@code l2}.
-     * @since Android 1.0
      */
     public static long min(long l1, long l2) {
         return l1 < l2 ? l1 : l2;
     }
 
     /**
-     * Returns the closest double approximation of the result of raising
-     * {@code x} to the power of {@code y}.
+     * Returns the closest double approximation of the result of raising {@code
+     * x} to the power of {@code y}.
      * <p>
      * Special cases:
      * <ul>
@@ -743,23 +701,18 @@
      * <li>{@code pow(+infinity, (+anything except 0, NaN)) = +infinity}</li>
      * <li>{@code pow(+infinity, (-anything except 0, NaN)) = +0.0}</li>
      * <li>{@code pow(-infinity, (anything)) = -pow(0, (-anything))}</li>
-     * <li>{@code pow((-anything), (integer))} {@code =}
-     * {@code pow(-1,(integer))*pow(+anything,integer) }</li>
+     * <li>{@code pow((-anything), (integer))} {@code =} {@code
+     * pow(-1,(integer))*pow(+anything,integer) }</li>
      * <li>{@code pow((-anything except 0 and inf), (non-integer)) = NAN}</li>
      * </ul>
-     * </p>
      * 
      * @param x
      *            the base of the operation.
      * @param y
      *            the exponent of the operation.
      * @return {@code x} to the power of {@code y}.
-     * @since Android 1.0
      */
     public static native double pow(double x, double y);
-    // BEGIN android-note
-    // parameter names changed from d1 / d2 to x / y
-    // END android-note
 
     /**
      * Returns the double conversion of the result of rounding the argument to
@@ -773,14 +726,14 @@
      * <li>{@code rint(-infinity) = -infinity}</li>
      * <li>{@code rint(NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param d
      *            the value to be rounded.
      * @return the closest integer to the argument (as a double).
-     * @since Android 1.0
      */
+    // 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
@@ -796,17 +749,16 @@
      * <li>{@code round(-infintiy) = Long.MIN_VALUE}</li>
      * <li>{@code round(NaN) = +0.0}</li>
      * </ul>
-     * </p>
      * 
      * @param d
      *            the value to be rounded.
      * @return the closest integer to the argument.
-     * @since Android 1.0
      */
     public static long round(double d) {
         // check for NaN
-        if (d != d)
+        if (d != d) {
             return 0L;
+        }
         return (long) floor(d + 0.5d);
     }
 
@@ -824,17 +776,16 @@
      * <li>{@code round(-infintiy) = Integer.MIN_VALUE}</li>
      * <li>{@code round(NaN) = +0.0}</li>
      * </ul>
-     * </p>
      * 
      * @param f
      *            the value to be rounded.
      * @return the closest integer to the argument.
-     * @since Android 1.0
      */
     public static int round(float f) {
         // check for NaN
-        if (f != f)
+        if (f != f) {
             return 0;
+        }
         return (int) floor(f + 0.5f);
     }
 
@@ -852,17 +803,15 @@
      * <li>{@code signum(-infinity) = -1.0}</li>
      * <li>{@code signum(NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param d
      *            the value whose signum has to be computed.
      * @return the value of the signum function.
-     * @since Android 1.0
      */
     public static double signum(double d) {
         return StrictMath.signum(d);
     }
-    
+
     /**
      * Returns the signum function of the argument. If the argument is less than
      * zero, it returns -1.0. If the argument is greater than zero, 1.0 is
@@ -877,12 +826,10 @@
      * <li>{@code signum(-infinity) = -1.0}</li>
      * <li>{@code signum(NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param f
      *            the value whose signum has to be computed.
      * @return the value of the signum function.
-     * @since Android 1.0
      */
     public static float signum(float f) {
         return StrictMath.signum(f);
@@ -901,15 +848,13 @@
      * <li>{@code sin(-infinity) = NaN}</li>
      * <li>{@code sin(NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param d
      *            the angle whose sin has to be computed, in radians.
      * @return the sine of the argument.
-     * @since Android 1.0
      */
     public static native double sin(double d);
-    
+
     /**
      * Returns the closest double approximation of the hyperbolic sine of the
      * argument. The returned result is within 2.5 ulps (units in the last
@@ -923,12 +868,10 @@
      * <li>{@code sinh(-infinity) = -infinity}</li>
      * <li>{@code sinh(NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param d
      *            the value whose hyperbolic sine has to be computed.
      * @return the hyperbolic sine of the argument.
-     * @since Android 1.0
      */
     public static native double sinh(double d);
 
@@ -944,12 +887,10 @@
      * <li>{@code sqrt(+infinity) = +infinity}</li>
      * <li>{@code sqrt(NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param d
      *            the value whose square root has to be computed.
      * @return the square root of the argument.
-     * @since Android 1.0
      */
     public static native double sqrt(double d);
 
@@ -966,15 +907,13 @@
      * <li>{@code tan(-infinity) = NaN}</li>
      * <li>{@code tan(NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param d
      *            the angle whose tangens has to be computed, in radians.
      * @return the tangent of the argument.
-     * @since Android 1.0
      */
     public static native double tan(double d);
-    
+
     /**
      * Returns the closest double approximation of the hyperbolic tangent of the
      * argument. The absolute value is always less than 1. The returned result
@@ -990,12 +929,10 @@
      * <li>{@code tanh(-infinity) = -1.0}</li>
      * <li>{@code tanh(NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param d
      *            the value whose hyperbolic tangent has to be computed.
      * @return the hyperbolic tangent of the argument.
-     * @since Android 1.0
      */
     public static native double tanh(double d);
 
@@ -1004,7 +941,6 @@
      * (exclusive).
      * 
      * @return a pseudo-random number.
-     * @since Android 1.0
      */
     public static double random() {
         if (random == null) {
@@ -1025,12 +961,10 @@
      * <li>{@code toRadians(-infinity) = -infinity}</li>
      * <li>{@code toRadians(NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param angdeg
      *            an angle in degrees.
      * @return the radian measure of the angle.
-     * @since Android 1.0
      */
     public static double toRadians(double angdeg) {
         return angdeg / 180d * PI;
@@ -1048,22 +982,20 @@
      * <li>{@code toDegrees(-infinity) = -infinity}</li>
      * <li>{@code toDegrees(NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param angrad
      *            an angle in radians.
      * @return the degree measure of the angle.
-     * @since Android 1.0
      */
     public static double toDegrees(double angrad) {
         return angrad * 180d / PI;
     }
-    
+
     /**
      * Returns the argument's ulp (unit in the last place). The size of a ulp of
      * a double value is the positive distance between this value and the double
-     * value next larger in magnitude. For non-NaN {@code x},
-     * {@code ulp(-x) == ulp(x)}.
+     * value next larger in magnitude. For non-NaN {@code x}, {@code ulp(-x) ==
+     * ulp(x)}.
      * <p>
      * Special cases:
      * <ul>
@@ -1073,12 +1005,10 @@
      * <li>{@code ulp(-infintiy) = infinity}</li>
      * <li>{@code ulp(NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param d
      *            the floating-point value to compute ulp of.
      * @return the size of a ulp of the argument.
-     * @since Android 1.0
      */
     public static double ulp(double d) {
         // special cases
@@ -1094,8 +1024,8 @@
     /**
      * Returns the argument's ulp (unit in the last place). The size of a ulp of
      * a float value is the positive distance between this value and the float
-     * value next larger in magnitude. For non-NaN {@code x},
-     * {@code ulp(-x) == ulp(x)}.
+     * value next larger in magnitude. For non-NaN {@code x}, {@code ulp(-x) ==
+     * ulp(x)}.
      * <p>
      * Special cases:
      * <ul>
@@ -1105,12 +1035,10 @@
      * <li>{@code ulp(-infintiy) = infinity}</li>
      * <li>{@code ulp(NaN) = NaN}</li>
      * </ul>
-     * </p>
      * 
      * @param f
      *            the floating-point value to compute ulp of.
      * @return the size of a ulp of the argument.
-     * @since Android 1.0
      */
     public static float ulp(float f) {
         // special cases
@@ -1127,5 +1055,5 @@
 
     private native static double nextafter(double x, double y);
 
-    private native static float nextafterf(float x, float y); 
+    private native static float nextafterf(float x, float y);
 }
diff --git a/libcore/luni/src/main/java/java/lang/NegativeArraySizeException.java b/libcore/luni/src/main/java/java/lang/NegativeArraySizeException.java
index 1ca7855..50b6929 100644
--- a/libcore/luni/src/main/java/java/lang/NegativeArraySizeException.java
+++ b/libcore/luni/src/main/java/java/lang/NegativeArraySizeException.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when an attempt is made to create an array with a size of less than
  * zero.
- * 
- * @since Android 1.0
  */
 public class NegativeArraySizeException extends RuntimeException {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code NegativeArraySizeException} that includes the
      * current stack trace.
-     * 
-     * @since Android 1.0
      */
     public NegativeArraySizeException() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public NegativeArraySizeException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/NoClassDefFoundError.java b/libcore/luni/src/main/java/java/lang/NoClassDefFoundError.java
index e23ecc6..9fae360 100644
--- a/libcore/luni/src/main/java/java/lang/NoClassDefFoundError.java
+++ b/libcore/luni/src/main/java/java/lang/NoClassDefFoundError.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when the virtual machine is unable to locate a class which it has been
  * asked to load.
- * 
- * @since Android 1.0
  */
 public class NoClassDefFoundError extends LinkageError {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code NoClassDefFoundError} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public NoClassDefFoundError() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this error.
-     * @since Android 1.0
      */
     public NoClassDefFoundError(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/NoSuchFieldError.java b/libcore/luni/src/main/java/java/lang/NoSuchFieldError.java
index 667d6a5..9b479f6 100644
--- a/libcore/luni/src/main/java/java/lang/NoSuchFieldError.java
+++ b/libcore/luni/src/main/java/java/lang/NoSuchFieldError.java
@@ -22,9 +22,6 @@
  * on a class or object, a field that does not exist.
  * <p>
  * Note that this can only occur when inconsistent class files are being loaded.
- * </p>
- * 
- * @since Android 1.0
  */
 public class NoSuchFieldError extends IncompatibleClassChangeError {
 
@@ -33,8 +30,6 @@
     /**
      * Constructs a new {@code NoSuchFieldError} that includes the current stack
      * trace.
-     * 
-     * @since Android 1.0
      */
     public NoSuchFieldError() {
         super();
@@ -46,7 +41,6 @@
      * 
      * @param detailMessage
      *            the detail message for this error.
-     * @since Android 1.0
      */
     public NoSuchFieldError(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/NoSuchFieldException.java b/libcore/luni/src/main/java/java/lang/NoSuchFieldException.java
index 31a566d..283bfab 100644
--- a/libcore/luni/src/main/java/java/lang/NoSuchFieldException.java
+++ b/libcore/luni/src/main/java/java/lang/NoSuchFieldException.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when the virtual machine notices that a program tries to reference,
  * on a class or object, a field that does not exist.
- * 
- * @since Android 1.0
  */
 public class NoSuchFieldException extends java.lang.Exception {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code NoSuchFieldException} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public NoSuchFieldException() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public NoSuchFieldException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/NoSuchMethodError.java b/libcore/luni/src/main/java/java/lang/NoSuchMethodError.java
index a72f76b..91ed06c 100644
--- a/libcore/luni/src/main/java/java/lang/NoSuchMethodError.java
+++ b/libcore/luni/src/main/java/java/lang/NoSuchMethodError.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when the virtual machine notices that a program tries to reference,
  * on a class or object, a method that does not exist.
- * 
- * @since Android 1.0
  */
 public class NoSuchMethodError extends IncompatibleClassChangeError {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code NoSuchMethodError} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public NoSuchMethodError() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public NoSuchMethodError(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/NoSuchMethodException.java b/libcore/luni/src/main/java/java/lang/NoSuchMethodException.java
index bd3cf01..cf4dbe0 100644
--- a/libcore/luni/src/main/java/java/lang/NoSuchMethodException.java
+++ b/libcore/luni/src/main/java/java/lang/NoSuchMethodException.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when the virtual machine notices that a program tries to reference,
  * on a class or object, a method that does not exist.
- * 
- * @since Android 1.0
  */
 public class NoSuchMethodException extends java.lang.Exception {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code NoSuchMethodException} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
    public NoSuchMethodException() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public NoSuchMethodException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/NullPointerException.java b/libcore/luni/src/main/java/java/lang/NullPointerException.java
index d11b282..90e9e50 100644
--- a/libcore/luni/src/main/java/java/lang/NullPointerException.java
+++ b/libcore/luni/src/main/java/java/lang/NullPointerException.java
@@ -23,8 +23,6 @@
  * object or array points to {@code null}. It also occurs in some other, less
  * obvious circumstances, like a {@code throw e} statement where the {@link
  * Throwable} reference is {@code null}.
- * 
- * @since Android 1.0
  */
 public class NullPointerException extends RuntimeException {
 
@@ -33,8 +31,6 @@
     /**
      * Constructs a new {@code NullPointerException} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public NullPointerException() {
         super();
@@ -46,7 +42,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public NullPointerException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/Number.java b/libcore/luni/src/main/java/java/lang/Number.java
index dc868cb..4fb5596 100644
--- a/libcore/luni/src/main/java/java/lang/Number.java
+++ b/libcore/luni/src/main/java/java/lang/Number.java
@@ -22,8 +22,6 @@
  * The abstract superclass of the classes which represent numeric base types
  * (that is {@link Byte}, {@link Short}, {@link Integer}, {@link Long},
  * {@link Float}, and {@link Double}. 
- * 
- * @since Android 1.0
  */
 public abstract class Number implements java.io.Serializable {
 
@@ -31,8 +29,6 @@
 
     /**
      * Empty default constructor.
-     * 
-     * @since Android 1.0
      */
     public Number() {
     }
@@ -42,7 +38,6 @@
      * truncating the value, so it fits into a byte.  
      * 
      * @return the primitive byte value of this object.
-     * @since Android 1.0
      */
     public byte byteValue() {
         return (byte) intValue();
@@ -52,7 +47,6 @@
      * Returns this object's value as a double. Might involve rounding.
      * 
      * @return the primitive double value of this object.
-     * @since Android 1.0
      */
     public abstract double doubleValue();
 
@@ -60,7 +54,6 @@
      * Returns this object's value as a float. Might involve rounding.
      * 
      * @return the primitive float value of this object.
-     * @since Android 1.0
      */
     public abstract float floatValue();
 
@@ -69,7 +62,6 @@
      * truncating the value, so it fits into an int.
      * 
      * @return the primitive int value of this object.
-     * @since Android 1.0
      */
     public abstract int intValue();
 
@@ -78,7 +70,6 @@
      * truncating the value, so it fits into a long.
      * 
      * @return the primitive long value of this object.
-     * @since Android 1.0
      */
     public abstract long longValue();
 
@@ -87,7 +78,6 @@
      * truncating the value, so it fits into a short.
      * 
      * @return the primitive short value of this object.
-     * @since Android 1.0
      */
     public short shortValue() {
         return (short) intValue();
diff --git a/libcore/luni/src/main/java/java/lang/NumberFormatException.java b/libcore/luni/src/main/java/java/lang/NumberFormatException.java
index ed5433d..9d2f0c7 100644
--- a/libcore/luni/src/main/java/java/lang/NumberFormatException.java
+++ b/libcore/luni/src/main/java/java/lang/NumberFormatException.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when an invalid value is passed to a string-to-number conversion
  * method.
- * 
- * @since Android 1.0
  */
 public class NumberFormatException extends java.lang.IllegalArgumentException {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code NumberFormatException} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public NumberFormatException() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public NumberFormatException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/OutOfMemoryError.java b/libcore/luni/src/main/java/java/lang/OutOfMemoryError.java
index 2c54ad1..a8f8a2c 100644
--- a/libcore/luni/src/main/java/java/lang/OutOfMemoryError.java
+++ b/libcore/luni/src/main/java/java/lang/OutOfMemoryError.java
@@ -21,8 +21,6 @@
  * Thrown when a request for memory is made that can not be satisfied using the
  * available platform resources. Such a request may be made by both the running
  * application or by an internal function of the virtual machine.
- * 
- * @since Android 1.0
  */
 public class OutOfMemoryError extends java.lang.VirtualMachineError {
 
@@ -31,8 +29,6 @@
     /**
      * Constructs a new {@code OutOfMemoryError} that includes the current stack
      * trace.
-     * 
-     * @since Android 1.0
      */
     public OutOfMemoryError() {
         super();
@@ -44,7 +40,6 @@
      * 
      * @param detailMessage
      *            the detail message for this error.
-     * @since Android 1.0
      */
     public OutOfMemoryError(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/Override.java b/libcore/luni/src/main/java/java/lang/Override.java
index 864357d..c4049cb 100644
--- a/libcore/luni/src/main/java/java/lang/Override.java
+++ b/libcore/luni/src/main/java/java/lang/Override.java
@@ -1,12 +1,12 @@
-/*
- * Copyright (C) 2007 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
- *
+/* 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.
@@ -16,19 +16,19 @@
 
 package java.lang;
 
-import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 
 /**
- * Annotation type used to mark methods that override a method declaration in a superclass.
- * Compilers produce an error if a method annotated with @Override does not actually override
- * a method in a superclass.
- * 
- * @since Android 1.0
+ * Annotation type used to mark methods that override a method declaration in a
+ * superclass. Compilers produce an error if a method annotated with @Override
+ * does not actually override a method in a superclass.
+ *
+ * @since 1.5
  */
-@Retention(value=java.lang.annotation.RetentionPolicy.SOURCE)
-@Target(value=java.lang.annotation.ElementType.METHOD)
-public @interface Override
-{
-
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.SOURCE)
+public @interface Override {
 }
diff --git a/libcore/luni/src/main/java/java/lang/Process.java b/libcore/luni/src/main/java/java/lang/Process.java
index 5fe8be7..c030fcc 100644
--- a/libcore/luni/src/main/java/java/lang/Process.java
+++ b/libcore/luni/src/main/java/java/lang/Process.java
@@ -17,25 +17,20 @@
 
 package java.lang;
 
-
 import java.io.InputStream;
 import java.io.OutputStream;
 
 /**
  * Represents an external process. Enables writing to, reading from, destroying,
  * and waiting for the external process, as well as querying its exit value.
- * 
+ *
  * @see Runtime#exec
  * @see ProcessBuilder#start()
- * 
- * @since Android 1.0
  */
 public abstract class Process {
 
     /**
      * Terminates this process and closes any associated streams.
-     * 
-     * @since Android 1.0
      */
     abstract public void destroy();
 
@@ -46,7 +41,6 @@
      * @return the exit value of this process.
      * @throws IllegalThreadStateException
      *             if this process has not terminated.
-     * @since Android 1.0
      */
     abstract public int exitValue();
 
@@ -56,7 +50,6 @@
      * 
      * @return the input stream to read from the error stream associated with
      *         the native process.
-     * @since Android 1.0
      */
     abstract public InputStream getErrorStream();
 
@@ -66,7 +59,6 @@
      * 
      * @return the input stream to read from the output stream associated with
      *         the native process.
-     * @since Android 1.0
      */
     abstract public InputStream getInputStream();
 
@@ -76,7 +68,6 @@
      * 
      * @return the output stream to write to the input stream associated with
      *         the native process.
-     * @since Android 1.0
      */
     abstract public OutputStream getOutputStream();
 
@@ -87,7 +78,6 @@
      * @return the exit value of the native process being waited on.
      * @throws InterruptedException
      *             if the calling thread is interrupted.
-     * @since Android 1.0
      */
     abstract public int waitFor() throws InterruptedException;
 }
diff --git a/libcore/luni/src/main/java/java/lang/ProcessBuilder.java b/libcore/luni/src/main/java/java/lang/ProcessBuilder.java
index 9d6b90b..f649fec 100644
--- a/libcore/luni/src/main/java/java/lang/ProcessBuilder.java
+++ b/libcore/luni/src/main/java/java/lang/ProcessBuilder.java
@@ -24,8 +24,8 @@
 
 /**
  * Creates operating system processes.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public final class ProcessBuilder {
 
@@ -40,10 +40,9 @@
     /**
      * Constructs a new {@code ProcessBuilder} instance with the specified
      * operating system program and its arguments.
-     * 
+     *
      * @param command
      *            the requested operating system program and its arguments.
-     * @since Android 1.0
      */
     public ProcessBuilder(String... command) {
         this(toList(command));
@@ -54,12 +53,11 @@
      * operating system program and its arguments. Note that the list passed to
      * this constructor is not copied, so any subsequent updates to it are
      * reflected in this instance's state.
-     * 
+     *
      * @param command
      *            the requested operating system program and its arguments.
      * @throws NullPointerException
      *             if {@code command} is {@code null}.
-     * @since Android 1.0
      */
     public ProcessBuilder(List<String> command) {
         super();
@@ -76,9 +74,8 @@
      * Returns this process builder's current program and arguments. Note that
      * the returned list is not a copy and modifications to it will change the
      * state of this instance.
-     * 
+     *
      * @return this process builder's program and arguments.
-     * @since Android 1.0
      */
     public List<String> command() {
         return command;
@@ -86,11 +83,10 @@
 
     /**
      * Changes the program and arguments of this process builder.
-     * 
+     *
      * @param command
      *            the new operating system program and its arguments.
      * @return this process builder instance.
-     * @since Android 1.0
      */
     public ProcessBuilder command(String... command) {
         return command(toList(command));
@@ -100,13 +96,12 @@
      * Changes the program and arguments of this process builder. Note that the
      * list passed to this method is not copied, so any subsequent updates to it
      * are reflected in this instance's state.
-     * 
+     *
      * @param command
      *            the new operating system program and its arguments.
      * @return this process builder instance.
      * @throws NullPointerException
      *             if {@code command} is {@code null}.
-     * @since Android 1.0
      */
     public ProcessBuilder command(List<String> command) {
         if (command == null) {
@@ -120,9 +115,8 @@
      * Returns the working directory of this process builder. If {@code null} is
      * returned, then the working directory of the Java process is used when a
      * process is started.
-     * 
+     *
      * @return the current working directory, may be {@code null}.
-     * @since Android 1.0
      */
     public File directory() {
         return directory;
@@ -132,11 +126,10 @@
      * Changes the working directory of this process builder. If the specified
      * directory is {@code null}, then the working directory of the Java
      * process is used when a process is started.
-     * 
+     *
      * @param directory
      *            the new working directory for this process builder.
      * @return this process builder instance.
-     * @since Android 1.0
      */
     public ProcessBuilder directory(File directory) {
         this.directory = directory;
@@ -149,9 +142,8 @@
      * the environment, as returned by {@link System#getenv()}. Note that the
      * map returned by this method is not a copy and any changes made to it are
      * reflected in this instance's state.
-     * 
+     *
      * @return the map containing this process builder's environment variables.
-     * @since Android 1.0
      */
     public Map<String, String> environment() {
         return environment;
@@ -162,10 +154,9 @@
      * output. If redirected, the {@link Process#getErrorStream()} will always
      * return end of stream and standard error is written to
      * {@link Process#getInputStream()}.
-     * 
+     *
      * @return {@code true} if the standard error is redirected; {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public boolean redirectErrorStream() {
         return redirectErrorStream;
@@ -174,12 +165,11 @@
     /**
      * Changes the state of whether or not standard error is redirected to
      * standard output.
-     * 
+     *
      * @param redirectErrorStream
      *            {@code true} to redirect standard error, {@code false}
      *            otherwise.
      * @return this process builder instance.
-     * @since Android 1.0
      */
     public ProcessBuilder redirectErrorStream(boolean redirectErrorStream) {
         this.redirectErrorStream = redirectErrorStream;
@@ -188,7 +178,7 @@
 
     /**
      * Starts a new process based on the current state of this process builder.
-     * 
+     *
      * @return the new {@code Process} instance.
      * @throws NullPointerException
      *             if any of the elements of {@link #command()} is {@code null}.
@@ -199,7 +189,6 @@
      *             process creation.
      * @throws IOException
      *             if an I/O error happens.
-     * @since Android 1.0
      */
     public Process start() throws IOException {
         if (command.isEmpty()) {
diff --git a/libcore/luni/src/main/java/java/lang/Readable.java b/libcore/luni/src/main/java/java/lang/Readable.java
index 1eca6cc..b536f59 100644
--- a/libcore/luni/src/main/java/java/lang/Readable.java
+++ b/libcore/luni/src/main/java/java/lang/Readable.java
@@ -22,8 +22,6 @@
 /**
  * Represents a sequence of characters that can be incrementally read (copied)
  * into a {@link CharBuffer}.
- * 
- * @since Android 1.0
  */
 public interface Readable {
 
@@ -37,7 +35,6 @@
      *         {@code Readable} reaches its end
      * @throws IOException
      *             if an I/O error occurs.
-     * @since Android 1.0
      */
     int read(CharBuffer cb) throws IOException;
 }
diff --git a/libcore/luni/src/main/java/java/lang/Runnable.java b/libcore/luni/src/main/java/java/lang/Runnable.java
index 2cca717..b09d914 100644
--- a/libcore/luni/src/main/java/java/lang/Runnable.java
+++ b/libcore/luni/src/main/java/java/lang/Runnable.java
@@ -21,8 +21,6 @@
 /**
  * Represents a command that can be executed. Often used to run code in a
  * different {@link Thread}.
- * 
- * @since Android 1.0
  */
 public interface Runnable {
 
@@ -30,8 +28,6 @@
      * Starts executing the active part of the class' code. This method is
      * called when a thread is started that has been created with a class which
      * implements {@code Runnable}.
-     * 
-     * @since Android 1.0
      */
     public void run();
 }
diff --git a/libcore/luni/src/main/java/java/lang/RuntimeException.java b/libcore/luni/src/main/java/java/lang/RuntimeException.java
index e519bf1..9229b0c 100644
--- a/libcore/luni/src/main/java/java/lang/RuntimeException.java
+++ b/libcore/luni/src/main/java/java/lang/RuntimeException.java
@@ -23,8 +23,6 @@
  * the virtual machine. Unlike checked exceptions (exceptions where the type
  * doesn't extend {@code RuntimeException} or {@link Error}), the compiler does
  * not require code to handle runtime exceptions.
- * 
- * @since Android 1.0
  */
 public class RuntimeException extends Exception {
     
@@ -33,8 +31,6 @@
     /**
      * Constructs a new {@code RuntimeException} that includes the current stack
      * trace.
-     * 
-     * @since Android 1.0
      */
     public RuntimeException() {
         super();
@@ -46,7 +42,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public RuntimeException(String detailMessage) {
         super(detailMessage);
@@ -60,7 +55,6 @@
      *            the detail message for this exception.
      * @param throwable
      *            the cause of this exception.
-     * @since Android 1.0
      */
     public RuntimeException(String detailMessage, Throwable throwable) {
         super(detailMessage, throwable);
@@ -72,7 +66,6 @@
      * 
      * @param throwable
      *            the cause of this exception.
-     * @since Android 1.0
      */
     public RuntimeException(Throwable throwable) {
         super(throwable);
diff --git a/libcore/luni/src/main/java/java/lang/RuntimePermission.java b/libcore/luni/src/main/java/java/lang/RuntimePermission.java
index 0f856a0..ba7e665 100644
--- a/libcore/luni/src/main/java/java/lang/RuntimePermission.java
+++ b/libcore/luni/src/main/java/java/lang/RuntimePermission.java
@@ -23,8 +23,6 @@
  * Represents the permission to execute a runtime-related function. There is no
  * action list associated with a {@code RuntimePermission}; the user either has
  * the permission or he doesn't.
- * 
- * @since Android 1.0
  */
 public final class RuntimePermission extends BasicPermission {
 
@@ -83,7 +81,6 @@
      * 
      * @param permissionName
      *            the name of the new permission.
-     * @since Android 1.0
      */
     public RuntimePermission(String permissionName) {
         super(permissionName);
@@ -97,7 +94,6 @@
      *            the name of the new permission.
      * @param actions
      *            ignored.
-     * @since Android 1.0
      */
     public RuntimePermission(String name, String actions) {
         super(name, actions);
diff --git a/libcore/luni/src/main/java/java/lang/SecurityException.java b/libcore/luni/src/main/java/java/lang/SecurityException.java
index 7387088..c977be0 100644
--- a/libcore/luni/src/main/java/java/lang/SecurityException.java
+++ b/libcore/luni/src/main/java/java/lang/SecurityException.java
@@ -19,8 +19,6 @@
 
 /**
  * Thrown when a security manager check fails.
- * 
- * @since Android 1.0
  */
 public class SecurityException extends java.lang.RuntimeException {
 
@@ -29,8 +27,6 @@
     /**
      * Constructs a new {@code SecurityException} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public SecurityException() {
         super();
@@ -42,7 +38,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public SecurityException(String detailMessage) {
         super(detailMessage);
@@ -56,7 +51,7 @@
      *            the detail message for this exception.
      * @param cause
      *            the optional cause of this exception, may be {@code null}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public SecurityException(String message, Throwable cause) {
         super(message, cause);
@@ -68,7 +63,7 @@
      * 
      * @param cause
      *            the optional cause of this exception, may be {@code null}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public SecurityException(Throwable cause) {
         super((cause == null ? null : cause.toString()), cause);
diff --git a/libcore/luni/src/main/java/java/lang/SecurityManager.java b/libcore/luni/src/main/java/java/lang/SecurityManager.java
index dc624e3..9125850 100644
--- a/libcore/luni/src/main/java/java/lang/SecurityManager.java
+++ b/libcore/luni/src/main/java/java/lang/SecurityManager.java
@@ -49,8 +49,6 @@
  * operation is not allowed, then they throw a {@link SecurityException}. The
  * only exception is {@link #checkTopLevelWindow(Object)}, which returns a
  * boolean to indicate permission.
- * 
- * @since Android 1.0
  */
 public class SecurityManager {
 
@@ -63,9 +61,8 @@
 
     /**
      * Flag to indicate whether a security check is in progress.
-     * 
+     *
      * @deprecated Use {@link #checkPermission}
-     * @since Android 1.0
      */
     @Deprecated
     protected boolean inCheck;
@@ -75,9 +72,6 @@
      * <p>
      * The {@code RuntimePermission("createSecurityManager")} is checked if a
      * security manager is installed.
-     * </p>
-     * 
-     * @since Android 1.0
      */
     public SecurityManager() {
         SecurityManager security = System.getSecurityManager();
@@ -94,7 +88,7 @@
     /**
      * Checks whether the calling thread is allowed to accept socket
      * connections.
-     * 
+     *
      * @param host
      *            the address of the host that attempts to connect.
      * @param port
@@ -104,7 +98,6 @@
      * @throws SecurityException
      *             if the calling thread is not allowed to accept socket
      *             connections from {@code host} through {@code port}.
-     * @since Android 1.0
      */
     public void checkAccept(String host, int port) {
         if (host == null) {
@@ -116,12 +109,11 @@
     /**
      * Checks whether the calling thread is allowed to modify the specified
      * thread.
-     * 
+     *
      * @param thread
      *            the thread to access.
      * @throws SecurityException
      *             if the calling thread is not allowed to access {@code thread}.
-     * @since Android 1.0
      */
     public void checkAccess(Thread thread) {
         // Only worry about system threads. Dead threads have a null group.
@@ -134,14 +126,13 @@
     /**
      * Checks whether the calling thread is allowed to modify the specified
      * thread group.
-     * 
+     *
      * @param group
      *            the thread group to access.
      * @throws NullPointerException
      *             if {@code group} is {@code null}.
      * @throws SecurityException
      *             if the calling thread is not allowed to access {@code group}.
-     * @since Android 1.0
      */
     public void checkAccess(ThreadGroup group) {
         // Only worry about system threads.
@@ -157,7 +148,7 @@
      * Checks whether the calling thread is allowed to establish socket
      * connections. A -1 port indicates the caller is trying to resolve the
      * hostname.
-     * 
+     *
      * @param host
      *            the address of the host to connect to.
      * @param port
@@ -167,7 +158,6 @@
      * @throws SecurityException
      *             if the calling thread is not allowed to connect to {@code
      *             host} through {@code port}.
-     * @since Android 1.0
      */
     public void checkConnect(String host, int port) {
         if (host == null) {
@@ -184,7 +174,7 @@
      * Checks whether the specified security context is allowed to establish
      * socket connections. A -1 port indicates the caller is trying to resolve
      * the hostname.
-     * 
+     *
      * @param host
      *            the address of the host to connect to.
      * @param port
@@ -196,7 +186,6 @@
      * @throws SecurityException
      *             if {@code context} is not allowed to connect to {@code host}
      *             through {@code port}.
-     * @since Android 1.0
      */
     public void checkConnect(String host, int port, Object context) {
         // BEGIN android-added
@@ -214,11 +203,10 @@
 
     /**
      * Checks whether the calling thread is allowed to create a class loader.
-     * 
+     *
      * @throws SecurityException
      *             if the calling thread is not allowed to create a class
      *             loader.
-     * @since Android 1.0
      */
     public void checkCreateClassLoader() {
         checkPermission(RuntimePermission.permissionToCreateClassLoader);
@@ -227,12 +215,11 @@
     /**
      * Checks whether the calling thread is allowed to delete the file with the
      * specified name, which should be passed in canonical form.
-     * 
+     *
      * @param file
      *            the name of the file to delete.
      * @throws SecurityException
      *             if the calling thread is not allowed to delete {@code file}.
-     * @since Android 1.0
      */
     public void checkDelete(String file) {
         checkPermission(new FilePermission(file, "delete")); //$NON-NLS-1$
@@ -241,12 +228,11 @@
     /**
      * Checks whether the calling thread is allowed to execute the specified
      * platform specific command.
-     * 
+     *
      * @param cmd
      *            the command line to execute.
      * @throws SecurityException
      *             if the calling thread is not allowed to execute {@code cmd}.
-     * @since Android 1.0
      */
     public void checkExec(String cmd) {
         checkPermission(new FilePermission(new File(cmd).isAbsolute() ? cmd
@@ -256,14 +242,13 @@
     /**
      * Checks whether the calling thread is allowed to terminate the virtual
      * machine.
-     * 
+     *
      * @param status
      *            the status that the virtual machine returns when it is
      *            terminated.
      * @throws SecurityException
      *             if the calling thread is not allowed to terminate the virtual
      *             machine with {@code status}.
-     * @since Android 1.0
      */
     public void checkExit(int status) {
         checkPermission(RuntimePermission.permissionToExitVM);
@@ -272,12 +257,11 @@
     /**
      * Checks whether the calling thread is allowed to load the specified native
      * library.
-     * 
+     *
      * @param libName
      *            the name of the library to load.
      * @throws SecurityException
      *             if the calling thread is not allowed to load {@code libName}.
-     * @since Android 1.0
      */
     public void checkLink(String libName) {
         if (libName == null) {
@@ -289,12 +273,11 @@
     /**
      * Checks whether the calling thread is allowed to listen on the specified
      * port.
-     * 
+     *
      * @param port
      *            the port number to check.
      * @throws SecurityException
      *             if the calling thread is not allowed listen on {@code port}.
-     * @since Android 1.0
      */
     public void checkListen(int port) {
         if (port == 0) {
@@ -312,7 +295,7 @@
      * reflect API). Due to the nature of the check, overriding implementations
      * cannot call {@code super.checkMemberAccess()} since the stack would no
      * longer be of the expected shape.
-     * 
+     *
      * @param cls
      *            the class of which members are accessed.
      * @param type
@@ -322,7 +305,6 @@
      * @throws SecurityException
      *             if the calling thread is not allowed to access members of
      *             {@code cls}.
-     * @since Android 1.0
      */
     public void checkMemberAccess(Class<?> cls, int type) {
         if (cls == null) {
@@ -352,12 +334,11 @@
     /**
      * Checks whether the calling thread is allowed to use the specified IP
      * multicast group address.
-     * 
+     *
      * @param maddr
      *            the internet group address to use.
      * @throws SecurityException
      *             if the calling thread is not allowed to use {@code maddr}.
-     * @since Android 1.0
      */
     public void checkMulticast(InetAddress maddr) {
         checkPermission(new SocketPermission(maddr.getHostAddress(),
@@ -367,7 +348,7 @@
     /**
      * Checks whether the calling thread is allowed to use the specified IP
      * multicast group address.
-     * 
+     *
      * @param maddr
      *            the internet group address to use.
      * @param ttl
@@ -376,7 +357,6 @@
      * @throws SecurityException
      *             if the calling thread is not allowed to use {@code maddr}.
      * @deprecated use {@link #checkMulticast(java.net.InetAddress)}
-     * @since Android 1.0
      */
     @Deprecated
     public void checkMulticast(InetAddress maddr, byte ttl) {
@@ -387,13 +367,12 @@
     /**
      * Checks whether the calling thread is allowed to access the specified
      * package.
-     * 
+     *
      * @param packageName
      *            the name of the package to access.
      * @throws SecurityException
      *             if the calling thread is not allowed to access {@code
      *             packageName}.
-     * @since Android 1.0
      */
     public void checkPackageAccess(String packageName) {
         if (packageName == null) {
@@ -408,13 +387,12 @@
     /**
      * Checks whether the calling thread is allowed to define new classes in the
      * specified package.
-     * 
+     *
      * @param packageName
      *            the name of the package to add a class to.
      * @throws SecurityException
      *             if the calling thread is not allowed to add classes to
      *             {@code packageName}.
-     * @since Android 1.0
      */
     public void checkPackageDefinition(String packageName) {
         if (packageName == null) {
@@ -459,11 +437,10 @@
     /**
      * Checks whether the calling thread is allowed to access the system
      * properties.
-     * 
+     *
      * @throws SecurityException
      *             if the calling thread is not allowed to access system
      *             properties.
-     * @since Android 1.0
      */
     public void checkPropertiesAccess() {
         checkPermission(READ_WRITE_ALL_PROPERTIES_PERMISSION);
@@ -472,13 +449,12 @@
     /**
      * Checks whether the calling thread is allowed to access a particular
      * system property.
-     * 
+     *
      * @param key
      *            the name of the property to access.
      * @throws SecurityException
      *             if the calling thread is not allowed to access the {@code
      *             key} system property.
-     * @since Android 1.0
      */
     public void checkPropertyAccess(String key) {
         checkPermission(new PropertyPermission(key, "read")); //$NON-NLS-1$
@@ -487,12 +463,11 @@
     /**
      * Checks whether the calling thread is allowed to read from the file with
      * the specified file descriptor.
-     * 
+     *
      * @param fd
      *            the file descriptor of the file to read from.
      * @throws SecurityException
      *             if the calling thread is not allowed to read from {@code fd}.
-     * @since Android 1.0
      */
     public void checkRead(FileDescriptor fd) {
         if (fd == null) {
@@ -504,13 +479,12 @@
     /**
      * Checks whether the calling thread is allowed to read from the file with
      * the specified name, which should be passed in canonical form.
-     * 
+     *
      * @param file
      *            the name of the file or directory to read from.
      * @throws SecurityException
      *             if the calling thread is not allowed to read from {@code
      *             file}.
-     * @since Android 1.0
      */
     public void checkRead(String file) {
         checkPermission(new FilePermission(file, "read")); //$NON-NLS-1$
@@ -519,14 +493,13 @@
     /**
      * Checks whether the given security context is allowed to read from the
      * file named by the argument, which should be passed in canonical form.
-     * 
+     *
      * @param file
      *            the name of the file or directory to check.
      * @param context
      *            the security context to use for the check.
      * @throws SecurityException
      *             if {@code context} is not allowed to read from {@code file}.
-     * @since Android 1.0
      */
     public void checkRead(String file, Object context) {
         checkPermission(new FilePermission(file, "read"), context); //$NON-NLS-1$
@@ -535,13 +508,12 @@
     /**
      * Checks whether the calling thread is allowed to perform the security
      * operation named by the target.
-     * 
+     *
      * @param target
      *            the name of the operation to perform.
      * @throws SecurityException
      *             if the calling thread is not allowed to perform
      *             {@code target}.
-     * @since Android 1.0
      */
     public void checkSecurityAccess(String target) {
         checkPermission(new SecurityPermission(target));
@@ -550,11 +522,10 @@
     /**
      * Checks whether the calling thread is allowed to set the net object
      * factories.
-     * 
+     *
      * @throws SecurityException
      *             if the calling thread is not allowed to set the net object
      *             factories.
-     * @since Android 1.0
      */
     public void checkSetFactory() {
         checkPermission(RuntimePermission.permissionToSetFactory);
@@ -563,14 +534,13 @@
     /**
      * Checks whether the calling thread is trusted to show the specified top
      * level window.
-     * 
+     *
      * @param window
      *            the window to show.
      * @return {@code true} if the calling thread is allowed to show {@code
      *         window}; {@code false} otherwise.
      * @throws NullPointerException
      *             if {@code window} is {@code null}.
-     * @since Android 1.0
      */
     public boolean checkTopLevelWindow(Object window) {
         if (window == null) {
@@ -597,11 +567,10 @@
     /**
      * Checks whether the calling thread is allowed to access the system
      * clipboard.
-     * 
+     *
      * @throws SecurityException
      *             if the calling thread is not allowed to access the system
      *             clipboard.
-     * @since Android 1.0
      */
     public void checkSystemClipboardAccess() {
         try {
@@ -623,11 +592,10 @@
     /**
      * Checks whether the calling thread is allowed to access the AWT event
      * queue.
-     * 
+     *
      * @throws SecurityException
      *             if the calling thread is not allowed to access the AWT event
      *             queue.
-     * @since Android 1.0
      */
     public void checkAwtEventQueueAccess() {
         try {
@@ -648,11 +616,10 @@
 
     /**
      * Checks whether the calling thread is allowed to start a new print job.
-     * 
+     *
      * @throws SecurityException
      *             if the calling thread is not allowed to start a new print
      *             job.
-     * @since Android 1.0
      */
     public void checkPrintJobAccess() {
         checkPermission(RuntimePermission.permissionToQueuePrintJob);
@@ -661,12 +628,11 @@
     /**
      * Checks whether the calling thread is allowed to write to the file with
      * the specified file descriptor.
-     * 
+     *
      * @param fd
      *            the file descriptor of the file to write to.
      * @throws SecurityException
      *             if the calling thread is not allowed to write to {@code fd}.
-     * @since Android 1.0
      */
     public void checkWrite(FileDescriptor fd) {
         if (fd == null) {
@@ -678,13 +644,12 @@
     /**
      * Checks whether the calling thread is allowed to write to the file with
      * the specified name, which should be passed in canonical form.
-     * 
+     *
      * @param file
      *            the name of the file or directory to write to.
      * @throws SecurityException
-     *             if the calling thread is not allowed to write to 
+     *             if the calling thread is not allowed to write to
      *             {@code file}.
-     * @since Android 1.0
      */
     public void checkWrite(String file) {
         checkPermission(new FilePermission(file, "write")); //$NON-NLS-1$
@@ -692,11 +657,10 @@
 
     /**
      * Indicates if this security manager is currently checking something.
-     * 
+     *
      * @return {@code true} if this security manager is executing a security
      *         check method; {@code false} otherwise.
      * @deprecated Use {@link #checkPermission}.
-     * @since Android 1.0
      */
     @Deprecated
     public boolean getInCheck() {
@@ -707,9 +671,8 @@
      * Returns an array containing one entry for each method in the current
      * execution stack. Each entry is the {@code java.lang.Class} which
      * represents the class in which the method is defined.
-     * 
+     *
      * @return all classes in the execution stack.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     protected Class[] getClassContext() {
@@ -719,10 +682,9 @@
     /**
      * Returns the class loader of the first class in the execution stack whose
      * class loader is not a system class loader.
-     * 
+     *
      * @return the most recent non-system class loader.
      * @deprecated Use {@link #checkPermission}.
-     * @since Android 1.0
      */
     @Deprecated
     protected ClassLoader currentClassLoader() {
@@ -755,11 +717,10 @@
     /**
      * Returns the index in the call stack of the first class whose class loader
      * is not a system class loader.
-     * 
+     *
      * @return the frame index of the first method whose class was loaded by a
      *         non-system class loader.
      * @deprecated Use {@link #checkPermission}.
-     * @since Android 1.0
      */
     @Deprecated
     protected int classLoaderDepth() {
@@ -791,10 +752,9 @@
     /**
      * Returns the first class in the call stack that was loaded by a class
      * loader which is not a system class loader.
-     * 
+     *
      * @return the most recent class loaded by a non-system class loader.
      * @deprecated Use {@link #checkPermission}.
-     * @since Android 1.0
      */
     @Deprecated
     protected Class<?> currentLoadedClass() {
@@ -827,13 +787,12 @@
      * Returns the index in the call stack of the first method which is
      * contained in the class with the specified name. Returns -1 if no methods
      * from this class are in the stack.
-     * 
+     *
      * @param name
      *            the name of the class to look for.
      * @return the frame index of the first method found is contained in the
      *         class identified by {@code name}.
      * @deprecated Use {@link #checkPermission}.
-     * @since Android 1.0
      */
     @Deprecated
     protected int classDepth(String name) {
@@ -849,13 +808,12 @@
     /**
      * Indicates whether there is a method in the call stack from the class with
      * the specified name.
-     * 
+     *
      * @param name
      *            the name of the class to look for.
      * @return {@code true} if a method from the class identified by {@code
      *         name} is executing; {@code false} otherwise.
      * @deprecated Use {@link #checkPermission}.
-     * @since Android 1.0
      */
     @Deprecated
     protected boolean inClass(String name) {
@@ -865,11 +823,10 @@
     /**
      * Indicates whether there is a method in the call stack from a class which
      * was defined by a non-system class loader.
-     * 
+     *
      * @return {@code true} if a method from a class that was defined by a
      *         non-system class loader is executing; {@code false} otherwise.
      * @deprecated Use {@link #checkPermission}
-     * @since Android 1.0
      */
     @Deprecated
     protected boolean inClassLoader() {
@@ -880,9 +837,8 @@
      * Returns the thread group which should be used to instantiate new threads.
      * By default, this is the same as the thread group of the thread running
      * this method.
-     * 
+     *
      * @return ThreadGroup the thread group to create new threads in.
-     * @since Android 1.0
      */
     public ThreadGroup getThreadGroup() {
         return Thread.currentThread().getThreadGroup();
@@ -890,12 +846,11 @@
 
     /**
      * Returns an object which encapsulates the security state of the current
-     * point in the execution. In the Android reference implementation, this is
-     * an {@link java.security.AccessControlContext}.
-     * 
+     * point in the execution. In our case, this is an {@link
+     * java.security.AccessControlContext}.
+     *
      * @return an object that encapsulates information about the current
      *         execution environment.
-     * @since Android 1.0
      */
     public Object getSecurityContext() {
         return AccessController.getContext();
@@ -904,13 +859,12 @@
     /**
      * Checks whether the calling thread is allowed to access the resource being
      * guarded by the specified permission object.
-     * 
+     *
      * @param permission
      *            the permission to check.
      * @throws SecurityException
      *             if the requested {@code permission} is denied according to
      *             the current security policy.
-     * @since Android 1.0
      */
     public void checkPermission(Permission permission) {
         try {
@@ -924,7 +878,7 @@
     /**
      * Checks whether the specified security context is allowed to access the
      * resource being guarded by the specified permission object.
-     * 
+     *
      * @param permission
      *            the permission to check.
      * @param context
@@ -934,7 +888,6 @@
      *             AccessControlContext} or if the requested {@code permission}
      *             is denied for {@code context} according to the current
      *             security policy.
-     * @since Android 1.0
      */
     public void checkPermission(Permission permission, Object context) {
         try {
diff --git a/libcore/luni/src/main/java/java/lang/Short.java b/libcore/luni/src/main/java/java/lang/Short.java
index cf95d22..9baf3a8 100644
--- a/libcore/luni/src/main/java/java/lang/Short.java
+++ b/libcore/luni/src/main/java/java/lang/Short.java
@@ -21,11 +21,11 @@
  * The wrapper for the primitive type {@code short}.
  * 
  * @see java.lang.Number
- * @since Android 1.0
+ * @since 1.1
  */
 public final class Short extends Number implements Comparable<Short> {
 
-    private static final long serialVersionUID = 7515723908773894738L;
+	private static final long serialVersionUID = 7515723908773894738L;
 
     /**
      * The value which the receiver represents.
@@ -34,69 +34,61 @@
 
     /**
      * Constant for the maximum {@code short} value, 2<sup>15</sup>-1.
-     * 
-     * @since Android 1.0
      */
     public static final short MAX_VALUE = (short) 0x7FFF;
 
     /**
      * Constant for the minimum {@code short} value, -2<sup>15</sup>.
-     * 
-     * @since Android 1.0
      */
     public static final short MIN_VALUE = (short) 0x8000;
 
     /**
      * Constant for the number of bits needed to represent a {@code short} in
      * two's complement form.
-     * 
-     * @since Android 1.0
+     *
+     * @since 1.5
      */
     public static final int SIZE = 16;
 
     /**
-     * The {@link Class} object that represents the primitive type {@code 
+     * The {@link Class} object that represents the primitive type {@code
      * short}.
-     * 
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static final Class<Short> TYPE = (Class<Short>) new short[0]
             .getClass().getComponentType();
 
-    // Note: This can't be set to "short.class", since *that* is
-    // defined to be "java.lang.Short.TYPE";
+	// Note: This can't be set to "short.class", since *that* is
+	// defined to be "java.lang.Short.TYPE";
 
     
     /**
      * Constructs a new {@code Short} from the specified string.
-     * 
+     *
      * @param string
      *            the string representation of a short value.
      * @throws NumberFormatException
      *             if {@code string} can not be decoded into a short value.
      * @see #parseShort(String)
-     * @since Android 1.0
      */
-    public Short(String string) throws NumberFormatException {
-        this(parseShort(string));
-    }
+	public Short(String string) throws NumberFormatException {
+		this(parseShort(string));
+	}
 
     /**
      * Constructs a new {@code Short} with the specified primitive short value.
-     * 
+     *
      * @param value
      *            the primitive short value to store in the new instance.
-     * @since Android 1.0
      */
-    public Short(short value) {
-        this.value = value;
-    }
+	public Short(short value) {
+		this.value = value;
+	}
 
-    @Override
+	@Override
     public byte byteValue() {
-        return (byte) value;
-    }
+		return (byte) value;
+	}
 
     /**
      * Compares this object to the specified short object to determine their
@@ -108,98 +100,97 @@
      *         value of {@code object}; 0 if the value of this short and the
      *         value of {@code object} are equal; a positive value if the value
      *         of this short is greater than the value of {@code object}.
+     * @throws NullPointerException
+     *             if {@code object} is null.
      * @see java.lang.Comparable
-     * @since Android 1.0
+     * @since 1.2
      */
-    public int compareTo(Short object) {
-        return value > object.value ? 1 : (value < object.value ? -1 : 0);
-    }
+	public int compareTo(Short object) {
+		return value > object.value ? 1 : (value < object.value ? -1 : 0);
+	}
 
     /**
      * Parses the specified string and returns a {@code Short} instance if the
      * string can be decoded into a short value. The string may be an optional
      * minus sign "-" followed by a hexadecimal ("0x..." or "#..."), octal
      * ("0..."), or decimal ("...") representation of a short.
-     * 
+     *
      * @param string
      *            a string representation of a short value.
      * @return a {@code Short} containing the value represented by
      *         {@code string}.
      * @throws NumberFormatException
      *             if {@code string} can not be parsed as a short value.
-     * @since Android 1.0
      */
-    public static Short decode(String string) throws NumberFormatException {
-        int intValue = Integer.decode(string).intValue();
-        short result = (short) intValue;
-        if (result == intValue) {
+	public static Short decode(String string) throws NumberFormatException {
+		int intValue = Integer.decode(string).intValue();
+		short result = (short) intValue;
+		if (result == intValue) {
             return valueOf(result);
         }
-        throw new NumberFormatException();
-    }
+		throw new NumberFormatException();
+	}
 
-    @Override
+	@Override
     public double doubleValue() {
-        return value;
-    }
+		return value;
+	}
 
     /**
      * Compares this instance with the specified object and indicates if they
      * are equal. In order to be equal, {@code object} must be an instance of
      * {@code Short} and have the same short value as this object.
-     * 
+     *
      * @param object
      *            the object to compare this short with.
      * @return {@code true} if the specified object is equal to this
      *         {@code Short}; {@code false} otherwise.
-     * @since Android 1.0
      */
-    @Override
+	@Override
     public boolean equals(Object object) {
-        return (object instanceof Short)
-                && (value == ((Short) object).value);
-    }
+		return (object instanceof Short)
+				&& (value == ((Short) object).value);
+	}
 
-    @Override
+	@Override
     public float floatValue() {
-        return value;
-    }
+		return value;
+	}
 
-    @Override
+	@Override
     public int hashCode() {
-        return value;
-    }
+		return value;
+	}
 
-    @Override
+	@Override
     public int intValue() {
-        return value;
-    }
+		return value;
+	}
 
-    @Override
+	@Override
     public long longValue() {
-        return value;
-    }
+		return value;
+	}
 
     /**
      * Parses the specified string as a signed decimal short value. The ASCII
      * character \u002d ('-') is recognized as the minus sign.
-     * 
+     *
      * @param string
      *            the string representation of a short value.
      * @return the primitive short value represented by {@code string}.
      * @throws NumberFormatException
      *             if {@code string} is {@code null}, has a length of zero or
      *             can not be parsed as a short value.
-     * @since Android 1.0
      */
-    public static short parseShort(String string) throws NumberFormatException {
-        return parseShort(string, 10);
-    }
+	public static short parseShort(String string) throws NumberFormatException {
+		return parseShort(string, 10);
+	}
 
     /**
      * Parses the specified string as a signed short value using the specified
      * radix. The ASCII character \u002d ('-') is recognized as the minus sign.
-     * 
+     *
      * @param string
      *            the string representation of a short value.
      * @param radix
@@ -211,50 +202,47 @@
      *             {@code radix < Character.MIN_RADIX},
      *             {@code radix > Character.MAX_RADIX}, or if {@code string}
      *             can not be parsed as a short value.
-     * @since Android 1.0
      */
-    public static short parseShort(String string, int radix)
-            throws NumberFormatException {
-        int intValue = Integer.parseInt(string, radix);
-        short result = (short) intValue;
-        if (result == intValue) {
+	public static short parseShort(String string, int radix)
+			throws NumberFormatException {
+		int intValue = Integer.parseInt(string, radix);
+		short result = (short) intValue;
+		if (result == intValue) {
             return result;
         }
-        throw new NumberFormatException();
-    }
+		throw new NumberFormatException();
+	}
 
     /**
      * Gets the primitive value of this short.
-     * 
+     *
      * @return this object's primitive value.
-     * @since Android 1.0
      */
     @Override
     public short shortValue() {
-        return value;
-    }
+		return value;
+	}
 
-    @Override
+	@Override
     public String toString() {
-        return Integer.toString(value);
-    }
+		return Integer.toString(value);
+	}
 
     /**
      * Returns a string containing a concise, human-readable description of the
      * specified short value with radix 10.
-     * 
+     *
      * @param value
      *             the short to convert to a string.
      * @return a printable representation of {@code value}.
-     * @since Android 1.0
      */
-    public static String toString(short value) {
-        return Integer.toString(value);
-    }
+	public static String toString(short value) {
+		return Integer.toString(value);
+	}
 
     /**
      * Parses the specified string as a signed decimal short value.
-     * 
+     *
      * @param string
      *            the string representation of a short value.
      * @return a {@code Short} instance containing the short value represented
@@ -263,16 +251,15 @@
      *             if {@code string} is {@code null}, has a length of zero or
      *             can not be parsed as a short value.
      * @see #parseShort(String)
-     * @since Android 1.0
      */
-    public static Short valueOf(String string) throws NumberFormatException {
-        return valueOf(parseShort(string));
-    }
+	public static Short valueOf(String string) throws NumberFormatException {
+		return valueOf(parseShort(string));
+	}
 
     /**
      * Parses the specified string as a signed short value using the specified
      * radix.
-     * 
+     *
      * @param string
      *            the string representation of a short value.
      * @param radix
@@ -285,12 +272,11 @@
      *             {@code radix > Character.MAX_RADIX}, or if {@code string}
      *             can not be parsed as a short value.
      * @see #parseShort(String, int)
-     * @since Android 1.0
      */
-    public static Short valueOf(String string, int radix)
-            throws NumberFormatException {
-        return valueOf(parseShort(string, radix));
-    }
+	public static Short valueOf(String string, int radix)
+			throws NumberFormatException {
+		return valueOf(parseShort(string, radix));
+	}
     
     /**
      * Reverses the bytes of the specified short.
@@ -298,7 +284,7 @@
      * @param s
      *            the short value for which to reverse bytes.
      * @return the reversed value.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static short reverseBytes(short s) {
         int high = (s >> 8) & 0xFF;
@@ -312,12 +298,11 @@
      * If it is not necessary to get a new {@code Short} instance, it is
      * recommended to use this method instead of the constructor, since it
      * maintains a cache of instances which may result in better performance.
-     * </p>
-     * 
+     *
      * @param s
      *            the short value to store in the instance.
      * @return a {@code Short} instance containing {@code s}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static Short valueOf(short s) {
         if (s < -128 || s > 127) {
@@ -328,9 +313,7 @@
 
     static class valueOfCache {
         /**
-         * <p>
          * A cache of instances used by {@link Short#valueOf(short)} and auto-boxing.
-         * </p>
          */
         private static final Short[] CACHE = new Short[256];
 
diff --git a/libcore/luni/src/main/java/java/lang/StackOverflowError.java b/libcore/luni/src/main/java/java/lang/StackOverflowError.java
index dd63b6b..3cbc0c7 100644
--- a/libcore/luni/src/main/java/java/lang/StackOverflowError.java
+++ b/libcore/luni/src/main/java/java/lang/StackOverflowError.java
@@ -22,8 +22,6 @@
  * platform or virtual machine specific limit. Typically, this will occur only
  * when a program becomes infinitely recursive, but it can also occur in
  * correctly written (but deeply recursive) programs.
- * 
- * @since Android 1.0
  */
 public class StackOverflowError extends java.lang.VirtualMachineError {
 
@@ -32,8 +30,6 @@
     /**
      * Constructs a new {@code StackOverflowError} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public StackOverflowError() {
         super();
@@ -45,7 +41,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public StackOverflowError(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/StrictMath.java b/libcore/luni/src/main/java/java/lang/StrictMath.java
index 66e4771..7a2da8e 100644
--- a/libcore/luni/src/main/java/java/lang/StrictMath.java
+++ b/libcore/luni/src/main/java/java/lang/StrictMath.java
@@ -37,25 +37,19 @@
  * Library" (fdlibm), version 5.3.
  * <p>
  * <a href="http://www.netlib.org/fdlibm/">http://www.netlib.org/fdlibm/</a>
- * 
- * @since Android 1.0
  */
 public final class StrictMath {
 
-    /**
+	/**
      * The double value closest to e, the base of the natural logarithm.
-     * 
-     * @since Android 1.0
-     */
-    public final static double E = Math.E;
+	 */
+	public final static double E = Math.E;
 
-    /**
+	/**
      * The double value closest to pi, the ratio of a circle's circumference to
      * its diameter.
-     * 
-     * @since Android 1.0
-     */
-    public final static double PI = Math.PI;
+	 */
+	public final static double PI = Math.PI;
 
     private static java.util.Random random;
 
@@ -65,7 +59,7 @@
     private StrictMath() {
     }
 
-    /**
+	/**
      * Returns the absolute value of the argument.
      * <p>
      * Special cases:
@@ -75,18 +69,16 @@
      * <li>{@code abs(-infinity) = +infinity}</li>
      * <li>{@code abs(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose absolute value has to be computed.
      * @return the absolute value of the argument.
-     * @since Android 1.0
      */
-    public static double abs(double d) {
-        long bits = Double.doubleToLongBits(d);
-        bits &= 0x7fffffffffffffffL;
-        return Double.longBitsToDouble(bits);
-    }
+	public static double abs(double d) {
+		long bits = Double.doubleToLongBits(d);
+		bits &= 0x7fffffffffffffffL;
+		return Double.longBitsToDouble(bits);
+	}
 
     /**
      * Returns the absolute value of the argument.
@@ -98,52 +90,47 @@
      * <li>{@code abs(-infinity) = +infinity}</li>
      * <li>{@code abs(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param f
      *            the value whose absolute value has to be computed.
      * @return the argument if it is positive, otherwise the negation of the
      *         argument.
-     * @since Android 1.0
      */
-    public static float abs(float f) {
-        int bits = Float.floatToIntBits(f);
-        bits &= 0x7fffffff;
-        return Float.intBitsToFloat(bits);
-    }
+	public static float abs(float f) {
+		int bits = Float.floatToIntBits(f);
+		bits &= 0x7fffffff;
+		return Float.intBitsToFloat(bits);
+	}
 
     /**
      * Returns the absolute value of the argument.
      * <p>
      * If the argument is {@code Integer.MIN_VALUE}, {@code Integer.MIN_VALUE}
      * is returned.
-     * 
+     *
      * @param i
      *            the value whose absolute value has to be computed.
      * @return the argument if it is positive, otherwise the negation of the
      *         argument.
-     * @since Android 1.0
      */
-    public static int abs(int i) {
-        return i >= 0 ? i : -i;
-    }
+	public static int abs(int i) {
+		return i >= 0 ? i : -i;
+	}
 
     /**
      * Returns the absolute value of the argument.
      * <p>
      * If the argument is {@code Long.MIN_VALUE}, {@code Long.MIN_VALUE} is
      * returned.
-     * </p>
-     * 
+     *
      * @param l
      *            the value whose absolute value has to be computed.
      * @return the argument if it is positive, otherwise the negation of the
      *         argument.
-     * @since Android 1.0
      */
-    public static long abs(long l) {
-        return l >= 0 ? l : -l;
-    }
+	public static long abs(long l) {
+		return l >= 0 ? l : -l;
+	}
 
     /**
      * Returns the closest double approximation of the arc cosine of the
@@ -155,14 +142,12 @@
      * <li>{@code acos((anything < -1) = NaN}</li>
      * <li>{@code acos(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value to compute arc cosine of.
      * @return the arc cosine of the argument.
-     * @since Android 1.0
      */
-    public static native double acos(double d);
+	public static native double acos(double d);
 
     /**
      * Returns the closest double approximation of the arc sine of the argument
@@ -174,14 +159,12 @@
      * <li>{@code asin((anything < -1)) = NaN}</li>
      * <li>{@code asin(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose arc sine has to be computed.
      * @return the arc sine of the argument.
-     * @since Android 1.0
      */
-    public static native double asin(double d);
+	public static native double asin(double d);
 
     /**
      * Returns the closest double approximation of the arc tangent of the
@@ -195,14 +178,12 @@
      * <li>{@code atan(-infinity) = -pi/2}</li>
      * <li>{@code atan(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose arc tangent has to be computed.
      * @return the arc tangent of the argument.
-     * @since Android 1.0
      */
-    public static native double atan(double d);
+	public static native double atan(double d);
 
     /**
      * Returns the closest double approximation of the arc tangent of
@@ -234,20 +215,15 @@
      * <li>{@code atan2(-infinity, (anything but,0, NaN, and infinity))}
      * {@code =} {@code -pi/2}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param y
      *            the numerator of the value whose atan has to be computed.
      * @param x
      *            the denominator of the value whose atan has to be computed.
      * @return the arc tangent of {@code y/x}.
-     * @since Android 1.0
      */
-    public static native double atan2(double y, double x);
-    // BEGIN android-note
-    // parameter names changed from d1 / d2 to x / y
-    // END android-note
-    
+	public static native double atan2(double y, double x);
+
     /**
      * Returns the closest double approximation of the cube root of the
      * argument.
@@ -260,12 +236,10 @@
      * <li>{@code cbrt(-infinity) = -infinity}</li>
      * <li>{@code cbrt(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose cube root has to be computed.
      * @return the cube root of the argument.
-     * @since Android 1.0
      */
     public static native double cbrt(double d);
 
@@ -282,15 +256,14 @@
      * <li>{@code ceil(-infinity) = -infinity}</li>
      * <li>{@code ceil(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose closest integer value has to be computed.
      * @return the ceiling of the argument.
-     * @since Android 1.0
      */
-    public static native double ceil(double d);
-    
+	public static native double ceil(double d);
+
+
     /**
      * Returns the closest double approximation of the hyperbolic cosine of the
      * argument.
@@ -301,12 +274,10 @@
      * <li>{@code cosh(-infinity) = +infinity}</li>
      * <li>{@code cosh(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose hyperbolic cosine has to be computed.
      * @return the hyperbolic cosine of the argument.
-     * @since Android 1.0
      */
     public static native double cosh(double d);
 
@@ -319,12 +290,10 @@
      * <li>{@code cos(-infinity) = NaN}</li>
      * <li>{@code cos(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the angle whose cosine has to be computed, in radians.
      * @return the cosine of the argument.
-     * @since Android 1.0
      */
     public static native double cos(double d);
 
@@ -338,15 +307,13 @@
      * <li>{@code exp(-infinity) = +0.0}</li>
      * <li>{@code exp(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose exponential has to be computed.
      * @return the exponential of the argument.
-     * @since Android 1.0
      */
     public static native double exp(double d);
-    
+
     /**
      * Returns the closest double approximation of <i>{@code e}</i><sup>
      * {@code d}</sup>{@code - 1}. If the argument is very close to 0, it is
@@ -361,14 +328,12 @@
      * <li>{@code expm1(-infinity) = -1.0}</li>
      * <li>{@code expm1(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value to compute the <i>{@code e}</i><sup>{@code d}</sup>
      *            {@code - 1} of.
      * @return the <i>{@code e}</i><sup>{@code d}</sup>{@code - 1} value
      *         of the argument.
-     * @since Android 1.0
      */
     public static native double expm1(double d);
 
@@ -384,14 +349,12 @@
      * <li>{@code floor(-infinity) = -infinity}</li>
      * <li>{@code floor(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d the value whose closest integer value has to be computed.
      * @return the floor of the argument.
-     * @since Android 1.0
      */
     public static native double floor(double d);
-    
+
     /**
      * Returns {@code sqrt(}<i>{@code x}</i><sup>{@code 2}</sup>{@code +}
      * <i> {@code y}</i><sup>{@code 2}</sup>{@code )}. The final result is
@@ -405,8 +368,7 @@
      * <li>{@code hypot((anything including NaN), -infinity) = +infinity}</li>
      * <li>{@code hypot(NaN, NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param x
      *            a double number.
      * @param y
@@ -414,7 +376,6 @@
      * @return the {@code sqrt(}<i>{@code x}</i><sup>{@code 2}</sup>{@code +}
      *         <i> {@code y}</i><sup>{@code 2}</sup>{@code )} value of the
      *         arguments.
-     * @since Android 1.0
      */
     public static native double hypot(double x, double y);
 
@@ -436,19 +397,14 @@
      * <li>{@code IEEEremainder(x, -infinity) = x } where x is anything but
      * +/-infinity</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param x
      *            the numerator of the operation.
      * @param y
      *            the denominator of the operation.
      * @return the IEEE754 floating point reminder of of {@code x/y}.
-     * @since Android 1.0
      */
-    public static native double IEEEremainder(double x, double y);
-    // BEGIN android-note
-    // parameter names changed from d1 / d2 to x / y
-    // END android-note
+	public static native double IEEEremainder(double x, double y);
 
     /**
      * Returns the closest double approximation of the natural logarithm of the
@@ -463,15 +419,13 @@
      * <li>{@code log(-infinity) = NaN}</li>
      * <li>{@code log(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose log has to be computed.
      * @return the natural logarithm of the argument.
-     * @since Android 1.0
      */
     public static native double log(double d);
-    
+
     /**
      * Returns the closest double approximation of the base 10 logarithm of the
      * argument.
@@ -485,15 +439,13 @@
      * <li>{@code log10(-infinity) = NaN}</li>
      * <li>{@code log10(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose base 10 log has to be computed.
      * @return the natural logarithm of the argument.
-     * @since Android 1.0
      */
     public static native double log10(double d);
-    
+
     /**
      * Returns the closest double approximation of the natural logarithm of the
      * sum of the argument and 1. If the argument is very close to 0, it is much
@@ -510,12 +462,10 @@
      * <li>{@code log1p(-infinity) = NaN}</li>
      * <li>{@code log1p(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value to compute the {@code ln(1+d)} of.
      * @return the natural logarithm of the sum of the argument and 1.
-     * @since Android 1.0
      */
     public static native double log1p(double d);
 
@@ -530,29 +480,27 @@
      * <li>{@code max(+0.0, -0.0) = +0.0}</li>
      * <li>{@code max(-0.0, +0.0) = +0.0}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d1
      *            the first argument.
      * @param d2
      *            the second argument.
      * @return the larger of {@code d1} and {@code d2}.
-     * @since Android 1.0
      */
-    public static double max(double d1, double d2) {
-        if (d1 > d2)
-            return d1;
-        if (d1 < d2)
-            return d2;
-        /* if either arg is NaN, return NaN */
-        if (d1 != d2)
-            return Double.NaN;
-        /* max( +0.0,-0.0) == +0.0 */
-        if (d1 == 0.0
-                && ((Double.doubleToLongBits(d1) & Double.doubleToLongBits(d2)) & 0x8000000000000000L) == 0)
-            return 0.0;
-        return d1;
-    }
+	public static double max(double d1, double d2) {
+		if (d1 > d2)
+			return d1;
+		if (d1 < d2)
+			return d2;
+		/* if either arg is NaN, return NaN */
+		if (d1 != d2)
+			return Double.NaN;
+		/* max( +0.0,-0.0) == +0.0 */
+		if (d1 == 0.0
+				&& ((Double.doubleToLongBits(d1) & Double.doubleToLongBits(d2)) & 0x8000000000000000L) == 0)
+			return 0.0;
+		return d1;
+	}
 
     /**
      * Returns the most positive (closest to positive infinity) of the two
@@ -565,59 +513,55 @@
      * <li>{@code max(+0.0, -0.0) = +0.0}</li>
      * <li>{@code max(-0.0, +0.0) = +0.0}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param f1
      *            the first argument.
      * @param f2
      *            the second argument.
      * @return the larger of {@code f1} and {@code f2}.
-     * @since Android 1.0
      */
-    public static float max(float f1, float f2) {
-        if (f1 > f2)
-            return f1;
-        if (f1 < f2)
-            return f2;
-        /* if either arg is NaN, return NaN */
-        if (f1 != f2)
-            return Float.NaN;
-        /* max( +0.0,-0.0) == +0.0 */
-        if (f1 == 0.0f
-                && ((Float.floatToIntBits(f1) & Float.floatToIntBits(f2)) & 0x80000000) == 0)
-            return 0.0f;
-        return f1;
-    }
+	public static float max(float f1, float f2) {
+		if (f1 > f2)
+			return f1;
+		if (f1 < f2)
+			return f2;
+		/* if either arg is NaN, return NaN */
+		if (f1 != f2)
+			return Float.NaN;
+		/* max( +0.0,-0.0) == +0.0 */
+		if (f1 == 0.0f
+				&& ((Float.floatToIntBits(f1) & Float.floatToIntBits(f2)) & 0x80000000) == 0)
+			return 0.0f;
+		return f1;
+	}
 
     /**
      * Returns the most positive (closest to positive infinity) of the two
      * arguments.
-     * 
+     *
      * @param i1
      *            the first argument.
      * @param i2
      *            the second argument.
      * @return the larger of {@code i1} and {@code i2}.
-     * @since Android 1.0
      */
-    public static int max(int i1, int i2) {
-        return i1 > i2 ? i1 : i2;
-    }
+	public static int max(int i1, int i2) {
+		return i1 > i2 ? i1 : i2;
+	}
 
     /**
      * Returns the most positive (closest to positive infinity) of the two
      * arguments.
-     * 
+     *
      * @param l1
      *            the first argument.
      * @param l2
      *            the second argument.
      * @return the larger of {@code l1} and {@code l2}.
-     * @since Android 1.0
      */
-    public static long max(long l1, long l2) {
-        return l1 > l2 ? l1 : l2;
-    }
+	public static long max(long l1, long l2) {
+		return l1 > l2 ? l1 : l2;
+	}
 
     /**
      * Returns the most negative (closest to negative infinity) of the two
@@ -630,29 +574,27 @@
      * <li>{@code min(+0.0, -0.0) = -0.0}</li>
      * <li>{@code min(-0.0, +0.0) = -0.0}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d1
      *            the first argument.
      * @param d2
      *            the second argument.
      * @return the smaller of {@code d1} and {@code d2}.
-     * @since Android 1.0
      */
-    public static double min(double d1, double d2) {
-        if (d1 > d2)
-            return d2;
-        if (d1 < d2)
-            return d1;
-        /* if either arg is NaN, return NaN */
-        if (d1 != d2)
-            return Double.NaN;
-        /* min( +0.0,-0.0) == -0.0 */
-        if (d1 == 0.0
-                && ((Double.doubleToLongBits(d1) | Double.doubleToLongBits(d2)) & 0x8000000000000000l) != 0)
-            return 0.0 * (-1.0);
-        return d1;
-    }
+	public static double min(double d1, double d2) {
+		if (d1 > d2)
+			return d2;
+		if (d1 < d2)
+			return d1;
+		/* if either arg is NaN, return NaN */
+		if (d1 != d2)
+			return Double.NaN;
+		/* min( +0.0,-0.0) == -0.0 */
+		if (d1 == 0.0
+				&& ((Double.doubleToLongBits(d1) | Double.doubleToLongBits(d2)) & 0x8000000000000000l) != 0)
+			return 0.0 * (-1.0);
+		return d1;
+	}
 
     /**
      * Returns the most negative (closest to negative infinity) of the two
@@ -665,59 +607,55 @@
      * <li>{@code min(+0.0, -0.0) = -0.0}</li>
      * <li>{@code min(-0.0, +0.0) = -0.0}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param f1
      *            the first argument.
      * @param f2
      *            the second argument.
      * @return the smaller of {@code f1} and {@code f2}.
-     * @since Android 1.0
      */
-    public static float min(float f1, float f2) {
-        if (f1 > f2)
-            return f2;
-        if (f1 < f2)
-            return f1;
-        /* if either arg is NaN, return NaN */
-        if (f1 != f2)
-            return Float.NaN;
-        /* min( +0.0,-0.0) == -0.0 */
-        if (f1 == 0.0f
-                && ((Float.floatToIntBits(f1) | Float.floatToIntBits(f2)) & 0x80000000) != 0)
-            return 0.0f * (-1.0f);
-        return f1;
-    }
+	public static float min(float f1, float f2) {
+		if (f1 > f2)
+			return f2;
+		if (f1 < f2)
+			return f1;
+		/* if either arg is NaN, return NaN */
+		if (f1 != f2)
+			return Float.NaN;
+		/* min( +0.0,-0.0) == -0.0 */
+		if (f1 == 0.0f
+				&& ((Float.floatToIntBits(f1) | Float.floatToIntBits(f2)) & 0x80000000) != 0)
+			return 0.0f * (-1.0f);
+		return f1;
+	}
 
     /**
      * Returns the most negative (closest to negative infinity) of the two
      * arguments.
-     * 
+     *
      * @param i1
      *            the first argument.
      * @param i2
      *            the second argument.
      * @return the smaller of {@code i1} and {@code i2}.
-     * @since Android 1.0
      */
-    public static int min(int i1, int i2) {
-        return i1 < i2 ? i1 : i2;
-    }
+	public static int min(int i1, int i2) {
+		return i1 < i2 ? i1 : i2;
+	}
 
     /**
      * Returns the most negative (closest to negative infinity) of the two
      * arguments.
-     * 
+     *
      * @param l1
      *            the first argument.
      * @param l2
      *            the second argument.
      * @return the smaller of {@code l1} and {@code l2}.
-     * @since Android 1.0
      */
-    public static long min(long l1, long l2) {
-        return l1 < l2 ? l1 : l2;
-    }
+	public static long min(long l1, long l2) {
+		return l1 < l2 ? l1 : l2;
+	}
 
     /**
      * Returns the closest double approximation of the result of raising
@@ -750,26 +688,20 @@
      * <li>{@code pow((-anything except 0 and infinity), (non-integer))}
      * {@code =} {@code NAN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param x
      *            the base of the operation.
      * @param y
      *            the exponent of the operation.
      * @return {@code x} to the power of {@code y}.
-     * @since Android 1.0
      */
-    public static native double pow(double x, double y);
-    // BEGIN android-note
-    // parameter names changed from d1 / d2 to x / y
-    // END android-note
+	public static native double pow(double x, double y);
 
     /**
      * Returns a pseudo-random number between 0.0 (inclusive) and 1.0
      * (exclusive).
-     * 
+     *
      * @return a pseudo-random number.
-     * @since Android 1.0
      */
     public static double random() {
         // BEGIN android-changed
@@ -777,8 +709,8 @@
             random = new java.util.Random();
         }
         // END android-changed
-        return random.nextDouble();
-    }
+		return random.nextDouble();
+	}
 
     /**
      * Returns the double conversion of the result of rounding the argument to
@@ -792,12 +724,10 @@
      * <li>{@code rint(-infinity) = -infinity}</li>
      * <li>{@code rint(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value to be rounded.
      * @return the closest integer to the argument (as a double).
-     * @since Android 1.0
      */
     public static native double rint(double d);
 
@@ -815,19 +745,17 @@
      * <li>{@code round(-infinity) = Long.MIN_VALUE}</li>
      * <li>{@code round(NaN) = +0.0}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value to be rounded.
      * @return the closest integer to the argument.
-     * @since Android 1.0
      */
-    public static long round(double d) {
-        // check for NaN
-        if (d != d)
-            return 0L;
-        return (long) Math.floor(d + 0.5d);
-    }
+	public static long round(double d) {
+		// check for NaN
+		if (d != d)
+			return 0L;
+		return (long) Math.floor(d + 0.5d);
+	}
 
     /**
      * Returns the result of rounding the argument to an integer. The result is
@@ -843,19 +771,17 @@
      * <li>{@code round(-infinity) = Integer.MIN_VALUE}</li>
      * <li>{@code round(NaN) = +0.0}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param f
      *            the value to be rounded.
      * @return the closest integer to the argument.
-     * @since Android 1.0
      */
-    public static int round(float f) {
-        // check for NaN
-        if (f != f)
-            return 0;
-        return (int) Math.floor(f + 0.5f);
-    }
+	public static int round(float f) {
+		// check for NaN
+		if (f != f)
+			return 0;
+		return (int) Math.floor(f + 0.5f);
+	}
 
     /**
      * Returns the signum function of the argument. If the argument is less than
@@ -871,12 +797,10 @@
      * <li>{@code signum(-infinity) = -1.0}</li>
      * <li>{@code signum(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose signum has to be computed.
      * @return the value of the signum function.
-     * @since Android 1.0
      */
     public static double signum(double d){
         if(Double.isNaN(d)){
@@ -905,12 +829,10 @@
      * <li>{@code signum(-infinity) = -1.0}</li>
      * <li>{@code signum(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param f
      *            the value whose signum has to be computed.
      * @return the value of the signum function.
-     * @since Android 1.0
      */
     public static float signum(float f){
         if(Float.isNaN(f)){
@@ -937,15 +859,13 @@
      * <li>{@code sinh(-infinity) = -infinity}</li>
      * <li>{@code sinh(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose hyperbolic sine has to be computed.
      * @return the hyperbolic sine of the argument.
-     * @since Android 1.0
      */
     public static native double sinh(double d);
-    
+
     /**
      * Returns the closest double approximation of the sine of the argument.
      * <p>
@@ -957,12 +877,10 @@
      * <li>{@code sin(-infinity) = NaN}</li>
      * <li>{@code sin(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the angle whose sin has to be computed, in radians.
      * @return the sine of the argument.
-     * @since Android 1.0
      */
     public static native double sin(double d);
 
@@ -978,12 +896,10 @@
      * <li>{@code sqrt(+infinity) = +infinity}</li>
      * <li>{@code sqrt(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose square root has to be computed.
      * @return the square root of the argument.
-     * @since Android 1.0
      */
     public static native double sqrt(double d);
 
@@ -998,12 +914,10 @@
      * <li>{@code tan(-infinity) = NaN}</li>
      * <li>{@code tan(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the angle whose tangens has to be computed, in radians.
      * @return the tangent of the argument.
-     * @since Android 1.0
      */
     public static native double tan(double d);
 
@@ -1019,15 +933,13 @@
      * <li>{@code tanh(-infinity) = -1.0}</li>
      * <li>{@code tanh(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the value whose hyperbolic tangent has to be computed.
      * @return the hyperbolic tangent of the argument
-     * @since Android 1.0
      */
     public static native double tanh(double d);
-    
+
     /**
      * Returns the measure in degrees of the supplied radian angle. The result
      * is {@code angrad * 180 / pi}.
@@ -1040,16 +952,14 @@
      * <li>{@code toDegrees(-infinity) = -infinity}</li>
      * <li>{@code toDegrees(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param angrad
      *            an angle in radians.
      * @return the degree measure of the angle.
-     * @since Android 1.0
      */
-    public static double toDegrees(double angrad) {
-        return angrad * 180d / PI;
-    }
+	public static double toDegrees(double angrad) {
+		return angrad * 180d / PI;
+	}
 
     /**
      * Returns the measure in radians of the supplied degree angle. The result
@@ -1063,18 +973,16 @@
      * <li>{@code toRadians(-infinity) = -infinity}</li>
      * <li>{@code toRadians(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param angdeg
      *            an angle in degrees.
      * @return the radian measure of the angle.
-     * @since Android 1.0
      */
-    public static double toRadians(double angdeg) {
-        return angdeg / 180d * PI;
-    }
-    
-    /**
+	public static double toRadians(double angdeg) {
+		return angdeg / 180d * PI;
+	}
+
+	/**
      * Returns the argument's ulp (unit in the last place). The size of a ulp of
      * a double value is the positive distance between this value and the double
      * value next larger in magnitude. For non-NaN {@code x},
@@ -1088,12 +996,10 @@
      * <li>{@code ulp(-infintiy) = infinity}</li>
      * <li>{@code ulp(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param d
      *            the floating-point value to compute ulp of.
      * @return the size of a ulp of the argument.
-     * @since Android 1.0
      */
     public static double ulp(double d) {
         // special cases
@@ -1120,12 +1026,10 @@
      * <li>{@code ulp(-infintiy) = infinity}</li>
      * <li>{@code ulp(NaN) = NaN}</li>
      * </ul>
-     * </p>
-     * 
+     *
      * @param f
      *            the floating-point value to compute ulp of.
      * @return the size of a ulp of the argument.
-     * @since Android 1.0
      */
     public static float ulp(float f) {
         // special cases
diff --git a/libcore/luni/src/main/java/java/lang/String.java b/libcore/luni/src/main/java/java/lang/String.java
index b257a36..6d53357 100644
--- a/libcore/luni/src/main/java/java/lang/String.java
+++ b/libcore/luni/src/main/java/java/lang/String.java
@@ -21,9 +21,6 @@
 import java.io.UnsupportedEncodingException;
 import java.util.Comparator;
 import java.util.Formatter;
-// BEGIN android-added
-import java.util.IllegalFormatException;
-// END android-added
 import java.util.Locale;
 
 import java.util.regex.Pattern;
@@ -50,7 +47,7 @@
  * @see StringBuffer
  * @see StringBuilder
  * @see Charset
- * @since Android 1.0
+ * @since 1.0
  */
 public final class String implements Serializable, Comparable<String>,
         CharSequence {
@@ -138,8 +135,6 @@
 
     /**
      * A comparator ignoring the case of the characters.
-     * 
-     * @since Android 1.0
      */
     public static final Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator();
 
@@ -166,8 +161,6 @@
 
     /**
      * Creates an empty string.
-     * 
-     * @since Android 1.0
      */
     public String() {
         value = new char[0];
@@ -175,6 +168,9 @@
         count = 0;
     }
 
+    /*
+     * Private constructor used for JIT optimization.
+     */
     @SuppressWarnings("unused")
     private String(String s, char c) {
         offset = 0;
@@ -192,7 +188,6 @@
      * 
      * @param data
      *            the byte array to convert to a string.
-     * @since Android 1.0
      */
     public String(byte[] data) {
         this(data, 0, data.length);
@@ -206,9 +201,10 @@
      *            the byte array to convert to a string.
      * @param high
      *            the high byte to use.
+     * @throws NullPointerException
+     *             when {@code data} is {@code null}.
      * @deprecated Use {@link #String(byte[])} or
      *             {@link #String(byte[], String)} instead.
-     * @since Android 1.0
      */
     @Deprecated
     public String(byte[] data, int high) {
@@ -227,10 +223,11 @@
      *            the starting offset in the byte array.
      * @param length
      *            the number of bytes to convert.
+     * @throws NullPointerException
+     *             when {@code data} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code length < 0, start < 0} or {@code start + length >
      *             data.length}.
-     * @since Android 1.0
      */
     public String(byte[] data, int start, int length) {
         // start + length could overflow, start/length maybe MaxInt
@@ -264,13 +261,13 @@
      *            the starting offset in the byte array.
      * @param length
      *            the number of bytes to convert.
-     *
+     * @throws NullPointerException
+     *             when {@code data} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code length < 0, start < 0} or
      *             {@code start + length > data.length}
      *
      * @deprecated Use {@link #String(byte[], int, int)} instead.
-     * @since Android 1.0
      */
     @Deprecated
     public String(byte[] data, int high, int start, int length) {
@@ -303,12 +300,13 @@
      *            the number of bytes to convert.
      * @param encoding
      *            the encoding.
+     * @throws NullPointerException
+     *             when {@code data} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code length < 0, start < 0} or {@code start + length >
      *             data.length}.
      * @throws UnsupportedEncodingException
      *             if {@code encoding} is not supported.
-     * @since Android 1.0
      */
     public String(byte[] data, int start, int length, final String encoding)
             throws UnsupportedEncodingException {
@@ -444,7 +442,7 @@
             try {
                 cb = charset.decode(ByteBuffer.wrap(data, start, length));
             } catch (Exception e) {
-                // do nothing. according to spec: 
+                // do nothing. according to spec:
                 // behavior is unspecified for invalid array
                 cb = CharBuffer.wrap("\u003f".toCharArray()); //$NON-NLS-1$
             }
@@ -467,9 +465,10 @@
      *            the byte array to convert to a string.
      * @param encoding
      *            the encoding.
+     * @throws NullPointerException
+     *             when {@code data} is {@code null}.
      * @throws UnsupportedEncodingException
      *             if {@code encoding} is not supported.
-     * @since Android 1.0
      */
     public String(byte[] data, String encoding) throws UnsupportedEncodingException {
         this(data, 0, data.length, encoding);
@@ -482,7 +481,8 @@
      * 
      * @param data
      *            the array of characters.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             when {@code data} is {@code null}.
      */
     public String(char[] data) {
         this(data, 0, data.length);
@@ -499,10 +499,11 @@
      *            the starting offset in the character array.
      * @param length
      *            the number of characters to use.
+     * @throws NullPointerException
+     *             when {@code data} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code length < 0, start < 0} or {@code start + length >
      *             data.length}
-     * @since Android 1.0
      */
     public String(char[] data, int start, int length) {
         // range check everything so a new char[] is not created
@@ -532,7 +533,6 @@
      * 
      * @param string
      *            the string to copy.
-     * @since Android 1.0
      */
     public String(String string) {
         value = string.value;
@@ -540,13 +540,53 @@
         count = string.count;
     }
 
+    /*
+     * Private constructor useful for JIT optimization.
+     */
+    @SuppressWarnings( { "unused", "nls" })
+    private String(String s1, String s2) {
+        if (s1 == null) {
+            s1 = "null";
+        }
+        if (s2 == null) {
+            s2 = "null";
+        }
+        count = s1.count + s2.count;
+        value = new char[count];
+        offset = 0;
+        System.arraycopy(s1.value, s1.offset, value, 0, s1.count);
+        System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count);
+    }
+
+    /*
+     * Private constructor useful for JIT optimization.
+     */
+    @SuppressWarnings( { "unused", "nls" })
+    private String(String s1, String s2, String s3) {
+        if (s1 == null) {
+            s1 = "null";
+        }
+        if (s2 == null) {
+            s2 = "null";
+        }
+        if (s3 == null) {
+            s3 = "null";
+        }
+        count = s1.count + s2.count + s3.count;
+        value = new char[count];
+        offset = 0;
+        System.arraycopy(s1.value, s1.offset, value, 0, s1.count);
+        System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count);
+        System.arraycopy(s3.value, s3.offset, value, s1.count + s2.count,
+                s3.count);
+    }
+
     /**
      * Creates a {@code String} from the contents of the specified
      * {@code StringBuffer}.
      * 
      * @param stringbuffer
      *            the buffer to get the contents from.
-     * @since Android 1.0
      */
     public String(StringBuffer stringbuffer) {
         offset = 0;
@@ -558,7 +598,7 @@
 
     /**
      * Creates a {@code String} from the sub-array of Unicode code points.
-     * 
+     *
      * @param codePoints
      *            the array of Unicode code points to convert.
      * @param offset
@@ -566,13 +606,15 @@
      *            converting from.
      * @param count
      *            the number of elements in {@code codePoints} to copy.
+     * @throws NullPointerException
+     *             if {@code codePoints} is {@code null}.
      * @throws IllegalArgumentException
      *             if any of the elements of {@code codePoints} are not valid
      *             Unicode code points.
      * @throws IndexOutOfBoundsException
      *             if {@code offset} or {@code count} are not within the bounds
      *             of {@code codePoints}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public String(int[] codePoints, int offset, int count) {
         super();
@@ -599,7 +641,9 @@
      * 
      * @param sb
      *            the {@code StringBuilder} to copy the contents from.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code sb} is {@code null}.
+     * @since 1.5
      */
     public String(StringBuilder sb) {
         if (sb == null) {
@@ -636,7 +680,6 @@
      * @return the character at the index.
      * @throws IndexOutOfBoundsException
      *             if {@code index < 0} or {@code index >= length()}.
-     * @since Android 1.0
      */
     public char charAt(int index) {
         if (0 <= index && index < count) {
@@ -645,6 +688,39 @@
         throw new StringIndexOutOfBoundsException();
     }
 
+    // Optimized for ASCII
+    private char compareValue(char ch) {
+        if (ch < 128) {
+            if ('A' <= ch && ch <= 'Z') {
+                return (char) (ch + ('a' - 'A'));
+            }
+            return ch;
+        }
+        return Character.toLowerCase(Character.toUpperCase(ch));
+    }
+
+    // Optimized for ASCII
+    private char toLowerCase(char ch) {
+        if (ch < 128) {
+            if ('A' <= ch && ch <= 'Z') {
+                return (char) (ch + ('a' - 'A'));
+            }
+            return ch;
+        }
+        return Character.toLowerCase(ch);
+    }
+
+    // Optimized for ASCII
+    private char toUpperCase(char ch) {
+        if (ch < 128) {
+            if ('a' <= ch && ch <= 'z') {
+                return (char) (ch - ('a' - 'A'));
+            }
+            return ch;
+        }
+        return Character.toUpperCase(ch);
+    }
+
     /**
      * Compares the specified string to this string using the Unicode values of
      * the characters. Returns 0 if the strings contain the same characters in
@@ -662,7 +738,8 @@
      * @return 0 if the strings are equal, a negative integer if this string is
      *         before the specified string, or a positive integer if this string
      *         is after the specified string.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code string} is {@code null}.
      */
     public int compareTo(String string) {
         // Code adapted from K&R, pg 101
@@ -694,7 +771,8 @@
      * @return 0 if the strings are equal, a negative integer if this string is
      *         before the specified string, or a positive integer if this string
      *         is after the specified string.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code string} is {@code null}.
      */
     public int compareToIgnoreCase(String string) {
         int o1 = offset, o2 = string.offset, result;
@@ -705,8 +783,8 @@
             if ((c1 = value[o1++]) == (c2 = target[o2++])) {
                 continue;
             }
-            c1 = Character.toLowerCase(Character.toUpperCase(c1));
-            c2 = Character.toLowerCase(Character.toUpperCase(c2));
+            c1 = compareValue(c1);
+            c2 = compareValue(c2);
             if ((result = c1 - c2) != 0) {
                 return result;
             }
@@ -721,7 +799,6 @@
      *            the string to concatenate
      * @return a new string which is the concatenation of this string and the
      *         specified string.
-     * @since Android 1.0
      */
     public String concat(String string) {
         if (string.count > 0 && count > 0) {
@@ -742,7 +819,8 @@
      * @param data
      *            the array of characters.
      * @return the new string.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code data} is {@code null}.
      */
     public static String copyValueOf(char[] data) {
         return new String(data, 0, data.length);
@@ -760,10 +838,11 @@
      * @param length
      *            the number of characters to use.
      * @return the new string.
+     * @throws NullPointerException
+     *             if {@code data} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code length < 0, start < 0} or {@code start + length >
      *             data.length}.
-     * @since Android 1.0
      */
     public static String copyValueOf(char[] data, int start, int length) {
         return new String(data, start, length);
@@ -799,7 +878,8 @@
      *            the suffix to look for.
      * @return {@code true} if the specified string is a suffix of this string,
      *         {@code false} otherwise.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code suffix} is {@code null}.
      */
     public boolean endsWith(String suffix) {
         return regionMatches(count - suffix.count, suffix, 0, suffix.count);
@@ -815,7 +895,6 @@
      * @return {@code true} if the specified object is equal to this string,
      *         {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -855,7 +934,6 @@
      *            the string to compare.
      * @return {@code true} if the specified string is equal to this string,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean equalsIgnoreCase(String string) {
         if (string == this) {
@@ -871,9 +949,9 @@
         char[] target = string.value;
         while (o1 < end) {
             if ((c1 = value[o1++]) != (c2 = target[o2++])
-                    && Character.toUpperCase(c1) != Character.toUpperCase(c2)
+                    && toUpperCase(c1) != toUpperCase(c2)
                     // Required for unicode that we test both cases
-                    && Character.toLowerCase(c1) != Character.toLowerCase(c2)) {
+                    && toLowerCase(c1) != toLowerCase(c2)) {
                 return false;
             }
         }
@@ -887,7 +965,6 @@
      * is not available, an ASCII encoding is used.
      * 
      * @return the byte array encoding of this string.
-     * @since Android 1.0
      */
     public byte[] getBytes() {
         ByteBuffer buffer = defaultCharset().encode(
@@ -909,11 +986,12 @@
      *            the destination byte array.
      * @param index
      *            the starting offset in the destination byte array.
+     * @throws NullPointerException
+     *             if {@code data} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code start < 0}, {@code end > length()}, {@code index <
      *             0} or {@code end - start > data.length - index}.
      * @deprecated Use {@link #getBytes()} or {@link #getBytes(String)}
-     * @since Android 1.0
      */
     @Deprecated
     public void getBytes(int start, int end, byte[] data, int index) {
@@ -939,7 +1017,6 @@
      * @return the encoded byte array of this string.
      * @throws UnsupportedEncodingException
      *             if the encoding is not supported.
-     * @since Android 1.0
      */
     public byte[] getBytes(String encoding) throws UnsupportedEncodingException {
         ByteBuffer buffer = getCharset(encoding).encode(
@@ -979,11 +1056,12 @@
      *            the destination character array.
      * @param index
      *            the starting offset in the character array.
+     * @throws NullPointerException
+     *             if {@code buffer} is {@code null}.
      * @throws IndexOutOfBoundsException
      *             if {@code start < 0}, {@code end > length()}, {@code start >
      *             end}, {@code index < 0}, {@code end - start > buffer.length -
      *             index}
-     * @since Android 1.0
      */
     public void getChars(int start, int end, char[] buffer, int index) {
         // NOTE last character not copied!
@@ -1036,7 +1114,6 @@
      *            the character to find.
      * @return the index in this string of the specified character, -1 if the
      *         character isn't found.
-     * @since Android 1.0
      */
     public int indexOf(int c) {
         // BEGIN android-changed
@@ -1066,7 +1143,6 @@
      *            the starting offset.
      * @return the index in this string of the specified character, -1 if the
      *         character isn't found.
-     * @since Android 1.0
      */
     public int indexOf(int c, int start) {
         // BEGIN android-changed
@@ -1097,7 +1173,8 @@
      *            the string to find.
      * @return the index of the first character of the specified string in this
      *         string, -1 if the specified string is not a substring.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code string} is {@code null}.
      */
     public int indexOf(String string) {
         // BEGIN android-changed
@@ -1143,7 +1220,8 @@
      *            the starting offset.
      * @return the index of the first character of the specified string in this
      *         string, -1 if the specified string is not a substring.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code subString} is {@code null}.
      */
     public int indexOf(String subString, int start) {
         // BEGIN android-changed
@@ -1187,11 +1265,9 @@
      * object is always returned for strings which are equal.
      * 
      * @return the interned string equal to this string.
-     * @since Android 1.0
      */
     native public String intern();
 
-
     /**
      * Searches in this string for the last index of the specified character.
      * The search for the character starts at the end and moves towards the
@@ -1201,7 +1277,6 @@
      *            the character to find.
      * @return the index in this string of the specified character, -1 if the
      *         character isn't found.
-     * @since Android 1.0
      */
     public int lastIndexOf(int c) {
         // BEGIN android-changed
@@ -1228,7 +1303,6 @@
      *            the starting offset.
      * @return the index in this string of the specified character, -1 if the
      *         character isn't found.
-     * @since Android 1.0
      */
     public int lastIndexOf(int c, int start) {
         // BEGIN android-changed
@@ -1258,7 +1332,8 @@
      *            the string to find.
      * @return the index of the first character of the specified string in this
      *         string, -1 if the specified string is not a substring.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code string} is {@code null}.
      */
     public int lastIndexOf(String string) {
         // Use count instead of count - 1 so lastIndexOf("") returns count
@@ -1276,7 +1351,8 @@
      *            the starting offset.
      * @return the index of the first character of the specified string in this
      *         string , -1 if the specified string is not a substring.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code subString} is {@code null}.
      */
     public int lastIndexOf(String subString, int start) {
         int subCount = subString.count;
@@ -1314,7 +1390,6 @@
      * Returns the size of this string.
      * 
      * @return the number of characters in this string.
-     * @since Android 1.0
      */
     public int length() {
         return count;
@@ -1334,7 +1409,8 @@
      *            the number of characters to compare.
      * @return {@code true} if the ranges of characters are equal, {@code false}
      *         otherwise
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code string} is {@code null}.
      */
     public boolean regionMatches(int thisStart, String string, int start,
             int length) {
@@ -1380,7 +1456,8 @@
      *            the number of characters to compare.
      * @return {@code true} if the ranges of characters are equal, {@code false}
      *         otherwise.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code string} is {@code null}.
      */
     public boolean regionMatches(boolean ignoreCase, int thisStart,
             String string, int start, int length) {
@@ -1403,11 +1480,9 @@
             char[] target = string.value;
             while (thisStart < end) {
                 if ((c1 = value[thisStart++]) != (c2 = target[start++])
-                        && Character.toUpperCase(c1) != Character
-                                .toUpperCase(c2)
+                        && toUpperCase(c1) != toUpperCase(c2)
                         // Required for unicode that we test both cases
-                        && Character.toLowerCase(c1) != Character
-                                .toLowerCase(c2)) {
+                        && toLowerCase(c1) != toLowerCase(c2)) {
                     return false;
                 }
             }
@@ -1425,7 +1500,6 @@
      * @param newChar
      *            the replacement character.
      * @return a new string with occurrences of oldChar replaced by newChar.
-     * @since Android 1.0
      */
     public String replace(char oldChar, char newChar) {
         // BEGIN endroid-changed
@@ -1465,7 +1539,8 @@
      * @param replacement
      *            the replacement sequence.
      * @return the resulting string.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code target} or {@code replacement} is {@code null}.
      */
     public String replace(CharSequence target, CharSequence replacement) {
         if (target == null) {
@@ -1489,7 +1564,7 @@
             buffer.append(rs);
             tail = index + tl;
         } while ((index = indexOf(ts, tail)) != -1);
-        //append trailing chars 
+        //append trailing chars
         buffer.append(value, offset + tail, count - tail);
 
         return buffer.toString();
@@ -1503,7 +1578,8 @@
      *            the string to look for.
      * @return {@code true} if the specified string is a prefix of this string,
      *         {@code false} otherwise
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code prefix} is {@code null}.
      */
     public boolean startsWith(String prefix) {
         return startsWith(prefix, 0);
@@ -1519,7 +1595,8 @@
      *            the starting offset.
      * @return {@code true} if the specified string occurs in this string at the
      *         specified offset, {@code false} otherwise.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code prefix} is {@code null}.
      */
     public boolean startsWith(String prefix, int start) {
         return regionMatches(start, prefix, 0, prefix.count);
@@ -1534,7 +1611,6 @@
      *         the string.
      * @throws IndexOutOfBoundsException
      *             if {@code start < 0} or {@code start > length()}.
-     * @since Android 1.0
      */
     public String substring(int start) {
         if (start == 0) {
@@ -1557,7 +1633,6 @@
      * @throws IndexOutOfBoundsException
      *             if {@code start < 0}, {@code start > end} or {@code end >
      *             length()}.
-     * @since Android 1.0
      */
     public String substring(int start, int end) {
         if (start == 0 && end == count) {
@@ -1575,7 +1650,6 @@
      * Copies the characters in this string to a character array.
      * 
      * @return a character array containing the characters of this string.
-     * @since Android 1.0
      */
     public char[] toCharArray() {
         char[] buffer = new char[count];
@@ -1589,7 +1663,6 @@
      * 
      * @return a new string containing the lowercase characters equivalent to
      *         the characters in this string.
-     * @since Android 1.0
      */
     public String toLowerCase() {
         return toLowerCase(Locale.getDefault());
@@ -1603,12 +1676,11 @@
      *            the Locale to use.
      * @return a new string containing the lowercase characters equivalent to
      *         the characters in this string.
-     * @since Android 1.0
      */
     public String toLowerCase(Locale locale) {
         for (int o = offset, end = offset + count; o < end; o++) {
             char ch = value[o];
-            if (ch != Character.toLowerCase(ch)) {
+            if (ch != toLowerCase(ch)) {
                 char[] buffer = new char[count];
                 int i = o - offset;
                 // Not worth checking for i == 0 case
@@ -1616,12 +1688,12 @@
                 // Turkish
                 if (!"tr".equals(locale.getLanguage())) { //$NON-NLS-1$
                     while (i < count) {
-                        buffer[i++] = Character.toLowerCase(value[o++]);
+                        buffer[i++] = toLowerCase(value[o++]);
                     }
                 } else {
                     while (i < count) {
-                        buffer[i++] = (ch = value[o++]) != 0x49 ? Character
-                                .toLowerCase(ch) : (char) 0x131;
+                        buffer[i++] = (ch = value[o++]) != 0x49 ? toLowerCase(ch)
+                                : (char) 0x131;
                     }
                 }
                 return new String(0, count, buffer);
@@ -1634,7 +1706,6 @@
      * Returns this string.
      *
      * @return this string.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -1647,12 +1718,14 @@
      * 
      * @return a new string containing the uppercase characters equivalent to
      *         the characters in this string.
-     * @since Android 1.0
      */
     public String toUpperCase() {
         return toUpperCase(Locale.getDefault());
     }
 
+    // BEGIN android-note
+    // put this in a helper class so that it's only initialized on demand?
+    // END android-note
     private static final char[] upperValues = "SS\u0000\u02bcN\u0000J\u030c\u0000\u0399\u0308\u0301\u03a5\u0308\u0301\u0535\u0552\u0000H\u0331\u0000T\u0308\u0000W\u030a\u0000Y\u030a\u0000A\u02be\u0000\u03a5\u0313\u0000\u03a5\u0313\u0300\u03a5\u0313\u0301\u03a5\u0313\u0342\u1f08\u0399\u0000\u1f09\u0399\u0000\u1f0a\u0399\u0000\u1f0b\u0399\u0000\u1f0c\u0399\u0000\u1f0d\u0399\u0000\u1f0e\u0399\u0000\u1f0f\u0399\u0000\u1f08\u0399\u0000\u1f09\u0399\u0000\u1f0a\u0399\u0000\u1f0b\u0399\u0000\u1f0c\u0399\u0000\u1f0d\u0399\u0000\u1f0e\u0399\u0000\u1f0f\u0399\u0000\u1f28\u0399\u0000\u1f29\u0399\u0000\u1f2a\u0399\u0000\u1f2b\u0399\u0000\u1f2c\u0399\u0000\u1f2d\u0399\u0000\u1f2e\u0399\u0000\u1f2f\u0399\u0000\u1f28\u0399\u0000\u1f29\u0399\u0000\u1f2a\u0399\u0000\u1f2b\u0399\u0000\u1f2c\u0399\u0000\u1f2d\u0399\u0000\u1f2e\u0399\u0000\u1f2f\u0399\u0000\u1f68\u0399\u0000\u1f69\u0399\u0000\u1f6a\u0399\u0000\u1f6b\u0399\u0000\u1f6c\u0399\u0000\u1f6d\u0399\u0000\u1f6e\u0399\u0000\u1f6f\u0399\u0000\u1f68\u0399\u0000\u1f69\u0399\u0000\u1f6a\u0399\u0000\u1f6b\u0399\u0000\u1f6c\u0399\u0000\u1f6d\u0399\u0000\u1f6e\u0399\u0000\u1f6f\u0399\u0000\u1fba\u0399\u0000\u0391\u0399\u0000\u0386\u0399\u0000\u0391\u0342\u0000\u0391\u0342\u0399\u0391\u0399\u0000\u1fca\u0399\u0000\u0397\u0399\u0000\u0389\u0399\u0000\u0397\u0342\u0000\u0397\u0342\u0399\u0397\u0399\u0000\u0399\u0308\u0300\u0399\u0308\u0301\u0399\u0342\u0000\u0399\u0308\u0342\u03a5\u0308\u0300\u03a5\u0308\u0301\u03a1\u0313\u0000\u03a5\u0342\u0000\u03a5\u0308\u0342\u1ffa\u0399\u0000\u03a9\u0399\u0000\u038f\u0399\u0000\u03a9\u0342\u0000\u03a9\u0342\u0399\u03a9\u0399\u0000FF\u0000FI\u0000FL\u0000FFIFFLST\u0000ST\u0000\u0544\u0546\u0000\u0544\u0535\u0000\u0544\u053b\u0000\u054e\u0546\u0000\u0544\u053d\u0000".value; //$NON-NLS-1$
 
     /**
@@ -1721,7 +1794,6 @@
      *            the Locale to use.
      * @return a new string containing the uppercase characters equivalent to
      *         the characters in this string.
-     * @since Android 1.0
      */
     public String toUpperCase(Locale locale) {
         boolean turkish = "tr".equals(locale.getLanguage()); //$NON-NLS-1$
@@ -1736,8 +1808,8 @@
                     System.arraycopy(output, 0, newoutput, 0, output.length);
                     output = newoutput;
                 }
-                char upch = !turkish ? Character.toUpperCase(ch)
-                        : (ch != 0x69 ? Character.toUpperCase(ch)
+                char upch = !turkish ? toUpperCase(ch)
+                        : (ch != 0x69 ? toUpperCase(ch)
                                 : (char) 0x130);
                 if (ch != upch) {
                     if (output == null) {
@@ -1785,7 +1857,6 @@
      * 
      * @return a new string with characters <code><= \\u0020</code> removed from
      *         the beginning and the end.
-     * @since Android 1.0
      */
     public String trim() {
         int start = offset, last = offset + count - 1;
@@ -1810,7 +1881,8 @@
      * @param data
      *            the array of characters.
      * @return the new string.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code data} is {@code null}.
      */
     public static String valueOf(char[] data) {
         return new String(data, 0, data.length);
@@ -1831,7 +1903,8 @@
      * @throws IndexOutOfBoundsException
      *             if {@code length < 0}, {@code start < 0} or {@code start +
      *             length > data.length}
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code data} is {@code null}.
      */
     public static String valueOf(char[] data, int start, int length) {
         return new String(data, start, length);
@@ -1843,7 +1916,6 @@
      * @param value
      *            the character.
      * @return the character converted to a string.
-     * @since Android 1.0
      */
     public static String valueOf(char value) {
         String s;
@@ -1862,7 +1934,6 @@
      * @param value
      *            the double.
      * @return the double converted to a string.
-     * @since Android 1.0
      */
     public static String valueOf(double value) {
         return Double.toString(value);
@@ -1874,7 +1945,6 @@
      * @param value
      *            the float.
      * @return the float converted to a string.
-     * @since Android 1.0
      */
     public static String valueOf(float value) {
         return Float.toString(value);
@@ -1886,7 +1956,6 @@
      * @param value
      *            the integer.
      * @return the integer converted to a string.
-     * @since Android 1.0
      */
     public static String valueOf(int value) {
         return Integer.toString(value);
@@ -1898,7 +1967,6 @@
      * @param value
      *            the long.
      * @return the long converted to a string.
-     * @since Android 1.0
      */
     public static String valueOf(long value) {
         return Long.toString(value);
@@ -1912,7 +1980,6 @@
      * @param value
      *            the object.
      * @return the object converted to a string, or the string {@code "null"}.
-     * @since Android 1.0
      */
     public static String valueOf(Object value) {
         return value != null ? value.toString() : "null"; //$NON-NLS-1$
@@ -1926,7 +1993,6 @@
      * @param value
      *            the boolean.
      * @return the boolean converted to a string.
-     * @since Android 1.0
      */
     public static String valueOf(boolean value) {
         return value ? "true" : "false"; //$NON-NLS-1$ //$NON-NLS-2$
@@ -1941,7 +2007,9 @@
      * @return {@code true} if the characters in {@code strbuf} are identical to
      *         those in this string. If they are not, {@code false} will be
      *         returned.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code strbuf} is {@code null}.
+     * @since 1.4
      */
     public boolean contentEquals(StringBuffer strbuf) {
         synchronized (strbuf) {
@@ -1957,11 +2025,11 @@
     /**
      * Compares a {@code CharSequence} to this {@code String} to determine if
      * their contents are equal.
-     * 
+     *
      * @param cs
      *            the character sequence to compare to.
      * @return {@code true} if equal, otherwise {@code false}
-     * @since Android 1.0
+     * @since 1.5
      */
     public boolean contentEquals(CharSequence cs) {
         if (cs == null) {
@@ -1990,7 +2058,9 @@
      * @throws PatternSyntaxException
      *             if the syntax of the supplied regular expression is not
      *             valid.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code expr} is {@code null}.
+     * @since 1.4
      */
     public boolean matches(String expr) {
         return Pattern.matches(expr, this);
@@ -2009,7 +2079,7 @@
      *             if the syntax of the supplied regular expression is not
      *             valid.
      * @see Pattern
-     * @since Android 1.0
+     * @since 1.4
      */
     public String replaceAll(String expr, String substitute) {
         return Pattern.compile(expr).matcher(this).replaceAll(substitute);
@@ -2027,8 +2097,10 @@
      * @throws PatternSyntaxException
      *             if the syntax of the supplied regular expression is not
      *             valid.
+     * @throws NullPointerException
+     *             if {@code strbuf} is {@code null}.
      * @see Pattern
-     * @since Android 1.0
+     * @since 1.4
      */
     public String replaceFirst(String expr, String substitute) {
         return Pattern.compile(expr).matcher(this).replaceFirst(substitute);
@@ -2041,11 +2113,13 @@
      *            the regular expression used to divide the string.
      * @return an array of Strings created by separating the string along
      *         matches of the regular expression.
+     * @throws NullPointerException
+     *             if {@code expr} is {@code null}.
      * @throws PatternSyntaxException
      *             if the syntax of the supplied regular expression is not
      *             valid.
      * @see Pattern
-     * @since Android 1.0
+     * @since 1.4
      */
     public String[] split(String expr) {
         return Pattern.compile(expr).split(this);
@@ -2062,11 +2136,13 @@
      *            the number of entries in the resulting array.
      * @return an array of Strings created by separating the string along
      *         matches of the regular expression.
+     * @throws NullPointerException
+     *             if {@code expr} is {@code null}.
      * @throws PatternSyntaxException
      *             if the syntax of the supplied regular expression is not
      *             valid.
      * @see Pattern#split(CharSequence, int)
-     * @since Android 1.0
+     * @since 1.4
      */
     public String[] split(String expr, int max) {
         return Pattern.compile(expr).split(this, max);
@@ -2085,7 +2161,7 @@
      *             if {@code start < 0}, {@code end < 0}, {@code start > end} or
      *             {@code end > length()}.
      * @see java.lang.CharSequence#subSequence(int, int)
-     * @since Android 1.0
+     * @since 1.4
      */
     public CharSequence subSequence(int start, int end) {
         return substring(start, end);
@@ -2102,7 +2178,7 @@
      *             if {@code index} is negative or greater than or equal to
      *             {@code length()}.
      * @see Character#codePointAt(char[], int, int)
-     * @since Android 1.0
+     * @since 1.5
      */
     public int codePointAt(int index) {
         if (index < 0 || index >= count) {
@@ -2123,7 +2199,7 @@
      *             if {@code index} is less than 1 or greater than
      *             {@code length()}.
      * @see Character#codePointBefore(char[], int, int)
-     * @since Android 1.0
+     * @since 1.5
      */
     public int codePointBefore(int index) {
         if (index < 1 || index > count) {
@@ -2147,7 +2223,7 @@
      *             endIndex} or {@code endIndex} is greater than {@code
      *             length()}.
      * @see Character#codePointCount(CharSequence, int, int)
-     * @since Android 1.0
+     * @since 1.5
      */
     public int codePointCount(int beginIndex, int endIndex) {
         if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) {
@@ -2160,12 +2236,12 @@
     /**
      * Determines if this {@code String} contains the sequence of characters in
      * the {@code CharSequence} passed.
-     * 
+     *
      * @param cs
      *            the character sequence to search for.
      * @return {@code true} if the sequence of characters are contained in this
      *         string, otherwise {@code false}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public boolean contains(CharSequence cs) {
         if (cs == null) {
@@ -2177,7 +2253,7 @@
     /**
      * Returns the index within this object that is offset from {@code index} by
      * {@code codePointOffset} code points.
-     * 
+     *
      * @param index
      *            the index within this object to calculate the offset from.
      * @param codePointOffset
@@ -2187,7 +2263,7 @@
      *             if {@code index} is negative or greater than {@code length()}
      *             or if there aren't enough code points before or after {@code
      *             index} to match {@code codePointOffset}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public int offsetByCodePoints(int index, int codePointOffset) {
         int s = index + offset;
@@ -2205,10 +2281,12 @@
      * @param args
      *            arguments to replace format specifiers (may be none).
      * @return the formatted string.
-     * @throws IllegalFormatException
+     * @throws NullPointerException
+     *             if {@code format} is {@code null}.
+     * @throws java.util.IllegalFormatException
      *             if the format is invalid.
      * @see java.util.Formatter
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String format(String format, Object... args) {
         return format(Locale.getDefault(), format, args);
@@ -2224,7 +2302,7 @@
      * if you use the method only rarely, but if you rely on it for formatting a
      * large number of strings, consider creating and reusing your own
      * {@link java.util.Formatter} instance instead.
-     * 
+     *
      * @param loc
      *            the locale to apply; {@code null} value means no localization.
      * @param format
@@ -2232,10 +2310,12 @@
      * @param args
      *            arguments to replace format specifiers (may be none).
      * @return the formatted string.
-     * @throws IllegalFormatException
+     * @throws NullPointerException
+     *             if {@code format} is {@code null}.
+     * @throws java.util.IllegalFormatException
      *             if the format is invalid.
      * @see java.util.Formatter
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String format(Locale loc, String format, Object... args) {
         if (format == null) {
diff --git a/libcore/luni/src/main/java/java/lang/StringBuffer.java b/libcore/luni/src/main/java/java/lang/StringBuffer.java
index 5cb5c24..3ec43dc 100644
--- a/libcore/luni/src/main/java/java/lang/StringBuffer.java
+++ b/libcore/luni/src/main/java/java/lang/StringBuffer.java
@@ -39,7 +39,7 @@
  * 
  * @see String
  * @see StringBuilder
- * @since Android 1.0
+ * @since 1.0
  */
 public final class StringBuffer extends AbstractStringBuilder implements
         Appendable, Serializable, CharSequence {
@@ -53,8 +53,6 @@
 
     /**
      * Constructs a new StringBuffer using the default capacity which is 16.
-     * 
-     * @since Android 1.0
      */
     public StringBuffer() {
         super();
@@ -65,7 +63,6 @@
      * 
      * @param capacity
      *            the initial capacity.
-     * @since Android 1.0
      */
     public StringBuffer(int capacity) {
         super(capacity);
@@ -73,12 +70,13 @@
 
     /**
      * Constructs a new StringBuffer containing the characters in the specified
-     * stringy. The capacity of the new buffer will be the length of the
+     * string. The capacity of the new buffer will be the length of the
      * {@code String} plus the default capacity.
      * 
      * @param string
      *            the string content with which to initialize the new instance.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *            if {@code string} is {@code null}.
      */
     public StringBuffer(String string) {
         super(string);
@@ -91,7 +89,9 @@
      * 
      * @param cs
      *            the content to initialize the instance.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *            if {@code cs} is {@code null}.
+     * @since 1.5
      */
     public StringBuffer(CharSequence cs) {
         super(cs.toString());
@@ -103,13 +103,11 @@
      * <p>
      * If the argument is {@code true} the string {@code "true"} is appended,
      * otherwise the string {@code "false"} is appended.
-     * </p>
-     * 
+     *
      * @param b
      *            the boolean to append.
      * @return this StringBuffer.
      * @see String#valueOf(boolean)
-     * @since Android 1.0
      */
     public StringBuffer append(boolean b) {
         return append(b ? "true" : "false"); //$NON-NLS-1$//$NON-NLS-2$
@@ -122,7 +120,6 @@
      *            the character to append.
      * @return this StringBuffer.
      * @see String#valueOf(char)
-     * @since Android 1.0
      */
     public synchronized StringBuffer append(char ch) {
         append0(ch);
@@ -137,7 +134,6 @@
      *            the double to append.
      * @return this StringBuffer.
      * @see String#valueOf(double)
-     * @since Android 1.0
      */
     public StringBuffer append(double d) {
         return append(Double.toString(d));
@@ -151,7 +147,6 @@
      *            the float to append.
      * @return this StringBuffer.
      * @see String#valueOf(float)
-     * @since Android 1.0
      */
     public StringBuffer append(float f) {
         return append(Float.toString(f));
@@ -165,7 +160,6 @@
      *            the integer to append.
      * @return this StringBuffer.
      * @see String#valueOf(int)
-     * @since Android 1.0
      */
     public StringBuffer append(int i) {
         return append(Integer.toString(i));
@@ -179,7 +173,6 @@
      *            the long to append.
      * @return this StringBuffer.
      * @see String#valueOf(long)
-     * @since Android 1.0
      */
     public StringBuffer append(long l) {
         return append(Long.toString(l));
@@ -192,13 +185,11 @@
      * If the specified object is {@code null} the string {@code "null"} is
      * appended, otherwise the objects {@code toString} is used to get its
      * string representation.
-     * </p>
-     * 
+     *
      * @param obj
      *            the object to append (may be null).
      * @return this StringBuffer.
      * @see String#valueOf(Object)
-     * @since Android 1.0
      */
     public synchronized StringBuffer append(Object obj) {
         if (obj == null) {
@@ -214,12 +205,10 @@
      * <p>
      * If the specified string is {@code null} the string {@code "null"} is
      * appended, otherwise the contents of the specified string is appended.
-     * </p>
-     * 
+     *
      * @param string
      *            the string to append (may be null).
      * @return this StringBuffer.
-     * @since Android 1.0
      */
     public synchronized StringBuffer append(String string) {
         append0(string);
@@ -232,12 +221,12 @@
      * If the specified StringBuffer is {@code null} the string {@code "null"}
      * is appended, otherwise the contents of the specified StringBuffer is
      * appended.
-     * </p>
-     * 
+     *
      * @param sb
      *            the StringBuffer to append (may be null).
      * @return this StringBuffer.
-     * @since Android 1.0
+     * 
+     * @since 1.4
      */
     public synchronized StringBuffer append(StringBuffer sb) {
         if (sb == null) {
@@ -256,7 +245,8 @@
      * @param chars
      *            the character array to append.
      * @return this StringBuffer.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *            if {@code chars} is {@code null}.
      */
     public synchronized StringBuffer append(char chars[]) {
         append0(chars);
@@ -276,7 +266,8 @@
      * @throws ArrayIndexOutOfBoundsException
      *             if {@code length < 0} , {@code start < 0} or {@code start +
      *             length > chars.length}.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *            if {@code chars} is {@code null}.
      */
     public synchronized StringBuffer append(char chars[], int start, int length) {
         append0(chars, start, length);
@@ -289,12 +280,11 @@
      * If the specified CharSequence is {@code null} the string {@code "null"}
      * is appended, otherwise the contents of the specified CharSequence is
      * appended.
-     * </p>
-     * 
+     *
      * @param s
      *            the CharSequence to append.
      * @return this StringBuffer.
-     * @since Android 1.0
+     * @since 1.5
      */
     public synchronized StringBuffer append(CharSequence s) {
         if (s == null) {
@@ -310,8 +300,7 @@
      * <p>
      * If the specified CharSequence is {@code null}, then the string {@code
      * "null"} is used to extract a subsequence.
-     * </p>
-     * 
+     *
      * @param s
      *            the CharSequence to append.
      * @param start
@@ -323,7 +312,7 @@
      *             if {@code start} or {@code end} are negative, {@code start}
      *             is greater than {@code end} or {@code end} is greater than
      *             the length of {@code s}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public synchronized StringBuffer append(CharSequence s, int start, int end) {
         append0(s, start, end);
@@ -336,13 +325,12 @@
      * <p>
      * The code point is converted to a {@code char[]} as defined by
      * {@link Character#toChars(int)}.
-     * </p>
-     * 
+     *
      * @param codePoint
      *            the Unicode code point to encode and append.
      * @return this StringBuffer.
      * @see Character#toChars(int)
-     * @since Android 1.0
+     * @since 1.5
      */
     public StringBuffer appendCodePoint(int codePoint) {
         return append(Character.toChars(codePoint));
@@ -379,7 +367,6 @@
      * @throws StringIndexOutOfBoundsException
      *             if {@code start < 0}, {@code start > end} or {@code end >
      *             length()}.
-     * @since Android 1.0
      */
     public synchronized StringBuffer delete(int start, int end) {
         delete0(start, end);
@@ -394,7 +381,6 @@
      * @return this StringBuffer.
      * @throws StringIndexOutOfBoundsException
      *             if {@code location < 0} or {@code location >= length()}
-     * @since Android 1.0
      */
     public synchronized StringBuffer deleteCharAt(int location) {
         deleteCharAt0(location);
@@ -405,6 +391,7 @@
     public synchronized void ensureCapacity(int min) {
         super.ensureCapacity(min);
     }
+
     /**
      * Copies the requested sequence of characters to the {@code char[]} passed
      * starting at {@code idx}.
@@ -421,7 +408,6 @@
      *             if {@code start < 0}, {@code end > length()}, {@code start >
      *             end}, {@code index < 0}, {@code end - start > buffer.length -
      *             index}
-     * @since Android 1.0
      */
     @Override
     public synchronized void getChars(int start, int end, char[] buffer, int idx) {
@@ -443,7 +429,6 @@
      * @return this buffer.
      * @throws ArrayIndexOutOfBoundsException
      *             if {@code index < 0} or {@code index > length()}.
-     * @since Android 1.0
      */
     public synchronized StringBuffer insert(int index, char ch) {
         insert0(index, ch);
@@ -461,7 +446,6 @@
      * @return this buffer.
      * @throws StringIndexOutOfBoundsException
      *             if {@code index < 0} or {@code index > length()}.
-     * @since Android 1.0
      */
     public StringBuffer insert(int index, boolean b) {
         return insert(index, b ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
@@ -478,7 +462,6 @@
      * @return this buffer.
      * @throws StringIndexOutOfBoundsException
      *             if {@code index < 0} or {@code index > length()}.
-     * @since Android 1.0
      */
     public StringBuffer insert(int index, int i) {
         return insert(index, Integer.toString(i));
@@ -495,7 +478,6 @@
      * @return this buffer.
      * @throws StringIndexOutOfBoundsException
      *             if {@code index < 0} or {@code index > length()}.
-     * @since Android 1.0
      */
     public StringBuffer insert(int index, long l) {
         return insert(index, Long.toString(l));
@@ -512,7 +494,6 @@
      * @return this buffer.
      * @throws StringIndexOutOfBoundsException
      *             if {@code index < 0} or {@code index > length()}.
-     * @since Android 1.0
      */
     public StringBuffer insert(int index, double d) {
         return insert(index, Double.toString(d));
@@ -529,7 +510,6 @@
      * @return this buffer.
      * @throws StringIndexOutOfBoundsException
      *             if {@code index < 0} or {@code index > length()}.
-     * @since Android 1.0
      */
     public StringBuffer insert(int index, float f) {
         return insert(index, Float.toString(f));
@@ -542,8 +522,7 @@
      * If the specified object is {@code null}, the string {@code "null"} is
      * inserted, otherwise the objects {@code toString} method is used to get
      * its string representation.
-     * </p>
-     * 
+     *
      * @param index
      *            the index at which to insert.
      * @param obj
@@ -551,7 +530,6 @@
      * @return this buffer.
      * @throws StringIndexOutOfBoundsException
      *             if {@code index < 0} or {@code index > length()}.
-     * @since Android 1.0
      */
     public StringBuffer insert(int index, Object obj) {
         return insert(index, obj == null ? "null" : obj.toString()); //$NON-NLS-1$
@@ -562,8 +540,7 @@
      * <p>
      * If the specified string is {@code null}, the string {@code "null"} is
      * inserted, otherwise the contents of the string is inserted.
-     * </p>
-     * 
+     *
      * @param index
      *            the index at which to insert.
      * @param string
@@ -571,7 +548,6 @@
      * @return this buffer.
      * @throws StringIndexOutOfBoundsException
      *             if {@code index < 0} or {@code index > length()}.
-     * @since Android 1.0
      */
     public synchronized StringBuffer insert(int index, String string) {
         insert0(index, string);
@@ -588,7 +564,8 @@
      * @return this buffer.
      * @throws StringIndexOutOfBoundsException
      *             if {@code index < 0} or {@code index > length()}.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *            if {@code chars} is {@code null}.
      */
     public synchronized StringBuffer insert(int index, char[] chars) {
         insert0(index, chars);
@@ -608,11 +585,12 @@
      * @param length
      *            the number of characters.
      * @return this buffer.
+     * @throws NullPointerException
+     *             if {@code chars} is {@code null}.
      * @throws StringIndexOutOfBoundsException
      *             if {@code length < 0}, {@code start < 0}, {@code start +
      *             length > chars.length}, {@code index < 0} or {@code index >
      *             length()}
-     * @since Android 1.0
      */
     public synchronized StringBuffer insert(int index, char chars[], int start,
             int length) {
@@ -626,8 +604,7 @@
      * <p>
      * If the specified CharSequence is {@code null}, the string {@code "null"}
      * is inserted, otherwise the contents of the CharSequence.
-     * </p>
-     * 
+     *
      * @param index
      *            The index at which to insert.
      * @param s
@@ -635,7 +612,7 @@
      * @return this buffer.
      * @throws IndexOutOfBoundsException
      *             if {@code index < 0} or {@code index > length()}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public synchronized StringBuffer insert(int index, CharSequence s) {
         insert0(index, s == null ? "null" : s.toString()); //$NON-NLS-1$
@@ -648,7 +625,6 @@
      * <p>
      * If the specified CharSequence is {@code null}, the string {@code "null"}
      * is inserted, otherwise the contents of the CharSequence.
-     * </p>
      * 
      * @param index
      *            The index at which to insert.
@@ -664,7 +640,7 @@
      *             length, {@code start} or {@code end} are negative, {@code
      *             start} is greater than {@code end} or {@code end} is greater
      *             than the length of {@code s}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public synchronized StringBuffer insert(int index, CharSequence s,
             int start, int end) {
@@ -697,7 +673,6 @@
      *             if {@code start} or {@code end} are negative, {@code start}
      *             is greater than {@code end} or {@code end} is greater than
      *             the length of {@code s}.
-     * @since Android 1.0
      */
     public synchronized StringBuffer replace(int start, int end, String string) {
         replace0(start, end, string);
@@ -708,7 +683,6 @@
      * Reverses the order of characters in this buffer.
      * 
      * @return this buffer.
-     * @since Android 1.0
      */
     public synchronized StringBuffer reverse() {
         reverse0();
diff --git a/libcore/luni/src/main/java/java/lang/StringBuilder.java b/libcore/luni/src/main/java/java/lang/StringBuilder.java
index d62f900..12d401f 100644
--- a/libcore/luni/src/main/java/java/lang/StringBuilder.java
+++ b/libcore/luni/src/main/java/java/lang/StringBuilder.java
@@ -32,13 +32,13 @@
  * StringBuilder}, so that, like {@code StringBuffer}s, they can be used in
  * chaining method calls together. For example, {@code new StringBuilder("One
  * should ").append("always strive ").append("to achieve Harmony")}.
- * </p>
  * 
  * @see CharSequence
  * @see Appendable
  * @see StringBuffer
  * @see String
- * @since Android 1.0
+ * 
+ * @since 1.5
  */
 public final class StringBuilder extends AbstractStringBuilder implements
         Appendable, CharSequence, Serializable {
@@ -49,7 +49,6 @@
      * Constructs an instance with an initial capacity of {@code 16}.
      * 
      * @see #capacity()
-     * @since Android 1.0
      */
     public StringBuilder() {
         super();
@@ -57,13 +56,12 @@
 
     /**
      * Constructs an instance with the specified capacity.
-     * 
+     *
      * @param capacity
      *            the initial capacity to use.
      * @throws NegativeArraySizeException
      *             if the specified {@code capacity} is negative.
      * @see #capacity()
-     * @since Android 1.0
      */
     public StringBuilder(int capacity) {
         super(capacity);
@@ -73,10 +71,11 @@
      * Constructs an instance that's initialized with the contents of the
      * specified {@code CharSequence}. The capacity of the new builder will be
      * the length of the {@code CharSequence} plus 16.
-     * 
+     *
      * @param seq
      *            the {@code CharSequence} to copy into the builder.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *            if {@code seq} is {@code null}.
      */
     public StringBuilder(CharSequence seq) {
         super(seq.toString());
@@ -86,10 +85,11 @@
      * Constructs an instance that's initialized with the contents of the
      * specified {@code String}. The capacity of the new builder will be the
      * length of the {@code String} plus 16.
-     * 
+     *
      * @param str
      *            the {@code String} to copy into the builder.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *            if {@code str} is {@code null}.
      */
     public StringBuilder(String str) {
         super(str);
@@ -99,12 +99,11 @@
      * Appends the string representation of the specified {@code boolean} value.
      * The {@code boolean} value is converted to a String according to the rule
      * defined by {@link String#valueOf(boolean)}.
-     * 
+     *
      * @param b
      *            the {@code boolean} value to append.
      * @return this builder.
      * @see String#valueOf(boolean)
-     * @since Android 1.0
      */
     public StringBuilder append(boolean b) {
         append0(b ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
@@ -115,12 +114,11 @@
      * Appends the string representation of the specified {@code char} value.
      * The {@code char} value is converted to a string according to the rule
      * defined by {@link String#valueOf(char)}.
-     * 
+     *
      * @param c
      *            the {@code char} value to append.
      * @return this builder.
      * @see String#valueOf(char)
-     * @since Android 1.0
      */
     public StringBuilder append(char c) {
         append0(c);
@@ -131,12 +129,11 @@
      * Appends the string representation of the specified {@code int} value. The
      * {@code int} value is converted to a string according to the rule defined
      * by {@link String#valueOf(int)}.
-     * 
+     *
      * @param i
      *            the {@code int} value to append.
      * @return this builder.
      * @see String#valueOf(int)
-     * @since Android 1.0
      */
     public StringBuilder append(int i) {
         append0(Integer.toString(i));
@@ -147,12 +144,11 @@
      * Appends the string representation of the specified {@code long} value.
      * The {@code long} value is converted to a string according to the rule
      * defined by {@link String#valueOf(long)}.
-     * 
+     *
      * @param lng
      *            the {@code long} value.
      * @return this builder.
      * @see String#valueOf(long)
-     * @since Android 1.0
      */
     public StringBuilder append(long lng) {
         append0(Long.toString(lng));
@@ -163,12 +159,11 @@
      * Appends the string representation of the specified {@code float} value.
      * The {@code float} value is converted to a string according to the rule
      * defined by {@link String#valueOf(float)}.
-     * 
+     *
      * @param f
      *            the {@code float} value to append.
      * @return this builder.
      * @see String#valueOf(float)
-     * @since Android 1.0
      */
     public StringBuilder append(float f) {
         append0(Float.toString(f));
@@ -179,12 +174,11 @@
      * Appends the string representation of the specified {@code double} value.
      * The {@code double} value is converted to a string according to the rule
      * defined by {@link String#valueOf(double)}.
-     * 
+     *
      * @param d
      *            the {@code double} value to append.
      * @return this builder.
      * @see String#valueOf(double)
-     * @since Android 1.0
      */
     public StringBuilder append(double d) {
         append0(Double.toString(d));
@@ -195,12 +189,11 @@
      * Appends the string representation of the specified {@code Object}.
      * The {@code Object} value is converted to a string according to the rule
      * defined by {@link String#valueOf(Object)}.
-     * 
+     *
      * @param obj
      *            the {@code Object} to append.
      * @return this builder.
      * @see String#valueOf(Object)
-     * @since Android 1.0
      */
     public StringBuilder append(Object obj) {
         if (obj == null) {
@@ -214,11 +207,10 @@
     /**
      * Appends the contents of the specified string. If the string is {@code
      * null}, then the string {@code "null"} is appended.
-     * 
+     *
      * @param str
      *            the string to append.
      * @return this builder.
-     * @since Android 1.0
      */
     public StringBuilder append(String str) {
         append0(str);
@@ -229,11 +221,10 @@
      * Appends the contents of the specified {@code StringBuffer}. If the
      * StringBuffer is {@code null}, then the string {@code "null"} is
      * appended.
-     * 
+     *
      * @param sb
      *            the {@code StringBuffer} to append.
      * @return this builder.
-     * @since Android 1.0
      */
     public StringBuilder append(StringBuffer sb) {
         if (sb == null) {
@@ -248,12 +239,11 @@
      * Appends the string representation of the specified {@code char[]}.
      * The {@code char[]} is converted to a string according to the rule
      * defined by {@link String#valueOf(char[])}.
-     * 
+     *
      * @param ch
      *            the {@code char[]} to append..
      * @return this builder.
      * @see String#valueOf(char[])
-     * @since Android 1.0
      */
     public StringBuilder append(char[] ch) {
         append0(ch);
@@ -264,7 +254,7 @@
      * Appends the string representation of the specified subset of the {@code
      * char[]}. The {@code char[]} value is converted to a String according to
      * the rule defined by {@link String#valueOf(char[],int,int)}.
-     * 
+     *
      * @param str
      *            the {@code char[]} to append.
      * @param offset
@@ -276,7 +266,6 @@
      *             if {@code offset} and {@code len} do not specify a valid
      *             subsequence.
      * @see String#valueOf(char[],int,int)
-     * @since Android 1.0
      */
     public StringBuilder append(char[] str, int offset, int len) {
         append0(str, offset, len);
@@ -287,11 +276,10 @@
      * Appends the string representation of the specified {@code CharSequence}.
      * If the {@code CharSequence} is {@code null}, then the string {@code
      * "null"} is appended.
-     * 
+     *
      * @param csq
      *            the {@code CharSequence} to append.
      * @return this builder.
-     * @since Android 1.0
      */
     public StringBuilder append(CharSequence csq) {
         if (csq == null) {
@@ -306,7 +294,7 @@
      * Appends the string representation of the specified subsequence of the
      * {@code CharSequence}. If the {@code CharSequence} is {@code null}, then
      * the string {@code "null"} is used to extract the subsequence from.
-     * 
+     *
      * @param csq
      *            the {@code CharSequence} to append.
      * @param start
@@ -318,7 +306,6 @@
      *             if {@code start} or {@code end} are negative, {@code start}
      *             is greater than {@code end} or {@code end} is greater than
      *             the length of {@code csq}.
-     * @since Android 1.0
      */
     public StringBuilder append(CharSequence csq, int start, int end) {
         append0(csq, start, end);
@@ -328,12 +315,11 @@
     /**
      * Appends the encoded Unicode code point. The code point is converted to a
      * {@code char[]} as defined by {@link Character#toChars(int)}.
-     * 
+     *
      * @param codePoint
      *            the Unicode code point to encode and append.
      * @return this builder.
      * @see Character#toChars(int)
-     * @since Android 1.0
      */
     public StringBuilder appendCodePoint(int codePoint) {
         append0(Character.toChars(codePoint));
@@ -352,7 +338,6 @@
      * @throws StringIndexOutOfBoundsException
      *             if {@code start} is less than zero, greater than the current
      *             length or greater than {@code end}.
-     * @since Android 1.0
      */
     public StringBuilder delete(int start, int end) {
         delete0(start, end);
@@ -369,7 +354,6 @@
      * @throws StringIndexOutOfBoundsException
      *             if {@code index} is less than zero or is greater than or
      *             equal to the current length.
-     * @since Android 1.0
      */
     public StringBuilder deleteCharAt(int index) {
         deleteCharAt0(index);
@@ -381,7 +365,7 @@
      * at the specified {@code offset}. The {@code boolean} value is converted
      * to a string according to the rule defined by
      * {@link String#valueOf(boolean)}.
-     * 
+     *
      * @param offset
      *            the index to insert at.
      * @param b
@@ -391,7 +375,6 @@
      *             if {@code offset} is negative or greater than the current
      *             {@code length}.
      * @see String#valueOf(boolean)
-     * @since Android 1.0
      */
     public StringBuilder insert(int offset, boolean b) {
         insert0(offset, b ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
@@ -402,7 +385,7 @@
      * Inserts the string representation of the specified {@code char} value at
      * the specified {@code offset}. The {@code char} value is converted to a
      * string according to the rule defined by {@link String#valueOf(char)}.
-     * 
+     *
      * @param offset
      *            the index to insert at.
      * @param c
@@ -412,7 +395,6 @@
      *             if {@code offset} is negative or greater than the current
      *             {@code length()}.
      * @see String#valueOf(char)
-     * @since Android 1.0
      */
     public StringBuilder insert(int offset, char c) {
         insert0(offset, c);
@@ -423,7 +405,7 @@
      * Inserts the string representation of the specified {@code int} value at
      * the specified {@code offset}. The {@code int} value is converted to a
      * String according to the rule defined by {@link String#valueOf(int)}.
-     * 
+     *
      * @param offset
      *            the index to insert at.
      * @param i
@@ -433,7 +415,6 @@
      *             if {@code offset} is negative or greater than the current
      *             {@code length()}.
      * @see String#valueOf(int)
-     * @since Android 1.0
      */
     public StringBuilder insert(int offset, int i) {
         insert0(offset, Integer.toString(i));
@@ -444,7 +425,7 @@
      * Inserts the string representation of the specified {@code long} value at
      * the specified {@code offset}. The {@code long} value is converted to a
      * String according to the rule defined by {@link String#valueOf(long)}.
-     * 
+     *
      * @param offset
      *            the index to insert at.
      * @param l
@@ -454,7 +435,6 @@
      *             if {@code offset} is negative or greater than the current
      *             {code length()}.
      * @see String#valueOf(long)
-     * @since Android 1.0
      */
     public StringBuilder insert(int offset, long l) {
         insert0(offset, Long.toString(l));
@@ -465,7 +445,7 @@
      * Inserts the string representation of the specified {@code float} value at
      * the specified {@code offset}. The {@code float} value is converted to a
      * string according to the rule defined by {@link String#valueOf(float)}.
-     * 
+     *
      * @param offset
      *            the index to insert at.
      * @param f
@@ -475,7 +455,6 @@
      *             if {@code offset} is negative or greater than the current
      *             {@code length()}.
      * @see String#valueOf(float)
-     * @since Android 1.0
      */
     public StringBuilder insert(int offset, float f) {
         insert0(offset, Float.toString(f));
@@ -487,7 +466,7 @@
      * at the specified {@code offset}. The {@code double} value is converted
      * to a String according to the rule defined by
      * {@link String#valueOf(double)}.
-     * 
+     *
      * @param offset
      *            the index to insert at.
      * @param d
@@ -497,7 +476,6 @@
      *             if {@code offset} is negative or greater than the current
      *             {@code length()}.
      * @see String#valueOf(double)
-     * @since Android 1.0
      */
     public StringBuilder insert(int offset, double d) {
         insert0(offset, Double.toString(d));
@@ -508,7 +486,7 @@
      * Inserts the string representation of the specified {@code Object} at the
      * specified {@code offset}. The {@code Object} value is converted to a
      * String according to the rule defined by {@link String#valueOf(Object)}.
-     * 
+     *
      * @param offset
      *            the index to insert at.
      * @param obj
@@ -518,7 +496,6 @@
      *             if {@code offset} is negative or greater than the current
      *             {@code length()}.
      * @see String#valueOf(Object)
-     * @since Android 1.0
      */
     public StringBuilder insert(int offset, Object obj) {
         insert0(offset, obj == null ? "null" : obj.toString()); //$NON-NLS-1$
@@ -528,7 +505,7 @@
     /**
      * Inserts the specified string at the specified {@code offset}. If the
      * specified string is null, then the String {@code "null"} is inserted.
-     * 
+     *
      * @param offset
      *            the index to insert at.
      * @param str
@@ -537,7 +514,6 @@
      * @throws StringIndexOutOfBoundsException
      *             if {@code offset} is negative or greater than the current
      *             {@code length()}.
-     * @since Android 1.0
      */
     public StringBuilder insert(int offset, String str) {
         insert0(offset, str);
@@ -548,7 +524,7 @@
      * Inserts the string representation of the specified {@code char[]} at the
      * specified {@code offset}. The {@code char[]} value is converted to a
      * String according to the rule defined by {@link String#valueOf(char[])}.
-     * 
+     *
      * @param offset
      *            the index to insert at.
      * @param ch
@@ -558,7 +534,6 @@
      *             if {@code offset} is negative or greater than the current
      *             {@code length()}.
      * @see String#valueOf(char[])
-     * @since Android 1.0
      */
     public StringBuilder insert(int offset, char[] ch) {
         insert0(offset, ch);
@@ -570,7 +545,7 @@
      * {@code char[]} at the specified {@code offset}. The {@code char[]} value
      * is converted to a String according to the rule defined by
      * {@link String#valueOf(char[],int,int)}.
-     * 
+     *
      * @param offset
      *            the index to insert at.
      * @param str
@@ -585,7 +560,6 @@
      *             {@code length()}, or {@code strOffset} and {@code strLen} do
      *             not specify a valid subsequence.
      * @see String#valueOf(char[],int,int)
-     * @since Android 1.0
      */
     public StringBuilder insert(int offset, char[] str, int strOffset,
             int strLen) {
@@ -598,7 +572,7 @@
      * at the specified {@code offset}. The {@code CharSequence} is converted
      * to a String as defined by {@link CharSequence#toString()}. If {@code s}
      * is {@code null}, then the String {@code "null"} is inserted.
-     * 
+     *
      * @param offset
      *            the index to insert at.
      * @param s
@@ -608,7 +582,6 @@
      *             if {@code offset} is negative or greater than the current
      *             {@code length()}.
      * @see CharSequence#toString()
-     * @since Android 1.0
      */
     public StringBuilder insert(int offset, CharSequence s) {
         insert0(offset, s == null ? "null" : s.toString()); //$NON-NLS-1$
@@ -622,7 +595,7 @@
      * {@link CharSequence#subSequence(int, int)}. If the {@code CharSequence}
      * is {@code null}, then the string {@code "null"} is used to determine the
      * subsequence.
-     * 
+     *
      * @param offset
      *            the index to insert at.
      * @param s
@@ -637,7 +610,6 @@
      *             {@code length()}, or {@code start} and {@code end} do not
      *             specify a valid subsequence.
      * @see CharSequence#subSequence(int, int)
-     * @since Android 1.0
      */
     public StringBuilder insert(int offset, CharSequence s, int start, int end) {
         insert0(offset, s, start, end);
@@ -658,7 +630,8 @@
      * @throws StringIndexOutOfBoundsException
      *             if {@code start} is negative, greater than the current
      *             {@code length()} or greater than {@code end}.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *            if {@code str} is {@code null}.
      */
     public StringBuilder replace(int start, int end, String str) {
         replace0(start, end, str);
@@ -669,7 +642,6 @@
      * Reverses the order of characters in this builder.
      * 
      * @return this buffer.
-     * @since Android 1.0
      */
     public StringBuilder reverse() {
         reverse0();
@@ -680,7 +652,6 @@
      * Returns the contents of this builder.
      * 
      * @return the string representation of the data in this builder.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -695,7 +666,7 @@
     /**
      * Reads the state of a {@code StringBuilder} from the passed stream and
      * restores it to this instance.
-     * 
+     *
      * @param in
      *            the stream to read the state from.
      * @throws IOException
@@ -713,7 +684,7 @@
 
     /**
      * Writes the state of this object to the stream passed.
-     * 
+     *
      * @param out
      *            the stream to write the state to.
      * @throws IOException
diff --git a/libcore/luni/src/main/java/java/lang/StringIndexOutOfBoundsException.java b/libcore/luni/src/main/java/java/lang/StringIndexOutOfBoundsException.java
index a2fca9a..b3fbf7e 100644
--- a/libcore/luni/src/main/java/java/lang/StringIndexOutOfBoundsException.java
+++ b/libcore/luni/src/main/java/java/lang/StringIndexOutOfBoundsException.java
@@ -23,8 +23,6 @@
 /**
  * Thrown when the a string is indexed with a value less than zero, or greater
  * than or equal to the size of the array.
- * 
- * @since Android 1.0
  */
 public class StringIndexOutOfBoundsException extends IndexOutOfBoundsException {
 
@@ -33,8 +31,6 @@
     /**
      * Constructs a new {@code StringIndexOutOfBoundsException} that includes
      * the current stack trace.
-     * 
-     * @since Android 1.0
      */
     public StringIndexOutOfBoundsException() {
         super();
@@ -47,7 +43,6 @@
      * 
      * @param index
      *            the index which is out of bounds.
-     * @since Android 1.0
      */    
     public StringIndexOutOfBoundsException(int index) {
         super(Msg.getString("K0055", index)); //$NON-NLS-1$
@@ -59,7 +54,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public StringIndexOutOfBoundsException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/SuppressWarnings.java b/libcore/luni/src/main/java/java/lang/SuppressWarnings.java
index d3b4289..1ff0e42 100644
--- a/libcore/luni/src/main/java/java/lang/SuppressWarnings.java
+++ b/libcore/luni/src/main/java/java/lang/SuppressWarnings.java
@@ -1,12 +1,12 @@
-/*
- * Copyright (C) 2007 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
- *
+/* 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.
@@ -16,15 +16,9 @@
 
 package java.lang;
 
-import static java.lang.annotation.ElementType.CONSTRUCTOR;
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.PARAMETER;
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
+import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
 /**
@@ -35,18 +29,17 @@
  * <p>
  * It is recommended that programmers always use this annotation on the most
  * deeply nested element where it is actually needed.
- * </p>
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
-@Target(value={TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE})
-@Retention(value=SOURCE)
-public @interface SuppressWarnings
-{
+@Target( { ElementType.TYPE, ElementType.FIELD, ElementType.METHOD,
+        ElementType.PARAMETER, ElementType.CONSTRUCTOR,
+        ElementType.LOCAL_VARIABLE })
+@Retention(RetentionPolicy.SOURCE)
+public @interface SuppressWarnings {
+
     /**
      * The list of warnings a compiler should not issue.
-     * 
-     * @since Android 1.0
      */
-    String[] value();
+    public String[] value();
 }
diff --git a/libcore/luni/src/main/java/java/lang/ThreadDeath.java b/libcore/luni/src/main/java/java/lang/ThreadDeath.java
index e4f2cc2..3006865 100644
--- a/libcore/luni/src/main/java/java/lang/ThreadDeath.java
+++ b/libcore/luni/src/main/java/java/lang/ThreadDeath.java
@@ -20,8 +20,6 @@
 /**
  * ThreadDeath is thrown when a thread stops executing. It is used to aid in the
  * orderly unrolling of the thread's stack (eg. cleanup of monitors).
- * 
- * @since Android 1.0
  */
 public class ThreadDeath extends Error {
 
@@ -31,8 +29,6 @@
      * Constructs a new instance of this class. Note that in the case of
      * ThreadDeath, the stacktrace may <em>not</em> be filled in a way which
      * allows a stack trace to be printed.
-     * 
-     * @since Android 1.0
      */
     public ThreadDeath() {
     }
diff --git a/libcore/luni/src/main/java/java/lang/ThreadLocal.java b/libcore/luni/src/main/java/java/lang/ThreadLocal.java
index 58e85be..90250b3 100644
--- a/libcore/luni/src/main/java/java/lang/ThreadLocal.java
+++ b/libcore/luni/src/main/java/java/lang/ThreadLocal.java
@@ -16,6 +16,12 @@
 
 package java.lang;
 
+/*
+ * Android's thread local is not derived from Harmony's classlib. It is used in
+ * Harmony's DRLVM, however, whose source is here:
+ * http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/
+ */
+
 import java.lang.ref.WeakReference;
 import java.lang.ref.Reference;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -29,7 +35,6 @@
  * 
  * @see java.lang.Thread
  * @author Bob Lee
- * @since Android 1.0
  */
 public class ThreadLocal<T> {
 
@@ -97,6 +102,8 @@
      * is followed by a {@link #get()} before a {@link #set},
      * {@code #get()} will call {@link #initialValue()} and create a new
      * entry with the resulting value.
+     *
+     * @since 1.5
      */
     public void remove() {
         Thread currentThread = Thread.currentThread();
diff --git a/libcore/luni/src/main/java/java/lang/TypeNotPresentException.java b/libcore/luni/src/main/java/java/lang/TypeNotPresentException.java
index 11ef4c1..d96f766 100644
--- a/libcore/luni/src/main/java/java/lang/TypeNotPresentException.java
+++ b/libcore/luni/src/main/java/java/lang/TypeNotPresentException.java
@@ -21,8 +21,8 @@
  * type through a string that contains the type's name and the type cannot be
  * found. This exception is an unchecked alternative to
  * {@link java.lang.ClassNotFoundException}.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public class TypeNotPresentException extends RuntimeException {
     private static final long serialVersionUID = -5101214195716534496L;
@@ -38,7 +38,6 @@
      *            the fully qualified name of the type that could not be found.
      * @param cause
      *            the optional cause of this exception, may be {@code null}.
-     * @since Android 1.0
      */
     public TypeNotPresentException(String typeName, Throwable cause) {
         super("Type " + typeName + " not present", cause);
diff --git a/libcore/luni/src/main/java/java/lang/UnknownError.java b/libcore/luni/src/main/java/java/lang/UnknownError.java
index a98a5d4..ecdb008 100644
--- a/libcore/luni/src/main/java/java/lang/UnknownError.java
+++ b/libcore/luni/src/main/java/java/lang/UnknownError.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when the virtual machine must throw an error which does not match any
  * known exceptional condition.
- * 
- * @since Android 1.0
  */
 public class UnknownError extends VirtualMachineError {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code UnknownError} that includes the current stack
      * trace.
-     * 
-     * @since Android 1.0
      */
     public UnknownError() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public UnknownError(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/UnsatisfiedLinkError.java b/libcore/luni/src/main/java/java/lang/UnsatisfiedLinkError.java
index 489601f..12429a0 100644
--- a/libcore/luni/src/main/java/java/lang/UnsatisfiedLinkError.java
+++ b/libcore/luni/src/main/java/java/lang/UnsatisfiedLinkError.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when an attempt is made to invoke a native for which an implementation
  * could not be found.
- * 
- * @since Android 1.0
  */
 public class UnsatisfiedLinkError extends LinkageError {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code UnsatisfiedLinkError} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public UnsatisfiedLinkError() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public UnsatisfiedLinkError(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/UnsupportedClassVersionError.java b/libcore/luni/src/main/java/java/lang/UnsupportedClassVersionError.java
index 3ee8f8c..7670f70 100644
--- a/libcore/luni/src/main/java/java/lang/UnsupportedClassVersionError.java
+++ b/libcore/luni/src/main/java/java/lang/UnsupportedClassVersionError.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when an attempt is made to load a class with a format version that is
  * not supported by the virtual machine.
- * 
- * @since Android 1.0
  */
 public class UnsupportedClassVersionError extends ClassFormatError {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code UnsupportedClassVersionError} that includes the
      * current stack trace.
-     * 
-     * @since Android 1.0
      */
     public UnsupportedClassVersionError() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public UnsupportedClassVersionError(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/UnsupportedOperationException.java b/libcore/luni/src/main/java/java/lang/UnsupportedOperationException.java
index 8b78226..ac27518 100644
--- a/libcore/luni/src/main/java/java/lang/UnsupportedOperationException.java
+++ b/libcore/luni/src/main/java/java/lang/UnsupportedOperationException.java
@@ -19,8 +19,6 @@
 
 /**
  * Thrown when an unsupported operation is attempted.
- * 
- * @since Android 1.0
  */
 public class UnsupportedOperationException extends RuntimeException {
 
@@ -29,13 +27,8 @@
     /**
      * Constructs a new {@code UnsupportedOperationException} that includes the
      * current stack trace.
-     * 
-     * @since Android 1.0
      */
     public UnsupportedOperationException() {
-        // BEGIN android-added
-        super();
-        // END android-added
     }
 
     /**
@@ -44,7 +37,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public UnsupportedOperationException(String detailMessage) {
         super(detailMessage);
@@ -58,7 +50,7 @@
      *            the detail message for this exception.
      * @param cause
      *            the optional cause of this exception, may be {@code null}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public UnsupportedOperationException(String message, Throwable cause) {
         super(message, cause);
@@ -70,7 +62,7 @@
      * 
      * @param cause
      *            the optional cause of this exception, may be {@code null}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public UnsupportedOperationException(Throwable cause) {
         super((cause == null ? null : cause.toString()), cause);
diff --git a/libcore/luni/src/main/java/java/lang/VerifyError.java b/libcore/luni/src/main/java/java/lang/VerifyError.java
index ddf4de7..35cf34b 100644
--- a/libcore/luni/src/main/java/java/lang/VerifyError.java
+++ b/libcore/luni/src/main/java/java/lang/VerifyError.java
@@ -20,8 +20,6 @@
 /**
  * Thrown when the virtual machine notices that an attempt is made to load a
  * class which does not pass the class verification phase.
- * 
- * @since Android 1.0
  */
 public class VerifyError extends LinkageError {
 
@@ -30,8 +28,6 @@
     /**
      * Constructs a new {@code VerifyError} that includes the current stack
      * trace.
-     * 
-     * @since Android 1.0
      */
     public VerifyError() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public VerifyError(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/VirtualMachineError.java b/libcore/luni/src/main/java/java/lang/VirtualMachineError.java
index 107f562..87a6342 100644
--- a/libcore/luni/src/main/java/java/lang/VirtualMachineError.java
+++ b/libcore/luni/src/main/java/java/lang/VirtualMachineError.java
@@ -23,7 +23,6 @@
  * during the operation of the virtual machine.
  * 
  * @see Error
- * @since Android 1.0
  */
 public abstract class VirtualMachineError extends Error {
 
@@ -32,8 +31,6 @@
     /**
      * Constructs a new {@code VirtualMachineError} that includes the current
      * stack trace.
-     * 
-     * @since Android 1.0
      */
     public VirtualMachineError() {
         super();
@@ -45,7 +42,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public VirtualMachineError(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/lang/Void.java b/libcore/luni/src/main/java/java/lang/Void.java
index 8d06b64..4132e41 100644
--- a/libcore/luni/src/main/java/java/lang/Void.java
+++ b/libcore/luni/src/main/java/java/lang/Void.java
@@ -21,15 +21,13 @@
 
 /**
  * Placeholder class for the Java keyword {@code void}.
- * 
- * @since Android 1.0
+ *
+ * @since 1.1
  */
 public final class Void extends Object {
     
     /**
      * The {@link Class} object that represents the primitive type {@code void}.
-     * 
-     * @since Android 1.0
      */
     public static final Class<Void> TYPE = lookupType();
 
@@ -48,6 +46,6 @@
         return (Class<Void>) voidType;
     }
 
-    private Void() {
-    }
+	private Void() {
+	}
 }
diff --git a/libcore/luni/src/main/java/java/lang/ref/ReferenceQueue.java b/libcore/luni/src/main/java/java/lang/ref/ReferenceQueue.java
index eb6280b..ac6d695 100644
--- a/libcore/luni/src/main/java/java/lang/ref/ReferenceQueue.java
+++ b/libcore/luni/src/main/java/java/lang/ref/ReferenceQueue.java
@@ -16,25 +16,24 @@
  */
 
 // BEGIN android-note
-// This implementation was changed significantly. Changes where not marked.
+// This implementation is quite different from Harmony. Changes are not marked.
 // END android-note
+
 package java.lang.ref;
 
 /**
  * The {@code ReferenceQueue} is the container on which reference objects are
  * enqueued when the garbage collector detects the reachability type specified
  * for the referent.
- * 
- * @since Android 1.0
+ *
+ * @since 1.2
  */
 public class ReferenceQueue<T> {
-    
+
     private Reference<? extends T> head;
 
     /**
      * Constructs a new instance of this class.
-     * 
-     * @since Android 1.0
      */
     public ReferenceQueue() {
         super();
@@ -43,11 +42,9 @@
     /**
      * Returns the next available reference from the queue, removing it in the
      * process. Does not wait for a reference to become available.
-     * 
+     *
      * @return the next available reference, or {@code null} if no reference is
      *         immediately available
-     *            
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public synchronized Reference<? extends T> poll() {
@@ -73,37 +70,31 @@
     /**
      * Returns the next available reference from the queue, removing it in the
      * process. Waits indefinitely for a reference to become available.
-     * 
+     *
      * @return the next available reference
-     * 
+     *
      * @throws InterruptedException
-     *             if the blocking call was interrupted for some reason  
-     *            
-     * @since Android 1.0
+     *             if the blocking call was interrupted for some reason
      */
     public Reference<? extends T> remove() throws InterruptedException {
         return remove(0L);
     }
-    
+
     /**
      * Returns the next available reference from the queue, removing it in the
      * process. Waits for a reference to become available or the given timeout
      * period to elapse, whichever happens first.
-     * 
+     *
      * @param timeout
      *            maximum time (in ms) to spend waiting for a reference object
      *            to become available. A value of zero results in the method
      *            waiting indefinitely.
-     *            
      * @return the next available reference, or {@code null} if no reference
      *         becomes available within the timeout period
-     * 
      * @throws IllegalArgumentException
      *             if the wait period is negative.
      * @throws InterruptedException
-     *             if the blocking call was interrupted for some reason  
-     *            
-     * @since Android 1.0
+     *             if the blocking call was interrupted for some reason
      */
     public synchronized Reference<? extends T> remove(long timeout) throws IllegalArgumentException,
             InterruptedException {
@@ -128,20 +119,20 @@
     }
 
     /**
-     * Enqueues the reference object on the receiver.
-     * 
-     * @param toQueue
+     * Enqueue the reference object on the receiver.
+     *
+     * @param reference
      *            reference object to be enqueued.
-     *            
-     * @since Android 1.0
+     * @return boolean true if reference is enqueued. false if reference failed
+     *         to enqueue.
      */
-    synchronized void enqueue(Reference<? extends T> toQueue) {
+    synchronized void enqueue(Reference<? extends T> reference) {
         if (head == null) {
-            toQueue.queueNext = toQueue;
+            reference.queueNext = reference;
         } else {
-            toQueue.queueNext = head;
+            reference.queueNext = head;
         }
-        head = toQueue;
+        head = reference;
         notify();
     }
 }
diff --git a/libcore/luni/src/main/java/java/lang/reflect/AnnotatedElement.java b/libcore/luni/src/main/java/java/lang/reflect/AnnotatedElement.java
index 1f081b9..426daba 100644
--- a/libcore/luni/src/main/java/java/lang/reflect/AnnotatedElement.java
+++ b/libcore/luni/src/main/java/java/lang/reflect/AnnotatedElement.java
@@ -21,8 +21,8 @@
 
 /**
  * This interface provides reflective access to annotation information.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public interface AnnotatedElement {
 
@@ -33,13 +33,9 @@
      * 
      * @param annotationType
      *            the type of the annotation to search for
-     *            
      * @return the annotation with the specified type or {@code null}
-     * 
      * @throws NullPointerException
      *             if {@code annotationType} is {@code null}
-     * 
-     * @since Android 1.0
      */
     <T extends Annotation> T getAnnotation(Class<T> annotationType);
 
@@ -49,8 +45,6 @@
      * returns a zero length array.
      * 
      * @return an array of all annotations for this element
-     * 
-     * @since Android 1.0
      */
     Annotation[] getAnnotations();
 
@@ -60,8 +54,6 @@
      * method returns a zero length array.
      * 
      * @return an array of annotations declared for this element
-     * 
-     * @since Android 1.0
      */
     Annotation[] getDeclaredAnnotations();
 
@@ -71,13 +63,9 @@
      * 
      * @param annotationType
      *            the type of the annotation to search for
-     *            
      * @return {@code true} if the annotation exists, {@code false} otherwise
-     * 
      * @throws NullPointerException
      *             if {@code annotationType} is {@code null}
-     * 
-     * @since Android 1.0
      */
     boolean isAnnotationPresent(Class<? extends Annotation> annotationType);
 }
diff --git a/libcore/luni/src/main/java/java/lang/reflect/GenericArrayType.java b/libcore/luni/src/main/java/java/lang/reflect/GenericArrayType.java
index 81fb39f..56f873d 100644
--- a/libcore/luni/src/main/java/java/lang/reflect/GenericArrayType.java
+++ b/libcore/luni/src/main/java/java/lang/reflect/GenericArrayType.java
@@ -21,22 +21,19 @@
  * This interface represents an array type with a component type that is either
  * a parameterized type or a type variable.
  * 
- * @since Android 1.0
+ * @since 1.5
  */
 public interface GenericArrayType extends Type {
-
     /**
      * Returns the component type of this array.
      *
      * @return the component type of this array
-     * 
+     *
      * @throws TypeNotPresentException
      *             if the component type points to a missing type
      * @throws MalformedParameterizedTypeException
      *             if the component type points to a type that cannot be
      *             instantiated for some reason
-     * 
-     * @since Android 1.0
      */
     Type getGenericComponentType();
-}
+}
\ No newline at end of file
diff --git a/libcore/luni/src/main/java/java/lang/reflect/GenericDeclaration.java b/libcore/luni/src/main/java/java/lang/reflect/GenericDeclaration.java
index c7cedcf..880350b 100644
--- a/libcore/luni/src/main/java/java/lang/reflect/GenericDeclaration.java
+++ b/libcore/luni/src/main/java/java/lang/reflect/GenericDeclaration.java
@@ -18,8 +18,8 @@
 
 /**
  * Common interface for language constructs that declare type parameters.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public interface GenericDeclaration {
 
@@ -28,11 +28,8 @@
      * no type parameters, this method returns a zero length array.
      * 
      * @return the declared type parameters in declaration order
-     * 
      * @throws GenericSignatureFormatError
      *             if the signature is malformed
-     * 
-     * @since Android 1.0
      */
     TypeVariable<?>[] getTypeParameters();
 }
diff --git a/libcore/luni/src/main/java/java/lang/reflect/GenericSignatureFormatError.java b/libcore/luni/src/main/java/java/lang/reflect/GenericSignatureFormatError.java
index bb901fd..c113006 100644
--- a/libcore/luni/src/main/java/java/lang/reflect/GenericSignatureFormatError.java
+++ b/libcore/luni/src/main/java/java/lang/reflect/GenericSignatureFormatError.java
@@ -20,8 +20,8 @@
 /**
  * Indicates that a malformed signature has been encountered via a reflective
  * method.
- *
- * @since Android 1.0
+ * 
+ * @since 1.5
  */
 public class GenericSignatureFormatError extends ClassFormatError {
 
@@ -29,8 +29,6 @@
 
     /**
      * Constructs a new {@code GenericSignatureFormatError} instance.
-     *
-     * @since Android 1.0
      */
     public GenericSignatureFormatError() {
         super();
diff --git a/libcore/luni/src/main/java/java/lang/reflect/InvocationHandler.java b/libcore/luni/src/main/java/java/lang/reflect/InvocationHandler.java
index b28d535..fe3eaba 100644
--- a/libcore/luni/src/main/java/java/lang/reflect/InvocationHandler.java
+++ b/libcore/luni/src/main/java/java/lang/reflect/InvocationHandler.java
@@ -21,8 +21,6 @@
  * Implementors of this interface dispatch methods invoked on proxy instances.
  * 
  * @see Proxy
- * 
- * @since Android 1.0
  */
 public interface InvocationHandler {
 
@@ -58,8 +56,6 @@
      *             The exception must match one of the declared exception types
      *             of the invoked method or any unchecked exception type. If not
      *             then an {@code UndeclaredThrowableException} is thrown
-     * 
-     * @since Android 1.0
      */
     public Object invoke(Object proxy, Method method, Object[] args)
             throws Throwable;
diff --git a/libcore/luni/src/main/java/java/lang/reflect/InvocationTargetException.java b/libcore/luni/src/main/java/java/lang/reflect/InvocationTargetException.java
index 2d69135..6dc44e7 100644
--- a/libcore/luni/src/main/java/java/lang/reflect/InvocationTargetException.java
+++ b/libcore/luni/src/main/java/java/lang/reflect/InvocationTargetException.java
@@ -23,8 +23,6 @@
  * 
  * @see Method#invoke
  * @see Constructor#newInstance
- * 
- * @since Android 1.0
  */
 public class InvocationTargetException extends Exception {
 
@@ -35,8 +33,6 @@
     /**
      * Constructs a new {@code InvocationTargetException} instance with a
      * {@code null} cause / target exception.
-     * 
-     * @since Android 1.0
      */
     protected InvocationTargetException() {
         super((Throwable) null);
@@ -49,8 +45,6 @@
      * @param exception
      *            the exception which occurred while running the Method or
      *            Constructor
-     *            
-     * @since Android 1.0
      */
     public InvocationTargetException(Throwable exception) {
         super(null, exception);
@@ -66,8 +60,6 @@
      * @param exception
      *            the exception which occurred while running the Method or
      *            Constructor
-     *            
-     * @since Android 1.0
      */
     public InvocationTargetException(Throwable exception, String detailMessage) {
         super(detailMessage, exception);
@@ -78,8 +70,6 @@
      * Returns the target exception, which may be {@code null}.
      * 
      * @return the target exception
-     * 
-     * @since Android 1.0
      */
     public Throwable getTargetException() {
         return target;
@@ -89,8 +79,6 @@
      * Returns the cause of this exception, which may be {@code null}.
      * 
      * @return the cause of this exception
-     * 
-     * @since Android 1.0
      */
     @Override
     public Throwable getCause() {
diff --git a/libcore/luni/src/main/java/java/lang/reflect/MalformedParameterizedTypeException.java b/libcore/luni/src/main/java/java/lang/reflect/MalformedParameterizedTypeException.java
index 7dfbc6f..71f2819 100644
--- a/libcore/luni/src/main/java/java/lang/reflect/MalformedParameterizedTypeException.java
+++ b/libcore/luni/src/main/java/java/lang/reflect/MalformedParameterizedTypeException.java
@@ -21,7 +21,7 @@
  * Indicates that a malformed parameterized type has been encountered by a
  * reflective method.
  * 
- * @since Android 1.0
+ * @since 1.5
  */
 public class MalformedParameterizedTypeException extends RuntimeException {
 
@@ -29,8 +29,6 @@
 
     /**
      * Constructs a new {@code MalformedParameterizedTypeException} instance.
-     * 
-     * @since Android 1.0
      */
     public MalformedParameterizedTypeException() {
         super();
diff --git a/libcore/luni/src/main/java/java/lang/reflect/Member.java b/libcore/luni/src/main/java/java/lang/reflect/Member.java
index fb0739f..a91e108 100644
--- a/libcore/luni/src/main/java/java/lang/reflect/Member.java
+++ b/libcore/luni/src/main/java/java/lang/reflect/Member.java
@@ -8,11 +8,11 @@
  *
  *     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.lang.reflect;
@@ -23,28 +23,22 @@
  * @see Field
  * @see Constructor
  * @see Method
- * 
- * @since Android 1.0
  */
 public interface Member {
 
     /**
      * Designates all public members of a class or interface (including
      * inherited members).
-     * 
+     *
      * @see java.lang.SecurityManager#checkMemberAccess
-     * 
-     * @since Android 1.0
      */
     public static final int PUBLIC = 0;
 
     /**
      * Designates all declared members of a class or interface (without
      * inherited members).
-     * 
+     *
      * @see java.lang.SecurityManager#checkMemberAccess
-     * 
-     * @since Android 1.0
      */
     public static final int DECLARED = 1;
 
@@ -52,8 +46,6 @@
      * Returns the class that declares this member.
      *
      * @return the declaring class
-     * 
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     Class getDeclaringClass();
@@ -63,10 +55,8 @@
      * be used to decode the result.
      *
      * @return the modifiers for this member
-     * 
+     *
      * @see Modifier
-     * 
-     * @since Android 1.0
      */
     int getModifiers();
 
@@ -74,8 +64,6 @@
      * Returns the name of this member.
      *
      * @return the name of this member
-     * 
-     * @since Android 1.0
      */
     String getName();
 
@@ -84,8 +72,6 @@
      * introduced by the compiler).
      * 
      * @return {@code true} if this member is synthetic, {@code false} otherwise
-     * 
-     * @since Android 1.0
      */
     boolean isSynthetic();
 }
diff --git a/libcore/luni/src/main/java/java/lang/reflect/Modifier.java b/libcore/luni/src/main/java/java/lang/reflect/Modifier.java
index ed201aa..9005647 100644
--- a/libcore/luni/src/main/java/java/lang/reflect/Modifier.java
+++ b/libcore/luni/src/main/java/java/lang/reflect/Modifier.java
@@ -22,100 +22,74 @@
  *
  * @see Class#getModifiers()
  * @see Member#getModifiers()
- * 
- * @since Android 1.0
  */
 public class Modifier {
 
     /**
      * The {@code int} value representing the {@code public}
      * modifier.
-     *
-     * @since Android 1.0
      */
     public static final int PUBLIC = 0x1;
 
     /**
      * The {@code int} value representing the {@code private}
      * modifier.
-     *
-     * @since Android 1.0
      */
     public static final int PRIVATE = 0x2;
 
     /**
      * The {@code int} value representing the {@code protected}
      * modifier.
-     *
-     * @since Android 1.0
      */
     public static final int PROTECTED = 0x4;
 
     /**
      * The {@code int} value representing the {@code static} modifier.
-     *
-     * @since Android 1.0
      */
     public static final int STATIC = 0x8;
 
     /**
      * The {@code int} value representing the {@code final} modifier.
-     *
-     * @since Android 1.0
      */
     public static final int FINAL = 0x10;
 
     /**
      * The {@code int} value representing the {@code synchronized}
      * modifier.
-     *
-     * @since Android 1.0
      */
     public static final int SYNCHRONIZED = 0x20;
 
     /**
      * The {@code int} value representing the {@code volatile}
      * modifier.
-     *
-     * @since Android 1.0
      */
     public static final int VOLATILE = 0x40;
 
     /**
      * The {@code int} value representing the {@code transient}
      * modifier.
-     *
-     * @since Android 1.0
      */
     public static final int TRANSIENT = 0x80;
 
     /**
      * The {@code int} value representing the {@code native} modifier.
-     *
-     * @since Android 1.0
      */
     public static final int NATIVE = 0x100;
 
     /**
      * The {@code int} value representing the {@code interface}
      * modifier.
-     *
-     * @since Android 1.0
      */
     public static final int INTERFACE = 0x200;
 
     /**
      * The {@code int} value representing the {@code abstract}
      * modifier.
-     *
-     * @since Android 1.0
      */
     public static final int ABSTRACT = 0x400;
 
     /**
      * The {@code int} value representing the {@code strict} modifier.
-     *
-     * @since Android 1.0
      */
     public static final int STRICT = 0x800;
 
@@ -132,8 +106,6 @@
 
     /**
      * Constructs a new {@code Modifier} instance.
-     *
-     * @since Android 1.0
      */
     public Modifier() {
     }
@@ -144,11 +116,8 @@
      * 
      * @param modifiers
      *            the modifiers to test
-     *            
      * @return {@code true} if the specified modifiers contain the {@code
      *         abstract} modifier, {@code false} otherwise
-     *         
-     * @since Android 1.0
      */
     public static boolean isAbstract(int modifiers) {
         return ((modifiers & ABSTRACT) != 0);
@@ -160,11 +129,8 @@
      * 
      * @param modifiers
      *            the modifiers to test
-     *            
      * @return {@code true} if the specified modifiers contain the {@code
      *         final} modifier, {@code false} otherwise
-     *         
-     * @since Android 1.0
      */
     public static boolean isFinal(int modifiers) {
         return ((modifiers & FINAL) != 0);
@@ -176,11 +142,8 @@
      * 
      * @param modifiers
      *            the modifiers to test
-     *
      * @return {@code true} if the specified modifiers contain the {@code
      *         interface} modifier, {@code false} otherwise
-     * 
-     * @since Android 1.0
      */
     public static boolean isInterface(int modifiers) {
         return ((modifiers & INTERFACE) != 0);
@@ -192,11 +155,8 @@
      * 
      * @param modifiers
      *            the modifiers to test
-     * 
      * @return {@code true} if the specified modifiers contain the {@code
      *         native} modifier, {@code false} otherwise
-     * 
-     * @since Android 1.0
      */
     public static boolean isNative(int modifiers) {
         return ((modifiers & NATIVE) != 0);
@@ -208,11 +168,8 @@
      * 
      * @param modifiers
      *            the modifiers to test
-     * 
      * @return {@code true} if the specified modifiers contain the {@code
      *         private} modifier, {@code false} otherwise
-     * 
-     * @since Android 1.0
      */
     public static boolean isPrivate(int modifiers) {
         return ((modifiers & PRIVATE) != 0);
@@ -224,11 +181,8 @@
      * 
      * @param modifiers
      *            the modifiers to test
-     * 
      * @return {@code true} if the specified modifiers contain the {@code
      *         protected} modifier, {@code false} otherwise
-     * 
-     * @since Android 1.0
      */
     public static boolean isProtected(int modifiers) {
         return ((modifiers & PROTECTED) != 0);
@@ -240,11 +194,8 @@
      * 
      * @param modifiers
      *            the modifiers to test
-     * 
      * @return {@code true} if the specified modifiers contain the {@code
      *         public} modifier, {@code false} otherwise
-     * 
-     * @since Android 1.0
      */
     public static boolean isPublic(int modifiers) {
         return ((modifiers & PUBLIC) != 0);
@@ -256,11 +207,8 @@
      * 
      * @param modifiers
      *            the modifiers to test
-     * 
      * @return {@code true} if the specified modifiers contain the {@code
      *         static} modifier, {@code false} otherwise
-     * 
-     * @since Android 1.0
      */
     public static boolean isStatic(int modifiers) {
         return ((modifiers & STATIC) != 0);
@@ -272,11 +220,8 @@
      * 
      * @param modifiers
      *            the modifiers to test
-     * 
      * @return {@code true} if the specified modifiers contain the {@code
      *         strict} modifier, {@code false} otherwise
-     * 
-     * @since Android 1.0
      */
     public static boolean isStrict(int modifiers) {
         return ((modifiers & STRICT) != 0);
@@ -288,11 +233,8 @@
      * 
      * @param modifiers
      *            the modifiers to test
-     * 
      * @return {@code true} if the specified modifiers contain the {@code
      *         synchronized} modifier, {@code false} otherwise
-     * 
-     * @since Android 1.0
      */
     public static boolean isSynchronized(int modifiers) {
         return ((modifiers & SYNCHRONIZED) != 0);
@@ -304,11 +246,8 @@
      * 
      * @param modifiers
      *            the modifiers to test
-     * 
      * @return {@code true} if the specified modifiers contain the {@code
      *         transient} modifier, {@code false} otherwise
-     * 
-     * @since Android 1.0
      */
     public static boolean isTransient(int modifiers) {
         return ((modifiers & TRANSIENT) != 0);
@@ -320,11 +259,8 @@
      * 
      * @param modifiers
      *            the modifiers to test
-     * 
      * @return {@code true} if the specified modifiers contain the {@code
      *         volatile} modifier, {@code false} otherwise
-     * 
-     * @since Android 1.0
      */
     public static boolean isVolatile(int modifiers) {
         return ((modifiers & VOLATILE) != 0);
@@ -339,16 +275,11 @@
      *
      * @param modifiers
      *            the modifiers to print
-     * 
      * @return a printable representation of the modifiers
-     * 
-     * @since Android 1.0
      */
     @SuppressWarnings("nls")
     public static java.lang.String toString(int modifiers) {
-        StringBuffer buf;
-
-        buf = new StringBuffer();
+        StringBuilder buf = new StringBuilder();
 
         if (isPublic(modifiers)) {
             buf.append("public ");
diff --git a/libcore/luni/src/main/java/java/lang/reflect/ParameterizedType.java b/libcore/luni/src/main/java/java/lang/reflect/ParameterizedType.java
index 3d03921..91f2520 100644
--- a/libcore/luni/src/main/java/java/lang/reflect/ParameterizedType.java
+++ b/libcore/luni/src/main/java/java/lang/reflect/ParameterizedType.java
@@ -18,10 +18,10 @@
 package java.lang.reflect;
 
 /**
- * This interface represents a parameterized type such as {@code 
+ * This interface represents a parameterized type such as {@code
  * 'Set&lt;String&gt;'}.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public interface ParameterizedType extends Type {
 
@@ -32,25 +32,23 @@
      * parameterized type, this method returns a zero length array. The generic
      * type of the following {@code field} declaration is an example for a
      * parameterized type without type arguments.
-     * 
+     *
      * <pre>
      * A&lt;String&gt;.B field;
-     * 
+     *
      * class A&lt;T&gt; {
      *     class B {
      *     }
      * }</pre>
-     * 
-     * 
+     *
+     *
      * @return the actual type arguments
-     * 
+     *
      * @throws TypeNotPresentException
      *             if one of the type arguments cannot be found
      * @throws MalformedParameterizedTypeException
      *             if one of the type arguments cannot be instantiated for some
      *             reason
-     * 
-     * @since Android 1.0
      */
     Type[] getActualTypeArguments();
 
@@ -59,13 +57,11 @@
      * {@code null} is returned if this is a top-level type.
      * 
      * @return the owner type or {@code null} if this is a top-level type
-     * 
+     *
      * @throws TypeNotPresentException
      *             if one of the type arguments cannot be found
      * @throws MalformedParameterizedTypeException
      *             if the owner type cannot be instantiated for some reason
-     * 
-     * @since Android 1.0
      */
     Type getOwnerType();
 
@@ -73,10 +69,8 @@
      * Returns the declaring type of this parameterized type.
      * <p>
      * The raw type of {@code Set&lt;String&gt; field;} is {@code Set}.
-     * 
+     *
      * @return the raw type of this parameterized type
-     * 
-     * @since Android 1.0
      */
     Type getRawType();
 }
diff --git a/libcore/luni/src/main/java/java/lang/reflect/Proxy.java b/libcore/luni/src/main/java/java/lang/reflect/Proxy.java
index 29d15c5..cc0c956 100644
--- a/libcore/luni/src/main/java/java/lang/reflect/Proxy.java
+++ b/libcore/luni/src/main/java/java/lang/reflect/Proxy.java
@@ -35,8 +35,7 @@
  * invocations to an {@code InvocationHandler}.
  *
  * @see InvocationHandler
- * 
- * @since Android 1.0
+ * @since 1.3
  */
 public class Proxy implements Serializable {
 
@@ -52,8 +51,6 @@
 
     /**
      * The invocation handler on which the method calls are dispatched.
-     *
-     * @since Android 1.0
      */
     protected InvocationHandler h;
 
@@ -64,11 +61,9 @@
     /**
      * Constructs a new {@code Proxy} instance with the specified invocation
      * handler.
-     * 
+     *
      * @param h
      *            the invocation handler for the newly created proxy
-     *            
-     * @since Android 1.0
      */
     protected Proxy(InvocationHandler h) {
         this.h = h;
@@ -81,24 +76,20 @@
      * different order result in different generated classes. The interfaces
      * must be visible from the supplied class loader; no duplicates are
      * permitted. All non-public interfaces must be defined in the same package.
-     * 
+     *
      * @param loader
      *            the class loader that will define the proxy class
      * @param interfaces
      *            an array of {@code Class} objects, each one identifying an
      *            interface that will be implemented by the returned proxy
      *            class
-     * 
      * @return a proxy class that implements all of the interfaces referred to
      *         in the contents of {@code interfaces}
-     * 
      * @throws IllegalArgumentException
      *                if any of the interface restrictions are violated
      * @throws NullPointerException
      *                if either {@code interfaces} or any of its elements are
      *                {@code null}
-     * 
-     * @since Android 1.0
      */
     public static Class<?> getProxyClass(ClassLoader loader,
             Class<?>... interfaces) throws IllegalArgumentException {
@@ -174,19 +165,17 @@
             WeakReference<Class<?>> ref = interfaceCache.get(interfaceKey);
             if (ref == null) {
                 String nextClassName = "$Proxy" + NextClassNameIndex++; //$NON-NLS-1$
-                if (commonPackageName != null) {
+                if (commonPackageName != null && commonPackageName.length() > 0) {
                     nextClassName = commonPackageName + "." + nextClassName; //$NON-NLS-1$
                 }
                 // BEGIN android-changed
-                //byte[] classFileBytes = ProxyClassFile.generateBytes(
-                //        nextClassName, interfaces);
-                // END android-changed
+                // byte[] classFileBytes = ProxyClassFile.generateBytes(
+                //         nextClassName, interfaces);
+                // newClass = defineClassImpl(loader, nextClassName.replace('.',
+                //         '/'), classFileBytes);
                 if (loader == null) {
                     loader = ClassLoader.getSystemClassLoader();
                 }
-                // BEGIN android-changed
-                //newClass = defineClassImpl(loader, nextClassName.replace('.',
-                //        '/'), classFileBytes);
                 newClass = generateProxy(nextClassName.replace('.', '/'),
                         interfaces, loader);
                 // END android-changed
@@ -200,6 +189,10 @@
                 }
             } else {
                 newClass = ref.get();
+                assert newClass != null : "\ninterfaceKey=\"" + interfaceKey + "\""
+                                        + "\nloaderCache=\"" + loaderCache + "\""
+                                        + "\nintfCache=\"" + interfaceCache + "\""
+                                        + "\nproxyCache=\"" + proxyCache + "\"";
             }
             return newClass;
         }
@@ -211,7 +204,7 @@
      * the specified invocation handler. The interfaces must be visible from the
      * supplied class loader; no duplicates are permitted. All non-public
      * interfaces must be defined in the same package.
-     * 
+     *
      * @param loader
      *            the class loader that will define the proxy class
      * @param interfaces
@@ -221,15 +214,11 @@
      * @param h
      *            the invocation handler that handles the dispatched method
      *            invocations
-     * 
      * @return a new proxy object that delegates to the handler {@code h}
-     * 
      * @throws IllegalArgumentException
      *                if any of the interface restrictions are violated
      * @throws NullPointerException
      *                if the interfaces or any of its elements are null
-     * 
-     * @since Android 1.0
      */
     public static Object newProxyInstance(ClassLoader loader,
             Class<?>[] interfaces, InvocationHandler h)
@@ -260,17 +249,13 @@
     /**
      * Indicates whether or not the specified class is a dynamically generated
      * proxy class.
-     * 
+     *
      * @param cl
      *            the class
-     * 
      * @return {@code true} if the class is a proxy class, {@code false}
      *         otherwise
-     * 
      * @throws NullPointerException
      *                if the class is {@code null}
-     * 
-     * @since Android 1.0
      */
     public static boolean isProxyClass(Class<?> cl) {
         if (cl == null) {
@@ -283,16 +268,12 @@
 
     /**
      * Returns the invocation handler of the specified proxy instance.
-     * 
+     *
      * @param proxy
      *            the proxy instance
-     * 
      * @return the invocation handler of the specified proxy instance
-     * 
      * @throws IllegalArgumentException
      *                if the supplied {@code proxy} is not a proxy object
-     * 
-     * @since Android 1.0
      */
     public static InvocationHandler getInvocationHandler(Object proxy)
             throws IllegalArgumentException {
diff --git a/libcore/luni/src/main/java/java/lang/reflect/ReflectPermission.java b/libcore/luni/src/main/java/java/lang/reflect/ReflectPermission.java
index b568663..93eef39 100644
--- a/libcore/luni/src/main/java/java/lang/reflect/ReflectPermission.java
+++ b/libcore/luni/src/main/java/java/lang/reflect/ReflectPermission.java
@@ -22,8 +22,6 @@
 /**
  * A {@code ReflectPermission} object represents a permission to access
  * operations in the reflection layer.
- * 
- * @since Android 1.0
  */
 public final class ReflectPermission extends BasicPermission {
 
@@ -35,13 +33,10 @@
      * 
      * @param permissionName
      *            the name of the new permission
-     *            
      * @throws IllegalArgumentException
      *             if {@code name} is empty
      * @throws NullPointerException
      *             if {@code name} is {@code null}
-     * 
-     * @since Android 1.0
      */
     public ReflectPermission(String permissionName) {
         super(permissionName);
@@ -55,13 +50,10 @@
      *            the name of the new permission
      * @param actions
      *            this parameter will be ignored
-     * 
      * @throws IllegalArgumentException
      *             if {@code name} is empty
      * @throws NullPointerException
      *             if {@code name} is {@code null}
-     * 
-     * @since Android 1.0
      */
     public ReflectPermission(String name, String actions) {
         super(name, actions);
diff --git a/libcore/luni/src/main/java/java/lang/reflect/Type.java b/libcore/luni/src/main/java/java/lang/reflect/Type.java
index abd4978..a057088 100644
--- a/libcore/luni/src/main/java/java/lang/reflect/Type.java
+++ b/libcore/luni/src/main/java/java/lang/reflect/Type.java
@@ -18,8 +18,8 @@
 
 /**
  * Common interface implemented by all Java types.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public interface Type {
     // Empty
diff --git a/libcore/luni/src/main/java/java/lang/reflect/TypeVariable.java b/libcore/luni/src/main/java/java/lang/reflect/TypeVariable.java
index 99aca77..e3f8c1d 100644
--- a/libcore/luni/src/main/java/java/lang/reflect/TypeVariable.java
+++ b/libcore/luni/src/main/java/java/lang/reflect/TypeVariable.java
@@ -17,15 +17,14 @@
 package java.lang.reflect;
 
 /**
- * This interface represents a type variables such as {@code 'T'} in {@code 
- * 'public interface Comparable&lt;T&gt;'}, the bounded {@code 'T'} in {@code 
+ * This interface represents a type variables such as {@code 'T'} in {@code
+ * 'public interface Comparable&lt;T&gt;'}, the bounded {@code 'T'} in {@code
  * 'public interface A&lt;T extends Number&gt;'} or the multiple bounded {@code
  * 'T'} in {@code 'public interface B&lt;T extends Number & Cloneable&gt;'}.
- * 
+ *
  * @param <D>
  *            the generic declaration that declares this type variable
- * 
- * @since Android 1.0
+ * @since 1.5
  */
 public interface TypeVariable<D extends GenericDeclaration> extends Type {
 
@@ -33,15 +32,13 @@
      * Returns the upper bounds of this type variable. {@code Object} is the
      * implicit upper bound if no other bounds are declared.
      *
-     * @return the upper bounds of this type variable 
-     * 
+     * @return the upper bounds of this type variable
+     *
      * @throws TypeNotPresentException
      *             if any of the bounds points to a missing type
      * @throws MalformedParameterizedTypeException
      *             if any of the bounds points to a type that cannot be
      *             instantiated for some reason
-     * 
-     * @since Android 1.0
      */
     Type[] getBounds();
 
@@ -49,8 +46,6 @@
      * Returns the language construct that declares this type variable.
      *
      * @return the generic declaration
-     * 
-     * @since Android 1.0
      */
     D getGenericDeclaration();
 
@@ -59,8 +54,6 @@
      * code.
      *
      * @return the name of this type variable
-     * 
-     * @since Android 1.0
      */
     String getName();
 }
diff --git a/libcore/luni/src/main/java/java/lang/reflect/UndeclaredThrowableException.java b/libcore/luni/src/main/java/java/lang/reflect/UndeclaredThrowableException.java
index 108f98a..bd5adfa 100644
--- a/libcore/luni/src/main/java/java/lang/reflect/UndeclaredThrowableException.java
+++ b/libcore/luni/src/main/java/java/lang/reflect/UndeclaredThrowableException.java
@@ -22,8 +22,6 @@
  * an InvocationHandler.
  *
  * @see java.lang.reflect.InvocationHandler#invoke
- *
- * @since Android 1.0
  */
 public class UndeclaredThrowableException extends RuntimeException {
 
@@ -37,8 +35,6 @@
      * 
      * @param exception
      *            the undeclared, checked exception that occurred
-     * 
-     * @since Android 1.0
      */
     public UndeclaredThrowableException(Throwable exception) {
         super();
@@ -54,8 +50,6 @@
      *            the detail message for the exception
      * @param exception
      *            the undeclared, checked exception that occurred
-     * 
-     * @since Android 1.0
      */
     public UndeclaredThrowableException(Throwable exception,
             String detailMessage) {
@@ -69,8 +63,6 @@
      * {@code null}.
      *
      * @return the undeclared, checked exception that occurred
-     * 
-     * @since Android 1.0
      */
     public Throwable getUndeclaredThrowable() {
         return undeclaredThrowable;
@@ -81,8 +73,6 @@
      * {@code null}.
      *
      * @return the undeclared, checked exception that occurred
-     * 
-     * @since Android 1.0
      */
     @Override
     public Throwable getCause() {
diff --git a/libcore/luni/src/main/java/java/lang/reflect/WildcardType.java b/libcore/luni/src/main/java/java/lang/reflect/WildcardType.java
index 72a022d..affd526 100644
--- a/libcore/luni/src/main/java/java/lang/reflect/WildcardType.java
+++ b/libcore/luni/src/main/java/java/lang/reflect/WildcardType.java
@@ -22,24 +22,21 @@
  * {@code '?'}, the upper bounded wildcard {@code '? extends Closeable'}, the
  * multiple upper bounded wildcard {@code '? extends Closeable & Flushable'} or
  * the lower bounded wildcard {@code '? super OutputStream'}.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public interface WildcardType extends Type {
-    
     /**
      * Returns the array of types that represent the upper bounds of this type.
      * The default upper bound is {@code Object}.
      *
      * @return an array containing the upper bounds types
-     * 
+     *
      * @throws TypeNotPresentException
      *             if any of the bounds points to a missing type
      * @throws MalformedParameterizedTypeException
      *             if any bound points to a type that cannot be instantiated for
      *             some reason
-     * 
-     * @since Android 1.0
      */
     Type[] getUpperBounds();
 
@@ -48,16 +45,14 @@
      * The default lower bound is {@code null}, in which case an empty array is
      * returned. Since only one lower bound is allowed, the returned array's
      * length will never exceed one.
-     * 
+     *
      * @return an array containing the lower bounds types
-     * 
+     *
      * @throws TypeNotPresentException
      *             if any of the bounds points to a missing type
      * @throws MalformedParameterizedTypeException
      *             if any of the bounds points to a type that cannot be
      *             instantiated for some reason
-     * 
-     * @since Android 1.0
      */
     Type[] getLowerBounds();
 }
diff --git a/libcore/luni/src/main/java/java/net/Authenticator.java b/libcore/luni/src/main/java/java/net/Authenticator.java
index 1eea8d8..75d68fa 100644
--- a/libcore/luni/src/main/java/java/net/Authenticator.java
+++ b/libcore/luni/src/main/java/java/net/Authenticator.java
@@ -27,7 +27,6 @@
  * 
  * @see #setDefault
  * @see #getPasswordAuthentication
- * @since Android 1.0
  */
 public abstract class Authenticator {
 
@@ -63,10 +62,8 @@
      * default which is {@code null}.
      * <p>
      * Returns {@code null} by default.
-     * </p>
-     * 
+     *
      * @return collected password authentication data.
-     * @since Android 1.0
      */
     protected PasswordAuthentication getPasswordAuthentication() {
         return null;
@@ -76,7 +73,6 @@
      * Returns the port of the connection that requests authorization.
      * 
      * @return port of the connection.
-     * @since Android 1.0
      */
     protected final int getRequestingPort() {
         return this.port;
@@ -87,7 +83,6 @@
      * {@code null} if unknown.
      * 
      * @return address of the connection.
-     * @since Android 1.0
      */
     protected final InetAddress getRequestingSite() {
         return this.addr;
@@ -98,7 +93,6 @@
      * authorization.
      * 
      * @return prompt string of the connection.
-     * @since Android 1.0
      */
     protected final String getRequestingPrompt() {
         return this.prompt;
@@ -108,7 +102,6 @@
      * Returns the protocol of the connection that requests authorization.
      * 
      * @return protocol of the connection.
-     * @since Android 1.0
      */
     protected final String getRequestingProtocol() {
         return this.protocol;
@@ -119,7 +112,6 @@
      * example HTTP Basic Authentication.
      * 
      * @return scheme of the connection.
-     * @since Android 1.0
      */
     protected final String getRequestingScheme() {
         return this.scheme;
@@ -145,7 +137,6 @@
      * @throws SecurityException
      *             if a security manager denies the password authentication
      *             permission.
-     * @since Android 1.0
      */
     public static synchronized PasswordAuthentication requestPasswordAuthentication(
             InetAddress rAddr, int rPort, String rProtocol, String rPrompt,
@@ -182,7 +173,6 @@
      * @throws SecurityException
      *             if a security manager denies the password authentication
      *             permission.
-     * @since Android 1.0
      */
     public static void setDefault(Authenticator a) {
         SecurityManager sm = System.getSecurityManager();
@@ -214,7 +204,6 @@
      * @throws SecurityException
      *             if a security manager denies the password authentication
      *             permission.
-     * @since Android 1.0
      */
     public static synchronized PasswordAuthentication requestPasswordAuthentication(
             String rHost, InetAddress rAddr, int rPort, String rProtocol,
@@ -244,9 +233,8 @@
     /**
      * Returns the host name of the connection that requests authentication or
      * {@code null} if unknown.
-     * 
+     *
      * @return name of the requesting host or {@code null}.
-     * @since Android 1.0
      */
     protected final String getRequestingHost() {
         return host;
@@ -278,7 +266,6 @@
      * @throws SecurityException
      *             if a security manager denies the password authentication
      *             permission.
-     * @since Android 1.0
      */
     public static PasswordAuthentication requestPasswordAuthentication(
             String rHost, InetAddress rAddr, int rPort, String rProtocol,
@@ -312,7 +299,6 @@
      * Returns the URL of the authentication request.
      * 
      * @return authentication request url.
-     * @since Android 1.0
      */
     protected URL getRequestingURL() {
         return url;
@@ -322,7 +308,6 @@
      * Returns the type of this request, it can be {@code PROXY} or {@code SERVER}.
      * 
      * @return RequestorType of the authentication request.
-     * @since Android 1.0
      */
     protected Authenticator.RequestorType getRequestorType() {
         return rt;
@@ -330,8 +315,6 @@
 
     /**
      * Enumeration class for the origin of the authentication request.
-     * 
-     * @since Android 1.0
      */
     public enum RequestorType {
 
diff --git a/libcore/luni/src/main/java/java/net/BindException.java b/libcore/luni/src/main/java/java/net/BindException.java
index 69be315..48f1cf6 100644
--- a/libcore/luni/src/main/java/java/net/BindException.java
+++ b/libcore/luni/src/main/java/java/net/BindException.java
@@ -20,8 +20,6 @@
 /**
  * A {@code BindException} is thrown when a process cannot bind a local
  * address/port, either because it is already bound or reserved by the OS.
- * 
- * @since Android 1.0
  */
 public class BindException extends SocketException {
 
@@ -29,8 +27,6 @@
 
     /**
      * Constructs a new instance with its walkback filled in.
-     * 
-     * @since Android 1.0
      */
     public BindException() {
         super();
@@ -41,7 +37,6 @@
      * 
      * @param detailMessage
      *            detail message of the exception.
-     * @since Android 1.0
      */
     public BindException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/net/CacheRequest.java b/libcore/luni/src/main/java/java/net/CacheRequest.java
index 8c67a44..778cb13 100644
--- a/libcore/luni/src/main/java/java/net/CacheRequest.java
+++ b/libcore/luni/src/main/java/java/net/CacheRequest.java
@@ -29,14 +29,11 @@
  * the current cache store operation is abandoned.
  * 
  * @see ResponseCache
- * @since Android 1.0
  */
 public abstract class CacheRequest {
 
     /**
      * This implementation does nothing.
-     * 
-     * @since Android 1.0
      */
     public CacheRequest() {
         super();
@@ -46,8 +43,6 @@
      * Aborts the current cache operation. If an {@code IOException} occurs
      * while reading the response or writing resource data to the cache, the
      * current cache store operation is aborted.
-     * 
-     * @since Android 1.0
      */
     public abstract void abort();
 
@@ -58,7 +53,6 @@
      * @throws IOException
      *             if an I/O error is encountered during writing response body
      *             operation.
-     * @since Android 1.0
      */
     public abstract OutputStream getBody() throws IOException;
 }
diff --git a/libcore/luni/src/main/java/java/net/CacheResponse.java b/libcore/luni/src/main/java/java/net/CacheResponse.java
index ae5be44..b0ad094 100644
--- a/libcore/luni/src/main/java/java/net/CacheResponse.java
+++ b/libcore/luni/src/main/java/java/net/CacheResponse.java
@@ -28,13 +28,10 @@
  * getHeaders()} to fetch the response headers.
  * 
  * @see ResponseCache
- * @since Android 1.0
  */
 public abstract class CacheResponse {
     /**
      * This implementation does nothing.
-     * 
-     * @since Android 1.0
      */
     public CacheResponse() {
         super();
@@ -48,7 +45,6 @@
      * @throws IOException
      *             if an I/O error is encountered while retrieving the response
      *             body.
-     * @since Android 1.0
      */
     public abstract InputStream getBody() throws IOException;
 
@@ -62,7 +58,6 @@
      * @throws IOException
      *             if an I/O error is encountered while retrieving the response
      *             headers.
-     * @since Android 1.0
      */
     public abstract Map<String, List<String>> getHeaders() throws IOException;
 }
diff --git a/libcore/luni/src/main/java/java/net/ConnectException.java b/libcore/luni/src/main/java/java/net/ConnectException.java
index 42389c7..84cd2bb 100644
--- a/libcore/luni/src/main/java/java/net/ConnectException.java
+++ b/libcore/luni/src/main/java/java/net/ConnectException.java
@@ -20,8 +20,6 @@
 /**
  * A {@code ConnectException} is thrown if a connection cannot be established to
  * a remote host on a specific port.
- * 
- * @since Android 1.0
  */
 public class ConnectException extends SocketException {
 
@@ -29,8 +27,6 @@
 
     /**
      * This implementation does nothing.
-     * 
-     * @since Android 1.0
      */
     public ConnectException() {
         super();
@@ -38,10 +34,9 @@
 
     /**
      * This implementation does nothing.
-     * 
+     *
      * @param detailMessage
      *            detail message of the exception.
-     * @since Android 1.0
      */
     public ConnectException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/net/ContentHandler.java b/libcore/luni/src/main/java/java/net/ContentHandler.java
index 05c6acf..8e0bbb7 100644
--- a/libcore/luni/src/main/java/java/net/ContentHandler.java
+++ b/libcore/luni/src/main/java/java/net/ContentHandler.java
@@ -23,28 +23,26 @@
  * This class converts the content of a certain format (i.e. a MIME type) into a
  * Java type object. It is created by {@code ContentHandlerFactory}. The data
  * values should be accessed via {@code URL} or {@code URLConnection}.
- * 
+ *
  * @see ContentHandlerFactory
  * @see URL#getContent()
  * @see URLConnection#getContent()
- * @since Android 1.0
  */
 public abstract class ContentHandler {
     /**
      * Returns the object pointed by the specified URL connection {@code uConn}.
-     * 
+     *
      * @param uConn
      *            URL connection that points to the desired object.
      * @return object referred by {@code uConn}.
      * @throws IOException
      *             if an IO error occurs during the retrieval of the object
-     * @since Android 1.0
      */
     public abstract Object getContent(URLConnection uConn) throws IOException;
 
     /**
      * Returns the object pointed by the specified URL connection {@code uConn}.
-     * 
+     *
      * @param uConn
      *            URL connection that points to the desired object.
      * @param types
@@ -53,7 +51,6 @@
      *         content doesn't match one of the specified content types.
      * @throws IOException
      *             if an error occurred while obtaining the content.
-     * @since Android 1.0
      */
     // Class arg not generified in the spec.
     @SuppressWarnings("unchecked")
diff --git a/libcore/luni/src/main/java/java/net/ContentHandlerFactory.java b/libcore/luni/src/main/java/java/net/ContentHandlerFactory.java
index 1a564ee..3089c04 100644
--- a/libcore/luni/src/main/java/java/net/ContentHandlerFactory.java
+++ b/libcore/luni/src/main/java/java/net/ContentHandlerFactory.java
@@ -21,7 +21,6 @@
  * Defines a factory which is responsible for creating a {@code ContentHandler}.
  * 
  * @see ContentHandler
- * @since Android 1.0
  */
 public interface ContentHandlerFactory {
     /**
@@ -31,7 +30,6 @@
      *            specifies the content type which is handled by the returned
      *            {@code ContentHandler}.
      * @return content handler object for a specific content type.
-     * @since Android 1.0
      */
     ContentHandler createContentHandler(String contentType);
 }
diff --git a/libcore/luni/src/main/java/java/net/CookieHandler.java b/libcore/luni/src/main/java/java/net/CookieHandler.java
index 29428ec..05eddde 100644
--- a/libcore/luni/src/main/java/java/net/CookieHandler.java
+++ b/libcore/luni/src/main/java/java/net/CookieHandler.java
@@ -22,8 +22,6 @@
 
 /**
  * This class provides a way to manage cookies with a HTTP protocol handler.
- * 
- * @since Android 1.0
  */
 public abstract class CookieHandler {
 
@@ -37,9 +35,8 @@
 
     /**
      * Returns the system-wide cookie handler or {@code null} if not set.
-     * 
+     *
      * @return the system-wide cookie handler.
-     * @since Android 1.0
      */
     public static CookieHandler getDefault() {
         SecurityManager sm = System.getSecurityManager();
@@ -51,10 +48,9 @@
 
     /**
      * Sets the system-wide cookie handler.
-     * 
+     *
      * @param cHandler
      *            a cookie handler to set as the system-wide default handler.
-     * @since Android 1.0
      */
     public static void setDefault(CookieHandler cHandler) {
         SecurityManager sm = System.getSecurityManager();
@@ -66,7 +62,7 @@
 
     /**
      * Gets all cookies for a specific URI from the cookie cache.
-     * 
+     *
      * @param uri
      *            a URI to search for applicable cookies.
      * @param requestHeaders
@@ -74,7 +70,6 @@
      * @return an unchangeable map of all appropriate cookies.
      * @throws IOException
      *             if an error occurs during the I/O operation.
-     * @since Android 1.0
      */
     public abstract Map<String, List<String>> get(URI uri,
             Map<String, List<String>> requestHeaders) throws IOException;
@@ -82,14 +77,13 @@
     /**
      * Sets all cookies of a specific URI in the {@code responseHeaders} into
      * the cookie cache.
-     * 
+     *
      * @param uri
      *            the origin URI of the cookies.
      * @param responseHeaders
      *            a list of request headers.
      * @throws IOException
      *             if an error occurs during the I/O operation.
-     * @since Android 1.0
      */
     public abstract void put(URI uri, Map<String, List<String>> responseHeaders)
             throws IOException;
diff --git a/libcore/luni/src/main/java/java/net/DatagramPacket.java b/libcore/luni/src/main/java/java/net/DatagramPacket.java
index bcc531e..7bbf553 100644
--- a/libcore/luni/src/main/java/java/net/DatagramPacket.java
+++ b/libcore/luni/src/main/java/java/net/DatagramPacket.java
@@ -25,20 +25,30 @@
  * such as its source or destination host.
  * 
  * @see DatagramSocket
- * @since Android 1.0
  */
 public final class DatagramPacket {
 
     byte[] data;
 
+    /**
+     * Length of the data to be sent or size of data that was received via
+     * DatagramSocket#receive() method call. 
+     */
     int length;
 
+    /**
+     * Size of internal buffer that is used to store received data. Should be
+     * greater or equal to "length" field.
+     */
+    int capacity;
+
     InetAddress address;
 
     int port = -1; // The default port number is -1
 
     int offset = 0;
 
+
     /**
      * Constructs a new {@code DatagramPacket} object to receive data up to
      * {@code length} bytes.
@@ -47,7 +57,6 @@
      *            a byte array to store the read characters.
      * @param length
      *            the length of the data buffer.
-     * @since Android 1.0
      */
     public DatagramPacket(byte[] data, int length) {
         this(data, 0, length);
@@ -63,7 +72,6 @@
      *            the offset of the byte array where the bytes is written.
      * @param length
      *            the length of the data.
-     * @since Android 1.0
      */
     public DatagramPacket(byte[] data, int offset, int length) {
         super();
@@ -75,7 +83,7 @@
      * {@code aPort} of the address {@code host}. The {@code length} must be
      * lesser than or equal to the size of {@code data}. The first {@code
      * length} bytes from the byte array position {@code offset} are sent.
-     * 
+     *
      * @param data
      *            a byte array which stores the characters to be sent.
      * @param offset
@@ -86,7 +94,6 @@
      *            the address of the target host.
      * @param aPort
      *            the port of the target host.
-     * @since Android 1.0
      */
     public DatagramPacket(byte[] data, int offset, int length,
             InetAddress host, int aPort) {
@@ -100,7 +107,7 @@
      * {@code aPort} of the address {@code host}. The {@code length} must be
      * lesser than or equal to the size of {@code data}. The first {@code
      * length} bytes are sent.
-     * 
+     *
      * @param data
      *            a byte array which stores the characters to be sent.
      * @param length
@@ -109,7 +116,6 @@
      *            the address of the target host.
      * @param port
      *            the port of the target host.
-     * @since Android 1.0
      */
     public DatagramPacket(byte[] data, int length, InetAddress host, int port) {
         this(data, 0, length, host, port);
@@ -120,7 +126,6 @@
      * 
      * @return the address from where the datagram was received or to which it
      *         is sent.
-     * @since Android 1.0
      */
     public synchronized InetAddress getAddress() {
         return address;
@@ -130,7 +135,6 @@
      * Gets the data of this datagram packet.
      * 
      * @return the received data or the data to be sent.
-     * @since Android 1.0
      */
     public synchronized byte[] getData() {
         return data;
@@ -140,7 +144,6 @@
      * Gets the length of the data stored in this datagram packet.
      * 
      * @return the length of the received data or the data to be sent.
-     * @since Android 1.0
      */
     public synchronized int getLength() {
         return length;
@@ -150,7 +153,6 @@
      * Gets the offset of the data stored in this datagram packet.
      * 
      * @return the position of the received data or the data to be sent.
-     * @since Android 1.0
      */
     public synchronized int getOffset() {
         return offset;
@@ -159,9 +161,8 @@
     /**
      * Gets the port number of the target or sender host of this datagram
      * packet.
-     * 
+     *
      * @return the port number of the origin or target host.
-     * @since Android 1.0
      */
     public synchronized int getPort() {
         return port;
@@ -172,7 +173,6 @@
      * 
      * @param addr
      *            the target host address.
-     * @since Android 1.0
      */
     public synchronized void setAddress(InetAddress addr) {
         address = addr;
@@ -188,7 +188,6 @@
      * @param aLength
      *            the length of the data to be sent or the length of buffer to
      *            store the received data.
-     * @since Android 1.0
      */
     public synchronized void setData(byte[] buf, int anOffset, int aLength) {
         if (0 > anOffset || anOffset > buf.length || 0 > aLength
@@ -198,6 +197,7 @@
         data = buf;
         offset = anOffset;
         length = aLength;
+        capacity = aLength;
     }
 
     /**
@@ -206,10 +206,10 @@
      * 
      * @param buf
      *            the buffer to store the data.
-     * @since Android 1.0
      */
     public synchronized void setData(byte[] buf) {
         length = buf.length; // This will check for null
+        capacity = buf.length;
         data = buf;
         offset = 0;
     }
@@ -220,13 +220,13 @@
      * 
      * @param len
      *            the length of this datagram packet.
-     * @since Android 1.0
      */
     public synchronized void setLength(int len) {
         if (0 > len || offset + len > data.length) {
             throw new IllegalArgumentException(Msg.getString("K002f")); //$NON-NLS-1$
         }
         length = len;
+        capacity = len;
     }
 
     /**
@@ -234,7 +234,6 @@
      * 
      * @param aPort
      *            the target host port number.
-     * @since Android 1.0
      */
     public synchronized void setPort(int aPort) {
         if (aPort < 0 || aPort > 65535) {
@@ -257,9 +256,9 @@
      *            the target host address and port.
      * @throws SocketException
      *             if an error in the underlying protocol occurs.
-     * @since Android 1.0
      */
-    public DatagramPacket(byte[] data, int length, SocketAddress sockAddr) throws SocketException {
+    public DatagramPacket(byte[] data, int length, SocketAddress sockAddr)
+            throws SocketException {
         this(data, 0, length);
         setSocketAddress(sockAddr);
     }
@@ -280,7 +279,6 @@
      *            the target host address and port.
      * @throws SocketException
      *             if an error in the underlying protocol occurs.
-     * @since Android 1.0
      */
     public DatagramPacket(byte[] data, int offset, int length,
             SocketAddress sockAddr) throws SocketException {
@@ -291,9 +289,8 @@
     /**
      * Gets the host address and the port to which this datagram packet is sent
      * as a {@code SocketAddress} object.
-     * 
+     *
      * @return the SocketAddress of the target host.
-     * @since Android 1.0
      */
     public synchronized SocketAddress getSocketAddress() {
         return new InetSocketAddress(getAddress(), getPort());
@@ -304,7 +301,6 @@
      * 
      * @param sockAddr
      *            the SocketAddress of the target host.
-     * @since Android 1.0
      */
     public synchronized void setSocketAddress(SocketAddress sockAddr) {
         if (!(sockAddr instanceof InetSocketAddress)) {
diff --git a/libcore/luni/src/main/java/java/net/DatagramSocket.java b/libcore/luni/src/main/java/java/net/DatagramSocket.java
index 0c7745f..ba5e207 100644
--- a/libcore/luni/src/main/java/java/net/DatagramSocket.java
+++ b/libcore/luni/src/main/java/java/net/DatagramSocket.java
@@ -20,19 +20,17 @@
 import java.io.IOException;
 import java.nio.channels.DatagramChannel;
 
-import org.apache.harmony.luni.net.SocketImplProvider;
+import org.apache.harmony.luni.net.PlainDatagramSocketImpl;
 import org.apache.harmony.luni.platform.Platform;
-
 import org.apache.harmony.luni.util.Msg;
 
 /**
  * This class implements a UDP socket for sending and receiving {@code
  * DatagramPacket}. A {@code DatagramSocket} object can be used for both
  * endpoints of a connection for a packet delivery service.
- * 
+ *
  * @see DatagramPacket
  * @see DatagramSocketImplFactory
- * @since Android 1.0
  */
 public class DatagramSocket {
 
@@ -56,16 +54,15 @@
     static {
         Platform.getNetworkSystem().oneTimeInitialization(true);
     }
-    
+
     private Object lock = new Lock();
 
     /**
      * Constructs a UDP datagram socket which is bound to any available port on
      * the localhost.
-     * 
+     *
      * @throws SocketException
      *             if an error occurs while creating or binding the socket.
-     * @since Android 1.0
      */
     public DatagramSocket() throws SocketException {
         this(0);
@@ -75,46 +72,43 @@
      * Constructs a UDP datagram socket which is bound to the specific port
      * {@code aPort} on the localhost. Valid values for {@code aPort} are
      * between 0 and 65535 inclusive.
-     * 
+     *
      * @param aPort
      *            the port to bind on the localhost.
      * @throws SocketException
      *             if an error occurs while creating or binding the socket.
-     * @since Android 1.0
      */
     public DatagramSocket(int aPort) throws SocketException {
         super();
         checkListen(aPort);
-        createSocket(aPort, InetAddress.ANY);
+        createSocket(aPort, Inet4Address.ANY);
     }
 
     /**
      * Constructs a UDP datagram socket which is bound to the specific local
      * address {@code addr} on port {@code aPort}. Valid values for {@code
      * aPort} are between 0 and 65535 inclusive.
-     * 
+     *
      * @param aPort
      *            the port to bind on the localhost.
      * @param addr
      *            the address to bind on the localhost.
      * @throws SocketException
      *             if an error occurs while creating or binding the socket.
-     * @since Android 1.0
      */
     public DatagramSocket(int aPort, InetAddress addr) throws SocketException {
         super();
         checkListen(aPort);
-        createSocket(aPort, null == addr ? InetAddress.ANY : addr);
+        createSocket(aPort, null == addr ? Inet4Address.ANY : addr);
     }
 
     /**
      * Sends prior to attempting to bind the socket, checks whether the port is
      * within the valid port range and verifies with the security manager that
      * the port may be bound by the current context.
-     * 
+     *
      * @param aPort
      *            the port on the localhost that is to be bound.
-     * @since Android 1.0
      */
     void checkListen(int aPort) {
         if (aPort < 0 || aPort > 65535) {
@@ -128,8 +122,6 @@
 
     /**
      * Closes this UDP datagram socket and all possibly associated channels.
-     * 
-     * @since Android 1.0
      */
     // In the documentation jdk1.1.7a/guide/net/miscNet.html, this method is
     // noted as not being synchronized.
@@ -144,12 +136,11 @@
      * validated, thereafter the only validation on {@code send()} and {@code
      * receive()} is to check whether the packet address/port matches the
      * connected target.
-     * 
+     *
      * @param anAddress
      *            the target address of this socket.
      * @param aPort
      *            the target port of this socket.
-     * @since Android 1.0
      */
     public void connect(InetAddress anAddress, int aPort) {
         if (anAddress == null || aPort < 0 || aPort > 65535) {
@@ -189,8 +180,6 @@
     /**
      * Disconnects this UDP datagram socket from the remote host. This method
      * called on an unconnected socket does nothing.
-     * 
-     * @since Android 1.0
      */
     public void disconnect() {
         if (isClosed() || !isConnected()) {
@@ -205,7 +194,7 @@
     synchronized void createSocket(int aPort, InetAddress addr)
             throws SocketException {
         impl = factory != null ? factory.createDatagramSocketImpl()
-                : SocketImplProvider.getDatagramSocketImpl();
+                : new PlainDatagramSocketImpl();
         impl.create();
         try {
             impl.bind(aPort, addr);
@@ -219,10 +208,9 @@
     /**
      * Gets the {@code InetAddress} instance representing the remote address to
      * which this UDP datagram socket is connected.
-     * 
+     *
      * @return the remote address this socket is connected to or {@code null} if
      *         this socket is not connected.
-     * @since Android 1.0
      */
     public InetAddress getInetAddress() {
         return address;
@@ -231,17 +219,16 @@
     /**
      * Gets the {@code InetAddress} instance representing the bound local
      * address of this UDP datagram socket.
-     * 
+     *
      * @return the local address to which this socket is bound to or {@code
      *         null} if this socket is closed.
-     * @since Android 1.0
      */
     public InetAddress getLocalAddress() {
         if (isClosed()) {
             return null;
         }
         if (!isBound()) {
-            return InetAddress.ANY;
+            return Inet4Address.ANY;
         }
         InetAddress anAddr = impl.getLocalAddress();
         try {
@@ -250,17 +237,16 @@
                 security.checkConnect(anAddr.getHostName(), -1);
             }
         } catch (SecurityException e) {
-            return InetAddress.ANY;
+            return Inet4Address.ANY;
         }
         return anAddr;
     }
 
     /**
      * Gets the local port which this socket is bound to.
-     * 
+     *
      * @return the local port of this socket or {@code -1} if this socket is
      *         closed and {@code 0} if it is unbound.
-     * @since Android 1.0
      */
     public int getLocalPort() {
         if (isClosed()) {
@@ -274,10 +260,9 @@
 
     /**
      * Gets the remote port which this socket is connected to.
-     * 
+     *
      * @return the remote port of this socket. The return value {@code -1}
      *         indicates that this socket is not connected.
-     * @since Android 1.0
      */
     public int getPort() {
         return port;
@@ -285,9 +270,8 @@
 
     /**
      * Indicates whether this socket is multicast or not.
-     * 
+     *
      * @return the return value is always {@code false}.
-     * @since Android 1.0
      */
     boolean isMulticastSocket() {
         return false;
@@ -295,11 +279,10 @@
 
     /**
      * Gets the socket receive buffer size. ( {@code SocketOptions.SO_RCVBUF} )
-     * 
+     *
      * @return the input buffer size.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs while getting the option value.
-     * @since Android 1.0
      */
     public synchronized int getReceiveBufferSize() throws SocketException {
         checkClosedAndBind(false);
@@ -308,11 +291,10 @@
 
     /**
      * Gets the socket send buffer size. ( {@code SocketOptions.SO_SNDBUF} )
-     * 
+     *
      * @return the output buffer size.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs while getting the option value.
-     * @since Android 1.0
      */
     public synchronized int getSendBufferSize() throws SocketException {
         checkClosedAndBind(false);
@@ -323,11 +305,10 @@
      * Gets the socket receive timeout in milliseconds. The return value {@code
      * 0} implies the timeout is disabled/infinitive. ( {@code
      * SocketOptions.SO_TIMEOUT} )
-     * 
+     *
      * @return the socket receive timeout.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs while getting the option value.
-     * @since Android 1.0
      */
     public synchronized int getSoTimeout() throws SocketException {
         checkClosedAndBind(false);
@@ -342,42 +323,49 @@
      * has expired. If a security manager exists, its {@code checkAccept} method
      * determines whether or not a packet is discarded. Any packets from
      * unacceptable origins are silently discarded.
-     * 
+     *
      * @param pack
      *            the {@code DatagramPacket} to store the received data.
-     * @exception IOException
+     * @throws IOException
      *                if an error occurs while receiving the packet.
-     * @since Android 1.0
      */
     public synchronized void receive(DatagramPacket pack) throws IOException {
         checkClosedAndBind(true);
 
-        boolean secure = true;
-
-        InetAddress senderAddr = null;
-
-        int senderPort = 0;
+        InetAddress senderAddr;
+        int senderPort;
         DatagramPacket tempPack = new DatagramPacket(new byte[1], 1);
+
+        // means that we have received the packet into the temporary buffer
         boolean copy = false;
 
         SecurityManager security = System.getSecurityManager();
-        if (address != null || security != null) { // The socket is connected
+
+        if (address != null || security != null) {
+            // The socket is connected or we need to check security permissions
+
             // Check pack before peeking
             if (pack == null) {
                 throw new NullPointerException();
             }
-            secure = false;
-            while (!secure) {
+
+            // iterate over incoming packets
+            while (true) {
                 copy = false;
+
+                // let's get sender's address and port
                 try {
                     senderPort = impl.peekData(tempPack);
                     senderAddr = tempPack.getAddress();
                 } catch (SocketException e) {
                     if (e.getMessage().equals(
                             "The socket does not support the operation")) { //$NON-NLS-1$
-                        tempPack = new DatagramPacket(new byte[pack.length],
-                                pack.getLength());
+                        // receive packet to temporary buffer
+                        tempPack = new DatagramPacket(new byte[pack.capacity],
+                                pack.capacity);
                         impl.receive(tempPack);
+                        // tempPack's length field is now updated, capacity is unchanged
+                        // let's extract address & port
                         senderAddr = tempPack.getAddress();
                         senderPort = tempPack.getPort();
                         copy = true;
@@ -385,46 +373,45 @@
                         throw e;
                     }
                 }
+
                 if (address == null) {
+                    // if we are not connected let's check if we are allowed to
+                    // receive packets from sender's address and port
                     try {
                         security.checkAccept(senderAddr.getHostName(),
                                 senderPort);
-                        if (!copy) {
-                            secure = true;
-                        }
+                        // address & port are valid
                         break;
                     } catch (SecurityException e) {
                         if (!copy) {
-                            if (tempPack == null) {
-                                tempPack = new DatagramPacket(
-                                        new byte[pack.length], pack.length);
-                            }
+                            // drop this packet and continue
                             impl.receive(tempPack);
                         }
                     }
                 } else if (port == senderPort && address.equals(senderAddr)) {
-                    if (!copy) {
-                        secure = true;
-                    }
+                    // we are connected and the packet came
+                    // from the address & port we are connected to
                     break;
                 } else if (!copy) {
-                    if (tempPack == null) {
-                        tempPack = new DatagramPacket(new byte[pack.length],
-                                pack.length);
-                    }
+                    // drop packet and continue
                     impl.receive(tempPack);
                 }
             }
         }
+
         if (copy) {
             System.arraycopy(tempPack.getData(), 0, pack.getData(), pack
                     .getOffset(), tempPack.getLength());
-            pack.setLength(tempPack.getLength());
+            // we shouldn't update the pack's capacity field in order to be
+            // compatible with RI
+            pack.length = tempPack.length;
             pack.setAddress(tempPack.getAddress());
             pack.setPort(tempPack.getPort());
-        }
-        if (secure) {
+        } else {
+            pack.setLength(pack.capacity);
             impl.receive(pack);
+            // pack's length field is now updated by native code call;
+            // pack's capacity field is unchanged
         }
     }
 
@@ -433,12 +420,11 @@
      * policy before it may be sent. If a security manager is installed, this
      * method checks whether it is allowed to send this packet to the specified
      * address.
-     * 
+     *
      * @param pack
      *            the {@code DatagramPacket} which has to be sent.
-     * @exception IOException
+     * @throws IOException
      *                if an error occurs while sending the packet.
-     * @since Android 1.0
      */
     public void send(DatagramPacket pack) throws IOException {
         checkClosedAndBind(true);
@@ -480,12 +466,11 @@
      * maximum packet size is that can be sent over this socket. It depends on
      * the network implementation what will happen if the packet is bigger than
      * the buffer size. ( {@code SocketOptions.SO_SNDBUF} )
-     * 
+     *
      * @param size
      *            the buffer size in bytes. The size must be at least one byte.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs while setting the option.
-     * @since Android 1.0
      */
     public synchronized void setSendBufferSize(int size) throws SocketException {
         if (size < 1) {
@@ -500,12 +485,11 @@
      * the maximum packet size is that can be received over this socket. It
      * depends on the network implementation what will happen if the packet is
      * bigger than the buffer size. ( {@code SocketOptions.SO_RCVBUF} )
-     * 
+     *
      * @param size
      *            the buffer size in bytes. The size must be at least one byte.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs while setting the option.
-     * @since Android 1.0
      */
     public synchronized void setReceiveBufferSize(int size)
             throws SocketException {
@@ -523,12 +507,11 @@
      * {@code 0} (default) is used to set an infinite timeout. To have effect
      * this option must be set before the blocking method was called. ( {@code
      * SocketOptions.SO_TIMEOUT} )
-     * 
+     *
      * @param timeout
      *            the timeout period in milliseconds or {@code 0} for infinite.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs while setting the option.
-     * @since Android 1.0
      */
     public synchronized void setSoTimeout(int timeout) throws SocketException {
         if (timeout < 0) {
@@ -545,13 +528,12 @@
      * method {@code checkSetFactory()} is called to check if the operation is
      * allowed. A {@code SecurityException} is thrown if the operation is not
      * allowed.
-     * 
+     *
      * @param fac
      *            the socket factory to use.
-     * @exception IOException
+     * @throws IOException
      *                if the factory has already been set.
      * @see DatagramSocketImplFactory
-     * @since Android 1.0
      */
     public static synchronized void setDatagramSocketImplFactory(
             DatagramSocketImplFactory fac) throws IOException {
@@ -569,10 +551,9 @@
      * Constructs a new {@code DatagramSocket} using the specific datagram
      * socket implementation {@code socketImpl}. The created {@code
      * DatagramSocket} will not be bound.
-     * 
+     *
      * @param socketImpl
      *            the DatagramSocketImpl to use.
-     * @since Android 1.0
      */
     protected DatagramSocket(DatagramSocketImpl socketImpl) {
         if (socketImpl == null) {
@@ -585,12 +566,13 @@
      * Constructs a new {@code DatagramSocket} bound to the host/port specified
      * by the {@code SocketAddress} {@code localAddr} or an unbound {@code
      * DatagramSocket} if the {@code SocketAddress} is {@code null}.
-     * 
+     *
      * @param localAddr
      *            the local machine address and port to bind to.
+     * @throws IllegalArgumentException
+     *             if the SocketAddress is not supported
      * @throws SocketException
      *             if a problem occurs creating or binding the socket.
-     * @since Android 1.0
      */
     public DatagramSocket(SocketAddress localAddr) throws SocketException {
         if (localAddr != null) {
@@ -601,7 +583,7 @@
             checkListen(((InetSocketAddress) localAddr).getPort());
         }
         impl = factory != null ? factory.createDatagramSocketImpl()
-                : SocketImplProvider.getDatagramSocketImpl();
+                : new PlainDatagramSocketImpl();
         impl.create();
         if (localAddr != null) {
             try {
@@ -621,7 +603,7 @@
         }
         if (bind && !isBound()) {
             checkListen(0);
-            impl.bind(0, InetAddress.ANY);
+            impl.bind(0, Inet4Address.ANY);
             isBound = true;
         }
     }
@@ -630,18 +612,19 @@
      * Binds this socket to the local address and port specified by {@code
      * localAddr}. If this value is {@code null} any free port on a valid local
      * address is used.
-     * 
+     *
      * @param localAddr
      *            the local machine address and port to bind on.
+     * @throws IllegalArgumentException
+     *             if the SocketAddress is not supported
      * @throws SocketException
      *             if the socket is already bound or a problem occurs during
      *             binding.
-     * @since Android 1.0
      */
     public void bind(SocketAddress localAddr) throws SocketException {
         checkClosedAndBind(false);
         int localPort = 0;
-        InetAddress addr = InetAddress.ANY;
+        InetAddress addr = Inet4Address.ANY;
         if (localAddr != null) {
             if (!(localAddr instanceof InetSocketAddress)) {
                 throw new IllegalArgumentException(Msg.getString(
@@ -665,12 +648,11 @@
      * {@code remoteAddr}. The host and port are validated, thereafter the only
      * validation on {@code send()} and {@code receive()} is that the packet
      * address/port matches the connected target.
-     * 
+     *
      * @param remoteAddr
      *            the address and port of the target host.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs during connecting.
-     * @since Android 1.0
      */
     public void connect(SocketAddress remoteAddr) throws SocketException {
         if (remoteAddr == null) {
@@ -720,9 +702,8 @@
 
     /**
      * Determines whether the socket is bound to an address or not.
-     * 
+     *
      * @return {@code true} if the socket is bound, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isBound() {
         return isBound;
@@ -730,9 +711,8 @@
 
     /**
      * Determines whether the socket is connected to a target host.
-     * 
+     *
      * @return {@code true} if the socket is connected, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isConnected() {
         return isConnected;
@@ -741,9 +721,8 @@
     /**
      * Gets the address and port of the connected remote host. If this socket is
      * not connected yet, {@code null} is returned.
-     * 
+     *
      * @return the remote socket address.
-     * @since Android 1.0
      */
     public SocketAddress getRemoteSocketAddress() {
         if (!isConnected()) {
@@ -755,9 +734,8 @@
     /**
      * Gets the bound local address and port of this socket. If the socket is
      * unbound, {@code null} is returned.
-     * 
+     *
      * @return the local socket address.
-     * @since Android 1.0
      */
     public SocketAddress getLocalSocketAddress() {
         if (!isBound()) {
@@ -773,13 +751,11 @@
      * <p>
      * There is an undefined behavior if this option is set after the socket is
      * already bound.
-     * </p>
-     * 
+     *
      * @param reuse
      *            the socket option value to enable or disable this option.
      * @throws SocketException
      *             if the socket is closed or the option could not be set.
-     * @since Android 1.0
      */
     public void setReuseAddress(boolean reuse) throws SocketException {
         checkClosedAndBind(false);
@@ -789,11 +765,10 @@
 
     /**
      * Gets the state of the socket option {@code SocketOptions.SO_REUSEADDR}.
-     * 
+     *
      * @return {@code true} if the option is enabled, {@code false} otherwise.
      * @throws SocketException
      *             if the socket is closed or the option is invalid.
-     * @since Android 1.0
      */
     public boolean getReuseAddress() throws SocketException {
         checkClosedAndBind(false);
@@ -804,12 +779,11 @@
     /**
      * Sets the socket option {@code SocketOptions.SO_BROADCAST}. This option
      * must be enabled to send broadcast messages.
-     * 
+     *
      * @param broadcast
      *            the socket option value to enable or disable this option.
      * @throws SocketException
      *             if the socket is closed or the option could not be set.
-     * @since Android 1.0
      */
     public void setBroadcast(boolean broadcast) throws SocketException {
         checkClosedAndBind(false);
@@ -819,11 +793,10 @@
 
     /**
      * Gets the state of the socket option {@code SocketOptions.SO_BROADCAST}.
-     * 
+     *
      * @return {@code true} if the option is enabled, {@code false} otherwise.
      * @throws SocketException
      *             if the socket is closed or the option is invalid.
-     * @since Android 1.0
      */
     public boolean getBroadcast() throws SocketException {
         checkClosedAndBind(false);
@@ -839,13 +812,11 @@
      * <p>
      * Values between {@code 0} and {@code 255} inclusive are valid for this
      * option.
-     * </p>
-     * 
+     *
      * @param value
      *            the socket option value to be set as type-of-service.
      * @throws SocketException
      *             if the socket is closed or the option could not be set.
-     * @since Android 1.0
      */
     public void setTrafficClass(int value) throws SocketException {
         checkClosedAndBind(false);
@@ -858,11 +829,10 @@
     /**
      * Gets the value of the type-of-service socket option {@code
      * SocketOptions.IP_TOS}.
-     * 
+     *
      * @return the type-of-service socket option value.
      * @throws SocketException
      *             if the socket is closed or the option is invalid.
-     * @since Android 1.0
      */
     public int getTrafficClass() throws SocketException {
         checkClosedAndBind(false);
@@ -871,9 +841,8 @@
 
     /**
      * Gets the state of this socket.
-     * 
+     *
      * @return {@code true} if the socket is closed, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isClosed() {
         return isClosed;
@@ -882,10 +851,9 @@
     /**
      * Gets the related DatagramChannel of this socket. This implementation
      * returns always {@code null}.
-     * 
+     *
      * @return the related DatagramChannel or {@code null} if this socket was
      *         not created by a {@code DatagramChannel} object.
-     * @since Android 1.0
      */
     public DatagramChannel getChannel() {
         return null;
diff --git a/libcore/luni/src/main/java/java/net/DatagramSocketImpl.java b/libcore/luni/src/main/java/java/net/DatagramSocketImpl.java
index 7915156..db3b9ec 100644
--- a/libcore/luni/src/main/java/java/net/DatagramSocketImpl.java
+++ b/libcore/luni/src/main/java/java/net/DatagramSocketImpl.java
@@ -25,29 +25,21 @@
 
 /**
  * The abstract superclass for datagram and multicast socket implementations.
- * 
- * @since Android 1.0
  */
 public abstract class DatagramSocketImpl implements SocketOptions {
 
     /**
      * File descriptor that is used to address this socket.
-     * 
-     * @since Android 1.0
      */
     protected FileDescriptor fd;
 
     /**
      * The number of the local port to which this socket is bound.
-     * 
-     * @since Android 1.0
      */
     protected int localPort;
 
     /**
      * Constructs an unbound datagram socket implementation.
-     * 
-     * @since Android 1.0
      */
     public DatagramSocketImpl() {
         localPort = -1;
@@ -61,28 +53,24 @@
      *            the port on the localhost to bind.
      * @param addr
      *            the address on the multihomed localhost to bind.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs while binding, for example, if the port
      *                has been already bound.
-     * @since Android 1.0
      */
     protected abstract void bind(int port, InetAddress addr)
             throws SocketException;
 
     /**
      * Closes this socket.
-     * 
-     * @since Android 1.0
      */
     protected abstract void close();
 
     /**
      * This method allocates the socket descriptor in the underlying operating
      * system.
-     * 
+     *
      * @throws SocketException
      *             if an error occurs while creating the socket.
-     * @since Android 1.0
      */
     protected abstract void create() throws SocketException;
 
@@ -91,7 +79,6 @@
      * if the socket is closed or not bound.
      * 
      * @return the current file descriptor of this socket.
-     * @since Android 1.0
      */
     protected FileDescriptor getFileDescriptor() {
         return fd;
@@ -101,7 +88,6 @@
      * Gets the local address to which the socket is bound.
      * 
      * @return the local address to which the socket is bound.
-     * @since Android 1.0
      */
     InetAddress getLocalAddress() {
         return Platform.getNetworkSystem().getSocketLocalAddress(fd,
@@ -112,7 +98,6 @@
      * Gets the local port of this socket.
      * 
      * @return the local port to which this socket is bound.
-     * @since Android 1.0
      */
     protected int getLocalPort() {
         return localPort;
@@ -124,9 +109,8 @@
      * @param optID
      *            the ID of the socket option to be retrieved.
      * @return the requested option value.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs while accessing the option.
-     * @since Android 1.0
      */
     public abstract Object getOption(int optID) throws SocketException;
 
@@ -139,7 +123,6 @@
      *             value.
      * @deprecated Replaced by {@link #getTimeToLive}
      * @see #getTimeToLive()
-     * @since Android 1.0
      */
     @Deprecated
     protected abstract byte getTTL() throws IOException;
@@ -148,12 +131,11 @@
      * Gets the time-to-live (TTL) for multicast packets sent on this socket.
      * The TTL option defines how many routers a packet may be pass before it is
      * discarded.
-     * 
+     *
      * @return the time-to-live option as an integer value.
      * @throws IOException
      *             if an error occurs while getting the time-to-live option
      *             value.
-     * @since Android 1.0
      */
     protected abstract int getTimeToLive() throws IOException;
 
@@ -167,7 +149,6 @@
      * @throws IOException
      *             if an error occurs while joining the specified multicast
      *             group.
-     * @since Android 1.0
      */
     protected abstract void join(InetAddress addr) throws IOException;
 
@@ -184,7 +165,6 @@
      * @throws IOException
      *             if an error occurs while joining the specified multicast
      *             group.
-     * @since Android 1.0
      */
     protected abstract void joinGroup(SocketAddress addr,
             NetworkInterface netInterface) throws IOException;
@@ -197,7 +177,6 @@
      * @throws IOException
      *             if an error occurs while leaving the group or no multicast
      *             address was assigned.
-     * @since Android 1.0
      */
     protected abstract void leave(InetAddress addr) throws IOException;
 
@@ -211,7 +190,6 @@
      *            removed.
      * @throws IOException
      *             if an error occurs while leaving the group.
-     * @since Android 1.0
      */
     protected abstract void leaveGroup(SocketAddress addr,
             NetworkInterface netInterface) throws IOException;
@@ -224,9 +202,8 @@
      * @param sender
      *            the origin address of a packet.
      * @return the address of {@code sender} as an integer value.
-     * @exception IOException
+     * @throws IOException
      *                if an error or a timeout occurs while reading the address.
-     * @since Android 1.0
      */
     protected abstract int peek(InetAddress sender) throws IOException;
 
@@ -238,9 +215,8 @@
      * 
      * @param pack
      *            the datagram packet container to fill in the received data.
-     * @exception IOException
+     * @throws IOException
      *                if an error or timeout occurs while receiving data.
-     * @since Android 1.0
      */
     protected abstract void receive(DatagramPacket pack) throws IOException;
 
@@ -250,9 +226,8 @@
      * 
      * @param pack
      *            the datagram packet to be sent.
-     * @exception IOException
+     * @throws IOException
      *                if an error occurs while sending the packet.
-     * @since Android 1.0
      */
     protected abstract void send(DatagramPacket pack) throws IOException;
 
@@ -263,9 +238,8 @@
      *            the ID of the socket option to be set.
      * @param val
      *            the value of the option.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs while setting the option.
-     * @since Android 1.0
      */
     public abstract void setOption(int optID, Object val)
             throws SocketException;
@@ -279,7 +253,6 @@
      *            &lt;= 255.
      * @throws IOException
      *             if an error occurs while setting the option.
-     * @since Android 1.0
      */
     protected abstract void setTimeToLive(int ttl) throws IOException;
 
@@ -294,7 +267,6 @@
      *             if an error occurs while setting the option.
      * @deprecated Replaced by {@link #setTimeToLive}
      * @see #setTimeToLive(int)
-     * @since Android 1.0
      */
     @Deprecated
     protected abstract void setTTL(byte ttl) throws IOException;
@@ -306,10 +278,9 @@
      *            the address of the target host which has to be connected.
      * @param port
      *            the port on the target host which has to be connected.
-     * @exception SocketException
+     * @throws SocketException
      *                if the datagram socket cannot be connected to the
      *                specified remote address and port.
-     * @since Android 1.0
      */
     protected void connect(InetAddress inetAddr, int port)
             throws SocketException {
@@ -318,8 +289,6 @@
 
     /**
      * Disconnects this socket from the remote host.
-     * 
-     * @since Android 1.0
      */
     protected void disconnect() {
         // do nothing
@@ -335,9 +304,8 @@
      * @param pack
      *            the datagram packet used to store the data.
      * @return the port the packet was received from.
-     * @exception IOException
+     * @throws IOException
      *                if an error occurs while peeking at the data.
-     * @since Android 1.0
      */
     protected abstract int peekData(DatagramPacket pack) throws IOException;
 }
diff --git a/libcore/luni/src/main/java/java/net/DatagramSocketImplFactory.java b/libcore/luni/src/main/java/java/net/DatagramSocketImplFactory.java
index b97146e..ce91738 100644
--- a/libcore/luni/src/main/java/java/net/DatagramSocketImplFactory.java
+++ b/libcore/luni/src/main/java/java/net/DatagramSocketImplFactory.java
@@ -23,7 +23,6 @@
  * implementation.
  * 
  * @see DatagramSocket
- * @since Android 1.0
  */
 public interface DatagramSocketImplFactory {
     
@@ -31,7 +30,6 @@
      * Creates a new {@code DatagramSocketImpl} instance.
      * 
      * @return the new datagram socket implementation.
-     * @since Android 1.0
      */
     DatagramSocketImpl createDatagramSocketImpl();
 }
diff --git a/libcore/luni/src/main/java/java/net/FileNameMap.java b/libcore/luni/src/main/java/java/net/FileNameMap.java
index e8ac35f..16fa0e0 100644
--- a/libcore/luni/src/main/java/java/net/FileNameMap.java
+++ b/libcore/luni/src/main/java/java/net/FileNameMap.java
@@ -26,7 +26,6 @@
  * @see URLConnection#getFileNameMap()
  * @see URLConnection#guessContentTypeFromName(String)
  * @see URLStreamHandler
- * @since Android 1.0
  */
 public interface FileNameMap {
 
@@ -36,7 +35,6 @@
      * @param fileName
      *            the name of the file to consider.
      * @return the appropriate MIME type of the given file.
-     * @since Android 1.0
      */
     public String getContentTypeFor(String fileName);
 }
diff --git a/libcore/luni/src/main/java/java/net/HttpRetryException.java b/libcore/luni/src/main/java/java/net/HttpRetryException.java
index 5f613ab..4ad14bd 100644
--- a/libcore/luni/src/main/java/java/net/HttpRetryException.java
+++ b/libcore/luni/src/main/java/java/net/HttpRetryException.java
@@ -21,8 +21,6 @@
 /**
  * If a HTTP request has to be retried, this exception will be thrown if the
  * request cannot be retried automatically.
- * 
- * @since Android 1.0
  */
 public class HttpRetryException extends IOException {
 
@@ -40,7 +38,6 @@
      *            the detail message for this exception.
      * @param code
      *            the HTTP response code from target host.
-     * @since Android 1.0
      */
     public HttpRetryException(String detail, int code) {
         super(detail);
@@ -58,7 +55,6 @@
      *            the HTTP response code from target host.
      * @param location
      *            the destination URL of the redirection.
-     * @since Android 1.0
      */
     public HttpRetryException(String detail, int code, String location) {
         super(detail);
@@ -68,9 +64,8 @@
 
     /**
      * Gets the location value.
-     * 
+     *
      * @return the stored location from the HTTP header.
-     * @since Android 1.0
      */
     public String getLocation() {
         return location;
@@ -78,9 +73,8 @@
 
     /**
      * Gets the detail message.
-     * 
+     *
      * @return the detail message.
-     * @since Android 1.0
      */
     public String getReason() {
         return getMessage();
@@ -88,9 +82,8 @@
 
     /**
      * Gets the response code.
-     * 
+     *
      * @return the HTTP response code.
-     * @since Android 1.0
      */
     public int responseCode() {
         return responseCode;
diff --git a/libcore/luni/src/main/java/java/net/HttpURLConnection.java b/libcore/luni/src/main/java/java/net/HttpURLConnection.java
index 55cc363..6be891f 100644
--- a/libcore/luni/src/main/java/java/net/HttpURLConnection.java
+++ b/libcore/luni/src/main/java/java/net/HttpURLConnection.java
@@ -29,7 +29,6 @@
  * @see URL
  * @see URLConnection
  * @see URLStreamHandler
- * @since Android 1.0
  */
 public abstract class HttpURLConnection extends URLConnection {
     @SuppressWarnings("nls")
@@ -39,8 +38,6 @@
    /**
      * The HTTP request method of this {@code HttpURLConnection}. The default
      * value is {@code "GET"}.
-     * 
-     * @since Android 1.0
      */
     protected String method = "GET"; //$NON-NLS-1$
 
@@ -53,24 +50,17 @@
      * <li>3xx: Relocation/Redirection</li>
      * <li>4xx: Client Error</li>
      * <li>5xx: Server Error</li>
-     * </p>
-     * 
-     * @since Android 1.0
      */
     protected int responseCode = -1;
 
     /**
      * The HTTP response message which corresponds to the response code.
-     * 
-     * @since Android 1.0
      */
     protected String responseMessage;
 
     /**
      * Flag to define whether the protocol will automatically follow redirects
      * or not. The default value is {@code true}.
-     * 
-     * @since Android 1.0
      */
     protected boolean instanceFollowRedirects = followRedirects;
 
@@ -80,8 +70,6 @@
      * If the HTTP chunked encoding is enabled this parameter defines the
      * chunk-length. Default value is {@code -1} that means the chunked encoding
      * mode is disabled.
-     * 
-     * @since Android 1.0
      */
     protected int chunkLength = -1;
 
@@ -89,8 +77,6 @@
      * If using HTTP fixed-length streaming mode this parameter defines the
      * fixed length of content. Default value is {@code -1} that means the
      * fixed-length streaming mode is disabled.
-     * 
-     * @since Android 1.0
      */
     protected int fixedContentLength = -1;
 
@@ -102,255 +88,184 @@
     // 5XX: server error
     /**
      * Numeric status code, 202: Accepted
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_ACCEPTED = 202;
 
     /**
      * Numeric status code, 502: Bad Gateway
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_BAD_GATEWAY = 502;
 
     /**
      * Numeric status code, 405: Bad Method
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_BAD_METHOD = 405;
 
     /**
      * Numeric status code, 400: Bad Request
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_BAD_REQUEST = 400;
 
     /**
      * Numeric status code, 408: Client Timeout
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_CLIENT_TIMEOUT = 408;
 
     /**
      * Numeric status code, 409: Conflict
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_CONFLICT = 409;
 
     /**
      * Numeric status code, 201: Created
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_CREATED = 201;
 
     /**
      * Numeric status code, 413: Entity too large
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_ENTITY_TOO_LARGE = 413;
 
     /**
      * Numeric status code, 403: Forbidden
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_FORBIDDEN = 403;
 
     /**
      * Numeric status code, 504: Gateway timeout
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_GATEWAY_TIMEOUT = 504;
 
     /**
      * Numeric status code, 410: Gone
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_GONE = 410;
 
     /**
      * Numeric status code, 500: Internal error
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_INTERNAL_ERROR = 500;
 
     /**
      * Numeric status code, 411: Length required
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_LENGTH_REQUIRED = 411;
 
     /**
      * Numeric status code, 301 Moved permanently
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_MOVED_PERM = 301;
 
     /**
      * Numeric status code, 302: Moved temporarily
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_MOVED_TEMP = 302;
 
     /**
      * Numeric status code, 300: Multiple choices
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_MULT_CHOICE = 300;
 
     /**
      * Numeric status code, 204: No content
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_NO_CONTENT = 204;
 
     /**
      * Numeric status code, 406: Not acceptable
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_NOT_ACCEPTABLE = 406;
 
     /**
      * Numeric status code, 203: Not authoritative
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_NOT_AUTHORITATIVE = 203;
 
     /**
      * Numeric status code, 404: Not found
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_NOT_FOUND = 404;
 
     /**
      * Numeric status code, 501: Not implemented
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_NOT_IMPLEMENTED = 501;
 
     /**
      * Numeric status code, 304: Not modified
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_NOT_MODIFIED = 304;
 
     /**
      * Numeric status code, 200: OK
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_OK = 200;
 
     /**
      * Numeric status code, 206: Partial
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_PARTIAL = 206;
 
     /**
      * Numeric status code, 402: Payment required
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_PAYMENT_REQUIRED = 402;
 
     /**
      * Numeric status code, 412: Precondition failed
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_PRECON_FAILED = 412;
 
     /**
      * Numeric status code, 407: Proxy authentication required
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_PROXY_AUTH = 407;
 
     /**
      * Numeric status code, 414: Request too long
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_REQ_TOO_LONG = 414;
 
     /**
      * Numeric status code, 205: Reset
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_RESET = 205;
 
     /**
      * Numeric status code, 303: See other
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_SEE_OTHER = 303;
 
     /**
      * Numeric status code, 500: Internal error
-     * 
+     *
      * @deprecated Use {@link #HTTP_INTERNAL_ERROR}
-     * @since Android 1.0
      */
     @Deprecated
     public final static int HTTP_SERVER_ERROR = 500;
 
     /**
      * Numeric status code, 305: Use proxy
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_USE_PROXY = 305;
 
     /**
      * Numeric status code, 401: Unauthorized
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_UNAUTHORIZED = 401;
 
     /**
      * Numeric status code, 415: Unsupported type
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_UNSUPPORTED_TYPE = 415;
 
     /**
      * Numeric status code, 503: Unavailable
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_UNAVAILABLE = 503;
 
     /**
      * Numeric status code, 505: Version not supported
-     * 
-     * @since Android 1.0
      */
     public final static int HTTP_VERSION = 505;
 
@@ -362,7 +277,6 @@
      *            the URL of this connection.
      * @see URL
      * @see URLConnection
-     * @since Android 1.0
      */
     protected HttpURLConnection(URL url) {
         super(url);
@@ -373,7 +287,6 @@
      * 
      * @see URLConnection#connect()
      * @see URLConnection#connected
-     * @since Android 1.0
      */
     public abstract void disconnect();
 
@@ -383,7 +296,6 @@
      * can be used to read the data the server will send back.
      * 
      * @return the error input stream returned by the server.
-     * @since Android 1.0
      */
     public java.io.InputStream getErrorStream() {
         return null;
@@ -396,7 +308,6 @@
      * 
      * @return the value of the flag.
      * @see #setFollowRedirects
-     * @since Android 1.0
      */
     public static boolean getFollowRedirects() {
         return followRedirects;
@@ -412,7 +323,6 @@
      * @throws IOException
      *             if an IO exception occurs during the creation of the
      *             permission object.
-     * @since Android 1.0
      */
     @Override
     public java.security.Permission getPermission() throws IOException {
@@ -432,7 +342,6 @@
      * @return the request method string.
      * @see #method
      * @see #setRequestMethod
-     * @since Android 1.0
      */
     public String getRequestMethod() {
         return method;
@@ -445,7 +354,6 @@
      * @throws IOException
      *             if there is an IO error during the retrieval.
      * @see #getResponseMessage
-     * @since Android 1.0
      */
     public int getResponseCode() throws IOException {
         // Call getInputStream() first since getHeaderField() doesn't return
@@ -478,7 +386,6 @@
      * @throws IOException
      *             if there is an error during the retrieval.
      * @see #getResponseCode()
-     * @since Android 1.0
      */
     public String getResponseMessage() throws IOException {
         if (responseMessage != null) {
@@ -496,7 +403,6 @@
      * @param auto
      *            the value to enable or disable this option.
      * @see SecurityManager#checkSetFactory()
-     * @since Android 1.0
      */
     public static void setFollowRedirects(boolean auto) {
         SecurityManager security = System.getSecurityManager();
@@ -517,7 +423,6 @@
      *             supported by this HTTP implementation.
      * @see #getRequestMethod()
      * @see #method
-     * @since Android 1.0
      */
     public void setRequestMethod(String method) throws ProtocolException {
         if (connected) {
@@ -540,7 +445,6 @@
      * 
      * @return {@code true} if this connection passes a proxy server, false
      *         otherwise.
-     * @since Android 1.0
      */
     public abstract boolean usingProxy();
 
@@ -549,7 +453,6 @@
      * 
      * @return {@code true} if this connection follows redirects, false
      *         otherwise.
-     * @since Android 1.0
      */
     public boolean getInstanceFollowRedirects() {
         return instanceFollowRedirects;
@@ -561,7 +464,6 @@
      * @param followRedirects
      *            {@code true} if this connection will follows redirects, false
      *            otherwise.
-     * @since Android 1.0
      */
     public void setInstanceFollowRedirects(boolean followRedirects) {
         instanceFollowRedirects = followRedirects;
@@ -579,7 +481,6 @@
      *            found.
      * @return the header field represented in milliseconds since January 1,
      *         1970 GMT.
-     * @since Android 1.0
      */
     @Override
     public long getHeaderFieldDate(String field, long defaultValue) {
@@ -598,7 +499,6 @@
      *             if already connected or an other mode already set.
      * @throws IllegalArgumentException
      *             if {@code contentLength} is less than zero.
-     * @since Android 1.0
      */
     public void setFixedLengthStreamingMode(int contentLength) {
         if (super.connected) {
@@ -624,7 +524,6 @@
      *            the length of a chunk.
      * @throws IllegalStateException
      *             if already connected or an other mode already set.
-     * @since Android 1.0
      */
     public void setChunkedStreamingMode(int chunklen) {
         if (super.connected) {
diff --git a/libcore/luni/src/main/java/java/net/Inet4Address.java b/libcore/luni/src/main/java/java/net/Inet4Address.java
index dd6b088..b467b64 100644
--- a/libcore/luni/src/main/java/java/net/Inet4Address.java
+++ b/libcore/luni/src/main/java/java/net/Inet4Address.java
@@ -28,18 +28,22 @@
  * address ({@code b.bbb} ) allows to represent a class A network address as
  * <i>net.host</i>. If there is only one part ({@code bbbb} ) the address is
  * represented without any byte rearrangement.
- * 
- * @since Android 1.0
  */
 public final class Inet4Address extends InetAddress {
 
     private static final long serialVersionUID = 3286316764910316507L;
 
+    final static InetAddress ANY = new Inet4Address(new byte[] { 0, 0, 0, 0 });
+    final static InetAddress LOOPBACK = new Inet4Address(
+            new byte[] { 127, 0, 0, 1 }, "localhost"); //$NON-NLS-1$
+
     Inet4Address(byte[] address) {
+        family = AF_INET;
         ipaddress = address;
     }
 
     Inet4Address(byte[] address, String name) {
+        family = AF_INET;
         ipaddress = address;
         hostName = name;
     }
@@ -50,7 +54,6 @@
      * 
      * @return {@code true} if this instance represents a multicast address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isMulticastAddress() {
@@ -63,7 +66,6 @@
      * 
      * @return {@code true} if this instance represents the wildcard ANY
      *         address, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isAnyLocalAddress() {
@@ -81,7 +83,6 @@
      * 
      * @return {@code true} if this instance represents a lookback address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isLoopbackAddress() {
@@ -95,11 +96,9 @@
      * Default Address Selection for Internet Protocol Version 6 (IPv6) states
      * IPv4 auto-configuration addresses, prefix 169.254/16, IPv4 loopback
      * addresses, prefix 127/8, are assigned link-local scope.
-     * </p>
-     * 
+     *
      * @return {@code true} if this instance represents a link-local address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isLinkLocalAddress() {
@@ -115,11 +114,9 @@
      * Default Address Selection for Internet Protocol Version 6 (IPv6) states
      * IPv4 private addresses, prefixes 10/8, 172.16/12, and 192.168/16, are
      * assigned site-local scope.
-     * </p>
      * 
      * @return {@code true} if this instance represents a site-local address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isSiteLocalAddress() {
@@ -135,7 +132,6 @@
      * 
      * @return {@code true} if the address is in the global multicast group,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isMCGlobal() {
@@ -174,7 +170,6 @@
      * addresses.
      * 
      * @return {@code false} for all IPv4 addresses.
-     * @since Android 1.0
      */
     @Override
     public boolean isMCNodeLocal() {
@@ -188,7 +183,6 @@
      * 
      * @return {@code true} if this instance represents a link-local address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isMCLinkLocal() {
@@ -202,7 +196,6 @@
      * 
      * @return {@code true} if this instance represents a site-local address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isMCSiteLocal() {
@@ -217,7 +210,6 @@
      * 
      * @return {@code true} if this instance represents a organization-local
      *         address, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isMCOrgLocal() {
@@ -225,51 +217,22 @@
         return prefix >= 0xEFC0 && prefix <= 0xEFC3;
     }
 
-    /**
-     * Returns a textual representation of this IP address.
-     * 
-     * @return the textual representation of this host address.
-     * @since Android 1.0
-     */
-    @Override
-    public String getHostAddress() {
-        String hostAddress = ""; //$NON-NLS-1$
-        for (int i = 0; i < 4; i++) {
-            hostAddress += ipaddress[i] & 255;
-            if (i != 3) {
-                hostAddress += "."; //$NON-NLS-1$
-            }
-        }
-        return hostAddress;
-    }
+    // BEGIN android-removed
+    // public String getHostAddress() {
+    // }
+    // END android-removed
 
-    /**
-     * Gets the hashcode of the represented IP address.
-     * 
-     * @return the appropriate hashcode value.
-     * @since Android 1.0
-     */
-    @Override
-    public int hashCode() {
-        return InetAddress.bytesToInt(ipaddress, 0);
-    }
+    // BEGIN android-removed
+    // public int hashCode() {
+    // }
+    // END android-removed
 
-    /**
-     * Compares this instance with the IP address in the object {@code obj} and
-     * returns {@code true} if they are of the same type and represent the same
-     * IP address, {@code false} otherwise.
-     * 
-     * @param obj
-     *            the object to be tested for equality.
-     * @return {@code true} if the addresses are equal, {@code false} otherwise.
-     * @since Android 1.0
-     */
-    @Override
-    public boolean equals(Object obj) {
-        return super.equals(obj);
-    }
+    // BEGIN android-removed
+    // public boolean equals(Object obj) {
+    // }
+    // END android-removed
 
     private Object writeReplace() throws ObjectStreamException {
-        return new InetAddress(ipaddress, hostName);
+        return new Inet4Address(ipaddress, hostName);
     }
 }
diff --git a/libcore/luni/src/main/java/java/net/Inet6Address.java b/libcore/luni/src/main/java/java/net/Inet6Address.java
index 4c10faa..f333770 100644
--- a/libcore/luni/src/main/java/java/net/Inet6Address.java
+++ b/libcore/luni/src/main/java/java/net/Inet6Address.java
@@ -28,23 +28,15 @@
 
 /**
  * This class represents a 128 bit long IPv6 address.
- * 
- * @since Android 1.0
  */
 public final class Inet6Address extends InetAddress {
 
     private static final long serialVersionUID = 6880410070516793377L;
 
-    static final byte[] any_bytes = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0 };
-
-    static final byte[] localhost_bytes = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 1 };
-
-    static final InetAddress ANY = new Inet6Address(any_bytes);
-
-    static final InetAddress LOOPBACK = new Inet6Address(localhost_bytes,
-            "localhost"); //$NON-NLS-1$
+    static final InetAddress ANY = new Inet6Address(new byte[]
+            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });
+    static final InetAddress LOOPBACK = new Inet6Address(new byte[]
+            {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, "localhost"); //$NON-NLS-1$
 
     int scope_id;
 
@@ -60,11 +52,13 @@
     transient NetworkInterface scopedIf;
 
     Inet6Address(byte address[]) {
+        family = AF_INET6;
         ipaddress = address;
         scope_id = 0;
     }
 
     Inet6Address(byte address[], String name) {
+        family = AF_INET6;
         hostName = name;
         ipaddress = address;
         scope_id = 0;
@@ -80,9 +74,9 @@
      *            the name associated with the address.
      * @param scope_id
      *            the scope id for link- or site-local addresses.
-     * @since Android 1.0
      */
     Inet6Address(byte address[], String name, int scope_id) {
+        family = AF_INET6;
         hostName = name;
         ipaddress = address;
         this.scope_id = scope_id;
@@ -104,7 +98,6 @@
      * @return the Inet6Address instance representing the IP address.
      * @throws UnknownHostException
      *             if the address is null or has an invalid length.
-     * @since Android 1.0
      */
     public static Inet6Address getByAddress(String host, byte[] addr,
             int scope_id) throws UnknownHostException {
@@ -135,7 +128,6 @@
      *             if the address is {@code null} or has an invalid length or
      *             the interface doesn't have a numeric scope id for the given
      *             address type.
-     * @since Android 1.0
      */
     public static Inet6Address getByAddress(String host, byte[] addr,
             NetworkInterface nif) throws UnknownHostException {
@@ -177,10 +169,11 @@
     /**
      * Returns {@code true} if one of following cases applies:
      * <p>
-     * <li>1. both addresses are site local</li>
-     * <li>2. both addresses are link local</li>
-     * <li>3. {@code ia} is neither site local nor link local</li>
-     * </p>
+     * <ol>
+     *  <li>both addresses are site local</li>
+     *  <li>both addresses are link local</li>
+     *  <li>{@code ia} is neither site local nor link local</li>
+     * </ol>
      */
     private boolean compareLocalType(Inet6Address ia) {
         if (ia.isSiteLocalAddress() && isSiteLocalAddress()) {
@@ -203,7 +196,6 @@
      *            the network address.
      * @param scope_id
      *            the scope id for link- or site-local addresses.
-     * @since Android 1.0
      */
     Inet6Address(byte address[], int scope_id) {
         ipaddress = address;
@@ -219,7 +211,6 @@
      * 
      * @return {@code true} if this address is in the multicast group, {@code
      *         false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isMulticastAddress() {
@@ -233,7 +224,6 @@
      * 
      * @return {@code true} if this instance represents a wildcard address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isAnyLocalAddress() {
@@ -251,7 +241,6 @@
      * 
      * @return {@code true} if this instance represents the loopback address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isLoopbackAddress() {
@@ -277,7 +266,6 @@
      * 
      * @return {@code true} if this instance represents a link-local address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isLinkLocalAddress() {
@@ -292,7 +280,6 @@
      * 
      * @return {@code true} if this instance represents a site-local address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isSiteLocalAddress() {
@@ -307,7 +294,6 @@
      * 
      * @return {@code true} if this instance represents a global multicast
      *         address, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isMCGlobal() {
@@ -323,7 +309,6 @@
      * 
      * @return {@code true} if this instance represents a node-local multicast
      *         address, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isMCNodeLocal() {
@@ -339,7 +324,6 @@
      * 
      * @return {@code true} if this instance represents a link-local multicast
      *         address, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isMCLinkLocal() {
@@ -355,7 +339,6 @@
      * 
      * @return {@code true} if this instance represents a site-local multicast
      *         address, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isMCSiteLocal() {
@@ -371,7 +354,6 @@
      * 
      * @return {@code true} if this instance represents a org-local multicast
      *         address, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isMCOrgLocal() {
@@ -380,16 +362,10 @@
         return (ipaddress[0] == -1) && (ipaddress[1] & 15) == 8;
     }
 
-    /**
-     * Gets the textual representation of this IP address.
-     * 
-     * @return the as a dotted string formatted IP address.
-     * @since Android 1.0
-     */
-    @Override
-    public String getHostAddress() {
-        return Inet6Util.createIPAddrStringFromByteArray(ipaddress);
-    }
+    // BEGIN android-removed
+    // public String getHostAddress() {
+    // }
+    // END android-removed
 
     /**
      * Gets the scope id as a number if this address is linked to an interface.
@@ -397,7 +373,6 @@
      * 
      * @return the scope_id of this address or 0 when not linked with an
      *         interface.
-     * @since Android 1.0
      */
     public int getScopeId() {
         if (scope_id_set) {
@@ -411,7 +386,6 @@
      * network interface. Otherwise returns {@code null}.
      * 
      * @return the scoped network interface of this address.
-     * @since Android 1.0
      */
     public NetworkInterface getScopedInterface() {
         if (scope_ifname_set) {
@@ -420,33 +394,13 @@
         return null;
     }
 
-    /**
-     * Gets the hashcode of the represented IP address.
-     * 
-     * @return the appropriate hashcode value.
-     * @since Android 1.0
-     */
-    @Override
-    public int hashCode() {
-        /* Returns the low order int as the hash code */
-        return bytesToInt(ipaddress, 12);
-    }
+    // BEGIN android-removed
+    // public int hashCode() {}
+    // END android-removed
 
-    /**
-     * Compares this instance with the IP address in the object {@code obj} and
-     * returns {@code true} if they are of the same type and represent the same
-     * IP address, {@code false} otherwise. The scope id does not seem to be
-     * part of the comparison.
-     * 
-     * @param obj
-     *            the object to be tested for equality.
-     * @return {@code true} if the addresses are equal, {@code false} otherwise.
-     * @since Android 1.0
-     */
-    @Override
-    public boolean equals(Object obj) {
-        return super.equals(obj);
-    }
+    // BEGIN android-removed
+    // public boolean equals(Object obj) {}
+    // END android-removed
 
     /**
      * Returns whether this address is IPv4 compatible or not. An IPv4
@@ -455,7 +409,6 @@
      * 
      * @return {@code true} if this instance represents an IPv4 compatible
      *         address, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isIPv4CompatibleAddress() {
         for (int i = 0; i < 12; i++) {
@@ -506,7 +459,6 @@
      * IP address.
      * 
      * @return the description, as host/address.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
diff --git a/libcore/luni/src/main/java/java/net/InetAddress.java b/libcore/luni/src/main/java/java/net/InetAddress.java
index 72c7669..33c25f3 100644
--- a/libcore/luni/src/main/java/java/net/InetAddress.java
+++ b/libcore/luni/src/main/java/java/net/InetAddress.java
@@ -25,7 +25,9 @@
 import java.io.ObjectStreamField;
 import java.io.Serializable;
 import java.security.AccessController;
+import java.util.Arrays;
 import java.util.ArrayList;
+import java.util.Comparator;
 import java.util.Enumeration;
 import java.util.StringTokenizer;
 
@@ -41,22 +43,11 @@
  * encapsulates an IP address and provides name and reverse name resolution
  * functions. The address is stored in network order, but as a signed (rather
  * than unsigned) integer.
- * 
- * @since Android 1.0
  */
 public class InetAddress extends Object implements Serializable {
 
-    final static byte[] any_bytes = { 0, 0, 0, 0 };
-
-    final static byte[] localhost_bytes = { 127, 0, 0, 1 };
-
-    static InetAddress ANY = new Inet4Address(any_bytes);
-
     private final static INetworkSystem NETIMPL = Platform.getNetworkSystem();
 
-    final static InetAddress LOOPBACK = new Inet4Address(localhost_bytes,
-            "localhost"); //$NON-NLS-1$
-
     private static final String ERRMSG_CONNECTION_REFUSED = "Connection refused"; //$NON-NLS-1$
 
     private static final long serialVersionUID = 3286316764910316507L;
@@ -79,84 +70,81 @@
 
     private int addrCount;
 
-    int family = 2;
+    int family = 0;
+    static final int AF_INET = 2;
+    static final int AF_INET6 = 10;
 
     byte[] ipaddress;
 
     // BEGIN android-removed
     // // Fill in the JNI id caches
     // private static native void oneTimeInitialization(boolean supportsIPv6);
-    // 
+    //
     // static {
     //     oneTimeInitialization(true);
     // }
     // END android-removed
 
     /**
-     * Constructs an InetAddress.
+     * Constructs an {@code InetAddress}.
+     *
+     * Note: this constructor should not be used. Creating an InetAddress
+     * without specifying whether it's an IPv4 or IPv6 address does not make
+     * sense, because subsequent code cannot know which of of the subclasses'
+     * methods need to be called to implement a given InetAddress method. The
+     * proper way to create an InetAddress is to call new Inet4Address or
+     * Inet6Address or to use one of the static methods that return
+     * InetAddresses (e.g., getByAddress). That is why the API does not have
+     * public constructors for any of these classes.
      */
     InetAddress() {
         super();
     }
 
-    /**
-     * Constructs an {@code InetAddress}, representing the {@code address} and
-     * {@code hostName}.
-     * 
-     * @param address
-     *            the network address.
-     */
-    InetAddress(byte[] address) {
-        super();
-        this.ipaddress = address;
-    }
-
-    /**
-     * Constructs an {@code InetAddress}, representing the {@code address} and
-     * {@code hostName}.
-     * 
-     * @param address
-     *            the network address.
-     */
-    InetAddress(byte[] address, String hostName) {
-        super();
-        this.ipaddress = address;
-        this.hostName = hostName;
-    }
-
     // BEGIN android-removed
-    // Removed in newer version of harmony
-    // /**
-    //  * Returns the IP address of the argument {@code addr} as a byte array. The
-    //  * elements are in network order (the highest order address byte is in the
-    //  * zeroth element).
-    //  * 
-    //  * @return the network address as a byte array.
-    //  */
-    // static byte[] addressOf(int addr) {
-    //     int temp = addr;
-    //     byte array[] = new byte[4];
-    //     array[3] = (byte) (temp & 0xFF);
-    //     array[2] = (byte) ((temp >>>= 8) & 0xFF);
-    //     array[1] = (byte) ((temp >>>= 8) & 0xFF);
-    //     array[0] = (byte) ((temp >>>= 8) & 0xFF);
-    //     return array;
+    /**
+     * Constructs an {@code InetAddress}, representing the {@code address} and
+     * {@code hostName}.
+     *
+     * @param address
+     *            the network address.
+     */
+    // InetAddress(byte[] address) {
+    //     super();
+    //     this.ipaddress = address;
     // }
-    // BEGIN android-removed
+    // END android-removed
 
-    CacheElement cacheElement() {
-        return new CacheElement();
-    }
+    // BEGIN android-removed
+    /**
+     * Constructs an {@code InetAddress}, representing the {@code address} and
+     * {@code hostName}.
+     *
+     * @param address
+     *            the network address.
+     *
+     */
+    // InetAddress(byte[] address, String hostName) {
+    //     super();
+    //     this.ipaddress = address;
+    //     this.hostName = hostName;
+    // }
+    // END android-removed
+
+    // BEGIN android-removed
+    // CacheElement cacheElement() {
+    //     return new CacheElement();
+    // }
+    // END android-removed
 
     /**
      * Compares this {@code InetAddress} instance against the specified address
      * in {@code obj}. Two addresses are equal if their address byte arrays have
      * the same length and if the bytes in the arrays are equal.
-     * 
+     *
      * @param obj
      *            the object to be tested for equality.
      * @return {@code true} if both objects are equal, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object obj) {
@@ -164,141 +152,137 @@
         if (!(obj instanceof InetAddress)) {
             return false;
         }
+        return Arrays.equals(this.ipaddress, ((InetAddress) obj).ipaddress);
         // END android-changed
-
-        // now check if their byte arrays match...
-        byte[] objIPaddress = ((InetAddress) obj).ipaddress;
-        // BEGIN android-added
-        if (objIPaddress.length != ipaddress.length) {
-            return false;
-        }
-        // END android-added
-        for (int i = 0; i < objIPaddress.length; i++) {
-            if (objIPaddress[i] != this.ipaddress[i]) {
-                return false;
-            }
-        }
-        return true;
     }
 
     /**
      * Returns the IP address represented by this {@code InetAddress} instance
      * as a byte array. The elements are in network order (the highest order
      * address byte is in the zeroth element).
-     * 
+     *
      * @return the address in form of a byte array.
-     * @since Android 1.0
      */
     public byte[] getAddress() {
         return ipaddress.clone();
     }
 
+    // BEGIN android-added
+    static final Comparator<byte[]> SHORTEST_FIRST = new Comparator<byte[]>() {
+        public int compare(byte[] a1, byte[] a2) {
+            return a1.length - a2.length;
+        }
+    };
+
+    static final Comparator<byte[]> LONGEST_FIRST = new Comparator<byte[]>() {
+        public int compare(byte[] a1, byte[] a2) {
+            return a2.length - a1.length;
+        }
+    };
+
+    /**
+     * Converts an array of byte arrays representing raw IP addresses of a host
+     * to an array of InetAddress objects, sorting to respect the value of the
+     * system preferIPv6Addresses preference.
+     *
+     * @param rawAddresses the raw addresses to convert.
+     * @param hostName the hostname corresponding to the IP address.
+     * @return the corresponding InetAddresses, appropriately sorted.
+     */
+    static InetAddress[] bytesToInetAddresses(byte[][] rawAddresses,
+            String hostName) {
+        // Sort the raw byte arrays.
+        Comparator<byte[]> comparator = preferIPv6Addresses()
+                ? LONGEST_FIRST : SHORTEST_FIRST;
+        Arrays.sort(rawAddresses, comparator);
+
+        // Convert the byte arrays to InetAddresses.
+        InetAddress[] returnedAddresses = new InetAddress[rawAddresses.length];
+        for (int i = 0; i < rawAddresses.length; i++) {
+            byte[] rawAddress = rawAddresses[i];
+            if (rawAddress.length == 16) {
+                returnedAddresses[i] = new Inet6Address(rawAddress, hostName);
+            } else if (rawAddress.length == 4) {
+                returnedAddresses[i] = new Inet4Address(rawAddress, hostName);
+            } else {
+              // Cannot happen, because the underlying code only returns
+              // addresses that are 4 or 16 bytes long.
+              throw new AssertionError("Impossible address length " +
+                                       rawAddress.length);
+            }
+        }
+        return returnedAddresses;
+    }
+    // END android-added
+
     /**
      * Gets all IP addresses associated with the given {@code host} identified
-     * by name or IP address in dot-notation. The IP address is resolved by the
+     * by name or literal IP address. The IP address is resolved by the
      * configured name service. If the host name is empty or {@code null} an
-     * {@code UnknownHostException} is thrown. If the host name is a dotted IP
+     * {@code UnknownHostException} is thrown. If the host name is a literal IP
      * address string an array with the corresponding single {@code InetAddress}
      * is returned.
-     * 
-     * @param host
-     *            the host's name or IP to be resolved to an address.
+     *
+     * @param host the hostname or literal IP string to be resolved.
      * @return the array of addresses associated with the specified host.
-     * @throws UnknownHostException
-     *             if the address lookup fails.
-     * @since Android 1.0
+     * @throws UnknownHostException if the address lookup fails.
      */
     public static InetAddress[] getAllByName(String host)
             throws UnknownHostException {
         // BEGIN android-changed
-        // Added change taken from newer harmony concerning zero length hostname.
-        // Added special handling for localhost, since it doesn't work properly.
-        // TODO Get rid of this later...
-        if (host == null || 0 == host.length() ||
-                "localhost".equalsIgnoreCase(host)) {
-            return new InetAddress[] { preferIPv6Addresses()
-                                       ? Inet6Address.LOOPBACK
-                                       : LOOPBACK };
-        }
+        return getAllByNameImpl(host, true);
         // END android-changed
+    }
+
+    // BEGIN android-added
+    /**
+     * Implementation of getAllByName.
+     *
+     * @param host the hostname or literal IP string to be resolved.
+     * @param returnUnshared requests a result that is modifiable by the caller.
+     * @return the array of addresses associated with the specified host.
+     * @throws UnknownHostException if the address lookup fails.
+     */
+    static InetAddress[] getAllByNameImpl(String host, boolean returnUnshared)
+            throws UnknownHostException {
+        if (host == null || 0 == host.length()) {
+            if (preferIPv6Addresses()) {
+                return new InetAddress[] { Inet6Address.LOOPBACK,
+                                           Inet4Address.LOOPBACK };
+            } else {
+                return new InetAddress[] { Inet4Address.LOOPBACK,
+                                           Inet6Address.LOOPBACK };
+            }
+        }
+
+        // Special-case "0" for legacy IPv4 applications.
+        if (host.equals("0")) { //$NON-NLS-1$
+            return new InetAddress[] { Inet4Address.ANY };
+        }
 
         if (isHostName(host)) {
             SecurityManager security = System.getSecurityManager();
             if (security != null) {
                 security.checkConnect(host, -1);
             }
-            // BEGIN android-changed
-            byte[][] rawAddresses = getallbyname(host,
-                                                 Socket.preferIPv4Stack());
-            InetAddress[] returnedAddresses = new
-                                              InetAddress[rawAddresses.length];
-            for (int i = 0; i < rawAddresses.length; i++) {
-                byte[] rawAddress = rawAddresses[i];
-                if (rawAddress.length == 16) {
-                    returnedAddresses[i] = new Inet6Address(rawAddress, host);
-                } else if (rawAddress.length == 4) {
-                    returnedAddresses[i] = new Inet4Address(rawAddress, host);
-                } else {
-                  // Cannot happen, because the underlying code only returns
-                  // addresses that are 4 or 16 bytes long.
-                  throw new AssertionError("Impossible address length " + 
-                                           rawAddress.length);
-                }
+            if (returnUnshared) {
+                return lookupHostByName(host).clone();
+            } else {
+                return lookupHostByName(host);
             }
-
-            // ok we may have to re-order to make sure the
-            // preferIPv6Addresses is respected
-            // END android-changed
-            InetAddress[] orderedAddresses = null;
-            if (returnedAddresses != null) {
-                orderedAddresses = new InetAddress[returnedAddresses.length];
-                int curPosition = 0;
-                if (InetAddress.preferIPv6Addresses()) {
-                    for (int i = 0; i < returnedAddresses.length; i++) {
-                        if (returnedAddresses[i] instanceof Inet6Address) {
-                            orderedAddresses[curPosition] = returnedAddresses[i];
-                            curPosition++;
-                        }
-                    }
-                    for (int i = 0; i < returnedAddresses.length; i++) {
-                        // BEGIN android-changed
-                        if (!(returnedAddresses[i] instanceof Inet6Address)) {
-                        // END android-changed
-                            orderedAddresses[curPosition] = returnedAddresses[i];
-                            curPosition++;
-                        }
-                    }
-                } else {
-                    for (int i = 0; i < returnedAddresses.length; i++) {
-                        // BEGIN android-changed
-                        if (!(returnedAddresses[i] instanceof Inet6Address)) {
-                        // END android-changed
-                            orderedAddresses[curPosition] = returnedAddresses[i];
-                            curPosition++;
-                        }
-                    }
-                    for (int i = 0; i < returnedAddresses.length; i++) {
-                        if (returnedAddresses[i] instanceof Inet6Address) {
-                            orderedAddresses[curPosition] = returnedAddresses[i];
-                            curPosition++;
-                        }
-                    }
-                }
-            }
-            return orderedAddresses;
         }
 
-        byte[] hBytes = Inet6Util.createByteArrayFromIPAddressString(host);
-        // BEGIN android-added
-        // Copied from a newer version of harmony
+        byte[] hBytes = NETIMPL.ipStringToByteArray(host);
         if (hBytes.length == 4) {
             return (new InetAddress[] { new Inet4Address(hBytes) });
         } else if (hBytes.length == 16) {
             return (new InetAddress[] { new Inet6Address(hBytes) });
+        } else {
+            throw new UnknownHostException(
+                    Msg.getString("K0339")); //$NON-NLS-1$
         }
-        // END android-added
-        return (new InetAddress[] { new InetAddress(hBytes) });
     }
+    // END android-added
 
     /**
      * Returns the address of a host according to the given host string name
@@ -306,57 +290,54 @@
      * string IP address. If the latter, the {@code hostName} field is
      * determined upon demand. {@code host} can be {@code null} which means that
      * an address of the loopback interface is returned.
-     * 
+     *
      * @param host
      *            the hostName to be resolved to an address or {@code null}.
      * @return the {@code InetAddress} instance representing the host.
      * @throws UnknownHostException
      *             if the address lookup fails.
-     * @since Android 1.0
      */
-    public static InetAddress getByName(String host)
-            throws UnknownHostException {
-        // BEGIN android-changed
-        // Added special handling for localhost, since it doesn't work properly.
-        // TODO Get rid of this later...
-        if (host == null || 0 == host.length() || 
-                "localhost".equalsIgnoreCase(host)) {
-            return InetAddress.LOOPBACK;
-        }
-        // END android-changed
-        if (host.equals("0")) { //$NON-NLS-1$
-            return InetAddress.ANY;
-        }
-
-        if (isHostName(host)) {
-            SecurityManager security = System.getSecurityManager();
-            if (security != null) {
-                security.checkConnect(host, -1);
-            }
-            return lookupHostByName(host);
-        }
-
-        return createHostNameFromIPAddress(host);
+    public static InetAddress getByName(String host) throws UnknownHostException {
+        return getAllByNameImpl(host, false)[0];
     }
 
+    // BEGIN android-added
+    /**
+     * Convenience method to convert a byte array to a string, converting
+     * exceptions to runtime exceptions. This is used when passing in byte
+     * arrays that have been verified to be correct and is necessary because
+     * some methods, such as getHostName(), are not allowed to throw exceptions
+     * but are implemented using byteArrayToIpString(), which throws
+     * UnknownHostException. Exceptions should never occur when the address is
+     * valid, but they cannot be simply ignored because they could be due to
+     * runtime errors such as out-of-memory conditions.
+     *
+     * @param ipaddress the byte array to convert
+     */
+    private static String ipAddressToString(byte[] ipaddress) {
+        try {
+            return NETIMPL.byteArrayToIpString(ipaddress);
+        } catch(UnknownHostException e) {
+            throw new RuntimeException(e);
+        }
+    }
+    // END android-added
+
     /**
      * Gets the textual representation of this IP address.
-     * 
-     * @return the textual representation of this host address in form of a
-     *         dotted string.
-     * @since Android 1.0
+     *
+     * @return the textual representation of host's IP address.
      */
     public String getHostAddress() {
-        return inetNtoaImpl(bytesToInt(ipaddress, 0));
+        return ipAddressToString(ipaddress);
     }
 
     /**
      * Gets the host name of this IP address. If the IP address could not be
      * resolved, the textual representation in a dotted-quad-notation is
      * returned.
-     * 
+     *
      * @return the corresponding string name of this IP address.
-     * @since Android 1.0
      */
     public String getHostName() {
         try {
@@ -365,18 +346,17 @@
                 if (ipaddress.length == 4) {
                     address = bytesToInt(ipaddress, 0);
                     if (address == 0) {
-                        return hostName = inetNtoaImpl(address);
+                        return hostName = ipAddressToString(ipaddress);
                     }
                 }
                 hostName = getHostByAddrImpl(ipaddress).hostName;
                 if (hostName.equals("localhost") && ipaddress.length == 4 //$NON-NLS-1$
                         && address != 0x7f000001) {
-                    return hostName = inetNtoaImpl(address);
+                    return hostName = ipAddressToString(ipaddress);
                 }
             }
         } catch (UnknownHostException e) {
-            return hostName = Inet6Util
-                    .createIPAddrStringFromByteArray(ipaddress);
+            return hostName = ipAddressToString(ipaddress);
         }
         SecurityManager security = System.getSecurityManager();
         try {
@@ -385,7 +365,7 @@
                 security.checkConnect(hostName, -1);
             }
         } catch (SecurityException e) {
-            return Inet6Util.createIPAddrStringFromByteArray(ipaddress);
+            return ipAddressToString(ipaddress);
         }
         return hostName;
     }
@@ -395,9 +375,8 @@
      * address. If a security manager is set, it is checked if the method caller
      * is allowed to get the hostname. Otherwise, the textual representation in
      * a dotted-quad-notation is returned.
-     * 
+     *
      * @return the fully qualified domain name of this IP address.
-     * @since Android 1.0
      */
     public String getCanonicalHostName() {
         String canonicalName;
@@ -406,12 +385,12 @@
             if (ipaddress.length == 4) {
                 address = bytesToInt(ipaddress, 0);
                 if (address == 0) {
-                    return inetNtoaImpl(address);
+                    return ipAddressToString(ipaddress);
                 }
             }
             canonicalName = getHostByAddrImpl(ipaddress).hostName;
         } catch (UnknownHostException e) {
-            return Inet6Util.createIPAddrStringFromByteArray(ipaddress);
+            return ipAddressToString(ipaddress);
         }
         SecurityManager security = System.getSecurityManager();
         try {
@@ -420,7 +399,7 @@
                 security.checkConnect(canonicalName, -1);
             }
         } catch (SecurityException e) {
-            return Inet6Util.createIPAddrStringFromByteArray(ipaddress);
+            return ipAddressToString(ipaddress);
         }
         return canonicalName;
     }
@@ -429,14 +408,10 @@
      * Gets the local host address if the security policy allows this.
      * Otherwise, gets the loopback address which allows this machine to be
      * contacted.
-     * <p>
-     * The current implementation returns always the loopback address.
-     * </p>
-     * 
+     *
      * @return the {@code InetAddress} representing the local host.
      * @throws UnknownHostException
      *             if the address lookup fails.
-     * @since Android 1.0
      */
     public static InetAddress getLocalHost() throws UnknownHostException {
         String host = getHostNameImpl();
@@ -446,34 +421,44 @@
                 security.checkConnect(host, -1);
             }
         } catch (SecurityException e) {
-            return InetAddress.LOOPBACK;
+            return Inet4Address.LOOPBACK;
         }
-        return lookupHostByName(host);
+        return lookupHostByName(host)[0];
     }
 
     /**
      * Gets the hashcode of the represented IP address.
-     * 
+     *
      * @return the appropriate hashcode value.
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
-        return bytesToInt(ipaddress, 0);
+        // BEGIN android-changed
+        return Arrays.hashCode(ipaddress);
+        // END android-changed
     }
 
-    /**
-     * Returns whether this address is an IP multicast address or not.
-     * 
+    // BEGIN android-changed
+    /*
+     * Returns whether this address is an IP multicast address or not. This
+     * implementation returns always {@code false}.
+     *
      * @return {@code true} if this address is in the multicast group, {@code
      *         false} otherwise.
-     * @since Android 1.0
      */
     public boolean isMulticastAddress() {
-        return ((ipaddress[0] & 255) >>> 4) == 0xE;
+        return false;
     }
+    // END android-changed
 
-    static synchronized InetAddress lookupHostByName(String host)
+
+    /**
+     * Resolves a hostname to its IP addresses using a cache for faster lookups.
+     *
+     * @param host the hostname to resolve.
+     * @return the IP addresses of the host.
+     */
+    static synchronized InetAddress[] lookupHostByName(String host)
             throws UnknownHostException {
         int ttl = -1;
 
@@ -490,40 +475,48 @@
             // Ignored
         }
         CacheElement element = null;
+        // BEGIN android-changed
         if (ttl == 0) {
             Cache.clear();
         } else {
             element = Cache.get(host);
-            // BEGIN android-changed
             if (element != null && ttl > 0) {
                 long delta = System.nanoTime() - element.nanoTimeAdded;
                 if (delta > secondsToNanos(ttl)) {
                     element = null;
                 }
             }
-            // END android-changed
         }
         if (element != null) {
-            return element.inetAddress();
+            return element.addresses();
         }
+        // END android-changed
+
+        // TODO Clean up NegativeCache; there's no need to maintain the failure message
 
         // now try the negative cache
         String failedMessage = NegativeCache.getFailedMessage(host);
         if (failedMessage != null) {
-            throw new UnknownHostException(host + " - " + failedMessage); //$NON-NLS-1$
+            throw new UnknownHostException(host);
         }
 
-        InetAddress anInetAddress;
+        // BEGIN android-changed
+        // TODO: Avoid doing I/O from a static synchronized lock.
+        byte[][] rawAddresses;
         try {
-            anInetAddress = getHostByNameImpl(host, preferIPv6Addresses());
+            rawAddresses = getallbyname(host, Socket.preferIPv4Stack());
         } catch (UnknownHostException e) {
             // put the entry in the negative cache
             NegativeCache.put(host, e.getMessage());
-            throw new UnknownHostException(host + " - " + e.getMessage()); //$NON-NLS-1$
+            // use host for message to match RI, save the cause for giggles
+            throw (UnknownHostException)new UnknownHostException(host).initCause(e);
         }
 
-        Cache.add(anInetAddress);
-        return anInetAddress;
+        InetAddress[] addresses = bytesToInetAddresses(rawAddresses, host);
+
+        Cache.add(host, addresses);
+        return addresses;
+        // END android-changed
     }
 
     // BEGIN android-added
@@ -540,17 +533,17 @@
     //     throws UnknownHostException;
     // END android-deleted
 
-    // BEGIN android-changed
+    // BEGIN android-added
     /**
      * Resolves a host name to its IP addresses. Thread safe.
      */
     private static native byte[][] getallbyname(String name,
-                                                boolean preferIPv4Stack);
-    // END android-changed
+            boolean preferIPv4Stack) throws UnknownHostException;
+    // END android-added
 
     /**
      * Query the IP stack for the host address. The host is in address form.
-     * 
+     *
      * @param addr
      *            the host address to lookup.
      * @throws UnknownHostException
@@ -561,7 +554,14 @@
     //    throws UnknownHostException;
     static InetAddress getHostByAddrImpl(byte[] addr)
             throws UnknownHostException {
-        return new InetAddress(addr, gethostbyaddr(addr));
+        if (addr.length == 4) {
+            return new Inet4Address(addr, gethostbyaddr(addr));
+        } else if (addr.length == 16) {
+            return new Inet6Address(addr, gethostbyaddr(addr));
+        } else {
+            throw new UnknownHostException(Msg.getString(
+                    "K0339")); //$NON-NLS-1$
+        }
     }
 
     /**
@@ -570,10 +570,9 @@
     private static native String gethostbyaddr(byte[] addr);
     // END android-changed
 
-    static int inetAddr(String host) throws UnknownHostException {
-        return (host.equals("255.255.255.255")) ? 0xFFFFFFFF //$NON-NLS-1$
-                : inetAddrImpl(host);
-    }
+    // BEGIN android-removed
+    // static int inetAddr(String host) throws UnknownHostException
+    // END android-removed
 
     /**
      * Convert a string containing an IPv4 Internet Protocol dotted address into
@@ -581,66 +580,37 @@
      * exception, so this value should not be used as an argument. See also
      * inetAddr(String).
      */
-    // BEGIN android-changed
+    // BEGIN android-removed
     // static native int inetAddrImpl(String host) throws UnknownHostException;
-    static int inetAddrImpl(String host) throws UnknownHostException {
-        // TODO Probably not exactly what we want, and also inefficient. Provide native later.
-        try {
-            String[] args = host.split("\\.");
-            
-            int a = Integer.parseInt(args[0]) << 24;
-            int b = Integer.parseInt(args[1]) << 16;
-            int c = Integer.parseInt(args[2]) <<  8;
-            int d = Integer.parseInt(args[3])      ;
-            
-            return a | b | c | d;
-        } catch (Exception ex) {
-            throw new UnknownHostException(host);
-        }
-    }
-    // END android-changed
+    // END android-removed
 
     /**
      * Convert a binary address into a string containing an Ipv4 Internet
      * Protocol dotted address.
      */
-    // BEGIN android-changed
+    // BEGIN android-removed
     // static native String inetNtoaImpl(int hipAddr);
-    static String inetNtoaImpl(int hipAddr) {
-        // TODO Inefficient and probably wrong. Provide proper (native?) implementation later.
-        int a = (hipAddr >> 24) & 0xFF;
-        int b = (hipAddr >> 16) & 0xFF;
-        int c = (hipAddr >>  8) & 0xFF;
-        int d = (hipAddr      ) & 0xFF;
-        
-        return "" + a + "." + b + "." + c + "." + d;
-    }
-    // END android-changed
+    // END android-removed
 
+    // BEGIN android-removed
     /**
      * Query the IP stack for the host address. The host is in string name form.
-     * 
+     *
      * @param name
      *            the host name to lookup
-     * @param preferIPv6Addresses
+     * @param preferIPv6Address
      *            address preference if underlying platform is V4/V6
      * @return InetAddress the host address
      * @throws UnknownHostException
      *             if an error occurs during lookup
      */
-    // BEGIN android-changed
     // static native InetAddress getHostByNameImpl(String name,
-    //          boolean preferIPv6Address) throws UnknownHostException;
-    static InetAddress getHostByNameImpl(String name,
-            boolean preferIPv6Address) throws UnknownHostException {
-        // TODO Mapped Harmony to Android native. Get rid of indirection later.
-        return getAllByName(name)[0];
-    }
-    // END android-changed
+    //         boolean preferIPv6Address) throws UnknownHostException;
+    // END android-removed
 
     /**
      * Gets the host name of the system.
-     * 
+     *
      * @return String the system hostname
      */
     // BEGIN android-changed
@@ -654,10 +624,10 @@
 
     static String getHostNameInternal(String host) throws UnknownHostException {
         if (host == null || 0 == host.length()) {
-            return InetAddress.LOOPBACK.getHostAddress();
+            return Inet4Address.LOOPBACK.getHostAddress();
         }
         if (isHostName(host)) {
-            return lookupHostByName(host).getHostAddress();
+            return lookupHostByName(host)[0].getHostAddress();
         }
         return host;
     }
@@ -665,38 +635,38 @@
     /**
      * Returns a string containing a concise, human-readable description of this
      * IP address.
-     * 
+     *
      * @return the description, as host/address.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
         return (hostName == null ? "" : hostName) + "/" + getHostAddress(); //$NON-NLS-1$ //$NON-NLS-2$
     }
 
-    class CacheElement {
-        // BEGIN android-changed
-        // Partly copied from a newer version of harmony
+    // BEGIN android-changed
+    // Partly copied from a newer version of harmony
+    static class CacheElement {
         final long nanoTimeAdded = System.nanoTime();
 
         CacheElement next;
+        final String hostName;
+        final InetAddress[] addresses;
 
-        CacheElement() {
-            super();
+        CacheElement(String hostName, InetAddress[] addresses) {
+            this.addresses = addresses;
+            this.hostName = hostName;
         }
-        // END android-changed
 
         String hostName() {
             return hostName;
         }
 
-        InetAddress inetAddress() {
-            return InetAddress.this;
+        InetAddress[] addresses() {
+            return addresses;
         }
+        // END android-changed
     }
 
-    // BEGIN android-changed
-    // Copied from a newer version of harmony
     static class Cache {
         private static int maxSize = 5;
 
@@ -709,8 +679,8 @@
             head = null;
         }
 
-        static synchronized void add(InetAddress value) {
-            CacheElement newElement = value.cacheElement();
+        static synchronized void add(String hostName, InetAddress[] addresses) {
+            CacheElement newElement = new CacheElement(hostName, addresses);
             if (size < maxSize) {
                 size++;
             } else {
@@ -764,24 +734,26 @@
             }
         }
     }
-    // END android-changed
 
     /**
      * Returns true if the string is a host name, false if it is an IP Address.
      */
     private static boolean isHostName(String value) {
-        return !(Inet6Util.isValidIPV4Address(value) || Inet6Util
-                .isValidIP6Address(value));
+        try {
+            NETIMPL.ipStringToByteArray(value);
+            return false;
+        } catch (UnknownHostException e) {
+            return true;
+        }
     }
 
     /**
      * Returns whether this address is a loopback address or not. This
      * implementation returns always {@code false}. Valid IPv4 loopback
      * addresses are 127.d.d.d The only valid IPv6 loopback address is ::1.
-     * 
+     *
      * @return {@code true} if this instance represents a loopback address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isLoopbackAddress() {
         return false;
@@ -793,14 +765,11 @@
      * <p>
      * Valid IPv6 link-local addresses are FE80::0 through to
      * FEBF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF.
-     * </p>
      * <p>
      * There are no valid IPv4 link-local addresses.
-     * </p>
-     * 
+     *
      * @return {@code true} if this instance represents a link-local address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isLinkLocalAddress() {
         return false;
@@ -812,14 +781,11 @@
      * <p>
      * Valid IPv6 site-local addresses are FEC0::0 through to
      * FEFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF.
-     * </p>
      * <p>
      * There are no valid IPv4 site-local addresses.
-     * </p>
-     * 
+     *
      * @return {@code true} if this instance represents a site-local address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isSiteLocalAddress() {
         return false;
@@ -832,15 +798,12 @@
      * Valid IPv6 link-global multicast addresses are FFxE:/112 where x is a set
      * of flags, and the additional 112 bits make up the global multicast
      * address space.
-     * </p>
      * <p>
      * Valid IPv4 global multicast addresses are between: 224.0.1.0 to
      * 238.255.255.255.
-     * </p>
-     * 
+     *
      * @return {@code true} if this instance represents a global multicast
      *         address, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isMCGlobal() {
         return false;
@@ -853,14 +816,11 @@
      * Valid IPv6 node-local multicast addresses are FFx1:/112 where x is a set
      * of flags, and the additional 112 bits make up the node-local multicast
      * address space.
-     * </p>
      * <p>
      * There are no valid IPv4 node-local multicast addresses.
-     * </p>
-     * 
+     *
      * @return {@code true} if this instance represents a node-local multicast
      *         address, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isMCNodeLocal() {
         return false;
@@ -873,14 +833,11 @@
      * Valid IPv6 link-local multicast addresses are FFx2:/112 where x is a set
      * of flags, and the additional 112 bits make up the link-local multicast
      * address space.
-     * </p>
      * <p>
      * Valid IPv4 link-local addresses are between: 224.0.0.0 to 224.0.0.255
-     * </p>
-     * 
+     *
      * @return {@code true} if this instance represents a link-local multicast
      *         address, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isMCLinkLocal() {
         return false;
@@ -893,15 +850,12 @@
      * Valid IPv6 site-local multicast addresses are FFx5:/112 where x is a set
      * of flags, and the additional 112 bits make up the site-local multicast
      * address space.
-     * </p>
      * <p>
      * Valid IPv4 site-local addresses are between: 239.252.0.0 to
      * 239.255.255.255
-     * </p>
-     * 
+     *
      * @return {@code true} if this instance represents a site-local multicast
      *         address, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isMCSiteLocal() {
         return false;
@@ -914,15 +868,12 @@
      * Valid IPv6 organization-local multicast addresses are FFx8:/112 where x
      * is a set of flags, and the additional 112 bits make up the
      * organization-local multicast address space.
-     * </p>
      * <p>
      * Valid IPv4 organization-local addresses are between: 239.192.0.0 to
      * 239.251.255.255
-     * </p>
-     * 
+     *
      * @return {@code true} if this instance represents a organization-local
      *         multicast address, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isMCOrgLocal() {
         return false;
@@ -931,10 +882,9 @@
     /**
      * Returns whether this is a wildcard address or not. This implementation
      * returns always {@code false}.
-     * 
+     *
      * @return {@code true} if this instance represents a wildcard address,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isAnyLocalAddress() {
         return false;
@@ -944,7 +894,7 @@
      * Tries to reach this {@code InetAddress}. This method first tries to use
      * ICMP <i>(ICMP ECHO REQUEST)</i>. When first step fails, a TCP connection
      * on port 7 (Echo) of the remote host is established.
-     * 
+     *
      * @param timeout
      *            timeout in milliseconds before the test fails if no connection
      *            could be established.
@@ -954,7 +904,6 @@
      *             if an error occurs during an I/O operation.
      * @throws IllegalArgumentException
      *             if timeout is less than zero.
-     * @since Android 1.0
      */
     public boolean isReachable(int timeout) throws IOException {
         return isReachable(null, 0, timeout);
@@ -964,7 +913,7 @@
      * Tries to reach this {@code InetAddress}. This method first tries to use
      * ICMP <i>(ICMP ECHO REQUEST)</i>. When first step fails, a TCP connection
      * on port 7 (Echo) of the remote host is established.
-     * 
+     *
      * @param netif
      *            the network interface on which to connection should be
      *            established.
@@ -979,7 +928,6 @@
      *             if an error occurs during an I/O operation.
      * @throws IllegalArgumentException
      *             if ttl or timeout is less than zero.
-     * @since Android 1.0
      */
     public boolean isReachable(NetworkInterface netif, final int ttl,
             final int timeout) throws IOException {
@@ -1073,8 +1021,8 @@
                     //             InetAddress.this, addr, ttl, timeout);
                     // } else {
                         try {
-                            threadReached = isReachableByTCP(InetAddress.this,
-                                    addr, timeout);
+                            threadReached = isReachableByTCP(addr,
+                                    InetAddress.this, timeout);
                         } catch (IOException e) {
                             // do nothing
                         }
@@ -1122,7 +1070,7 @@
     //         int ttl, int timeout) throws IOException {
     //     return isReachableByMultiThread(netif, ttl, timeout, true);
     // }
-    // 
+    //
     // private boolean isReachableByTCPUseMultiThread(NetworkInterface netif,
     //         int ttl, int timeout) throws IOException {
     //     return isReachableByMultiThread(netif, ttl, timeout, false);
@@ -1135,10 +1083,10 @@
         // define traffic only for parameter
         int traffic = 0;
         boolean reached = false;
-        NETIMPL.createSocket(fd, NetUtil.preferIPv4Stack());
+        NETIMPL.createStreamSocket(fd, NetUtil.preferIPv4Stack());
         try {
             if (null != source) {
-                NETIMPL.bind(fd, 0, source);
+                NETIMPL.bind(fd, source, 0);
             }
             NETIMPL.connectStreamWithTimeoutSocket(fd, 7, timeout, traffic,
                     dest);
@@ -1161,24 +1109,21 @@
      * exactly 16 bytes. If not, an {@code UnknownHostException} is thrown.
      * <p>
      * The IP address is not validated by a name service.
-     * </p>
      * <p>
      * The high order byte is {@code ipAddress[0]}.
-     * </p>
-     * 
+     *
      * @param ipAddress
      *            is either a 4 (IPv4) or 16 (IPv6) byte long array.
      * @return an {@code InetAddress} instance representing the given IP address
      *         {@code ipAddress}.
      * @throws UnknownHostException
      *             if the given byte array has no valid length.
-     * @since Android 1.0
      */
     public static InetAddress getByAddress(byte[] ipAddress)
             throws UnknownHostException {
         // simply call the method by the same name specifying the default scope
         // id of 0
-        return getByAddress(ipAddress, 0);
+        return getByAddressInternal(null, ipAddress, 0);
     }
 
     /**
@@ -1187,7 +1132,7 @@
      * exactly 16 bytes. If not, an {@code UnknownHostException} is thrown. The
      * IP address is not validated by a name service. The high order byte is
      * {@code ipAddress[0]}.
-     * 
+     *
      * @param ipAddress
      *            either a 4 (IPv4) or 16 (IPv6) byte array.
      * @param scope_id
@@ -1198,52 +1143,35 @@
      */
     static InetAddress getByAddress(byte[] ipAddress, int scope_id)
             throws UnknownHostException {
-        byte[] copy_address;
-        if (ipAddress != null && ipAddress.length == 4) {
-            copy_address = new byte[4];
-            for (int i = 0; i < 4; i++) {
-                copy_address[i] = ipAddress[i];
-            }
-            // BEGIN adnroid-changed
-            // Copied from a newer version of harmony
-            return new Inet4Address(copy_address);
-            // END android-changed
-        }
-
-        if (ipAddress != null && ipAddress.length == 16) {
-            // First check to see if the address is an IPv6-mapped
-            // IPv4 address. If it is, then we can make it a IPv4
-            // address, otherwise, we'll create an IPv6 address.
-            if (isIPv4MappedAddress(ipAddress)) {
-                copy_address = new byte[4];
-                for (int i = 0; i < 4; i++) {
-                    copy_address[i] = ipAddress[12 + i];
-                }
-                return new Inet4Address(copy_address);
-            }
-            copy_address = ipAddress.clone();
-            return new Inet6Address(copy_address, scope_id);
-        }
-        throw new UnknownHostException(Msg.getString("K0339")); //$NON-NLS-1$
+        return getByAddressInternal(null, ipAddress, scope_id);
     }
 
     private static boolean isIPv4MappedAddress(byte ipAddress[]) {
         // Check if the address matches ::FFFF:d.d.d.d
         // The first 10 bytes are 0. The next to are -1 (FF).
         // The last 4 bytes are varied.
+        if (ipAddress == null || ipAddress.length != 16) {
+            return false;
+        }
         for (int i = 0; i < 10; i++) {
             if (ipAddress[i] != 0) {
                 return false;
             }
         }
-
         if (ipAddress[10] != -1 || ipAddress[11] != -1) {
             return false;
         }
-
         return true;
     }
 
+    private static byte[] ipv4MappedToIPv4(byte[] mappedAddress) {
+        byte[] ipv4Address = new byte[4];
+        for(int i = 0; i < 4; i++) {
+            ipv4Address[i] = mappedAddress[12 + i];
+        }
+        return ipv4Address;
+    }
+
     /**
      * Returns the {@code InetAddress} corresponding to the array of bytes, and
      * the given hostname. In the case of an IPv4 address there must be exactly
@@ -1251,15 +1179,12 @@
      * UnknownHostException} will be thrown.
      * <p>
      * The host name and IP address are not validated.
-     * </p>
      * <p>
      * The hostname either be a machine alias or a valid IPv6 or IPv4 address
      * format.
-     * </p>
      * <p>
      * The high order byte is {@code ipAddress[0]}.
-     * </p>
-     * 
+     *
      * @param hostName
      *            the string representation of hostname or IP address.
      * @param ipAddress
@@ -1268,7 +1193,6 @@
      *         and hostname.
      * @throws UnknownHostException
      *             if the given byte array has no valid length.
-     * @since Android 1.0
      */
     public static InetAddress getByAddress(String hostName, byte[] ipAddress)
             throws UnknownHostException {
@@ -1284,7 +1208,7 @@
      * UnknownHostException} is thrown. The host name and IP address are not
      * validated. The hostname either be a machine alias or a valid IPv6 or IPv4
      * address format. The high order byte is {@code ipAddress[0]}.
-     * 
+     *
      * @param hostName
      *            string representation of hostname or IP address.
      * @param ipAddress
@@ -1297,36 +1221,36 @@
      */
     static InetAddress getByAddressInternal(String hostName, byte[] ipAddress,
             int scope_id) throws UnknownHostException {
-        byte[] copy_address;
-        if (ipAddress != null && ipAddress.length == 4) {
-            copy_address = new byte[4];
-            for (int i = 0; i < 4; i++) {
-                copy_address[i] = ipAddress[i];
-            }
-            return new Inet4Address(ipAddress, hostName);
+        if (ipAddress == null) {
+            // We don't throw NullPointerException here for RI compatibility,
+            // but we do say "address is null" (K0331), instead of "addr is of
+            // illegal length".
+            throw new UnknownHostException(
+                Msg.getString("K0331", hostName)); //$NON-NLS-1$
         }
-
-        if (ipAddress != null && ipAddress.length == 16) {
-            // First check to see if the address is an IPv6-mapped
-            // IPv4 address. If it is, then we can make it a IPv4
-            // address, otherwise, we'll create an IPv6 address.
-            if (isIPv4MappedAddress(ipAddress)) {
-                copy_address = new byte[4];
-                for (int i = 0; i < 4; i++) {
-                    copy_address[i] = ipAddress[12 + i];
+        switch (ipAddress.length) {
+            case 4:
+                return new Inet4Address(ipAddress.clone());
+            case 16:
+                // First check to see if the address is an IPv6-mapped
+                // IPv4 address. If it is, then we can make it a IPv4
+                // address, otherwise, we'll create an IPv6 address.
+                if (isIPv4MappedAddress(ipAddress)) {
+                    return new Inet4Address(ipv4MappedToIPv4(ipAddress));
+                } else {
+                    return new Inet6Address(ipAddress.clone(), scope_id);
                 }
-                return new Inet4Address(ipAddress, hostName);
-            }
-
-            copy_address = new byte[16];
-            for (int i = 0; i < 16; i++) {
-                copy_address[i] = ipAddress[i];
-            }
-
-            return new Inet6Address(ipAddress, hostName, scope_id);
+            default:
+                if (hostName != null) {
+                    // "Invalid IP Address is neither 4 or 16 bytes: <hostName>"
+                    throw new UnknownHostException(
+                            Msg.getString("K0332", hostName)); //$NON-NLS-1$
+                } else {
+                    // "Invalid IP Address is neither 4 or 16 bytes"
+                    throw new UnknownHostException(
+                            Msg.getString("K0339")); //$NON-NLS-1$
+                }
         }
-
-        throw new UnknownHostException(Msg.getString("K0332", hostName)); //$NON-NLS-1$
     }
 
     /**
@@ -1362,173 +1286,6 @@
         return value;
     }
 
-    /**
-     * Creates an InetAddress based on the {@code ipAddressString}. No error
-     * handling is performed here.
-     */
-    static InetAddress createHostNameFromIPAddress(String ipAddressString)
-            throws UnknownHostException {
-
-        InetAddress address = null;
-
-        if (Inet6Util.isValidIPV4Address(ipAddressString)) {
-            byte[] byteAddress = new byte[4];
-            String[] parts = ipAddressString.split("\\."); //$NON-NLS-1$
-            int length = parts.length;
-            if (length == 1) {
-                long value = Long.parseLong(parts[0]);
-                for (int i = 0; i < 4; i++) {
-                    byteAddress[i] = (byte) (value >> ((3 - i) * 8));
-                }
-            } else {
-                for (int i = 0; i < length; i++) {
-                    byteAddress[i] = (byte) Integer.parseInt(parts[i]);
-                }
-            }
-
-            // adjust for 2/3 parts address
-            if (length == 2) {
-                byteAddress[3] = byteAddress[1];
-                byteAddress[1] = 0;
-            }
-            if (length == 3) {
-                byteAddress[3] = byteAddress[2];
-                byteAddress[2] = 0;
-            }
-
-            address = new Inet4Address(byteAddress);
-        } else { // otherwise it must be ipv6
-
-            if (ipAddressString.charAt(0) == '[') {
-                ipAddressString = ipAddressString.substring(1, ipAddressString
-                        .length() - 1);
-            }
-
-            StringTokenizer tokenizer = new StringTokenizer(ipAddressString,
-                    ":.%", true); //$NON-NLS-1$
-            ArrayList<String> hexStrings = new ArrayList<String>();
-            ArrayList<String> decStrings = new ArrayList<String>();
-            String scopeString = null;
-            String token = ""; //$NON-NLS-1$
-            String prevToken = ""; //$NON-NLS-1$
-            String prevPrevToken = ""; //$NON-NLS-1$
-            int doubleColonIndex = -1; // If a double colon exists, we need to
-            // insert 0s.
-
-            // Go through the tokens, including the separators ':' and '.'
-            // When we hit a : or . the previous token will be added to either
-            // the hex list or decimal list. In the case where we hit a ::
-            // we will save the index of the hexStrings so we can add zeros
-            // in to fill out the string
-            while (tokenizer.hasMoreTokens()) {
-                prevPrevToken = prevToken;
-                prevToken = token;
-                token = tokenizer.nextToken();
-
-                if (token.equals(":")) { //$NON-NLS-1$
-                    if (prevToken.equals(":")) { //$NON-NLS-1$
-                        doubleColonIndex = hexStrings.size();
-                    } else if (!prevToken.equals("")) { //$NON-NLS-1$
-                        hexStrings.add(prevToken);
-                    }
-                } else if (token.equals(".")) { //$NON-NLS-1$
-                    decStrings.add(prevToken);
-                } else if (token.equals("%")) { //$NON-NLS-1$
-                    // add the last word before the % properly
-                    if (!prevToken.equals(":") && !prevToken.equals(".")) { //$NON-NLS-1$ //$NON-NLS-2$
-                        if (prevPrevToken.equals(":")) { //$NON-NLS-1$
-                            hexStrings.add(prevToken);
-                        } else if (prevPrevToken.equals(".")) { //$NON-NLS-1$
-                            decStrings.add(prevToken);
-                        }
-                    }
-
-                    // the rest should be the scope string
-                    scopeString = tokenizer.nextToken();
-                    while (tokenizer.hasMoreTokens()) {
-                        scopeString = scopeString + tokenizer.nextToken();
-                    }
-                }
-            }
-
-            if (prevToken.equals(":")) { //$NON-NLS-1$
-                if (token.equals(":")) { //$NON-NLS-1$
-                    doubleColonIndex = hexStrings.size();
-                } else {
-                    hexStrings.add(token);
-                }
-            } else if (prevToken.equals(".")) { //$NON-NLS-1$
-                decStrings.add(token);
-            }
-
-            // figure out how many hexStrings we should have
-            // also check if it is a IPv4 address
-            int hexStringsLength = 8;
-
-            // If we have an IPv4 address tagged on at the end, subtract
-            // 4 bytes, or 2 hex words from the total
-            if (decStrings.size() > 0) {
-                hexStringsLength -= 2;
-            }
-
-            // if we hit a double Colon add the appropriate hex strings
-            if (doubleColonIndex != -1) {
-                int numberToInsert = hexStringsLength - hexStrings.size();
-                for (int i = 0; i < numberToInsert; i++) {
-                    hexStrings.add(doubleColonIndex, "0"); //$NON-NLS-1$
-                }
-            }
-
-            byte ipByteArray[] = new byte[16];
-
-            // Finally convert these strings to bytes...
-            for (int i = 0; i < hexStrings.size(); i++) {
-                Inet6Util.convertToBytes(hexStrings.get(i), ipByteArray, i * 2);
-            }
-
-            // Now if there are any decimal values, we know where they go...
-            for (int i = 0; i < decStrings.size(); i++) {
-                ipByteArray[i + 12] = (byte) (Integer.parseInt(decStrings
-                        .get(i)) & 255);
-            }
-
-            // now check to see if this guy is actually and IPv4 address
-            // an ipV4 address is ::FFFF:d.d.d.d
-            boolean ipV4 = true;
-            for (int i = 0; i < 10; i++) {
-                if (ipByteArray[i] != 0) {
-                    ipV4 = false;
-                    break;
-                }
-            }
-
-            if (ipByteArray[10] != -1 || ipByteArray[11] != -1) {
-                ipV4 = false;
-            }
-
-            if (ipV4) {
-                byte ipv4ByteArray[] = new byte[4];
-                for (int i = 0; i < 4; i++) {
-                    ipv4ByteArray[i] = ipByteArray[i + 12];
-                }
-                address = InetAddress.getByAddress(ipv4ByteArray);
-            } else {
-                int scopeId = 0;
-                if (scopeString != null) {
-                    try {
-                        scopeId = Integer.parseInt(scopeString);
-                    } catch (Exception e) {
-                        // this should not occur as we should not get into this
-                        // function unless the address is in a valid format
-                    }
-                }
-                address = InetAddress.getByAddress(ipByteArray, scopeId);
-            }
-        }
-
-        return address;
-    }
-
     static boolean preferIPv6Addresses() {
         String result = AccessController.doPrivileged(new PriviAction<String>(
                 "java.net.preferIPv6Addresses")); //$NON-NLS-1$
diff --git a/libcore/luni/src/main/java/java/net/InetSocketAddress.java b/libcore/luni/src/main/java/java/net/InetSocketAddress.java
index 6901053..08e75a9 100644
--- a/libcore/luni/src/main/java/java/net/InetSocketAddress.java
+++ b/libcore/luni/src/main/java/java/net/InetSocketAddress.java
@@ -23,8 +23,6 @@
 /**
  * This class represents a socket endpoint described by a IP address and a port
  * number. It is a concrete implementation of {@code SocketAddress} for IP.
- * 
- * @since Android 1.0
  */
 public class InetSocketAddress extends SocketAddress {
 
@@ -37,13 +35,12 @@
     private int port;
 
     /**
-     * Creates a socket endpoint with the given port number {@code port} and the
-     * wildcard address {@code InetAddress.ANY}. The range for valid port numbers
-     * is between 0 and 65535 inclusive.
-     * 
+     * Creates a socket endpoint with the given port number {@code port} and
+     * no specified address. The range for valid port numbers is between 0 and
+     * 65535 inclusive.
+     *
      * @param port
      *            the specified port number to which this socket is bound.
-     * @since Android 1.0
      */
     public InetSocketAddress(int port) {
         this((InetAddress) null, port);
@@ -53,20 +50,19 @@
      * Creates a socket endpoint with the given port number {@code port} and
      * {@code address}. The range for valid port numbers is between 0 and 65535
      * inclusive. If {@code address} is {@code null} this socket is bound to the
-     * wildcard address {@code InetAddress.ANY}.
-     * 
+     * IPv4 wildcard address.
+     *
      * @param port
      *            the specified port number to which this socket is bound.
      * @param address
      *            the specified address to which this socket is bound.
-     * @since Android 1.0
      */
     public InetSocketAddress(InetAddress address, int port) {
         if (port < 0 || port > 65535) {
             throw new IllegalArgumentException();
         }
         if (address == null) {
-            addr = InetAddress.ANY;
+            addr = Inet4Address.ANY;
         } else {
             addr = address;
         }
@@ -79,7 +75,7 @@
      * hostname {@code host}. The hostname is tried to be resolved and cannot be
      * {@code null}. The range for valid port numbers is between 0 and 65535
      * inclusive.
-     * 
+     *
      * @param port
      *            the specified port number to which this socket is bound.
      * @param host
@@ -88,14 +84,13 @@
      *             if a {@link SecurityManager} is installed and its {@code
      *             checkConnect()} method does not allow the resolving of the
      *             host name.
-     * @since Android 1.0
      */
     public InetSocketAddress(String host, int port) {
         this(host, port, true);
     }
 
     /*
-     * Internal contructor for InetSocketAddress(String, int) and
+     * Internal constructor for InetSocketAddress(String, int) and
      * createUnresolved(String, int);
      */
     InetSocketAddress(String host, int port, boolean needResolved) {
@@ -126,7 +121,7 @@
      * Creates an {@code InetSocketAddress} without trying to resolve the
      * hostname into an {@code InetAddress}. The address field is marked as
      * unresolved.
-     * 
+     *
      * @param host
      *            the specified hostname to which this socket is bound.
      * @param port
@@ -135,7 +130,6 @@
      * @throws IllegalArgumentException
      *             if the hostname {@code host} is {@code null} or the port is
      *             not in the range between 0 and 65535.
-     * @since Android 1.0
      */
     public static InetSocketAddress createUnresolved(String host, int port) {
         return new InetSocketAddress(host, port, false);
@@ -143,9 +137,8 @@
 
     /**
      * Gets the port number of this socket.
-     * 
+     *
      * @return the socket endpoint port number.
-     * @since Android 1.0
      */
     public final int getPort() {
         return port;
@@ -153,9 +146,8 @@
 
     /**
      * Gets the address of this socket.
-     * 
+     *
      * @return the socket endpoint address.
-     * @since Android 1.0
      */
     public final InetAddress getAddress() {
         return addr;
@@ -163,9 +155,8 @@
 
     /**
      * Gets the hostname of this socket.
-     * 
+     *
      * @return the socket endpoint hostname.
-     * @since Android 1.0
      */
     public final String getHostName() {
         return (null != addr) ? addr.getHostName() : hostname;
@@ -173,10 +164,9 @@
 
     /**
      * Returns whether this socket address is unresolved or not.
-     * 
+     *
      * @return {@code true} if this socket address is unresolved, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public final boolean isUnresolved() {
         return addr == null;
@@ -185,9 +175,8 @@
     /**
      * Gets a string representation of this socket included the address and the
      * port number.
-     * 
+     *
      * @return the address and port number as a textual representation.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -204,12 +193,11 @@
      * Compares two socket endpoints and returns true if they are equal. Two
      * socket endpoints are equal if the IP address or the hostname of both are
      * equal and they are bound to the same port.
-     * 
+     *
      * @param socketAddr
      *            the object to be tested for equality.
      * @return {@code true} if this socket and the given socket object {@code
      *         socketAddr} are equal, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public final boolean equals(Object socketAddr) {
@@ -243,9 +231,8 @@
 
     /**
      * Gets the hashcode of this socket.
-     * 
+     *
      * @return the appropriate hashcode.
-     * @since Android 1.0
      */
     @Override
     public final int hashCode() {
diff --git a/libcore/luni/src/main/java/java/net/JarURLConnection.java b/libcore/luni/src/main/java/java/net/JarURLConnection.java
index 11545fa..da39d9c 100644
--- a/libcore/luni/src/main/java/java/net/JarURLConnection.java
+++ b/libcore/luni/src/main/java/java/net/JarURLConnection.java
@@ -38,15 +38,11 @@
  * jar:http://www.example.com/applets/archive.jar!/test.class}</li>
  * <li>Directory Entry: {@code
  * jar:http://www.example.com/applets/archive.jar!/applets/}</li>
- * 
- * @since Android 1.0
  */
 public abstract class JarURLConnection extends URLConnection {
 
     /**
      * The location part of the represented URL.
-     * 
-     * @since Android 1.0
      */
     protected URLConnection jarFileURLConnection;
 
@@ -60,12 +56,11 @@
     /**
      * Constructs an instance of {@code JarURLConnection} that refers to the
      * specified URL.
-     * 
+     *
      * @param url
      *            the URL that contains the location to connect to.
      * @throws MalformedURLException
      *             if an invalid URL has been entered.
-     * @since Android 1.0
      */
     protected JarURLConnection(URL url) throws MalformedURLException {
         super(url);
@@ -74,10 +69,12 @@
         if ((sepIdx = file.indexOf("!/")) < 0) { //$NON-NLS-1$
             throw new MalformedURLException();
         }
-        if (file.length() == sepIdx + 2) {
+        fileURL = new URL(url.getFile().substring(0,sepIdx)); //$NON-NLS-1$
+        sepIdx += 2;
+        if (file.length() == sepIdx) {
             return;
         }
-        entryName = file.substring(sepIdx + 2, file.length());
+        entryName = file.substring(sepIdx, file.length());
         if (null != url.getRef()) {
             entryName += "#" + url.getRef(); //$NON-NLS-1$
         }
@@ -86,12 +83,11 @@
     /**
      * Returns all attributes of the {@code JarEntry} referenced by this {@code
      * JarURLConnection}.
-     * 
+     *
      * @return the attributes of the referenced {@code JarEntry}.
-     * @exception IOException
+     * @throws IOException
      *                if an I/O exception occurs while retrieving the
      *                JAR-entries.
-     * @since Android 1.0
      */
     public Attributes getAttributes() throws java.io.IOException {
         JarEntry jEntry = getJarEntry();
@@ -102,12 +98,11 @@
      * Returns all certificates of the {@code JarEntry} referenced by this
      * {@code JarURLConnection} instance. This method will return {@code null}
      * until the {@code InputStream} has been completely verified.
-     * 
+     *
      * @return the certificates of the {@code JarEntry} as an array.
-     * @exception IOException
+     * @throws IOException
      *                if there is an I/O exception occurs while getting the
      *                {@code JarEntry}.
-     * @since Android 1.0
      */
     public Certificate[] getCertificates() throws java.io.IOException {
         JarEntry jEntry = getJarEntry();
@@ -122,9 +117,8 @@
      * Gets the name of the entry referenced by this {@code JarURLConnection}.
      * The return value will be {@code null} if this instance refers to a JAR
      * file rather than an JAR file entry.
-     * 
+     *
      * @return the {@code JarEntry} name this instance refers to.
-     * @since Android 1.0
      */
     public String getEntryName() {
         return entryName;
@@ -133,12 +127,11 @@
     /**
      * Gets the {@code JarEntry} object of the entry referenced by this {@code
      * JarURLConnection}.
-     * 
+     *
      * @return the referenced {@code JarEntry} object or {@code null} if no
      *         entry name is specified.
      * @throws IOException
      *             if an error occurs while getting the file or file-entry.
-     * @since Android 1.0
      */
     public JarEntry getJarEntry() throws IOException {
         if (!connected) {
@@ -153,56 +146,44 @@
 
     /**
      * Gets the manifest file associated with this JAR-URL.
-     * 
+     *
      * @return the manifest of the referenced JAR-file.
      * @throws IOException
      *             if an error occurs while getting the manifest file.
-     * @since Android 1.0
      */
     public Manifest getManifest() throws java.io.IOException {
-        return getJarFile().getManifest();
+        return (Manifest)getJarFile().getManifest().clone();
     }
 
     /**
      * Gets the {@code JarFile} object referenced by this {@code
      * JarURLConnection}.
-     * 
+     *
      * @return the referenced JarFile object.
-     * @exception IOException
+     * @throws IOException
      *                if an I/O exception occurs while retrieving the JAR-file.
-     * @since Android 1.0
      */
     public abstract JarFile getJarFile() throws java.io.IOException;
 
     /**
      * Gets the URL to the JAR-file referenced by this {@code JarURLConnection}.
-     * 
+     *
      * @return the URL to the JAR-file or {@code null} if there was an error
      *         retrieving the URL.
-     * @since Android 1.0
      */
     public URL getJarFileURL() {
-        if (fileURL != null) {
-            return fileURL;
-        }
-        try {
-            return fileURL = new URL(url.getFile().substring(0,
-                    url.getFile().indexOf("!/"))); //$NON-NLS-1$
-        } catch (MalformedURLException e) {
-            return null;
-        }
+        return fileURL;
     }
 
     /**
      * Gets all attributes of the manifest file referenced by this {@code
      * JarURLConnection}. If this instance refers to a JAR-file rather than a
      * JAR-file entry, {@code null} will be returned.
-     * 
+     *
      * @return the attributes of the manifest file or {@code null}.
-     * @exception IOException
+     * @throws IOException
      *                if an I/O exception occurs while retrieving the {@code
      *                JarFile}.
-     * @since Android 1.0
      */
     public Attributes getMainAttributes() throws java.io.IOException {
         Manifest m = getJarFile().getManifest();
diff --git a/libcore/luni/src/main/java/java/net/MalformedURLException.java b/libcore/luni/src/main/java/java/net/MalformedURLException.java
index 386228b..cf8aa46 100644
--- a/libcore/luni/src/main/java/java/net/MalformedURLException.java
+++ b/libcore/luni/src/main/java/java/net/MalformedURLException.java
@@ -24,7 +24,6 @@
  * incorrect specification.
  * 
  * @see URL
- * @since Android 1.0
  */
 public class MalformedURLException extends IOException {
 
@@ -32,8 +31,6 @@
 
     /**
      * Constructs a new instance of this class with its walkback filled in.
-     * 
-     * @since Android 1.0
      */
     public MalformedURLException() {
         super();
@@ -45,7 +42,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception instance.
-     * @since Android 1.0
      */
     public MalformedURLException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/net/MulticastSocket.java b/libcore/luni/src/main/java/java/net/MulticastSocket.java
index cf20890..60d967b 100644
--- a/libcore/luni/src/main/java/java/net/MulticastSocket.java
+++ b/libcore/luni/src/main/java/java/net/MulticastSocket.java
@@ -20,15 +20,14 @@
 import java.io.IOException;
 import java.util.Enumeration;
 
-import org.apache.harmony.luni.net.SocketImplProvider;
+import org.apache.harmony.luni.net.PlainDatagramSocketImpl;
 import org.apache.harmony.luni.util.Msg;
 
 /**
  * This class implements a multicast socket for sending and receiving IP
  * multicast datagram packets.
- * 
+ *
  * @see DatagramSocket
- * @since Android 1.0
  */
 public class MulticastSocket extends DatagramSocket {
 
@@ -39,10 +38,9 @@
     /**
      * Constructs a multicast socket, bound to any available port on the
      * localhost.
-     * 
+     *
      * @throws IOException
      *             if an error occurs creating or binding the socket.
-     * @since Android 1.0
      */
     public MulticastSocket() throws IOException {
         super();
@@ -52,12 +50,11 @@
     /**
      * Constructs a multicast socket, bound to the specified port on the
      * localhost.
-     * 
+     *
      * @param aPort
      *            the port to bind on the localhost.
      * @throws IOException
      *             if an error occurs creating or binding the socket.
-     * @since Android 1.0
      */
     public MulticastSocket(int aPort) throws IOException {
         super(aPort);
@@ -67,12 +64,11 @@
     /**
      * Gets the network address used by this socket. This is useful on
      * multihomed machines.
-     * 
+     *
      * @return the address of the network interface through which the datagram
      *         packets are sent or received.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs while getting the interface address.
-     * @since Android 1.0
      */
     public InetAddress getInterface() throws SocketException {
         checkClosedAndBind(false);
@@ -104,12 +100,12 @@
     /**
      * Gets the network interface used by this socket. This is useful on
      * multihomed machines.
-     * 
+     *
      * @return the network interface used by this socket or {@code null} if no
      *         interface is set.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs while getting the interface.
-     * @since Android 1.0
+     * @since 1.4
      */
     public NetworkInterface getNetworkInterface() throws SocketException {
         checkClosedAndBind(false);
@@ -150,7 +146,7 @@
                     && (InetAddress.preferIPv6Addresses() == true)) {
                 theAddresses[0] = Inet6Address.ANY;
             } else {
-                theAddresses[0] = InetAddress.ANY;
+                theAddresses[0] = Inet4Address.ANY;
             }
             return new NetworkInterface(null, null, theAddresses,
                     NetworkInterface.UNSET_INTERFACE_INDEX);
@@ -162,11 +158,10 @@
 
     /**
      * Gets the time-to-live (TTL) for multicast packets sent on this socket.
-     * 
+     *
      * @return the default value for the time-to-life field.
-     * @exception IOException
+     * @throws IOException
      *                if an error occurs reading the default value.
-     * @since Android 1.0
      */
     public int getTimeToLive() throws IOException {
         checkClosedAndBind(false);
@@ -175,13 +170,12 @@
 
     /**
      * Gets the time-to-live (TTL) for multicast packets sent on this socket.
-     * 
+     *
      * @return the default value for the time-to-life field.
-     * @exception IOException
+     * @throws IOException
      *                if an error occurs reading the default value.
      * @deprecated Replaced by {@link #getTimeToLive}
      * @see #getTimeToLive()
-     * @since Android 1.0
      */
     @Deprecated
     public byte getTTL() throws IOException {
@@ -189,21 +183,15 @@
         return impl.getTTL();
     }
 
-    @Override
-    boolean isMulticastSocket() {
-        return true;
-    }
-
     /**
      * Adds this socket to the specified multicast group. A socket must join a
      * group before data may be received. A socket may be a member of multiple
      * groups but may join any group only once.
-     * 
+     *
      * @param groupAddr
      *            the multicast group to be joined.
-     * @exception IOException
+     * @throws IOException
      *                if an error occurs while joining a group.
-     * @since Android 1.0
      */
     public void joinGroup(InetAddress groupAddr) throws IOException {
         checkClosedAndBind(false);
@@ -221,19 +209,19 @@
      * Adds this socket to the specified multicast group. A socket must join a
      * group before data may be received. A socket may be a member of multiple
      * groups but may join any group only once.
-     * 
+     *
      * @param groupAddress
      *            the multicast group to be joined.
      * @param netInterface
      *            the network interface on which the datagram packets will be
      *            received.
-     * @exception IOException
+     * @throws IOException
      *                if the specified address is not a multicast address.
-     * @exception SecurityException
+     * @throws SecurityException
      *                if the caller is not authorized to join the group.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if no multicast group is specified.
-     * @since Android 1.0
+     * @since 1.4
      */
     public void joinGroup(SocketAddress groupAddress,
             NetworkInterface netInterface) throws IOException {
@@ -271,14 +259,15 @@
 
     /**
      * Removes this socket from the specified multicast group.
-     * 
+     *
      * @param groupAddr
      *            the multicast group to be left.
-     * @exception IOException
+     * @throws NullPointerException
+     *                if {@code groupAddr} is {@code null}.
+     * @throws IOException
      *                if the specified group address is not a multicast address.
-     * @exception SecurityException
+     * @throws SecurityException
      *                if the caller is not authorized to leave the group.
-     * @since Android 1.0
      */
     public void leaveGroup(InetAddress groupAddr) throws IOException {
         checkClosedAndBind(false);
@@ -294,19 +283,19 @@
 
     /**
      * Removes this socket from the specified multicast group.
-     * 
+     *
      * @param groupAddress
      *            the multicast group to be left.
      * @param netInterface
      *            the network interface on which the addresses should be
      *            dropped.
-     * @exception IOException
+     * @throws IOException
      *                if the specified group address is not a multicast address.
-     * @exception SecurityException
+     * @throws SecurityException
      *                if the caller is not authorized to leave the group.
-     * @exception IllegalArgumentException
-     *                if no multicast group is specified.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *                if {@code groupAddress} is {@code null}.
+     * @since 1.4
      */
     public void leaveGroup(SocketAddress groupAddress,
             NetworkInterface netInterface) throws IOException {
@@ -344,16 +333,15 @@
     /**
      * Send the packet on this socket. The packet must satisfy the security
      * policy before it may be sent.
-     * 
+     *
      * @param pack
      *            the {@code DatagramPacket} to send
      * @param ttl
      *            the TTL setting for this transmission, overriding the socket
      *            default
-     * @exception IOException
+     * @throws IOException
      *                if an error occurs while sending data or setting options.
      * @deprecated use {@link #setTimeToLive}.
-     * @since Android 1.0
      */
     @Deprecated
     public void send(DatagramPacket pack, byte ttl) throws IOException {
@@ -384,13 +372,12 @@
      * Sets the interface address used by this socket. This allows to send
      * multicast packets on a different interface than the default interface of
      * the local system. This is useful on multihomed machines.
-     * 
+     *
      * @param addr
      *            the multicast interface network address to set.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs while setting the network interface
      *                address option.
-     * @since Android 1.0
      */
     public void setInterface(InetAddress addr) throws SocketException {
         checkClosedAndBind(false);
@@ -398,7 +385,7 @@
             throw new NullPointerException();
         }
         if (addr.isAnyLocalAddress()) {
-            impl.setOption(SocketOptions.IP_MULTICAST_IF, InetAddress.ANY);
+            impl.setOption(SocketOptions.IP_MULTICAST_IF, Inet4Address.ANY);
         } else if (addr instanceof Inet4Address) {
             impl.setOption(SocketOptions.IP_MULTICAST_IF, addr);
             // keep the address used to do the set as we must return the same
@@ -435,13 +422,13 @@
     /**
      * Sets the network interface used by this socket. This is useful for
      * multihomed machines.
-     * 
+     *
      * @param netInterface
      *            the multicast network interface to set.
-     * @exception SocketException
+     * @throws SocketException
      *                if an error occurs while setting the network interface
      *                option.
-     * @since Android 1.0
+     * @since 1.4
      */
     public void setNetworkInterface(NetworkInterface netInterface)
             throws SocketException {
@@ -462,7 +449,7 @@
         if (netInterface.getIndex() == NetworkInterface.UNSET_INTERFACE_INDEX) {
             // set the address using IP_MULTICAST_IF to make sure this
             // works for both IPV4 and IPV6
-            impl.setOption(SocketOptions.IP_MULTICAST_IF, InetAddress.ANY);
+            impl.setOption(SocketOptions.IP_MULTICAST_IF, Inet4Address.ANY);
 
             try {
                 // we have the index so now we pass set the interface
@@ -529,13 +516,12 @@
     /**
      * Sets the time-to-live (TTL) for multicast packets sent on this socket.
      * Valid TTL values are between 0 and 255 inclusive.
-     * 
+     *
      * @param ttl
      *            the default time-to-live field value for packets sent on this
      *            socket. {@code 0 <= ttl <= 255}.
-     * @exception IOException
+     * @throws IOException
      *                if an error occurs while setting the TTL option value.
-     * @since Android 1.0
      */
     public void setTimeToLive(int ttl) throws IOException {
         checkClosedAndBind(false);
@@ -548,15 +534,14 @@
     /**
      * Sets the time-to-live (TTL) for multicast packets sent on this socket.
      * Valid TTL values are between 0 and 255 inclusive.
-     * 
+     *
      * @param ttl
      *            the default time-to-live field value for packets sent on this
      *            socket: {@code 0 <= ttl <= 255}.
-     * @exception IOException
+     * @throws IOException
      *                if an error occurs while setting the TTL option value.
      * @deprecated Replaced by {@link #setTimeToLive}
      * @see #setTimeToLive(int)
-     * @since Android 1.0
      */
     @Deprecated
     public void setTTL(byte ttl) throws IOException {
@@ -568,11 +553,10 @@
     synchronized void createSocket(int aPort, InetAddress addr)
             throws SocketException {
         impl = factory != null ? factory.createDatagramSocketImpl()
-                : SocketImplProvider.getMulticastSocketImpl();
+                : new PlainDatagramSocketImpl();
         impl.create();
         try {
-            // the required default options are now set in the VM where they
-            // should be
+            impl.setOption(SocketOptions.SO_REUSEADDR, Boolean.TRUE);
             impl.bind(aPort, addr);
             isBound = true;
         } catch (SocketException e) {
@@ -585,14 +569,14 @@
      * Constructs a {@code MulticastSocket} bound to the host/port specified by
      * the {@code SocketAddress}, or an unbound {@code DatagramSocket} if the
      * {@code SocketAddress} is {@code null}.
-     * 
+     *
      * @param localAddr
      *            the local machine address and port to bind to.
      * @throws IllegalArgumentException
      *             if the {@code SocketAddress} is not supported.
      * @throws IOException
      *             if an error occurs creating or binding the socket.
-     * @since Android 1.0
+     * @since 1.4
      */
     public MulticastSocket(SocketAddress localAddr) throws IOException {
         super(localAddr);
@@ -601,12 +585,12 @@
 
     /**
      * Gets the state of the {@code SocketOptions.IP_MULTICAST_LOOP}.
-     * 
+     *
      * @return {@code true} if the IP multicast loop is enabled, {@code false}
      *         otherwise.
      * @throws SocketException
      *             if the socket is closed or the option is invalid.
-     * @since Android 1.0
+     * @since 1.4
      */
     public boolean getLoopbackMode() throws SocketException {
         checkClosedAndBind(false);
@@ -616,13 +600,13 @@
 
     /**
      * Sets the {@code SocketOptions.IP_MULTICAST_LOOP}.
-     * 
+     *
      * @param loop
      *            the value for the socket option socket {@code
      *            SocketOptions.IP_MULTICAST_LOOP}.
      * @throws SocketException
      *             if the socket is closed or the option is invalid.
-     * @since Android 1.0
+     * @since 1.4
      */
     public void setLoopbackMode(boolean loop) throws SocketException {
         checkClosedAndBind(false);
diff --git a/libcore/luni/src/main/java/java/net/NegCacheElement.java b/libcore/luni/src/main/java/java/net/NegCacheElement.java
index 7285a14..e195f31 100644
--- a/libcore/luni/src/main/java/java/net/NegCacheElement.java
+++ b/libcore/luni/src/main/java/java/net/NegCacheElement.java
@@ -4,9 +4,9 @@
  * 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.
@@ -18,28 +18,27 @@
 
 /**
  * This class is used to hold information about failed host name lookups.
- * 
+ *
  * @see NegativeCache
- * @since Android 1.0
  */
 class NegCacheElement {
 
     // we need the time to figure out when the entry is stale
     // BEGIN android-changed
     final long nanoTimeAdded = System.nanoTime();
+    // END android-changed
 
-    // holds the name of the host for which the lookup failed
-    final String hostName;
-    
+    // holds the name of the lookup failure message for this host
+    final String failedMessage;
+
     /**
      * Constructor used to set the hostname for the entry for which the lookup
      * failed.
-     * 
-     * @param hostName
+     *
+     * @param failedMessage
      *            name of the host for which the lookup failed.
      */
-    NegCacheElement(String hostName) {
-        this.hostName = hostName;
+    NegCacheElement(String failedMessage) {
+        this.failedMessage = failedMessage;
     }
-    // END android-changed
 }
diff --git a/libcore/luni/src/main/java/java/net/NegativeCache.java b/libcore/luni/src/main/java/java/net/NegativeCache.java
index 58078fc..d6b1515 100644
--- a/libcore/luni/src/main/java/java/net/NegativeCache.java
+++ b/libcore/luni/src/main/java/java/net/NegativeCache.java
@@ -4,9 +4,9 @@
  * 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.
@@ -25,83 +25,60 @@
 /**
  * This class is used to maintain the negative name lookup cache, which caches
  * host names which could not be resolved, as a security feature.
- * 
+ *
  * @see NegCacheElement
- * @since Android 1.0
  */
-class NegativeCache<K, V> extends LinkedHashMap<K, V> {
-
-    private static final long serialVersionUID = 1L;
-
-    // BEGIN android-changed
-    // Copied from a newer version of harmony
-    private static NegativeCache<String, NegCacheElement> negCache;
-
-    // maximum number of entries in the cache
+class NegativeCache {
+   // maximum number of entries in the cache
     private static final int MAX_NEGATIVE_ENTRIES = 5;
 
     // the loading for the cache
-    private static final float LOADING = 0.75F;
-    // END android-changed
+    private static final float LOAD_FACTOR = 0.75F;
 
-    /**
-     * Returns the hostname for the cache element.
-     * 
-     * @return hostName name of the host for which the lookup failed.
-     * @since Android 1.0
-     */
-    NegativeCache(int initialCapacity, float loadFactor, boolean accessOrder) {
-        super(initialCapacity, loadFactor, accessOrder);
-    }
+    private static final Map<String, NegCacheElement> negCache
+            = new LinkedHashMap<String, NegCacheElement>(
+                2 * MAX_NEGATIVE_ENTRIES, LOAD_FACTOR, true) {
 
-    /**
-     * Returns whether the eldest entry should be removed. It is removed if the
-     * size has grown beyond the maximum size allowed for the cache. A {@code
-     * LinkedHashMap} is created such that the least recently used entry is
-     * deleted.
-     * 
-     * @param eldest
-     *            the map entry which will be deleted if we return {@code true}.
-     * @since Android 1.0
-     */
-    @Override
-    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
-        return size() > MAX_NEGATIVE_ENTRIES;
+        /**
+         * Returns whether the eldest entry should be removed. It is removed if
+         * the size has grown beyond the maximum size allowed for the cache.
+         *
+         * @param eldest
+         *            the LRU entry, which will be deleted if we return true.
+         */
+        @Override protected boolean removeEldestEntry(
+                Entry<String, NegCacheElement> eldest) {
+            return size() > MAX_NEGATIVE_ENTRIES;
+        }
+    };
+
+    /** Ensures non-instantiability */
+    private NegativeCache() {
     }
 
     /**
      * Adds the host name and the corresponding name lookup fail message to the
      * cache.
-     * 
+     *
      * @param hostName
      *            the name of the host for which the lookup failed.
      * @param failedMessage
      *            the message returned when the lookup fails.
-     * @since Android 1.0
      */
     static synchronized void put(String hostName, String failedMessage) {
-        // BEGIN android-note
-        // Made synchronized. copied from a newer version of harmony
-        // END android-note
-        checkCacheExists();
         negCache.put(hostName, new NegCacheElement(failedMessage));
     }
 
     /**
      * Returns the message of the negative cache if the entry has not yet
      * expired.
-     * 
+     *
      * @param hostName
      *            the name of the host for which we look up the entry.
      * @return the message which was returned when the host lookup failed if the
      *         entry has not yet expired.
-     * @since Android 1.0
      */
     static synchronized String getFailedMessage(String hostName) {
-        // BEGIN android-note
-        // Made synchronized. copied from a newer version of harmony
-        // END android-note
-        checkCacheExists();
         NegCacheElement element = negCache.get(hostName);
         if (element != null) {
             // check if element is still valid
@@ -111,9 +88,10 @@
             int ttl = 10;
             try {
                 if (ttlValue != null) {
-                    ttl = Integer.decode(ttlValue).intValue();
+                    ttl = Integer.decode(ttlValue);
                 }
             } catch (NumberFormatException e) {
+                // If exception, go with ttl == 10
             }
             if (ttl == 0) {
                 negCache.clear();
@@ -130,10 +108,7 @@
             }
         }
         if (element != null) {
-            // BEGIN android-changed
-            // Copied from a newer version of harmony
-            return element.hostName;
-            // END android-changed
+            return element.failedMessage;
         }
         return null;
     }
@@ -146,24 +121,4 @@
         return ttl * 1000000000;
     }
     // END android-added
-
-    /**
-     * This method checks whether the cache was already created and if not
-     * creates it.
-     */
-    static synchronized void checkCacheExists() {
-        // BEGIN android-note
-        // Made synchronized. copied from a newer version of harmony
-        // END android-note
-        if (negCache == null) {
-            /*
-             * Create with the access order set so ordering is based on when the
-             * entries were last accessed. We make the default cache size one
-             * greater than the maximum number of entries as we will grow to one
-             * larger and then delete the LRU entry
-             */
-            negCache = new NegativeCache<String, NegCacheElement>(
-                    MAX_NEGATIVE_ENTRIES + 1, LOADING, true);
-        }
-    }
 }
diff --git a/libcore/luni/src/main/java/java/net/NetPermission.java b/libcore/luni/src/main/java/java/net/NetPermission.java
index e7cca8b..bac9d89 100644
--- a/libcore/luni/src/main/java/java/net/NetPermission.java
+++ b/libcore/luni/src/main/java/java/net/NetPermission.java
@@ -31,11 +31,9 @@
  * <dd>Allows a stream (protocol) handler to be set when constructing an URL
  * object</dd>
  * </dl>
- * </p>
  * 
  * @see java.security.BasicPermission
  * @see SecurityManager
- * @since Android 1.0
  */
 public final class NetPermission extends java.security.BasicPermission {
 
@@ -46,7 +44,6 @@
      * 
      * @param name
      *            the name of the new NetPermission instance.
-     * @since Android 1.0
      */
     public NetPermission(String name) {
         super(name);
@@ -60,7 +57,6 @@
      *            the name of the new {@code NetPermission} instance.
      * @param actions
      *            the ignored action string.
-     * @since Android 1.0
      */
     public NetPermission(String name, String actions) {
         super(name, actions);
diff --git a/libcore/luni/src/main/java/java/net/NetworkInterface.java b/libcore/luni/src/main/java/java/net/NetworkInterface.java
index 68452e6b..091eb9f 100644
--- a/libcore/luni/src/main/java/java/net/NetworkInterface.java
+++ b/libcore/luni/src/main/java/java/net/NetworkInterface.java
@@ -28,8 +28,6 @@
  * interface is defined by its address and a platform dependent name. The class
  * provides methods to get all information about the available interfaces of the
  * system or to identify the local interface of a joined multicast group.
- * 
- * @since Android 1.0
  */
 public final class NetworkInterface extends Object {
 
@@ -115,7 +113,6 @@
      * Gets the name associated with this network interface.
      * 
      * @return the name of this {@code NetworkInterface} instance.
-     * @since Android 1.0
      */
     public String getName() {
         return name;
@@ -125,7 +122,6 @@
      * Gets a list of addresses bound to this network interface.
      * 
      * @return the address list of the represented network interface.
-     * @since Android 1.0
      */
     public Enumeration<InetAddress> getInetAddresses() {
         /*
@@ -192,7 +188,6 @@
      * 
      * @return the display name of this network interface or the name if the
      *         display name is not available.
-     * @since Android 1.0
      */
     public String getDisplayName() {
         /*
@@ -217,7 +212,6 @@
      *             information.
      * @throws NullPointerException
      *             if the given interface's name is {@code null}.
-     * @since Android 1.0
      */
     public static NetworkInterface getByName(String interfaceName)
             throws SocketException {
@@ -244,7 +238,7 @@
 
     /**
      * Gets the specific network interface according to the given address.
-     * 
+     *
      * @param address
      *            the address to identify the searched network interface.
      * @return the network interface with the specified address if one exists or
@@ -254,7 +248,6 @@
      *             information.
      * @throws NullPointerException
      *             if the given interface address is invalid.
-     * @since Android 1.0
      */
     public static NetworkInterface getByInetAddress(InetAddress address)
             throws SocketException {
@@ -302,7 +295,6 @@
      * @throws SocketException
      *             if an error occurs while getting the network interface
      *             information.
-     * @since Android 1.0
      */
     public static Enumeration<NetworkInterface> getNetworkInterfaces()
             throws SocketException {
@@ -343,7 +335,6 @@
      * @return {@code true} if the specified object is equal to this {@code
      *         NetworkInterface}, {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object obj) {
@@ -412,7 +403,6 @@
      * generated using this name.
      * 
      * @return the hashcode value for this {@code NetworkInterface} instance.
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -427,7 +417,6 @@
      * network interface.
      * 
      * @return the textual representation for this network interface.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
diff --git a/libcore/luni/src/main/java/java/net/NoRouteToHostException.java b/libcore/luni/src/main/java/java/net/NoRouteToHostException.java
index 042ccd4..f2e2c36 100644
--- a/libcore/luni/src/main/java/java/net/NoRouteToHostException.java
+++ b/libcore/luni/src/main/java/java/net/NoRouteToHostException.java
@@ -21,8 +21,6 @@
  * The {@code NoRouteToHostException} will be thrown while attempting to connect
  * to a remote host but the host cannot be reached for instance because of a
  * badly configured router or a blocking firewall.
- * 
- * @since Android 1.0
  */
 public class NoRouteToHostException extends SocketException {
 
@@ -30,8 +28,6 @@
 
     /**
      * Constructs a new instance of this exception with its walkback filled in.
-     * 
-     * @since Android 1.0
      */
     public NoRouteToHostException() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public NoRouteToHostException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/net/PasswordAuthentication.java b/libcore/luni/src/main/java/java/net/PasswordAuthentication.java
index 324f878..735810d 100644
--- a/libcore/luni/src/main/java/java/net/PasswordAuthentication.java
+++ b/libcore/luni/src/main/java/java/net/PasswordAuthentication.java
@@ -20,9 +20,8 @@
 /**
  * This immutable class is a data structure that encapsulates username and
  * password which is used by the {@code Authenticator} class.
- * 
+ *
  * @see Authenticator
- * @since Android 1.0
  */
 public final class PasswordAuthentication {
 
@@ -38,7 +37,6 @@
      *            the username to store.
      * @param password
      *            the associated password to store.
-     * @since Android 1.0
      */
     public PasswordAuthentication(String userName, char[] password) {
         this.userName = userName;
@@ -51,7 +49,6 @@
      * longer needed.
      * 
      * @return the copied password.
-     * @since Android 1.0
      */
     public char[] getPassword() {
         return password.clone();
@@ -61,7 +58,6 @@
      * Gets the username stored by this instance.
      * 
      * @return the stored username.
-     * @since Android 1.0
      */
     public String getUserName() {
         return userName;
diff --git a/libcore/luni/src/main/java/java/net/PortUnreachableException.java b/libcore/luni/src/main/java/java/net/PortUnreachableException.java
index 973a978..2b5b25b 100644
--- a/libcore/luni/src/main/java/java/net/PortUnreachableException.java
+++ b/libcore/luni/src/main/java/java/net/PortUnreachableException.java
@@ -27,8 +27,6 @@
 
     /**
      * Constructs a new instance of this class with its walkback filled in.
-     * 
-     * @since Android 1.0
      */
     public PortUnreachableException() {
     }
@@ -39,7 +37,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public PortUnreachableException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/net/ProtocolException.java b/libcore/luni/src/main/java/java/net/ProtocolException.java
index f32dedc..ebbdc44 100644
--- a/libcore/luni/src/main/java/java/net/ProtocolException.java
+++ b/libcore/luni/src/main/java/java/net/ProtocolException.java
@@ -21,8 +21,6 @@
  * Signals that either a connection attempt to a socket of the wrong type, the
  * application of an unsupported operation or that a general error in the
  * underlying protocol has occurred.
- * 
- * @since Android 1.0
  */
 public class ProtocolException extends java.io.IOException {
 
@@ -30,8 +28,6 @@
 
     /**
      * Constructs a new instance of this class with its walkback filled in.
-     * 
-     * @since Android 1.0
      */
     public ProtocolException() {
         super();
@@ -43,7 +39,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public ProtocolException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/net/Proxy.java b/libcore/luni/src/main/java/java/net/Proxy.java
index df0383d..3442339 100644
--- a/libcore/luni/src/main/java/java/net/Proxy.java
+++ b/libcore/luni/src/main/java/java/net/Proxy.java
@@ -25,8 +25,6 @@
  * <li>DIRECT</li>
  * <li>HTTP</li>
  * <li>SOCKS</li></ul
- * 
- * @since Android 1.0
  */
 public class Proxy {
 
@@ -34,8 +32,6 @@
      * Represents the proxy type setting {@code Proxy.Type.DIRECT}. It tells
      * protocol handlers that there is no proxy to be used. The address is set
      * to {@code null}.
-     * 
-     * @since Android 1.0
      */
     public static final Proxy NO_PROXY = new Proxy();
 
@@ -58,7 +54,6 @@
      *             if the parameter {@code type} is set to {@code
      *             Proxy.Type.DIRECT} or the value for {@code SocketAddress} is
      *             {@code null}.
-     * @since Android 1.0
      */
     public Proxy(Proxy.Type type, SocketAddress sa) {
         /*
@@ -86,7 +81,6 @@
      * Gets the type of this {@code Proxy} instance.
      * 
      * @return the stored proxy type.
-     * @since Android 1.0
      */
     public Proxy.Type type() {
         return type;
@@ -97,7 +91,6 @@
      * 
      * @return the stored proxy address or {@code null} if the proxy type is
      *         {@code DIRECT}.
-     * @since Android 1.0
      */
     public SocketAddress address() {
         return address;
@@ -107,9 +100,8 @@
      * Gets a textual representation of this {@code Proxy} instance. The string
      * includes the two parts {@code type.toString()} and {@code
      * address.toString()} if {@code address} is not {@code null}.
-     * 
+     *
      * @return the representing string of this proxy.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -131,7 +123,6 @@
      * @return {@code true} if the given object represents the same {@code
      *         Proxy} as this instance, {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public final boolean equals(Object obj) {
@@ -150,7 +141,6 @@
      * Gets the hashcode for this {@code Proxy} instance.
      * 
      * @return the hashcode value for this Proxy instance.
-     * @since Android 1.0
      */
     @Override
     public final int hashCode() {
@@ -165,8 +155,6 @@
     /**
      * {@code Enum} class for the proxy type. Possible options are {@code
      * DIRECT}, {@code HTTP} and {@code SOCKS}.
-     * 
-     * @since Android 1.0
      */
     public enum Type {
         /**
diff --git a/libcore/luni/src/main/java/java/net/ProxySelector.java b/libcore/luni/src/main/java/java/net/ProxySelector.java
index aad4bcc..334ea1e 100644
--- a/libcore/luni/src/main/java/java/net/ProxySelector.java
+++ b/libcore/luni/src/main/java/java/net/ProxySelector.java
@@ -24,8 +24,6 @@
  * can be set as default by calling the {@code setDefault()} method. If a
  * connection can't be established, the caller should notify the proxy selector
  * by invoking the {@code connectFailed()} method.
- * 
- * @since Android 1.0
  */
 public abstract class ProxySelector {
 
@@ -47,8 +45,6 @@
 
     /**
      * Creates a new {@code ProxySelector} instance.
-     * 
-     * @since Android 1.0
      */
     public ProxySelector() {
         super();
@@ -61,7 +57,6 @@
      * @throws SecurityException
      *             if a security manager is installed but it doesn't have the
      *             NetPermission("getProxySelector").
-     * @since Android 1.0
      */
     public static ProxySelector getDefault() {
         SecurityManager sm = System.getSecurityManager();
@@ -83,7 +78,6 @@
      * @throws SecurityException
      *             if a security manager is installed but it doesn't have the
      *             NetPermission("setProxySelector").
-     * @since Android 1.0
      */
     public static void setDefault(ProxySelector selector) {
         SecurityManager sm = System.getSecurityManager();
@@ -101,14 +95,14 @@
      * <li>https URI stands for https connection.</li>
      * <li>ftp URI stands for ftp connection.</li>
      * <li>socket:://ip:port URI stands for tcp client sockets connection.</li>
-     * </p>
-     * 
+     *
      * @param uri
      *            the target URI object.
      * @return a list containing all applicable proxies. If no proxy is
      *         available, the list contains only the {@code Proxy.NO_PROXY}
      *         element.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *             if {@code uri} is {@code null}.
      */
     public abstract List<Proxy> select(URI uri);
 
@@ -125,8 +119,9 @@
      * @param ioe
      *            the exception which was thrown during connection
      *            establishment.
+     * @throws IllegalArgumentException
+     *             if any argument is {@code null}.
      * @see #select(URI)
-     * @since Android 1.0
      */
     public abstract void connectFailed(URI uri, SocketAddress sa,
             IOException ioe);
diff --git a/libcore/luni/src/main/java/java/net/ProxySelectorImpl.java b/libcore/luni/src/main/java/java/net/ProxySelectorImpl.java
index 79ce0cf..fa8d049 100644
--- a/libcore/luni/src/main/java/java/net/ProxySelectorImpl.java
+++ b/libcore/luni/src/main/java/java/net/ProxySelectorImpl.java
@@ -30,9 +30,8 @@
 
 /**
  * Default implementation for {@code ProxySelector}.
- * 
- * @since Android 1.0
  */
+@SuppressWarnings("unchecked")
 class ProxySelectorImpl extends ProxySelector {
 
     private static final int HTTP_PROXY_PORT = 80;
@@ -239,7 +238,7 @@
      */
     private boolean isNonProxyHost(String host, String nonProxyHosts) {
         // nonProxyHosts is not set
-        if (null == nonProxyHosts) {
+        if (null == host || null == nonProxyHosts) {
             return false;
         }
         // Construct regex expression of nonProxyHosts
diff --git a/libcore/luni/src/main/java/java/net/ResponseCache.java b/libcore/luni/src/main/java/java/net/ResponseCache.java
index e7a0aca..427b63d 100644
--- a/libcore/luni/src/main/java/java/net/ResponseCache.java
+++ b/libcore/luni/src/main/java/java/net/ResponseCache.java
@@ -28,24 +28,20 @@
  * getDefault()}. If {@code URLConnection#useCaches} is set, {@code
  * URLConnection} class will use {@code ResponseCache} to store and get
  * resources.
- * </p>
  * <p>
  * Whether the resource is cached depends on the implementation of {@code
  * ResponseCache}. If so, a {@code CacheResponse} is returned from which the
  * stream handler reads. If the stream handler fails to get a resource from the
  * cache, it must get the resource from its original location.
- * </p>
  * <p>
  * To write to the cache, the protocol handlers call {@code put()}, upon which a
  * {@code CacheRequest} is supplied to which the resources are written.
- * </p>
- * 
+ *
  * @see #put(URI, URLConnection)
  * @see CacheRequest
  * @see CacheResponse
  * @see URLConnection
  * @see URLStreamHandler
- * @since Android 1.0
  */
 public abstract class ResponseCache {
 
@@ -92,8 +88,6 @@
 
     /**
      * Creates a new instance of this class.
-     * 
-     * @since Android 1.0
      */
     public ResponseCache() {
         super();
@@ -106,7 +100,6 @@
      * @throws SecurityException
      *             if a security manager is installed but it doesn't have the
      *             {@code NetPermission("getResponseCache")}.
-     * @since Android 1.0
      */
     public static ResponseCache getDefault() {
         checkGetResponseCachePermission();
@@ -126,7 +119,6 @@
      * @throws SecurityException
      *             if a security manager is installed but it doesn't have the
      *             {@code NetPermission("setResponseCache")}.
-     * @since Android 1.0
      */
     public static void setDefault(ResponseCache responseCache) {
         checkSetResponseCachePermission();
@@ -149,7 +141,6 @@
      *             if an I/O error occurs while getting the cached data.
      * @throws IllegalArgumentException
      *             if any one of the parameters is set to {@code null}.
-     * @since Android 1.0
      */
     public abstract CacheResponse get(URI uri, String rqstMethod,
             Map<String, List<String>> rqstHeaders) throws IOException;
@@ -171,7 +162,6 @@
      *             if an I/O error occurs while adding the resource.
      * @throws IllegalArgumentException
      *             if any one of the parameters is set to {@code null}.
-     * @since Android 1.0
      */
     public abstract CacheRequest put(URI uri, URLConnection conn)
             throws IOException;
diff --git a/libcore/luni/src/main/java/java/net/SecureCacheResponse.java b/libcore/luni/src/main/java/java/net/SecureCacheResponse.java
index fff6b82..0031b3a 100644
--- a/libcore/luni/src/main/java/java/net/SecureCacheResponse.java
+++ b/libcore/luni/src/main/java/java/net/SecureCacheResponse.java
@@ -27,14 +27,11 @@
  * protocol like TLS or SSL.
  * 
  * @see ResponseCache
- * @since Android 1.0
  */
 public abstract class SecureCacheResponse extends CacheResponse {
 
     /**
      * Creates a new instance of this class.
-     * 
-     * @since Android 1.0
      */
     public SecureCacheResponse() {
         super();
@@ -45,7 +42,6 @@
      * to retrieve the network resource.
      * 
      * @return the cipher suite string.
-     * @since Android 1.0
      */
     public abstract String getCipherSuite();
 
@@ -57,7 +53,6 @@
      * 
      * @return the certificate chain that was sent to the server. If no
      *         certificate chain was sent, the method returns {@code null}.
-     * @since Android 1.0
      */
     public abstract List<Certificate> getLocalCertificateChain();
 
@@ -71,7 +66,6 @@
      * @return the server's certificate chain.
      * @throws SSLPeerUnverifiedException
      *             if the peer is unverified.
-     * @since Android 1.0
      */
     public abstract List<Certificate> getServerCertificateChain()
             throws SSLPeerUnverifiedException;
@@ -84,7 +78,6 @@
      * @return a principal object representing the server's principal.
      * @throws SSLPeerUnverifiedException
      *             if the peer is unverified.
-     * @since Android 1.0
      */
     public abstract Principal getPeerPrincipal()
             throws SSLPeerUnverifiedException;
@@ -97,7 +90,6 @@
      * @return the local principal object being sent to the server. Returns an
      *         {@code X500Principal} object for X509-based cipher suites. If no
      *         principal was sent, it returns {@code null}.
-     * @since Android 1.0
      */
     public abstract Principal getLocalPrincipal();
 }
diff --git a/libcore/luni/src/main/java/java/net/ServerSocket.java b/libcore/luni/src/main/java/java/net/ServerSocket.java
index 5f7e079..f9d5b22 100644
--- a/libcore/luni/src/main/java/java/net/ServerSocket.java
+++ b/libcore/luni/src/main/java/java/net/ServerSocket.java
@@ -20,9 +20,8 @@
 import java.io.IOException;
 import java.nio.channels.ServerSocketChannel;
 
-import org.apache.harmony.luni.net.SocketImplProvider;
+import org.apache.harmony.luni.net.PlainServerSocketImpl;
 import org.apache.harmony.luni.platform.Platform;
-
 import org.apache.harmony.luni.util.Msg;
 
 /**
@@ -30,8 +29,6 @@
  * connections. A {@code ServerSocket} handles the requests and sends back an
  * appropriate reply. The actual tasks that a server socket must accomplish are
  * implemented by an internal {@code SocketImpl} instance.
- * 
- * @since Android 1.0
  */
 public class ServerSocket {
 
@@ -44,7 +41,7 @@
     private boolean isBound;
 
     private boolean isClosed;
-    
+
     static {
         Platform.getNetworkSystem().oneTimeInitialization(true);
     }
@@ -52,14 +49,13 @@
     /**
      * Constructs a new {@code ServerSocket} instance which is not bound to any
      * port. The default number of pending connections may be backlogged.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while creating the server socket.
-     * @since Android 1.0
      */
     public ServerSocket() throws IOException {
         impl = factory != null ? factory.createSocketImpl()
-                : SocketImplProvider.getServerSocketImpl();
+                : new PlainServerSocketImpl();
     }
 
     /**
@@ -81,15 +77,14 @@
      * Constructs a new {@code ServerSocket} instance bound to the nominated
      * port on the localhost. The default number of pending connections may be
      * backlogged. If {@code aport} is 0 a free port is assigned to the socket.
-     * 
+     *
      * @param aport
      *            the port number to listen for connection requests on.
      * @throws IOException
      *             if an error occurs while creating the server socket.
-     * @since Android 1.0
      */
     public ServerSocket(int aport) throws IOException {
-        this(aport, defaultBacklog(), InetAddress.ANY);
+        this(aport, defaultBacklog(), Inet4Address.ANY);
     }
 
     /**
@@ -97,7 +92,7 @@
      * port on the localhost. The number of pending connections that may be
      * backlogged is specified by {@code backlog}. If {@code aport} is 0 a free
      * port is assigned to the socket.
-     * 
+     *
      * @param aport
      *            the port number to listen for connection requests on.
      * @param backlog
@@ -105,10 +100,9 @@
      *            will be rejected.
      * @throws IOException
      *             if an error occurs while creating the server socket.
-     * @since Android 1.0
      */
     public ServerSocket(int aport, int backlog) throws IOException {
-        this(aport, backlog, InetAddress.ANY);
+        this(aport, backlog, Inet4Address.ANY);
     }
 
     /**
@@ -116,7 +110,7 @@
      * local host address and port. The number of pending connections that may
      * be backlogged is specified by {@code backlog}. If {@code aport} is 0 a
      * free port is assigned to the socket.
-     * 
+     *
      * @param aport
      *            the port number to listen for connection requests on.
      * @param localAddr
@@ -126,15 +120,14 @@
      *            will be rejected.
      * @throws IOException
      *             if an error occurs while creating the server socket.
-     * @since Android 1.0
      */
     public ServerSocket(int aport, int backlog, InetAddress localAddr)
             throws IOException {
         super();
         checkListen(aport);
         impl = factory != null ? factory.createSocketImpl()
-                : SocketImplProvider.getServerSocketImpl();
-        InetAddress addr = localAddr == null ? InetAddress.ANY : localAddr;
+                : new PlainServerSocketImpl();
+        InetAddress addr = localAddr == null ? Inet4Address.ANY : localAddr;
 
         synchronized (this) {
             impl.create(true);
@@ -154,11 +147,10 @@
      * Waits for an incoming request and blocks until the connection is opened.
      * This method returns a socket object representing the just opened
      * connection.
-     * 
+     *
      * @return the connection representing socket.
      * @throws IOException
      *             if an error occurs while accepting a new connection.
-     * @since Android 1.0
      */
     public Socket accept() throws IOException {
         checkClosedAndCreate(false);
@@ -190,10 +182,9 @@
      * Checks whether the server may listen for connection requests on {@code
      * aport}. Throws an exception if the port is outside the valid range
      * {@code 0 <= aport <= 65535 }or does not satisfy the security policy.
-     * 
+     *
      * @param aPort
      *            the candidate port to listen on.
-     * @since Android 1.0
      */
     void checkListen(int aPort) {
         if (aPort < 0 || aPort > 65535) {
@@ -208,10 +199,9 @@
     /**
      * Closes this server socket and its implementation. Any attempt to connect
      * to this socket thereafter will fail.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this socket.
-     * @since Android 1.0
      */
     public void close() throws IOException {
         isClosed = true;
@@ -222,7 +212,7 @@
      * Answer the default number of pending connections on a server socket. If
      * the backlog value maximum is reached, any subsequent incoming request is
      * rejected.
-     * 
+     *
      * @return int the default number of pending connection requests
      */
     static int defaultBacklog() {
@@ -232,9 +222,8 @@
     /**
      * Gets the local IP address of this server socket or {@code null} if the
      * socket is unbound. This is useful for multihomed hosts.
-     * 
+     *
      * @return the local address of this server socket.
-     * @since Android 1.0
      */
     public InetAddress getInetAddress() {
         if (!isBound()) {
@@ -246,9 +235,8 @@
     /**
      * Gets the local port of this server socket or {@code -1} if the socket is
      * unbound.
-     * 
+     *
      * @return the local port this server is listening on.
-     * @since Android 1.0
      */
     public int getLocalPort() {
         if (!isBound()) {
@@ -260,11 +248,10 @@
     /**
      * Gets the timeout period of this server socket. This is the time the
      * server will wait listening for accepted connections before exiting.
-     * 
+     *
      * @return the listening timeout value of this server socket.
      * @throws IOException
      *             if the option cannot be retrieved.
-     * @since Android 1.0
      */
     public synchronized int getSoTimeout() throws IOException {
         if (!isCreated) {
@@ -287,13 +274,12 @@
     /**
      * Invokes the server socket implementation to accept a connection on the
      * given socket {@code aSocket}.
-     * 
+     *
      * @param aSocket
      *            the concrete {@code SocketImpl} to accept the connection
      *            request on.
      * @throws IOException
      *             if the connection cannot be accepted.
-     * @since Android 1.0
      */
     protected final void implAccept(Socket aSocket) throws IOException {
         impl.accept(aSocket.impl);
@@ -304,13 +290,12 @@
      * Sets the server socket implementation factory of this instance. This
      * method may only be invoked with sufficient security privilege and only
      * once during the application lifetime.
-     * 
+     *
      * @param aFactory
      *            the streaming socket factory to be used for further socket
      *            instantiations.
      * @throws IOException
      *             if the factory could not be set or is already set.
-     * @since Android 1.0
      */
     public static synchronized void setSocketFactory(SocketImplFactory aFactory)
             throws IOException {
@@ -328,12 +313,11 @@
      * Sets the timeout period of this server socket. This is the time the
      * server will wait listening for accepted connections before exiting. This
      * value must be a positive number.
-     * 
+     *
      * @param timeout
      *            the listening timeout value of this server socket.
      * @throws SocketException
      *             if an error occurs while setting the option.
-     * @since Android 1.0
      */
     public synchronized void setSoTimeout(int timeout) throws SocketException {
         checkClosedAndCreate(true);
@@ -347,13 +331,12 @@
      * Returns a textual representation of this server socket including the
      * address, port and the state. The port field is set to {@code 0} if there
      * is no connection to the server socket.
-     * 
+     *
      * @return the textual socket representation.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
-        StringBuffer result = new StringBuffer(64);
+        StringBuilder result = new StringBuilder(64);
         result.append("ServerSocket["); //$NON-NLS-1$
         if (!isBound()) {
             return result.append("unbound]").toString(); //$NON-NLS-1$
@@ -371,7 +354,7 @@
      * number of pending connections may be backlogged. If the {@code localAddr}
      * is set to {@code null} the socket will be bound to an available local
      * address on any free port of the system.
-     * 
+     *
      * @param localAddr
      *            the local address and port to bind on.
      * @throws IllegalArgumentException
@@ -379,7 +362,6 @@
      * @throws IOException
      *             if the socket is already bound or a problem occurs during
      *             binding.
-     * @since Android 1.0
      */
     public void bind(SocketAddress localAddr) throws IOException {
         bind(localAddr, defaultBacklog());
@@ -391,7 +373,7 @@
      * available local address on any free port of the system. The value for
      * {@code backlog} must e greater than {@code 0} otherwise the default value
      * will be used.
-     * 
+     *
      * @param localAddr
      *            the local machine address and port to bind on.
      * @param backlog
@@ -402,7 +384,6 @@
      * @throws IOException
      *             if the socket is already bound or a problem occurs during
      *             binding.
-     * @since Android 1.0
      */
     public void bind(SocketAddress localAddr, int backlog) throws IOException {
         checkClosedAndCreate(true);
@@ -410,7 +391,7 @@
             throw new BindException(Msg.getString("K0315")); //$NON-NLS-1$
         }
         int port = 0;
-        InetAddress addr = InetAddress.ANY;
+        InetAddress addr = Inet4Address.ANY;
         if (localAddr != null) {
             if (!(localAddr instanceof InetSocketAddress)) {
                 throw new IllegalArgumentException(Msg.getString(
@@ -443,9 +424,8 @@
     /**
      * Gets the local socket address of this server socket or {@code null} if
      * the socket is unbound. This is useful on multihomed hosts.
-     * 
+     *
      * @return the local socket address and port this socket is bound to.
-     * @since Android 1.0
      */
     public SocketAddress getLocalSocketAddress() {
         if (!isBound()) {
@@ -457,9 +437,8 @@
     /**
      * Returns whether this server socket is bound to a local address and port
      * or not.
-     * 
+     *
      * @return {@code true} if this socket is bound, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isBound() {
         return isBound;
@@ -467,9 +446,8 @@
 
     /**
      * Returns whether this server socket is closed or not.
-     * 
+     *
      * @return {@code true} if this socket is closed, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isClosed() {
         return isClosed;
@@ -504,12 +482,11 @@
 
     /**
      * Sets the value for the socket option {@code SocketOptions.SO_REUSEADDR}.
-     * 
+     *
      * @param reuse
      *            the socket option setting.
      * @throws SocketException
      *             if an error occurs while setting the option value.
-     * @since Android 1.0
      */
     public void setReuseAddress(boolean reuse) throws SocketException {
         checkClosedAndCreate(true);
@@ -519,11 +496,10 @@
 
     /**
      * Gets the value of the socket option {@code SocketOptions.SO_REUSEADDR}.
-     * 
+     *
      * @return {@code true} if the option is enabled, {@code false} otherwise.
      * @throws SocketException
      *             if an error occurs while reading the option value.
-     * @since Android 1.0
      */
     public boolean getReuseAddress() throws SocketException {
         checkClosedAndCreate(true);
@@ -534,13 +510,12 @@
     /**
      * Sets the server socket receive buffer size {@code
      * SocketOptions.SO_RCVBUF}.
-     * 
+     *
      * @param size
      *            the buffer size in bytes.
      * @throws SocketException
      *             if an error occurs while setting the size or the size is
      *             invalid.
-     * @since Android 1.0
      */
     public void setReceiveBufferSize(int size) throws SocketException {
         checkClosedAndCreate(true);
@@ -553,11 +528,10 @@
     /**
      * Gets the value for the receive buffer size socket option {@code
      * SocketOptions.SO_RCVBUF}.
-     * 
+     *
      * @return the receive buffer size of this socket.
      * @throws SocketException
      *             if an error occurs while reading the option value.
-     * @since Android 1.0
      */
     public int getReceiveBufferSize() throws SocketException {
         checkClosedAndCreate(true);
@@ -568,9 +542,8 @@
      * Gets the related channel if this instance was created by a
      * {@code ServerSocketChannel}. The current implementation returns always {@code
      * null}.
-     * 
+     *
      * @return the related {@code ServerSocketChannel} if any.
-     * @since Android 1.0
      */
     public ServerSocketChannel getChannel() {
         return null;
@@ -580,8 +553,7 @@
      * Sets performance preferences for connection time, latency and bandwidth.
      * <p>
      * This method does currently nothing.
-     * </p>
-     * 
+     *
      * @param connectionTime
      *            the value representing the importance of a short connecting
      *            time.
@@ -589,7 +561,6 @@
      *            the value representing the importance of low latency.
      * @param bandwidth
      *            the value representing the importance of high bandwidth.
-     * @since Android 1.0
      */
     public void setPerformancePreferences(int connectionTime, int latency,
             int bandwidth) {
diff --git a/libcore/luni/src/main/java/java/net/Socket.java b/libcore/luni/src/main/java/java/net/Socket.java
index b29b965..5289566 100644
--- a/libcore/luni/src/main/java/java/net/Socket.java
+++ b/libcore/luni/src/main/java/java/net/Socket.java
@@ -22,17 +22,19 @@
 import java.io.OutputStream;
 import java.nio.channels.SocketChannel;
 import java.security.AccessController;
+// BEGIN android-added
+import java.util.logging.Logger;
+import java.util.logging.Level;
+// END android-added
 
 import org.apache.harmony.luni.net.NetUtil;
-import org.apache.harmony.luni.net.SocketImplProvider;
+import org.apache.harmony.luni.net.PlainSocketImpl;
 import org.apache.harmony.luni.platform.Platform;
 import org.apache.harmony.luni.util.Msg;
 import org.apache.harmony.luni.util.PriviAction;
 
 /**
  * Provides a client-side TCP socket.
- * 
- * @since Android 1.0
  */
 public class Socket {
 
@@ -66,7 +68,16 @@
     static final int TCP_NODELAY = 4;
 
     static final int FLAG_SHUTDOWN = 8;
-   
+
+    static private Logger logger;
+
+    static private Logger getLogger() {
+        if (logger == null) {
+            logger = Logger.getLogger(Socket.class.getName());
+        }
+        return logger;
+    }
+
     static {
         Platform.getNetworkSystem().oneTimeInitialization(true);
     }
@@ -75,14 +86,13 @@
      * Creates a new unconnected socket. When a SocketImplFactory is defined it
      * creates the internal socket implementation, otherwise the default socket
      * implementation will be used for this socket.
-     * 
+     *
      * @see SocketImplFactory
      * @see SocketImpl
-     * @since Android 1.0
      */
     public Socket() {
         impl = factory != null ? factory.createSocketImpl()
-                : SocketImplProvider.getSocketImpl();
+                : new PlainSocketImpl();
     }
 
     /**
@@ -95,8 +105,7 @@
      * proxy server: <br>
      * {@code Socket sock = new Socket(new Proxy(Proxy.Type.SOCKS, new
      * InetSocketAddress("test.domain.org", 2130)));}
-     * </p>
-     * 
+     *
      * @param proxy
      *            the specified proxy for this socket.
      * @throws IllegalArgumentException
@@ -107,7 +116,6 @@
      *             connect to the given proxy.
      * @see SocketImplFactory
      * @see SocketImpl
-     * @since Android 1.0
      */
     public Socket(Proxy proxy) {
         if (null == proxy || Proxy.Type.HTTP == proxy.type()) {
@@ -127,15 +135,73 @@
             checkConnectPermission(host, port);
         }
         impl = factory != null ? factory.createSocketImpl()
-                : SocketImplProvider.getSocketImpl(proxy);
+                : new PlainSocketImpl(proxy);
         this.proxy = proxy;
     }
 
+    // BEGIN android-added
+    /**
+     * Tries to connect a socket to all IP addresses of the given hostname.
+     *
+     * @param dstName
+     *            the target host name or IP address to connect to.
+     * @param dstPort
+     *            the port on the target host to connect to.
+     * @param localAddress
+     *            the address on the local host to bind to.
+     * @param localPort
+     *            the port on the local host to bind to.
+     * @param streaming
+     *            if {@code true} a streaming socket is returned, a datagram
+     *            socket otherwise.
+     * @throws UnknownHostException
+     *             if the host name could not be resolved into an IP address.
+     * @throws IOException
+     *             if an error occurs while creating the socket.
+     * @throws SecurityException
+     *             if a security manager exists and it denies the permission to
+     *             connect to the given address and port.
+     */
+    private void tryAllAddresses(String dstName, int dstPort, InetAddress
+            localAddress, int localPort, boolean streaming) throws IOException {
+        InetAddress[] dstAddresses = InetAddress.getAllByName(dstName);
+        // Loop through all the destination addresses except the last, trying to
+        // connect to each one and ignoring errors. There must be at least one
+        // address, or getAllByName would have thrown UnknownHostException.
+        InetAddress dstAddress;
+        for (int i = 0; i < dstAddresses.length - 1; i++) {
+            dstAddress = dstAddresses[i];
+            try {
+                checkDestination(dstAddress, dstPort);
+                startupSocket(dstAddress, dstPort, localAddress, localPort,
+                        streaming);
+                return;
+            } catch(SecurityException e1) {
+                getLogger().log(Level.INFO, dstAddress + "(" + dstPort + "): " +
+                        e1.getClass().getName() + ": " + e1.getMessage());
+            } catch(IOException e2) {
+                getLogger().log(Level.INFO, dstAddress + "(" + dstPort + "): " +
+                        e2.getClass().getName() + ": " + e2.getMessage());
+            }
+        }
+
+        // Now try to connect to the last address in the array, handing back to
+        // the caller any exceptions that are thrown.
+        dstAddress = dstAddresses[dstAddresses.length - 1];
+        checkDestination(dstAddress, dstPort);
+        startupSocket(dstAddress, dstPort, localAddress, localPort, streaming);
+    }
+    // END android-added
+
     /**
      * Creates a new streaming socket connected to the target host specified by
      * the parameters {@code dstName} and {@code dstPort}. The socket is bound
      * to any available port on the local host.
-     * 
+     * <p><strong>Implementation note:</strong> this implementation tries each
+     * IP address for the given hostname until it either connects successfully
+     * or it exhausts the set. It will try both IPv4 and IPv6 addresses in the
+     * order specified by {@code preferIPv6Addresses}.
+     *
      * @param dstName
      *            the target host name or IP address to connect to.
      * @param dstPort
@@ -147,14 +213,12 @@
      * @throws SecurityException
      *             if a security manager exists and it denies the permission to
      *             connect to the given address and port.
-     * @since Android 1.0
      */
     public Socket(String dstName, int dstPort) throws UnknownHostException,
             IOException {
-        this();
-        InetAddress dstAddress = InetAddress.getByName(dstName);
-        checkDestination(dstAddress, dstPort);
-        startupSocket(dstAddress, dstPort, null, 0, true);
+        // BEGIN android-changed
+        this(dstName, dstPort, null, 0);
+        // END android-changed
     }
 
     /**
@@ -162,9 +226,13 @@
      * the parameters {@code dstName} and {@code dstPort}. On the local endpoint
      * the socket is bound to the given address {@code localAddress} on port
      * {@code localPort}.
-     * 
+     *
      * If {@code host} is {@code null} a loopback address is used to connect to.
-     * 
+     * <p><strong>Implementation note:</strong> this implementation tries each
+     * IP address for the given hostname until it either connects successfully
+     * or it exhausts the set. It will try both IPv4 and IPv6 addresses in the
+     * order specified by {@code preferIPv6Addresses}.
+     *
      * @param dstName
      *            the target host name or IP address to connect to.
      * @param dstPort
@@ -180,21 +248,24 @@
      * @throws SecurityException
      *             if a security manager exists and it denies the permission to
      *             connect to the given address and port.
-     * @since Android 1.0
      */
     public Socket(String dstName, int dstPort, InetAddress localAddress,
             int localPort) throws IOException {
         this();
-        InetAddress dstAddress = InetAddress.getByName(dstName);
-        checkDestination(dstAddress, dstPort);
-        startupSocket(dstAddress, dstPort, localAddress, localPort, true);
+        // BEGIN android-changed
+        tryAllAddresses(dstName, dstPort, localAddress, localPort, true);
+        // END android-changed
     }
 
     /**
      * Creates a new streaming or datagram socket connected to the target host
      * specified by the parameters {@code hostName} and {@code port}. The socket
      * is bound to any available port on the local host.
-     * 
+     * <p><strong>Implementation note:</strong> this implementation tries each
+     * IP address for the given hostname until it either connects successfully
+     * or it exhausts the set. It will try both IPv4 and IPv6 addresses in the
+     * order specified by {@code preferIPv6Addresses}.
+     *
      * @param hostName
      *            the target host name or IP address to connect to.
      * @param port
@@ -212,22 +283,21 @@
      * @deprecated Use {@code Socket(String, int)} instead of this for streaming
      *             sockets or an appropriate constructor of {@code
      *             DatagramSocket} for UDP transport.
-     * @since Android 1.0
      */
     @Deprecated
     public Socket(String hostName, int port, boolean streaming)
             throws IOException {
         this();
-        InetAddress host = InetAddress.getByName(hostName);
-        checkDestination(host, port);
-        startupSocket(host, port, null, 0, streaming);
+        // BEGIN android-changed
+        tryAllAddresses(hostName, port, null, 0, streaming);
+        // END android-changed
     }
 
     /**
      * Creates a new streaming socket connected to the target host specified by
      * the parameters {@code dstAddress} and {@code dstPort}. The socket is
      * bound to any available port on the local host.
-     * 
+     *
      * @param dstAddress
      *            the target host address to connect to.
      * @param dstPort
@@ -237,7 +307,6 @@
      * @throws SecurityException
      *             if a security manager exists and it denies the permission to
      *             connect to the given address and port.
-     * @since Android 1.0
      */
     public Socket(InetAddress dstAddress, int dstPort) throws IOException {
         this();
@@ -250,7 +319,7 @@
      * the parameters {@code dstAddress} and {@code dstPort}. On the local
      * endpoint the socket is bound to the given address {@code localAddress} on
      * port {@code localPort}.
-     * 
+     *
      * @param dstAddress
      *            the target host address to connect to.
      * @param dstPort
@@ -264,7 +333,6 @@
      * @throws SecurityException
      *             if a security manager exists and it denies the permission to
      *             connect to the given address and port.
-     * @since Android 1.0
      */
     public Socket(InetAddress dstAddress, int dstPort,
             InetAddress localAddress, int localPort) throws IOException {
@@ -277,7 +345,7 @@
      * Creates a new streaming or datagram socket connected to the target host
      * specified by the parameters {@code addr} and {@code port}. The socket is
      * bound to any available port on the local host.
-     * 
+     *
      * @param addr
      *            the Internet address to connect to.
      * @param port
@@ -293,7 +361,6 @@
      * @deprecated Use {@code Socket(InetAddress, int)} instead of this for
      *             streaming sockets or an appropriate constructor of {@code
      *             DatagramSocket} for UDP transport.
-     * @since Android 1.0
      */
     @Deprecated
     public Socket(InetAddress addr, int port, boolean streaming)
@@ -305,12 +372,11 @@
 
     /**
      * Creates an unconnected socket with the given socket implementation.
-     * 
+     *
      * @param anImpl
      *            the socket implementation to be used.
      * @throws SocketException
      *             if an error occurs while creating the socket.
-     * @since Android 1.0
      */
     protected Socket(SocketImpl anImpl) throws SocketException {
         impl = anImpl;
@@ -319,7 +385,7 @@
     /**
      * Checks whether the connection destination satisfies the security policy
      * and the validity of the port range.
-     * 
+     *
      * @param destAddr
      *            the destination host address.
      * @param dstPort
@@ -336,7 +402,7 @@
 
     /**
      * Checks whether the connection destination satisfies the security policy.
-     * 
+     *
      * @param hostname
      *            the destination hostname.
      * @param dstPort
@@ -352,10 +418,9 @@
     /**
      * Closes the socket. It is not possible to reconnect or rebind to this
      * socket thereafter which means a new socket instance has to be created.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing the socket.
-     * @since Android 1.0
      */
     public synchronized void close() throws IOException {
         isClosed = true;
@@ -364,10 +429,9 @@
 
     /**
      * Gets the IP address of the target host this socket is connected to.
-     * 
+     *
      * @return the IP address of the connected target host or {@code null} if
      *         this socket is not yet connected.
-     * @since Android 1.0
      */
     public InetAddress getInetAddress() {
         if (!isConnected()) {
@@ -378,12 +442,11 @@
 
     /**
      * Gets an input stream to read data from this socket.
-     * 
+     *
      * @return the byte-oriented input stream.
      * @throws IOException
      *             if an error occurs while creating the input stream or the
      *             socket is in an invalid state.
-     * @since Android 1.0
      */
     public InputStream getInputStream() throws IOException {
         checkClosedAndCreate(false);
@@ -395,13 +458,12 @@
 
     /**
      * Gets the setting of the socket option {@code SocketOptions.SO_KEEPALIVE}.
-     * 
+     *
      * @return {@code true} if the {@code SocketOptions.SO_KEEPALIVE} is
      *         enabled, {@code false} otherwise.
      * @throws SocketException
      *             if an error occurs while reading the socket option.
      * @see SocketOptions#SO_KEEPALIVE
-     * @since Android 1.0
      */
     public boolean getKeepAlive() throws SocketException {
         checkClosedAndCreate(true);
@@ -411,14 +473,13 @@
 
     /**
      * Gets the local IP address this socket is bound to.
-     * 
+     *
      * @return the local IP address of this socket or {@code InetAddress.ANY} if
      *         the socket is unbound.
-     * @since Android 1.0
      */
     public InetAddress getLocalAddress() {
         if (!isBound()) {
-            return InetAddress.ANY;
+            return Inet4Address.ANY;
         }
         return Platform.getNetworkSystem().getSocketLocalAddress(impl.fd,
                 InetAddress.preferIPv6Addresses());
@@ -426,10 +487,9 @@
 
     /**
      * Gets the local port this socket is bound to.
-     * 
+     *
      * @return the local port of this socket or {@code -1} if the socket is
      *         unbound.
-     * @since Android 1.0
      */
     public int getLocalPort() {
         if (!isBound()) {
@@ -440,12 +500,11 @@
 
     /**
      * Gets an output stream to write data into this socket.
-     * 
+     *
      * @return the byte-oriented output stream.
      * @throws IOException
      *             if an error occurs while creating the output stream or the
      *             socket is in an invalid state.
-     * @since Android 1.0
      */
     public OutputStream getOutputStream() throws IOException {
         checkClosedAndCreate(false);
@@ -457,10 +516,9 @@
 
     /**
      * Gets the port number of the target host this socket is connected to.
-     * 
+     *
      * @return the port number of the connected target host or {@code 0} if this
      *         socket is not yet connected.
-     * @since Android 1.0
      */
     public int getPort() {
         if (!isConnected()) {
@@ -471,13 +529,12 @@
 
     /**
      * Gets the value of the socket option {@code SocketOptions.SO_LINGER}.
-     * 
+     *
      * @return the current value of the option {@code SocketOptions.SO_LINGER}
      *         or {@code -1} if this option is disabled.
      * @throws SocketException
      *             if an error occurs while reading the socket option.
      * @see SocketOptions#SO_LINGER
-     * @since Android 1.0
      */
     public int getSoLinger() throws SocketException {
         checkClosedAndCreate(true);
@@ -486,12 +543,11 @@
 
     /**
      * Gets the receive buffer size of this socket.
-     * 
+     *
      * @return the current value of the option {@code SocketOptions.SO_RCVBUF}.
      * @throws SocketException
      *             if an error occurs while reading the socket option.
      * @see SocketOptions#SO_RCVBUF
-     * @since Android 1.0
      */
     public synchronized int getReceiveBufferSize() throws SocketException {
         checkClosedAndCreate(true);
@@ -500,12 +556,11 @@
 
     /**
      * Gets the send buffer size of this socket.
-     * 
+     *
      * @return the current value of the option {@code SocketOptions.SO_SNDBUF}.
      * @throws SocketException
      *             if an error occurs while reading the socket option.
      * @see SocketOptions#SO_SNDBUF
-     * @since Android 1.0
      */
     public synchronized int getSendBufferSize() throws SocketException {
         checkClosedAndCreate(true);
@@ -515,13 +570,12 @@
     /**
      * Gets the timeout for this socket during which a reading operation shall
      * block while waiting for data.
-     * 
+     *
      * @return the current value of the option {@code SocketOptions.SO_TIMEOUT}
      *         or {@code 0} which represents an infinite timeout.
      * @throws SocketException
      *             if an error occurs while reading the socket option.
      * @see SocketOptions#SO_TIMEOUT
-     * @since Android 1.0
      */
     public synchronized int getSoTimeout() throws SocketException {
         checkClosedAndCreate(true);
@@ -530,13 +584,12 @@
 
     /**
      * Gets the setting of the socket option {@code SocketOptions.TCP_NODELAY}.
-     * 
+     *
      * @return {@code true} if the {@code SocketOptions.TCP_NODELAY} is enabled,
      *         {@code false} otherwise.
      * @throws SocketException
      *             if an error occurs while reading the socket option.
      * @see SocketOptions#TCP_NODELAY
-     * @since Android 1.0
      */
     public boolean getTcpNoDelay() throws SocketException {
         checkClosedAndCreate(true);
@@ -546,13 +599,12 @@
 
     /**
      * Sets the state of the {@code SocketOptions.SO_KEEPALIVE} for this socket.
-     * 
+     *
      * @param value
      *            the state whether this option is enabled or not.
      * @throws SocketException
      *             if an error occurs while setting the option.
      * @see SocketOptions#SO_KEEPALIVE
-     * @since Android 1.0
      */
     public void setKeepAlive(boolean value) throws SocketException {
         if (impl != null) {
@@ -565,12 +617,11 @@
     /**
      * Sets the internal factory for creating socket implementations. This may
      * only be executed once during the lifetime of the application.
-     * 
+     *
      * @param fac
      *            the socket implementation factory to be set.
      * @throws IOException
      *             if the factory has been already set.
-     * @since Android 1.0
      */
     public static synchronized void setSocketImplFactory(SocketImplFactory fac)
             throws IOException {
@@ -586,7 +637,7 @@
 
     /**
      * Sets the send buffer size of this socket.
-     * 
+     *
      * @param size
      *            the buffer size in bytes. This value must be a positive number
      *            greater than {@code 0}.
@@ -594,7 +645,6 @@
      *             if an error occurs while setting the size or the given value
      *             is an invalid size.
      * @see SocketOptions#SO_SNDBUF
-     * @since Android 1.0
      */
     public synchronized void setSendBufferSize(int size) throws SocketException {
         checkClosedAndCreate(true);
@@ -606,7 +656,7 @@
 
     /**
      * Sets the receive buffer size of this socket.
-     * 
+     *
      * @param size
      *            the buffer size in bytes. This value must be a positive number
      *            greater than {@code 0}.
@@ -614,7 +664,6 @@
      *             if an error occurs while setting the size or the given value
      *             is an invalid size.
      * @see SocketOptions#SO_RCVBUF
-     * @since Android 1.0
      */
     public synchronized void setReceiveBufferSize(int size)
             throws SocketException {
@@ -629,7 +678,7 @@
      * Sets the state of the {@code SocketOptions.SO_LINGER} with the given
      * timeout in seconds. The timeout value for this option is silently limited
      * to the maximum of {@code 65535}.
-     * 
+     *
      * @param on
      *            the state whether this option is enabled or not.
      * @param timeout
@@ -637,7 +686,6 @@
      * @throws SocketException
      *             if an error occurs while setting the option.
      * @see SocketOptions#SO_LINGER
-     * @since Android 1.0
      */
     public void setSoLinger(boolean on, int timeout) throws SocketException {
         checkClosedAndCreate(true);
@@ -665,14 +713,13 @@
      * operation will block indefinitely if this option value is set to {@code
      * 0}. The timeout must be set before calling the read operation. A
      * {@code SocketTimeoutException} is thrown when this timeout expires.
-     * 
+     *
      * @param timeout
      *            the reading timeout value as number greater than {@code 0} or
      *            {@code 0} for an infinite timeout.
      * @throws SocketException
      *             if an error occurs while setting the option.
      * @see SocketOptions#SO_TIMEOUT
-     * @since Android 1.0
      */
     public synchronized void setSoTimeout(int timeout) throws SocketException {
         checkClosedAndCreate(true);
@@ -684,13 +731,12 @@
 
     /**
      * Sets the state of the {@code SocketOptions.TCP_NODELAY} for this socket.
-     * 
+     *
      * @param on
      *            the state whether this option is enabled or not.
      * @throws SocketException
      *             if an error occurs while setting the option.
      * @see SocketOptions#TCP_NODELAY
-     * @since Android 1.0
      */
     public void setTcpNoDelay(boolean on) throws SocketException {
         checkClosedAndCreate(true);
@@ -700,7 +746,7 @@
     /**
      * Creates a stream socket, binds it to the nominated local address/port,
      * then connects it to the nominated destination address/port.
-     * 
+     *
      * @param dstAddress
      *            the destination host address.
      * @param dstPort
@@ -721,7 +767,7 @@
             throw new IllegalArgumentException(Msg.getString("K0046")); //$NON-NLS-1$
         }
 
-        InetAddress addr = localAddress == null ? InetAddress.ANY
+        InetAddress addr = localAddress == null ? Inet4Address.ANY
                 : localAddress;
         synchronized (this) {
             impl.create(streaming);
@@ -743,9 +789,8 @@
     /**
      * Returns a {@code String} containing a concise, human-readable description of the
      * socket.
-     * 
+     *
      * @return the textual representation of this socket.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -759,12 +804,11 @@
      * Closes the input stream of this socket. Any further data sent to this
      * socket will be discarded. Reading from this socket after this method has
      * been called will return the value {@code EOF}.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing the socket input stream.
      * @throws SocketException
      *             if the input stream is already closed.
-     * @since Android 1.0
      */
     public void shutdownInput() throws IOException {
         if (isInputShutdown()) {
@@ -779,12 +823,11 @@
      * Closes the output stream of this socket. All buffered data will be sent
      * followed by the termination sequence. Writing to the closed output stream
      * will cause an {@code IOException}.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing the socket output stream.
      * @throws SocketException
      *             if the output stream is already closed.
-     * @since Android 1.0
      */
     public void shutdownOutput() throws IOException {
         if (isOutputShutdown()) {
@@ -798,7 +841,7 @@
     /**
      * Checks whether the socket is closed, and throws an exception. Otherwise
      * creates the underlying SocketImpl.
-     * 
+     *
      * @throws SocketException
      *             if the socket is closed.
      */
@@ -840,9 +883,8 @@
      * Gets the local address and port of this socket as a SocketAddress or
      * {@code null} if the socket is unbound. This is useful on multihomed
      * hosts.
-     * 
+     *
      * @return the bound local socket address and port.
-     * @since Android 1.0
      */
     public SocketAddress getLocalSocketAddress() {
         if (!isBound()) {
@@ -854,9 +896,8 @@
     /**
      * Gets the remote address and port of this socket as a {@code
      * SocketAddress} or {@code null} if the socket is not connected.
-     * 
+     *
      * @return the remote socket address and port.
-     * @since Android 1.0
      */
     public SocketAddress getRemoteSocketAddress() {
         if (!isConnected()) {
@@ -867,10 +908,9 @@
 
     /**
      * Returns whether this socket is bound to a local address and port.
-     * 
+     *
      * @return {@code true} if the socket is bound to a local address, {@code
      *         false} otherwise.
-     * @since Android 1.0
      */
     public boolean isBound() {
         return isBound;
@@ -878,9 +918,8 @@
 
     /**
      * Returns whether this socket is connected to a remote host.
-     * 
+     *
      * @return {@code true} if the socket is connected, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isConnected() {
         return isConnected;
@@ -888,9 +927,8 @@
 
     /**
      * Returns whether this socket is closed.
-     * 
+     *
      * @return {@code true} if the socket is closed, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isClosed() {
         return isClosed;
@@ -901,7 +939,7 @@
      * the SocketAddress {@code localAddr}. If {@code localAddr} is set to
      * {@code null}, this socket will be bound to an available local address on
      * any free port.
-     * 
+     *
      * @param localAddr
      *            the specific address and port on the local machine to bind to.
      * @throws IllegalArgumentException
@@ -909,7 +947,6 @@
      * @throws IOException
      *             if the socket is already bound or an error occurs while
      *             binding.
-     * @since Android 1.0
      */
     public void bind(SocketAddress localAddr) throws IOException {
         checkClosedAndCreate(true);
@@ -918,7 +955,7 @@
         }
 
         int port = 0;
-        InetAddress addr = InetAddress.ANY;
+        InetAddress addr = Inet4Address.ANY;
         if (localAddr != null) {
             if (!(localAddr instanceof InetSocketAddress)) {
                 throw new IllegalArgumentException(Msg.getString(
@@ -946,7 +983,7 @@
     /**
      * Connects this socket to the given remote host address and port specified
      * by the SocketAddress {@code remoteAddr}.
-     * 
+     *
      * @param remoteAddr
      *            the address and port of the remote host to connect to.
      * @throws IllegalArgumentException
@@ -954,7 +991,6 @@
      * @throws IOException
      *             if the socket is already connected or an error occurs while
      *             connecting.
-     * @since Android 1.0
      */
     public void connect(SocketAddress remoteAddr) throws IOException {
         connect(remoteAddr, 0);
@@ -965,7 +1001,7 @@
      * by the SocketAddress {@code remoteAddr} with the specified timeout. The
      * connecting method will block until the connection is established or an
      * error occurred.
-     * 
+     *
      * @param remoteAddr
      *            the address and port of the remote host to connect to.
      * @param timeout
@@ -977,7 +1013,6 @@
      * @throws IOException
      *             if the socket is already connected or an error occurs while
      *             connecting.
-     * @since Android 1.0
      */
     public void connect(SocketAddress remoteAddr, int timeout)
             throws IOException {
@@ -1012,7 +1047,7 @@
                     // options on create
                     // impl.create(true);
                     if (!NetUtil.usingSocks(proxy)) {
-                        impl.bind(InetAddress.ANY, 0);
+                        impl.bind(Inet4Address.ANY, 0);
                     }
                     isBound = true;
                 }
@@ -1028,22 +1063,20 @@
     /**
      * Returns whether the incoming channel of the socket has already been
      * closed.
-     * 
+     *
      * @return {@code true} if reading from this socket is not possible anymore,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isInputShutdown() {
         return isInputShutdown;
     }
 
     /**
-     * Returns whether the outgoing channel of the socket has already been 
+     * Returns whether the outgoing channel of the socket has already been
      * closed.
-     * 
+     *
      * @return {@code true} if writing to this socket is not possible anymore,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isOutputShutdown() {
         return isOutputShutdown;
@@ -1051,13 +1084,12 @@
 
     /**
      * Sets the state of the {@code SocketOptions.SO_REUSEADDR} for this socket.
-     * 
+     *
      * @param reuse
      *            the state whether this option is enabled or not.
      * @throws SocketException
      *             if an error occurs while setting the option.
      * @see SocketOptions#SO_REUSEADDR
-     * @since Android 1.0
      */
     public void setReuseAddress(boolean reuse) throws SocketException {
         checkClosedAndCreate(true);
@@ -1067,13 +1099,12 @@
 
     /**
      * Gets the setting of the socket option {@code SocketOptions.SO_REUSEADDR}.
-     * 
+     *
      * @return {@code true} if the {@code SocketOptions.SO_REUSEADDR} is
      *         enabled, {@code false} otherwise.
      * @throws SocketException
      *             if an error occurs while reading the socket option.
      * @see SocketOptions#SO_REUSEADDR
-     * @since Android 1.0
      */
     public boolean getReuseAddress() throws SocketException {
         checkClosedAndCreate(true);
@@ -1085,13 +1116,12 @@
      * Sets the state of the {@code SocketOptions.SO_OOBINLINE} for this socket.
      * When this option is enabled urgent data can be received in-line with
      * normal data.
-     * 
+     *
      * @param oobinline
      *            whether this option is enabled or not.
      * @throws SocketException
      *             if an error occurs while setting the option.
      * @see SocketOptions#SO_OOBINLINE
-     * @since Android 1.0
      */
     public void setOOBInline(boolean oobinline) throws SocketException {
         checkClosedAndCreate(true);
@@ -1101,13 +1131,12 @@
 
     /**
      * Gets the setting of the socket option {@code SocketOptions.SO_OOBINLINE}.
-     * 
+     *
      * @return {@code true} if the {@code SocketOptions.SO_OOBINLINE} is
      *         enabled, {@code false} otherwise.
      * @throws SocketException
      *             if an error occurs while reading the socket option.
      * @see SocketOptions#SO_OOBINLINE
-     * @since Android 1.0
      */
     public boolean getOOBInline() throws SocketException {
         checkClosedAndCreate(true);
@@ -1119,14 +1148,13 @@
      * Sets the value of the {@code SocketOptions.IP_TOS} for this socket. See
      * the specification RFC 1349 for more information about the type of service
      * field.
-     * 
+     *
      * @param value
      *            the value to be set for this option with a valid range of
      *            {@code 0-255}.
      * @throws SocketException
      *             if an error occurs while setting the option.
      * @see SocketOptions#IP_TOS
-     * @since Android 1.0
      */
     public void setTrafficClass(int value) throws SocketException {
         checkClosedAndCreate(true);
@@ -1138,12 +1166,11 @@
 
     /**
      * Gets the value of the socket option {@code SocketOptions.IP_TOS}.
-     * 
+     *
      * @return the value which represents the type of service.
      * @throws SocketException
      *             if an error occurs while reading the socket option.
      * @see SocketOptions#IP_TOS
-     * @since Android 1.0
      */
     public int getTrafficClass() throws SocketException {
         checkClosedAndCreate(true);
@@ -1153,12 +1180,11 @@
     /**
      * Sends the given single byte data which is represented by the lowest octet
      * of {@code value} as "TCP urgent data".
-     * 
+     *
      * @param value
      *            the byte of urgent data to be sent.
      * @throws IOException
      *             if an error occurs while sending urgent data.
-     * @since Android 1.0
      */
     public void sendUrgentData(int value) throws IOException {
         if (!impl.supportsUrgentData()) {
@@ -1170,7 +1196,7 @@
     /**
      * Set the appropriate flags for a socket created by {@code
      * ServerSocket.accept()}.
-     * 
+     *
      * @see ServerSocket#implAccept
      */
     void accepted() {
@@ -1186,9 +1212,8 @@
     /**
      * Gets the SocketChannel of this socket, if one is available. The current
      * implementation of this method returns always {@code null}.
-     * 
+     *
      * @return the related SocketChannel or {@code null} if no channel exists.
-     * @since Android 1.0
      */
     public SocketChannel getChannel() {
         return null;
@@ -1198,8 +1223,7 @@
      * Sets performance preferences for connectionTime, latency and bandwidth.
      * <p>
      * This method does currently nothing.
-     * </p>
-     * 
+     *
      * @param connectionTime
      *            the value representing the importance of a short connecting
      *            time.
@@ -1207,7 +1231,6 @@
      *            the value representing the importance of low latency.
      * @param bandwidth
      *            the value representing the importance of high bandwidth.
-     * @since Android 1.0
      */
     public void setPerformancePreferences(int connectionTime, int latency,
             int bandwidth) {
diff --git a/libcore/luni/src/main/java/java/net/SocketAddress.java b/libcore/luni/src/main/java/java/net/SocketAddress.java
index 756b5fd..32a4c36 100644
--- a/libcore/luni/src/main/java/java/net/SocketAddress.java
+++ b/libcore/luni/src/main/java/java/net/SocketAddress.java
@@ -23,15 +23,11 @@
  * This abstract class represents a protocol-independent base for
  * socket-endpoint representing classes. The class has to be implemented
  * according to a specific protocol.
- * 
- * @since Android 1.0
  */
 public abstract class SocketAddress implements Serializable {
 
     /**
      * Creates a new {@code SocketAddress} instance.
-     * 
-     * @since Android 1.0
      */
     public SocketAddress() {
         super();
diff --git a/libcore/luni/src/main/java/java/net/SocketException.java b/libcore/luni/src/main/java/java/net/SocketException.java
index b9b3a14..23d3744 100644
--- a/libcore/luni/src/main/java/java/net/SocketException.java
+++ b/libcore/luni/src/main/java/java/net/SocketException.java
@@ -22,8 +22,6 @@
 /**
  * This {@code SocketException} may be thrown during socket creation or setting
  * options, and is the superclass of all other socket related exceptions.
- * 
- * @since Android 1.0
  */
 public class SocketException extends IOException {
 
@@ -32,8 +30,6 @@
     /**
      * Constructs a new {@code SocketException} instance with its walkback
      * filled in.
-     * 
-     * @since Android 1.0
      */
     public SocketException() {
         super();
@@ -45,7 +41,6 @@
      * 
      * @param detailMessage
      *            the detail message of this exception.
-     * @since Android 1.0
      */
     public SocketException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/net/SocketImpl.java b/libcore/luni/src/main/java/java/net/SocketImpl.java
index f011e63..6ac41cd 100644
--- a/libcore/luni/src/main/java/java/net/SocketImpl.java
+++ b/libcore/luni/src/main/java/java/net/SocketImpl.java
@@ -20,7 +20,6 @@
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.InterruptedIOException;
 import java.io.OutputStream;
 
 import org.apache.harmony.luni.platform.INetworkSystem;
@@ -35,36 +34,26 @@
  * ServerSocket} on a well known port (referred to as listener) used to
  * establish a connection and the resulting {@code Socket} (referred to as
  * host).
- * 
- * @since Android 1.0
  */
 public abstract class SocketImpl implements SocketOptions {
 
     /**
      * The remote address this socket is connected to.
-     * 
-     * @since Android 1.0
      */
     protected InetAddress address;
 
     /**
      * The remote port this socket is connected to.
-     * 
-     * @since Android 1.0
      */
     protected int port;
 
     /**
      * The file descriptor of this socket.
-     * 
-     * @since Android 1.0
      */
     protected FileDescriptor fd;
 
     /**
      * The local port this socket is connected to.
-     * 
-     * @since Android 1.0
      */
     protected int localport;
 
@@ -80,9 +69,8 @@
 
     /**
      * Creates a new connection-oriented socket implementation.
-     * 
+     *
      * @see SocketImplFactory
-     * @since Android 1.0
      */
     public SocketImpl() {
         this.netImpl = Platform.getNetworkSystem();
@@ -91,73 +79,67 @@
     /**
      * Waits for an incoming request and blocks until the connection is opened
      * on the given socket.
-     * 
+     *
      * @param newSocket
      *            the socket to accept connections on.
      * @throws IOException
      *             if an error occurs while accepting a new connection.
-     * @since Android 1.0
      */
     protected abstract void accept(SocketImpl newSocket) throws IOException;
 
     /**
      * Returns the available number of bytes which are readable from this socket
      * without blocking.
-     * 
+     *
      * @return the number of bytes that may be read without blocking.
      * @throws IOException
      *             if an error occurs while reading the number of bytes.
-     * @since Android 1.0
      */
     protected abstract int available() throws IOException;
 
     /**
      * Binds this socket to the specified local host address and port number.
-     * 
+     *
      * @param address
      *            the local machine address to bind this socket to.
      * @param port
      *            the port on the local machine to bind this socket to.
      * @throws IOException
      *             if an error occurs while binding this socket.
-     * @since Android 1.0
      */
     protected abstract void bind(InetAddress address, int port)
             throws IOException;
 
     /**
      * Closes this socket. This makes later access invalid.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while closing this socket.
-     * @since Android 1.0
      */
     protected abstract void close() throws IOException;
 
     /**
      * Connects this socket to the specified remote host and port number.
-     * 
+     *
      * @param host
      *            the remote host this socket has to be connected to.
      * @param port
      *            the remote port on which this socket has to be connected.
      * @throws IOException
      *             if an error occurs while connecting to the remote host.
-     * @since Android 1.0
      */
     protected abstract void connect(String host, int port) throws IOException;
 
     /**
      * Connects this socket to the specified remote host address and port
      * number.
-     * 
+     *
      * @param address
      *            the remote host address this socket has to be connected to.
      * @param port
      *            the remote port on which this socket has to be connected.
      * @throws IOException
      *             if an error occurs while connecting to the remote host.
-     * @since Android 1.0
      */
     protected abstract void connect(InetAddress address, int port)
             throws IOException;
@@ -165,21 +147,19 @@
     /**
      * Creates a new unconnected socket. The argument {@code isStreaming}
      * defines whether the new socket is a streaming or a datagram socket.
-     * 
+     *
      * @param isStreaming
      *            defines whether the type of the new socket is streaming or
      *            datagram.
      * @throws IOException
      *             if an error occurs while creating the socket.
-     * @since Android 1.0
      */
     protected abstract void create(boolean isStreaming) throws IOException;
 
     /**
      * Gets the file descriptor of this socket.
-     * 
+     *
      * @return the file descriptor of this socket.
-     * @since Android 1.0
      */
     protected FileDescriptor getFileDescriptor() {
         return fd;
@@ -187,9 +167,8 @@
 
     /**
      * Gets the remote address this socket is connected to.
-     * 
+     *
      * @return the remote address of this socket.
-     * @since Android 1.0
      */
     protected InetAddress getInetAddress() {
         return address;
@@ -197,11 +176,10 @@
 
     /**
      * Gets the input stream of this socket.
-     * 
+     *
      * @return the input stream of this socket.
      * @throws IOException
      *             if an error occurs while accessing the input stream.
-     * @since Android 1.0
      */
     protected abstract InputStream getInputStream() throws IOException;
 
@@ -209,9 +187,8 @@
      * Gets the local port number of this socket. The field is initialized to
      * {@code -1} and upon demand will go to the IP stack to get the bound
      * value. See the class comment for the context of the local port.
-     * 
+     *
      * @return the local port number this socket is bound to.
-     * @since Android 1.0
      */
     protected int getLocalPort() {
         return localport;
@@ -219,32 +196,29 @@
 
     /**
      * Gets the value of the given socket option.
-     * 
+     *
      * @param optID
      *            the socket option to retrieve.
      * @return the option value.
      * @throws SocketException
      *             if an error occurs while accessing the option.
-     * @since Android 1.0
      */
     public abstract Object getOption(int optID) throws SocketException;
 
     /**
      * Gets the output stream of this socket.
-     * 
+     *
      * @return the output stream of this socket.
      * @throws IOException
      *             if an error occurs while accessing the output stream.
-     * @since Android 1.0
      */
     protected abstract OutputStream getOutputStream() throws IOException;
 
     /**
      * Gets the remote port number of this socket. This value is not meaningful
      * when this instance is wrapped by a {@code ServerSocket}.
-     * 
+     *
      * @return the remote port this socket is connected to.
-     * @since Android 1.0
      */
     protected int getPort() {
         return port;
@@ -255,60 +229,23 @@
      * connection requests are queued up to the limit specified by {@code
      * backlog}. Additional requests are rejected. The method {@code listen()}
      * may only be invoked on streaming sockets.
-     * 
+     *
      * @param backlog
      *            the maximum number of outstanding connection requests.
      * @throws IOException
      *             if an error occurs while listening.
-     * @since Android 1.0
      */
     protected abstract void listen(int backlog) throws IOException;
 
     /**
-     * In the IP stack, read at most {@code count} bytes off the socket
-     * into the {@code buffer}, at the {@code offset}. If the timeout
-     * is zero, block indefinitely waiting for data, otherwise wait the
-     * specified period (in milliseconds).
-     * 
-     * @param buffer
-     *            the buffer to read into
-     * @param offset
-     *            the offset into the buffer
-     * @param count
-     *            the max number of bytes to read
-     * @return int the actual number of bytes read
-     * @exception IOException
-     *                thrown if an error occurs while reading
-     */
-    int read(byte[] buffer, int offset, int count) throws IOException {
-        if (shutdownInput) {
-            return -1;
-        }
-        try {
-            // BEGIN android-added
-            int receiveTimeout = (Integer)getOption(SocketOptions.SO_TIMEOUT);
-            // END android-added
-            int read = this.netImpl.receiveStream(fd, buffer, offset, count,
-                    receiveTimeout);
-            if (read == -1) {
-                shutdownInput = true;
-            }
-            return read;
-        } catch (InterruptedIOException e) {
-            throw new SocketTimeoutException(e.getMessage());
-        }
-    }
-
-    /**
      * Sets the value for the specified socket option.
-     * 
+     *
      * @param optID
      *            the socket option to be set.
      * @param val
      *            the option value.
      * @throws SocketException
      *             if an error occurs while setting the option.
-     * @since Android 1.0
      */
     public abstract void setOption(int optID, Object val)
             throws SocketException;
@@ -316,14 +253,13 @@
     /**
      * Returns a string containing a concise, human-readable description of the
      * socket.
-     * 
+     *
      * @return the textual representation of this socket.
-     * @since Android 1.0
      */
     @SuppressWarnings("nls")
     @Override
     public String toString() {
-        return new StringBuffer(100).append("Socket[addr=").append(
+        return new StringBuilder(100).append("Socket[addr=").append(
                 getInetAddress()).append(",port=").append(port).append(
                 ",localport=").append(getLocalPort()).append("]").toString();
     }
@@ -331,7 +267,7 @@
     /**
      * In the IP stack, write at most {@code count} bytes on the socket
      * from the {@code buffer}, from the {@code offset}.
-     * 
+     *
      * @param buffer
      *            the buffer to read into
      * @param offset
@@ -339,18 +275,15 @@
      * @param count
      *            the number of bytes to write
      * @return int the actual number of bytes written
-     * @exception IOException
+     * @throws IOException
      *                thrown if an error occurs while writing
      */
     int write(byte[] buffer, int offset, int count) throws IOException {
         if (!streaming) {
-            // BEGIN android-changed
-            // copied from newer harmony version
-            return this.netImpl
-                    .sendDatagram2(fd, buffer, offset, count, port, address);
-            // END android-changed
+            return this.netImpl.sendDatagram2(fd, buffer, offset, count, port,
+                    address);
         }
-        return this.netImpl.sendStream(fd, buffer, offset, count);
+        return this.netImpl.write(fd, buffer, offset, count);
     }
 
     /**
@@ -358,11 +291,9 @@
      * <p>
      * This default implementation always throws an {@link IOException} to
      * indicate that the subclass should have overridden this method.
-     * </p>
-     * 
+     *
      * @throws IOException
      *             always because this method should be overridden.
-     * @since Android 1.0
      */
     protected void shutdownInput() throws IOException {
         // KA025=Method has not been implemented
@@ -374,11 +305,9 @@
      * <p>
      * This default implementation always throws an {@link IOException} to
      * indicate that the subclass should have overridden this method.
-     * </p>
-     * 
+     *
      * @throws IOException
      *             always because this method should be overridden.
-     * @since Android 1.0
      */
     protected void shutdownOutput() throws IOException {
         // KA025=Method has not been implemented
@@ -389,14 +318,13 @@
      * Connects this socket to the remote host address and port number specified
      * by the {@code SocketAddress} object with the given timeout. This method
      * will block indefinitely if the timeout is set to zero.
-     * 
+     *
      * @param remoteAddr
      *            the remote host address and port number to connect to.
      * @param timeout
      *            the timeout value in milliseconds.
      * @throws IOException
      *             if an error occurs while connecting.
-     * @since Android 1.0
      */
     protected abstract void connect(SocketAddress remoteAddr, int timeout)
             throws IOException;
@@ -404,9 +332,8 @@
     /**
      * Returns whether the socket supports urgent data or not. Subclasses should
      * override this method.
-     * 
+     *
      * @return {@code false} because subclasses must override this method.
-     * @since Android 1.0
      */
     protected boolean supportsUrgentData() {
         return false;
@@ -414,26 +341,24 @@
 
     /**
      * Sends the single byte of urgent data on the socket.
-     * 
+     *
      * @param value
      *            the byte of urgent data.
      * @throws IOException
      *             if an error occurs sending urgent data.
-     * @since Android 1.0
      */
     protected abstract void sendUrgentData(int value) throws IOException;
 
     /**
      * Sets performance preference for connection time, latency and bandwidth.
      * Does nothing by default.
-     * 
+     *
      * @param connectionTime
      *            the importance of connect time.
      * @param latency
      *            the importance of latency.
      * @param bandwidth
      *            the importance of bandwidth.
-     * @since Android 1.0
      */
     protected void setPerformancePreferences(int connectionTime, int latency,
             int bandwidth) {
diff --git a/libcore/luni/src/main/java/java/net/SocketImplFactory.java b/libcore/luni/src/main/java/java/net/SocketImplFactory.java
index 3cc42b0..57b0bc3 100644
--- a/libcore/luni/src/main/java/java/net/SocketImplFactory.java
+++ b/libcore/luni/src/main/java/java/net/SocketImplFactory.java
@@ -19,16 +19,13 @@
 
 /**
  * This interface defines a factory for socket implementations.
- * 
- * @since Android 1.0
  */
 public interface SocketImplFactory {
-    
+
     /**
      * Creates a new {@code SocketImpl} instance.
      * 
      * @return the created {@code SocketImpl} instance.
-     * @since Android 1.0
      */
     SocketImpl createSocketImpl();
 }
diff --git a/libcore/luni/src/main/java/java/net/SocketOptions.java b/libcore/luni/src/main/java/java/net/SocketOptions.java
index 6e1753f..38c9301 100644
--- a/libcore/luni/src/main/java/java/net/SocketOptions.java
+++ b/libcore/luni/src/main/java/java/net/SocketOptions.java
@@ -25,7 +25,6 @@
  * 
  * @see SocketImpl
  * @see DatagramSocketImpl
- * @since Android 1.0
  */
 public interface SocketOptions {
 
@@ -38,8 +37,6 @@
      * during this timeout the socket is closed normally otherwise forcefully.
      * Valid values for this option are in the range {@code 0 <= SO_LINGER <=
      * 65535}.
-     * 
-     * @since Android 1.0
      */
     public static final int SO_LINGER = 128;
 
@@ -47,8 +44,6 @@
      * Timeout for blocking operations. The argument value is specified in
      * milliseconds. An {@code InterruptedIOException} is thrown if this timeout
      * expires.
-     * 
-     * @since Android 1.0
      */
     public static final int SO_TIMEOUT = 4102;
 
@@ -57,8 +52,6 @@
      * a side-effect though, this could lead to a low packet efficiency. The
      * socket implementation uses the Nagle's algorithm to try to reach a higher
      * packet efficiency if this option is disabled.
-     * 
-     * @since Android 1.0
      */
     public static final int TCP_NODELAY = 1;
 
@@ -69,8 +62,6 @@
     /**
      * This option specifies the interface which is used to send multicast
      * packets. It's only available on a {@code MulticastSocket}.
-     * 
-     * @since Android 1.0
      */
     public static final int IP_MULTICAST_IF = 16;
 
@@ -78,8 +69,6 @@
      * This option can be used to set one specific interface on a multihomed
      * host on which incoming connections are accepted. It's only available on
      * server-side sockets.
-     * 
-     * @since Android 1.0
      */
     public static final int SO_BINDADDR = 15;
 
@@ -87,8 +76,6 @@
      * This option specifies whether a reuse of a local address is allowed even
      * if an other socket is not yet removed by the operating system. It's only
      * available on a {@code MulticastSocket}.
-     * 
-     * @since Android 1.0
      */
     public static final int SO_REUSEADDR = 4;
 
@@ -96,15 +83,11 @@
     
     /**
      * Buffer size of the outgoing channel.
-     * 
-     * @since Android 1.0
      */
     public static final int SO_SNDBUF = 4097;
 
     /**
      * Buffer size of the incoming channel.
-     * 
-     * @since Android 1.0
      */
     public static final int SO_RCVBUF = 4098;
 
@@ -113,16 +96,12 @@
     /**
      * This option specifies whether socket implementations can send keepalive
      * messages if no data has been sent for a longer time.
-     * 
-     * @since Android 1.0
      */
     public static final int SO_KEEPALIVE = 8;
     
     /**
      * This option specifies the value for the Type-of-Service (TOS) field of
      * the IP header.
-     * 
-     * @since Android 1.0
      */
     public static final int IP_TOS = 3;
     
@@ -130,23 +109,17 @@
      * This option specifies whether the local loopback of multicast packets is
      * enabled or disabled. This option is enabled by default on multicast
      * sockets.
-     * 
-     * @since Android 1.0
      */
     public static final int IP_MULTICAST_LOOP = 18;
     
     /**
      * This option can be used to enable broadcasting on datagram sockets.
-     * 
-     * @since Android 1.0
      */
     public static final int SO_BROADCAST = 32;
     
     /**
      * This option specifies whether sending TCP urgent data is supported on
      * this socket or not.
-     * 
-     * @since Android 1.0
      */
     public static final int SO_OOBINLINE = 4099;
     
@@ -155,8 +128,6 @@
      * host on which incoming connections are accepted. It's only available on
      * server-side sockets. This option supports setting outgoing interfaces
      * with either IPv4 or IPv6 addresses.
-     * 
-     * @since Android 1.0
      */
     public static final int IP_MULTICAST_IF2 = 31;
 
@@ -168,7 +139,6 @@
      *            the option identifier.
      * @throws SocketException
      *             if an error occurs reading the option value.
-     * @since Android 1.0
      */
     public Object getOption(int optID) throws SocketException;
 
@@ -181,7 +151,6 @@
      *            the value to be set for the option.
      * @throws SocketException
      *             if an error occurs setting the option value.
-     * @since Android 1.0
      */
     public void setOption(int optID, Object val) throws SocketException;
 }
diff --git a/libcore/luni/src/main/java/java/net/SocketPermission.java b/libcore/luni/src/main/java/java/net/SocketPermission.java
index 72d77e7..4353e2e 100644
--- a/libcore/luni/src/main/java/java/net/SocketPermission.java
+++ b/libcore/luni/src/main/java/java/net/SocketPermission.java
@@ -14,9 +14,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-// BEGIN andorid-note
-// This class was copied from a newer version of harmony
-// END andorid-note
 
 package java.net;
 
@@ -57,16 +54,13 @@
  * <i>LOW-HIGH</i> where <i>LOW</i> and <i>HIGH</i> are valid port numbers. If
  * either <i>LOW</i> or <i>HIGH</i> is omitted it is equivalent to entering the
  * lowest or highest possible value respectively. For example:
- * 
+ *
  * <pre>
  * {@code SocketPermission(&quot;www.company.com:7000-&quot;, &quot;connect,accept&quot;)}
  * </pre>
- * 
+ *
  * represents the permission to connect to and accept connections from {@code
  * www.company.com} on ports in the range {@code 7000} to {@code 65535}.
- * </p>
- * 
- * @since Android 1.0
  */
 public final class SocketPermission extends Permission implements Serializable {
 
@@ -122,13 +116,11 @@
      * possible operations {@code "connect"}, {@code "listen"}, {@code "accept"}
      * , and {@code "resolve"}. They are case-insensitive and can be put
      * together in any order. {@code "resolve"} is implied per default.
-     * </p>
-     * 
+     *
      * @param host
      *            the hostname this permission is valid for.
      * @param action
      *            the action string of this permission.
-     * @since Android 1.0
      */
     public SocketPermission(String host, String action) {
         super(host.equals("") ? "localhost" : host); //$NON-NLS-1$ //$NON-NLS-2$
@@ -149,14 +141,13 @@
     /**
      * Compares the argument {@code o} to this instance and returns {@code true}
      * if they represent the same permission using a class specific comparison.
-     * 
+     *
      * @param o
      *            the object to compare with this {@code SocketPermission}
      *            instance.
      * @return {@code true} if they represent the same permission, {@code false}
      *         otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object o) {
@@ -187,10 +178,9 @@
      * Returns the hash value for this {@code SocketPermission} instance. Any
      * two objects which returns {@code true} when passed to {@code equals()}
      * must return the same value as a result of this method.
-     * 
+     *
      * @return the hashcode value for this instance.
      * @see #equals
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -201,9 +191,8 @@
      * Gets a comma-separated list of all actions allowed by this permission. If
      * more than one action is returned they follow this order: {@code connect},
      * {@code listen}, {@code accept}, {@code resolve}.
-     * 
+     *
      * @return the comma-separated action list.
-     * @since Android 1.0
      */
     @Override
     public String getActions() {
@@ -212,7 +201,7 @@
 
     /**
      * Stores the actions for this permission as a bit field.
-     * 
+     *
      * @param actions
      *            java.lang.String the action list
      */
@@ -222,7 +211,7 @@
         }
         boolean parsing = true;
         String action;
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         int pos = 0, length = actions.length();
         while (parsing) {
             char c;
@@ -255,13 +244,12 @@
      * permission actions, hosts and ports must be implied by this permission
      * instance in order to return {@code true}. This permission may imply
      * additional actions not present in the argument permission.
-     * 
+     *
      * @param p
      *            the socket permission which has to be implied by this
      *            instance.
      * @return {@code true} if this permission instance implies all permissions
      *         represented by {@code p}, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean implies(Permission p) {
@@ -293,15 +281,14 @@
     /**
      * Creates a new {@code PermissionCollection} to store {@code
      * SocketPermission} objects.
-     * 
+     *
      * @return the new permission collection.
-     * @since Android 1.0
      */
     @Override
     public PermissionCollection newPermissionCollection() {
         return new SocketPermissionCollection();
     }
-    
+
     /**
      * Parse the port, including the minPort, maxPort
      * @param hostPort the host[:port] one
@@ -319,14 +306,14 @@
            portMax = 80;
            return;
        }
-       
+
        if (":*".equals(port)) {
            // The port range should be 0-65535
            portMin = 0;
            portMax = 65535;
            return;
        }
-       
+
        // Omit ':'
        port = port.substring(1);
        int negIdx = port.indexOf('-');
@@ -349,21 +336,23 @@
        try {
            portMin = Integer.valueOf(strPortMin).intValue();
            portMax = Integer.valueOf(strPortMax).intValue();
-           
+
            if (portMin > portMax) {
-               throw new IllegalArgumentException(Msg.getString("K0049") + " " + port); //$NON-NLS-1$
+               // K0049=MinPort is greater than MaxPort\: {0}
+               throw new IllegalArgumentException(Msg.getString("K0049", port)); //$NON-NLS-1$
            }
        } catch (NumberFormatException e) {
-           throw new IllegalArgumentException(Msg.getString("K004a") + " " + port); //$NON-NLS-1$
+           // K004a=Invalid port number specified\: {0}
+           throw new IllegalArgumentException(Msg.getString("K004a", port)); //$NON-NLS-1$
        }
     }
 
     /**
      * Creates a canonical action list.
-     * 
+     *
      * @param action
      *            java.lang.String
-     * 
+     *
      * @return java.lang.String
      */
     private String toCanonicalActionString(String action) {
@@ -371,7 +360,7 @@
             return actionNames[SP_RESOLVE]; // If none specified return the
         }
         // implied action resolve
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         if ((actionsMask & SP_CONNECT) == SP_CONNECT) {
             sb.append(',');
             sb.append(actionNames[SP_CONNECT]);
@@ -403,15 +392,20 @@
     }
 
     /**
-     * Get the host part from the host[:port] one.
-     * The host should be
+     * Get the host part from the host[:port] one. The host should be
+     *
+     * <pre>
      *      host = (hostname | IPv4address | IPv6reference | IPv6 in full uncompressed form)
-     * The wildcard "*" may be included once in a DNS name host specification. If it is included, 
-     * it must be in the leftmost position
-     * 
+     * </pre>
+     *
+     * The wildcard "*" may be included once in a DNS name host specification.
+     * If it is included, it must be in the leftmost position
+     *
      * @param host
-     * @return
-     * @throws IllegalArgumentException   if the host is invalid.
+     *            the {@code host[:port]} string.
+     * @return the host name.
+     * @throws IllegalArgumentException
+     *             if the host is invalid.
      */
     private String getHostString(String host) throws IllegalArgumentException {
         host = host.trim();
@@ -431,7 +425,7 @@
         }
 
         int lastIdx = host.lastIndexOf(':');
-        
+
         if (idx == lastIdx) {
             if (-1 != idx) {
                 // only one colon, should be port
@@ -456,21 +450,22 @@
             if (Inet6Util.isIP6AddressInFullForm(host)) {
                 return host.toLowerCase();
             }
-            throw new IllegalArgumentException(Msg.getString("K004a") + " "
-                    + host);
+            // K004a=Invalid port number specified\: {0}
+            throw new IllegalArgumentException(Msg.getString("K004a", host));
         }
         // forward bracket found
         int bbracketIdx = host.indexOf(']');
         if (-1 == bbracketIdx) {
             // no back bracket found, wrong
-            throw new IllegalArgumentException(Msg.getString("K004a") + " "
-                    + host);
+            // K004a=Invalid port number specified\: {0}
+            throw new IllegalArgumentException(Msg.getString("K004a", host));
         }
         host = host.substring(0, bbracketIdx + 1);
         if (Inet6Util.isValidIP6Address(host)) {
             return host.toLowerCase();
         }
-        throw new IllegalArgumentException(Msg.getString("K004a") + " " + host);
+        // K004a=Invalid port number specified\: {0}
+        throw new IllegalArgumentException(Msg.getString("K004a", host));
     }
 
     /**
diff --git a/libcore/luni/src/main/java/java/net/SocketPermissionCollection.java b/libcore/luni/src/main/java/java/net/SocketPermissionCollection.java
index 777f9a7..60bb831 100644
--- a/libcore/luni/src/main/java/java/net/SocketPermissionCollection.java
+++ b/libcore/luni/src/main/java/java/net/SocketPermissionCollection.java
@@ -26,8 +26,6 @@
  * This class represents a list of {@code SocketPermission} objects and provides
  * a method to check whether or not a specific permission is implied by this
  * {@code SocketPermissionCollection}.
- * 
- * @since Android 1.0
  */
 final class SocketPermissionCollection extends PermissionCollection {
 
@@ -62,8 +60,6 @@
      * Returns whether this permission collection implies {@code permission}.
      * Basically it tests whether {@code permission} is the subset of this
      * collection.
-     * 
-     * @since Android 1.0
      */
     @Override
     public boolean implies(Permission permission) {
diff --git a/libcore/luni/src/main/java/java/net/SocketTimeoutException.java b/libcore/luni/src/main/java/java/net/SocketTimeoutException.java
index 32ba183..c1c762e 100644
--- a/libcore/luni/src/main/java/java/net/SocketTimeoutException.java
+++ b/libcore/luni/src/main/java/java/net/SocketTimeoutException.java
@@ -22,8 +22,6 @@
 /**
  * This exception is thrown when a timeout expired on a socket {@code read} or
  * {@code accept} operation.
- * 
- * @since Android 1.0
  */
 public class SocketTimeoutException extends InterruptedIOException {
 
@@ -32,8 +30,6 @@
     /**
      * Creates a new {@code SocketTimeoutException} instance with its walkback
      * filled in.
-     * 
-     * @since Android 1.0
      */
     public SocketTimeoutException() {
         super();
@@ -45,7 +41,6 @@
      * 
      * @param detailMessage
      *            the detail message of this exception.
-     * @since Android 1.0
      */
     public SocketTimeoutException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/net/URI.java b/libcore/luni/src/main/java/java/net/URI.java
index 4b1f4df..85c16eb 100644
--- a/libcore/luni/src/main/java/java/net/URI.java
+++ b/libcore/luni/src/main/java/java/net/URI.java
@@ -28,8 +28,6 @@
 
 /**
  * This class represents an instance of a URI as defined by RFC 2396.
- * 
- * @since Android 1.0
  */
 public final class URI implements Comparable<URI>, Serializable {
 
@@ -78,13 +76,12 @@
 
     /**
      * Creates a new URI instance according to the given string {@code uri}.
-     * 
+     *
      * @param uri
      *            the textual URI representation to be parsed into a URI object.
      * @throws URISyntaxException
      *             if the given string {@code uri} doesn't fit to the
      *             specification RFC2396 or could not be parsed correctly.
-     * @since Android 1.0
      */
     public URI(String uri) throws URISyntaxException {
         new Helper().parseURI(uri, false);
@@ -96,8 +93,7 @@
      * string will be parsed later on to create the URI instance.
      * <p>
      * {@code [scheme:]scheme-specific-part[#fragment]}
-     * </p>
-     * 
+     *
      * @param scheme
      *            the scheme part of the URI.
      * @param ssp
@@ -107,11 +103,10 @@
      * @throws URISyntaxException
      *             if the temporary created string doesn't fit to the
      *             specification RFC2396 or could not be parsed correctly.
-     * @since Android 1.0
      */
     public URI(String scheme, String ssp, String frag)
             throws URISyntaxException {
-        StringBuffer uri = new StringBuffer();
+        StringBuilder uri = new StringBuilder();
         if (scheme != null) {
             uri.append(scheme);
             uri.append(':');
@@ -135,8 +130,7 @@
      * string will be parsed later on to create the URI instance.
      * <p>
      * {@code [scheme:][user-info@]host[:port][path][?query][#fragment]}
-     * </p>
-     * 
+     *
      * @param scheme
      *            the scheme part of the URI.
      * @param userinfo
@@ -156,7 +150,6 @@
      * @throws URISyntaxException
      *             if the temporary created string doesn't fit to the
      *             specification RFC2396 or could not be parsed correctly.
-     * @since Android 1.0
      */
     public URI(String scheme, String userinfo, String host, int port,
             String path, String query, String fragment)
@@ -173,7 +166,7 @@
             throw new URISyntaxException(path, Msg.getString("K0302")); //$NON-NLS-1$
         }
 
-        StringBuffer uri = new StringBuffer();
+        StringBuilder uri = new StringBuilder();
         if (scheme != null) {
             uri.append(scheme);
             uri.append(':');
@@ -230,8 +223,7 @@
      * string will be parsed later on to create the URI instance.
      * <p>
      * {@code [scheme:]host[path][#fragment]}
-     * </p>
-     * 
+     *
      * @param scheme
      *            the scheme part of the URI.
      * @param host
@@ -243,7 +235,6 @@
      * @throws URISyntaxException
      *             if the temporary created string doesn't fit to the
      *             specification RFC2396 or could not be parsed correctly.
-     * @since Android 1.0
      */
     public URI(String scheme, String host, String path, String fragment)
             throws URISyntaxException {
@@ -256,8 +247,7 @@
      * string will be parsed later on to create the URI instance.
      * <p>
      * {@code [scheme:][//authority][path][?query][#fragment]}
-     * </p>
-     * 
+     *
      * @param scheme
      *            the scheme part of the URI.
      * @param authority
@@ -272,7 +262,6 @@
      * @throws URISyntaxException
      *             if the temporary created string doesn't fit to the
      *             specification RFC2396 or could not be parsed correctly.
-     * @since Android 1.0
      */
     public URI(String scheme, String authority, String path, String query,
             String fragment) throws URISyntaxException {
@@ -281,7 +270,7 @@
             throw new URISyntaxException(path, Msg.getString("K0302")); //$NON-NLS-1$
         }
 
-        StringBuffer uri = new StringBuffer();
+        StringBuilder uri = new StringBuilder();
         if (scheme != null) {
             uri.append(scheme);
             uri.append(':');
@@ -718,7 +707,7 @@
                     // case for a closed bracket at end of IP [x:x:x:...x]
                     case ']':
                         if (i != length - 1) {
-                            return false; // must be last charcter
+                            return false; // must be last character
                         }
                         if (ipAddress.charAt(0) != '[') {
                             return false; // must have a open [
@@ -856,11 +845,10 @@
      * in the natural case-sensitive way. A hierarchical URI is less than an
      * opaque URI and if one part is {@code null} the URI with the undefined
      * part is less than the other one.
-     * 
+     *
      * @param uri
      *            the URI this instance has to compare with.
      * @return the value representing the order of the two instances.
-     * @since Android 1.0
      */
     public int compareTo(URI uri) {
         int ret = 0;
@@ -969,11 +957,10 @@
     /**
      * Parses the given argument {@code uri} and creates an appropriate URI
      * instance.
-     * 
+     *
      * @param uri
      *            the string which has to be parsed to create the URI instance.
      * @return the created instance representing the given URI.
-     * @since Android 1.0
      */
     public static URI create(String uri) {
         URI result = null;
@@ -1007,7 +994,7 @@
      * converts the hex values following the '%' to lowercase
      */
     private String convertHexToLowerCase(String s) {
-        StringBuffer result = new StringBuffer(""); //$NON-NLS-1$
+        StringBuilder result = new StringBuilder(""); //$NON-NLS-1$
         if (s.indexOf('%') == -1) {
             return s;
         }
@@ -1057,12 +1044,11 @@
      * Compares this URI instance with the given argument {@code o} and
      * determines if both are equal. Two URI instances are equal if all single
      * parts are identical in their meaning.
-     * 
+     *
      * @param o
      *            the URI this instance has to be compared with.
      * @return {@code true} if both URI instances point to the same resource,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object o) {
@@ -1147,9 +1133,8 @@
 
     /**
      * Gets the decoded authority part of this URI.
-     * 
+     *
      * @return the decoded authority part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getAuthority() {
         return decode(authority);
@@ -1159,7 +1144,6 @@
      * Gets the decoded fragment part of this URI.
      * 
      * @return the decoded fragment part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getFragment() {
         return decode(fragment);
@@ -1169,7 +1153,6 @@
      * Gets the host part of this URI.
      * 
      * @return the host part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getHost() {
         return host;
@@ -1179,7 +1162,6 @@
      * Gets the decoded path part of this URI.
      * 
      * @return the decoded path part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getPath() {
         return decode(path);
@@ -1189,7 +1171,6 @@
      * Gets the port number of this URI.
      * 
      * @return the port number or {@code -1} if undefined.
-     * @since Android 1.0
      */
     public int getPort() {
         return port;
@@ -1199,7 +1180,6 @@
      * Gets the decoded query part of this URI.
      * 
      * @return the decoded query part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getQuery() {
         return decode(query);
@@ -1209,7 +1189,6 @@
      * Gets the authority part of this URI in raw form.
      * 
      * @return the encoded authority part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getRawAuthority() {
         return authority;
@@ -1219,7 +1198,6 @@
      * Gets the fragment part of this URI in raw form.
      * 
      * @return the encoded fragment part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getRawFragment() {
         return fragment;
@@ -1229,7 +1207,6 @@
      * Gets the path part of this URI in raw form.
      * 
      * @return the encoded path part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getRawPath() {
         return path;
@@ -1239,7 +1216,6 @@
      * Gets the query part of this URI in raw form.
      * 
      * @return the encoded query part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getRawQuery() {
         return query;
@@ -1249,17 +1225,15 @@
      * Gets the scheme-specific part of this URI in raw form.
      * 
      * @return the encoded scheme-specific part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getRawSchemeSpecificPart() {
         return schemespecificpart;
     }
-    
+
     /**
      * Gets the user-info part of this URI in raw form.
      * 
      * @return the encoded user-info part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getRawUserInfo() {
         return userinfo;
@@ -1269,17 +1243,15 @@
      * Gets the scheme part of this URI.
      * 
      * @return the scheme part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getScheme() {
         return scheme;
     }
-    
+
     /**
      * Gets the decoded scheme-specific part of this URI.
      * 
      * @return the decoded scheme-specific part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getSchemeSpecificPart() {
         return decode(schemespecificpart);
@@ -1289,7 +1261,6 @@
      * Gets the decoded user-info part of this URI.
      * 
      * @return the decoded user-info part or {@code null} if undefined.
-     * @since Android 1.0
      */
     public String getUserInfo() {
         return decode(userinfo);
@@ -1297,9 +1268,8 @@
 
     /**
      * Gets the hashcode value of this URI instance.
-     * 
+     *
      * @return the appropriate hashcode value.
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -1314,7 +1284,6 @@
      * defined in this URI.
      * 
      * @return {@code true} if this URI is absolute, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isAbsolute() {
         return absolute;
@@ -1327,7 +1296,6 @@
      * undefined.
      * 
      * @return {@code true} if the URI is opaque, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isOpaque() {
         return opaque;
@@ -1389,7 +1357,7 @@
         }
 
         // put the path back together
-        StringBuffer newpath = new StringBuffer();
+        StringBuilder newpath = new StringBuilder();
         if (path.startsWith("/")) { //$NON-NLS-1$
             newpath.append('/');
         }
@@ -1424,10 +1392,9 @@
 
     /**
      * Normalizes the path part of this URI.
-     * 
+     *
      * @return an URI object which represents this instance with a normalized
      *         path.
-     * @since Android 1.0
      */
     public URI normalize() {
         if (opaque) {
@@ -1450,12 +1417,11 @@
      * Tries to parse the authority component of this URI to divide it into the
      * host, port, and user-info. If this URI is already determined as a
      * ServerAuthority this instance will be returned without changes.
-     * 
+     *
      * @return this instance with the components of the parsed server authority.
      * @throws URISyntaxException
      *             if the authority part could not be parsed as a server-based
      *             authority.
-     * @since Android 1.0
      */
     public URI parseServerAuthority() throws URISyntaxException {
         if (!serverAuthority) {
@@ -1467,11 +1433,10 @@
     /**
      * Makes the given URI {@code relative} to a relative URI against the URI
      * represented by this instance.
-     * 
+     *
      * @param relative
      *            the URI which has to be relativized against this URI.
      * @return the relative URI.
-     * @since Android 1.0
      */
     public URI relativize(URI relative) {
         if (relative.opaque || opaque) {
@@ -1516,17 +1481,17 @@
         result.query = relative.query;
         // the result URI is the remainder of the relative URI's path
         result.path = relativePath.substring(thisPath.length());
+        result.setSchemeSpecificPart();
         return result;
     }
 
     /**
      * Resolves the given URI {@code relative} against the URI represented by
      * this instance.
-     * 
+     *
      * @param relative
      *            the URI which has to be resolved against this URI.
      * @return the resolved URI.
-     * @since Android 1.0
      */
     public URI resolve(URI relative) {
         if (relative.absolute || opaque) {
@@ -1583,7 +1548,7 @@
      */
     private void setSchemeSpecificPart() {
         // ssp = [//authority][path][?query]
-        StringBuffer ssp = new StringBuffer();
+        StringBuilder ssp = new StringBuilder();
         if (authority != null) {
             ssp.append("//" + authority); //$NON-NLS-1$
         }
@@ -1602,12 +1567,11 @@
      * Creates a new URI instance by parsing the given string {@code relative}
      * and resolves the created URI against the URI represented by this
      * instance.
-     * 
+     *
      * @param relative
      *            the given string to create the new URI instance which has to
      *            be resolved later on.
      * @return the created and resolved URI.
-     * @since Android 1.0
      */
     public URI resolve(String relative) {
         return resolve(create(relative));
@@ -1652,9 +1616,8 @@
     /**
      * Returns the textual string representation of this URI instance using the
      * US-ASCII encoding.
-     * 
+     *
      * @return the US-ASCII string representation of this URI.
-     * @since Android 1.0
      */
     public String toASCIIString() {
         return encodeOthers(toString());
@@ -1662,14 +1625,13 @@
 
     /**
      * Returns the textual string representation of this URI instance.
-     * 
+     *
      * @return the textual string representation of this URI.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
         if (string == null) {
-            StringBuffer result = new StringBuffer();
+            StringBuilder result = new StringBuilder();
             if (scheme != null) {
                 result.append(scheme);
                 result.append(':');
@@ -1708,7 +1670,7 @@
      * and converts escaped octets to lowercase.
      */
     private String getHashString() {
-        StringBuffer result = new StringBuffer();
+        StringBuilder result = new StringBuilder();
         if (scheme != null) {
             result.append(scheme.toLowerCase());
             result.append(':');
@@ -1751,12 +1713,11 @@
 
     /**
      * Converts this URI instance to a URL.
-     * 
+     *
      * @return the created URL representing the same resource as this URI.
      * @throws MalformedURLException
      *             if an error occurs while creating the URL or no protocol
      *             handler could be found.
-     * @since Android 1.0
      */
     public URL toURL() throws MalformedURLException {
         if (!absolute) {
diff --git a/libcore/luni/src/main/java/java/net/URIEncoderDecoder.java b/libcore/luni/src/main/java/java/net/URIEncoderDecoder.java
index a9ef3c1..d2b0044 100644
--- a/libcore/luni/src/main/java/java/net/URIEncoderDecoder.java
+++ b/libcore/luni/src/main/java/java/net/URIEncoderDecoder.java
@@ -27,8 +27,6 @@
  * application/x-www-form-urlencoded} MIME content type. It contains helper
  * methods used by the URI class, and performs encoding and decoding in a
  * slightly different way than {@code URLEncoder} and {@code URLDecoder}.
- * 
- * @since Android 1.0
  */
 class URIEncoderDecoder {
 
@@ -43,8 +41,7 @@
      * US-ASCII set, and are not ISO Control or are not ISO Space characters)
      * <p>
      * called from {@code URI.Helper.parseURI()} to validate each component
-     * </p>
-     * 
+     *
      * @param s
      *            {@code java.lang.String} the string to be validated
      * @param legal
@@ -100,14 +97,12 @@
      * by '%'.
      * <p>
      * For example: '#' -> %23
-     * </p>
      * Other characters, which are unicode chars that are not US-ASCII, and are
      * not ISO Control or are not ISO Space chars, are preserved.
      * <p>
      * Called from {@code URI.quoteComponent()} (for multiple argument
      * constructors)
-     * </p>
-     * 
+     *
      * @param s
      *            java.lang.String the string to be converted
      * @param legal
@@ -117,7 +112,7 @@
      */
     static String quoteIllegal(String s, String legal)
             throws UnsupportedEncodingException {
-        StringBuffer buf = new StringBuffer();
+        StringBuilder buf = new StringBuilder();
         for (int i = 0; i < s.length(); i++) {
             char ch = s.charAt(i);
             if ((ch >= 'a' && ch <= 'z')
@@ -145,16 +140,15 @@
      * converted into their hexidecimal value prepended by '%'.
      * <p>
      * For example: Euro currency symbol -> "%E2%82%AC".
-     * </p>
+     * <p>
      * Called from URI.toASCIIString()
-     * </p>
-     * 
+     *
      * @param s
      *            java.lang.String the string to be converted
      * @return java.lang.String the converted string
      */
     static String encodeOthers(String s) throws UnsupportedEncodingException {
-        StringBuffer buf = new StringBuffer();
+        StringBuilder buf = new StringBuilder();
         for (int i = 0; i < s.length(); i++) {
             char ch = s.charAt(i);
             if (ch <= 127) {
@@ -178,11 +172,10 @@
      *'%' and two following hex digit characters are converted to the
      * equivalent byte value. All other characters are passed through
      * unmodified.
-     * </p>
+     * <p>
      * e.g. "A%20B%20C %24%25" -> "A B C $%"
      * <p>
      * Called from URI.getXYZ() methods
-     * </p>
      * 
      * @param s
      *            java.lang.String The encoded string.
@@ -190,7 +183,7 @@
      */
     static String decode(String s) throws UnsupportedEncodingException {
 
-        StringBuffer result = new StringBuffer();
+        StringBuilder result = new StringBuilder();
         ByteArrayOutputStream out = new ByteArrayOutputStream();
         for (int i = 0; i < s.length();) {
             char c = s.charAt(i);
diff --git a/libcore/luni/src/main/java/java/net/URISyntaxException.java b/libcore/luni/src/main/java/java/net/URISyntaxException.java
index e7e332e..2daf35f 100644
--- a/libcore/luni/src/main/java/java/net/URISyntaxException.java
+++ b/libcore/luni/src/main/java/java/net/URISyntaxException.java
@@ -22,8 +22,6 @@
 /**
  * A {@code URISyntaxException} will be thrown if some information could not be parsed
  * while creating a URI.
- * 
- * @since Android 1.0
  */
 public class URISyntaxException extends Exception {
 
@@ -49,7 +47,6 @@
      *             {@code null}.
      * @throws IllegalArgumentException
      *             if the value for {@code index} is lesser than {@code -1}.
-     * @since Android 1.0
      */
     public URISyntaxException(String input, String reason, int index) {
         super(reason);
@@ -77,7 +74,6 @@
      * @throws NullPointerException
      *             if one of the arguments {@code input} or {@code reason} is
      *             {@code null}.
-     * @since Android 1.0
      */
     public URISyntaxException(String input, String reason) {
         super(reason);
@@ -95,7 +91,6 @@
      * index is unknown/unavailable.
      * 
      * @return the index of the syntax error.
-     * @since Android 1.0
      */
     public int getIndex() {
         return index;
@@ -105,7 +100,6 @@
      * Gets a description of the syntax error.
      * 
      * @return the string describing the syntax error.
-     * @since Android 1.0
      */
     public String getReason() {
         return super.getMessage();
@@ -115,7 +109,6 @@
      * Gets the initial string that contains an invalid syntax.
      * 
      * @return the string that caused the exception.
-     * @since Android 1.0
      */
     public String getInput() {
         return input;
@@ -128,7 +121,6 @@
      * 
      * @return a sting containing information about the exception.
      * @see java.lang.Throwable#getMessage()
-     * @since Android 1.0
      */
     @Override
     public String getMessage() {
diff --git a/libcore/luni/src/main/java/java/net/URL.java b/libcore/luni/src/main/java/java/net/URL.java
index 2bc8c6c..9b0fdc4 100644
--- a/libcore/luni/src/main/java/java/net/URL.java
+++ b/libcore/luni/src/main/java/java/net/URL.java
@@ -34,8 +34,6 @@
  * which generates the output dynamically. A URL is divided in its parts
  * protocol, host name, port, path, file, user-info, query, reference and
  * authority. However, not each of this parts has to be defined.
- * 
- * @since Android 1.0
  */
 public final class URL implements java.io.Serializable {
     private static final long serialVersionUID = -7627629688361524110L;
@@ -131,11 +129,9 @@
      * <p>
      * A security check is performed to verify whether the current policy allows
      * to set the stream handler factory.
-     * </p>
-     * 
+     *
      * @param streamFactory
      *            the factory to be used for creating stream protocol handlers.
-     * @since Android 1.0
      */
     public static synchronized void setURLStreamHandlerFactory(
             URLStreamHandlerFactory streamFactory) {
@@ -158,7 +154,6 @@
      * @throws MalformedURLException
      *             if the given string {@code spec} could not be parsed as a
      *             URL.
-     * @since Android 1.0
      */
     public URL(String spec) throws MalformedURLException {
         this((URL) null, spec, (URLStreamHandler) null);
@@ -178,7 +173,6 @@
      * @throws MalformedURLException
      *             if the given string {@code spec} could not be parsed as a URL
      *             or an invalid protocol has been found.
-     * @since Android 1.0
      */
     public URL(URL context, String spec) throws MalformedURLException {
         this(context, spec, (URLStreamHandler) null);
@@ -202,7 +196,6 @@
      * @throws MalformedURLException
      *             if the given string {@code spec} could not be parsed as a URL
      *             or an invalid protocol has been found.
-     * @since Android 1.0
      */
     public URL(URL context, String spec, URLStreamHandler handler)
             throws MalformedURLException {
@@ -235,8 +228,6 @@
                 // According to RFC 2396 scheme part should match
                 // the following expression:
                 // alpha *( alpha | digit | "+" | "-" | "." )
-                // BEGIN android-changed
-                // copied from newer version of harmony
                 char c = protocol.charAt(0);
                 boolean valid = ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
                 for (int i = 1; valid && (i < protocol.length()); i++) {
@@ -253,10 +244,9 @@
                     index = -1;
                 } else {
                     // Ignore case in protocol names.
-                    // Scheme is defined by ASCII characters.
+                	// Scheme is defined by ASCII characters.
                     protocol = Util.toASCIILowerCase(protocol);
                 }
-                // END android-changed
             }
         }
 
@@ -338,7 +328,6 @@
      * @throws MalformedURLException
      *             if the combination of all arguments do not represent a valid
      *             URL or the protocol is invalid.
-     * @since Android 1.0
      */
     public URL(String protocol, String host, String file)
             throws MalformedURLException {
@@ -361,7 +350,6 @@
      * @throws MalformedURLException
      *             if the combination of all arguments do not represent a valid
      *             URL or the protocol is invalid.
-     * @since Android 1.0
      */
     public URL(String protocol, String host, int port, String file)
             throws MalformedURLException {
@@ -371,7 +359,7 @@
     /**
      * Creates a new URL instance using the given arguments. The URL uses the
      * specified port instead of the default port for the given protocol.
-     * 
+     *
      * @param protocol
      *            the protocol of the new URL.
      * @param host
@@ -386,25 +374,26 @@
      * @throws MalformedURLException
      *             if the combination of all arguments do not represent a valid
      *             URL or the protocol is invalid.
-     * @since Android 1.0
+     * @throws SecurityException
+     *             if {@code handler} is non-{@code null}, and a security
+     *             manager is installed that disallows user-defined protocol
+     *             handlers.
      */
     public URL(String protocol, String host, int port, String file,
             URLStreamHandler handler) throws MalformedURLException {
         if (port < -1) {
-            throw new MalformedURLException(org.apache.harmony.luni.util.Msg
-                    .getString("K0325", port)); //$NON-NLS-1$
+            throw new MalformedURLException(Msg.getString("K0325", port)); //$NON-NLS-1$
         }
 
         if (host != null && host.indexOf(":") != -1 && host.charAt(0) != '[') { //$NON-NLS-1$
             host = "[" + host + "]"; //$NON-NLS-1$ //$NON-NLS-2$
         }
 
-        if (protocol != null) {
-            this.protocol = protocol;
-        } else {
-            throw new NullPointerException(Msg.getString("K00b3", protocol)); //$NON-NLS-1$
+        if (protocol == null) {
+            throw new NullPointerException(Msg.getString("K00b3", "null")); //$NON-NLS-1$ //$NON-NLS-2$
         }
 
+        this.protocol = protocol;
         this.host = host;
         this.port = port;
 
@@ -427,8 +416,7 @@
             setupStreamHandler();
             if (strmHandler == null) {
                 throw new MalformedURLException(
-                        org.apache.harmony.luni.util.Msg.getString(
-                                "K00b3", protocol)); //$NON-NLS-1$
+                        Msg.getString("K00b3", protocol)); //$NON-NLS-1$
             }
         } else {
             SecurityManager sm = System.getSecurityManager();
@@ -479,7 +467,6 @@
      *            the file to be set.
      * @param ref
      *            the reference to be set.
-     * @since Android 1.0
      */
     protected void set(String protocol, String host, int port, String file,
             String ref) {
@@ -506,8 +493,7 @@
      *            the URL this instance has to be compared with.
      * @return {@code true} if both instances represents the same URL, {@code
      *         false} otherwise.
-     * @see #hashCode
-     * @since Android 1.0
+     * @see #hashCode()
      */
     @Override
     public boolean equals(Object o) {
@@ -532,7 +518,6 @@
      *            the URL to compare against.
      * @return {@code true} if both instances refer to the same resource,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean sameFile(URL otherURL) {
         return strmHandler.sameFile(this, otherURL);
@@ -542,7 +527,6 @@
      * Gets the hashcode value of this URL instance.
      * 
      * @return the appropriate hashcode value.
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -560,7 +544,6 @@
      * Note that this will overwrite any existing stream handler with the new
      * one. Senders must check if the strmHandler is null before calling the
      * method if they do not want this behavior (a speed optimization).
-     * </p>
      */
     void setupStreamHandler() {
         // Check for a cached (previously looked up) handler for
@@ -629,12 +612,10 @@
      * <li>Image for pictures</li>
      * <li>AudioClip for audio sequences</li>
      * <li>{@link InputStream} for all other data</li>
-     * </p>
      * 
      * @return the content of the referred resource.
      * @throws IOException
      *             if an error occurs obtaining the content.
-     * @since Android 1.0
      */
     public final Object getContent() throws IOException {
         return openConnection().getContent();
@@ -654,7 +635,6 @@
      *         type.
      * @throws IOException
      *             if an error occurs obtaining the content.
-     * @since Android 1.0
      */
     // Param not generic in spec
     @SuppressWarnings("unchecked")
@@ -668,7 +648,6 @@
      * @return the stream which allows to read the resource.
      * @throws IOException
      *             if an error occurs while opening the InputStream.
-     * @since Android 1.0
      */
     public final InputStream openStream() throws java.io.IOException {
         return openConnection().getInputStream();
@@ -681,7 +660,6 @@
      * @return the connection to this URL.
      * @throws IOException
      *             if an error occurs while opening the connection.
-     * @since Android 1.0
      */
     public URLConnection openConnection() throws IOException {
         return strmHandler.openConnection(this);
@@ -693,7 +671,6 @@
      * @return the URI instance that represents this URL.
      * @throws URISyntaxException
      *             if this URL cannot be converted into a URI.
-     * @since Android 1.0
      */
     public URI toURI() throws URISyntaxException {
         return new URI(toExternalForm());
@@ -718,7 +695,6 @@
      * @throws UnsupportedOperationException
      *             if the protocol handler does not support opening connections
      *             through proxies.
-     * @since Android 1.0
      */
     public URLConnection openConnection(Proxy proxy) throws IOException {
         if (null == proxy) {
@@ -733,7 +709,6 @@
      * {@code toExternalForm()}.
      * 
      * @return the string representation of this URL.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -745,7 +720,6 @@
      * this URL.
      * 
      * @return the string representation of this URL.
-     * @since Android 1.0
      */
     public String toExternalForm() {
         if (strmHandler == null) {
@@ -798,8 +772,7 @@
      * <p>
      * Note that, we really only need the readObject method but the spec that
      * says readObject will be ignored if no writeObject is present.
-     * </p>
-     * 
+     *
      * @param s
      *            the stream to write on.
      * @throws IOException
@@ -814,7 +787,6 @@
      * 
      * @return the file name this URL refers to or an empty string if the file
      *         part is not set.
-     * @since Android 1.0
      */
     public String getFile() {
         return file;
@@ -824,7 +796,6 @@
      * Gets the value of the host part of this URL.
      * 
      * @return the host name or IP address of this URL.
-     * @since Android 1.0
      */
     public String getHost() {
         return host;
@@ -834,7 +805,6 @@
      * Gets the port number of this URL or {@code -1} if the port is not set.
      * 
      * @return the port number of this URL.
-     * @since Android 1.0
      */
     public int getPort() {
         return port;
@@ -844,7 +814,6 @@
      * Gets the protocol of this URL.
      * 
      * @return the protocol type of this URL.
-     * @since Android 1.0
      */
     public String getProtocol() {
         return protocol;
@@ -854,7 +823,6 @@
      * Gets the value of the reference part of this URL.
      * 
      * @return the reference part of this URL.
-     * @since Android 1.0
      */
     public String getRef() {
         return ref;
@@ -864,7 +832,6 @@
      * Gets the value of the query part of this URL.
      * 
      * @return the query part of this URL.
-     * @since Android 1.0
      */
     public String getQuery() {
         return query;
@@ -874,7 +841,6 @@
      * Gets the value of the path part of this URL.
      * 
      * @return the path part of this URL.
-     * @since Android 1.0
      */
     public String getPath() {
         return path;
@@ -884,7 +850,6 @@
      * Gets the value of the user-info part of this URL.
      * 
      * @return the user-info part of this URL.
-     * @since Android 1.0
      */
     public String getUserInfo() {
         return userInfo;
@@ -894,7 +859,6 @@
      * Gets the value of the authority part of this URL.
      * 
      * @return the authority part of this URL.
-     * @since Android 1.0
      */
     public String getAuthority() {
         return authority;
@@ -921,7 +885,6 @@
      *            the query to be set.
      * @param ref
      *            the reference to be set.
-     * @since Android 1.0
      */
     protected void set(String protocol, String host, int port,
             String authority, String userInfo, String path, String query,
@@ -941,21 +904,13 @@
         this.query = query;
     }
 
-    // BEGIN android-removed
-    // copied from newer version of harmony
-    // URLStreamHandler getStreamHandler() {
-    //     return strmHandler;
-    // }
-    // END android-removed
-
     /**
      * Gets the default port number of the protocol used by this URL. If no
      * default port is defined by the protocol or the {@code URLStreamHandler},
      * {@code -1} will be returned.
-     * 
+     *
      * @return the default port number according to the protocol of this URL.
      * @see URLStreamHandler#getDefaultPort
-     * @since Android 1.0
      */
     public int getDefaultPort() {
         return strmHandler.getDefaultPort();
diff --git a/libcore/luni/src/main/java/java/net/URLClassLoader.java b/libcore/luni/src/main/java/java/net/URLClassLoader.java
index c70ed45..6dfa385 100644
--- a/libcore/luni/src/main/java/java/net/URLClassLoader.java
+++ b/libcore/luni/src/main/java/java/net/URLClassLoader.java
@@ -17,12 +17,15 @@
 
 package java.net;
 
+import java.io.BufferedReader;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.FilePermission;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.io.UnsupportedEncodingException;
 import java.security.AccessControlContext;
 import java.security.AccessController;
@@ -35,22 +38,14 @@
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.IdentityHashMap;
 import java.util.List;
-import java.util.ListIterator;
 import java.util.Map;
-import java.util.Set;
 import java.util.StringTokenizer;
-import java.util.Vector;
 import java.util.jar.Attributes;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 import java.util.jar.Manifest;
-import java.util.zip.ZipEntry;
 
-import org.apache.harmony.luni.util.InvalidJarIndexException;
 import org.apache.harmony.luni.util.Msg;
 
 /**
@@ -58,33 +53,17 @@
  * list of URLs which can refer to either directories or JAR files. Classes
  * loaded by this {@code URLClassLoader} are granted permission to access the
  * URLs contained in the URL search list.
- * 
- * @since Android 1.0
  */
 public class URLClassLoader extends SecureClassLoader {
 
-    private static URL[] NO_PATH = new URL[0];
+    ArrayList<URL> originalUrls;
 
-    @SuppressWarnings("unchecked")
-    private static <K, V> Hashtable<K, V>[] newHashtableArray(int size) {
-        return new Hashtable[size];
-    }
-
-    URL[] urls, orgUrls;
-
-    Set<URL> invalidUrls = Collections.synchronizedSet(new HashSet<URL>());
-
-    private Map<URL, JarFile> resCache = 
-            Collections.synchronizedMap(new IdentityHashMap<URL, JarFile>(32));
-
-    private Object lock = new Object();
+    List<URL> searchList;
+    ArrayList<URLHandler> handlerList;
+    Map<URL, URLHandler> handlerMap = new HashMap<URL, URLHandler>();
 
     private URLStreamHandlerFactory factory;
 
-    HashMap<URL, URL[]> extensions;
-
-    Hashtable<String, URL[]>[] indexes;
-
     private AccessControlContext currentContext;
 
     static class SubURLClassLoader extends URLClassLoader {
@@ -103,7 +82,7 @@
          * Overrides the {@code loadClass()} of {@code ClassLoader}. It calls
          * the security manager's {@code checkPackageAccess()} before
          * attempting to load the class.
-         * 
+         *
          * @return the Class object.
          * @param className
          *            String the name of the class to search for.
@@ -115,7 +94,7 @@
          */
         @Override
         protected synchronized Class<?> loadClass(String className,
-                boolean resolveClass) throws ClassNotFoundException {
+                                                  boolean resolveClass) throws ClassNotFoundException {
             SecurityManager sm = System.getSecurityManager();
             if (sm != null && !checkingPackageAccess) {
                 int index = className.lastIndexOf('.');
@@ -132,12 +111,503 @@
         }
     }
 
+    static class IndexFile {
+
+        private HashMap<String, ArrayList<URL>> map;
+        //private URLClassLoader host;
+
+
+        static IndexFile readIndexFile(JarFile jf, JarEntry indexEntry, URL url) {
+            BufferedReader in = null;
+            InputStream is = null;
+            try {
+                // Add mappings from resource to jar file
+                String parentURLString = getParentURL(url).toExternalForm();
+                String prefix = "jar:" //$NON-NLS-1$
+                        + parentURLString + "/"; //$NON-NLS-1$
+                is = jf.getInputStream(indexEntry);
+                in = new BufferedReader(new InputStreamReader(is, "UTF8"));
+                HashMap<String, ArrayList<URL>> pre_map = new HashMap<String, ArrayList<URL>>();
+                // Ignore the 2 first lines (index version)
+                if (in.readLine() == null) return null;
+                if (in.readLine() == null) return null;
+                TOP_CYCLE:
+                while (true) {
+                    String line = in.readLine();
+                    if (line == null) {
+                        break;
+                    }
+                    URL jar = new URL(prefix + line + "!/"); //$NON-NLS-1$
+                    while (true) {
+                        line = in.readLine();
+                        if (line == null) {
+                            break TOP_CYCLE;
+                        }
+                        if ("".equals(line)) {
+                            break;
+                        }
+                        ArrayList<URL> list;
+                        if (pre_map.containsKey(line)) {
+                            list = pre_map.get(line);
+                        } else {
+                            list = new ArrayList<URL>();
+                            pre_map.put(line, list);
+                        }
+                        list.add(jar);
+                    }
+                }
+                if (!pre_map.isEmpty()) {
+                    return new IndexFile(pre_map);
+                }
+            } catch (MalformedURLException e) {
+                // Ignore this jar's index
+            } catch (IOException e) {
+                // Ignore this jar's index
+            }
+            finally {
+                if (in != null) {
+                    try {
+                        in.close();
+                    } catch (IOException e) {
+                    }
+                }
+                if (is != null) {
+                    try {
+                        is.close();
+                    } catch (IOException e) {
+                    }
+                }
+            }
+            return null;
+        }
+
+        private static URL getParentURL(URL url) throws IOException {
+            URL fileURL = ((JarURLConnection) url.openConnection()).getJarFileURL();
+            String file = fileURL.getFile();
+            String parentFile = new File(file).getParent();
+            parentFile = parentFile.replace(File.separatorChar, '/');
+            if (parentFile.charAt(0) != '/') {
+                parentFile = "/" + parentFile; //$NON-NLS-1$
+            }
+            URL parentURL = new URL(fileURL.getProtocol(), fileURL
+                    .getHost(), fileURL.getPort(), parentFile);
+            return parentURL;
+        }
+
+        public IndexFile(HashMap<String, ArrayList<URL>> map) {
+            this.map = map;
+        }
+
+        ArrayList<URL> get(String name) {
+            return map.get(name);
+        }
+    }
+
+    class URLHandler {
+        URL url;
+        URL codeSourceUrl;
+
+        public URLHandler(URL url) {
+            this.url = url;
+            this.codeSourceUrl = url;
+        }
+
+        void findResources(String name, ArrayList<URL> resources) {
+            URL res = findResource(name);
+            if (res != null && !resources.contains(res)) {
+                resources.add(res);
+            }
+        }
+
+        Class<?> findClass(String packageName, String name, String origName) {
+            URL resURL = targetURL(url, name);
+            if (resURL != null) {
+                try {
+                    InputStream is = resURL.openStream();
+                    return createClass(is, packageName, origName);
+                } catch (IOException e) {
+                }
+            }
+            return null;
+        }
+
+
+        Class<?> createClass(InputStream is, String packageName, String origName) {
+            if (is == null) {
+                return null;
+            }
+            byte[] clBuf = null;
+            try {
+                clBuf = getBytes(is);
+            } catch (IOException e) {
+                return null;
+            } finally {
+                try {
+                    is.close();
+                } catch (IOException e) {
+                }
+            }
+            if (packageName != null) {
+                String packageDotName = packageName.replace('/', '.');
+                Package packageObj = getPackage(packageDotName);
+                if (packageObj == null) {
+                    definePackage(packageDotName, null, null,
+                            null, null, null, null, null);
+                } else {
+                    if (packageObj.isSealed()) {
+                        throw new SecurityException(Msg
+                                .getString("K004c")); //$NON-NLS-1$
+                    }
+                }
+            }
+            return defineClass(origName, clBuf, 0, clBuf.length, new CodeSource(codeSourceUrl, (Certificate[]) null));
+        }
+
+        URL findResource(String name) {
+            URL resURL = targetURL(url, name);
+            if (resURL != null) {
+                try {
+                    URLConnection uc = resURL.openConnection();
+                    uc.getInputStream().close();
+                    // HTTP can return a stream on a non-existent file
+                    // So check for the return code;
+                    if (!resURL.getProtocol().equals("http")) { //$NON-NLS-1$
+                        return resURL;
+                    }
+                    int code;
+                    if ((code = ((HttpURLConnection) uc).getResponseCode()) >= 200
+                            && code < 300) {
+                        return resURL;
+                    }
+                } catch (SecurityException e) {
+                    return null;
+                } catch (IOException e) {
+                    return null;
+                }
+            }
+            return null;
+        }
+
+        URL targetURL(URL base, String name) {
+            try {
+                String file = base.getFile() + URIEncoderDecoder.quoteIllegal(name,
+                        "/@" + URI.someLegal);
+
+                return new URL(base.getProtocol(), base.getHost(), base.getPort(),
+                        file, null);
+            } catch (UnsupportedEncodingException e) {
+                return null;
+            } catch (MalformedURLException e) {
+                return null;
+            }
+        }
+
+    }
+
+    class URLJarHandler extends URLHandler {
+        final JarFile jf;
+        final String prefixName;
+        final IndexFile index;
+        final Map<URL, URLHandler> subHandlers = new HashMap<URL, URLHandler>();
+
+        public URLJarHandler(URL url, URL jarURL, JarFile jf, String prefixName) {
+            super(url);
+            this.jf = jf;
+            this.prefixName = prefixName;
+            this.codeSourceUrl = jarURL;
+            final JarEntry je = jf.getJarEntry("META-INF/INDEX.LIST"); //$NON-NLS-1$
+            this.index = (je == null ? null : IndexFile.readIndexFile(jf, je, url));
+        }
+
+        public URLJarHandler(URL url, URL jarURL, JarFile jf, String prefixName, IndexFile index) {
+            super(url);
+            this.jf = jf;
+            this.prefixName = prefixName;
+            this.index = index;
+            this.codeSourceUrl = jarURL;
+        }
+
+        IndexFile getIndex() {
+            return index;
+        }
+
+        @Override
+        void findResources(String name, ArrayList<URL> resources) {
+            URL res = findResourceInOwn(name);
+            if (res != null && !resources.contains(res)) {
+                resources.add(res);
+            }
+            if (index != null) {
+                int pos = name.lastIndexOf("/"); //$NON-NLS-1$
+                // only keep the directory part of the resource
+                // as index.list only keeps track of directories and root files
+                String indexedName = (pos > 0) ? name.substring(0, pos) : name;
+                ArrayList<URL> urls = index.get(indexedName);
+                if (urls != null) {
+                    urls.remove(url);
+                    for (URL url : urls) {
+                        URLHandler h = getSubHandler(url);
+                        if (h != null) {
+                            h.findResources(name, resources);
+                        }
+                    }
+                }
+            }
+
+        }
+
+        @Override
+        Class<?> findClass(String packageName, String name, String origName) {
+            String entryName = prefixName + name;
+            JarEntry entry = jf.getJarEntry(entryName);
+            if (entry != null) {
+                /**
+                 * Avoid recursive load class, especially the class
+                 * is an implementation class of security provider
+                 * and the jar is signed.
+                 */
+                try {
+                    Manifest manifest = jf.getManifest();
+                    return createClass(entry, manifest, packageName, origName);
+                } catch (IOException e) {
+                }
+            }
+            if (index != null) {
+                ArrayList<URL> urls;
+                if (packageName == null) {
+                    urls = index.get(name);
+                } else {
+                    urls = index.get(packageName);
+                }
+                if (urls != null) {
+                    urls.remove(url);
+                    for (URL url : urls) {
+                        URLHandler h = getSubHandler(url);
+                        if (h != null) {
+                            Class<?> res = h.findClass(packageName, name, origName);
+                            if (res != null) {
+                                return res;
+                            }
+                        }
+                    }
+                }
+            }
+            return null;
+        }
+
+        private Class<?> createClass(JarEntry entry, Manifest manifest, String packageName, String origName) {
+            InputStream is = null;
+            byte[] clBuf = null;
+            try {
+                is = jf.getInputStream(entry);
+                clBuf = getBytes(is);
+            } catch (IOException e) {
+                return null;
+            } finally {
+                if (is != null) {
+                    try {
+                        is.close();
+                    } catch (IOException e) {
+                    }
+                }
+            }
+            if (packageName != null) {
+                String packageDotName = packageName.replace('/', '.');
+                Package packageObj = getPackage(packageDotName);
+                if (packageObj == null) {
+                    if (manifest != null) {
+                        definePackage(packageDotName, manifest,
+                                codeSourceUrl);
+                    } else {
+                        definePackage(packageDotName, null, null,
+                                null, null, null, null, null);
+                    }
+                } else {
+                    boolean exception = packageObj.isSealed();
+                    if (manifest != null) {
+                        if (isSealed(manifest, packageName + "/")) {
+                            exception = !packageObj
+                                    .isSealed(codeSourceUrl);
+                        }
+                    }
+                    if (exception) {
+                        throw new SecurityException(Msg
+                                .getString("K0352", packageName)); //$NON-NLS-1$
+                    }
+                }
+            }
+            CodeSource codeS = new CodeSource(codeSourceUrl, entry.getCertificates());
+            return defineClass(origName, clBuf, 0, clBuf.length, codeS);
+        }
+
+        URL findResourceInOwn(String name) {
+            String entryName = prefixName + name;
+            if (jf.getEntry(entryName) != null) {
+                return targetURL(url, name);
+            }
+            return null;
+        }
+
+        @Override
+        URL findResource(String name) {
+            URL res = findResourceInOwn(name);
+            if (res != null) {
+                return res;
+            }
+            if (index != null) {
+                int pos = name.lastIndexOf("/"); //$NON-NLS-1$
+                // only keep the directory part of the resource
+                // as index.list only keeps track of directories and root files
+                String indexedName = (pos > 0) ? name.substring(0, pos) : name;
+                ArrayList<URL> urls = index.get(indexedName);
+                if (urls != null) {
+                    urls.remove(url);
+                    for (URL url : urls) {
+                        URLHandler h = getSubHandler(url);
+                        if (h != null) {
+                            res = h.findResource(name);
+                            if (res != null) {
+                                return res;
+                            }
+                        }
+                    }
+                }
+            }
+            return null;
+        }
+
+        private synchronized URLHandler getSubHandler(URL url) {
+            URLHandler sub = subHandlers.get(url);
+            if (sub != null) {
+                return sub;
+            }
+            String protocol = url.getProtocol();
+            if (protocol.equals("jar")) { //$NON-NLS-1$
+                sub = createURLJarHandler(url);
+            } else if (protocol.equals("file")) { //$NON-NLS-1$
+                sub = createURLSubJarHandler(url);
+            } else {
+                sub = createURLHandler(url);
+            }
+            if (sub != null) {
+                subHandlers.put(url, sub);
+            }
+            return sub;
+        }
+
+        private URLHandler createURLSubJarHandler(URL url) {
+            String prefixName;
+            String file = url.getFile();
+            if (url.getFile().endsWith("!/")) { //$NON-NLS-1$
+                prefixName = "";
+            } else {
+                int sepIdx = file.lastIndexOf("!/"); //$NON-NLS-1$
+                if (sepIdx == -1) {
+                    // Invalid URL, don't look here again
+                    return null;
+                }
+                sepIdx += 2;
+                prefixName = file.substring(sepIdx);
+            }
+            try {
+                URL jarURL = ((JarURLConnection) url
+                        .openConnection()).getJarFileURL();
+                JarURLConnection juc = (JarURLConnection) new URL(
+                        "jar", "", //$NON-NLS-1$ //$NON-NLS-2$
+                        jarURL.toExternalForm() + "!/").openConnection(); //$NON-NLS-1$
+                JarFile jf = juc.getJarFile();
+                URLJarHandler jarH = new URLJarHandler(url, jarURL, jf, prefixName, null);
+                // TODO : to think what we should do with indexes & manifest.class file here
+                return jarH;
+            } catch (IOException e) {
+            }
+            return null;
+        }
+
+    }
+
+    class URLFileHandler extends URLHandler {
+        private String prefix;
+
+        public URLFileHandler(URL url) {
+            super(url);
+            String baseFile = url.getFile();
+            String host = url.getHost();
+            int hostLength = 0;
+            if (host != null) {
+                hostLength = host.length();
+            }
+            StringBuilder buf = new StringBuilder(2 + hostLength
+                    + baseFile.length());
+            if (hostLength > 0) {
+                buf.append("//").append(host); //$NON-NLS-1$
+            }
+            // baseFile always ends with '/'
+            buf.append(baseFile);
+            prefix = buf.toString();
+        }
+
+        @Override
+        Class<?> findClass(String packageName, String name, String origName) {
+            String filename = prefix + name;
+            try {
+                filename = URLDecoder.decode(filename, "UTF-8"); //$NON-NLS-1$
+            } catch (IllegalArgumentException e) {
+                return null;
+            } catch (UnsupportedEncodingException e) {
+                return null;
+            }
+
+            File file = new File(filename);
+            if (file.exists()) {
+                try {
+                    InputStream is = new FileInputStream(file);
+                    return createClass(is, packageName, origName);
+                } catch (FileNotFoundException e) {
+                }
+            }
+            return null;
+        }
+
+        @Override
+        URL findResource(String name) {
+            int idx = 0;
+            String filename;
+
+            // Do not create a UNC path, i.e. \\host
+            while (idx < name.length() &&
+                   ((name.charAt(idx) == '/') || (name.charAt(idx) == '\\'))) {
+                idx++;
+            }
+
+            if (idx > 0) {
+                name = name.substring(idx);
+            }
+
+            try {
+                filename = URLDecoder.decode(prefix, "UTF-8") + name; //$NON-NLS-1$
+
+                if (new File(filename).exists()) {
+                    return targetURL(url, name);
+                }
+                return null;
+            } catch (IllegalArgumentException e) {
+                return null;
+            } catch (UnsupportedEncodingException e) {
+                // must not happen
+                throw new AssertionError(e);
+            }
+        }
+
+    }
+
+
     /**
      * Constructs a new {@code URLClassLoader} instance. The newly created
      * instance will have the system ClassLoader as its parent. URLs that end
      * with "/" are assumed to be directories, otherwise they are assumed to be
      * JAR files.
-     * 
+     *
      * @param urls
      *            the list of URLs where a specific class or file could be
      *            found.
@@ -145,7 +615,6 @@
      *             if a security manager exists and its {@code
      *             checkCreateClassLoader()} method doesn't allow creation of
      *             new ClassLoaders.
-     * @since Android 1.0
      */
     public URLClassLoader(URL[] urls) {
         this(urls, ClassLoader.getSystemClassLoader(), null);
@@ -155,7 +624,7 @@
      * Constructs a new URLClassLoader instance. The newly created instance will
      * have the system ClassLoader as its parent. URLs that end with "/" are
      * assumed to be directories, otherwise they are assumed to be JAR files.
-     * 
+     *
      * @param urls
      *            the list of URLs where a specific class or file could be
      *            found.
@@ -165,7 +634,6 @@
      *             if a security manager exists and its {@code
      *             checkCreateClassLoader()} method doesn't allow creation of
      *             new class loaders.
-     * @since Android 1.0
      */
     public URLClassLoader(URL[] urls, ClassLoader parent) {
         this(urls, parent, null);
@@ -173,267 +641,81 @@
 
     /**
      * Adds the specified URL to the search list.
-     * 
+     *
      * @param url
      *            the URL which is to add.
-     * @since Android 1.0
      */
     protected void addURL(URL url) {
         try {
-            URL search = createSearchURL(url);
-            urls = addURL(urls, search);
-            orgUrls = addURL(orgUrls, url);
-            synchronized (extensions) {
-                extensions.put(search, null);
-            }
+            originalUrls.add(url);
+            searchList.add(createSearchURL(url));
         } catch (MalformedURLException e) {
         }
     }
 
     /**
-     * Returns an array with the given URL added to the given array.
-     * 
-     * @param urlArray
-     *            {@code java.net.URL[]} the source array
-     * @param url
-     *            {@code java.net.URL} the URL to be added
-     * @return java.net.URL[] an array made of the given array and the new URL
-     */
-    URL[] addURL(URL[] urlArray, URL url) {
-        URL[] newPath = new URL[urlArray.length + 1];
-        System.arraycopy(urlArray, 0, newPath, 0, urlArray.length);
-        newPath[urlArray.length] = url;
-        Hashtable<String, URL[]>[] newIndexes = newHashtableArray(indexes.length + 1);
-        System.arraycopy(indexes, 0, newIndexes, 0, indexes.length);
-        indexes = newIndexes;
-        return newPath;
-    }
-
-    /**
      * Returns all known URLs which point to the specified resource.
-     * 
+     *
      * @param name
      *            the name of the requested resource.
      * @return the enumeration of URLs which point to the specified resource.
      * @throws IOException
      *             if an I/O error occurs while attempting to connect.
-     * @since Android 1.0
      */
     @Override
     public Enumeration<URL> findResources(final String name) throws IOException {
         if (name == null) {
             return null;
         }
-        Vector<URL> result = AccessController.doPrivileged(
-                new PrivilegedAction<Vector<URL>>() {
-                    public Vector<URL> run() {
-                        return findResources(urls, name, new Vector<URL>());
+        ArrayList<URL> result = AccessController.doPrivileged(
+                new PrivilegedAction<ArrayList<URL>>() {
+                    public ArrayList<URL> run() {
+                        ArrayList<URL> results = new ArrayList<URL>();
+                        findResourcesImpl(name, results);
+                        return results;
                     }
                 }, currentContext);
         SecurityManager sm;
         int length = result.size();
         if (length > 0 && (sm = System.getSecurityManager()) != null) {
-            Vector<URL> reduced = new Vector<URL>(length);
+            ArrayList<URL> reduced = new ArrayList<URL>(length);
             for (int i = 0; i < length; i++) {
-                URL url = result.elementAt(i);
+                URL url = result.get(i);
                 try {
                     sm.checkPermission(url.openConnection().getPermission());
-                    reduced.addElement(url);
+                    reduced.add(url);
                 } catch (IOException e) {
                 } catch (SecurityException e) {
                 }
             }
             result = reduced;
         }
-        return result.elements();
+        return Collections.enumeration(result);
     }
 
-    /**
-     * Returns a Vector of URLs among the given ones that contain the specified
-     * resource.
-     * 
-     * @return Vector the enumeration of URLs that contain the specified
-     *         resource.
-     * @param searchURLs
-     *            {@code java.net.URL[]} the array to be searched.
-     * @param name
-     *            {@code java.lang.String} the name of the requested resource.
-     */
-    Vector<URL> findResources(URL[] searchURLs, String name, Vector<URL> result) {
-        boolean findInExtensions = searchURLs == urls;
-        for (int i = 0; i < searchURLs.length; i++) {
-            if (!invalidUrls.contains(searchURLs[i])) {
-                URL[] search = new URL[] { searchURLs[i] };
-                URL res = findResourceImpl(search, name);
-                if (!invalidUrls.contains(search[0])) {
-                    if (res != null && !result.contains(res)) {
-                        result.addElement(res);
-                    }
-                    if (findInExtensions) {
-                        findInExtensions(explore(searchURLs[i], i), name, i,
-                                result, false);
-                    }
-                }
+    void findResourcesImpl(String name, ArrayList<URL> result) {
+        int n = 0;
+        while (true) {
+            URLHandler handler = getHandler(n++);
+            if (handler == null) {
+                break;
             }
+            handler.findResources(name, result);
         }
-        return result;
     }
 
-    /**
-     * Returns an {@code Object[]} containing a class, a URL, and a vector of
-     * URLs, two of which are {@code null}, according to the caller, which is
-     * identified by the {@code int} type.
-     * 
-     * @return Object[] a 3-element array : {Class, URL, Vector}. The non-null
-     *         element contains the resource(s) found, which are searched in in
-     *         {@code indexes[i]}.
-     * @param i
-     *            the index of 'indexes' array to use.
-     * @param name
-     *            the resource to look for : either a resource or a class.
-     * @param resources
-     *            {@code boolean} indicates that a vector of URL should be
-     *            returned as the non {@code null} element in {@code Object[]}.
-     * @param url
-     *            if {@code true} a URL should be returned as the non-null
-     *            element, if {@code false} a class should be returned.
-     */
-    Object findInIndex(int i, String name, Vector<URL> resources, boolean url) {
-        Hashtable<String, URL[]> index = indexes[i];
-        if (index != null) {
-            int pos = name.lastIndexOf("/"); //$NON-NLS-1$
-            // only keep the directory part of the resource
-            // as index.list only keeps track of directories and root files
-            String indexedName = (pos > 0) ? name.substring(0, pos) : name;
-            URL[] jarURLs;
-            if (resources != null) {
-                jarURLs = index.get(indexedName);
-                if (jarURLs != null) {
-                    findResources(jarURLs, name, resources);
-                }
-            } else if (url) {
-                jarURLs = index.get(indexedName);
-                if (jarURLs != null) {
-                    return findResourceImpl(jarURLs, name);
-                }
-            } else {
-                String clsName = name;
-                String partialName = clsName.replace('.', '/');
-                int position;
-                if ((position = partialName.lastIndexOf('/')) != -1) {
-                    String packageName = partialName.substring(0, position);
-                    jarURLs = index.get(packageName);
-                } else {
-                    String className = partialName.substring(0, partialName
-                            .length())
-                            + ".class"; //$NON-NLS-1$
-                    jarURLs = index.get(className);
-                }
-                if (jarURLs != null) {
-                    Class<?> c = findClassImpl(jarURLs, clsName);
-                    // InvalidJarException is thrown when a mapping for a class
-                    // is not valid, i.e. we can't find the class by following
-                    // the mapping.
-                    if (c == null) {
-                        throw new InvalidJarIndexException();
-                    }
-                    return c;
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Returns an {@code Object[]} containing a Class, a URL, and a Vector of
-     * URLs, two of which are {@code null}, according to the caller, which is
-     * identified by the {@code int} type.
-     * 
-     * @return Object[] a 3-element array : {Class, URL, Vector}. The non-null
-     *         element contains the resource(s) found, which are searched in
-     *         newExtensions.
-     * @param newExtensions
-     *            URL[] the URLs to look in for.
-     * @param name
-     *            the resource to look for : either a resource or a class.
-     * @param i
-     *            the index of 'indexes' array to use.
-     * @param resources
-     *            indicates that a Vector of URL should be returned as the
-     *            non-null element in {@code Object[]}.
-     * @param url
-     *            if {@code true} a URL should be returned as the non-null
-     *            element, if {@code false} a class should be returned.
-     */
-    Object findInExtensions(URL[] newExtensions, String name, int i,
-            Vector<URL> resources, boolean url) {
-        if (newExtensions != null) {
-            for (int k = 0; k < newExtensions.length; k++) {
-                if (newExtensions[k] != null) {
-                    URL[] search = new URL[] { newExtensions[k] };
-                    if (resources != null) {
-                        URL res = findResourceImpl(search, name);
-                        if (!invalidUrls.contains(search[0])) { // the URL does
-                            // not exist
-                            if (res != null && !resources.contains(res)) {
-                                resources.addElement(res);
-                            }
-                            findInExtensions(explore(newExtensions[k], i),
-                                    name, i, resources, url);
-                        }
-                    } else {
-                        Object result;
-                        if (url) {
-                            result = findResourceImpl(search, name);
-                        } else {
-                            result = findClassImpl(search, name);
-                        }
-                        if (result != null) {
-                            return result;
-                        }
-                        if (!invalidUrls.contains(search[0])) { // the URL
-                            // exists
-                            result = findInExtensions(explore(newExtensions[k],
-                                    i), name, i, null, url);
-                            if (result != null) {
-                                return result;
-                            }
-                        }
-                    }
-                }
-            }
-        } else {
-            try {
-                return findInIndex(i, name, resources, url);
-            } catch (InvalidJarIndexException ex) {
-                // Ignore misleading/wrong jar index
-                return null;
-            }
-        }
-        return null;
-    }
 
     /**
      * Converts an input stream into a byte array.
-     * 
-     * @return byte[] the byte array
+     *
      * @param is
      *            the input stream
+     * @return byte[] the byte array
      */
-    private static byte[] getBytes(InputStream is, boolean readAvailable)
+    private static byte[] getBytes(InputStream is)
             throws IOException {
-        if (readAvailable) {
-            byte[] buf = new byte[is.available()];
-            is.read(buf, 0, buf.length);
-            is.close();
-            return buf;
-        }
         byte[] buf = new byte[4096];
-        int size = is.available();
-        if (size < 1024) {
-            size = 1024;
-        }
-        ByteArrayOutputStream bos = new ByteArrayOutputStream(size);
+        ByteArrayOutputStream bos = new ByteArrayOutputStream(4096);
         int count;
         while ((count = is.read(buf)) > 0) {
             bos.write(buf, 0, count);
@@ -448,11 +730,10 @@
      * read permission to the file is added to the permission collection.
      * Otherwise, connecting to and accepting connections from the URL is
      * granted.
-     * 
+     *
      * @param codesource
      *            the code source object whose permissions have to be known.
      * @return the list of permissions according to the code source object.
-     * @since Android 1.0
      */
     @Override
     protected PermissionCollection getPermissions(final CodeSource codesource) {
@@ -494,12 +775,11 @@
 
     /**
      * Returns the search list of this {@code URLClassLoader}.
-     * 
+     *
      * @return the list of all known URLs of this instance.
-     * @since Android 1.0
      */
     public URL[] getURLs() {
-        return orgUrls.clone();
+        return originalUrls.toArray(new URL[originalUrls.size()]);
     }
 
     /**
@@ -515,12 +795,11 @@
      * system {@code ClassLoader} as its parent. The method {@code loadClass()}
      * of the new instance will call {@code
      * SecurityManager.checkPackageAccess()} before loading a class.
-     * 
+     *
      * @param urls
      *            the list of URLs that is passed to the new {@code
      *            URLClassloader}.
      * @return the created {@code URLClassLoader} instance.
-     * @since Android 1.0
      */
     public static URLClassLoader newInstance(final URL[] urls) {
         URLClassLoader sub = AccessController
@@ -538,17 +817,16 @@
      * specified {@code ClassLoader} as its parent. The method {@code
      * loadClass()} of the new instance will call the SecurityManager's {@code
      * checkPackageAccess()} before loading a class.
-     * 
+     *
      * @param urls
      *            the list of URLs that is passed to the new URLClassloader.
      * @param parentCl
      *            the parent class loader that is passed to the new
      *            URLClassloader.
      * @return the created {@code URLClassLoader} instance.
-     * @since Android 1.0
      */
     public static URLClassLoader newInstance(final URL[] urls,
-            final ClassLoader parentCl) {
+                                             final ClassLoader parentCl) {
         URLClassLoader sub = AccessController
                 .doPrivileged(new PrivilegedAction<URLClassLoader>() {
                     public URLClassLoader run() {
@@ -565,7 +843,7 @@
      * use the specified factory to create stream handlers. URLs that end with
      * "/" are assumed to be directories, otherwise they are assumed to be JAR
      * files.
-     * 
+     *
      * @param searchUrls
      *            the list of URLs where a specific class or file could be
      *            found.
@@ -578,10 +856,9 @@
      *             if a security manager exists and its {@code
      *             checkCreateClassLoader()} method doesn't allow creation of
      *             new {@code ClassLoader}s.
-     * @since Android 1.0
      */
     public URLClassLoader(URL[] searchUrls, ClassLoader parent,
-            URLStreamHandlerFactory factory) {
+                          URLStreamHandlerFactory factory) {
         super(parent);
         // Required for pre-v1.2 security managers to work
         SecurityManager security = System.getSecurityManager();
@@ -592,33 +869,28 @@
         // capture the context of the thread that creates this URLClassLoader
         currentContext = AccessController.getContext();
         int nbUrls = searchUrls.length;
-        urls = new URL[nbUrls];
-        orgUrls = new URL[nbUrls];
-        // Search each jar for CLASS-PATH attribute in manifest
-        extensions = new HashMap<URL, URL[]>(nbUrls * 2);
+        originalUrls = new ArrayList<URL>(nbUrls);
+        handlerList = new ArrayList<URLHandler>(nbUrls);
+        searchList = Collections.synchronizedList(new ArrayList<URL>(nbUrls));
         for (int i = 0; i < nbUrls; i++) {
+            originalUrls.add(searchUrls[i]);
             try {
-                urls[i] = createSearchURL(searchUrls[i]);
-                extensions.put(urls[i], null);
+                searchList.add(createSearchURL(searchUrls[i]));
             } catch (MalformedURLException e) {
             }
-            orgUrls[i] = searchUrls[i];
         }
-        // Search each jar for META-INF/INDEX.LIST
-        indexes = newHashtableArray(nbUrls);
     }
 
     /**
      * Tries to locate and load the specified class using the known URLs. If the
      * class could be found, a class object representing the loaded class will
      * be returned.
-     * 
-     * @return the class that has been loaded.
+     *
      * @param clsName
      *            the name of the class which has to be found.
+     * @return the class that has been loaded.
      * @throws ClassNotFoundException
      *             if the specified class cannot be loaded.
-     * @since Android 1.0
      */
     @Override
     protected Class<?> findClass(final String clsName)
@@ -626,7 +898,7 @@
         Class<?> cls = AccessController.doPrivileged(
                 new PrivilegedAction<Class<?>>() {
                     public Class<?> run() {
-                        return findClassImpl(urls, clsName);
+                        return findClassImpl(clsName);
                     }
                 }, currentContext);
         if (cls != null) {
@@ -639,7 +911,7 @@
      * Returns an URL that will be checked if it contains the class or resource.
      * If the file component of the URL is not a directory, a Jar URL will be
      * created.
-     * 
+     *
      * @return java.net.URL a test URL
      */
     private URL createSearchURL(URL url) throws MalformedURLException {
@@ -656,19 +928,19 @@
             return new URL("jar", "", //$NON-NLS-1$ //$NON-NLS-2$
                     -1, url.toString() + "!/"); //$NON-NLS-1$
         }
+        // use jar protocol as the stream handler protocol
         return new URL("jar", "", //$NON-NLS-1$ //$NON-NLS-2$
                 -1, url.toString() + "!/", //$NON-NLS-1$
-                factory.createURLStreamHandler(protocol));
+                factory.createURLStreamHandler("jar"));//$NON-NLS-1$
     }
 
     /**
      * Returns an URL referencing the specified resource or {@code null} if the
      * resource could not be found.
-     * 
+     *
      * @param name
      *            the name of the requested resource.
      * @return the URL which points to the given resource.
-     * @since Android 1.0
      */
     @Override
     public URL findResource(final String name) {
@@ -677,7 +949,7 @@
         }
         URL result = AccessController.doPrivileged(new PrivilegedAction<URL>() {
             public URL run() {
-                return findResourceImpl(urls, name);
+                return findResourceImpl(name);
             }
         }, currentContext);
         SecurityManager sm;
@@ -696,161 +968,108 @@
     /**
      * Returns a URL among the given ones referencing the specified resource or
      * null if no resource could be found.
-     * 
+     *
+     * @param resName java.lang.String the name of the requested resource
      * @return URL URL for the resource.
-     * @param searchList
-     *            java.net.URL[] the array to be searched
-     * @param resName
-     *            java.lang.String the name of the requested resource
      */
-    URL findResourceImpl(URL[] searchList, String resName) {
-        boolean findInExtensions = searchList == urls;
-        int i = 0;
-        while (i < searchList.length) {
-            if (searchList[i] == null) {
-                // KA024=One of urls is null
+    URL findResourceImpl(String resName) {
+        int n = 0;
+
+        while (true) {
+            URLHandler handler = getHandler(n++);
+            if (handler == null) {
+                break;
+            }
+            URL res = handler.findResource(resName);
+            if (res != null) {
+                return res;
+            }
+        }
+        return null;
+    }
+
+    URLHandler getHandler(int num) {
+        if (num < handlerList.size()) {
+            return handlerList.get(num);
+        }
+        makeNewHandler();
+        if (num < handlerList.size()) {
+            return handlerList.get(num);
+        }
+        return null;
+    }
+
+    private synchronized void makeNewHandler() {
+        while (!searchList.isEmpty()) {
+            URL nextCandidate = searchList.remove(0);
+            if (nextCandidate == null) {  // KA024=One of urls is null
                 throw new NullPointerException(Msg.getString("KA024")); //$NON-NLS-1$
-            } else if (!invalidUrls.contains(searchList[i])) {
-                JarFile jf = null;
-                try {
-                    URL currentUrl = searchList[i];
-                    String protocol = currentUrl.getProtocol();
-                    
-                    if (protocol.equals("jar")) { //$NON-NLS-1$
-                        jf = resCache.get(currentUrl);
-                        if (jf == null) {
-                            if (invalidUrls.contains(currentUrl)) {
-                                continue;
-                            }
-                            // each jf should be found only once 
-                            // so we do this job in the synchronized block
-                            synchronized (lock) {
-                                // Check the cache again in case another thread 
-                                // updated it while we're waiting on lock
-                                jf = resCache.get(currentUrl);
-                                if (jf == null) {
-                                    if (invalidUrls.contains(currentUrl)) {
-                                        continue;
-                                    }
-                                    /*
-                                     * If the connection for currentUrl or resURL is
-                                     * used, getJarFile() will throw an exception if the
-                                     * entry doesn't exist.
-                                     */
-                                    URL jarURL = ((JarURLConnection) currentUrl
-                                              .openConnection()).getJarFileURL();
-                                    try {
-                                        JarURLConnection juc = (JarURLConnection) new URL(
-                                                "jar", "", //$NON-NLS-1$ //$NON-NLS-2$
-                                                jarURL.toExternalForm() + "!/").openConnection(); //$NON-NLS-1$
-                                        jf = juc.getJarFile();
-                                        resCache.put(currentUrl, jf);
-                                    } catch (IOException e) {
-                                        // Don't look for this jar file again
-                                        invalidUrls.add(searchList[i]);
-                                        throw e;
-                                    }
-                                }
-                            }
-                        }
-                        String entryName;
-                        if (currentUrl.getFile().endsWith("!/")) { //$NON-NLS-1$
-                            entryName = resName;
-                        } else {
-                            String file = currentUrl.getFile();
-                            int sepIdx = file.lastIndexOf("!/"); //$NON-NLS-1$
-                            if (sepIdx == -1) {
-                                // Invalid URL, don't look here again
-                                invalidUrls.add(searchList[i]);
-                                continue;
-                            }
-                            sepIdx += 2;
-                            entryName = new StringBuffer(file.length() - sepIdx
-                                    + resName.length()).append(
-                                    file.substring(sepIdx)).append(resName)
-                                    .toString();
-                        }
-                        if (jf.getEntry(entryName) != null) {
-                            return targetURL(currentUrl, resName);
-                        }
-                    } else if (protocol.equals("file")) { //$NON-NLS-1$
-                        String baseFile = currentUrl.getFile();
-                        String host = currentUrl.getHost();
-                        int hostLength = 0;
-                        if (host != null) {
-                            hostLength = host.length();
-                        }
-                        StringBuffer buf = new StringBuffer(2 + hostLength
-                                + baseFile.length() + resName.length());
-                        if (hostLength > 0) {
-                            buf.append("//").append(host); //$NON-NLS-1$
-                        }
-                        // baseFile always ends with '/'
-                        buf.append(baseFile);
-                        String fixedResName = resName;
-                        // Do not create a UNC path, i.e. \\host
-                        while (fixedResName.startsWith("/") //$NON-NLS-1$
-                                || fixedResName.startsWith("\\")) { //$NON-NLS-1$
-                            fixedResName = fixedResName.substring(1);
-                        }
-                        buf.append(fixedResName);
-
-                        String filename = buf.toString();
-                        
-                        try {
-                            filename = URLDecoder.decode(filename, "UTF-8"); //$NON-NLS-1$
-                        } catch (IllegalArgumentException e) {
-                            return null;
-                        }
-
-                        if (new File(filename).exists()) {
-                            return targetURL(currentUrl, fixedResName);
-                        }
-                    } else {
-                        URL resURL = targetURL(currentUrl, resName);
-                        URLConnection uc = resURL.openConnection();
-                        try {
-                            uc.getInputStream().close();
-                        } catch (SecurityException e) {
-                            return null;
-                        }
-                        // HTTP can return a stream on a non-existent file
-                        // So check for the return code;
-                        if (!resURL.getProtocol().equals("http")) { //$NON-NLS-1$
-                            return resURL;
-                        }
-                        int code;
-                        if ((code = ((HttpURLConnection) uc).getResponseCode()) >= 200
-                                && code < 300) {
-                            return resURL;
-                        }
-                    }
-                } catch (MalformedURLException e) {
-                    // Keep iterating through the URL list
-                } catch (IOException e) {
-                } catch (SecurityException e) {
+            }
+            if (!handlerMap.containsKey(nextCandidate)) {
+                URLHandler result;
+                String protocol = nextCandidate.getProtocol();
+                if (protocol.equals("jar")) { //$NON-NLS-1$
+                    result = createURLJarHandler(nextCandidate);
+                } else if (protocol.equals("file")) { //$NON-NLS-1$
+                    result = createURLFileHandler(nextCandidate);
+                } else {
+                    result = createURLHandler(nextCandidate);
                 }
-                if ((jf != null) && findInExtensions) {
-                    if (indexes[i] != null) {
-                        try {
-                            URL result = (URL) findInIndex(i, resName, null,
-                                    true);
-                            if (result != null) {
-                                return result;
-                            }
-                        } catch (InvalidJarIndexException ex) {
-                            // Ignore invalid/misleading JAR index file
-                        }
-                    } else {
-                        URL result = (URL) findInExtensions(explore(
-                                searchList[i], i), resName, i, null, true);
-                        if (result != null) {
-                            return result;
-                        }
-                    }
+                if (result != null) {
+                    handlerMap.put(nextCandidate, result);
+                    handlerList.add(result);
+                    return;
                 }
             }
-            ++i;
+        }
+    }
+
+    private URLHandler createURLHandler(URL url) {
+        return new URLHandler(url);
+    }
+
+    private URLHandler createURLFileHandler(URL url) {
+        return new URLFileHandler(url);
+    }
+
+    private URLHandler createURLJarHandler(URL url) {
+        String prefixName;
+        String file = url.getFile();
+        if (url.getFile().endsWith("!/")) { //$NON-NLS-1$
+            prefixName = "";
+        } else {
+            int sepIdx = file.lastIndexOf("!/"); //$NON-NLS-1$
+            if (sepIdx == -1) {
+                // Invalid URL, don't look here again
+                return null;
+            }
+            sepIdx += 2;
+            prefixName = file.substring(sepIdx);
+        }
+        try {
+            URL jarURL = ((JarURLConnection) url
+                    .openConnection()).getJarFileURL();
+            JarURLConnection juc = (JarURLConnection) new URL(
+                    "jar", "", //$NON-NLS-1$ //$NON-NLS-2$
+                    jarURL.toExternalForm() + "!/").openConnection(); //$NON-NLS-1$
+            JarFile jf = juc.getJarFile();
+            URLJarHandler jarH = new URLJarHandler(url, jarURL, jf, prefixName);
+
+            if (jarH.getIndex() == null) {
+                try {
+                    Manifest manifest = jf.getManifest();
+                    if (manifest != null) {
+                        String classpath = manifest.getMainAttributes().getValue(
+                                Attributes.Name.CLASS_PATH);
+                        if (classpath != null) {
+                            searchList.addAll(0, getInternalURLs(url, classpath));
+                        }
+                    }
+                } catch (IOException e) {
+                }
+            }
+            return jarH;
+        } catch (IOException e) {
         }
         return null;
     }
@@ -858,7 +1077,7 @@
     /**
      * Defines a new package using the information extracted from the specified
      * manifest.
-     * 
+     *
      * @param packageName
      *            the name of the new package.
      * @param manifest
@@ -869,10 +1088,9 @@
      * @return the created package.
      * @throws IllegalArgumentException
      *             if a package with the given name already exists.
-     * @since Android 1.0
      */
     protected Package definePackage(String packageName, Manifest manifest,
-            URL url) throws IllegalArgumentException {
+                                    URL url) throws IllegalArgumentException {
         Attributes mainAttributes = manifest.getMainAttributes();
         String dirName = packageName.replace('.', '/') + "/"; //$NON-NLS-1$
         Attributes packageAttributes = manifest.getAttributes(dirName);
@@ -921,7 +1139,7 @@
         return definePackage(packageName, specificationTitle,
                 specificationVersion, specificationVendor, implementationTitle,
                 implementationVersion, implementationVendor, isSealed(manifest,
-                        dirName) ? url : null);
+                dirName) ? url : null);
     }
 
     private boolean isSealed(Manifest manifest, String dirName) {
@@ -940,19 +1158,18 @@
 
     /**
      * returns URLs referenced in the string classpath.
-     * 
+     *
      * @param root
      *            the jar URL that classpath is related to
      * @param classpath
      *            the relative URLs separated by spaces
-     * 
      * @return URL[] the URLs contained in the string classpath.
      */
-    private URL[] getInternalURLs(URL root, String classpath) {
+    private ArrayList<URL> getInternalURLs(URL root, String classpath) {
         // Class-path attribute is composed of space-separated values.
         StringTokenizer tokenizer = new java.util.StringTokenizer(classpath);
-        Vector<URL> addedURLs = new Vector<URL>();
-        String file = root.getFile();        
+        ArrayList<URL> addedURLs = new ArrayList<URL>();
+        String file = root.getFile();
         int jarIndex = file.lastIndexOf("!/") - 1; //$NON-NLS-1$
         int index = file.lastIndexOf("/", jarIndex) + 1; //$NON-NLS-1$
         if (index == 0) {
@@ -967,383 +1184,38 @@
             String element = tokenizer.nextToken();
             if (!element.equals("")) { //$NON-NLS-1$
                 try {
-                    URL newURL = new URL(protocol, host, port, file + element
-                            + "!/"); //$NON-NLS-1$
-                    synchronized (extensions) {
-                        if (!extensions.containsKey(newURL)) {
-                            extensions.put(newURL, null);
-                            addedURLs.add(newURL);
-                        }
-                    }
+                    // Take absolute path case into consideration
+                    URL url = new URL(new URL(file), element);
+                    addedURLs.add(createSearchURL(url));
                 } catch (MalformedURLException e) {
                     // Nothing is added
                 }
             }
         }
-        URL[] newURLs = addedURLs.toArray(new URL[] {});
-        return newURLs;
+        return addedURLs;
     }
 
-    /**
-     * @param in
-     *            InputStream the stream to read lines from
-     * @return List a list of String lines
-     */
-    private List<String> readLines(InputStream in) throws IOException {
-        byte[] buff = new byte[144];
-        List<String> lines = new ArrayList<String>();
-        int pos = 0;
-        int next;
-        while ((next = in.read()) != -1) {
-            if (next == '\n') {
-                lines.add(new String(buff, 0, pos, "UTF8")); //$NON-NLS-1$
-                pos = 0;
-                continue;
-            }
-            if (next == '\r') {
-                lines.add(new String(buff, 0, pos, "UTF8")); //$NON-NLS-1$
-                pos = 0;
-                if ((next = in.read()) == '\n') {
-                    continue;
-                }
-            }
-            if (pos == buff.length) {
-                byte[] newBuf = new byte[buff.length * 2];
-                System.arraycopy(buff, 0, newBuf, 0, buff.length);
-                buff = newBuf;
-            }
-            buff[pos++] = (byte) next;
+    Class<?> findClassImpl(String className) {
+        String partialName = className.replace('.', '/');
+        final String classFileName = new StringBuilder(partialName).append(".class").toString(); //$NON-NLS-1$
+        String packageName = null;
+        int position = partialName.lastIndexOf('/');
+        if ((position = partialName.lastIndexOf('/')) != -1) {
+            packageName = partialName.substring(0, position);
         }
-        if (pos > 0) {
-            lines.add(new String(buff, 0, pos, "UTF8")); //$NON-NLS-1$
-        }
-        return lines;
-    }
-
-    private URL targetURL(URL base, String name) throws MalformedURLException {
-        try {
-            String file = base.getFile() + URIEncoderDecoder.quoteIllegal(name,
-                    "/@" + URI.someLegal);
-
-            return new URL(base.getProtocol(), base.getHost(), base.getPort(),
-                    file, null);
-        } catch (UnsupportedEncodingException e) {
-            MalformedURLException e2 = new MalformedURLException(e.toString());
-            
-            e2.initCause(e);
-            throw e2;
-        }
-        
-    }
-
-    /**
-     * @param searchURLs
-     *            java.net.URL[] the URLs to search in
-     * @param clsName
-     *            java.lang.String the class name to be found
-     * @return Class the class found or null if not found
-     */
-    Class<?> findClassImpl(URL[] searchURLs, String clsName) {
-        boolean readAvailable = false;
-        boolean findInExtensions = searchURLs == urls;
-        final String name = new StringBuffer(clsName.replace('.', '/')).append(
-                ".class").toString(); //$NON-NLS-1$
-        for (int i = 0; i < searchURLs.length; i++) {
-            if (searchURLs[i] == null) {
-                // KA024=One of urls is null
-                throw new NullPointerException(Msg.getString("KA024")); //$NON-NLS-1$
-            } else if (!invalidUrls.contains(searchURLs[i])) {
-                Manifest manifest = null;
-                InputStream is = null;
-                JarEntry entry = null;
-                JarFile jf = null;
-                byte[] clBuf = null;
-                try {
-                    URL thisURL = searchURLs[i];
-                    String protocol = thisURL.getProtocol();
-                    if (protocol.equals("jar")) { //$NON-NLS-1$
-                        jf = resCache.get(thisURL);
-                        if ((jf == null) && (!invalidUrls.contains(thisURL))) {
-                            synchronized (lock) {
-                                // Check the cache again in case another thread updated it 
-                                // updated it while we're waiting on lock
-                                jf = resCache.get(thisURL);
-                                if (jf == null) {
-                                    if (invalidUrls.contains(thisURL)) {
-                                        continue;
-                                    }
-                                    // If the connection for testURL or thisURL is used,
-                                    // getJarFile() will throw an exception if the entry
-                                    // doesn't exist.
-                                    URL jarURL = ((JarURLConnection) thisURL
-                                              .openConnection()).getJarFileURL();
-                                    try {
-                                        JarURLConnection juc = (JarURLConnection) new URL(
-                                                "jar", "", jarURL.toExternalForm() + "!/") //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-                                                .openConnection();
-                                        jf = juc.getJarFile();
-                                        resCache.put(thisURL, jf);
-                                    } catch (IOException e) {
-                                        // Don't look for this jar file again
-                                        invalidUrls.add(searchURLs[i]);
-                                        throw e;
-                                    }
-                                }
-                            }
-                        }
-                        if (thisURL.getFile().endsWith("!/")) { //$NON-NLS-1$
-                            entry = jf.getJarEntry(name);
-                        } else {
-                            String file = thisURL.getFile();
-                            int sepIdx = file.lastIndexOf("!/"); //$NON-NLS-1$
-                            if (sepIdx == -1) {
-                                // Invalid URL, don't look here again
-                                invalidUrls.add(searchURLs[i]);
-                                continue;
-                            }
-                            sepIdx += 2;
-                            String entryName = new StringBuffer(file.length()
-                                    - sepIdx + name.length()).append(
-                                    file.substring(sepIdx)).append(name)
-                                    .toString();
-                            entry = jf.getJarEntry(entryName);
-                        }
-                        if (entry != null) {
-                            readAvailable = true;
-                            is = jf.getInputStream(entry);
-                            /**
-                             * Avoid recursive load class, especially the class
-                             * is an implementation class of security provider
-                             * and the jar is signed.
-                             */
-                            Class loadedClass = findLoadedClass(clsName);
-                            if (null != loadedClass) {
-                                is.close();
-                                return loadedClass;
-                            }
-                            manifest = jf.getManifest();
-                        }
-                    } else if (protocol.equals("file")) { //$NON-NLS-1$
-                        String filename = thisURL.getFile();
-                        String host = thisURL.getHost();
-                        if (host != null && host.length() > 0) {
-                            filename = new StringBuffer(host.length()
-                                    + filename.length() + name.length() + 2)
-                                    .append("//").append(host).append(filename) //$NON-NLS-1$
-                                    .append(name).toString();
-                        } else {
-                            filename = new StringBuffer(filename.length()
-                                    + name.length()).append(filename).append(
-                                    name).toString();
-                        }
-
-                        // Just return null for caller to throw
-                        // ClassNotFoundException.
-                        try {
-                            filename = URLDecoder.decode(filename, "UTF-8"); //$NON-NLS-1$
-                        } catch (IllegalArgumentException e) {
-                            return null;
-                        }
-
-                        File file = new File(filename);
-                        // Don't throw exceptions for speed
-                        if (file.exists()) {
-                            is = new FileInputStream(file);
-                            readAvailable = true;
-                        } else {
-                            continue;
-                        }
-                    } else {
-                        is = targetURL(thisURL, name).openStream();
-                    }
-                } catch (MalformedURLException e) {
-                    // Keep iterating through the URL list
-                } catch (IOException e) {
-                }
-                if (is != null) {
-                    URL codeSourceURL = null;
-                    Certificate[] certificates = null;
-                    CodeSource codeS = null;
-                    try {
-                        codeSourceURL = findInExtensions ? orgUrls[i]
-                                : ((JarURLConnection) searchURLs[i]
-                                        .openConnection()).getJarFileURL();
-                    } catch (IOException e) {
-                        codeSourceURL = searchURLs[i];
-                    }
-                    if (is != null) {
-                        try {
-                            clBuf = getBytes(is, readAvailable);
-                            is.close();
-                        } catch (IOException e) {
-                            return null;
-                        }
-                    }
-                    if (entry != null) {
-                        certificates = entry.getCertificates();
-                    }
-                    // Use the original URL, not the possible jar URL
-                    codeS = new CodeSource(codeSourceURL, certificates);
-                    int dotIndex = clsName.lastIndexOf("."); //$NON-NLS-1$
-                    if (dotIndex != -1) {
-                        String packageName = clsName.substring(0, dotIndex);
-                        synchronized (this) {
-                            Package packageObj = getPackage(packageName);
-                            if (packageObj == null) {
-                                if (manifest != null) {
-                                    definePackage(packageName, manifest,
-                                            codeSourceURL);
-                                } else {
-                                    definePackage(packageName, null, null,
-                                            null, null, null, null, null);
-                                }
-                            } else {
-                                boolean exception = false;
-                                if (manifest != null) {
-                                    String dirName = packageName.replace('.',
-                                            '/')
-                                            + "/"; //$NON-NLS-1$
-                                    if (isSealed(manifest, dirName)) {
-                                        exception = !packageObj
-                                                .isSealed(codeSourceURL);
-                                    }
-                                } else {
-                                    exception = packageObj.isSealed();
-                                }
-                                if (exception) {
-                                    throw new SecurityException(Msg
-                                            .getString("K004c")); //$NON-NLS-1$
-                                }
-                            }
-                        }
-                    }
-                    return defineClass(clsName, clBuf, 0, clBuf.length, codeS);
-                }
-                if ((jf != null) && findInExtensions) {
-                    if (indexes[i] != null) {
-                        try {
-                            Class<?> c = (Class<?>) findInIndex(i, clsName,
-                                    null, false);
-                            if (c != null) {
-                                return c;
-                            }
-                        } catch (InvalidJarIndexException ex) {
-                            // Ignore misleading/wrong jar index
-                        }
-                    } else {
-                        Class<?> c = (Class<?>) findInExtensions(explore(
-                                searchURLs[i], i), clsName, i, null, false);
-                        if (c != null) {
-                            return c;
-                        }
-                    }
-                }
+        int n = 0;
+        while (true) {
+            URLHandler handler = getHandler(n++);
+            if (handler == null) {
+                break;
+            }
+            Class<?> res = handler.findClass(packageName, classFileName, className);
+            if (res != null) {
+                return res;
             }
         }
         return null;
+
     }
 
-    /**
-     * @param url
-     *            URL the URL to explore
-     * @param indexNumber
-     *            int the index in extensions to consider
-     * 
-     * @return URL[] the URLs of bundled extensions that have been found (i.e.
-     *         the URL of jar files in the class-path attribute), or null if
-     *         none. if an INDEX.LIST has been found, an empty array is returned
-     */
-    URL[] explore(URL url, int indexNumber) {
-        URL[] internal;
-        synchronized (extensions) {
-            internal = extensions.get(url);
-        }
-        if (internal != null) {
-            return internal;
-        }
-        if (indexes[indexNumber] != null) {
-            return null;
-        }
-
-        if (!url.getProtocol().equals("jar")) { //$NON-NLS-1$
-            return null;
-        }
-
-        JarFile jf = resCache.get(url);
-        // Add mappings from INDEX.LIST
-        ZipEntry ze = jf.getEntry("META-INF/INDEX.LIST"); //$NON-NLS-1$
-        if (ze != null) {
-            if (url.equals(urls[indexNumber])) {
-                try {
-                    Hashtable<String, URL[]> index = new Hashtable<String, URL[]>(
-                            15);
-                    InputStream indexIS = jf.getInputStream(ze);
-                    List<String> lines = readLines(indexIS);
-                    indexIS.close();
-                    ListIterator<String> iterator = lines.listIterator();
-                    // Ignore the 2 first lines (index version)
-                    iterator.next();
-                    iterator.next();
-                    // Add mappings from resource to jar file
-                    URL fileURL = ((JarURLConnection) url.openConnection())
-                            .getJarFileURL();
-                    String file = fileURL.getFile();
-                    String parentFile = new File(file).getParent();
-                    parentFile = parentFile.replace(File.separatorChar, '/');
-                    if (parentFile.charAt(0) != '/') {
-                        parentFile = "/" + parentFile; //$NON-NLS-1$
-                    }
-                    URL parentURL = new URL(fileURL.getProtocol(), fileURL
-                            .getHost(), fileURL.getPort(), parentFile);
-                    while (iterator.hasNext()) {
-                        URL jar = new URL("jar:" //$NON-NLS-1$
-                                + parentURL.toExternalForm() + "/" //$NON-NLS-1$
-                                + iterator.next() + "!/"); //$NON-NLS-1$
-                        String resource = null;
-                        while (iterator.hasNext()
-                                && !(resource = iterator.next()).equals("")) { //$NON-NLS-1$
-                            if (index.containsKey(resource)) {
-                                URL[] jars = index.get(resource);
-                                URL[] newJars = new URL[jars.length + 1];
-                                System.arraycopy(jars, 0, newJars, 0,
-                                        jars.length);
-                                newJars[jars.length] = jar;
-                                index.put(resource, newJars);
-                            } else {
-                                URL[] jars = { jar };
-                                index.put(resource, jars);
-                            }
-                        }
-                    }
-                    indexes[indexNumber] = index;
-                } catch (MalformedURLException e) {
-                    // Ignore this jar's index
-                } catch (IOException e) {
-                    // Ignore this jar's index
-                }
-            }
-            return null;
-        }
-
-        // Returns URLs referenced by the class-path attribute.
-        Manifest manifest = null;
-        try {
-            manifest = jf.getManifest();
-        } catch (IOException e) {
-        }
-        String classpath = null;
-        if (manifest != null) {
-            classpath = manifest.getMainAttributes().getValue(
-                    Attributes.Name.CLASS_PATH);
-        }
-        synchronized (extensions) {
-            internal = extensions.get(url);
-            if (internal == null) {
-                internal = classpath != null ? getInternalURLs(url, classpath)
-                        : NO_PATH;
-                extensions.put(url, internal);
-            }
-        }
-        return internal;
-    }
 }
diff --git a/libcore/luni/src/main/java/java/net/URLConnection.java b/libcore/luni/src/main/java/java/net/URLConnection.java
index 6c1a192..573a2d2 100644
--- a/libcore/luni/src/main/java/java/net/URLConnection.java
+++ b/libcore/luni/src/main/java/java/net/URLConnection.java
@@ -23,6 +23,7 @@
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.Collections;
+import java.util.Date;
 import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
@@ -31,22 +32,17 @@
 import org.apache.harmony.luni.internal.net.www.MimeTable;
 import org.apache.harmony.luni.util.Msg;
 import org.apache.harmony.luni.util.PriviAction;
-import org.apache.harmony.luni.util.Util;
 
 /**
  * Concrete implementations of the abstract {@code URLConnection} class provide
  * a communication link to a URL for exchanging data with a specific protocol
  * type. A {@code URLConnection} can only be set up after the instantiation but
  * before connecting to the remote resource.
- * 
- * @since Android 1.0
  */
 public abstract class URLConnection {
 
     /**
      * The URL which represents the remote target of this {@code URLConnection}.
-     * 
-     * @since Android 1.0
      */
     protected URL url;
 
@@ -63,16 +59,12 @@
     /**
      * The data must be modified more recently than this time in milliseconds
      * since January 1, 1970, GMT to be transmitted.
-     * 
-     * @since Android 1.0
      */
     protected long ifModifiedSince;
 
     /**
      * Specifies whether the using of caches is enabled or the data has to be
      * recent for every request.
-     * 
-     * @since Android 1.0
      */
     protected boolean useCaches = defaultUseCaches;
 
@@ -80,30 +72,22 @@
      * Specifies whether this {@code URLConnection} is already connected to the
      * remote resource. If this field is set to {@code true} the flags for
      * setting up the connection are not changeable anymore.
-     * 
-     * @since Android 1.0
      */
     protected boolean connected;
 
     /**
      * Specifies whether this {@code URLConnection} allows sending data.
-     * 
-     * @since Android 1.0
      */
     protected boolean doOutput;
 
     /**
      * Specifies whether this {@code URLConnection} allows receiving data.
-     * 
-     * @since Android 1.0
      */
     protected boolean doInput = true;
 
     /**
      * Specifies whether this {@code URLConnection} allows user interaction as
      * it is needed for authentication purposes.
-     * 
-     * @since Android 1.0
      */
     protected boolean allowUserInteraction = defaultAllowUserInteraction;
 
@@ -127,11 +111,10 @@
     /**
      * Creates a new {@code URLConnection} instance pointing to the resource
      * specified by the given URL.
-     * 
+     *
      * @param url
      *            the URL which represents the resource this {@code
      *            URLConnection} will point to.
-     * @since Android 1.0
      */
     protected URLConnection(URL url) {
         this.url = url;
@@ -140,20 +123,18 @@
     /**
      * Establishes the connection to the earlier configured resource. The
      * connection can only be set up before this method has been called.
-     * 
+     *
      * @throws IOException
      *             if an error occurs while connecting to the resource.
-     * @since Android 1.0
      */
     public abstract void connect() throws IOException;
 
     /**
      * Gets the option value which indicates whether user interaction is allowed
      * on this {@code URLConnection}.
-     * 
+     *
      * @return the value of the option {@code allowUserInteraction}.
      * @see #allowUserInteraction
-     * @since Android 1.0
      */
     public boolean getAllowUserInteraction() {
         return allowUserInteraction;
@@ -166,11 +147,10 @@
      * header field "Content-Type". If none is found it will guess the content
      * type from the filename extension. If that fails the stream itself will be
      * used to guess the content type.
-     * 
+     *
      * @return the content representing object.
      * @throws IOException
      *             if an error occurs obtaining the content.
-     * @since Android 1.0
      */
     public Object getContent() throws java.io.IOException {
         if (!connected) {
@@ -196,14 +176,13 @@
      * type from the filename extension. If that fails the stream itself will be
      * used to guess the content type. The content type must match with one of
      * the list {@code types}.
-     * 
+     *
      * @param types
      *            the list of acceptable content types.
      * @return the content representing object or {@code null} if the content
      *         type does not match with one of the specified types.
      * @throws IOException
      *             if an error occurs obtaining the content.
-     * @since Android 1.0
      */
     // Param is not generic in spec
     @SuppressWarnings("unchecked")
@@ -226,9 +205,8 @@
     /**
      * Gets the content encoding type specified by the response header field
      * {@code content-encoding} or {@code null} if this field is not set.
-     * 
+     *
      * @return the value of the response header field {@code content-encoding}.
-     * @since Android 1.0
      */
     public String getContentEncoding() {
         return getHeaderField("Content-Encoding"); //$NON-NLS-1$
@@ -237,7 +215,7 @@
     /**
      * Returns the specific ContentHandler that will handle the type {@code
      * contentType}.
-     * 
+     *
      * @param type
      *            The type that needs to be handled
      * @return An instance of the Content Handler
@@ -286,7 +264,8 @@
                     .doPrivileged(new PrivilegedAction<Object>() {
                         public Object run() {
                             try {
-                                String className = "org.apache.harmony.luni.internal.net.www.content." //$NON-NLS-1$
+                                // Try looking up AWT image content handlers
+                                String className = "org.apache.harmony.awt.www.content." //$NON-NLS-1$
                                         + typeString;
                                 return Class.forName(className).newInstance();
                             } catch (ClassNotFoundException e) {
@@ -312,9 +291,8 @@
     /**
      * Gets the content length in bytes specified by the response header field
      * {@code content-length} or {@code -1} if this field is not set.
-     * 
+     *
      * @return the value of the response header field {@code content-length}.
-     * @since Android 1.0
      */
     public int getContentLength() {
         return getHeaderFieldInt("Content-Length", -1); //$NON-NLS-1$
@@ -323,9 +301,8 @@
     /**
      * Gets the MIME-type of the content specified by the response header field
      * {@code content-type} or {@code null} if type is unknown.
-     * 
+     *
      * @return the value of the response header field {@code content-type}.
-     * @since Android 1.0
      */
     public String getContentType() {
         return getHeaderField("Content-Type"); //$NON-NLS-1$
@@ -335,9 +312,8 @@
      * Gets the timestamp when this response has been sent as a date in
      * milliseconds since January 1, 1970 GMT or {@code 0} if this timestamp is
      * unknown.
-     * 
+     *
      * @return the sending timestamp of the current response.
-     * @since Android 1.0
      */
     public long getDate() {
         return getHeaderFieldDate("Date", 0); //$NON-NLS-1$
@@ -345,11 +321,10 @@
 
     /**
      * Gets the default setting whether this connection allows user interaction.
-     * 
+     *
      * @return the value of the default setting {@code
      *         defaultAllowUserInteraction}.
      * @see #allowUserInteraction
-     * @since Android 1.0
      */
     public static boolean getDefaultAllowUserInteraction() {
         return defaultAllowUserInteraction;
@@ -359,12 +334,11 @@
      * Gets the default value for the specified request {@code field} or {@code
      * null} if the field could not be found. The current implementation of this
      * method returns always {@code null}.
-     * 
+     *
      * @param field
      *            the request field whose default value shall be returned.
      * @return the default value for the given field.
      * @deprecated Use {@link #getRequestProperty}
-     * @since Android 1.0
      */
     @Deprecated
     public static String getDefaultRequestProperty(String field) {
@@ -373,10 +347,9 @@
 
     /**
      * Gets the default setting whether this connection allows using caches.
-     * 
+     *
      * @return the value of the default setting {@code defaultUseCaches}.
      * @see #useCaches
-     * @since Android 1.0
      */
     public boolean getDefaultUseCaches() {
         return defaultUseCaches;
@@ -385,11 +358,10 @@
     /**
      * Gets the value of the option {@code doInput} which specifies whether this
      * connection allows to receive data.
-     * 
+     *
      * @return {@code true} if this connection allows input, {@code false}
      *         otherwise.
      * @see #doInput
-     * @since Android 1.0
      */
     public boolean getDoInput() {
         return doInput;
@@ -398,11 +370,10 @@
     /**
      * Gets the value of the option {@code doOutput} which specifies whether
      * this connection allows to send data.
-     * 
+     *
      * @return {@code true} if this connection allows output, {@code false}
      *         otherwise.
      * @see #doOutput
-     * @since Android 1.0
      */
     public boolean getDoOutput() {
         return doOutput;
@@ -411,9 +382,8 @@
     /**
      * Gets the timestamp when this response will be expired in milliseconds
      * since January 1, 1970 GMT or {@code 0} if this timestamp is unknown.
-     * 
+     *
      * @return the value of the response header field {@code expires}.
-     * @since Android 1.0
      */
     public long getExpiration() {
         return getHeaderFieldDate("Expires", 0); //$NON-NLS-1$
@@ -422,9 +392,8 @@
     /**
      * Gets the table which is used by all {@code URLConnection} instances to
      * determine the MIME-type according to a file extension.
-     * 
+     *
      * @return the file name map to determine the MIME-type.
-     * @since Android 1.0
      */
     public static FileNameMap getFileNameMap() {
         // Must use lazy initialization or there is a bootstrap problem
@@ -440,11 +409,10 @@
      * Gets the header value at the field position {@code pos} or {@code null}
      * if the header has fewer than {@code pos} fields. The current
      * implementation of this method returns always {@code null}.
-     * 
+     *
      * @param pos
      *            the field position of the response header.
      * @return the value of the field at position {@code pos}.
-     * @since Android 1.0
      */
     public String getHeaderField(int pos) {
         return null;
@@ -454,9 +422,9 @@
      * Gets an unchangeable map of the response-header fields and values. The
      * response-header field names are the key values of the map. The map values
      * are lists of header field values associated with a particular key name.
-     * 
+     *
      * @return the response-header representing generic map.
-     * @since Android 1.0
+     * @since 1.4
      */
     public Map<String, List<String>> getHeaderFields() {
         return Collections.emptyMap();
@@ -466,9 +434,9 @@
      * Gets an unchangeable map of general request properties used by this
      * connection. The request property names are the key values of the map. The
      * map values are lists of property values of the corresponding key name.
-     * 
+     *
      * @return the request-property representing generic map.
-     * @since Android 1.0
+     * @since 1.4
      */
     public Map<String, List<String>> getRequestProperties() {
         if (connected) {
@@ -480,7 +448,7 @@
     /**
      * Adds the given property to the request header. Existing properties with
      * the same name will not be overwritten by this method.
-     * 
+     *
      * @param field
      *            the request property field name to add.
      * @param newValue
@@ -489,7 +457,7 @@
      *             if the connection has been already established.
      * @throws NullPointerException
      *             if the property name is {@code null}.
-     * @since Android 1.0
+     * @since 1.4
      */
     public void addRequestProperty(String field, String newValue) {
         if (connected) {
@@ -504,11 +472,10 @@
      * Gets the value of the header field specified by {@code key} or {@code
      * null} if there is no field with this name. The current implementation of
      * this method returns always {@code null}.
-     * 
+     *
      * @param key
      *            the name of the header field.
      * @return the value of the header field.
-     * @since Android 1.0
      */
     public String getHeaderField(String key) {
         return null;
@@ -518,34 +485,37 @@
      * Gets the specified header value as a date in milliseconds since January
      * 1, 1970 GMT. Returns the {@code defaultValue} if no such header field
      * could be found.
-     * 
+     *
      * @param field
      *            the header field name whose value is needed.
      * @param defaultValue
      *            the default value if no field has been found.
      * @return the value of the specified header field as a date in
      *         milliseconds.
-     * @since Android 1.0
      */
+    @SuppressWarnings("deprecation")
     public long getHeaderFieldDate(String field, long defaultValue) {
         String date = getHeaderField(field);
         if (date == null) {
             return defaultValue;
         }
-        return Util.parseDate(date);
+        try {
+            return Date.parse(date);
+        } catch (Exception e) {
+            return defaultValue;
+        }
     }
 
     /**
      * Gets the specified header value as a number. Returns the {@code
      * defaultValue} if no such header field could be found or the value could
      * not be parsed as an {@code Integer}.
-     * 
+     *
      * @param field
      *            the header field name whose value is needed.
      * @param defaultValue
      *            the default value if no field has been found.
      * @return the value of the specified header field as a number.
-     * @since Android 1.0
      */
     public int getHeaderFieldInt(String field, int defaultValue) {
         try {
@@ -559,11 +529,10 @@
      * Gets the name of the header field at the given position {@code posn} or
      * {@code null} if there are fewer than {@code posn} fields. The current
      * implementation of this method returns always {@code null}.
-     * 
+     *
      * @param posn
      *            the position of the header field which has to be returned.
      * @return the header field name at the given position.
-     * @since Android 1.0
      */
     public String getHeaderFieldKey(int posn) {
         return null;
@@ -573,10 +542,9 @@
      * Gets the point of time since when the data must be modified to be
      * transmitted. Some protocols transmit data only if it has been modified
      * more recently than a particular time.
-     * 
+     *
      * @return the time in milliseconds since January 1, 1970 GMT.
      * @see #ifModifiedSince
-     * @since Android 1.0
      */
     public long getIfModifiedSince() {
         return ifModifiedSince;
@@ -586,11 +554,10 @@
      * Gets an {@code InputStream} for reading data from the resource pointed by
      * this {@code URLConnection}. It throws an UnknownServiceException by
      * default. This method must be overridden by its subclasses.
-     * 
+     *
      * @return the InputStream to read data from.
      * @throws IOException
      *             if no InputStream could be created.
-     * @since Android 1.0
      */
     public InputStream getInputStream() throws IOException {
         throw new UnknownServiceException(Msg.getString("K004d")); //$NON-NLS-1$
@@ -599,9 +566,8 @@
     /**
      * Gets the value of the response header field {@code last-modified} or
      * {@code 0} if this value is not set.
-     * 
+     *
      * @return the value of the {@code last-modified} header field.
-     * @since Android 1.0
      */
     public long getLastModified() {
         if (lastModified != -1) {
@@ -614,11 +580,10 @@
      * Gets an {@code OutputStream} for writing data to this {@code
      * URLConnection}. It throws an {@code UnknownServiceException} by default.
      * This method must be overridden by its subclasses.
-     * 
+     *
      * @return the OutputStream to write data.
      * @throws IOException
      *             if no OutputStream could be created.
-     * @since Android 1.0
      */
     public OutputStream getOutputStream() throws IOException {
         throw new UnknownServiceException(Msg.getString("K005f")); //$NON-NLS-1$
@@ -631,12 +596,11 @@
      * necessary. By default, this method returns {@code AllPermission}.
      * Subclasses should overwrite this method to return an appropriate
      * permission object.
-     * 
+     *
      * @return the permission object representing the needed permissions to open
      *         this connection.
      * @throws IOException
      *             if an I/O error occurs while creating the permission object.
-     * @since Android 1.0
      */
     public java.security.Permission getPermission() throws IOException {
         return new java.security.AllPermission();
@@ -646,13 +610,12 @@
      * Gets the value of the request header property specified by {code field}
      * or {@code null} if there is no field with this name. The current
      * implementation of this method returns always {@code null}.
-     * 
+     *
      * @param field
      *            the name of the request header property.
      * @return the value of the property.
      * @throws IllegalStateException
      *             if the connection has been already established.
-     * @since Android 1.0
      */
     public String getRequestProperty(String field) {
         if (connected) {
@@ -663,9 +626,8 @@
 
     /**
      * Gets the URL represented by this {@code URLConnection}.
-     * 
+     *
      * @return the URL of this connection.
-     * @since Android 1.0
      */
     public URL getURL() {
         return url;
@@ -674,9 +636,8 @@
     /**
      * Gets the value of the flag which specifies whether this {@code
      * URLConnection} allows to use caches.
-     * 
+     *
      * @return {@code true} if using caches is allowed, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean getUseCaches() {
         return useCaches;
@@ -686,12 +647,11 @@
      * Determines the MIME-type of the given resource {@code url} by resolving
      * the filename extension with the internal FileNameMap. Any fragment
      * identifier is removed before processing.
-     * 
+     *
      * @param url
      *            the URL with the filename to get the MIME type.
      * @return the guessed content type or {@code null} if the type could not be
      *         determined.
-     * @since Android 1.0
      */
     public static String guessContentTypeFromName(String url) {
         return getFileNameMap().getContentTypeFor(url);
@@ -700,7 +660,7 @@
     /**
      * Determines the MIME-type of the resource represented by the input stream
      * {@code is} by reading its first few characters.
-     * 
+     *
      * @param is
      *            the resource representing input stream to determine the
      *            content type.
@@ -708,41 +668,97 @@
      *         determined.
      * @throws IOException
      *             if an I/O error occurs while reading from the input stream.
-     * @since Android 1.0
      */
+    @SuppressWarnings("nls")
     public static String guessContentTypeFromStream(InputStream is)
             throws IOException {
+
         if (!is.markSupported()) {
             return null;
         }
-        is.mark(4);
-        char[] chars = new char[4];
-        for (int i = 0; i < chars.length; i++) {
-            chars[i] = (char) is.read();
-        }
+        // Look ahead up to 64 bytes for the longest encoded header
+        is.mark(64);
+        byte[] bytes = new byte[64];
+        int length = is.read(bytes);
         is.reset();
-        if ((chars[0] == 'P') && (chars[1] == 'K')) {
-            return "application/zip"; //$NON-NLS-1$
+
+        // Check for Unicode BOM encoding indicators
+        String encoding = "ASCII";
+        int start = 0;
+        if (length > 1) {
+            if ((bytes[0] == (byte) 0xFF) && (bytes[1] == (byte) 0xFE)) {
+                encoding = "UTF-16LE";
+                start = 2;
+                length -= length & 1;
+            }
+            if ((bytes[0] == (byte) 0xFE) && (bytes[1] == (byte) 0xFF)) {
+                encoding = "UTF-16BE";
+                start = 2;
+                length -= length & 1;
+            }
+            if (length > 2) {
+                if ((bytes[0] == (byte) 0xEF) && (bytes[1] == (byte) 0xBB)
+                        && (bytes[2] == (byte) 0xBF)) {
+                    encoding = "UTF-8";
+                    start = 3;
+                }
+                if (length > 3) {
+                    if ((bytes[0] == (byte) 0x00) && (bytes[1] == (byte) 0x00)
+                            && (bytes[2] == (byte) 0xFE)
+                            && (bytes[3] == (byte) 0xFF)) {
+                        encoding = "UTF-32BE";
+                        start = 4;
+                        length -= length & 3;
+                    }
+                    if ((bytes[0] == (byte) 0xFF) && (bytes[1] == (byte) 0xFE)
+                            && (bytes[2] == (byte) 0x00)
+                            && (bytes[3] == (byte) 0x00)) {
+                        encoding = "UTF-32LE";
+                        start = 4;
+                        length -= length & 3;
+                    }
+                }
+            }
         }
-        if ((chars[0] == 'G') && (chars[1] == 'I')) {
-            return "image/gif"; //$NON-NLS-1$
+
+        String header = new String(bytes, start, length - start, encoding);
+
+        // Check binary types
+        if (header.startsWith("PK")) {
+            return "application/zip";
         }
-        if (new String(chars).trim().startsWith("<")) { //$NON-NLS-1$
-            return "text/html"; //$NON-NLS-1$
+        if (header.startsWith("GI")) {
+            return "image/gif";
         }
+
+        // Check text types
+        String textHeader = header.trim().toUpperCase();
+        if (textHeader.startsWith("<!DOCTYPE HTML") ||
+                textHeader.startsWith("<HTML") ||
+                textHeader.startsWith("<HEAD") ||
+                textHeader.startsWith("<BODY") ||
+                textHeader.startsWith("<HEAD")) {
+            return "text/html";
+        }
+
+        if (textHeader.startsWith("<?XML")) {
+            return "application/xml";
+        }
+
+        // Give up
         return null;
     }
 
     /**
      * Performs any necessary string parsing on the input string such as
      * converting non-alphanumeric character into underscore.
-     * 
+     *
      * @param typeString
      *            the parsed string
      * @return the string to be parsed
      */
     private String parseTypeString(String typeString) {
-        StringBuffer typeStringBuffer = new StringBuffer(typeString);
+        StringBuilder typeStringBuffer = new StringBuilder(typeString);
         for (int i = 0; i < typeStringBuffer.length(); i++) {
             // if non-alphanumeric, replace it with '_'
             char c = typeStringBuffer.charAt(i);
@@ -757,14 +773,13 @@
      * Sets the flag indicating whether this connection allows user interaction
      * or not. This method can only be called prior to the connection
      * establishment.
-     * 
+     *
      * @param newValue
      *            the value of the flag to be set.
      * @throws IllegalStateException
      *             if this method attempts to change the flag after the
      *             connection has been established.
      * @see #allowUserInteraction
-     * @since Android 1.0
      */
     public void setAllowUserInteraction(boolean newValue) {
         if (connected) {
@@ -777,13 +792,12 @@
      * Sets the internally used content handler factory. The content factory can
      * only be set if it is allowed by the security manager and only once during
      * the lifetime of the application.
-     * 
+     *
      * @param contentFactory
      *            the content factory to be set.
      * @throws Error
      *             if the security manager does not allow to set the content
      *             factory or it has been already set earlier ago.
-     * @since Android 1.0
      */
     public static synchronized void setContentHandlerFactory(
             ContentHandlerFactory contentFactory) {
@@ -801,12 +815,11 @@
      * Sets the default value for the flag indicating whether this connection
      * allows user interaction or not. Existing {@code URLConnection}s are
      * unaffected.
-     * 
+     *
      * @param allows
      *            the default value of the flag to be used for new connections.
      * @see #defaultAllowUserInteraction
      * @see #allowUserInteraction
-     * @since Android 1.0
      */
     public static void setDefaultAllowUserInteraction(boolean allows) {
         defaultAllowUserInteraction = allows;
@@ -816,14 +829,13 @@
      * Sets the default value of the specified request header field. This value
      * will be used for the specific field of every newly created connection.
      * The current implementation of this method does nothing.
-     * 
+     *
      * @param field
      *            the request header field to be set.
      * @param value
      *            the default value to be used.
      * @deprecated Use {@link #setRequestProperty} of an existing {@code
      *             URLConnection} instance.
-     * @since Android 1.0
      */
     @Deprecated
     public static void setDefaultRequestProperty(String field, String value) {
@@ -832,12 +844,11 @@
     /**
      * Sets the default value for the flag indicating whether this connection
      * allows to use caches. Existing {@code URLConnection}s are unaffected.
-     * 
+     *
      * @param newValue
      *            the default value of the flag to be used for new connections.
      * @see #defaultUseCaches
      * @see #useCaches
-     * @since Android 1.0
      */
     public void setDefaultUseCaches(boolean newValue) {
         // BEGIN android-removed
@@ -852,14 +863,13 @@
     /**
      * Sets the flag indicating whether this {@code URLConnection} allows input.
      * It cannot be set after the connection is established.
-     * 
+     *
      * @param newValue
      *            the new value for the flag to be set.
      * @throws IllegalAccessError
      *             if this method attempts to change the value after the
      *             connection has been already established.
      * @see #doInput
-     * @since Android 1.0
      */
     public void setDoInput(boolean newValue) {
         if (connected) {
@@ -871,14 +881,13 @@
     /**
      * Sets the flag indicating whether this {@code URLConnection} allows
      * output. It cannot be set after the connection is established.
-     * 
+     *
      * @param newValue
      *            the new value for the flag to be set.
      * @throws IllegalAccessError
      *             if this method attempts to change the value after the
      *             connection has been already established.
      * @see #doOutput
-     * @since Android 1.0
      */
     public void setDoOutput(boolean newValue) {
         if (connected) {
@@ -890,10 +899,9 @@
     /**
      * Sets the internal map which is used by all {@code URLConnection}
      * instances to determine the MIME-type according to a filename extension.
-     * 
+     *
      * @param map
      *            the MIME table to be set.
-     * @since Android 1.0
      */
     public static void setFileNameMap(FileNameMap map) {
         SecurityManager manager = System.getSecurityManager();
@@ -908,13 +916,12 @@
      * transmitted. Some protocols transmit data only if it has been modified
      * more recently than a particular time. The data will be transmitted
      * regardless of its timestamp if this option is set to {@code 0}.
-     * 
+     *
      * @param newValue
      *            the time in milliseconds since January 1, 1970 GMT.
      * @throws IllegalStateException
      *             if this {@code URLConnection} has already been connected.
      * @see #ifModifiedSince
-     * @since Android 1.0
      */
     public void setIfModifiedSince(long newValue) {
         if (connected) {
@@ -927,7 +934,7 @@
      * Sets the value of the specified request header field. The value will only
      * be used by the current {@code URLConnection} instance. This method can
      * only be called before the connection is established.
-     * 
+     *
      * @param field
      *            the request header field to be set.
      * @param newValue
@@ -936,7 +943,6 @@
      *             if the connection has been already established.
      * @throws NullPointerException
      *             if the parameter {@code field} is {@code null}.
-     * @since Android 1.0
      */
     public void setRequestProperty(String field, String newValue) {
         if (connected) {
@@ -951,14 +957,13 @@
      * Sets the flag indicating whether this connection allows to use caches or
      * not. This method can only be called prior to the connection
      * establishment.
-     * 
+     *
      * @param newValue
      *            the value of the flag to be set.
      * @throws IllegalStateException
      *             if this method attempts to change the flag after the
      *             connection has been established.
      * @see #useCaches
-     * @since Android 1.0
      */
     public void setUseCaches(boolean newValue) {
         if (connected) {
@@ -973,12 +978,11 @@
      * SocketTimeoutException} is thrown if the connection could not be
      * established in this time. Default is {@code 0} which stands for an
      * infinite timeout.
-     * 
+     *
      * @param timeout
      *            the connecting timeout in milliseconds.
      * @throws IllegalArgumentException
      *             if the parameter {@code timeout} is less than zero.
-     * @since Android 1.0
      */
     public void setConnectTimeout(int timeout) {
         if (0 > timeout) {
@@ -989,9 +993,8 @@
 
     /**
      * Gets the configured connecting timeout.
-     * 
+     *
      * @return the connecting timeout value in milliseconds.
-     * @since Android 1.0
      */
     public int getConnectTimeout() {
         return connectTimeout;
@@ -1003,12 +1006,11 @@
      * SocketTimeoutException} is thrown if the connection could not be
      * established in this time. Default is {@code 0} which stands for an
      * infinite timeout.
-     * 
+     *
      * @param timeout
      *            the reading timeout in milliseconds.
      * @throws IllegalArgumentException
      *             if the parameter {@code timeout} is less than zero.
-     * @since Android 1.0
      */
     public void setReadTimeout(int timeout) {
         if (0 > timeout) {
@@ -1020,9 +1022,8 @@
     /**
      * Gets the configured timeout for reading from the input stream of an
      * established connection to the resource.
-     * 
+     *
      * @return the reading timeout value in milliseconds.
-     * @since Android 1.0
      */
     public int getReadTimeout() {
         return readTimeout;
@@ -1031,9 +1032,8 @@
     /**
      * Returns the string representation containing the name of this class and
      * the URL.
-     * 
+     *
      * @return the string representation of this {@code URLConnection} instance.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
diff --git a/libcore/luni/src/main/java/java/net/URLDecoder.java b/libcore/luni/src/main/java/java/net/URLDecoder.java
index d272aa7..fd2753c 100644
--- a/libcore/luni/src/main/java/java/net/URLDecoder.java
+++ b/libcore/luni/src/main/java/java/net/URLDecoder.java
@@ -17,20 +17,23 @@
 
 package java.net;
 
-import java.io.ByteArrayOutputStream;
 import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
 
 import org.apache.harmony.luni.util.Msg;
-import org.apache.harmony.luni.util.Util;
 
 /**
  * This class is used to decode a string which is encoded in the {@code
  * application/x-www-form-urlencoded} MIME content type.
- * 
- * @since Android 1.0
  */
 public class URLDecoder {
 
+    static Charset defaultCharset;
+
     /**
      * Decodes the argument which is assumed to be encoded in the {@code
      * x-www-form-urlencoded} MIME content type.
@@ -39,19 +42,32 @@
      * characters are converted to the equivalent byte value. All other
      * characters are passed through unmodified. For example "A+B+C %24%25" ->
      * "A B C $%".
-     * </p>
-     * 
+     *
      * @param s
      *            the encoded string.
      * @return the decoded clear-text representation of the given string.
      * @deprecated use {@link #decode(String, String)} instead.
-     * @since Android 1.0
      */
     @Deprecated
     public static String decode(String s) {
-        return Util.decode(s, true);
+
+        if (defaultCharset == null) {
+            try {
+                defaultCharset = Charset.forName(
+                        System.getProperty("file.encoding")); //$NON-NLS-1$
+            } catch (IllegalCharsetNameException e) {
+                // Ignored
+            } catch (UnsupportedCharsetException e) {
+                // Ignored
+            }
+
+            if (defaultCharset == null) {
+                defaultCharset = Charset.forName("ISO-8859-1"); //$NON-NLS-1$
+            }
+        }
+        return decode(s, defaultCharset);
     }
-    
+
     /**
      * Decodes the argument which is assumed to be encoded in the {@code
      * x-www-form-urlencoded} MIME content type using the specified encoding
@@ -61,8 +77,7 @@
      * characters are converted to the equivalent byte value. All other
      * characters are passed through unmodified. For example "A+B+C %24%25" ->
      * "A B C $%".
-     * </p>
-     * 
+     *
      * @param s
      *            the encoded string.
      * @param enc
@@ -70,7 +85,6 @@
      * @return the decoded clear-text representation of the given string.
      * @throws UnsupportedEncodingException
      *             if the specified encoding scheme is invalid.
-     * @since Android 1.0
      */
     public static String decode(String s, String enc)
             throws UnsupportedEncodingException {
@@ -81,40 +95,80 @@
 
         // If the given encoding is an empty string throw an exception.
         if (enc.length() == 0) {
-            throw new UnsupportedEncodingException(Msg
-                    .getString("K00a5", "enc")); //$NON-NLS-1$ //$NON-NLS-2$
+            throw new UnsupportedEncodingException(
+                    // K00a5=Invalid parameter - {0}
+                    Msg.getString("K00a5", "enc")); //$NON-NLS-1$ //$NON-NLS-2$
         }
 
-        StringBuffer result = new StringBuffer(s.length());
-        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        if (s.indexOf('%') == -1) {
+            if (s.indexOf('+') == -1)
+                return s;
+            char str[] = s.toCharArray();
+            for (int i = 0; i < str.length; i++) {
+                if (str[i] == '+')
+                    str[i] = ' ';
+            }
+            return new String(str);
+        }
+
+        Charset charset = null;
+        try {
+            charset = Charset.forName(enc);
+        } catch (IllegalCharsetNameException e) {
+            throw (UnsupportedEncodingException) (new UnsupportedEncodingException(
+                    enc).initCause(e));
+        } catch (UnsupportedCharsetException e) {
+            throw (UnsupportedEncodingException) (new UnsupportedEncodingException(
+                    enc).initCause(e));
+        }
+
+        return decode(s, charset);
+    }
+
+    private static String decode(String s, Charset charset) {
+
+        char str_buf[] = new char[s.length()];
+        byte buf[] = new byte[s.length() / 3];
+        int buf_len = 0;
+
         for (int i = 0; i < s.length();) {
             char c = s.charAt(i);
             if (c == '+') {
-                result.append(' ');
+                str_buf[buf_len] = ' ';
             } else if (c == '%') {
-                out.reset();
+
+                int len = 0;
                 do {
                     if (i + 2 >= s.length()) {
-                        throw new IllegalArgumentException(Msg.getString(
-                                "K01fe", i)); //$NON-NLS-1$
+                        throw new IllegalArgumentException(
+                                // K01fe=Incomplete % sequence at\: {0}
+                                Msg.getString("K01fe", i)); //$NON-NLS-1$
                     }
                     int d1 = Character.digit(s.charAt(i + 1), 16);
                     int d2 = Character.digit(s.charAt(i + 2), 16);
                     if (d1 == -1 || d2 == -1) {
-                        throw new IllegalArgumentException(Msg.getString(
-                                "K01ff", //$NON-NLS-1$
-                                s.substring(i, i + 3), String.valueOf(i)));
+                        throw new IllegalArgumentException(
+                                // K01ff=Invalid % sequence ({0}) at\: {1}
+                                Msg.getString(
+                                        "K01ff", //$NON-NLS-1$
+                                        s.substring(i, i + 3),
+                                        String.valueOf(i)));
                     }
-                    out.write((byte) ((d1 << 4) + d2));
+                    buf[len++] = (byte) ((d1 << 4) + d2);
                     i += 3;
                 } while (i < s.length() && s.charAt(i) == '%');
-                result.append(out.toString(enc));
+
+                CharBuffer cb = charset.decode(ByteBuffer.wrap(buf, 0, len));
+                len = cb.length();
+                System.arraycopy(cb.array(), 0, str_buf, buf_len, len);
+                buf_len += len;
                 continue;
             } else {
-                result.append(c);
+                str_buf[buf_len] = c;
             }
             i++;
+            buf_len++;
         }
-        return result.toString();
+        return new String(str_buf, 0, buf_len);
     }
 }
diff --git a/libcore/luni/src/main/java/java/net/URLEncoder.java b/libcore/luni/src/main/java/java/net/URLEncoder.java
index 69f2d37..b764cc7 100644
--- a/libcore/luni/src/main/java/java/net/URLEncoder.java
+++ b/libcore/luni/src/main/java/java/net/URLEncoder.java
@@ -22,8 +22,6 @@
 /**
  * This class is used to encode a string using the format required by
  * {@code application/x-www-form-urlencoded} MIME content type.
- * 
- * @since Android 1.0
  */
 public class URLEncoder {
 
@@ -43,17 +41,15 @@
      * and characters '.', '-', '*', '_' are converted into their hexadecimal
      * value prepended by '%'. For example: '#' -> %23. In addition, spaces are
      * substituted by '+'
-     * </p>
-     * 
+     *
      * @param s
      *            the string to be encoded.
      * @return the encoded string.
      * @deprecated use {@link #encode(String, String)} instead.
-     * @since Android 1.0
      */
     @Deprecated
     public static String encode(String s) {
-        StringBuffer buf = new StringBuffer();
+        StringBuilder buf = new StringBuilder();
         for (int i = 0; i < s.length(); i++) {
             char ch = s.charAt(i);
             if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')
@@ -81,8 +77,7 @@
      * and characters '.', '-', '*', '_' are converted into their hexadecimal
      * value prepended by '%'. For example: '#' -> %23. In addition, spaces are
      * substituted by '+'
-     * </p>
-     * 
+     *
      * @param s
      *            the string to be encoded.
      * @param enc
@@ -90,10 +85,10 @@
      * @return the encoded string.
      * @throws UnsupportedEncodingException
      *             if the specified encoding scheme is invalid.
-     * @since Android 1.0
      */
     public static String encode(String s, String enc)
             throws UnsupportedEncodingException {
+
         if (s == null || enc == null) {
             throw new NullPointerException();
         }
diff --git a/libcore/luni/src/main/java/java/net/URLStreamHandler.java b/libcore/luni/src/main/java/java/net/URLStreamHandler.java
index f05c8bd..54e550b 100644
--- a/libcore/luni/src/main/java/java/net/URLStreamHandler.java
+++ b/libcore/luni/src/main/java/java/net/URLStreamHandler.java
@@ -26,11 +26,8 @@
  * The abstract class {@code URLStreamHandler} is the base for all classes which
  * can handle the communication with a URL object over a particular protocol
  * type.
- * 
- * @since Android 1.0
  */
 public abstract class URLStreamHandler {
-
     /**
      * Establishes a new connection to the resource specified by the URL {@code
      * u}. Since different protocols also have unique ways of connecting, it
@@ -41,7 +38,6 @@
      * @return the opened URLConnection to the specified resource.
      * @throws IOException
      *             if an I/O error occurs during opening the connection.
-     * @since Android 1.0
      */
     protected abstract URLConnection openConnection(URL u) throws IOException;
 
@@ -62,7 +58,6 @@
      *             wrong.
      * @throws UnsupportedOperationException
      *             if the protocol handler doesn't support this method.
-     * @since Android 1.0
      */
     protected URLConnection openConnection(URL u, Proxy proxy)
             throws IOException {
@@ -74,7 +69,7 @@
      * generally have the following format:
      * <p>
      * http://www.company.com/java/file1.java#reference
-     * </p>
+     * <p>
      * The string is parsed in HTTP format. If the protocol has a different URL
      * format this method must be overridden.
      * 
@@ -88,7 +83,6 @@
      *            the string position to stop parsing.
      * @see #toExternalForm
      * @see URL
-     * @since Android 1.0
      */
     protected void parseURL(URL u, String str, int start, int end) {
         // For compatibility, refer to Harmony-2941
@@ -259,7 +253,6 @@
      *            the reference.
      * @deprecated use setURL(URL, String String, int, String, String, String,
      *             String, String) instead.
-     * @since Android 1.0
      */
     @Deprecated
     protected void setURL(URL u, String protocol, String host, int port,
@@ -292,7 +285,6 @@
      *            the query.
      * @param ref
      *            the reference.
-     * @since Android 1.0
      */
     protected void setURL(URL u, String protocol, String host, int port,
             String authority, String userInfo, String file, String query,
@@ -311,11 +303,9 @@
      * @return the clear text representation of the specified URL.
      * @see #parseURL
      * @see URL#toExternalForm()
-     * @since Android 1.0
      */
     protected String toExternalForm(URL url) {
-        StringBuffer answer = new StringBuffer(url.getProtocol().length()
-                + url.getFile().length() + 16);
+        StringBuilder answer = new StringBuilder();
         answer.append(url.getProtocol());
         answer.append(':');
         String authority = url.getAuthority();
@@ -326,8 +316,9 @@
 
         String file = url.getFile();
         String ref = url.getRef();
-        // file is never null
-        answer.append(file);
+        if (file != null) {
+            answer.append(file);
+        }
         if (ref != null) {
             answer.append('#');
             answer.append(ref);
@@ -346,7 +337,6 @@
      *            the second URL to compare.
      * @return {@code true} if the URLs are the same, {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     protected boolean equals(URL url1, URL url2) {
         if (!sameFile(url1, url2)) {
@@ -364,9 +354,8 @@
     /**
      * Returns the default port of the protocol used by the handled URL. The
      * current implementation returns always {@code -1}.
-     * 
+     *
      * @return the appropriate default port number of the protocol.
-     * @since Android 1.0
      */
     protected int getDefaultPort() {
         return -1;
@@ -374,11 +363,10 @@
 
     /**
      * Returns the host address of the given URL.
-     * 
+     *
      * @param url
      *            the URL object where to read the host address from.
      * @return the host address of the specified URL.
-     * @since Android 1.0
      */
     protected InetAddress getHostAddress(URL url) {
         try {
@@ -398,7 +386,6 @@
      * @param url
      *            the URL to determine the hashcode.
      * @return the hashcode of the given URL.
-     * @since Android 1.0
      */
     protected int hashCode(URL url) {
         return toExternalForm(url).hashCode();
@@ -406,14 +393,13 @@
 
     /**
      * Compares two URL objects whether they refer to the same host.
-     * 
+     *
      * @param url1
      *            the first URL to be compared.
      * @param url2
      *            the second URL to be compared.
      * @return {@code true} if both URLs refer to the same host, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     protected boolean hostsEqual(URL url1, URL url2) {
         String host1 = getHost(url1), host2 = getHost(url2);
@@ -439,7 +425,6 @@
      *            the second URL to be compared.
      * @return {@code true} if both URLs refer to the same file, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     protected boolean sameFile(URL url1, URL url2) {
         String s1 = url1.getProtocol();
diff --git a/libcore/luni/src/main/java/java/net/URLStreamHandlerFactory.java b/libcore/luni/src/main/java/java/net/URLStreamHandlerFactory.java
index e696410..4e50792 100644
--- a/libcore/luni/src/main/java/java/net/URLStreamHandlerFactory.java
+++ b/libcore/luni/src/main/java/java/net/URLStreamHandlerFactory.java
@@ -20,11 +20,9 @@
 /**
  * Defines a factory which creates an {@code URLStreamHandler} for a specified
  * protocol. It is used by the class {@code URL}.
- * 
- * @since Android 1.0
  */
 public interface URLStreamHandlerFactory {
-    
+
     /**
      * Creates a new {@code URLStreamHandler} instance for the given {@code
      * protocol}.
@@ -32,7 +30,6 @@
      * @param protocol
      *            the protocol for which a handler is needed.
      * @return the created handler.
-     * @since Android 1.0
      */
     URLStreamHandler createURLStreamHandler(String protocol);
 }
diff --git a/libcore/luni/src/main/java/java/net/UnknownHostException.java b/libcore/luni/src/main/java/java/net/UnknownHostException.java
index 9f7c63a..db05558 100644
--- a/libcore/luni/src/main/java/java/net/UnknownHostException.java
+++ b/libcore/luni/src/main/java/java/net/UnknownHostException.java
@@ -21,8 +21,6 @@
 
 /**
  * Is thrown when a hostname can not be resolved.
- * 
- * @since Android 1.0
  */
 public class UnknownHostException extends IOException {
 
@@ -31,8 +29,6 @@
     /**
      * Constructs a new {@code UnknownHostException} instance with its walkback
      * filled in.
-     * 
-     * @since Android 1.0
      */
     public UnknownHostException() {
         super();
@@ -44,7 +40,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public UnknownHostException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/net/UnknownServiceException.java b/libcore/luni/src/main/java/java/net/UnknownServiceException.java
index 4865d6d..6ad2a19 100644
--- a/libcore/luni/src/main/java/java/net/UnknownServiceException.java
+++ b/libcore/luni/src/main/java/java/net/UnknownServiceException.java
@@ -24,8 +24,6 @@
  * particular service requested by the URL connection. This could be happened if
  * there is an invalid MIME type or the application wants to send data over a
  * read-only connection.
- * 
- * @since Android 1.0
  */
 public class UnknownServiceException extends IOException {
 
@@ -34,8 +32,6 @@
     /**
      * Constructs a new {@code UnknownServiceException} instance with its
      * walkback filled in.
-     * 
-     * @since Android 1.0
      */
     public UnknownServiceException() {
         super();
@@ -47,7 +43,6 @@
      * 
      * @param detailMessage
      *            the detail message for this exception.
-     * @since Android 1.0
      */
     public UnknownServiceException(String detailMessage) {
         super(detailMessage);
diff --git a/libcore/luni/src/main/java/java/util/AbstractCollection.java b/libcore/luni/src/main/java/java/util/AbstractCollection.java
index 9f26445..6511b11 100644
--- a/libcore/luni/src/main/java/java/util/AbstractCollection.java
+++ b/libcore/luni/src/main/java/java/util/AbstractCollection.java
@@ -17,7 +17,6 @@
 
 package java.util;
 
-
 import java.lang.reflect.Array;
 
 /**
@@ -26,23 +25,18 @@
  * iterator()} and {@code size()} to create an immutable collection. To create a
  * modifiable collection it's necessary to override the {@code add()} method that
  * currently throws an {@code UnsupportedOperationException}.
- * 
- * @since Android 1.0
+ *
+ * @since 1.2
  */
 public abstract class AbstractCollection<E> implements Collection<E> {
 
     /**
-     * Constructs a new instance of this {@code AbstractCollection}.
-     * 
-     * @since Android 1.0
+     * Constructs a new instance of this AbstractCollection.
      */
     protected AbstractCollection() {
         super();
     }
 
-    /**
-     * @see Collection#add
-     */         
     public boolean add(E object) {
         throw new UnsupportedOperationException();
     }
@@ -64,18 +58,17 @@
      *            the collection of objects.
      * @return {@code true} if this {@code Collection} is modified, {@code false}
      *         otherwise.
-     * @exception UnsupportedOperationException
-     *                when adding to this {@code Collection} is not supported.
-     * @exception ClassCastException
-     *                when the class of an object is inappropriate for this
+     * @throws UnsupportedOperationException
+     *                if adding to this {@code Collection} is not supported.
+     * @throws ClassCastException
+     *                if the class of an object is inappropriate for this
      *                {@code Collection}.
-     * @exception IllegalArgumentException
-     *                when an object cannot be added to this {@code Collection}.
-     * @exception NullPointerException
-     *                when {@code collection} is {@code null}, or if it contains
+     * @throws IllegalArgumentException
+     *                if an object cannot be added to this {@code Collection}.
+     * @throws NullPointerException
+     *                if {@code collection} is {@code null}, or if it contains
      *                {@code null} elements and this {@code Collection} does not support
      *                such elements.
-     * @since Android 1.0
      */
     public boolean addAll(Collection<? extends E> collection) {
         boolean result = false;
@@ -97,13 +90,12 @@
      * Concrete implementations usually can clear a {@code Collection} more efficiently
      * and should therefore overwrite this method.
      * 
-     * @exception UnsupportedOperationException
-     *                when the iterator does not support removing elements from
+     * @throws UnsupportedOperationException
+     *                it the iterator does not support removing elements from
      *                this {@code Collection}
      * @see #iterator
      * @see #isEmpty
      * @see #size
-     * @since Android 1.0
      */
     public void clear() {
         Iterator<E> it = iterator();
@@ -126,12 +118,11 @@
      *            the object to search for.
      * @return {@code true} if object is an element of this {@code Collection}, {@code
      *         false} otherwise.
-     * @exception ClassCastException
+     * @throws ClassCastException
      *                if the object to look for isn't of the correct type.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if the object to look for is {@code null} and this
      *                {@code Collection} doesn't support {@code null} elements.
-     * @since Android 1.0
      */
     public boolean contains(Object object) {
         Iterator<E> it = iterator();
@@ -161,16 +152,15 @@
      *            the collection of objects.
      * @return {@code true} if all objects in the specified {@code Collection} are
      *         elements of this {@code Collection}, {@code false} otherwise.
-     * @exception ClassCastException
+     * @throws ClassCastException
      *                if one or more elements of {@code collection} isn't of the
      *                correct type.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if {@code collection} contains at least one {@code null}
      *                element and this {@code Collection} doesn't support {@code null}
      *                elements.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if {@code collection} is {@code null}.
-     * @since Android 1.0
      */
     public boolean containsAll(Collection<?> collection) {
         Iterator<?> it = collection.iterator();
@@ -188,9 +178,8 @@
      * 
      * @return {@code true} if this {@code Collection} has no elements, {@code false}
      *         otherwise.
-     * 
+     *
      * @see #size
-     * @since Android 1.0
      */
     public boolean isEmpty() {
         return size() == 0;
@@ -206,7 +195,6 @@
      * by concrete {@code Collection} implementations.
      * 
      * @return an iterator for accessing the {@code Collection} contents.
-     * @since Android 1.0
      */
     public abstract Iterator<E> iterator();
 
@@ -226,14 +214,13 @@
      *            the object to remove.
      * @return {@code true} if this {@code Collection} is modified, {@code false}
      *         otherwise.
-     * @exception UnsupportedOperationException
-     *                when removing from this {@code Collection} is not supported.
-     * @exception ClassCastException
-     *                when the object passed is not of the correct type.
-     * @exception NullPointerException
+     * @throws UnsupportedOperationException
+     *                if removing from this {@code Collection} is not supported.
+     * @throws ClassCastException
+     *                if the object passed is not of the correct type.
+     * @throws NullPointerException
      *                if {@code object} is {@code null} and this {@code Collection}
      *                doesn't support {@code null} elements.
-     * @since Android 1.0
      */
     public boolean remove(Object object) {
         Iterator<?> it = iterator();
@@ -272,18 +259,17 @@
      *            the collection of objects to remove.
      * @return {@code true} if this {@code Collection} is modified, {@code false}
      *         otherwise.
-     * @exception UnsupportedOperationException
-     *                when removing from this {@code Collection} is not supported.
-     * @exception ClassCastException
+     * @throws UnsupportedOperationException
+     *                if removing from this {@code Collection} is not supported.
+     * @throws ClassCastException
      *                if one or more elements of {@code collection} isn't of the
      *                correct type.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if {@code collection} contains at least one {@code null}
      *                element and this {@code Collection} doesn't support {@code null}
      *                elements.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if {@code collection} is {@code null}.
-     * @since Android 1.0
      */
     public boolean removeAll(Collection<?> collection) {
         boolean result = false;
@@ -314,18 +300,17 @@
      *            the collection of objects to retain.
      * @return {@code true} if this {@code Collection} is modified, {@code false}
      *         otherwise.
-     * @exception UnsupportedOperationException
-     *                when removing from this {@code Collection} is not supported.
-     * @exception ClassCastException
+     * @throws UnsupportedOperationException
+     *                if removing from this {@code Collection} is not supported.
+     * @throws ClassCastException
      *                if one or more elements of {@code collection}
      *                isn't of the correct type.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if {@code collection} contains at least one
      *                {@code null} element and this {@code Collection} doesn't support
      *                {@code null} elements.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if {@code collection} is {@code null}.
-     * @since Android 1.0
      */
     public boolean retainAll(Collection<?> collection) {
         boolean result = false;
@@ -348,7 +333,6 @@
      * @return how many objects this {@code Collection} contains, or {@code Integer.MAX_VALUE}
      *         if there are more than {@code Integer.MAX_VALUE} elements in this
      *         {@code Collection}.
-     * @since Android 1.0
      */
     public abstract int size();
 
@@ -367,10 +351,10 @@
         int size = size(), index = 0;
         if (size > contents.length) {
             Class<?> ct = contents.getClass().getComponentType();
-            contents = (T[])Array.newInstance(ct, size);
+            contents = (T[]) Array.newInstance(ct, size);
         }
-        for (E entry: this) {
-            contents[index++] = (T)entry;
+        for (E entry : this) {
+            contents[index++] = (T) entry;
         }
         if (index < contents.length) {
             contents[index] = null;
@@ -384,7 +368,6 @@
      * are separated by ', ' (comma and space).
      * 
      * @return the string representation of this {@code Collection}.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -402,7 +385,7 @@
             } else {
                 buffer.append("(this Collection)"); //$NON-NLS-1$
             }
-            if(it.hasNext()) {
+            if (it.hasNext()) {
                 buffer.append(", "); //$NON-NLS-1$
             }
         }
diff --git a/libcore/luni/src/main/java/java/util/AbstractList.java b/libcore/luni/src/main/java/java/util/AbstractList.java
index cfd8c6f..8f1e79f 100644
--- a/libcore/luni/src/main/java/java/util/AbstractList.java
+++ b/libcore/luni/src/main/java/java/util/AbstractList.java
@@ -24,16 +24,14 @@
  * methods {@code get()} and {@code size()}, and to create a
  * modifiable {@code List} it's necessary to override the {@code add()} method that
  * currently throws an {@code UnsupportedOperationException}.
- * 
- * @since Android 1.0
+ *
+ * @since 1.2
  */
 public abstract class AbstractList<E> extends AbstractCollection<E> implements
         List<E> {
 
     /**
      * A counter for changes to the list.
-     * 
-     * @since Android 1.0
      */
     protected transient int modCount;
 
@@ -67,22 +65,25 @@
         }
 
         public void remove() {
-            if (expectedModCount == modCount) {
-                try {
-                    AbstractList.this.remove(lastPosition);
-                } catch (IndexOutOfBoundsException e) {
-                    throw new IllegalStateException();
-                }
-                if (modCount != expectedModCount) {
-                    expectedModCount++;
-                }
-                if (pos == lastPosition) {
-                    pos--;
-                }
-                lastPosition = -1;
-            } else {
+            if (this.lastPosition == -1) {
+                throw new IllegalStateException();
+            }
+
+            if (expectedModCount != modCount) {
                 throw new ConcurrentModificationException();
             }
+
+            try {
+                AbstractList.this.remove(lastPosition);
+            } catch (IndexOutOfBoundsException e) {
+                throw new ConcurrentModificationException();
+            }
+
+            expectedModCount = modCount;
+            if (pos == lastPosition) {
+                pos--;
+            }
+            lastPosition = -1;
         }
     }
 
@@ -107,7 +108,7 @@
                 pos++;
                 lastPosition = -1;
                 if (modCount != expectedModCount) {
-                    expectedModCount++;
+                    expectedModCount = modCount;
                 }
             } else {
                 throw new ConcurrentModificationException();
@@ -359,7 +360,10 @@
 
         @Override
         public int size() {
-            return size;
+            if (modCount == fullList.modCount) {
+                return size;
+            }
+            throw new ConcurrentModificationException();
         }
 
         void sizeChanged(boolean increment) {
@@ -374,8 +378,6 @@
 
     /**
      * Constructs a new instance of this AbstractList.
-     * 
-     * @since Android 1.0
      */
     protected AbstractList() {
         super();
@@ -386,15 +388,15 @@
      * The object is inserted before any previous element at the specified
      * location. If the location is equal to the size of this List, the object
      * is added at the end.
-     * 
+     * <p>
      * Concrete implementations that would like to support the add functionality
-     * must override this method.          
-     * 
+     * must override this method.
+     *
      * @param location
      *            the index at which to insert.
      * @param object
      *            the object to add.
-     * 
+     *
      * @throws UnsupportedOperationException
      *                if adding to this List is not supported.
      * @throws ClassCastException
@@ -404,7 +406,6 @@
      *                if the object cannot be added to this List
      * @throws IndexOutOfBoundsException
      *                if {@code location < 0 || >= size()}
-     * @since Android 1.0
      */
     public void add(int location, E object) {
         throw new UnsupportedOperationException();
@@ -412,12 +413,12 @@
 
     /**
      * Adds the specified object at the end of this List.
-     * 
-     * 
+     *
+     *
      * @param object
      *            the object to add
      * @return true
-     * 
+     *
      * @throws UnsupportedOperationException
      *                if adding to this List is not supported
      * @throws ClassCastException
@@ -425,7 +426,6 @@
      *                List
      * @throws IllegalArgumentException
      *                if the object cannot be added to this List
-     * @since Android 1.0
      */
     @Override
     public boolean add(E object) {
@@ -437,7 +437,7 @@
      * 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 location
      *            the index at which to insert.
      * @param collection
@@ -451,7 +451,6 @@
      *             if an object cannot be added to this list.
      * @throws IndexOutOfBoundsException
      *             if {@code location < 0 || > size()}
-     * @since Android 1.0
      */
     public boolean addAll(int location, Collection<? extends E> collection) {
         Iterator<? extends E> it = collection.iterator();
@@ -463,12 +462,11 @@
 
     /**
      * Removes all elements from this list, leaving it empty.
-     * 
+     *
      * @throws UnsupportedOperationException
      *             if removing from this list is not supported.
      * @see List#isEmpty
      * @see List#size
-     * @since Android 1.0
      */
     @Override
     public void clear() {
@@ -479,13 +477,12 @@
      * Compares the specified object to this list and return true if they are
      * equal. Two lists are equal when they both contain the same objects in the
      * same order.
-     * 
+     *
      * @param object
      *            the object to compare to this object.
      * @return {@code true} if the specified object is equal to this list,
      *         {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -512,24 +509,22 @@
 
     /**
      * Returns the element at the specified location in this list.
-     * 
+     *
      * @param location
      *            the index of the element to return.
      * @return the element at the specified index.
      * @throws IndexOutOfBoundsException
      *             if {@code location < 0 || >= size()}
-     * @since Android 1.0
      */
     public abstract E get(int location);
 
     /**
      * Returns the hash code of this list. The hash code is calculated by taking
      * each element's hashcode into account.
-     * 
+     *
      * @return the hash code.
      * @see #equals
      * @see List#hashCode()
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -545,12 +540,11 @@
     /**
      * Searches this list for the specified object and returns the index of the
      * first occurrence.
-     * 
+     *
      * @param object
      *            the object to search for.
      * @return the index of the first occurrence of the object, or -1 if it was
      *         not found.
-     * @since Android 1.0
      */
     public int indexOf(Object object) {
         ListIterator<?> it = listIterator();
@@ -573,10 +567,9 @@
     /**
      * Returns an iterator on the elements of this list. The elements are
      * iterated in the same order as they occur in the list.
-     * 
+     *
      * @return an iterator on the elements of this list.
      * @see Iterator
-     * @since Android 1.0
      */
     @Override
     public Iterator<E> iterator() {
@@ -586,12 +579,11 @@
     /**
      * Searches this list for the specified object and returns the index of the
      * last occurrence.
-     * 
+     *
      * @param object
      *            the object to search for.
      * @return the index of the last occurrence of the object, or -1 if the
      *         object was not found.
-     * @since Android 1.0
      */
     public int lastIndexOf(Object object) {
         ListIterator<?> it = listIterator(size());
@@ -614,10 +606,9 @@
     /**
      * Returns a ListIterator on the elements of this list. The elements are
      * iterated in the same order that they occur in the list.
-     * 
+     *
      * @return a ListIterator on the elements of this list
      * @see ListIterator
-     * @since Android 1.0
      */
     public ListIterator<E> listIterator() {
         return listIterator(0);
@@ -627,14 +618,13 @@
      * Returns a list iterator on the elements of this list. The elements are
      * iterated in the same order as they occur in the list. The iteration
      * starts at the specified location.
-     * 
+     *
      * @param location
      *            the index at which to start the iteration.
      * @return a ListIterator on the elements of this list.
      * @throws IndexOutOfBoundsException
      *             if {@code location < 0 || location > size()}
      * @see ListIterator
-     * @since Android 1.0
      */
     public ListIterator<E> listIterator(int location) {
         return new FullListIterator(location);
@@ -642,7 +632,7 @@
 
     /**
      * Removes the object at the specified location from this list.
-     * 
+     *
      * @param location
      *            the index of the object to remove.
      * @return the removed object.
@@ -650,7 +640,6 @@
      *             if removing from this list is not supported.
      * @throws IndexOutOfBoundsException
      *             if {@code location < 0 || >= size()}
-     * @since Android 1.0
      */
     public E remove(int location) {
         throw new UnsupportedOperationException();
@@ -659,7 +648,7 @@
     /**
      * Removes the objects in the specified range from the start to the end
      * index minus one.
-     * 
+     *
      * @param start
      *            the index at which to start removing.
      * @param end
@@ -668,7 +657,6 @@
      *             if removing from this list is not supported.
      * @throws IndexOutOfBoundsException
      *             if {@code start < 0} or {@code start >= size()}.
-     * @since Android 1.0
      */
     protected void removeRange(int start, int end) {
         Iterator<?> it = listIterator(start);
@@ -681,7 +669,7 @@
     /**
      * Replaces the element at the specified location in this list with the
      * specified object.
-     * 
+     *
      * @param location
      *            the index at which to put the specified object.
      * @param object
@@ -695,7 +683,6 @@
      *             if an object cannot be added to this list.
      * @throws IndexOutOfBoundsException
      *             if {@code location < 0 || >= size()}
-     * @since Android 1.0
      */
     public E set(int location, E object) {
         throw new UnsupportedOperationException();
@@ -733,7 +720,7 @@
      * <p>
      * All methods will throw a ConcurrentModificationException if the modCount
      * of the original list is not equal to the expected value.
-     * 
+     *
      * @param start
      *            start index of the subList (inclusive).
      * @param end
@@ -744,7 +731,6 @@
      *             if (start < 0 || end > size())
      * @throws IllegalArgumentException
      *             if (start > end)
-     * @since Android 1.0
      */
     public List<E> subList(int start, int end) {
         if (0 <= start && end <= size()) {
diff --git a/libcore/luni/src/main/java/java/util/AbstractMap.java b/libcore/luni/src/main/java/java/util/AbstractMap.java
index 00266a7..b687e72 100644
--- a/libcore/luni/src/main/java/java/util/AbstractMap.java
+++ b/libcore/luni/src/main/java/java/util/AbstractMap.java
@@ -17,17 +17,12 @@
 
 package java.util;
 
-// BEGIN android-added
-// copied from newer harmony
-import java.util.Map.Entry;
-// END android-added
-
 /**
  * This class is an abstract implementation of the {@code Map} interface. This
  * implementation does not support adding. A subclass must implement the
  * abstract method entrySet().
- * 
- * @since Android 1.0
+ *
+ * @since 1.2
  */
 public abstract class AbstractMap<K, V> implements Map<K, V> {
 
@@ -38,8 +33,6 @@
 
     /**
      * Constructs a new instance of this {@code AbstractMap}.
-     * 
-     * @since Android 1.0
      */
     protected AbstractMap() {
         super();
@@ -47,12 +40,11 @@
 
     /**
      * Removes all elements from this map, leaving it empty.
-     * 
+     *
      * @throws UnsupportedOperationException
      *                if removing from this map is not supported.
      * @see #isEmpty()
      * @see #size()
-     * @since Android 1.0
      */
     public void clear() {
         entrySet().clear();
@@ -60,12 +52,11 @@
 
     /**
      * Returns whether this map contains the specified key.
-     * 
+     *
      * @param key
      *            the key to search for.
      * @return {@code true} if this map contains the specified key,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean containsKey(Object key) {
         Iterator<Map.Entry<K, V>> it = entrySet().iterator();
@@ -87,12 +78,11 @@
 
     /**
      * Returns whether this map contains the specified value.
-     * 
+     *
      * @param value
      *            the value to search for.
      * @return {@code true} if this map contains the specified value,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean containsValue(Object value) {
         Iterator<Map.Entry<K, V>> it = entrySet().iterator();
@@ -116,23 +106,21 @@
      * Returns a set containing all of the mappings in this map. Each mapping is
      * an instance of {@link Map.Entry}. As the set is backed by this map,
      * changes in one will be reflected in the other.
-     * 
+     *
      * @return a set of the mappings.
-     * @since Android 1.0
      */
     public abstract Set<Map.Entry<K, V>> entrySet();
 
     /**
      * Compares the specified object to this instance, and returns {@code true}
      * if the specified object is a map and both maps contain the same mappings.
-     * 
+     *
      * @param object
      *            the object to compare with this object.
      * @return boolean {@code true} if the object is the same as this object,
      *         and {@code false} if it is different from this object.
      * @see #hashCode()
      * @see #entrySet()
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -145,19 +133,21 @@
                 return false;
             }
 
-            // BEGIN android-changed
-            // copied from newer version of harmony
             Iterator<Map.Entry<K, V>> it = entrySet().iterator();
-            while (it.hasNext()) {
-                Entry<K, V> entry = it.next();
-                K key = entry.getKey();
-                V value = entry.getValue();
-                Object obj = map.get(key);
-                if( null != obj && (!obj.equals(value)) || null == obj && obj != value) {
-                    return false;
+
+            try {
+                while (it.hasNext()) {
+                    Entry<K, V> entry = it.next();
+                    K key = entry.getKey();
+                    V value = entry.getValue();
+                    Object obj = map.get(key);
+                    if( null != obj && (!obj.equals(value)) || null == obj && obj != value) {
+                        return false;
+                    }
                 }
+            } catch (ClassCastException cce) {
+                return false;
             }
-            // END android-changed
             return true;
         }
         return false;
@@ -165,12 +155,11 @@
 
     /**
      * Returns the value of the mapping with the specified key.
-     * 
+     *
      * @param key
      *            the key.
      * @return the value of the mapping with the specified key, or {@code null}
      *         if no mapping for the specified key is found.
-     * @since Android 1.0
      */
     public V get(Object key) {
         Iterator<Map.Entry<K, V>> it = entrySet().iterator();
@@ -195,10 +184,9 @@
     /**
      * Returns the hash code for this object. Objects which are equal must
      * return the same value for this method.
-     * 
+     *
      * @return the hash code of this object.
      * @see #equals(Object)
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -212,11 +200,10 @@
 
     /**
      * Returns whether this map is empty.
-     * 
+     *
      * @return {@code true} if this map has no elements, {@code false}
      *         otherwise.
      * @see #size()
-     * @since Android 1.0
      */
     public boolean isEmpty() {
         return size() == 0;
@@ -226,9 +213,8 @@
      * Returns a set of the keys contained in this map. The set is backed by
      * this map so changes to one are reflected by the other. The returned set
      * does not support adding.
-     * 
+     *
      * @return a set of the keys.
-     * @since Android 1.0
      */
     public Set<K> keySet() {
         if (keySet == null) {
@@ -269,7 +255,7 @@
 
     /**
      * Maps the specified key to the specified value.
-     * 
+     *
      * @param key
      *            the key.
      * @param value
@@ -286,7 +272,6 @@
      * @throws NullPointerException
      *                if the key or value is {@code null} and this Map does not
      *                support {@code null} keys or values.
-     * @since Android 1.0
      */
     public V put(K key, V value) {
         throw new UnsupportedOperationException();
@@ -294,7 +279,7 @@
 
     /**
      * Copies every mapping in the specified map to this map.
-     * 
+     *
      * @param map
      *            the map to copy mappings from.
      * @throws UnsupportedOperationException
@@ -307,7 +292,6 @@
      * @throws NullPointerException
      *                if a key or value is {@code null} and this map does not
      *                support {@code null} keys or values.
-     * @since Android 1.0
      */
     public void putAll(Map<? extends K, ? extends V> map) {
         for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
@@ -317,14 +301,13 @@
 
     /**
      * Removes a mapping with the specified key from this Map.
-     * 
+     *
      * @param key
      *            the key of the mapping to remove.
      * @return the value of the removed mapping or {@code null} if no mapping
      *         for the specified key was found.
      * @throws UnsupportedOperationException
      *                if removing from this map is not supported.
-     * @since Android 1.0
      */
     public V remove(Object key) {
         Iterator<Map.Entry<K, V>> it = entrySet().iterator();
@@ -350,9 +333,8 @@
 
     /**
      * Returns the number of elements in this map.
-     * 
+     *
      * @return the number of elements in this map.
-     * @since Android 1.0
      */
     public int size() {
         return entrySet().size();
@@ -360,9 +342,8 @@
 
     /**
      * Returns the string representation of this map.
-     * 
+     *
      * @return the string representation of this map.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -407,16 +388,13 @@
      * "wrapper object" over the iterator of map's entrySet(). The {@code size}
      * method wraps the map's size method and the {@code contains} method wraps
      * the map's containsValue method.
-     * </p>
      * <p>
      * The collection is created when this method is called for the first time
      * and returned in response to all subsequent calls. This method may return
      * different collections when multiple concurrent calls occur to this
      * method, since no synchronization is performed.
-     * </p>
-     * 
+     *
      * @return a collection of the values contained in this map.
-     * @since Android 1.0
      */
     public Collection<V> values() {
         if (valuesCollection == null) {
@@ -458,12 +436,11 @@
     /**
      * Returns a new instance of the same class as this instance, whose slots
      * have been filled in with the values of the slots of this instance.
-     * 
+     *
      * @return a shallow copy of this object.
      * @throws CloneNotSupportedException
      *                if the receiver's class does not implement the interface
      *                {@code Cloneable}.
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
diff --git a/libcore/luni/src/main/java/java/util/AbstractQueue.java b/libcore/luni/src/main/java/java/util/AbstractQueue.java
index 0b9bdf1..4b4fccf 100644
--- a/libcore/luni/src/main/java/java/util/AbstractQueue.java
+++ b/libcore/luni/src/main/java/java/util/AbstractQueue.java
@@ -22,18 +22,15 @@
  * {@code element} are based on {@code offer, poll}, and {@code peek} except
  * that they throw exceptions to indicate some error instead of returning true
  * or false.
- * 
+ *
  * @param <E>
  *            the type of the element in the collection.
- * @since Android 1.0
  */
 public abstract class AbstractQueue<E> extends AbstractCollection<E> implements
         Queue<E> {
 
     /**
      * Constructor to be used by subclasses.
-     * 
-     * @since Android 1.0
      */
     protected AbstractQueue() {
         super();
@@ -47,7 +44,6 @@
      * @return {@code true} if the operation succeeds, otherwise {@code false}.
      * @throws IllegalStateException
      *             if the element is not allowed to be added to the queue.
-     * @since Android 1.0
      */
     @Override
     public boolean add(E o) {
@@ -76,7 +72,6 @@
      * @throws IllegalArgumentException
      *             If the collection to be added to the queue is the queue
      *             itself.
-     * @since Android 1.0
      */
     @Override
     public boolean addAll(Collection<? extends E> c) {
@@ -95,7 +90,6 @@
      * @return the element at the head of the queue.
      * @throws NoSuchElementException
      *             if the queue is empty.
-     * @since Android 1.0
      */
     public E remove() {
         E o = poll();
@@ -111,7 +105,6 @@
      * @return the element at the head of the queue.
      * @throws NoSuchElementException
      *             if the queue is empty.
-     * @since Android 1.0
      */
     public E element() {
         E o = peek();
@@ -123,8 +116,6 @@
 
     /**
      * Removes all elements of the queue, leaving it empty.
-     * 
-     * @since Android 1.0
      */
     @Override
     public void clear() {
diff --git a/libcore/luni/src/main/java/java/util/AbstractSequentialList.java b/libcore/luni/src/main/java/java/util/AbstractSequentialList.java
index 4ca8f7b..dcdecaa 100644
--- a/libcore/luni/src/main/java/java/util/AbstractSequentialList.java
+++ b/libcore/luni/src/main/java/java/util/AbstractSequentialList.java
@@ -17,20 +17,17 @@
 
 package java.util;
 
-
 /**
  * AbstractSequentialList is an abstract implementation of the List interface.
  * This implementation does not support adding. A subclass must implement the
  * abstract method listIterator().
- * 
- * @since Android 1.0
+ *
+ * @since 1.2
  */
 public abstract class AbstractSequentialList<E> extends AbstractList<E> {
 
     /**
      * Constructs a new instance of this AbstractSequentialList.
-     * 
-     * @since Android 1.0
      */
     protected AbstractSequentialList() {
         super();
@@ -45,24 +42,11 @@
     public boolean addAll(int location, Collection<? extends E> collection) {
         ListIterator<E> it = listIterator(location);
         Iterator<? extends E> colIt = collection.iterator();
-        // BEGIN android-removed
-        // int next = it.nextIndex();
-        // while (colIt.hasNext()) {
-        //     it.add(colIt.next());
-        //     it.previous();
-        // }
-        // return next != it.nextIndex();
-        // END android-removed
-
-        // BEGIN android-added
-        // BUG: previous/next inconsistant.  We care for list
-        // modification NOT iterator modification.
-        int size = this.size();
+        int next = it.nextIndex();
         while (colIt.hasNext()) {
             it.add(colIt.next());
         }
-        return size != this.size();
-        // END android-added
+        return next != it.nextIndex();
     }
 
     @Override
@@ -97,6 +81,9 @@
     @Override
     public E set(int location, E object) {
         ListIterator<E> it = listIterator(location);
+        if (!it.hasNext()) {
+            throw new IndexOutOfBoundsException();
+        }
         E result = it.next();
         it.set(object);
         return result;
diff --git a/libcore/luni/src/main/java/java/util/AbstractSet.java b/libcore/luni/src/main/java/java/util/AbstractSet.java
index a19b1f7..e6ef0bb 100644
--- a/libcore/luni/src/main/java/java/util/AbstractSet.java
+++ b/libcore/luni/src/main/java/java/util/AbstractSet.java
@@ -22,15 +22,13 @@
  * implementation does not support adding. A subclass must implement the
  * abstract methods iterator() and size().
  * 
- * @since Android 1.0
+ * @since 1.2
  */
 public abstract class AbstractSet<E> extends AbstractCollection<E> implements
         Set<E> {
 
     /**
      * Constructs a new instance of this AbstractSet.
-     * 
-     * @since Android 1.0
      */
     protected AbstractSet() {
         super();
@@ -46,7 +44,6 @@
      * @return {@code true} if the specified object is equal to this set,
      *         {@code false} otherwise
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -55,14 +52,12 @@
         }
         if (object instanceof Set) {
             Set<?> s = (Set<?>) object;
-            // BEGIN android-changed
-            // copied from a newer version of harmony
+
             try {
                 return size() == s.size() && containsAll(s);
             } catch (ClassCastException cce) {
                 return false;
             }
-            // END android-changed
         }
         return false;
     }
@@ -74,7 +69,6 @@
      * 
      * @return the hash code of this set.
      * @see #equals
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -95,9 +89,8 @@
      *            the collection of objects to remove.
      * @return {@code true} if this collection was modified, {@code false}
      *         otherwise.
-     * @exception UnsupportedOperationException
-     *                when removing from this collection is not supported.
-     * @since Android 1.0
+     * @throws UnsupportedOperationException
+     *                if removing from this collection is not supported.
      */
     @Override
     public boolean removeAll(Collection<?> collection) {
diff --git a/libcore/luni/src/main/java/java/util/ArrayList.java b/libcore/luni/src/main/java/java/util/ArrayList.java
index 78f9690..b8c7056 100644
--- a/libcore/luni/src/main/java/java/util/ArrayList.java
+++ b/libcore/luni/src/main/java/java/util/ArrayList.java
@@ -17,7 +17,6 @@
 
 package java.util;
 
-
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
@@ -29,11 +28,11 @@
  * ArrayList is an implementation of {@link List}, backed by an array. All
  * optional operations adding, removing, and replacing are supported. The
  * elements can be any objects.
- * 
- * @since Android 1.0
+ *
+ * @since 1.2
  */
-public class ArrayList<E> extends AbstractList<E> implements List<E>, Cloneable,
-        Serializable, RandomAccess {
+public class ArrayList<E> extends AbstractList<E> implements List<E>,
+        Cloneable, Serializable, RandomAccess {
 
     private static final long serialVersionUID = 8683452581122892189L;
 
@@ -43,53 +42,54 @@
     // END android-added
 
     private transient int firstIndex;
-    
+
     private transient int lastIndex;
 
     private transient E[] array;
 
     /**
      * Constructs a new instance of {@code ArrayList} with zero capacity.
-     * 
-     * @since Android 1.0
      */
     public ArrayList() {
+        // BEGIN android-changed
+        // default capacity is zero, not ten
         this(0);
+        // END android-changed
     }
 
     /**
      * Constructs a new instance of {@code ArrayList} with the specified
      * capacity.
-     * 
+     *
      * @param capacity
      *            the initial capacity of this {@code ArrayList}.
-     * @since Android 1.0
      */
     public ArrayList(int capacity) {
-        firstIndex = lastIndex = 0;
-        try {
-            array = newElementArray(capacity);
-        } catch (NegativeArraySizeException e) {
+        if (capacity < 0) {
             throw new IllegalArgumentException();
         }
+        firstIndex = lastIndex = 0;
+        array = newElementArray(capacity);
     }
 
     /**
      * 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.
-     * 
+     *
      * @param collection
      *            the collection of elements to add.
-     * @since Android 1.0
      */
     public ArrayList(Collection<? extends E> collection) {
-        int size = collection.size();
-        firstIndex = lastIndex = 0;
+        firstIndex = 0;
+        Object[] objects = collection.toArray();
+        int size = objects.length;
         array = newElementArray(size + (size / 10));
-        addAll(collection);
+        System.arraycopy(objects, 0, array, 0, size);
+        lastIndex = size;
+        modCount = 1;
     }
-    
+
     @SuppressWarnings("unchecked")
     private E[] newElementArray(int size) {
         // BEGIN android-added
@@ -98,7 +98,7 @@
         }
         // END android-added
 
-        return (E[])new Object[size];
+        return (E[]) new Object[size];
     }
 
     /**
@@ -106,20 +106,17 @@
      * 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()}
-     * @since Android 1.0
      */
     @Override
     public void add(int location, E object) {
-        // BEGIN android-changed: slight performance improvement
         int size = lastIndex - firstIndex;
-        // END android-changed
         if (0 < location && location < size) {
             if (firstIndex == 0 && lastIndex == array.length) {
                 growForInsert(location, 1);
@@ -153,11 +150,10 @@
 
     /**
      * Adds the specified object at the end of this {@code ArrayList}.
-     * 
+     *
      * @param object
      *            the object to add.
      * @return always true
-     * @since Android 1.0
      */
     @Override
     public boolean add(E object) {
@@ -173,7 +169,7 @@
      * 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 location
      *            the index at which to insert.
      * @param collection
@@ -182,15 +178,22 @@
      *         otherwise.
      * @throws IndexOutOfBoundsException
      *             when {@code location < 0 || > size()}
-     * @since Android 1.0
      */
     @Override
     public boolean addAll(int location, Collection<? extends E> collection) {
-        int size = size();
+        int size = lastIndex - firstIndex;
         if (location < 0 || location > size) {
             throw new IndexOutOfBoundsException();
         }
-        int growSize = collection.size();
+        if (this == collection) {
+            collection = (ArrayList)clone();
+        }
+        Object[] dumparray = collection.toArray();
+        int growSize = dumparray.length;
+        if (growSize == 0) {
+            return false;
+        }
+
         if (0 < location && location < size) {
             if (array.length - size < growSize) {
                 growForInsert(location, growSize);
@@ -222,52 +225,40 @@
             lastIndex += growSize;
         }
 
-        if (growSize > 0) {
-            Iterator<? extends E> it = collection.iterator();
-            int index = location + firstIndex;
-            int end = index + growSize;
-            while (index < end) {
-                array[index++] = it.next();
-            }
-            modCount++;
-            return true;
-        }
-        return false;
+        System.arraycopy(dumparray, 0, this.array, location + firstIndex,
+                growSize);
+        modCount++;
+        return true;
     }
 
     /**
      * Adds the objects in the specified collection to this {@code ArrayList}.
-     * 
+     *
      * @param collection
      *            the collection of objects.
      * @return {@code true} if this {@code ArrayList} is modified, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean addAll(Collection<? extends E> collection) {
-        int growSize = collection.size();
-        if (growSize > 0) {
-            if (lastIndex > array.length - growSize) {
-                growAtEnd(growSize);
-            }
-            Iterator<? extends E> it = collection.iterator();
-            int end = lastIndex + growSize;
-            while (lastIndex < end) {
-                array[lastIndex++] = it.next();
-            }
-            modCount++;
-            return true;
+        Object[] dumpArray = collection.toArray();
+        if (dumpArray.length == 0) {
+            return false;
         }
-        return false;
+        if (dumpArray.length > array.length - lastIndex) {
+            growAtEnd(dumpArray.length);
+        }
+        System.arraycopy(dumpArray, 0, this.array, lastIndex, dumpArray.length);
+        lastIndex += dumpArray.length;
+        modCount++;
+        return true;
     }
 
     /**
      * Removes all elements from this {@code ArrayList}, leaving it empty.
-     * 
+     *
      * @see #isEmpty
      * @see #size
-     * @since Android 1.0
      */
     @Override
     public void clear() {
@@ -281,10 +272,9 @@
     /**
      * Returns a new {@code ArrayList} with the same elements, the same size and
      * the same capacity as this {@code ArrayList}.
-     * 
+     *
      * @return a shallow copy of this {@code ArrayList}
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
@@ -300,12 +290,11 @@
 
     /**
      * 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
-     * @since Android 1.0
      */
     @Override
     public boolean contains(Object object) {
@@ -328,10 +317,9 @@
     /**
      * Ensures that after this operation the {@code ArrayList} can hold the
      * specified number of elements without further growing.
-     * 
+     *
      * @param minimumCapacity
      *            the minimum capacity asked for.
-     * @since Android 1.0
      */
     public void ensureCapacity(int minimumCapacity) {
         if (array.length < minimumCapacity) {
@@ -356,7 +344,7 @@
     }
 
     private void growAtEnd(int required) {
-        int size = size();
+        int size = lastIndex - firstIndex;
         if (firstIndex >= required - (array.length - lastIndex)) {
             int newLast = lastIndex - firstIndex;
             if (size > 0) {
@@ -385,8 +373,8 @@
     }
 
     private void growAtFront(int required) {
-        int size = size();
-        if (array.length - lastIndex >= 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);
@@ -416,7 +404,8 @@
     }
 
     private void growForInsert(int location, int required) {
-        int size = size(), increment = size / 2;
+        int size = lastIndex - firstIndex;
+        int increment = size / 2;
         if (required > increment) {
             increment = required;
         }
@@ -480,20 +469,17 @@
 
     /**
      * Removes the object at the specified location from this list.
-     * 
+     *
      * @param location
      *            the index of the object to remove.
      * @return the removed object.
      * @throws IndexOutOfBoundsException
      *             when {@code location < 0 || >= size()}
-     * @since Android 1.0
      */
     @Override
     public E remove(int location) {
         E result;
-        // BEGIN android-changed: slight performance improvement
         int size = lastIndex - firstIndex;
-        // END android-changed
         if (0 <= location && location < size) {
             if (location == size - 1) {
                 result = array[--lastIndex];
@@ -514,6 +500,9 @@
                     array[--lastIndex] = null;
                 }
             }
+            if (firstIndex == lastIndex) {
+                firstIndex = lastIndex = 0;
+            }
         } else {
             throw new IndexOutOfBoundsException();
         }
@@ -522,41 +511,34 @@
         return result;
     }
 
-    // BEGIN android-added
-    /*
-     * The remove(Object) implementation from AbstractCollection creates
-     * a new Iterator on every remove and ends up calling remove(int).
-     */
     @Override
     public boolean remove(Object object) {
-        int index = indexOf(object);
-        if (index >= 0) {
-            remove(index);
+        int location = indexOf(object);
+        if (location >= 0) {
+            remove(location);
             return true;
         }
         return false;
     }
-    // END android-added
 
     /**
      * 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()}
-     * @since Android 1.0
      */
     @Override
     protected void removeRange(int start, int end) {
-        if (start >= 0 && start <= end && end <= size()) {
+        if (start >= 0 && start <= end && end <= (lastIndex - firstIndex)) {
             if (start == end) {
                 return;
             }
-            int size = size();
+            int size = lastIndex - firstIndex;
             if (end == size) {
                 Arrays.fill(array, firstIndex + start, lastIndex, null);
                 lastIndex = firstIndex + start;
@@ -579,7 +561,7 @@
     /**
      * Replaces the element at the specified location in this {@code ArrayList}
      * with the specified object.
-     * 
+     *
      * @param location
      *            the index at which to put the specified object.
      * @param object
@@ -587,13 +569,10 @@
      * @return the previous element at the index.
      * @throws IndexOutOfBoundsException
      *             when {@code location < 0 || >= size()}
-     * @since Android 1.0
      */
     @Override
     public E set(int location, E object) {
-        // BEGIN android-changed: slight performance improvement
         if (0 <= location && location < (lastIndex - firstIndex)) {
-        // END android-changed
             E result = array[firstIndex + location];
             array[firstIndex + location] = object;
             return result;
@@ -603,9 +582,8 @@
 
     /**
      * Returns the number of elements in this {@code ArrayList}.
-     * 
+     *
      * @return the number of elements in this {@code ArrayList}.
-     * @since Android 1.0
      */
     @Override
     public int size() {
@@ -615,13 +593,12 @@
     /**
      * Returns a new array containing all elements contained in this
      * {@code ArrayList}.
-     * 
+     *
      * @return an array of the elements from this {@code ArrayList}
-     * @since Android 1.0
      */
     @Override
     public Object[] toArray() {
-        int size = size();
+        int size = lastIndex - firstIndex;
         Object[] result = new Object[size];
         System.arraycopy(array, firstIndex, result, 0, size);
         return result;
@@ -634,19 +611,18 @@
      * type is created. If the specified array is used and is larger than this
      * {@code ArrayList}, the array element following the collection elements
      * is set to null.
-     * 
+     *
      * @param contents
      *            the array.
      * @return an array of the elements from this {@code ArrayList}.
      * @throws ArrayStoreException
      *             when the type of an element in this {@code ArrayList} cannot
      *             be stored in the type of the specified array.
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
     public <T> T[] toArray(T[] contents) {
-        int size = size();
+        int size = lastIndex - firstIndex;
         if (size > contents.length) {
             Class<?> ct = contents.getClass().getComponentType();
             contents = (T[]) Array.newInstance(ct, size);
@@ -661,17 +637,17 @@
     /**
      * Sets the capacity of this {@code ArrayList} to be the same as the current
      * size.
-     * 
+     *
      * @see #size
-     * @since Android 1.0
      */
     public void trimToSize() {
-        int size = size();
+        int size = lastIndex - firstIndex;
         E[] newArray = newElementArray(size);
         System.arraycopy(array, firstIndex, newArray, 0, size);
         array = newArray;
         firstIndex = 0;
         lastIndex = array.length;
+        modCount = 0;
     }
 
     private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField(
@@ -679,7 +655,7 @@
 
     private void writeObject(ObjectOutputStream stream) throws IOException {
         ObjectOutputStream.PutField fields = stream.putFields();
-        fields.put("size", size()); //$NON-NLS-1$
+        fields.put("size", lastIndex - firstIndex); //$NON-NLS-1$
         stream.writeFields();
         stream.writeInt(array.length);
         Iterator<?> it = iterator();
@@ -695,7 +671,7 @@
         lastIndex = fields.get("size", 0); //$NON-NLS-1$
         array = newElementArray(stream.readInt());
         for (int i = 0; i < lastIndex; i++) {
-            array[i] = (E)stream.readObject();
+            array[i] = (E) 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 d479945..4fc1e85 100644
--- a/libcore/luni/src/main/java/java/util/Arrays.java
+++ b/libcore/luni/src/main/java/java/util/Arrays.java
@@ -22,11 +22,16 @@
 
 /**
  * {@code Arrays} contains static methods which operate on arrays.
- *  
- * @since Android 1.0
+ *
+ * @since 1.2
  */
 public class Arrays {
 
+    // BEGIN android-removed
+    /* Specifies when to switch to insertion sort */
+    // private static final int SIMPLE_LENGTH = 7;
+    // END android-removed
+
     private static class ArrayList<E> extends AbstractList<E> implements
             List<E>, Serializable, RandomAccess {
 
@@ -152,11 +157,10 @@
      * {@code List} cannot be modified, i.e. adding and removing are unsupported, but
      * the elements can be set. Setting an element modifies the underlying
      * array.
-     * 
+     *
      * @param array
      *            the array.
      * @return a {@code List} of the elements of the specified array.
-     * @since Android 1.0
      */
     public static <T> List<T> asList(T... array) {
         return new ArrayList<T>(array);
@@ -167,19 +171,18 @@
      * ascending sorted array. Searching in an unsorted array has an undefined
      * result. It's also undefined which element is found if there are multiple
      * occurrences of the same element.
-     * 
+     *
      * @param array
      *            the sorted {@code byte} array to search.
      * @param value
      *            the {@code byte} element to find.
      * @return the non-negative index of the element, or a negative index which
      *         is {@code -index - 1} where the element would be inserted.
-     * @since Android 1.0
      */
     public static int binarySearch(byte[] array, byte value) {
         int low = 0, mid = -1, high = array.length - 1;
         while (low <= high) {
-            mid = (low + high) >> 1;
+            mid = (low + high) >>> 1;
             if (value > array[mid]) {
                 low = mid + 1;
             } else if (value == array[mid]) {
@@ -200,19 +203,18 @@
      * ascending sorted array. Searching in an unsorted array has an undefined
      * result. It's also undefined which element is found if there are multiple
      * occurrences of the same element.
-     * 
+     *
      * @param array
      *            the sorted {@code char} array to search.
      * @param value
      *            the {@code char} element to find.
      * @return the non-negative index of the element, or a negative index which
      *         is {@code -index - 1} where the element would be inserted.
-     * @since Android 1.0
      */
     public static int binarySearch(char[] array, char value) {
         int low = 0, mid = -1, high = array.length - 1;
         while (low <= high) {
-            mid = (low + high) >> 1;
+            mid = (low + high) >>> 1;
             if (value > array[mid]) {
                 low = mid + 1;
             } else if (value == array[mid]) {
@@ -232,20 +234,19 @@
      * ascending sorted array. Searching in an unsorted array has an undefined
      * result. It's also undefined which element is found if there are multiple
      * occurrences of the same element.
-     * 
+     *
      * @param array
      *            the sorted {@code double} array to search.
      * @param value
      *            the {@code double} element to find.
      * @return the non-negative index of the element, or a negative index which
      *         is {@code -index - 1} where the element would be inserted.
-     * @since Android 1.0
      */
     public static int binarySearch(double[] array, double value) {
         long longBits = Double.doubleToLongBits(value);
         int low = 0, mid = -1, high = array.length - 1;
         while (low <= high) {
-            mid = (low + high) >> 1;
+            mid = (low + high) >>> 1;
             if (lessThan(array[mid], value)) {
                 low = mid + 1;
             } else if (longBits == Double.doubleToLongBits(array[mid])) {
@@ -265,20 +266,19 @@
      * ascending sorted array. Searching in an unsorted array has an undefined
      * result. It's also undefined which element is found if there are multiple
      * occurrences of the same element.
-     * 
+     *
      * @param array
      *            the sorted {@code float} array to search.
      * @param value
      *            the {@code float} element to find.
      * @return the non-negative index of the element, or a negative index which
      *         is {@code -index - 1} where the element would be inserted.
-     * @since Android 1.0
      */
     public static int binarySearch(float[] array, float value) {
         int intBits = Float.floatToIntBits(value);
         int low = 0, mid = -1, high = array.length - 1;
         while (low <= high) {
-            mid = (low + high) >> 1;
+            mid = (low + high) >>> 1;
             if (lessThan(array[mid], value)) {
                 low = mid + 1;
             } else if (intBits == Float.floatToIntBits(array[mid])) {
@@ -298,19 +298,18 @@
      * ascending sorted array. Searching in an unsorted array has an undefined
      * result. It's also undefined which element is found if there are multiple
      * occurrences of the same element.
-     * 
+     *
      * @param array
      *            the sorted {@code int} array to search.
      * @param value
      *            the {@code int} element to find.
      * @return the non-negative index of the element, or a negative index which
      *         is {@code -index - 1} where the element would be inserted.
-     * @since Android 1.0
      */
     public static int binarySearch(int[] array, int value) {
         int low = 0, mid = -1, high = array.length - 1;
         while (low <= high) {
-            mid = (low + high) >> 1;
+            mid = (low + high) >>> 1;
             if (value > array[mid]) {
                 low = mid + 1;
             } else if (value == array[mid]) {
@@ -330,19 +329,18 @@
      * ascending sorted array. Searching in an unsorted array has an undefined
      * result. It's also undefined which element is found if there are multiple
      * occurrences of the same element.
-     * 
+     *
      * @param array
      *            the sorted {@code long} array to search.
      * @param value
      *            the {@code long} element to find.
      * @return the non-negative index of the element, or a negative index which
      *         is {@code -index - 1} where the element would be inserted.
-     * @since Android 1.0
      */
     public static int binarySearch(long[] array, long value) {
         int low = 0, mid = -1, high = array.length - 1;
         while (low <= high) {
-            mid = (low + high) >> 1;
+            mid = (low + high) >>> 1;
             if (value > array[mid]) {
                 low = mid + 1;
             } else if (value == array[mid]) {
@@ -362,28 +360,27 @@
      * ascending sorted array. Searching in an unsorted array has an undefined
      * result. It's also undefined which element is found if there are multiple
      * occurrences of the same element.
-     * 
+     *
      * @param array
      *            the sorted {@code Object} array to search.
      * @param object
      *            the {@code Object} element to find.
      * @return the non-negative index of the element, or a negative index which
      *         is {@code -index - 1} where the element would be inserted.
-     * @exception ClassCastException
+     * @throws ClassCastException
      *                if an element in the array or the search element does not
      *                implement {@code Comparable}, or cannot be compared to each other.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static int binarySearch(Object[] array, Object object) {
         if (array.length == 0) {
             return -1;
         }
-        Comparable<Object> key = (Comparable<Object>) object;
+
         int low = 0, mid = 0, high = array.length - 1, result = 0;
         while (low <= high) {
-            mid = (low + high) >> 1;
-            if ((result = key.compareTo(array[mid])) > 0) {
+            mid = (low + high) >>> 1;
+            if ((result = ((Comparable<Object>)array[mid]).compareTo(object)) < 0){
                 low = mid + 1;
             } else if (result == 0) {
                 return mid;
@@ -391,7 +388,7 @@
                 high = mid - 1;
             }
         }
-        return -mid - (result <= 0 ? 1 : 2);
+        return -mid - (result >= 0 ? 1 : 2);
     }
 
     /**
@@ -400,7 +397,7 @@
      * Searching in an unsorted array has an undefined result. It's also
      * undefined which element is found if there are multiple occurrences of the
      * same element.
-     * 
+     *
      * @param array
      *            the sorted array to search
      * @param object
@@ -409,10 +406,9 @@
      *            the {@code Comparator} sued to compare the elements.
      * @return the non-negative index of the element, or a negative index which
      *         is {@code -index - 1} where the element would be inserted.
-     * @exception ClassCastException
-     *                if an element in the array cannot be compared to the search element 
+     * @throws ClassCastException
+     *                if an element in the array cannot be compared to the search element
      *                using the {@code Comparator}.
-     * @since Android 1.0
      */
     public static <T> int binarySearch(T[] array, T object,
             Comparator<? super T> comparator) {
@@ -422,7 +418,7 @@
 
         int low = 0, mid = 0, high = array.length - 1, result = 0;
         while (low <= high) {
-            mid = (low + high) >> 1;
+            mid = (low + high) >>> 1;
             if ((result = comparator.compare(array[mid], object)) < 0) {
                 low = mid + 1;
             } else if (result == 0) {
@@ -439,19 +435,18 @@
      * ascending sorted array. Searching in an unsorted array has an undefined
      * result. It's also undefined which element is found if there are multiple
      * occurrences of the same element.
-     * 
+     *
      * @param array
      *            the sorted {@code short} array to search.
      * @param value
      *            the {@code short} element to find.
      * @return the non-negative index of the element, or a negative index which
      *         is {@code -index - 1} where the element would be inserted.
-     * @since Android 1.0
      */
     public static int binarySearch(short[] array, short value) {
         int low = 0, mid = -1, high = array.length - 1;
         while (low <= high) {
-            mid = (low + high) >> 1;
+            mid = (low + high) >>> 1;
             if (value > array[mid]) {
                 low = mid + 1;
             } else if (value == array[mid]) {
@@ -468,12 +463,11 @@
 
     /**
      * Fills the specified array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code byte} array to fill.
      * @param value
      *            the {@code byte} element.
-     * @since Android 1.0
      */
     public static void fill(byte[] array, byte value) {
         for (int i = 0; i < array.length; i++) {
@@ -483,7 +477,7 @@
 
     /**
      * Fills the specified range in the array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code byte} array to fill.
      * @param start
@@ -492,11 +486,10 @@
      *            the last + 1 index to fill.
      * @param value
      *            the {@code byte} element.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void fill(byte[] array, int start, int end, byte value) {
         // Check for null first
@@ -514,12 +507,11 @@
 
     /**
      * Fills the specified array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code short} array to fill.
      * @param value
      *            the {@code short} element.
-     * @since Android 1.0
      */
     public static void fill(short[] array, short value) {
         for (int i = 0; i < array.length; i++) {
@@ -529,7 +521,7 @@
 
     /**
      * Fills the specified range in the array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code short} array to fill.
      * @param start
@@ -538,11 +530,10 @@
      *            the last + 1 index to fill.
      * @param value
      *            the {@code short} element.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void fill(short[] array, int start, int end, short value) {
         // Check for null first
@@ -560,12 +551,11 @@
 
     /**
      * Fills the specified array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code char} array to fill.
      * @param value
      *            the {@code char} element.
-     * @since Android 1.0
      */
     public static void fill(char[] array, char value) {
         for (int i = 0; i < array.length; i++) {
@@ -575,7 +565,7 @@
 
     /**
      * Fills the specified range in the array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code char} array to fill.
      * @param start
@@ -584,11 +574,10 @@
      *            the last + 1 index to fill.
      * @param value
      *            the {@code char} element.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void fill(char[] array, int start, int end, char value) {
         // Check for null first
@@ -606,12 +595,11 @@
 
     /**
      * Fills the specified array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code int} array to fill.
      * @param value
      *            the {@code int} element.
-     * @since Android 1.0
      */
     public static void fill(int[] array, int value) {
         for (int i = 0; i < array.length; i++) {
@@ -621,7 +609,7 @@
 
     /**
      * Fills the specified range in the array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code int} array to fill.
      * @param start
@@ -630,11 +618,10 @@
      *            the last + 1 index to fill.
      * @param value
      *            the {@code int} element.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void fill(int[] array, int start, int end, int value) {
         // Check for null first
@@ -652,12 +639,11 @@
 
     /**
      * Fills the specified array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code long} array to fill.
      * @param value
      *            the {@code long} element.
-     * @since Android 1.0
      */
     public static void fill(long[] array, long value) {
         for (int i = 0; i < array.length; i++) {
@@ -667,7 +653,7 @@
 
     /**
      * Fills the specified range in the array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code long} array to fill.
      * @param start
@@ -676,11 +662,10 @@
      *            the last + 1 index to fill.
      * @param value
      *            the {@code long} element.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void fill(long[] array, int start, int end, long value) {
         // Check for null first
@@ -698,12 +683,11 @@
 
     /**
      * Fills the specified array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code float} array to fill.
      * @param value
      *            the {@code float} element.
-     * @since Android 1.0
      */
     public static void fill(float[] array, float value) {
         for (int i = 0; i < array.length; i++) {
@@ -713,7 +697,7 @@
 
     /**
      * Fills the specified range in the array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code float} array to fill.
      * @param start
@@ -722,11 +706,10 @@
      *            the last + 1 index to fill.
      * @param value
      *            the {@code float} element.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void fill(float[] array, int start, int end, float value) {
         // Check for null first
@@ -744,12 +727,11 @@
 
     /**
      * Fills the specified array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code double} array to fill.
      * @param value
      *            the {@code double} element.
-     * @since Android 1.0
      */
     public static void fill(double[] array, double value) {
         for (int i = 0; i < array.length; i++) {
@@ -759,7 +741,7 @@
 
     /**
      * Fills the specified range in the array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code double} array to fill.
      * @param start
@@ -768,11 +750,10 @@
      *            the last + 1 index to fill.
      * @param value
      *            the {@code double} element.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void fill(double[] array, int start, int end, double value) {
         // Check for null first
@@ -790,12 +771,11 @@
 
     /**
      * Fills the specified array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code boolean} array to fill.
      * @param value
      *            the {@code boolean} element.
-     * @since Android 1.0
      */
     public static void fill(boolean[] array, boolean value) {
         for (int i = 0; i < array.length; i++) {
@@ -805,7 +785,7 @@
 
     /**
      * Fills the specified range in the array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code boolean} array to fill.
      * @param start
@@ -814,11 +794,10 @@
      *            the last + 1 index to fill.
      * @param value
      *            the {@code boolean} element.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void fill(boolean[] array, int start, int end, boolean value) {
         // Check for null first
@@ -836,12 +815,11 @@
 
     /**
      * Fills the specified array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code Object} array to fill.
      * @param value
      *            the {@code Object} element.
-     * @since Android 1.0
      */
     public static void fill(Object[] array, Object value) {
         for (int i = 0; i < array.length; i++) {
@@ -851,7 +829,7 @@
 
     /**
      * Fills the specified range in the array with the specified element.
-     * 
+     *
      * @param array
      *            the {@code Object} array to fill.
      * @param start
@@ -860,11 +838,10 @@
      *            the last + 1 index to fill.
      * @param value
      *            the {@code Object} element.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void fill(Object[] array, int start, int end, Object value) {
         // Check for null first
@@ -882,7 +859,7 @@
 
     /**
      * Returns a hash code based on the contents of the given array. For any two
-     * {@code boolean} arrays {@code a} and {@code b}, if 
+     * {@code boolean} arrays {@code a} and {@code b}, if
      * {@code Arrays.equals(a, b)} returns {@code true}, it means
      * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
      * <p>
@@ -891,11 +868,10 @@
      * containing a sequence of {@link Boolean}} instances representing the
      * elements of array in the same order. If the array is {@code null}, the return
      * value is 0.
-     * 
+     *
      * @param array
      *            the array whose hash code to compute.
      * @return the hash code for {@code array}.
-     * @since Android 1.0
      */
     public static int hashCode(boolean[] array) {
         if (array == null) {
@@ -911,7 +887,7 @@
 
     /**
      * Returns a hash code based on the contents of the given array. For any two
-     * not-null {@code int} arrays {@code a} and {@code b}, if 
+     * not-null {@code int} arrays {@code a} and {@code b}, if
      * {@code Arrays.equals(a, b)} returns {@code true}, it means
      * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
      * <p>
@@ -920,11 +896,10 @@
      * containing a sequence of {@link Integer}} instances representing the
      * elements of array in the same order. If the array is {@code null}, the return
      * value is 0.
-     * 
+     *
      * @param array
      *            the array whose hash code to compute.
      * @return the hash code for {@code array}.
-     * @since Android 1.0
      */
     public static int hashCode(int[] array) {
         if (array == null) {
@@ -940,7 +915,7 @@
 
     /**
      * Returns a hash code based on the contents of the given array. For any two
-     * {@code short} arrays {@code a} and {@code b}, if 
+     * {@code short} arrays {@code a} and {@code b}, if
      * {@code Arrays.equals(a, b)} returns {@code true}, it means
      * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
      * <p>
@@ -949,11 +924,10 @@
      * containing a sequence of {@link Short}} instances representing the
      * elements of array in the same order. If the array is {@code null}, the return
      * value is 0.
-     * 
+     *
      * @param array
      *            the array whose hash code to compute.
      * @return the hash code for {@code array}.
-     * @since Android 1.0
      */
     public static int hashCode(short[] array) {
         if (array == null) {
@@ -969,7 +943,7 @@
 
     /**
      * Returns a hash code based on the contents of the given array. For any two
-     * {@code char} arrays {@code a} and {@code b}, if 
+     * {@code char} arrays {@code a} and {@code b}, if
      * {@code Arrays.equals(a, b)} returns {@code true}, it means
      * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
      * <p>
@@ -978,11 +952,10 @@
      * containing a sequence of {@link Character}} instances representing the
      * elements of array in the same order. If the array is {@code null}, the return
      * value is 0.
-     * 
+     *
      * @param array
      *            the array whose hash code to compute.
      * @return the hash code for {@code array}.
-     * @since Android 1.0
      */
     public static int hashCode(char[] array) {
         if (array == null) {
@@ -998,7 +971,7 @@
 
     /**
      * Returns a hash code based on the contents of the given array. For any two
-     * {@code byte} arrays {@code a} and {@code b}, if 
+     * {@code byte} arrays {@code a} and {@code b}, if
      * {@code Arrays.equals(a, b)} returns {@code true}, it means
      * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
      * <p>
@@ -1007,11 +980,10 @@
      * containing a sequence of {@link Byte}} instances representing the
      * elements of array in the same order. If the array is {@code null}, the return
      * value is 0.
-     * 
+     *
      * @param array
      *            the array whose hash code to compute.
      * @return the hash code for {@code array}.
-     * @since Android 1.0
      */
     public static int hashCode(byte[] array) {
         if (array == null) {
@@ -1027,7 +999,7 @@
 
     /**
      * Returns a hash code based on the contents of the given array. For any two
-     * {@code long} arrays {@code a} and {@code b}, if 
+     * {@code long} arrays {@code a} and {@code b}, if
      * {@code Arrays.equals(a, b)} returns {@code true}, it means
      * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
      * <p>
@@ -1036,11 +1008,10 @@
      * containing a sequence of {@link Long}} instances representing the
      * elements of array in the same order. If the array is {@code null}, the return
      * value is 0.
-     * 
+     *
      * @param array
      *            the array whose hash code to compute.
      * @return the hash code for {@code array}.
-     * @since Android 1.0
      */
     public static int hashCode(long[] array) {
         if (array == null) {
@@ -1060,7 +1031,7 @@
 
     /**
      * Returns a hash code based on the contents of the given array. For any two
-     * {@code float} arrays {@code a} and {@code b}, if 
+     * {@code float} arrays {@code a} and {@code b}, if
      * {@code Arrays.equals(a, b)} returns {@code true}, it means
      * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
      * <p>
@@ -1069,11 +1040,10 @@
      * containing a sequence of {@link Float}} instances representing the
      * elements of array in the same order. If the array is {@code null}, the return
      * value is 0.
-     * 
+     *
      * @param array
      *            the array whose hash code to compute.
      * @return the hash code for {@code array}.
-     * @since Android 1.0
      */
     public static int hashCode(float[] array) {
         if (array == null) {
@@ -1092,7 +1062,7 @@
 
     /**
      * Returns a hash code based on the contents of the given array. For any two
-     * {@code double} arrays {@code a} and {@code b}, if 
+     * {@code double} arrays {@code a} and {@code b}, if
      * {@code Arrays.equals(a, b)} returns {@code true}, it means
      * that the return value of {@code Arrays.hashCode(a)} equals {@code Arrays.hashCode(b)}.
      * <p>
@@ -1101,11 +1071,10 @@
      * containing a sequence of {@link Double}} instances representing the
      * elements of array in the same order. If the array is {@code null}, the return
      * value is 0.
-     * 
+     *
      * @param array
      *            the array whose hash code to compute.
      * @return the hash code for {@code array}.
-     * @since Android 1.0
      */
     public static int hashCode(double[] array) {
         if (array == null) {
@@ -1131,19 +1100,18 @@
      * method on an array that contains itself as an element, either directly or
      * indirectly.
      * <p>
-     * For any two arrays {@code a} and {@code b}, if 
+     * For any two arrays {@code a} and {@code b}, if
      * {@code Arrays.equals(a, b)} returns {@code true}, it means
-     * that the return value of {@code Arrays.hashCode(a)} equals 
+     * that the return value of {@code Arrays.hashCode(a)} equals
      * {@code Arrays.hashCode(b)}.
      * <p>
      * The value returned by this method is the same value as the method
      * Arrays.asList(array).hashCode(). If the array is {@code null}, the return value
      * is 0.
-     * 
+     *
      * @param array
      *            the array whose hash code to compute.
      * @return the hash code for {@code array}.
-     * @since Android 1.0
      */
     public static int hashCode(Object[] array) {
         if (array == null) {
@@ -1170,7 +1138,7 @@
      * this method on an array that contains itself as an element, either
      * directly or indirectly.
      * <p>
-     * For any two arrays {@code a} and {@code b}, if 
+     * For any two arrays {@code a} and {@code b}, if
      * {@code Arrays.deepEquals(a, b)} returns {@code true}, it
      * means that the return value of {@code Arrays.deepHashCode(a)} equals
      * {@code Arrays.deepHashCode(b)}.
@@ -1185,11 +1153,10 @@
      * an array of a reference type. The value returned by this method is the
      * same value as the method {@code Arrays.asList(array).hashCode()}. If the array is
      * {@code null}, the return value is 0.
-     * 
+     *
      * @param array
      *            the array whose hash code to compute.
      * @return the hash code for {@code array}.
-     * @since Android 1.0
      */
     public static int deepHashCode(Object[] array) {
         if (array == null) {
@@ -1247,7 +1214,7 @@
 
     /**
      * Compares the two arrays.
-     * 
+     *
      * @param array1
      *            the first {@code byte} array.
      * @param array2
@@ -1255,7 +1222,6 @@
      * @return {@code true} if both arrays are {@code null} or if the arrays have the
      *         same length and the elements at each index in the two arrays are
      *         equal, {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean equals(byte[] array1, byte[] array2) {
         if (array1 == array2) {
@@ -1274,7 +1240,7 @@
 
     /**
      * Compares the two arrays.
-     * 
+     *
      * @param array1
      *            the first {@code short} array.
      * @param array2
@@ -1282,7 +1248,6 @@
      * @return {@code true} if both arrays are {@code null} or if the arrays have the
      *         same length and the elements at each index in the two arrays are
      *         equal, {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean equals(short[] array1, short[] array2) {
         if (array1 == array2) {
@@ -1301,7 +1266,7 @@
 
     /**
      * Compares the two arrays.
-     * 
+     *
      * @param array1
      *            the first {@code char} array.
      * @param array2
@@ -1309,7 +1274,6 @@
      * @return {@code true} if both arrays are {@code null} or if the arrays have the
      *         same length and the elements at each index in the two arrays are
      *         equal, {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean equals(char[] array1, char[] array2) {
         if (array1 == array2) {
@@ -1328,7 +1292,7 @@
 
     /**
      * Compares the two arrays.
-     * 
+     *
      * @param array1
      *            the first {@code int} array.
      * @param array2
@@ -1336,7 +1300,6 @@
      * @return {@code true} if both arrays are {@code null} or if the arrays have the
      *         same length and the elements at each index in the two arrays are
      *         equal, {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean equals(int[] array1, int[] array2) {
         if (array1 == array2) {
@@ -1355,7 +1318,7 @@
 
     /**
      * Compares the two arrays.
-     * 
+     *
      * @param array1
      *            the first {@code long} array.
      * @param array2
@@ -1363,7 +1326,6 @@
      * @return {@code true} if both arrays are {@code null} or if the arrays have the
      *         same length and the elements at each index in the two arrays are
      *         equal, {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean equals(long[] array1, long[] array2) {
         if (array1 == array2) {
@@ -1383,7 +1345,7 @@
     /**
      * Compares the two arrays. The values are compared in the same manner as
      * {@code Float.equals()}.
-     * 
+     *
      * @param array1
      *            the first {@code float} array.
      * @param array2
@@ -1392,7 +1354,6 @@
      *         same length and the elements at each index in the two arrays are
      *         equal, {@code false} otherwise.
      * @see Float#equals(Object)
-     * @since Android 1.0
      */
     public static boolean equals(float[] array1, float[] array2) {
         if (array1 == array2) {
@@ -1413,7 +1374,7 @@
     /**
      * Compares the two arrays. The values are compared in the same manner as
      * {@code Double.equals()}.
-     * 
+     *
      * @param array1
      *            the first {@code double} array.
      * @param array2
@@ -1422,7 +1383,6 @@
      *         same length and the elements at each index in the two arrays are
      *         equal, {@code false} otherwise.
      * @see Double#equals(Object)
-     * @since Android 1.0
      */
     public static boolean equals(double[] array1, double[] array2) {
         if (array1 == array2) {
@@ -1442,7 +1402,7 @@
 
     /**
      * Compares the two arrays.
-     * 
+     *
      * @param array1
      *            the first {@code boolean} array.
      * @param array2
@@ -1450,7 +1410,6 @@
      * @return {@code true} if both arrays are {@code null} or if the arrays have the
      *         same length and the elements at each index in the two arrays are
      *         equal, {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean equals(boolean[] array1, boolean[] array2) {
         if (array1 == array2) {
@@ -1469,7 +1428,7 @@
 
     /**
      * Compares the two arrays.
-     * 
+     *
      * @param array1
      *            the first {@code Object} array.
      * @param array2
@@ -1477,7 +1436,6 @@
      * @return {@code true} if both arrays are {@code null} or if the arrays have the
      *         same length and the elements at each index in the two arrays are
      *         equal according to {@code equals()}, {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean equals(Object[] array1, Object[] array2) {
         if (array1 == array2) {
@@ -1522,7 +1480,7 @@
      * <p>
      * If either of the given arrays contain themselves as elements, the
      * behavior of this method is uncertain.
-     * 
+     *
      * @param array1
      *            the first {@code Object} array.
      * @param array2
@@ -1530,7 +1488,6 @@
      * @return {@code true} if both arrays are {@code null} or if the arrays have the
      *         same length and the elements at each index in the two arrays are
      *         equal according to {@code equals()}, {@code false} otherwise.
-     * @since Android 1.0
      */
     public static boolean deepEquals(Object[] array1, Object[] array2) {
         if (array1 == array2) {
@@ -1603,41 +1560,58 @@
     }
 
     private static boolean lessThan(double double1, double double2) {
-        long d1, d2;
-        long NaNbits = Double.doubleToLongBits(Double.NaN);
-        if ((d1 = Double.doubleToLongBits(double1)) == NaNbits) {
-            return false;
-        }
-        if ((d2 = Double.doubleToLongBits(double2)) == NaNbits) {
+        // A slightly specialized version of
+        // Double.compare(double1, double2) < 0.
+
+        // Non-zero and non-NaN checking.
+        if (double1 < double2) {
             return true;
         }
-        if (double1 == double2) {
-            if (d1 == d2) {
-                return false;
-            }
-            // check for -0
-            return d1 < d2;
+        if (double1 > double2) {
+            return false;
         }
-        return double1 < double2;
+        if (double1 == double2 && 0.0d != double1) {
+            return false;
+        }
+
+        // NaNs are equal to other NaNs and larger than any other double.
+        if (Double.isNaN(double1)) {
+            return false;
+        } else if (Double.isNaN(double2)) {
+            return true;
+        }
+
+        // Deal with +0.0 and -0.0.
+        long d1 = Double.doubleToRawLongBits(double1);
+        long d2 = Double.doubleToRawLongBits(double2);
+        return d1 < d2;
     }
 
     private static boolean lessThan(float float1, float float2) {
-        int f1, f2;
-        int NaNbits = Float.floatToIntBits(Float.NaN);
-        if ((f1 = Float.floatToIntBits(float1)) == NaNbits) {
-            return false;
-        }
-        if ((f2 = Float.floatToIntBits(float2)) == NaNbits) {
+        // A slightly specialized version of Float.compare(float1, float2) < 0.
+
+        // Non-zero and non-NaN checking.
+        if (float1 < float2) {
             return true;
         }
-        if (float1 == float2) {
-            if (f1 == f2) {
-                return false;
-            }
-            // check for -0
-            return f1 < f2;
+        if (float1 > float2) {
+            return false;
         }
-        return float1 < float2;
+        if (float1 == float2 && 0.0f != float1) {
+            return false;
+        }
+
+        // NaNs are equal to other NaNs and larger than any other float
+        if (Float.isNaN(float1)) {
+            return false;
+        } else if (Float.isNaN(float2)) {
+            return true;
+        }
+
+        // Deal with +0.0 and -0.0
+        int f1 = Float.floatToRawIntBits(float1);
+        int f2 = Float.floatToRawIntBits(float2);
+        return f1 < f2;
     }
 
     private static int med3(byte[] array, int a, int b, int c) {
@@ -1684,10 +1658,9 @@
 
     /**
      * Sorts the specified array in ascending numerical order.
-     * 
+     *
      * @param array
      *            the {@code byte} array to be sorted.
-     * @since Android 1.0
      */
     public static void sort(byte[] array) {
         sort(0, array.length, array);
@@ -1695,18 +1668,17 @@
 
     /**
      * Sorts the specified range in the array in ascending numerical order.
-     * 
+     *
      * @param array
      *            the {@code byte} array to be sorted.
      * @param start
      *            the start index to sort.
      * @param end
      *            the last + 1 index to sort.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void sort(byte[] array, int start, int end) {
         if (array == null) {
@@ -1718,8 +1690,8 @@
 
     private static void checkBounds(int arrLength, int start, int end) {
         if (start > end) {
-            throw new IllegalArgumentException("fromIndex(" + start //$NON-NLS-1$
-                    + ") > toIndex(" + end + ")"); //$NON-NLS-1$ //$NON-NLS-2$
+            throw new IllegalArgumentException("start(" + start //$NON-NLS-1$
+                    + ") > end(" + end + ")"); //$NON-NLS-1$ //$NON-NLS-2$
         }
         if (start < 0 || end > arrLength) {
             throw new ArrayIndexOutOfBoundsException();
@@ -1806,10 +1778,9 @@
 
     /**
      * Sorts the specified array in ascending numerical order.
-     * 
+     *
      * @param array
      *            the {@code char} array to be sorted.
-     * @since Android 1.0
      */
     public static void sort(char[] array) {
         sort(0, array.length, array);
@@ -1817,18 +1788,17 @@
 
     /**
      * Sorts the specified range in the array in ascending numerical order.
-     * 
+     *
      * @param array
      *            the {@code char} array to be sorted.
      * @param start
      *            the start index to sort.
      * @param end
      *            the last + 1 index to sort.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void sort(char[] array, int start, int end) {
         if (array == null) {
@@ -1918,11 +1888,10 @@
 
     /**
      * Sorts the specified array in ascending numerical order.
-     * 
+     *
      * @param array
      *            the {@code double} array to be sorted.
      * @see #sort(double[], int, int)
-     * @since Android 1.0
      */
     public static void sort(double[] array) {
         sort(0, array.length, array);
@@ -1931,19 +1900,18 @@
     /**
      * Sorts the specified range in the array in ascending numerical order. The
      * values are sorted according to the order imposed by {@code Double.compareTo()}.
-     * 
+     *
      * @param array
      *            the {@code double} array to be sorted.
      * @param start
      *            the start index to sort.
      * @param end
      *            the last + 1 index to sort.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
      * @see Double#compareTo(Double)
-     * @since Android 1.0
      */
     public static void sort(double[] array, int start, int end) {
         if (array == null) {
@@ -2033,11 +2001,10 @@
 
     /**
      * Sorts the specified array in ascending numerical order.
-     * 
+     *
      * @param array
      *            the {@code float} array to be sorted.
      * @see #sort(float[], int, int)
-     * @since Android 1.0
      */
     public static void sort(float[] array) {
         sort(0, array.length, array);
@@ -2046,19 +2013,18 @@
     /**
      * Sorts the specified range in the array in ascending numerical order. The
      * values are sorted according to the order imposed by {@code Float.compareTo()}.
-     * 
+     *
      * @param array
      *            the {@code float} array to be sorted.
      * @param start
      *            the start index to sort.
      * @param end
      *            the last + 1 index to sort.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
      * @see Float#compareTo(Float)
-     * @since Android 1.0
      */
     public static void sort(float[] array, int start, int end) {
         if (array == null) {
@@ -2148,10 +2114,9 @@
 
     /**
      * Sorts the specified array in ascending numerical order.
-     * 
+     *
      * @param array
      *            the {@code int} array to be sorted.
-     * @since Android 1.0
      */
     public static void sort(int[] array) {
         sort(0, array.length, array);
@@ -2159,18 +2124,17 @@
 
     /**
      * Sorts the specified range in the array in ascending numerical order.
-     * 
+     *
      * @param array
      *            the {@code int} array to be sorted.
      * @param start
      *            the start index to sort.
      * @param end
      *            the last + 1 index to sort.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void sort(int[] array, int start, int end) {
         if (array == null) {
@@ -2260,10 +2224,9 @@
 
     /**
      * Sorts the specified array in ascending numerical order.
-     * 
+     *
      * @param array
      *            the {@code long} array to be sorted.
-     * @since Android 1.0
      */
     public static void sort(long[] array) {
         sort(0, array.length, array);
@@ -2271,18 +2234,17 @@
 
     /**
      * Sorts the specified range in the array in ascending numerical order.
-     * 
+     *
      * @param array
      *            the {@code long} array to be sorted.
      * @param start
      *            the start index to sort.
      * @param end
      *            the last + 1 index to sort.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void sort(long[] array, int start, int end) {
         if (array == null) {
@@ -2370,7 +2332,7 @@
         }
     }
 
-// BEGIN android-changed
+// BEGIN android-note
 
     /*
      * <p>If this platform has an optimizing VM, check whether ComparableTimSort
@@ -2405,19 +2367,22 @@
 //        sort(a, fromIndex, toIndex, NATURAL_ORDER);
 //    }
 
+// END android-note
+
     /**
      * Sorts the specified array in ascending natural order.
-     * 
+     *
      * @param array
      *            the {@code Object} array to be sorted.
-     * @exception ClassCastException
+     * @throws ClassCastException
      *                if an element in the array does not implement {@code Comparable}
      *                or if some elements cannot be compared to each other.
      * @see #sort(Object[], int, int)
-     * @since Android 1.0
      */
     public static void sort(Object[] array) {
+        // BEGIN android-changed
         ComparableTimSort.sort(array);
+        // END android-changed
     }
 
     /**
@@ -2425,31 +2390,76 @@
      * elements must implement the {@code Comparable} interface and must be
      * comparable to each other without a {@code ClassCastException} being
      * thrown.
-     * 
+     *
      * @param array
      *            the {@code Object} array to be sorted.
      * @param start
      *            the start index to sort.
      * @param end
      *            the last + 1 index to sort.
-     * @exception ClassCastException
+     * @throws ClassCastException
      *                if an element in the array does not implement {@code Comparable}
      *                or some elements cannot be compared to each other.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void sort(Object[] array, int start, int end) {
+        // BEGIN android-changed
         ComparableTimSort.sort(array, start, end);
+        // END android-changed
     }
 
+    // BEGIN android-removed
+    /*
+    private static void sort(int start, int end, Object[] array) {
+            ...
+    }
+    private static void swap(int a, int b, Object[] arr) {
+            ...
+    }
+    private static void mergeSort(Object[] in, Object[] out, int start,
+            int end) {
+            ...
+    }
+    private static void mergeSort(Object[] in, Object[] out, int start,
+            int end, Comparator c) {
+            ...
+    }
+    private static int find(Object[] arr, Comparable val, int bnd, int l, int r) {
+            ...
+    }
+    private static int find(Object[] arr, Object val, int bnd, int l, int r,
+            Comparator c) {
+            ...
+    }
+    private static int medChar(int a, int b, int c, String[] arr, int id) {
+            ...
+    }
+    private static int charAt(String str, int i) {
+            ...
+    }
+    private static void copySwap(Object[] src, int from, Object[] dst, int to,
+            int len) {
+            ...
+    }
+    private static void stableStringSort(String[] arr, int start,
+            int end) {
+            ...
+    }
+    private static void stableStringSort(String[] arr, String[] src,
+            String[] dst, int start, int end, int chId) {
+            ...
+    }
+    */
+    // END android-removed
+
     /**
      * Sorts the specified range in the array using the specified {@code Comparator}.
      * All elements must be comparable to each other without a
      * {@code ClassCastException} being thrown.
-     * 
+     *
      * @param array
      *            the {@code Object} array to be sorted.
      * @param start
@@ -2458,45 +2468,44 @@
      *            the last + 1 index to sort.
      * @param comparator
      *            the {@code Comparator}.
-     * @exception ClassCastException
+     * @throws ClassCastException
      *                if elements in the array cannot be compared to each other
      *                using the {@code Comparator}.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static <T> void sort(T[] array, int start, int end,
             Comparator<? super T> comparator) {
+        // BEGIN android-changed
         TimSort.sort(array, start, end, comparator);
+        // END android-changed
     }
 
     /**
      * Sorts the specified array using the specified {@code Comparator}. All elements
      * must be comparable to each other without a {@code ClassCastException} being thrown.
-     * 
+     *
      * @param array
      *            the {@code Object} array to be sorted.
      * @param comparator
      *            the {@code Comparator}.
-     * @exception ClassCastException
+     * @throws ClassCastException
      *                if elements in the array cannot be compared to each other
      *                using the {@code Comparator}.
-     * @since Android 1.0
      */
     public static <T> void sort(T[] array, Comparator<? super T> comparator) {
+        // BEGIN android-changed
         TimSort.sort(array, comparator);
+        // END android-changed
     }
 
-// END  android-changed
-
     /**
      * Sorts the specified array in ascending numerical order.
-     * 
+     *
      * @param array
      *            the {@code short} array to be sorted.
-     * @since Android 1.0
      */
     public static void sort(short[] array) {
         sort(0, array.length, array);
@@ -2504,18 +2513,17 @@
 
     /**
      * Sorts the specified range in the array in ascending numerical order.
-     * 
+     *
      * @param array
      *            the {@code short} array to be sorted.
      * @param start
      *            the start index to sort.
      * @param end
      *            the last + 1 index to sort.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code start > end}.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if {@code start < 0} or {@code end > array.length}.
-     * @since Android 1.0
      */
     public static void sort(short[] array, int start, int end) {
         if (array == null) {
@@ -2604,18 +2612,16 @@
     }
 
     /**
-     * <p>
      * Creates a {@code String} representation of the {@code boolean[]} passed.
      * The result is surrounded by brackets ({@code &quot;[]&quot;}), each
      * element is converted to a {@code String} via the
      * {@link String#valueOf(boolean)} and separated by {@code &quot;, &quot;}.
      * If the array is {@code null}, then {@code &quot;null&quot;} is returned.
-     * </p>
-     * 
+     *
      * @param array
      *            the {@code boolean} array to convert.
      * @return the {@code String} representation of {@code array}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String toString(boolean[] array) {
         if (array == null) {
@@ -2636,18 +2642,16 @@
     }
 
     /**
-     * <p>
      * Creates a {@code String} representation of the {@code byte[]} passed. The
      * result is surrounded by brackets ({@code &quot;[]&quot;}), each element
      * is converted to a {@code String} via the {@link String#valueOf(int)} and
      * separated by {@code &quot;, &quot;}. If the array is {@code null}, then
      * {@code &quot;null&quot;} is returned.
-     * </p>
-     * 
+     *
      * @param array
      *            the {@code byte} array to convert.
      * @return the {@code String} representation of {@code array}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String toString(byte[] array) {
         if (array == null) {
@@ -2668,18 +2672,16 @@
     }
 
     /**
-     * <p>
      * Creates a {@code String} representation of the {@code char[]} passed. The
      * result is surrounded by brackets ({@code &quot;[]&quot;}), each element
      * is converted to a {@code String} via the {@link String#valueOf(char)} and
      * separated by {@code &quot;, &quot;}. If the array is {@code null}, then
      * {@code &quot;null&quot;} is returned.
-     * </p>
-     * 
+     *
      * @param array
      *            the {@code char} array to convert.
      * @return the {@code String} representation of {@code array}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String toString(char[] array) {
         if (array == null) {
@@ -2700,18 +2702,16 @@
     }
 
     /**
-     * <p>
      * Creates a {@code String} representation of the {@code double[]} passed.
      * The result is surrounded by brackets ({@code &quot;[]&quot;}), each
      * element is converted to a {@code String} via the
      * {@link String#valueOf(double)} and separated by {@code &quot;, &quot;}.
      * If the array is {@code null}, then {@code &quot;null&quot;} is returned.
-     * </p>
-     * 
+     *
      * @param array
      *            the {@code double} array to convert.
      * @return the {@code String} representation of {@code array}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String toString(double[] array) {
         if (array == null) {
@@ -2732,18 +2732,16 @@
     }
 
     /**
-     * <p>
      * Creates a {@code String} representation of the {@code float[]} passed.
      * The result is surrounded by brackets ({@code &quot;[]&quot;}), each
      * element is converted to a {@code String} via the
      * {@link String#valueOf(float)} and separated by {@code &quot;, &quot;}.
      * If the array is {@code null}, then {@code &quot;null&quot;} is returned.
-     * </p>
-     * 
+     *
      * @param array
      *            the {@code float} array to convert.
      * @return the {@code String} representation of {@code array}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String toString(float[] array) {
         if (array == null) {
@@ -2764,18 +2762,16 @@
     }
 
     /**
-     * <p>
      * Creates a {@code String} representation of the {@code int[]} passed. The
      * result is surrounded by brackets ({@code &quot;[]&quot;}), each element
      * is converted to a {@code String} via the {@link String#valueOf(int)} and
      * separated by {@code &quot;, &quot;}. If the array is {@code null}, then
      * {@code &quot;null&quot;} is returned.
-     * </p>
-     * 
+     *
      * @param array
      *            the {@code int} array to convert.
      * @return the {@code String} representation of {@code array}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String toString(int[] array) {
         if (array == null) {
@@ -2796,18 +2792,16 @@
     }
 
     /**
-     * <p>
      * Creates a {@code String} representation of the {@code long[]} passed. The
      * result is surrounded by brackets ({@code &quot;[]&quot;}), each element
      * is converted to a {@code String} via the {@link String#valueOf(long)} and
      * separated by {@code &quot;, &quot;}. If the array is {@code null}, then
      * {@code &quot;null&quot;} is returned.
-     * </p>
-     * 
+     *
      * @param array
      *            the {@code long} array to convert.
      * @return the {@code String} representation of {@code array}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String toString(long[] array) {
         if (array == null) {
@@ -2828,18 +2822,16 @@
     }
 
     /**
-     * <p>
      * Creates a {@code String} representation of the {@code short[]} passed.
      * The result is surrounded by brackets ({@code &quot;[]&quot;}), each
      * element is converted to a {@code String} via the
      * {@link String#valueOf(int)} and separated by {@code &quot;, &quot;}. If
      * the array is {@code null}, then {@code &quot;null&quot;} is returned.
-     * </p>
-     * 
+     *
      * @param array
      *            the {@code short} array to convert.
      * @return the {@code String} representation of {@code array}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String toString(short[] array) {
         if (array == null) {
@@ -2860,18 +2852,16 @@
     }
 
     /**
-     * <p>
      * Creates a {@code String} representation of the {@code Object[]} passed.
      * The result is surrounded by brackets ({@code &quot;[]&quot;}), each
      * element is converted to a {@code String} via the
      * {@link String#valueOf(Object)} and separated by {@code &quot;, &quot;}.
      * If the array is {@code null}, then {@code &quot;null&quot;} is returned.
-     * </p>
-     * 
+     *
      * @param array
      *            the {@code Object} array to convert.
      * @return the {@code String} representation of {@code array}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String toString(Object[] array) {
         if (array == null) {
@@ -2892,11 +2882,9 @@
     }
 
     /**
-     * <p>
      * Creates a <i>"deep"</i> {@code String} representation of the
      * {@code Object[]} passed, such that if the array contains other arrays,
      * the {@code String} representation of those arrays is generated as well.
-     * </p>
      * <p>
      * If any of the elements are primitive arrays, the generation is delegated
      * to the other {@code toString} methods in this class. If any element
@@ -2904,12 +2892,11 @@
      * as {@code "[...]"}. If an element is an {@code Object[]}, then its
      * representation is generated by a recursive call to this method. All other
      * elements are converted via the {@link String#valueOf(Object)} method.
-     * </p>
-     * 
+     *
      * @param array
      *            the {@code Object} array to convert.
      * @return the {@code String} representation of {@code array}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static String deepToString(Object[] array) {
         // Special case null to prevent NPE
@@ -2923,10 +2910,8 @@
     }
 
     /**
-     * <p>
      * Implementation method used by {@link #deepToString(Object[])}.
-     * </p>
-     * 
+     *
      * @param array
      *            the {@code Object[]} to dive into.
      * @param origArrays
@@ -3010,11 +2995,9 @@
     }
 
     /**
-     * <p>
      * Utility method used to assist the implementation of
      * {@link #deepToString(Object[])}.
-     * </p>
-     * 
+     *
      * @param origArrays
      *            An array of Object[] references.
      * @param array
diff --git a/libcore/luni/src/main/java/java/util/BitSet.java b/libcore/luni/src/main/java/java/util/BitSet.java
index aa60be0..4e01cbf 100644
--- a/libcore/luni/src/main/java/java/util/BitSet.java
+++ b/libcore/luni/src/main/java/java/util/BitSet.java
@@ -17,6 +17,8 @@
 
 package java.util;
 
+import java.io.IOException;
+import java.io.ObjectInputStream;
 import java.io.Serializable;
 
 import org.apache.harmony.luni.util.Msg;
@@ -26,20 +28,43 @@
  * {@code BitSet} can be on(1) or off(0). A {@code BitSet} is created with a
  * given size and grows if this size is exceeded. Growth is always rounded to a
  * 64 bit boundary.
- *  
- * @since Android 1.0
  */
 public class BitSet implements Serializable, Cloneable {
     private static final long serialVersionUID = 7997698588986878753L;
 
-    // Size in bits of the data type being used in the bits array
-    private static final int ELM_SIZE = 64;
+    private static final int OFFSET = 6;
+
+    private static final int ELM_SIZE = 1 << OFFSET;
+
+    private static final int RIGHT_BITS = ELM_SIZE - 1;
+
+    private static final long[] TWO_N_ARRAY = new long[] { 0x1L, 0x2L, 0x4L,
+            0x8L, 0x10L, 0x20L, 0x40L, 0x80L, 0x100L, 0x200L, 0x400L, 0x800L,
+            0x1000L, 0x2000L, 0x4000L, 0x8000L, 0x10000L, 0x20000L, 0x40000L,
+            0x80000L, 0x100000L, 0x200000L, 0x400000L, 0x800000L, 0x1000000L,
+            0x2000000L, 0x4000000L, 0x8000000L, 0x10000000L, 0x20000000L,
+            0x40000000L, 0x80000000L, 0x100000000L, 0x200000000L, 0x400000000L,
+            0x800000000L, 0x1000000000L, 0x2000000000L, 0x4000000000L,
+            0x8000000000L, 0x10000000000L, 0x20000000000L, 0x40000000000L,
+            0x80000000000L, 0x100000000000L, 0x200000000000L, 0x400000000000L,
+            0x800000000000L, 0x1000000000000L, 0x2000000000000L,
+            0x4000000000000L, 0x8000000000000L, 0x10000000000000L,
+            0x20000000000000L, 0x40000000000000L, 0x80000000000000L,
+            0x100000000000000L, 0x200000000000000L, 0x400000000000000L,
+            0x800000000000000L, 0x1000000000000000L, 0x2000000000000000L,
+            0x4000000000000000L, 0x8000000000000000L };
 
     private long[] bits;
 
+    private transient boolean needClear;
+
+    private transient int actualArrayLength;
+
+    private transient boolean isLengthActual;
+
     /**
      * Create a new {@code BitSet} with size equal to 64 bits.
-     * 
+     *
      * @see #clear(int)
      * @see #set(int)
      * @see #clear()
@@ -47,17 +72,18 @@
      * @see #set(int, boolean)
      * @see #set(int, int)
      * @see #set(int, int, boolean)
-     * @since Android 1.0
      */
     public BitSet() {
-        this(64);
+        bits = new long[1];
+        actualArrayLength = 0;
+        isLengthActual = true;
     }
 
     /**
      * Create a new {@code BitSet} with size equal to nbits. If nbits is not a
      * multiple of 64, then create a {@code BitSet} with size nbits rounded to
      * the next closest multiple of 64.
-     * 
+     *
      * @param nbits
      *            the size of the bit set.
      * @throws NegativeArraySizeException
@@ -69,31 +95,34 @@
      * @see #set(int, boolean)
      * @see #set(int, int)
      * @see #set(int, int, boolean)
-     * @since Android 1.0
      */
     public BitSet(int nbits) {
-        if (nbits >= 0) {
-            bits = new long[(nbits / ELM_SIZE) + (nbits % ELM_SIZE > 0 ? 1 : 0)];
-        } else {
+        if (nbits < 0) {
             throw new NegativeArraySizeException();
         }
+        bits = new long[(nbits >> OFFSET) + ((nbits & RIGHT_BITS) > 0 ? 1 : 0)];
+        actualArrayLength = 0;
+        isLengthActual = true;
     }
 
     /**
      * Private constructor called from get(int, int) method
-     * 
+     *
      * @param bits
      *            the size of the bit set
      */
-    private BitSet(long[] bits) {
+    private BitSet(long[] bits, boolean needClear, int actualArrayLength,
+            boolean isLengthActual) {
         this.bits = bits;
+        this.needClear = needClear;
+        this.actualArrayLength = actualArrayLength;
+        this.isLengthActual = isLengthActual;
     }
 
     /**
      * Creates a copy of this {@code BitSet}.
-     * 
+     *
      * @return a copy of this {@code BitSet}.
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -110,13 +139,12 @@
      * Compares the argument to this {@code BitSet} and returns whether they are
      * equal. The object must be an instance of {@code BitSet} with the same
      * bits set.
-     * 
+     *
      * @param obj
      *            the {@code BitSet} object to compare.
      * @return a {@code boolean} indicating whether or not this {@code BitSet} and
      *         {@code obj} are equal.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object obj) {
@@ -125,10 +153,13 @@
         }
         if (obj instanceof BitSet) {
             long[] bsBits = ((BitSet) obj).bits;
-            int length1 = bits.length, length2 = bsBits.length;
+            int length1 = this.actualArrayLength, length2 = ((BitSet) obj).actualArrayLength;
+            if (this.isLengthActual && ((BitSet) obj).isLengthActual
+                    && length1 != length2) {
+                return false;
+            }
             // If one of the BitSets is larger than the other, check to see if
-            // any of
-            // its extra bits are set. If so return false.
+            // any of its extra bits are set. If so return false.
             if (length1 <= length2) {
                 for (int i = 0; i < length1; i++) {
                     if (bits[i] != bsBits[i]) {
@@ -160,35 +191,29 @@
     /**
      * Increase the size of the internal array to accommodate {@code pos} bits.
      * The new array max index will be a multiple of 64.
-     * 
-     * @param pos
+     *
+     * @param len
      *            the index the new array needs to be able to access.
-     * @since Android 1.0
      */
-    private void growBits(int pos) {
-        pos++; // Inc to get correct bit count
-        long[] tempBits = new long[(pos / ELM_SIZE)
-                + (pos % ELM_SIZE > 0 ? 1 : 0)];
-        System.arraycopy(bits, 0, tempBits, 0, bits.length);
+    private final void growLength(int len) {
+        long[] tempBits = new long[Math.max(len, bits.length * 2)];
+        System.arraycopy(bits, 0, tempBits, 0, this.actualArrayLength);
         bits = tempBits;
     }
 
     /**
      * Computes the hash code for this {@code BitSet}. If two {@code BitSet}s are equal
      * the have to return the same result for {@code hashCode()}.
-     * 
+     *
      * @return the {@code int} representing the hash code for this bit
      *         set.
      * @see #equals
      * @see java.util.Hashtable
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
         long x = 1234;
-        // for (int i = 0, length = bits.length; i < length; i+=2)
-        // x ^= (bits[i] + ((long)bits[i+1] << 32)) * (i/2 + 1);
-        for (int i = 0, length = bits.length; i < length; i++) {
+        for (int i = 0, length = actualArrayLength; i < length; i++) {
             x ^= bits[i] * (i + 1);
         }
         return (int) ((x >> 32) ^ x);
@@ -197,7 +222,7 @@
     /**
      * Retrieves the bit at index {@code pos}. Grows the {@code BitSet} if
      * {@code pos > size}.
-     * 
+     *
      * @param pos
      *            the index of the bit to be retrieved.
      * @return {@code true} if the bit at {@code pos} is set,
@@ -211,89 +236,98 @@
      * @see #set(int, boolean)
      * @see #set(int, int)
      * @see #set(int, int, boolean)
-     * @since Android 1.0
      */
     public boolean get(int pos) {
-        if (pos >= 0) {
-            if (pos < bits.length * ELM_SIZE) {
-                return (bits[pos / ELM_SIZE] & (1L << (pos % ELM_SIZE))) != 0;
-            }
-            return false;
+        if (pos < 0) {
+            // Negative index specified
+            throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
         }
-        // Negative index specified
-        throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
+
+        int arrayPos = pos >> OFFSET;
+        if (arrayPos < actualArrayLength) {
+            return (bits[arrayPos] & TWO_N_ARRAY[pos & RIGHT_BITS]) != 0;
+        }
+        return false;
     }
 
     /**
      * Retrieves the bits starting from {@code pos1} to {@code pos2} and returns
      * back a new bitset made of these bits. Grows the {@code BitSet} if
      * {@code pos2 > size}.
-     * 
+     *
      * @param pos1
-     *            beginning position.
+     *            inclusive beginning position.
      * @param pos2
-     *            ending position.
+     *            exclusive ending position.
      * @return new bitset of the range specified.
      * @throws IndexOutOfBoundsException
      *             if {@code pos1} or {@code pos2} is negative, or if
      *             {@code pos2} is smaller than {@code pos1}.
      * @see #get(int)
-     * @since Android 1.0
      */
     public BitSet get(int pos1, int pos2) {
-        if (pos1 >= 0 && pos2 >= 0 && pos2 >= pos1) {
-            int last = (bits.length * ELM_SIZE);
-            if (pos1 >= last || pos1 == pos2) {
+        if (pos1 < 0 || pos2 < 0 || pos2 < pos1) {
+            throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
+        }
+
+        int last = actualArrayLength << OFFSET;
+        if (pos1 >= last || pos1 == pos2) {
+            return new BitSet(0);
+        }
+        if (pos2 > last) {
+            pos2 = last;
+        }
+
+        int idx1 = pos1 >> OFFSET;
+        int idx2 = (pos2 - 1) >> OFFSET;
+        long factor1 = (~0L) << (pos1 & RIGHT_BITS);
+        long factor2 = (~0L) >>> (ELM_SIZE - (pos2 & RIGHT_BITS));
+
+        if (idx1 == idx2) {
+            long result = (bits[idx1] & (factor1 & factor2)) >>> (pos1 % ELM_SIZE);
+            if (result == 0) {
                 return new BitSet(0);
             }
-            if (pos2 > last) {
-                pos2 = last;
-            }
+            return new BitSet(new long[] { result }, needClear, 1, true);
+        }
+        long[] newbits = new long[idx2 - idx1 + 1];
+        // first fill in the first and last indexes in the new bitset
+        newbits[0] = bits[idx1] & factor1;
+        newbits[newbits.length - 1] = bits[idx2] & factor2;
 
-            int idx1 = pos1 / ELM_SIZE;
-            int idx2 = (pos2 - 1) / ELM_SIZE;
-            long factor1 = (~0L) << (pos1 % ELM_SIZE);
-            long factor2 = (~0L) >>> (ELM_SIZE - (pos2 % ELM_SIZE));
+        // fill in the in between elements of the new bitset
+        for (int i = 1; i < idx2 - idx1; i++) {
+            newbits[i] = bits[idx1 + i];
+        }
 
-            if (idx1 == idx2) {
-                long result = (bits[idx1] & (factor1 & factor2)) >>> (pos1 % ELM_SIZE);
-                return new BitSet(new long[] { result });
-            }
-            long[] newbits = new long[idx2 - idx1 + 1];
-            // first fill in the first and last indexes in the new bitset
-            newbits[0] = bits[idx1] & factor1;
-            newbits[newbits.length - 1] = bits[idx2] & factor2;
+        // shift all the elements in the new bitset to the right by pos1
+        // % ELM_SIZE
+        int numBitsToShift = pos1 & RIGHT_BITS;
+        int actualLen = newbits.length;
+        if (numBitsToShift != 0) {
+            for (int i = 0; i < newbits.length; i++) {
+                // shift the current element to the right regardless of
+                // sign
+                newbits[i] = newbits[i] >>> (numBitsToShift);
 
-            // fill in the in between elements of the new bitset
-            for (int i = 1; i < idx2 - idx1; i++) {
-                newbits[i] = bits[idx1 + i];
-            }
-
-            // shift all the elements in the new bitset to the right by pos1
-            // % ELM_SIZE
-            int numBitsToShift = pos1 % ELM_SIZE;
-            if (numBitsToShift != 0) {
-                for (int i = 0; i < newbits.length; i++) {
-                    // shift the current element to the right regardless of
-                    // sign
-                    newbits[i] = newbits[i] >>> (numBitsToShift);
-
-                    // apply the last x bits of newbits[i+1] to the current
-                    // element
-                    if (i != newbits.length - 1) {
-                        newbits[i] |= newbits[i + 1] << (ELM_SIZE - (numBitsToShift));
-                    }
+                // apply the last x bits of newbits[i+1] to the current
+                // element
+                if (i != newbits.length - 1) {
+                    newbits[i] |= newbits[i + 1] << (ELM_SIZE - (numBitsToShift));
+                }
+                if (newbits[i] != 0) {
+                    actualLen = i + 1;
                 }
             }
-            return new BitSet(newbits);
         }
-        throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
+        return new BitSet(newbits, needClear, actualLen,
+                newbits[actualLen - 1] != 0);
     }
 
     /**
      * Sets the bit at index {@code pos} to 1. Grows the {@code BitSet} if
      * {@code pos > size}.
-     * 
+     *
      * @param pos
      *            the index of the bit to set.
      * @throws IndexOutOfBoundsException
@@ -301,23 +335,28 @@
      * @see #clear(int)
      * @see #clear()
      * @see #clear(int, int)
-     * @since Android 1.0
      */
     public void set(int pos) {
-        if (pos >= 0) {
-            if (pos >= bits.length * ELM_SIZE) {
-                growBits(pos);
-            }
-            bits[pos / ELM_SIZE] |= 1L << (pos % ELM_SIZE);
-        } else {
+        if (pos < 0) {
             throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
         }
+
+        int len = (pos >> OFFSET) + 1;
+        if (len > bits.length) {
+            growLength(len);
+        }
+        bits[len - 1] |= TWO_N_ARRAY[pos & RIGHT_BITS];
+        if (len > actualArrayLength) {
+            actualArrayLength = len;
+            isLengthActual = true;
+        }
+        needClear();
     }
 
     /**
      * Sets the bit at index {@code pos} to {@code val}. Grows the
      * {@code BitSet} if {@code pos > size}.
-     * 
+     *
      * @param pos
      *            the index of the bit to set.
      * @param val
@@ -325,7 +364,6 @@
      * @throws IndexOutOfBoundsException
      *             if {@code pos} is negative.
      * @see #set(int)
-     * @since Android 1.0
      */
     public void set(int pos, boolean val) {
         if (val) {
@@ -338,60 +376,68 @@
     /**
      * Sets the bits starting from {@code pos1} to {@code pos2}. Grows the
      * {@code BitSet} if {@code pos2 > size}.
-     * 
+     *
      * @param pos1
-     *            beginning position.
+     *            inclusive beginning position.
      * @param pos2
-     *            ending position.
+     *            exclusive ending position.
      * @throws IndexOutOfBoundsException
      *             if {@code pos1} or {@code pos2} is negative, or if
      *             {@code pos2} is smaller than {@code pos1}.
      * @see #set(int)
-     * @since Android 1.0
      */
     public void set(int pos1, int pos2) {
-        if (pos1 >= 0 && pos2 >= 0 && pos2 >= pos1) {
-            if (pos1 == pos2) {
-                return;
-            }
-            if (pos2 >= bits.length * ELM_SIZE) {
-                growBits(pos2);
-            }
-
-            int idx1 = pos1 / ELM_SIZE;
-            int idx2 = (pos2 - 1) / ELM_SIZE;
-            long factor1 = (~0L) << (pos1 % ELM_SIZE);
-            long factor2 = (~0L) >>> (ELM_SIZE - (pos2 % ELM_SIZE));
-
-            if (idx1 == idx2) {
-                bits[idx1] |= (factor1 & factor2);
-            } else {
-                bits[idx1] |= factor1;
-                bits[idx2] |= factor2;
-                for (int i = idx1 + 1; i < idx2; i++) {
-                    bits[i] |= (~0L);
-                }
-            }
-        } else {
+        if (pos1 < 0 || pos2 < 0 || pos2 < pos1) {
             throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
         }
+
+        if (pos1 == pos2) {
+            return;
+        }
+        int len2 = ((pos2 - 1) >> OFFSET) + 1;
+        if (len2 > bits.length) {
+            growLength(len2);
+        }
+
+        int idx1 = pos1 >> OFFSET;
+        int idx2 = (pos2 - 1) >> OFFSET;
+        long factor1 = (~0L) << (pos1 & RIGHT_BITS);
+        long factor2 = (~0L) >>> (ELM_SIZE - (pos2 & RIGHT_BITS));
+
+        if (idx1 == idx2) {
+            bits[idx1] |= (factor1 & factor2);
+        } else {
+            bits[idx1] |= factor1;
+            bits[idx2] |= factor2;
+            for (int i = idx1 + 1; i < idx2; i++) {
+                bits[i] |= (~0L);
+            }
+        }
+        if (idx2 + 1 > actualArrayLength) {
+            actualArrayLength = idx2 + 1;
+            isLengthActual = true;
+        }
+        needClear();
+    }
+
+    private void needClear() {
+        this.needClear = true;
     }
 
     /**
      * Sets the bits starting from {@code pos1} to {@code pos2} to the given
      * {@code val}. Grows the {@code BitSet} if {@code pos2 > size}.
-     * 
+     *
      * @param pos1
-     *            beginning position.
+     *            inclusive beginning position.
      * @param pos2
-     *            ending position.
+     *            exclusive ending position.
      * @param val
      *            value to set these bits.
      * @throws IndexOutOfBoundsException
      *             if {@code pos1} or {@code pos2} is negative, or if
      *             {@code pos2} is smaller than {@code pos1}.
      * @see #set(int,int)
-     * @since Android 1.0
      */
     public void set(int pos1, int pos2, boolean val) {
         if (val) {
@@ -403,159 +449,183 @@
 
     /**
      * Clears all the bits in this {@code BitSet}.
-     * 
+     *
      * @see #clear(int)
      * @see #clear(int, int)
-     * @since Android 1.0
      */
     public void clear() {
-        for (int i = 0; i < bits.length; i++) {
-            bits[i] = 0L;
+        if (needClear) {
+            for (int i = 0; i < bits.length; i++) {
+                bits[i] = 0L;
+            }
+            actualArrayLength = 0;
+            isLengthActual = true;
+            needClear = false;
         }
     }
 
     /**
      * Clears the bit at index {@code pos}. Grows the {@code BitSet} if
      * {@code pos > size}.
-     * 
+     *
      * @param pos
      *            the index of the bit to clear.
      * @throws IndexOutOfBoundsException
      *             if {@code pos} is negative.
      * @see #clear(int, int)
-     * @since Android 1.0
      */
     public void clear(int pos) {
-        if (pos >= 0) {
-            if (pos < bits.length * ELM_SIZE) {
-                bits[pos / ELM_SIZE] &= ~(1L << (pos % ELM_SIZE));
-            }
-        } else {
+        if (pos < 0) {
             // Negative index specified
             throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
         }
+
+        if (!needClear) {
+            return;
+        }
+        int arrayPos = pos >> OFFSET;
+        if (arrayPos < actualArrayLength) {
+            bits[arrayPos] &= ~(TWO_N_ARRAY[pos & RIGHT_BITS]);
+            if (bits[actualArrayLength - 1] == 0) {
+                isLengthActual = false;
+            }
+        }
     }
 
     /**
      * Clears the bits starting from {@code pos1} to {@code pos2}. Grows the
      * {@code BitSet} if {@code pos2 > size}.
-     * 
+     *
      * @param pos1
-     *            beginning position.
+     *            inclusive beginning position.
      * @param pos2
-     *            ending position.
+     *            exclusive ending position.
      * @throws IndexOutOfBoundsException
      *             if {@code pos1} or {@code pos2} is negative, or if
      *             {@code pos2} is smaller than {@code pos1}.
      * @see #clear(int)
-     * @since Android 1.0
      */
     public void clear(int pos1, int pos2) {
-        if (pos1 >= 0 && pos2 >= 0 && pos2 >= pos1) {
-            int last = (bits.length * ELM_SIZE);
-            if (pos1 >= last || pos1 == pos2) {
-                return;
-            }
-            if (pos2 > last) {
-                pos2 = last;
-            }
-
-            int idx1 = pos1 / ELM_SIZE;
-            int idx2 = (pos2 - 1) / ELM_SIZE;
-            long factor1 = (~0L) << (pos1 % ELM_SIZE);
-            long factor2 = (~0L) >>> (ELM_SIZE - (pos2 % ELM_SIZE));
-
-            if (idx1 == idx2) {
-                bits[idx1] &= ~(factor1 & factor2);
-            } else {
-                bits[idx1] &= ~factor1;
-                bits[idx2] &= ~factor2;
-                for (int i = idx1 + 1; i < idx2; i++) {
-                    bits[i] = 0L;
-                }
-            }
-        } else {
+        if (pos1 < 0 || pos2 < 0 || pos2 < pos1) {
             throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
         }
+
+        if (!needClear) {
+            return;
+        }
+        int last = (actualArrayLength << OFFSET);
+        if (pos1 >= last || pos1 == pos2) {
+            return;
+        }
+        if (pos2 > last) {
+            pos2 = last;
+        }
+
+        int idx1 = pos1 >> OFFSET;
+        int idx2 = (pos2 - 1) >> OFFSET;
+        long factor1 = (~0L) << (pos1 & RIGHT_BITS);
+        long factor2 = (~0L) >>> (ELM_SIZE - (pos2 & RIGHT_BITS));
+
+        if (idx1 == idx2) {
+            bits[idx1] &= ~(factor1 & factor2);
+        } else {
+            bits[idx1] &= ~factor1;
+            bits[idx2] &= ~factor2;
+            for (int i = idx1 + 1; i < idx2; i++) {
+                bits[i] = 0L;
+            }
+        }
+        if ((actualArrayLength > 0) && (bits[actualArrayLength - 1] == 0)) {
+            isLengthActual = false;
+        }
     }
 
     /**
      * Flips the bit at index {@code pos}. Grows the {@code BitSet} if
      * {@code pos > size}.
-     * 
+     *
      * @param pos
      *            the index of the bit to flip.
      * @throws IndexOutOfBoundsException
      *             if {@code pos} is negative.
      * @see #flip(int, int)
-     * @since Android 1.0
      */
     public void flip(int pos) {
-        if (pos >= 0) {
-            if (pos >= bits.length * ELM_SIZE) {
-                growBits(pos);
-            }
-            bits[pos / ELM_SIZE] ^= 1L << (pos % ELM_SIZE);
-        } else {
+        if (pos < 0) {
             throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
         }
+
+        int len = (pos >> OFFSET) + 1;
+        if (len > bits.length) {
+            growLength(len);
+        }
+        bits[len - 1] ^= TWO_N_ARRAY[pos & RIGHT_BITS];
+        if (len > actualArrayLength) {
+            actualArrayLength = len;
+        }
+        isLengthActual = !((actualArrayLength > 0) && (bits[actualArrayLength - 1] == 0));
+        needClear();
     }
 
     /**
      * Flips the bits starting from {@code pos1} to {@code pos2}. Grows the
      * {@code BitSet} if {@code pos2 > size}.
-     * 
+     *
      * @param pos1
-     *            beginning position.
+     *            inclusive beginning position.
      * @param pos2
-     *            ending position.
+     *            exclusive ending position.
      * @throws IndexOutOfBoundsException
      *             if {@code pos1} or {@code pos2} is negative, or if
      *             {@code pos2} is smaller than {@code pos1}.
      * @see #flip(int)
-     * @since Android 1.0
      */
     public void flip(int pos1, int pos2) {
-        if (pos1 >= 0 && pos2 >= 0 && pos2 >= pos1) {
-            if (pos1 == pos2) {
-                return;
-            }
-            if (pos2 >= bits.length * ELM_SIZE) {
-                growBits(pos2);
-            }
-
-            int idx1 = pos1 / ELM_SIZE;
-            int idx2 = (pos2 - 1) / ELM_SIZE;
-            long factor1 = (~0L) << (pos1 % ELM_SIZE);
-            long factor2 = (~0L) >>> (ELM_SIZE - (pos2 % ELM_SIZE));
-
-            if (idx1 == idx2) {
-                bits[idx1] ^= (factor1 & factor2);
-            } else {
-                bits[idx1] ^= factor1;
-                bits[idx2] ^= factor2;
-                for (int i = idx1 + 1; i < idx2; i++) {
-                    bits[i] ^= (~0L);
-                }
-            }
-        } else {
+        if (pos1 < 0 || pos2 < 0 || pos2 < pos1) {
             throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
         }
+
+        if (pos1 == pos2) {
+            return;
+        }
+        int len2 = ((pos2 - 1) >> OFFSET) + 1;
+        if (len2 > bits.length) {
+            growLength(len2);
+        }
+
+        int idx1 = pos1 >> OFFSET;
+        int idx2 = (pos2 - 1) >> OFFSET;
+        long factor1 = (~0L) << (pos1 & RIGHT_BITS);
+        long factor2 = (~0L) >>> (ELM_SIZE - (pos2 & RIGHT_BITS));
+
+        if (idx1 == idx2) {
+            bits[idx1] ^= (factor1 & factor2);
+        } else {
+            bits[idx1] ^= factor1;
+            bits[idx2] ^= factor2;
+            for (int i = idx1 + 1; i < idx2; i++) {
+                bits[i] ^= (~0L);
+            }
+        }
+        if (len2 > actualArrayLength) {
+            actualArrayLength = len2;
+        }
+        isLengthActual = !((actualArrayLength > 0) && (bits[actualArrayLength - 1] == 0));
+        needClear();
     }
 
     /**
      * Checks if these two {@code BitSet}s have at least one bit set to true in the same
      * position.
-     * 
+     *
      * @param bs
      *            {@code BitSet} used to calculate the intersection.
      * @return {@code true} if bs intersects with this {@code BitSet},
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean intersects(BitSet bs) {
         long[] bsBits = bs.bits;
-        int length1 = bits.length, length2 = bsBits.length;
+        int length1 = actualArrayLength, length2 = bs.actualArrayLength;
 
         if (length1 <= length2) {
             for (int i = 0; i < length1; i++) {
@@ -575,19 +645,20 @@
     }
 
     /**
-     * Performs the logical AND of this {@code BitSet} with another 
+     * Performs the logical AND of this {@code BitSet} with another
      * {@code BitSet}. The values of this {@code BitSet} are changed accordingly.
-     * 
+     *
      * @param bs
      *            {@code BitSet} to AND with.
      * @see #or
      * @see #xor
-     * @since Android 1.0
      */
-
     public void and(BitSet bs) {
         long[] bsBits = bs.bits;
-        int length1 = bits.length, length2 = bsBits.length;
+        if (!needClear) {
+            return;
+        }
+        int length1 = actualArrayLength, length2 = bs.actualArrayLength;
         if (length1 <= length2) {
             for (int i = 0; i < length1; i++) {
                 bits[i] &= bsBits[i];
@@ -599,113 +670,155 @@
             for (int i = length2; i < length1; i++) {
                 bits[i] = 0;
             }
+            actualArrayLength = length2;
         }
+        isLengthActual = !((actualArrayLength > 0) && (bits[actualArrayLength - 1] == 0));
     }
 
     /**
      * Clears all bits in the receiver which are also set in the parameter
      * {@code BitSet}. The values of this {@code BitSet} are changed accordingly.
-     * 
+     *
      * @param bs
      *            {@code BitSet} to ANDNOT with.
-     * @since Android 1.0
      */
     public void andNot(BitSet bs) {
         long[] bsBits = bs.bits;
-        int range = bits.length < bsBits.length ? bits.length : bsBits.length;
+        if (!needClear) {
+            return;
+        }
+        int range = actualArrayLength < bs.actualArrayLength ? actualArrayLength
+                : bs.actualArrayLength;
         for (int i = 0; i < range; i++) {
             bits[i] &= ~bsBits[i];
         }
+
+        if (actualArrayLength < range) {
+            actualArrayLength = range;
+        }
+        isLengthActual = !((actualArrayLength > 0) && (bits[actualArrayLength - 1] == 0));
     }
 
     /**
      * Performs the logical OR of this {@code BitSet} with another {@code BitSet}.
      * The values of this {@code BitSet} are changed accordingly.
-     * 
+     *
      * @param bs
      *            {@code BitSet} to OR with.
      * @see #xor
      * @see #and
-     * @since Android 1.0
      */
     public void or(BitSet bs) {
-        int nbits = bs.length();
-        int length = nbits / ELM_SIZE + (nbits % ELM_SIZE > 0 ? 1 : 0);
-        if (length > bits.length) {
-            growBits(nbits - 1);
+        int bsActualLen = bs.getActualArrayLength();
+        if (bsActualLen > bits.length) {
+            long[] tempBits = new long[bsActualLen];
+            System.arraycopy(bs.bits, 0, tempBits, 0, bs.actualArrayLength);
+            for (int i = 0; i < actualArrayLength; i++) {
+                tempBits[i] |= bits[i];
+            }
+            bits = tempBits;
+            actualArrayLength = bsActualLen;
+            isLengthActual = true;
+        } else {
+            long[] bsBits = bs.bits;
+            for (int i = 0; i < bsActualLen; i++) {
+                bits[i] |= bsBits[i];
+            }
+            if (bsActualLen > actualArrayLength) {
+                actualArrayLength = bsActualLen;
+                isLengthActual = true;
+            }
         }
-        long[] bsBits = bs.bits;
-        for (int i = 0; i < length; i++) {
-            bits[i] |= bsBits[i];
-        }
+        needClear();
     }
 
     /**
      * Performs the logical XOR of this {@code BitSet} with another {@code BitSet}.
      * The values of this {@code BitSet} are changed accordingly.
-     * 
+     *
      * @param bs
      *            {@code BitSet} to XOR with.
      * @see #or
      * @see #and
-     * @since Android 1.0
      */
     public void xor(BitSet bs) {
-        int nbits = bs.length();
-        int length = nbits / ELM_SIZE + (nbits % ELM_SIZE > 0 ? 1 : 0);
-        if (length > bits.length) {
-            growBits(nbits - 1);
+        int bsActualLen = bs.getActualArrayLength();
+        if (bsActualLen > bits.length) {
+            long[] tempBits = new long[bsActualLen];
+            System.arraycopy(bs.bits, 0, tempBits, 0, bs.actualArrayLength);
+            for (int i = 0; i < actualArrayLength; i++) {
+                tempBits[i] ^= bits[i];
+            }
+            bits = tempBits;
+            actualArrayLength = bsActualLen;
+            isLengthActual = !((actualArrayLength > 0) && (bits[actualArrayLength - 1] == 0));
+        } else {
+            long[] bsBits = bs.bits;
+            for (int i = 0; i < bsActualLen; i++) {
+                bits[i] ^= bsBits[i];
+            }
+            if (bsActualLen > actualArrayLength) {
+                actualArrayLength = bsActualLen;
+                isLengthActual = true;
+            }
         }
-        long[] bsBits = bs.bits;
-        for (int i = 0; i < length; i++) {
-            bits[i] ^= bsBits[i];
-        }
-
+        needClear();
     }
 
     /**
      * Returns the number of bits this {@code BitSet} has.
-     * 
+     *
      * @return the number of bits contained in this {@code BitSet}.
      * @see #length
-     * @since Android 1.0
      */
     public int size() {
-        return bits.length * ELM_SIZE;
+        return bits.length << OFFSET;
     }
 
     /**
      * Returns the number of bits up to and including the highest bit set.
-     * 
+     *
      * @return the length of the {@code BitSet}.
-     * @since Android 1.0
      */
     public int length() {
-        int idx = bits.length - 1;
+        int idx = actualArrayLength - 1;
         while (idx >= 0 && bits[idx] == 0) {
             --idx;
         }
+        actualArrayLength = idx + 1;
         if (idx == -1) {
             return 0;
         }
         int i = ELM_SIZE - 1;
         long val = bits[idx];
-        while ((val & (1L << i)) == 0 && i > 0) {
+        while ((val & (TWO_N_ARRAY[i])) == 0 && i > 0) {
             i--;
         }
-        return idx * ELM_SIZE + i + 1;
+        return (idx << OFFSET) + i + 1;
+    }
+
+    private final int getActualArrayLength() {
+        if (isLengthActual) {
+            return actualArrayLength;
+        }
+        int idx = actualArrayLength - 1;
+        while (idx >= 0 && bits[idx] == 0) {
+            --idx;
+        }
+        actualArrayLength = idx + 1;
+        isLengthActual = true;
+        return actualArrayLength;
     }
 
     /**
      * Returns a string containing a concise, human-readable description of the
      * receiver.
-     * 
+     *
      * @return a comma delimited list of the indices of all bits that are set.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
-        StringBuffer sb = new StringBuffer(bits.length / 2);
+        StringBuilder sb = new StringBuilder(bits.length / 2);
         int bitCount = 0;
         sb.append('{');
         boolean comma = false;
@@ -715,7 +828,7 @@
                 continue;
             }
             for (int j = 0; j < ELM_SIZE; j++) {
-                if (((bits[i] & (1L << j)) != 0)) {
+                if (((bits[i] & (TWO_N_ARRAY[j])) != 0)) {
                     if (comma) {
                         sb.append(", "); //$NON-NLS-1$
                     }
@@ -731,131 +844,152 @@
 
     /**
      * Returns the position of the first bit that is {@code true} on or after {@code pos}.
-     * 
+     *
      * @param pos
      *            the starting position (inclusive).
      * @return -1 if there is no bits that are set to {@code true} on or after {@code pos}.
-     * @since Android 1.0
      */
     public int nextSetBit(int pos) {
-        if (pos >= 0) {
-            if (pos >= bits.length * ELM_SIZE) {
-                return -1;
-            }
+        if (pos < 0) {
+            throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
+        }
 
-            int idx = pos / ELM_SIZE;
-            // first check in the same bit set element
-            if (bits[idx] != 0L) {
-                for (int j = pos % ELM_SIZE; j < ELM_SIZE; j++) {
-                    if (((bits[idx] & (1L << j)) != 0)) {
-                        return idx * ELM_SIZE + j;
-                    }
-                }
-
-            }
-            idx++;
-            while (idx < bits.length && bits[idx] == 0L) {
-                idx++;
-            }
-            if (idx == bits.length) {
-                return -1;
-            }
-
-            // we know for sure there is a bit set to true in this element
-            // since the bitset value is not 0L
-            for (int j = 0; j < ELM_SIZE; j++) {
-                if (((bits[idx] & (1L << j)) != 0)) {
-                    return idx * ELM_SIZE + j;
-                }
-            }
-
+        if (pos >= actualArrayLength << OFFSET) {
             return -1;
         }
-        throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
+
+        int idx = pos >> OFFSET;
+        // first check in the same bit set element
+        if (bits[idx] != 0L) {
+            for (int j = pos & RIGHT_BITS; j < ELM_SIZE; j++) {
+                if (((bits[idx] & (TWO_N_ARRAY[j])) != 0)) {
+                    return (idx << OFFSET) + j;
+                }
+            }
+
+        }
+        idx++;
+        while (idx < actualArrayLength && bits[idx] == 0L) {
+            idx++;
+        }
+        if (idx == actualArrayLength) {
+            return -1;
+        }
+
+        // we know for sure there is a bit set to true in this element
+        // since the bitset value is not 0L
+        for (int j = 0; j < ELM_SIZE; j++) {
+            if (((bits[idx] & (TWO_N_ARRAY[j])) != 0)) {
+                return (idx << OFFSET) + j;
+            }
+        }
+
+        return -1;
     }
 
     /**
      * Returns the position of the first bit that is {@code false} on or after {@code pos}.
-     * 
+     *
      * @param pos
      *            the starting position (inclusive).
      * @return the position of the next bit set to {@code false}, even if it is further
      *         than this {@code BitSet}'s size.
-     * @since Android 1.0
      */
     public int nextClearBit(int pos) {
-        if (pos >= 0) {
-            int bssize = bits.length * ELM_SIZE;
-            if (pos >= bssize) {
-                return pos;
-            }
+        if (pos < 0) {
+            throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
+        }
 
-            int idx = pos / ELM_SIZE;
-            // first check in the same bit set element
-            if (bits[idx] != (~0L)) {
-                for (int j = pos % ELM_SIZE; j < ELM_SIZE; j++) {
-                    if (((bits[idx] & (1L << j)) == 0)) {
-                        return idx * ELM_SIZE + j;
-                    }
-                }
+        int length = actualArrayLength;
+        int bssize = length << OFFSET;
+        if (pos >= bssize) {
+            return pos;
+        }
 
-            }
-            idx++;
-            while (idx < bits.length && bits[idx] == (~0L)) {
-                idx++;
-            }
-            if (idx == bits.length) {
-                return bssize;
-            }
-
-            // we know for sure there is a bit set to true in this element
-            // since the bitset value is not 0L
-            for (int j = 0; j < ELM_SIZE; j++) {
-                if (((bits[idx] & (1L << j)) == 0)) {
+        int idx = pos >> OFFSET;
+        // first check in the same bit set element
+        if (bits[idx] != (~0L)) {
+            for (int j = pos % ELM_SIZE; j < ELM_SIZE; j++) {
+                if (((bits[idx] & (TWO_N_ARRAY[j])) == 0)) {
                     return idx * ELM_SIZE + j;
                 }
             }
-
+        }
+        idx++;
+        while (idx < length && bits[idx] == (~0L)) {
+            idx++;
+        }
+        if (idx == length) {
             return bssize;
         }
-        throw new IndexOutOfBoundsException(Msg.getString("K0006")); //$NON-NLS-1$
+
+        // we know for sure there is a bit set to true in this element
+        // since the bitset value is not 0L
+        for (int j = 0; j < ELM_SIZE; j++) {
+            if (((bits[idx] & (TWO_N_ARRAY[j])) == 0)) {
+                return (idx << OFFSET) + j;
+            }
+        }
+
+        return bssize;
     }
 
     /**
      * Returns true if all the bits in this {@code BitSet} are set to false.
-     * 
+     *
      * @return {@code true} if the {@code BitSet} is empty,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isEmpty() {
-        for (int idx = 0; idx < bits.length; idx++) {
+        if (!needClear) {
+            return true;
+        }
+        int length = bits.length;
+        for (int idx = 0; idx < length; idx++) {
             if (bits[idx] != 0L) {
                 return false;
             }
         }
-
         return true;
     }
 
     /**
      * Returns the number of bits that are {@code true} in this {@code BitSet}.
-     * 
+     *
      * @return the number of {@code true} bits in the set.
-     * @since Android 1.0
      */
     public int cardinality() {
+        if (!needClear) {
+            return 0;
+        }
         int count = 0;
-        for (int idx = 0; idx < bits.length; idx++) {
-            long temp = bits[idx];
-            if (temp != 0L) {
-                for (int i = 0; i < ELM_SIZE; i++) {
-                    if ((temp & (1L << i)) != 0L) {
-                        count++;
-                    }
-                }
-            }
+        int length = bits.length;
+        // FIXME: need to test performance, if still not satisfied, change it to
+        // 256-bits table based
+        for (int idx = 0; idx < length; idx++) {
+            count += pop(bits[idx] & 0xffffffffL);
+            count += pop(bits[idx] >>> 32);
         }
         return count;
     }
+
+    private final int pop(long x) {
+        // BEGIN android-note
+        // delegate to Integer.bitCount(i); consider using native code
+        // END android-note
+        x = x - ((x >>> 1) & 0x55555555);
+        x = (x & 0x33333333) + ((x >>> 2) & 0x33333333);
+        x = (x + (x >>> 4)) & 0x0f0f0f0f;
+        x = x + (x >>> 8);
+        x = x + (x >>> 16);
+        return (int) x & 0x0000003f;
+    }
+
+    private void readObject(ObjectInputStream ois) throws IOException,
+            ClassNotFoundException {
+        ois.defaultReadObject();
+        this.isLengthActual = false;
+        this.actualArrayLength = bits.length;
+        this.needClear = this.getActualArrayLength() != 0;
+    }
 }
diff --git a/libcore/luni/src/main/java/java/util/Calendar.java b/libcore/luni/src/main/java/java/util/Calendar.java
index 98840b2..0ac574c 100644
--- a/libcore/luni/src/main/java/java/util/Calendar.java
+++ b/libcore/luni/src/main/java/java/util/Calendar.java
@@ -14,27 +14,15 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-/**
-*******************************************************************************
-* Copyright (C) 1996-2008, International Business Machines Corporation and    *
-* others. All Rights Reserved.                                                *
-*******************************************************************************
-*/
 
 package java.util;
 
-
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.ObjectStreamField;
 import java.io.Serializable;
 
-// BEGIN android-note
-// The class javadoc and some of the method descriptions are copied from ICU4J
-// source files. Changes have been made to the copied descriptions.
-// The icu license header was added to this file. 
-// END android-note
 /**
  * {@code Calendar} is an abstract base class for converting between a
  * {@code Date} object and a set of integer fields such as
@@ -42,22 +30,22 @@
  * {@code HOUR}, and so on. (A {@code Date} object represents a
  * specific instant in time with millisecond precision. See {@link Date} for
  * information about the {@code Date} class.)
- * 
+ *
  * <p>
  * Subclasses of {@code Calendar} interpret a {@code Date}
  * according to the rules of a specific calendar system.
- * 
+ *
  * <p>
  * Like other locale-sensitive classes, {@code Calendar} provides a class
  * method, {@code getInstance}, for getting a default instance of
  * this class for general use. {@code Calendar}'s {@code getInstance} method
  * returns a calendar whose locale is based on system settings and whose time fields
  * have been initialized with the current date and time: <blockquote>
- * 
+ *
  * <pre>Calendar rightNow = Calendar.getInstance()</pre>
- * 
+ *
  * </blockquote>
- * 
+ *
  * <p>
  * A {@code Calendar} object can produce all the time field values needed
  * to implement the date-time formatting for a particular language and calendar
@@ -68,7 +56,7 @@
  * Other values are defined by the concrete subclass, such as {@code ERA}
  * and {@code YEAR}. See individual field documentation and subclass
  * documentation for details.
- * 
+ *
  * <p>
  * When a {@code Calendar} is <em>lenient</em>, it accepts a wider
  * range of field values than it produces. For example, a lenient
@@ -79,14 +67,14 @@
  * by {@code get()}, they normalize them. For example, a
  * {@code GregorianCalendar} always produces {@code DAY_OF_MONTH}
  * values between 1 and the length of the month.
- * 
+ *
  * <p>
  * {@code Calendar} defines a locale-specific seven day week using two
  * parameters: the first day of the week and the minimal days in first week
  * (from 1 to 7). These numbers are taken from the locale resource data when a
  * {@code Calendar} is constructed. They may also be specified explicitly
  * through the API.
- * 
+ *
  * <p>
  * When setting or getting the {@code WEEK_OF_MONTH} or
  * {@code WEEK_OF_YEAR} fields, {@code Calendar} must determine
@@ -99,76 +87,74 @@
  * be different. For example, a specific {@code Calendar} subclass may
  * designate the week before week 1 of a year as week <em>n</em> of the
  * previous year.
- * 
+ *
  * <p>
  * When computing a {@code Date} from time fields, two special
  * circumstances may arise: there may be insufficient information to compute the
  * {@code Date} (such as only year and month but no day in the month), or
  * there may be inconsistent information (such as "Tuesday, July 15, 1996" --
  * July 15, 1996 is actually a Monday).
- * 
+ *
  * <p>
  * <strong>Insufficient information.</strong> The calendar will use default
  * information to specify the missing fields. This may vary by calendar; for the
  * Gregorian calendar, the default for a field is the same as that of the start
  * of the epoch: i.e., YEAR = 1970, MONTH = JANUARY, DATE = 1, etc.
- * 
+ *
  * <p>
  * <strong>Inconsistent information.</strong> If fields conflict, the calendar
  * will give preference to fields set more recently. For example, when
  * determining the day, the calendar will look for one of the following
  * combinations of fields. The most recent combination, as determined by the
  * most recently set single field, will be used.
- * 
+ *
  * <blockquote>
- * 
+ *
  * <pre>
  * MONTH + DAY_OF_MONTH
  * MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
  * MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
  * DAY_OF_YEAR
  * DAY_OF_WEEK + WEEK_OF_YEAR</pre>
- * 
+ *
  * </blockquote>
- * 
+ *
  * For the time of day:
- * 
+ *
  * <blockquote>
- * 
+ *
  * <pre>
  * HOUR_OF_DAY
  * AM_PM + HOUR</pre>
- * 
+ *
  * </blockquote>
- * 
+ *
  * <p>
  * <strong>Note:</strong> There are certain possible ambiguities in
  * interpretation of certain singular times, which are resolved in the following
  * ways:
  * <ol>
  * <li> 24:00:00 "belongs" to the following day. That is, 23:59 on Dec 31, 1969
- * &lt; 24:00 on Jan 1, 1970 &lt; 24:01:00 on Jan 1, 1970 form a sequence of 
- * three consecutive minutes in time. 
- * 
+ * &lt; 24:00 on Jan 1, 1970 &lt; 24:01:00 on Jan 1, 1970 form a sequence of
+ * three consecutive minutes in time.
+ *
  * <li> Although historically not precise, midnight also belongs to "am", and
  * noon belongs to "pm", so on the same day, we have 12:00 am (midnight) &lt; 12:01 am,
  * and 12:00 pm (noon) &lt; 12:01 pm
  * </ol>
- * 
+ *
  * <p>
  * The date or time format strings are not part of the definition of a calendar,
  * as those must be modifiable or overridable by the user at runtime. Use
  * {@link java.text.DateFormat} to format dates.
- * 
+ *
  * <p>
  * <strong>Field manipulation methods</strong>
- * </p>
- * 
+ *
  * <p>
  * {@code Calendar} fields can be changed using three methods:
  * {@code set()}, {@code add()}, and {@code roll()}.
- * </p>
- * 
+ *
  * <p>
  * <strong>{@code set(f, value)}</strong> changes field {@code f}
  * to {@code value}. In addition, it sets an internal member variable to
@@ -182,8 +168,7 @@
  * the calendar system. In addition, {@code get(f)} will not necessarily
  * return {@code value} after the fields have been recomputed. The
  * specifics are determined by the concrete calendar class.
- * </p>
- * 
+ *
  * <p>
  * <em>Example</em>: Consider a {@code GregorianCalendar} originally
  * set to August 31, 1999. Calling <code>set(Calendar.MONTH,
@@ -193,15 +178,13 @@
  * then called. However, a call to {@code set(Calendar.DAY_OF_MONTH, 30)}
  * before the call to {@code getTime()} sets the calendar to September
  * 30, 1999, since no recomputation occurs after {@code set()} itself.
- * </p>
- * 
+ *
  * <p>
  * <strong>{@code add(f, delta)}</strong> adds {@code delta} to
  * field {@code f}. This is equivalent to calling <code>set(f,
  * get(f) + delta)</code>
  * with two adjustments:
- * </p>
- * 
+ *
  * <blockquote>
  * <p>
  * <strong>Add rule 1</strong>. The value of field {@code f} after the
@@ -210,8 +193,7 @@
  * {@code f}. Overflow occurs when a field value exceeds its range and,
  * as a result, the next larger field is incremented or decremented and the
  * field value is adjusted back into its range.
- * </p>
- * 
+ *
  * <p>
  * <strong>Add rule 2</strong>. If a smaller field is expected to be invariant,
  * but &nbsp; it is impossible for it to be equal to its prior value because of
@@ -221,14 +203,12 @@
  * smaller field than {@code DAY_OF_MONTH}. No adjustment is made to
  * smaller fields that are not expected to be invariant. The calendar system
  * determines what fields are expected to be invariant.
- * </p>
  * </blockquote>
- * 
+ *
  * <p>
  * In addition, unlike {@code set()}, {@code add()} forces an
  * immediate recomputation of the calendar's milliseconds and all fields.
- * </p>
- * 
+ *
  * <p>
  * <em>Example</em>: Consider a {@code GregorianCalendar} originally
  * set to August 31, 1999. Calling {@code add(Calendar.MONTH, 13)} sets
@@ -240,22 +220,19 @@
  * Although it is a smaller field, {@code DAY_OF_WEEK} is not adjusted by
  * rule 2, since it is expected to change when the month changes in a
  * {@code GregorianCalendar}.
- * </p>
- * 
+ *
  * <p>
  * <strong>{@code roll(f, delta)}</strong> adds {@code delta} to
  * field {@code f} without changing larger fields. This is equivalent to
  * calling {@code add(f, delta)} with the following adjustment:
- * </p>
- * 
+ *
  * <blockquote>
  * <p>
  * <strong>Roll rule</strong>. Larger fields are unchanged after the call. A
  * larger field represents a larger unit of time. {@code DAY_OF_MONTH} is
  * a larger field than {@code HOUR}.
- * </p>
  * </blockquote>
- * 
+ *
  * <p>
  * <em>Example</em>: Consider a {@code GregorianCalendar} originally
  * set to August 31, 1999. Calling <code>roll(Calendar.MONTH,
@@ -265,8 +242,7 @@
  * the {@code DAY_OF_MONTH} cannot be 31 in the month April. Add rule 2
  * sets it to the closest possible value, 30. Finally, the <strong>roll rule</strong>
  * maintains the {@code YEAR} field value of 1999.
- * </p>
- * 
+ *
  * <p>
  * <em>Example</em>: Consider a {@code GregorianCalendar} originally
  * set to Sunday June 6, 1999. Calling
@@ -279,8 +255,7 @@
  * According to add rule 2, the {@code DAY_OF_WEEK}, an invariant when
  * changing the {@code WEEK_OF_MONTH}, is set to Tuesday, the closest
  * possible value to Sunday (where Sunday is the first day of the week).
- * </p>
- * 
+ *
  * <p>
  * <strong>Usage model</strong>. To motivate the behavior of {@code add()}
  * and {@code roll()}, consider a user interface component with
@@ -294,8 +269,7 @@
  * {@code add()} or {@code roll()}, depending on whether larger
  * fields should be affected, the user interface can behave as most users will
  * intuitively expect.
- * </p>
- * 
+ *
  * <p>
  * <b>Note:</b> You should always use {@code roll} and {@code add} rather than
  * attempting to perform arithmetic operations directly on the fields of a
@@ -304,11 +278,10 @@
  * during non-leap years. The subclasses' <tt>add</tt> and <tt>roll</tt>
  * methods will take this into account, while simple arithmetic manipulations
  * may give invalid results.
- * 
+ *
  * @see Date
  * @see GregorianCalendar
  * @see TimeZone
- * @since Android 1.0
  */
 public abstract class Calendar implements Serializable, Cloneable,
         Comparable<Calendar> {
@@ -318,38 +291,28 @@
     /**
      * Set to {@code true} when the calendar fields have been set from the time, set to
      * {@code false} when a field is changed and the fields must be recomputed.
-     * 
-     * @since Android 1.0
      */
     protected boolean areFieldsSet;
 
     /**
      * An integer array of calendar fields. The length is {@code FIELD_COUNT}.
-     * 
-     * @since Android 1.0
      */
     protected int[] fields;
 
     /**
      * A boolean array. Each element indicates if the corresponding field has
      * been set. The length is {@code FIELD_COUNT}.
-     * 
-     * @since Android 1.0
      */
     protected boolean[] isSet;
 
     /**
      * Set to {@code true} when the time has been set, set to {@code false} when a field is
      * changed and the time must be recomputed.
-     * 
-     * @since Android 1.0
      */
     protected boolean isTimeSet;
 
     /**
      * The time in milliseconds since January 1, 1970.
-     * 
-     * @since Android 1.0
      */
     protected long time;
 
@@ -365,100 +328,75 @@
 
     private TimeZone zone;
 
-    // BEGIN android-changed
     /**
      * Value of the {@code MONTH} field indicating the first month of the
      * year.
-     * 
-     * @since Android 1.0
      */
     public static final int JANUARY = 0;
 
     /**
      * Value of the {@code MONTH} field indicating the second month of
      * the year.
-     * 
-     * @since Android 1.0
      */
     public static final int FEBRUARY = 1;
 
     /**
      * Value of the {@code MONTH} field indicating the third month of the
      * year.
-     * 
-     * @since Android 1.0
      */
     public static final int MARCH = 2;
 
     /**
      * Value of the {@code MONTH} field indicating the fourth month of
      * the year.
-     * 
-     * @since Android 1.0
      */
     public static final int APRIL = 3;
 
     /**
      * Value of the {@code MONTH} field indicating the fifth month of the
      * year.
-     * 
-     * @since Android 1.0
      */
     public static final int MAY = 4;
 
     /**
      * Value of the {@code MONTH} field indicating the sixth month of the
      * year.
-     * 
-     * @since Android 1.0
      */
     public static final int JUNE = 5;
 
     /**
      * Value of the {@code MONTH} field indicating the seventh month of
      * the year.
-     * 
-     * @since Android 1.0
      */
     public static final int JULY = 6;
 
     /**
      * Value of the {@code MONTH} field indicating the eighth month of
      * the year.
-     * 
-     * @since Android 1.0
      */
     public static final int AUGUST = 7;
 
     /**
      * Value of the {@code MONTH} field indicating the ninth month of the
      * year.
-     * 
-     * @since Android 1.0
      */
     public static final int SEPTEMBER = 8;
 
     /**
      * Value of the {@code MONTH} field indicating the tenth month of the
      * year.
-     * 
-     * @since Android 1.0
      */
     public static final int OCTOBER = 9;
 
     /**
      * Value of the {@code MONTH} field indicating the eleventh month of
      * the year.
-     * 
-     * @since Android 1.0
      */
     public static final int NOVEMBER = 10;
 
     /**
      * Value of the {@code MONTH} field indicating the twelfth month of
      * the year.
-     * 
-     * @since Android 1.0
      */
     public static final int DECEMBER = 11;
 
@@ -466,57 +404,41 @@
      * Value of the {@code MONTH} field indicating the thirteenth month
      * of the year. Although {@code GregorianCalendar} does not use this
      * value, lunar calendars do.
-     * 
-     * @since Android 1.0
      */
     public static final int UNDECIMBER = 12;
 
     /**
      * Value of the {@code DAY_OF_WEEK} field indicating Sunday.
-     * 
-     * @since Android 1.0
      */
     public static final int SUNDAY = 1;
 
     /**
      * Value of the {@code DAY_OF_WEEK} field indicating Monday.
-     * 
-     * @since Android 1.0
      */
     public static final int MONDAY = 2;
 
     /**
      * Value of the {@code DAY_OF_WEEK} field indicating Tuesday.
-     * 
-     * @since Android 1.0
      */
     public static final int TUESDAY = 3;
 
     /**
      * Value of the {@code DAY_OF_WEEK} field indicating Wednesday.
-     * 
-     * @since Android 1.0
      */
     public static final int WEDNESDAY = 4;
 
     /**
      * Value of the {@code DAY_OF_WEEK} field indicating Thursday.
-     * 
-     * @since Android 1.0
      */
     public static final int THURSDAY = 5;
 
     /**
      * Value of the {@code DAY_OF_WEEK} field indicating Friday.
-     * 
-     * @since Android 1.0
      */
     public static final int FRIDAY = 6;
 
     /**
      * Value of the {@code DAY_OF_WEEK} field indicating Saturday.
-     * 
-     * @since Android 1.0
      */
     public static final int SATURDAY = 7;
 
@@ -524,19 +446,15 @@
      * Field number for {@code get} and {@code set} indicating the
      * era, e.g., AD or BC in the Julian calendar. This is a calendar-specific
      * value; see subclass documentation.
-     * 
+     *
      * @see GregorianCalendar#AD
      * @see GregorianCalendar#BC
-     * 
-     * @since Android 1.0
      */
     public static final int ERA = 0;
 
     /**
      * Field number for {@code get} and {@code set} indicating the
      * year. This is a calendar-specific value; see subclass documentation.
-     * 
-     * @since Android 1.0
      */
     public static final int YEAR = 1;
 
@@ -545,7 +463,7 @@
      * month. This is a calendar-specific value. The first month of the year is
      * {@code JANUARY}; the last depends on the number of months in a
      * year.
-     * 
+     *
      * @see #JANUARY
      * @see #FEBRUARY
      * @see #MARCH
@@ -559,8 +477,6 @@
      * @see #NOVEMBER
      * @see #DECEMBER
      * @see #UNDECIMBER
-     * 
-     * @since Android 1.0
      */
     public static final int MONTH = 2;
 
@@ -571,11 +487,9 @@
      * {@code getMinimalDaysInFirstWeek()}, has value 1. Subclasses
      * define the value of {@code WEEK_OF_YEAR} for days before the first
      * week of the year.
-     * 
+     *
      * @see #getFirstDayOfWeek
      * @see #getMinimalDaysInFirstWeek
-     * 
-     * @since Android 1.0
      */
     public static final int WEEK_OF_YEAR = 3;
 
@@ -586,11 +500,9 @@
      * {@code getMinimalDaysInFirstWeek()}, has value 1. Subclasses
      * define the value of {@code WEEK_OF_MONTH} for days before the
      * first week of the month.
-     * 
+     *
      * @see #getFirstDayOfWeek
      * @see #getMinimalDaysInFirstWeek
-     * 
-     * @since Android 1.0
      */
     public static final int WEEK_OF_MONTH = 4;
 
@@ -598,10 +510,8 @@
      * Field number for {@code get} and {@code set} indicating the
      * day of the month. This is a synonym for {@code DAY_OF_MONTH}. The
      * first day of the month has value 1.
-     * 
+     *
      * @see #DAY_OF_MONTH
-     * 
-     * @since Android 1.0
      */
     public static final int DATE = 5;
 
@@ -609,10 +519,8 @@
      * Field number for {@code get} and {@code set} indicating the
      * day of the month. This is a synonym for {@code DATE}. The first
      * day of the month has value 1.
-     * 
+     *
      * @see #DATE
-     * 
-     * @since Android 1.0
      */
     public static final int DAY_OF_MONTH = 5;
 
@@ -620,8 +528,6 @@
      * Field number for {@code get} and {@code set} indicating the
      * day number within the current year. The first day of the year has value
      * 1.
-     * 
-     * @since Android 1.0
      */
     public static final int DAY_OF_YEAR = 6;
 
@@ -631,7 +537,7 @@
      * {@code MONDAY}, {@code TUESDAY}, {@code WEDNESDAY},
      * {@code THURSDAY}, {@code FRIDAY}, and
      * {@code SATURDAY}.
-     * 
+     *
      * @see #SUNDAY
      * @see #MONDAY
      * @see #TUESDAY
@@ -639,8 +545,6 @@
      * @see #THURSDAY
      * @see #FRIDAY
      * @see #SATURDAY
-     * 
-     * @since Android 1.0
      */
     public static final int DAY_OF_WEEK = 7;
 
@@ -664,11 +568,9 @@
      * within the month than positive values. For example, if a month has 31
      * days, {@code DAY_OF_WEEK_IN_MONTH -1} will overlap
      * {@code DAY_OF_WEEK_IN_MONTH 5} and the end of {@code 4}.
-     * 
+     *
      * @see #DAY_OF_WEEK
      * @see #WEEK_OF_MONTH
-     * 
-     * @since Android 1.0
      */
     public static final int DAY_OF_WEEK_IN_MONTH = 8;
 
@@ -676,12 +578,10 @@
      * Field number for {@code get} and {@code set} indicating
      * whether the {@code HOUR} is before or after noon. E.g., at
      * 10:04:15.250 PM the {@code AM_PM} is {@code PM}.
-     * 
+     *
      * @see #AM
      * @see #PM
      * @see #HOUR
-     * 
-     * @since Android 1.0
      */
     public static final int AM_PM = 9;
 
@@ -689,11 +589,9 @@
      * Field number for {@code get} and {@code set} indicating the
      * hour of the morning or afternoon. {@code HOUR} is used for the
      * 12-hour clock. E.g., at 10:04:15.250 PM the {@code HOUR} is 10.
-     * 
+     *
      * @see #AM_PM
      * @see #HOUR_OF_DAY
-     * 
-     * @since Android 1.0
      */
     public static final int HOUR = 10;
 
@@ -701,10 +599,8 @@
      * Field number for {@code get} and {@code set} indicating the
      * hour of the day. {@code HOUR_OF_DAY} is used for the 24-hour
      * clock. E.g., at 10:04:15.250 PM the {@code HOUR_OF_DAY} is 22.
-     * 
+     *
      * @see #HOUR
-     * 
-     * @since Android 1.0
      */
     public static final int HOUR_OF_DAY = 11;
 
@@ -712,8 +608,6 @@
      * Field number for {@code get} and {@code set} indicating the
      * minute within the hour. E.g., at 10:04:15.250 PM the {@code MINUTE}
      * is 4.
-     * 
-     * @since Android 1.0
      */
     public static final int MINUTE = 12;
 
@@ -721,8 +615,6 @@
      * Field number for {@code get} and {@code set} indicating the
      * second within the minute. E.g., at 10:04:15.250 PM the
      * {@code SECOND} is 15.
-     * 
-     * @since Android 1.0
      */
     public static final int SECOND = 13;
 
@@ -730,61 +622,46 @@
      * Field number for {@code get} and {@code set} indicating the
      * millisecond within the second. E.g., at 10:04:15.250 PM the
      * {@code MILLISECOND} is 250.
-     * 
-     * @since Android 1.0
      */
     public static final int MILLISECOND = 14;
 
     /**
      * Field number for {@code get} and {@code set} indicating the
      * raw offset from GMT in milliseconds.
-     * 
-     * @since Android 1.0
      */
     public static final int ZONE_OFFSET = 15;
 
     /**
      * Field number for {@code get} and {@code set} indicating the
      * daylight savings offset in milliseconds.
-     * 
-     * @since Android 1.0
      */
     public static final int DST_OFFSET = 16;
 
     /**
      * This is the total number of fields in this calendar.
-     * 
-     * @since Android 1.0
      */
     public static final int FIELD_COUNT = 17;
 
     /**
      * Value of the {@code AM_PM} field indicating the period of the day
      * from midnight to just before noon.
-     * 
-     * @since Android 1.0
      */
     public static final int AM = 0;
 
     /**
      * Value of the {@code AM_PM} field indicating the period of the day
      * from noon to just before midnight.
-     * 
-     * @since Android 1.0
      */
     public static final int PM = 1;
-    // END android-changed
 
     private static String[] fieldNames = { "ERA=", "YEAR=", "MONTH=", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-            "WEEK_OF_YEAR=", "WEEK_OF_MONTH=", "DAY_OF_MONTH=", "DAY_OF_YEAR=",  //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-            "DAY_OF_WEEK=", "DAY_OF_WEEK_IN_MONTH=", "AM_PM=", "HOUR=",   //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$
+            "WEEK_OF_YEAR=", "WEEK_OF_MONTH=", "DAY_OF_MONTH=", "DAY_OF_YEAR=", //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+            "DAY_OF_WEEK=", "DAY_OF_WEEK_IN_MONTH=", "AM_PM=", "HOUR=", //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$
             "HOUR_OF_DAY", "MINUTE=", "SECOND=", "MILLISECOND=", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
             "ZONE_OFFSET=", "DST_OFFSET=" }; //$NON-NLS-1$ //$NON-NLS-2$
 
     /**
      * Constructs a {@code Calendar} instance using the default {@code TimeZone} and {@code Locale}.
-     * 
-     * @since Android 1.0
      */
     protected Calendar() {
         this(TimeZone.getDefault(), Locale.getDefault());
@@ -800,30 +677,38 @@
 
     /**
      * Constructs a {@code Calendar} instance using the specified {@code TimeZone} and {@code Locale}.
-     * 
+     *
      * @param timezone
      *            the timezone.
      * @param locale
      *            the locale.
-     * 
-     * @since Android 1.0
      */
     protected Calendar(TimeZone timezone, Locale locale) {
         this(timezone);
+        // BEGIN android-changed
+        // com.ibm.icu.util.Calendar icuCalendar = com.ibm.icu.util.Calendar
+        //         .getInstance(com.ibm.icu.util.SimpleTimeZone
+        //                 .getTimeZone(timezone.getID()), locale);
+        // setFirstDayOfWeek(icuCalendar.getFirstDayOfWeek());
+        // setMinimalDaysInFirstWeek(icuCalendar.getMinimalDaysInFirstWeek());
         ResourceBundle bundle = Locale.getBundle("Locale", locale); //$NON-NLS-1$
         setFirstDayOfWeek(((Integer) bundle.getObject("First_Day")).intValue()); //$NON-NLS-1$
         setMinimalDaysInFirstWeek(((Integer) bundle.getObject("Minimal_Days")) //$NON-NLS-1$
                 .intValue());
+        // END android-changed
     }
 
+
     /**
      * Adds the specified amount to a {@code Calendar} field.
-     * 
+     *
      * @param field
      *            the {@code Calendar} field to modify.
      * @param value
      *            the amount to add to the field.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *                if {@code field} is {@code DST_OFFSET} or {@code
+     *                ZONE_OFFSET}.
      */
     abstract public void add(int field, int value);
 
@@ -831,11 +716,13 @@
      * Returns whether the {@code Date} specified by this {@code Calendar} instance is after the {@code Date}
      * specified by the parameter. The comparison is not dependent on the time
      * zones of the {@code Calendar}.
-     * 
+     *
      * @param calendar
      *            the {@code Calendar} instance to compare.
      * @return {@code true} when this Calendar is after calendar, {@code false} otherwise.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *                if the time is not set and the time cannot be computed
+     *                from the current field values.
      */
     public boolean after(Object calendar) {
         if (!(calendar instanceof Calendar)) {
@@ -848,11 +735,13 @@
      * Returns whether the {@code Date} specified by this {@code Calendar} instance is before the
      * {@code Date} specified by the parameter. The comparison is not dependent on the
      * time zones of the {@code Calendar}.
-     * 
+     *
      * @param calendar
      *            the {@code Calendar} instance to compare.
      * @return {@code true} when this Calendar is before calendar, {@code false} otherwise.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *                if the time is not set and the time cannot be computed
+     *                from the current field values.
      */
     public boolean before(Object calendar) {
         if (!(calendar instanceof Calendar)) {
@@ -864,8 +753,6 @@
     /**
      * Clears all of the fields of this {@code Calendar}. All fields are initialized to
      * zero.
-     * 
-     * @since Android 1.0
      */
     public final void clear() {
         for (int i = 0; i < FIELD_COUNT; i++) {
@@ -877,10 +764,9 @@
 
     /**
      * Clears the specified field to zero and sets the isSet flag to {@code false}.
-     * 
+     *
      * @param field
      *            the field to clear.
-     * @since Android 1.0
      */
     public final void clear(int field) {
         fields[field] = 0;
@@ -890,11 +776,10 @@
 
     /**
      * Returns a new {@code Calendar} with the same properties.
-     * 
+     *
      * @return a shallow copy of this {@code Calendar}.
-     * 
+     *
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -912,11 +797,10 @@
     /**
      * Computes the time from the fields if the time has not already been set.
      * Computes the fields from the time if the fields are not already set.
-     * 
-     * @exception IllegalArgumentException
-     *                when the time is not set and the time cannot be computed
+     *
+     * @throws IllegalArgumentException
+     *                if the time is not set and the time cannot be computed
      *                from the current field values.
-     * @since Android 1.0
      */
     protected void complete() {
         if (!isTimeSet) {
@@ -931,18 +815,15 @@
 
     /**
      * Computes the {@code Calendar} fields from {@code time}.
-     * 
-     * @since Android 1.0
      */
     protected abstract void computeFields();
 
     /**
      * Computes {@code time} from the Calendar fields.
-     * 
-     * @exception IllegalArgumentException
-     *                when the time cannot be computed from the current field
+     *
+     * @throws IllegalArgumentException
+     *                if the time cannot be computed from the current field
      *                values.
-     * @since Android 1.0
      */
     protected abstract void computeTime();
 
@@ -950,12 +831,11 @@
      * Compares the specified object to this {@code Calendar} and returns whether they are
      * equal. The object must be an instance of {@code Calendar} and have the same
      * properties.
-     * 
+     *
      * @param object
      *            the object to compare with this object.
      * @return {@code true} if the specified object is equal to this {@code Calendar}, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -977,18 +857,17 @@
     /**
      * Gets the value of the specified field after computing the field values by
      * calling {@code complete()} first.
-     * 
+     *
      * @param field
      *            the field to get.
      * @return the value of the specified field.
-     * 
-     * @exception IllegalArgumentException
-     *                when the fields are not set, the time is not set, and the
+     *
+     * @throws IllegalArgumentException
+     *                if the fields are not set, the time is not set, and the
      *                time cannot be computed from the current field values.
-     * @exception ArrayIndexOutOfBoundsException
+     * @throws ArrayIndexOutOfBoundsException
      *                if the field is not inside the range of possible fields.
      *                The range is starting at 0 up to {@code FIELD_COUNT}.
-     * @since Android 1.0
      */
     public int get(int field) {
         complete();
@@ -997,11 +876,10 @@
 
     /**
      * Gets the maximum value of the specified field for the current date.
-     * 
+     *
      * @param field
      *            the field.
      * @return the maximum value of the specified field.
-     * @since Android 1.0
      */
     public int getActualMaximum(int field) {
         int value, next;
@@ -1023,11 +901,10 @@
 
     /**
      * Gets the minimum value of the specified field for the current date.
-     * 
+     *
      * @param field
      *            the field.
      * @return the minimum value of the specified field.
-     * @since Android 1.0
      */
     public int getActualMinimum(int field) {
         int value, next;
@@ -1049,9 +926,8 @@
 
     /**
      * Gets the list of installed {@code Locale}s which support {@code Calendar}.
-     * 
+     *
      * @return an array of {@code Locale}.
-     * @since Android 1.0
      */
     public static synchronized Locale[] getAvailableLocales() {
         return Locale.getAvailableLocales();
@@ -1059,9 +935,8 @@
 
     /**
      * Gets the first day of the week for this {@code Calendar}.
-     * 
+     *
      * @return the first day of the week.
-     * @since Android 1.0
      */
     public int getFirstDayOfWeek() {
         return firstDayOfWeek;
@@ -1071,21 +946,19 @@
      * Gets the greatest minimum value of the specified field. This is the
      * biggest value that {@code getActualMinimum} can return for any possible
      * time.
-     * 
+     *
      * @param field
      *            the field.
      * @return the greatest minimum value of the specified field.
-     * @since Android 1.0
      */
     abstract public int getGreatestMinimum(int field);
 
     /**
      * Constructs a new instance of the {@code Calendar} subclass appropriate for the
      * default {@code Locale}.
-     * 
+     *
      * @return a {@code Calendar} subclass instance set to the current date and time in
      *         the default {@code Timezone}.
-     * @since Android 1.0
      */
     public static synchronized Calendar getInstance() {
         return new GregorianCalendar();
@@ -1094,11 +967,10 @@
     /**
      * Constructs a new instance of the {@code Calendar} subclass appropriate for the
      * specified {@code Locale}.
-     * 
+     *
      * @param locale
      *            the locale to use.
      * @return a {@code Calendar} subclass instance set to the current date and time.
-     * @since Android 1.0
      */
     public static synchronized Calendar getInstance(Locale locale) {
         return new GregorianCalendar(locale);
@@ -1107,12 +979,11 @@
     /**
      * Constructs a new instance of the {@code Calendar} subclass appropriate for the
      * default {@code Locale}, using the specified {@code TimeZone}.
-     * 
+     *
      * @param timezone
      *            the {@code TimeZone} to use.
      * @return a {@code Calendar} subclass instance set to the current date and time in
      *         the specified timezone.
-     * @since Android 1.0
      */
     public static synchronized Calendar getInstance(TimeZone timezone) {
         return new GregorianCalendar(timezone);
@@ -1121,14 +992,13 @@
     /**
      * Constructs a new instance of the {@code Calendar} subclass appropriate for the
      * specified {@code Locale}.
-     * 
+     *
      * @param timezone
      *            the {@code TimeZone} to use.
      * @param locale
      *            the {@code Locale} to use.
      * @return a {@code Calendar} subclass instance set to the current date and time in
      *         the specified timezone.
-     * @since Android 1.0
      */
     public static synchronized Calendar getInstance(TimeZone timezone,
             Locale locale) {
@@ -1139,30 +1009,27 @@
      * Gets the smallest maximum value of the specified field. This is the
      * smallest value that {@code getActualMaximum()} can return for any
      * possible time.
-     * 
+     *
      * @param field
      *            the field number.
      * @return the smallest maximum value of the specified field.
-     * @since Android 1.0
      */
     abstract public int getLeastMaximum(int field);
 
     /**
      * Gets the greatest maximum value of the specified field. This returns the
      * biggest value that {@code get} can return for the specified field.
-     * 
+     *
      * @param field
      *            the field.
      * @return the greatest maximum value of the specified field.
-     * @since Android 1.0
      */
     abstract public int getMaximum(int field);
 
     /**
      * Gets the minimal days in the first week of the year.
-     * 
+     *
      * @return the minimal days in the first week of the year.
-     * @since Android 1.0
      */
     public int getMinimalDaysInFirstWeek() {
         return minimalDaysInFirstWeek;
@@ -1171,23 +1038,21 @@
     /**
      * Gets the smallest minimum value of the specified field. this returns the
      * smallest value thet {@code get} can return for the specified field.
-     * 
+     *
      * @param field
      *            the field number.
      * @return the smallest minimum value of the specified field.
-     * @since Android 1.0
      */
     abstract public int getMinimum(int field);
 
     /**
      * Gets the time of this {@code Calendar} as a {@code Date} object.
-     * 
+     *
      * @return a new {@code Date} initialized to the time of this {@code Calendar}.
-     * 
-     * @exception IllegalArgumentException
-     *                when the time is not set and the time cannot be computed
+     *
+     * @throws IllegalArgumentException
+     *                if the time is not set and the time cannot be computed
      *                from the current field values.
-     * @since Android 1.0
      */
     public final Date getTime() {
         return new Date(getTimeInMillis());
@@ -1195,13 +1060,12 @@
 
     /**
      * Computes the time from the fields if required and returns the time.
-     * 
+     *
      * @return the time of this {@code Calendar}.
-     * 
-     * @exception IllegalArgumentException
-     *                when the time is not set and the time cannot be computed
+     *
+     * @throws IllegalArgumentException
+     *                if the time is not set and the time cannot be computed
      *                from the current field values.
-     * @since Android 1.0
      */
     public long getTimeInMillis() {
         if (!isTimeSet) {
@@ -1213,9 +1077,8 @@
 
     /**
      * Gets the timezone of this {@code Calendar}.
-     * 
+     *
      * @return the {@code TimeZone} used by this {@code Calendar}.
-     * @since Android 1.0
      */
     public TimeZone getTimeZone() {
         return zone;
@@ -1224,11 +1087,10 @@
     /**
      * Returns an integer hash code for the receiver. Objects which are equal
      * return the same value for this method.
-     * 
+     *
      * @return the receiver's hash.
-     * 
+     *
      * @see #equals
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -1238,11 +1100,10 @@
 
     /**
      * Gets the value of the specified field without recomputing.
-     * 
+     *
      * @param field
      *            the field.
      * @return the value of the specified field.
-     * @since Android 1.0
      */
     protected final int internalGet(int field) {
         return fields[field];
@@ -1251,9 +1112,8 @@
     /**
      * Returns if this {@code Calendar} accepts field values which are outside the valid
      * range for the field.
-     * 
+     *
      * @return {@code true} if this {@code Calendar} is lenient, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isLenient() {
         return lenient;
@@ -1261,11 +1121,10 @@
 
     /**
      * Returns whether the specified field is set.
-     * 
+     *
      * @param field
      *            a {@code Calendar} field number.
      * @return {@code true} if the specified field is set, {@code false} otherwise.
-     * @since Android 1.0
      */
     public final boolean isSet(int field) {
         return isSet[field];
@@ -1276,12 +1135,11 @@
      * the field when it goes beyond the maximum or minimum value for the
      * current date. Other fields will be adjusted as required to maintain a
      * consistent date.
-     * 
+     *
      * @param field
      *            the field to roll.
      * @param value
      *            the amount to add.
-     * @since Android 1.0
      */
     public void roll(int field, int value) {
         boolean increment = value >= 0;
@@ -1296,23 +1154,21 @@
      * field when it goes beyond the maximum or minimum value for the current
      * date. Other fields will be adjusted as required to maintain a consistent
      * date.
-     * 
+     *
      * @param field
      *            the number indicating the field to roll.
      * @param increment
      *            {@code true} to increment the field, {@code false} to decrement.
-     * @since Android 1.0
      */
     abstract public void roll(int field, boolean increment);
 
     /**
      * Sets a field to the specified value.
-     * 
+     *
      * @param field
      *            the code indicating the {@code Calendar} field to modify.
      * @param value
      *            the value.
-     * @since Android 1.0
      */
     public void set(int field, int value) {
         fields[field] = value;
@@ -1332,14 +1188,13 @@
     /**
      * Sets the year, month and day of the month fields. Other fields are not
      * changed.
-     * 
+     *
      * @param year
      *            the year.
      * @param month
      *            the month.
      * @param day
      *            the day of the month.
-     * @since Android 1.0
      */
     public final void set(int year, int month, int day) {
         set(YEAR, year);
@@ -1350,7 +1205,7 @@
     /**
      * Sets the year, month, day of the month, hour of day and minute fields.
      * Other fields are not changed.
-     * 
+     *
      * @param year
      *            the year.
      * @param month
@@ -1361,7 +1216,6 @@
      *            the hour of day.
      * @param minute
      *            the minute.
-     * @since Android 1.0
      */
     public final void set(int year, int month, int day, int hourOfDay,
             int minute) {
@@ -1373,7 +1227,7 @@
     /**
      * Sets the year, month, day of the month, hour of day, minute and second
      * fields. Other fields are not changed.
-     * 
+     *
      * @param year
      *            the year.
      * @param month
@@ -1386,7 +1240,6 @@
      *            the minute.
      * @param second
      *            the second.
-     * @since Android 1.0
      */
     public final void set(int year, int month, int day, int hourOfDay,
             int minute, int second) {
@@ -1396,10 +1249,9 @@
 
     /**
      * Sets the first day of the week for this {@code Calendar}.
-     * 
+     *
      * @param value
      *            a {@code Calendar} day of the week.
-     * @since Android 1.0
      */
     public void setFirstDayOfWeek(int value) {
         firstDayOfWeek = value;
@@ -1408,10 +1260,9 @@
     /**
      * Sets this {@code Calendar} to accept field values which are outside the valid
      * range for the field.
-     * 
+     *
      * @param value
      *            a boolean value.
-     * @since Android 1.0
      */
     public void setLenient(boolean value) {
         lenient = value;
@@ -1419,10 +1270,9 @@
 
     /**
      * Sets the minimal days in the first week of the year.
-     * 
+     *
      * @param value
      *            the minimal days in the first week of the year.
-     * @since Android 1.0
      */
     public void setMinimalDaysInFirstWeek(int value) {
         minimalDaysInFirstWeek = value;
@@ -1430,10 +1280,9 @@
 
     /**
      * Sets the time of this {@code Calendar}.
-     * 
+     *
      * @param date
      *            a {@code Date} object.
-     * @since Android 1.0
      */
     public final void setTime(Date date) {
         setTimeInMillis(date.getTime());
@@ -1441,43 +1290,45 @@
 
     /**
      * Sets the time of this {@code Calendar}.
-     * 
+     *
      * @param milliseconds
      *            the time as the number of milliseconds since Jan. 1, 1970.
-     * @since Android 1.0
      */
     public void setTimeInMillis(long milliseconds) {
-        time = milliseconds;
-        isTimeSet = true;
-        areFieldsSet = false;
-        complete();
+        if (!isTimeSet || !areFieldsSet || time != milliseconds) {
+            time = milliseconds;
+            isTimeSet = true;
+            areFieldsSet = false;
+            complete();
+        }
     }
 
     /**
      * Sets the {@code TimeZone} used by this Calendar.
-     * 
+     *
      * @param timezone
      *            a {@code TimeZone}.
-     * @since Android 1.0
      */
     public void setTimeZone(TimeZone timezone) {
         zone = timezone;
+        areFieldsSet = false;
     }
 
     /**
      * Returns the string representation of this {@code Calendar}.
-     * 
+     *
      * @return the string representation of this {@code Calendar}.
-     * @since Android 1.0
      */
     @Override
+    @SuppressWarnings("nls")
     public String toString() {
-        StringBuffer result = new StringBuffer(getClass().getName() + "[time=" //$NON-NLS-1$
-                + (isTimeSet ? String.valueOf(time) : "?") + ",areFieldsSet="  //$NON-NLS-1$//$NON-NLS-2$
-                + areFieldsSet +
-                // ",areAllFieldsSet=" + areAllFieldsSet +
-                ",lenient=" + lenient + ",zone=" + zone + ",firstDayOfWeek=" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-                + firstDayOfWeek + ",minimalDaysInFirstWeek=" //$NON-NLS-1$
+        StringBuilder result = new StringBuilder(getClass().getName() + "[time="
+                + (isTimeSet ? String.valueOf(time) : "?")
+                + ",areFieldsSet="
+                + areFieldsSet
+                + // ",areAllFieldsSet=" + areAllFieldsSet +
+                ",lenient=" + lenient + ",zone=" + zone + ",firstDayOfWeek="
+                + firstDayOfWeek + ",minimalDaysInFirstWeek="
                 + minimalDaysInFirstWeek);
         for (int i = 0; i < FIELD_COUNT; i++) {
             result.append(',');
@@ -1496,7 +1347,7 @@
     /**
      * Compares the times of the two {@code Calendar}, which represent the milliseconds
      * from the January 1, 1970 00:00:00.000 GMT (Gregorian).
-     * 
+     *
      * @param anotherCalendar
      *            another calendar that this one is compared with.
      * @return 0 if the times of the two {@code Calendar}s are equal, -1 if the time of
@@ -1507,7 +1358,6 @@
      * @throws IllegalArgumentException
      *             if the argument does not include a valid time
      *             value.
-     * @since Android 1.0
      */
     public int compareTo(Calendar anotherCalendar) {
         if (null == anotherCalendar) {
@@ -1524,6 +1374,7 @@
         return -1;
     }
 
+    @SuppressWarnings("nls")
     private static final ObjectStreamField[] serialPersistentFields = {
             new ObjectStreamField("areFieldsSet", Boolean.TYPE), //$NON-NLS-1$
             new ObjectStreamField("fields", int[].class), //$NON-NLS-1$
@@ -1537,6 +1388,7 @@
             new ObjectStreamField("time", Long.TYPE), //$NON-NLS-1$
             new ObjectStreamField("zone", TimeZone.class), }; //$NON-NLS-1$
 
+    @SuppressWarnings("nls")
     private void writeObject(ObjectOutputStream stream) throws IOException {
         complete();
         ObjectOutputStream.PutField putFields = stream.putFields();
@@ -1554,6 +1406,7 @@
         stream.writeFields();
     }
 
+    @SuppressWarnings("nls")
     private void readObject(ObjectInputStream stream) throws IOException,
             ClassNotFoundException {
         ObjectInputStream.GetField readFields = stream.readFields();
diff --git a/libcore/luni/src/main/java/java/util/Collection.java b/libcore/luni/src/main/java/java/util/Collection.java
index e26dba6..6447e39 100644
--- a/libcore/luni/src/main/java/java/util/Collection.java
+++ b/libcore/luni/src/main/java/java/util/Collection.java
@@ -22,7 +22,7 @@
  * {@code Collection} is the root of the collection hierarchy. It defines operations on
  * data collections and the behavior that they will have in all implementations
  * 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
  * collection and one with a parameter of type {@code Collection}. This second
@@ -30,58 +30,55 @@
  * initial collection but with the same elements. Implementations of {@code Collection}
  * cannot be forced to implement these two constructors but at least all
  * implementations under {@code java.util} do.
- * 
+ *
  * Methods that change the content of a collection throw an
  * {@code UnsupportedOperationException} if the underlying collection does not
  * support that operation, though it's not mandatory to throw such an {@code Exception}
  * in cases where the requested operation would not change the collection. In
  * these cases it's up to the implementation whether it throws an
  * {@code UnsupportedOperationException} or not.
- * 
+ *
  * Methods marked with (optional) can throw an
  * {@code UnsupportedOperationException} if the underlying collection doesn't
  * support that method.
- * 
- * @since Android 1.0
  */
 public interface Collection<E> extends Iterable<E> {
 
     /**
      * Attempts to add {@code object} to the contents of this
      * {@code Collection} (optional).
-     * 
+     *
      * After this method finishes successfully it is guaranteed that the object
      * is contained in the collection.
-     * 
+     *
      * If the collection was modified it returns {@code true}, {@code false} if
      * no changes were made.
-     * 
+     *
      * An implementation of {@code Collection} may narrow the set of accepted
      * objects, but it has to specify this in the documentation. If the object
      * to be added does not meet this restriction, then an
      * {@code IllegalArgumentException} is thrown.
-     * 
+     *
      * If a collection does not yet contain an object that is to be added and
      * adding the object fails, this method <i>must</i> throw an appropriate
      * unchecked Exception. Returning false is not permitted in this case
      * because it would violate the postcondition that the element will be part
      * of the collection after this method finishes.
-     * 
+     *
      * @param object
      *            the object to add.
      * @return {@code true} if this {@code Collection} is
      *         modified, {@code false} otherwise.
-     * 
-     * @exception UnsupportedOperationException
-     *                when adding to this {@code Collection} is not supported.
-     * @exception ClassCastException
-     *                when the class of the object is inappropriate for this
+     *
+     * @throws UnsupportedOperationException
+     *                if adding to this {@code Collection} is not supported.
+     * @throws ClassCastException
+     *                if the class of the object is inappropriate for this
      *                collection.
-     * @exception IllegalArgumentException
-     *                when the object cannot be added to this {@code Collection}.
-     * @exception NullPointerException
-     *                when null elements cannot be added to the {@code Collection}.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *                if the object cannot be added to this {@code Collection}.
+     * @throws NullPointerException
+     *                if null elements cannot be added to the {@code Collection}.
      */
     public boolean add(E object);
 
@@ -90,35 +87,33 @@
      * to the contents of this {@code Collection} (optional). If the passed {@code Collection}
      * is changed during the process of adding elements to this {@code Collection}, the
      * behavior is not defined.
-     * 
+     *
      * @param collection
      *            the {@code Collection} of objects.
      * @return {@code true} if this {@code Collection} is modified, {@code false}
      *         otherwise.
-     * @exception UnsupportedOperationException
-     *                when adding to this {@code Collection} is not supported.
-     * @exception ClassCastException
-     *                when the class of an object is inappropriate for this
+     * @throws UnsupportedOperationException
+     *                if adding to this {@code Collection} is not supported.
+     * @throws ClassCastException
+     *                if the class of an object is inappropriate for this
      *                {@code Collection}.
-     * @exception IllegalArgumentException
-     *                when an object cannot be added to this {@code Collection}.
-     * @exception NullPointerException
-     *                when {@code collection} is {@code null}, or if it
+     * @throws IllegalArgumentException
+     *                if an object cannot be added to this {@code Collection}.
+     * @throws NullPointerException
+     *                if {@code collection} is {@code null}, or if it
      *                contains {@code null} elements and this {@code Collection} does
      *                not support such elements.
-     * @since Android 1.0
      */
     public boolean addAll(Collection<? extends E> collection);
 
     /**
      * Removes all elements from this {@code Collection}, leaving it empty (optional).
-     * 
-     * @exception UnsupportedOperationException
-     *                when removing from this {@code Collection} is not supported.
-     * 
+     *
+     * @throws UnsupportedOperationException
+     *                if removing from this {@code Collection} is not supported.
+     *
      * @see #isEmpty
      * @see #size
-     * @since Android 1.0
      */
     public void clear();
 
@@ -127,18 +122,17 @@
      * {@code true} if and only if at least one element {@code elem} in this
      * {@code Collection} meets following requirement:
      * {@code (object==null ? elem==null : object.equals(elem))}.
-     * 
+     *
      * @param object
      *            the object to search for.
      * @return {@code true} if object is an element of this {@code Collection},
      *         {@code false} otherwise.
-     * @exception ClassCastException
+     * @throws ClassCastException
      *                if the object to look for isn't of the correct
      *                type.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if the object to look for is {@code null} and this
      *                {@code Collection} doesn't support {@code null} elements.
-     * @since Android 1.0
      */
     public boolean contains(Object object);
 
@@ -147,56 +141,52 @@
      * specified {@code Collection}. If an elemenet {@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}.
-     * 
+     *
      * @param collection
      *            the collection of objects.
      * @return {@code true} if all objects in the specified {@code Collection} are
      *         elements of this {@code Collection}, {@code false} otherwise.
-     * @exception ClassCastException
+     * @throws ClassCastException
      *                if one or more elements of {@code collection} isn't of the
      *                correct type.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if {@code collection} contains at least one {@code null}
      *                element and this {@code Collection} doesn't support {@code null}
      *                elements.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if {@code collection} is {@code null}.
-     * @since Android 1.0
      */
     public boolean containsAll(Collection<?> collection);
 
     /**
      * Compares the argument to the receiver, and returns true if they represent
      * the <em>same</em> object using a class specific comparison.
-     * 
+     *
      * @param object
      *            the object to compare with this object.
      * @return {@code true} if the object is the same as this object and
      *         {@code false} if it is different from this object.
      * @see #hashCode
-     * @since Android 1.0
      */
     public boolean equals(Object object);
 
     /**
      * Returns an integer hash code for the receiver. Objects which are equal
      * return the same value for this method.
-     * 
+     *
      * @return the receiver's hash.
-     * 
+     *
      * @see #equals
-     * @since Android 1.0
      */
     public int hashCode();
 
     /**
      * Returns if this {@code Collection} contains no elements.
-     * 
+     *
      * @return {@code true} if this {@code Collection} has no elements, {@code false}
      *         otherwise.
-     * 
+     *
      * @see #size
-     * @since Android 1.0
      */
     public boolean isEmpty();
 
@@ -205,9 +195,8 @@
      * objects contained by this {@code Collection}. The order in which the elements are
      * returned by the iterator is not defined. Only if the instance of the
      * {@code Collection} has a defined order the elements are returned in that order.
-     * 
+     *
      * @return an iterator for accessing the {@code Collection} contents.
-     * @since Android 1.0
      */
     public Iterator<E> iterator();
 
@@ -215,19 +204,18 @@
      * Removes one instance of the specified object from this {@code Collection} if one
      * is contained (optional). The element {@code elem} that is removed
      * complies with {@code (object==null ? elem==null : object.equals(elem)}.
-     * 
+     *
      * @param object
      *            the object to remove.
      * @return {@code true} if this {@code Collection} is modified, {@code false}
      *         otherwise.
-     * @exception UnsupportedOperationException
-     *                when removing from this {@code Collection} is not supported.
-     * @exception ClassCastException
-     *                when the object passed is not of the correct type.
-     * @exception NullPointerException
+     * @throws UnsupportedOperationException
+     *                if removing from this {@code Collection} is not supported.
+     * @throws ClassCastException
+     *                if the object passed is not of the correct type.
+     * @throws NullPointerException
      *                if {@code object} is {@code null} and this {@code Collection}
      *                doesn't support {@code null} elements.
-     * @since Android 1.0
      */
     public boolean remove(Object object);
 
@@ -236,24 +224,23 @@
      * specified {@code Collection} (optional). After this method returns none of the
      * elements in the passed {@code Collection} can be found in this {@code Collection}
      * anymore.
-     * 
+     *
      * @param collection
      *            the collection of objects to remove.
      * @return {@code true} if this {@code Collection} is modified, {@code false}
      *         otherwise.
-     * 
-     * @exception UnsupportedOperationException
-     *                when removing from this {@code Collection} is not supported.
-     * @exception ClassCastException
+     *
+     * @throws UnsupportedOperationException
+     *                if removing from this {@code Collection} is not supported.
+     * @throws ClassCastException
      *                if one or more elements of {@code collection}
      *                isn't of the correct type.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if {@code collection} contains at least one
      *                {@code null} element and this {@code Collection} doesn't support
      *                {@code null} elements.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if {@code collection} is {@code null}.
-     * @since Android 1.0
      */
     public boolean removeAll(Collection<?> collection);
 
@@ -262,48 +249,45 @@
      * {@code Collection} passed (optional). After this method returns this {@code Collection}
      * will only contain elements that also can be found in the {@code Collection}
      * passed to this method.
-     * 
+     *
      * @param collection
      *            the collection of objects to retain.
      * @return {@code true} if this {@code Collection} is modified, {@code false}
      *         otherwise.
-     * @exception UnsupportedOperationException
-     *                when removing from this {@code Collection} is not supported.
-     * @exception ClassCastException
+     * @throws UnsupportedOperationException
+     *                if removing from this {@code Collection} is not supported.
+     * @throws ClassCastException
      *                if one or more elements of {@code collection}
      *                isn't of the correct type.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if {@code collection} contains at least one
      *                {@code null} element and this {@code Collection} doesn't support
      *                {@code null} elements.
-     * @exception NullPointerException
+     * @throws NullPointerException
      *                if {@code collection} is {@code null}.
-     * @since Android 1.0
      */
     public boolean retainAll(Collection<?> collection);
 
     /**
      * Returns a count of how many objects this {@code Collection} contains.
-     * 
+     *
      * @return how many objects this {@code Collection} contains, or Integer.MAX_VALUE
      *         if there are more than Integer.MAX_VALUE elements in this
      *         {@code Collection}.
-     * @since Android 1.0
      */
     public int size();
 
     /**
      * Returns a new array containing all elements contained in this {@code Collection}.
-     * 
+     *
      * If the implementation has ordered elements it will return the element
      * array in the same order as an iterator would return them.
-     * 
+     *
      * The array returned does not reflect any changes of the {@code Collection}. A new
      * array is created even if the underlying data structure is already an
      * array.
-     * 
+     *
      * @return an array of the elements from this {@code Collection}.
-     * @since Android 1.0
      */
     public Object[] toArray();
 
@@ -313,21 +297,20 @@
      * array is used, otherwise an array of the same type is created. If the
      * specified array is used and is larger than this {@code Collection}, the array
      * element following the {@code Collection} elements is set to null.
-     * 
+     *
      * If the implementation has ordered elements it will return the element
      * array in the same order as an iterator would return them.
-     * 
+     *
      * {@code toArray(new Object[0])} behaves exactly the same way as
      * {@code toArray()} does.
-     * 
+     *
      * @param array
      *            the array.
      * @return an array of the elements from this {@code Collection}.
-     * 
-     * @exception ArrayStoreException
-     *                when the type of an element in this {@code Collection} cannot be
+     *
+     * @throws ArrayStoreException
+     *                if the type of an element in this {@code Collection} cannot be
      *                stored in the type of the specified array.
-     * @since Android 1.0
      */
     public <T> T[] toArray(T[] array);
 }
diff --git a/libcore/luni/src/main/java/java/util/Collections.java b/libcore/luni/src/main/java/java/util/Collections.java
index 5905bc2..767d98b 100644
--- a/libcore/luni/src/main/java/java/util/Collections.java
+++ b/libcore/luni/src/main/java/java/util/Collections.java
@@ -27,8 +27,8 @@
 /**
  * {@code Collections} contains static methods which operate on
  * {@code Collection} classes.
- * 
- * @since Android 1.0
+ *
+ * @since 1.2
  */
 public class Collections {
 
@@ -69,7 +69,7 @@
 
     @SuppressWarnings("unchecked")
     private static final class EmptyList extends AbstractList implements
-            Serializable {
+            RandomAccess, Serializable {
         private static final long serialVersionUID = 8842843931221139166L;
 
         @Override
@@ -171,24 +171,18 @@
 
     /**
      * An empty immutable instance of {@link List}.
-     * 
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static final List EMPTY_LIST = new EmptyList();
 
     /**
      * An empty immutable instance of {@link Set}.
-     * 
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static final Set EMPTY_SET = new EmptySet();
 
     /**
      * An empty immutable instance of {@link Map}.
-     * 
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static final Map EMPTY_MAP = new EmptyMap();
@@ -532,9 +526,9 @@
          * problems. This is necessary since RandomAccess API was introduced
          * only in 1.4.
          * <p>
-         * 
+         *
          * @return SynchronizedList
-         * 
+         *
          * @see SynchronizedList#readResolve()
          */
         private Object writeReplace() {
@@ -591,15 +585,51 @@
         }
 
         public int indexOf(Object object) {
+            final int size;
+            final Object[] array;
             synchronized (mutex) {
-                return list.indexOf(object);
+                size = list.size();
+                array = new Object[size];
+                list.toArray(array);
             }
+            if (null != object)
+                for (int i = 0; i < size; i++) {
+                    if (object.equals(array[i])) {
+                        return i;
+                    }
+                }
+            else {
+                for (int i = 0; i < size; i++) {
+                    if (null == array[i]) {
+                        return i;
+                    }
+                }
+            }
+            return -1;
         }
 
         public int lastIndexOf(Object object) {
+            final int size;
+            final Object[] array;
             synchronized (mutex) {
-                return list.lastIndexOf(object);
+                size = list.size();
+                array = new Object[size];
+                list.toArray(array);
             }
+            if (null != object)
+                for (int i = size - 1; i >= 0; i--) {
+                    if (object.equals(array[i])) {
+                        return i;
+                    }
+                }
+            else {
+                for (int i = size - 1; i >= 0; i--) {
+                    if (null == array[i]) {
+                        return i;
+                    }
+                }
+            }
+            return -1;
         }
 
         public ListIterator<E> listIterator() {
@@ -646,10 +676,10 @@
          * replaced with SynchronizedList instances during serialization for
          * compliance with JREs before 1.4.
          * <p>
-         * 
+         *
          * @return a SynchronizedList instance if the underlying list implements
          *         RandomAccess interface, or this same object if not.
-         * 
+         *
          * @see SynchronizedRandomAccessList#writeReplace()
          */
         private Object readResolve() {
@@ -1033,9 +1063,9 @@
          * problems. This is necessary since RandomAccess API was introduced
          * only in 1.4.
          * <p>
-         * 
+         *
          * @return UnmodifiableList
-         * 
+         *
          * @see UnmodifiableList#readResolve()
          */
         private Object writeReplace() {
@@ -1150,11 +1180,11 @@
          * replaced with UnmodifiableList instances during serialization for
          * compliance with JREs before 1.4.
          * <p>
-         * 
+         *
          * @return an UnmodifiableList instance if the underlying list
          *         implements RandomAccess interface, or this same object if
          *         not.
-         * 
+         *
          * @see UnmodifiableRandomAccessList#writeReplace()
          */
         private Object readResolve() {
@@ -1429,13 +1459,13 @@
 
     /**
      * Performs a binary search for the specified element in the specified
-     * sorted List. The List needs to be already sorted in natural sorting
+     * sorted list. The list needs to be already sorted in natural sorting
      * order. Searching in an unsorted array has an undefined result. It's also
      * undefined which element is found if there are multiple occurrences of the
      * same element.
-     * 
+     *
      * @param list
-     *            the sorted List to search.
+     *            the sorted list to search.
      * @param object
      *            the element to find.
      * @return the non-negative index of the element, or a negative index which
@@ -1443,7 +1473,6 @@
      * @throws ClassCastException
      *             if an element in the List or the search element does not
      *             implement Comparable, or cannot be compared to each other.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static <T> int binarySearch(
@@ -1455,12 +1484,12 @@
             return -1;
         }
 
-        Comparable<T> key = (Comparable<T>) object;
+
         if (!(list instanceof RandomAccess)) {
-            ListIterator<T> it = (ListIterator<T>) list.listIterator();
+            ListIterator<? extends Comparable<? super T>> it = list.listIterator();
             while (it.hasNext()) {
                 int result;
-                if ((result = key.compareTo(it.next())) <= 0) {
+                if ((result = -it.next().compareTo(object)) <= 0) {
                     if (result == 0) {
                         return it.previousIndex();
                     }
@@ -1473,7 +1502,7 @@
         int low = 0, mid = list.size(), high = mid - 1, result = -1;
         while (low <= high) {
             mid = (low + high) >> 1;
-            if ((result = key.compareTo((T) list.get(mid))) > 0) {
+            if ((result = -list.get(mid).compareTo(object)) > 0) {
                 low = mid + 1;
             } else if (result == 0) {
                 return mid;
@@ -1486,26 +1515,28 @@
 
     /**
      * Performs a binary search for the specified element in the specified
-     * sorted List using the specified Comparator. The List needs to be already
+     * sorted list using the specified comparator. The list needs to be already
      * sorted according to the comparator passed. Searching in an unsorted array
      * has an undefined result. It's also undefined which element is found if
      * there are multiple occurrences of the same element.
-     * 
+     *
      * @param list
      *            the sorted List to search.
      * @param object
      *            the element to find.
      * @param comparator
-     *            the Comparator. If the comparator is {@code null} then the
+     *            the comparator. If the comparator is {@code null} then the
      *            search uses the objects' natural ordering.
      * @return the non-negative index of the element, or a negative index which
      *         is the {@code -index - 1} where the element would be inserted.
      * @throws ClassCastException
      *             when an element in the list and the searched element cannot
-     *             be compared to each other using the Comparator.
-     * @since Android 1.0
+     *             be compared to each other using the comparator.
      */
     @SuppressWarnings("unchecked")
+    // BEGIN android-note
+    // removed "@param <T> The element type", which is rejected by apicheck
+    // END android-note
     public static <T> int binarySearch(List<? extends T> list, T object,
             Comparator<? super T> comparator) {
         if (comparator == null) {
@@ -1516,7 +1547,7 @@
             ListIterator<? extends T> it = list.listIterator();
             while (it.hasNext()) {
                 int result;
-                if ((result = comparator.compare(object, it.next())) <= 0) {
+                if ((result = -comparator.compare(it.next(), object)) <= 0) {
                     if (result == 0) {
                         return it.previousIndex();
                     }
@@ -1529,7 +1560,7 @@
         int low = 0, mid = list.size(), high = mid - 1, result = -1;
         while (low <= high) {
             mid = (low + high) >> 1;
-            if ((result = comparator.compare(object, list.get(mid))) > 0) {
+            if ((result = -comparator.compare(list.get(mid),object)) > 0) {
                 low = mid + 1;
             } else if (result == 0) {
                 return mid;
@@ -1545,17 +1576,16 @@
      * end both lists will have the same objects at the same index. If the
      * destination array is larger than the source list, the elements in the
      * destination list with {@code index >= source.size()} will be unchanged.
-     * 
+     *
      * @param destination
      *            the list whose elements are set from the source list.
      * @param source
      *            the list with the elements to be copied into the destination.
      * @throws IndexOutOfBoundsException
-     *             when the destination List is smaller than the source List.
+     *             when the destination list is smaller than the source list.
      * @throws UnsupportedOperationException
      *             when replacing an element in the destination list is not
      *             supported.
-     * @since Android 1.0
      */
     public static <T> void copy(List<? super T> destination,
             List<? extends T> source) {
@@ -1576,11 +1606,10 @@
 
     /**
      * Returns an {@code Enumeration} on the specified collection.
-     * 
+     *
      * @param collection
      *            the collection to enumerate.
      * @return an Enumeration.
-     * @since Android 1.0
      */
     public static <T> Enumeration<T> enumeration(Collection<T> collection) {
         final Collection<T> c = collection;
@@ -1598,15 +1627,14 @@
     }
 
     /**
-     * Fills the specified List with the specified element.
-     * 
+     * Fills the specified list with the specified element.
+     *
      * @param list
-     *            the List to fill.
+     *            the list to fill.
      * @param object
      *            the element to fill the list with.
      * @throws UnsupportedOperationException
      *             when replacing an element in the List is not supported.
-     * @since Android 1.0
      */
     public static <T> void fill(List<? super T> list, T object) {
         ListIterator<? super T> it = list.listIterator();
@@ -1617,16 +1645,15 @@
     }
 
     /**
-     * Searches the specified Collection for the maximum element.
-     * 
+     * Searches the specified collection for the maximum element.
+     *
      * @param collection
-     *            the Collection to search.
+     *            the collection to search.
      * @return the maximum element in the Collection.
      * @throws ClassCastException
-     *             when an element in the Collection does not implement
+     *             when an element in the collection does not implement
      *             {@code Comparable} or elements cannot be compared to each
      *             other.
-     * @since Android 1.0
      */
     public static <T extends Object & Comparable<? super T>> T max(
             Collection<? extends T> collection) {
@@ -1642,18 +1669,17 @@
     }
 
     /**
-     * Searches the specified Collection for the maximum element using the
-     * specified Comparator.
-     * 
+     * Searches the specified collection for the maximum element using the
+     * specified comparator.
+     *
      * @param collection
-     *            the Collection to search.
+     *            the collection to search.
      * @param comparator
-     *            the Comparator.
+     *            the comparator.
      * @return the maximum element in the Collection.
      * @throws ClassCastException
-     *             when elements in the Collection cannot be compared to each
+     *             when elements in the collection cannot be compared to each
      *             other using the {@code Comparator}.
-     * @since Android 1.0
      */
     public static <T> T max(Collection<? extends T> collection,
             Comparator<? super T> comparator) {
@@ -1669,16 +1695,15 @@
     }
 
     /**
-     * Searches the specified Collection for the minimum element.
-     * 
+     * Searches the specified collection for the minimum element.
+     *
      * @param collection
-     *            the Collection to search.
-     * @return the minimum element in the Collection.
+     *            the collection to search.
+     * @return the minimum element in the collection.
      * @throws ClassCastException
-     *             when an element in the Collection does not implement
+     *             when an element in the collection does not implement
      *             {@code Comparable} or elements cannot be compared to each
      *             other.
-     * @since Android 1.0
      */
     public static <T extends Object & Comparable<? super T>> T min(
             Collection<? extends T> collection) {
@@ -1694,18 +1719,17 @@
     }
 
     /**
-     * Searches the specified Collection for the minimum element using the
-     * specified Comparator.
-     * 
+     * Searches the specified collection for the minimum element using the
+     * specified comparator.
+     *
      * @param collection
-     *            the Collection to search.
+     *            the collection to search.
      * @param comparator
-     *            the Comparator.
-     * @return the minimum element in the Collection.
+     *            the comparator.
+     * @return the minimum element in the collection.
      * @throws ClassCastException
-     *             when elements in the Collection cannot be compared to each
+     *             when elements in the collection cannot be compared to each
      *             other using the {@code Comparator}.
-     * @since Android 1.0
      */
     public static <T> T min(Collection<? extends T> collection,
             Comparator<? super T> comparator) {
@@ -1721,17 +1745,16 @@
     }
 
     /**
-     * Returns a List containing the specified number of the specified element.
+     * Returns a list containing the specified number of the specified element.
      * The list cannot be modified. The list is serializable.
-     * 
+     *
      * @param length
      *            the size of the returned list.
      * @param object
      *            the element to be added {@code length} times to a list.
-     * @return a List containing {@code length} copies of the element.
+     * @return a list containing {@code length} copies of the element.
      * @throws IllegalArgumentException
      *             when {@code length < 0}.
-     * @since Android 1.0
      */
     public static <T> List<T> nCopies(final int length, T object) {
         return new CopiesList<T>(length, object);
@@ -1740,12 +1763,11 @@
     /**
      * Modifies the specified {@code List} by reversing the order of the
      * elements.
-     * 
+     *
      * @param list
-     *            the List to reverse.
+     *            the list to reverse.
      * @throws UnsupportedOperationException
      *             when replacing an element in the List is not supported.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static void reverse(List<?> list) {
@@ -1762,14 +1784,13 @@
     }
 
     /**
-     * A Comparator which reverses the natural order of the elements. The
+     * A comparator which reverses the natural order of the elements. The
      * {@code Comparator} that's returned is {@link Serializable}.
-     * 
+     *
      * @return a {@code Comparator} instance.
      * @see Comparator
      * @see Comparable
      * @see Serializable
-     * @since Android 1.0
      */
     public static <T> Comparator<T> reverseOrder() {
         return new ReverseComparator<T>();
@@ -1782,13 +1803,12 @@
      * <p>
      * The {@code Comparator} that's returned is {@link Serializable} if the
      * {@code Comparator} passed is serializable or {@code null}.
-     * </p>
-     * 
+     *
      * @param c
      *            the {@code Comparator} to reverse or {@code null}.
      * @return a {@code Comparator} instance.
      * @see Comparator
-     * @since Android 1.0
+     * @since 1.5
      */
     public static <T> Comparator<T> reverseOrder(Comparator<T> c) {
         if (c == null) {
@@ -1798,38 +1818,35 @@
     }
 
     /**
-     * Moves every element of the List to a random new position in the list.
-     * 
+     * Moves every element of the list to a random new position in the list.
+     *
      * @param list
      *            the List to shuffle.
-     * 
+     *
      * @throws UnsupportedOperationException
      *             when replacing an element in the List is not supported.
-     * @since Android 1.0
      */
     public static void shuffle(List<?> list) {
         shuffle(list, new Random());
     }
 
     /**
-     * Moves every element of the List to a random new position in the list
+     * Moves every element of the list to a random new position in the list
      * using the specified random number generator.
-     * 
+     *
      * @param list
-     *            the List to shuffle.
+     *            the list to shuffle.
      * @param random
      *            the random number generator.
-     * 
      * @throws UnsupportedOperationException
-     *             when replacing an element in the List is not supported.
-     * @since Android 1.0
+     *             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();
             for (int i = array.length - 1; i > 0; i--) {
-                int index = random.nextInt() % (i + 1);
+                int index = random.nextInt(i + 1);
                 if (index < 0) {
                     index = -index;
                 }
@@ -1848,7 +1865,7 @@
         } else {
             List<Object> rawList = (List<Object>) list;
             for (int i = rawList.size() - 1; i > 0; i--) {
-                int index = random.nextInt() % (i + 1);
+                int index = random.nextInt(i + 1);
                 if (index < 0) {
                     index = -index;
                 }
@@ -1858,26 +1875,24 @@
     }
 
     /**
-     * Returns a Set containing the specified element. The set cannot be
+     * Returns a set containing the specified element. The set cannot be
      * modified. The set is serializable.
-     * 
+     *
      * @param object
      *            the element.
-     * @return a Set containing the element.
-     * @since Android 1.0
+     * @return a set containing the element.
      */
     public static <E> Set<E> singleton(E object) {
         return new SingletonSet<E>(object);
     }
 
     /**
-     * Returns a List containing the specified element. The list cannot be
+     * Returns a list containing the specified element. The list cannot be
      * modified. The list is serializable.
-     * 
+     *
      * @param object
      *            the element.
-     * @return a List containing the element.
-     * @since Android 1.0
+     * @return a list containing the element.
      */
     public static <E> List<E> singletonList(E object) {
         return new SingletonList<E>(object);
@@ -1886,28 +1901,26 @@
     /**
      * Returns a Map containing the specified key and value. The map cannot be
      * modified. The map is serializable.
-     * 
+     *
      * @param key
      *            the key.
      * @param value
      *            the value.
      * @return a Map containing the key and value.
-     * @since Android 1.0
      */
     public static <K, V> Map<K, V> singletonMap(K key, V value) {
         return new SingletonMap<K, V>(key, value);
     }
 
     /**
-     * Sorts the specified List in ascending natural order. The algorithm is
+     * Sorts the specified list in ascending natural order. The algorithm is
      * stable which means equal elements don't get reordered.
-     * 
+     *
      * @param list
-     *            the List to be sorted.
+     *            the list to be sorted.
      * @throws ClassCastException
      *             when an element in the List does not implement Comparable or
      *             elements cannot be compared to each other.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static <T extends Comparable<? super T>> void sort(List<T> list) {
@@ -1922,17 +1935,16 @@
     }
 
     /**
-     * Sorts the specified List using the specified Comparator. The algorithm is
+     * Sorts the specified list using the specified comparator. The algorithm is
      * stable which means equal elements don't get reordered.
-     * 
+     *
      * @param list
-     *            the List to be sorted.
+     *            the list to be sorted.
      * @param comparator
-     *            the Comparator.
+     *            the comparator.
      * @throws ClassCastException
-     *             when elements in the List cannot be compared to each other
-     *             using the Comparator.
-     * @since Android 1.0
+     *             when elements in the list cannot be compared to each other
+     *             using the comparator.
      */
     @SuppressWarnings("unchecked")
     public static <T> void sort(List<T> list, Comparator<? super T> comparator) {
@@ -1947,26 +1959,30 @@
     }
 
     /**
-     * Swaps the elements of List {@code list} at indices {@code index1} and
+     * Swaps the elements of list {@code list} at indices {@code index1} and
      * {@code index2}.
-     * 
+     *
      * @param list
-     *            the List to manipulate.
+     *            the list to manipulate.
      * @param index1
      *            position of the first element to swap with the element in
      *            index2.
      * @param index2
      *            position of the other element.
-     * 
+     *
      * @throws IndexOutOfBoundsException
      *             if index1 or index2 is out of range of this list.
-     * @since Android 1.0
+     * @since 1.4
      */
     @SuppressWarnings("unchecked")
     public static void swap(List<?> list, int index1, int index2) {
         if (list == null) {
             throw new NullPointerException();
         }
+        final int size = list.size();
+        if (index1 < 0 || index1 >= size || index2 < 0 || index2 >= size) {
+            throw new IndexOutOfBoundsException();
+        }
         if (index1 == index2) {
             return;
         }
@@ -1978,20 +1994,18 @@
      * Replaces all occurrences of Object {@code obj} in {@code list} with
      * {@code newObj}. If the {@code obj} is {@code null}, then all
      * occurrences of {@code null} are replaced with {@code newObj}.
-     * 
+     *
      * @param list
-     *            the List to modify.
+     *            the list to modify.
      * @param obj
-     *            the Object to find and replace occurrences of.
+     *            the object to find and replace occurrences of.
      * @param obj2
-     *            the Object to replace all occurrences of {@code obj} in
+     *            the object to replace all occurrences of {@code obj} in
      *            {@code list}.
      * @return true, if at least one occurrence of {@code obj} has been found in
      *         {@code list}.
-     * 
      * @throws UnsupportedOperationException
      *             if the list does not support setting elements.
-     * @since Android 1.0
      */
     public static <T> boolean replaceAll(List<T> list, T obj, T obj2) {
         int index;
@@ -2005,19 +2019,17 @@
     }
 
     /**
-     * Rotates the elements in List {@code list} by the distance {@code dist}
+     * Rotates the elements in {@code list} by the distance {@code dist}
      * <p>
      * e.g. for a given list with elements [1, 2, 3, 4, 5, 6, 7, 8, 9, 0],
      * calling rotate(list, 3) or rotate(list, -7) would modify the list to look
      * like this: [8, 9, 0, 1, 2, 3, 4, 5, 6, 7]
-     * </p>
-     * 
+     *
      * @param lst
      *            the list whose elements are to be rotated.
      * @param dist
      *            is the distance the list is rotated. This can be any valid
      *            integer. Negative values rotate the list backwards.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static void rotate(List<?> lst, int dist) {
@@ -2069,14 +2081,13 @@
      * index of the first occurrence.
      * <p>
      * -1 is returned if the {@code sublist} does not exist in {@code list}.
-     * 
+     *
      * @param list
      *            the List to search {@code sublist} in.
      * @param sublist
      *            the List to search in {@code list}.
      * @return the beginning index of the first occurrence of {@code sublist} in
      *         {@code list}, or -1.
-     * @since Android 1.0
      */
     public static int indexOfSubList(List<?> list, List<?> sublist) {
         int size = list.size();
@@ -2137,14 +2148,13 @@
      * index of the last occurrence.
      * <p>
      * -1 is returned if the {@code sublist} does not exist in {@code list}.
-     * 
+     *
      * @param list
-     *            the List to search {@code sublist} in.
+     *            the list to search {@code sublist} in.
      * @param sublist
-     *            the List to search in {@code list}.
+     *            the list to search in {@code list}.
      * @return the beginning index of the last occurrence of {@code sublist} in
      *         {@code list}, or -1.
-     * @since Android 1.0
      */
     public static int lastIndexOfSubList(List<?> list, List<?> sublist) {
         int sublistSize = sublist.size();
@@ -2198,14 +2208,13 @@
     }
 
     /**
-     * Returns an {@code ArrayList} with all the elements in the
-     * {@code enumeration}. The elements in the returned ArrayList are in the
+     * Returns an {@code ArrayList} with all the elements in the {@code
+     * enumeration}. The elements in the returned {@code ArrayList} are in the
      * same order as in the {@code enumeration}.
-     * 
+     *
      * @param enumeration
      *            the source {@link Enumeration}.
      * @return an {@code ArrayList} from {@code enumeration}.
-     * @since Android 1.0
      */
     public static <T> ArrayList<T> list(Enumeration<T> enumeration) {
         ArrayList<T> list = new ArrayList<T>();
@@ -2216,13 +2225,12 @@
     }
 
     /**
-     * Returns a wrapper on the specified Collection which synchronizes all
-     * access to the Collection.
-     * 
+     * Returns a wrapper on the specified collection which synchronizes all
+     * access to the collection.
+     *
      * @param collection
      *            the Collection to wrap in a synchronized collection.
      * @return a synchronized Collection.
-     * @since Android 1.0
      */
     public static <T> Collection<T> synchronizedCollection(
             Collection<T> collection) {
@@ -2235,11 +2243,10 @@
     /**
      * Returns a wrapper on the specified List which synchronizes all access to
      * the List.
-     * 
+     *
      * @param list
      *            the List to wrap in a synchronized list.
      * @return a synchronized List.
-     * @since Android 1.0
      */
     public static <T> List<T> synchronizedList(List<T> list) {
         if (list == null) {
@@ -2252,13 +2259,12 @@
     }
 
     /**
-     * Returns a wrapper on the specified Map which synchronizes all access to
-     * the Map.
-     * 
+     * Returns a wrapper on the specified map which synchronizes all access to
+     * the map.
+     *
      * @param map
-     *            the Map to wrap in a synchronized map.
+     *            the map to wrap in a synchronized map.
      * @return a synchronized Map.
-     * @since Android 1.0
      */
     public static <K, V> Map<K, V> synchronizedMap(Map<K, V> map) {
         if (map == null) {
@@ -2268,13 +2274,12 @@
     }
 
     /**
-     * Returns a wrapper on the specified Set which synchronizes all access to
-     * the Set.
-     * 
+     * Returns a wrapper on the specified set which synchronizes all access to
+     * the set.
+     *
      * @param set
-     *            the Set to wrap in a synchronized set.
-     * @return a synchronized Set.
-     * @since Android 1.0
+     *            the set to wrap in a synchronized set.
+     * @return a synchronized set.
      */
     public static <E> Set<E> synchronizedSet(Set<E> set) {
         if (set == null) {
@@ -2284,13 +2289,12 @@
     }
 
     /**
-     * Returns a wrapper on the specified SortedMap which synchronizes all
-     * access to the SortedMap.
-     * 
+     * Returns a wrapper on the specified sorted map which synchronizes all
+     * access to the sorted map.
+     *
      * @param map
-     *            the SortedMap to wrap in a synchronized sorted map.
-     * @return a synchronized SortedMap.
-     * @since Android 1.0
+     *            the sorted map to wrap in a synchronized sorted map.
+     * @return a synchronized sorted map.
      */
     public static <K, V> SortedMap<K, V> synchronizedSortedMap(
             SortedMap<K, V> map) {
@@ -2301,13 +2305,12 @@
     }
 
     /**
-     * Returns a wrapper on the specified SortedSet which synchronizes all
-     * access to the SortedSet.
-     * 
+     * Returns a wrapper on the specified sorted set which synchronizes all
+     * access to the sorted set.
+     *
      * @param set
-     *            the SortedSet to wrap in a synchronized sorted set.
-     * @return a synchronized SortedSet.
-     * @since Android 1.0
+     *            the sorted set to wrap in a synchronized sorted set.
+     * @return a synchronized sorted set.
      */
     public static <E> SortedSet<E> synchronizedSortedSet(SortedSet<E> set) {
         if (set == null) {
@@ -2317,14 +2320,13 @@
     }
 
     /**
-     * Returns a wrapper on the specified Collection which throws an
+     * Returns a wrapper on the specified collection which throws an
      * {@code UnsupportedOperationException} whenever an attempt is made to
-     * modify the Collection.
-     * 
+     * modify the collection.
+     *
      * @param collection
-     *            the Collection to wrap in an unmodifiable collection.
-     * @return an unmodifiable Collection.
-     * @since Android 1.0
+     *            the collection to wrap in an unmodifiable collection.
+     * @return an unmodifiable collection.
      */
     @SuppressWarnings("unchecked")
     public static <E> Collection<E> unmodifiableCollection(
@@ -2336,14 +2338,13 @@
     }
 
     /**
-     * Returns a wrapper on the specified List which throws an
+     * Returns a wrapper on the specified list which throws an
      * {@code UnsupportedOperationException} whenever an attempt is made to
-     * modify the List.
-     * 
+     * modify the list.
+     *
      * @param list
-     *            the List to wrap in an unmodifiable list.
+     *            the list to wrap in an unmodifiable list.
      * @return an unmodifiable List.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static <E> List<E> unmodifiableList(List<? extends E> list) {
@@ -2357,14 +2358,13 @@
     }
 
     /**
-     * Returns a wrapper on the specified Map which throws an
+     * Returns a wrapper on the specified map which throws an
      * {@code UnsupportedOperationException} whenever an attempt is made to
-     * modify the Map.
-     * 
+     * modify the map.
+     *
      * @param map
-     *            the Map to wrap in an unmodifiable map.
-     * @return a unmodifiable Map.
-     * @since Android 1.0
+     *            the map to wrap in an unmodifiable map.
+     * @return a unmodifiable map.
      */
     @SuppressWarnings("unchecked")
     public static <K, V> Map<K, V> unmodifiableMap(
@@ -2376,14 +2376,13 @@
     }
 
     /**
-     * Returns a wrapper on the specified Set which throws an
+     * Returns a wrapper on the specified set which throws an
      * {@code UnsupportedOperationException} whenever an attempt is made to
-     * modify the Set.
-     * 
+     * modify the set.
+     *
      * @param set
-     *            the Set to wrap in an unmodifiable set.
-     * @return a unmodifiable Set.
-     * @since Android 1.0
+     *            the set to wrap in an unmodifiable set.
+     * @return a unmodifiable set
      */
     @SuppressWarnings("unchecked")
     public static <E> Set<E> unmodifiableSet(Set<? extends E> set) {
@@ -2394,14 +2393,13 @@
     }
 
     /**
-     * Returns a wrapper on the specified SortedMap which throws an
+     * Returns a wrapper on the specified sorted map which throws an
      * {@code UnsupportedOperationException} whenever an attempt is made to
-     * modify the SortedMap.
-     * 
+     * modify the sorted map.
+     *
      * @param map
-     *            the SortedMap to wrap in an unmodifiable sorted map.
-     * @return a unmodifiable SortedMap.
-     * @since Android 1.0
+     *            the sorted map to wrap in an unmodifiable sorted map.
+     * @return a unmodifiable sorted map
      */
     @SuppressWarnings("unchecked")
     public static <K, V> SortedMap<K, V> unmodifiableSortedMap(
@@ -2413,14 +2411,13 @@
     }
 
     /**
-     * Returns a wrapper on the specified SortedSet which throws an
+     * Returns a wrapper on the specified sorted set which throws an
      * {@code UnsupportedOperationException} whenever an attempt is made to
-     * modify the SortedSet.
-     * 
+     * modify the sorted set.
+     *
      * @param set
-     *            the SortedSet to wrap in an unmodifiable sorted set.
-     * @return a unmodifiable SortedSet.
-     * @since Android 1.0
+     *            the sorted set to wrap in an unmodifiable sorted set.
+     * @return a unmodifiable sorted set.
      */
     public static <E> SortedSet<E> unmodifiableSortedSet(SortedSet<E> set) {
         if (set == null) {
@@ -2433,8 +2430,7 @@
      * Returns the number of elements in the {@code Collection} that match the
      * {@code Object} passed. If the {@code Object} is {@code null}, then the
      * number of {@code null} elements is returned.
-     * </p>
-     * 
+     *
      * @param c
      *            the {@code Collection} to search.
      * @param o
@@ -2442,7 +2438,7 @@
      * @return the number of matching elements.
      * @throws NullPointerException
      *             if the {@code Collection} parameter is {@code null}.
-     * @since Android 1.0
+     * @since 1.5
      */
     public static int frequency(Collection<?> c, Object o) {
         if (c == null) {
@@ -2464,10 +2460,10 @@
 
     /**
      * Returns a type-safe empty, immutable {@link List}.
-     * 
+     *
      * @return an empty {@link List}.
+     * @since 1.5
      * @see #EMPTY_LIST
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static final <T> List<T> emptyList() {
@@ -2476,10 +2472,10 @@
 
     /**
      * Returns a type-safe empty, immutable {@link Set}.
-     * 
+     *
      * @return an empty {@link Set}.
+     * @since 1.5
      * @see #EMPTY_SET
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static final <T> Set<T> emptySet() {
@@ -2488,10 +2484,10 @@
 
     /**
      * Returns a type-safe empty, immutable {@link Map}.
-     * 
+     *
      * @return an empty {@link Map}.
+     * @since 1.5
      * @see #EMPTY_MAP
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public static final <K, V> Map<K, V> emptyMap() {
@@ -2503,13 +2499,12 @@
      * to insert an element of the wrong type into this collection throws a
      * {@code ClassCastException}. At creation time the types in {@code c} are
      * not checked for correct type.
-     * 
+     *
      * @param c
      *            the collection to be wrapped in a typesafe collection.
      * @param type
      *            the type of the elements permitted to insert.
      * @return a typesafe collection.
-     * @since Android 1.0
      */
     public static <E> Collection<E> checkedCollection(Collection<E> c,
             Class<E> type) {
@@ -2521,7 +2516,7 @@
      * insert an element of the wrong type into this map throws a
      * {@code ClassCastException}. At creation time the types in {@code m} are
      * not checked for correct type.
-     * 
+     *
      * @param m
      *            the map to be wrapped in a typesafe map.
      * @param keyType
@@ -2529,7 +2524,6 @@
      * @param valueType
      *            the type of the values permitted to insert.
      * @return a typesafe map.
-     * @since Android 1.0
      */
     public static <K, V> Map<K, V> checkedMap(Map<K, V> m, Class<K> keyType,
             Class<V> valueType) {
@@ -2541,13 +2535,12 @@
      * insert an element of the wrong type into this list throws a
      * {@code ClassCastException}. At creation time the types in {@code list}
      * are not checked for correct type.
-     * 
+     *
      * @param list
      *            the list to be wrapped in a typesafe list.
      * @param type
      *            the type of the elements permitted to insert.
      * @return a typesafe list.
-     * @since Android 1.0
      */
     public static <E> List<E> checkedList(List<E> list, Class<E> type) {
         if (list instanceof RandomAccess) {
@@ -2561,13 +2554,12 @@
      * insert an element of the wrong type into this set throws a
      * {@code ClassCastException}. At creation time the types in {@code s} are
      * not checked for correct type.
-     * 
+     *
      * @param s
      *            the set to be wrapped in a typesafe set.
      * @param type
      *            the type of the elements permitted to insert.
      * @return a typesafe set.
-     * @since Android 1.0
      */
     public static <E> Set<E> checkedSet(Set<E> s, Class<E> type) {
         return new CheckedSet<E>(s, type);
@@ -2578,7 +2570,7 @@
      * to insert an element of the wrong type into this sorted map throws a
      * {@code ClassCastException}. At creation time the types in {@code m} are
      * not checked for correct type.
-     * 
+     *
      * @param m
      *            the sorted map to be wrapped in a typesafe sorted map.
      * @param keyType
@@ -2586,7 +2578,6 @@
      * @param valueType
      *            the type of the values permitted to insert.
      * @return a typesafe sorted map.
-     * @since Android 1.0
      */
     public static <K, V> SortedMap<K, V> checkedSortedMap(SortedMap<K, V> m,
             Class<K> keyType, Class<V> valueType) {
@@ -2598,13 +2589,12 @@
      * to insert an element of the wrong type into this sorted set throws a
      * {@code ClassCastException}. At creation time the types in {@code s} are
      * not checked for correct type.
-     * 
+     *
      * @param s
      *            the sorted set to be wrapped in a typesafe sorted set.
      * @param type
      *            the type of the elements permitted to insert.
      * @return a typesafe sorted set.
-     * @since Android 1.0
      */
     public static <E> SortedSet<E> checkedSortedSet(SortedSet<E> s,
             Class<E> type) {
@@ -2613,7 +2603,7 @@
 
     /**
      * Adds all the specified elements to the specified collection.
-     * 
+     *
      * @param c
      *            the collection the elements are to be inserted into.
      * @param a
@@ -2628,7 +2618,6 @@
      * @throws IllegalArgumentException
      *             if at least one of the elements can't be inserted into the
      *             collection.
-     * @since Android 1.0
      */
     public static <T> boolean addAll(Collection<? super T> c, T... a) {
         boolean modified = false;
@@ -2640,7 +2629,7 @@
 
     /**
      * Returns whether the specified collections have no elements in common.
-     * 
+     *
      * @param c1
      *            the first collection.
      * @param c2
@@ -2649,7 +2638,6 @@
      *         {@code false} otherwise.
      * @throws NullPointerException
      *             if one of the collections is {@code null}.
-     * @since Android 1.0
      */
     public static boolean disjoint(Collection<?> c1, Collection<?> c2) {
         if ((c1 instanceof Set) && !(c2 instanceof Set)
@@ -2670,7 +2658,7 @@
     /**
      * Checks if specified object is instance of specified class. Used for a
      * dynamically typesafe view of the collections.
-     * 
+     *
      * @param obj -
      *            object is to be checked
      * @param type -
@@ -2701,7 +2689,7 @@
 
         /**
          * Constructs a dynamically typesafe view of the specified collection.
-         * 
+         *
          * @param c -
          *            the collection for which an unmodifiable view is to be
          *            constructed.
@@ -2844,7 +2832,7 @@
 
         /**
          * Constructs a dynamically typesafe view of the specified ListIterator.
-         * 
+         *
          * @param i -
          *            the listIterator for which a dynamically typesafe view to
          *            be constructed.
@@ -2930,7 +2918,7 @@
 
         /**
          * Constructs a dynamically typesafe view of the specified list.
-         * 
+         *
          * @param l -
          *            the list for which a dynamically typesafe view is to be
          *            constructed.
@@ -3049,7 +3037,7 @@
         /**
          * Constructs a dynamically typesafe view of the specified
          * randomAccessList.
-         * 
+         *
          * @param l -
          *            the randomAccessList for which a dynamically typesafe view
          *            is to be constructed.
@@ -3069,7 +3057,7 @@
 
         /**
          * Constructs a dynamically typesafe view of the specified set.
-         * 
+         *
          * @param s -
          *            the set for which a dynamically typesafe view is to be
          *            constructed.
@@ -3111,7 +3099,7 @@
 
         /**
          * Constructs a dynamically typesafe view of the specified map.
-         * 
+         *
          * @param m -
          *            the map for which a dynamically typesafe view is to be
          *            constructed.
@@ -3262,10 +3250,12 @@
             /**
              * Constructs a dynamically typesafe view of the specified map
              * entry.
-             * 
-             * @param e -
+             *
+             * @param e
              *            the map entry for which a dynamically typesafe view is
              *            to be constructed.
+             * @param valueType
+             *            the type of the value
              */
             public CheckedEntry(Map.Entry<K, V> e, Class<V> valueType) {
                 if (e == null) {
diff --git a/libcore/luni/src/main/java/java/util/ComparableTimSort.java b/libcore/luni/src/main/java/java/util/ComparableTimSort.java
index 882add1..cda4b12 100644
--- a/libcore/luni/src/main/java/java/util/ComparableTimSort.java
+++ b/libcore/luni/src/main/java/java/util/ComparableTimSort.java
@@ -150,7 +150,7 @@
 
         // If array is small, do a "mini-TimSort" with no merges
         if (nRemaining < MIN_MERGE) {
-            int initRunLen = countRunAndMakeAscending(a, lo, nRemaining);
+            int initRunLen = countRunAndMakeAscending(a, lo, hi);
             binarySort(a, lo, hi, lo + initRunLen);
             return;
         }
diff --git a/libcore/luni/src/main/java/java/util/Comparator.java b/libcore/luni/src/main/java/java/util/Comparator.java
index 7b09448..2d6f598 100644
--- a/libcore/luni/src/main/java/java/util/Comparator.java
+++ b/libcore/luni/src/main/java/java/util/Comparator.java
@@ -25,8 +25,8 @@
  * method has to return zero for each pair of elements (a,b) where a.equals(b)
  * holds true. It is recommended that a {@code Comparator} implements
  * {@link java.io.Serializable}.
- *  
- * @since Android 1.0
+ *
+ * @since 1.2
  */
 public interface Comparator<T> {
     /**
@@ -42,15 +42,15 @@
      * follow {@code compare(a,c) > 0} for all possible combinations of {@code
      * (a,b,c)}</li>
      * </ul>
-     * 
+     *
      * @param object1
      *            an {@code Object}.
      * @param object2
      *            a second {@code Object} to compare with {@code object1}.
      * @return an integer < 0 if {@code object1} is less than {@code object2}, 0 if they are
      *         equal, and > 0 if {@code object1} is greater than {@code object2}.
-     * @exception ClassCastException
-     *                when objects are not of the correct type.
+     * @throws ClassCastException
+     *                if objects are not of the correct type.
      */
     public int compare(T object1, T object2);
 
@@ -61,7 +61,7 @@
      * <p>
      * A {@code Comparator} never needs to override this method, but may choose so for
      * performance reasons.
-     * 
+     *
      * @param object
      *            the {@code Object} to compare with this comparator.
      * @return boolean {@code true} if specified {@code Object} is the same as this
diff --git a/libcore/luni/src/main/java/java/util/Currency.java b/libcore/luni/src/main/java/java/util/Currency.java
index 8ac0e6e..79de49d 100644
--- a/libcore/luni/src/main/java/java/util/Currency.java
+++ b/libcore/luni/src/main/java/java/util/Currency.java
@@ -17,15 +17,15 @@
 
 package java.util;
 
-import java.io.Serializable;
-
+// BEGIN android-added
 import org.apache.harmony.luni.util.Msg;
+// END android-added
+
+import java.io.Serializable;
 
 /**
  * This class represents a currency as identified in the ISO 4217 currency
  * codes.
- * 
- * @since Android 1.0
  */
 public final class Currency implements Serializable {
 
@@ -35,9 +35,11 @@
 
     private String currencyCode;
 
+    // BEGIN android-added
     private static String currencyVars = "EURO, HK, PREEURO"; //$NON-NLS-1$
 
     private transient int defaultFractionDigits;
+    // END android-added
 
     /**
      * @param currencyCode
@@ -49,20 +51,20 @@
     /**
      * Returns the {@code Currency} instance for this currency code.
      * <p>
-     * 
+     *
      * @param currencyCode
      *            the currency code.
      * @return the {@code Currency} instance for this currency code.
-     * 
+     *
      * @throws IllegalArgumentException
      *             if the currency code is not a supported ISO 4217 currency
      *             code.
-     * @since Android 1.0
      */
     public static Currency getInstance(String currencyCode) {
         Currency currency = codesToCurrencies.get(currencyCode);
 
         if (currency == null) {
+            // BEGIN android-added
             ResourceBundle bundle = Locale.getBundle(
                     "ISO4CurrenciesToDigits", Locale.getDefault()); //$NON-NLS-1$
             currency = new Currency(currencyCode);
@@ -77,6 +79,7 @@
             }
             currency.defaultFractionDigits = Integer
                     .parseInt(defaultFractionDigits);
+            // END android-added
             codesToCurrencies.put(currencyCode, currency);
         }
 
@@ -85,16 +88,26 @@
 
     /**
      * Returns the {@code Currency} instance for this {@code Locale}'s country.
-     * 
+     *
      * @param locale
      *            the {@code Locale} of a country.
      * @return the {@code Currency} used in the country defined by the locale parameter.
-     * 
+     *
      * @throws IllegalArgumentException
      *             if the locale's country is not a supported ISO 3166 Country.
-     * @since Android 1.0
      */
     public static Currency getInstance(Locale locale) {
+        // BEGIN android-changed
+        // com.ibm.icu.util.Currency currency = null;
+        // try {
+        //     currency = com.ibm.icu.util.Currency.getInstance(locale);
+        // } catch (IllegalArgumentException e) {
+        //     return null;
+        // }
+        // if (currency == null) {
+        //     throw new IllegalArgumentException(locale.getCountry());
+        // }
+        // String currencyCode = currency.getCurrencyCode();
         String country = locale.getCountry();
         String variant = locale.getVariant();
         if (!variant.equals("") && currencyVars.indexOf(variant) > -1) { //$NON-NLS-1$
@@ -110,6 +123,7 @@
             throw new IllegalArgumentException(Msg.getString(
                     "K0323", locale.toString())); //$NON-NLS-1$
         }
+        // END android-changed
 
         if (currencyCode.equals("None")) { //$NON-NLS-1$
             return null;
@@ -120,9 +134,8 @@
 
     /**
      * Returns this {@code Currency}'s ISO 4217 currency code.
-     * 
+     *
      * @return this {@code Currency}'s ISO 4217 currency code.
-     * @since Android 1.0
      */
     public String getCurrencyCode() {
         return currencyCode;
@@ -133,9 +146,8 @@
      * if the default locale is the US, the symbol of the US dollar is "$". For
      * other locales it may be "US$". If no symbol can be determined, the ISO
      * 4217 currency code of the US dollar is returned.
-     * 
+     *
      * @return the symbol for this {@code Currency} in the default {@code Locale}.
-     * @since Android 1.0
      */
     public String getSymbol() {
         return getSymbol(Locale.getDefault());
@@ -157,18 +169,19 @@
      * symbol for this currency in this bundle, then the
      * ISO 4217 currency code is returned.
      * <p>
-     * 
+     *
      * @param locale
      *            the locale for which the currency symbol should be returned.
      * @return the representation of this {@code Currency}'s symbol in the specified
      *         locale.
-     * @since Android 1.0
      */
     public String getSymbol(Locale locale) {
         if (locale.getCountry().equals("")) { //$NON-NLS-1$
             return currencyCode;
         }
 
+        // BEGIN android-changed
+        // return com.ibm.icu.util.Currency.getInstance(currencyCode).getSymbol(locale);
         // check in the Locale bundle first, if the local has the same currency
         ResourceBundle bundle = Locale.getBundle("Locale", locale); //$NON-NLS-1$
         if (((String) bundle.getObject("IntCurrencySymbol")) //$NON-NLS-1$
@@ -197,6 +210,7 @@
             return result;
         }
         return currencyCode;
+        // END android-changed
     }
 
     /**
@@ -204,19 +218,20 @@
      * instance, the default number of fraction digits for the US dollar is 2.
      * For the Japanese Yen the number is 0. In the case of pseudo-currencies,
      * such as IMF Special Drawing Rights, -1 is returned.
-     * 
+     *
      * @return the default number of fraction digits for this currency.
-     * @since Android 1.0
      */
     public int getDefaultFractionDigits() {
+        // BEGIN android-changed
+        // return com.ibm.icu.util.Currency.getInstance(currencyCode).getDefaultFractionDigits();
         return defaultFractionDigits;
+        // END android-changed
     }
 
     /**
      * Returns this currency's ISO 4217 currency code.
-     * 
+     *
      * @return this currency's ISO 4217 currency code.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
diff --git a/libcore/luni/src/main/java/java/util/Date.java b/libcore/luni/src/main/java/java/util/Date.java
index 172f682..80610d3 100644
--- a/libcore/luni/src/main/java/java/util/Date.java
+++ b/libcore/luni/src/main/java/java/util/Date.java
@@ -29,13 +29,12 @@
 
 /**
  * {@code Date} represents a specific moment in time, to the millisecond.
- * 
+ *
  * @see System#currentTimeMillis
  * @see Calendar
  * @see GregorianCalendar
  * @see SimpleTimeZone
  * @see TimeZone
- * @since Android 1.0
  */
 public class Date implements Serializable, Cloneable, Comparable<Date> {
 
@@ -46,10 +45,15 @@
 
     private transient long milliseconds;
 
+    private static String[] dayOfWeekNames = { "Sun", "Mon", "Tue", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+        "Wed", "Thu", "Fri", "Sat" }; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+
+    private static String[] monthNames = { "Jan", "Feb", "Mar", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+        "Apr", "May", "Jun", "Jul", //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+        "Aug", "Sep", "Oct", "Nov", "Dec"};  //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
+
     /**
      * Initializes this {@code Date} instance to the current date and time.
-     * 
-     * @since Android 1.0
      */
     public Date() {
         this(System.currentTimeMillis());
@@ -58,17 +62,16 @@
     /**
      * Constructs a new {@code Date} initialized to midnight in the default {@code TimeZone} on
      * the specified date.
-     * 
+     *
      * @param year
      *            the year, 0 is 1900.
      * @param month
      *            the month, 0 - 11.
      * @param day
      *            the day of the month, 1 - 31.
-     * 
+     *
      * @deprecated use
      *             {@link GregorianCalendar#GregorianCalendar(int, int, int)}
-     * @since Android 1.0
      */
     @Deprecated
     public Date(int year, int month, int day) {
@@ -80,7 +83,7 @@
     /**
      * Constructs a new {@code Date} initialized to the specified date and time in the
      * default {@code TimeZone}.
-     * 
+     *
      * @param year
      *            the year, 0 is 1900.
      * @param month
@@ -91,10 +94,9 @@
      *            the hour of day, 0 - 23.
      * @param minute
      *            the minute of the hour, 0 - 59.
-     * 
+     *
      * @deprecated use
      *             {@link GregorianCalendar#GregorianCalendar(int, int, int, int, int)}
-     * @since Android 1.0
      */
     @Deprecated
     public Date(int year, int month, int day, int hour, int minute) {
@@ -106,7 +108,7 @@
     /**
      * Constructs a new {@code Date} initialized to the specified date and time in the
      * default {@code TimeZone}.
-     * 
+     *
      * @param year
      *            the year, 0 is 1900.
      * @param month
@@ -119,10 +121,9 @@
      *            the minute of the hour, 0 - 59.
      * @param second
      *            the second of the minute, 0 - 59.
-     * 
+     *
      * @deprecated use
      *             {@link GregorianCalendar#GregorianCalendar(int, int, int, int, int, int)}
-     * @since Android 1.0
      */
     @Deprecated
     public Date(int year, int month, int day, int hour, int minute, int second) {
@@ -134,24 +135,22 @@
     /**
      * Initializes this {@code Date} instance using the specified millisecond value. The
      * value is the number of milliseconds since Jan. 1, 1970 GMT.
-     * 
+     *
      * @param milliseconds
      *            the number of milliseconds since Jan. 1, 1970 GMT.
-     * @since Android 1.0
      */
     public Date(long milliseconds) {
-        this.setTime(milliseconds);
+        this.milliseconds = milliseconds;
     }
 
     /**
      * Constructs a new {@code Date} initialized to the date and time parsed from the
      * specified String.
-     * 
+     *
      * @param string
      *            the String to parse.
-     * 
+     *
      * @deprecated use {@link DateFormat}
-     * @since Android 1.0
      */
     @Deprecated
     public Date(String string) {
@@ -160,12 +159,11 @@
 
     /**
      * Returns if this {@code Date} is after the specified Date.
-     * 
+     *
      * @param date
      *            a Date instance to compare.
      * @return {@code true} if this {@code Date} is after the specified {@code Date},
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean after(Date date) {
         return milliseconds > date.milliseconds;
@@ -173,12 +171,11 @@
 
     /**
      * Returns if this {@code Date} is before the specified Date.
-     * 
+     *
      * @param date
      *            a {@code Date} instance to compare.
      * @return {@code true} if this {@code Date} is before the specified {@code Date},
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean before(Date date) {
         return milliseconds < date.milliseconds;
@@ -186,11 +183,10 @@
 
     /**
      * Returns a new {@code Date} with the same millisecond value as this {@code Date}.
-     * 
+     *
      * @return a shallow copy of this {@code Date}.
-     * 
+     *
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -204,12 +200,11 @@
     /**
      * Compare the receiver to the specified {@code Date} to determine the relative
      * ordering.
-     * 
+     *
      * @param date
      *            a {@code Date} to compare against.
      * @return an {@code int < 0} if this {@code Date} is less than the specified {@code Date}, {@code 0} if
      *         they are equal, and an {@code int > 0} if this {@code Date} is greater.
-     * @since Android 1.0
      */
     public int compareTo(Date date) {
         if (milliseconds < date.milliseconds) {
@@ -225,14 +220,13 @@
      * Compares the specified object to this {@code Date} and returns if they are equal.
      * To be equal, the object must be an instance of {@code Date} and have the same millisecond
      * value.
-     * 
+     *
      * @param object
      *            the object to compare with this object.
      * @return {@code true} if the specified object is equal to this {@code Date}, {@code false}
      *         otherwise.
-     * 
+     *
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -242,11 +236,10 @@
 
     /**
      * Returns the gregorian calendar day of the month for this {@code Date} object.
-     * 
+     *
      * @return the day of the month.
-     * 
+     *
      * @deprecated use {@code Calendar.get(Calendar.DATE)}
-     * @since Android 1.0
      */
     @Deprecated
     public int getDate() {
@@ -255,11 +248,10 @@
 
     /**
      * Returns the gregorian calendar day of the week for this {@code Date} object.
-     * 
+     *
      * @return the day of the week.
-     * 
+     *
      * @deprecated use {@code Calendar.get(Calendar.DAY_OF_WEEK)}
-     * @since Android 1.0
      */
     @Deprecated
     public int getDay() {
@@ -268,11 +260,10 @@
 
     /**
      * Returns the gregorian calendar hour of the day for this {@code Date} object.
-     * 
+     *
      * @return the hour of the day.
-     * 
+     *
      * @deprecated use {@code Calendar.get(Calendar.HOUR_OF_DAY)}
-     * @since Android 1.0
      */
     @Deprecated
     public int getHours() {
@@ -281,11 +272,10 @@
 
     /**
      * Returns the gregorian calendar minute of the hour for this {@code Date} object.
-     * 
+     *
      * @return the minutes.
-     * 
+     *
      * @deprecated use {@code Calendar.get(Calendar.MINUTE)}
-     * @since Android 1.0
      */
     @Deprecated
     public int getMinutes() {
@@ -294,11 +284,10 @@
 
     /**
      * Returns the gregorian calendar month for this {@code Date} object.
-     * 
+     *
      * @return the month.
-     * 
+     *
      * @deprecated use {@code Calendar.get(Calendar.MONTH)}
-     * @since Android 1.0
      */
     @Deprecated
     public int getMonth() {
@@ -307,11 +296,10 @@
 
     /**
      * Returns the gregorian calendar second of the minute for this {@code Date} object.
-     * 
+     *
      * @return the seconds.
-     * 
+     *
      * @deprecated use {@code Calendar.get(Calendar.SECOND)}
-     * @since Android 1.0
      */
     @Deprecated
     public int getSeconds() {
@@ -321,9 +309,8 @@
     /**
      * Returns this {@code Date} as a millisecond value. The value is the number of
      * milliseconds since Jan. 1, 1970, midnight GMT.
-     * 
+     *
      * @return the number of milliseconds since Jan. 1, 1970, midnight GMT.
-     * @since Android 1.0
      */
     public long getTime() {
         return milliseconds;
@@ -331,12 +318,11 @@
 
     /**
      * Returns the timezone offset in minutes of the default {@code TimeZone}.
-     * 
+     *
      * @return the timezone offset in minutes of the default {@code TimeZone}.
-     * 
+     *
      * @deprecated use
      *             {@code (Calendar.get(Calendar.ZONE_OFFSET) + Calendar.get(Calendar.DST_OFFSET)) / 60000}
-     * @since Android 1.0
      */
     @Deprecated
     public int getTimezoneOffset() {
@@ -346,11 +332,10 @@
 
     /**
      * Returns the gregorian calendar year since 1900 for this {@code Date} object.
-     * 
+     *
      * @return the year - 1900.
-     * 
+     *
      * @deprecated use {@code Calendar.get(Calendar.YEAR) - 1900}
-     * @since Android 1.0
      */
     @Deprecated
     public int getYear() {
@@ -360,11 +345,10 @@
     /**
      * Returns an integer hash code for the receiver. Objects which are equal
      * return the same value for this method.
-     * 
+     *
      * @return this {@code Date}'s hash.
-     * 
+     *
      * @see #equals
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -384,13 +368,12 @@
      * Returns the millisecond value of the date and time parsed from the
      * specified {@code String}. Many date/time formats are recognized, including IETF
      * standard syntax, i.e. Tue, 22 Jun 1999 12:16:00 GMT-0500
-     * 
+     *
      * @param string
      *            the String to parse.
      * @return the millisecond value parsed from the String.
-     * 
+     *
      * @deprecated use {@link DateFormat}
-     * @since Android 1.0
      */
     @Deprecated
     public static long parse(String string) {
@@ -404,10 +387,10 @@
         int commentLevel = 0;
         int offset = 0, length = string.length(), state = 0;
         int year = -1, month = -1, date = -1;
-        int hour = -1, minute = -1, second = -1, zoneOffset = 0;
+        int hour = -1, minute = -1, second = -1, zoneOffset = 0, minutesOffset = 0;
         boolean zone = false;
         final int PAD = 0, LETTERS = 1, NUMBERS = 2;
-        StringBuffer buffer = new StringBuffer();
+        StringBuilder buffer = new StringBuilder();
 
         while (offset <= length) {
             char next = offset < length ? string.charAt(offset) : '\r';
@@ -442,6 +425,14 @@
                 if (sign == '+' || sign == '-') {
                     if (zoneOffset == 0) {
                         zone = true;
+                        if (next == ':') {
+                            minutesOffset = sign == '-' ? -Integer
+                                    .parseInt(string.substring(offset,
+                                            offset + 2)) : Integer
+                                    .parseInt(string.substring(offset,
+                                            offset + 2));
+                            offset += 2;
+                        }
                         zoneOffset = sign == '-' ? -digit : digit;
                         sign = 0;
                     } else {
@@ -557,6 +548,7 @@
             } else if (year < 100) {
                 year += 1900;
             }
+            minute -= minutesOffset;
             if (zone) {
                 if (zoneOffset >= 24 || zoneOffset <= -24) {
                     hour -= zoneOffset / 100;
@@ -574,12 +566,11 @@
 
     /**
      * Sets the gregorian calendar day of the month for this {@code Date} object.
-     * 
+     *
      * @param day
      *            the day of the month.
-     * 
+     *
      * @deprecated use {@code Calendar.set(Calendar.DATE, day)}
-     * @since Android 1.0
      */
     @Deprecated
     public void setDate(int day) {
@@ -590,12 +581,11 @@
 
     /**
      * Sets the gregorian calendar hour of the day for this {@code Date} object.
-     * 
+     *
      * @param hour
      *            the hour of the day.
-     * 
+     *
      * @deprecated use {@code Calendar.set(Calendar.HOUR_OF_DAY, hour)}
-     * @since Android 1.0
      */
     @Deprecated
     public void setHours(int hour) {
@@ -606,12 +596,11 @@
 
     /**
      * Sets the gregorian calendar minute of the hour for this {@code Date} object.
-     * 
+     *
      * @param minute
      *            the minutes.
-     * 
+     *
      * @deprecated use {@code Calendar.set(Calendar.MINUTE, minute)}
-     * @since Android 1.0
      */
     @Deprecated
     public void setMinutes(int minute) {
@@ -622,12 +611,11 @@
 
     /**
      * Sets the gregorian calendar month for this {@code Date} object.
-     * 
+     *
      * @param month
      *            the month.
-     * 
+     *
      * @deprecated use {@code Calendar.set(Calendar.MONTH, month)}
-     * @since Android 1.0
      */
     @Deprecated
     public void setMonth(int month) {
@@ -638,12 +626,11 @@
 
     /**
      * Sets the gregorian calendar second of the minute for this {@code Date} object.
-     * 
+     *
      * @param second
      *            the seconds.
-     * 
+     *
      * @deprecated use {@code Calendar.set(Calendar.SECOND, second)}
-     * @since Android 1.0
      */
     @Deprecated
     public void setSeconds(int second) {
@@ -655,10 +642,9 @@
     /**
      * Sets this {@code Date} to the specified millisecond value. The value is the
      * number of milliseconds since Jan. 1, 1970 GMT.
-     * 
+     *
      * @param milliseconds
      *            the number of milliseconds since Jan. 1, 1970 GMT.
-     * @since Android 1.0
      */
     public void setTime(long milliseconds) {
         this.milliseconds = milliseconds;
@@ -666,12 +652,11 @@
 
     /**
      * Sets the gregorian calendar year since 1900 for this {@code Date} object.
-     * 
+     *
      * @param year
      *            the year since 1900.
-     * 
+     *
      * @deprecated use {@code Calendar.set(Calendar.YEAR, year + 1900)}
-     * @since Android 1.0
      */
     @Deprecated
     public void setYear(int year) {
@@ -683,11 +668,10 @@
     /**
      * Returns the string representation of this {@code Date} in GMT in the format: 22
      * Jun 1999 13:02:00 GMT
-     * 
+     *
      * @return the string representation of this {@code Date} in GMT.
-     * 
+     *
      * @deprecated use {@link DateFormat}
-     * @since Android 1.0
      */
     @Deprecated
     public String toGMTString() {
@@ -705,11 +689,10 @@
 
     /**
      * Returns the string representation of this {@code Date} for the default {@code Locale}.
-     * 
+     *
      * @return the string representation of this {@code Date} for the default {@code Locale}.
-     * 
+     *
      * @deprecated use {@link DateFormat}
-     * @since Android 1.0
      */
     @Deprecated
     public String toLocaleString() {
@@ -719,20 +702,29 @@
     /**
      * Returns the string representation of this {@code Date} in the format: Tue Jun 22
      * 13:07:00 GMT 1999
-     * 
+     *
      * @return the string representation of this {@code Date}.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
-        return new SimpleDateFormat("E MMM dd HH:mm:ss z ", Locale.US) //$NON-NLS-1$
-                .format(this)
-                + new GregorianCalendar(milliseconds).get(Calendar.YEAR);
+        Calendar cal = new GregorianCalendar(milliseconds);
+        return dayOfWeekNames[cal.get(Calendar.DAY_OF_WEEK) - 1] + " " + monthNames[cal.get(Calendar.MONTH)]//$NON-NLS-1$
+                + " " + toTwoDigits(cal.get(Calendar.DAY_OF_MONTH)) + " " + toTwoDigits(cal.get(Calendar.HOUR_OF_DAY))//$NON-NLS-1$ //$NON-NLS-2$
+                + ":" + toTwoDigits(cal.get(Calendar.MINUTE)) + ":" + toTwoDigits(cal.get(Calendar.SECOND))//$NON-NLS-1$ //$NON-NLS-2$
+                + " " + cal.getTimeZone().getID() + " " + cal.get(Calendar.YEAR);//$NON-NLS-1$ //$NON-NLS-2$
+    }
+
+    private String toTwoDigits(int digit) {
+        if(digit >= 10) {
+            return "" + digit;//$NON-NLS-1$
+        } else {
+            return "0" + digit;//$NON-NLS-1$
+        }
     }
 
     /**
      * Returns the millisecond value of the specified date and time in GMT.
-     * 
+     *
      * @param year
      *            the year, 0 is 1900.
      * @param month
@@ -746,12 +738,11 @@
      * @param second
      *            the second of the minute, 0 - 59.
      * @return the date and time in GMT in milliseconds.
-     * 
+     *
      * @deprecated use: <code>
      *  Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
      *  cal.set(year + 1900, month, day, hour, minute, second);
      *  cal.getTime().getTime();</code>
-     * @since Android 1.0
      */
     @Deprecated
     public static long UTC(int year, int month, int day, int hour, int minute,
diff --git a/libcore/luni/src/main/java/java/util/Dictionary.java b/libcore/luni/src/main/java/java/util/Dictionary.java
index 236ddf0..c29b11b 100644
--- a/libcore/luni/src/main/java/java/util/Dictionary.java
+++ b/libcore/luni/src/main/java/java/util/Dictionary.java
@@ -25,14 +25,11 @@
  * associate keys with values, such as {@code Hashtable}.
  * 
  * @see Hashtable
- * @since Android 1.0
+ * @since 1.0
  */
-public abstract class Dictionary<K,V> {
-
+public abstract class Dictionary<K, V> {
     /**
      * Constructs a new instance of this class.
-     * 
-     * @since Android 1.0
      */
     public Dictionary() {
         super();
@@ -45,7 +42,6 @@
      * @see #keys
      * @see #size
      * @see Enumeration
-     * @since Android 1.0
      */
     public abstract Enumeration<V> elements();
 
@@ -57,7 +53,6 @@
      * @return the value associated with {@code key}, or {@code null} if the
      *         specified key does not exist.
      * @see #put
-     * @since Android 1.0
      */
     public abstract V get(Object key);
 
@@ -67,7 +62,6 @@
      * @return {@code true} if this dictionary has no key/value pairs,
      *         {@code false} otherwise.
      * @see #size
-     * @since Android 1.0
      */
     public abstract boolean isEmpty();
 
@@ -78,7 +72,6 @@
      * @see #elements
      * @see #size
      * @see Enumeration
-     * @since Android 1.0
      */
     public abstract Enumeration<K> keys();
 
@@ -96,7 +89,6 @@
      * @see #elements
      * @see #get
      * @see #keys
-     * @since Android 1.0
      */
     public abstract V put(K key, V value);
 
@@ -110,7 +102,6 @@
      *         {@code key} was not known to this dictionary.
      * @see #get
      * @see #put
-     * @since Android 1.0
      */
     public abstract V remove(Object key);
 
@@ -120,7 +111,6 @@
      * @return the number of key/value pairs in this dictionary.
      * @see #elements
      * @see #keys
-     * @since Android 1.0
      */
     public abstract int size();
 }
diff --git a/libcore/luni/src/main/java/java/util/DuplicateFormatFlagsException.java b/libcore/luni/src/main/java/java/util/DuplicateFormatFlagsException.java
index 908aa36..3330dcb 100644
--- a/libcore/luni/src/main/java/java/util/DuplicateFormatFlagsException.java
+++ b/libcore/luni/src/main/java/java/util/DuplicateFormatFlagsException.java
@@ -19,12 +19,11 @@
 /**
  * The unchecked exception will be thrown out if there are duplicate flags given
  * out in the format specifier.
- * 
+ *
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class DuplicateFormatFlagsException extends IllegalFormatException {
-    
+
     private static final long serialVersionUID = 18890531L;
 
     private String flags;
diff --git a/libcore/luni/src/main/java/java/util/EmptyStackException.java b/libcore/luni/src/main/java/java/util/EmptyStackException.java
index 73d33ba..d8a48cc 100644
--- a/libcore/luni/src/main/java/java/util/EmptyStackException.java
+++ b/libcore/luni/src/main/java/java/util/EmptyStackException.java
@@ -21,9 +21,8 @@
 /**
  * An {@code EmptyStackException} is thrown if the pop/peek method of a stack is
  * executed on an empty stack.
- * 
+ *
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class EmptyStackException extends RuntimeException {
 
diff --git a/libcore/luni/src/main/java/java/util/EnumMap.java b/libcore/luni/src/main/java/java/util/EnumMap.java
index 1351069..975fdad 100644
--- a/libcore/luni/src/main/java/java/util/EnumMap.java
+++ b/libcore/luni/src/main/java/java/util/EnumMap.java
@@ -24,11 +24,14 @@
 
 /**
  * An {@code Map} specialized for use with {@code Enum} types as keys.
- *  
- * @since Android 1.0
  */
 public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V> implements
-        Map<K, V>, Serializable, Cloneable {
+        Serializable, Cloneable, Map<K, V> {
+
+    // BEGIN android-changed
+    // added implements Map<K, V> for apicheck
+    // END android-changed
+
     private static final long serialVersionUID = 458661240069192865L;
 
     private Class<K> keyType;
@@ -57,6 +60,7 @@
             ordinal = ((Enum) theKey).ordinal();
         }
 
+        @SuppressWarnings("unchecked")
         @Override
         public boolean equals(Object object) {
             if (!enumMap.hasMapping[ordinal]) {
@@ -83,18 +87,21 @@
                             : enumMap.values[ordinal].hashCode());
         }
 
+        @SuppressWarnings("unchecked")
         @Override
         public KT getKey() {
             checkEntryStatus();
             return (KT) enumMap.keys[ordinal];
         }
 
+        @SuppressWarnings("unchecked")
         @Override
         public VT getValue() {
             checkEntryStatus();
             return (VT) enumMap.values[ordinal];
         }
 
+        @SuppressWarnings("unchecked")
         @Override
         public VT setValue(VT value) {
             checkEntryStatus();
@@ -285,6 +292,7 @@
             super(value, em);
         }
 
+        @SuppressWarnings("unchecked")
         @Override
         public E next() {
             if (!hasNext()) {
@@ -354,6 +362,7 @@
             return toArray(entryArray);
         }
 
+        @SuppressWarnings("unchecked")
         @Override
         public Object[] toArray(Object[] array) {
             int size = enumMap.size();
@@ -378,10 +387,11 @@
 
     /**
      * Constructs an empty {@code EnumMap} using the given key type.
-     * 
+     *
      * @param keyType
      *            the class object giving the type of the keys used by this {@code EnumMap}.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code keyType} is {@code null}.
      */
     public EnumMap(Class<K> keyType) {
         initialization(keyType);
@@ -390,10 +400,11 @@
     /**
      * Constructs an {@code EnumMap} using the same key type as the given {@code EnumMap} and
      * initially containing the same mappings.
-     * 
+     *
      * @param map
      *            the {@code EnumMap} from which this {@code EnumMap} is initialized.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code map} is {@code null}.
      */
     public EnumMap(EnumMap<K, ? extends V> map) {
         initialization(map);
@@ -402,16 +413,18 @@
     /**
      * Constructs an {@code EnumMap} initialized from the given map. If the given map
      * is an {@code EnumMap} instance, this constructor behaves in the exactly the same
-     * way as {@link EnumMap#EnumMap(EnumMap)}}. Otherwise, the given map 
+     * way as {@link EnumMap#EnumMap(EnumMap)}}. Otherwise, the given map
      * should contain at least one mapping.
-     * 
+     *
      * @param map
      *            the map from which this {@code EnumMap} is initialized.
      * @throws IllegalArgumentException
      *             if {@code map} is not an {@code EnumMap} instance and does not contain
      *             any mappings.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code map} is {@code null}.
      */
+    @SuppressWarnings("unchecked")
     public EnumMap(Map<K, ? extends V> map) {
         if (map instanceof EnumMap) {
             initialization((EnumMap<K, V>) map);
@@ -433,10 +446,9 @@
 
     /**
      * Removes all elements from this {@code EnumMap}, leaving it empty.
-     * 
+     *
      * @see #isEmpty()
      * @see #size()
-     * @since Android 1.0
      */
     @Override
     public void clear() {
@@ -447,10 +459,10 @@
 
     /**
      * Returns a shallow copy of this {@code EnumMap}.
-     * 
+     *
      * @return a shallow copy of this {@code EnumMap}.
-     * @since Android 1.0
      */
+    @SuppressWarnings("unchecked")
     @Override
     public EnumMap<K, V> clone() {
         try {
@@ -464,12 +476,11 @@
 
     /**
      * Returns whether this {@code EnumMap} contains the specified key.
-     * 
+     *
      * @param key
      *            the key to search for.
      * @return {@code true} if this {@code EnumMap} contains the specified key,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean containsKey(Object key) {
@@ -482,12 +493,11 @@
 
     /**
      * Returns whether this {@code EnumMap} contains the specified value.
-     * 
+     *
      * @param value
      *            the value to search for.
      * @return {@code true} if this {@code EnumMap} contains the specified value,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean containsValue(Object value) {
@@ -511,9 +521,11 @@
      * Returns a {@code Set} containing all of the mappings in this {@code EnumMap}. Each mapping is
      * an instance of {@link Map.Entry}. As the {@code Set} is backed by this {@code EnumMap},
      * changes in one will be reflected in the other.
-     * 
+     * <p>
+     * The order of the entries in the set will be the order that the enum keys
+     * were declared in.
+     *
      * @return a {@code Set} of the mappings.
-     * @since Android 1.0
      */
     @Override
     public Set<Map.Entry<K, V>> entrySet() {
@@ -526,15 +538,15 @@
     /**
      * Compares the argument to the receiver, and returns {@code true} if the
      * specified {@code Object} is an {@code EnumMap} and both {@code EnumMap}s contain the same mappings.
-     * 
+     *
      * @param object
      *            the {@code Object} to compare with this {@code EnumMap}.
      * @return boolean {@code true} if {@code object} is the same as this {@code EnumMap},
      *         {@code false} otherwise.
      * @see #hashCode()
      * @see #entrySet()
-     * @since Android 1.0
      */
+    @SuppressWarnings("unchecked")
     @Override
     public boolean equals(Object object) {
         if (this == object) {
@@ -553,12 +565,11 @@
 
     /**
      * Returns the value of the mapping with the specified key.
-     * 
+     *
      * @param key
      *            the key.
      * @return the value of the mapping with the specified key, or {@code null}
      *         if no mapping for the specified key is found.
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
@@ -574,9 +585,11 @@
      * Returns a set of the keys contained in this {@code EnumMap}. The {@code Set} is backed by
      * this {@code EnumMap} so changes to one are reflected in the other. The {@code Set} does not
      * support adding.
-     * 
+     * <p>
+     * The order of the set will be the order that the enum keys were declared
+     * in.
+     *
      * @return a {@code Set} of the keys.
-     * @since Android 1.0
      */
     @Override
     public Set<K> keySet() {
@@ -588,7 +601,7 @@
 
     /**
      * Maps the specified key to the specified value.
-     * 
+     *
      * @param key
      *            the key.
      * @param value
@@ -605,7 +618,6 @@
      * @throws NullPointerException
      *                if the key or value is {@code null} and this {@code EnumMap} does not
      *                support {@code null} keys or values.
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
@@ -615,7 +627,7 @@
 
     /**
      * Copies every mapping in the specified {@code Map} to this {@code EnumMap}.
-     * 
+     *
      * @param map
      *            the {@code Map} to copy mappings from.
      * @throws UnsupportedOperationException
@@ -628,7 +640,6 @@
      * @throws NullPointerException
      *                if a key or value is {@code null} and this {@code EnumMap} does not
      *                support {@code null} keys or values.
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
@@ -638,14 +649,13 @@
 
     /**
      * Removes a mapping with the specified key from this {@code EnumMap}.
-     * 
+     *
      * @param key
      *            the key of the mapping to remove.
      * @return the value of the removed mapping or {@code null} if no mapping
      *         for the specified key was found.
      * @throws UnsupportedOperationException
      *                if removing from this {@code EnumMap} is not supported.
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
@@ -665,9 +675,8 @@
 
     /**
      * Returns the number of elements in this {@code EnumMap}.
-     * 
+     *
      * @return the number of elements in this {@code EnumMap}.
-     * @since Android 1.0
      */
     @Override
     public int size() {
@@ -680,9 +689,11 @@
      * {@link Map#values()}. The {@code Collection}'s {@code Iterator} will return the values
      * in the their corresponding keys' natural order (the {@code Enum} constants are
      * declared in this order).
-     * 
+     * <p>
+     * The order of the values in the collection will be the order that their
+     * corresponding enum keys were declared in.
+     *
      * @return a collection of the values contained in this {@code EnumMap}.
-     * @since Android 1.0
      */
     @Override
     public Collection<V> values() {
@@ -692,6 +703,7 @@
         return valuesCollection;
     }
 
+    @SuppressWarnings("unchecked")
     private void readObject(ObjectInputStream stream) throws IOException,
             ClassNotFoundException {
         stream.defaultReadObject();
diff --git a/libcore/luni/src/main/java/java/util/EnumSet.java b/libcore/luni/src/main/java/java/util/EnumSet.java
index 4e44f2e..d49d900 100644
--- a/libcore/luni/src/main/java/java/util/EnumSet.java
+++ b/libcore/luni/src/main/java/java/util/EnumSet.java
@@ -23,8 +23,6 @@
 
 /**
  * An EnumSet is a specialized Set to be used with enums as keys.
- * 
- * @since Android 1.0
  */
 public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E>
         implements Cloneable, Serializable {
@@ -37,7 +35,7 @@
     static /*package*/ LangAccess LANG_BOOTSTRAP = null;
     // END android-added
 
-    private static final long serialVersionUID = 4782406773684236311L;
+    private static final long serialVersionUID = 1009687484059888093L;
 
     final Class<E> elementClass;
 
@@ -48,14 +46,13 @@
     /**
      * Creates an empty enum set. The permitted elements are of type
      * Class&lt;E&gt;.
-     * 
+     *
      * @param elementType
      *            the class object for the elements contained.
      * @return an empty enum set, with permitted elements of type {@code
      *         elementType}.
      * @throws ClassCastException
      *             if the specified element type is not and enum type.
-     * @since Android 1.0
      */
     public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
         if (!elementType.isEnum()) {
@@ -73,13 +70,12 @@
     /**
      * Creates an enum set filled with all the enum elements of the specified
      * {@code elementType}.
-     * 
+     *
      * @param elementType
      *            the class object for the elements contained.
      * @return an enum set with elements solely from the specified element type.
      * @throws ClassCastException
      *             if the specified element type is not and enum type.
-     * @since Android 1.0
      */
     public static <E extends Enum<E>> EnumSet<E> allOf(Class<E> elementType) {
         EnumSet<E> set = noneOf(elementType);
@@ -91,13 +87,12 @@
      * Creates an enum set. All the contained elements are of type
      * Class&lt;E&gt;, and the contained elements are the same as those
      * contained in {@code s}.
-     * 
+     *
      * @param s
      *            the enum set from which to copy.
      * @return an enum set with all the elements from the specified enum set.
      * @throws ClassCastException
      *             if the specified element type is not and enum type.
-     * @since Android 1.0
      */
     public static <E extends Enum<E>> EnumSet<E> copyOf(EnumSet<E> s) {
         EnumSet<E> set = EnumSet.noneOf(s.elementClass);
@@ -109,14 +104,15 @@
      * Creates an enum set. The contained elements are the same as those
      * contained in collection {@code c}. If c is an enum set, invoking this
      * method is the same as invoking {@link #copyOf(EnumSet)}.
-     * 
+     *
      * @param c
      *            the collection from which to copy. if it is not an enum set,
      *            it must not be empty.
      * @return an enum set with all the elements from the specified collection.
      * @throws IllegalArgumentException
      *             if c is not an enum set and contains no elements at all.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code c} is {@code null}.
      */
     public static <E extends Enum<E>> EnumSet<E> copyOf(Collection<E> c) {
         if (c instanceof EnumSet) {
@@ -138,12 +134,13 @@
     /**
      * Creates an enum set. All the contained elements complement those from the
      * specified enum set.
-     * 
+     *
      * @param s
      *            the specified enum set.
      * @return an enum set with all the elements complementary to those from the
      *         specified enum set.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code s} is {@code null}.
      */
     public static <E extends Enum<E>> EnumSet<E> complementOf(EnumSet<E> s) {
         EnumSet<E> set = EnumSet.noneOf(s.elementClass);
@@ -159,11 +156,12 @@
      * six overloadings of the method. They accept from one to five elements
      * respectively. The sixth one receives an arbitrary number of elements, and
      * runs slower than those that only receive a fixed number of elements.
-     * 
+     *
      * @param e
      *            the element to be initially contained.
      * @return an enum set containing the specified element.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code e} is {@code null}.
      */
     public static <E extends Enum<E>> EnumSet<E> of(E e) {
         EnumSet<E> set = EnumSet.noneOf(e.getDeclaringClass());
@@ -172,17 +170,18 @@
     }
 
     /**
-     * Creates a new enum set, containing only the specified element. There are
+     * Creates a new enum set, containing only the specified elements. There are
      * six overloadings of the method. They accept from one to five elements
      * respectively. The sixth one receives an arbitrary number of elements, and
      * runs slower than those that only receive a fixed number of elements.
-     * 
+     *
      * @param e1
      *            the initially contained element.
      * @param e2
      *            another initially contained element.
-     * @return an enum set containing the specified element.
-     * @since Android 1.0
+     * @return an enum set containing the specified elements.
+     * @throws NullPointerException
+     *             if any of the specified elements is {@code null}.
      */
     public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2) {
         EnumSet<E> set = of(e1);
@@ -191,19 +190,20 @@
     }
 
     /**
-     * Creates a new enum set, containing only the specified element. There are
+     * Creates a new enum set, containing only the specified elements. There are
      * six overloadings of the method. They accept from one to five elements
      * respectively. The sixth one receives an arbitrary number of elements, and
      * runs slower than those that only receive a fixed number of elements.
-     * 
+     *
      * @param e1
      *            the initially contained element.
      * @param e2
      *            another initially contained element.
      * @param e3
      *            another initially contained element.
-     * @return an enum set containing the specified element.
-     * @since Android 1.0
+     * @return an enum set containing the specified elements.
+     * @throws NullPointerException
+     *             if any of the specified elements is {@code null}.
      */
     public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3) {
         EnumSet<E> set = of(e1, e2);
@@ -212,11 +212,11 @@
     }
 
     /**
-     * Creates a new enum set, containing only the specified element. There are
+     * Creates a new enum set, containing only the specified elements. There are
      * six overloadings of the method. They accept from one to five elements
      * respectively. The sixth one receives an arbitrary number of elements, and
      * runs slower than those that only receive a fixed number of elements.
-     * 
+     *
      * @param e1
      *            the initially contained element.
      * @param e2
@@ -225,8 +225,9 @@
      *            another initially contained element.
      * @param e4
      *            another initially contained element.
-     * @return an enum set containing the specified element.
-     * @since Android 1.0
+     * @return an enum set containing the specified elements.
+     * @throws NullPointerException
+     *             if any of the specified elements is {@code null}.
      */
     public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4) {
         EnumSet<E> set = of(e1, e2, e3);
@@ -235,11 +236,11 @@
     }
 
     /**
-     * Creates a new enum set, containing only the specified element. There are
+     * Creates a new enum set, containing only the specified elements. There are
      * six overloadings of the method. They accept from one to five elements
      * respectively. The sixth one receives an arbitrary number of elements, and
      * runs slower than those that only receive a fixed number of elements.
-     * 
+     *
      * @param e1
      *            the initially contained element.
      * @param e2
@@ -250,8 +251,9 @@
      *            another initially contained element.
      * @param e5
      *            another initially contained element.
-     * @return an enum set containing the specified element.
-     * @since Android 1.0
+     * @return an enum set containing the specified elements.
+     * @throws NullPointerException
+     *             if any of the specified elements is {@code null}.
      */
     public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4, E e5) {
         EnumSet<E> set = of(e1, e2, e3, e4);
@@ -263,13 +265,14 @@
      * Creates a new enum set, containing only the specified elements. It can
      * receive an arbitrary number of elements, and runs slower than those only
      * receiving a fixed number of elements.
-     * 
+     *
      * @param start
      *            the first initially contained element.
      * @param others
      *            the other initially contained elements.
      * @return an enum set containing the specified elements.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if any of the specified elements is {@code null}.
      */
     public static <E extends Enum<E>> EnumSet<E> of(E start, E... others) {
         EnumSet<E> set = of(start);
@@ -283,15 +286,16 @@
      * Creates an enum set containing all the elements within the range defined
      * by {@code start} and {@code end} (inclusive). All the elements must be in
      * order.
-     * 
+     *
      * @param start
      *            the element used to define the beginning of the range.
      * @param end
      *            the element used to define the end of the range.
      * @return an enum set with elements in the range from start to end.
+     * @throws NullPointerException
+     *             if any one of {@code start} or {@code end} is {@code null}.
      * @throws IllegalArgumentException
      *             if {@code start} is behind {@code end}.
-     * @since Android 1.0
      */
     public static <E extends Enum<E>> EnumSet<E> range(E start, E end) {
         if (start.compareTo(end) > 0) {
@@ -307,10 +311,9 @@
     /**
      * Creates a new enum set with the same elements as those contained in this
      * enum set.
-     * 
+     *
      * @return a new enum set with the same elements as those contained in this
      *         enum set.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     @Override
diff --git a/libcore/luni/src/main/java/java/util/Enumeration.java b/libcore/luni/src/main/java/java/util/Enumeration.java
index d60bdd2..8b8f7bd 100644
--- a/libcore/luni/src/main/java/java/util/Enumeration.java
+++ b/libcore/luni/src/main/java/java/util/Enumeration.java
@@ -17,18 +17,16 @@
 
 package java.util;
 
-
 /**
  * An Enumeration is used to sequence over a collection of objects.
  * <p>
- * Preferably an Iterator should be used. Iterator replaces the Enumeration
- * interface and adds a way to remove elements from a collection.
- * </p>
- * 
+ * Preferably an {@link Iterator} should be used. {@code Iterator} replaces the
+ * enumeration interface and adds a way to remove elements from a collection.
+ *
  * @see Hashtable
  * @see Properties
  * @see Vector
- * @since Android 1.0
+ * @version 1.0
  */
 public interface Enumeration<E> {
 
@@ -37,7 +35,6 @@
      * 
      * @return {@code true} if there are more elements, {@code false} otherwise.
      * @see #nextElement
-     * @since Android 1.0
      */
     public boolean hasMoreElements();
 
@@ -48,7 +45,6 @@
      * @throws NoSuchElementException
      *             if there are no more elements.
      * @see #hasMoreElements
-     * @since Android 1.0
      */
     public E nextElement();
 }
diff --git a/libcore/luni/src/main/java/java/util/EventListener.java b/libcore/luni/src/main/java/java/util/EventListener.java
index 9ff4876..b100f0c 100644
--- a/libcore/luni/src/main/java/java/util/EventListener.java
+++ b/libcore/luni/src/main/java/java/util/EventListener.java
@@ -17,13 +17,11 @@
 
 package java.util;
 
-
 /**
  * EventListener is the superclass of all event listener interfaces.
- *
+ * 
  * @see EventObject
- * @since Android 1.0
  */
 public interface EventListener {
-    /*empty*/
+    /* empty */
 }
diff --git a/libcore/luni/src/main/java/java/util/EventListenerProxy.java b/libcore/luni/src/main/java/java/util/EventListenerProxy.java
index a165385..1e023f6 100644
--- a/libcore/luni/src/main/java/java/util/EventListenerProxy.java
+++ b/libcore/luni/src/main/java/java/util/EventListenerProxy.java
@@ -20,8 +20,6 @@
 
 /**
  * This abstract class provides a simple wrapper for objects of type {@code EventListener}.
- *  
- * @since Android 1.0
  */
 public abstract class EventListenerProxy implements EventListener {
 
@@ -32,7 +30,6 @@
      * 
      * @param listener
      *            the listener wrapped by this proxy.
-     * @since Android 1.0
      */
     public EventListenerProxy(EventListener listener) {
         super();
@@ -43,7 +40,6 @@
      * Returns the wrapped {@code EventListener}.
      * 
      * @return the wrapped {@code EventListener}.
-     * @since Android 1.0
      */
     public EventListener getListener() {
         return listener;
diff --git a/libcore/luni/src/main/java/java/util/EventObject.java b/libcore/luni/src/main/java/java/util/EventObject.java
index 61e530a..76da7e2 100644
--- a/libcore/luni/src/main/java/java/util/EventObject.java
+++ b/libcore/luni/src/main/java/java/util/EventObject.java
@@ -25,8 +25,6 @@
  * add event specific information.
  * 
  * @see EventListener
- *  
- * @since Android 1.0
  */
 public class EventObject implements Serializable {
     
@@ -34,8 +32,6 @@
 
     /**
      * The event source.
-     * 
-     * @since Android 1.0
      */
     protected transient Object source;
 
@@ -44,7 +40,6 @@
      * 
      * @param source
      *            the object which fired the event.
-     * @since Android 1.0
      */
     public EventObject(Object source) {
         if (source != null) {
@@ -58,7 +53,6 @@
      * Returns the event source.
      * 
      * @return the object which fired the event.
-     * @since Android 1.0
      */
     public Object getSource() {
         return source;
@@ -68,7 +62,6 @@
      * Returns the string representation of this {@code EventObject}.
      * 
      * @return the string representation of this {@code EventObject}.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
diff --git a/libcore/luni/src/main/java/java/util/FormatFlagsConversionMismatchException.java b/libcore/luni/src/main/java/java/util/FormatFlagsConversionMismatchException.java
index aa0c967..e4f39d2 100644
--- a/libcore/luni/src/main/java/java/util/FormatFlagsConversionMismatchException.java
+++ b/libcore/luni/src/main/java/java/util/FormatFlagsConversionMismatchException.java
@@ -23,7 +23,6 @@
  * conversion and the flags are incompatible.
  * 
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class FormatFlagsConversionMismatchException extends
         IllegalFormatException implements Serializable {
diff --git a/libcore/luni/src/main/java/java/util/Formattable.java b/libcore/luni/src/main/java/java/util/Formattable.java
index 2564c04..15b66b5 100644
--- a/libcore/luni/src/main/java/java/util/Formattable.java
+++ b/libcore/luni/src/main/java/java/util/Formattable.java
@@ -20,16 +20,15 @@
  * Classes that handle custom formatting for the 's' specifier of {@code Formatter}
  * should implement the {@code Formattable} interface. It gives basic control over
  * formatting objects.
- *  
+ *
  * @see Formatter
- * @since Android 1.0
  */
 
 public interface Formattable {
 
     /**
      * Formats the object using the specified {@code Formatter}.
-     * 
+     *
      * @param formatter
      *            the {@code Formatter} to use.
      * @param flags
@@ -54,7 +53,6 @@
      *            is -1, then maximum length is not enforced.
      * @throws IllegalFormatException
      *             if any of the parameters is not supported.
-     * @since Android 1.0
      */
     void formatTo(Formatter formatter, int flags, int width, int precision)
             throws IllegalFormatException;
diff --git a/libcore/luni/src/main/java/java/util/FormattableFlags.java b/libcore/luni/src/main/java/java/util/FormattableFlags.java
index b5078e4..b8d44d4 100644
--- a/libcore/luni/src/main/java/java/util/FormattableFlags.java
+++ b/libcore/luni/src/main/java/java/util/FormattableFlags.java
@@ -22,7 +22,6 @@
  * flags must be done by the implementations.
  *  
  * @see Formattable
- * @since Android 1.0
  */
 public class FormattableFlags {
     
@@ -37,8 +36,6 @@
      * right-justified.
      * 
      * The flag corresponds to '-' ('\u002d') in the format specifier.
-     * 
-     * @since Android 1.0
      */
     public static final int LEFT_JUSTIFY = 1;
 
@@ -48,8 +45,6 @@
      * effect as {@code String.toUpperCase(java.util.Locale)}.
      * 
      * This flag corresponds to {@code '^' ('\u005e')} in the format specifier.
-     * 
-     * @since Android 1.0
      */
     public static final int UPPERCASE = 2;
 
@@ -58,8 +53,6 @@
      * of the alternate form is determined by the {@code Formattable}.
      * 
      * This flag corresponds to {@code '#' ('\u0023')} in the format specifier.
-     * 
-     * @since Android 1.0
      */
     public static final int ALTERNATE = 4;
 }
diff --git a/libcore/luni/src/main/java/java/util/Formatter.java b/libcore/luni/src/main/java/java/util/Formatter.java
index a6f14f0..d1dd417 100644
--- a/libcore/luni/src/main/java/java/util/Formatter.java
+++ b/libcore/luni/src/main/java/java/util/Formatter.java
@@ -28,6 +28,7 @@
 import java.io.UnsupportedEncodingException;
 import java.math.BigDecimal;
 import java.math.BigInteger;
+import java.math.MathContext;
 import java.nio.CharBuffer;
 import java.nio.charset.Charset;
 import java.security.AccessController;
@@ -37,63 +38,59 @@
 import java.text.DecimalFormatSymbols;
 import java.text.NumberFormat;
 
-// BEGIN android-note
-// Added quite extensive class documentation. Almost none was present before.
-// END android-note
-
 /**
  * <p>The {@code Formatter} class is a String-formatting utility that is designed
- * to work like the {@code printf} function of the C programming language. 
+ * to work like the {@code printf} function of the C programming language.
  * Its key methods are the {@code format} methods which create a formatted
- * {@code String} by replacing a set of placeholders (format tokens) with formatted 
+ * {@code String} by replacing a set of placeholders (format tokens) with formatted
  * values. The style used to format each value is determined by the format
  * token used.  For example, the call<br/>
  * {@code format("My decimal value is %d and my String is %s.", 3, "Hello");}<br/>
  * returns the {@code String}<br/>
- * {@code My decimal value is 3 and my String is Hello.}</p>
- * 
- *<p>The format token consists of a percent sign, optionally followed 
- * by flags and precision arguments, and then a single character that 
+ * {@code My decimal value is 3 and my String is Hello.}
+ *
+ * <p>The format token consists of a percent sign, optionally followed
+ * by flags and precision arguments, and then a single character that
  * indicates the type of value
  * being formatted.  If the type is a time/date, then the type character
- * {@code t} is followed by an additional character that indicates how the 
- * date is to be formatted. The two characters {@code <$} immediately 
+ * {@code t} is followed by an additional character that indicates how the
+ * date is to be formatted. The two characters {@code <$} immediately
  * following the % sign indicate that the previous value should be used again
  * instead of moving on to the next value argument. A number {@code n}
  * and a dollar sign immediately following the % sign make n the next argument
- * to be used.</p>  
- * 
- * <p>The available choices are the following:</p>
- * 
+ * to be used.
+ *
+ * <p>The available choices are the following:
+ *
  * <table BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
  * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
  * <TD COLSPAN=4>
  * <B>Text value types</B></TD>
  * </tr>
  * <tr>
- * <td width="5%">{@code s}</td> 
- * <td width="10%">String</td> 
- * <td width="30%">{@code format("%s, %s", "hello", "Hello");}</td> 
- * <td width="30%">{@code hello, Hello}</td> 
- * </tr>  
+ * <td width="5%">{@code s}</td>
+ * <td width="10%">String</td>
+ * <td width="30%">{@code format("%s, %s", "hello", "Hello");}</td>
+ * <td width="30%">{@code hello, Hello}</td>
+ * </tr>
  * <tr>
- * <td width="5%">{@code S}, {@code s}</td> 
- * <td width="10%">String to capitals</td> 
- * <td width="30%">{@code format("%S, %S", "hello", "Hello");}</td> 
- * <td width="30%">{@code HELLO, HELLO}</td> 
- * </tr>  
+ * <td width="5%">{@code S}, {@code s}</td>
+ * <td width="10%">String to capitals</td>
+ * <td width="30%">{@code format("%S, %S", "hello", "Hello");}</td>
+ * <td width="30%">{@code HELLO, HELLO}</td>
+ * </tr>
  * <tr>
- * <td width="5%">{@code c}</td> 
- * <td width="10%">Character</td> 
- * <td width="30%">{@code format("%c, %c", 'd', 0x65);}</td> 
+ * <td width="5%">{@code c}</td>
+ * <td width="10%">Character</td>
+ * <td width="30%">{@code format("%c, %c", 'd', 0x65);}</td>
  * <td width="30%">{@code d, e}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code C}</td> 
- * <td width="10%">Character to capitals</td> 
- * <td width="30%">{@code format("%C, %C", 'd', 0x65);}</td> 
+ * <td width="5%">{@code C}</td>
+ * <td width="10%">Character to capitals</td>
+ * <td width="30%">{@code format("%C, %C", 'd', 0x65);}</td>
  * <td width="30%">{@code D, E}</td>
- * </tr>  
+ * </tr>
  * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
  * <TD COLSPAN=4>
  * <B>Text option flags</B><br/>The value between the
@@ -101,33 +98,33 @@
  * characters of the formatted value  </TD>
  * </tr>
  * <tr>
- * <td width="5%">{@code -}</td> 
- * <td width="10%">Left justify (width value is required)</td> 
- * <td width="30%">{@code format("%-3C, %3C", 'd', 0x65);}</td> 
+ * <td width="5%">{@code -}</td>
+ * <td width="10%">Left justify (width value is required)</td>
+ * <td width="30%">{@code format("%-3C, %3C", 'd', 0x65);}</td>
  * <td width="30%">{@code D  ,   E}</td>
- * </tr>  
+ * </tr>
  * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
  * <TD COLSPAN=4>
  * <B>Integer types</B></TD>
  * </tr>
  * <tr>
- * <td width="5%">{@code d}</td> 
- * <td width="10%">int, formatted as decimal</td> 
- * <td width="30%">{@code format("%d, %d"1$, 35, 0x10);}</td> 
+ * <td width="5%">{@code d}</td>
+ * <td width="10%">int, formatted as decimal</td>
+ * <td width="30%">{@code format("%d, %d"1$, 35, 0x10);}</td>
  * <td width="30%">{@code 35, 16}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code o}</td> 
- * <td width="10%">int, formatted as octal</td> 
- * <td width="30%">{@code format("%o, %o", 8, 010);}</td> 
+ * <td width="5%">{@code o}</td>
+ * <td width="10%">int, formatted as octal</td>
+ * <td width="30%">{@code format("%o, %o", 8, 010);}</td>
  * <td width="30%">{@code 10, 10}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code X}, {@code x}</td> 
- * <td width="10%">int, formatted as hexidecimal</td> 
- * <td width="30%">{@code format("%x, %X", 10, 10);}</td> 
+ * <td width="5%">{@code X}, {@code x}</td>
+ * <td width="10%">int, formatted as hexidecimal</td>
+ * <td width="30%">{@code format("%x, %X", 10, 10);}</td>
  * <td width="30%">{@code a, A}</td>
- * </tr>  
+ * </tr>
  * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
  * <TD COLSPAN=4>
  * <B>Integer option flags</B><br/>The value between the
@@ -135,43 +132,43 @@
  * characters of the formatted value  </TD>
  * </tr>
  * <tr>
- * <td width="5%">{@code +}</td> 
- * <td width="10%">lead with the number's sign</td> 
- * <td width="30%">{@code format("%+d, %+4d", 5, 5);}</td> 
+ * <td width="5%">{@code +}</td>
+ * <td width="10%">lead with the number's sign</td>
+ * <td width="30%">{@code format("%+d, %+4d", 5, 5);}</td>
  * <td width="30%">{@code +5,   +5}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code -}</td> 
- * <td width="10%">Left justify (width value is required)</td> 
- * <td width="30%">{@code format("%-6dx", 5);}</td> 
+ * <td width="5%">{@code -}</td>
+ * <td width="10%">Left justify (width value is required)</td>
+ * <td width="30%">{@code format("%-6dx", 5);}</td>
  * <td width="30%">{@code 5      x}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code #}</td> 
- * <td width="10%">Print the leading characters that indicate 
- * hexidecimal or octal (for use only with hex and octal types) </td> 
- * <td width="30%">{@code format("%#o", 010);}</td> 
+ * <td width="5%">{@code #}</td>
+ * <td width="10%">Print the leading characters that indicate
+ * hexidecimal or octal (for use only with hex and octal types) </td>
+ * <td width="30%">{@code format("%#o", 010);}</td>
  * <td width="30%">{@code 010}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code  }</td> 
- * <td width="10%">A space indicates that non-negative numbers 
- * should have a leading space. </td> 
- * <td width="30%">{@code format("x% d% 5d", 4, 4);}</td> 
+ * <td width="5%">{@code  }</td>
+ * <td width="10%">A space indicates that non-negative numbers
+ * should have a leading space. </td>
+ * <td width="30%">{@code format("x% d% 5d", 4, 4);}</td>
  * <td width="30%">{@code x 4    4}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code 0}</td> 
- * <td width="10%">Pad the number with leading zeros (width value is required)</td> 
- * <td width="30%">{@code format("%07d, %03d", 4, 5555);}</td> 
+ * <td width="5%">{@code 0}</td>
+ * <td width="10%">Pad the number with leading zeros (width value is required)</td>
+ * <td width="30%">{@code format("%07d, %03d", 4, 5555);}</td>
  * <td width="30%">{@code 0000004, 5555}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code (}</td> 
- * <td width="10%">Put parentheses around negative numbers (decimal only)</td> 
- * <td width="30%">{@code format("%(d, %(d, %(6d", 12, -12, -12);}</td> 
+ * <td width="5%">{@code (}</td>
+ * <td width="10%">Put parentheses around negative numbers (decimal only)</td>
+ * <td width="30%">{@code format("%(d, %(d, %(6d", 12, -12, -12);}</td>
  * <td width="30%">{@code 12, (12),   (12)}</td>
- * </tr>  
+ * </tr>
  * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
  * <TD COLSPAN=4>
  * <B>Float types</B><br/>A value immediately following the % symbol
@@ -180,229 +177,223 @@
  * gives the precision (6 by default).</TD>
  * </tr>
  * <tr>
- * <td width="5%">{@code f}</td> 
- * <td width="10%">float (or double) formatted as a decimal, where 
- * the precision indicates the number of digits after the decimal.</td> 
- * <td width="30%">{@code format("%f %<.1f %<1.5f %<10f %<6.0f", 123.456f);}</td> 
+ * <td width="5%">{@code f}</td>
+ * <td width="10%">float (or double) formatted as a decimal, where
+ * the precision indicates the number of digits after the decimal.</td>
+ * <td width="30%">{@code format("%f %<.1f %<1.5f %<10f %<6.0f", 123.456f);}</td>
  * <td width="30%">{@code 123.456001 123.5 123.45600 123.456001    123}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code E}, {@code e}</td> 
+ * <td width="5%">{@code E}, {@code e}</td>
  * <td width="10%">float (or double) formatted in decimal exponential
- * notation, where the precision indicates the number of significant digits.</td> 
- * <td width="30%">{@code format("%E %<.1e %<1.5E %<10E %<6.0E", 123.456f);}</td> 
+ * notation, where the precision indicates the number of significant digits.</td>
+ * <td width="30%">{@code format("%E %<.1e %<1.5E %<10E %<6.0E", 123.456f);}</td>
  * <td width="30%">{@code 1.234560E+02 1.2e+02 1.23456E+02 1.234560E+02  1E+02}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code G}, {@code g}</td> 
+ * <td width="5%">{@code G}, {@code g}</td>
  * <td width="10%">float (or double) formatted in decimal exponential
- * notation , where the precision indicates the maximum number of significant digits.</td> 
- * <td width="30%">{@code format("%G %<.1g %<1.5G %<10G %<6.0G", 123.456f);}</td> 
+ * notation , where the precision indicates the maximum number of significant digits.</td>
+ * <td width="30%">{@code format("%G %<.1g %<1.5G %<10G %<6.0G", 123.456f);}</td>
  * <td width="30%">{@code 123.456 1e+02 123.46    123.456  1E+02}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code A}, {@code a}</td> 
+ * <td width="5%">{@code A}, {@code a}</td>
  * <td width="10%">float (or double) formatted as a hexidecimal in exponential
- * notation, where the precision indicates the number of significant digits.</td> 
- * <td width="30%">{@code format("%A %<.1a %<1.5A %<10A %<6.0A", 123.456f);}</td> 
+ * notation, where the precision indicates the number of significant digits.</td>
+ * <td width="30%">{@code format("%A %<.1a %<1.5A %<10A %<6.0A", 123.456f);}</td>
  * <td width="30%">{@code 0X1.EDD2F2P6 0x1.fp6 0X1.EDD2FP6 0X1.EDD2F2P6 0X1.FP6}</td>
- * </tr>  
+ * </tr>
  * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
  * <TD COLSPAN=4>
- * <B>Float-type option flags</B><br/>See the Integer-type options.  
+ * <B>Float-type option flags</B><br/>See the Integer-type options.
  * The options for float-types are the
  * same as for integer types with one addition: </TD>
  * </tr>
  * <tr>
- * <td width="5%">{@code ,}</td> 
+ * <td width="5%">{@code ,}</td>
  * <td width="10%">Use a comma in place of a decimal if the locale
- * requires it. </td> 
- * <td width="30%">{@code format(new Locale("fr"), "%,7.2f", 6.03f);}</td> 
+ * requires it. </td>
+ * <td width="30%">{@code format(new Locale("fr"), "%,7.2f", 6.03f);}</td>
  * <td width="30%">{@code    6,03}</td>
- * </tr>  
+ * </tr>
  * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
  * <TD COLSPAN=4>
  * <B>Date types</B></TD>
  * </tr>
  * <tr>
- * <td width="5%">{@code t}, {@code T}</td> 
- * <td width="10%">Date</td> 
- * <td width="30%">{@code format(new Locale("fr"), "%tB %TB", Calendar.getInstance(), Calendar.getInstance());}</td> 
+ * <td width="5%">{@code t}, {@code T}</td>
+ * <td width="10%">Date</td>
+ * <td width="30%">{@code format(new Locale("fr"), "%tB %TB", Calendar.getInstance(), Calendar.getInstance());}</td>
  * <td width="30%">{@code avril AVRIL}</td>
- * </tr>  
+ * </tr>
  * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
  * <TD COLSPAN=4>
- * <B>Date format precisions</B><br/>The format precision character 
+ * <B>Date format precisions</B><br/>The format precision character
  * follows the {@code t}. </TD>
  * </tr>
  * <tr>
- * <td width="5%">{@code A}, {@code a}</td> 
- * <td width="10%">The day of the week</td> 
- * <td width="30%">{@code format("%ta %tA", cal, cal);}</td> 
+ * <td width="5%">{@code A}, {@code a}</td>
+ * <td width="10%">The day of the week</td>
+ * <td width="30%">{@code format("%ta %tA", cal, cal);}</td>
  * <td width="30%">{@code Tue Tuesday}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code b}, {@code B}, {@code h}</td> 
- * <td width="10%">The name of the month</td> 
- * <td width="30%">{@code format("%tb %<tB %<th", cal, cal, cal);}</td> 
+ * <td width="5%">{@code b}, {@code B}, {@code h}</td>
+ * <td width="10%">The name of the month</td>
+ * <td width="30%">{@code format("%tb %<tB %<th", cal, cal, cal);}</td>
  * <td width="30%">{@code Apr April Apr}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code C}</td> 
- * <td width="10%">The century</td> 
- * <td width="30%">{@code format("%tC\n", cal);}</td> 
+ * <td width="5%">{@code C}</td>
+ * <td width="10%">The century</td>
+ * <td width="30%">{@code format("%tC\n", cal);}</td>
  * <td width="30%">{@code 20}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code d}, {@code e}</td> 
- * <td width="10%">The day of the month (with or without leading zeros)</td> 
- * <td width="30%">{@code format("%td %te", cal, cal);}</td> 
+ * <td width="5%">{@code d}, {@code e}</td>
+ * <td width="10%">The day of the month (with or without leading zeros)</td>
+ * <td width="30%">{@code format("%td %te", cal, cal);}</td>
  * <td width="30%">{@code 01 1}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code F}</td> 
- * <td width="10%">The complete date formatted as YYYY-MM-DD</td> 
- * <td width="30%">{@code format("%tF", cal);}</td> 
+ * <td width="5%">{@code F}</td>
+ * <td width="10%">The complete date formatted as YYYY-MM-DD</td>
+ * <td width="30%">{@code format("%tF", cal);}</td>
  * <td width="30%">{@code 2008-04-01}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code D}</td> 
- * <td width="10%">The complete date formatted as MM/DD/YY 
- * (not corrected for locale) </td> 
- * <td width="30%">{@code format(new Locale("en_US"), "%tD", cal);<br/>format(new Locale("en_UK"), " %tD", cal);}</td> 
+ * <td width="5%">{@code D}</td>
+ * <td width="10%">The complete date formatted as MM/DD/YY
+ * (not corrected for locale) </td>
+ * <td width="30%">{@code format(new Locale("en_US"), "%tD", cal);<br/>format(new Locale("en_UK"), " %tD", cal);}</td>
  * <td width="30%">{@code 04/01/08 04/01/08}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code j}</td> 
- * <td width="10%">The number of the day (from the beginning of the year).</td> 
- * <td width="30%">{@code format("%tj\n", cal);}</td> 
+ * <td width="5%">{@code j}</td>
+ * <td width="10%">The number of the day (from the beginning of the year).</td>
+ * <td width="30%">{@code format("%tj\n", cal);}</td>
  * <td width="30%">{@code 092}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code m}</td> 
- * <td width="10%">The number of the month</td> 
- * <td width="30%">{@code format("%tm\n", cal);}</td> 
+ * <td width="5%">{@code m}</td>
+ * <td width="10%">The number of the month</td>
+ * <td width="30%">{@code format("%tm\n", cal);}</td>
  * <td width="30%">{@code 04}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code y}, {@code Y}</td> 
- * <td width="10%">The year</td> 
- * <td width="30%">{@code format("%ty %tY", cal, cal);}</td> 
+ * <td width="5%">{@code y}, {@code Y}</td>
+ * <td width="10%">The year</td>
+ * <td width="30%">{@code format("%ty %tY", cal, cal);}</td>
  * <td width="30%">{@code 08 2008}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code H}, {@code I}, {@code k}, {@code l}</td> 
+ * <td width="5%">{@code H}, {@code I}, {@code k}, {@code l}</td>
  * <td width="10%">The hour of the day, in 12 or 24 hour format, with or
- * without a leading zero</td> 
- * <td width="30%">{@code format("%tH %tI %tk %tl", cal, cal, cal, cal);}</td> 
+ * without a leading zero</td>
+ * <td width="30%">{@code format("%tH %tI %tk %tl", cal, cal, cal, cal);}</td>
  * <td width="30%">{@code 16 04 16 4}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code p}</td> 
- * <td width="10%">a.m. or p.m.</td> 
- * <td width="30%">{@code format("%tp %Tp", cal, cal);}</td> 
+ * <td width="5%">{@code p}</td>
+ * <td width="10%">a.m. or p.m.</td>
+ * <td width="30%">{@code format("%tp %Tp", cal, cal);}</td>
  * <td width="30%">{@code pm PM}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code M}, {@code S}, {@code L}, {@code N}</td> 
- * <td width="10%">The minutes, seconds, milliseconds, and nanoseconds</td> 
- * <td width="30%">{@code format("%tM %tS %tL %tN", cal, cal, cal, cal);}</td> 
+ * <td width="5%">{@code M}, {@code S}, {@code L}, {@code N}</td>
+ * <td width="10%">The minutes, seconds, milliseconds, and nanoseconds</td>
+ * <td width="30%">{@code format("%tM %tS %tL %tN", cal, cal, cal, cal);}</td>
  * <td width="30%">{@code 08 17 359 359000000}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code Z}, {@code z}</td> 
- * <td width="10%">The time zone: its abbreviation or offset from GMT</td> 
- * <td width="30%">{@code format("%tZ %tz", cal, cal);}</td> 
+ * <td width="5%">{@code Z}, {@code z}</td>
+ * <td width="10%">The time zone: its abbreviation or offset from GMT</td>
+ * <td width="30%">{@code format("%tZ %tz", cal, cal);}</td>
  * <td width="30%">{@code CEST +0100}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code R}, {@code r}, {@code T}</td> 
- * <td width="10%">The complete time</td> 
- * <td width="30%">{@code format("%tR %tr %tT", cal, cal, cal);}</td> 
+ * <td width="5%">{@code R}, {@code r}, {@code T}</td>
+ * <td width="10%">The complete time</td>
+ * <td width="30%">{@code format("%tR %tr %tT", cal, cal, cal);}</td>
  * <td width="30%">{@code 16:15 04:15:32 PM 16:15:32}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code s}, {@code Q}</td> 
+ * <td width="5%">{@code s}, {@code Q}</td>
  * <td width="10%">The number of seconds or milliseconds from "the epoch"
- * (1 January 1970 00:00:00 UTC) </td> 
- * <td width="30%">{@code format("%ts %tQ", cal, cal);}</td> 
+ * (1 January 1970 00:00:00 UTC) </td>
+ * <td width="30%">{@code format("%ts %tQ", cal, cal);}</td>
  * <td width="30%">{@code 1207059412 1207059412656}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code c}</td> 
- * <td width="10%">The complete time and date</td> 
- * <td width="30%">{@code format("%tc", cal);}</td> 
+ * <td width="5%">{@code c}</td>
+ * <td width="10%">The complete time and date</td>
+ * <td width="30%">{@code format("%tc", cal);}</td>
  * <td width="30%">{@code Tue Apr 01 16:19:17 CEST 2008}</td>
- * </tr>  
+ * </tr>
  * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
  * <TD COLSPAN=4>
  * <B>Other data types</B></TD>
  * </tr>
  * <tr>
- * <td width="5%">{@code B}, {@code b}</td> 
- * <td width="10%">Boolean</td> 
- * <td width="30%">{@code format("%b, %B", true, false);}</td> 
+ * <td width="5%">{@code B}, {@code b}</td>
+ * <td width="10%">Boolean</td>
+ * <td width="30%">{@code format("%b, %B", true, false);}</td>
  * <td width="30%">{@code true, FALSE}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code H}, {@code h}</td> 
- * <td width="10%">Hashcode</td> 
- * <td width="30%">{@code format("%h, %H", obj, obj);}</td> 
+ * <td width="5%">{@code H}, {@code h}</td>
+ * <td width="10%">Hashcode</td>
+ * <td width="30%">{@code format("%h, %H", obj, obj);}</td>
  * <td width="30%">{@code 190d11, 190D11}</td>
- * </tr>  
+ * </tr>
  * <tr>
- * <td width="5%">{@code n}</td> 
- * <td width="10%">line separator</td> 
- * <td width="30%">{@code format("first%nsecond", "???");}</td> 
+ * <td width="5%">{@code n}</td>
+ * <td width="10%">line separator</td>
+ * <td width="30%">{@code format("first%nsecond", "???");}</td>
  * <td width="30%">{@code first<br/>second}</td>
- * </tr>  
+ * </tr>
  * <tr BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
  * <TD COLSPAN=4>
  * <B>Escape sequences</B></TD>
  * </tr>
  * <tr>
- * <td width="5%">{@code %}</td> 
- * <td width="10%">Escape the % character</td> 
- * <td width="30%">{@code format("%d%%, %d", 50, 60);}</td> 
+ * <td width="5%">{@code %}</td>
+ * <td width="10%">Escape the % character</td>
+ * <td width="30%">{@code format("%d%%, %d", 50, 60);}</td>
  * <td width="30%">{@code 50%, 60}</td>
- * </tr>  
- * </table>   
- * 
+ * </tr>
+ * </table>
+ *
  * <p>An instance of Formatter can be created to write the formatted
- * output to standard types of output streams.  Its functionality can 
- * also be accessed through the format methods of an output stream 
+ * output to standard types of output streams.  Its functionality can
+ * also be accessed through the format methods of an output stream
  * or of {@code String}:<br/>
  * {@code System.out.println(String.format("%ty\n", cal));}<br/>
- * {@code System.out.format("%ty\n", cal);}</p>
- * 
- * <p>The class is not multi-threaded safe. The user is responsible for 
+ * {@code System.out.format("%ty\n", cal);}
+ *
+ * <p>The class is not multi-threaded safe. The user is responsible for
  * maintaining a thread-safe design if a {@code Formatter} is
- * accessed by multiple threads. </p>
- * 
- * @since Android 1.0
+ * accessed by multiple threads.
+ *
+ * @since 1.5
  */
 public final class Formatter implements Closeable, Flushable {
 
-    // BEGIN android-changed
     /**
      * The enumeration giving the available styles for formatting very large
      * decimal numbers.
-     * 
-     * @since Android 1.0
-     */    
+     */
     public enum BigDecimalLayoutForm {
         /**
          * Use scientific style for BigDecimals.
-         * @since Android 1.0
          */
-        SCIENTIFIC, 
+        SCIENTIFIC,
         /**
          * Use normal decimal/float style for BigDecimals.
-         * @since Android 1.0
          */
         DECIMAL_FLOAT
     }
-    // END android-changed
 
     private Appendable out;
 
@@ -414,29 +405,26 @@
 
     /**
      * Constructs a {@code Formatter}.
-     * 
+     *
      * The output is written to a {@code StringBuilder} which can be acquired by invoking
      * {@link #out()} and whose content can be obtained by calling
      * {@code toString()}.
-     * 
+     *
      * The {@code Locale} for the {@code Formatter} is the default {@code Locale}.
-     * 
-     * @since Android 1.0
      */
     public Formatter() {
         this(new StringBuilder(), Locale.getDefault());
     }
 
     /**
-     * Constructs a {@code Formatter} whose output will be written to the 
+     * Constructs a {@code Formatter} whose output will be written to the
      * specified {@code Appendable}.
-     * 
+     *
      * The locale for the {@code Formatter} is the default {@code Locale}.
-     * 
+     *
      * @param a
      *            the output destination of the {@code Formatter}. If {@code a} is {@code null},
      *            then a {@code StringBuilder} will be used.
-     * @since Android 1.0
      */
     public Formatter(Appendable a) {
         this(a, Locale.getDefault());
@@ -444,32 +432,30 @@
 
     /**
      * Constructs a {@code Formatter} with the specified {@code Locale}.
-     * 
+     *
      * The output is written to a {@code StringBuilder} which can be acquired by invoking
      * {@link #out()} and whose content can be obtained by calling
      * {@code toString()}.
-     * 
+     *
      * @param l
      *            the {@code Locale} of the {@code Formatter}. If {@code l} is {@code null},
      *            then no localization will be used.
-     * @since Android 1.0
      */
     public Formatter(Locale l) {
         this(new StringBuilder(), l);
     }
 
     /**
-     * Constructs a {@code Formatter} with the specified {@code Locale} 
-     * and whose output will be written to the 
+     * Constructs a {@code Formatter} with the specified {@code Locale}
+     * and whose output will be written to the
      * specified {@code Appendable}.
-     * 
+     *
      * @param a
      *            the output destination of the {@code Formatter}. If {@code a} is {@code null},
      *            then a {@code StringBuilder} will be used.
      * @param l
      *            the {@code Locale} of the {@code Formatter}. If {@code l} is {@code null},
      *            then no localization will be used.
-     * @since Android 1.0
      */
     public Formatter(Appendable a, Locale l) {
         if (null == a) {
@@ -482,17 +468,16 @@
 
     /**
      * Constructs a {@code Formatter} whose output is written to the specified file.
-     * 
+     *
      * The charset of the {@code Formatter} is the default charset.
-     * 
+     *
      * The {@code Locale} for the {@code Formatter} is the default {@code Locale}.
-     * 
+     *
      * @param fileName
      *            the filename of the file that is used as the output
      *            destination for the {@code Formatter}. The file will be truncated to
      *            zero size if the file exists, or else a new file will be
      *            created. The output of the {@code Formatter} is buffered.
-     * 
      * @throws FileNotFoundException
      *             if the filename does not denote a normal and writable file,
      *             or if a new file cannot be created, or if any error arises when
@@ -500,7 +485,6 @@
      * @throws SecurityException
      *             if there is a {@code SecurityManager} in place which denies permission
      *             to write to the file in {@code checkWrite(file.getPath())}.
-     * @since Android 1.0
      */
     public Formatter(String fileName) throws FileNotFoundException {
         this(new File(fileName));
@@ -509,9 +493,9 @@
 
     /**
      * Constructs a {@code Formatter} whose output is written to the specified file.
-     * 
+     *
      * The {@code Locale} for the {@code Formatter} is the default {@code Locale}.
-     * 
+     *
      * @param fileName
      *            the filename of the file that is used as the output
      *            destination for the {@code Formatter}. The file will be truncated to
@@ -519,7 +503,6 @@
      *            created. The output of the {@code Formatter} is buffered.
      * @param csn
      *            the name of the charset for the {@code Formatter}.
-     * 
      * @throws FileNotFoundException
      *             if the filename does not denote a normal and writable file,
      *             or if a new file cannot be created, or if any error arises when
@@ -529,7 +512,6 @@
      *             to write to the file in {@code checkWrite(file.getPath())}.
      * @throws UnsupportedEncodingException
      *             if the charset with the specified name is not supported.
-     * @since Android 1.0
      */
     public Formatter(String fileName, String csn) throws FileNotFoundException,
             UnsupportedEncodingException {
@@ -537,9 +519,9 @@
     }
 
     /**
-     * Constructs a {@code Formatter} with the given {@code Locale} and charset, 
+     * Constructs a {@code Formatter} with the given {@code Locale} and charset,
      * and whose output is written to the specified file.
-     * 
+     *
      * @param fileName
      *            the filename of the file that is used as the output
      *            destination for the {@code Formatter}. The file will be truncated to
@@ -550,7 +532,6 @@
      * @param l
      *            the {@code Locale} of the {@code Formatter}. If {@code l} is {@code null},
      *            then no localization will be used.
-     * 
      * @throws FileNotFoundException
      *             if the filename does not denote a normal and writable file,
      *             or if a new file cannot be created, or if any error arises when
@@ -560,7 +541,6 @@
      *             to write to the file in {@code checkWrite(file.getPath())}.
      * @throws UnsupportedEncodingException
      *             if the charset with the specified name is not supported.
-     * @since Android 1.0
      */
     public Formatter(String fileName, String csn, Locale l)
             throws FileNotFoundException, UnsupportedEncodingException {
@@ -570,17 +550,16 @@
 
     /**
      * Constructs a {@code Formatter} whose output is written to the specified {@code File}.
-     * 
+     *
      * The charset of the {@code Formatter} is the default charset.
-     * 
+     *
      * The {@code Locale} for the {@code Formatter} is the default {@code Locale}.
-     * 
+     *
      * @param file
      *            the {@code File} that is used as the output destination for the
      *            {@code Formatter}. The {@code File} will be truncated to zero size if the {@code File}
      *            exists, or else a new {@code File} will be created. The output of the
      *            {@code Formatter} is buffered.
-     * 
      * @throws FileNotFoundException
      *             if the {@code File} is not a normal and writable {@code File}, or if a
      *             new {@code File} cannot be created, or if any error rises when opening or
@@ -588,18 +567,17 @@
      * @throws SecurityException
      *             if there is a {@code SecurityManager} in place which denies permission
      *             to write to the {@code File} in {@code checkWrite(file.getPath())}.
-     * @since Android 1.0
      */
     public Formatter(File file) throws FileNotFoundException {
         this(new FileOutputStream(file));
     }
 
     /**
-     * Constructs a {@code Formatter} with the given charset, 
+     * Constructs a {@code Formatter} with the given charset,
      * and whose output is written to the specified {@code File}.
-     * 
+     *
      * The {@code Locale} for the {@code Formatter} is the default {@code Locale}.
-     * 
+     *
      * @param file
      *            the {@code File} that is used as the output destination for the
      *            {@code Formatter}. The {@code File} will be truncated to zero size if the {@code File}
@@ -616,7 +594,6 @@
      *             to write to the {@code File} in {@code checkWrite(file.getPath())}.
      * @throws UnsupportedEncodingException
      *             if the charset with the specified name is not supported.
-     * @since Android 1.0
      */
     public Formatter(File file, String csn) throws FileNotFoundException,
             UnsupportedEncodingException {
@@ -624,9 +601,9 @@
     }
 
     /**
-     * Constructs a {@code Formatter} with the given {@code Locale} and charset, 
+     * Constructs a {@code Formatter} with the given {@code Locale} and charset,
      * and whose output is written to the specified {@code File}.
-     * 
+     *
      * @param file
      *            the {@code File} that is used as the output destination for the
      *            {@code Formatter}. The {@code File} will be truncated to zero size if the {@code File}
@@ -646,7 +623,6 @@
      *             to write to the {@code File} in {@code checkWrite(file.getPath())}.
      * @throws UnsupportedEncodingException
      *             if the charset with the specified name is not supported.
-     * @since Android 1.0
      */
     public Formatter(File file, String csn, Locale l)
             throws FileNotFoundException, UnsupportedEncodingException {
@@ -654,9 +630,9 @@
         try {
             fout = new FileOutputStream(file);
             OutputStreamWriter writer = new OutputStreamWriter(fout, csn);
-            // BEGIN android-modified
+            // BEGIN android-changed
             out = new BufferedWriter(writer, 8192);
-            // END android-modified
+            // END android-changed
         } catch (RuntimeException e) {
             closeOutputStream(fout);
             throw e;
@@ -670,37 +646,35 @@
 
     /**
      * Constructs a {@code Formatter} whose output is written to the specified {@code OutputStream}.
-     * 
+     *
      * The charset of the {@code Formatter} is the default charset.
-     * 
+     *
      * The {@code Locale} for the {@code Formatter} is the default {@code Locale}.
-     * 
+     *
      * @param os
      *            the stream to be used as the destination of the {@code Formatter}.
-     * @since Android 1.0
      */
     public Formatter(OutputStream os) {
         OutputStreamWriter writer = new OutputStreamWriter(os, Charset
                 .defaultCharset());
-        // BEGIN android-modified
+        // BEGIN android-changed
         out = new BufferedWriter(writer, 8192);
-        // END android-modified
+        // END android-changed
         locale = Locale.getDefault();
     }
 
     /**
-     * Constructs a {@code Formatter} with the given charset, 
+     * Constructs a {@code Formatter} with the given charset,
      * and whose output is written to the specified {@code OutputStream}.
-     * 
+     *
      * The {@code Locale} for the {@code Formatter} is the default {@code Locale}.
-     * 
+     *
      * @param os
      *            the stream to be used as the destination of the {@code Formatter}.
      * @param csn
      *            the name of the charset for the {@code Formatter}.
      * @throws UnsupportedEncodingException
      *             if the charset with the specified name is not supported.
-     * @since Android 1.0
      */
     public Formatter(OutputStream os, String csn)
             throws UnsupportedEncodingException {
@@ -709,9 +683,9 @@
     }
 
     /**
-     * Constructs a {@code Formatter} with the given {@code Locale} and charset, 
+     * Constructs a {@code Formatter} with the given {@code Locale} and charset,
      * and whose output is written to the specified {@code OutputStream}.
-     * 
+     *
      * @param os
      *            the stream to be used as the destination of the {@code Formatter}.
      * @param csn
@@ -721,31 +695,29 @@
      *            then no localization will be used.
      * @throws UnsupportedEncodingException
      *             if the charset with the specified name is not supported.
-     * @since Android 1.0
      */
     public Formatter(OutputStream os, String csn, Locale l)
             throws UnsupportedEncodingException {
 
         OutputStreamWriter writer = new OutputStreamWriter(os, csn);
-        // BEGIN android-modified
+        // BEGIN android-changed
         out = new BufferedWriter(writer, 8192);
-        // END android-modified
+        // END android-changed
 
         locale = l;
     }
 
     /**
      * Constructs a {@code Formatter} whose output is written to the specified {@code PrintStream}.
-     * 
+     *
      * The charset of the {@code Formatter} is the default charset.
-     * 
+     *
      * The {@code Locale} for the {@code Formatter} is the default {@code Locale}.
-     * 
+     *
      * @param ps
      *            the {@code PrintStream} used as destination of the {@code Formatter}. If
-     *            {@code ps} is {@code null}, then a {@ code NullPointerExcepiton} will
+     *            {@code ps} is {@code null}, then a {@code NullPointerException} will
      *            be raised.
-     * @since Android 1.0
      */
     public Formatter(PrintStream ps) {
         if (null == ps) {
@@ -763,11 +735,10 @@
 
     /**
      * Returns the {@code Locale} of the {@code Formatter}.
-     * 
+     *
      * @return the {@code Locale} for the {@code Formatter} or {@code null} for no {@code Locale}.
      * @throws FormatterClosedException
      *             if the {@code Formatter} has been closed.
-     * @since Android 1.0
      */
     public Locale locale() {
         checkClosed();
@@ -776,11 +747,10 @@
 
     /**
      * Returns the output destination of the {@code Formatter}.
-     * 
+     *
      * @return the output destination of the {@code Formatter}.
      * @throws FormatterClosedException
      *             if the {@code Formatter} has been closed.
-     * @since Android 1.0
      */
     public Appendable out() {
         checkClosed();
@@ -790,12 +760,11 @@
     /**
      * Returns the content by calling the {@code toString()} method of the output
      * destination.
-     * 
+     *
      * @return the content by calling the {@code toString()} method of the output
      *         destination.
      * @throws FormatterClosedException
      *             if the {@code Formatter} has been closed.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -805,11 +774,10 @@
 
     /**
      * Flushes the {@code Formatter}. If the output destination is {@link Flushable},
-     * then the method {@ code flush()} will be called on that destination.
-     * 
+     * then the method {@code flush()} will be called on that destination.
+     *
      * @throws FormatterClosedException
      *             if the {@code Formatter} has been closed.
-     * @since Android 1.0
      */
     public void flush() {
         checkClosed();
@@ -825,14 +793,12 @@
     /**
      * Closes the {@code Formatter}. If the output destination is {@link Closeable},
      * then the method {@code close()} will be called on that destination.
-     * 
+     *
      * If the {@code Formatter} has been closed, then calling the this method will have no
      * effect.
-     * 
+     *
      * Any method but the {@link #ioException()} that is called after the
      * {@code Formatter} has been closed will raise a {@code FormatterClosedException}.
-     * 
-     * @since Android 1.0
      */
     public void close() {
         closed = true;
@@ -850,10 +816,9 @@
      * Returns the last {@code IOException} thrown by the {@code Formatter}'s output
      * destination. If the {@code append()} method of the destination does not throw
      * {@code IOException}s, the {@code ioException()} method will always return {@code null}.
-     * 
+     *
      * @return the last {@code IOException} thrown by the {@code Formatter}'s output
      *         destination.
-     * @since Android 1.0
      */
     public IOException ioException() {
         return lastIOException;
@@ -861,7 +826,7 @@
 
     /**
      * Writes a formatted string to the output destination of the {@code Formatter}.
-     * 
+     *
      * @param format
      *            a format string.
      * @param args
@@ -875,23 +840,22 @@
      *             the format string, or any other illegal situation.
      * @throws FormatterClosedException
      *             if the {@code Formatter} has been closed.
-     * @since Android 1.0
      */
     public Formatter format(String format, Object... args) {
         return format(locale, format, args);
     }
 
-// BEGIN android-changed
+    // BEGIN android-added
     /**
      * Cached transformer. Improves performance when format() is called multiple
      * times.
      */
     private Transformer transformer;
-// END android-changed
+    // END android-added
 
     /**
      * Writes a formatted string to the output destination of the {@code Formatter}.
-     * 
+     *
      * @param l
      *            the {@code Locale} used in the method. If {@code locale} is
      *            {@code null}, then no localization will be applied. This
@@ -910,7 +874,6 @@
      *             the format string, or any other illegal situation.
      * @throws FormatterClosedException
      *             if the {@code Formatter} has been closed.
-     * @since Android 1.0
      */
     public Formatter format(Locale l, String format, Object... args) {
         checkClosed();
@@ -1275,7 +1238,7 @@
                     break;
                 }
                 case 'n': {
-                    result = transfromFromLineSeparator();
+                    result = transformFromLineSeparator();
                     break;
                 }
                 case 't':
@@ -1499,7 +1462,7 @@
          * Transforms line separator to a formatted string. Any flag, the width
          * or the precision is illegal.
          */
-        private String transfromFromLineSeparator() {
+        private String transformFromLineSeparator() {
             if (formatToken.isPrecisionSet()) {
                 throw new IllegalFormatPrecisionException(formatToken
                         .getPrecision());
@@ -2121,9 +2084,18 @@
             boolean requireScientificRepresentation = true;
             double d = ((Number) argument).doubleValue();
             d = Math.abs(d);
-            long l = Math.round(d);
+            if (Double.isInfinite(d)) {
+                precision = formatToken.getPrecision();
+                precision--;
+                formatToken.setPrecision(precision);
+                transform_e();
+                return;
+            }
+            BigDecimal b = new BigDecimal(d, new MathContext(precision));
+            d = b.doubleValue();
+            long l = b.longValue();
 
-            if (l >= 1) {
+            if (d >= 1 && d < Math.pow(10, precision)) {
                 if (l < Math.pow(10, precision)) {
                     requireScientificRepresentation = false;
                     precision -= String.valueOf(l).length();
@@ -2137,19 +2109,20 @@
                 }
 
             } else {
-                l = Math.round(d * Math.pow(10, 4));
-                if (l >= 1) {
+                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 = Math.round(d * Math.pow(10, precision + 1));
+                    l = b.movePointRight(precision + 1).longValue();
+                    b.movePointLeft(precision + 1);
                     if (String.valueOf(l).length() <= formatToken
                             .getPrecision()) {
                         precision++;
                     }
-                    l = Math.round(d * Math.pow(10, precision));
-                    if (l < Math.pow(10, precision - 4)) {
-                        requireScientificRepresentation = true;
-                    } else {
+                    l = b.movePointRight(precision).longValue();
+                    b.movePointLeft(precision);
+                    if (l >= Math.pow(10, precision - 4)) {
                         formatToken.setPrecision(precision);
                     }
                 }
@@ -2461,9 +2434,10 @@
 
         private void transform_Z() {
             TimeZone timeZone = calendar.getTimeZone();
-            result
-                    .append(timeZone.getDisplayName(true, TimeZone.SHORT,
-                            locale));
+            result.append(timeZone
+                    .getDisplayName(
+                            timeZone.inDaylightTime(calendar.getTime()),
+                            TimeZone.SHORT, locale));
         }
 
         private void transform_z() {
diff --git a/libcore/luni/src/main/java/java/util/FormatterClosedException.java b/libcore/luni/src/main/java/java/util/FormatterClosedException.java
index 63d1052..e7e57ba 100644
--- a/libcore/luni/src/main/java/java/util/FormatterClosedException.java
+++ b/libcore/luni/src/main/java/java/util/FormatterClosedException.java
@@ -23,7 +23,6 @@
  * closed.
  * 
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class FormatterClosedException extends IllegalStateException implements
         Serializable {
diff --git a/libcore/luni/src/main/java/java/util/GregorianCalendar.java b/libcore/luni/src/main/java/java/util/GregorianCalendar.java
index 32368ec..d8cd556 100644
--- a/libcore/luni/src/main/java/java/util/GregorianCalendar.java
+++ b/libcore/luni/src/main/java/java/util/GregorianCalendar.java
@@ -14,12 +14,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-/**
-*******************************************************************************
-* Copyright (C) 1996-2008, International Business Machines Corporation and    *
-* others. All Rights Reserved.                                                *
-*******************************************************************************
-*/
 
 package java.util;
 
@@ -27,24 +21,19 @@
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 
-// BEGIN android-note
-// The class javadoc and some of the method descriptions are copied from ICU4J
-// source files. Changes have been made to the copied descriptions.
-// The icu license header was added to this file. 
-// END android-note
 /**
  * {@code GregorianCalendar} is a concrete subclass of {@link Calendar}
  * and provides the standard calendar used by most of the world.
- * 
+ *
  * <p>
  * The standard (Gregorian) calendar has 2 eras, BC and AD.
- * 
+ *
  * <p>
  * This implementation handles a single discontinuity, which corresponds by
  * default to the date the Gregorian calendar was instituted (October 15, 1582
  * in some countries, later in others). The cutover date may be changed by the
  * caller by calling {@code setGregorianChange()}.
- * 
+ *
  * <p>
  * Historically, in those countries which adopted the Gregorian calendar first,
  * October 4, 1582 was thus followed by October 15, 1582. This calendar models
@@ -53,7 +42,7 @@
  * the Julian calendar is the leap year rule. The Julian calendar specifies leap
  * years every four years, whereas the Gregorian calendar omits century years
  * which are not divisible by 400.
- * 
+ *
  * <p>
  * {@code GregorianCalendar} implements <em>proleptic</em> Gregorian
  * and Julian calendars. That is, dates are computed by extrapolating the
@@ -64,13 +53,13 @@
  * 4 AD onward, when modern Julian calendar rules were adopted. Before this
  * date, leap year rules were applied irregularly, and before 45 BC the Julian
  * calendar did not even exist.
- * 
+ *
  * <p>
  * Prior to the institution of the Gregorian calendar, New Year's Day was March
  * 25. To avoid confusion, this calendar always uses January 1. A manual
  * adjustment may be made if desired for dates that are prior to the Gregorian
  * changeover and which fall between January 1 and March 24.
- * 
+ *
  * <p>
  * Values calculated for the {@code WEEK_OF_YEAR} field range from 1 to
  * 53. Week 1 for a year is the earliest seven day period starting on
@@ -80,7 +69,7 @@
  * {@code getFirstDayOfWeek()}, and the day of the week of January 1.
  * Weeks between week 1 of one year and week 1 of the following year are
  * numbered sequentially from 2 to 52 or 53 (as needed).
- * 
+ *
  * <p>
  * For example, January 1, 1998 was a Thursday. If
  * {@code getFirstDayOfWeek()} is {@code MONDAY} and
@@ -90,7 +79,7 @@
  * {@code getFirstDayOfWeek()} is {@code SUNDAY}, then week 1 of
  * 1998 starts on January 4, 1998, and ends on January 10, 1998; the first three
  * days of 1998 then are part of week 53 of 1997.
- * 
+ *
  * <p>
  * Values calculated for the {@code WEEK_OF_MONTH} field range from 0 or
  * 1 to 4 or 5. Week 1 of a month (the days with <code>WEEK_OF_MONTH =
@@ -102,7 +91,7 @@
  * {@code getFirstDayOfWeek()}, and will not include days of the
  * previous month. Days of a month before week 1 have a
  * {@code WEEK_OF_MONTH} of 0.
- * 
+ *
  * <p>
  * For example, if {@code getFirstDayOfWeek()} is {@code SUNDAY}
  * and {@code getMinimalDaysInFirstWeek()} is 4, then the first week of
@@ -111,10 +100,10 @@
  * Saturday, January 3 have a {@code WEEK_OF_MONTH} of 0. If
  * {@code getMinimalDaysInFirstWeek()} is changed to 3, then January 1
  * through January 3 have a {@code WEEK_OF_MONTH} of 1.
- * 
+ *
  * <p>
  * <strong>Example:</strong> <blockquote>
- * 
+ *
  * <pre>
  * // get the supported ids for GMT-08:00 (Pacific Standard Time)
  * String[] ids = TimeZone.getAvailableIDs(-8 * 60 * 60 * 1000);
@@ -186,13 +175,11 @@
  * System.out.println("DST_OFFSET: "
  *        + (calendar.get(Calendar.DST_OFFSET)/(60*60*1000))); // in hours
  * </pre>
- * 
+ *
  * </blockquote>
- * 
+ *
  * @see Calendar
  * @see TimeZone
- * 
- * @since Android 1.0
  */
 public class GregorianCalendar extends Calendar {
 
@@ -200,18 +187,14 @@
 
     /**
      * Value for the BC era.
-     * 
-     * @since Android 1.0
      */
     public static final int BC = 0;
 
     /**
      * Value for the AD era.
-     * 
-     * @since Android 1.0
      */
     public static final int AD = 1;
-    
+
     private static final long defaultGregorianCutover = -12219292800000l;
 
     private long gregorianCutover = defaultGregorianCutover;
@@ -251,8 +234,6 @@
     /**
      * Constructs a new {@code GregorianCalendar} initialized to the current date and
      * time with the default {@code Locale} and {@code TimeZone}.
-     * 
-     * @since Android 1.0
      */
     public GregorianCalendar() {
         this(TimeZone.getDefault(), Locale.getDefault());
@@ -261,14 +242,13 @@
     /**
      * Constructs a new {@code GregorianCalendar} initialized to midnight in the default
      * {@code TimeZone} and {@code Locale} on the specified date.
-     * 
+     *
      * @param year
      *            the year.
      * @param month
      *            the month.
      * @param day
      *            the day of the month.
-     * @since Android 1.0
      */
     public GregorianCalendar(int year, int month, int day) {
         super(TimeZone.getDefault(), Locale.getDefault());
@@ -278,7 +258,7 @@
     /**
      * Constructs a new {@code GregorianCalendar} initialized to the specified date and
      * time in the default {@code TimeZone} and {@code Locale}.
-     * 
+     *
      * @param year
      *            the year.
      * @param month
@@ -289,7 +269,6 @@
      *            the hour.
      * @param minute
      *            the minute.
-     * @since Android 1.0
      */
     public GregorianCalendar(int year, int month, int day, int hour, int minute) {
         super(TimeZone.getDefault(), Locale.getDefault());
@@ -299,7 +278,7 @@
     /**
      * Constructs a new {@code GregorianCalendar} initialized to the specified date and
      * time in the default {@code TimeZone} and {@code Locale}.
-     * 
+     *
      * @param year
      *            the year.
      * @param month
@@ -312,7 +291,6 @@
      *            the minute.
      * @param second
      *            the second.
-     * @since Android 1.0
      */
     public GregorianCalendar(int year, int month, int day, int hour,
             int minute, int second) {
@@ -328,10 +306,9 @@
     /**
      * Constructs a new {@code GregorianCalendar} initialized to the current date and
      * time and using the specified {@code Locale} and the default {@code TimeZone}.
-     * 
+     *
      * @param locale
      *            the {@code Locale}.
-     * @since Android 1.0
      */
     public GregorianCalendar(Locale locale) {
         this(TimeZone.getDefault(), locale);
@@ -340,10 +317,9 @@
     /**
      * Constructs a new {@code GregorianCalendar} initialized to the current date and
      * time and using the specified {@code TimeZone} and the default {@code Locale}.
-     * 
+     *
      * @param timezone
      *            the {@code TimeZone}.
-     * @since Android 1.0
      */
     public GregorianCalendar(TimeZone timezone) {
         this(timezone, Locale.getDefault());
@@ -352,12 +328,11 @@
     /**
      * Constructs a new {@code GregorianCalendar} initialized to the current date and
      * time and using the specified {@code TimeZone} and {@code Locale}.
-     * 
+     *
      * @param timezone
      *            the {@code TimeZone}.
      * @param locale
      *            the {@code Locale}.
-     * @since Android 1.0
      */
     public GregorianCalendar(TimeZone timezone, Locale locale) {
         super(timezone, locale);
@@ -372,15 +347,14 @@
 
     /**
      * Adds the specified amount to a {@code Calendar} field.
-     * 
+     *
      * @param field
      *            the {@code Calendar} field to modify.
      * @param value
      *            the amount to add to the field.
-     * 
-     * @exception IllegalArgumentException
-     *                when the specified field is DST_OFFSET or ZONE_OFFSET.
-     * @since Android 1.0
+     *
+     * @throws IllegalArgumentException
+     *                if the specified field is DST_OFFSET or ZONE_OFFSET.
      */
     @Override
     public void add(int field, int value) {
@@ -477,9 +451,8 @@
 
     /**
      * Creates new instance of {@code GregorianCalendar} with the same properties.
-     * 
+     *
      * @return a shallow copy of this {@code GregorianCalendar}.
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -508,7 +481,7 @@
 
         int dayOfYear = computeYearAndDay(days, timeVal + zoneOffset);
         fields[DAY_OF_YEAR] = dayOfYear;
-        if(fields[YEAR] == changeYear && gregorianCutover < timeVal + zoneOffset){
+        if(fields[YEAR] == changeYear && gregorianCutover <= timeVal + zoneOffset){
             dayOfYear += currentYearSkew;
         }
         int month = dayOfYear / 32;
@@ -539,7 +512,7 @@
                 dayOfYear = computeYearAndDay(days, timeVal - zoneOffset
                         + dstOffset);
                 fields[DAY_OF_YEAR] = dayOfYear;
-                if(fields[YEAR] == changeYear && gregorianCutover < timeVal - zoneOffset + dstOffset){
+                if(fields[YEAR] == changeYear && gregorianCutover <= timeVal - zoneOffset + dstOffset){
                     dayOfYear += currentYearSkew;
                 }
                 month = dayOfYear / 32;
@@ -621,7 +594,9 @@
     protected void computeFields() {
         int zoneOffset = getTimeZone().getRawOffset();
 
-        fields[ZONE_OFFSET] = zoneOffset;
+        if(!isSet[ZONE_OFFSET]) {
+            fields[ZONE_OFFSET] = zoneOffset;
+        }
 
         int millis = (int) (time % 86400000);
         int savedMillis = millis;
@@ -864,6 +839,9 @@
                                         - (days + daysInMonth(leapYear, month) - 3))
                                 + fields[DAY_OF_WEEK_IN_MONTH] * 7;
                     }
+                } else if (isSet[DAY_OF_WEEK]) {
+                    int skew = mod7(days - 3 - (getFirstDayOfWeek() - 1));
+                    days += mod7(mod7(skew + dayOfWeek - (days - 3)) - skew);
                 }
             }
         } else {
@@ -967,7 +945,7 @@
         return (year - 1970) * 365 + ((year - 1972) / 4)
                 - ((year - 2000) / 100) + ((year - 2000) / 400);
     }
-    
+
     private int daysInMonth() {
         return daysInMonth(isLeapYear(fields[YEAR]), fields[MONTH]);
     }
@@ -1003,16 +981,15 @@
      * Compares the specified {@code Object} to this {@code GregorianCalendar} and returns whether
      * they are equal. To be equal, the {@code Object} must be an instance of {@code GregorianCalendar} and
      * have the same properties.
-     * 
+     *
      * @param object
      *            the {@code Object} to compare with this {@code GregorianCalendar}.
      * @return {@code true} if {@code object} is equal to this
      *         {@code GregorianCalendar}, {@code false} otherwise.
-     * @exception IllegalArgumentException
-     *                when the time is not set and the time cannot be computed
+     * @throws IllegalArgumentException
+     *                if the time is not set and the time cannot be computed
      *                from the current field values.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -1023,11 +1000,10 @@
     /**
      * Gets the maximum value of the specified field for the current date. For
      * example, the maximum number of days in the current month.
-     * 
+     *
      * @param field
      *            the field.
      * @return the maximum value of the specified field.
-     * @since Android 1.0
      */
     @Override
     public int getActualMaximum(int field) {
@@ -1095,11 +1071,10 @@
      * Gets the minimum value of the specified field for the current date. For
      * the gregorian calendar, this value is the same as
      * {@code getMinimum()}.
-     * 
+     *
      * @param field
      *            the field.
      * @return the minimum value of the specified field.
-     * @since Android 1.0
      */
     @Override
     public int getActualMinimum(int field) {
@@ -1109,11 +1084,10 @@
     /**
      * Gets the greatest minimum value of the specified field. For the gregorian
      * calendar, this value is the same as {@code getMinimum()}.
-     * 
+     *
      * @param field
      *            the field.
      * @return the greatest minimum value of the specified field.
-     * @since Android 1.0
      */
     @Override
     public int getGreatestMinimum(int field) {
@@ -1123,9 +1097,8 @@
     /**
      * Returns the gregorian change date of this calendar. This is the date on
      * which the gregorian calendar came into effect.
-     * 
+     *
      * @return a {@code Date} which represents the gregorian change date.
-     * @since Android 1.0
      */
     public final Date getGregorianChange() {
         return new Date(gregorianCutover);
@@ -1134,11 +1107,10 @@
     /**
      * Gets the smallest maximum value of the specified field. For example, 28
      * for the day of month field.
-     * 
+     *
      * @param field
      *            the field.
      * @return the smallest maximum value of the specified field.
-     * @since Android 1.0
      */
     @Override
     public int getLeastMaximum(int field) {
@@ -1158,11 +1130,10 @@
     /**
      * Gets the greatest maximum value of the specified field. For example, 31
      * for the day of month field.
-     * 
+     *
      * @param field
      *            the field.
      * @return the greatest maximum value of the specified field.
-     * @since Android 1.0
      */
     @Override
     public int getMaximum(int field) {
@@ -1171,11 +1142,10 @@
 
     /**
      * Gets the smallest minimum value of the specified field.
-     * 
+     *
      * @param field
      *            the field.
      * @return the smallest minimum value of the specified field.
-     * @since Android 1.0
      */
     @Override
     public int getMinimum(int field) {
@@ -1234,11 +1204,10 @@
     /**
      * Returns an integer hash code for the receiver. Objects which are equal
      * return the same value for this method.
-     * 
+     *
      * @return the receiver's hash.
-     * 
+     *
      * @see #equals
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -1248,12 +1217,11 @@
 
     /**
      * Returns whether the specified year is a leap year.
-     * 
+     *
      * @param year
      *            the year.
      * @return {@code true} if the specified year is a leap year, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public boolean isLeapYear(int year) {
         if (year > changeYear) {
@@ -1288,15 +1256,14 @@
      * field when it goes beyond the maximum or minimum value for the current
      * date. Other fields will be adjusted as required to maintain a consistent
      * date.
-     * 
+     *
      * @param field
      *            the field to roll.
      * @param value
      *            the amount to add.
-     * 
-     * @exception IllegalArgumentException
-     *                when an invalid field is specified.
-     * @since Android 1.0
+     *
+     * @throws IllegalArgumentException
+     *                if an invalid field is specified.
      */
     @Override
     public void roll(int field, int value) {
@@ -1310,72 +1277,90 @@
         isCached = false;
 
         complete();
+        int days, day, mod, maxWeeks, newWeek;
         int max = -1;
         switch (field) {
-            case YEAR:
-                max = maximums[field];
-                break;
-            case WEEK_OF_YEAR:
-            case WEEK_OF_MONTH:
-                int days,
-                day;
-                if (field == WEEK_OF_YEAR) {
-                    days = daysInYear(fields[YEAR]);
-                    day = DAY_OF_YEAR;
+        case YEAR:
+            max = maximums[field];
+            break;
+        case WEEK_OF_YEAR:
+            days = daysInYear(fields[YEAR]);
+            day = DAY_OF_YEAR;
+            mod = mod7(fields[DAY_OF_WEEK] - fields[day]
+                    - (getFirstDayOfWeek() - 1));
+            maxWeeks = (days - 1 + mod) / 7 + 1;
+            newWeek = mod(fields[field] - 1 + value, maxWeeks) + 1;
+            if (newWeek == maxWeeks) {
+                int addDays = (newWeek - fields[field]) * 7;
+                if (fields[day] > addDays && fields[day] + addDays > days) {
+                    set(field, 1);
                 } else {
-                    days = daysInMonth();
-                    day = DATE;
+                    set(field, newWeek - 1);
                 }
-                int mod = mod7(fields[DAY_OF_WEEK] - fields[day]
-                        - (getFirstDayOfWeek() - 1));
-                int maxWeeks = (days - 1 + mod) / 7 + 1;
-                int newWeek = mod(fields[field] - 1 + value, maxWeeks) + 1;
-                if (newWeek == maxWeeks) {
-                    if (fields[day] + (newWeek - fields[field]) * 7 > days) {
-                        set(day, days);
-                    } else {
-                        set(field, newWeek);
-                    }
-                } else if (newWeek == 1) {
-                    int week = (fields[day] - ((fields[day] - 1) / 7 * 7) - 1 + mod) / 7 + 1;
-                    if (week > 1) {
-                        set(day, 1);
-                    } else {
-                        set(field, newWeek);
-                    }
+            } else if (newWeek == 1) {
+                int week = (fields[day] - ((fields[day] - 1) / 7 * 7) - 1 + mod) / 7 + 1;
+                if (week > 1) {
+                    set(field, 1);
                 } else {
                     set(field, newWeek);
                 }
-                break;
-            case DATE:
-                max = daysInMonth();
-                break;
-            case DAY_OF_YEAR:
-                max = daysInYear(fields[YEAR]);
-                break;
-            case DAY_OF_WEEK:
-                max = maximums[field];
-                lastDateFieldSet = WEEK_OF_MONTH;
-                break;
-            case DAY_OF_WEEK_IN_MONTH:
-                max = (fields[DATE] + ((daysInMonth() - fields[DATE]) / 7 * 7) - 1) / 7 + 1;
-                break;
-
-            case ERA:
-            case MONTH:
-            case AM_PM:
-            case HOUR:
-            case HOUR_OF_DAY:
-            case MINUTE:
-            case SECOND:
-            case MILLISECOND:
-                set(field, mod(fields[field] + value, maximums[field] + 1));
-                if (field == MONTH && fields[DATE] > daysInMonth()) {
-                    set(DATE, daysInMonth());
-                } else if (field == AM_PM) {
-                    lastTimeFieldSet = HOUR;
+            } else {
+                set(field, newWeek);
+            }
+            break;
+        case WEEK_OF_MONTH:
+            days = daysInMonth();
+            day = DATE;
+            mod = mod7(fields[DAY_OF_WEEK] - fields[day]
+                    - (getFirstDayOfWeek() - 1));
+            maxWeeks = (days - 1 + mod) / 7 + 1;
+            newWeek = mod(fields[field] - 1 + value, maxWeeks) + 1;
+            if (newWeek == maxWeeks) {
+                if (fields[day] + (newWeek - fields[field]) * 7 > days) {
+                    set(day, days);
+                } else {
+                    set(field, newWeek);
                 }
-                break;
+            } else if (newWeek == 1) {
+                int week = (fields[day] - ((fields[day] - 1) / 7 * 7) - 1 + mod) / 7 + 1;
+                if (week > 1) {
+                    set(day, 1);
+                } else {
+                    set(field, newWeek);
+                }
+            } else {
+                set(field, newWeek);
+            }
+            break;
+        case DATE:
+            max = daysInMonth();
+            break;
+        case DAY_OF_YEAR:
+            max = daysInYear(fields[YEAR]);
+            break;
+        case DAY_OF_WEEK:
+            max = maximums[field];
+            lastDateFieldSet = WEEK_OF_MONTH;
+            break;
+        case DAY_OF_WEEK_IN_MONTH:
+            max = (fields[DATE] + ((daysInMonth() - fields[DATE]) / 7 * 7) - 1) / 7 + 1;
+            break;
+
+        case ERA:
+        case MONTH:
+        case AM_PM:
+        case HOUR:
+        case HOUR_OF_DAY:
+        case MINUTE:
+        case SECOND:
+        case MILLISECOND:
+            set(field, mod(fields[field] + value, maximums[field] + 1));
+            if (field == MONTH && fields[DATE] > daysInMonth()) {
+                set(DATE, daysInMonth());
+            } else if (field == AM_PM) {
+                lastTimeFieldSet = HOUR;
+            }
+            break;
         }
         if (max != -1) {
             set(field, mod(fields[field] - 1 + value, max) + 1);
@@ -1389,15 +1374,14 @@
      * date. Other fields will be adjusted as required to maintain a consistent
      * date. For example, March 31 will roll to April 30 when rolling the month
      * field.
-     * 
+     *
      * @param field
      *            the field to roll.
      * @param increment
      *            {@code true} to increment the field, {@code false} to
      *            decrement.
-     * @exception IllegalArgumentException
-     *                when an invalid field is specified.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *                if an invalid field is specified.
      */
     @Override
     public void roll(int field, boolean increment) {
@@ -1406,10 +1390,9 @@
 
     /**
      * Sets the gregorian change date of this calendar.
-     * 
+     *
      * @param date
      *            a {@code Date} which represents the gregorian change date.
-     * @since Android 1.0
      */
     public void setGregorianChange(Date date) {
         gregorianCutover = date.getTime();
diff --git a/libcore/luni/src/main/java/java/util/HashMap.java b/libcore/luni/src/main/java/java/util/HashMap.java
index 594e8a8..28978d4 100644
--- a/libcore/luni/src/main/java/java/util/HashMap.java
+++ b/libcore/luni/src/main/java/java/util/HashMap.java
@@ -1,10 +1,10 @@
 /*
  *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
+ *  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
+ *  the License. You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
@@ -15,705 +15,657 @@
  *  limitations under the License.
  */
 
+// BEGIN android-note
+// Completely different implementation from harmony.  Runs much faster.
+// 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;
 
 /**
  * HashMap is an implementation of Map. All optional operations (adding and
  * removing) are supported. Keys and values can be any objects.
- * 
- * @since Android 1.0
+ *
+ * @param <K> the type of keys maintained by this map
+ * @param <V> the type of mapped values
  */
-public class HashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>,
-        Cloneable, Serializable {
-    private static final long serialVersionUID = 362498820763181265L;
+public class HashMap<K, V> extends AbstractMap<K, V>
+        implements Cloneable, Serializable, Map<K, V> {
+    /**
+     * Min capacity (other than zero) for a HashMap. Must be a power of two
+     * greater than 1 (and less than 1 << 30).
+     */
+    private static final int MINIMUM_CAPACITY = 4;
 
-    transient int elementCount;
+    /**
+     * Max capacity for a HashMap. Must be a power of two >= MINIMUM_CAPACITY.
+     */
+    private static final int MAXIMUM_CAPACITY = 1 << 30;
 
-    transient Entry<K, V>[] elementData;
+    /**
+     * An empty table shared by all zero-capacity maps (typically from default
+     * constructor). It is never written to, and replaced on first put. Its size
+     * is set to half the minimum, so that the first resize will create a
+     * minimum-sized table.
+     */
+    private static final Entry[] EMPTY_TABLE
+            = new HashMapEntry[MINIMUM_CAPACITY >>> 1];
 
-    final float loadFactor;
+    /**
+     * The default load factor. Note that this implementation ignores the
+     * load factor, but cannot do away with it entirely because it's
+     * metioned in the API.
+     *
+     * <p>Note that this constant has no impact on the behavior of the program,
+     * but it is emitted as part of the serialized form. The load factor of
+     * .75 is hardwired into the program, which uses cheap shifts in place of
+     * expensive division.
+     */
+    static final float DEFAULT_LOAD_FACTOR = .75F;
 
-    int threshold;
+    /**
+     * The hash table. If this hash map contains a mapping for null, it is
+     * not represented this hash table.
+     */
+    transient HashMapEntry<K, V>[] table;
 
-    transient int modCount = 0;
+    /**
+     * The entry representing the null key, or null if there's no such mapping.
+     */
+    transient HashMapEntry<K, V> entryForNullKey;
 
-    private static final int DEFAULT_SIZE = 16;
+    /**
+     * The number of mappings in this hash map.
+     */
+    transient int size;
 
-    static class Entry<K, V> extends MapEntry<K, V> {
-        final int origKeyHash;
+    /**
+     * Incremented by "structural modifications" to allow (best effort)
+     * detection of concurrent modification.
+     */
+    transient int modCount;
 
-        Entry<K, V> next;
+    /**
+     * The table is rehashed when its size exceeds this threshold.
+     * The value of this field is generally .75 * capacity, except when
+     * the capacity is zero, as described in the EMPTY_TABLE declaration
+     * above.
+     */
+    private transient int threshold;
 
-        Entry(K theKey, int hash) {
-            super(theKey, null);
-            this.origKeyHash = hash;
-        }
-
-        Entry(K theKey, V theValue) {
-            super(theKey, theValue);
-            origKeyHash = (theKey == null ? 0 : theKey.hashCode());
-        }
-
-        @Override
-        @SuppressWarnings("unchecked")
-        public Object clone() {
-            Entry<K, V> entry = (Entry<K, V>) super.clone();
-            if (next != null) {
-                entry.next = (Entry<K, V>) next.clone();
-            }
-            return entry;
-        }
-    }
-
-    static class HashMapIterator<E, KT, VT> implements Iterator<E> {
-        private int position = 0;
-
-        int expectedModCount;
-
-        final MapEntry.Type<E, KT, VT> type;
-
-        boolean canRemove = false;
-
-        Entry<KT, VT> entry;
-
-        Entry<KT, VT> lastEntry;
-
-        final HashMap<KT, VT> associatedMap;
-
-        HashMapIterator(MapEntry.Type<E, KT, VT> value, HashMap<KT, VT> hm) {
-            associatedMap = hm;
-            type = value;
-            expectedModCount = hm.modCount;
-        }
-
-        public boolean hasNext() {
-            if (entry != null) {
-                return true;
-            }
-            // BEGIN android-changed
-            Entry<KT, VT>[] elementData = associatedMap.elementData;
-            int length = elementData.length;
-            int newPosition = position;
-            boolean result = false;
-
-            while (newPosition < length) {
-                if (elementData[newPosition] == null) {
-                    newPosition++;
-                } else {
-                    result = true;
-                    break;
-                }
-            }
-
-            position = newPosition;
-            return result;
-            // END android-changed
-        }
-
-        void checkConcurrentMod() throws ConcurrentModificationException {
-            if (expectedModCount != associatedMap.modCount) {
-                throw new ConcurrentModificationException();
-            }
-        }
-
-        public E next() {
-            // BEGIN android-changed
-            // inline checkConcurrentMod()
-            if (expectedModCount != associatedMap.modCount) {
-                throw new ConcurrentModificationException();
-            }
-            if (!hasNext()) {
-                throw new NoSuchElementException();
-            }
-
-            MapEntry<KT, VT> result;
-            Entry<KT, VT> _entry  = entry;
-            if (_entry == null) {
-                result = lastEntry = associatedMap.elementData[position++];
-                entry = lastEntry.next;
-            } else {
-                if (lastEntry.next != _entry) {
-                    lastEntry = lastEntry.next;
-                }
-                result = _entry;
-                entry = _entry.next;
-            }
-            canRemove = true;
-            return type.get(result);
-            // END android-changed
-        }
-
-        public void remove() {
-            checkConcurrentMod();
-            if (!canRemove) {
-                throw new IllegalStateException();
-            }
-
-            canRemove = false;
-            associatedMap.modCount++;
-            if (lastEntry.next == entry) {
-                while (associatedMap.elementData[--position] == null) {
-                    // Do nothing
-                }
-                associatedMap.elementData[position] = associatedMap.elementData[position].next;
-                entry = null;
-            } else {
-                lastEntry.next = entry;
-            }
-            associatedMap.elementCount--;
-            expectedModCount++;
-        }
-    }
-
-    static class HashMapEntrySet<KT, VT> extends AbstractSet<Map.Entry<KT, VT>> {
-        private final HashMap<KT, VT> associatedMap;
-
-        public HashMapEntrySet(HashMap<KT, VT> hm) {
-            associatedMap = hm;
-        }
-
-        HashMap<KT, VT> hashMap() {
-            return associatedMap;
-        }
-
-        @Override
-        public int size() {
-            return associatedMap.elementCount;
-        }
-
-        @Override
-        public void clear() {
-            associatedMap.clear();
-        }
-
-        @Override
-        public boolean remove(Object object) {
-            if (contains(object)) {
-                associatedMap.remove(((Map.Entry<?, ?>) object).getKey());
-                return true;
-            }
-            return false;
-        }
-
-        @Override
-        public boolean contains(Object object) {
-            if (object instanceof Map.Entry) {
-                Object key = ((Map.Entry<?, ?>) object).getKey();
-                Entry entry;
-                if (key == null) {
-                    entry = associatedMap.findNullKeyEntry();
-                } else {
-                    int hash = key.hashCode();
-                    int index = (hash & 0x7FFFFFFF) % associatedMap.elementData.length;
-                    entry = associatedMap.findNonNullKeyEntry(key, index, hash);
-                }
-                return object.equals(entry);
-            }
-            return false;
-        }
-
-        @Override
-        public Iterator<Map.Entry<KT, VT>> iterator() {
-            return new HashMapIterator<Map.Entry<KT, VT>, KT, VT>(
-                    new MapEntry.Type<Map.Entry<KT, VT>, KT, VT>() {
-                        public Map.Entry<KT, VT> get(MapEntry<KT, VT> entry) {
-                            return entry;
-                        }
-                    }, associatedMap);
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    Entry<K, V>[] newElementArray(int s) {
-        return new Entry[s];
-    }
+    // Views - lazily initialized
+    private transient Set<K> keySet;
+    private transient Set<Entry<K, V>> entrySet;
+    private transient Collection<V> values;
 
     /**
      * Constructs a new empty {@code HashMap} instance.
-     * 
-     * @since Android 1.0
      */
+    @SuppressWarnings("unchecked")
     public HashMap() {
-        this(DEFAULT_SIZE);
+        table = (HashMapEntry<K, V>[]) EMPTY_TABLE;
+        threshold = -1; // Forces first put invocation to replace EMPTY_TABLE
     }
 
     /**
      * Constructs a new {@code HashMap} instance with the specified capacity.
-     * 
+     *
      * @param capacity
      *            the initial capacity of this hash map.
      * @throws IllegalArgumentException
      *                when the capacity is less than zero.
-     * @since Android 1.0
      */
     public HashMap(int capacity) {
-        if (capacity >= 0) {
-            elementCount = 0;
-            elementData = newElementArray(capacity == 0 ? 1 : capacity);
-            loadFactor = 0.75f; // Default load factor of 0.75
-            computeMaxSize();
-        } else {
-            throw new IllegalArgumentException();
+        if (capacity < 0) {
+            throw new IllegalArgumentException("Capacity: " + capacity);
         }
+
+        if (capacity == 0) {
+            @SuppressWarnings("unchecked")
+            HashMapEntry<K, V>[] tab = (HashMapEntry<K, V>[]) EMPTY_TABLE;
+            table = tab;
+            threshold = -1; // Forces first put() to replace EMPTY_TABLE
+            return;
+        }
+
+        if (capacity < MINIMUM_CAPACITY) {
+            capacity = MINIMUM_CAPACITY;
+        } else if (capacity > MAXIMUM_CAPACITY) {
+            capacity = MAXIMUM_CAPACITY;
+        } else {
+            capacity = roundUpToPowerOfTwo(capacity);
+        }
+        makeTable(capacity);
     }
 
     /**
      * Constructs a new {@code HashMap} instance with the specified capacity and
      * load factor.
-     * 
+     *
      * @param capacity
      *            the initial capacity of this hash map.
      * @param loadFactor
      *            the initial load factor.
      * @throws IllegalArgumentException
      *                when the capacity is less than zero or the load factor is
-     *                less or equal to zero.
-     * @since Android 1.0
+     *                less or equal to zero or NaN.
      */
     public HashMap(int capacity, float loadFactor) {
-        if (capacity >= 0 && loadFactor > 0) {
-            elementCount = 0;
-            elementData = newElementArray(capacity == 0 ? 1 : capacity);
-            this.loadFactor = loadFactor;
-            computeMaxSize();
-        } else {
-            throw new IllegalArgumentException();
+        this(capacity);
+
+        if (loadFactor <= 0 || Float.isNaN(loadFactor)) {
+            throw new IllegalArgumentException("Load factor: " + loadFactor);
         }
+
+        /*
+         * Note that this implementation ignores loadFactor; it always uses
+         * a load facator of 3/4. This simplifies the code and generally
+         * improves performance.
+         */
     }
 
     /**
      * Constructs a new {@code HashMap} instance containing the mappings from
      * the specified map.
-     * 
+     *
      * @param map
      *            the mappings to add.
-     * @since Android 1.0
      */
     public HashMap(Map<? extends K, ? extends V> map) {
-        this(map.size() < 6 ? 11 : map.size() * 2);
-        putAllImpl(map);
+        this(capacityForInitSize(map.size()));
+        constructorPutAll(map);
     }
 
-    // BEGIN android-changed
     /**
-     * Removes all mappings from this hash map, leaving it empty.
-     * 
-     * @see #isEmpty
-     * @see #size
-     * @since Android 1.0
+     * Inserts all of the elements of map into this HashMap in a manner
+     * suitable for use by constructors and pseudocostructors (i.e., clone,
+     * readObject). Also used by LinkedHashMap.
      */
-    @Override
-    public void clear() {
-        internalClear();
-    }
-
-    void internalClear() {
-        if (elementCount > 0) {
-            elementCount = 0;
-            Arrays.fill(elementData, null);
-            modCount++;
+    final void constructorPutAll(Map<? extends K, ? extends V> map) {
+        for (Entry<? extends K, ? extends V> e : map.entrySet()) {
+            constructorPut(e.getKey(), e.getValue());
         }
     }
-    // END android-changed
+
+    /**
+     * Returns an appropriate capacity for the specified initial size. Does
+     * not round the result up to a power of two; the caller must do this!
+     * The returned value will be between 0 and MAXIMUM_CAPACITY (inclusive).
+     */
+    static int capacityForInitSize(int size) {
+        int result = (size >> 1) + size; // Multiply by 3/2 to allow for growth
+
+        // boolean expr is equivalent to result >= 0 && result<MAXIMUM_CAPACITY
+        return (result & ~(MAXIMUM_CAPACITY-1))==0 ? result : MAXIMUM_CAPACITY;
+    }
 
     /**
      * Returns a shallow copy of this map.
-     * 
+     *
      * @return a shallow copy of this map.
-     * @since Android 1.0
      */
-    @Override
     @SuppressWarnings("unchecked")
-    public Object clone() {
+    @Override public Object clone() {
+        /*
+         * This could be made more efficient. It unnecessarily hashes all of
+         * the elements in the map.
+         */
+        HashMap<K, V> result;
         try {
-            // BEGIN android-changed
-            // copied from newer version of harmony
-            HashMap<K, V> map = (HashMap<K, V>) super.clone();
-            map.elementData = newElementArray(elementData.length);
-            map.internalClear();
-            Entry<K, V> entry;
-            for (int i = 0; i < elementData.length; i++) {
-                if ((entry = elementData[i]) != null){
-                    map.putImpl(entry.getKey(), entry.getValue());
-                    while (entry.next != null){
-                        entry = entry.next;
-                        map.putImpl(entry.getKey(), entry.getValue());
-                    }
-                }
-            // END android-changed
-            }
-            return map;
+            result = (HashMap<K, V>) super.clone();
         } catch (CloneNotSupportedException e) {
-            return null;
+            throw new AssertionError(e);
         }
+
+        // Restore clone to empty state, retaining our capacity and threshold
+        result.makeTable(table.length);
+        result.entryForNullKey = null;
+        result.size = 0;
+        result.keySet = null;
+        result.entrySet = null;
+        result.values = null;
+
+        result.init(); // Give subclass a chance to initialize itself
+        result.constructorPutAll(this); // Calls method overridden in subclass!!
+        return result;
     }
 
-    private void computeMaxSize() {
-        threshold = (int) (elementData.length * loadFactor);
+    /**
+     * This method is called from the pseudo-constructors (clone and readObject)
+     * prior to invoking constructorPut/constructorPutAll, which invoke the
+     * overriden constructorNewEntry method. Normally it is a VERY bad idea to
+     * invoke an overridden method from a pseudo-constructor (Effective Java
+     * Item 17). In this cases it is unavoidable, and the init method provides a
+     * workaround.
+     */
+    void init() { }
+
+    /**
+     * Returns whether this map is empty.
+     *
+     * @return {@code true} if this map has no elements, {@code false}
+     *         otherwise.
+     * @see #size()
+     */
+    @Override public boolean isEmpty() {
+        return size == 0;
+    }
+
+    /**
+     * Returns the number of elements in this map.
+     *
+     * @return the number of elements in this map.
+     */
+    @Override public int size() {
+        return size;
+    }
+
+    /**
+     * Returns the value of the mapping with the specified key.
+     *
+     * @param key
+     *            the key.
+     * @return the value of the mapping with the specified key, or {@code null}
+     *         if no mapping for the specified key is found.
+     */
+    public V get(Object key) {
+        if (key == null) {
+            HashMapEntry<K, V> e = entryForNullKey;
+            return e == null ? null : e.value;
+        }
+
+        // Doug Lea's supplemental secondaryHash function (inlined)
+        int hash = key.hashCode();
+        hash ^= (hash >>> 20) ^ (hash >>> 12);
+        hash ^= (hash >>> 7) ^ (hash >>> 4);
+
+        HashMapEntry<K, V>[] tab = table;
+        for (HashMapEntry<K, V> e = tab[hash & (tab.length - 1)];
+                e != null; e = e.next) {
+            K eKey = e.key;
+            if (eKey == key || (e.hash == hash && key.equals(eKey))) {
+                return e.value;
+            }
+        }
+        return null;
     }
 
     /**
      * Returns whether this map contains the specified key.
-     * 
+     *
      * @param key
      *            the key to search for.
      * @return {@code true} if this map contains the specified key,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
-    @Override
-    public boolean containsKey(Object key) {
-        Entry<K, V> m;
+    @Override public boolean containsKey(Object key) {
         if (key == null) {
-            m = findNullKeyEntry();
-        } else {
-            int hash = key.hashCode();
-            int index = (hash & 0x7FFFFFFF) % elementData.length;
-            m = findNonNullKeyEntry(key, index, hash);
+            return entryForNullKey != null;
         }
-        return m != null;
-    }
 
-    /**
-     * Returns whether this map contains the specified value.
-     * 
-     * @param value
-     *            the value to search for.
-     * @return {@code true} if this map contains the specified value,
-     *         {@code false} otherwise.
-     * @since Android 1.0
-     */
-    @Override
-    public boolean containsValue(Object value) {
-        if (value != null) {
-            for (int i = elementData.length; --i >= 0;) {
-                Entry<K, V> entry = elementData[i];
-                while (entry != null) {
-                    if (value.equals(entry.value)) {
-                        return true;
-                    }
-                    entry = entry.next;
-                }
-            }
-        } else {
-            for (int i = elementData.length; --i >= 0;) {
-                Entry<K, V> entry = elementData[i];
-                while (entry != null) {
-                    if (entry.value == null) {
-                        return true;
-                    }
-                    entry = entry.next;
-                }
+        // Doug Lea's supplemental secondaryHash function (inlined)
+        int hash = key.hashCode();
+        hash ^= (hash >>> 20) ^ (hash >>> 12);
+        hash ^= (hash >>> 7) ^ (hash >>> 4);
+
+        HashMapEntry<K, V>[] tab = table;
+        for (HashMapEntry<K, V> e = tab[hash & (tab.length - 1)];
+                e != null; e = e.next) {
+            K eKey = e.key;
+            if (eKey == key || (e.hash == hash && key.equals(eKey))) {
+                return true;
             }
         }
         return false;
     }
 
     /**
-     * Returns a set containing all of the mappings in this map. Each mapping is
-     * an instance of {@link Map.Entry}. As the set is backed by this map,
-     * changes in one will be reflected in the other.
-     * 
-     * @return a set of the mappings.
-     * @since Android 1.0
+     * Returns whether this map contains the specified value.
+     *
+     * @param value
+     *            the value to search for.
+     * @return {@code true} if this map contains the specified value,
+     *         {@code false} otherwise.
      */
-    @Override
-    public Set<Map.Entry<K, V>> entrySet() {
-        return new HashMapEntrySet<K, V>(this);
-    }
-
-    /**
-     * Returns the value of the mapping with the specified key.
-     * 
-     * @param key
-     *            the key.
-     * @return the value of the mapping with the specified key, or {@code null}
-     *         if no mapping for the specified key is found.
-     * @since Android 1.0
-     */
-    @Override
-    public V get(Object key) {
-        Entry<K, V> m;
-        if (key == null) {
-            m = findNullKeyEntry();
-        } else {
-            int hash = key.hashCode();
-            int index = (hash & 0x7FFFFFFF) % elementData.length;
-            m = findNonNullKeyEntry(key, index, hash);
-        }
-        if (m != null) {
-            return m.value;
-        }
-        return null;
-    }
-
-    final Entry<K,V> findNonNullKeyEntry(Object key, int index, int keyHash) {
-        Entry<K,V> m = elementData[index];
-        // BEGIN android-changed
-        // The VM can optimize String.equals but not Object.equals
-        if (key instanceof String) {
-            String keyString = (String) key;
-            while (m != null) {
-                if (m.origKeyHash == keyHash) {
-                    if (keyString.equals(m.key)) {
-                        return m;
+    @Override public boolean containsValue(Object value) {
+        HashMapEntry[] tab = table;
+        int len = tab.length;
+        if (value == null) {
+            for (int i = 0; i < len; i++) {
+                for (HashMapEntry e = tab[i]; e != null; e = e.next) {
+                    if (e.value == null) {
+                        return true;
                     }
                 }
-                m = m.next;
             }
-        } else {
-            while (m != null) {
-                if (m.origKeyHash == keyHash) {
-                    if (key.equals(m.key)) {
-                        return m;
-                    }
+            return entryForNullKey != null && entryForNullKey.value == null;
+        }
+
+        // value is non-null
+        for (int i = 0; i < len; i++) {
+            for (HashMapEntry e = tab[i]; e != null; e = e.next) {
+                if (value.equals(e.value)) {
+                    return true;
                 }
-                m = m.next;
             }
         }
-        return null;
-        // END android-changed
-    }
-
-    final Entry<K,V> findNullKeyEntry() {
-        Entry<K,V> m = elementData[0];
-        while (m != null && m.key != null)
-            m = m.next;
-        return m;
-    }
-
-    /**
-     * Returns whether this map is empty.
-     * 
-     * @return {@code true} if this map has no elements, {@code false}
-     *         otherwise.
-     * @see #size()
-     * @since Android 1.0
-     */
-    @Override
-    public boolean isEmpty() {
-        return elementCount == 0;
-    }
-
-    /**
-     * Returns a set of the keys contained in this map. The set is backed by
-     * this map so changes to one are reflected by the other. The set does not
-     * support adding.
-     * 
-     * @return a set of the keys.
-     * @since Android 1.0
-     */
-    @Override
-    public Set<K> keySet() {
-        if (keySet == null) {
-            keySet = new AbstractSet<K>() {
-                @Override
-                public boolean contains(Object object) {
-                    return containsKey(object);
-                }
-
-                @Override
-                public int size() {
-                    return HashMap.this.size();
-                }
-
-                @Override
-                public void clear() {
-                    HashMap.this.clear();
-                }
-
-                @Override
-                public boolean remove(Object key) {
-                    Entry<K, V> entry = HashMap.this.removeEntry(key);
-                    return entry != null;
-                }
-
-                @Override
-                public Iterator<K> iterator() {
-                    return new HashMapIterator<K, K, V>(
-                            new MapEntry.Type<K, K, V>() {
-                                public K get(MapEntry<K, V> entry) {
-                                    return entry.key;
-                                }
-                            }, HashMap.this);
-                }
-            };
-        }
-        return keySet;
+        return entryForNullKey != null && value.equals(entryForNullKey.value);
     }
 
     /**
      * Maps the specified key to the specified value.
-     * 
+     *
      * @param key
      *            the key.
      * @param value
      *            the value.
      * @return the value of any previous mapping with the specified key or
      *         {@code null} if there was no such mapping.
-     * @since Android 1.0
      */
-    @Override
-    public V put(K key, V value) {
-        return putImpl(key, value);
-    }
+    @Override public V put(K key, V value) {
+        if (key == null) {
+            return putValueForNullKey(value);
+        }
 
-    private V putImpl(K key, V value) {
-        Entry<K,V> entry;
-        if(key == null) {
-            entry = findNullKeyEntry();
-            if (entry == null) {
-                modCount++;
-                if (++elementCount > threshold) {
-                    rehash();
-                }
-                entry = createHashedEntry(key, 0, 0);
-            }
-        } else {
-            int hash = key.hashCode();
-            int index = (hash & 0x7FFFFFFF) % elementData.length;
-            entry = findNonNullKeyEntry(key, index, hash);
-            if (entry == null) {
-                modCount++;
-                if (++elementCount > threshold) {
-                    rehash();
-                    index = (hash & 0x7FFFFFFF) % elementData.length;
-                }
-                entry = createHashedEntry(key, index, hash);
+        int hash = secondaryHash(key.hashCode());
+        HashMapEntry<K, V>[] tab = table;
+        int index = hash & (tab.length - 1);
+        for (HashMapEntry<K, V> e = tab[index]; e != null; e = e.next) {
+            if (e.hash == hash && key.equals(e.key)) {
+                preModify(e);
+                V oldValue = e.value;
+                e.value = value;
+                return oldValue;
             }
         }
 
-        V result = entry.value;
-        entry.value = value;
-        return result;
+        // No entry for (non-null) key is present; create one
+        modCount++;
+        if (size++ > threshold) {
+            tab = doubleCapacity();
+            index = hash & (tab.length - 1);
+        }
+        addNewEntry(key, value, hash, index);
+        return null;
     }
 
-    Entry<K, V> createEntry(K key, int index, V value) {
-        Entry<K, V> entry = new Entry<K, V>(key, value);
-        entry.next = elementData[index];
-        elementData[index] = entry;
-        return entry;
+    private V putValueForNullKey(V value) {
+        HashMapEntry<K, V> entry = entryForNullKey;
+        if (entry == null) {
+            addNewEntryForNullKey(value);
+            size++;
+            modCount++;
+            return null;
+        } else {
+            preModify(entry);
+            V oldValue = entry.value;
+            entry.value = value;
+            return oldValue;
+        }
     }
 
-    Entry<K,V> createHashedEntry(K key, int index, int hash) {
-        Entry<K,V> entry = new Entry<K,V>(key,hash);
-        entry.next = elementData[index];
-        elementData[index] = entry;
-        return entry;
+    /**
+     * Give LinkedHashMap a chance to take action when we modify an exisitng
+     * entry.
+     *
+     * @param e the entry we're about to modify.
+     */
+    void preModify(HashMapEntry<K, V> e) { }
+
+    /**
+     * This method is just like put, except that it doesn't do things that
+     * are inappropriate or unnecessary for constructors and pseudo-constructors
+     * (i.e., clone, readObject). In particular, this method does not check to
+     * ensure that capacity is sufficient, and does not increment modCount.
+     */
+    private void constructorPut(K key, V value) {
+        if (key == null) {
+            HashMapEntry<K, V> entry = entryForNullKey;
+            if (entry == null) {
+                entryForNullKey = constructorNewEntry(null, value, 0, null);
+                size++;
+            } else {
+                entry.value = value;
+            }
+            return;
+        }
+
+        int hash = secondaryHash(key.hashCode());
+        HashMapEntry<K, V>[] tab = table;
+        int index = hash & (tab.length - 1);
+        HashMapEntry<K, V> first = tab[index];
+        for (HashMapEntry<K, V> e = first; e != null; e = e.next) {
+            if (e.hash == hash && key.equals(e.key)) {
+                e.value = value;
+                return;
+            }
+        }
+
+        // No entry for (non-null) key is present; create one
+        tab[index] = constructorNewEntry(key, value, hash, first);
+        size++;
+    }
+
+    /**
+     * Creates a new entry for the given key, value, hash, and index and
+     * inserts it into the hash table. This method is called by put
+     * (and indirectly, putAll), and overridden by LinkedHashMap. The hash
+     * must incorporate the secondary hash function.
+     */
+    void addNewEntry(K key, V value, int hash, int index) {
+        table[index] = new HashMapEntry<K, V>(key, value, hash, table[index]);
+    }
+
+    /**
+     * Creates a new entry for the null key, and the given value and
+     * inserts it into the hash table. This method is called by put
+     * (and indirectly, putAll), and overridden by LinkedHashMap.
+     */
+    void addNewEntryForNullKey(V value) {
+        entryForNullKey = new HashMapEntry<K, V>(null, value, 0, null);
+    }
+
+    /**
+     * Like newEntry, but does not perform any activity that would be
+     * unnecessary or inappropriate for constructors. In this class, the
+     * two methods behave identically; in LinkedHashMap, they differ.
+     */
+    HashMapEntry<K, V> constructorNewEntry(
+            K key, V value, int hash, HashMapEntry<K, V> first) {
+        return new HashMapEntry<K, V>(key, value, hash, first);
     }
 
     /**
      * Copies all the mappings in the specified map to this map. These mappings
      * will replace all mappings that this map had for any of the keys currently
      * in the given map.
-     * 
+     *
      * @param map
      *            the map to copy mappings from.
-     * @since Android 1.0
      */
-    @Override
-    public void putAll(Map<? extends K, ? extends V> map) {
-        if (!map.isEmpty()) {
-            putAllImpl(map);
-        }
+    @Override public void putAll(Map<? extends K, ? extends V> map) {
+        ensureCapacity(map.size());
+        super.putAll(map);
     }
 
-    private void putAllImpl(Map<? extends K, ? extends V> map) {
-        int capacity = elementCount + map.size();
-        if (capacity > threshold) {
-            rehash(capacity);
+    /**
+     * Ensures that the hash table has sufficient capacity to store the
+     * specified number of mappings, with room to grow. If not, it increases the
+     * capacity as appropriate. Like doubleCapacity, this method moves existing
+     * entries to new buckets as appropriate. Unlike doubleCapacity, this method
+     * can grow the table by factors of 2^n for n > 1. Hopefully, a single call
+     * to this method will be faster than multiple calls to doubleCapacity.
+     *
+     *  <p>This method is called only by putAll.
+     */
+    private void ensureCapacity(int numMappings) {
+        int newCapacity = roundUpToPowerOfTwo(capacityForInitSize(numMappings));
+        HashMapEntry<K, V>[] oldTable = table;
+        int oldCapacity = oldTable.length;
+        if (newCapacity <= oldCapacity) {
+            return;
         }
-        for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
-            putImpl(entry.getKey(), entry.getValue());
+        if (newCapacity == oldCapacity << 1) {
+            doubleCapacity();
+            return;
         }
-    }
 
-    void rehash(int capacity) {
-        int length = (capacity == 0 ? 1 : capacity << 1);
-
-        Entry<K, V>[] newData = newElementArray(length);
-        for (int i = 0; i < elementData.length; i++) {
-            Entry<K, V> entry = elementData[i];
-            while (entry != null) {
-                int index = (entry.origKeyHash & 0x7FFFFFFF) % length;
-                Entry<K, V> next = entry.next;
-                entry.next = newData[index];
-                newData[index] = entry;
-                entry = next;
+        // We're growing by at least 4x, rehash in the obvious way
+        HashMapEntry<K, V>[] newTable = makeTable(newCapacity);
+        if (size != 0) {
+            int newMask = newCapacity - 1;
+            for (int i = 0; i < oldCapacity; i++) {
+                for (HashMapEntry<K, V> e = oldTable[i]; e != null;) {
+                    HashMapEntry<K, V> oldNext = e.next;
+                    int newIndex = e.hash & newMask;
+                    HashMapEntry<K, V> newNext = newTable[newIndex];
+                    newTable[newIndex] = e;
+                    e.next = newNext;
+                    e = oldNext;
+                }
             }
         }
-        elementData = newData;
-        computeMaxSize();
     }
 
-    void rehash() {
-        rehash(elementData.length);
+    /**
+     * Allocate a table of the given capacity and set the threshold accordingly.
+     * @param newCapacity must be a power of two
+     */
+    private HashMapEntry<K, V>[] makeTable(int newCapacity) {
+        @SuppressWarnings("unchecked") HashMapEntry<K, V>[] newTable
+                = (HashMapEntry<K, V>[]) new HashMapEntry[newCapacity];
+        table = newTable;
+        threshold = (newCapacity >> 1) + (newCapacity >> 2); // 3/4 capacity
+        return newTable;
+    }
+
+    /**
+     * Doubles the capacity of the hash table. Existing entries are placed in
+     * the correct bucket on the enlarged table. If the current capacity is,
+     * MAXIMUM_CAPACITY, this method is a no-op. Returns the table, which
+     * will be new unless we were already at MAXIMUM_CAPACITY.
+     */
+    private HashMapEntry<K, V>[] doubleCapacity() {
+        HashMapEntry<K, V>[] oldTable = table;
+        int oldCapacity = oldTable.length;
+        if (oldCapacity == MAXIMUM_CAPACITY) {
+            return oldTable;
+        }
+        int newCapacity = oldCapacity << 1;
+        HashMapEntry<K, V>[] newTable = makeTable(newCapacity);
+        if (size == 0) {
+            return newTable;
+        }
+
+        for (int j = 0; j < oldCapacity; j++) {
+            /*
+             * Rehash the bucket using the minimum number of field writes.
+             * This is the most subtle and delicate code in the class.
+             */
+            HashMapEntry<K, V> e = oldTable[j];
+            if (e == null) {
+                continue;
+            }
+            int highBit = e.hash & oldCapacity;
+            HashMapEntry<K, V> broken = null;
+            newTable[j | highBit] = e;
+            for (HashMapEntry<K, V> n = e.next; n != null; e = n, n = n.next) {
+                int nextHighBit = n.hash & oldCapacity;
+                if (nextHighBit != highBit) {
+                    if (broken == null)
+                        newTable[j | nextHighBit] = n;
+                    else
+                        broken.next = n;
+                    broken = e;
+                    highBit = nextHighBit;
+                }
+            }
+            if (broken != null)
+                broken.next = null;
+        }
+        return newTable;
     }
 
     /**
      * Removes the mapping with the specified key from this map.
-     * 
+     *
      * @param key
      *            the key of the mapping to remove.
      * @return the value of the removed mapping or {@code null} if no mapping
      *         for the specified key was found.
-     * @since Android 1.0
      */
-    @Override
-    public V remove(Object key) {
-        Entry<K, V> entry = removeEntry(key);
-        if (entry != null) {
-            return entry.value;
+    @Override public V remove(Object key) {
+        if (key == null) {
+            return removeNullKey();
+        }
+        int hash = secondaryHash(key.hashCode());
+        HashMapEntry<K, V>[] tab = table;
+        int index = hash & (tab.length - 1);
+        for (HashMapEntry<K, V> e = tab[index], prev = null;
+                e != null; prev = e, e = e.next) {
+            if (e.hash == hash && key.equals(e.key)) {
+                if (prev == null) {
+                    tab[index] = e.next;
+                } else {
+                    prev.next = e.next;
+                }
+                modCount++;
+                size--;
+                postRemove(e);
+                return e.value;
+            }
         }
         return null;
     }
 
-    Entry<K, V> removeEntry(Object key) {
-        int index = 0;
-        Entry<K, V> entry;
-        Entry<K, V> last = null;
-        if (key != null) {
-            int hash = key.hashCode();
-            index = (hash & 0x7FFFFFFF) % elementData.length;
-            entry = elementData[index];
-            while (entry != null && !(entry.origKeyHash == hash && key.equals(entry.key))) {
-                last = entry;
-                entry = entry.next;
-            }
-        } else {
-            entry = elementData[0];
-            while (entry != null && entry.key != null) {
-                last = entry;
-                entry = entry.next;
-            }
-        }
-        if (entry == null) {
+    private V removeNullKey() {
+        HashMapEntry<K, V> e = entryForNullKey;
+        if (e == null) {
             return null;
         }
-        if (last == null) {
-            elementData[index] = entry.next;
-        } else {
-            last.next = entry.next;
-        }
+        entryForNullKey = null;
         modCount++;
-        elementCount--;
-        return entry;
+        size--;
+        postRemove(e);
+        return e.value;
     }
 
     /**
-     * Returns the number of elements in this map.
-     * 
-     * @return the number of elements in this map.
-     * @since Android 1.0
+     * Subclass overrides this method to unlink entry.
      */
-    @Override
-    public int size() {
-        return elementCount;
+    void postRemove(HashMapEntry<K, V> e) { }
+
+    /**
+     * Removes all mappings from this hash map, leaving it empty.
+     *
+     * @see #isEmpty
+     * @see #size
+     */
+    @Override public void clear() {
+        if (size != 0) {
+            Arrays.fill(table, null);
+            entryForNullKey = null;
+            modCount++;
+            size = 0;
+        }
+    }
+
+    /**
+     * Returns a set of the keys contained in this map. The set is backed by
+     * this map so changes to one are reflected by the other. The set does not
+     * support adding.
+     *
+     * @return a set of the keys.
+     */
+    @Override public Set<K> keySet() {
+        Set<K> ks = keySet;
+        return (ks != null) ? ks : (keySet = new KeySet());
     }
 
     /**
@@ -734,69 +686,356 @@
      * different collections when multiple concurrent calls occur, since no
      * synchronization is performed.
      * </p>
-     * 
+     *
      * @return a collection of the values contained in this map.
-     * @since Android 1.0
      */
-    @Override
-    public Collection<V> values() {
-        if (valuesCollection == null) {
-            valuesCollection = new AbstractCollection<V>() {
-                @Override
-                public boolean contains(Object object) {
-                    return containsValue(object);
-                }
-
-                @Override
-                public int size() {
-                    return HashMap.this.size();
-                }
-
-                @Override
-                public void clear() {
-                    HashMap.this.clear();
-                }
-
-                @Override
-                public Iterator<V> iterator() {
-                    return new HashMapIterator<V, K, V>(
-                            new MapEntry.Type<V, K, V>() {
-                                public V get(MapEntry<K, V> entry) {
-                                    return entry.value;
-                                }
-                            }, HashMap.this);
-                }
-            };
-        }
-        return valuesCollection;
+    @Override public Collection<V> values() {
+        Collection<V> vs = values;
+        return (vs != null) ? vs : (values = new Values());
     }
 
+    /**
+     * Returns a set containing all of the mappings in this map. Each mapping is
+     * an instance of {@link Map.Entry}. As the set is backed by this map,
+     * changes in one will be reflected in the other.
+     *
+     * @return a set of the mappings.
+     */
+    public Set<Entry<K, V>> entrySet() {
+        Set<Entry<K, V>> es = entrySet;
+        return (es != null) ? es : (entrySet = new EntrySet());
+    }
+
+    static class HashMapEntry<K, V> implements Entry<K, V> {
+        final K key;
+        V value;
+        final int hash;
+        HashMapEntry<K, V> next;
+
+        HashMapEntry(K key, V value, int hash, HashMapEntry<K, V> next) {
+            this.key = key;
+            this.value = value;
+            this.hash = hash;
+            this.next = next;
+        }
+
+        public final K getKey() {
+            return key;
+        }
+
+        public final V getValue() {
+            return value;
+        }
+
+        public final V setValue(V value) {
+            V oldValue = this.value;
+            this.value = value;
+            return oldValue;
+        }
+
+        @Override public final boolean equals(Object o) {
+            if (!(o instanceof Entry)) {
+                return false;
+            }
+            Entry<?, ?> e = (Entry<?, ?>) o;
+            return HashMap.equals(e.getKey(), key)
+                    && HashMap.equals(e.getValue(), value);
+        }
+
+        @Override public final int hashCode() {
+            return (key == null ? 0 : key.hashCode()) ^
+                    (value == null ? 0 : value.hashCode());
+        }
+
+        @Override public final String toString() {
+            return key + "=" + value;
+        }
+    }
+
+    private abstract class HashIterator {
+        int nextIndex;
+        HashMapEntry<K, V> nextEntry = entryForNullKey;
+        HashMapEntry<K, V> lastEntryReturned;
+        int expectedModCount = modCount;
+
+        HashIterator() {
+            if (nextEntry == null) {
+                HashMapEntry<K, V>[] tab = table;
+                HashMapEntry<K, V> next = null;
+                while (next == null && nextIndex < tab.length) {
+                    next = tab[nextIndex++];
+                }
+                nextEntry = next;
+            }
+        }
+
+        public boolean hasNext() {
+            return nextEntry != null;
+        }
+
+        HashMapEntry<K, V> nextEntry() {
+            if (modCount != expectedModCount)
+                throw new ConcurrentModificationException();
+            if (nextEntry == null)
+                throw new NoSuchElementException();
+
+            HashMapEntry<K, V> entryToReturn = nextEntry;
+            HashMapEntry<K, V>[] tab = table;
+            HashMapEntry<K, V> next = entryToReturn.next;
+            while (next == null && nextIndex < tab.length) {
+                next = tab[nextIndex++];
+            }
+            nextEntry = next;
+            return lastEntryReturned = entryToReturn;
+        }
+
+        public void remove() {
+            if (lastEntryReturned == null)
+                throw new IllegalStateException();
+            if (modCount != expectedModCount)
+                throw new ConcurrentModificationException();
+            HashMap.this.remove(lastEntryReturned.key);
+            lastEntryReturned = null;
+            expectedModCount = modCount;
+        }
+    }
+
+    private final class KeyIterator extends HashIterator
+            implements Iterator<K> {
+        public K next() { return nextEntry().key; }
+    }
+
+    private final class ValueIterator extends HashIterator
+            implements Iterator<V> {
+        public V next() { return nextEntry().value; }
+    }
+
+    private final class EntryIterator extends HashIterator
+            implements Iterator<Entry<K, V>> {
+        public Entry<K, V> next() { return nextEntry(); }
+    }
+
+    /**
+     * Returns true if this map contains the specified mapping.
+     */
+    private boolean containsMapping(Object key, Object value) {
+        if (key == null) {
+            HashMapEntry<K, V> e = entryForNullKey;
+            return e != null && equals(value, e.value);
+        }
+
+        int hash = secondaryHash(key.hashCode());
+        HashMapEntry<K, V>[] tab = table;
+        int index = hash & (tab.length - 1);
+        for (HashMapEntry<K, V> e = tab[index]; e != null; e = e.next) {
+            if (e.hash == hash && key.equals(e.key)) {
+                return equals(value, e.value);
+            }
+        }
+        return false; // No entry for key
+    }
+
+    /**
+     * Removes the mapping from key to value and returns true if this mapping
+     * exists; otherwise, returns does nothing and returns false.
+     */
+    private boolean removeMapping(Object key, Object value) {
+        if (key == null) {
+            HashMapEntry<K, V> e = entryForNullKey;
+            if (e == null || !equals(value, e.value)) {
+                return false;
+            }
+            entryForNullKey = null;
+            modCount++;
+            size--;
+            postRemove(e);
+            return true;
+        }
+
+        int hash = secondaryHash(key.hashCode());
+        HashMapEntry<K, V>[] tab = table;
+        int index = hash & (tab.length - 1);
+        for (HashMapEntry<K, V> e = tab[index], prev = null;
+                e != null; prev = e, e = e.next) {
+            if (e.hash == hash && key.equals(e.key)) {
+                if (!equals(value, e.value)) {
+                    return false;  // Map has wrong value for key
+                }
+                if (prev == null) {
+                    tab[index] = e.next;
+                } else {
+                    prev.next = e.next;
+                }
+                modCount++;
+                size--;
+                postRemove(e);
+                return true;
+            }
+        }
+        return false; // No entry for key
+    }
+
+    private static boolean equals(Object o1, Object o2) {
+        return o1 == o2 || (o1 != null && o1.equals(o2));
+    }
+
+    // Subclass (LinkedHashMap) overrrides these for correct iteration order
+    Iterator<K> newKeyIterator() { return new KeyIterator();   }
+    Iterator<V> newValueIterator() { return new ValueIterator(); }
+    Iterator<Entry<K, V>> newEntryIterator() { return new EntryIterator(); }
+
+    private final class KeySet extends AbstractSet<K> {
+        public Iterator<K> iterator() {
+            return newKeyIterator();
+        }
+        public int size() {
+            return size;
+        }
+        public boolean isEmpty() {
+            return size == 0;
+        }
+        public boolean contains(Object o) {
+            return containsKey(o);
+        }
+        public boolean remove(Object o) {
+            int oldSize = size;
+            HashMap.this.remove(o);
+            return size != oldSize;
+        }
+        public void clear() {
+            HashMap.this.clear();
+        }
+    }
+
+    private final class Values extends AbstractCollection<V> {
+        public Iterator<V> iterator() {
+            return newValueIterator();
+        }
+        public int size() {
+            return size;
+        }
+        public boolean isEmpty() {
+            return size == 0;
+        }
+        public boolean contains(Object o) {
+            return containsValue(o);
+        }
+        public void clear() {
+            HashMap.this.clear();
+        }
+    }
+
+    private final class EntrySet extends AbstractSet<Entry<K, V>> {
+        public Iterator<Entry<K, V>> iterator() {
+            return newEntryIterator();
+        }
+        public boolean contains(Object o) {
+            if (!(o instanceof Entry))
+                return false;
+            Entry<?, ?> e = (Entry<?, ?>) o;
+            return containsMapping(e.getKey(), e.getValue());
+        }
+        public boolean remove(Object o) {
+            if (!(o instanceof Entry))
+                return false;
+            Entry<?, ?> e = (Entry<?, ?>)o;
+            return removeMapping(e.getKey(), e.getValue());
+        }
+        public int size() {
+            return size;
+        }
+        public boolean isEmpty() {
+            return size == 0;
+        }
+        public void clear() {
+            HashMap.this.clear();
+        }
+    }
+
+    /**
+     * Applies a supplemental hash function to a given hashCode, which defends
+     * against poor quality hash functions. This is critical because HashMap
+     * uses power-of-two length hash tables, that otherwise encounter collisions
+     * for hashCodes that do not differ in lower or upper bits.
+     */
+    private static int secondaryHash(int h) {
+        // Doug Lea's supplemental hash function
+        h ^= (h >>> 20) ^ (h >>> 12);
+        return h ^ (h >>> 7) ^ (h >>> 4);
+    }
+
+    /**
+     * Returns the smallest power of two >= its argument, with several caveats:
+     * If the argument is negative but not Integer.MIN_VALUE, the method returns
+     * zero. If the argument is > 2^30 or equal to Integer.MIN_VALUE, the method
+     * returns Integer.MIN_VALUE. If the argument is zero, the method returns
+     * zero.
+     */
+    private static int roundUpToPowerOfTwo(int i) {
+        i--; // If input is a power of two, shift its high-order bit right
+
+        // "Smear" the high-order bit all the way to the right
+        i |= i >>>  1;
+        i |= i >>>  2;
+        i |= i >>>  4;
+        i |= i >>>  8;
+        i |= i >>> 16;
+
+        return i + 1;
+    }
+
+    private static final long serialVersionUID = 362498820763181265L;
+
+    /**
+     * Serializable fields.
+     *
+     * @serialField loadFactor float
+     *              load factor for this HashMap
+     */
+    private static final ObjectStreamField[] serialPersistentFields = {
+        new ObjectStreamField("loadFactor", Float.TYPE)
+    };
+
     private void writeObject(ObjectOutputStream stream) throws IOException {
-        stream.defaultWriteObject();
-        stream.writeInt(elementData.length);
-        stream.writeInt(elementCount);
-        Iterator<?> iterator = entrySet().iterator();
-        while (iterator.hasNext()) {
-            Entry<?, ?> entry = (Entry<?, ?>) iterator.next();
-            stream.writeObject(entry.key);
-            stream.writeObject(entry.value);
-            entry = entry.next;
+        // Emulate loadFactor field for other implementations to read
+        ObjectOutputStream.PutField fields = stream.putFields();
+        fields.put("loadFactor", DEFAULT_LOAD_FACTOR);
+        stream.writeFields();
+
+        stream.writeInt(table.length); // Capacity
+        stream.writeInt(size);
+        for (Entry<K, V> e : entrySet()) {
+            stream.writeObject(e.getKey());
+            stream.writeObject(e.getValue());
         }
     }
 
-    @SuppressWarnings("unchecked")
     private void readObject(ObjectInputStream stream) throws IOException,
             ClassNotFoundException {
         stream.defaultReadObject();
-        int length = stream.readInt();
-        elementData = newElementArray(length);
-        elementCount = stream.readInt();
-        for (int i = elementCount; --i >= 0;) {
-            K key = (K) stream.readObject();
-            int index = (null == key) ? 0 : (key.hashCode() & 0x7FFFFFFF)
-                    % length;
-            createEntry(key, index, (V) stream.readObject());
+        int capacity = stream.readInt();
+        if (capacity < 0) {
+            throw new InvalidObjectException("Capacity: " + capacity);
+        }
+        if (capacity < MINIMUM_CAPACITY) {
+            capacity = MINIMUM_CAPACITY;
+        } else if (capacity > MAXIMUM_CAPACITY) {
+            capacity = MAXIMUM_CAPACITY;
+        } else {
+            capacity = roundUpToPowerOfTwo(capacity);
+        }
+        makeTable(capacity);
+
+        int size = stream.readInt();
+        if (size < 0) {
+            throw new InvalidObjectException("Size: " + size);
+        }
+
+        init(); // Give subclass (LinkedHashMap) a chance to initialize itself
+        for (int i = 0; i < size; i++) {
+            @SuppressWarnings("unchecked") K key = (K) stream.readObject();
+            @SuppressWarnings("unchecked") V val = (V) stream.readObject();
+            constructorPut(key, val);
         }
     }
-
 }
diff --git a/libcore/luni/src/main/java/java/util/HashSet.java b/libcore/luni/src/main/java/java/util/HashSet.java
index fe89109..4c97ca5 100644
--- a/libcore/luni/src/main/java/java/util/HashSet.java
+++ b/libcore/luni/src/main/java/java/util/HashSet.java
@@ -17,7 +17,6 @@
 
 package java.util;
 
-
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
@@ -26,8 +25,6 @@
 /**
  * HashSet is an implementation of a Set. All optional operations (adding and
  * removing) are supported. The elements can be any objects.
- * 
- * @since Android 1.0
  */
 public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable,
         Serializable {
@@ -38,8 +35,6 @@
 
     /**
      * Constructs a new empty instance of {@code HashSet}.
-     * 
-     * @since Android 1.0
      */
     public HashSet() {
         this(new HashMap<E, HashSet<E>>());
@@ -50,7 +45,6 @@
      * 
      * @param capacity
      *            the initial capacity of this {@code HashSet}.
-     * @since Android 1.0
      */
     public HashSet(int capacity) {
         this(new HashMap<E, HashSet<E>>(capacity));
@@ -64,7 +58,6 @@
      *            the initial capacity.
      * @param loadFactor
      *            the initial load factor.
-     * @since Android 1.0
      */
     public HashSet(int capacity, float loadFactor) {
         this(new HashMap<E, HashSet<E>>(capacity, loadFactor));
@@ -76,10 +69,10 @@
      * 
      * @param collection
      *            the collection of elements to add.
-     * @since Android 1.0
      */
     public HashSet(Collection<? extends E> collection) {
-        this(new HashMap<E, HashSet<E>>(collection.size() < 6 ? 11 : collection.size() * 2));
+        this(new HashMap<E, HashSet<E>>(collection.size() < 6 ? 11 : collection
+                .size() * 2));
         for (E e : collection) {
             add(e);
         }
@@ -96,7 +89,6 @@
      *            the object to add.
      * @return {@code true} when this {@code HashSet} did not already contain
      *         the object, {@code false} otherwise
-     * @since Android 1.0
      */
     @Override
     public boolean add(E object) {
@@ -108,7 +100,6 @@
      * 
      * @see #isEmpty
      * @see #size
-     * @since Android 1.0
      */
     @Override
     public void clear() {
@@ -121,7 +112,6 @@
      * 
      * @return a shallow copy of this {@code HashSet}.
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
@@ -142,7 +132,6 @@
      *            the object to search for.
      * @return {@code true} if {@code object} is an element of this
      *         {@code HashSet}, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean contains(Object object) {
@@ -155,7 +144,6 @@
      * @return {@code true} if this {@code HashSet} has no elements,
      *         {@code false} otherwise.
      * @see #size
-     * @since Android 1.0
      */
     @Override
     public boolean isEmpty() {
@@ -167,7 +155,6 @@
      * 
      * @return an Iterator on the elements of this {@code HashSet}.
      * @see Iterator
-     * @since Android 1.0
      */
     @Override
     public Iterator<E> iterator() {
@@ -180,7 +167,6 @@
      * @param object
      *            the object to remove.
      * @return {@code true} if the object was removed, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean remove(Object object) {
@@ -191,7 +177,6 @@
      * Returns the number of elements in this {@code HashSet}.
      * 
      * @return the number of elements in this {@code HashSet}.
-     * @since Android 1.0
      */
     @Override
     public int size() {
@@ -200,15 +185,11 @@
 
     private void writeObject(ObjectOutputStream stream) throws IOException {
         stream.defaultWriteObject();
-        stream.writeInt(backingMap.elementData.length);
-        stream.writeFloat(backingMap.loadFactor);
-        stream.writeInt(backingMap.elementCount);
-        for (int i = backingMap.elementData.length; --i >= 0;) {
-            HashMap.Entry<E, HashSet<E>> entry = backingMap.elementData[i];
-            while (entry != null) {
-                stream.writeObject(entry.key);
-                entry = entry.next;
-            }
+        stream.writeInt(backingMap.table.length);
+        stream.writeFloat(HashMap.DEFAULT_LOAD_FACTOR);
+        stream.writeInt(size());
+        for (E e : this) {
+            stream.writeObject(e);
         }
     }
 
@@ -221,7 +202,7 @@
         backingMap = createBackingMap(length, loadFactor);
         int elementCount = stream.readInt();
         for (int i = elementCount; --i >= 0;) {
-            E key = (E)stream.readObject();
+            E key = (E) stream.readObject();
             backingMap.put(key, this);
         }
     }
diff --git a/libcore/luni/src/main/java/java/util/Hashtable.java b/libcore/luni/src/main/java/java/util/Hashtable.java
index abede2d..ead0db3 100644
--- a/libcore/luni/src/main/java/java/util/Hashtable.java
+++ b/libcore/luni/src/main/java/java/util/Hashtable.java
@@ -15,15 +15,19 @@
  *  limitations under the License.
  */
 
+// BEGIN android-note
+// Completely different implementation from harmony.  Runs much faster.
+// 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 org.apache.harmony.luni.internal.nls.Messages;
-
 /**
  * Hashtable associates keys with values. Both keys and values cannot be null.
  * The size of the Hashtable is the number of key/value pairs it contains. The
@@ -31,659 +35,331 @@
  * factor is a float value which determines how full the Hashtable gets before
  * expanding the capacity. If the load factor of the Hashtable is exceeded, the
  * capacity is doubled.
- * 
+ *
+ * @param <K> the type of keys maintained by this map
+ * @param <V> the type of mapped values
+ *
  * @see Enumeration
  * @see java.io.Serializable
  * @see java.lang.Object#equals
  * @see java.lang.Object#hashCode
- * @since Android 1.0
  */
 
-public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>,
-        Cloneable, Serializable {
+public class Hashtable<K, V> extends Dictionary<K, V>
+        implements Map<K, V>, Cloneable, Serializable {
+    /**
+     * Min capacity (other than zero) for a Hashtable. Must be a power of two
+     * greater than 1 (and less than 1 << 30).
+     */
+    private static final int MINIMUM_CAPACITY = 4;
 
-    private static final long serialVersionUID = 1421746759512286392L;
+    /**
+     * Max capacity for a Hashtable. Must be a power of two >= MINIMUM_CAPACITY.
+     */
+    private static final int MAXIMUM_CAPACITY = 1 << 30;
 
-    transient int elementCount;
+    /**
+     * An empty table shared by all zero-capacity maps (typically from default
+     * constructor). It is never written to, and replaced on first put. Its size
+     * is set to half the minimum, so that the first resize will create a
+     * minimum-sized table.
+     */
+    private static final Entry[] EMPTY_TABLE
+            = new HashtableEntry[MINIMUM_CAPACITY >>> 1];
 
-    transient Entry<K, V>[] elementData;
+    /**
+     * The default load factor. Note that this implementation ignores the
+     * load factor, but cannot do away with it entirely because it's
+     * metioned in the API.
+     *
+     * <p>Note that this constant has no impact on the behavior of the program,
+     * but it is emitted as part of the serialized form. The load factor of
+     * .75 is hardwired into the program, which uses cheap shifts in place of
+     * expensive division.
+     */
+    private static final float DEFAULT_LOAD_FACTOR = .75F;
 
-    private float loadFactor;
+    /**
+     * The hash table.
+     */
+    private transient HashtableEntry<K, V>[] table;
 
-    private int threshold;
+    /**
+     * The number of mappings in this hash map.
+     */
+    private transient int size;
 
-    transient int firstSlot;
+    /**
+     * Incremented by "structural modifications" to allow (best effort)
+     * detection of concurrent modification.
+     */
+    private transient int modCount;
 
-    transient int lastSlot = -1;
+    /**
+     * The table is rehashed when its size exceeds this threshold.
+     * The value of this field is generally .75 * capacity, except when
+     * the capacity is zero, as described in the EMPTY_TABLE declaration
+     * above.
+     */
+    private transient int threshold;
 
-    transient int modCount;
-
-    private static final Enumeration<?> EMPTY_ENUMERATION = new Enumeration<Object>() {
-        public boolean hasMoreElements() {
-            return false;
-        }
-
-        public Object nextElement() {
-            throw new NoSuchElementException();
-        }
-    };
-
-    private static <K, V> Entry<K, V> newEntry(K key, V value, int hash) {
-        return new Entry<K, V>(key, value);
-    }
-
-    private static class Entry<K, V> extends MapEntry<K, V> {
-        Entry<K, V> next;
-
-        final int hashcode;
-
-        Entry(K theKey, V theValue) {
-            super(theKey, theValue);
-            hashcode = theKey.hashCode();
-        }
-
-        @Override
-        @SuppressWarnings("unchecked")
-        public Object clone() {
-            Entry<K, V> entry = (Entry<K, V>) super.clone();
-            if (next != null) {
-                entry.next = (Entry<K, V>) next.clone();
-            }
-            return entry;
-        }
-
-        @Override
-        public V setValue(V object) {
-            if (object == null) {
-                throw new NullPointerException();
-            }
-            V result = value;
-            value = object;
-            return result;
-        }
-
-        public int getKeyHash() {
-            return key.hashCode();
-        }
-
-        public boolean equalsKey(Object aKey, int hash) {
-            // BEGIN android-changed
-            // The VM can inline String.equals
-            return hashcode == aKey.hashCode()
-               && (key instanceof String
-                   ? ((String) key).equals(aKey) : key.equals(aKey));
-            // END android-changed
-        }
-
-        @Override
-        public String toString() {
-            return key + "=" + value; //$NON-NLS-1$
-        }
-    }
-
-    private final class HashIterator<E> implements Iterator<E> {
-        private int position, expectedModCount;
-
-        private final MapEntry.Type<E, K, V> type;
-
-        private Entry<K, V> lastEntry;
-
-        private int lastPosition;
-
-        private boolean canRemove = false;
-
-        HashIterator(MapEntry.Type<E, K, V> value) {
-            type = value;
-            position = lastSlot;
-            expectedModCount = modCount;
-        }
-
-        public boolean hasNext() {
-            if (lastEntry != null && lastEntry.next != null) {
-                return true;
-            }
-            while (position >= firstSlot) {
-                if (elementData[position] == null) {
-                    position--;
-                } else {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        public E next() {
-            if (expectedModCount == modCount) {
-                if (lastEntry != null) {
-                    lastEntry = lastEntry.next;
-                }
-                if (lastEntry == null) {
-                    while (position >= firstSlot
-                            && (lastEntry = elementData[position]) == null) {
-                        position--;
-                    }
-                    if (lastEntry != null) {
-                        lastPosition = position;
-                        // decrement the position so we don't find the same slot
-                        // next time
-                        position--;
-                    }
-                }
-                if (lastEntry != null) {
-                    canRemove = true;
-                    return type.get(lastEntry);
-                }
-                throw new NoSuchElementException();
-            }
-            throw new ConcurrentModificationException();
-        }
-
-        public void remove() {
-            if (expectedModCount == modCount) {
-                if (canRemove) {
-                    canRemove = false;
-                    synchronized (Hashtable.this) {
-                        boolean removed = false;
-                        Entry<K, V> entry = elementData[lastPosition];
-                        if (entry == lastEntry) {
-                            elementData[lastPosition] = entry.next;
-                            removed = true;
-                        } else {
-                            while (entry != null && entry.next != lastEntry) {
-                                entry = entry.next;
-                            }
-                            if (entry != null) {
-                                entry.next = lastEntry.next;
-                                removed = true;
-                            }
-                        }
-                        if (removed) {
-                            modCount++;
-                            elementCount--;
-                            expectedModCount++;
-                            return;
-                        }
-                        // the entry must have been (re)moved outside of the
-                        // iterator
-                        // but this condition wasn't caught by the modCount
-                        // check
-                        // throw ConcurrentModificationException() outside of
-                        // synchronized block
-                    }
-                } else {
-                    throw new IllegalStateException();
-                }
-            }
-            throw new ConcurrentModificationException();
-        }
-    }
-
-    private final class HashEnumerator<E> implements Enumeration<E> {
-        boolean key;
-
-        int start;
-
-        Entry<K, V> entry;
-
-        HashEnumerator(boolean isKey) {
-            key = isKey;
-            start = lastSlot + 1;
-        }
-
-        public boolean hasMoreElements() {
-            if (entry != null) {
-                return true;
-            }
-            while (--start >= firstSlot) {
-                if (elementData[start] != null) {
-                    entry = elementData[start];
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        @SuppressWarnings("unchecked")
-        public E nextElement() {
-            if (hasMoreElements()) {
-                Object result = key ? entry.key : entry.value;
-                entry = entry.next;
-                return (E) result;
-            }
-            throw new NoSuchElementException();
-        }
-    }
+    // Views - lazily initialized
+    private transient Set<K> keySet;
+    private transient Set<Entry<K, V>> entrySet;
+    private transient Collection<V> values;
 
     /**
      * Constructs a new {@code Hashtable} using the default capacity and load
      * factor.
-     * 
-     * @since Android 1.0
      */
+    @SuppressWarnings("unchecked")
     public Hashtable() {
-        this(11);
+        table = (HashtableEntry<K, V>[]) EMPTY_TABLE;
+        threshold = -1; // Forces first put invocation to replace EMPTY_TABLE
     }
 
     /**
      * Constructs a new {@code Hashtable} using the specified capacity and the
      * default load factor.
-     * 
+     *
      * @param capacity
      *            the initial capacity.
-     * @since Android 1.0
      */
     public Hashtable(int capacity) {
-        if (capacity >= 0) {
-            elementCount = 0;
-            elementData = newElementArray(capacity == 0 ? 1 : capacity);
-            firstSlot = elementData.length;
-            loadFactor = 0.75f;
-            computeMaxSize();
-        } else {
-            throw new IllegalArgumentException();
+        if (capacity < 0) {
+            throw new IllegalArgumentException("Capacity: " + capacity);
         }
+
+        if (capacity == 0) {
+            @SuppressWarnings("unchecked")
+            HashtableEntry<K, V>[] tab = (HashtableEntry<K, V>[]) EMPTY_TABLE;
+            table = tab;
+            threshold = -1; // Forces first put() to replace EMPTY_TABLE
+            return;
+        }
+
+        if (capacity < MINIMUM_CAPACITY) {
+            capacity = MINIMUM_CAPACITY;
+        } else if (capacity > MAXIMUM_CAPACITY) {
+            capacity = MAXIMUM_CAPACITY;
+        } else {
+            capacity = roundUpToPowerOfTwo(capacity);
+        }
+        makeTable(capacity);
     }
 
     /**
      * Constructs a new {@code Hashtable} using the specified capacity and load
      * factor.
-     * 
+     *
      * @param capacity
      *            the initial capacity.
      * @param loadFactor
      *            the initial load factor.
-     * @since Android 1.0
      */
     public Hashtable(int capacity, float loadFactor) {
-        if (capacity >= 0 && loadFactor > 0) {
-            elementCount = 0;
-            firstSlot = capacity;
-            elementData = newElementArray(capacity == 0 ? 1 : capacity);
-            this.loadFactor = loadFactor;
-            computeMaxSize();
-        } else {
-            throw new IllegalArgumentException();
+        this(capacity);
+
+        if (loadFactor <= 0 || Float.isNaN(loadFactor)) {
+            throw new IllegalArgumentException("Load factor: " + loadFactor);
         }
+
+        /*
+         * Note that this implementation ignores loadFactor; it always uses
+         * a load facator of 3/4. This simplifies the code and generally
+         * improves performance.
+         */
     }
 
     /**
      * Constructs a new instance of {@code Hashtable} containing the mappings
      * from the specified map.
-     * 
+     *
      * @param map
      *            the mappings to add.
-     * @since Android 1.0
      */
     public Hashtable(Map<? extends K, ? extends V> map) {
-        this(map.size() < 6 ? 11 : (map.size() * 4 / 3) + 11);
-        putAll(map);
-    }
-
-    @SuppressWarnings("unchecked")
-    private Entry<K, V>[] newElementArray(int size) {
-        return new Entry[size];
+        this(capacityForInitSize(map.size()));
+        constructorPutAll(map);
     }
 
     /**
-     * Removes all key/value pairs from this {@code Hashtable}, leaving the
-     * size zero and the capacity unchanged.
-     * 
-     * @see #isEmpty
-     * @see #size
-     * @since Android 1.0
+     * Inserts all of the elements of map into this Hashtable in a manner
+     * suitable for use by constructors and pseudocostructors (i.e., clone,
+     * readObject).
      */
-    public synchronized void clear() {
-        elementCount = 0;
-        Arrays.fill(elementData, null);
-        modCount++;
+    private void constructorPutAll(Map<? extends K, ? extends V> map) {
+        for (Entry<? extends K, ? extends V> e : map.entrySet()) {
+            constructorPut(e.getKey(), e.getValue());
+        }
+    }
+
+    /**
+     * Returns an appropriate capacity for the specified initial size. Does
+     * not round the result up to a power of two; the caller must do this!
+     * The returned value will be between 0 and MAXIMUM_CAPACITY (inclusive).
+     */
+    private static int capacityForInitSize(int size) {
+        int result = (size >> 1) + size; // Multiply by 3/2 to allow for growth
+
+        // boolean expr is equivalent to result >= 0 && result<MAXIMUM_CAPACITY
+        return (result & ~(MAXIMUM_CAPACITY-1))==0 ? result : MAXIMUM_CAPACITY;
     }
 
     /**
      * Returns a new {@code Hashtable} with the same key/value pairs, capacity
      * and load factor.
-     * 
+     *
      * @return a shallow copy of this {@code Hashtable}.
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
-    @Override
     @SuppressWarnings("unchecked")
-    public synchronized Object clone() {
+    @Override public synchronized Object clone() {
+        /*
+         * This could be made more efficient. It unnecessarily hashes all of
+         * the elements in the map.
+         */
+        Hashtable<K, V> result;
         try {
-            Hashtable<K, V> hashtable = (Hashtable<K, V>) super.clone();
-            hashtable.elementData = elementData.clone();
-            Entry<K, V> entry;
-            for (int i = elementData.length; --i >= 0;) {
-                if ((entry = elementData[i]) != null) {
-                    hashtable.elementData[i] = (Entry<K, V>) entry.clone();
-                }
-            }
-            return hashtable;
+            result = (Hashtable<K, V>) super.clone();
         } catch (CloneNotSupportedException e) {
-            return null;
+            throw new AssertionError(e);
         }
-    }
 
-    private void computeMaxSize() {
-        threshold = (int) (elementData.length * loadFactor);
+        // Restore clone to empty state, retaining our capacity and threshold
+        result.makeTable(table.length);
+        result.size = 0;
+        result.keySet = null;
+        result.entrySet = null;
+        result.values = null;
+
+        result.constructorPutAll(this);
+        return result;
     }
 
     /**
-     * Returns true if this {@code Hashtable} contains the specified object as
-     * the value of at least one of the key/value pairs.
-     * 
-     * @param value
-     *            the object to look for as a value in this {@code Hashtable}.
-     * @return {@code true} if object is a value in this {@code Hashtable},
+     * Returns true if this {@code Hashtable} has no key/value pairs.
+     *
+     * @return {@code true} if this {@code Hashtable} has no key/value pairs,
      *         {@code false} otherwise.
-     * @see #containsKey
-     * @see java.lang.Object#equals
-     * @since Android 1.0
+     * @see #size
      */
-    public synchronized boolean contains(Object value) {
-        if (value == null) {
-            throw new NullPointerException();
-        }
+    public synchronized boolean isEmpty() {
+        return size == 0;
+    }
 
-        for (int i = elementData.length; --i >= 0;) {
-            Entry<K, V> entry = elementData[i];
-            while (entry != null) {
-                if (value.equals(entry.value)) {
-                    return true;
-                }
-                entry = entry.next;
+    /**
+     * Returns the number of key/value pairs in this {@code Hashtable}.
+     *
+     * @return the number of key/value pairs in this {@code Hashtable}.
+     * @see #elements
+     * @see #keys
+     */
+    public synchronized int size() {
+        return size;
+    }
+
+    /**
+     * Returns the value associated with the specified key in this
+     * {@code Hashtable}.
+     *
+     * @param key
+     *            the key of the value returned.
+     * @return the value associated with the specified key, or {@code null} if
+     *         the specified key does not exist.
+     * @see #put
+     */
+    public synchronized V get(Object key) {
+        // Doug Lea's supplemental secondaryHash function (inlined)
+        int hash = key.hashCode();
+        hash ^= (hash >>> 20) ^ (hash >>> 12);
+        hash ^= (hash >>> 7) ^ (hash >>> 4);
+
+        HashtableEntry<K, V>[] tab = table;
+        for (HashtableEntry<K, V> e = tab[hash & (tab.length - 1)];
+                e != null; e = e.next) {
+            K eKey = e.key;
+            if (eKey == key || (e.hash == hash && key.equals(eKey))) {
+                return e.value;
             }
         }
-        return false;
+        return null;
     }
 
     /**
      * Returns true if this {@code Hashtable} contains the specified object as a
      * key of one of the key/value pairs.
-     * 
+     *
      * @param key
      *            the object to look for as a key in this {@code Hashtable}.
      * @return {@code true} if object is a key in this {@code Hashtable},
      *         {@code false} otherwise.
      * @see #contains
      * @see java.lang.Object#equals
-     * @since Android 1.0
      */
     public synchronized boolean containsKey(Object key) {
-        return getEntry(key) != null;
-    }
+        // Doug Lea's supplemental secondaryHash function (inlined)
+        int hash = key.hashCode();
+        hash ^= (hash >>> 20) ^ (hash >>> 12);
+        hash ^= (hash >>> 7) ^ (hash >>> 4);
 
-    /**
-     * Searches this {@code Hashtable} for the specified value.
-     * 
-     * @param value
-     *            the object to search for.
-     * @return {@code true} if {@code value} is a value of this
-     *         {@code Hashtable}, {@code false} otherwise.
-     * @since Android 1.0
-     */
-    public boolean containsValue(Object value) {
-        return contains(value);
-    }
-
-    /**
-     * Returns an enumeration on the values of this {@code Hashtable}. The
-     * results of the Enumeration may be affected if the contents of this
-     * {@code Hashtable} are modified.
-     * 
-     * @return an enumeration of the values of this {@code Hashtable}.
-     * @see #keys
-     * @see #size
-     * @see Enumeration
-     * @since Android 1.0
-     */
-    @Override
-    @SuppressWarnings("unchecked")
-    public synchronized Enumeration<V> elements() {
-        if (elementCount == 0) {
-            return (Enumeration<V>) EMPTY_ENUMERATION;
-        }
-        return new HashEnumerator<V>(false);
-    }
-
-    /**
-     * Returns a set of the mappings contained in this {@code Hashtable}. Each
-     * element in the set is a {@link Map.Entry}. The set is backed by this
-     * {@code Hashtable} so changes to one are reflected by the other. The set
-     * does not support adding.
-     * 
-     * @return a set of the mappings.
-     * @since Android 1.0
-     */
-    public Set<Map.Entry<K, V>> entrySet() {
-        return new Collections.SynchronizedSet<Map.Entry<K, V>>(
-                new AbstractSet<Map.Entry<K, V>>() {
-                    @Override
-                    public int size() {
-                        synchronized (Hashtable.this) {
-                            return elementCount;
-                        }
-                    }
-
-                    @Override
-                    public void clear() {
-                        Hashtable.this.clear();
-                    }
-
-                    @Override
-                    @SuppressWarnings("unchecked")
-                    public boolean remove(Object object) {
-                        synchronized (Hashtable.this) {
-                            if (contains(object)) {
-                                Hashtable.this
-                                        .remove(((Map.Entry<K, V>) object)
-                                                .getKey());
-                                return true;
-                            }
-                            return false;
-                        }
-                    }
-
-                    @Override
-                    @SuppressWarnings("unchecked")
-                    public boolean contains(Object object) {
-                        synchronized (Hashtable.this) {
-                            Entry<K, V> entry = getEntry(((Map.Entry<K, V>) object)
-                                    .getKey());
-                            return object.equals(entry);
-                        }
-                    }
-
-                    @Override
-                    public Iterator<Map.Entry<K, V>> iterator() {
-                        return new HashIterator<Map.Entry<K, V>>(
-                                new MapEntry.Type<Map.Entry<K, V>, K, V>() {
-                                    public Map.Entry<K, V> get(
-                                            MapEntry<K, V> entry) {
-                                        return entry;
-                                    }
-                                });
-                    }
-                }, this);
-    }
-
-    /**
-     * Compares this {@code Hashtable} with the specified object and indicates
-     * if they are equal. In order to be equal, {@code object} must be an
-     * instance of Map and contain the same key/value pairs.
-     * 
-     * @param object
-     *            the object to compare with this object.
-     * @return {@code true} if the specified object is equal to this Map,
-     *         {@code false} otherwise.
-     * @see #hashCode
-     * @since Android 1.0
-     */
-    @Override
-    public synchronized boolean equals(Object object) {
-        if (this == object) {
-            return true;
-        }
-        if (object instanceof Map) {
-            Map<?, ?> map = (Map<?, ?>) object;
-            if (size() != map.size()) {
-                return false;
+        HashtableEntry<K, V>[] tab = table;
+        for (HashtableEntry<K, V> e = tab[hash & (tab.length - 1)];
+                e != null; e = e.next) {
+            K eKey = e.key;
+            if (eKey == key || (e.hash == hash && key.equals(eKey))) {
+                return true;
             }
-
-            Set<Map.Entry<K, V>> entries = entrySet();
-            for (Map.Entry<?, ?> e : map.entrySet()) {
-                if (!entries.contains(e)) {
-                    return false;
-                }
-            }
-            return true;
         }
         return false;
     }
 
     /**
-     * Returns the value associated with the specified key in this
-     * {@code Hashtable}.
-     * 
-     * @param key
-     *            the key of the value returned.
-     * @return the value associated with the specified key, or {@code null} if
-     *         the specified key does not exist.
-     * @see #put
-     * @since Android 1.0
+     * Searches this {@code Hashtable} for the specified value.
+     *
+     * @param value
+     *            the object to search for.
+     * @return {@code true} if {@code value} is a value of this
+     *         {@code Hashtable}, {@code false} otherwise.
      */
-    @Override
-    public synchronized V get(Object key) {
-        int hash = key.hashCode();
-        int index = (hash & 0x7FFFFFFF) % elementData.length;
-        Entry<K, V> entry = elementData[index];
-        while (entry != null) {
-            if (entry.equalsKey(key, hash)) {
-                return entry.value;
-            }
-            entry = entry.next;
+    public synchronized boolean containsValue(Object value) {
+        if (value == null) {
+            throw new NullPointerException();
         }
-        return null;
-    }
 
-    Entry<K, V> getEntry(Object key) {
-        int hash = key.hashCode();
-        int index = (hash & 0x7FFFFFFF) % elementData.length;
-        Entry<K, V> entry = elementData[index];
-        while (entry != null) {
-            if (entry.equalsKey(key, hash)) {
-                return entry;
-            }
-            entry = entry.next;
-        }
-        return null;
-    }
+        HashtableEntry[] tab = table;
+        int len = tab.length;
 
-    @Override
-    public synchronized int hashCode() {
-        int result = 0;
-        Iterator<Map.Entry<K, V>> it = entrySet().iterator();
-        while (it.hasNext()) {
-            Map.Entry<K, V> entry = it.next();
-            Object key = entry.getKey();
-            Object value = entry.getValue();
-            int hash = (key != this ? key.hashCode() : 0)
-                    ^ (value != this ? (value != null ? value.hashCode() : 0)
-                            : 0);
-            result += hash;
+        for (int i = 0; i < len; i++) {
+            for (HashtableEntry e = tab[i]; e != null; e = e.next) {
+                if (value.equals(e.value)) {
+                    return true;
+                }
+            }
         }
-        return result;
+        return false;
     }
 
     /**
-     * Returns true if this {@code Hashtable} has no key/value pairs.
-     * 
-     * @return {@code true} if this {@code Hashtable} has no key/value pairs,
+     * Returns true if this {@code Hashtable} contains the specified object as
+     * the value of at least one of the key/value pairs.
+     *
+     * @param value
+     *            the object to look for as a value in this {@code Hashtable}.
+     * @return {@code true} if object is a value in this {@code Hashtable},
      *         {@code false} otherwise.
-     * @see #size
-     * @since Android 1.0
+     * @see #containsKey
+     * @see java.lang.Object#equals
      */
-    @Override
-    public synchronized boolean isEmpty() {
-        return elementCount == 0;
-    }
-
-    /**
-     * Returns an enumeration on the keys of this {@code Hashtable} instance.
-     * The results of the enumeration may be affected if the contents of this
-     * {@code Hashtable} are modified.
-     * 
-     * @return an enumeration of the keys of this {@code Hashtable}.
-     * @see #elements
-     * @see #size
-     * @see Enumeration
-     * @since Android 1.0
-     */
-    @Override
-    @SuppressWarnings("unchecked")
-    public synchronized Enumeration<K> keys() {
-        if (elementCount == 0) {
-            return (Enumeration<K>) EMPTY_ENUMERATION;
-        }
-        return new HashEnumerator<K>(true);
-    }
-
-    /**
-     * Returns a set of the keys contained in this {@code Hashtable}. The set
-     * is backed by this {@code Hashtable} so changes to one are reflected by
-     * the other. The set does not support adding.
-     * 
-     * @return a set of the keys.
-     * @since Android 1.0
-     */
-    public Set<K> keySet() {
-        return new Collections.SynchronizedSet<K>(new AbstractSet<K>() {
-            @Override
-            public boolean contains(Object object) {
-                synchronized (Hashtable.this) {
-                    return containsKey(object);
-                }
-            }
-
-            @Override
-            public int size() {
-                synchronized (Hashtable.this) {
-                    return elementCount;
-                }
-            }
-
-            @Override
-            public void clear() {
-                Hashtable.this.clear();
-            }
-
-            @Override
-            public boolean remove(Object key) {
-                synchronized (Hashtable.this) {
-                    if (containsKey(key)) {
-                        Hashtable.this.remove(key);
-                        return true;
-                    }
-                    return false;
-                }
-            }
-
-            @Override
-            public Iterator<K> iterator() {
-                return new HashIterator<K>(new MapEntry.Type<K, K, V>() {
-                    public K get(MapEntry<K, V> entry) {
-                        return entry.key;
-                    }
-                });
-            }
-        }, this);
+    public boolean contains(Object value) {
+        return containsValue(value);
     }
 
     /**
      * Associate the specified value with the specified key in this
      * {@code Hashtable}. If the key already exists, the old value is replaced.
      * The key and value cannot be null.
-     * 
+     *
      * @param key
      *            the key to add.
      * @param value
@@ -694,259 +370,791 @@
      * @see #get
      * @see #keys
      * @see java.lang.Object#equals
-     * @since Android 1.0
      */
-    @Override
     public synchronized V put(K key, V value) {
-        if (key != null && value != null) {
-            int hash = key.hashCode();
-            int index = (hash & 0x7FFFFFFF) % elementData.length;
-            Entry<K, V> entry = elementData[index];
-            while (entry != null && !entry.equalsKey(key, hash)) {
-                entry = entry.next;
-            }
-            if (entry == null) {
-                modCount++;
-                if (++elementCount > threshold) {
-                    rehash();
-                    index = (hash & 0x7FFFFFFF) % elementData.length;
-                }
-                if (index < firstSlot) {
-                    firstSlot = index;
-                }
-                if (index > lastSlot) {
-                    lastSlot = index;
-                }
-                entry = newEntry(key, value, hash);
-                entry.next = elementData[index];
-                elementData[index] = entry;
-                return null;
-            }
-            V result = entry.value;
-            entry.value = value;
-            return result;
+        if (value == null) {
+            throw new NullPointerException();
         }
-        throw new NullPointerException();
+        int hash = secondaryHash(key.hashCode());
+        HashtableEntry<K, V>[] tab = table;
+        int index = hash & (tab.length - 1);
+        HashtableEntry<K, V> first = tab[index];
+        for (HashtableEntry<K, V> e = first; e != null; e = e.next) {
+            if (e.hash == hash && key.equals(e.key)) {
+                V oldValue = e.value;
+                e.value = value;
+                return oldValue;
+            }
+        }
+
+        // No entry for key is present; create one
+        modCount++;
+        if (size++ > threshold) {
+            rehash();  // Does nothing!!
+            tab = doubleCapacity();
+            index = hash & (tab.length - 1);
+            first = tab[index];
+        }
+        tab[index] = new HashtableEntry<K, V>(key, value, hash, first);
+        return null;
+    }
+
+    /**
+     * This method is just like put, except that it doesn't do things that
+     * are inappropriate or unnecessary for constructors and pseudo-constructors
+     * (i.e., clone, readObject). In particular, this method does not check to
+     * ensure that capacity is sufficient, and does not increment modCount.
+     */
+    private void constructorPut(K key, V value) {
+        if (value == null) {
+            throw new NullPointerException();
+        }
+        int hash = secondaryHash(key.hashCode());
+        HashtableEntry<K, V>[] tab = table;
+        int index = hash & (tab.length - 1);
+        HashtableEntry<K, V> first = tab[index];
+        for (HashtableEntry<K, V> e = first; e != null; e = e.next) {
+            if (e.hash == hash && key.equals(e.key)) {
+                e.value = value;
+                return;
+            }
+        }
+
+        // No entry for key is present; create one
+        tab[index] = new HashtableEntry<K, V>(key, value, hash, first);
+        size++;
     }
 
     /**
      * Copies every mapping to this {@code Hashtable} from the specified map.
-     * 
+     *
      * @param map
      *            the map to copy mappings from.
-     * @since Android 1.0
      */
     public synchronized void putAll(Map<? extends K, ? extends V> map) {
-        for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
-            put(entry.getKey(), entry.getValue());
+        ensureCapacity(map.size());
+        for (Entry<? extends K, ? extends V> e : map.entrySet()) {
+            put(e.getKey(), e.getValue());
+        }
+    }
+
+    /**
+     * Ensures that the hash table has sufficient capacity to store the
+     * specified number of mappings, with room to grow. If not, it increases the
+     * capacity as appropriate. Like doubleCapacity, this method moves existing
+     * entries to new buckets as appropriate. Unlike doubleCapacity, this method
+     * can grow the table by factors of 2^n for n > 1. Hopefully, a single call
+     * to this method will be faster than multiple calls to doubleCapacity.
+     *
+     *  <p>This method is called only by putAll.
+     */
+    private void ensureCapacity(int numMappings) {
+        int newCapacity = roundUpToPowerOfTwo(capacityForInitSize(numMappings));
+        HashtableEntry<K, V>[] oldTable = table;
+        int oldCapacity = oldTable.length;
+        if (newCapacity <= oldCapacity) {
+            return;
+        }
+
+        rehash();  // Does nothing!!
+
+        if (newCapacity == oldCapacity << 1) {
+            doubleCapacity();
+            return;
+        }
+
+        // We're growing by at least 4x, rehash in the obvious way
+        HashtableEntry<K, V>[] newTable = makeTable(newCapacity);
+        if (size != 0) {
+            int newMask = newCapacity - 1;
+            for (int i = 0; i < oldCapacity; i++) {
+                for (HashtableEntry<K, V> e = oldTable[i]; e != null;) {
+                    HashtableEntry<K, V> oldNext = e.next;
+                    int newIndex = e.hash & newMask;
+                    HashtableEntry<K, V> newNext = newTable[newIndex];
+                    newTable[newIndex] = e;
+                    e.next = newNext;
+                    e = oldNext;
+                }
+            }
         }
     }
 
     /**
      * Increases the capacity of this {@code Hashtable}. This method is called
      * when the size of this {@code Hashtable} exceeds the load factor.
-     * 
-     * @since Android 1.0
      */
     protected void rehash() {
-        int length = (elementData.length << 1) + 1;
-        if (length == 0) {
-            length = 1;
+        /*
+         * This method has no testable semantics, other than that it gets
+         * called from time to time.
+         */
+    }
+
+    /**
+     * Allocate a table of the given capacity and set the threshold accordingly.
+     * @param newCapacity must be a power of two
+     */
+    private HashtableEntry<K, V>[] makeTable(int newCapacity) {
+        @SuppressWarnings("unchecked") HashtableEntry<K, V>[] newTable
+                = (HashtableEntry<K, V>[]) new HashtableEntry[newCapacity];
+        table = newTable;
+        threshold = (newCapacity >> 1) + (newCapacity >> 2); // 3/4 capacity
+        return newTable;
+    }
+
+    /**
+     * Doubles the capacity of the hash table. Existing entries are placed in
+     * the correct bucket on the enlarged table. If the current capacity is,
+     * MAXIMUM_CAPACITY, this method is a no-op. Returns the table, which
+     * will be new unless we were already at MAXIMUM_CAPACITY.
+     */
+    private HashtableEntry<K, V>[] doubleCapacity() {
+        HashtableEntry<K, V>[] oldTable = table;
+        int oldCapacity = oldTable.length;
+        if (oldCapacity == MAXIMUM_CAPACITY) {
+            return oldTable;
         }
-        int newFirst = length;
-        int newLast = -1;
-        Entry<K, V>[] newData = newElementArray(length);
-        for (int i = lastSlot + 1; --i >= firstSlot;) {
-            Entry<K, V> entry = elementData[i];
-            while (entry != null) {
-                int index = (entry.getKeyHash() & 0x7FFFFFFF) % length;
-                if (index < newFirst) {
-                    newFirst = index;
-                }
-                if (index > newLast) {
-                    newLast = index;
-                }
-                Entry<K, V> next = entry.next;
-                entry.next = newData[index];
-                newData[index] = entry;
-                entry = next;
+        int newCapacity = oldCapacity << 1;
+        HashtableEntry<K, V>[] newTable = makeTable(newCapacity);
+        if (size == 0) {
+            return newTable;
+        }
+
+        for (int j = 0; j < oldCapacity; j++) {
+            /*
+             * Rehash the bucket using the minimum number of field writes.
+             * This is the most subtle and delicate code in the class.
+             */
+            HashtableEntry<K, V> e = oldTable[j];
+            if (e == null) {
+                continue;
             }
+            int highBit = e.hash & oldCapacity;
+            HashtableEntry<K, V> broken = null;
+            newTable[j | highBit] = e;
+            for (HashtableEntry<K,V> n = e.next; n != null; e = n, n = n.next) {
+                int nextHighBit = n.hash & oldCapacity;
+                if (nextHighBit != highBit) {
+                    if (broken == null)
+                        newTable[j | nextHighBit] = n;
+                    else
+                        broken.next = n;
+                    broken = e;
+                    highBit = nextHighBit;
+                }
+            }
+            if (broken != null)
+                broken.next = null;
         }
-        firstSlot = newFirst;
-        lastSlot = newLast;
-        elementData = newData;
-        computeMaxSize();
+        return newTable;
     }
 
     /**
      * Removes the key/value pair with the specified key from this
      * {@code Hashtable}.
-     * 
+     *
      * @param key
      *            the key to remove.
      * @return the value associated with the specified key, or {@code null} if
      *         the specified key did not exist.
      * @see #get
      * @see #put
-     * @since Android 1.0
      */
-    @Override
     public synchronized V remove(Object key) {
-        int hash = key.hashCode();
-        int index = (hash & 0x7FFFFFFF) % elementData.length;
-        Entry<K, V> last = null;
-        Entry<K, V> entry = elementData[index];
-        while (entry != null && !entry.equalsKey(key, hash)) {
-            last = entry;
-            entry = entry.next;
-        }
-        if (entry != null) {
-            modCount++;
-            if (last == null) {
-                elementData[index] = entry.next;
-            } else {
-                last.next = entry.next;
+        int hash = secondaryHash(key.hashCode());
+        HashtableEntry<K, V>[] tab = table;
+        int index = hash & (tab.length - 1);
+        for (HashtableEntry<K, V> e = tab[index], prev = null;
+                e != null; prev = e, e = e.next) {
+            if (e.hash == hash && key.equals(e.key)) {
+                if (prev == null) {
+                    tab[index] = e.next;
+                } else {
+                    prev.next = e.next;
+                }
+                modCount++;
+                size--;
+                return e.value;
             }
-            elementCount--;
-            V result = entry.value;
-            entry.value = null;
-            return result;
         }
         return null;
     }
 
     /**
-     * Returns the number of key/value pairs in this {@code Hashtable}.
-     * 
-     * @return the number of key/value pairs in this {@code Hashtable}.
-     * @see #elements
-     * @see #keys
-     * @since Android 1.0
+     * Removes all key/value pairs from this {@code Hashtable}, leaving the
+     * size zero and the capacity unchanged.
+     *
+     * @see #isEmpty
+     * @see #size
      */
-    @Override
-    public synchronized int size() {
-        return elementCount;
+    public synchronized void clear() {
+        if (size != 0) {
+            Arrays.fill(table, null);
+            modCount++;
+            size = 0;
+        }
     }
 
     /**
-     * Returns the string representation of this {@code Hashtable}.
-     * 
-     * @return the string representation of this {@code Hashtable}.
-     * @since Android 1.0
+     * Returns a set of the keys contained in this {@code Hashtable}. The set
+     * is backed by this {@code Hashtable} so changes to one are reflected by
+     * the other. The set does not support adding.
+     *
+     * @return a set of the keys.
      */
-    @Override
-    public synchronized String toString() {
-        if (isEmpty()) {
-            return "{}"; //$NON-NLS-1$
-        }
-
-        StringBuilder buffer = new StringBuilder(size() * 28);
-        buffer.append('{');
-        for (int i = lastSlot; i >= firstSlot; i--) {
-            Entry<K, V> entry = elementData[i];
-            while (entry != null) {
-                if (entry.key != this) {
-                    buffer.append(entry.key);
-                } else {
-                    // luni.04=this Map
-                    buffer.append("(" + Messages.getString("luni.04") + ")"); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
-                }
-                buffer.append('=');
-                if (entry.value != this) {
-                    buffer.append(entry.value);
-                } else {
-                    // luni.04=this Map
-                    buffer.append("(" + Messages.getString("luni.04") + ")"); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
-                }
-                buffer.append(", "); //$NON-NLS-1$
-                entry = entry.next;
-            }
-        }
-        // Remove the last ", "
-        if (elementCount > 0) {
-            buffer.setLength(buffer.length() - 2);
-        }
-        buffer.append('}');
-        return buffer.toString();
+    public synchronized Set<K> keySet() {
+        Set<K> ks = keySet;
+        return (ks != null) ? ks : (keySet = new KeySet());
     }
 
     /**
      * Returns a collection of the values contained in this {@code Hashtable}.
      * The collection is backed by this {@code Hashtable} so changes to one are
      * reflected by the other. The collection does not support adding.
-     * 
+     *
      * @return a collection of the values.
-     * @since Android 1.0
      */
-    public Collection<V> values() {
-        return new Collections.SynchronizedCollection<V>(
-                new AbstractCollection<V>() {
-                    @Override
-                    public boolean contains(Object object) {
-                        synchronized (Hashtable.this) {
-                            return Hashtable.this.contains(object);
-                        }
-                    }
-
-                    @Override
-                    public int size() {
-                        synchronized (Hashtable.this) {
-                            return elementCount;
-                        }
-                    }
-
-                    @Override
-                    public void clear() {
-                        Hashtable.this.clear();
-                    }
-
-                    @Override
-                    public Iterator<V> iterator() {
-                        return new HashIterator<V>(
-                                new MapEntry.Type<V, K, V>() {
-                                    public V get(MapEntry<K, V> entry) {
-                                        return entry.value;
-                                    }
-                                });
-                    }
-                }, this);
+    public synchronized Collection<V> values() {
+        Collection<V> vs = values;
+        return (vs != null) ? vs : (values = new Values());
     }
 
-    private synchronized void writeObject(ObjectOutputStream stream)
-            throws IOException {
-        stream.defaultWriteObject();
-        stream.writeInt(elementData.length);
-        stream.writeInt(elementCount);
-        for (int i = elementData.length; --i >= 0;) {
-            Entry<K, V> entry = elementData[i];
-            while (entry != null) {
-                stream.writeObject(entry.key);
-                stream.writeObject(entry.value);
-                entry = entry.next;
+    /**
+     * Returns a set of the mappings contained in this {@code Hashtable}. Each
+     * element in the set is a {@link Map.Entry}. The set is backed by this
+     * {@code Hashtable} so changes to one are reflected by the other. The set
+     * does not support adding.
+     *
+     * @return a set of the mappings.
+     */
+    public synchronized Set<Entry<K, V>> entrySet() {
+        Set<Entry<K, V>> es = entrySet;
+        return (es != null) ? es : (entrySet = new EntrySet());
+    }
+
+
+    /**
+     * Returns an enumeration on the keys of this {@code Hashtable} instance.
+     * The results of the enumeration may be affected if the contents of this
+     * {@code Hashtable} are modified.
+     *
+     * @return an enumeration of the keys of this {@code Hashtable}.
+     * @see #elements
+     * @see #size
+     * @see Enumeration
+     */
+    public synchronized Enumeration<K> keys() {
+        return new KeyEnumeration();
+    }
+
+    /**
+     * Returns an enumeration on the values of this {@code Hashtable}. The
+     * results of the Enumeration may be affected if the contents of this
+     * {@code Hashtable} are modified.
+     *
+     * @return an enumeration of the values of this {@code Hashtable}.
+     * @see #keys
+     * @see #size
+     * @see Enumeration
+     */
+    public synchronized Enumeration<V> elements() {
+        return new ValueEnumeration();
+    }
+
+    /**
+     * Note: technically the methods of this class should synchronize the
+     * backing map.  However, this would require them to have a reference
+     * to it, which would cause consiserable bloat.  Moreover, the RI
+     * behaves the same way.
+     */
+    private static class HashtableEntry<K, V> implements Entry<K, V> {
+        final K key;
+        V value;
+        final int hash;
+        HashtableEntry<K, V> next;
+
+        HashtableEntry(K key, V value, int hash, HashtableEntry<K, V> next) {
+            this.key = key;
+            this.value = value;
+            this.hash = hash;
+            this.next = next;
+        }
+
+        public final K getKey() {
+            return key;
+        }
+
+        public final V getValue() {
+            return value;
+        }
+
+        public final V setValue(V value) {
+            if (value == null) {
+                throw new NullPointerException();
+            }
+            V oldValue = this.value;
+            this.value = value;
+            return oldValue;
+        }
+
+        @Override public final boolean equals(Object o) {
+            if (!(o instanceof Entry)) {
+                return false;
+            }
+            Entry<?, ?> e = (Entry<?, ?>) o;
+            return key.equals(e.getKey()) && value.equals(e.getValue());
+        }
+
+        @Override public final int hashCode() {
+            return key.hashCode() ^ value.hashCode();
+        }
+
+        @Override public final String toString() {
+            return key + "=" + value;
+        }
+    }
+
+    private abstract class HashIterator {
+        int nextIndex;
+        HashtableEntry<K, V> nextEntry;
+        HashtableEntry<K, V> lastEntryReturned;
+        int expectedModCount = modCount;
+
+        HashIterator() {
+            HashtableEntry<K, V>[] tab = table;
+            HashtableEntry<K, V> next = null;
+            while (next == null && nextIndex < tab.length) {
+                next = tab[nextIndex++];
+            }
+            nextEntry = next;
+        }
+
+        public boolean hasNext() {
+            return nextEntry != null;
+        }
+
+        HashtableEntry<K, V> nextEntry() {
+            if (modCount != expectedModCount)
+                throw new ConcurrentModificationException();
+            if (nextEntry == null)
+                throw new NoSuchElementException();
+
+            HashtableEntry<K, V> entryToReturn = nextEntry;
+            HashtableEntry<K, V>[] tab = table;
+            HashtableEntry<K, V> next = entryToReturn.next;
+            while (next == null && nextIndex < tab.length) {
+                next = tab[nextIndex++];
+            }
+            nextEntry = next;
+            return lastEntryReturned = entryToReturn;
+        }
+
+        HashtableEntry<K, V> nextEntryNotFailFast() {
+            if (nextEntry == null)
+                throw new NoSuchElementException();
+
+            HashtableEntry<K, V> entryToReturn = nextEntry;
+            HashtableEntry<K, V>[] tab = table;
+            HashtableEntry<K, V> next = entryToReturn.next;
+            while (next == null && nextIndex < tab.length) {
+                next = tab[nextIndex++];
+            }
+            nextEntry = next;
+            return lastEntryReturned = entryToReturn;
+        }
+
+        public void remove() {
+            if (lastEntryReturned == null)
+                throw new IllegalStateException();
+            if (modCount != expectedModCount)
+                throw new ConcurrentModificationException();
+            Hashtable.this.remove(lastEntryReturned.key);
+            lastEntryReturned = null;
+            expectedModCount = modCount;
+        }
+    }
+
+    private final class KeyIterator extends HashIterator
+            implements Iterator<K> {
+        public K next() { return nextEntry().key; }
+    }
+
+    private final class ValueIterator extends HashIterator
+            implements Iterator<V> {
+        public V next() { return nextEntry().value; }
+    }
+
+    private final class EntryIterator extends HashIterator
+            implements Iterator<Entry<K, V>> {
+        public Entry<K, V> next() { return nextEntry(); }
+    }
+
+    private final class KeyEnumeration extends HashIterator
+            implements Enumeration<K> {
+        public boolean hasMoreElements() { return hasNext(); }
+        public K nextElement() { return nextEntryNotFailFast().key; }
+    }
+
+    private final class ValueEnumeration extends HashIterator
+            implements Enumeration<V> {
+        public boolean hasMoreElements() { return hasNext(); }
+        public V nextElement() { return nextEntryNotFailFast().value; }
+    }
+
+    /**
+     * Returns true if this map contains the specified mapping.
+     */
+    private synchronized boolean containsMapping(Object key, Object value) {
+        int hash = secondaryHash(key.hashCode());
+        HashtableEntry<K, V>[] tab = table;
+        int index = hash & (tab.length - 1);
+        for (HashtableEntry<K, V> e = tab[index]; e != null; e = e.next) {
+            if (e.hash == hash && e.key.equals(key)) {
+                return e.value.equals(value);
+            }
+        }
+        return false; // No entry for key
+    }
+
+    /**
+     * Removes the mapping from key to value and returns true if this mapping
+     * exists; otherwise, returns does nothing and returns false.
+     */
+    private synchronized boolean removeMapping(Object key, Object value) {
+        int hash = secondaryHash(key.hashCode());
+        HashtableEntry<K, V>[] tab = table;
+        int index = hash & (tab.length - 1);
+        for (HashtableEntry<K, V> e = tab[index], prev = null;
+                e != null; prev = e, e = e.next) {
+            if (e.hash == hash && e.key.equals(key)) {
+                if (!e.value.equals(value)) {
+                    return false;  // Map has wrong value for key
+                }
+                if (prev == null) {
+                    tab[index] = e.next;
+                } else {
+                    prev.next = e.next;
+                }
+                modCount++;
+                size--;
+                return true;
+            }
+        }
+        return false; // No entry for key
+    }
+
+    /**
+     * Compares this {@code Hashtable} with the specified object and indicates
+     * if they are equal. In order to be equal, {@code object} must be an
+     * instance of Map and contain the same key/value pairs.
+     *
+     * @param object
+     *            the object to compare with this object.
+     * @return {@code true} if the specified object is equal to this Map,
+     *         {@code false} otherwise.
+     * @see #hashCode
+     */
+    @Override public synchronized boolean equals(Object object) {
+        return (object instanceof Map) &&
+                entrySet().equals(((Map<?, ?>)object).entrySet());
+    }
+
+    @Override public synchronized int hashCode() {
+        int result = 0;
+        for (Entry<K, V> e : entrySet()) {
+            K key = e.getKey();
+            V value = e.getValue();
+            if (key == this || value == this) {
+                continue;
+            }
+            result += (key != null ? key.hashCode() : 0)
+                    ^ (value != null ? value.hashCode() : 0);
+        }
+        return result;
+    }
+
+    /**
+     * A rough estimate of the number of characters per entry, for use
+     * when creating a string buffer in the toString method.
+     */
+    private static final int CHARS_PER_ENTRY = 15;
+
+    /**
+     * Returns the string representation of this {@code Hashtable}.
+     *
+     * @return the string representation of this {@code Hashtable}.
+     */
+    @Override public synchronized String toString() {
+        StringBuilder result = new StringBuilder(CHARS_PER_ENTRY * size);
+        result.append('{');
+        Iterator<Entry<K, V>> i = entrySet().iterator();
+        boolean hasMore = i.hasNext();
+        while (hasMore) {
+            Entry<K, V> entry = i.next();
+
+            K key = entry.getKey();
+            result.append(key == this ? "(this Map)" : key.toString());
+
+            result.append('=');
+
+            V value = entry.getValue();
+            result.append(value == this ? "(this Map)" : value.toString());
+
+            if (hasMore = i.hasNext()) {
+                result.append(", ");
+            }
+        }
+
+        result.append('}');
+        return result.toString();
+    }
+
+    private final class KeySet extends AbstractSet<K> {
+        public Iterator<K> iterator() {
+            return new KeyIterator();
+        }
+        public int size() {
+            return Hashtable.this.size();
+        }
+        public boolean contains(Object o) {
+            return containsKey(o);
+        }
+        public boolean remove(Object o) {
+            synchronized (Hashtable.this) {
+                int oldSize = size;
+                Hashtable.this.remove(o);
+                return size != oldSize;
+            }
+        }
+        public void clear() {
+            Hashtable.this.clear();
+        }
+        public boolean removeAll(Collection<?> collection) {
+            synchronized (Hashtable.this) {
+                return super.removeAll(collection);
+            }
+        }
+        public boolean retainAll(Collection<?> collection) {
+            synchronized (Hashtable.this) {
+                return super.retainAll(collection);
+            }
+        }
+        public boolean containsAll(Collection<?> collection) {
+            synchronized (Hashtable.this) {
+                return super.containsAll(collection);
+            }
+        }
+        public boolean equals(Object object) {
+            synchronized (Hashtable.this) {
+                return super.equals(object);
+            }
+        }
+        public int hashCode() {
+            synchronized (Hashtable.this) {
+                return super.hashCode();
+            }
+        }
+        public String toString() {
+            synchronized (Hashtable.this) {
+                return super.toString();
+            }
+        }
+        public Object[] toArray() {
+            synchronized (Hashtable.this) {
+                return super.toArray();
+            }
+        }
+        public <T> T[] toArray(T[] a) {
+            synchronized (Hashtable.this) {
+                return super.toArray(a);
             }
         }
     }
 
-    @SuppressWarnings("unchecked")
+    private final class Values extends AbstractCollection<V> {
+        public Iterator<V> iterator() {
+            return new ValueIterator();
+        }
+        public int size() {
+            return Hashtable.this.size();
+        }
+        public boolean contains(Object o) {
+            return containsValue(o);
+        }
+        public void clear() {
+            Hashtable.this.clear();
+        }
+        public boolean containsAll(Collection<?> collection) {
+            synchronized (Hashtable.this) {
+                return super.containsAll(collection);
+            }
+        }
+        public String toString() {
+            synchronized (Hashtable.this) {
+                return super.toString();
+            }
+        }
+        public Object[] toArray() {
+            synchronized (Hashtable.this) {
+                return super.toArray();
+            }
+        }
+        public <T> T[] toArray(T[] a) {
+            synchronized (Hashtable.this) {
+                return super.toArray(a);
+            }
+        }
+    }
+
+    private final class EntrySet extends AbstractSet<Entry<K, V>> {
+        public Iterator<Entry<K, V>> iterator() {
+            return new EntryIterator();
+        }
+        public boolean contains(Object o) {
+            if (!(o instanceof Entry))
+                return false;
+            Entry<?, ?> e = (Entry<?, ?>) o;
+            return containsMapping(e.getKey(), e.getValue());
+        }
+        public boolean remove(Object o) {
+            if (!(o instanceof Entry))
+                return false;
+            Entry<?, ?> e = (Entry<?, ?>)o;
+            return removeMapping(e.getKey(), e.getValue());
+        }
+        public int size() {
+            return Hashtable.this.size();
+        }
+        public void clear() {
+            Hashtable.this.clear();
+        }
+        public boolean removeAll(Collection<?> collection) {
+            synchronized (Hashtable.this) {
+                return super.removeAll(collection);
+            }
+        }
+        public boolean retainAll(Collection<?> collection) {
+            synchronized (Hashtable.this) {
+                return super.retainAll(collection);
+            }
+        }
+        public boolean containsAll(Collection<?> collection) {
+            synchronized (Hashtable.this) {
+                return super.containsAll(collection);
+            }
+        }
+        public boolean equals(Object object) {
+            synchronized (Hashtable.this) {
+                return super.equals(object);
+            }
+        }
+        public int hashCode() {
+            return Hashtable.this.hashCode();
+        }
+        public String toString() {
+            synchronized (Hashtable.this) {
+                return super.toString();
+            }
+        }
+        public Object[] toArray() {
+            synchronized (Hashtable.this) {
+                return super.toArray();
+            }
+        }
+        public <T> T[] toArray(T[] a) {
+            synchronized (Hashtable.this) {
+                return super.toArray(a);
+            }
+        }
+    }
+
+    /**
+     * Applies a supplemental hash function to a given hashCode, which defends
+     * against poor quality hash functions. This is critical because Hashtable
+     * uses power-of-two length hash tables, that otherwise encounter collisions
+     * for hashCodes that do not differ in lower or upper bits.
+     */
+    private static int secondaryHash(int h) {
+        // Doug Lea's supplemental hash function
+        h ^= (h >>> 20) ^ (h >>> 12);
+        return h ^ (h >>> 7) ^ (h >>> 4);
+    }
+
+    /**
+     * Returns the smallest power of two >= its argument, with several caveats:
+     * If the argument is negative but not Integer.MIN_VALUE, the method returns
+     * zero. If the argument is > 2^30 or equal to Integer.MIN_VALUE, the method
+     * returns Integer.MIN_VALUE. If the argument is zero, the method returns
+     * zero.
+     */
+    private static int roundUpToPowerOfTwo(int i) {
+        i--; // If input is a power of two, shift its high-order bit right
+
+        // "Smear" the high-order bit all the way to the right
+        i |= i >>>  1;
+        i |= i >>>  2;
+        i |= i >>>  4;
+        i |= i >>>  8;
+        i |= i >>> 16;
+
+        return i + 1;
+    }
+
+    private static final long serialVersionUID = 1421746759512286392L;
+
+    /**
+     * Serializable fields.
+     *
+     * @serialField loadFactor float
+     *              load factor for this Hashtable
+     */
+    private static final ObjectStreamField[] serialPersistentFields = {
+        new ObjectStreamField("threshold", Integer.TYPE),
+        new ObjectStreamField("loadFactor", Float.TYPE)
+    };
+
+    private synchronized void writeObject(ObjectOutputStream stream)
+            throws IOException {
+        // Emulate loadFactor field for other implementations to read
+        ObjectOutputStream.PutField fields = stream.putFields();
+        fields.put("threshold",  (int) (DEFAULT_LOAD_FACTOR * table.length));
+        fields.put("loadFactor", DEFAULT_LOAD_FACTOR);
+        stream.writeFields();
+
+        stream.writeInt(table.length); // Capacity
+        stream.writeInt(size);
+        for (Entry<K, V> e : entrySet()) {
+            stream.writeObject(e.getKey());
+            stream.writeObject(e.getValue());
+        }
+    }
+
     private void readObject(ObjectInputStream stream) throws IOException,
             ClassNotFoundException {
         stream.defaultReadObject();
-        int length = stream.readInt();
-        elementData = newElementArray(length);
-        elementCount = stream.readInt();
-        for (int i = elementCount; --i >= 0;) {
-            Object key = stream.readObject();
-            int hash = key.hashCode();
-            int index = (hash & 0x7FFFFFFF) % length;
-            if (index < firstSlot) {
-                firstSlot = index;
-            }
-            if (index > lastSlot) {
-                lastSlot = index;
-            }
-            Entry<K, V> entry = newEntry((K) key, (V) stream.readObject(), hash);
-            entry.next = elementData[index];
-            elementData[index] = entry;
+        int capacity = stream.readInt();
+        if (capacity < 0) {
+            throw new InvalidObjectException("Capacity: " + capacity);
+        }
+        if (capacity < MINIMUM_CAPACITY) {
+            capacity = MINIMUM_CAPACITY;
+        } else if (capacity > MAXIMUM_CAPACITY) {
+            capacity = MAXIMUM_CAPACITY;
+        } else {
+            capacity = roundUpToPowerOfTwo(capacity);
+        }
+        makeTable(capacity);
+
+        int size = stream.readInt();
+        if (size < 0) {
+            throw new InvalidObjectException("Size: " + size);
+        }
+
+        for (int i = 0; i < size; i++) {
+            @SuppressWarnings("unchecked") K key = (K) stream.readObject();
+            @SuppressWarnings("unchecked") V val = (V) stream.readObject();
+            constructorPut(key, val);
         }
     }
 }
diff --git a/libcore/luni/src/main/java/java/util/HugeEnumSet.java b/libcore/luni/src/main/java/java/util/HugeEnumSet.java
index 1d43360..fd3e1bd 100644
--- a/libcore/luni/src/main/java/java/util/HugeEnumSet.java
+++ b/libcore/luni/src/main/java/java/util/HugeEnumSet.java
@@ -92,6 +92,8 @@
             currentElementMask = unProcessedBits[bitsPosition]
                     & (-unProcessedBits[bitsPosition]);
             unProcessedBits[bitsPosition] -= currentElementMask;
+            int index = Long.numberOfTrailingZeros(currentElementMask)
+                    + bitsPosition * BIT_IN_LONG;
             if (0 == unProcessedBits[bitsPosition]) {
                 int oldBitsPosition = bitsPosition;
                 findNextNoneZeroPosition(bitsPosition + 1);
@@ -99,8 +101,7 @@
                     canProcess = false;
                 }
             }
-            return enums[Long.numberOfTrailingZeros(currentElementMask)
-                    + bitsPosition * BIT_IN_LONG];
+            return enums[index];
         }
 
         public void remove() {
@@ -185,6 +186,7 @@
         }
     }
     
+    @SuppressWarnings("unchecked")
     @Override
     public boolean contains(Object object) {
         if (null == object) {
@@ -329,7 +331,7 @@
 
             // endElementInBits + 1 is the number of consecutive ones.
             // 63 - endElementInBits is the following zeros of the right most one.
-            range = -1l >>> (BIT_IN_LONG - (endElementInBits + 1)) << (63 - endElementInBits);
+            range = -1l >>> (BIT_IN_LONG - (endElementInBits + 1));
             size -= Long.bitCount(bits[endBitsIndex]);
             bits[endBitsIndex] |= range;
             size += Long.bitCount(bits[endBitsIndex]);
diff --git a/libcore/luni/src/main/java/java/util/IdentityHashMap.java b/libcore/luni/src/main/java/java/util/IdentityHashMap.java
index 3301a99..053de1d 100644
--- a/libcore/luni/src/main/java/java/util/IdentityHashMap.java
+++ b/libcore/luni/src/main/java/java/util/IdentityHashMap.java
@@ -30,16 +30,15 @@
  * <p>
  * <b>Note: This class intentionally violates the general contract of {@code
  * Map}'s on comparing objects by their {@code equals} method.</b>
- * </p>
  * <p>
  * IdentityHashMap uses open addressing (linear probing in particular) for
  * collision resolution. This is different from HashMap which uses Chaining.
- * </p>
+ * <p>
  * Like HashMap, IdentityHashMap is not thread safe, so access by multiple
  * threads must be synchronized by an external mechanism such as
  * Collections.synchronizedMap.
  * 
- * @since Android 1.0
+ * @since 1.4
  */
 public class IdentityHashMap<K, V> extends AbstractMap<K, V> implements
         Map<K, V>, Serializable, Cloneable {
@@ -239,8 +238,6 @@
 
     /**
      * Creates an IdentityHashMap with default expected maximum size.
-     * 
-     * @since Android 1.0
      */
     public IdentityHashMap() {
         this(DEFAULT_MAX_SIZE);
@@ -252,7 +249,6 @@
      * @param maxSize
      *            The estimated maximum number of entries that will be put in
      *            this map.
-     * @since Android 1.0
      */
     public IdentityHashMap(int maxSize) {
         if (maxSize >= 0) {
@@ -271,9 +267,19 @@
     }
 
     private int computeElementArraySize() {
-        return (int) (((long) threshold * 10000) / loadFactor) * 2;
+        int arraySize = (int) (((long) threshold * 10000) / loadFactor) * 2;
+        // ensure arraySize is positive, the above cast from long to int type
+        // leads to overflow and negative arraySize if threshold is too big
+        return arraySize < 0 ? -arraySize : arraySize;
     }
 
+    /**
+     * Create a new element array
+     * 
+     * @param s
+     *            the number of elements
+     * @return Reference to the element array
+     */
     private Object[] newElementArray(int s) {
         return new Object[s];
     }
@@ -283,7 +289,6 @@
      * 
      * @param map
      *            A map of (key,value) pairs to copy into the IdentityHashMap.
-     * @since Android 1.0
      */
     public IdentityHashMap(Map<? extends K, ? extends V> map) {
         this(map.size() < 6 ? 11 : map.size() * 2);
@@ -300,7 +305,6 @@
      * 
      * @see #isEmpty()
      * @see #size()
-     * @since Android 1.0
      */
     @Override
     public void clear() {
@@ -318,7 +322,6 @@
      *            the key to search for.
      * @return {@code true} if this map contains the specified key,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean containsKey(Object key) {
@@ -337,7 +340,6 @@
      *            the value to search for.
      * @return {@code true} if this map contains the specified value,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean containsValue(Object value) {
@@ -359,7 +361,6 @@
      * @param key
      *            the key.
      * @return the value of the mapping with the specified key.
-     * @since Android 1.0
      */
     @Override
     public V get(Object key) {
@@ -390,6 +391,10 @@
         return null;
     }
 
+    /**
+     * Convenience method for getting the IdentityHashMapEntry without the
+     * NULL_OBJECT elements
+     */
     @SuppressWarnings("unchecked")
     private IdentityHashMapEntry<K, V> getEntry(int index) {
         Object key = elementData[index];
@@ -405,6 +410,10 @@
         return new IdentityHashMapEntry<K, V>((K) key, (V) value);
     }
 
+    /**
+     * Returns the index where the key is found at, or the index of the next
+     * empty spot if the key is not found in this table.
+     */
     private int findIndex(Object key, Object[] array) {
         int length = array.length;
         int index = getModuloHash(key, length);
@@ -435,7 +444,6 @@
      *            the value.
      * @return the value of any previous mapping with the specified key or
      *         {@code null} if there was no such mapping.
-     * @since Android 1.0
      */
     @Override
     public V put(K key, V value) {
@@ -478,7 +486,8 @@
      * 
      * @param map
      *            the map to copy mappings from.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code map} is {@code null}.
      */
     @Override
     public void putAll(Map<? extends K, ? extends V> map) {
@@ -515,7 +524,6 @@
      *            the key of the mapping to remove.
      * @return the value of the removed mapping, or {@code null} if no mapping
      *         for the specified key was found.
-     * @since Android 1.0
      */
     @Override
     public V remove(Object key) {
@@ -575,7 +583,6 @@
      * changes in one will be reflected in the other.
      * 
      * @return a set of the mappings.
-     * @since Android 1.0
      */
     @Override
     public Set<Map.Entry<K, V>> entrySet() {
@@ -588,7 +595,6 @@
      * support adding.
      * 
      * @return a set of the keys.
-     * @since Android 1.0
      */
     @Override
     public Set<K> keySet() {
@@ -643,16 +649,13 @@
      * "wrapper object" over the iterator of map's entrySet(). The {@code size}
      * method wraps the map's size method and the {@code contains} method wraps
      * the map's containsValue method.
-     * </p>
      * <p>
      * The collection is created when this method is called for the first time
      * and returned in response to all subsequent calls. This method may return
      * different collections when multiple concurrent calls occur, since no
      * synchronization is performed.
-     * </p>
      * 
      * @return a collection of the values contained in this map.
-     * @since Android 1.0
      */
     @Override
     public Collection<V> values() {
@@ -710,7 +713,6 @@
      * @param object
      *            the object to compare to.
      * @return whether the argument object is equal to this object.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -745,12 +747,16 @@
      * 
      * @return a shallow copy of this IdentityHashMap.
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
         try {
-            return super.clone();
+            IdentityHashMap<K, V> cloneHashMap = (IdentityHashMap<K, V>) super
+                    .clone();
+            cloneHashMap.elementData = newElementArray(elementData.length);
+            System.arraycopy(elementData, 0, cloneHashMap.elementData, 0,
+                    elementData.length);
+            return cloneHashMap;
         } catch (CloneNotSupportedException e) {
             return null;
         }
@@ -762,7 +768,6 @@
      * @return {@code true} if this IdentityHashMap has no elements,
      *         {@code false} otherwise.
      * @see #size()
-     * @since Android 1.0
      */
     @Override
     public boolean isEmpty() {
@@ -773,7 +778,6 @@
      * Returns the number of mappings in this IdentityHashMap.
      * 
      * @return the number of mappings in this IdentityHashMap.
-     * @since Android 1.0
      */
     @Override
     public int size() {
diff --git a/libcore/luni/src/main/java/java/util/IllegalFormatCodePointException.java b/libcore/luni/src/main/java/java/util/IllegalFormatCodePointException.java
index e04eeba..c0d6b6f 100644
--- a/libcore/luni/src/main/java/java/util/IllegalFormatCodePointException.java
+++ b/libcore/luni/src/main/java/java/util/IllegalFormatCodePointException.java
@@ -24,7 +24,6 @@
  * passed as a parameter to a Formatter.
  * 
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class IllegalFormatCodePointException extends IllegalFormatException
         implements Serializable {
diff --git a/libcore/luni/src/main/java/java/util/IllegalFormatConversionException.java b/libcore/luni/src/main/java/java/util/IllegalFormatConversionException.java
index 769381b..696f4f2 100644
--- a/libcore/luni/src/main/java/java/util/IllegalFormatConversionException.java
+++ b/libcore/luni/src/main/java/java/util/IllegalFormatConversionException.java
@@ -23,7 +23,8 @@
  * is incompatible with the corresponding format specifier.
  * 
  * @see java.lang.RuntimeException
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public class IllegalFormatConversionException extends IllegalFormatException
         implements Serializable {
diff --git a/libcore/luni/src/main/java/java/util/IllegalFormatException.java b/libcore/luni/src/main/java/java/util/IllegalFormatException.java
index 2c1f2d7..3d37cd0 100644
--- a/libcore/luni/src/main/java/java/util/IllegalFormatException.java
+++ b/libcore/luni/src/main/java/java/util/IllegalFormatException.java
@@ -24,7 +24,6 @@
  * allowed to be instantiated.
  * 
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class IllegalFormatException extends IllegalArgumentException implements
         Serializable {
diff --git a/libcore/luni/src/main/java/java/util/IllegalFormatFlagsException.java b/libcore/luni/src/main/java/java/util/IllegalFormatFlagsException.java
index 6b27c74..4fa2d9c 100644
--- a/libcore/luni/src/main/java/java/util/IllegalFormatFlagsException.java
+++ b/libcore/luni/src/main/java/java/util/IllegalFormatFlagsException.java
@@ -23,7 +23,6 @@
  * the format flags is illegal.
  * 
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class IllegalFormatFlagsException extends IllegalFormatException
         implements Serializable {
diff --git a/libcore/luni/src/main/java/java/util/IllegalFormatPrecisionException.java b/libcore/luni/src/main/java/java/util/IllegalFormatPrecisionException.java
index 6ccf5d2..5d5113f 100644
--- a/libcore/luni/src/main/java/java/util/IllegalFormatPrecisionException.java
+++ b/libcore/luni/src/main/java/java/util/IllegalFormatPrecisionException.java
@@ -21,7 +21,6 @@
  * a negative other than -1 or in other cases where precision is not supported.
  * 
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 
 public class IllegalFormatPrecisionException extends IllegalFormatException {
diff --git a/libcore/luni/src/main/java/java/util/IllegalFormatWidthException.java b/libcore/luni/src/main/java/java/util/IllegalFormatWidthException.java
index 8348ec7..01904f8 100644
--- a/libcore/luni/src/main/java/java/util/IllegalFormatWidthException.java
+++ b/libcore/luni/src/main/java/java/util/IllegalFormatWidthException.java
@@ -22,7 +22,6 @@
  * supported.
  * 
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class IllegalFormatWidthException extends IllegalFormatException {
 
diff --git a/libcore/luni/src/main/java/java/util/InputMismatchException.java b/libcore/luni/src/main/java/java/util/InputMismatchException.java
index 0fc5385..eed0b83 100644
--- a/libcore/luni/src/main/java/java/util/InputMismatchException.java
+++ b/libcore/luni/src/main/java/java/util/InputMismatchException.java
@@ -24,13 +24,12 @@
  * 
  * @see Scanner
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class InputMismatchException extends NoSuchElementException implements
         Serializable {
 
-    static final long serialVersionUID = 8811230760997066428L;
-    
+    private static final long serialVersionUID = 8811230760997066428L;
+
     /**
      * Constructs a new {@code InputMismatchException} with the current stack
      * trace filled in.
diff --git a/libcore/luni/src/main/java/java/util/InvalidPropertiesFormatException.java b/libcore/luni/src/main/java/java/util/InvalidPropertiesFormatException.java
index 4e8a3e3..015c3d0 100644
--- a/libcore/luni/src/main/java/java/util/InvalidPropertiesFormatException.java
+++ b/libcore/luni/src/main/java/java/util/InvalidPropertiesFormatException.java
@@ -30,8 +30,6 @@
  * Even though this Exception inherits the {@code Serializable} interface, it is not
  * serializable. The methods used for serialization throw
  * {@code NotSerializableException}s.
- * 
- * @since Android 1.0
  */
 public class InvalidPropertiesFormatException extends IOException {
     
diff --git a/libcore/luni/src/main/java/java/util/Iterator.java b/libcore/luni/src/main/java/java/util/Iterator.java
index 9f20dc5..6ebae04 100644
--- a/libcore/luni/src/main/java/java/util/Iterator.java
+++ b/libcore/luni/src/main/java/java/util/Iterator.java
@@ -17,17 +17,18 @@
 
 package java.util;
 
-
 /**
- * An Iterator is used to sequence over a collection of objects. Conceptual, an
- * iterator is always positioned between two elements of a collection. A fresh
- * iterator is always positioned in front of the first element.
+ * An {@code Iterator} is used to sequence over a collection of objects.
+ * Conceptually, an iterator is always positioned between two elements of a
+ * collection. A fresh iterator is always positioned in front of the first
+ * element.
  * 
  * If a collection has been changed since its creation, methods {@code next} and
  * {@code hasNext()} may throw a {@code ConcurrentModificationException}.
  * Iterators with this behavior are called fail-fast iterators.
  * 
- * @since Android 1.0
+ * @param <E>
+ *            the type of object returned by the iterator.
  */
 public interface Iterator<E> {
     /**
@@ -36,7 +37,6 @@
      * 
      * @return {@code true} if there are more elements, {@code false} otherwise.
      * @see #next
-     * @since Android 1.0
      */
     public boolean hasNext();
 
@@ -48,7 +48,6 @@
      * @throws NoSuchElementException
      *             if there are no more elements.
      * @see #hasNext
-     * @since Android 1.0
      */
     public E next();
 
@@ -62,7 +61,6 @@
      * @throws IllegalStateException
      *             if {@code next} has not been called, or {@code remove} has
      *             already been called after the last call to {@code next}.
-     * @since Android 1.0
      */
     public void remove();
 }
diff --git a/libcore/luni/src/main/java/java/util/LinkedHashMap.java b/libcore/luni/src/main/java/java/util/LinkedHashMap.java
index a32a28b..cd6825b 100644
--- a/libcore/luni/src/main/java/java/util/LinkedHashMap.java
+++ b/libcore/luni/src/main/java/java/util/LinkedHashMap.java
@@ -1,10 +1,10 @@
 /*
  *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
+ *  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
+ *  the License. You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
@@ -15,8 +15,11 @@
  *  limitations under the License.
  */
 
-package java.util;
+// BEGIN android-note
+// Completely different implementation from harmony.  Runs much faster.
+// BEGIN android-note
 
+package java.util;
 
 /**
  * LinkedHashMap is a variant of HashMap. Its entries are kept in a
@@ -46,73 +49,68 @@
  * elements during iteration. It is not possible to guarantee that this
  * mechanism works in all cases of unsynchronized concurrent modification. It
  * should only be used for debugging purposes.
- * 
- * @since Android 1.0
  */
 public class LinkedHashMap<K, V> extends HashMap<K, V> {
 
-    private static final long serialVersionUID = 3801124242820219131L;
+    /**
+     * A dummy entry in the circular linked list of entries in the map.
+     * The first real entry is header.nxt, and the last is header.prv.
+     * If the map is empty, header.nxt == header && header.prv == header.
+     */
+    transient LinkedEntry<K, V> header;
 
+    /**
+     * True if access ordered, false if insertion ordered.
+     */
     private final boolean accessOrder;
 
-    transient private LinkedHashMapEntry<K, V> head, tail;
-
     /**
      * Constructs a new empty {@code LinkedHashMap} instance.
-     * 
-     * @since Android 1.0
      */
     public LinkedHashMap() {
         super();
+        init();
         accessOrder = false;
-        head = null;
     }
 
     /**
      * Constructs a new {@code LinkedHashMap} instance with the specified
      * capacity.
-     * 
-     * @param s
+     *
+     * @param initialCapacity
      *            the initial capacity of this map.
      * @exception IllegalArgumentException
      *                when the capacity is less than zero.
-     * @since Android 1.0
      */
-    public LinkedHashMap(int s) {
-        super(s);
-        accessOrder = false;
-        head = null;
+    public LinkedHashMap(int initialCapacity) {
+        this(initialCapacity, DEFAULT_LOAD_FACTOR);
     }
 
     /**
      * Constructs a new {@code LinkedHashMap} instance with the specified
      * capacity and load factor.
-     * 
-     * @param s
+     *
+     * @param initialCapacity
      *            the initial capacity of this map.
-     * @param lf
+     * @param loadFactor
      *            the initial load factor.
      * @throws IllegalArgumentException
      *             when the capacity is less than zero or the load factor is
      *             less or equal to zero.
-     * @since Android 1.0
      */
-    public LinkedHashMap(int s, float lf) {
-        super(s, lf);
-        accessOrder = false;
-        head = null;
-        tail = null;
+    public LinkedHashMap(int initialCapacity, float loadFactor) {
+        this(initialCapacity, loadFactor, false);
     }
 
     /**
      * Constructs a new {@code LinkedHashMap} instance with the specified
      * capacity, load factor and a flag specifying the ordering behavior.
-     * 
-     * @param s
+     *
+     * @param initialCapacity
      *            the initial capacity of this hash map.
-     * @param lf
+     * @param loadFactor
      *            the initial load factor.
-     * @param order
+     * @param accessOrder
      *            {@code true} if the ordering should be done based on the last
      *            access (from least-recently accessed to most-recently
      *            accessed), and {@code false} if the ordering should be the
@@ -120,536 +118,277 @@
      * @throws IllegalArgumentException
      *             when the capacity is less than zero or the load factor is
      *             less or equal to zero.
-     * @since Android 1.0
      */
-    public LinkedHashMap(int s, float lf, boolean order) {
-        super(s, lf);
-        accessOrder = order;
-        head = null;
-        tail = null;
+    public LinkedHashMap(
+            int initialCapacity, float loadFactor, boolean accessOrder) {
+        super(initialCapacity, loadFactor);
+        init();
+        this.accessOrder = accessOrder;
     }
 
     /**
      * Constructs a new {@code LinkedHashMap} instance containing the mappings
      * from the specified map. The order of the elements is preserved.
-     * 
-     * @param m
+     *
+     * @param map
      *            the mappings to add.
-     * @since Android 1.0
      */
-    public LinkedHashMap(Map<? extends K, ? extends V> m) {
-        accessOrder = false;
-        head = null;
-        tail = null;
-        putAll(m);
+    public LinkedHashMap(Map<? extends K, ? extends V> map) {
+        this(capacityForInitSize(map.size()));
+        constructorPutAll(map);
     }
 
-    static final class LinkedHashIterator<E, KT, VT> extends HashMapIterator<E, KT, VT> {
-        LinkedHashIterator(MapEntry.Type<E, KT, VT> value, LinkedHashMap<KT, VT> hm) {
-            super(value, hm);
-            entry = hm.head;
+    @Override void init() {
+        header = new LinkedEntry<K, V>();
+    }
+
+    /**
+     * LinkedEntry adds nxt/prv double-links to plain HashMapEntry.
+     */
+    static class LinkedEntry<K, V> extends HashMapEntry<K, V> {
+        LinkedEntry<K, V> nxt;
+        LinkedEntry<K, V> prv;
+
+        /** Create the header entry */
+        LinkedEntry() {
+            super(null, null, 0, null);
+            nxt = prv = this;
         }
 
-        @Override
-        public boolean hasNext() {
-            return (entry != null);
-        }
-
-        @Override
-        public E next() {
-            checkConcurrentMod();
-            if (!hasNext()) {
-                throw new NoSuchElementException();
-            }
-            E result = type.get(entry);
-            lastEntry = entry;
-            entry = ((LinkedHashMapEntry<KT, VT>)entry).chainForward;
-            canRemove = true;
-            return result;
-        }
-
-        @Override
-        public void remove() {
-            checkConcurrentMod();
-            if (!canRemove) {
-                throw new IllegalStateException();
-            }
-
-            canRemove = false;
-            associatedMap.modCount++;
-
-            int index = (lastEntry.key == null)? 0 : (lastEntry.key.hashCode() & 0x7FFFFFFF) % associatedMap.elementData.length;
-            LinkedHashMapEntry<KT, VT> m = (LinkedHashMapEntry<KT, VT>) associatedMap.elementData[index];
-            if (m == lastEntry) {
-                associatedMap.elementData[index] = lastEntry.next;
-            } else {
-                while (m.next != null) {
-                    if (m.next == lastEntry) {
-                        break;
-                    }
-                    m = (LinkedHashMapEntry<KT, VT>) m.next;
-                }
-                // assert m.next == entry
-                m.next = lastEntry.next;
-            }
-            LinkedHashMapEntry<KT, VT> lhme = (LinkedHashMapEntry<KT, VT>) lastEntry;
-            LinkedHashMapEntry<KT, VT> p = lhme.chainBackward;
-            LinkedHashMapEntry<KT, VT> n = lhme.chainForward;
-            LinkedHashMap<KT, VT> lhm = (LinkedHashMap<KT, VT>) associatedMap;
-            if (p != null) {
-                p.chainForward = n;
-                if (n != null) {
-                    n.chainBackward = p;
-                } else {
-                    lhm.tail = p;
-                }
-            } else {
-                lhm.head = n;
-                if (n != null) {
-                    n.chainBackward = null;
-                } else {
-                    lhm.tail = null;
-                }
-            }
-            associatedMap.elementCount--;
-            expectedModCount++;
+        /** Create a normal entry */
+        LinkedEntry(K key, V value, int hash, HashMapEntry<K, V> next,
+                    LinkedEntry<K, V> nxt, LinkedEntry<K, V> prv) {
+            super(key, value, hash, next);
+            this.nxt = nxt;
+            this.prv = prv;
         }
     }
 
-    static final class LinkedHashMapEntrySet<KT, VT> extends HashMapEntrySet<KT, VT> {
-        public LinkedHashMapEntrySet(LinkedHashMap<KT, VT> lhm) {
-            super(lhm);
+    /**
+     * Evicts eldest entry if instructed, creates a new entry and links it in
+     * as head of linked list. This method should call constructorNewEntry
+     * (instead of duplicating code) if the performance of your VM permits.
+     *
+     * <p>It may seem strange that this method is tasked with adding the entry
+     * to the hash table (which is properly the province of our superclass).
+     * The alternative of passing the "next" link in to this method and
+     * returning the newly created element does not work! If we remove an
+     * (eldest) entry that happens to be the first entry in the same bucket
+     * as the newly created entry, the "next" link would become invalid, and
+     * the resulting hash table corrupt.
+     */
+    @Override void addNewEntry(K key, V value, int hash, int index) {
+        LinkedEntry<K, V> header = this.header;
+
+        // Remove eldest entry if instructed to do so.
+        LinkedEntry<K, V> eldest = header.nxt;
+        if (eldest != header && removeEldestEntry(eldest)) {
+            remove(eldest.key);
         }
 
-        @Override
-        public Iterator<Map.Entry<KT,VT>> iterator() {
-            return new LinkedHashIterator<Map.Entry<KT,VT>,KT,VT>(new MapEntry.Type<Map.Entry<KT,VT>, KT, VT>() {
-                public Map.Entry<KT,VT> get(MapEntry<KT,VT> entry) {
-                    return entry;
-                }
-            }, (LinkedHashMap<KT, VT>) hashMap());
-        }
+        // Create new entry, link it on to list, and put it into table
+        LinkedEntry<K, V> oldTail = header.prv;
+        LinkedEntry<K, V> newTail = new LinkedEntry<K,V>(
+                key, value, hash, table[index], header, oldTail);
+        table[index] = oldTail.nxt = header.prv = newTail;
     }
 
-    static final class LinkedHashMapEntry<K, V> extends Entry<K, V> {
-        LinkedHashMapEntry<K, V> chainForward, chainBackward;
+    @Override void addNewEntryForNullKey(V value) {
+        LinkedEntry<K, V> header = this.header;
 
-        LinkedHashMapEntry(K theKey, V theValue) {
-            super(theKey, theValue);
-            chainForward = null;
-            chainBackward = null;
+        // Remove eldest entry if instructed to do so.
+        LinkedEntry<K, V> eldest = header.nxt;
+        if (eldest != header && removeEldestEntry(eldest)) {
+            remove(eldest.key);
         }
 
-        LinkedHashMapEntry(K theKey, int hash) {
-            super(theKey, hash);
-            chainForward = null;
-            chainBackward = null;
-        }
-
-
-        @Override
-        @SuppressWarnings("unchecked")
-        public Object clone() {
-            LinkedHashMapEntry<K, V> entry = (LinkedHashMapEntry<K, V>) super.clone();
-            entry.chainBackward = chainBackward;
-            entry.chainForward = chainForward;
-            LinkedHashMapEntry<K, V> lnext = (LinkedHashMapEntry<K, V>) entry.next;
-            if (lnext != null) {
-                entry.next = (LinkedHashMapEntry<K, V>) lnext.clone();
-            }
-            return entry;
-        }
+        // Create new entry, link it on to list, and put it into table
+        LinkedEntry<K, V> oldTail = header.prv;
+        LinkedEntry<K, V> newTail = new LinkedEntry<K,V>(
+                null, value, 0, null, header, oldTail);
+        entryForNullKey = oldTail.nxt = header.prv = newTail;
     }
 
-    @Override
-    @SuppressWarnings("unchecked")
-    Entry<K, V>[] newElementArray(int s) {
-        return new LinkedHashMapEntry[s];
+    /**
+     * As above, but without eviction.
+     */
+    @Override HashMapEntry<K, V> constructorNewEntry(
+            K key, V value, int hash, HashMapEntry<K, V> next) {
+        LinkedEntry<K, V> header = this.header;
+        LinkedEntry<K, V> oldTail = header.prv;
+        LinkedEntry<K, V> newTail
+                = new LinkedEntry<K,V>(key, value, hash, next, header, oldTail);
+        return oldTail.nxt = header.prv = newTail;
     }
 
     /**
      * Returns the value of the mapping with the specified key.
-     * 
+     *
      * @param key
      *            the key.
      * @return the value of the mapping with the specified key, or {@code null}
      *         if no mapping for the specified key is found.
-     * @since Android 1.0
      */
-    @Override
-    public V get(Object key) {
-        LinkedHashMapEntry<K, V> m;
+    @Override public V get(Object key) {
+        /*
+         * This method is overridden to eliminate the need for a polymorphic
+         * invocation in superclass at the expense of code duplication.
+         */
         if (key == null) {
-            m = (LinkedHashMapEntry<K, V>)findNullKeyEntry();
-        } else {
-            int hash = key.hashCode();
-            int index = (hash & 0x7FFFFFFF) % elementData.length;
-            m = (LinkedHashMapEntry<K, V>)findNonNullKeyEntry(key, index, hash);
+            HashMapEntry<K, V> e = entryForNullKey;
+            if (e == null)
+                return null;
+            if (accessOrder)
+                makeTail((LinkedEntry<K, V>) e);
+            return e.value;
         }
-        if (m == null) {
-            return null;
-        }
-        if (accessOrder && tail != m) {
-            // BEGIN android-added
-            modCount++;
-            // END android-added
-            LinkedHashMapEntry<K, V> p = m.chainBackward;
-            LinkedHashMapEntry<K, V> n = m.chainForward;
-            n.chainBackward = p;
-            if (p != null) {
-                p.chainForward = n;
-            } else {
-                head = n;
+
+        // Doug Lea's supplemental secondaryHash function (inlined)
+        int hash = key.hashCode();
+        hash ^= (hash >>> 20) ^ (hash >>> 12);
+        hash ^= (hash >>> 7) ^ (hash >>> 4);
+
+        HashMapEntry<K, V>[] tab = table;
+        for (HashMapEntry<K, V> e = tab[hash & (tab.length - 1)];
+                e != null; e = e.next) {
+            K eKey = e.key;
+            if (eKey == key || (e.hash == hash && key.equals(eKey))) {
+                if (accessOrder)
+                    makeTail((LinkedEntry<K, V>) e);
+                return e.value;
             }
-            m.chainForward = null;
-            m.chainBackward = tail;
-            tail.chainForward = m;
-            tail = m;
         }
-        return m.value;
+        return null;
     }
 
-    /*
-     * @param key @param index @return Entry
-     */
-    @Override
-    Entry<K, V> createEntry(K key, int index, V value) {
-        LinkedHashMapEntry<K, V> m = new LinkedHashMapEntry<K, V>(key, value);
-        m.next = elementData[index];
-        elementData[index] = m;
-        linkEntry(m);
-        return m;
-    }
-
-    Entry<K,V> createHashedEntry(K key, int index, int hash) {
-        LinkedHashMapEntry<K, V> m = new LinkedHashMapEntry<K, V>(key, hash);
-        m.next = elementData[index];
-        elementData[index] = m;
-        linkEntry(m);
-        return m;
-    }
-
-    // BEGIN android-changed
-    // copied from newer version of harmony
     /**
-     * Maps the specified key to the specified value.
-     * 
-     * @param key
-     *            the key.
-     * @param value
-     *            the value.
-     * @return the value of any previous mapping with the specified key or
-     *         {@code null} if there was no such mapping.
-     * @since Android 1.0
+     * Relinks the given entry to the tail of the list. Under access ordering,
+     * this method is invoked whenever the value of a  pre-existing entry is
+     * read by Map.get or modified by Map.put.
      */
-    @Override
-    public V put(K key, V value) {
-        V result = putImpl(key,value);
+    private void makeTail(LinkedEntry<K, V> e) {
+        // Unlink e
+        e.prv.nxt = e.nxt;
+        e.nxt.prv = e.prv;
 
-        if (removeEldestEntry(head)) {
-            remove(head.key);
-        }
-
-        return result;
+        // Relink e as tail
+        LinkedEntry<K, V> header = this.header;
+        LinkedEntry<K, V> oldTail = header.prv;
+        e.nxt = header;
+        e.prv = oldTail;
+        oldTail.nxt = header.prv = e;
+        modCount++;
     }
-    
-    V putImpl(K key, V value){
-        LinkedHashMapEntry<K, V> m;
-        if (elementCount == 0){
-            head = tail = null;
-        }
-        if (key == null) {
-            m = (LinkedHashMapEntry<K, V>)findNullKeyEntry();
-            if (m == null) {
-                modCount++;
-                // Check if we need to remove the oldest entry
-                // The check includes accessOrder since an accessOrder LinkedHashMap
-                // does not record
-                // the oldest member in 'head'.
-                if (++elementCount > threshold) {
-                    rehash();
-                }
-                    m = (LinkedHashMapEntry<K, V>) createHashedEntry(null, 0, 0);
-            } else {
-                linkEntry(m);
-            }
-        } else {
-            int hash = key.hashCode();
-            int index = (hash & 0x7FFFFFFF) % elementData.length;
-            m = (LinkedHashMapEntry<K, V>)findNonNullKeyEntry(key, index, hash);
-            if (m == null) {
-                modCount++;
-                if (++elementCount > threshold) {
-                    rehash();
-                    index = (hash & 0x7FFFFFFF) % elementData.length;
-                }
-                m = (LinkedHashMapEntry<K, V>) createHashedEntry(key, index, hash);
-            } else {
-                linkEntry(m);
-            }
-        }
 
-        V result = m.value;
-        m.value = value;
-        return result;
-    }
-    // END android-changed
-
-    /*
-     * @param m
-     */
-    void linkEntry(LinkedHashMapEntry<K, V> m) {
-        if (tail == m) {
-            return;
-        }
-
-        if (head == null) {
-            // Check if the map is empty
-            head = tail = m;
-            return;
-        }
-
-        // we need to link the new entry into either the head or tail
-        // of the chain depending on if the LinkedHashMap is accessOrder or not
-        LinkedHashMapEntry<K, V> p = m.chainBackward;
-        LinkedHashMapEntry<K, V> n = m.chainForward;
-        if (p == null) {
-            if (n != null) {
-                // The entry must be the head but not the tail
-                if (accessOrder) {
-                    head = n;
-                    n.chainBackward = null;
-                    m.chainBackward = tail;
-                    m.chainForward = null;
-                    tail.chainForward = m;
-                    tail = m;
-                }
-            } else {
-                // This is a new entry
-                m.chainBackward = tail;
-                m.chainForward = null;
-                tail.chainForward = m;
-                tail = m;
-            }
-            return;
-        }
-
-        if (n == null) {
-            // The entry must be the tail so we can't get here
-            return;
-        }
-
-        // The entry is neither the head nor tail
+    @Override void preModify(HashMapEntry<K, V> e) {
         if (accessOrder) {
-            p.chainForward = n;
-            n.chainBackward = p;
-            m.chainForward = null;
-            m.chainBackward = tail;
-            tail.chainForward = m;
-            tail = m;
+            makeTail((LinkedEntry<K, V>) e);
         }
+    }
 
+    @Override void postRemove(HashMapEntry<K, V> e) {
+        LinkedEntry<K, V> le = (LinkedEntry<K, V>) e;
+        le.prv.nxt = le.nxt;
+        le.nxt.prv = le.prv;
+        le.nxt = le.prv = null; // Help the GC (for performance)
     }
 
     /**
-     * Returns a set containing all of the mappings in this map. Each mapping is
-     * an instance of {@link Map.Entry}. As the set is backed by this map,
-     * changes in one will be reflected in the other.
-     * 
-     * @return a set of the mappings.
-     * @since Android 1.0
+     * This override is done for LinkedHashMap performance: iteration is cheaper
+     * via LinkedHashMap nxt links.
      */
-    @Override
-    public Set<Map.Entry<K, V>> entrySet() {
-        return new LinkedHashMapEntrySet<K, V>(this);
-    }
-
-    /**
-     * Returns a set of the keys contained in this map. The set is backed by
-     * this map so changes to one are reflected by the other. The set does not
-     * support adding.
-     * 
-     * @return a set of the keys.
-     * @since Android 1.0
-     */
-    @Override
-    public Set<K> keySet() {
-        if (keySet == null) {
-            keySet = new AbstractSet<K>() {
-                @Override
-                public boolean contains(Object object) {
-                    return containsKey(object);
+    @Override public boolean containsValue(Object value) {
+        if (value == null) {
+            for (LinkedEntry<K, V> header = this.header, e = header.nxt;
+                    e != header; e = e.nxt) {
+                if (e.value == null) {
+                    return true;
                 }
-
-                @Override
-                public int size() {
-                    return LinkedHashMap.this.size();
-                }
-
-                @Override
-                public void clear() {
-                    LinkedHashMap.this.clear();
-                }
-
-                @Override
-                public boolean remove(Object key) {
-                    if (containsKey(key)) {
-                        LinkedHashMap.this.remove(key);
-                        return true;
-                    }
-                    return false;
-                }
-
-                @Override
-                public Iterator<K> iterator() {
-                    return new LinkedHashIterator<K,K,V>(new MapEntry.Type<K,K,V>() {
-                        public K get(MapEntry<K,V> entry) {
-                            return entry.key;
-                        }
-                    }, LinkedHashMap.this);
-                }
-            };
+            }
+            return false;
         }
-        return keySet;
-    }
 
-    /**
-     * Returns a collection of the values contained in this map. The collection
-     * is backed by this map so changes to one are reflected by the other. The
-     * collection supports remove, removeAll, retainAll and clear operations,
-     * and it does not support add or addAll operations.
-     * <p>
-     * This method returns a collection which is the subclass of
-     * AbstractCollection. The iterator method of this subclass returns a
-     * "wrapper object" over the iterator of map's entrySet(). The size method
-     * wraps the map's size method and the contains method wraps the map's
-     * containsValue method.
-     * </p>
-     * <p>
-     * The collection is created when this method is called for the first time
-     * and returned in response to all subsequent calls. This method may return
-     * different collections when multiple concurrent calls occur, since no
-     * synchronization is performed.
-     * </p>
-     * 
-     * @return a collection of the values contained in this map.
-     * @since Android 1.0
-     */
-    @Override
-    public Collection<V> values() {
-        if (valuesCollection == null) {
-            valuesCollection = new AbstractCollection<V>() {
-                @Override
-                public boolean contains(Object object) {
-                    return containsValue(object);
-                }
-
-                @Override
-                public int size() {
-                    return LinkedHashMap.this.size();
-                }
-
-                @Override
-                public void clear() {
-                    LinkedHashMap.this.clear();
-                }
-
-                @Override
-                public Iterator<V> iterator() {
-                    return new LinkedHashIterator<V,K,V>(new MapEntry.Type<V,K,V>() {
-                        public V get(MapEntry<K,V> entry) {
-                            return entry.value;
-                        }
-                    }, LinkedHashMap.this);
-                }
-            };
+        // value is non-null
+        for (LinkedEntry<K, V> header = this.header, e = header.nxt;
+                e != header; e = e.nxt) {
+            if (value.equals(e.value)) {
+                return true;
+            }
         }
-        return valuesCollection;
-    }
-
-    /**
-     * Removes the mapping with the specified key from this map.
-     * 
-     * @param key
-     *            the key of the mapping to remove.
-     * @return the value of the removed mapping or {@code null} if no mapping
-     *         for the specified key was found.
-     * @since Android 1.0
-     */
-    @Override
-    public V remove(Object key) {
-        LinkedHashMapEntry<K, V> m = (LinkedHashMapEntry<K, V>) removeEntry(key);
-        if (m == null) {
-            return null;
-        }
-        LinkedHashMapEntry<K, V> p = m.chainBackward;
-        LinkedHashMapEntry<K, V> n = m.chainForward;
-        if (p != null) {
-            p.chainForward = n;
-        } else {
-            head = n;
-        }
-        if (n != null) {
-            n.chainBackward = p;
-        } else {
-            tail = p;
-        }
-        return m.value;
-    }
-
-    /**
-     * This method is queried from the put and putAll methods to check if the
-     * eldest member of the map should be deleted before adding the new member.
-     * If this map was created with accessOrder = true, then the result of
-     * removeEldestEntry is assumed to be false.
-     * 
-     * @param eldest
-     *            the entry to check if it should be removed.
-     * @return {@code true} if the eldest member should be removed.
-     * @since Android 1.0
-     */
-    protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
         return false;
     }
 
-    // BEGIN android-changed
-    /**
-     * Removes all elements from this map, leaving it empty.
-     * 
-     * @see #isEmpty()
-     * @see #size()
-     * @since Android 1.0
-     */
-    @Override
     public void clear() {
-        internalClear();
+        super.clear();
+
+        // Clear all links to help GC
+        LinkedEntry<K, V> header = this.header;
+        for (LinkedEntry<K, V> e = header.nxt; e != header; ) {
+            LinkedEntry<K, V> nxt = e.nxt;
+            e.nxt = e.prv = null;
+            e = nxt;
+        }
+
+        header.nxt = header.prv = header;
     }
 
-    @Override
-    void internalClear() {
-        super.internalClear();
-        head = tail = null;
-    }
-    // END android-changed
+    private abstract class LinkedHashIterator<T> implements Iterator<T> {
+        LinkedEntry<K, V> next = header.nxt;
+        LinkedEntry<K, V> lastReturned = null;
+        int expectedModCount = modCount;
 
-    // BEGIN android-removed
-    // copied from newer version of harmony
-    // /**
-    //  * Answers a new HashMap with the same mappings and size as this HashMap.
-    //  * 
-    //  * @return a shallow copy of this HashMap
-    //  * 
-    //  * @see java.lang.Cloneable
-    //  */
-    // @Override
-    // @SuppressWarnings("unchecked")
-    // public Object clone() {
-    //     LinkedHashMap<K, V> map = (LinkedHashMap<K, V>) super.clone();
-    //     map.clear();
-    //     for (Map.Entry<K, V> entry : entrySet()) {
-    //         map.put(entry.getKey(), entry.getValue());
-    //     }
-    //     return map;
-    // }
-    // END android-removed
+        public final boolean hasNext() {
+            return next != header;
+        }
+
+        final LinkedEntry<K, V> nextEntry() {
+            if (modCount != expectedModCount)
+                throw new ConcurrentModificationException();
+            LinkedEntry<K, V> e = next;
+            if (e == header)
+                throw new NoSuchElementException();
+            next = e.nxt;
+            return lastReturned = e;
+        }
+
+        public final void remove() {
+            if (modCount != expectedModCount)
+                throw new ConcurrentModificationException();
+            if (lastReturned == null)
+                throw new IllegalStateException();
+            LinkedHashMap.this.remove(lastReturned.key);
+            lastReturned = null;
+            expectedModCount = modCount;
+        }
+    }
+
+    private final class KeyIterator extends LinkedHashIterator<K> {
+        public final K next() { return nextEntry().key; }
+    }
+
+    private final class ValueIterator extends LinkedHashIterator<V> {
+        public final V next() { return nextEntry().value; }
+    }
+
+    private final class EntryIterator
+            extends LinkedHashIterator<Map.Entry<K, V>> {
+        public final Map.Entry<K, V> next() { return nextEntry(); }
+    }
+
+    // Override view iterator methods to generate correct iteration order
+    @Override Iterator<K> newKeyIterator() {
+        return new KeyIterator();
+    }
+    @Override Iterator<V> newValueIterator() {
+        return new ValueIterator();
+    }
+    @Override Iterator<Map.Entry<K, V>> newEntryIterator() {
+        return new EntryIterator();
+    }
+
+    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
+        return false;
+    }
+
+    private static final long serialVersionUID = 3801124242820219131L;
 }
diff --git a/libcore/luni/src/main/java/java/util/LinkedHashSet.java b/libcore/luni/src/main/java/java/util/LinkedHashSet.java
index 943e01c..3add460 100644
--- a/libcore/luni/src/main/java/java/util/LinkedHashSet.java
+++ b/libcore/luni/src/main/java/java/util/LinkedHashSet.java
@@ -17,7 +17,6 @@
 
 package java.util;
 
-
 import java.io.Serializable;
 
 /**
@@ -30,18 +29,16 @@
  * Like HashSet, LinkedHashSet is not thread safe, so access by multiple threads
  * must be synchronized by an external mechanism such as
  * {@link Collections#synchronizedSet(Set)}.
- * 
- * @since Android 1.0
+ *
+ * @since 1.4
  */
 public class LinkedHashSet<E> extends HashSet<E> implements Set<E>, Cloneable,
         Serializable {
-    
+
     private static final long serialVersionUID = -2851667679971038690L;
 
     /**
      * Constructs a new empty instance of {@code LinkedHashSet}.
-     * 
-     * @since Android 1.0
      */
     public LinkedHashSet() {
         super(new LinkedHashMap<E, HashSet<E>>());
@@ -53,7 +50,6 @@
      * 
      * @param capacity
      *            the initial capacity of this {@code LinkedHashSet}.
-     * @since Android 1.0
      */
     public LinkedHashSet(int capacity) {
         super(new LinkedHashMap<E, HashSet<E>>(capacity));
@@ -67,7 +63,6 @@
      *            the initial capacity.
      * @param loadFactor
      *            the initial load factor.
-     * @since Android 1.0
      */
     public LinkedHashSet(int capacity, float loadFactor) {
         super(new LinkedHashMap<E, HashSet<E>>(capacity, loadFactor));
@@ -79,7 +74,6 @@
      * 
      * @param collection
      *            the collection of elements to add.
-     * @since Android 1.0
      */
     public LinkedHashSet(Collection<? extends E> collection) {
         super(new LinkedHashMap<E, HashSet<E>>(collection.size() < 6 ? 11
diff --git a/libcore/luni/src/main/java/java/util/LinkedList.java b/libcore/luni/src/main/java/java/util/LinkedList.java
index 7cfefe6..64326e3 100644
--- a/libcore/luni/src/main/java/java/util/LinkedList.java
+++ b/libcore/luni/src/main/java/java/util/LinkedList.java
@@ -17,7 +17,6 @@
 
 package java.util;
 
-
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
@@ -28,12 +27,12 @@
  * LinkedList is an implementation of List, backed by a linked list. All
  * optional operations (adding, removing and replacing) are supported. The
  * elements can be any objects.
- * 
- * @since Android 1.0
+ *
+ * @since 1.2
  */
 public class LinkedList<E> extends AbstractSequentialList<E> implements
         List<E>, Queue<E>, Cloneable, Serializable {
-    
+
     private static final long serialVersionUID = 876323262645176354L;
 
     transient int size = 0;
@@ -178,8 +177,6 @@
 
     /**
      * Constructs a new empty instance of {@code LinkedList}.
-     * 
-     * @since Android 1.0
      */
     public LinkedList() {
         voidLink = new Link<E>(null, null, null);
@@ -192,10 +189,9 @@
      * elements contained in the specified {@code collection}. The order of the
      * elements in this new {@code LinkedList} will be determined by the
      * iteration order of {@code collection}.
-     * 
+     *
      * @param collection
      *            the collection of elements to add.
-     * @since Android 1.0
      */
     public LinkedList(Collection<? extends E> collection) {
         this();
@@ -207,14 +203,13 @@
      * 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 LinkedList}, the object is added at the end.
-     * 
+     *
      * @param location
      *            the index at which to insert.
      * @param object
      *            the object to add.
      * @throws IndexOutOfBoundsException
      *             if {@code location < 0 || >= size()}
-     * @since Android 1.0
      */
     @Override
     public void add(int location, E object) {
@@ -242,11 +237,10 @@
 
     /**
      * Adds the specified object at the end of this {@code LinkedList}.
-     * 
+     *
      * @param object
      *            the object to add.
      * @return always true
-     * @since Android 1.0
      */
     @Override
     public boolean add(E object) {
@@ -264,7 +258,7 @@
      * Inserts the objects in the specified collection at the specified location
      * in this {@code LinkedList}. The objects are added in the order they are
      * returned from the collection's iterator.
-     * 
+     *
      * @param location
      *            the index at which to insert.
      * @param collection
@@ -277,7 +271,6 @@
      *             if an object cannot be added to this list.
      * @throws IndexOutOfBoundsException
      *             if {@code location < 0 || > size()}
-     * @since Android 1.0
      */
     @Override
     public boolean addAll(int location, Collection<? extends E> collection) {
@@ -288,6 +281,9 @@
         if (adding == 0) {
             return false;
         }
+        Collection<? extends E> elements = (collection == this) ?
+                new ArrayList<E>(collection) : collection;
+
         Link<E> previous = voidLink;
         if (location < (size / 2)) {
             for (int i = 0; i < location; i++) {
@@ -299,7 +295,7 @@
             }
         }
         Link<E> next = previous.next;
-        for (E e : collection) {
+        for (E e : elements) {
             Link<E> newLink = new Link<E>(e, previous, null);
             previous.next = newLink;
             previous = newLink;
@@ -311,15 +307,13 @@
         return true;
     }
 
-
     /**
      * Adds the objects in the specified Collection to this {@code LinkedList}.
-     * 
+     *
      * @param collection
      *            the collection of objects.
      * @return {@code true} if this {@code LinkedList} is modified,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean addAll(Collection<? extends E> collection) {
@@ -327,8 +321,11 @@
         if (adding == 0) {
             return false;
         }
+        Collection<? extends E> elements = (collection == this) ?
+                new ArrayList<E>(collection) : collection;
+
         Link<E> previous = voidLink.previous;
-        for (E e : collection) {
+        for (E e : elements) {
             Link<E> newLink = new Link<E>(e, previous, null);
             previous.next = newLink;
             previous = newLink;
@@ -342,10 +339,9 @@
 
     /**
      * Adds the specified object at the beginning of this {@code LinkedList}.
-     * 
+     *
      * @param object
      *            the object to add.
-     * @since Android 1.0
      */
     public void addFirst(E object) {
         Link<E> oldFirst = voidLink.next;
@@ -358,10 +354,9 @@
 
     /**
      * Adds the specified object at the end of this {@code LinkedList}.
-     * 
+     *
      * @param object
      *            the object to add.
-     * @since Android 1.0
      */
     public void addLast(E object) {
         Link<E> oldLast = voidLink.previous;
@@ -374,10 +369,9 @@
 
     /**
      * Removes all elements from this {@code LinkedList}, leaving it empty.
-     * 
+     *
      * @see List#isEmpty
      * @see #size
-     * @since Android 1.0
      */
     @Override
     public void clear() {
@@ -392,10 +386,9 @@
     /**
      * Returns a new {@code LinkedList} with the same elements and size as this
      * {@code LinkedList}.
-     * 
+     *
      * @return a shallow copy of this {@code LinkedList}.
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     @Override
@@ -415,12 +408,11 @@
 
     /**
      * Searches this {@code LinkedList} for the specified object.
-     * 
+     *
      * @param object
      *            the object to search for.
      * @return {@code true} if {@code object} is an element of this
      *         {@code LinkedList}, {@code false} otherwise
-     * @since Android 1.0
      */
     @Override
     public boolean contains(Object object) {
@@ -463,11 +455,10 @@
 
     /**
      * Returns the first element in this {@code LinkedList}.
-     * 
+     *
      * @return the first element.
      * @throws NoSuchElementException
      *             if this {@code LinkedList} is empty.
-     * @since Android 1.0
      */
     public E getFirst() {
         Link<E> first = voidLink.next;
@@ -479,11 +470,10 @@
 
     /**
      * Returns the last element in this {@code LinkedList}.
-     * 
+     *
      * @return the last element
      * @throws NoSuchElementException
      *             if this {@code LinkedList} is empty
-     * @since Android 1.0
      */
     public E getLast() {
         Link<E> last = voidLink.previous;
@@ -520,12 +510,11 @@
     /**
      * Searches this {@code LinkedList} for the specified object and returns the
      * index of the last occurrence.
-     * 
+     *
      * @param object
      *            the object to search for
      * @return the index of the last occurrence of the object, or -1 if it was
      *         not found.
-     * @since Android 1.0
      */
     @Override
     public int lastIndexOf(Object object) {
@@ -555,14 +544,13 @@
      * Returns a ListIterator on the elements of this {@code LinkedList}. The
      * elements are iterated in the same order that they occur in the
      * {@code LinkedList}. The iteration starts at the specified location.
-     * 
+     *
      * @param location
      *            the index at which to start the iteration
      * @return a ListIterator on the elements of this {@code LinkedList}
      * @throws IndexOutOfBoundsException
      *             if {@code location < 0 || >= size()}
      * @see ListIterator
-     * @since Android 1.0
      */
     @Override
     public ListIterator<E> listIterator(int location) {
@@ -571,13 +559,12 @@
 
     /**
      * Removes the object at the specified location from this {@code LinkedList}.
-     * 
+     *
      * @param location
      *            the index of the object to remove
      * @return the removed object
      * @throws IndexOutOfBoundsException
      *             if {@code location < 0 || >= size()}
-     * @since Android 1.0
      */
     @Override
     public E remove(int location) {
@@ -629,11 +616,10 @@
 
     /**
      * Removes the first object from this {@code LinkedList}.
-     * 
+     *
      * @return the removed object.
      * @throws NoSuchElementException
      *             if this {@code LinkedList} is empty.
-     * @since Android 1.0
      */
     public E removeFirst() {
         Link<E> first = voidLink.next;
@@ -650,11 +636,10 @@
 
     /**
      * Removes the last object from this {@code LinkedList}.
-     * 
+     *
      * @return the removed object.
      * @throws NoSuchElementException
      *             if this {@code LinkedList} is empty.
-     * @since Android 1.0
      */
     public E removeLast() {
         Link<E> last = voidLink.previous;
@@ -672,7 +657,7 @@
     /**
      * Replaces the element at the specified location in this {@code LinkedList}
      * with the specified object.
-     * 
+     *
      * @param location
      *            the index at which to put the specified object.
      * @param object
@@ -684,7 +669,6 @@
      *             if an object cannot be added to this list.
      * @throws IndexOutOfBoundsException
      *             if {@code location < 0 || >= size()}
-     * @since Android 1.0
      */
     @Override
     public E set(int location, E object) {
@@ -708,15 +692,14 @@
 
     /**
      * Returns the number of elements in this {@code LinkedList}.
-     * 
+     *
      * @return the number of elements in this {@code LinkedList}.
-     * @since Android 1.0
      */
     @Override
     public int size() {
         return size;
     }
-    
+
     public boolean offer(E o) {
         add(o);
         return true;
@@ -742,9 +725,8 @@
     /**
      * Returns a new array containing all elements contained in this
      * {@code LinkedList}.
-     * 
+     *
      * @return an array of the elements from this {@code LinkedList}.
-     * @since Android 1.0
      */
     @Override
     public Object[] toArray() {
@@ -765,14 +747,13 @@
      * type is created. If the specified array is used and is larger than this
      * {@code LinkedList}, the array element following the collection elements
      * is set to null.
-     * 
+     *
      * @param contents
      *            the array.
      * @return an array of the elements from this {@code LinkedList}.
      * @throws ArrayStoreException
      *             if the type of an element in this {@code LinkedList} cannot
      *             be stored in the type of the specified array.
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
@@ -784,7 +765,7 @@
         }
         Link<E> link = voidLink.next;
         while (link != voidLink) {
-            contents[index++] = (T)link.data;
+            contents[index++] = (T) link.data;
             link = link.next;
         }
         if (index < contents.length) {
@@ -810,7 +791,7 @@
         voidLink = new Link<E>(null, null, null);
         Link<E> link = voidLink;
         for (int i = size; --i >= 0;) {
-            Link<E> nextLink = new Link<E>((E)stream.readObject(), link, null);
+            Link<E> nextLink = new Link<E>((E) stream.readObject(), link, null);
             link.next = nextLink;
             link = nextLink;
         }
diff --git a/libcore/luni/src/main/java/java/util/List.java b/libcore/luni/src/main/java/java/util/List.java
index d95b2d5..68e1ad9 100644
--- a/libcore/luni/src/main/java/java/util/List.java
+++ b/libcore/luni/src/main/java/java/util/List.java
@@ -23,8 +23,6 @@
  * element in the {@code List} has an index. Each element can thus be accessed by its
  * index, with the first index being zero. Normally, {@code List}s allow duplicate
  * elements, as compared to Sets, where elements have to be unique.
- * 
- * @since Android 1.0
  */
 public interface List<E> extends Collection<E> {
     /**
@@ -39,16 +37,15 @@
      *            the index at which to insert.
      * @param object
      *            the object to add.
-     * @exception UnsupportedOperationException
-     *                when adding to this {@code List} is not supported.
-     * @exception ClassCastException
-     *                when the class of the object is inappropriate for this
+     * @throws UnsupportedOperationException
+     *                if adding to this {@code List} is not supported.
+     * @throws ClassCastException
+     *                if the class of the object is inappropriate for this
      *                {@code List}.
-     * @exception IllegalArgumentException
-     *                when the object cannot be added to this {@code List}.
-     * @exception IndexOutOfBoundsException
-     *                when {@code location < 0 || location > size()}
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *                if the object cannot be added to this {@code List}.
+     * @throws IndexOutOfBoundsException
+     *                if {@code location < 0 || location > size()}
      */
     public void add(int location, E object);
 
@@ -58,14 +55,13 @@
      * @param object
      *            the object to add.
      * @return always true.
-     * @exception UnsupportedOperationException
-     *                when adding to this {@code List} is not supported.
-     * @exception ClassCastException
-     *                when the class of the object is inappropriate for this
+     * @throws UnsupportedOperationException
+     *                if adding to this {@code List} is not supported.
+     * @throws ClassCastException
+     *                if the class of the object is inappropriate for this
      *                {@code List}.
-     * @exception IllegalArgumentException
-     *                when the object cannot be added to this {@code List}.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *                if the object cannot be added to this {@code List}.
      */
     public boolean add(E object);
 
@@ -80,16 +76,15 @@
      *            the collection of objects to be inserted.
      * @return true if this {@code List} has been modified through the insertion, false
      *         otherwise (i.e. if the passed collection was empty).
-     * @exception UnsupportedOperationException
-     *                when adding to this {@code List} is not supported.
-     * @exception ClassCastException
-     *                when the class of an object is inappropriate for this
+     * @throws UnsupportedOperationException
+     *                if adding to this {@code List} is not supported.
+     * @throws ClassCastException
+     *                if the class of an object is inappropriate for this
      *                {@code List}.
-     * @exception IllegalArgumentException
-     *                when an object cannot be added to this {@code List}.
-     * @exception IndexOutOfBoundsException
-     *                when {@code location < 0 || > size()}
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *                if an object cannot be added to this {@code List}.
+     * @throws IndexOutOfBoundsException
+     *                if {@code location < 0 || > size()}
      */
     public boolean addAll(int location, Collection<? extends E> collection);
 
@@ -102,25 +97,23 @@
      *            the collection of objects.
      * @return {@code true} if this {@code List} is modified, {@code false} otherwise
      *         (i.e. if the passed collection was empty).
-     * @exception UnsupportedOperationException
-     *                when adding to this {@code List} is not supported.
-     * @exception ClassCastException
-     *                when the class of an object is inappropriate for this
+     * @throws UnsupportedOperationException
+     *                if adding to this {@code List} is not supported.
+     * @throws ClassCastException
+     *                if the class of an object is inappropriate for this
      *                {@code List}.
-     * @exception IllegalArgumentException
-     *                when an object cannot be added to this {@code List}.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *                if an object cannot be added to this {@code List}.
      */
     public boolean addAll(Collection<? extends E> collection);
 
     /**
      * Removes all elements from this {@code List}, leaving it empty.
      * 
-     * @exception UnsupportedOperationException
-     *                when removing from this {@code List} is not supported.
+     * @throws UnsupportedOperationException
+     *                if removing from this {@code List} is not supported.
      * @see #isEmpty
      * @see #size
-     * @since Android 1.0
      */
     public void clear();
 
@@ -131,7 +124,6 @@
      *            the object to search for.
      * @return {@code true} if object is an element of this {@code List}, {@code false}
      *         otherwise
-     * @since Android 1.0
      */
     public boolean contains(Object object);
 
@@ -143,7 +135,6 @@
      *            the collection of objects
      * @return {@code true} if all objects in the specified collection are
      *         elements of this {@code List}, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean containsAll(Collection<?> collection);
 
@@ -158,7 +149,6 @@
      * @return boolean {@code true} if the object is the same as this object,
      *         and {@code false} if it is different from this object.
      * @see #hashCode
-     * @since Android 1.0
      */
     public boolean equals(Object object);
 
@@ -168,9 +158,8 @@
      * @param location
      *            the index of the element to return.
      * @return the element at the specified location.
-     * @exception IndexOutOfBoundsException
-     *                when {@code location < 0 || >= size()}
-     * @since Android 1.0
+     * @throws IndexOutOfBoundsException
+     *                if {@code location < 0 || >= size()}
      */
     public E get(int location);
 
@@ -179,7 +168,6 @@
      * element' hashcode and its position in the {@code List} into account.
      * 
      * @return the hash code of the {@code List}.
-     * @since Android 1.0
      */
     public int hashCode();
 
@@ -191,7 +179,6 @@
      *            the object to search for.
      * @return the index of the first occurrence of the object or -1 if the
      *         object was not found.
-     * @since Android 1.0
      */
     public int indexOf(Object object);
 
@@ -201,7 +188,6 @@
      * @return {@code true} if this {@code List} has no elements, {@code false}
      *         otherwise.
      * @see #size
-     * @since Android 1.0
      */
     public boolean isEmpty();
 
@@ -211,7 +197,6 @@
      * 
      * @return an iterator on the elements of this {@code List}.
      * @see Iterator
-     * @since Android 1.0
      */
     public Iterator<E> iterator();
 
@@ -223,7 +208,6 @@
      *            the object to search for.
      * @return the index of the last occurrence of the object, or -1 if the
      *         object was not found.
-     * @since Android 1.0
      */
     public int lastIndexOf(Object object);
 
@@ -234,7 +218,6 @@
      * @return a {@code List} iterator on the elements of this {@code List}
      * 
      * @see ListIterator
-     * @since Android 1.0
      */
     public ListIterator<E> listIterator();
 
@@ -246,10 +229,9 @@
      * @param location
      *            the index at which to start the iteration.
      * @return a list iterator on the elements of this {@code List}.
-     * @exception IndexOutOfBoundsException
-     *                when {@code location < 0 || location > size()}
+     * @throws IndexOutOfBoundsException
+     *                if {@code location < 0 || location > size()}
      * @see ListIterator
-     * @since Android 1.0
      */
     public ListIterator<E> listIterator(int location);
 
@@ -259,11 +241,10 @@
      * @param location
      *            the index of the object to remove.
      * @return the removed object.
-     * @exception UnsupportedOperationException
-     *                when removing from this {@code List} is not supported.
-     * @exception IndexOutOfBoundsException
-     *                when {@code location < 0 || >= size()}
-     * @since Android 1.0
+     * @throws UnsupportedOperationException
+     *                if removing from this {@code List} is not supported.
+     * @throws IndexOutOfBoundsException
+     *                if {@code location < 0 || >= size()}
      */
     public E remove(int location);
 
@@ -274,9 +255,8 @@
      *            the object to remove.
      * @return true if this {@code List} was modified by this operation, false
      *         otherwise.
-     * @exception UnsupportedOperationException
-     *                when removing from this {@code List} is not supported.
-     * @since Android 1.0
+     * @throws UnsupportedOperationException
+     *                if removing from this {@code List} is not supported.
      */
     public boolean remove(Object object);
 
@@ -287,9 +267,8 @@
      * @param collection
      *            the collection of objects to remove.
      * @return {@code true} if this {@code List} is modified, {@code false} otherwise.
-     * @exception UnsupportedOperationException
-     *                when removing from this {@code List} is not supported.
-     * @since Android 1.0
+     * @throws UnsupportedOperationException
+     *                if removing from this {@code List} is not supported.
      */
     public boolean removeAll(Collection<?> collection);
 
@@ -300,9 +279,8 @@
      * @param collection
      *            the collection of objects to retain.
      * @return {@code true} if this {@code List} is modified, {@code false} otherwise.
-     * @exception UnsupportedOperationException
-     *                when removing from this {@code List} is not supported.
-     * @since Android 1.0
+     * @throws UnsupportedOperationException
+     *                if removing from this {@code List} is not supported.
      */
     public boolean retainAll(Collection<?> collection);
 
@@ -315,16 +293,15 @@
      * @param object
      *            the object to insert.
      * @return the previous element at the index.
-     * @exception UnsupportedOperationException
-     *                when replacing elements in this {@code List} is not supported.
-     * @exception ClassCastException
-     *                when the class of an object is inappropriate for this
+     * @throws UnsupportedOperationException
+     *                if replacing elements in this {@code List} is not supported.
+     * @throws ClassCastException
+     *                if the class of an object is inappropriate for this
      *                {@code List}.
-     * @exception IllegalArgumentException
-     *                when an object cannot be added to this {@code List}.
-     * @exception IndexOutOfBoundsException
-     *                when {@code location < 0 || >= size()}
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *                if an object cannot be added to this {@code List}.
+     * @throws IndexOutOfBoundsException
+     *                if {@code location < 0 || >= size()}
      */
     public E set(int location, E object);
 
@@ -332,7 +309,6 @@
      * Returns the number of elements in this {@code List}.
      * 
      * @return the number of elements in this {@code List}.
-     * @since Android 1.0
      */
     public int size();
 
@@ -346,10 +322,9 @@
      * @param end
      *            the index one past the end of the sublist.
      * @return a list of a portion of this {@code List}.
-     * @exception IndexOutOfBoundsException
-     *                when {@code start < 0, start > end} or {@code end >
+     * @throws IndexOutOfBoundsException
+     *                if {@code start < 0, start > end} or {@code end >
      *                size()}
-     * @since Android 1.0
      */
     public List<E> subList(int start, int end);
 
@@ -357,7 +332,6 @@
      * Returns an array containing all elements contained in this {@code List}.
      * 
      * @return an array of the elements from this {@code List}.
-     * @since Android 1.0
      */
     public Object[] toArray();
 
@@ -371,10 +345,9 @@
      * @param array
      *            the array.
      * @return an array of the elements from this {@code List}.
-     * @exception ArrayStoreException
-     *                when the type of an element in this {@code List} cannot be stored
+     * @throws ArrayStoreException
+     *                if the type of an element in this {@code List} cannot be stored
      *                in the type of the specified array.
-     * @since Android 1.0
      */
     public <T> T[] toArray(T[] array);
 }
diff --git a/libcore/luni/src/main/java/java/util/ListIterator.java b/libcore/luni/src/main/java/java/util/ListIterator.java
index 6ce94c3..1c62a22 100644
--- a/libcore/luni/src/main/java/java/util/ListIterator.java
+++ b/libcore/luni/src/main/java/java/util/ListIterator.java
@@ -21,8 +21,6 @@
 /**
  * An ListIterator is used to sequence over a List of objects. ListIterator can
  * move backwards or forwards through the list.
- * 
- * @since Android 1.0
  */
 public interface ListIterator<E> extends Iterator<E> {
     
@@ -38,7 +36,6 @@
      *             if the class of the object is inappropriate for the list.
      * @throws IllegalArgumentException
      *             if the object cannot be added to the list.
-     * @since Android 1.0
      */
     void add(E object);
 
@@ -47,7 +44,6 @@
      * 
      * @return {@code true} if there are more elements, {@code false} otherwise.
      * @see #next
-     * @since Android 1.0
      */
     public boolean hasNext();
 
@@ -57,7 +53,6 @@
      * @return {@code true} if there are previous elements, {@code false}
      *         otherwise.
      * @see #previous
-     * @since Android 1.0
      */
     public boolean hasPrevious();
 
@@ -68,7 +63,6 @@
      * @throws NoSuchElementException
      *             if there are no more elements.
      * @see #hasNext
-     * @since Android 1.0
      */
     public E next();
 
@@ -80,7 +74,6 @@
      * @throws NoSuchElementException
      *             if there are no more elements.
      * @see #next
-     * @since Android 1.0
      */
     public int nextIndex();
 
@@ -91,7 +84,6 @@
      * @throws NoSuchElementException
      *             if there are no previous elements.
      * @see #hasPrevious
-     * @since Android 1.0
      */
     public E previous();
 
@@ -103,7 +95,6 @@
      * @throws NoSuchElementException
      *             if there are no previous elements.
      * @see #previous
-     * @since Android 1.0
      */
     public int previousIndex();
 
@@ -117,7 +108,6 @@
      *             if {@code next} or {@code previous} have not been called, or
      *             {@code remove} or {@code add} have already been called after
      *             the last call to {@code next} or {@code previous}.
-     * @since Android 1.0
      */
     public void remove();
 
@@ -137,7 +127,6 @@
      *             if {@code next} or {@code previous} have not been called, or
      *             {@code remove} or {@code add} have already been called after
      *             the last call to {@code next} or {@code previous}.
-     * @since Android 1.0
      */
     void set(E object);
 }
diff --git a/libcore/luni/src/main/java/java/util/ListResourceBundle.java b/libcore/luni/src/main/java/java/util/ListResourceBundle.java
index 20d64ac..6206ee6 100644
--- a/libcore/luni/src/main/java/java/util/ListResourceBundle.java
+++ b/libcore/luni/src/main/java/java/util/ListResourceBundle.java
@@ -17,22 +17,19 @@
 
 package java.util;
 
-
 /**
  * {@code ListResourceBundle} is the abstract superclass of classes which provide
  * resources by implementing the {@code getContents()} method to return
  * the list of resources.
- * 
+ *
  * @see ResourceBundle
- * @since Android 1.0
+ * @since 1.1
  */
 public abstract class ListResourceBundle extends ResourceBundle {
-    Hashtable<String, Object> table;
+    HashMap<String, Object> table;
 
     /**
      * Constructs a new instance of this class.
-     * 
-     * @since Android 1.0
      */
     public ListResourceBundle() {
         super();
@@ -43,73 +40,81 @@
      * {@code ListResourceBundle}. Each element in the array is an array of two
      * elements, the first is the resource key string and the second is the
      * resource.
-     * 
+     *
      * @return a {@code Object} array containing the resources.
-     * @since Android 1.0
      */
     protected abstract Object[][] getContents();
 
     /**
      * Returns the names of the resources contained in this {@code ListResourceBundle}.
-     * 
+     *
      * @return an {@code Enumeration} of the resource names.
-     * @since Android 1.0
      */
     @Override
     public Enumeration<String> getKeys() {
-        if (table == null) {
-            initializeTable();
-        }
-        if (parent == null) {
-            return table.keys();
-        }
-        return new Enumeration<String>() {
-            Enumeration<String> local = table.keys();
+        initializeTable();
+        if (parent != null) {
+            return new Enumeration<String>() {
+                Iterator<String> local = table.keySet().iterator();
 
-            Enumeration<String> pEnum = parent.getKeys();
+                Enumeration<String> pEnum = parent.getKeys();
 
-            String nextElement;
+                String nextElement;
 
-            private boolean findNext() {
-                if (nextElement != null) {
-                    return true;
-                }
-                while (pEnum.hasMoreElements()) {
-                    String next = pEnum.nextElement();
-                    if (!table.containsKey(next)) {
-                        nextElement = next;
+                private boolean findNext() {
+                    if (nextElement != null) {
                         return true;
                     }
+                    while (pEnum.hasMoreElements()) {
+                        String next = pEnum.nextElement();
+                        if (!table.containsKey(next)) {
+                            nextElement = next;
+                            return true;
+                        }
+                    }
+                    return false;
                 }
-                return false;
-            }
 
-            public boolean hasMoreElements() {
-                if (local.hasMoreElements()) {
-                    return true;
+                public boolean hasMoreElements() {
+                    if (local.hasNext()) {
+                        return true;
+                    }
+                    return findNext();
                 }
-                return findNext();
-            }
 
-            public String nextElement() {
-                if (local.hasMoreElements()) {
-                    return local.nextElement();
+                public String nextElement() {
+                    if (local.hasNext()) {
+                        return local.next();
+                    }
+                    if (findNext()) {
+                        String result = nextElement;
+                        nextElement = null;
+                        return result;
+                    }
+                    // Cause an exception
+                    return pEnum.nextElement();
                 }
-                if (findNext()) {
-                    String result = nextElement;
-                    nextElement = null;
-                    return result;
+            };
+        } else {
+            return new Enumeration<String>() {
+                Iterator<String> it = table.keySet().iterator();
+
+                public boolean hasMoreElements() {
+                    return it.hasNext();
                 }
-                // Cause an exception
-                return pEnum.nextElement();
-            }
-        };
+
+                public String nextElement() {
+                    return it.next();
+                }
+            };
+        }
     }
 
     @Override
     public final Object handleGetObject(String key) {
-        if (table == null) {
-            initializeTable();
+        initializeTable();
+        if (key == null) {
+            throw new NullPointerException();
         }
         return table.get(key);
     }
@@ -117,9 +122,12 @@
     private synchronized void initializeTable() {
         if (table == null) {
             Object[][] contents = getContents();
-            table = new Hashtable<String, Object>(contents.length / 3 * 4 + 3);
-            for (int i = 0; i < contents.length; i++) {
-                table.put((String)contents[i][0], contents[i][1]);
+            table = new HashMap<String, Object>(contents.length / 3 * 4 + 3);
+            for (Object[] content : contents) {
+                if (content[0] == null || content[1] == null) {
+                    throw new NullPointerException();
+                }
+                table.put((String) content[0], content[1]);
             }
         }
     }
diff --git a/libcore/luni/src/main/java/java/util/Locale.java b/libcore/luni/src/main/java/java/util/Locale.java
index bbf7239..b1a1821 100644
--- a/libcore/luni/src/main/java/java/util/Locale.java
+++ b/libcore/luni/src/main/java/java/util/Locale.java
@@ -17,7 +17,8 @@
 
 package java.util;
 
-import java.io.File;
+// BEGIN android-changed
+// import java.io.File;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
@@ -25,19 +26,14 @@
 import java.io.Serializable;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
+// import java.util.zip.ZipEntry;
+// import java.util.zip.ZipFile;
 
-// BEGIN android-removed
-//import org.apache.harmony.luni.internal.locale.Country;
-//import org.apache.harmony.luni.internal.locale.Language;
-// END android-removed
 import org.apache.harmony.luni.util.PriviAction;
 import org.apache.harmony.luni.util.Util;
 
-//BEGIN android-added
 import com.ibm.icu4jni.util.Resources;
-// END android-added
+// END android-changed
 
 /**
  * {@code Locale} represents a language/country/variant combination. It is an identifier
@@ -45,15 +41,14 @@
  * The language codes are two letter lowercase codes as defined by ISO-639. The
  * country codes are three letter uppercase codes as defined by ISO-3166. The
  * variant codes are unspecified.
- * 
+ *
  * @see ResourceBundle
- * @since Android 1.0
  */
 public final class Locale implements Cloneable, Serializable {
-    
+
     private static final long serialVersionUID = 9149081749638150636L;
 
-    private static Locale[] availableLocales;
+    private static volatile Locale[] availableLocales;
 
     // Initialize a default which is used during static
     // initialization of the default for the platform.
@@ -61,200 +56,159 @@
 
     /**
      * Locale constant for en_CA.
-     * 
-     * @since Android 1.0
      */
     public static final Locale CANADA = new Locale("en", "CA"); //$NON-NLS-1$ //$NON-NLS-2$
 
     /**
      * Locale constant for fr_CA.
-     * 
-     * @since Android 1.0
      */
     public static final Locale CANADA_FRENCH = new Locale("fr", "CA"); //$NON-NLS-1$ //$NON-NLS-2$
 
     /**
      * Locale constant for zh_CN.
-     * 
-     * @since Android 1.0
      */
     public static final Locale CHINA = new Locale("zh", "CN"); //$NON-NLS-1$ //$NON-NLS-2$
 
     /**
      * Locale constant for zh.
-     * 
-     * @since Android 1.0
      */
-    public static final Locale CHINESE = new Locale("zh", "");  //$NON-NLS-1$//$NON-NLS-2$
+    public static final Locale CHINESE = new Locale("zh", ""); //$NON-NLS-1$//$NON-NLS-2$
 
     /**
      * Locale constant for en.
-     * 
-     * @since Android 1.0
      */
     public static final Locale ENGLISH = new Locale("en", ""); //$NON-NLS-1$ //$NON-NLS-2$
 
     /**
      * Locale constant for fr_FR.
-     * 
-     * @since Android 1.0
      */
-    public static final Locale FRANCE = new Locale("fr", "FR");  //$NON-NLS-1$//$NON-NLS-2$
+    public static final Locale FRANCE = new Locale("fr", "FR"); //$NON-NLS-1$//$NON-NLS-2$
 
     /**
      * Locale constant for fr.
-     * 
-     * @since Android 1.0
      */
-    public static final Locale FRENCH = new Locale("fr", "");  //$NON-NLS-1$//$NON-NLS-2$
+    public static final Locale FRENCH = new Locale("fr", ""); //$NON-NLS-1$//$NON-NLS-2$
 
     /**
      * Locale constant for de.
-     * 
-     * @since Android 1.0
      */
     public static final Locale GERMAN = new Locale("de", ""); //$NON-NLS-1$ //$NON-NLS-2$
 
     /**
      * Locale constant for de_DE.
-     * 
-     * @since Android 1.0
      */
     public static final Locale GERMANY = new Locale("de", "DE"); //$NON-NLS-1$ //$NON-NLS-2$
 
     /**
      * Locale constant for it.
-     * 
-     * @since Android 1.0
      */
     public static final Locale ITALIAN = new Locale("it", ""); //$NON-NLS-1$ //$NON-NLS-2$
 
     /**
      * Locale constant for it_IT.
-     * 
-     * @since Android 1.0
      */
     public static final Locale ITALY = new Locale("it", "IT"); //$NON-NLS-1$ //$NON-NLS-2$
 
     /**
      * Locale constant for ja_JP.
-     * 
-     * @since Android 1.0
      */
-    public static final Locale JAPAN = new Locale("ja", "JP");  //$NON-NLS-1$//$NON-NLS-2$
+    public static final Locale JAPAN = new Locale("ja", "JP"); //$NON-NLS-1$//$NON-NLS-2$
 
     /**
      * Locale constant for ja.
-     * 
-     * @since Android 1.0
      */
-    public static final Locale JAPANESE = new Locale("ja", "");  //$NON-NLS-1$//$NON-NLS-2$
+    public static final Locale JAPANESE = new Locale("ja", ""); //$NON-NLS-1$//$NON-NLS-2$
 
     /**
      * Locale constant for ko_KR.
-     * 
-     * @since Android 1.0
      */
-    public static final Locale KOREA = new Locale("ko", "KR");  //$NON-NLS-1$//$NON-NLS-2$
+    public static final Locale KOREA = new Locale("ko", "KR"); //$NON-NLS-1$//$NON-NLS-2$
 
     /**
      * Locale constant for ko.
-     * 
-     * @since Android 1.0
      */
-    public static final Locale KOREAN = new Locale("ko", "");  //$NON-NLS-1$//$NON-NLS-2$
+    public static final Locale KOREAN = new Locale("ko", ""); //$NON-NLS-1$//$NON-NLS-2$
 
     /**
      * Locale constant for zh_CN.
-     * 
-     * @since Android 1.0
      */
-    public static final Locale PRC = new Locale("zh", "CN");  //$NON-NLS-1$//$NON-NLS-2$
+    public static final Locale PRC = new Locale("zh", "CN"); //$NON-NLS-1$//$NON-NLS-2$
 
     /**
      * Locale constant for zh_CN.
-     * 
-     * @since Android 1.0
      */
-    public static final Locale SIMPLIFIED_CHINESE = new Locale("zh", "CN");  //$NON-NLS-1$//$NON-NLS-2$
+    public static final Locale SIMPLIFIED_CHINESE = new Locale("zh", "CN"); //$NON-NLS-1$//$NON-NLS-2$
 
     /**
      * Locale constant for zh_TW.
-     * 
-     * @since Android 1.0
      */
     public static final Locale TAIWAN = new Locale("zh", "TW"); //$NON-NLS-1$ //$NON-NLS-2$
 
     /**
      * Locale constant for zh_TW.
-     * 
-     * @since Android 1.0
      */
     public static final Locale TRADITIONAL_CHINESE = new Locale("zh", "TW"); //$NON-NLS-1$ //$NON-NLS-2$
 
     /**
      * Locale constant for en_GB.
-     * 
-     * @since Android 1.0
      */
     public static final Locale UK = new Locale("en", "GB"); //$NON-NLS-1$ //$NON-NLS-2$
 
     /**
      * Locale constant for en_US.
-     * 
-     * @since Android 1.0
      */
-    public static final Locale US = new Locale("en", "US");  //$NON-NLS-1$//$NON-NLS-2$
+    public static final Locale US = new Locale("en", "US"); //$NON-NLS-1$//$NON-NLS-2$
 
     private static final PropertyPermission setLocalePermission = new PropertyPermission(
-            "user.language", "write");  //$NON-NLS-1$//$NON-NLS-2$
+            "user.language", "write"); //$NON-NLS-1$//$NON-NLS-2$
 
     static {
         String language = AccessController
                 .doPrivileged(new PriviAction<String>("user.language", "en")); //$NON-NLS-1$ //$NON-NLS-2$
         // BEGIN android-changed
-        String region = AccessController
-                .doPrivileged(new PriviAction<String>("user.region", "US")); //$NON-NLS-1$ //$NON-NLS-2$
+        String region = AccessController.doPrivileged(new PriviAction<String>(
+                "user.region", "US")); //$NON-NLS-1$ //$NON-NLS-2$
         // END android-changed
-        String variant = AccessController
-                .doPrivileged(new PriviAction<String>("user.variant", "")); //$NON-NLS-1$ //$NON-NLS-2$
+        String variant = AccessController.doPrivileged(new PriviAction<String>(
+                "user.variant", "")); //$NON-NLS-1$ //$NON-NLS-2$
         defaultLocale = new Locale(language, region, variant);
     }
-    
+
     private transient String countryCode;
     private transient String languageCode;
     private transient String variantCode;
 
-    /**
-     * Constructs a default which is used during static initialization of the
-     * default for the platform.
-     */
-    private Locale() {
-        languageCode = "en"; //$NON-NLS-1$
-        countryCode = "US"; //$NON-NLS-1$
-        variantCode = ""; //$NON-NLS-1$
-    }
+    // BEGIN android-removed
+    // private transient ULocale uLocale;
+    // END android-removed
+
+	/**
+	 * Constructs a default which is used during static initialization of the
+	 * default for the platform.
+	 */
+	private Locale() {
+		languageCode = "en"; //$NON-NLS-1$
+		countryCode = "US"; //$NON-NLS-1$
+		variantCode = ""; //$NON-NLS-1$
+	}
 
     /**
      * Constructs a new {@code Locale} using the specified language.
-     * 
+     *
      * @param language
      *            the language this {@code Locale} represents.
-     * 
-     * @since Android 1.0
      */
     public Locale(String language) {
-        this(language, "", "");  //$NON-NLS-1$//$NON-NLS-2$
+        this(language, "", ""); //$NON-NLS-1$//$NON-NLS-2$
     }
 
     /**
      * Constructs a new {@code Locale} using the specified language and country codes.
-     * 
+     *
      * @param language
      *            the language this {@code Locale} represents.
      * @param country
      *            the country this {@code Locale} represents.
-     * @since Android 1.0
      */
     public Locale(String language, String country) {
         this(language, country, ""); //$NON-NLS-1$
@@ -263,7 +217,7 @@
     /**
      * Constructs a new {@code Locale} using the specified language, country, and
      * variant codes.
-     * 
+     *
      * @param language
      *            the language this {@code Locale} represents.
      * @param country
@@ -273,13 +227,22 @@
      * @throws NullPointerException
      *             if {@code language}, {@code country}, or
      *             {@code variant} is {@code null}.
-     * @since Android 1.0
      */
     public Locale(String language, String country, String variant) {
         if (language == null || country == null || variant == null) {
             throw new NullPointerException();
         }
+        if(language.length() == 0 && country.length() == 0){
+            languageCode = "";
+            countryCode = "";
+            variantCode = variant;
+            return;
+        }
+        // BEGIN android-changed
+        // this.uLocale = new ULocale(language, country, variant);
+        // languageCode = uLocale.getLanguage();
         languageCode = Util.toASCIILowerCase(language);
+        // END android-changed
         // Map new language codes to the obsolete language
         // codes so the correct resource bundles will be used.
         if (languageCode.equals("he")) {//$NON-NLS-1$
@@ -291,18 +254,21 @@
         }
 
         // countryCode is defined in ASCII character set
+        // BEGIN android-changed
+        // countryCode = country.length()!=0?uLocale.getCountry():"";
         countryCode = Util.toASCIIUpperCase(country);
+        // END android-changed
 
+        // Work around for be compatible with RI
         variantCode = variant;
     }
 
     /**
      * Returns a new {@code Locale} with the same language, country and variant codes as
      * this {@code Locale}.
-     * 
+     *
      * @return a shallow copy of this {@code Locale}.
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -317,13 +283,12 @@
      * Compares the specified object to this {@code Locale} and returns whether they are
      * equal. The object must be an instance of {@code Locale} and have the same
      * language, country and variant.
-     * 
+     *
      * @param object
      *            the object to compare with this object.
      * @return {@code true} if the specified object is equal to this {@code Locale},
      *         {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -347,13 +312,8 @@
     //     final String classPrefix = prefix.substring(last + 1, length);
     //     Set<String> result = new HashSet<String>();
     //     StringTokenizer paths = new StringTokenizer(System.getProperty(
-    //             // BEGIN android-removed
-    //             // "org.apache.harmony.boot.class.path", ""), System.getProperty( //$NON-NLS-1$ //$NON-NLS-2$
-    //             // END android-removed
-    //             // BEGIN android-added
-    //             "java.boot.class.path", ""), System.getProperty( //$NON-NLS-1$ //$NON-NLS-2$
-    //             // END android-added
-    //             "path.separator", ";"));  //$NON-NLS-1$//$NON-NLS-2$
+    //             "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);
@@ -378,12 +338,13 @@
     //                         String name = list[i];
     //                         if (name.startsWith(classPrefix)
     //                                 && name.endsWith(".class")) { //$NON-NLS-1$
-    //                             result.add(name.substring(0,
+    //                             result
+    //                                     .add(name.substring(0,
     //                                             name.length() - 6));
     //                         }
     //                     }
     //                 }
-    //                 
+    //
     //             } else {
     //                 // Handle ZIP/JAR files.
     //                 try {
@@ -394,25 +355,26 @@
     //                         String name = e.getName();
     //                         if (name.startsWith(prefix)
     //                                 && name.endsWith(".class")) {//$NON-NLS-1$
-    //                             result.add(name.substring(last+1, name.length() - 6));
+    //                             result.add(name.substring(last + 1, name
+    //                                     .length() - 6));
     //                         }
     //                     }
     //                     zip.close();
     //                 } catch (IOException e) {
-    //                    // Empty
+    //                     // Empty
     //                 }
     //             }
     //         }
     //     }
     //     Locale[] locales = new Locale[result.size()];
     //     int i = 0;
-    //     for (String name: result) {
+    //     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{
+    //             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) {
@@ -437,7 +399,7 @@
             String s = locales[i];
             int first = s.indexOf('_');
             int second = s.indexOf('_', first + 1);
-            
+
             if (first == -1) {
                 // Language only
                 temp.add(new Locale(s));
@@ -454,37 +416,32 @@
     }
     // END android-added
 
-    /**
+	/**
      * Gets the list of installed {@code Locale}. At least a {@code Locale} that is equal to
      * {@code Locale.US} must be contained in this array.
-     * 
+     *
      * @return an array of {@code Locale}s.
-     * @since Android 1.0
-     */
-    public static Locale[] getAvailableLocales() {
+	 */
+	public static Locale[] getAvailableLocales() {
+        // BEGIN android-changed
+        // ULocale[] ulocales =  ULocale.getAvailableLocales();
+        // Locale[] locales = new Locale[ulocales.length];
+        // for (int i = 0; i < locales.length; i++) {
+        //     locales[i] = ulocales[i].toLocale();
+        // }
+        // return locales;
         if (availableLocales == null) {
-            // BEGIN android-removed
-            // availableLocales = AccessController
-            //         .doPrivileged(new PrivilegedAction<Locale[]>() {
-            //             public Locale[] run() {
-            //                 return find("org/apache/harmony/luni/internal/locale/Locale_"); //$NON-NLS-1$
-            //             }
-            //         });
-            // END android-removed
-            
-            // BEGIN android-added
             availableLocales = find();
-            // END android-added
         }
         return availableLocales.clone();
-    }
+        // END android-changed
+	}
 
     /**
      * Gets the country code for this {@code Locale} or an empty string of no country
      * was set.
-     * 
+     *
      * @return a country code.
-     * @since Android 1.0
      */
     public String getCountry() {
         return countryCode;
@@ -492,9 +449,8 @@
 
     /**
      * Gets the default {@code Locale}.
-     * 
+     *
      * @return the default {@code Locale}.
-     * @since Android 1.0
      */
     public static Locale getDefault() {
         return defaultLocale;
@@ -504,9 +460,8 @@
      * Gets the full country name in the default {@code Locale} for the country code of
      * this {@code Locale}. If there is no matching country name, the country code is
      * returned.
-     * 
+     *
      * @return a country name.
-     * @since Android 1.0
      */
     public final String getDisplayCountry() {
         return getDisplayCountry(getDefault());
@@ -516,22 +471,21 @@
      * Gets the full country name in the specified {@code Locale} for the country code
      * of this {@code Locale}. If there is no matching country name, the country code is
      * returned.
-     * 
+     *
      * @param locale
      *            the {@code Locale} for which the display name is retrieved.
      * @return a country name.
-     * @since Android 1.0
      */
-    public String getDisplayCountry(Locale locale) {
+	public String getDisplayCountry(Locale locale) {
+        // BEGIN android-changed
+		// return ULocale.forLocale(this).getDisplayCountry(ULocale.forLocale(locale));
         if (countryCode.length() == 0) {
             return countryCode;
         }
         try {
             // First try the specified locale
             ResourceBundle bundle = getBundle("Country", locale); //$NON-NLS-1$
-            // BEGIN android-changed
             String result = bundle.getString(this.toString());
-            // END android-changed
             if (result != null) {
                 return result;
             }
@@ -543,15 +497,15 @@
         } catch (MissingResourceException e) {
             return countryCode;
         }
-    }
+        // END android-changed
+	}
 
     /**
      * Gets the full language name in the default {@code Locale} for the language code
      * of this {@code Locale}. If there is no matching language name, the language code
      * is returned.
-     * 
+     *
      * @return a language name.
-     * @since Android 1.0
      */
     public final String getDisplayLanguage() {
         return getDisplayLanguage(getDefault());
@@ -561,22 +515,21 @@
      * Gets the full language name in the specified {@code Locale} for the language code
      * of this {@code Locale}. If there is no matching language name, the language code
      * is returned.
-     * 
+     *
      * @param locale
      *            the {@code Locale} for which the display name is retrieved.
      * @return a language name.
-     * @since Android 1.0
      */
-    public String getDisplayLanguage(Locale locale) {
+	public String getDisplayLanguage(Locale locale) {
+        // BEGIN android-changed
+        // return ULocale.forLocale(this).getDisplayLanguage(ULocale.forLocale(locale));
         if (languageCode.length() == 0) {
             return languageCode;
         }
         try {
             // First try the specified locale
             ResourceBundle bundle = getBundle("Language", locale); //$NON-NLS-1$
-            // BEGIN android-changed
             String result = bundle.getString(this.toString());
-            // END android-changed
             if (result != null) {
                 return result;
             }
@@ -588,14 +541,14 @@
         } catch (MissingResourceException e) {
             return languageCode;
         }
-    }
+        // END android-changed
+	}
 
     /**
      * Gets the full language, country, and variant names in the default {@code Locale}
      * for the codes of this {@code Locale}.
-     * 
+     *
      * @return a {@code Locale} name.
-     * @since Android 1.0
      */
     public final String getDisplayName() {
         return getDisplayName(getDefault());
@@ -604,15 +557,14 @@
     /**
      * Gets the full language, country, and variant names in the specified
      * Locale for the codes of this {@code Locale}.
-     * 
+     *
      * @param locale
      *            the {@code Locale} for which the display name is retrieved.
      * @return a {@code Locale} name.
-     * @since Android 1.0
      */
     public String getDisplayName(Locale locale) {
         int count = 0;
-        StringBuffer buffer = new StringBuffer();
+        StringBuilder buffer = new StringBuilder();
         if (languageCode.length() > 0) {
             buffer.append(getDisplayLanguage(locale));
             count++;
@@ -643,9 +595,8 @@
      * Gets the full variant name in the default {@code Locale} for the variant code of
      * this {@code Locale}. If there is no matching variant name, the variant code is
      * returned.
-     * 
+     *
      * @return a variant name.
-     * @since Android 1.0
      */
     public final String getDisplayVariant() {
         return getDisplayVariant(getDefault());
@@ -655,41 +606,17 @@
      * Gets the full variant name in the specified {@code Locale} for the variant code
      * of this {@code Locale}. If there is no matching variant name, the variant code is
      * returned.
-     * 
+     *
      * @param locale
      *            the {@code Locale} for which the display name is retrieved.
      * @return a variant name.
-     * @since Android 1.0
      */
-    public String getDisplayVariant(Locale locale) {
+	public String getDisplayVariant(Locale locale) {
+        // BEGIN android-changed
+        // return ULocale.forLocale(this).getDisplayVariant(ULocale.forLocale(locale));
         if (variantCode.length() == 0) {
             return variantCode;
         }
-// BEGIN android-removed
-//         ResourceBundle bundle;
-//         try {
-//             bundle = getBundle("Variant", locale); //$NON-NLS-1$
-//         } catch (MissingResourceException e) {
-//             return variantCode.replace('_', ',');
-//         }
-// 
-//         StringBuffer result = new StringBuffer();
-//         StringTokenizer tokens = new StringTokenizer(variantCode, "_"); //$NON-NLS-1$
-//         while (tokens.hasMoreTokens()) {
-//             String code, variant = tokens.nextToken();
-//             try {
-//                 code = bundle.getString(variant);
-//             } catch (MissingResourceException e) {
-//                 code = variant;
-//             }
-//             result.append(code);
-//             if (tokens.hasMoreTokens()) {
-//                 result.append(',');
-//             }
-//         }
-//         return result.toString();
-// END android-removed
-// BEGIN android-added
         try {
             // First try the specified locale
             ResourceBundle bundle = getBundle("Variant", locale); //$NON-NLS-1$
@@ -705,105 +632,78 @@
         } catch (MissingResourceException e) {
             return variantCode;
         }
-// END android-added
-    }
+        // END android-changed
+	}
 
     /**
      * Gets the three letter ISO country code which corresponds to the country
      * code for this {@code Locale}.
-     * 
+     *
      * @return a three letter ISO language code.
-     * @exception MissingResourceException
-     *                when there is no matching three letter ISO country code.
-     * @since Android 1.0
+     * @throws MissingResourceException
+     *                if there is no matching three letter ISO country code.
      */
-    public String getISO3Country() throws MissingResourceException {
+	public String getISO3Country() throws MissingResourceException {
+        // BEGIN android-changed
+        // return ULocale.forLocale(this).getISO3Country();
         if (countryCode.length() == 0) {
             return ""; //$NON-NLS-1$
         }
         ResourceBundle bundle = getBundle("ISO3Countries", this); //$NON-NLS-1$
-        // BEGIN android-changed
         return bundle.getString(this.toString());
         // END android-changed
-    }
+	}
 
     /**
      * Gets the three letter ISO language code which corresponds to the language
      * code for this {@code Locale}.
-     * 
+     *
      * @return a three letter ISO language code.
-     * @exception MissingResourceException
-     *                when there is no matching three letter ISO language code.
-     * @since Android 1.0
+     * @throws MissingResourceException
+     *                if there is no matching three letter ISO language code.
      */
-    public String getISO3Language() throws MissingResourceException {
+	public String getISO3Language() throws MissingResourceException {
+        // BEGIN android-changed
+        // return ULocale.forLocale(this).getISO3Language();
         if (languageCode.length() == 0) {
             return ""; //$NON-NLS-1$
         }
         ResourceBundle bundle = getBundle("ISO3Languages", this); //$NON-NLS-1$
-        // BEGIN android-changed
         return bundle.getString(this.toString());
         // END android-changed
-    }
+	}
 
     /**
      * Gets the list of two letter ISO country codes which can be used as the
      * country code for a {@code Locale}.
-     * 
+     *
      * @return an array of strings.
-     * @since Android 1.0
      */
     public static String[] getISOCountries() {
-        // BEGIN android-removed
-        // ListResourceBundle bundle = new Country();
-        // 
-        // // To initialize the table
-        // Enumeration<String> keys = bundle.getKeys();
-        // int size = bundle.table.size();
-        // String[] result = new String[size];
-        // int index = 0;
-        // while (keys.hasMoreElements()) {
-        //     String element = keys.nextElement();
-        //     result[index++] = element;
-        // }
-        // return result;
-        // END android-removed
-        
-        // BEGIN android-added
+        // BEGIN android-changed
+        // return ULocale.getISOCountries();
         return Resources.getISOCountries();
-        // END android-added
+        // END android-changed
     }
 
     /**
      * Gets the list of two letter ISO language codes which can be used as the
      * language code for a {@code Locale}.
-     * 
+     *
      * @return an array of strings.
-     * @since Android 1.0
      */
-    public static String[] getISOLanguages() {
-        // BEGIN android-removed
-        // ListResourceBundle bundle = new Language();
-        // Enumeration<String> keys = bundle.getKeys(); // to initialize the table
-        // String[] result = new String[bundle.table.size()];
-        // int index = 0;
-        // while (keys.hasMoreElements()) {
-        //     result[index++] = keys.nextElement();
-        // }
-        // return result;
-        // END android-removed
-        
-        // BEGIN android-added
+	public static String[] getISOLanguages() {
+        // BEGIN android-changed
+        // return ULocale.getISOLanguages();
         return Resources.getISOLanguages();
-        // END android-added
-    }
+        // END android-changed
+	}
 
     /**
      * Gets the language code for this {@code Locale} or the empty string of no language
      * was set.
-     * 
+     *
      * @return a language code.
-     * @since Android 1.0
      */
     public String getLanguage() {
         return languageCode;
@@ -812,9 +712,8 @@
     /**
      * Gets the variant code for this {@code Locale} or an empty {@code String} of no variant
      * was set.
-     * 
+     *
      * @return a variant code.
-     * @since Android 1.0
      */
     public String getVariant() {
         return variantCode;
@@ -823,10 +722,9 @@
     /**
      * Returns an integer hash code for the receiver. Objects which are equal
      * return the same value for this method.
-     * 
+     *
      * @return the receiver's hash.
      * @see #equals
-     * @since Android 1.0
      */
     @Override
     public synchronized int hashCode() {
@@ -836,13 +734,12 @@
 
     /**
      * Sets the default {@code Locale} to the specified {@code Locale}.
-     * 
+     *
      * @param locale
      *            the new default {@code Locale}.
-     * @exception SecurityException
+     * @throws SecurityException
      *                if there is a {@code SecurityManager} in place which does not allow this
      *                operation.
-     * @since Android 1.0
      */
     public synchronized static void setDefault(Locale locale) {
         if (locale != null) {
@@ -864,11 +761,10 @@
      * between the language and the variant. the variant alone canot be defined
      * without a language and/or a country (in this case this method would
      * return the empty string).
-     * 
+     *
      * Examples: "en", "en_US", "_US", "en__POSIX", "en_US_POSIX"
-     * 
+     *
      * @return the string representation of this {@code Locale}.
-     * @since Android 1.0
      */
     @Override
     public final String toString() {
@@ -878,7 +774,7 @@
             result.append('_');
             result.append(countryCode);
         }
-        if (variantCode.length() > 0 && result.length() > 0 ) {
+        if (variantCode.length() > 0 && result.length() > 0) {
             if (0 == countryCode.length()) {
                 result.append("__"); //$NON-NLS-1$
             } else {
@@ -889,14 +785,16 @@
         return result.toString();
     }
 
+    // BEGIN android-added
     static ResourceBundle getBundle(final String clName, final Locale locale) {
         return AccessController.doPrivileged(new PrivilegedAction<ResourceBundle>() {
-                    public ResourceBundle run() {
-                        return ResourceBundle.getBundle("org.apache.harmony.luni.internal.locale." //$NON-NLS-1$
-                                + clName, locale);
-                    }
-                });
+            public ResourceBundle run() {
+                return ResourceBundle.getBundle("org.apache.harmony.luni.internal.locale." //$NON-NLS-1$
+                        + clName, locale);
+            }
+        });
     }
+    // END android-added
 
     private static final ObjectStreamField[] serialPersistentFields = {
             new ObjectStreamField("country", String.class), //$NON-NLS-1$
@@ -916,9 +814,8 @@
     private void readObject(ObjectInputStream stream) throws IOException,
             ClassNotFoundException {
         ObjectInputStream.GetField fields = stream.readFields();
-        countryCode = (String) fields.get("country", "");  //$NON-NLS-1$//$NON-NLS-2$
-        languageCode = (String) fields.get("language", "");  //$NON-NLS-1$//$NON-NLS-2$
-        variantCode = (String) fields.get("variant", "");  //$NON-NLS-1$//$NON-NLS-2$
+        countryCode = (String) fields.get("country", ""); //$NON-NLS-1$//$NON-NLS-2$
+        languageCode = (String) fields.get("language", ""); //$NON-NLS-1$//$NON-NLS-2$
+        variantCode = (String) fields.get("variant", ""); //$NON-NLS-1$//$NON-NLS-2$
     }
 }
-
diff --git a/libcore/luni/src/main/java/java/util/Map.java b/libcore/luni/src/main/java/java/util/Map.java
index d8b1e62..7509d1a 100644
--- a/libcore/luni/src/main/java/java/util/Map.java
+++ b/libcore/luni/src/main/java/java/util/Map.java
@@ -23,19 +23,15 @@
  * in which each key is mapped to a single value.  The class of the objects
  * used as keys is declared when the {@code Map} is declared, as is the 
  * class of the corresponding values.
- * <p>A {@code Map} provides helper methods to iterate through all of the 
+ * <p>
+ * A {@code Map} provides helper methods to iterate through all of the
  * keys contained in it, as well as various methods to access and update 
  * the key/value pairs.  
- * </p>  
- *  
- * @since Android 1.0
  */
 public interface Map<K,V> {
 
     /**
      * {@code Map.Entry} is a key/value mapping contained in a {@code Map}.
-     *      
-     * @since Android 1.0
      */
     public static interface Entry<K,V> {
         /**
@@ -48,7 +44,6 @@
          * @return {@code true} if the specified {@code Object} is equal to this
          *         {@code Map.Entry}, {@code false} otherwise.
          * @see #hashCode()
-         * @since Android 1.0
          */
         public boolean equals(Object object);
 
@@ -56,7 +51,6 @@
          * Returns the key.
          * 
          * @return the key
-         * @since Android 1.0
          */
         public K getKey();
 
@@ -64,7 +58,6 @@
          * Returns the value.
          * 
          * @return the value
-         * @since Android 1.0
          */
         public V getValue();
 
@@ -74,7 +67,6 @@
          * 
          * @return the receiver's hash code.
          * @see #equals(Object)
-         * @since Android 1.0
          */
         public int hashCode();
 
@@ -85,7 +77,6 @@
          * @param object
          *            the new value to set.
          * @return object the replaced value of this entry.
-         * @since Android 1.0
          */
         public V setValue(V object);
     };
@@ -97,7 +88,6 @@
      *                if removing elements from this {@code Map} is not supported.
      * @see #isEmpty()
      * @see #size()
-     * @since Android 1.0
      */
     public void clear();
 
@@ -108,7 +98,6 @@
      *            the key to search for.
      * @return {@code true} if this map contains the specified key,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean containsKey(Object key);
 
@@ -119,7 +108,6 @@
      *            the value to search for.
      * @return {@code true} if this map contains the specified value,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean containsValue(Object value);
 
@@ -129,7 +117,6 @@
      * changes in one will be reflected in the other.
      * 
      * @return a set of the mappings
-     * @since Android 1.0
      */
     public Set<Map.Entry<K,V>> entrySet();
 
@@ -143,7 +130,6 @@
      *         {@code false} if it is different from this {@code Object}.
      * @see #hashCode()
      * @see #entrySet()
-     * @since Android 1.0
      */
     public boolean equals(Object object);
 
@@ -154,7 +140,6 @@
      *            the key.
      * @return the value of the mapping with the specified key, or {@code null}
      *         if no mapping for the specified key is found.
-     * @since Android 1.0
      */
     public V get(Object key);
 
@@ -164,7 +149,6 @@
      * 
      * @return the receiver's hash.
      * @see #equals(Object)
-     * @since Android 1.0
      */
     public int hashCode();
 
@@ -174,7 +158,6 @@
      * @return {@code true} if this map has no elements, {@code false}
      *         otherwise.
      * @see #size()
-     * @since Android 1.0
      */
     public boolean isEmpty();
 
@@ -184,7 +167,6 @@
      * support adding.
      * 
      * @return a set of the keys.
-     * @since Android 1.0
      */
     public Set<K> keySet();
 
@@ -207,7 +189,6 @@
      * @throws NullPointerException
      *                if the key or value is {@code null} and this {@code Map} does
      *                not support {@code null} keys or values.
-     * @since Android 1.0
      */
     public V put(K key, V value);
 
@@ -226,7 +207,6 @@
      * @throws NullPointerException
      *                if a key or value is {@code null} and this {@code Map} does not
      *                support {@code null} keys or values.
-     * @since Android 1.0
      */
     public void putAll(Map<? extends K,? extends V> map);
 
@@ -239,7 +219,6 @@
      *         for the specified key was found.
      * @throws UnsupportedOperationException
      *                if removing from this {@code Map} is not supported.
-     * @since Android 1.0
      */
     public V remove(Object key);
 
@@ -247,7 +226,6 @@
      * Returns the number of mappings in this {@code Map}.
      * 
      * @return the number of mappings in this {@code Map}.
-     * @since Android 1.0
      */
     public int size();
 
@@ -263,16 +241,13 @@
      * "wrapper object" over the iterator of this {@code Map}'s {@link #entrySet()}. The {@link AbstractCollection#size} method
      * wraps this {@code Map}'s {@link #size} method and the {@link AbstractCollection#contains} method wraps this {@code Map}'s
      * {@link #containsValue} method.
-     * </p>
      * <p>
      * The collection is created when this method is called at first time and
      * returned in response to all subsequent calls. This method may return
      * different Collection when multiple calls to this method, since it has no
      * synchronization performed.
-     * </p>
      * 
      * @return a collection of the values contained in this map.
-     * @since Android 1.0
      */
     public Collection<V> values();
 }
diff --git a/libcore/luni/src/main/java/java/util/MapEntry.java b/libcore/luni/src/main/java/java/util/MapEntry.java
index a63f2fd..6a5bf0f 100644
--- a/libcore/luni/src/main/java/java/util/MapEntry.java
+++ b/libcore/luni/src/main/java/java/util/MapEntry.java
@@ -17,17 +17,16 @@
 
 package java.util;
 
-
 /**
  * MapEntry is an internal class which provides an implementation of Map.Entry.
  */
-class MapEntry<K,V> implements Map.Entry<K,V>, Cloneable {
-    
+class MapEntry<K, V> implements Map.Entry<K, V>, Cloneable {
+
     K key;
     V value;
 
-    interface Type<RT,KT,VT> {
-        RT get(MapEntry<KT,VT> entry);
+    interface Type<RT, KT, VT> {
+        RT get(MapEntry<KT, VT> entry);
     }
 
     MapEntry(K theKey) {
@@ -82,7 +81,7 @@
         value = object;
         return result;
     }
-    
+
     @Override
     public String toString() {
         return key + "=" + value;
diff --git a/libcore/luni/src/main/java/java/util/MissingFormatArgumentException.java b/libcore/luni/src/main/java/java/util/MissingFormatArgumentException.java
index bcd240c..dfa0c73 100644
--- a/libcore/luni/src/main/java/java/util/MissingFormatArgumentException.java
+++ b/libcore/luni/src/main/java/java/util/MissingFormatArgumentException.java
@@ -24,7 +24,6 @@
  * that refers to a missing argument.
  * 
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class MissingFormatArgumentException extends IllegalFormatException {
     private static final long serialVersionUID = 19190115L;
diff --git a/libcore/luni/src/main/java/java/util/MissingFormatWidthException.java b/libcore/luni/src/main/java/java/util/MissingFormatWidthException.java
index 19af7d7..8b4e1f8 100644
--- a/libcore/luni/src/main/java/java/util/MissingFormatWidthException.java
+++ b/libcore/luni/src/main/java/java/util/MissingFormatWidthException.java
@@ -21,7 +21,6 @@
  * missing but is required.
  * 
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class MissingFormatWidthException extends IllegalFormatException {
     private static final long serialVersionUID = 15560123L;
diff --git a/libcore/luni/src/main/java/java/util/MissingResourceException.java b/libcore/luni/src/main/java/java/util/MissingResourceException.java
index c3a7efe..9a0cbbb 100644
--- a/libcore/luni/src/main/java/java/util/MissingResourceException.java
+++ b/libcore/luni/src/main/java/java/util/MissingResourceException.java
@@ -25,7 +25,6 @@
  * 
  * @see ResourceBundle
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class MissingResourceException extends RuntimeException {
 
diff --git a/libcore/luni/src/main/java/java/util/Observable.java b/libcore/luni/src/main/java/java/util/Observable.java
index a4c0333..5ed4563 100644
--- a/libcore/luni/src/main/java/java/util/Observable.java
+++ b/libcore/luni/src/main/java/java/util/Observable.java
@@ -17,7 +17,6 @@
 
 package java.util;
 
-
 /**
  * Observable is used to notify a group of Observer objects when a change
  * occurs. On creation, the set of observers is empty. After a change occurred,
@@ -26,21 +25,17 @@
  * Observers. The order of invocation is not specified. This implementation will
  * call the Observers in the order they registered. Subclasses are completely
  * free in what order they call the update methods.
- * 
+ *
  * @see Observer
- * 
- * @since Android 1.0
  */
 public class Observable {
-    
-    Vector<Observer> observers = new Vector<Observer>();
+
+    List<Observer> observers = new ArrayList<Observer>();
 
     boolean changed = false;
 
     /**
      * Constructs a new {@code Observable} object.
-     * 
-     * @since Android 1.0
      */
     public Observable() {
         super();
@@ -49,68 +44,62 @@
     /**
      * Adds the specified observer to the list of observers. If it is already
      * registered, it is not added a second time.
-     * 
+     *
      * @param observer
      *            the Observer to add.
-     * @since Android 1.0
      */
-    public synchronized void addObserver(Observer observer) {
+    public void addObserver(Observer observer) {
         if (observer == null) {
             throw new NullPointerException();
         }
-        if (!observers.contains(observer))
-            observers.addElement(observer);
+        synchronized (this) {
+            if (!observers.contains(observer))
+                observers.add(observer);
+        }
     }
 
     /**
      * Clears the changed flag for this {@code Observable}. After calling
      * {@code clearChanged()}, {@code hasChanged()} will return {@code false}.
-     * 
-     * @since Android 1.0
      */
-    protected synchronized void clearChanged() {
+    protected void clearChanged() {
         changed = false;
     }
 
     /**
      * Returns the number of observers registered to this {@code Observable}.
-     * 
+     *
      * @return the number of observers.
-     * @since Android 1.0
      */
-    public synchronized int countObservers() {
+    public int countObservers() {
         return observers.size();
     }
 
     /**
      * Removes the specified observer from the list of observers. Passing null
      * won't do anything.
-     * 
+     *
      * @param observer
      *            the observer to remove.
-     * @since Android 1.0
      */
     public synchronized void deleteObserver(Observer observer) {
-        observers.removeElement(observer);
+        observers.remove(observer);
     }
 
     /**
      * Removes all observers from the list of observers.
-     * 
-     * @since Android 1.0
      */
     public synchronized void deleteObservers() {
-        observers.setSize(0);
+        observers.clear();
     }
 
     /**
      * Returns the changed flag for this {@code Observable}.
-     * 
+     *
      * @return {@code true} when the changed flag for this {@code Observable} is
      *         set, {@code false} otherwise.
-     * @since Android 1.0
      */
-    public synchronized boolean hasChanged() {
+    public boolean hasChanged() {
         return changed;
     }
 
@@ -120,9 +109,6 @@
      * argument. Afterwards, calls {@code clearChanged()}.
      * <p>
      * Equivalent to calling {@code notifyObservers(null)}.
-     * </p>
-     * 
-     * @since Android 1.0
      */
     public void notifyObservers() {
         notifyObservers(null);
@@ -132,31 +118,34 @@
      * If {@code hasChanged()} returns {@code true}, calls the {@code update()}
      * method for every Observer in the list of observers using the specified
      * argument. Afterwards calls {@code clearChanged()}.
-     * 
+     *
      * @param data
      *            the argument passed to {@code update()}.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public void notifyObservers(Object data) {
-        if (hasChanged()) {
-            // Must clone the vector in case deleteObserver is called
-            Vector<Observer> clone = (Vector<Observer>)observers.clone();
-            int size = clone.size();
-            for (int i = 0; i < size; i++) {
-                clone.elementAt(i).update(this, data);
+        int size = 0;
+        Observer[] arrays = null;
+        synchronized (this) {
+            if (hasChanged()) {
+                clearChanged();
+                size = observers.size();
+                arrays = new Observer[size];
+                observers.toArray(arrays);
             }
-            clearChanged();
+        }
+        if (arrays != null) {
+            for (Observer observer : arrays) {
+                observer.update(this, data);
+            }
         }
     }
 
     /**
      * Sets the changed flag for this {@code Observable}. After calling
      * {@code setChanged()}, {@code hasChanged()} will return {@code true}.
-     * 
-     * @since Android 1.0
      */
-    protected synchronized void setChanged() {
+    protected void setChanged() {
         changed = true;
     }
 }
diff --git a/libcore/luni/src/main/java/java/util/Observer.java b/libcore/luni/src/main/java/java/util/Observer.java
index 2c8417b..c398e1b 100644
--- a/libcore/luni/src/main/java/java/util/Observer.java
+++ b/libcore/luni/src/main/java/java/util/Observer.java
@@ -23,7 +23,6 @@
  * receive notification of updates on an {@code Observable} object.
  * 
  * @see Observable 
- * @since Android 1.0
  */
 public interface Observer {
 
@@ -36,7 +35,6 @@
      *            the {@link Observable} object.
      * @param data
      *            the data passed to {@link Observable#notifyObservers(Object)}.
-     * @since Android 1.0
      */
     void update(Observable observable, Object data);
 }
diff --git a/libcore/luni/src/main/java/java/util/PriorityQueue.java b/libcore/luni/src/main/java/java/util/PriorityQueue.java
index 544c538..c17e7f9 100644
--- a/libcore/luni/src/main/java/java/util/PriorityQueue.java
+++ b/libcore/luni/src/main/java/java/util/PriorityQueue.java
@@ -31,8 +31,6 @@
  * <p>
  * A PriorityQueue is not synchronized. If multiple threads will have to access
  * it concurrently, use the {@link java.util.concurrent.PriorityBlockingQueue}.
- * 
- * @since Android 1.0
  */
 public class PriorityQueue<E> extends AbstractQueue<E> implements Serializable {
 
@@ -53,8 +51,6 @@
     /**
      * Constructs a priority queue with an initial capacity of 11 and natural
      * ordering.
-     * 
-     * @since Android 1.0
      */
     public PriorityQueue() {
         this(DEFAULT_CAPACITY);
@@ -68,7 +64,6 @@
      *            the specified capacity.
      * @throws IllegalArgumentException
      *             if the initialCapacity is less than 1.
-     * @since Android 1.0
      */
     public PriorityQueue(int initialCapacity) {
         this(initialCapacity, null);
@@ -84,7 +79,6 @@
      *            will be used.
      * @throws IllegalArgumentException
      *             if the initialCapacity is less than 1.
-     * @since Android 1.0
      */
     public PriorityQueue(int initialCapacity, Comparator<? super E> comparator) {
         if (initialCapacity < 1) {
@@ -107,7 +101,6 @@
      *             if any of the elements in the collection are not comparable.
      * @throws NullPointerException
      *             if any of the elements in the collection are null.
-     * @since Android 1.0
      */
     public PriorityQueue(Collection<? extends E> c) {
         if (c instanceof PriorityQueue) {
@@ -129,7 +122,6 @@
      * @param c
      *            the priority queue whose elements will be added to the
      *            priority queue to be constructed.
-     * @since Android 1.0
      */
     public PriorityQueue(PriorityQueue<? extends E> c) {
         getFromPriorityQueue(c);
@@ -144,7 +136,6 @@
      * @param c
      *            the sorted set whose elements will be added to the priority
      *            queue to be constructed.
-     * @since Android 1.0
      */
     public PriorityQueue(SortedSet<? extends E> c) {
         getFromSortedSet(c);
@@ -155,7 +146,6 @@
      * in any specified ordering.
      * 
      * @return the iterator of the priority queue.
-     * @since Android 1.0
      */
     @Override
     public Iterator<E> iterator() {
@@ -167,7 +157,6 @@
      * than the Integer.MAX, then it returns Integer.MAX.
      * 
      * @return the size of the priority queue.
-     * @since Android 1.0
      */
     @Override
     public int size() {
@@ -176,8 +165,6 @@
 
     /**
      * Removes all the elements of the priority queue.
-     * 
-     * @since Android 1.0
      */
     @Override
     public void clear() {
@@ -194,7 +181,8 @@
      * @throws ClassCastException
      *             if the element cannot be compared with the elements in the
      *             priority queue using the ordering of the priority queue.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code o} is {@code null}.
      */
     public boolean offer(E o) {
         if (null == o) {
@@ -210,7 +198,6 @@
      * Gets and removes the head of the queue.
      * 
      * @return the head of the queue or null if the queue is empty.
-     * @since Android 1.0
      */
     public E poll() {
         if (isEmpty()) {
@@ -225,7 +212,6 @@
      * Gets but does not remove the head of the queue.
      * 
      * @return the head of the queue or null if the queue is empty.
-     * @since Android 1.0
      */
     public E peek() {
         if (isEmpty()) {
@@ -239,7 +225,6 @@
      * 
      * @return the comparator of the priority queue or null if the natural
      *         ordering is used.
-     * @since Android 1.0
      */
     public Comparator<? super E> comparator() {
         return comparator;
@@ -252,7 +237,6 @@
      *            the object to be removed.
      * @return true if the object was in the priority queue, false if the object
      *         was not in the priority queue.
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
@@ -282,7 +266,8 @@
      * @throws ClassCastException
      *             if the element cannot be compared with the elements in the
      *             priority queue using the ordering of the priority queue.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code o} is {@code null}.
      */
     @Override
     public boolean add(E o) {
diff --git a/libcore/luni/src/main/java/java/util/Properties.java b/libcore/luni/src/main/java/java/util/Properties.java
index 15b74ee..b0f3b9d 100644
--- a/libcore/luni/src/main/java/java/util/Properties.java
+++ b/libcore/luni/src/main/java/java/util/Properties.java
@@ -17,9 +17,9 @@
 
 package java.util;
 
-
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.BufferedInputStream;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.PrintStream;
@@ -48,45 +48,37 @@
 import org.w3c.dom.Text;
 // END android-added
 
-// BEGIN android-added
-// copied from newer version of Haromny
 import org.apache.harmony.luni.internal.nls.Messages;
-// END android-added
 import org.apache.harmony.luni.util.PriviAction;
 
 /**
- * A {@code Properties} object is a {@code Hashtable} where the keys and values 
- * must be {@code String}s. Each property can have a default 
+ * A {@code Properties} object is a {@code Hashtable} where the keys and values
+ * must be {@code String}s. Each property can have a default
  * {@code Properties} list which specifies the default
  * values to be used when a given key is not found in this {@code Properties}
  * instance.
- * 
+ *
  * @see Hashtable
  * @see java.lang.System#getProperties
- * @since Android 1.0
  */
-public class Properties extends Hashtable<Object,Object> {
-    
+public class Properties extends Hashtable<Object, Object> {
+
     private static final long serialVersionUID = 4112578634029874840L;
 
     private transient DocumentBuilder builder = null;
 
-    private static final String PROP_DTD_NAME 
-            = "http://java.sun.com/dtd/properties.dtd";
+    private static final String PROP_DTD_NAME = "http://java.sun.com/dtd/properties.dtd";
 
-    private static final String PROP_DTD 
-            = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+    private static final String PROP_DTD = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
             + "    <!ELEMENT properties (comment?, entry*) >"
             + "    <!ATTLIST properties version CDATA #FIXED \"1.0\" >"
             + "    <!ELEMENT comment (#PCDATA) >"
             + "    <!ELEMENT entry (#PCDATA) >"
             + "    <!ATTLIST entry key CDATA #REQUIRED >";
-    
+
     /**
      * The default values for keys not found in this {@code Properties}
      * instance.
-     * 
-     * @since Android 1.0
      */
     protected Properties defaults;
 
@@ -95,8 +87,6 @@
 
     /**
      * Constructs a new {@code Properties} object.
-     * 
-     * @since Android 1.0
      */
     public Properties() {
         super();
@@ -105,10 +95,9 @@
     /**
      * Constructs a new {@code Properties} object using the specified default
      * {@code Properties}.
-     * 
+     *
      * @param properties
      *            the default {@code Properties}.
-     * @since Android 1.0
      */
     public Properties(Properties properties) {
         defaults = properties;
@@ -158,11 +147,10 @@
      * Searches for the property with the specified name. If the property is not
      * found, the default {@code Properties} are checked. If the property is not
      * found in the default {@code Properties}, {@code null} is returned.
-     * 
+     *
      * @param name
      *            the name of the property to find.
      * @return the named property value, or {@code null} if it can't be found.
-     * @since Android 1.0
      */
     public String getProperty(String name) {
         Object result = super.get(name);
@@ -178,13 +166,12 @@
      * found, it looks in the default {@code Properties}. If the property is not
      * found in the default {@code Properties}, it returns the specified
      * default.
-     * 
+     *
      * @param name
      *            the name of the property to find.
      * @param defaultValue
      *            the default value.
      * @return the named property value.
-     * @since Android 1.0
      */
     public String getProperty(String name, String defaultValue) {
         Object result = super.get(name);
@@ -202,17 +189,16 @@
      * Lists the mappings in this {@code Properties} to the specified
      * {@code PrintStream} in a
      * human readable form.
-     * 
+     *
      * @param out
      *            the {@code PrintStream} to write the content to in human readable
      *            form.
-     * @since Android 1.0
      */
     public void list(PrintStream out) {
         if (out == null) {
             throw new NullPointerException();
         }
-        StringBuffer buffer = new StringBuffer(80);
+        StringBuilder buffer = new StringBuilder(80);
         Enumeration<?> keys = propertyNames();
         while (keys.hasMoreElements()) {
             String key = (String) keys.nextElement();
@@ -239,17 +225,16 @@
      * Lists the mappings in this {@code Properties} to the specified
      * {@code PrintWriter} in a
      * human readable form.
-     * 
+     *
      * @param writer
      *            the {@code PrintWriter} to write the content to in human
      *            readable form.
-     * @since Android 1.0
      */
     public void list(PrintWriter writer) {
         if (writer == null) {
             throw new NullPointerException();
         }
-        StringBuffer buffer = new StringBuffer(80);
+        StringBuilder buffer = new StringBuilder(80);
         Enumeration<?> keys = propertyNames();
         while (keys.hasMoreElements()) {
             String key = (String) keys.nextElement();
@@ -293,29 +278,43 @@
      * <li>Following escape sequences are recognized: "\ ", "\\", "\r", "\n",
      * "\!", "\#", "\t", "\b", "\f", and "&#92;uXXXX" (unicode character).</li>
      * </ul>
-     * 
+     *
      * @param in
      *            the {@code InputStream}.
      * @throws IOException
      *             if error occurs during reading from the {@code InputStream}.
-     * @since Android 1.0
      */
+    @SuppressWarnings("fallthrough")
     public synchronized void load(InputStream in) throws IOException {
+        if (in == null) {
+            throw new NullPointerException();
+        }
         int mode = NONE, unicode = 0, count = 0;
         char nextChar, buf[] = new char[40];
-        int offset = 0, keyLength = -1;
+        int offset = 0, keyLength = -1, intVal;
         boolean firstChar = true;
-        byte[] inbuf = new byte[256];
-        int inbufCount = 0, inbufPos = 0;
+
+        // BEGIN android-changed
+        BufferedInputStream bis = new BufferedInputStream(in, 8192);
+        // END android-changed
 
         while (true) {
-            if (inbufPos == inbufCount) {
-                if ((inbufCount = in.read(inbuf)) == -1) {
-                    break;
+            intVal = bis.read();
+            if (intVal == -1) {
+                // if mode is UNICODE but has less than 4 hex digits, should
+                // throw an IllegalArgumentException
+                // luni.08=Invalid Unicode sequence: expected format \\uxxxx
+                if (mode == UNICODE && count < 4) {
+                    throw new IllegalArgumentException(Messages.getString("luni.08")); //$NON-NLS-1$
                 }
-                inbufPos = 0;
+                // if mode is SLASH and no data is read, should append '\u0000'
+                // to buf
+                if (mode == SLASH) {
+                    buf[offset++] = '\u0000';
+                }
+                break;
             }
-            nextChar = (char) (inbuf[inbufPos++] & 0xff);
+            nextChar = (char) (intVal & 0xff);
 
             if (offset == buf.length) {
                 char[] newBuf = new char[buf.length * 2];
@@ -324,8 +323,6 @@
             }
             if (mode == UNICODE) {
                 int digit = Character.digit(nextChar, 16);
-                // BEGIN android-changed
-                // copied from newer version of Harmony
                 if (digit >= 0) {
                     unicode = (unicode << 4) + digit;
                     if (++count < 4) {
@@ -333,9 +330,8 @@
                     }
                 } else if (count <= 4) {
                     // luni.09=Invalid Unicode sequence: illegal character
-                    throw new IllegalArgumentException(Messages.getString("luni.09"));
+                    throw new IllegalArgumentException(Messages.getString("luni.09")); //$NON-NLS-1$
                 }
-                // END android-changed
                 mode = NONE;
                 buf[offset++] = (char) unicode;
                 if (nextChar != '\n') {
@@ -377,16 +373,12 @@
                 case '!':
                     if (firstChar) {
                         while (true) {
-                            if (inbufPos == inbufCount) {
-                                if ((inbufCount = in.read(inbuf)) == -1) {
-                                    inbufPos = -1;
-                                    break;
-                                }
-                                inbufPos = 0;
+                            intVal = bis.read();
+                            if (intVal == -1) {
+                                break;
                             }
-                            nextChar = (char) inbuf[inbufPos++]; // & 0xff
-                                                                    // not
-                                                                    // required
+                            // & 0xff not required
+                            nextChar = (char) intVal;
                             if (nextChar == '\r' || nextChar == '\n') {
                                 break;
                             }
@@ -399,11 +391,11 @@
                         mode = IGNORE; // Ignore whitespace on the next line
                         continue;
                     }
-                // fall into the next case
+                    // fall into the next case
                 case '\r':
                     mode = NONE;
                     firstChar = true;
-                    if (offset > 0) {
+                    if (offset > 0 || (offset == 0 && keyLength == 0)) {
                         if (keyLength == -1) {
                             keyLength = offset;
                         }
@@ -453,13 +445,9 @@
             }
             buf[offset++] = nextChar;
         }
-        // BEGIN android-added
-        // copied from a newer version of Harmony
-        if (mode == UNICODE && count <= 4) {
-            // luni.08=Invalid Unicode sequence: expected format \\uxxxx
-            throw new IllegalArgumentException(Messages.getString("luni.08"));
+        if (keyLength == -1 && offset > 0) {
+            keyLength = offset;
         }
-        // END android-added
         if (keyLength >= 0) {
             String temp = new String(buf, 0, offset);
             put(temp.substring(0, keyLength), temp.substring(keyLength));
@@ -469,17 +457,18 @@
     /**
      * Returns all of the property names that this {@code Properties} object
      * contains.
-     * 
+     *
      * @return an {@code Enumeration} containing the names of all properties
      *         that this {@code Properties} object contains.
-     * @since Android 1.0
      */
     public Enumeration<?> propertyNames() {
         if (defaults == null) {
             return keys();
         }
 
-        Hashtable<Object, Object> set = new Hashtable<Object, Object>(defaults.size() + size());
+        Hashtable<Object, Object> set = new Hashtable<Object, Object>(defaults
+                .size()
+                + size());
         Enumeration<?> keys = defaults.propertyNames();
         while (keys.hasMoreElements()) {
             set.put(keys.nextElement(), set);
@@ -496,15 +485,14 @@
      * OutputStream}, putting the specified comment at the beginning. The output
      * from this method is suitable for being read by the
      * {@link #load(InputStream)} method.
-     * 
+     *
      * @param out the {@code OutputStream} to write to.
      * @param comment the comment to add at the beginning.
-     * @exception ClassCastException when the key or value of a mapping is not a
+     * @throws ClassCastException if the key or value of a mapping is not a
      *                String.
      * @deprecated This method ignores any {@code IOException} thrown while
      *             writing -- use {@link #store} instead for better exception
      *             handling.
-     * @since Android 1.0
      */
     @Deprecated
     public void save(OutputStream out, String comment) {
@@ -517,13 +505,12 @@
     /**
      * Maps the specified key to the specified value. If the key already exists,
      * the old value is replaced. The key and value cannot be {@code null}.
-     * 
+     *
      * @param name
      *            the key.
      * @param value
      *            the value.
      * @return the old value mapped to the key, or {@code null}.
-     * @since Android 1.0
      */
     public Object setProperty(String name, String value) {
         return put(name, value);
@@ -536,14 +523,13 @@
      * OutputStream}, putting the specified comment at the beginning. The output
      * from this method is suitable for being read by the
      * {@link #load(InputStream)} method.
-     * 
+     *
      * @param out the {@code OutputStream} to write to.
      * @param comment the comment to put at the beginning.
      * @throws IOException if an error occurs during the write to the {@code
      *             OutputStream}.
-     * @exception ClassCastException when the key or value of a mapping is not a
+     * @throws ClassCastException if the key or value of a mapping is not a
      *                {@code String}.
-     * @since Android 1.0
      */
     public synchronized void store(OutputStream out, String comment)
             throws IOException {
@@ -557,11 +543,11 @@
         if (comment != null) {
             writer.write("#"); //$NON-NLS-1$
             writer.write(comment);
-            writer.write(lineSeparator); 
+            writer.write(lineSeparator);
         }
         writer.write("#"); //$NON-NLS-1$
         writer.write(new Date().toString());
-        writer.write(lineSeparator); 
+        writer.write(lineSeparator);
 
         for (Map.Entry<Object, Object> entry : entrySet()) {
             String key = (String) entry.getKey();
@@ -579,39 +565,38 @@
      * Loads the properties from an {@code InputStream} containing the
      * properties in XML form. The XML document must begin with (and conform to)
      * following DOCTYPE:
-     * 
+     *
      * <pre>
      * &lt;!DOCTYPE properties SYSTEM &quot;http://java.sun.com/dtd/properties.dtd&quot;&gt;
      * </pre>
-     * 
+     *
      * Also the content of the XML data must satisfy the DTD but the xml is not
      * validated against it. The DTD is not loaded from the SYSTEM ID. After
      * this method returns the InputStream is not closed.
-     * 
+     *
      * @param in the InputStream containing the XML document.
      * @throws IOException in case an error occurs during a read operation.
      * @throws InvalidPropertiesFormatException if the XML data is not a valid
      *             properties file.
-     * @since Android 1.0
      */
-    public synchronized void loadFromXML(InputStream in) 
-            throws IOException, InvalidPropertiesFormatException {
+    public synchronized void loadFromXML(InputStream in) throws IOException,
+            InvalidPropertiesFormatException {
         if (in == null) {
             throw new NullPointerException();
         }
-        
+
         if (builder == null) {
             DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
             // BEGIN android-removed
             // factory.setValidating(true);
             // END android-removed
-            
+
             try {
                 builder = factory.newDocumentBuilder();
             } catch (ParserConfigurationException e) {
                 throw new Error(e);
             }
-            
+
             builder.setErrorHandler(new ErrorHandler() {
                 public void warning(SAXParseException e) throws SAXException {
                     throw e;
@@ -625,30 +610,30 @@
                     throw e;
                 }
             });
-            
+
             builder.setEntityResolver(new EntityResolver() {
-                public InputSource resolveEntity(String publicId, String systemId)
-                        throws SAXException, IOException {
+                public InputSource resolveEntity(String publicId,
+                        String systemId) throws SAXException, IOException {
                     if (systemId.equals(PROP_DTD_NAME)) {
                         InputSource result = new InputSource(new StringReader(
                                 PROP_DTD));
                         result.setSystemId(PROP_DTD_NAME);
                         return result;
                     }
-                    throw new SAXException(
-                            "Invalid DOCTYPE declaration: " + systemId);
+                    throw new SAXException("Invalid DOCTYPE declaration: "
+                            + systemId);
                 }
             });
         }
-        
+
         try {
             Document doc = builder.parse(in);
-            NodeList entries = doc.getElementsByTagName("entry"); 
+            NodeList entries = doc.getElementsByTagName("entry");
             if (entries == null) {
                 return;
             }
             int entriesListLength = entries.getLength();
-            
+
             for (int i = 0; i < entriesListLength; i++) {
                 Element entry = (Element) entries.item(i);
                 String key = entry.getAttribute("key");
@@ -658,10 +643,10 @@
                 // BEGIN android-added
                 String value = getTextContent(entry);
                 // END android-added
-                
+
                 /*
-                 * key != null & value != null
-                 * but key or(and) value can be empty String
+                 * key != null & value != null but key or(and) value can be
+                 * empty String
                  */
                 put(key, value);
             }
@@ -675,44 +660,41 @@
     /**
      * Writes all properties stored in this instance into the {@code
      * OutputStream} in XML representation. The DOCTYPE is
-     * 
+     *
      * <pre>
      * &lt;!DOCTYPE properties SYSTEM &quot;http://java.sun.com/dtd/properties.dtd&quot;&gt;
      * </pre>
-     * 
+     *
      * If the comment is null, no comment is added to the output. UTF-8 is used
      * as the encoding. The {@code OutputStream} is not closed at the end. A
      * call to this method is the same as a call to {@code storeToXML(os,
      * comment, "UTF-8")}.
-     * 
+     *
      * @param os the {@code OutputStream} to write to.
      * @param comment the comment to add. If null, no comment is added.
      * @throws IOException if an error occurs during writing to the output.
-     * @since Android 1.0
      */
-    public void storeToXML(OutputStream os, String comment) 
-            throws IOException {
-        storeToXML(os, comment, "UTF-8");
+    public void storeToXML(OutputStream os, String comment) throws IOException {
+        storeToXML(os, comment, "UTF-8"); //$NON-NLS-1$
     }
 
     /**
      * Writes all properties stored in this instance into the {@code
      * OutputStream} in XML representation. The DOCTYPE is
-     * 
+     *
      * <pre>
      * &lt;!DOCTYPE properties SYSTEM &quot;http://java.sun.com/dtd/properties.dtd&quot;&gt;
      * </pre>
-     * 
+     *
      * If the comment is null, no comment is added to the output. The parameter
      * {@code encoding} defines which encoding should be used. The {@code
      * OutputStream} is not closed at the end.
-     * 
+     *
      * @param os the {@code OutputStream} to write to.
      * @param comment the comment to add. If null, no comment is added.
      * @param encoding the code identifying the encoding that should be used to
      *            write into the {@code OutputStream}.
      * @throws IOException if an error occurs during writing to the output.
-     * @since Android 1.0
      */
     public synchronized void storeToXML(OutputStream os, String comment,
             String encoding) throws IOException {
@@ -720,14 +702,14 @@
         if (os == null || encoding == null) {
             throw new NullPointerException();
         }
-        
+
         /*
          * We can write to XML file using encoding parameter but note that some
          * aliases for encodings are not supported by the XML parser. Thus we
          * have to know canonical name for encoding used to store data in XML
          * since the XML parser must recognize encoding name used to store data.
          */
-        
+
         String encodingCanonicalName;
         try {
             encodingCanonicalName = Charset.forName(encoding).name();
@@ -741,18 +723,19 @@
             encodingCanonicalName = "UTF-8";
         }
 
-        PrintStream printStream = new PrintStream(os, false, encodingCanonicalName);
-        
+        PrintStream printStream = new PrintStream(os, false,
+                encodingCanonicalName);
+
         printStream.print("<?xml version=\"1.0\" encoding=\"");
         printStream.print(encodingCanonicalName);
         printStream.println("\"?>");
-        
+
         printStream.print("<!DOCTYPE properties SYSTEM \"");
         printStream.print(PROP_DTD_NAME);
         printStream.println("\">");
-        
+
         printStream.println("<properties>");
-        
+
         if (comment != null) {
             printStream.print("<comment>");
             printStream.print(substitutePredefinedEntries(comment));
@@ -771,18 +754,16 @@
         printStream.println("</properties>");
         printStream.flush();
     }
-    
+
     private String substitutePredefinedEntries(String s) {
-        
+
         /*
-         * substitution for predefined character entities
-         * to use them safely in XML
+         * substitution for predefined character entities to use them safely in
+         * XML
          */
-        return s.replaceAll("&", "&amp;")
-            .replaceAll("<", "&lt;")
-            .replaceAll(">", "&gt;")
-            .replaceAll("\u0027", "&apos;")
-            .replaceAll("\"", "&quot;");
+        return s.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(
+                ">", "&gt;").replaceAll("\u0027", "&apos;").replaceAll("\"",
+                "&quot;");
     }
 
     // BEGIN android-added
diff --git a/libcore/luni/src/main/java/java/util/PropertyPermission.java b/libcore/luni/src/main/java/java/util/PropertyPermission.java
index cdbfe34..1cd7143 100644
--- a/libcore/luni/src/main/java/java/util/PropertyPermission.java
+++ b/libcore/luni/src/main/java/java/util/PropertyPermission.java
@@ -39,8 +39,6 @@
  * <p>
  * There are two possible permission action types: read and write. Possible
  * actions are "read", "write", or "read,write"/"write,read".
- *  
- * @since Android 1.0
  */
 public final class PropertyPermission extends BasicPermission {
     private static final long serialVersionUID = 885438825399942851L;
@@ -56,7 +54,6 @@
      *            the actions which are applicable to it. Possible actions are
      *            "read", "write", or "read,write"/"write,read". Anything else
      *            will result in an {@code IllegalArgumentException}.
-     * @since Android 1.0
      */
     public PropertyPermission(String name, String actions) {
         super(name);
@@ -84,17 +81,16 @@
     /**
      * Compares the argument to the receiver, and returns true if they represent
      * the <em>same</em> object using a class specific comparison. In this
-     * case, the receiver must be a {@code PropertyPermission} for the same 
+     * case, the receiver must be a {@code PropertyPermission} for the same
      * property as the argument, and must have the same actions.
      * If {@code o} is a permission that is not a {@code PropertyPermission},
-     * this method may throw a {@code ClassCastException}.     
-     * 
+     * this method may throw a {@code ClassCastException}.
+     *
      * @param o
      *            the {@code Object} to compare with this {@code Object}.
      * @return {@code true} if the {@code Object} is the same as this {@code Object},
      *         {@code false} if it is different from this {@code Object}.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object o) {
@@ -110,7 +106,6 @@
      * either "read", "write", or "read,write".
      * 
      * @return the actions associated with the receiver.
-     * @since Android 1.0
      */
     @Override
     public String getActions() {
@@ -124,7 +119,6 @@
      * 
      * @return the receiver's hash.
      * @see #equals
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -138,7 +132,6 @@
      *         receiver, and {@code false} if it is not.
      * @param permission
      *            the permission to check.
-     * @since Android 1.0
      */
     @Override
     public boolean implies(Permission permission) {
@@ -155,7 +148,6 @@
      * 
      * @return a new {@code PermissionCollection} or {@code null}.
      * @see java.security.PermissionCollection
-     * @since Android 1.0
      */
     @Override
     public PermissionCollection newPermissionCollection() {
diff --git a/libcore/luni/src/main/java/java/util/PropertyPermissionCollection.java b/libcore/luni/src/main/java/java/util/PropertyPermissionCollection.java
index 45e89d9..bf88534 100644
--- a/libcore/luni/src/main/java/java/util/PropertyPermissionCollection.java
+++ b/libcore/luni/src/main/java/java/util/PropertyPermissionCollection.java
@@ -26,8 +26,6 @@
 
 /**
  * A {@code PermissionCollection} for holding {@code PropertyPermission}s.
- *  
- * @since Android 1.0
  */
 class PropertyPermissionCollection extends PermissionCollection {
 
diff --git a/libcore/luni/src/main/java/java/util/PropertyResourceBundle.java b/libcore/luni/src/main/java/java/util/PropertyResourceBundle.java
index acc3263..835e892 100644
--- a/libcore/luni/src/main/java/java/util/PropertyResourceBundle.java
+++ b/libcore/luni/src/main/java/java/util/PropertyResourceBundle.java
@@ -17,7 +17,6 @@
 
 package java.util;
 
-
 import java.io.IOException;
 import java.io.InputStream;
 
@@ -28,9 +27,10 @@
  * 
  * @see ResourceBundle
  * @see Properties
- * @since Android 1.0
+ * @since 1.1
  */
 public class PropertyResourceBundle extends ResourceBundle {
+
     Properties resources;
 
     /**
@@ -42,18 +42,23 @@
      * @throws IOException
      *             if an error occurs during a read operation on the
      *             {@code InputStream}.
-     * @since Android 1.0
      */
     public PropertyResourceBundle(InputStream stream) throws IOException {
         resources = new Properties();
         resources.load(stream);
     }
-    
+
     @SuppressWarnings("unchecked")
     private Enumeration<String> getLocalKeys() {
-        return (Enumeration<String>)resources.propertyNames();
+        return (Enumeration<String>) resources.propertyNames();
     }
 
+    /**
+     * Returns the names of the resources contained in this
+     * PropertyResourceBundle.
+     * 
+     * @return an Enumeration of the resource names
+     */
     @Override
     public Enumeration<String> getKeys() {
         if (parent == null) {
@@ -102,6 +107,14 @@
         };
     }
 
+    /**
+     * Returns the named resource from this PropertyResourceBundle, or null if
+     * the resource is not found.
+     * 
+     * @param key
+     *            the name of the resource
+     * @return the resource object
+     */
     @Override
     public Object handleGetObject(String key) {
         return resources.get(key);
diff --git a/libcore/luni/src/main/java/java/util/Queue.java b/libcore/luni/src/main/java/java/util/Queue.java
index 5035ce7..6ef776a 100644
--- a/libcore/luni/src/main/java/java/util/Queue.java
+++ b/libcore/luni/src/main/java/java/util/Queue.java
@@ -24,22 +24,17 @@
  * However, a priority queue orders its elements according to a comparator
  * specified or the elements' natural order. Furthermore, a stack orders its
  * elements last-in-first out.
- * </p>
  * <p>
  * A typical queue does not allow {@code null} to be inserted as its element,
  * while some implementations such as {@code LinkedList} allow it. But {@code
  * null} should not be inserted even in these implementations, since the method
  * {@code poll} returns {@code null} to indicate that there is no element left
  * in the queue.
- * </p>
  * <p>
  * {@code Queue} does not provide blocking queue methods, which would block
  * until the operation of the method is allowed. See the
  * {@link java.util.concurrent.BlockingQueue} interface for information about
  * blocking queue methods.
- * </p>
- * 
- * @since Android 1.0
  */
 public interface Queue<E> extends Collection<E> {
 
@@ -53,7 +48,6 @@
      *            the specified element to insert into the queue.
      * @return {@code true} if the operation succeeds and {@code false} if it
      *         fails.
-     * @since Android 1.0
      */
     public boolean offer(E o);
 
@@ -63,7 +57,6 @@
      * 
      * @return the element at the head of the queue or {@code null} if there is
      *         no element in the queue.
-     * @since Android 1.0
      */
     public E poll();
 
@@ -74,7 +67,6 @@
      * @return the element at the head of the queue.
      * @throws NoSuchElementException
      *             if there is no element in the queue.
-     * @since Android 1.0
      */
     public E remove();
 
@@ -83,7 +75,6 @@
      * 
      * @return the element at the head of the queue or {@code null} if there is
      *         no element in the queue.
-     * @since Android 1.0
      */
     public E peek();
 
@@ -94,7 +85,6 @@
      * @return the element at the head of the queue.
      * @throws NoSuchElementException
      *             if there is no element in the queue.
-     * @since Android 1.0
      */
     public E element();
 
diff --git a/libcore/luni/src/main/java/java/util/Random.java b/libcore/luni/src/main/java/java/util/Random.java
index f92c3ee..be27258 100644
--- a/libcore/luni/src/main/java/java/util/Random.java
+++ b/libcore/luni/src/main/java/java/util/Random.java
@@ -26,44 +26,40 @@
  * 
  * @see Properties
  * @see PropertyResourceBundle
- * @since Android 1.0
  */
 public class Random implements Serializable {
     
     private static final long serialVersionUID = 3905348978240129619L;
 
-    static final long multiplier = 0x5deece66dL;
+    private static final long multiplier = 0x5deece66dL;
 
     /**
      * The boolean value indicating if the second Gaussian number is available.
      * 
      * @serial
      */
-    boolean haveNextNextGaussian = false;
+    private boolean haveNextNextGaussian;
 
     /**
-     * It is associated with the internal state of this generator.
-     *      
-     * @serial
+     * @serial It is associated with the internal state of this generator.
      */
-    long seed;
+    private long seed;
 
     /**
      * The second Gaussian generated number.
      * 
      * @serial
      */
-    double nextNextGaussian = 0;
+    private double nextNextGaussian;
 
     /**
      * Construct a random generator with the current time of day in milliseconds
      * as the initial state.
      * 
      * @see #setSeed
-     * @since Android 1.0
      */
     public Random() {
-        setSeed(System.currentTimeMillis());
+        setSeed(System.currentTimeMillis() + hashCode());
     }
 
     /**
@@ -74,7 +70,6 @@
      *            the seed that will determine the initial state of this random
      *            number generator.
      * @see #setSeed
-     * @since Android 1.0
      */
     public Random(long seed) {
         setSeed(seed);
@@ -89,7 +84,6 @@
      * @param bits
      *            number of bits of the returned value.
      * @return a pseudo-random generated int number.
-     * @since Android 1.0
      * @see #nextBytes
      * @see #nextDouble
      * @see #nextFloat
@@ -97,7 +91,6 @@
      * @see #nextInt(int)
      * @see #nextGaussian
      * @see #nextLong
-     * @since Android 1.0
      */
     protected synchronized int next(int bits) {
         seed = (seed * multiplier + 0xbL) & ((1L << 48) - 1);
@@ -109,7 +102,6 @@
      * generated by this generator.
      * 
      * @return a pseudo-random, uniformly distributed boolean value.
-     * @since Android 1.0
      */
     public boolean nextBoolean() {
         return next(1) != 0;
@@ -122,7 +114,6 @@
      * @param buf
      *            non-null array to contain the new random {@code byte}s.
      * @see #next
-     * @since Android 1.0
      */
     public void nextBytes(byte[] buf) {
         int rand = 0, count = 0, loop = 0;
@@ -144,7 +135,6 @@
      * 
      * @return a random {@code double} in the range [0.0 - 1.0)
      * @see #nextFloat
-     * @since Android 1.0
      */
     public double nextDouble() {
         return ((((long) next(26) << 27) + next(27)) / (double) (1L << 53));
@@ -156,7 +146,6 @@
      * 
      * @return float a random {@code float} number between [0.0 and 1.0)
      * @see #nextDouble
-     * @since Android 1.0
      */
     public float nextFloat() {
         return (next(24) / 16777216f);
@@ -172,7 +161,6 @@
      * 
      * @return a random {@code double}
      * @see #nextDouble
-     * @since Android 1.0
      */
     public synchronized double nextGaussian() {
         if (haveNextNextGaussian) { // if X1 has been returned, return the
@@ -205,7 +193,6 @@
      * @see java.lang.Integer#MIN_VALUE
      * @see #next
      * @see #nextLong
-     * @since Android 1.0
      */
     public int nextInt() {
         return next(32);
@@ -218,7 +205,6 @@
      * @param n
      *            the exclusive upper border of the range [0 - n).
      * @return a random {@code int}.
-     * @since Android 1.0
      */
     public int nextInt(int n) {
         if (n > 0) {
@@ -245,7 +231,6 @@
      * @see #next
      * @see #nextInt()
      * @see #nextInt(int)
-     * @since Android 1.0
      */
     public long nextLong() {
         return ((long) next(32) << 32) + next(32);
@@ -260,7 +245,6 @@
      * @see #next
      * @see #Random()
      * @see #Random(long)
-     * @since Android 1.0
      */
     public synchronized void setSeed(long seed) {
         this.seed = (seed ^ multiplier) & ((1L << 48) - 1);
diff --git a/libcore/luni/src/main/java/java/util/RandomAccess.java b/libcore/luni/src/main/java/java/util/RandomAccess.java
index a8a90de..7121bff 100644
--- a/libcore/luni/src/main/java/java/util/RandomAccess.java
+++ b/libcore/luni/src/main/java/java/util/RandomAccess.java
@@ -17,13 +17,10 @@
 
 package java.util;
 
-
 /**
  * RandomAccess is implemented by {@code List} implementations that support fast
  * (usually constant time) random access.
- * 
- * @since Android 1.0
  */
 public interface RandomAccess {
-    /*empty*/
+    /* empty */
 }
diff --git a/libcore/luni/src/main/java/java/util/ResourceBundle.java b/libcore/luni/src/main/java/java/util/ResourceBundle.java
index 1187358..218d3f3 100644
--- a/libcore/luni/src/main/java/java/util/ResourceBundle.java
+++ b/libcore/luni/src/main/java/java/util/ResourceBundle.java
@@ -27,6 +27,7 @@
 import com.ibm.icu4jni.util.Resources;
 import dalvik.system.VMStack;
 // END android-changed
+import org.apache.harmony.luni.util.Msg;
 
 /**
  * {@code ResourceBundle} is an abstract class which is the superclass of classes which
@@ -35,7 +36,7 @@
  * and when a resource is not found in a bundle, the parent bundle is searched for
  * the resource. If the fallback mechanism reaches the base bundle and still
  * can't find the resource it throws a {@code MissingResourceException}.
- * 
+ *
  * <ul>
  * <li>All bundles for the same group of resources share a common base bundle.
  * This base bundle acts as the root and is the last fallback in case none of
@@ -53,7 +54,7 @@
  * current currency (Euro) and the {@code PREEURO} variant bundle would return the old
  * currency (e.g. DM for Germany).</li>
  * </ul>
- * 
+ *
  * <strong>Examples</strong>
  * <ul>
  * <li>BaseName (base bundle)
@@ -67,24 +68,22 @@
  * <li>BaseName_fr_FR_PREEURO (bundle with France specific resources in french of
  * the time before the Euro)
  * </ul>
- * 
+ *
  * It's also possible to create variants for languages or countries. This can be
  * done by just skipping the country or language abbreviation:
  * BaseName_us__POSIX or BaseName__DE_PREEURO. But it's not allowed to
  * circumvent both language and country: BaseName___VARIANT is illegal.
- * 
+ *
  * @see Properties
  * @see PropertyResourceBundle
  * @see ListResourceBundle
- * @since Android 1.0
+ * @since 1.1
  */
 public abstract class ResourceBundle {
 
     /**
      * The parent of this {@code ResourceBundle} that is used if this bundle doesn't
      * include the requested resource.
-     * 
-     * @since Android 1.0
      */
     protected ResourceBundle parent;
 
@@ -114,8 +113,6 @@
 
     /**
      * Constructs a new instance of this class.
-     * 
-     * @since Android 1.0
      */
     public ResourceBundle() {
         /* empty */
@@ -124,13 +121,12 @@
     /**
      * Finds the named resource bundle for the default {@code Locale} and the caller's
      * {@code ClassLoader}.
-     * 
+     *
      * @param bundleName
      *            the name of the {@code ResourceBundle}.
      * @return the requested {@code ResourceBundle}.
-     * @exception MissingResourceException
+     * @throws MissingResourceException
      *                if the {@code ResourceBundle} cannot be found.
-     * @since Android 1.0
      */
     public static final ResourceBundle getBundle(String bundleName)
             throws MissingResourceException {
@@ -143,15 +139,14 @@
     /**
      * Finds the named {@code ResourceBundle} for the specified {@code Locale} and the caller
      * {@code ClassLoader}.
-     * 
+     *
      * @param bundleName
      *            the name of the {@code ResourceBundle}.
      * @param locale
      *            the {@code Locale}.
      * @return the requested resource bundle.
-     * @exception MissingResourceException
+     * @throws MissingResourceException
      *                if the resource bundle cannot be found.
-     * @since Android 1.0
      */
     public static final ResourceBundle getBundle(String bundleName,
             Locale locale) {
@@ -163,17 +158,17 @@
 
     /**
      * Finds the named resource bundle for the specified {@code Locale} and {@code ClassLoader}.
-     * 
+     *
      * The passed base name and {@code Locale} are used to create resource bundle names.
      * The first name is created by concatenating the base name with the result
      * of {@link Locale#toString()}. From this name all parent bundle names are
      * derived. Then the same thing is done for the default {@code Locale}. This results
      * in a list of possible bundle names.
-     * 
+     *
      * <strong>Example</strong> For the basename "BaseName", the {@code Locale} of the
      * German part of Switzerland (de_CH) and the default {@code Locale} en_US the list
      * would look something like this:
-     * 
+     *
      * <ol>
      * <li>BaseName_de_CH</li>
      * <li>BaseName_de</li>
@@ -181,11 +176,11 @@
      * <li>Basename_en</li>
      * <li>BaseName</li>
      * </ol>
-     * 
+     *
      * This list also shows the order in which the bundles will be searched for a requested
      * resource in the German part of Switzerland (de_CH).
-     * 
-     * As a first step, this method tries to instantiate 
+     *
+     * As a first step, this method tries to instantiate
      * a {@code ResourceBundle} with the names provided.
      * If such a class can be instantiated and initialized, it is returned and
      * all the parent bundles are instantiated too. If no such class can be
@@ -195,11 +190,11 @@
      * by calling {@link ClassLoader#getResource(String)} it is used to
      * initialize a {@link PropertyResourceBundle}. If this succeeds, it will
      * also load the parents of this {@code ResourceBundle}.
-     * 
+     *
      * For compatibility with older code, the bundle name isn't required to be
      * a fully qualified class name. It's also possible to directly pass
      * the path to a properties file (without a file extension).
-     * 
+     *
      * @param bundleName
      *            the name of the {@code ResourceBundle}.
      * @param locale
@@ -207,9 +202,8 @@
      * @param loader
      *            the {@code ClassLoader} to use.
      * @return the requested {@code ResourceBundle}.
-     * @exception MissingResourceException
+     * @throws MissingResourceException
      *                if the {@code ResourceBundle} cannot be found.
-     * @since Android 1.0
      */
     public static ResourceBundle getBundle(String bundleName, Locale locale,
             ClassLoader loader) throws MissingResourceException {
@@ -248,7 +242,7 @@
             if ((bundle = handleGetBundle(bundleName, localeName, true, loader)) != null) {
                 return bundle;
             }
-            throw new MissingResourceException(null, bundleName + '_' + locale,
+            throw new MissingResourceException(Msg.getString("KA029", bundleName, locale), bundleName + '_' + locale, //$NON-NLS-1$
                     ""); //$NON-NLS-1$
         }
         throw new NullPointerException();
@@ -256,9 +250,8 @@
 
     /**
      * Returns the names of the resources contained in this {@code ResourceBundle}.
-     * 
+     *
      * @return an {@code Enumeration} of the resource names.
-     * @since Android 1.0
      */
     public abstract Enumeration<String> getKeys();
 
@@ -266,9 +259,8 @@
      * Gets the {@code Locale} of this {@code ResourceBundle}. In case a bundle was not
      * found for the requested {@code Locale}, this will return the actual {@code Locale} of
      * this resource bundle that was found after doing a fallback.
-     * 
+     *
      * @return the {@code Locale} of this {@code ResourceBundle}.
-     * @since Android 1.0
      */
     public Locale getLocale() {
         return locale;
@@ -279,13 +271,12 @@
      * cannot be found in this bundle, it falls back to the parent bundle (if
      * it's not null) by calling the {@link #handleGetObject} method. If the resource still
      * can't be found it throws a {@code MissingResourceException}.
-     * 
+     *
      * @param key
      *            the name of the resource.
      * @return the resource object.
-     * @exception MissingResourceException
+     * @throws MissingResourceException
      *                if the resource is not found.
-     * @since Android 1.0
      */
     public final Object getObject(String key) {
         ResourceBundle last, theParent = this;
@@ -297,21 +288,20 @@
             last = theParent;
             theParent = theParent.parent;
         } while (theParent != null);
-        throw new MissingResourceException(null, last.getClass().getName(), key);
+        throw new MissingResourceException(Msg.getString("KA029", last.getClass().getName(), key), last.getClass().getName(), key); //$NON-NLS-1$
     }
 
     /**
      * Returns the named string resource from this {@code ResourceBundle}.
-     * 
+     *
      * @param key
      *            the name of the resource.
      * @return the resource string.
-     * @exception MissingResourceException
+     * @throws MissingResourceException
      *                if the resource is not found.
-     * @exception ClassCastException
+     * @throws ClassCastException
      *                if the resource found is not a string.
      * @see #getObject(String)
-     * @since Android 1.0
      */
     public final String getString(String key) {
         return (String) getObject(key);
@@ -319,16 +309,15 @@
 
     /**
      * Returns the named resource from this {@code ResourceBundle}.
-     * 
+     *
      * @param key
      *            the name of the resource.
      * @return the resource string array.
-     * @exception MissingResourceException
+     * @throws MissingResourceException
      *                if the resource is not found.
-     * @exception ClassCastException
+     * @throws ClassCastException
      *                if the resource found is not an array of strings.
      * @see #getObject(String)
-     * @since Android 1.0
      */
     public final String[] getStringArray(String key) {
         return (String[]) getObject(key);
@@ -343,7 +332,7 @@
         synchronized (cache) {
             loaderCache = cache.get(cacheKey);
             if (loaderCache == null) {
-                loaderCache = new Hashtable<String, ResourceBundle>(13);
+                loaderCache = new Hashtable<String, ResourceBundle>();
                 cache.put(cacheKey, loaderCache);
             }
         }
@@ -389,13 +378,9 @@
         } catch (Exception e) {
         }
 
-        // BEGIN android-added
-        // copied from newer version of Harmony
         if (bundle != null) {
             bundle.setLocale(locale);
-        }
-        // END android-added
-        if (bundle == null) {
+        } else {
             final String fileName = bundleName.replace('.', '/');
             InputStream stream = AccessController
                     .doPrivileged(new PrivilegedAction<InputStream>() {
@@ -447,21 +432,19 @@
     /**
      * Returns the named resource from this {@code ResourceBundle}, or null if the
      * resource is not found.
-     * 
+     *
      * @param key
      *            the name of the resource.
      * @return the resource object.
-     * @since Android 1.0
      */
     protected abstract Object handleGetObject(String key);
 
     /**
      * Sets the parent resource bundle of this {@code ResourceBundle}. The parent is
      * searched for resources which are not found in this {@code ResourceBundle}.
-     * 
+     *
      * @param bundle
      *            the parent {@code ResourceBundle}.
-     * @since Android 1.0
      */
     protected void setParent(ResourceBundle bundle) {
         parent = bundle;
diff --git a/libcore/luni/src/main/java/java/util/Scanner.java b/libcore/luni/src/main/java/java/util/Scanner.java
index acacebb..dd5c024 100644
--- a/libcore/luni/src/main/java/java/util/Scanner.java
+++ b/libcore/luni/src/main/java/java/util/Scanner.java
@@ -44,7 +44,7 @@
  * next* methods. If the token is not in a valid format, an
  * {@code InputMismatchException} is thrown.
  * <p>
- * For example: </p>
+ * For example:
  * <pre>
  * Scanner s = new Scanner("1A true");
  * System.out.println(s.nextInt(16));
@@ -52,28 +52,25 @@
  * </pre>
  * <p>
  * Yields the result: {@code 26 true}
- * </p>
  * <p>A {@code Scanner} can also find or skip specific patterns without regard for the
  * delimiter. All these methods and the various next* and hasNext* methods may
  * block.
- * </p>
+ * <p>
  * The {@code Scanner} class is not thread-safe.
- * @since Android 1.0
  */
 public final class Scanner implements Iterator<String> {
 
-    //  Default delimiting pattern.
+    // Default delimiting pattern.
     private static final Pattern DEFAULT_DELIMITER = Pattern
             .compile("\\p{javaWhitespace}+"); //$NON-NLS-1$
-    
+
     // The boolean's pattern.
     private static final Pattern BOOLEAN_PATTERN = Pattern.compile(
             "true|false", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
-    
-    
+
     // Pattern used to recognize line terminator.
     private static final Pattern LINE_TERMINATOR;
-    
+
     // Pattern used to recognize multiple line terminators.
     private static final Pattern MULTI_LINE_TERMINATOR;
 
@@ -81,24 +78,22 @@
     private static final Pattern LINE_PATTERN;
 
     static {
-        String terminator = "\n|\r\n|\r|\u0085|\u2028|\u2029";  //$NON-NLS-1$
-        
+        String terminator = "\n|\r\n|\r|\u0085|\u2028|\u2029"; //$NON-NLS-1$
+
         LINE_TERMINATOR = Pattern.compile(terminator);
-        
+
+        // BEGIN android-note
+        // consider plain old string concatenation for better performance
+        // END android-note
         StringBuilder multiTerminator = new StringBuilder();
-        MULTI_LINE_TERMINATOR = Pattern
-            .compile(multiTerminator.append("(") //$NON-NLS-1$
-                    .append(terminator)
-                    .append(")+").toString()); //$NON-NLS-1$
+        MULTI_LINE_TERMINATOR = Pattern.compile(multiTerminator.append("(") //$NON-NLS-1$
+                .append(terminator).append(")+").toString()); //$NON-NLS-1$
         StringBuilder line = new StringBuilder();
-        LINE_PATTERN = Pattern
-            .compile(line.append(".*(") //$NON-NLS-1$
-                    .append(terminator)
-                    .append(")|.+(") //$NON-NLS-1$
-                    .append(terminator)
-                    .append(")?").toString()); //$NON-NLS-1$
+        LINE_PATTERN = Pattern.compile(line.append(".*(") //$NON-NLS-1$
+                .append(terminator).append(")|.+(") //$NON-NLS-1$
+                .append(terminator).append(")?").toString()); //$NON-NLS-1$
     }
-    
+
     // The pattern matches anything.
     private static final Pattern ANY_PATTERN = Pattern.compile("(?s).*"); //$NON-NLS-1$
 
@@ -131,24 +126,24 @@
     // The length of the buffer.
     private int bufferLength = 0;
 
-    // Record the status of this scanner. True if the scanner 
+    // Record the status of this scanner. True if the scanner
     // is closed.
     private boolean closed = false;
 
     private IOException lastIOException;
-    
+
     private boolean matchSuccessful = false;
-    
+
     private DecimalFormat decimalFormat;
-    
+
     // Records whether the underlying readable has more input.
     private boolean inputExhausted = false;
-    
+
     private Object cacheHasNextValue = null;
-    
+
     private int cachehasNextIndex = -1;
-    
-    private enum DataType{
+
+    private enum DataType {
         /*
          * Stands for Integer
          */
@@ -162,12 +157,11 @@
     /**
      * Creates a {@code Scanner} with the specified {@code File} as input. The default charset
      * is applied when reading the file.
-     * 
+     *
      * @param src
      *            the file to be scanned.
      * @throws FileNotFoundException
      *             if the specified file does not exist.
-     * @since Android 1.0
      */
     public Scanner(File src) throws FileNotFoundException {
         this(src, Charset.defaultCharset().name());
@@ -176,7 +170,7 @@
     /**
      * Creates a {@code Scanner} with the specified {@code File} as input. The specified charset
      * is applied when reading the file.
-     * 
+     *
      * @param src
      *            the file to be scanned.
      * @param charsetName
@@ -185,7 +179,6 @@
      *             if the specified file does not exist.
      * @throws IllegalArgumentException
      *             if the specified coding does not exist.
-     * @since Android 1.0
      */
     public Scanner(File src, String charsetName) throws FileNotFoundException {
         if (null == src) {
@@ -212,10 +205,9 @@
 
     /**
      * Creates a {@code Scanner} on the specified string.
-     * 
+     *
      * @param src
      *            the string to be scanned.
-     * @since Android 1.0
      */
     public Scanner(String src) {
         input = new StringReader(src);
@@ -225,10 +217,9 @@
     /**
      * Creates a {@code Scanner} on the specified {@code InputStream}. The default charset is
      * applied when decoding the input.
-     * 
+     *
      * @param src
      *            the {@code InputStream} to be scanned.
-     * @since Android 1.0
      */
     public Scanner(InputStream src) {
         this(src, Charset.defaultCharset().name());
@@ -237,14 +228,13 @@
     /**
      * Creates a {@code Scanner} on the specified {@code InputStream}. The specified charset is
      * applied when decoding the input.
-     * 
+     *
      * @param src
      *            the {@code InputStream} to be scanned.
      * @param charsetName
      *            the encoding type of the {@code InputStream}.
      * @throws IllegalArgumentException
      *             if the specified character set is not found.
-     * @since Android 1.0
      */
     public Scanner(InputStream src, String charsetName) {
         if (null == src) {
@@ -261,10 +251,9 @@
 
     /**
      * Creates a {@code Scanner} with the specified {@code Readable} as input.
-     * 
+     *
      * @param src
      *            the {@code Readable} to be scanned.
-     * @since Android 1.0
      */
     public Scanner(Readable src) {
         if (null == src) {
@@ -277,10 +266,9 @@
     /**
      * Creates a {@code Scanner} with the specified {@code ReadableByteChannel} as
      * input. The default charset is applied when decoding the input.
-     * 
+     *
      * @param src
      *            the {@code ReadableByteChannel} to be scanned.
-     * @since Android 1.0
      */
     public Scanner(ReadableByteChannel src) {
         this(src, Charset.defaultCharset().name());
@@ -289,14 +277,13 @@
     /**
      * Creates a {@code Scanner} with the specified {@code ReadableByteChannel} as
      * input. The specified charset is applied when decoding the input.
-     * 
+     *
      * @param src
      *            the {@code ReadableByteChannel} to be scanned.
      * @param charsetName
      *            the encoding type of the content.
      * @throws IllegalArgumentException
      *             if the specified character set is not found.
-     * @since Android 1.0
      */
     public Scanner(ReadableByteChannel src, String charsetName) {
         if (null == src) {
@@ -316,9 +303,8 @@
      * {@code Closeable}. If the {@code Scanner} has been closed, this method will have
      * no effect. Any scanning operation called after calling this method will throw
      * an {@code IllegalStateException}.
-     * 
+     *
      * @see Closeable
-     * @since Android 1.0
      */
     public void close() {
         if (closed) {
@@ -336,9 +322,8 @@
 
     /**
      * Returns the delimiter {@code Pattern} in use by this {@code Scanner}.
-     * 
+     *
      * @return the delimiter {@code Pattern} in use by this {@code Scanner}.
-     * @since Android 1.0
      */
     public Pattern delimiter() {
         return delimiter;
@@ -351,14 +336,13 @@
      * Otherwise, {@code null} will be returned and the {@code Scanner} will not advance.
      * When waiting for input, the {@code Scanner} may be blocked. All the
      * input may be cached if no line terminator exists in the buffer.
-     * 
+     *
      * @param pattern
      *            the pattern to find in the input.
      * @return the matched string or {@code null} if the pattern is not found
      *         before the next line terminator.
      * @throws IllegalStateException
      *             if the {@code Scanner} is closed.
-     * @since Android 1.0
      */
     public String findInLine(Pattern pattern) {
         checkClosed();
@@ -395,17 +379,32 @@
          * bug is fixed.
          */
         int oldLimit = buffer.limit();
-        buffer.limit(horizonLineSeparator);
+        // Considering the look ahead feature, the line terminator should be involved as RI
+        buffer.limit(horizonLineSeparator + terminatorLength);
         // ========== To deal with regex bug ====================
 
-        matcher.region(findStartIndex, horizonLineSeparator);
+        // Considering the look ahead feature, the line terminator should be involved as RI
+        matcher.region(findStartIndex, horizonLineSeparator + terminatorLength);
         if (matcher.find()) {
             // The scanner advances past the input that matched
             findStartIndex = matcher.end();
-            // If the matched pattern is immediately followed by line terminator. 
-            if(horizonLineSeparator == matcher.end()) {
+            // If the matched pattern is immediately followed by line
+            // terminator.
+            if (horizonLineSeparator == matcher.end()) {
                 findStartIndex += terminatorLength;
             }
+            // the line terminator itself should not be a part of
+            // the match result according to the Spec
+            if (horizonLineSeparator != bufferLength
+                    && (horizonLineSeparator + terminatorLength == matcher
+                            .end())) {
+                // ========== To deal with regex bug ====================
+                buffer.limit(oldLimit);
+                // ========== To deal with regex bug ====================
+
+                matchSuccessful = false;
+                return null;
+            }
             matchSuccessful = true;
 
             // ========== To deal with regex bug ====================
@@ -427,7 +426,7 @@
      * Compiles the pattern string and tries to find a substing matching it in the input data. The
      * delimiter will be ignored. This is the same as invoking
      * {@code findInLine(Pattern.compile(pattern))}.
-     * 
+     *
      * @param pattern
      *            a string used to construct a pattern which is in turn used to
      *            match a substring of the input data.
@@ -436,7 +435,6 @@
      * @throws IllegalStateException
      *             if the {@code Scanner} is closed.
      * @see #findInLine(Pattern)
-     * @since Android 1.0
      */
     public String findInLine(String pattern) {
         return findInLine(Pattern.compile(pattern));
@@ -450,7 +448,7 @@
      * advance. When waiting for input, the {@code Scanner} may be blocked.
      * <p>
      * The {@code Scanner}'s search will never go more than {@code horizon} code points from current
-     * position. The position of {@code horizon} does have an effect on the result of the 
+     * position. The position of {@code horizon} does have an effect on the result of the
      * match. For example, when the input is "123" and current position is at zero,
      * {@code findWithinHorizon(Pattern.compile("\\p&#123;Digit&#125;&#123;3&#125;"), 2)}
      * will return {@code null}. While
@@ -459,10 +457,10 @@
      * non-anchoring bound. (refer to
      * {@link Matcher#useTransparentBounds(boolean)} and
      * {@link Matcher#useAnchoringBounds(boolean)})
-     * </p>
+     * <p>
      * A {@code horizon} whose value is zero will be ignored and the whole input will be
      * used for search. In this situation, all the input may be cached.
-     * 
+     *
      * @param pattern
      *            the pattern used to scan.
      * @param horizon
@@ -473,7 +471,6 @@
      *             if the {@code Scanner} is closed.
      * @throws IllegalArgumentException
      *             if {@code horizon} is less than zero.
-     * @since Android 1.0
      */
     public String findWithinHorizon(Pattern pattern, int horizon) {
         checkClosed();
@@ -538,7 +535,7 @@
      * Tries to find the pattern in the input between the current position and the specified
      * {@code horizon}. Delimiters are ignored. This call is the same as invoking
      * {@code findWithinHorizon(Pattern.compile(pattern))}.
-     * 
+     *
      * @param pattern
      *            the pattern used to scan.
      * @param horizon
@@ -550,7 +547,6 @@
      * @throws IllegalArgumentException
      *             if {@code horizon} is less than zero.
      * @see #findWithinHorizon(Pattern, int)
-     * @since Android 1.0
      */
     public String findWithinHorizon(String pattern, int horizon) {
         return findWithinHorizon(Pattern.compile(pattern), horizon);
@@ -559,12 +555,11 @@
     /**
      * Returns whether this {@code Scanner} has one or more tokens remaining to parse.
      * This method will block if the data is still being read.
-     * 
+     *
      * @return {@code true} if this {@code Scanner} has one or more tokens remaining,
      *         otherwise {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNext() {
         return hasNext(ANY_PATTERN);
@@ -574,28 +569,28 @@
      * Returns whether this {@code Scanner} has one or more tokens remaining to parse
      * and the next token matches the given pattern. This method will block if the data is
      * still being read.
-     * 
+     *
      * @param pattern
      *            the pattern to check for.
      * @return {@code true} if this {@code Scanner} has more tokens and the next token
      *         matches the pattern, {@code false} otherwise.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNext(Pattern pattern) {
         checkClosed();
         checkNull(pattern);
         matchSuccessful = false;
         saveCurrentStatus();
-        //if the next token exists, set the match region, otherwise return false
+        // if the next token exists, set the match region, otherwise return
+        // false
         if (!setTokenRegion()) {
             recoverPreviousStatus();
             return false;
         }
         matcher.usePattern(pattern);
         boolean hasNext = false;
-        //check whether next token matches the specified pattern
+        // check whether next token matches the specified pattern
         if (matcher.matches()) {
             cachehasNextIndex = findStartIndex;
             matchSuccessful = true;
@@ -605,20 +600,18 @@
         return hasNext;
     }
 
-
     /**
      * Returns {@code true} if this {@code Scanner} has one or more tokens remaining to parse
      * and the next token matches a pattern compiled from the given string. This method will
      * block if the data is still being read. This call is equivalent to
      * {@code hasNext(Pattern.compile(pattern))}.
-     * 
+     *
      * @param pattern
      *            the string specifying the pattern to scan for
      * @return {@code true} if the specified pattern matches this {@code Scanner}'s
      *         next token, {@code false} otherwise.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNext(String pattern) {
         return hasNext(Pattern.compile(pattern));
@@ -627,12 +620,11 @@
     /**
      * Returns whether the next token can be translated into a valid
      * {@code BigDecimal}.
-     * 
+     *
      * @return {@code true} if the next token can be translated into a valid
      *         {@code BigDecimal}, otherwise {@code false.}
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNextBigDecimal() {
         Pattern floatPattern = getFloatPattern();
@@ -653,12 +645,11 @@
     /**
      * Returns whether the next token can be translated into a valid
      * {@code BigInteger} in the default radix.
-     * 
+     *
      * @return {@code true} if the next token can be translated into a valid
      *         {@code BigInteger}, otherwise {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNextBigInteger() {
         return hasNextBigInteger(integerRadix);
@@ -667,7 +658,7 @@
     /**
      * Returns whether the next token can be translated into a valid
      * {@code BigInteger} in the specified radix.
-     * 
+     *
      * @param radix
      *            the radix used to translate the token into a
      *            {@code BigInteger}.
@@ -675,7 +666,6 @@
      *         {@code BigInteger}, otherwise {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNextBigInteger(int radix) {
         Pattern integerPattern = getIntegerPattern(radix);
@@ -696,12 +686,11 @@
     /**
      * Returns whether the next token can be translated into a valid
      * {@code boolean} value.
-     * 
+     *
      * @return {@code true} if the next token can be translated into a valid
      *         {@code boolean} value, otherwise {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNextBoolean() {
         return hasNext(BOOLEAN_PATTERN);
@@ -710,12 +699,11 @@
     /**
      * Returns whether the next token can be translated into a valid
      * {@code byte} value in the default radix.
-     * 
+     *
      * @return {@code true} if the next token can be translated into a valid
      *         {@code byte} value, otherwise {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNextByte() {
         return hasNextByte(integerRadix);
@@ -724,7 +712,7 @@
     /**
      * Returns whether the next token can be translated into a valid
      * {@code byte} value in the specified radix.
-     * 
+     *
      * @param radix
      *            the radix used to translate the token into a {@code byte}
      *            value
@@ -732,7 +720,6 @@
      *         {@code byte} value, otherwise {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNextByte(int radix) {
         Pattern integerPattern = getIntegerPattern(radix);
@@ -753,12 +740,11 @@
     /**
      * Returns whether the next token translated into a valid {@code double}
      * value.
-     * 
+     *
      * @return {@code true} if the next token can be translated into a valid
      *         {@code double} value, otherwise {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNextDouble() {
         Pattern floatPattern = getFloatPattern();
@@ -779,12 +765,11 @@
     /**
      * Returns whether the next token can be translated into a valid
      * {@code float} value.
-     * 
+     *
      * @return {@code true} if the next token can be translated into a valid
      *         {@code float} value, otherwise {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNextFloat() {
         Pattern floatPattern = getFloatPattern();
@@ -805,12 +790,11 @@
     /**
      * Returns whether the next token can be translated into a valid {@code int}
      * value in the default radix.
-     * 
+     *
      * @return {@code true} if the next token can be translated into a valid
      *         {@code int} value, otherwise {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed,
-     * @since Android 1.0
      */
     public boolean hasNextInt() {
         return hasNextInt(integerRadix);
@@ -819,7 +803,7 @@
     /**
      * Returns whether the next token can be translated into a valid {@code int}
      * value in the specified radix.
-     * 
+     *
      * @param radix
      *            the radix used to translate the token into an {@code int}
      *            value.
@@ -828,7 +812,6 @@
      *         {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNextInt(int radix) {
         Pattern integerPattern = getIntegerPattern(radix);
@@ -849,12 +832,11 @@
     /**
      * Returns whether there is a line terminator in the input.
      * This method may block.
-     * 
+     *
      * @return {@code true} if there is a line terminator in the input,
      *         otherwise, {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} is closed.
-     * @since Android 1.0
      */
     public boolean hasNextLine() {
         checkClosed();
@@ -886,12 +868,11 @@
     /**
      * Returns whether the next token can be translated into a valid
      * {@code long} value in the default radix.
-     * 
+     *
      * @return {@code true} if the next token can be translated into a valid
      *         {@code long} value, otherwise {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNextLong() {
         return hasNextLong(integerRadix);
@@ -900,7 +881,7 @@
     /**
      * Returns whether the next token can be translated into a valid
      * {@code long} value in the specified radix.
-     * 
+     *
      * @param radix
      *            the radix used to translate the token into a {@code long}
      *            value.
@@ -908,7 +889,6 @@
      *         {@code long} value, otherwise {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNextLong(int radix) {
         Pattern integerPattern = getIntegerPattern(radix);
@@ -926,16 +906,14 @@
         return isLongValue;
     }
 
-
     /**
      * Returns whether the next token can be translated into a valid
      * {@code short} value in the default radix.
-     * 
+     *
      * @return {@code true} if the next token can be translated into a valid
      *         {@code short} value, otherwise {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNextShort() {
         return hasNextShort(integerRadix);
@@ -944,7 +922,7 @@
     /**
      * Returns whether the next token can be translated into a valid
      * {@code short} value in the specified radix.
-     * 
+     *
      * @param radix
      *            the radix used to translate the token into a {@code short}
      *            value.
@@ -952,7 +930,6 @@
      *         {@code short} value, otherwise {@code false}.
      * @throws IllegalStateException
      *             if the {@code Scanner} has been closed.
-     * @since Android 1.0
      */
     public boolean hasNextShort(int radix) {
         Pattern integerPattern = getIntegerPattern(radix);
@@ -973,9 +950,8 @@
     /**
      * Returns the last {@code IOException} that was raised while reading from the underlying
      * input.
-     * 
+     *
      * @return the last thrown {@code IOException}, or {@code null} if none was thrown.
-     * @since Android 1.0
      */
     public IOException ioException() {
         return lastIOException;
@@ -983,9 +959,8 @@
 
     /**
      * Return the {@code Locale} of this {@code Scanner}.
-     * 
+     *
      * @return the {@code Locale} of this {@code Scanner}.
-     * @since Android 1.0
      */
     public Locale locale() {
         return locale;
@@ -996,13 +971,11 @@
      * <p>
      * The next* and find* methods return the match result in the case of a
      * successful match.
-     * </p>
-     * 
+     *
      * @return the match result of the last successful match operation
      * @throws IllegalStateException
      *             if the match result is not available, of if the last match
      *             was not successful.
-     * @since Android 1.0
      */
     public MatchResult match() {
         if (!matchSuccessful) {
@@ -1015,13 +988,12 @@
      * Returns the next token. 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.
-     * 
+     *
      * @return the next complete token.
      * @throws IllegalStateException
      *             if this {@code Scanner} has been closed.
      * @throws NoSuchElementException
      *             if input has been exhausted.
-     * @since Android 1.0
      */
     public String next() {
         return next(ANY_PATTERN);
@@ -1032,7 +1004,7 @@
      * 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.
-     * 
+     *
      * @param pattern
      *            the specified pattern to scan.
      * @return the next token.
@@ -1042,7 +1014,6 @@
      *             if input has been exhausted.
      * @throws InputMismatchException
      *             if the next token does not match the pattern given.
-     * @since Android 1.0
      */
     public String next(Pattern pattern) {
         checkClosed();
@@ -1070,7 +1041,7 @@
      * 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
      * {@code next(Pattern.compile(pattern))}.
-     * 
+     *
      * @param pattern
      *            the string specifying the pattern to scan for.
      * @return the next token.
@@ -1080,7 +1051,6 @@
      *             if input has been exhausted.
      * @throws InputMismatchException
      *             if the next token does not match the pattern given.
-     * @since Android 1.0
      */
     public String next(String pattern) {
         return next(Pattern.compile(pattern));
@@ -1095,7 +1065,7 @@
      * negative sign (-) is added if the {@code Locale}-specific negative prefix or
      * suffix was present. Finally the resulting string is passed to
      * {@code BigDecimal(String) }.
-     * 
+     *
      * @return the next token as a {@code BigDecimal}.
      * @throws IllegalStateException
      *             if this {@code Scanner} has been closed.
@@ -1104,7 +1074,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code BigDecimal}.
-     * @since Android 1.0
      */
     public BigDecimal nextBigDecimal() {
         checkClosed();
@@ -1131,7 +1100,7 @@
     /**
      * Returns the next token as a {@code BigInteger}. This method will block if input is
      * being read. Equivalent to {@code nextBigInteger(DEFAULT_RADIX)}.
-     * 
+     *
      * @return the next token as {@code BigInteger}.
      * @throws IllegalStateException
      *             if this {@code Scanner} has been closed.
@@ -1140,7 +1109,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code BigInteger}.
-     * @since Android 1.0
      */
     public BigInteger nextBigInteger() {
         return nextBigInteger(integerRadix);
@@ -1156,7 +1124,7 @@
      * {@code Locale}-specific negative prefix or suffix was present. Finally the
      * resulting String is passed to {@link BigInteger#BigInteger(String, int)}}
      * with the specified radix.
-     * 
+     *
      * @param radix
      *            the radix used to translate the token into a
      *            {@code BigInteger}.
@@ -1168,7 +1136,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code BigInteger}.
-     * @since Android 1.0
      */
     public BigInteger nextBigInteger(int radix) {
         checkClosed();
@@ -1195,7 +1162,7 @@
     /**
      * Returns the next token as a {@code boolean}. This method will block if input is
      * being read.
-     * 
+     *
      * @return the next token as a {@code boolean}.
      * @throws IllegalStateException
      *             if this {@code Scanner} has been closed.
@@ -1204,7 +1171,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code boolean} value.
-     * @since Android 1.0
      */
     public boolean nextBoolean() {
         return Boolean.parseBoolean(next(BOOLEAN_PATTERN));
@@ -1213,7 +1179,7 @@
     /**
      * Returns the next token as a {@code byte}. This method will block if input is being
      * read. Equivalent to {@code nextByte(DEFAULT_RADIX)}.
-     * 
+     *
      * @return the next token as a {@code byte}.
      * @throws IllegalStateException
      *             if this {@code Scanner} has been closed.
@@ -1222,7 +1188,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code byte} value.
-     * @since Android 1.0
      */
     public byte nextByte() {
         return nextByte(integerRadix);
@@ -1238,7 +1203,7 @@
      * {@code Locale}-specific negative prefix or suffix was present. Finally the
      * resulting String is passed to {@link Byte#parseByte(String, int)}} with
      * the specified radix.
-     * 
+     *
      * @param radix
      *            the radix used to translate the token into {@code byte} value.
      * @return the next token as a {@code byte}.
@@ -1249,7 +1214,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code byte} value.
-     * @since Android 1.0
      */
     @SuppressWarnings("boxing")
     public byte nextByte(int radix) {
@@ -1285,7 +1249,7 @@
      * {@link Double#parseDouble(String)}}. If the token matches the localized
      * NaN or infinity strings, it is also passed to
      * {@link Double#parseDouble(String)}}.
-     * 
+     *
      * @return the next token as a {@code double}.
      * @throws IllegalStateException
      *             if this {@code Scanner} has been closed.
@@ -1294,7 +1258,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code double} value.
-     * @since Android 1.0
      */
     @SuppressWarnings("boxing")
     public double nextDouble() {
@@ -1330,7 +1293,7 @@
      * {@link Float#parseFloat(String)}}.If the token matches the localized NaN
      * or infinity strings, it is also passed to
      * {@link Float#parseFloat(String)}}.
-     * 
+     *
      * @return the next token as a {@code float}.
      * @throws IllegalStateException
      *             if this {@code Scanner} has been closed.
@@ -1339,7 +1302,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code float} value.
-     * @since Android 1.0
      */
     @SuppressWarnings("boxing")
     public float nextFloat() {
@@ -1367,7 +1329,7 @@
     /**
      * Returns the next token as an {@code int}. This method will block if input is being
      * read. Equivalent to {@code nextInt(DEFAULT_RADIX)}.
-     * 
+     *
      * @return the next token as an {@code int}
      * @throws IllegalStateException
      *             if this {@code Scanner} has been closed.
@@ -1376,7 +1338,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code int} value.
-     * @since Android 1.0
      */
     public int nextInt() {
         return nextInt(integerRadix);
@@ -1392,7 +1353,7 @@
      * {@code Locale}-specific negative prefix or suffix was present. Finally the
      * resulting String is passed to {@link Integer#parseInt(String, int)} with
      * the specified radix.
-     * 
+     *
      * @param radix
      *            the radix used to translate the token into an {@code int}
      *            value.
@@ -1404,7 +1365,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code int} value.
-     * @since Android 1.0
      */
     @SuppressWarnings("boxing")
     public int nextInt(int radix) {
@@ -1416,7 +1376,7 @@
             return (Integer) obj;
         }
         Pattern integerPattern = getIntegerPattern(radix);
-        String intString=next(integerPattern);
+        String intString = next(integerPattern);
         intString = removeLocaleInfo(intString, DataType.INT);
         int intValue = 0;
         try {
@@ -1435,13 +1395,12 @@
      * searching, if no line terminator is found, then a large amount of input
      * will be cached. If no line at all can be found, a {@code NoSuchElementException}
      * will be thrown.
-     * 
+     *
      * @return the skipped line.
      * @throws IllegalStateException
      *             if the {@code Scanner} is closed.
      * @throws NoSuchElementException
      *             if no line can be found, e.g. when input is an empty string.
-     * @since Android 1.0
      */
     public String nextLine() {
         checkClosed();
@@ -1451,7 +1410,8 @@
         String result = null;
         while (true) {
             if (matcher.find()) {
-                if (inputExhausted || matcher.end() != bufferLength) {
+                if (inputExhausted || matcher.end() != bufferLength
+                        || bufferLength < buffer.capacity()) {
                     matchSuccessful = true;
                     findStartIndex = matcher.end();
                     result = matcher.group();
@@ -1466,7 +1426,7 @@
             if (!inputExhausted) {
                 readMore();
                 resetMatcher();
-            } 
+            }
         }
         // Find text without line terminator here.
         if (null != result) {
@@ -1481,7 +1441,7 @@
     /**
      * Returns the next token as a {@code long}. This method will block if input is being
      * read. Equivalent to {@code nextLong(DEFAULT_RADIX)}.
-     * 
+     *
      * @return the next token as a {@code long}.
      * @throws IllegalStateException
      *             if this {@code Scanner} has been closed.
@@ -1490,7 +1450,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code long} value.
-     * @since Android 1.0
      */
     public long nextLong() {
         return nextLong(integerRadix);
@@ -1506,7 +1465,7 @@
      * {@code Locale}-specific negative prefix or suffix was present. Finally the
      * resulting String is passed to {@link Long#parseLong(String, int)}} with
      * the specified radix.
-     * 
+     *
      * @param radix
      *            the radix used to translate the token into a {@code long}
      *            value.
@@ -1518,7 +1477,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code long} value.
-     * @since Android 1.0
      */
     @SuppressWarnings("boxing")
     public long nextLong(int radix) {
@@ -1546,7 +1504,7 @@
     /**
      * Returns the next token as a {@code short}. This method will block if input is being
      * read. Equivalent to {@code nextShort(DEFAULT_RADIX)}.
-     * 
+     *
      * @return the next token as a {@code short}.
      * @throws IllegalStateException
      *             if this {@code Scanner} has been closed.
@@ -1555,7 +1513,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code short} value.
-     * @since Android 1.0
      */
     public short nextShort() {
         return nextShort(integerRadix);
@@ -1571,7 +1528,7 @@
      * {@code Locale}-specific negative prefix or suffix was present. Finally the
      * resulting String is passed to {@link Short#parseShort(String, int)}}
      * with the specified radix.
-     * 
+     *
      * @param radix
      *            the radix used to translate the token into {@code short}
      *            value.
@@ -1583,7 +1540,6 @@
      * @throws InputMismatchException
      *             if the next token can not be translated into a valid
      *             {@code short} value.
-     * @since Android 1.0
      */
     @SuppressWarnings("boxing")
     public short nextShort(int radix) {
@@ -1610,9 +1566,8 @@
 
     /**
      * Return the radix of this {@code Scanner}.
-     * 
+     *
      * @return the radix of this {@code Scanner}
-     * @since Android 1.0
      */
     public int radix() {
         return integerRadix;
@@ -1624,8 +1579,8 @@
      * skipped. If an anchored match of the specified pattern succeeds, the corresponding input
      * will also be skipped. Otherwise, a {@code NoSuchElementException} will be thrown.
      * Patterns that can match a lot of input may cause the {@code Scanner} to read
-     * in a large amount of input. 
-     * 
+     * in a large amount of input.
+     *
      * @param pattern
      *            used to skip over input.
      * @return the {@code Scanner} itself.
@@ -1633,7 +1588,6 @@
      *             if the {@code Scanner} is closed.
      * @throws NoSuchElementException
      *             if the specified pattern match fails.
-     * @since Android 1.0
      */
     public Scanner skip(Pattern pattern) {
         checkClosed();
@@ -1668,14 +1622,13 @@
      * the constructed pattern to match input starting from the current position. The
      * delimiter will be ignored. This call is the same as invoke
      * {@code skip(Pattern.compile(pattern))}.
-     * 
+     *
      * @param pattern
      *            the string used to construct a pattern which in turn is used to
      *            match input.
      * @return the {@code Scanner} itself.
      * @throws IllegalStateException
      *             if the {@code Scanner} is closed.
-     * @since Android 1.0
      */
     public Scanner skip(String pattern) {
         return skip(Pattern.compile(pattern));
@@ -1684,9 +1637,8 @@
     /**
      * 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}.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -1702,11 +1654,10 @@
 
     /**
      * Sets the delimiting pattern of this {@code Scanner}.
-     * 
+     *
      * @param pattern
      *            the delimiting pattern to use.
      * @return this {@code Scanner}.
-     * @since Android 1.0
      */
     public Scanner useDelimiter(Pattern pattern) {
         delimiter = pattern;
@@ -1716,11 +1667,10 @@
     /**
      * Sets the delimiting pattern of this {@code Scanner} with a pattern compiled from
      * the supplied string value.
-     * 
+     *
      * @param pattern
      *            a string from which a {@code Pattern} can be compiled.
      * @return this {@code Scanner}.
-     * @since Android 1.0
      */
     public Scanner useDelimiter(String pattern) {
         return useDelimiter(Pattern.compile(pattern));
@@ -1728,11 +1678,10 @@
 
     /**
      * Sets the {@code Locale} of this {@code Scanner} to a specified {@code Locale}.
-     * 
+     *
      * @param l
      *            the specified {@code Locale} to use.
      * @return this {@code Scanner}.
-     * @since Android 1.0
      */
     public Scanner useLocale(Locale l) {
         if (null == l) {
@@ -1744,11 +1693,10 @@
 
     /**
      * Sets the radix of this {@code Scanner} to the specified radix.
-     * 
+     *
      * @param radix
      *            the specified radix to use.
      * @return this {@code Scanner}.
-     * @since Android 1.0
      */
     public Scanner useRadix(int radix) {
         if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
@@ -1761,10 +1709,9 @@
 
     /**
      * Remove is not a supported operation on {@code Scanner}.
-     * 
+     *
      * @throws UnsupportedOperationException
      *             if this method is invoked.
-     * @since Android 1.0
      */
     public void remove() {
         throw new UnsupportedOperationException();
@@ -1778,7 +1725,7 @@
         buffer.limit(0);
         matcher = delimiter.matcher(buffer);
     }
-    
+
     /*
      * Check the {@code Scanner}'s state, if it is closed, IllegalStateException will be
      * thrown.
@@ -1788,7 +1735,7 @@
             throw new IllegalStateException();
         }
     }
-    
+
     /*
      * Check the inputed pattern. If it is null, then a NullPointerException
      * will be thrown out.
@@ -1824,7 +1771,7 @@
     private void recoverPreviousStatus() {
         findStartIndex = preStartIndex;
     }
-    
+
     /*
      * Get integer's pattern
      */
@@ -1834,12 +1781,12 @@
                     .getString("KA00e", radix)); //$NON-NLS-1$
         }
         decimalFormat = (DecimalFormat) NumberFormat.getInstance(locale);
-        
-        String allAvailableDigits="0123456789abcdefghijklmnopqrstuvwxyz"; //$NON-NLS-1$ 
-        String ASCIIDigit=allAvailableDigits.substring(0, radix);
-        String nonZeroASCIIDigit=allAvailableDigits.substring(1, radix);
 
-        StringBuilder digit = new StringBuilder("((?i)[").append(ASCIIDigit) //$NON-NLS-1$ 
+        String allAvailableDigits = "0123456789abcdefghijklmnopqrstuvwxyz"; //$NON-NLS-1$
+        String ASCIIDigit = allAvailableDigits.substring(0, radix);
+        String nonZeroASCIIDigit = allAvailableDigits.substring(1, radix);
+
+        StringBuilder digit = new StringBuilder("((?i)[").append(ASCIIDigit) //$NON-NLS-1$
                 .append("]|\\p{javaDigit})"); //$NON-NLS-1$
         StringBuilder nonZeroDigit = new StringBuilder("((?i)[").append( //$NON-NLS-1$
                 nonZeroASCIIDigit).append("]|([\\p{javaDigit}&&[^0]]))"); //$NON-NLS-1$
@@ -1912,16 +1859,16 @@
     }
 
     /*
-     * Add the {@code Locale}-specific positive prefixes and suffixes to the pattern
+     * Add the locale specific positive prefixes and suffixes to the pattern
      */
     private StringBuilder addPositiveSign(StringBuilder unSignNumeral) {
         String positivePrefix = ""; //$NON-NLS-1$
         String positiveSuffix = ""; //$NON-NLS-1$
         if (!decimalFormat.getPositivePrefix().equals("")) { //$NON-NLS-1$
-            positivePrefix = "\\Q" + decimalFormat.getPositivePrefix()+"\\E"; //$NON-NLS-1$ //$NON-NLS-2$
+            positivePrefix = "\\Q" + decimalFormat.getPositivePrefix() + "\\E"; //$NON-NLS-1$ //$NON-NLS-2$
         }
         if (!decimalFormat.getPositiveSuffix().equals("")) { //$NON-NLS-1$
-            positiveSuffix = "\\Q" + decimalFormat.getPositiveSuffix()+"\\E"; //$NON-NLS-1$ //$NON-NLS-2$
+            positiveSuffix = "\\Q" + decimalFormat.getPositiveSuffix() + "\\E"; //$NON-NLS-1$ //$NON-NLS-2$
         }
         StringBuilder signedNumeral = new StringBuilder()
                 .append(positivePrefix).append(unSignNumeral).append(
@@ -1930,16 +1877,16 @@
     }
 
     /*
-     * Add the {@code Locale} specific negative prefixes and suffixes to the pattern
+     * Add the locale specific negative prefixes and suffixes to the pattern
      */
     private StringBuilder addNegativeSign(StringBuilder unSignNumeral) {
         String negativePrefix = ""; //$NON-NLS-1$
         String negativeSuffix = ""; //$NON-NLS-1$
         if (!decimalFormat.getNegativePrefix().equals("")) { //$NON-NLS-1$
-            negativePrefix = "\\Q" + decimalFormat.getNegativePrefix()+"\\E"; //$NON-NLS-1$//$NON-NLS-2$
+            negativePrefix = "\\Q" + decimalFormat.getNegativePrefix() + "\\E"; //$NON-NLS-1$//$NON-NLS-2$
         }
         if (!decimalFormat.getNegativeSuffix().equals("")) { //$NON-NLS-1$
-            negativeSuffix = "\\Q" + decimalFormat.getNegativeSuffix()+"\\E"; //$NON-NLS-1$//$NON-NLS-2$
+            negativeSuffix = "\\Q" + decimalFormat.getNegativeSuffix() + "\\E"; //$NON-NLS-1$//$NON-NLS-2$
         }
         StringBuilder signedNumeral = new StringBuilder()
                 .append(negativePrefix).append(unSignNumeral).append(
@@ -1948,15 +1895,14 @@
     }
 
     /*
-     * Remove {@code Locale} related information from float String
+     * Remove locale related information from float String
      */
     private String removeLocaleInfoFromFloat(String floatString) {
         // If the token is HexFloat
-        if (-1 != floatString.indexOf('x')
-                || -1 != floatString.indexOf('X')) {
+        if (-1 != floatString.indexOf('x') || -1 != floatString.indexOf('X')) {
             return floatString;
         }
-        
+
         int exponentIndex;
         String decimalNumeralString;
         String exponentString;
@@ -1968,11 +1914,11 @@
                     floatString.length());
             decimalNumeralString = removeLocaleInfo(decimalNumeralString,
                     DataType.FLOAT);
-            return decimalNumeralString + "e" + exponentString; //$NON-NLS-1$ 
+            return decimalNumeralString + "e" + exponentString; //$NON-NLS-1$
         }
         return removeLocaleInfo(floatString, DataType.FLOAT);
     }
-    
+
     /*
      * Remove the locale specific prefixes, group separators, and locale
      * specific suffixes from input string
@@ -2001,12 +1947,12 @@
             }
         }
         if (DataType.FLOAT == type) {
-            if (tokenBuilder.toString().equals(decimalFormat.getDecimalFormatSymbols()
-                    .getNaN())) {
-                result.append("NaN");//$NON-NLS-1$ 
-            } else if (tokenBuilder.toString().equals(decimalFormat
-                    .getDecimalFormatSymbols().getInfinity())) {
-                result.append("Infinity");//$NON-NLS-1$ 
+            if (tokenBuilder.toString().equals(
+                    decimalFormat.getDecimalFormatSymbols().getNaN())) {
+                result.append("NaN");//$NON-NLS-1$
+            } else if (tokenBuilder.toString().equals(
+                    decimalFormat.getDecimalFormatSymbols().getInfinity())) {
+                result.append("Infinity");//$NON-NLS-1$
             } else {
                 for (int i = 0; i < tokenBuilder.length(); i++) {
                     if (-1 != Character.digit(tokenBuilder.charAt(i), 10)) {
@@ -2029,8 +1975,9 @@
         }
         return result.toString();
     }
+
     /*
-     * remove positive and negative sign from the parameter stringBuilder, and
+     * Remove positive and negative sign from the parameter stringBuilder, and
      * return whether the input string is negative
      */
     private boolean removeLocaleSign(StringBuilder tokenBuilder) {
@@ -2106,7 +2053,7 @@
     }
 
     /*
-     * Find prefixed delimiter
+     * Find prefix delimiter
      */
     private int findPreDelimiter() {
         int tokenStartIndex;
@@ -2166,7 +2113,7 @@
     }
 
     /*
-     * Find postfixed delimiter
+     * Find postfix delimiter
      */
     private int findPostDelimiter() {
         int tokenEndIndex = 0;
@@ -2215,7 +2162,8 @@
             }
         } catch (IOException e) {
             // Consider the scenario: readable puts 4 chars into
-            // buffer and then an IOException is thrown out. In this case, buffer is
+            // buffer and then an IOException is thrown out. In this case,
+            // buffer is
             // actually grown, but readable.read() will never return.
             bufferLength = buffer.position();
             /*
@@ -2226,7 +2174,6 @@
             lastIOException = e;
         }
 
-
         buffer.flip();
         buffer.position(oldPosition);
         if (-1 == readCount) {
diff --git a/libcore/luni/src/main/java/java/util/Set.java b/libcore/luni/src/main/java/java/util/Set.java
index f52666d..109c8df 100644
--- a/libcore/luni/src/main/java/java/util/Set.java
+++ b/libcore/luni/src/main/java/java/util/Set.java
@@ -20,8 +20,8 @@
 
 /**
  * A {@code Set} is a data structure which does not allow duplicate elements.
- * 
- * @since Android 1.0
+ *
+ * @since 1.2
  */
 public interface Set<E> extends Collection<E> {
     
@@ -38,7 +38,6 @@
      *             when the class of the object is inappropriate for this set.
      * @throws IllegalArgumentException
      *             when the object cannot be added to this set.
-     * @since Android 1.0
      */
     public boolean add(E object);
 
@@ -55,7 +54,6 @@
      *             when the class of an object is inappropriate for this set.
      * @throws IllegalArgumentException
      *             when an object cannot be added to this set.
-     * @since Android 1.0
      */
     public boolean addAll(Collection<? extends E> collection);
 
@@ -66,7 +64,6 @@
      *             when removing from this set is not supported.
      * @see #isEmpty
      * @see #size
-     * @since Android 1.0
      */
     public void clear();
 
@@ -77,7 +74,6 @@
      *            the object to search for.
      * @return {@code true} if object is an element of this set, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public boolean contains(Object object);
 
@@ -88,7 +84,6 @@
      *            the collection of objects.
      * @return {@code true} if all objects in the specified collection are
      *         elements of this set, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean containsAll(Collection<?> collection);
 
@@ -103,7 +98,6 @@
      * @return boolean {@code true} if the object is the same as this object,
      *         and {@code false} if it is different from this object.
      * @see #hashCode
-     * @since Android 1.0
      */
     public boolean equals(Object object);
 
@@ -114,7 +108,6 @@
      * @return the hash code of this set.
      * 
      * @see #equals
-     * @since Android 1.0
      */
     public int hashCode();
 
@@ -124,7 +117,6 @@
      * @return {@code true} if this set has no elements, {@code false}
      *         otherwise.
      * @see #size
-     * @since Android 1.0
      */
     public boolean isEmpty();
 
@@ -134,7 +126,6 @@
      * 
      * @return an iterator on the elements of this set.
      * @see Iterator
-     * @since Android 1.0
      */
     public Iterator<E> iterator();
 
@@ -146,7 +137,6 @@
      * @return {@code true} if this set was modified, {@code false} otherwise.
      * @throws UnsupportedOperationException
      *             when removing from this set is not supported.
-     * @since Android 1.0
      */
     public boolean remove(Object object);
 
@@ -158,7 +148,6 @@
      * @return {@code true} if this set was modified, {@code false} otherwise.
      * @throws UnsupportedOperationException
      *             when removing from this set is not supported.
-     * @since Android 1.0
      */
     public boolean removeAll(Collection<?> collection);
 
@@ -171,7 +160,6 @@
      * @return {@code true} if this set was modified, {@code false} otherwise.
      * @throws UnsupportedOperationException
      *             when removing from this set is not supported.
-     * @since Android 1.0
      */
     public boolean retainAll(Collection<?> collection);
 
@@ -179,7 +167,6 @@
      * Returns the number of elements in this set.
      * 
      * @return the number of elements in this set.
-     * @since Android 1.0
      */
     public int size();
 
@@ -187,7 +174,6 @@
      * Returns an array containing all elements contained in this set.
      * 
      * @return an array of the elements from this set.
-     * @since Android 1.0
      */
     public Object[] toArray();
 
@@ -205,7 +191,6 @@
      *             when the type of an element in this set cannot be stored in
      *             the type of the specified array.
      * @see Collection#toArray(Object[])
-     * @since Android 1.0
      */
     public <T> T[] toArray(T[] array);
 }
diff --git a/libcore/luni/src/main/java/java/util/SimpleTimeZone.java b/libcore/luni/src/main/java/java/util/SimpleTimeZone.java
index 18d076f..702b6ef 100644
--- a/libcore/luni/src/main/java/java/util/SimpleTimeZone.java
+++ b/libcore/luni/src/main/java/java/util/SimpleTimeZone.java
@@ -14,12 +14,12 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-/**
-*******************************************************************************
-* Copyright (C) 1996-2008, International Business Machines Corporation and    *
-* others. All Rights Reserved.                                                *
-*******************************************************************************
-*/
+
+// BEGIN android-note
+// This implementation is based on an old version of Apache Harmony. The current
+// Harmony uses ICU4J, which makes it much simpler. We should consider updating
+// this implementation to leverage ICU4JNI.
+// END android-note
 
 package java.util;
 
@@ -27,33 +27,41 @@
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.ObjectStreamField;
+// BEGIN android-removed
+// import java.security.AccessController;
+// import java.security.PrivilegedAction;
+// END android-removed
 
 import org.apache.harmony.luni.util.Msg;
 
-// BEGIN android-note
-// The class javadoc and some of the method descriptions are copied from ICU4J
-// source files. Changes have been made to the copied descriptions.
-// The icu license header was added to this file. 
-// END android-note
 /**
  * {@code SimpleTimeZone} is a concrete subclass of {@code TimeZone}
  * that represents a time zone for use with a Gregorian calendar. This class
  * does not handle historical changes.
- * <P>
+ * <p>
  * Use a negative value for {@code dayOfWeekInMonth} to indicate that
  * {@code SimpleTimeZone} should count from the end of the month
  * backwards. For example, Daylight Savings Time ends at the last
  * (dayOfWeekInMonth = -1) Sunday in October, at 2 AM in standard time.
- * 
+ *
  * @see Calendar
  * @see GregorianCalendar
  * @see TimeZone
- * @since Android 1.0
  */
 public class SimpleTimeZone extends TimeZone {
-    
+
     private static final long serialVersionUID = -403250971215465050L;
 
+    // BEGIN android-removed
+    // private static com.ibm.icu.util.TimeZone getICUTimeZone(final String name){
+    //     return AccessController.doPrivileged(new PrivilegedAction<com.ibm.icu.util.TimeZone>(){
+    //         public com.ibm.icu.util.TimeZone run() {
+    //             return com.ibm.icu.util.TimeZone.getTimeZone(name);
+    //         }
+    //     });
+    // }
+    // END android-removed
+
     private int rawOffset;
 
     private int startYear, startMonth, startDay, startDayOfWeek, startTime;
@@ -67,8 +75,6 @@
 
     /**
      * The constant for representing a start or end time in GMT time mode.
-     * 
-     * @since Android 1.0
      */
     public static final int UTC_TIME = 2;
 
@@ -76,8 +82,6 @@
      * The constant for representing a start or end time in standard local time mode,
      * based on timezone's raw offset from GMT; does not include Daylight
      * savings.
-     * 
-     * @since Android 1.0
      */
     public static final int STANDARD_TIME = 1;
 
@@ -85,8 +89,6 @@
      * The constant for representing a start or end time in local wall clock time
      * mode, based on timezone's adjusted offset from GMT; includes
      * Daylight savings.
-     * 
-     * @since Android 1.0
      */
     public static final int WALL_TIME = 0;
 
@@ -96,22 +98,37 @@
 
     private int dstSavings = 3600000;
 
+    // BEGIN android-removed
+    // private final transient com.ibm.icu.util.TimeZone icuTZ;
+    //
+    // private final transient boolean isSimple;
+    // END android-removed
+
     /**
      * Constructs a {@code SimpleTimeZone} with the given base time zone offset from GMT
      * and time zone ID. Timezone IDs can be obtained from
      * {@code TimeZone.getAvailableIDs}. Normally you should use {@code TimeZone.getDefault} to
      * construct a {@code TimeZone}.
-     * 
+     *
      * @param offset
      *            the given base time zone offset to GMT.
      * @param name
      *            the time zone ID which is obtained from
      *            {@code TimeZone.getAvailableIDs}.
-     * @since Android 1.0
      */
-    public SimpleTimeZone(int offset, String name) {
+    public SimpleTimeZone(int offset, final String name) {
         setID(name);
         rawOffset = offset;
+        // BEGIN android-removed
+        // icuTZ = getICUTimeZone(name);
+        // if (icuTZ instanceof com.ibm.icu.util.SimpleTimeZone) {
+        //     isSimple = true;
+        //     icuTZ.setRawOffset(offset);
+        // } else {
+        //     isSimple = false;
+        // }
+        // useDaylight = icuTZ.useDaylightTime();
+        // END android-removed
     }
 
     /**
@@ -146,8 +163,8 @@
      * The above examples refer to the {@code startMonth}, {@code startDay}, and {@code startDayOfWeek};
      * the same applies for the {@code endMonth}, {@code endDay}, and {@code endDayOfWeek}.
      * <p>
-     * The daylight savings time difference is set to the default value: one hour.          
-     * 
+     * The daylight savings time difference is set to the default value: one hour.
+     *
      * @param offset
      *            the given base time zone offset to GMT.
      * @param name
@@ -182,7 +199,6 @@
      * @throws IllegalArgumentException
      *             if the month, day, dayOfWeek, or time parameters are out of
      *             range for the start or end rule.
-     * @since Android 1.0
      */
     public SimpleTimeZone(int offset, String name, int startMonth,
             int startDay, int startDayOfWeek, int startTime, int endMonth,
@@ -193,9 +209,9 @@
 
     /**
      * Constructs a {@code SimpleTimeZone} with the given base time zone offset from GMT,
-     * time zone ID, times to start and end the daylight savings time, and 
-     * the daylight savings time difference in milliseconds
-     * 
+     * time zone ID, times to start and end the daylight savings time, and
+     * the daylight savings time difference in milliseconds.
+     *
      * @param offset
      *            the given base time zone offset to GMT.
      * @param name
@@ -212,7 +228,7 @@
      *            description of {@link #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)} for an example.
      * @param startTime
      *            The daylight savings starting time in local wall time, which
-     *            is standard time in this case. Please see the description of 
+     *            is standard time in this case. Please see the description of
      *            {@link #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)} for an example.
      * @param endMonth
      *            the daylight savings ending month. Month is 0-based. eg, 0 for
@@ -221,7 +237,7 @@
      *            the daylight savings ending day-of-week-in-month. Please see
      *            the description of {@link #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)} for an example.
      * @param endDayOfWeek
-     *            the daylight savings ending day-of-week. Please see the description of 
+     *            the daylight savings ending day-of-week. Please see the description of
      *            {@link #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)} for an example.
      * @param endTime
      *            the daylight savings ending time in local wall time, which is
@@ -229,31 +245,50 @@
      *            for an example.
      * @param daylightSavings
      *            the daylight savings time difference in milliseconds.
-     * @exception IllegalArgumentException
-     *                the month, day, dayOfWeek, or time parameters are out of
+     * @throws IllegalArgumentException
+     *                if the month, day, dayOfWeek, or time parameters are out of
      *                range for the start or end rule.
-     * @since Android 1.0
      */
     public SimpleTimeZone(int offset, String name, int startMonth,
             int startDay, int startDayOfWeek, int startTime, int endMonth,
             int endDay, int endDayOfWeek, int endTime, int daylightSavings) {
+        // BEGIN android-changed
+        // icuTZ = getICUTimeZone(name);
+        // if (icuTZ instanceof com.ibm.icu.util.SimpleTimeZone) {
+        //     isSimple = true;
+        //     com.ibm.icu.util.SimpleTimeZone tz = (com.ibm.icu.util.SimpleTimeZone)icuTZ;
+        //     tz.setRawOffset(offset);
+        //     tz.setStartRule(startMonth, startDay, startDayOfWeek, startTime);
+        //     tz.setEndRule(endMonth, endDay, endDayOfWeek, endTime);
+        //     tz.setDSTSavings(daylightSavings);
+        // } else {
+        //     isSimple = false;
+        // }
+        // setID(name);
+        // rawOffset = offset;
         this(offset, name);
+        // END android-changed
         if (daylightSavings <= 0) {
-            throw new IllegalArgumentException(Msg.getString("K00e9", daylightSavings)); //$NON-NLS-1$
+            throw new IllegalArgumentException(Msg.getString(
+                    "K00e9", daylightSavings)); //$NON-NLS-1$
         }
         dstSavings = daylightSavings;
 
         setStartRule(startMonth, startDay, startDayOfWeek, startTime);
         setEndRule(endMonth, endDay, endDayOfWeek, endTime);
+
+        // BEGIN android-removed
+        // useDaylight = daylightSavings > 0 || icuTZ.useDaylightTime();
+        // END android-removed
     }
 
     /**
      * Construct a {@code SimpleTimeZone} with the given base time zone offset from GMT,
-     * time zone ID, times to start and end the daylight savings time including a 
+     * time zone ID, times to start and end the daylight savings time including a
      * mode specifier, the daylight savings time difference in milliseconds.
      * The mode specifies either {@link #WALL_TIME}, {@link #STANDARD_TIME}, or
      * {@link #UTC_TIME}.
-     * 
+     *
      * @param offset
      *            the given base time zone offset to GMT.
      * @param name
@@ -269,21 +304,21 @@
      *            the daylight savings starting day-of-week. Please see the
      *            description of {@link #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)} for an example.
      * @param startTime
-     *            the time of day in milliseconds on which daylight savings 
+     *            the time of day in milliseconds on which daylight savings
      *            time starts, based on the {@code startTimeMode}.
      * @param startTimeMode
      *            the mode (UTC, standard, or wall time) of the start time
      *            value.
-     * @param endDay 
-     *            the day of the week on which daylight savings time ends. 
+     * @param endDay
+     *            the day of the week on which daylight savings time ends.
      * @param endMonth
      *            the daylight savings ending month. The month indexing is 0-based. eg, 0 for
      *            January.
      * @param endDayOfWeek
-     *            the daylight savings ending day-of-week. Please see the description of 
+     *            the daylight savings ending day-of-week. Please see the description of
      *            {@link #SimpleTimeZone(int, String, int, int, int, int, int, int, int, int)} for an example.
      * @param endTime
-     *            the time of day in milliseconds on which daylight savings 
+     *            the time of day in milliseconds on which daylight savings
      *            time ends, based on the {@code endTimeMode}.
      * @param endTimeMode
      *            the mode (UTC, standard, or wall time) of the end time value.
@@ -292,7 +327,6 @@
      * @throws IllegalArgumentException
      *             if the month, day, dayOfWeek, or time parameters are out of
      *             range for the start or end rule.
-     * @since Android 1.0
      */
     public SimpleTimeZone(int offset, String name, int startMonth,
             int startDay, int startDayOfWeek, int startTime, int startTimeMode,
@@ -308,10 +342,9 @@
     /**
      * Returns a new {@code SimpleTimeZone} with the same ID, {@code rawOffset} and daylight
      * savings time rules as this SimpleTimeZone.
-     * 
+     *
      * @return a shallow copy of this {@code SimpleTimeZone}.
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -326,13 +359,12 @@
      * Compares the specified object to this {@code SimpleTimeZone} and returns whether they
      * are equal. The object must be an instance of {@code SimpleTimeZone} and have the
      * same internal data.
-     * 
+     *
      * @param object
      *            the object to compare with this object.
      * @return {@code true} if the specified object is equal to this
      *         {@code SimpleTimeZone}, {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -372,6 +404,8 @@
             checkDay(month, day);
         }
 
+        // BEGIN android-changed
+        // return icuTZ.getOffset(era, year, month, day, dayOfWeek, time);
         if (!useDaylightTime() || era != GregorianCalendar.AD
                 || year < startYear) {
             return rawOffset;
@@ -389,38 +423,39 @@
         int ruleDay = 0, daysInMonth, firstDayOfMonth = mod7(dayOfWeek - day);
         if (month == startMonth) {
             switch (startMode) {
-            case DOM_MODE:
-                ruleDay = startDay;
-                break;
-            case DOW_IN_MONTH_MODE:
-                if (startDay >= 0) {
-                    ruleDay = mod7(startDayOfWeek - firstDayOfMonth) + 1
-                            + (startDay - 1) * 7;
-                } else {
-                    daysInMonth = GregorianCalendar.DaysInMonth[startMonth];
-                    if (startMonth == Calendar.FEBRUARY && isLeapYear(year)) {
-                        daysInMonth += 1;
+                case DOM_MODE:
+                    ruleDay = startDay;
+                    break;
+                case DOW_IN_MONTH_MODE:
+                    if (startDay >= 0) {
+                        ruleDay = mod7(startDayOfWeek - firstDayOfMonth) + 1
+                                + (startDay - 1) * 7;
+                    } else {
+                        daysInMonth = GregorianCalendar.DaysInMonth[startMonth];
+                        if (startMonth == Calendar.FEBRUARY && isLeapYear(
+                                year)) {
+                            daysInMonth += 1;
+                        }
+                        ruleDay = daysInMonth
+                                + 1
+                                + mod7(startDayOfWeek
+                                - (firstDayOfMonth + daysInMonth))
+                                + startDay * 7;
                     }
-                    ruleDay = daysInMonth
-                            + 1
+                    break;
+                case DOW_GE_DOM_MODE:
+                    ruleDay = startDay
                             + mod7(startDayOfWeek
-                                    - (firstDayOfMonth + daysInMonth))
-                            + startDay * 7;
-                }
-                break;
-            case DOW_GE_DOM_MODE:
-                ruleDay = startDay
-                        + mod7(startDayOfWeek
-                                - (firstDayOfMonth + startDay - 1));
-                break;
-            case DOW_LE_DOM_MODE:
-                ruleDay = startDay
-                        + mod7(startDayOfWeek
-                                - (firstDayOfMonth + startDay - 1));
-                if (ruleDay != startDay) {
-                    ruleDay -= 7;
-                }
-                break;
+                            - (firstDayOfMonth + startDay - 1));
+                    break;
+                case DOW_LE_DOM_MODE:
+                    ruleDay = startDay
+                            + mod7(startDayOfWeek
+                            - (firstDayOfMonth + startDay - 1));
+                    if (ruleDay != startDay) {
+                        ruleDay -= 7;
+                    }
+                    break;
             }
             if (ruleDay > day || ruleDay == day && time < startTime) {
                 return rawOffset;
@@ -431,36 +466,38 @@
         int nextMonth = (month + 1) % 12;
         if (month == endMonth || (ruleTime < 0 && nextMonth == endMonth)) {
             switch (endMode) {
-            case DOM_MODE:
-                ruleDay = endDay;
-                break;
-            case DOW_IN_MONTH_MODE:
-                if (endDay >= 0) {
-                    ruleDay = mod7(endDayOfWeek - firstDayOfMonth) + 1
-                            + (endDay - 1) * 7;
-                } else {
-                    daysInMonth = GregorianCalendar.DaysInMonth[endMonth];
-                    if (endMonth == Calendar.FEBRUARY && isLeapYear(year)) {
-                        daysInMonth++;
+                case DOM_MODE:
+                    ruleDay = endDay;
+                    break;
+                case DOW_IN_MONTH_MODE:
+                    if (endDay >= 0) {
+                        ruleDay = mod7(endDayOfWeek - firstDayOfMonth) + 1
+                                + (endDay - 1) * 7;
+                    } else {
+                        daysInMonth = GregorianCalendar.DaysInMonth[endMonth];
+                        if (endMonth == Calendar.FEBRUARY && isLeapYear(year)) {
+                            daysInMonth++;
+                        }
+                        ruleDay = daysInMonth
+                                + 1
+                                + mod7(endDayOfWeek
+                                - (firstDayOfMonth + daysInMonth)) + endDay
+                                * 7;
                     }
-                    ruleDay = daysInMonth
-                            + 1
-                            + mod7(endDayOfWeek
-                                    - (firstDayOfMonth + daysInMonth)) + endDay
-                            * 7;
-                }
-                break;
-            case DOW_GE_DOM_MODE:
-                ruleDay = endDay
-                        + mod7(endDayOfWeek - (firstDayOfMonth + endDay - 1));
-                break;
-            case DOW_LE_DOM_MODE:
-                ruleDay = endDay
-                        + mod7(endDayOfWeek - (firstDayOfMonth + endDay - 1));
-                if (ruleDay != endDay) {
-                    ruleDay -= 7;
-                }
-                break;
+                    break;
+                case DOW_GE_DOM_MODE:
+                    ruleDay = endDay
+                            + mod7(
+                            endDayOfWeek - (firstDayOfMonth + endDay - 1));
+                    break;
+                case DOW_LE_DOM_MODE:
+                    ruleDay = endDay
+                            + mod7(
+                            endDayOfWeek - (firstDayOfMonth + endDay - 1));
+                    if (ruleDay != endDay) {
+                        ruleDay -= 7;
+                    }
+                    break;
             }
 
             int ruleMonth = endMonth;
@@ -488,10 +525,13 @@
             }
         }
         return rawOffset + dstSavings;
+        // END android-changed
     }
 
     @Override
     public int getOffset(long time) {
+        // BEGIN android-changed
+        // return icuTZ.getOffset(time);
         if (!useDaylightTime()) {
             return rawOffset;
         }
@@ -499,6 +539,7 @@
             daylightSavings = new GregorianCalendar(this);
         }
         return daylightSavings.getOffset(time + rawOffset);
+        // END android-changed
     }
 
     @Override
@@ -509,10 +550,9 @@
     /**
      * Returns an integer hash code for the receiver. Objects which are equal
      * return the same value for this method.
-     * 
+     *
      * @return the receiver's hash.
      * @see #equals
-     * @since Android 1.0
      */
     @Override
     public synchronized int hashCode() {
@@ -548,6 +588,8 @@
 
     @Override
     public boolean inDaylightTime(Date time) {
+        // BEGIN android-changed
+        // return icuTZ.inDaylightTime(time);
         // check for null pointer
         long millis = time.getTime();
         if (!useDaylightTime()) {
@@ -557,6 +599,7 @@
             daylightSavings = new GregorianCalendar(this);
         }
         return daylightSavings.getOffset(millis + rawOffset) != rawOffset;
+        // END android-changed
     }
 
     private boolean isLeapYear(int year) {
@@ -566,17 +609,18 @@
         return year % 4 == 0;
     }
 
+    // BEGIN android-added
     private int mod7(int num1) {
         int rem = num1 % 7;
         return (num1 < 0 && rem < 0) ? 7 + rem : rem;
     }
+    // END android-added
 
     /**
      * Sets the daylight savings offset in milliseconds for this {@code SimpleTimeZone}.
-     * 
+     *
      * @param milliseconds
      *            the daylight savings offset in milliseconds.
-     * @since Android 1.0
      */
     public void setDSTSavings(int milliseconds) {
         if (milliseconds > 0) {
@@ -591,7 +635,8 @@
             throw new IllegalArgumentException(Msg.getString("K00e5", month)); //$NON-NLS-1$
         }
         if (dayOfWeek < Calendar.SUNDAY || dayOfWeek > Calendar.SATURDAY) {
-            throw new IllegalArgumentException(Msg.getString("K00e7", dayOfWeek)); //$NON-NLS-1$
+            throw new IllegalArgumentException(Msg
+                    .getString("K00e7", dayOfWeek)); //$NON-NLS-1$
         }
         if (time < 0 || time >= 24 * 3600000) {
             throw new IllegalArgumentException(Msg.getString("K00e8", time)); //$NON-NLS-1$
@@ -626,7 +671,8 @@
                 checkDay(endMonth, endDay);
             } else {
                 if (endDay < -5 || endDay > 5) {
-                    throw new IllegalArgumentException(Msg.getString("K00f8", endDay)); //$NON-NLS-1$
+                    throw new IllegalArgumentException(Msg.getString(
+                            "K00f8", endDay)); //$NON-NLS-1$
                 }
             }
         }
@@ -637,7 +683,7 @@
 
     /**
      * Sets the rule which specifies the end of daylight savings time.
-     * 
+     *
      * @param month
      *            the {@code Calendar} month in which daylight savings time ends.
      * @param dayOfMonth
@@ -646,7 +692,6 @@
      * @param time
      *            the time of day in milliseconds standard time on which
      *            daylight savings time ends.
-     * @since Android 1.0
      */
     public void setEndRule(int month, int dayOfMonth, int time) {
         endMonth = month;
@@ -654,11 +699,17 @@
         endDayOfWeek = 0; // Initialize this value for hasSameRules()
         endTime = time;
         setEndMode();
+        // BEGIN android-removed
+        // if (isSimple) {
+        //     ((com.ibm.icu.util.SimpleTimeZone) icuTZ).setEndRule(month,
+        //             dayOfMonth, time);
+        // }
+        // END android-removed
     }
 
     /**
      * Sets the rule which specifies the end of daylight savings time.
-     * 
+     *
      * @param month
      *            the {@code Calendar} month in which daylight savings time ends.
      * @param day
@@ -670,7 +721,6 @@
      * @param time
      *            the time of day in milliseconds standard time on which
      *            daylight savings time ends.
-     * @since Android 1.0
      */
     public void setEndRule(int month, int day, int dayOfWeek, int time) {
         endMonth = month;
@@ -678,11 +728,17 @@
         endDayOfWeek = dayOfWeek;
         endTime = time;
         setEndMode();
+        // BEGIN android-removed
+        // if (isSimple) {
+        //     ((com.ibm.icu.util.SimpleTimeZone) icuTZ).setEndRule(month, day,
+        //             dayOfWeek, time);
+        // }
+        // END android-removed
     }
 
     /**
      * Sets the rule which specifies the end of daylight savings time.
-     * 
+     *
      * @param month
      *            the {@code Calendar} month in which daylight savings time ends.
      * @param day
@@ -695,7 +751,6 @@
      *            ends.
      * @param after
      *            selects the day after or before the day of month.
-     * @since Android 1.0
      */
     public void setEndRule(int month, int day, int dayOfWeek, int time,
             boolean after) {
@@ -704,18 +759,26 @@
         endDayOfWeek = -dayOfWeek;
         endTime = time;
         setEndMode();
+        // BEGIN android-removed
+        // if (isSimple) {
+        //     ((com.ibm.icu.util.SimpleTimeZone) icuTZ).setEndRule(month, day,
+        //             dayOfWeek, time, after);
+        // }
+        // END android-removed
     }
 
     /**
      * Sets the offset for standard time from GMT for this {@code SimpleTimeZone}.
-     * 
+     *
      * @param offset
      *            the offset from GMT of standard time in milliseconds.
-     * @since Android 1.0
      */
     @Override
     public void setRawOffset(int offset) {
         rawOffset = offset;
+        // BEGIN android-removed
+        // icuTZ.setRawOffset(offset);
+        // END android-removed
     }
 
     private void setStartMode() {
@@ -740,7 +803,8 @@
                 checkDay(startMonth, startDay);
             } else {
                 if (startDay < -5 || startDay > 5) {
-                    throw new IllegalArgumentException(Msg.getString("K00f8", startDay)); //$NON-NLS-1$
+                    throw new IllegalArgumentException(Msg.getString(
+                            "K00f8", startDay)); //$NON-NLS-1$
                 }
             }
         }
@@ -751,7 +815,7 @@
 
     /**
      * Sets the rule which specifies the start of daylight savings time.
-     * 
+     *
      * @param month
      *            the {@code Calendar} month in which daylight savings time starts.
      * @param dayOfMonth
@@ -760,7 +824,6 @@
      * @param time
      *            the time of day in milliseconds on which daylight savings time
      *            starts.
-     * @since Android 1.0
      */
     public void setStartRule(int month, int dayOfMonth, int time) {
         startMonth = month;
@@ -768,11 +831,17 @@
         startDayOfWeek = 0; // Initialize this value for hasSameRules()
         startTime = time;
         setStartMode();
+        // BEGIN android-removed
+        // if (isSimple) {
+        //     ((com.ibm.icu.util.SimpleTimeZone) icuTZ).setStartRule(month,
+        //             dayOfMonth, time);
+        // }
+        // END android-removed
     }
 
     /**
      * Sets the rule which specifies the start of daylight savings time.
-     * 
+     *
      * @param month
      *            the {@code Calendar} month in which daylight savings time starts.
      * @param day
@@ -784,7 +853,6 @@
      * @param time
      *            the time of day in milliseconds on which daylight savings time
      *            starts.
-     * @since Android 1.0
      */
     public void setStartRule(int month, int day, int dayOfWeek, int time) {
         startMonth = month;
@@ -792,11 +860,17 @@
         startDayOfWeek = dayOfWeek;
         startTime = time;
         setStartMode();
+        // BEGIN android-removed
+        // if (isSimple) {
+        //     ((com.ibm.icu.util.SimpleTimeZone) icuTZ).setStartRule(month, day,
+        //             dayOfWeek, time);
+        // }
+        // END android-removed
     }
 
     /**
      * Sets the rule which specifies the start of daylight savings time.
-     * 
+     *
      * @param month
      *            the {@code Calendar} month in which daylight savings time starts.
      * @param day
@@ -809,7 +883,6 @@
      *            starts.
      * @param after
      *            selects the day after or before the day of month.
-     * @since Android 1.0
      */
     public void setStartRule(int month, int day, int dayOfWeek, int time,
             boolean after) {
@@ -818,15 +891,20 @@
         startDayOfWeek = -dayOfWeek;
         startTime = time;
         setStartMode();
+        // BEGIN android-removed
+        // if (isSimple) {
+        //     ((com.ibm.icu.util.SimpleTimeZone) icuTZ).setStartRule(month, day,
+        //             dayOfWeek, time, after);
+        // }
+        // END android-removed
     }
 
     /**
      * Sets the starting year for daylight savings time in this {@code SimpleTimeZone}.
      * Years before this start year will always be in standard time.
-     * 
+     *
      * @param year
      *            the starting year.
-     * @since Android 1.0
      */
     public void setStartYear(int year) {
         startYear = year;
@@ -835,9 +913,8 @@
 
     /**
      * Returns the string representation of this {@code SimpleTimeZone}.
-     * 
+     *
      * @return the string representation of this {@code SimpleTimeZone}.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -864,7 +941,7 @@
                 + endMode + ",endMonth=" + endMonth + ",endDay=" + endDay //$NON-NLS-1$ //$NON-NLS-2$
                 + ",endDayOfWeek=" //$NON-NLS-1$
                 + (useDaylight && (endMode != DOM_MODE) ? endDayOfWeek + 1 : 0)
-                + ",endTime=" + endTime + "]";  //$NON-NLS-1$//$NON-NLS-2$
+                + ",endTime=" + endTime + "]"; //$NON-NLS-1$//$NON-NLS-2$
     }
 
     @Override
diff --git a/libcore/luni/src/main/java/java/util/SortedMap.java b/libcore/luni/src/main/java/java/util/SortedMap.java
index 10b2647..2fb25fd 100644
--- a/libcore/luni/src/main/java/java/util/SortedMap.java
+++ b/libcore/luni/src/main/java/java/util/SortedMap.java
@@ -21,8 +21,6 @@
 /**
  * A map that has its keys ordered. The sorting is according to either the
  * natural ordering of its keys or the ordering given by a specified comparator.
- * 
- * @since Android 1.0
  */
 public interface SortedMap<K,V> extends Map<K,V> {
     
@@ -30,7 +28,6 @@
      * Returns the comparator used to compare keys in this sorted map.
      * 
      * @return the comparator or {@code null} if the natural order is used.
-     * @since Android 1.0
      */
     public Comparator<? super K> comparator();
 
@@ -38,9 +35,8 @@
      * Returns the first key in this sorted map.
      * 
      * @return the first key in this sorted map.
-     * @exception NoSuchElementException
+     * @throws NoSuchElementException
      *                if this sorted map is empty.
-     * @since Android 1.0
      */
     public K firstKey();
 
@@ -51,8 +47,7 @@
      * <p>
      * Note: The returned map will not allow an insertion of a key outside the
      * specified range.
-     * </p>
-     * 
+     *
      * @param endKey
      *            the high boundary of the range specified.
      * @return a sorted map where the keys are less than {@code endKey}.
@@ -65,7 +60,6 @@
      * @throws IllegalArgumentException
      *             if this map is itself a sorted map over a range of another
      *             map and the specified key is outside of its range.
-     * @since Android 1.0
      */
     public SortedMap<K,V> headMap(K endKey);
 
@@ -73,9 +67,8 @@
      * Returns the last key in this sorted map.
      * 
      * @return the last key in this sorted map.
-     * @exception NoSuchElementException
+     * @throws NoSuchElementException
      *                if this sorted map is empty.
-     * @since Android 1.0
      */
     public K lastKey();
 
@@ -87,8 +80,7 @@
      * <p>
      * Note: The returned map will not allow an insertion of a key outside the
      * specified range.
-     * </p>
-     * 
+     *
      * @param startKey
      *            the low boundary of the range (inclusive).
      * @param endKey
@@ -104,7 +96,6 @@
      *             if the start key is greater than the end key, or if this map
      *             is itself a sorted map over a range of another sorted map and
      *             the specified range is outside of its range.
-     * @since Android 1.0
      */
     public SortedMap<K,V> subMap(K startKey, K endKey);
 
@@ -115,7 +106,6 @@
      * <p>
      * Note: The returned map will not allow an insertion of a key outside the
      * specified range.
-     * </p>
      * 
      * @param startKey
      *            the low boundary of the range specified.
@@ -130,7 +120,6 @@
      * @throws IllegalArgumentException
      *             if this map itself a sorted map over a range of another map
      *             and the specified key is outside of its range.
-     * @since Android 1.0
      */
     public SortedMap<K,V> tailMap(K startKey);
 }
diff --git a/libcore/luni/src/main/java/java/util/SortedSet.java b/libcore/luni/src/main/java/java/util/SortedSet.java
index 24fa017..d387540 100644
--- a/libcore/luni/src/main/java/java/util/SortedSet.java
+++ b/libcore/luni/src/main/java/java/util/SortedSet.java
@@ -27,7 +27,6 @@
  * 
  * @see Comparator
  * @see Comparable
- * @since Android 1.0
  */
 public interface SortedSet<E> extends Set<E> {
     
@@ -35,7 +34,6 @@
      * Returns the comparator used to compare elements in this {@code SortedSet}.
      * 
      * @return a comparator or null if the natural ordering is used.
-     * @since Android 1.0
      */
     public Comparator<? super E> comparator();
 
@@ -46,7 +44,6 @@
      * @return the first element.
      * @throws NoSuchElementException
      *             when this {@code SortedSet} is empty.
-     * @since Android 1.0
      */
     public E first();
 
@@ -65,7 +62,6 @@
      * @throws NullPointerException
      *             when the end element is null and this {@code SortedSet} does
      *             not support null elements.
-     * @since Android 1.0
      */
     public SortedSet<E> headSet(E end);
 
@@ -76,7 +72,6 @@
      * @return the last element.
      * @throws NoSuchElementException
      *             when this {@code SortedSet} is empty.
-     * @since Android 1.0
      */
     public E last();
 
@@ -101,7 +96,6 @@
      *             {@code SortedSet} does not support null elements.
      * @throws IllegalArgumentException
      *             when the start element is greater than the end element.
-     * @since Android 1.0
      */
     public SortedSet<E> subSet(E start, E end);
 
@@ -120,7 +114,6 @@
      * @throws NullPointerException
      *             when the start element is null and this {@code SortedSet}
      *             does not support null elements.
-     * @since Android 1.0
      */
     public SortedSet<E> tailSet(E start);
 }
diff --git a/libcore/luni/src/main/java/java/util/Stack.java b/libcore/luni/src/main/java/java/util/Stack.java
index 8ecb765..1572a08 100644
--- a/libcore/luni/src/main/java/java/util/Stack.java
+++ b/libcore/luni/src/main/java/java/util/Stack.java
@@ -17,22 +17,17 @@
 
 package java.util;
 
-
 /**
  * {@code Stack} is a Last-In/First-Out(LIFO) data structure which represents a
  * stack of objects. It enables users to pop to and push from the stack,
  * including null objects. There is no limit to the size of the stack.
- * 
- * @since Android 1.0
  */
 public class Stack<E> extends Vector<E> {
-    
+
     private static final long serialVersionUID = 1224463164541339165L;
 
     /**
      * Constructs a stack with the default size of {@code Vector}.
-     * 
-     * @since Android 1.0
      */
     public Stack() {
         super();
@@ -40,9 +35,8 @@
 
     /**
      * Returns whether the stack is empty or not.
-     * 
+     *
      * @return {@code true} if the stack is empty, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean empty() {
         return elementCount == 0;
@@ -50,16 +44,16 @@
 
     /**
      * Returns the element at the top of the stack without removing it.
-     * 
+     *
      * @return the element at the top of the stack.
      * @throws EmptyStackException
      *             if the stack is empty.
      * @see #pop
-     * @since Android 1.0
      */
+    @SuppressWarnings("unchecked")
     public synchronized E peek() {
         try {
-            return (E)elementData[elementCount - 1];
+            return (E) elementData[elementCount - 1];
         } catch (IndexOutOfBoundsException e) {
             throw new EmptyStackException();
         }
@@ -67,36 +61,35 @@
 
     /**
      * Returns the element at the top of the stack and removes it.
-     * 
+     *
      * @return the element at the top of the stack.
      * @throws EmptyStackException
      *             if the stack is empty.
      * @see #peek
      * @see #push
-     * @since Android 1.0
      */
+    @SuppressWarnings("unchecked")
     public synchronized E pop() {
-        try {
-            int index = elementCount - 1;
-            E obj = (E)elementData[index];
-            removeElementAt(index);
-            return obj;
-        } catch (IndexOutOfBoundsException e) {
+        if (elementCount == 0) {
             throw new EmptyStackException();
         }
+        final int index = --elementCount;
+        final E obj = (E) elementData[index];
+        elementData[index] = null;
+        modCount++;
+        return obj;
     }
 
     /**
      * Pushes the specified object onto the top of the stack.
-     * 
+     *
      * @param object
      *            The object to be added on top of the stack.
      * @return the object argument.
      * @see #peek
      * @see #pop
-     * @since Android 1.0
      */
-    public synchronized E push(E object) {
+    public E push(E object) {
         addElement(object);
         return object;
     }
@@ -104,17 +97,28 @@
     /**
      * Returns the index of the first occurrence of the object, starting from
      * the top of the stack.
-     * 
+     *
      * @return the index of the first occurrence of the object, assuming that
      *         the topmost object on the stack has a distance of one.
      * @param o
      *            the object to be searched.
-     * @since Android 1.0
      */
     public synchronized int search(Object o) {
-        int index = lastIndexOf(o);
-        if (index >= 0)
-            return (elementCount - index);
+        final Object[] dumpArray = elementData;
+        final int size = elementCount;
+        if (o != null) {
+            for (int i = size - 1; i >= 0; i--) {
+                if (o.equals(dumpArray[i])) {
+                    return size - i;
+                }
+            }
+        } else {
+            for (int i = size - 1; i >= 0; i--) {
+                if (dumpArray[i] == null) {
+                    return size - i;
+                }
+            }
+        }
         return -1;
     }
 }
diff --git a/libcore/luni/src/main/java/java/util/StringTokenizer.java b/libcore/luni/src/main/java/java/util/StringTokenizer.java
index 3bbeefa..2800283 100644
--- a/libcore/luni/src/main/java/java/util/StringTokenizer.java
+++ b/libcore/luni/src/main/java/java/util/StringTokenizer.java
@@ -14,32 +14,17 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-/**
-*******************************************************************************
-* Copyright (C) 1996-2006, International Business Machines Corporation and    *
-* others. All Rights Reserved.                                                *
-*******************************************************************************
-*/
 
 package java.util;
 
-
-// BEGIN android-note
-// The class javadoc and some of the method descriptions are copied from ICU4J
-// source files. Changes have been made to the copied descriptions.
-// The icu license header was added to this file. 
-// END android-note
 /**
- * <p>
  * The {@code StringTokenizer} class allows an application to break a string
  * into tokens by performing code point comparison. The {@code StringTokenizer}
  * methods do not distinguish among identifiers, numbers, and quoted strings,
  * nor do they recognize and skip comments.
- * </p>
  * <p>
  * The set of delimiters (the codepoints that separate tokens) may be specified
  * either at creation time or on a per-token basis.
- * </p>
  * <p>
  * An instance of {@code StringTokenizer} behaves in one of three ways,
  * depending on whether it was created with the {@code returnDelimiters} flag
@@ -55,45 +40,40 @@
  * <p>
  * A token is thus either one delimiter code point, or a maximal sequence of
  * consecutive code points that are not delimiters.
- * </p>
  * <p>
  * A {@code StringTokenizer} object internally maintains a current position
  * within the string to be tokenized. Some operations advance this current
  * position past the code point processed.
- * </p>
  * <p>
  * A token is returned by taking a substring of the string that was used to
  * create the {@code StringTokenizer} object.
- * </p>
  * <p>
  * Here's an example of the use of the default delimiter {@code StringTokenizer}
  * : <blockquote>
- * 
+ *
  * <pre>
  * StringTokenizer st = new StringTokenizer(&quot;this is a test&quot;);
  * while (st.hasMoreTokens()) {
  *     println(st.nextToken());
  * }
  * </pre>
- * 
+ *
  * </blockquote>
- * </p>
  * <p>
  * This prints the following output: <blockquote>
- * 
+ *
  * <pre>
  *     this
  *     is
  *     a
  *     test
  * </pre>
- * 
+ *
  * </blockquote>
- * </p>
  * <p>
  * Here's an example of how to use a {@code StringTokenizer} with a user
  * specified delimiter: <blockquote>
- * 
+ *
  * <pre>
  * StringTokenizer st = new StringTokenizer(
  *         &quot;this is a test with supplementary characters \ud800\ud800\udc00\udc00&quot;,
@@ -102,12 +82,11 @@
  *     println(st.nextToken());
  * }
  * </pre>
- * 
+ *
  * </blockquote>
- * </p>
  * <p>
  * This prints the following output: <blockquote>
- * 
+ *
  * <pre>
  *     this
  *     is
@@ -119,14 +98,11 @@
  *     \ud800
  *     \udc00
  * </pre>
- * 
+ *
  * </blockquote>
- * </p>
- * 
- * @since Android 1.0
  */
 public class StringTokenizer implements Enumeration<Object> {
-    
+
     private String string;
 
     private String delimiters;
@@ -139,10 +115,9 @@
      * Constructs a new {@code StringTokenizer} for the parameter string using
      * whitespace as the delimiter. The {@code returnDelimiters} flag is set to
      * {@code false}.
-     * 
+     *
      * @param string
      *            the string to be tokenized.
-     * @since Android 1.0
      */
     public StringTokenizer(String string) {
         this(string, " \t\n\r\f", false); //$NON-NLS-1$
@@ -154,12 +129,11 @@
      * {@code false}. If {@code delimiters} is {@code null}, this constructor
      * doesn't throw an {@code Exception}, but later calls to some methods might
      * throw a {@code NullPointerException}.
-     * 
+     *
      * @param string
      *            the string to be tokenized.
      * @param delimiters
      *            the delimiters to use.
-     * @since Android 1.0
      */
     public StringTokenizer(String string, String delimiters) {
         this(string, delimiters, false);
@@ -171,14 +145,13 @@
      * parameter {@code returnDelimiters} is {@code true}. If {@code delimiters}
      * is null this constructor doesn't throw an {@code Exception}, but later
      * calls to some methods might throw a {@code NullPointerException}.
-     * 
+     *
      * @param string
      *            the string to be tokenized.
      * @param delimiters
      *            the delimiters to use.
      * @param returnDelimiters
      *            {@code true} to return each delimiter as a token.
-     * @since Android 1.0
      */
     public StringTokenizer(String string, String delimiters,
             boolean returnDelimiters) {
@@ -193,10 +166,9 @@
 
     /**
      * Returns the number of unprocessed tokens remaining in the string.
-     * 
+     *
      * @return number of tokens that can be retreived before an {@code
      *         Exception} will result from a call to {@code nextToken()}.
-     * @since Android 1.0
      */
     public int countTokens() {
         int count = 0;
@@ -221,9 +193,8 @@
     /**
      * Returns {@code true} if unprocessed tokens remain. This method is
      * implemented in order to satisfy the {@code Enumeration} interface.
-     * 
+     *
      * @return {@code true} if unprocessed tokens remain.
-     * @since Android 1.0
      */
     public boolean hasMoreElements() {
         return hasMoreTokens();
@@ -231,11 +202,13 @@
 
     /**
      * Returns {@code true} if unprocessed tokens remain.
-     * 
+     *
      * @return {@code true} if unprocessed tokens remain.
-     * @since Android 1.0
      */
     public boolean hasMoreTokens() {
+        if (delimiters == null) {
+            throw new NullPointerException();
+        }
         int length = string.length();
         if (position < length) {
             if (returnDelimiters)
@@ -253,11 +226,10 @@
     /**
      * Returns the next token in the string as an {@code Object}. This method is
      * implemented in order to satisfy the {@code Enumeration} interface.
-     * 
+     *
      * @return next token in the string as an {@code Object}
-     * @exception NoSuchElementException
+     * @throws NoSuchElementException
      *                if no tokens remain.
-     * @since Android 1.0
      */
     public Object nextElement() {
         return nextToken();
@@ -265,13 +237,15 @@
 
     /**
      * Returns the next token in the string as a {@code String}.
-     * 
+     *
      * @return next token in the string as a {@code String}.
-     * @exception NoSuchElementException
+     * @throws NoSuchElementException
      *                if no tokens remain.
-     * @since Android 1.0
      */
     public String nextToken() {
+        if (delimiters == null) {
+            throw new NullPointerException();
+        }
         int i = position;
         int length = string.length();
 
@@ -301,20 +275,14 @@
     /**
      * Returns the next token in the string as a {@code String}. The delimiters
      * used are changed to the specified delimiters.
-     * 
+     *
      * @param delims
      *            the new delimiters to use.
      * @return next token in the string as a {@code String}.
-     * @exception NoSuchElementException
+     * @throws NoSuchElementException
      *                if no tokens remain.
-     * @since Android 1.0
      */
     public String nextToken(String delims) {
-        // BEGIN android-added
-        if (delims == null) {
-            throw new NullPointerException();
-        }
-        // END android-added
         this.delimiters = delims;
         return nextToken();
     }
diff --git a/libcore/luni/src/main/java/java/util/TimSort.java b/libcore/luni/src/main/java/java/util/TimSort.java
index 9c27ddc..4a9c05b 100644
--- a/libcore/luni/src/main/java/java/util/TimSort.java
+++ b/libcore/luni/src/main/java/java/util/TimSort.java
@@ -182,7 +182,7 @@
 
         // If array is small, do a "mini-TimSort" with no merges
         if (nRemaining < MIN_MERGE) {
-            int initRunLen = countRunAndMakeAscending(a, lo, nRemaining, c);
+            int initRunLen = countRunAndMakeAscending(a, lo, hi, c);
             binarySort(a, lo, hi, lo + initRunLen, c);
             return;
         }
diff --git a/libcore/luni/src/main/java/java/util/TimeZone.java b/libcore/luni/src/main/java/java/util/TimeZone.java
index c9709ce..b4878ca 100644
--- a/libcore/luni/src/main/java/java/util/TimeZone.java
+++ b/libcore/luni/src/main/java/java/util/TimeZone.java
@@ -14,35 +14,17 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-/**
-*******************************************************************************
-* Copyright (C) 1996-2008, International Business Machines Corporation and    *
-* others. All Rights Reserved.                                                *
-*******************************************************************************
-*/
-
-// BEGIN android-note
-// The class javadoc and some of the method descriptions are copied from ICU4J
-// source files. Changes have been made to the copied descriptions.
-// The icu license header was added to this file. 
-// END android-note
 
 package java.util;
 
-
 import java.io.Serializable;
-// BEGIN android-removed
-// import java.security.AccessController;
-// import java.text.DateFormatSymbols;
-// 
-// import org.apache.harmony.luni.util.PriviAction;
-// END android-removed
 
 // BEGIN android-added
 import org.apache.harmony.luni.internal.util.ZoneInfo;
 import org.apache.harmony.luni.internal.util.ZoneInfoDB;
 import com.ibm.icu4jni.util.Resources;
 // END android-added
+
 /**
  * {@code TimeZone} represents a time zone offset, taking into account
  * daylight savings.
@@ -57,21 +39,21 @@
  * along with a time zone ID. For instance, the time zone ID for the U.S.
  * Pacific Time zone is "America/Los_Angeles". So, you can get a U.S. Pacific
  * Time {@code TimeZone} object with the following: <blockquote>
- * 
+ *
  * <pre>
  * TimeZone tz = TimeZone.getTimeZone(&quot;America/Los_Angeles&quot;);
  * </pre>
- * 
+ *
  * </blockquote> You can use the {@code getAvailableIDs} method to iterate
  * through all the supported time zone IDs. You can then choose a supported ID
  * to get a {@code TimeZone}. If the time zone you want is not
  * represented by one of the supported IDs, then you can create a custom time
  * zone ID with the following syntax: <blockquote>
- * 
+ *
  * <pre>
  * GMT[+|-]hh[[:]mm]
  * </pre>
- * 
+ *
  * </blockquote> For example, you might specify GMT+14:00 as a custom time zone
  * ID. The {@code TimeZone} that is returned when you specify a custom
  * time zone ID does not include daylight savings time.
@@ -83,33 +65,26 @@
  * "China Standard Time"), and the Java platform can then only recognize one of
  * them.
  * <p>
- * Please note the type returned by factory methods, i.e.
- * {@code getDefault()} and {@code getTimeZone(String)}, is
- * implementation dependent, so it may introduce serialization
- * incompatibility issues between different implementations. Android returns
- * instances of {@link SimpleTimeZone} so that the bytes serialized by Android
- * can be deserialized successfully on other implementations, but the reverse
- * compatibility cannot be guaranteed.
- * 
+ * Please note the type returned by factory methods, i.e. {@code getDefault()}
+ * and {@code getTimeZone(String)}, is implementation dependent, so it may
+ * introduce serialization incompatibility issues between different
+ * implementations. Android returns instances of {@link SimpleTimeZone} so that
+ * the bytes serialized by Android can be deserialized successfully on other
+ * implementations, but the reverse compatibility cannot be guaranteed.
+ *
  * @see GregorianCalendar
  * @see SimpleTimeZone
- * @since Android 1.0
  */
-
 public abstract class TimeZone implements Serializable, Cloneable {
     private static final long serialVersionUID = 3581463369166924961L;
 
     /**
      * The SHORT display name style.
-     * 
-     * @since Android 1.0
      */
     public static final int SHORT = 0;
 
     /**
      * The LONG display name style.
-     * 
-     * @since Android 1.0
      */
     public static final int LONG = 1;
 
@@ -124,41 +99,49 @@
     private String ID;
 
     // BEGIN android-removed
+    // private com.ibm.icu.util.TimeZone icuTimeZone = null;
+    //
     // private static void initializeAvailable() {
     //     TimeZone[] zones = TimeZones.getTimeZones();
-    //     AvailableZones = new HashMap<String, TimeZone>((zones.length + 1) * 4 / 3);
+    //     AvailableZones = new HashMap<String, TimeZone>(
+    //             (zones.length + 1) * 4 / 3);
     //     AvailableZones.put(GMT.getID(), GMT);
     //     for (int i = 0; i < zones.length; i++) {
     //         AvailableZones.put(zones[i].getID(), zones[i]);
     //     }
+    //}
+    //
+    // private static boolean isAvailableIDInICU(String name) {
+    //     String[] availableIDs = com.ibm.icu.util.TimeZone.getAvailableIDs();
+    //     for (int i = 0; i < availableIDs.length; i++) {
+    //         if (availableIDs[i].equals(name)) {
+    //             return true;
+    //         }
+    //     }
+    //     return false;
+    // }
+    //
+    // private static void appendAvailableZones(String name) {
+    //     com.ibm.icu.util.TimeZone icuTZ = com.ibm.icu.util.TimeZone
+    //             .getTimeZone(name);
+    //     int raw = icuTZ.getRawOffset();
+    //     TimeZone zone = new SimpleTimeZone(raw, name);
+    //     AvailableZones.put(name, zone);
     // }
     // END android-removed
 
     /**
      * Constructs a new instance of this class.
-     * 
-     * @since Android 1.0
      */
     public TimeZone() {
     }
 
-    private void appendNumber(StringBuffer buffer, int count, int value) {
-        String string = Integer.toString(value);
-        if (count > string.length()) {
-            for (int i = 0; i < count - string.length(); i++) {
-                buffer.append('0');
-            }
-        }
-        buffer.append(string);
-    }
-
     /**
      * Returns a new {@code TimeZone} with the same ID, {@code rawOffset} and daylight savings
      * time rules as this {@code TimeZone}.
-     * 
+     *
      * @return a shallow copy of this {@code TimeZone}.
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -173,49 +156,34 @@
     /**
      * Gets the available time zone IDs. Any one of these IDs can be passed to
      * {@code get()} to create the corresponding {@code TimeZone} instance.
-     * 
+     *
      * @return an array of time zone ID strings.
-     * @since Android 1.0
      */
     public static synchronized String[] getAvailableIDs() {
-        // BEGIN android-removed
-        // if (AvailableZones == null) {
-        //     initializeAvailable();
-        // }
-        // int length = AvailableZones.size();
-        // String[] answer = new String[length];
-        // Iterator<String> keys = AvailableZones.keySet().iterator();
-        // for (int i = 0; i < length; i++) {
-        //     answer[i] = keys.next();
-        // }
-        // return answer;
-        // END android-removed
-
-        // BEGIN android-added
+        // BEGIN android-changed
+        // return com.ibm.icu.util.TimeZone.getAvailableIDs();
         return ZoneInfoDB.getAvailableIDs();
-        // END android-added
+        // END android-changed
     }
 
     /**
      * Gets the available time zone IDs which match the specified offset from
      * GMT. Any one of these IDs can be passed to {@code get()} to create the corresponding
      * {@code TimeZone} instance.
-     * 
+     *
      * @param offset
      *            the offset from GMT in milliseconds.
      * @return an array of time zone ID strings.
-     * @since Android 1.0
      */
     public static synchronized String[] getAvailableIDs(int offset) {
-        // BEGIN android-removed
-        // if (AvailableZones == null) {
-        //     initializeAvailable();
-        // }
-        // int count = 0, length = AvailableZones.size();
+        // BEGIN android-changed
+        // String[] availableIDs = com.ibm.icu.util.TimeZone.getAvailableIDs();
+        // int count = 0;
+        // int length = availableIDs.length;
         // String[] all = new String[length];
-        // Iterator<TimeZone> zones = AvailableZones.values().iterator();
         // for (int i = 0; i < length; i++) {
-        //     TimeZone tz = zones.next();
+        //     com.ibm.icu.util.TimeZone tz = com.ibm.icu.util.TimeZone
+        //             .getTimeZone(availableIDs[i]);
         //     if (tz.getRawOffset() == offset) {
         //         all[count++] = tz.getID();
         //     }
@@ -223,23 +191,21 @@
         // String[] answer = new String[count];
         // System.arraycopy(all, 0, answer, 0, count);
         // return answer;
-        // END android-removed
-        
-        // BEGIN android-added
         return ZoneInfoDB.getAvailableIDs(offset);
-        // END android-added
-        
+        // END android-changed
     }
 
     /**
      * Gets the default time zone.
-     * 
+     *
      * @return the default time zone.
-     * @since Android 1.0
      */
     public static synchronized TimeZone getDefault() {
         if (Default == null) {
+            // BEGIN android-changed
+            // setDefault(null);
             Default = ZoneInfoDB.getDefault();
+            // END android-changed
         }
         return (TimeZone) Default.clone();
     }
@@ -248,9 +214,8 @@
      * Gets the LONG name for this {@code TimeZone} for the default {@code Locale} in standard
      * time. If the name is not available, the result is in the format
      * {@code GMT[+-]hh:mm}.
-     * 
+     *
      * @return the {@code TimeZone} name.
-     * @since Android 1.0
      */
     public final String getDisplayName() {
         return getDisplayName(false, LONG, Locale.getDefault());
@@ -260,11 +225,10 @@
      * Gets the LONG name for this {@code TimeZone} for the specified {@code Locale} in standard
      * time. If the name is not available, the result is in the format
      * {@code GMT[+-]hh:mm}.
-     * 
+     *
      * @param locale
      *            the {@code Locale}.
      * @return the {@code TimeZone} name.
-     * @since Android 1.0
      */
     public final String getDisplayName(Locale locale) {
         return getDisplayName(false, LONG, locale);
@@ -274,14 +238,13 @@
      * Gets the specified style of name ({@code LONG} or {@code SHORT}) for this {@code TimeZone} for
      * the default {@code Locale} in either standard or daylight time as specified. If
      * the name is not available, the result is in the format {@code GMT[+-]hh:mm}.
-     * 
+     *
      * @param daylightTime
      *            {@code true} for daylight time, {@code false} for standard
      *            time.
      * @param style
-     *            Either {@code LONG} or {@code SHORT}.
+     *            either {@code LONG} or {@code SHORT}.
      * @return the {@code TimeZone} name.
-     * @since Android 1.0
      */
     public final String getDisplayName(boolean daylightTime, int style) {
         return getDisplayName(daylightTime, style, Locale.getDefault());
@@ -291,39 +254,31 @@
      * Gets the specified style of name ({@code LONG} or {@code SHORT}) for this {@code TimeZone} for
      * the specified {@code Locale} in either standard or daylight time as specified. If
      * the name is not available, the result is in the format {@code GMT[+-]hh:mm}.
-     * 
+     *
      * @param daylightTime
      *            {@code true} for daylight time, {@code false} for standard
      *            time.
      * @param style
-     *            Either LONG or SHORT.
+     *            either LONG or SHORT.
      * @param locale
-     *            Either {@code LONG} or {@code SHORT}.
+     *            either {@code LONG} or {@code SHORT}.
      * @return the {@code TimeZone} name.
-     * @since Android 1.0
      */
     public String getDisplayName(boolean daylightTime, int style, Locale locale) {
+        // BEGIN android-changed
+        // if(icuTimeZone == null || !ID.equals(icuTimeZone.getID())){
+        //     icuTimeZone = com.ibm.icu.util.TimeZone.getTimeZone(ID);
+        // }
+        // return icuTimeZone.getDisplayName(
+        //         daylightTime, style, locale);
         if (style == SHORT || style == LONG) {
             boolean useDaylight = daylightTime && useDaylightTime();
-            // BEGIN android-removed
-            // DateFormatSymbols data = new DateFormatSymbols(locale);
-            // String id = getID();
-            // String[][] zones = data.getZoneStrings();
-            // for (int i = 0; i < zones.length; i++) {
-            //     if (id.equals(zones[i][0])) {
-            //         return style == SHORT ? zones[i][useDaylight ? 4 : 2]
-            //                 : zones[i][useDaylight ? 3 : 1];
-            //     }
-            // }
-            // BEGIN android-removed
-            
-            // BEGIN android-added
+
             String result = Resources.getDisplayTimeZone(getID(), daylightTime, style, locale.toString());
             if (result != null) {
                 return result;
             }
-            // END android-added
-            
+
             int offset = getRawOffset();
             if (useDaylight && this instanceof SimpleTimeZone) {
                 offset += ((SimpleTimeZone) this).getDSTSavings();
@@ -343,13 +298,25 @@
             return buffer.toString();
         }
         throw new IllegalArgumentException();
+        // END android-changed
     }
 
+    // BEGIN android-added
+    private void appendNumber(StringBuffer buffer, int count, int value) {
+        String string = Integer.toString(value);
+        if (count > string.length()) {
+            for (int i = 0; i < count - string.length(); i++) {
+                buffer.append('0');
+            }
+        }
+        buffer.append(string);
+    }
+    // END android-added
+
     /**
      * Gets the ID of this {@code TimeZone}.
-     * 
+     *
      * @return the time zone ID string.
-     * @since Android 1.0
      */
     public String getID() {
         return ID;
@@ -364,10 +331,9 @@
      * Subclasses may override to return daylight savings values other than 1
      * hour.
      * <p>
-     * 
+     *
      * @return the daylight savings offset in milliseconds if this {@code TimeZone}
      *         observes daylight savings, zero otherwise.
-     * @since Android 1.0
      */
     public int getDSTSavings() {
         if (useDaylightTime()) {
@@ -380,11 +346,10 @@
      * Gets the offset from GMT of this {@code TimeZone} for the specified date. The
      * offset includes daylight savings time if the specified date is within the
      * daylight savings time period.
-     * 
+     *
      * @param time
      *            the date in milliseconds since January 1, 1970 00:00:00 GMT
      * @return the offset from GMT in milliseconds.
-     * @since Android 1.0
      */
     public int getOffset(long time) {
         if (inDaylightTime(new Date(time))) {
@@ -397,7 +362,7 @@
      * Gets the offset from GMT of this {@code TimeZone} for the specified date and
      * time. The offset includes daylight savings time if the specified date and
      * time are within the daylight savings time period.
-     * 
+     *
      * @param era
      *            the {@code GregorianCalendar} era, either {@code GregorianCalendar.BC} or
      *            {@code GregorianCalendar.AD}.
@@ -412,39 +377,38 @@
      * @param time
      *            the time of day in milliseconds.
      * @return the offset from GMT in milliseconds.
-     * @since Android 1.0
      */
     abstract public int getOffset(int era, int year, int month, int day,
             int dayOfWeek, int time);
 
     /**
      * Gets the offset for standard time from GMT for this {@code TimeZone}.
-     * 
+     *
      * @return the offset from GMT in milliseconds.
-     * @since Android 1.0
      */
     abstract public int getRawOffset();
 
     /**
      * Gets the {@code TimeZone} with the specified ID.
-     * 
+     *
      * @param name
      *            a time zone string ID.
      * @return the {@code TimeZone} with the specified ID or null if no {@code TimeZone} with
      *         the specified ID exists.
-     * @since Android 1.0
      */
     public static synchronized TimeZone getTimeZone(String name) {
-        // BEGIN android-removed
+        // BEGIN android-changed
         // if (AvailableZones == null) {
         //     initializeAvailable();
         // }
+        //
         // TimeZone zone = AvailableZones.get(name);
-        // END android-removed
-        
-        // BEGIN android-added
+        // if(zone == null && isAvailableIDInICU(name)){
+        //     appendAvailableZones(name);
+        //     zone = AvailableZones.get(name);
+        // }
         TimeZone zone = ZoneInfo.getTimeZone(name);
-        // END android-added
+        // END android-changed
         if (zone == null) {
             if (name.startsWith("GMT") && name.length() > 3) {
                 char sign = name.charAt(3);
@@ -482,7 +446,7 @@
     }
 
     private static String formatTimeZoneName(String name, int offset) {
-        StringBuffer buf = new StringBuffer();
+        StringBuilder buf = new StringBuilder();
         int index = offset, length = name.length();
         buf.append(name.substring(0, offset));
 
@@ -513,12 +477,11 @@
     /**
      * Returns whether the specified {@code TimeZone} has the same raw offset as this
      * {@code TimeZone}.
-     * 
+     *
      * @param zone
      *            a {@code TimeZone}.
      * @return {@code true} when the {@code TimeZone} have the same raw offset, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public boolean hasSameRules(TimeZone zone) {
         if (zone == null) {
@@ -530,12 +493,11 @@
     /**
      * Returns whether the specified {@code Date} is in the daylight savings time period for
      * this {@code TimeZone}.
-     * 
+     *
      * @param time
      *            a {@code Date}.
      * @return {@code true} when the {@code Date} is in the daylight savings time period, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     abstract public boolean inDaylightTime(Date time);
 
@@ -555,34 +517,30 @@
      * time {@link #getDefault} is called, the default time zone will be
      * determined. This behavior is slightly different than the canonical
      * description of this method, but it follows the spirit of it.
-     * 
+     *
      * @param timezone
      *            a {@code TimeZone} object.
-     * @since Android 1.0
      */
     public static synchronized void setDefault(TimeZone timezone) {
         // BEGIN android-removed
         // if (timezone != null) {
+        //     setICUDefaultTimeZone(timezone);
         //     Default = timezone;
         //     return;
         // }
-        // END android-removed
-
-        // BEGIN android-added
-        Default = timezone;
-
-        // TODO Not sure if this is spec-compliant. Shouldn't be persistent.
-        ZoneInfoDB.setDefault(timezone);
-        // END android-added
-        
-        // BEGIN android-removed
+        //
         // String zone = AccessController.doPrivileged(new PriviAction<String>(
-        // "user.timezone"));
+        //         "user.timezone"));
+        //
+        // // sometimes DRLVM incorrectly adds "\n" to the end of timezone ID
+        // if (zone != null && zone.contains("\n")) {
+        //     zone = zone.substring(0, zone.indexOf("\n"));
+        // }
         //
         // // if property user.timezone is not set, we call the native method
         // // getCustomTimeZone
-        // if (zone == null) {
-        //    int[] tzinfo = new int[10];
+        // if (zone == null || zone.length() == 0) {
+        //     int[] tzinfo = new int[10];
         //     boolean[] isCustomTimeZone = new boolean[1];
         //
         //     String zoneId = getCustomTimeZone(tzinfo, isCustomTimeZone);
@@ -609,15 +567,45 @@
         //     // if property user.timezone is set in command line (with -D option)
         //     Default = getTimeZone(zone);
         // }
+        // setICUDefaultTimeZone(Default);
         // END android-removed
+
+        // BEGIN android-added
+        Default = timezone;
+
+        // TODO Not sure if this is spec-compliant. Shouldn't be persistent.
+        ZoneInfoDB.setDefault(timezone);
+        // END android-added
     }
 
+    // BEGIN android-removed
+    // private static void setICUDefaultTimeZone(TimeZone timezone) {
+    //     final com.ibm.icu.util.TimeZone icuTZ = com.ibm.icu.util.TimeZone
+    //             .getTimeZone(timezone.getID());
+    //
+    //     AccessController
+    //             .doPrivileged(new PrivilegedAction<java.lang.reflect.Field>() {
+    //                 public java.lang.reflect.Field run() {
+    //                     java.lang.reflect.Field field = null;
+    //                     try {
+    //                         field = com.ibm.icu.util.TimeZone.class
+    //                                 .getDeclaredField("defaultZone");
+    //                         field.setAccessible(true);
+    //                         field.set("defaultZone", icuTZ);
+    //                     } catch (Exception e) {
+    //                         return null;
+    //                     }
+    //                     return field;
+    //                 }
+    //             });
+    // }
+    // END android-removed
+
     /**
      * Sets the ID of this {@code TimeZone}.
-     * 
+     *
      * @param name
      *            a string which is the time zone ID.
-     * @since Android 1.0
      */
     public void setID(String name) {
         if (name == null) {
@@ -628,44 +616,40 @@
 
     /**
      * Sets the offset for standard time from GMT for this {@code TimeZone}.
-     * 
+     *
      * @param offset
      *            the offset from GMT in milliseconds.
-     * @since Android 1.0
      */
     abstract public void setRawOffset(int offset);
 
     /**
      * Returns whether this {@code TimeZone} has a daylight savings time period.
-     * 
+     *
      * @return {@code true} if this {@code TimeZone} has a daylight savings time period, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     abstract public boolean useDaylightTime();
 
-    // BEGIN android-removed
-    // /**
-    //  * Gets the name and the details of the user-selected TimeZone on the
-    //  * device.
-    //  * 
-    //  * @param tzinfo
-    //  *            int array of 10 elements to be filled with the TimeZone
-    //  *            information. Once filled, the contents of the array are
-    //  *            formatted as follows: tzinfo[0] -> the timezone offset;
-    //  *            tzinfo[1] -> the dst adjustment; tzinfo[2] -> the dst start
-    //  *            hour; tzinfo[3] -> the dst start day of week; tzinfo[4] -> the
-    //  *            dst start week of month; tzinfo[5] -> the dst start month;
-    //  *            tzinfo[6] -> the dst end hour; tzinfo[7] -> the dst end day of
-    //  *            week; tzinfo[8] -> the dst end week of month; tzinfo[9] -> the
-    //  *            dst end month;
-    //  * @param isCustomTimeZone
-    //  *            boolean array of size 1 that indicates if a timezone
-    //  *            match is found
-    //  * @return the name of the TimeZone or null if error occurs in native
-    //  *         method.
-    //  */
-    // private static native String getCustomTimeZone(int[] tzinfo,
-    //         boolean[] isCustomTimeZone);
-    // END android-removed
+    /**
+     * Gets the name and the details of the user-selected TimeZone on the
+     * device.
+     *
+     * @param tzinfo
+     *            int array of 10 elements to be filled with the TimeZone
+     *            information. Once filled, the contents of the array are
+     *            formatted as follows: tzinfo[0] -> the timezone offset;
+     *            tzinfo[1] -> the dst adjustment; tzinfo[2] -> the dst start
+     *            hour; tzinfo[3] -> the dst start day of week; tzinfo[4] -> the
+     *            dst start week of month; tzinfo[5] -> the dst start month;
+     *            tzinfo[6] -> the dst end hour; tzinfo[7] -> the dst end day of
+     *            week; tzinfo[8] -> the dst end week of month; tzinfo[9] -> the
+     *            dst end month;
+     * @param isCustomTimeZone
+     *            boolean array of size 1 that indicates if a timezone match is
+     *            found
+     * @return the name of the TimeZone or null if error occurs in native
+     *         method.
+     */
+    private static native String getCustomTimeZone(int[] tzinfo,
+            boolean[] isCustomTimeZone);
 }
diff --git a/libcore/luni/src/main/java/java/util/Timer.java b/libcore/luni/src/main/java/java/util/Timer.java
index ccff929..6090031 100644
--- a/libcore/luni/src/main/java/java/util/Timer.java
+++ b/libcore/luni/src/main/java/java/util/Timer.java
@@ -29,145 +29,143 @@
  * excessive amount of time to run it may impact the time at which subsequent
  * tasks may run.
  * <p>
- * 
+ *
  * The {@code TimerTask} does not offer any guarantees about the real-time nature of
  * scheduling tasks as its underlying implementation relies on the
  * {@code Object.wait(long)} method.
- * </p>
  * <p>
  * Multiple threads can share a single {@code Timer} without the need for their own
- * synchronization.</p>
+ * synchronization.
  * <p>
- * A {@code Timer} can be set to schedule tasks either at a fixed rate or 
- * with a fixed period. Fixed-period execution is the default.</p>
+ * A {@code Timer} can be set to schedule tasks either at a fixed rate or
+ * with a fixed period. Fixed-period execution is the default.
  * <p>
- * The difference between fixed-rate and fixed-period execution 
- * is the following:  With fixed-rate execution, the start time of each 
+ * The difference between fixed-rate and fixed-period execution
+ * is the following:  With fixed-rate execution, the start time of each
  * successive run of the task is scheduled in absolute terms without regard for when the previous
- * task run actually took place. This can result in a series of bunched-up runs 
- * (one launched immediately after another) if busy resources or other 
+ * task run actually took place. This can result in a series of bunched-up runs
+ * (one launched immediately after another) if busy resources or other
  * system delays prevent the {@code Timer} from firing for an extended time.
- * With fixed-period execution, each successive run of the 
- * task is scheduled relative to the start time of the previous run of the 
- * task, so two runs of the task are never fired closer together in time than 
- * the specified {@code period}.</p>
- * </p>
- * 
+ * With fixed-period execution, each successive run of the
+ * task is scheduled relative to the start time of the previous run of the
+ * task, so two runs of the task are never fired closer together in time than
+ * the specified {@code period}.
+ *
  * @see TimerTask
  * @see java.lang.Object#wait(long)
- * @since Android 1.0
  */
 public class Timer {
 
     private static final class TimerImpl extends Thread {
 
-        private static final class TimerNode {
-            TimerNode parent, left, right;
+        private static final class TimerHeap {
+            private int DEFAULT_HEAP_SIZE = 256;
 
-            TimerTask task;
+            private TimerTask[] timers = new TimerTask[DEFAULT_HEAP_SIZE];
 
-            public TimerNode(TimerTask value) {
-                this.task = value;
+            private int size = 0;
+
+            private int deletedCancelledNumber = 0;
+
+            public TimerTask minimum() {
+                return timers[0];
             }
 
-            public void deleteIfCancelled(TimerTree tasks) {
-                /*
-                 * All changes in the tree structure during deleting this node
-                 * affect only the structure of the subtree having this node as
-                 * its root
-                 */
-                if (left != null) {
-                    left.deleteIfCancelled(tasks);
-                }
-                if (right != null) {
-                    right.deleteIfCancelled(tasks);
-                }
-                if (task.cancelled) {
-                    tasks.delete(this);
-                    tasks.deletedCancelledNumber++;
-                }
-            }
-        }
-
-        private static final class TimerTree {
-
-            int deletedCancelledNumber;
-
-            TimerNode root;
-
-            boolean isEmpty() {
-                return root == null;
+            public boolean isEmpty() {
+                return size == 0;
             }
 
-            void insert(TimerNode z) {
-                TimerNode y = null, x = root;
-                while (x != null) {
-                    y = x;
-                    if (z.task.getWhen() < x.task.getWhen()) {
-                        x = x.left;
-                    } else {
-                        x = x.right;
+            public void insert(TimerTask task) {
+                if (timers.length == size) {
+                    TimerTask[] appendedTimers = new TimerTask[size * 2];
+                    System.arraycopy(timers, 0, appendedTimers, 0, size);
+                    timers = appendedTimers;
+                }
+                timers[size++] = task;
+                upHeap();
+            }
+
+            public void delete(int pos) {
+                // posible to delete any position of the heap
+                if (pos >= 0 && pos < size) {
+                    timers[pos] = timers[--size];
+                    timers[size] = null;
+                    downHeap(pos);
+                }
+            }
+
+            private void upHeap() {
+                int current = size - 1;
+                int parent = (current - 1) / 2;
+
+                while (timers[current].when < timers[parent].when) {
+                    // swap the two
+                    TimerTask tmp = timers[current];
+                    timers[current] = timers[parent];
+                    timers[parent] = tmp;
+
+                    // update pos and current
+                    current = parent;
+                    parent = (current - 1) / 2;
+                }
+            }
+
+            private void downHeap(int pos) {
+                int current = pos;
+                int child = 2 * current + 1;
+
+                while (child < size && size > 0) {
+                    // compare the children if they exist
+                    if (child + 1 < size
+                            && timers[child + 1].when < timers[child].when) {
+                        child++;
+                    }
+
+                    // compare selected child with parent
+                    if (timers[current].when < timers[child].when) {
+                        break;
+                    }
+
+                    // swap the two
+                    TimerTask tmp = timers[current];
+                    timers[current] = timers[child];
+                    timers[child] = tmp;
+
+                    // update pos and current
+                    current = child;
+                    child = 2 * current + 1;
+                }
+            }
+
+            public void reset() {
+                timers = new TimerTask[DEFAULT_HEAP_SIZE];
+                size = 0;
+            }
+
+            public void adjustMinimum() {
+                downHeap(0);
+            }
+
+            public void deleteIfCancelled() {
+                for (int i = 0; i < size; i++) {
+                    if (timers[i].cancelled) {
+                        deletedCancelledNumber++;
+                        delete(i);
+                        // re-try this point
+                        i--;
                     }
                 }
-                z.parent = y;
-                if (y == null) {
-                    root = z;
-                } else if (z.task.getWhen() < y.task.getWhen()) {
-                    y.left = z;
-                } else {
-                    y.right = z;
-                }
             }
 
-            void delete(TimerNode z) {
-                TimerNode y = null, x = null;
-                if (z.left == null || z.right == null) {
-                    y = z;
-                } else {
-                    y = successor(z);
+            private int getTask(TimerTask task) {
+                for (int i = 0; i < timers.length; i++) {
+                    if (timers[i] == task) {
+                        return i;
+                    }
                 }
-                if (y.left != null) {
-                    x = y.left;
-                } else {
-                    x = y.right;
-                }
-                if (x != null) {
-                    x.parent = y.parent;
-                }
-                if (y.parent == null) {
-                    root = x;
-                } else if (y == y.parent.left) {
-                    y.parent.left = x;
-                } else {
-                    y.parent.right = x;
-                }
-                if (y != z) {
-                    z.task = y.task;
-                }
+                return -1;
             }
 
-            private TimerNode successor(TimerNode x) {
-                if (x.right != null) {
-                    return minimum(x.right);
-                }
-                TimerNode y = x.parent;
-                while (y != null && x == y.right) {
-                    x = y;
-                    y = y.parent;
-                }
-                return y;
-            }
-
-            private TimerNode minimum(TimerNode x) {
-                while (x.left != null) {
-                    x = x.left;
-                }
-                return x;
-            }
-
-            TimerNode minimum() {
-                return minimum(root);
-            }
         }
 
         /**
@@ -185,18 +183,14 @@
          * Vector consists of scheduled events, sorted according to
          * {@code when} field of TaskScheduled object.
          */
-        private TimerTree tasks = new TimerTree();
+        private TimerHeap tasks = new TimerHeap();
 
         /**
          * Starts a new timer.
          * 
-         * @param isDaemon
+         * @param name thread's name
+         * @param isDaemon daemon thread or not
          */
-        TimerImpl(boolean isDaemon) {
-            this.setDaemon(isDaemon);
-            this.start();
-        }
-
         TimerImpl(String name, boolean isDaemon) {
             this.setName(name);
             this.setDaemon(isDaemon);
@@ -230,13 +224,12 @@
 
                     long currentTime = System.currentTimeMillis();
 
-                    TimerNode taskNode = tasks.minimum();
-                    task = taskNode.task;
+                    task = tasks.minimum();
                     long timeToSleep;
 
                     synchronized (task.lock) {
                         if (task.cancelled) {
-                            tasks.delete(taskNode);
+                            tasks.delete(0);
                             continue;
                         }
 
@@ -257,8 +250,12 @@
                     // no sleep is necessary before launching the task
 
                     synchronized (task.lock) {
+                        int pos = 0;
+                        if (tasks.minimum().when != task.when) {
+                            pos = tasks.getTask(task);
+                        }
                         if (task.cancelled) {
-                            tasks.delete(taskNode);
+                            tasks.delete(tasks.getTask(task));
                             continue;
                         }
 
@@ -266,7 +263,7 @@
                         task.setScheduledTime(task.when);
 
                         // remove task from queue
-                        tasks.delete(taskNode);
+                        tasks.delete(pos);
 
                         // set when the next task should be launched
                         if (task.period >= 0) {
@@ -299,7 +296,7 @@
 
         private void insertTask(TimerTask newTask) {
             // callers are synchronized
-            tasks.insert(new TimerNode(newTask));
+            tasks.insert(newTask);
             this.notify();
         }
 
@@ -308,7 +305,7 @@
          */
         public synchronized void cancel() {
             cancelled = true;
-            tasks = new TimerTree();
+            tasks.reset();
             this.notify();
         }
 
@@ -318,82 +315,89 @@
             }
             // callers are synchronized
             tasks.deletedCancelledNumber = 0;
-            tasks.root.deleteIfCancelled(tasks);
+            tasks.deleteIfCancelled();
             return tasks.deletedCancelledNumber;
         }
 
     }
+    
+	private static final class FinalizerHelper {
+		private final TimerImpl impl;
+		
+		FinalizerHelper(TimerImpl impl) {
+			super();
+			this.impl = impl;
+		}
+		
+		@Override
+		protected void finalize() {
+			synchronized (impl) {
+				impl.finished = true;
+				impl.notify();
+			}
+		}
+	}
+	
+	private static long timerId;
+	
+	private synchronized static long nextId() {
+		return timerId++;
+	}
 
     /* This object will be used in synchronization purposes */
-    private TimerImpl impl;
+    private final TimerImpl impl;
 
     // Used to finalize thread
     @SuppressWarnings("unused")
-    private Object finalizer = new Object() { // $NON-LOCK-1$
-        @Override
-        protected void finalize() {
-            synchronized (impl) {
-                impl.finished = true;
-                impl.notify();
-            }
-        }
-    };
-
-    /**
-     * Creates a new {@code Timer} which may be specified to be run as a daemon thread.
-     * 
-     * @param isDaemon
-     *            {@code true} if the {@code Timer}'s thread should be a daemon thread.
-     * @since Android 1.0
-     */
-    public Timer(boolean isDaemon) {
-        // BEGIN android-changed
-        impl = new TimerImpl("java.util.Timer", isDaemon);
-        // END android-changed
-    }
-
-    /**
-     * Creates a new non-daemon {@code Timer}.
-     * 
-     * @since Android 1.0
-     */
-    public Timer() {
-        // BEGIN android-changed
-        impl = new TimerImpl("java.util.Timer", false);
-        // END android-changed
-    }
+    private final FinalizerHelper finalizer;
 
     /**
      * Creates a new named {@code Timer} which may be specified to be run as a
      * daemon thread.
-     * 
-     * @param name
-     *            the name of the {@code Timer}.
-     * @param isDaemon
-     *            true if {@code Timer}'s thread should be a daemon thread.
-     * @since Android 1.0
+     *
+     * @param name the name of the {@code Timer}.
+     * @param isDaemon true if {@code Timer}'s thread should be a daemon thread.
+     * @throws NullPointerException is {@code name} is {@code null}
      */
     public Timer(String name, boolean isDaemon) {
-        impl = new TimerImpl(name, isDaemon);
+    	super();
+    	if (name == null){
+    		throw new NullPointerException("name is null");
+    	}
+        this.impl = new TimerImpl(name, isDaemon);
+        this.finalizer = new FinalizerHelper(impl);
+    }
+    
+    /**
+     * Creates a new named {@code Timer} which does not run as a daemon thread.
+     *
+     * @param name the name of the Timer.
+     * @throws NullPointerException is {@code name} is {@code null}
+     */
+    public Timer(String name) {
+        this(name, false);
+    }
+    
+    /**
+     * Creates a new {@code Timer} which may be specified to be run as a daemon thread.
+     *
+     * @param isDaemon {@code true} if the {@code Timer}'s thread should be a daemon thread.
+     */
+    public Timer(boolean isDaemon) {
+        this("Timer-" + Timer.nextId(), isDaemon);
     }
 
     /**
-     * Creates a new named {@code Timer} which does not run as a daemon thread.
-     * 
-     * @param name
-     *            the name of the Timer.
-     * @since Android 1.0
+     * Creates a new non-daemon {@code Timer}.
      */
-    public Timer(String name) {
-        impl = new TimerImpl(name, false);
+    public Timer() {
+        this(false);
     }
 
     /**
      * Cancels the {@code Timer} and removes any scheduled tasks. If there is a
      * currently running task it is not affected. No more tasks may be scheduled
      * on this {@code Timer}. Subsequent calls do nothing.
-     * 
-     * @since Android 1.0
      */
     public void cancel() {
         impl.cancel();
@@ -401,12 +405,11 @@
 
     /**
      * Removes all canceled tasks from the task queue. If there are no
-     * other references on the tasks, then after this call they are free 
+     * other references on the tasks, then after this call they are free
      * to be garbage collected.
-     * 
+     *
      * @return the number of canceled tasks that were removed from the task
      *         queue.
-     * @since Android 1.0
      */
     public int purge() {
         synchronized (impl) {
@@ -417,17 +420,16 @@
     /**
      * Schedule a task for single execution. If {@code when} is less than the
      * current time, it will be scheduled to be executed as soon as possible.
-     * 
+     *
      * @param task
      *            the task to schedule.
      * @param when
      *            time of execution.
-     * @exception IllegalArgumentException
+     * @throws IllegalArgumentException
      *                if {@code when.getTime() < 0}.
-     * @exception IllegalStateException
+     * @throws IllegalStateException
      *                if the {@code Timer} has been canceled, or if the task has been
      *                scheduled or canceled.
-     * @since Android 1.0
      */
     public void schedule(TimerTask task, Date when) {
         if (when.getTime() < 0) {
@@ -439,17 +441,16 @@
 
     /**
      * Schedule a task for single execution after a specified delay.
-     * 
+     *
      * @param task
      *            the task to schedule.
      * @param delay
-     *            amount of time before execution.
-     * @exception IllegalArgumentException
+     *            amount of time in milliseconds before execution.
+     * @throws IllegalArgumentException
      *                if {@code delay < 0}.
-     * @exception IllegalStateException
+     * @throws IllegalStateException
      *                if the {@code Timer} has been canceled, or if the task has been
      *                scheduled or canceled.
-     * @since Android 1.0
      */
     public void schedule(TimerTask task, long delay) {
         if (delay < 0) {
@@ -460,19 +461,18 @@
 
     /**
      * Schedule a task for repeated fixed-delay execution after a specific delay.
-     * 
+     *
      * @param task
      *            the task to schedule.
      * @param delay
-     *            amount of time before first execution.
+     *            amount of time in milliseconds before first execution.
      * @param period
-     *            amount of time between subsequent executions.
-     * @exception IllegalArgumentException
+     *            amount of time in milliseconds between subsequent executions.
+     * @throws IllegalArgumentException
      *                if {@code delay < 0} or {@code period < 0}.
-     * @exception IllegalStateException
+     * @throws IllegalStateException
      *                if the {@code Timer} has been canceled, or if the task has been
      *                scheduled or canceled.
-     * @since Android 1.0
      */
     public void schedule(TimerTask task, long delay, long period) {
         if (delay < 0 || period <= 0) {
@@ -484,19 +484,18 @@
     /**
      * Schedule a task for repeated fixed-delay execution after a specific time
      * has been reached.
-     * 
+     *
      * @param task
      *            the task to schedule.
      * @param when
      *            time of first execution.
      * @param period
-     *            amount of time between subsequent executions.
-     * @exception IllegalArgumentException
+     *            amount of time in milliseconds between subsequent executions.
+     * @throws IllegalArgumentException
      *                if {@code when.getTime() < 0} or {@code period < 0}.
-     * @exception IllegalStateException
+     * @throws IllegalStateException
      *                if the {@code Timer} has been canceled, or if the task has been
      *                scheduled or canceled.
-     * @since Android 1.0
      */
     public void schedule(TimerTask task, Date when, long period) {
         if (period <= 0 || when.getTime() < 0) {
@@ -509,19 +508,18 @@
     /**
      * Schedule a task for repeated fixed-rate execution after a specific delay
      * has passed.
-     * 
+     *
      * @param task
      *            the task to schedule.
      * @param delay
-     *            amount of time before first execution.
+     *            amount of time in milliseconds before first execution.
      * @param period
-     *            amount of time between subsequent executions.
-     * @exception IllegalArgumentException
+     *            amount of time in milliseconds between subsequent executions.
+     * @throws IllegalArgumentException
      *                if {@code delay < 0} or {@code period < 0}.
-     * @exception IllegalStateException
+     * @throws IllegalStateException
      *                if the {@code Timer} has been canceled, or if the task has been
      *                scheduled or canceled.
-     * @since Android 1.0
      */
     public void scheduleAtFixedRate(TimerTask task, long delay, long period) {
         if (delay < 0 || period <= 0) {
@@ -533,19 +531,18 @@
     /**
      * Schedule a task for repeated fixed-rate execution after a specific time
      * has been reached.
-     * 
+     *
      * @param task
      *            the task to schedule.
      * @param when
      *            time of first execution.
      * @param period
-     *            amount of time between subsequent executions.
-     * @exception IllegalArgumentException
+     *            amount of time in milliseconds between subsequent executions.
+     * @throws IllegalArgumentException
      *                if {@code when.getTime() < 0} or {@code period < 0}.
-     * @exception IllegalStateException
+     * @throws IllegalStateException
      *                if the {@code Timer} has been canceled, or if the task has been
      *                scheduled or canceled.
-     * @since Android 1.0
      */
     public void scheduleAtFixedRate(TimerTask task, Date when, long period) {
         if (period <= 0 || when.getTime() < 0) {
@@ -555,13 +552,8 @@
         scheduleImpl(task, delay < 0 ? 0 : delay, period, true);
     }
 
-    /**
+    /*
      * Schedule a task.
-     * 
-     * @param task
-     * @param delay
-     * @param period
-     * @param fixed
      */
     private void scheduleImpl(TimerTask task, long delay, long period,
             boolean fixed) {
diff --git a/libcore/luni/src/main/java/java/util/TimerTask.java b/libcore/luni/src/main/java/java/util/TimerTask.java
index 384746f..319ed58 100644
--- a/libcore/luni/src/main/java/java/util/TimerTask.java
+++ b/libcore/luni/src/main/java/java/util/TimerTask.java
@@ -23,7 +23,6 @@
  * 
  * @see Timer
  * @see java.lang.Object#wait(long)
- * @since Android 1.0
  */
 public abstract class TimerTask implements Runnable {
     /* Lock object for synchronization. It's also used by Timer class. */
@@ -77,8 +76,6 @@
 
     /**
      * Creates a new {@code TimerTask}.
-     * 
-     * @since Android 1.0
      */
     protected TimerTask() {
         super();
@@ -91,7 +88,6 @@
      * 
      * @return {@code true} if the call prevented a scheduled execution
      *         from taking place, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean cancel() {
         synchronized (lock) {
@@ -107,7 +103,6 @@
      * have not yet run return an undefined value.
      * 
      * @return the most recent execution time.
-     * @since Android 1.0
      */
     public long scheduledExecutionTime() {
         synchronized (lock) {
@@ -118,8 +113,6 @@
     /**
      * The task to run should be specified in the implementation of the {@code run()}
      * method.
-     * 
-     * @since Android 1.0
      */
     public abstract void run();
 
diff --git a/libcore/luni/src/main/java/java/util/TooManyListenersException.java b/libcore/luni/src/main/java/java/util/TooManyListenersException.java
index 32b2133..8c044c0 100644
--- a/libcore/luni/src/main/java/java/util/TooManyListenersException.java
+++ b/libcore/luni/src/main/java/java/util/TooManyListenersException.java
@@ -22,8 +22,6 @@
  * A {@code TooManyListenersException} is thrown when an attempt is made to add
  * more than one listener to an event source which only supports a single
  * listener. It is also thrown when the same listener is added more than once.
- * 
- * @since Android 1.0
  */
 public class TooManyListenersException extends Exception {
 
diff --git a/libcore/luni/src/main/java/java/util/TreeMap.java b/libcore/luni/src/main/java/java/util/TreeMap.java
index e3dc5a7..b97821f 100644
--- a/libcore/luni/src/main/java/java/util/TreeMap.java
+++ b/libcore/luni/src/main/java/java/util/TreeMap.java
@@ -27,43 +27,124 @@
  * and removing) are supported. The values can be any objects. The keys can be
  * any objects which are comparable to each other either using their natural
  * order or a specified Comparator.
- * 
- * @since Android 1.0
+ *
+ * @since 1.2
  */
-public class TreeMap<K, V> extends AbstractMap<K, V> implements SortedMap<K, V>, Cloneable,
-        Serializable {
+public class TreeMap <K, V> extends AbstractMap<K, V> implements SortedMap<K, V>,
+                                                        Cloneable, Serializable {
     private static final long serialVersionUID = 919286545866124006L;
 
     transient int size;
 
-    transient Entry<K, V> root;
-
     private Comparator<? super K> comparator;
 
     transient int modCount;
 
     transient Set<Map.Entry<K, V>> entrySet;
 
-    /**
-     * Entry is an internal class which is used to hold the entries of a
-     * TreeMap.
-     */
-    static class Entry<K, V> extends MapEntry<K, V> {
-        Entry<K, V> parent, left, right;
+    transient Node<K, V> root;
+    
+class MapEntry implements Map.Entry<K, V>, Cloneable {
+		
+		final int offset;
+		final Node<K, V> node;
+		final K key;
+		
+	    MapEntry(Node<K, V> node, int offset) {
+	    	this.node = node;
+	    	this.offset = offset;
+	    	key = node.keys[offset];
+	    }
 
+	    @Override
+	    public Object clone() {
+	        try {
+	            return super.clone();
+	        } catch (CloneNotSupportedException e) {
+	            return null;
+	        }
+	    }
+
+	    @Override
+	    public boolean equals(Object object) {
+	        if (this == object) {
+	            return true;
+	        }
+	        if (object instanceof Map.Entry) {
+	            Map.Entry<?, ?> entry = (Map.Entry<?, ?>) object;	            
+	            V value = getValue();
+	            return (key == null ? entry.getKey() == null : key.equals(entry
+	                    .getKey()))
+	                    && (value == null ? entry.getValue() == null : value
+	                            .equals(entry.getValue()));
+	        }
+	        return false;
+	    }
+
+	    public K getKey() {
+	        return key;
+	    }
+
+	    public V getValue() {
+	    	if (node.keys[offset] == key) {
+	    		return node.values[offset];
+	    	}
+	    	if (containsKey(key)) {
+	    		return get(key);
+	    	}
+	    	throw new IllegalStateException();
+	    }
+
+	    @Override
+	    public int hashCode() {
+	    	V value = getValue();
+	        return (key == null ? 0 : key.hashCode())
+	                ^ (value == null ? 0 : value.hashCode());
+	    }
+
+	    public V setValue(V object) {
+	    	if (node.keys[offset] == key) {
+	    		V res = node.values[offset];
+	    		node.values[offset] = object;
+	    		return res;
+	    	}
+	    	if (containsKey(key)) {
+	    		return put(key, object);
+	    	}
+	    	throw new IllegalStateException();
+	    }
+
+	    @Override
+	    public String toString() {
+	        return key + "=" + getValue();
+	    }
+	}
+
+    static class Node <K,V> implements Cloneable {
+        static final int NODE_SIZE = 64;
+        Node<K, V> prev, next;
+        Node<K, V> parent, left, right;
+        V[] values;
+        K[] keys;
+        int left_idx = 0;
+        int right_idx = -1;
+        int size = 0;
         boolean color;
 
-        Entry(K key) {
-            super(key);
-        }
-
-        Entry(K key, V value) {
-            super(key, value);
+        public Node() {
+            keys = (K[]) new Object[NODE_SIZE];
+            values = (V[]) new Object[NODE_SIZE];
         }
 
         @SuppressWarnings("unchecked")
-        Entry<K, V> clone(Entry<K, V> parent) {
-            Entry<K, V> clone = (Entry<K, V>) super.clone();
+        Node<K, V> clone(Node<K, V> parent) throws CloneNotSupportedException {
+            Node<K, V> clone = (Node<K, V>) super.clone();
+            clone.keys   = (K[]) new Object[NODE_SIZE];
+            clone.values = (V[]) new Object[NODE_SIZE];
+            System.arraycopy(keys,   0, clone.keys,   0, keys.length);
+            System.arraycopy(values, 0, clone.values, 0, values.length);
+            clone.left_idx  = left_idx;
+            clone.right_idx = right_idx;
             clone.parent = parent;
             if (left != null) {
                 clone.left = left.clone(clone);
@@ -71,45 +152,45 @@
             if (right != null) {
                 clone.right = right.clone(clone);
             }
+            clone.prev = null;
+            clone.next = null;
             return clone;
         }
     }
-    
+
     @SuppressWarnings("unchecked")
-    private static <T> Comparable<T> toComparable(T obj) {
-        return (Comparable<T>)obj;
+     private static <T> Comparable<T> toComparable(T obj) {
+        return (Comparable) obj;
     }
 
-    private static class AbstractMapIterator <K,V> {
+    static class AbstractMapIterator <K,V> {
         TreeMap<K, V> backingMap;
         int expectedModCount;
-        TreeMap.Entry<K, V> node;
-        TreeMap.Entry<K, V> lastNode;
+        Node<K, V> node;
+        Node<K, V> lastNode;
+        int offset;
+        int lastOffset;
 
-        AbstractMapIterator(TreeMap<K, V> map, Entry<K, V> startNode) {
+        AbstractMapIterator(TreeMap<K, V> map, Node<K, V> startNode, int startOffset) {
             backingMap = map;
             expectedModCount = map.modCount;
             node = startNode;
+            offset = startOffset;
+        }
+
+        AbstractMapIterator(TreeMap<K, V> map, Node<K, V> startNode) {
+            this(map, startNode, startNode != null ?
+                                 startNode.right_idx - startNode.left_idx : 0);
+        }
+
+        AbstractMapIterator(TreeMap<K, V> map) {
+            this(map, minimum(map.root));
         }
 
         public boolean hasNext() {
             return node != null;
         }
 
-        final public void remove() {
-            if (expectedModCount == backingMap.modCount) {
-                if (lastNode != null) {
-                    backingMap.rbDelete(lastNode);
-                    lastNode = null;
-                    expectedModCount++;
-                } else {
-                    throw new IllegalStateException();
-                }
-            } else {
-                throw new ConcurrentModificationException();
-            }
-        }
-
         final void makeNext() {
             if (expectedModCount != backingMap.modCount) {
                 throw new ConcurrentModificationException();
@@ -117,564 +198,777 @@
                 throw new NoSuchElementException();
             }
             lastNode = node;
-            node = TreeMap.successor(node);
+            lastOffset = offset;
+            if (offset != 0) {
+                offset--;
+            } else {
+                node = node.next;
+                if (node != null) {
+                    offset = node.right_idx - node.left_idx;
+                }
             }
         }
 
-        private static class UnboundedEntryIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<Map.Entry<K, V>> {
-
-            UnboundedEntryIterator(TreeMap<K, V> map, Entry<K, V> startNode) {
-                super(map, startNode);
-            }
-
-            UnboundedEntryIterator(TreeMap<K, V> map) {
-                super(map, map.root == null ? null : TreeMap.minimum(map.root));
-            }
-
-            public Map.Entry<K, V> next() {
-                makeNext();
-                return lastNode;
+        final public void remove() {
+            if (expectedModCount == backingMap.modCount) {
+                if (lastNode != null) {
+                    int idx = lastNode.right_idx - lastOffset;
+                    backingMap.removeFromIterator(lastNode, idx);
+                    lastNode = null;
+                    expectedModCount++;
+                } else {
+                    throw new IllegalStateException();
+                }
+            } else {
+                throw new ConcurrentModificationException();
             }
         }
+    }
 
-        static class UnboundedKeyIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<K> {
-            public UnboundedKeyIterator(TreeMap<K, V> treeMap, Entry<K, V> entry) {
-                super(treeMap, entry);
-            }
+    static class UnboundedEntryIterator <K, V> extends AbstractMapIterator<K, V>
+                                            implements Iterator<Map.Entry<K, V>> {
 
-            public UnboundedKeyIterator(TreeMap<K, V> map) {
-                super(map, map.root == null ? null : TreeMap.minimum(map.root));
-            }
-
-            public K next() {
-                makeNext();
-                return lastNode.key;
-            }
+        UnboundedEntryIterator(TreeMap<K, V> map, Node<K, V> startNode, int startOffset) {
+            super(map, startNode, startOffset);
         }
 
-        static class UnboundedValueIterator <K, V> extends AbstractMapIterator<K, V> implements Iterator<V> {
-     
-            public UnboundedValueIterator(TreeMap<K, V> treeMap, Entry<K, V> startNode) {
-                super(treeMap, startNode);
-            }
-     
-            public UnboundedValueIterator(TreeMap<K, V> map) {
-                super(map, map.root == null ? null : TreeMap.minimum(map.root));
-            }
-     
-            public V next() {
-                makeNext();
-                return lastNode.value;
-            }
+        UnboundedEntryIterator(TreeMap<K, V> map) {
+            super(map);
         }
 
-        private static class ComparatorBoundedIterator<K, V> extends AbstractMapIterator<K, V> {
-            private final  K endKey;
+        public Map.Entry<K, V> next() {
+            makeNext();
+            int idx = lastNode.right_idx - lastOffset;
+            return backingMap.new MapEntry(lastNode, idx);
+        }
+    }
 
-            private final Comparator<? super K> cmp;
+    static class UnboundedKeyIterator <K, V> extends AbstractMapIterator<K, V>
+                                                          implements Iterator<K> {
 
-        ComparatorBoundedIterator(TreeMap<K, V> map, Entry<K, V> startNode, K end) {
-            super(map, startNode);
+        UnboundedKeyIterator(TreeMap<K, V> map, Node<K, V> startNode, int startOffset) {
+            super(map, startNode, startOffset);
+        }
+
+        UnboundedKeyIterator(TreeMap<K, V> map) {
+            super(map);
+        }
+
+        public K next() {
+            makeNext();
+            return lastNode.keys[lastNode.right_idx - lastOffset];
+        }
+    }
+
+    static class UnboundedValueIterator <K, V> extends AbstractMapIterator<K, V>
+                                                          implements Iterator<V> {
+
+        UnboundedValueIterator(TreeMap<K, V> map, Node<K, V> startNode, int startOffset) {
+            super(map, startNode, startOffset);
+        }
+
+        UnboundedValueIterator(TreeMap<K, V> map) {
+            super(map);
+        }
+
+        public V next() {
+            makeNext();
+            return lastNode.values[lastNode.right_idx - lastOffset];
+        }
+    }
+
+    static class BoundedMapIterator <K, V> extends AbstractMapIterator<K, V> {
+
+        Node<K, V> finalNode;
+        int finalOffset;
+
+        BoundedMapIterator(Node<K, V> startNode, int startOffset, TreeMap<K, V> map,
+                           Node<K, V> finalNode, int finalOffset) {
+            super(map, finalNode==null? null : startNode, startOffset);
+            this.finalNode = finalNode;
+            this.finalOffset = finalOffset;
+        }
+
+        BoundedMapIterator(Node<K, V> startNode, TreeMap<K, V> map,
+                           Node<K, V> finalNode, int finalOffset) {
+            this(startNode, startNode != null ?
+                            startNode.right_idx - startNode.left_idx : 0,
+                            map, finalNode, finalOffset);
+        }
+
+        BoundedMapIterator(Node<K, V> startNode, int startOffset,
+                           TreeMap<K, V> map, Node<K, V> finalNode) {
+            this(startNode, startOffset, map, finalNode,
+                         finalNode.right_idx - finalNode.left_idx);
+        }
+
+        void makeBoundedNext() {
+            makeNext();
+            if (lastNode == finalNode && lastOffset == finalOffset) {
+                node = null;
+            }
+        }
+    }
+
+    static class BoundedEntryIterator <K, V> extends BoundedMapIterator<K, V>
+                                          implements Iterator<Map.Entry<K, V>> {
+
+        public BoundedEntryIterator(Node<K, V> startNode, int startOffset, TreeMap<K, V> map,
+                                    Node<K, V> finalNode, int finalOffset) {
+            super(startNode, startOffset, map, finalNode, finalOffset);
+        }
+
+        public Map.Entry<K, V> next() {
+            makeBoundedNext();
+            int idx = lastNode.right_idx - lastOffset;
+            return backingMap.new MapEntry(lastNode, idx);
+        }
+    }
+
+    static class BoundedKeyIterator <K, V> extends BoundedMapIterator<K, V>
+                                                     implements Iterator<K> {
+
+        public BoundedKeyIterator(Node<K, V> startNode, int startOffset, TreeMap<K, V> map,
+                                  Node<K, V> finalNode, int finalOffset) {
+            super(startNode, startOffset, map, finalNode, finalOffset);
+        }
+
+        public K next() {
+            makeBoundedNext();
+            return lastNode.keys[lastNode.right_idx - lastOffset];
+        }
+    }
+
+    static class BoundedValueIterator <K, V> extends BoundedMapIterator<K, V>
+                                                       implements Iterator<V> {
+
+        public BoundedValueIterator(Node<K, V> startNode, int startOffset, TreeMap<K, V> map,
+                                    Node<K, V> finalNode, int finalOffset) {
+            super(startNode, startOffset, map, finalNode, finalOffset);
+        }
+
+        public V next() {
+            makeBoundedNext();
+            return lastNode.values[lastNode.right_idx - lastOffset];
+        }
+    }
+
+    static final class SubMap <K,V> extends AbstractMap<K, V>
+                                 implements SortedMap<K, V>, Serializable {
+        private static final long serialVersionUID = -6520786458950516097L;
+
+        private TreeMap<K, V> backingMap;
+
+        boolean hasStart, hasEnd;
+        K startKey, endKey;
+        transient Set<Map.Entry<K, V>> entrySet = null;
+        transient int firstKeyModCount = -1;
+        transient int lastKeyModCount = -1;
+        transient Node<K, V> firstKeyNode;
+        transient int firstKeyIndex;
+        transient Node<K, V> lastKeyNode;
+        transient int lastKeyIndex;
+
+        SubMap(K start, TreeMap<K, V> map) {
+            backingMap = map;
+            hasStart = true;
+            startKey = start;
+        }
+
+        SubMap(K start, TreeMap<K, V> map, K end) {
+            backingMap = map;
+            hasStart = hasEnd = true;
+            startKey = start;
             endKey = end;
-            cmp = map.comparator();
         }
 
-        final void cleanNext() {
-            if (node != null && cmp.compare(endKey, node.key) <= 0) {
-                node = null;
+        SubMap(TreeMap<K, V> map, K end) {
+            backingMap = map;
+            hasEnd = true;
+            endKey = end;
+        }
+
+        private void checkRange(K key) {
+            Comparator<? super K> cmp = backingMap.comparator;
+            if (cmp == null) {
+                Comparable<K> object = toComparable(key);
+                if (hasStart && object.compareTo(startKey) < 0) {
+                    throw new IllegalArgumentException();
+                }
+                if (hasEnd && object.compareTo(endKey) > 0) {
+                    throw new IllegalArgumentException();
+                }
+            } else {
+                if (hasStart
+                    && backingMap.comparator().compare(key, startKey) < 0) {
+                    throw new IllegalArgumentException();
+                }
+                if (hasEnd && backingMap.comparator().compare(key, endKey) > 0) {
+                    throw new IllegalArgumentException();
+                }
             }
         }
 
+        private boolean isInRange(K key) {
+            Comparator<? super K> cmp = backingMap.comparator;
+            if (cmp == null) {
+                Comparable<K> object = toComparable(key);
+                if (hasStart && object.compareTo(startKey) < 0) {
+                    return false;
+                }
+                if (hasEnd && object.compareTo(endKey) >= 0) {
+                    return false;
+                }
+            } else {
+                if (hasStart && cmp.compare(key, startKey) < 0) {
+                    return false;
+                }
+                if (hasEnd && cmp.compare(key, endKey) >= 0) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        private boolean checkUpperBound(K key) {
+            if (hasEnd) {
+                Comparator<? super K> cmp = backingMap.comparator;
+                if (cmp == null) {
+                    return (toComparable(key).compareTo(endKey) < 0);
+                }
+                return (cmp.compare(key, endKey) < 0);
+            }
+            return true;
+        }
+
+        private boolean checkLowerBound(K key) {
+            if (hasStart) {
+                Comparator<? super K> cmp = backingMap.comparator;
+                if (cmp == null) {
+                    return (toComparable(key).compareTo(startKey) >= 0);
+                }
+                return (cmp.compare(key, startKey) >= 0);
+            }
+            return true;
+        }
+
+        public Comparator<? super K> comparator() {
+            return backingMap.comparator();
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public boolean containsKey(Object key) {
+            if (isInRange((K) key)) {
+                return backingMap.containsKey(key);
+            }
+            return false;
+        }
+
         @Override
-        public boolean hasNext() {
-            return (node != null && endKey != null) && (cmp.compare(node.key, endKey) < 0);
-        }
-    }
-
-    private static class ComparatorBoundedEntryIterator<K, V> extends
-            ComparatorBoundedIterator<K, V> implements Iterator<Map.Entry<K, V>> {
-
-        ComparatorBoundedEntryIterator(TreeMap<K, V> map, Entry<K, V> startNode, K end) {
-            super(map, startNode, end);
-        }
-
-        public Map.Entry<K, V> next() {
-            makeNext();
-            cleanNext();
-            return lastNode;
-        }
-    }
-
-    private static class ComparatorBoundedKeyIterator<K, V> extends
-            ComparatorBoundedIterator<K, V> implements Iterator<K> {
-
-        ComparatorBoundedKeyIterator(TreeMap<K, V> map, Entry<K, V> startNode, K end) {
-            super(map, startNode, end);
-        }
-
-        public K next() {
-            makeNext();
-            cleanNext();
-            return lastNode.key;
-        }
-    }
-
-    private static class ComparatorBoundedValueIterator<K, V> extends
-            ComparatorBoundedIterator<K, V> implements Iterator<V> {
-
-        ComparatorBoundedValueIterator(TreeMap<K, V> map, Entry<K, V> startNode, K end) {
-            super(map, startNode, end);
-        }
-
-        public V next() {
-            makeNext();
-            cleanNext();
-            return lastNode.value;
-        }
-    }
-
-    private static class ComparableBoundedIterator<K, V> extends AbstractMapIterator<K, V> {
-        private final Comparable<K> endKey;
-
-        public ComparableBoundedIterator(TreeMap<K, V> treeMap, Entry<K, V> entry,
-                Comparable<K> endKey) {
-            super(treeMap, entry);
-            this.endKey = endKey;
-        }
-
-        final void cleanNext() {
-            if ((node != null) && (endKey.compareTo(node.key) <= 0)) {
-                node = null;
-            }
+         public void clear() {
+            keySet().clear();
         }
 
         @Override
-        public boolean hasNext() {
-            return (node != null) && (endKey.compareTo(node.key) > 0);
-        }
-    }
-
-    private static class ComparableBoundedEntryIterator<K, V> extends
-            ComparableBoundedIterator<K, V> implements Iterator<Map.Entry<K, V>> {
-
-        ComparableBoundedEntryIterator(TreeMap<K, V> map, Entry<K, V> startNode,
-                Comparable<K> end) {
-            super(map, startNode, end);
-        }
-
-        public Map.Entry<K, V> next() {
-            makeNext();
-            cleanNext();
-            return lastNode;
-        }
-
-    }
-
-    private static class ComparableBoundedKeyIterator<K, V> extends
-            ComparableBoundedIterator<K, V> implements Iterator<K> {
-
-        ComparableBoundedKeyIterator(TreeMap<K, V> map, Entry<K, V> startNode, Comparable<K> end) {
-            super(map, startNode, end);
-        }
-
-        public K next() {
-            makeNext();
-            cleanNext();
-            return lastNode.key;
-        }
-    }
-
-    private static class ComparableBoundedValueIterator<K, V> extends
-            ComparableBoundedIterator<K, V> implements Iterator<V> {
-
-        ComparableBoundedValueIterator(TreeMap<K, V> map, Entry<K, V> startNode,
-                Comparable<K> end) {
-            super(map, startNode, end);
-        }
-
-        public V next() {
-            makeNext();
-            cleanNext();
-            return lastNode.value;
-        }
-    }
-
-        static final class SubMap<K,V> extends AbstractMap<K,V> implements SortedMap<K,V>, Serializable {
-            private static final long serialVersionUID = -6520786458950516097L;
-
-            private TreeMap<K,V> backingMap;
-
-            boolean hasStart, hasEnd;
-
-            K startKey, endKey;
-
-            transient Set<Map.Entry<K,V>> entrySet = null;
-
-            SubMap(K start, TreeMap<K,V> map) {
-                backingMap = map;
-                hasStart = true;
-                startKey = start;
-            }
-
-            SubMap(K start, TreeMap<K,V> map, K end) {
-                backingMap = map;
-                hasStart = hasEnd = true;
-                startKey = start;
-                endKey = end;
-            }
-            
-            SubMap(TreeMap<K,V> map, K end) {
-                backingMap = map;
-                hasEnd = true;
-                endKey = end;
-            }
-
-            private void checkRange(K key) {
-                Comparator<? super K> cmp = backingMap.comparator;
-                if (cmp == null) {
-                    Comparable<K> object = toComparable(key);
-                    if (hasStart && object.compareTo(startKey) < 0) {
-                        throw new IllegalArgumentException();
+         public boolean containsValue(Object value) {
+            Iterator<V> it = values().iterator();
+            if (value != null) {
+                while (it.hasNext()) {
+                    if (value.equals(it.next())) {
+                        return true;
                     }
-                    if (hasEnd && object.compareTo(endKey) > 0) {
-                        throw new IllegalArgumentException();
+                }
+            } else {
+                while (it.hasNext()) {
+                    if (it.next() == null) {
+                        return true;
                     }
+                }
+            }
+            return false;
+        }
+
+        @Override
+        public Set<Map.Entry<K, V>> entrySet() {
+            if (entrySet == null) {
+                entrySet = new SubMapEntrySet<K, V>(this);
+            }
+            return entrySet;
+        }
+
+        private void setFirstKey() {
+            if (firstKeyModCount == backingMap.modCount) {
+                return;
+            }
+            Comparable<K> object = backingMap.comparator == null ?
+                                   toComparable((K) startKey) : null;
+            K key = (K) startKey;
+            Node<K, V> node = backingMap.root;
+            Node<K, V> foundNode = null;
+            int foundIndex = -1;
+            TOP_LOOP:
+            while (node != null) {
+                K[] keys = node.keys;
+                int left_idx = node.left_idx;
+                int result = backingMap.cmp(object, key, keys[left_idx]);
+                if (result < 0) {
+                    foundNode = node;
+                    foundIndex = left_idx;
+                    node = node.left;
+                } else if (result == 0) {
+                    foundNode = node;
+                    foundIndex = left_idx;
+                    break;
                 } else {
-                    if (hasStart
-                            && backingMap.comparator().compare(key, startKey) < 0) {
-                        throw new IllegalArgumentException();
+                    int right_idx = node.right_idx;
+                    if (left_idx != right_idx) {
+                        result = backingMap.cmp(object, key, keys[right_idx]);
                     }
-                    if (hasEnd && backingMap.comparator().compare(key, endKey) > 0) {
-                        throw new IllegalArgumentException();
+                    if (result > 0) {
+                        node = node.right;
+                    } else if (result == 0) {
+                        foundNode = node;
+                        foundIndex = right_idx;
+                        break;
+                    } else { /*search in node*/
+                        foundNode = node;
+                        foundIndex = right_idx;
+                        int low = left_idx + 1, mid = 0, high = right_idx - 1;
+                        while (low <= high) {
+                            mid = (low + high) >> 1;
+                            result = backingMap.cmp(object, key, keys[mid]);
+                            if (result > 0) {
+                                low = mid + 1;
+                            } else if (result == 0) {
+                                foundNode = node;
+                                foundIndex = mid;
+                                break TOP_LOOP;
+                            } else {
+                                foundNode = node;
+                                foundIndex = mid;
+                                high = mid - 1;
+                            }
+                        }
+                        break TOP_LOOP;
                     }
                 }
             }
-
-            private boolean isInRange(K key) {
-                Comparator<? super K> cmp = backingMap.comparator;
-                if (cmp == null) {
-                    Comparable<K> object = toComparable(key);
-                    if (hasStart && object.compareTo(startKey) < 0) {
-                        return false;
-                    }
-                    if (hasEnd && object.compareTo(endKey) >= 0) {
-                        return false;
-                    }
-                } else {
-                    if (hasStart && cmp.compare(key, startKey) < 0) {
-                        return false;
-                    }
-                    if (hasEnd && cmp.compare(key, endKey) >= 0) {
-                        return false;
-                    }
-                }
-                return true;
+            if (foundNode != null && !checkUpperBound(foundNode.keys[foundIndex])) {
+                foundNode = null;
             }
+            firstKeyNode = foundNode;
+            firstKeyIndex = foundIndex;
+            firstKeyModCount = backingMap.modCount;
+        }
 
-            private boolean checkUpperBound(K key) {
-                if (hasEnd) {
-                    Comparator<? super K> cmp = backingMap.comparator;
-                    if (cmp == null) {
-                        return (toComparable(key).compareTo(endKey) < 0);
-                    }
-                    return (cmp.compare(key, endKey) < 0);
-                }
-                return true;
-            }
-
-            private boolean checkLowerBound(K key) {
-                if (hasStart) {
-                    Comparator<? super K> cmp = backingMap.comparator;
-                    if (cmp == null) {
-                        return (toComparable(key).compareTo(startKey) >= 0);
-                    }
-                    return (cmp.compare(key, startKey) >= 0);
-                }
-                return true;
-            }
-
-            public Comparator<? super K> comparator() {
-                return backingMap.comparator();
-            }
-
-            @SuppressWarnings("unchecked")
-            @Override
-            public boolean containsKey(Object key) {
-                if (isInRange((K)key)) {
-                    return backingMap.containsKey(key);
-                }
-                return false;
-            }
-
-            @Override
-            public Set<Map.Entry<K,V>> entrySet() {
-                if(entrySet==null) {
-                    entrySet = new SubMapEntrySet<K,V>(this);
-                }
-                return entrySet;
-            }
-
-            public K firstKey() {
-                TreeMap.Entry<K,V> node = firstEntry();
-                if (node != null ) {
-                    return node.key;
-                }
-                throw new NoSuchElementException();
-            }
-
-            TreeMap.Entry<K,V> firstEntry() {
+        public K firstKey() {
+            if (backingMap.size > 0) {
                 if (!hasStart) {
-                    TreeMap.Entry<K,V> root = backingMap.root;
-                    return (root == null) ? null : minimum(backingMap.root);
-                }
-                TreeMap.Entry<K,V> node = backingMap.findAfter(startKey);
-                if (node != null && checkUpperBound(node.key)) {
-                    return node;
-                }
-                return null;
-            }
-
-            @SuppressWarnings("unchecked")
-            @Override
-            public V get(Object key) {
-                if (isInRange((K)key)) {
-                    return backingMap.get(key);
-                }
-                return null;
-            }
-
-            public SortedMap<K,V> headMap(K endKey) {
-                checkRange(endKey);
-                if (hasStart) {
-                    return new SubMap<K,V>(startKey, backingMap, endKey);
-                }
-                return new SubMap<K,V>(backingMap, endKey);
-            }
-
-            @Override
-            public boolean isEmpty() {
-                if (hasStart) {
-                    TreeMap.Entry<K,V> node = backingMap.findAfter(startKey);
-                    return node == null || !checkUpperBound(node.key);
-                }
-                return backingMap.findBefore(endKey) == null;
-            }
-
-            @Override
-            public Set<K> keySet() {
-                if (keySet == null) {
-                    keySet = new SubMapKeySet<K,V>(this);
-                }
-                return keySet;
-            }
-
-            public K lastKey() {
-                if (!hasEnd) {
-                    return backingMap.lastKey();
-                }
-                TreeMap.Entry<K,V> node = backingMap.findBefore(endKey);
-                if (node != null && checkLowerBound(node.key)) {
-                    return node.key;
-                }
-                throw new NoSuchElementException();
-            }
-
-            @Override
-            public V put(K key, V value) {
-                if (isInRange(key)) {
-                    return backingMap.put(key, value);
-                }
-                throw new IllegalArgumentException();
-            }
-
-            @SuppressWarnings("unchecked")
-            @Override
-            public V remove(Object key) {
-                if (isInRange((K)key)) {
-                    return backingMap.remove(key);
-                }
-                return null;
-            }
-
-            public SortedMap<K,V> subMap(K startKey, K endKey) {
-                checkRange(startKey);
-                checkRange(endKey);
-                Comparator<? super K> c = backingMap.comparator();
-                if (c == null) {
-                    if (toComparable(startKey).compareTo(endKey) <= 0) {
-                        return new SubMap<K,V>(startKey, backingMap, endKey);
+                    Node<K, V> node = minimum(backingMap.root);
+                    if (node != null && checkUpperBound(node.keys[node.left_idx])) {
+                        return node.keys[node.left_idx];
                     }
                 } else {
-                    if (c.compare(startKey, endKey) <= 0) {
-                        return new SubMap<K,V>(startKey, backingMap, endKey);
+                    setFirstKey();
+                    if (firstKeyNode != null) {
+                        return firstKeyNode.keys[firstKeyIndex];
                     }
                 }
-                throw new IllegalArgumentException();
             }
+            throw new NoSuchElementException();
+        }
 
-            public SortedMap<K,V> tailMap(K startKey) {
-                checkRange(startKey);
-                if (hasEnd) {
-                    return new SubMap<K,V>(startKey, backingMap, endKey);
-                }
-                return new SubMap<K,V>(startKey, backingMap);
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public V get(Object key) {
+            if (isInRange((K) key)) {
+                return backingMap.get(key);
             }
+            return null;
+        }
 
-            @Override
-            public Collection<V> values() {
-                if(valuesCollection==null) {
-                    valuesCollection = new SubMapValuesCollection<K,V>(this);
-                }
-                return valuesCollection;
+        public SortedMap<K, V> headMap(K endKey) {
+            checkRange(endKey);
+            if (hasStart) {
+                return new SubMap<K, V>(startKey, backingMap, endKey);
+            }
+            return new SubMap<K, V>(backingMap, endKey);
+        }
+
+        @Override
+        public boolean isEmpty() {
+            if (hasStart) {
+                setFirstKey();
+                return firstKeyNode == null;
+            } else {
+                setLastKey();
+                return lastKeyNode == null;
             }
         }
 
-        static class SubMapEntrySet<K,V> extends AbstractSet<Map.Entry<K,V>> implements Set<Map.Entry<K,V>> {
-            SubMap<K,V> subMap;
-
-            SubMapEntrySet(SubMap<K,V> map) {
-                subMap = map;
+        @Override
+        public Set<K> keySet() {
+            if (keySet == null) {
+                keySet = new SubMapKeySet<K, V>(this);
             }
-
-            @Override
-            public boolean isEmpty() {
-                return subMap.isEmpty();
-            }
-
-            @Override
-            public Iterator<Map.Entry<K,V>> iterator() {
-                TreeMap.Entry<K,V> startNode = subMap.firstEntry();
-                if (subMap.hasEnd) {
-                    Comparator<? super K> cmp = subMap.comparator();
-                    if (cmp == null) {
-                        return new ComparableBoundedEntryIterator<K,V>(subMap.backingMap, startNode, toComparable(subMap.endKey));
-                    }
-                    return new ComparatorBoundedEntryIterator<K,V>(subMap.backingMap, startNode, subMap.endKey);
-                }
-                return new UnboundedEntryIterator<K,V>(subMap.backingMap, startNode);
-            }
-
-            @Override
-            public int size() {
-                int size = 0;
-                Iterator<Map.Entry<K,V>> it = iterator();
-                while (it.hasNext()) {
-                    size++;
-                    it.next();
-                }
-                return size;
-            }
-
-            @SuppressWarnings("unchecked")
-            @Override
-            public boolean contains(Object object) {
-                if (object instanceof Map.Entry) {
-                    Map.Entry<K,V> entry = (Map.Entry<K,V>) object;
-                    K key = entry.getKey();
-                    if (subMap.isInRange(key)) {
-                        V v1 = subMap.get(key), v2 = entry.getValue();
-                        return v1 == null ? v2 == null : v1.equals(v2);
-                    }
-                }
-                return false;
-            }
-
+            return keySet;
         }
 
-        static class SubMapKeySet<K,V> extends  AbstractSet<K> implements Set<K> {
-            SubMap<K,V> subMap;
-
-            SubMapKeySet(SubMap<K,V> map) {
-                subMap = map;
+        private void setLastKey() {
+            if (lastKeyModCount == backingMap.modCount) {
+                return;
             }
-
-            @Override
-            public boolean contains(Object object) {
-                return subMap.containsKey(object);
-            }
-
-            @Override
-            public boolean isEmpty() {
-                return subMap.isEmpty();
-            }
-
-            @Override
-            public int size() {
-                int size = 0;
-                Iterator<K> it = iterator();
-                while (it.hasNext()) {
-                    size++;
-                    it.next();
-                }
-                return size;
-            }
-
-            @Override
-            public Iterator<K> iterator() {
-                TreeMap.Entry<K,V> startNode = subMap.firstEntry();
-                if (subMap.hasEnd) {
-                    Comparator<? super K> cmp = subMap.comparator();
-                    if (cmp == null) {
-                        return new ComparableBoundedKeyIterator<K,V>(subMap.backingMap, startNode, toComparable(subMap.endKey));
+            Comparable<K> object = backingMap.comparator == null ?
+                                   toComparable((K) endKey) : null;
+            K key = (K) endKey;
+            Node<K, V> node = backingMap.root;
+            Node<K, V> foundNode = null;
+            int foundIndex = -1;
+            TOP_LOOP:
+            while (node != null) {
+                K[] keys = node.keys;
+                int left_idx = node.left_idx;
+                int result = backingMap.cmp(object, key, keys[left_idx]);
+                if (result <= 0) {
+                    node = node.left;
+                } else {
+                    int right_idx = node.right_idx;
+                    if (left_idx != right_idx) {
+                        result = backingMap.cmp(object, key, keys[right_idx]);
                     }
-                    return new ComparatorBoundedKeyIterator<K,V>(subMap.backingMap, startNode, subMap.endKey);
+                    if (result > 0) {
+                        foundNode = node;
+                        foundIndex = right_idx;
+                        node = node.right;
+                    } else if (result == 0) {
+                        if (node.left_idx == node.right_idx) {
+                            foundNode = node.prev;
+                            if (foundNode != null) {
+                                foundIndex = foundNode.right_idx - 1;
+                            }
+                        } else {
+                            foundNode = node;
+                            foundIndex = right_idx - 1;
+                        }
+                        break;
+                    } else { /*search in node*/
+                        foundNode = node;
+                        foundIndex = left_idx;
+                        int low = left_idx + 1, mid = 0, high = right_idx - 1;
+                        while (low <= high) {
+                            mid = (low + high) >> 1;
+                            result = backingMap.cmp(object, key, keys[mid]);
+                            if (result > 0) {
+                                foundNode = node;
+                                foundIndex = mid;
+                                low = mid + 1;
+                            } else if (result == 0) {
+                                foundNode = node;
+                                foundIndex = mid - 1;
+                                break TOP_LOOP;
+                            } else {
+                                high = mid - 1;
+                            }
+                        }
+                        break TOP_LOOP;
+                    }
                 }
-                return new UnboundedKeyIterator<K,V>(subMap.backingMap, startNode);
             }
+            if (foundNode != null && !checkLowerBound(foundNode.keys[foundIndex])) {
+                foundNode = null;
+            }
+            lastKeyNode = foundNode;
+            lastKeyIndex = foundIndex;
+            lastKeyModCount = backingMap.modCount;
         }
 
-        static class SubMapValuesCollection<K,V> extends AbstractCollection<V> {
-            SubMap<K,V> subMap;
-
-            public SubMapValuesCollection(SubMap<K,V> subMap) {
-                this.subMap = subMap;
-            }
-
-            @Override
-            public boolean isEmpty() {
-                return subMap.isEmpty();
-            }
-
-            @Override
-            public Iterator<V> iterator() {
-                TreeMap.Entry<K,V> startNode = subMap.firstEntry();
-                if (subMap.hasEnd) {
-                    Comparator<? super K> cmp = subMap.comparator();
-                    if (cmp == null) {
-                        return new ComparableBoundedValueIterator<K,V>(subMap.backingMap, startNode, toComparable(subMap.endKey));
+        public K lastKey() {
+            if (backingMap.size > 0) {
+                if (!hasEnd) {
+                    Node<K, V> node = maximum(backingMap.root);
+                    if (node != null && checkLowerBound(node.keys[node.right_idx])) {
+                        return node.keys[node.right_idx];
                     }
-                    return new ComparatorBoundedValueIterator<K,V>(subMap.backingMap, startNode, subMap.endKey);
+                } else {
+                    setLastKey();
+                    if (lastKeyNode != null) {
+                        return lastKeyNode.keys[lastKeyIndex];
+                    }
                 }
-                return new UnboundedValueIterator<K,V>(subMap.backingMap, startNode);
             }
-
-            @Override
-            public int size() {
-                int cnt = 0;
-                for (Iterator<V> it = iterator(); it.hasNext();) {
-                    it.next();
-                    cnt++;
-                }
-                return cnt;
-            }
+            throw new NoSuchElementException();
         }
 
+
+        @Override
+        public V put(K key, V value) {
+            if (isInRange(key)) {
+                return backingMap.put(key, value);
+            }
+            throw new IllegalArgumentException();
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public V remove(Object key) {
+            if (isInRange((K) key)) {
+                return backingMap.remove(key);
+            }
+            return null;
+        }
+
+        public SortedMap<K, V> subMap(K startKey, K endKey) {
+            checkRange(startKey);
+            checkRange(endKey);
+            Comparator<? super K> c = backingMap.comparator();
+            if (c == null) {
+                if (toComparable(startKey).compareTo(endKey) <= 0) {
+                    return new SubMap<K, V>(startKey, backingMap, endKey);
+                }
+            } else {
+                if (c.compare(startKey, endKey) <= 0) {
+                    return new SubMap<K, V>(startKey, backingMap, endKey);
+                }
+            }
+            throw new IllegalArgumentException();
+        }
+
+        public SortedMap<K, V> tailMap(K startKey) {
+            checkRange(startKey);
+            if (hasEnd) {
+                return new SubMap<K, V>(startKey, backingMap, endKey);
+            }
+            return new SubMap<K, V>(startKey, backingMap);
+        }
+
+        @Override
+        public Collection<V> values() {
+            if (valuesCollection == null) {
+                valuesCollection = new SubMapValuesCollection<K, V>(this);
+            }
+            return valuesCollection;
+        }
+
+        public int size() {
+            Node<K, V> from, to;
+            int fromIndex, toIndex;
+            if (hasStart) {
+                setFirstKey();
+                from = firstKeyNode;
+                fromIndex = firstKeyIndex;
+            } else {
+                from = minimum(backingMap.root);
+                fromIndex = from == null ? 0 : from.left_idx;
+            }
+            if (from == null) {
+                return 0;
+            }
+            if (hasEnd) {
+                setLastKey();
+                to = lastKeyNode;
+                toIndex = lastKeyIndex;
+            } else {
+                to = maximum(backingMap.root);
+                toIndex = to == null ? 0 : to.right_idx;
+            }
+            if (to == null) {
+                return 0;
+            }
+            if (from == to) {
+                return toIndex - fromIndex + 1;
+            }
+            int sum = 0;
+            while (from != to) {
+                sum += (from.right_idx - fromIndex + 1);
+                from = from.next;
+                fromIndex = from.left_idx;
+            }
+            return sum + toIndex - fromIndex + 1;
+        }
+
+        private void readObject(ObjectInputStream stream) throws IOException,
+                                                                 ClassNotFoundException {
+            stream.defaultReadObject();
+            firstKeyModCount = -1;
+            lastKeyModCount = -1;
+        }
+    }
+
+    static class SubMapEntrySet <K,V> extends AbstractSet<Map.Entry<K, V>>
+                                                implements Set<Map.Entry<K, V>> {
+        SubMap<K, V> subMap;
+
+        SubMapEntrySet(SubMap<K, V> map) {
+            subMap = map;
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return subMap.isEmpty();
+        }
+
+        public Iterator<Map.Entry<K, V>> iterator() {
+            Node<K, V> from;
+            int fromIndex;
+            if (subMap.hasStart) {
+                subMap.setFirstKey();
+                from = subMap.firstKeyNode;
+                fromIndex = subMap.firstKeyIndex;
+            } else {
+                from = minimum(subMap.backingMap.root);
+                fromIndex = from != null ? from.left_idx : 0;
+            }
+            if (!subMap.hasEnd) {
+                return new UnboundedEntryIterator<K, V>(subMap.backingMap, from, from == null ? 0 : from.right_idx - fromIndex);
+            }
+            subMap.setLastKey();
+            Node<K, V> to = subMap.lastKeyNode;
+            int toIndex = subMap.lastKeyIndex;
+            return new BoundedEntryIterator<K, V>(from, from == null ? 0 : from.right_idx - fromIndex, subMap.backingMap, to, to == null ? 0 : to.right_idx - toIndex);
+        }
+
+        @Override
+        public int size() {
+            return subMap.size();
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public boolean contains(Object object) {
+            if (object instanceof Map.Entry) {
+                Map.Entry<K, V> entry = (Map.Entry<K, V>) object;
+                K key = entry.getKey();
+                if (subMap.isInRange(key)) {
+                    V v1 = subMap.get(key), v2 = entry.getValue();
+                    return v1 == null ? ( v2 == null && subMap.containsKey(key) ) : v1.equals(v2);
+                }
+            }
+            return false;
+        }
+
+        @Override
+        public boolean remove(Object object) {
+            if (contains(object)) {
+                Map.Entry<K, V> entry = (Map.Entry<K, V>) object;
+                K key = entry.getKey();
+                subMap.remove(key);
+                return true;
+            }
+            return false;
+        }
+    }
+
+    static class SubMapKeySet <K,V> extends AbstractSet<K> implements Set<K> {
+        SubMap<K, V> subMap;
+
+        SubMapKeySet(SubMap<K, V> map) {
+            subMap = map;
+        }
+
+        @Override
+        public boolean contains(Object object) {
+            return subMap.containsKey(object);
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return subMap.isEmpty();
+        }
+
+        @Override
+        public int size() {
+            return subMap.size();
+        }
+
+        @Override
+        public boolean remove(Object object) {
+            if (subMap.containsKey(object)) {
+                subMap.remove(object);
+                return true;
+            }
+            return false;
+        }
+
+        public Iterator<K> iterator() {
+            Node<K, V> from;
+            int fromIndex;
+            if (subMap.hasStart) {
+                subMap.setFirstKey();
+                from = subMap.firstKeyNode;
+                fromIndex = subMap.firstKeyIndex;
+            } else {
+                from = minimum(subMap.backingMap.root);
+                fromIndex = from != null ? from.left_idx : 0;
+            }
+            if (!subMap.hasEnd) {
+                return new UnboundedKeyIterator<K, V>(subMap.backingMap, from,
+                                   from == null ? 0 : from.right_idx - fromIndex);
+            }
+            subMap.setLastKey();
+            Node<K, V> to = subMap.lastKeyNode;
+            int toIndex = subMap.lastKeyIndex;
+            return new BoundedKeyIterator<K, V>(from,
+               from == null ? 0 : from.right_idx - fromIndex, subMap.backingMap, to,
+                 to == null ? 0 : to.right_idx   - toIndex);
+        }
+    }
+
+    static class SubMapValuesCollection <K,V> extends AbstractCollection<V> {
+        SubMap<K, V> subMap;
+
+        public SubMapValuesCollection(SubMap<K, V> subMap) {
+            this.subMap = subMap;
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return subMap.isEmpty();
+        }
+
+        @Override
+        public Iterator<V> iterator() {
+            Node<K, V> from;
+            int fromIndex;
+            if (subMap.hasStart) {
+                subMap.setFirstKey();
+                from = subMap.firstKeyNode;
+                fromIndex = subMap.firstKeyIndex;
+            } else {
+                from = minimum(subMap.backingMap.root);
+                fromIndex = from != null ? from.left_idx : 0;
+            }
+            if (!subMap.hasEnd) {
+                return new UnboundedValueIterator<K, V>(subMap.backingMap, from,
+                                   from == null ? 0 : from.right_idx - fromIndex);
+            }
+            subMap.setLastKey();
+            Node<K, V> to = subMap.lastKeyNode;
+            int toIndex = subMap.lastKeyIndex;
+            return new BoundedValueIterator<K, V>(from,
+               from == null ? 0 : from.right_idx - fromIndex, subMap.backingMap, to,
+                 to == null ? 0 : to.right_idx - toIndex);
+        }
+
+        @Override
+        public int size() {
+            return subMap.size();
+        }
+    }
+
     /**
      * Constructs a new empty {@code TreeMap} instance.
-     * 
-     * @since Android 1.0
      */
     public TreeMap() {
-        super();
     }
 
     /**
      * Constructs a new empty {@code TreeMap} instance with the specified
      * comparator.
-     * 
+     *
      * @param comparator
      *            the comparator to compare keys with.
-     * @since Android 1.0
      */
     public TreeMap(Comparator<? super K> comparator) {
         this.comparator = comparator;
@@ -683,50 +977,753 @@
     /**
      * Constructs a new {@code TreeMap} instance containing the mappings from
      * the specified map and using natural ordering.
-     * 
+     *
      * @param map
      *            the mappings to add.
      * @throws ClassCastException
      *             if a key in the specified map does not implement the
      *             Comparable interface, or if the keys in the map cannot be
      *             compared.
-     * @since Android 1.0
      */
-    public TreeMap(Map<? extends K,? extends V> map) {
-        this();
+    public TreeMap(Map<? extends K, ? extends V> map) {
         putAll(map);
     }
 
     /**
      * Constructs a new {@code TreeMap} instance containing the mappings from
      * the specified SortedMap and using the same comparator.
-     * 
+     *
      * @param map
      *            the mappings to add.
-     * @since Android 1.0
      */
-    public TreeMap(SortedMap<K,? extends V> map) {
+    public TreeMap(SortedMap<K, ? extends V> map) {
         this(map.comparator());
+        Node<K, V> lastNode = null;
         Iterator<? extends Map.Entry<K, ? extends V>> it = map.entrySet().iterator();
-        if (it.hasNext()) {
+        while (it.hasNext()) {
             Map.Entry<K, ? extends V> entry = it.next();
-            Entry<K, V> last = new Entry<K, V>(entry.getKey(), entry.getValue());
-            root = last;
-            size = 1;
-            while (it.hasNext()) {
-                entry = it.next();
-                Entry<K, V> x = new Entry<K, V>(entry.getKey(), entry.getValue());
-                x.parent = last;
-                last.right = x;
-                size++;
-                balance(x);
-                last = x;
-            }
+            lastNode = addToLast(lastNode, entry.getKey(), entry.getValue());
         }
     }
 
-    void balance(Entry<K, V> x) {
-        Entry<K, V> y;
+    Node<K, V> addToLast(Node<K, V> last, K key, V value) {
+        if (last == null) {
+            root = last = createNode(key, value);
+            size = 1;
+        } else if (last.size == Node.NODE_SIZE) {
+            Node<K, V> newNode = createNode(key, value);
+            attachToRight(last, newNode);
+            balance(newNode);
+            size++;
+            last = newNode;
+        } else {
+            appendFromRight(last, key, value);
+            size++;
+        }
+        return last;
+    }
+
+    /**
+     * Removes all mappings from this TreeMap, leaving it empty.
+     *
+     * @see Map#isEmpty()
+     * @see #size()
+     */
+    @Override
+    public void clear() {
+        root = null;
+        size = 0;
+        modCount++;
+    }
+
+    /**
+     * Returns a new {@code TreeMap} with the same mappings, size and comparator
+     * as this instance.
+     *
+     * @return a shallow copy of this instance.
+     * @see java.lang.Cloneable
+     */
+    @SuppressWarnings("unchecked")
+    @Override
+    public Object clone() {
+        try {
+            TreeMap<K, V> clone = (TreeMap<K, V>) super.clone();
+            clone.entrySet = null;
+            if (root != null) {
+                clone.root = root.clone(null);
+                // restore prev/next chain
+                Node<K, V> node = minimum(clone.root);
+                while (true) {
+                    Node<K, V> nxt = successor(node);
+                    if (nxt == null) {
+                        break;
+                    }
+                    nxt.prev = node;
+                    node.next = nxt;
+                    node = nxt;
+                }
+            }
+            return clone;
+        } catch (CloneNotSupportedException e) {
+            return null;
+        }
+    }
+
+    static private <K, V> Node<K, V> successor(Node<K, V> x) {
+        if (x.right != null) {
+            return minimum(x.right);
+        }
+        Node<K, V> y = x.parent;
+        while (y != null && x == y.right) {
+            x = y;
+            y = y.parent;
+        }
+        return y;
+    }
+
+    /**
+     * Returns the comparator used to compare elements in this map.
+     *
+     * @return the comparator or {@code null} if the natural ordering is used.
+     */
+    public Comparator<? super K> comparator() {
+        return comparator;
+    }
+
+    /**
+     * Returns whether this map contains the specified key.
+     *
+     * @param key
+     *            the key to search for.
+     * @return {@code true} if this map contains the specified key,
+     *         {@code false} otherwise.
+     * @throws ClassCastException
+     *             if the specified key cannot be compared with the keys in this
+     *             map.
+     * @throws NullPointerException
+     *             if the specified key is {@code null} and the comparator
+     *             cannot handle {@code null} keys.
+     */
+    @Override
+    public boolean containsKey(Object key) {
+        Comparable<K> object = comparator == null ? toComparable((K) key) : null;
+        K keyK = (K) key;
+        Node<K, V> node = root;
+        while (node != null) {
+            K[] keys = node.keys;
+            int left_idx = node.left_idx;
+            int result = cmp(object, keyK, keys[left_idx]);
+            if (result < 0) {
+                node = node.left;
+            } else if (result == 0) {
+                return true;
+            } else {
+                int right_idx = node.right_idx;
+                if (left_idx != right_idx) {
+                    result = cmp(object, keyK, keys[right_idx]);
+                }
+                if (result > 0) {
+                    node = node.right;
+                } else if (result == 0) {
+                    return true;
+                } else { /*search in node*/
+                    int low = left_idx + 1, mid = 0, high = right_idx - 1;
+                    while (low <= high) {
+                        mid = (low + high) >> 1;
+                        result = cmp(object, keyK, keys[mid]);
+                        if (result > 0) {
+                            low = mid + 1;
+                        } else if (result == 0) {
+                            return true;
+                        } else {
+                            high = mid - 1;
+                        }
+                    }
+                    return false;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns whether this map contains the specified value.
+     *
+     * @param value
+     *            the value to search for.
+     * @return {@code true} if this map contains the specified value,
+     *         {@code false} otherwise.
+     */
+    @Override
+    public boolean containsValue(Object value) {
+        if (root == null) {
+            return false;
+        }
+        Node<K, V> node = minimum(root);
+        if (value != null) {
+            while (node != null) {
+                int to = node.right_idx;
+                V[] values = node.values;
+                for (int i = node.left_idx; i <= to; i++) {
+                    if (value.equals(values[i])) {
+                        return true;
+                    }
+                }
+                node = node.next;
+            }
+        } else {
+            while (node != null) {
+                int to = node.right_idx;
+                V[] values = node.values;
+                for (int i = node.left_idx; i <= to; i++) {
+                    if (values[i] == null) {
+                        return true;
+                    }
+                }
+                node = node.next;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns a set containing all of the mappings in this map. Each mapping is
+     * an instance of {@link Map.Entry}. As the set is backed by this map,
+     * changes in one will be reflected in the other. It does not support adding
+     * operations.
+     *
+     * @return a set of the mappings.
+     */
+    @Override
+    public Set<Map.Entry<K, V>> entrySet() {
+        if (entrySet == null) {
+            entrySet = new AbstractSet<Map.Entry<K, V>>() {
+                @Override
+                public int size() {
+                    return size;
+                }
+
+                @Override
+                public void clear() {
+                    TreeMap.this.clear();
+                }
+
+                @SuppressWarnings("unchecked")
+                @Override
+                public boolean contains(Object object) {
+                    if (object instanceof Map.Entry) {
+                        Map.Entry<K, V> entry = (Map.Entry<K, V>) object;
+                        K key = entry.getKey();
+                        Object v1 = TreeMap.this.get(key), v2 = entry.getValue();
+                        return v1 == null ? ( v2 == null && TreeMap.this.containsKey(key) ) : v1.equals(v2);
+                    }
+                    return false;
+                }
+
+                @Override
+                public boolean remove(Object object) {
+                    if (contains(object)) {
+                        Map.Entry<K, V> entry = (Map.Entry<K, V>) object;
+                        K key = entry.getKey();
+                        TreeMap.this.remove(key);
+                        return true;
+                    }
+                    return false;
+                }
+
+                @Override
+                public Iterator<Map.Entry<K, V>> iterator() {
+                    return new UnboundedEntryIterator<K, V>(TreeMap.this);
+                }
+            };
+        }
+        return entrySet;
+    }
+
+    /**
+     * Returns the first key in this map.
+     *
+     * @return the first key in this map.
+     * @throws NoSuchElementException
+     *                if this map is empty.
+     */
+    public K firstKey() {
+        if (root != null) {
+            Node<K, V> node = minimum(root);
+            return node.keys[node.left_idx];
+        }
+        throw new NoSuchElementException();
+    }
+
+
+    /**
+     * Returns the value of the mapping with the specified key.
+     *
+     * @param key
+     *            the key.
+     * @return the value of the mapping with the specified key.
+     * @throws ClassCastException
+     *             if the key cannot be compared with the keys in this map.
+     * @throws NullPointerException
+     *             if the key is {@code null} and the comparator cannot handle
+     *             {@code null}.
+     */
+    @Override
+    public V get(Object key) {
+        Comparable<K> object = comparator == null ? toComparable((K) key) : null;
+        K keyK = (K) key;
+        Node<K, V> node = root;
+        while (node != null) {
+            K[] keys = node.keys;
+            int left_idx = node.left_idx;
+            int result = cmp(object, keyK, keys[left_idx]);
+            if (result < 0) {
+                node = node.left;
+            } else if (result == 0) {
+                return node.values[left_idx];
+            } else {
+                int right_idx = node.right_idx;
+                if (left_idx != right_idx) {
+                    result = cmp(object, keyK, keys[right_idx]);
+                }
+                if (result > 0) {
+                    node = node.right;
+                } else if (result == 0) {
+                    return node.values[right_idx];
+                } else { /*search in node*/
+                    int low = left_idx + 1, mid = 0, high = right_idx - 1;
+                    while (low <= high) {
+                        mid = (low + high) >> 1;
+                        result = cmp(object, keyK, keys[mid]);
+                        if (result > 0) {
+                            low = mid + 1;
+                        } else if (result == 0) {
+                            return node.values[mid];
+                        } else {
+                            high = mid - 1;
+                        }
+                    }
+                    return null;
+                }
+            }
+        }
+        return null;
+    }
+
+    private int cmp(Comparable<K> object, K key1, K key2) {
+        return object != null ?
+               object.compareTo(key2) : comparator.compare(key1, key2);
+    }
+
+    /**
+     * Returns a sorted map over a range of this sorted map with all keys that
+     * are less than the specified {@code endKey}. Changes to the returned
+     * sorted map are reflected in this sorted map and vice versa.
+     * <p>
+     * Note: The returned map will not allow an insertion of a key outside the
+     * specified range.
+     *
+     * @param endKey
+     *            the high boundary of the range specified.
+     * @return a sorted map where the keys are less than {@code endKey}.
+     * @throws ClassCastException
+     *             if the specified key cannot be compared with the keys in this
+     *             map.
+     * @throws NullPointerException
+     *             if the specified key is {@code null} and the comparator
+     *             cannot handle {@code null} keys.
+     * @throws IllegalArgumentException
+     *             if this map is itself a sorted map over a range of another
+     *             map and the specified key is outside of its range.
+     */
+    public SortedMap<K, V> headMap(K endKey) {
+        // Check for errors
+        if (comparator == null) {
+            toComparable(endKey).compareTo(endKey);
+        } else {
+            comparator.compare(endKey, endKey);
+        }
+        return new SubMap<K, V>(this, endKey);
+    }
+
+    /**
+     * Returns a set of the keys contained in this map. The set is backed by
+     * this map so changes to one are reflected by the other. The set does not
+     * support adding.
+     *
+     * @return a set of the keys.
+     */
+    @Override
+    public Set<K> keySet() {
+        if (keySet == null) {
+            keySet = new AbstractSet<K>() {
+                @Override
+                public boolean contains(Object object) {
+                    return TreeMap.this.containsKey(object);
+                }
+
+                @Override
+                public int size() {
+                    return TreeMap.this.size;
+                }
+
+                @Override
+                public void clear() {
+                    TreeMap.this.clear();
+                }
+
+                @Override
+                public boolean remove(Object object) {
+                    if (contains(object)) {
+                        TreeMap.this.remove(object);
+                        return true;
+                    }
+                    return false;
+                }
+
+                @Override
+                public Iterator<K> iterator() {
+                    return new UnboundedKeyIterator<K, V>(TreeMap.this);
+                }
+            };
+        }
+        return keySet;
+    }
+
+    /**
+     * Returns the last key in this map.
+     *
+     * @return the last key in this map.
+     * @throws NoSuchElementException
+     *             if this map is empty.
+     */
+    public K lastKey() {
+        if (root != null) {
+            Node<K, V> node = maximum(root);
+            return node.keys[node.right_idx];
+        }
+        throw new NoSuchElementException();
+    }
+
+    static <K,V> Node<K, V> minimum(Node<K, V> x) {
+        if (x == null) {
+            return null;
+        }
+        while (x.left != null) {
+            x = x.left;
+        }
+        return x;
+    }
+
+    static <K,V> Node<K, V> maximum(Node<K, V> x) {
+        if (x == null) {
+            return null;
+        }
+        while (x.right != null) {
+            x = x.right;
+        }
+        return x;
+    }
+
+    /**
+     * Maps the specified key to the specified value.
+     *
+     * @param key
+     *            the key.
+     * @param value
+     *            the value.
+     * @return the value of any previous mapping with the specified key or
+     *         {@code null} if there was no mapping.
+     * @throws ClassCastException
+     *             if the specified key cannot be compared with the keys in this
+     *             map.
+     * @throws NullPointerException
+     *             if the specified key is {@code null} and the comparator
+     *             cannot handle {@code null} keys.
+     */
+    @Override
+    public V put(K key, V value) {
+        if (root == null) {
+            root = createNode(key, value);
+            size = 1;
+            modCount++;
+            return null;
+        }
+        Comparable<K> object = comparator == null ? toComparable((K) key) : null;
+        K keyK = (K) key;
+        Node<K, V> node = root;
+        Node<K, V> prevNode = null;
+        int result = 0;
+        while (node != null) {
+            prevNode = node;
+            K[] keys = node.keys;
+            int left_idx = node.left_idx;
+            result = cmp(object, keyK, keys[left_idx]);
+            if (result < 0) {
+                node = node.left;
+            } else if (result == 0) {
+                V res = node.values[left_idx];
+                node.values[left_idx] = value;
+                return res;
+            } else {
+                int right_idx = node.right_idx;
+                if (left_idx != right_idx) {
+                    result = cmp(object, keyK, keys[right_idx]);
+                }
+                if (result > 0) {
+                    node = node.right;
+                } else if (result == 0) {
+                    V res = node.values[right_idx];
+                    node.values[right_idx] = value;
+                    return res;
+                } else { /*search in node*/
+                    int low = left_idx + 1, mid = 0, high = right_idx - 1;
+                    while (low <= high) {
+                        mid = (low + high) >> 1;
+                        result = cmp(object, keyK, keys[mid]);
+                        if (result > 0) {
+                            low = mid + 1;
+                        } else if (result == 0) {
+                            V res = node.values[mid];
+                            node.values[mid] = value;
+                            return res;
+                        } else {
+                            high = mid - 1;
+                        }
+                    }
+                    result = low;
+                    break;
+                }
+            }
+        } /* while */
+/*
+          if(node == null) {
+             if(prevNode==null) {
+                - case of empty Tree
+             } else {
+                result < 0 - prevNode.left==null - attach here
+                result > 0 - prevNode.right==null - attach here
+             }
+          } else {
+             insert into node.
+             result - index where it should be inserted.
+          }
+        */
+        size++;
+        modCount++;
+        if (node == null) {
+            if (prevNode == null) {
+                // case of empty Tree
+                root = createNode(key, value);
+            } else if (prevNode.size < Node.NODE_SIZE) {
+                // there is a place for insert
+                if (result < 0) {
+                    appendFromLeft(prevNode, key, value);
+                } else {
+                    appendFromRight(prevNode, key, value);
+                }
+            } else {
+                // create and link
+                Node<K, V> newNode = createNode(key, value);
+                if (result < 0) {
+                    attachToLeft(prevNode, newNode);
+                } else {
+                    attachToRight(prevNode, newNode);
+                }
+                balance(newNode);
+            }
+        } else {
+            // insert into node.
+            // result - index where it should be inserted.
+            if (node.size < Node.NODE_SIZE) { // insert and ok
+                int left_idx = node.left_idx;
+                int right_idx = node.right_idx;
+                if (left_idx == 0 || ((right_idx != Node.NODE_SIZE - 1) && (right_idx - result <= result - left_idx))) {
+                    int right_idxPlus1 = right_idx + 1;
+                    System.arraycopy(node.keys,   result, node.keys,   result + 1, right_idxPlus1 - result);
+                    System.arraycopy(node.values, result, node.values, result + 1, right_idxPlus1 - result);
+                    node.right_idx = right_idxPlus1;
+                    node.keys[result] = key;
+                    node.values[result] = value;
+                } else {
+                    int left_idxMinus1 = left_idx - 1;
+                    System.arraycopy(node.keys,   left_idx, node.keys,   left_idxMinus1, result - left_idx);
+                    System.arraycopy(node.values, left_idx, node.values, left_idxMinus1, result - left_idx);
+                    node.left_idx = left_idxMinus1;
+                    node.keys[result - 1] = key;
+                    node.values[result - 1] = value;
+                }
+                node.size++;
+            } else {
+                // there are no place here
+                // insert and push old pair
+                Node<K, V> previous = node.prev;
+                Node<K, V> nextNode = node.next;
+                boolean removeFromStart;
+                boolean attachFromLeft = false;
+                Node<K, V> attachHere = null;
+                if (previous == null) {
+                    if (nextNode != null && nextNode.size < Node.NODE_SIZE) {
+                        // move last pair to next
+                        removeFromStart = false;
+                    } else {
+                        // next node doesn't exist or full
+                        // left==null
+                        // drop first pair to new node from left
+                        removeFromStart = true;
+                        attachFromLeft = true;
+                        attachHere = node;
+                    }
+                } else if (nextNode == null) {
+                    if (previous.size < Node.NODE_SIZE) {
+                        // move first pair to prev
+                        removeFromStart = true;
+                    } else {
+                        // right == null;
+                        // drop last pair to new node from right
+                        removeFromStart = false;
+                        attachFromLeft = false;
+                        attachHere = node;
+                    }
+                } else {
+                    if (previous.size < Node.NODE_SIZE) {
+                        if (nextNode.size < Node.NODE_SIZE) {
+                            // choose prev or next for moving
+                            removeFromStart = previous.size < nextNode.size;
+                        } else {
+                            // move first pair to prev
+                            removeFromStart = true;
+                        }
+                    } else {
+                        if (nextNode.size < Node.NODE_SIZE) {
+                            // move last pair to next
+                            removeFromStart = false;
+                        } else {
+                            // prev & next are full
+                            // if node.right!=null then node.next.left==null
+                            // if node.left!=null then node.prev.right==null
+                            if (node.right == null) {
+                                attachHere = node;
+                                attachFromLeft = false;
+                                removeFromStart = false;
+                            } else {
+                                attachHere = nextNode;
+                                attachFromLeft = true;
+                                removeFromStart = false;
+                            }
+                        }
+                    }
+                }
+                K movedKey;
+                V movedValue;
+                if (removeFromStart) {
+                    // node.left_idx == 0
+                    movedKey = node.keys[0];
+                    movedValue = node.values[0];
+                    int resMunus1 = result - 1;
+                    System.arraycopy(node.keys,   1, node.keys,   0, resMunus1);
+                    System.arraycopy(node.values, 1, node.values, 0, resMunus1);
+                    node.keys  [resMunus1] = key;
+                    node.values[resMunus1] = value;
+                } else {
+                    // node.right_idx == Node.NODE_SIZE - 1
+                    movedKey   = node.keys[Node.NODE_SIZE - 1];
+                    movedValue = node.values[Node.NODE_SIZE - 1];
+                    System.arraycopy(node.keys,   result, node.keys,   result + 1, Node.NODE_SIZE - 1 - result);
+                    System.arraycopy(node.values, result, node.values, result + 1, Node.NODE_SIZE - 1 - result);
+                    node.keys[result] = key;
+                    node.values[result] = value;
+                }
+                if (attachHere == null) {
+                    if (removeFromStart) {
+                        appendFromRight(previous, movedKey, movedValue);
+                    } else {
+                        appendFromLeft(nextNode, movedKey, movedValue);
+                    }
+                } else {
+                    Node<K, V> newNode = createNode(movedKey, movedValue);
+                    if (attachFromLeft) {
+                        attachToLeft(attachHere, newNode);
+                    } else {
+                        attachToRight(attachHere, newNode);
+                    }
+                    balance(newNode);
+                }
+            }
+        }
+        return null;
+    }
+
+    private void appendFromLeft(Node<K, V> node, K keyObj, V value) {
+        if (node.left_idx == 0) {
+            int new_right = node.right_idx + 1;
+            System.arraycopy(node.keys,   0, node.keys,   1, new_right);
+            System.arraycopy(node.values, 0, node.values, 1, new_right);
+            node.right_idx = new_right;
+        } else {
+            node.left_idx--;
+        }
+        node.size++;
+        node.keys[node.left_idx] = keyObj;
+        node.values[node.left_idx] = value;
+    }
+
+    private void attachToLeft(Node<K, V> node, Node<K, V> newNode) {
+        newNode.parent = node;
+        // node.left==null - attach here
+        node.left = newNode;
+        Node<K, V> predecessor = node.prev;
+        newNode.prev = predecessor;
+        newNode.next = node;
+        if (predecessor != null) {
+            predecessor.next = newNode;
+        }
+        node.prev = newNode;
+    }
+
+    /* add pair into node; existence free room in the node should be checked
+     * before call
+     */
+    private void appendFromRight(Node<K, V> node, K keyObj, V value) {
+        if (node.right_idx == Node.NODE_SIZE - 1) {
+            int left_idx = node.left_idx;
+            int left_idxMinus1 = left_idx - 1;
+            System.arraycopy(node.keys,   left_idx, node.keys,   left_idxMinus1, Node.NODE_SIZE - left_idx);
+            System.arraycopy(node.values, left_idx, node.values, left_idxMinus1, Node.NODE_SIZE - left_idx);
+            node.left_idx = left_idxMinus1;
+        } else {
+            node.right_idx++;
+        }
+        node.size++;
+        node.keys[node.right_idx] = keyObj;
+        node.values[node.right_idx] = value;
+    }
+
+    private void attachToRight(Node<K, V> node, Node<K, V> newNode) {
+        newNode.parent = node;
+        // - node.right==null - attach here
+        node.right = newNode;
+        newNode.prev = node;
+        Node<K, V> successor = node.next;
+        newNode.next = successor;
+        if (successor != null) {
+            successor.prev = newNode;
+        }
+        node.next = newNode;
+    }
+
+    private Node<K, V> createNode(K keyObj, V value) {
+        Node<K, V> node = new Node<K, V>();
+        node.keys[0] = keyObj;
+        node.values[0] = value;
+        node.left_idx = 0;
+        node.right_idx = 0;
+        node.size = 1;
+        return node;
+    }
+
+    void balance(Node<K, V> x) {
+        Node<K, V> y;
         x.color = true;
         while (x != root && x.parent.color) {
             if (x.parent == x.parent.parent.left) {
@@ -766,226 +1763,421 @@
         root.color = false;
     }
 
+    private void rightRotate(Node<K, V> x) {
+        Node<K, V> y = x.left;
+        x.left = y.right;
+        if (y.right != null) {
+            y.right.parent = x;
+        }
+        y.parent = x.parent;
+        if (x.parent == null) {
+            root = y;
+        } else {
+            if (x == x.parent.right) {
+                x.parent.right = y;
+            } else {
+                x.parent.left = y;
+            }
+        }
+        y.right = x;
+        x.parent = y;
+    }
+
+
+    private void leftRotate(Node<K, V> x) {
+        Node<K, V> y = x.right;
+        x.right = y.left;
+        if (y.left != null) {
+            y.left.parent = x;
+        }
+        y.parent = x.parent;
+        if (x.parent == null) {
+            root = y;
+        } else {
+            if (x == x.parent.left) {
+                x.parent.left = y;
+            } else {
+                x.parent.right = y;
+            }
+        }
+        y.left = x;
+        x.parent = y;
+    }
+
+
     /**
-     * Removes all mappings from this TreeMap, leaving it empty.
-     * 
-     * @see Map#isEmpty()
-     * @see #size()
-     * @since Android 1.0
+     * Copies all the mappings in the given map to this map. These mappings will
+     * replace all mappings that this map had for any of the keys currently in
+     * the given map.
+     *
+     * @param map
+     *            the map to copy mappings from.
+     * @throws ClassCastException
+     *             if a key in the specified map cannot be compared with the
+     *             keys in this map.
+     * @throws NullPointerException
+     *             if a key in the specified map is {@code null} and the
+     *             comparator cannot handle {@code null} keys.
      */
     @Override
-    public void clear() {
-        root = null;
-        size = 0;
-        modCount++;
+    public void putAll(Map<? extends K, ? extends V> map) {
+        super.putAll(map);
     }
 
     /**
-     * Returns a new {@code TreeMap} with the same mappings, size and comparator
-     * as this instance.
-     * 
-     * @return a shallow copy of this instance.
-     * @see java.lang.Cloneable
-     * @since Android 1.0
+     * Removes the mapping with the specified key from this map.
+     *
+     * @param key
+     *            the key of the mapping to remove.
+     * @return the value of the removed mapping or {@code null} if no mapping
+     *         for the specified key was found.
+     * @throws ClassCastException
+     *             if the specified key cannot be compared with the keys in this
+     *             map.
+     * @throws NullPointerException
+     *             if the specified key is {@code null} and the comparator
+     *             cannot handle {@code null} keys.
      */
-    @SuppressWarnings("unchecked")
     @Override
-    public Object clone() {
-        try {
-            TreeMap<K, V> clone = (TreeMap<K, V>) super.clone();
-            clone.entrySet = null;
-            if (root != null) {
-                clone.root = root.clone(null);
-            }
-            return clone;
-        } catch (CloneNotSupportedException e) {
+    public V remove(Object key) {
+        if (size == 0) {
             return null;
         }
-    }
-
-    /**
-     * Returns the comparator used to compare elements in this map.
-     * 
-     * @return the comparator or {@code null} if the natural ordering is used.
-     * @since Android 1.0
-     */
-    public Comparator<? super K> comparator() {
-        return comparator;
-    }
-
-    /**
-     * Returns whether this map contains the specified key.
-     * 
-     * @param key
-     *            the key to search for.
-     * @return {@code true} if this map contains the specified key,
-     *         {@code false} otherwise.
-     * @since Android 1.0
-     */
-    @Override
-    public boolean containsKey(Object key) {
-        return find(key) != null;
-    }
-
-    /**
-     * Returns whether this map contains the specified value.
-     * 
-     * @param value
-     *            the value to search for.
-     * @return {@code true} if this map contains the specified value,
-     *         {@code false} otherwise.
-     * @since Android 1.0
-     */
-    @Override
-    public boolean containsValue(Object value) {
-        if (root != null) {
-            return containsValue(root, value);
-        }
-        return false;
-    }
-
-    private boolean containsValue(Entry<K, V> node, Object value) {
-        if (value == null ? node.value == null : value.equals(node.value)) {
-            return true;
-        }
-        if (node.left != null) {
-            if (containsValue(node.left, value)) {
-                return true;
-            }
-        }
-        if (node.right != null) {
-            if (containsValue(node.right, value)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Returns a set containing all of the mappings in this map. Each mapping is
-     * an instance of {@link Map.Entry}. As the set is backed by this map,
-     * changes in one will be reflected in the other. It does not support adding
-     * operations.
-     * 
-     * @return a set of the mappings.
-     * @since Android 1.0
-     */
-    @Override
-    public Set<Map.Entry<K, V>> entrySet() {
-        if (entrySet == null) {
-            entrySet = new AbstractSet<Map.Entry<K, V>>() {
-                 @Override
-                public int size() {
-                    return size;
+        Comparable<K> object = comparator == null ? toComparable((K) key) : null;
+        K keyK = (K) key;
+        Node<K, V> node = root;
+        while (node != null) {
+            K[] keys = node.keys;
+            int left_idx = node.left_idx;
+            int result = cmp(object, keyK, keys[left_idx]);
+            if (result < 0) {
+                node = node.left;
+            } else if (result == 0) {
+                V value = node.values[left_idx];
+                removeLeftmost(node);
+                return value;
+            } else {
+                int right_idx = node.right_idx;
+                if (left_idx != right_idx) {
+                    result = cmp(object, keyK, keys[right_idx]);
                 }
-
-                @Override
-                public void clear() {
-                    TreeMap.this.clear();
-                }
-
-                @SuppressWarnings("unchecked")
-                @Override
-                public boolean contains(Object object) {
-                    if (object instanceof Map.Entry) {
-                        Map.Entry<K, V> entry = (Map.Entry<K, V>) object;
-                        Object v1 = get(entry.getKey()), v2 = entry.getValue();
-                        return v1 == null ? v2 == null : v1.equals(v2);
+                if (result > 0) {
+                    node = node.right;
+                } else if (result == 0) {
+                    V value = node.values[right_idx];
+                    removeRightmost(node);
+                    return value;
+                } else { /*search in node*/
+                    int low = left_idx + 1, mid = 0, high = right_idx - 1;
+                    while (low <= high) {
+                        mid = (low + high) >> 1;
+                        result = cmp(object, keyK, keys[mid]);
+                        if (result > 0) {
+                            low = mid + 1;
+                        } else if (result == 0) {
+                            V value = node.values[mid];
+                            removeMiddleElement(node, mid);
+                            return value;
+                        } else {
+                            high = mid - 1;
+                        }
                     }
-                    return false;
+                    return null;
                 }
-
-                @Override
-                public Iterator<Map.Entry<K, V>> iterator() {
-                    return new UnboundedEntryIterator<K, V>(TreeMap.this);
-                }
-            };
-        }
-        return entrySet;
-    }
-
-    @SuppressWarnings("unchecked")
-    private Entry<K, V> find(Object keyObj) {
-        int result;
-        K key = (K)keyObj;
-        Comparable<K> object = null;
-        if (comparator == null) {
-            object = toComparable(key);
-        }
-        Entry<K, V> x = root;
-        while (x != null) {
-            result = object != null ? object.compareTo(x.key) : comparator
-                    .compare(key, x.key);
-            if (result == 0) {
-                return x;
             }
-            x = result < 0 ? x.left : x.right;
         }
         return null;
     }
 
-    @SuppressWarnings("unchecked")
-    Entry<K, V> findAfter(Object keyObj) {
-        K key = (K)keyObj;
-        int result;
-        Comparable<K> object = null;
-        if (comparator == null) {
-            object = toComparable(key);
-        }
-        Entry<K, V> x = root, last = null;
-        while (x != null) {
-            result = object != null ? object.compareTo(x.key) : comparator
-                    .compare(key, x.key);
-            if (result == 0) {
-                return x;
+    void removeLeftmost(Node<K, V> node) {
+        int index = node.left_idx;
+        if (node.size == 1) {
+            deleteNode(node);
+        } else if (node.prev != null && (Node.NODE_SIZE - 1 - node.prev.right_idx) > node.size) {
+            // move all to prev node and kill it
+            Node<K, V> prev = node.prev;
+            int size = node.right_idx - index;
+            System.arraycopy(node.keys,   index + 1, prev.keys,   prev.right_idx + 1, size);
+            System.arraycopy(node.values, index + 1, prev.values, prev.right_idx + 1, size);
+            prev.right_idx += size;
+            prev.size += size;
+            deleteNode(node);
+        } else if (node.next != null && (node.next.left_idx) > node.size) {
+            // move all to next node and kill it
+            Node<K, V> next = node.next;
+            int size = node.right_idx - index;
+            int next_new_left = next.left_idx - size;
+            next.left_idx = next_new_left;
+            System.arraycopy(node.keys,   index + 1, next.keys,   next_new_left, size);
+            System.arraycopy(node.values, index + 1, next.values, next_new_left, size);
+            next.size += size;
+            deleteNode(node);
+        } else {
+            node.keys[index] = null;
+            node.values[index] = null;
+            node.left_idx++;
+            node.size--;
+            Node<K, V> prev = node.prev;
+            if (prev != null && prev.size == 1) {
+                node.size++;
+                node.left_idx--;
+                node.keys  [node.left_idx] = prev.keys  [prev.left_idx];
+                node.values[node.left_idx] = prev.values[prev.left_idx];
+                deleteNode(prev);
             }
-            if (result < 0) {
-                last = x;
-                x = x.left;
+        }
+        modCount++;
+        size--;
+    }
+
+    void removeRightmost(Node<K, V> node) {
+        int index = node.right_idx;
+        if (node.size == 1) {
+            deleteNode(node);
+        } else if (node.prev != null && (Node.NODE_SIZE - 1 - node.prev.right_idx) > node.size) {
+            // move all to prev node and kill it
+            Node<K, V> prev = node.prev;
+            int left_idx = node.left_idx;
+            int size = index - left_idx;
+            System.arraycopy(node.keys,   left_idx, prev.keys,   prev.right_idx + 1, size);
+            System.arraycopy(node.values, left_idx, prev.values, prev.right_idx + 1, size);
+            prev.right_idx += size;
+            prev.size += size;
+            deleteNode(node);
+        } else if (node.next != null && (node.next.left_idx) > node.size) {
+            // move all to next node and kill it
+            Node<K, V> next = node.next;
+            int left_idx = node.left_idx;
+            int size = index - left_idx;
+            int next_new_left = next.left_idx - size;
+            next.left_idx = next_new_left;
+            System.arraycopy(node.keys,   left_idx, next.keys,   next_new_left, size);
+            System.arraycopy(node.values, left_idx, next.values, next_new_left, size);
+            next.size += size;
+            deleteNode(node);
+        } else {
+            node.keys[index] = null;
+            node.values[index] = null;
+            node.right_idx--;
+            node.size--;
+            Node<K, V> next = node.next;
+            if (next != null && next.size == 1) {
+                node.size++;
+                node.right_idx++;
+                node.keys[node.right_idx]   = next.keys[next.left_idx];
+                node.values[node.right_idx] = next.values[next.left_idx];
+                deleteNode(next);
+            }
+        }
+        modCount++;
+        size--;
+    }
+
+    void removeMiddleElement(Node<K, V> node, int index) {
+        // this function is called iff index if some middle element;
+        // so node.left_idx < index < node.right_idx
+        // condition above assume that node.size > 1
+        if (node.prev != null && (Node.NODE_SIZE - 1 - node.prev.right_idx) > node.size) {
+            // move all to prev node and kill it
+            Node<K, V> prev = node.prev;
+            int left_idx = node.left_idx;
+            int size = index - left_idx;
+            System.arraycopy(node.keys,   left_idx, prev.keys,   prev.right_idx + 1, size);
+            System.arraycopy(node.values, left_idx, prev.values, prev.right_idx + 1, size);
+            prev.right_idx += size;
+            size = node.right_idx - index;
+            System.arraycopy(node.keys,   index + 1, prev.keys,   prev.right_idx + 1, size);
+            System.arraycopy(node.values, index + 1, prev.values, prev.right_idx + 1, size);
+            prev.right_idx += size;
+            prev.size += (node.size - 1);
+            deleteNode(node);
+        } else if (node.next != null && (node.next.left_idx) > node.size) {
+            // move all to next node and kill it
+            Node<K, V> next = node.next;
+            int left_idx = node.left_idx;
+            int next_new_left = next.left_idx - node.size + 1;
+            next.left_idx = next_new_left;
+            int size = index - left_idx;
+            System.arraycopy(node.keys,   left_idx, next.keys,   next_new_left, size);
+            System.arraycopy(node.values, left_idx, next.values, next_new_left, size);
+            next_new_left += size;
+            size = node.right_idx - index;
+            System.arraycopy(node.keys,   index + 1, next.keys,   next_new_left, size);
+            System.arraycopy(node.values, index + 1, next.values, next_new_left, size);
+            next.size += (node.size - 1);
+            deleteNode(node);
+        } else {
+            int moveFromRight = node.right_idx - index;
+            int left_idx = node.left_idx;
+            int moveFromLeft = index - left_idx ;
+            if (moveFromRight <= moveFromLeft) {
+                System.arraycopy(node.keys,   index + 1, node.keys,   index, moveFromRight);
+                System.arraycopy(node.values, index + 1, node.values, index, moveFromRight);
+                Node<K, V> next = node.next;
+                if (next != null && next.size == 1) {
+                    node.keys  [node.right_idx] = next.keys  [next.left_idx];
+                    node.values[node.right_idx] = next.values[next.left_idx];
+                    deleteNode(next);
+                } else {
+                    node.keys  [node.right_idx] = null;
+                    node.values[node.right_idx] = null;
+                    node.right_idx--;
+                    node.size--;
+                }
             } else {
-                x = x.right;
+                System.arraycopy(node.keys,   left_idx , node.keys,   left_idx  + 1, moveFromLeft);
+                System.arraycopy(node.values, left_idx , node.values, left_idx + 1, moveFromLeft);
+                Node<K, V> prev = node.prev;
+                if (prev != null && prev.size == 1) {
+                    node.keys  [left_idx ] = prev.keys  [prev.left_idx];
+                    node.values[left_idx ] = prev.values[prev.left_idx];
+                    deleteNode(prev);
+                } else {
+                    node.keys  [left_idx ] = null;
+                    node.values[left_idx ] = null;
+                    node.left_idx++;
+                    node.size--;
+                }
             }
         }
-        return last;
+        modCount++;
+        size--;
     }
 
-    Entry<K, V> findBefore(K key) {
-        int result;
-        Comparable<K> object = null;
-        if (comparator == null) {
-            object = toComparable(key);
-        }
-        Entry<K, V> x = root, last = null;
-        while (x != null) {
-            result = object != null ? object.compareTo(x.key) : comparator
-                    .compare(key, x.key);
-            if (result <= 0) {
-                x = x.left;
+    void removeFromIterator(Node<K, V> node, int index) {
+        if (node.size == 1) {
+            // it is safe to delete the whole node here.
+            // iterator already moved to the next node;
+            deleteNode(node);
+        } else {
+            int left_idx = node.left_idx;
+            if (index == left_idx) {
+                Node<K, V> prev = node.prev;
+                if (prev != null && prev.size == 1) {
+                    node.keys  [left_idx] = prev.keys  [prev.left_idx];
+                    node.values[left_idx] = prev.values[prev.left_idx];
+                    deleteNode(prev);
+                } else {
+                    node.keys  [left_idx] = null;
+                    node.values[left_idx] = null;
+                    node.left_idx++;
+                    node.size--;
+                }
+            } else if (index == node.right_idx) {
+                node.keys  [index] = null;
+                node.values[index] = null;
+                node.right_idx--;
+                node.size--;
             } else {
-                last = x;
-                x = x.right;
+                int moveFromRight = node.right_idx - index;
+                int moveFromLeft = index - left_idx;
+                if (moveFromRight <= moveFromLeft) {
+                    System.arraycopy(node.keys,   index + 1, node.keys,   index, moveFromRight );
+                    System.arraycopy(node.values, index + 1, node.values, index, moveFromRight );
+                    node.keys  [node.right_idx] = null;
+                    node.values[node.right_idx] = null;
+                    node.right_idx--;
+                    node.size--;
+                } else {
+                    System.arraycopy(node.keys,   left_idx, node.keys,   left_idx+ 1, moveFromLeft);
+                    System.arraycopy(node.values, left_idx, node.values, left_idx+ 1, moveFromLeft);
+                    node.keys  [left_idx] = null;
+                    node.values[left_idx] = null;
+                    node.left_idx++;
+                    node.size--;
+               }
             }
         }
-        return last;
+        modCount++;
+        size--;
     }
 
-    /**
-     * Returns the first key in this map.
-     * 
-     * @return the first key in this map.
-     * @exception NoSuchElementException
-     *                if this sorted map is empty.
-     * @since Android 1.0
-     */
-    public K firstKey() {
-        if (root != null) {
-            return minimum(root).key;
+    private void deleteNode(Node<K, V> node) {
+        if (node.right == null) {
+            if (node.left != null) {
+                attachToParent(node, node.left);
+           } else {
+                attachNullToParent(node);
+            }
+            fixNextChain(node);
+        } else if(node.left == null) { // node.right != null
+            attachToParent(node, node.right);
+            fixNextChain(node);
+        } else {
+            // Here node.left!=nul && node.right!=null
+            // node.next should replace node in tree
+            // node.next!=null by tree logic.
+            // node.next.left==null by tree logic.
+            // node.next.right may be null or non-null
+            Node<K, V> toMoveUp = node.next;
+            fixNextChain(node);
+            if(toMoveUp.right==null){
+                attachNullToParent(toMoveUp);
+            } else {
+                attachToParent(toMoveUp, toMoveUp.right);
+            }
+            // Here toMoveUp is ready to replace node
+            toMoveUp.left = node.left;
+            if (node.left != null) {
+            	node.left.parent = toMoveUp;
+            }
+            toMoveUp.right = node.right;
+            if (node.right != null) {
+            	node.right.parent = toMoveUp;
+            }
+            attachToParentNoFixup(node,toMoveUp);
+            toMoveUp.color = node.color;
         }
-        throw new NoSuchElementException();
     }
 
-    private void fixup(Entry<K, V> x) {
-        Entry<K, V> w;
+    private void attachToParentNoFixup(Node<K, V> toDelete, Node<K, V> toConnect) {
+        // assert toConnect!=null
+        Node<K,V> parent = toDelete.parent;
+        toConnect.parent = parent;
+        if (parent == null) {
+            root = toConnect;
+        } else if (toDelete == parent.left) {
+            parent.left = toConnect;
+        } else {
+            parent.right = toConnect;
+        }
+    }
+
+    private void attachToParent(Node<K, V> toDelete, Node<K, V> toConnect) {
+        // assert toConnect!=null
+        attachToParentNoFixup(toDelete,toConnect);
+        if (!toDelete.color) {
+            fixup(toConnect);
+        }
+    }
+
+    private void attachNullToParent(Node<K, V> toDelete) {
+        Node<K, V> parent = toDelete.parent;
+        if (parent == null) {
+            root = null;
+        } else {
+            if (toDelete == parent.left) {
+                parent.left = null;
+            } else {
+                parent.right = null;
+            }
+            if (!toDelete.color) {
+                fixup(parent);
+            }
+        }
+    }
+
+    private void fixNextChain(Node<K, V> node) {
+        if (node.prev != null) {
+            node.prev.next = node.next;
+        }
+        if (node.next != null) {
+            node.next.prev = node.prev;
+        }
+    }
+
+    private void fixup(Node<K, V> x) {
+        Node<K, V> w;
         while (x != root && !x.color) {
             if (x == x.parent.left) {
                 w = x.parent.right;
@@ -1004,7 +2196,7 @@
                     }
                 }
                 if ((w.left == null || !w.left.color)
-                        && (w.right == null || !w.right.color)) {
+                    && (w.right == null || !w.right.color)) {
                     w.color = true;
                     x = x.parent;
                 } else {
@@ -1037,7 +2229,7 @@
                     }
                 }
                 if ((w.left == null || !w.left.color)
-                        && (w.right == null || !w.right.color)) {
+                    && (w.right == null || !w.right.color)) {
                     w.color = true;
                     x = x.parent;
                 } else {
@@ -1058,321 +2250,11 @@
         x.color = false;
     }
 
-    /**
-     * Returns the value of the mapping with the specified key.
-     * 
-     * @param key
-     *            the key.
-     * @return the value of the mapping with the specified key.
-     * @throws ClassCastException
-     *             if the key cannot be compared with the keys in this map.
-     * @throws NullPointerException
-     *             if the key is {@code null} and the comparator cannot handle
-     *             {@code null}.
-     * @since Android 1.0
-     */
-    @Override
-    public V get(Object key) {
-        Entry<K, V> node = find(key);
-        if (node != null) {
-            return node.value;
-        }
-        return null;
-    }
-
-    /**
-     * Returns a sorted map over a range of this sorted map with all keys that
-     * are less than the specified {@code endKey}. Changes to the returned
-     * sorted map are reflected in this sorted map and vice versa.
-     * <p>
-     * Note: The returned map will not allow an insertion of a key outside the
-     * specified range.
-     * </p>
-     * 
-     * @param endKey
-     *            the high boundary of the range specified.
-     * @return a sorted map where the keys are less than {@code endKey}.
-     * @throws ClassCastException
-     *             if the specified key cannot be compared with the keys in this
-     *             map.
-     * @throws NullPointerException
-     *             if the specified key is {@code null} and the comparator
-     *             cannot handle {@code null} keys.
-     * @throws IllegalArgumentException
-     *             if this map is itself a sorted map over a range of another
-     *             map and the specified key is outside of its range.
-     * @since Android 1.0
-     */
-    public SortedMap<K, V> headMap(K endKey) {
-        // Check for errors
-        if (comparator == null) {
-            toComparable(endKey).compareTo(endKey);
-        } else {
-            comparator.compare(endKey, endKey);
-        }
-        return new SubMap<K, V>(this, endKey);
-    }
-
-    /**
-     * Returns a set of the keys contained in this map. The set is backed by
-     * this map so changes to one are reflected by the other. The set does not
-     * support adding.
-     * 
-     * @return a set of the keys.
-     * @since Android 1.0
-     */
-    @Override
-    public Set<K> keySet() {
-        if (keySet == null) {
-            keySet = new AbstractSet<K>() {
-                @Override
-                public boolean contains(Object object) {
-                    return containsKey(object);
-                }
-
-                @Override
-                public int size() {
-                    return size;
-                }
-
-                @Override
-                public void clear() {
-                    TreeMap.this.clear();
-                }
-
-                @Override
-                public Iterator<K> iterator() {
-                    return new UnboundedKeyIterator<K,V> (TreeMap.this);
-                }
-            };
-        }
-        return keySet;
-    }
-
-    /**
-     * Returns the last key in this map.
-     * 
-     * @return the last key in this map.
-     * @throws NoSuchElementException
-     *             if this map is empty.
-     * @since Android 1.0
-     */
-    public K lastKey() {
-        if (root != null) {
-            return maximum(root).key;
-        }
-        throw new NoSuchElementException();
-    }
-
-    private void leftRotate(Entry<K, V> x) {
-        Entry<K, V> y = x.right;
-        x.right = y.left;
-        if (y.left != null) {
-            y.left.parent = x;
-        }
-        y.parent = x.parent;
-        if (x.parent == null) {
-            root = y;
-        } else {
-            if (x == x.parent.left) {
-                x.parent.left = y;
-            } else {
-                x.parent.right = y;
-            }
-        }
-        y.left = x;
-        x.parent = y;
-    }
-
-    static <K, V> Entry<K, V> maximum(Entry<K, V> x) {
-        while (x.right != null) {
-            x = x.right;
-        }
-        return x;
-    }
-
-    static <K, V> Entry<K, V> minimum(Entry<K, V> x) {
-        while (x.left != null) {
-            x = x.left;
-        }
-        return x;
-    }
-
-    static <K, V> Entry<K, V> predecessor(Entry<K, V> x) {
-        if (x.left != null) {
-            return maximum(x.left);
-        }
-        Entry<K, V> y = x.parent;
-        while (y != null && x == y.left) {
-            x = y;
-            y = y.parent;
-        }
-        return y;
-    }
-
-    /**
-     * Maps the specified key to the specified value.
-     * 
-     * @param key
-     *            the key.
-     * @param value
-     *            the value.
-     * @return the value of any previous mapping with the specified key or
-     *         {@code null} if there was no mapping.
-     * @throws ClassCastException
-     *             if the specified key cannot be compared with the keys in this
-     *             map.
-     * @throws NullPointerException
-     *             if the specified key is {@code null} and the comparator
-     *             cannot handle {@code null} keys.
-     * @since Android 1.0
-     */
-    @Override
-    public V put(K key, V value) {
-        MapEntry<K, V> entry = rbInsert(key);
-        V result = entry.value;
-        entry.value = value;
-        return result;
-    }
-
-    /**
-     * Copies all the mappings in the given map to this map. These mappings will
-     * replace all mappings that this map had for any of the keys currently in
-     * the given map.
-     * 
-     * @param map
-     *            the map to copy mappings from.
-     * @throws ClassCastException
-     *             if a key in the specified map cannot be compared with the
-     *             keys in this map.
-     * @throws NullPointerException
-     *             if a key in the specified map is {@code null} and the
-     *             comparator cannot handle {@code null} keys.
-     * @since Android 1.0
-     */
-    @Override
-    public void putAll(Map<? extends K, ? extends V> map) {
-        super.putAll(map);
-    }
-
-    void rbDelete(Entry<K, V> z) {
-        Entry<K, V> y = z.left == null || z.right == null ? z : successor(z);
-        Entry<K, V> x = y.left != null ? y.left : y.right;
-        if (x != null) {
-            x.parent = y.parent;
-        }
-        if (y.parent == null) {
-            root = x;
-        } else if (y == y.parent.left) {
-            y.parent.left = x;
-        } else {
-            y.parent.right = x;
-        }
-        modCount++;
-        if (y != z) {
-            z.key = y.key;
-            z.value = y.value;
-        }
-        if (!y.color && root != null) {
-            if (x == null) {
-                fixup(y.parent);
-            } else {
-                fixup(x);
-            }
-        }
-        size--;
-    }
-
-    private Entry<K, V> rbInsert(K object) {
-        int result = 0;
-        Entry<K, V> y = null;
-        if (size != 0) {
-            Comparable<K> key = null;
-            if (comparator == null) {
-                key = toComparable(object);
-            }
-            Entry<K, V> x = root;
-            while (x != null) {
-                y = x;
-                result = key != null ? key.compareTo(x.key) : comparator
-                        .compare(object, x.key);
-                if (result == 0) {
-                    return x;
-                }
-                x = result < 0 ? x.left : x.right;
-            }
-        }
-
-        size++;
-        modCount++;
-        Entry<K, V> z = new Entry<K, V>(object);
-        if (y == null) {
-            return root = z;
-        }
-        z.parent = y;
-        if (result < 0) {
-            y.left = z;
-        } else {
-            y.right = z;
-        }
-        balance(z);
-        return z;
-    }
-
-    /**
-     * Removes the mapping with the specified key from this map.
-     * 
-     * @param key
-     *            the key of the mapping to remove.
-     * @return the value of the removed mapping or {@code null} if no mapping
-     *         for the specified key was found.
-     * @throws ClassCastException
-     *             if the specified key cannot be compared with the keys in this
-     *             map.
-     * @throws NullPointerException
-     *             if the specified key is {@code null} and the comparator
-     *             cannot handle {@code null} keys.
-     * @since Android 1.0
-     */
-    @Override
-    public V remove(Object key) {
-        if (size == 0) {
-            return null;
-        }
-        Entry<K, V> node = find(key);
-        if (node == null) {
-            return null;
-        }
-        V result = node.value;
-        rbDelete(node);
-        return result;
-    }
-
-    private void rightRotate(Entry<K, V> x) {
-        Entry<K, V> y = x.left;
-        x.left = y.right;
-        if (y.right != null) {
-            y.right.parent = x;
-        }
-        y.parent = x.parent;
-        if (x.parent == null) {
-            root = y;
-        } else {
-            if (x == x.parent.right) {
-                x.parent.right = y;
-            } else {
-                x.parent.left = y;
-            }
-        }
-        y.right = x;
-        x.parent = y;
-    }
 
     /**
      * Returns the number of mappings in this map.
-     * 
+     *
      * @return the number of mappings in this map.
-     * @since Android 1.0
      */
     @Override
     public int size() {
@@ -1387,8 +2269,7 @@
      * <p>
      * Note: The returned map will not allow an insertion of a key outside the
      * specified range.
-     * </p>
-     * 
+     *
      * @param startKey
      *            the low boundary of the range (inclusive).
      * @param endKey
@@ -1404,7 +2285,6 @@
      *             if the start key is greater than the end key, or if this map
      *             is itself a sorted map over a range of another sorted map and
      *             the specified range is outside of its range.
-     * @since Android 1.0
      */
     public SortedMap<K, V> subMap(K startKey, K endKey) {
         if (comparator == null) {
@@ -1419,18 +2299,6 @@
         throw new IllegalArgumentException();
     }
 
-    static <K, V> Entry<K, V> successor(Entry<K, V> x) {
-        if (x.right != null) {
-            return minimum(x.right);
-        }
-        Entry<K, V> y = x.parent;
-        while (y != null && x == y.right) {
-            x = y;
-            y = y.parent;
-        }
-        return y;
-    }
-
     /**
      * Returns a sorted map over a range of this sorted map with all keys that
      * are greater than or equal to the specified {@code startKey}. Changes to
@@ -1438,8 +2306,7 @@
      * <p>
      * Note: The returned map will not allow an insertion of a key outside the
      * specified range.
-     * </p>
-     * 
+     *
      * @param startKey
      *            the low boundary of the range specified.
      * @return a sorted map where the keys are greater or equal to
@@ -1453,7 +2320,6 @@
      * @throws IllegalArgumentException
      *             if this map itself a sorted map over a range of another map
      *             and the specified key is outside of its range.
-     * @since Android 1.0
      */
     public SortedMap<K, V> tailMap(K startKey) {
         // Check for errors
@@ -1476,16 +2342,13 @@
      * "wrapper object" over the iterator of map's entrySet(). The {@code size}
      * method wraps the map's size method and the {@code contains} method wraps
      * the map's containsValue method.
-     * </p>
      * <p>
      * The collection is created when this method is called for the first time
      * and returned in response to all subsequent calls. This method may return
      * different collections when multiple concurrent calls occur, since no
      * synchronization is performed.
-     * </p>
-     * 
+     *
      * @return a collection of the values contained in this map.
-     * @since Android 1.0
      */
     @Override
     public Collection<V> values() {
@@ -1508,7 +2371,7 @@
 
                 @Override
                 public Iterator<V> iterator() {
-                    return new UnboundedValueIterator<K,V> (TreeMap.this);
+                    return new UnboundedValueIterator<K, V>(TreeMap.this);
                 }
             };
         }
@@ -1519,32 +2382,26 @@
         stream.defaultWriteObject();
         stream.writeInt(size);
         if (size > 0) {
-            Entry<K, V> node = minimum(root);
+            Node<K, V> node = minimum(root);
             while (node != null) {
-                stream.writeObject(node.key);
-                stream.writeObject(node.value);
-                node = successor(node);
+                int to = node.right_idx;
+                for (int i = node.left_idx; i <= to; i++) {
+                    stream.writeObject(node.keys[i]);
+                    stream.writeObject(node.values[i]);
+                }
+                node = node.next;
             }
         }
     }
 
     @SuppressWarnings("unchecked")
     private void readObject(ObjectInputStream stream) throws IOException,
-            ClassNotFoundException {
+                                                          ClassNotFoundException {
         stream.defaultReadObject();
-        size = stream.readInt();
-        Entry<K, V> last = null;
-        for (int i = size; --i >= 0;) {
-            Entry<K, V> node = new Entry<K, V>((K)stream.readObject());
-            node.value = (V)stream.readObject();
-            if (last == null) {
-                root = node;
-            } else {
-                node.parent = last;
-                last.right = node;
-                balance(node);
-            }
-            last = node;
+        int size = stream.readInt();
+        Node<K, V> lastNode = null;
+        for (int i = 0; i < size; i++) {
+            lastNode = addToLast(lastNode, (K) stream.readObject(), (V) stream.readObject());
         }
     }
 }
diff --git a/libcore/luni/src/main/java/java/util/TreeSet.java b/libcore/luni/src/main/java/java/util/TreeSet.java
index bfd572f..375b9c8 100644
--- a/libcore/luni/src/main/java/java/util/TreeSet.java
+++ b/libcore/luni/src/main/java/java/util/TreeSet.java
@@ -17,7 +17,6 @@
 
 package java.util;
 
-
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
@@ -28,25 +27,23 @@
  * and removing) are supported. The elements can be any objects which are
  * comparable to each other either using their natural order or a specified
  * Comparator.
- * 
- * @since Android 1.0
+ *
+ * @since 1.2
  */
-public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>, Cloneable,
-        Serializable {
-    
+public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>,
+        Cloneable, Serializable {
+
     private static final long serialVersionUID = -2479143000061671589L;
 
     private transient SortedMap<E, E> backingMap;
 
-    private TreeSet(SortedMap<E,E> map) {
+    private TreeSet(SortedMap<E, E> map) {
         this.backingMap = map;
     }
 
     /**
      * Constructs a new empty instance of {@code TreeSet} which uses natural
      * ordering.
-     * 
-     * @since Android 1.0
      */
     public TreeSet() {
         backingMap = new TreeMap<E, E>();
@@ -55,14 +52,13 @@
     /**
      * Constructs a new instance of {@code TreeSet} which uses natural ordering
      * and containing the unique elements in the specified collection.
-     * 
+     *
      * @param collection
      *            the collection of elements to add.
      * @throws ClassCastException
      *                when an element in the collection does not implement the
      *                Comparable interface, or the elements in the collection
      *                cannot be compared.
-     * @since Android 1.0
      */
     public TreeSet(Collection<? extends E> collection) {
         this();
@@ -72,10 +68,9 @@
     /**
      * Constructs a new empty instance of {@code TreeSet} which uses the
      * specified comparator.
-     * 
+     *
      * @param comparator
      *            the comparator to use.
-     * @since Android 1.0
      */
     public TreeSet(Comparator<? super E> comparator) {
         backingMap = new TreeMap<E, E>(comparator);
@@ -84,10 +79,9 @@
     /**
      * Constructs a new instance of {@code TreeSet} containing the elements of
      * the specified SortedSet and using the same Comparator.
-     * 
+     *
      * @param set
      *            the SortedSet of elements to add.
-     * @since Android 1.0
      */
     public TreeSet(SortedSet<E> set) {
         this(set.comparator());
@@ -99,7 +93,7 @@
 
     /**
      * Adds the specified object to this {@code TreeSet}.
-     * 
+     *
      * @param object
      *            the object to add.
      * @return {@code true} when this {@code TreeSet} did not already contain
@@ -110,7 +104,6 @@
      * @throws NullPointerException
      *             when the object is null and the comparator cannot handle
      *             null.
-     * @since Android 1.0
      */
     @Override
     public boolean add(E object) {
@@ -119,7 +112,7 @@
 
     /**
      * Adds the objects in the specified collection to this {@code TreeSet}.
-     * 
+     *
      * @param collection
      *            the collection of objects to add.
      * @return {@code true} if this {@code TreeSet} was modified, {@code false}
@@ -130,7 +123,6 @@
      * @throws NullPointerException
      *             when an object in the collection is null and the comparator
      *             cannot handle null.
-     * @since Android 1.0
      */
     @Override
     public boolean addAll(Collection<? extends E> collection) {
@@ -139,10 +131,9 @@
 
     /**
      * Removes all elements from this {@code TreeSet}, leaving it empty.
-     * 
+     *
      * @see #isEmpty
      * @see #size
-     * @since Android 1.0
      */
     @Override
     public void clear() {
@@ -152,10 +143,9 @@
     /**
      * Returns a new {@code TreeSet} with the same elements, size and comparator
      * as this {@code TreeSet}.
-     * 
+     *
      * @return a shallow copy of this {@code TreeSet}.
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     @Override
@@ -163,7 +153,8 @@
         try {
             TreeSet<E> clone = (TreeSet<E>) super.clone();
             if (backingMap instanceof TreeMap) {
-                clone.backingMap = (SortedMap<E, E>) ((TreeMap<E, E>) backingMap).clone();
+                clone.backingMap = (SortedMap<E, E>) ((TreeMap<E, E>) backingMap)
+                        .clone();
             } else {
                 clone.backingMap = new TreeMap<E, E>(backingMap);
             }
@@ -175,9 +166,8 @@
 
     /**
      * Returns the comparator used to compare elements in this {@code TreeSet}.
-     * 
+     *
      * @return a Comparator or null if the natural ordering is used
-     * @since Android 1.0
      */
     public Comparator<? super E> comparator() {
         return backingMap.comparator();
@@ -185,7 +175,7 @@
 
     /**
      * Searches this {@code TreeSet} for the specified object.
-     * 
+     *
      * @param object
      *            the object to search for.
      * @return {@code true} if {@code object} is an element of this
@@ -196,7 +186,6 @@
      * @throws NullPointerException
      *             when the object is null and the comparator cannot handle
      *             null.
-     * @since Android 1.0
      */
     @Override
     public boolean contains(Object object) {
@@ -205,11 +194,10 @@
 
     /**
      * Returns the first element in this {@code TreeSet}.
-     * 
+     *
      * @return the first element.
      * @throws NoSuchElementException
      *             when this {@code TreeSet} is empty.
-     * @since Android 1.0
      */
     public E first() {
         return backingMap.firstKey();
@@ -220,7 +208,7 @@
      * which contains elements which are all less than the end element. The
      * returned SortedSet is backed by this {@code TreeSet} so changes to one
      * are reflected by the other.
-     * 
+     *
      * @param end
      *            the end element.
      * @return a subset where the elements are less than {@code end}
@@ -230,7 +218,6 @@
      * @throws NullPointerException
      *             when the end object is null and the comparator cannot handle
      *             null.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public SortedSet<E> headSet(E end) {
@@ -246,10 +233,9 @@
 
     /**
      * Returns true if this {@code TreeSet} has no element, otherwise false.
-     * 
+     *
      * @return true if this {@code TreeSet} has no element.
      * @see #size
-     * @since Android 1.0
      */
     @Override
     public boolean isEmpty() {
@@ -258,10 +244,9 @@
 
     /**
      * Returns an Iterator on the elements of this {@code TreeSet}.
-     * 
+     *
      * @return an Iterator on the elements of this {@code TreeSet}.
      * @see Iterator
-     * @since Android 1.0
      */
     @Override
     public Iterator<E> iterator() {
@@ -271,11 +256,10 @@
     /**
      * Returns the last element in this {@code TreeSet}. The last element is
      * the highest element.
-     * 
+     *
      * @return the last element.
      * @throws NoSuchElementException
      *             when this {@code TreeSet} is empty.
-     * @since Android 1.0
      */
     public E last() {
         return backingMap.lastKey();
@@ -283,7 +267,7 @@
 
     /**
      * Removes an occurrence of the specified object from this {@code TreeSet}.
-     * 
+     *
      * @param object
      *            the object to remove.
      * @return {@code true} if this {@code TreeSet} was modified, {@code false}
@@ -294,7 +278,6 @@
      * @throws NullPointerException
      *             when the object is null and the comparator cannot handle
      *             null.
-     * @since Android 1.0
      */
     @Override
     public boolean remove(Object object) {
@@ -303,9 +286,8 @@
 
     /**
      * Returns the number of elements in this {@code TreeSet}.
-     * 
+     *
      * @return the number of elements in this {@code TreeSet}.
-     * @since Android 1.0
      */
     @Override
     public int size() {
@@ -317,7 +299,7 @@
      * which contains elements greater or equal to the start element but less
      * than the end element. The returned SortedSet is backed by this
      * {@code TreeSet} so changes to one are reflected by the other.
-     * 
+     *
      * @param start
      *            the start element.
      * @param end
@@ -330,7 +312,6 @@
      * @throws NullPointerException
      *             when the start or end object is null and the comparator
      *             cannot handle null.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public SortedSet<E> subSet(E start, E end) {
@@ -352,7 +333,7 @@
      * which contains elements greater or equal to the start element. The
      * returned SortedSet is backed by this {@code TreeSet} so changes to one
      * are reflected by the other.
-     * 
+     *
      * @param start
      *            the start element.
      * @return a subset where the elements are greater or equal to {@code start}
@@ -362,7 +343,6 @@
      * @throws NullPointerException
      *             when the start object is null and the comparator cannot
      *             handle null.
-     * @since Android 1.0
      */
     @SuppressWarnings("unchecked")
     public SortedSet<E> tailSet(E start) {
@@ -391,23 +371,16 @@
 
     @SuppressWarnings("unchecked")
     private void readObject(ObjectInputStream stream) throws IOException,
-    ClassNotFoundException {
+            ClassNotFoundException {
         stream.defaultReadObject();
-        TreeMap<E, E> map = new TreeMap<E, E>((Comparator<? super E>) stream.readObject());
+        TreeMap<E, E> map = new TreeMap<E, E>((Comparator<? super E>) stream
+                .readObject());
         int size = stream.readInt();
         if (size > 0) {
-            E key = (E)stream.readObject();
-            TreeMap.Entry<E,E> last = new TreeMap.Entry<E,E>(key,key);
-            map.root = last;
-            map.size = 1;
-            for (int i=1; i<size; i++) {
-                key = (E)stream.readObject();
-                TreeMap.Entry<E,E> x = new TreeMap.Entry<E,E>(key,key);
-                x.parent = last;
-                last.right = x;
-                map.size++;
-                map.balance(x);
-                last = x;
+            TreeMap.Node<E,E> lastNode = null;
+            for(int i=0; i<size; i++) {
+                E elem = (E)stream.readObject();
+                lastNode = map.addToLast(lastNode,elem,elem);
             }
         }
         backingMap = map;
diff --git a/libcore/luni/src/main/java/java/util/UUID.java b/libcore/luni/src/main/java/java/util/UUID.java
index a5ab702..081e900 100644
--- a/libcore/luni/src/main/java/java/util/UUID.java
+++ b/libcore/luni/src/main/java/java/util/UUID.java
@@ -27,19 +27,16 @@
 import org.apache.harmony.luni.util.Msg;
 
 /**
- * <p>
  * UUID is an immutable representation of a 128-bit universally unique
  * identifier (UUID).
- * </p>
  * <p>
  * There are multiple, variant layouts of UUIDs, but this class is based upon
  * variant 2 of <a href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>, the
  * Leach-Salz variant. This class can be used to model alternate variants, but
  * most of the methods will be unsupported in those cases; see each method for
  * details.
- * </p>
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public final class UUID implements Serializable, Comparable<UUID> {
 
@@ -60,13 +57,11 @@
     /**
      * <p>
      * Constructs an instance with the specified bits.
-     * </p>
-     * 
+     *
      * @param mostSigBits
      *            The 64 most significant bits of the UUID.
      * @param leastSigBits
      *            The 64 least significant bits of the UUID.
-     * @since Android 1.0
      */
     public UUID(long mostSigBits, long leastSigBits) {
         super();
@@ -79,7 +74,6 @@
      * <p>
      * Sets up the transient fields of this instance based on the current values
      * of the {@code mostSigBits} and {@code leastSigBits} fields.
-     * </p>
      */
     private void init() {
         // setup hash field
@@ -123,10 +117,8 @@
      * <p>
      * Generates a variant 2, version 4 (randomly generated number) UUID as per
      * <a href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>.
-     * </p>
-     * 
+     *
      * @return an UUID instance.
-     * @since Android 1.0
      */
     public static UUID randomUUID() {
         byte[] data;
@@ -135,9 +127,8 @@
             if (rng == null) {
                 rng = new SecureRandom();
             }
-            rng.nextBytes(data = new byte[16]);
         }
-
+        rng.nextBytes(data = new byte[16]);
         long msb = (data[0] & 0xFFL) << 56;
         msb |= (data[1] & 0xFFL) << 48;
         msb |= (data[2] & 0xFFL) << 40;
@@ -164,12 +155,10 @@
      * <p>
      * Generates a variant 2, version 3 (name-based, MD5-hashed) UUID as per <a
      * href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>.
-     * </p>
-     * 
+     *
      * @param name
      *            the name used as byte array to create an UUID.
      * @return an UUID instance.
-     * @since Android 1.0
      */
     public static UUID nameUUIDFromBytes(byte[] name) {
         if (name == null) {
@@ -209,57 +198,57 @@
     /**
      * <p>
      * Parses a UUID string with the format defined by {@link #toString()}.
-     * </p>
-     * 
+     *
      * @param uuid
      *            the UUID string to parse.
      * @return an UUID instance.
+     * @throws NullPointerException
+     *             if {@code uuid} is {@code null}.
      * @throws IllegalArgumentException
      *             if {@code uuid} is not formatted correctly.
-     * @since Android 1.0
      */
     public static UUID fromString(String uuid) {
         if (uuid == null) {
             throw new NullPointerException();
         }
-        
+
         int[] position = new int[5];
         int lastPosition = 1;
         int startPosition = 0;
-        
+
         int i = 0;
-        for (; i < position.length  && lastPosition > 0; i++) {
+        for (; i < position.length && lastPosition > 0; i++) {
             position[i] = uuid.indexOf("-", startPosition); //$NON-NLS-1$
             lastPosition = position[i];
             startPosition = position[i] + 1;
         }
 
         // should have and only can have four "-" in UUID
-        if(i != position.length || lastPosition != -1)
-        {
+        if (i != position.length || lastPosition != -1) {
             throw new IllegalArgumentException(Msg.getString("KA014") + uuid); //$NON-NLS-1$
         }
 
         long m1 = Long.parseLong(uuid.substring(0, position[0]), 16);
-        long m2 = Long.parseLong(uuid.substring(position[0]+ 1, position[1]), 16);
-        long m3 = Long.parseLong(uuid.substring(position[1] + 1, position[2]), 16);
+        long m2 = Long.parseLong(uuid.substring(position[0] + 1, position[1]),
+                16);
+        long m3 = Long.parseLong(uuid.substring(position[1] + 1, position[2]),
+                16);
 
-        long lsb1 = Long.parseLong(uuid.substring(position[2] + 1, position[3]), 16);
-        long lsb2 = Long.parseLong(uuid.substring(position[3]+ 1), 16);
+        long lsb1 = Long.parseLong(
+                uuid.substring(position[2] + 1, position[3]), 16);
+        long lsb2 = Long.parseLong(uuid.substring(position[3] + 1), 16);
 
         long msb = (m1 << 32) | (m2 << 16) | m3;
         long lsb = (lsb1 << 48) | lsb2;
-        
+
         return new UUID(msb, lsb);
     }
 
     /**
      * <p>
      * The 64 least significant bits of the UUID.
-     * </p>
-     * 
+     *
      * @return the 64 least significant bits.
-     * @since Android 1.0
      */
     public long getLeastSignificantBits() {
         return leastSigBits;
@@ -268,10 +257,8 @@
     /**
      * <p>
      * The 64 most significant bits of the UUID.
-     * </p>
-     * 
+     *
      * @return the 64 most significant bits.
-     * @since Android 1.0
      */
     public long getMostSignificantBits() {
         return mostSigBits;
@@ -282,7 +269,6 @@
      * The version of the variant 2 UUID as per <a
      * href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>. If the variant
      * is not 2, then the version will be 0.
-     * </p>
      * <ul>
      * <li>1 - Time-based UUID</li>
      * <li>2 - DCE Security UUID</li>
@@ -290,9 +276,8 @@
      * <li>4 - Randomly generated UUID ({@link #randomUUID()})</li>
      * <li>5 - Name-based with SHA-1 hashing UUID</li>
      * </ul>
-     * 
+     *
      * @return an {@code int} value.
-     * @since Android 1.0
      */
     public int version() {
         return version;
@@ -302,16 +287,14 @@
      * <p>
      * The variant of the UUID as per <a
      * href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>.
-     * </p>
      * <ul>
      * <li>0 - Reserved for NCS compatibility</li>
      * <li>2 - RFC 4122/Leach-Salz</li>
      * <li>6 - Reserved for Microsoft Corporation compatibility</li>
      * <li>7 - Reserved for future use</li>
      * </ul>
-     * 
+     *
      * @return an {@code int} value.
-     * @since Android 1.0
      */
     public int variant() {
         return variant;
@@ -321,12 +304,10 @@
      * <p>
      * The timestamp value of the version 1, variant 2 UUID as per <a
      * href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>.
-     * </p>
-     * 
+     *
      * @return a {@code long} value.
      * @throws UnsupportedOperationException
      *             if {@link #version()} is not 1.
-     * @since Android 1.0
      */
     public long timestamp() {
         if (version != 1) {
@@ -339,12 +320,10 @@
      * <p>
      * The clock sequence value of the version 1, variant 2 UUID as per <a
      * href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>.
-     * </p>
-     * 
+     *
      * @return a {@code long} value.
      * @throws UnsupportedOperationException
      *             if {@link #version()} is not 1.
-     * @since Android 1.0
      */
     public int clockSequence() {
         if (version != 1) {
@@ -357,12 +336,10 @@
      * <p>
      * The node value of the version 1, variant 2 UUID as per <a
      * href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>.
-     * </p>
-     * 
+     *
      * @return a {@code long} value.
      * @throws UnsupportedOperationException
      *             if {@link #version()} is not 1.
-     * @since Android 1.0
      */
     public long node() {
         if (version != 1) {
@@ -376,13 +353,11 @@
      * Compares this UUID to the specified UUID. The natural ordering of UUIDs
      * is based upon the value of the bits from most significant to least
      * significant.
-     * </p>
-     * 
+     *
      * @param uuid
      *            the UUID to compare to.
      * @return a value of -1, 0 or 1 if this UUID is less than, equal to or
      *         greater than {@code uuid}.
-     * @since Android 1.0
      */
     public int compareTo(UUID uuid) {
         if (uuid == this) {
@@ -409,13 +384,11 @@
      * Compares this UUID to another object for equality. If {@code object}
      * is not {@code null}, is a UUID instance, and all bits are equal, then
      * {@code true} is returned.
-     * </p>
-     * 
+     *
      * @param object
      *            the {@code Object} to compare to.
      * @return {@code true} if this UUID is equal to {@code object}
      *         or {@code false} if not.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -441,10 +414,8 @@
      * <p>
      * Returns a hash value for this UUID that is consistent with the
      * {@link #equals(Object)} method.
-     * </p>
-     * 
+     *
      * @return an {@code int} value.
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -455,8 +426,7 @@
      * <p>
      * Returns a string representation of this UUID in the following format, as
      * per <a href="http://www.ietf.org/rfc/rfc4122.txt">RFC 4122</a>.
-     * </p>
-     * 
+     *
      * <pre>
      *            UUID                   = time-low &quot;-&quot; time-mid &quot;-&quot;
      *                                     time-high-and-version &quot;-&quot;
@@ -474,9 +444,8 @@
      *                &quot;a&quot; / &quot;b&quot; / &quot;c&quot; / &quot;d&quot; / &quot;e&quot; / &quot;f&quot; /
      *                &quot;A&quot; / &quot;B&quot; / &quot;C&quot; / &quot;D&quot; / &quot;E&quot; / &quot;F&quot;
      * </pre>
-     * 
+     *
      * @return a String instance.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -507,8 +476,7 @@
     /**
      * <p>
      * Resets the transient fields to match the behavior of the constructor.
-     * </p>
-     * 
+     *
      * @param in
      *            the {@code InputStream} to read from.
      * @throws IOException
diff --git a/libcore/luni/src/main/java/java/util/UnknownFormatConversionException.java b/libcore/luni/src/main/java/java/util/UnknownFormatConversionException.java
index 19b9b6d..8bb9441 100644
--- a/libcore/luni/src/main/java/java/util/UnknownFormatConversionException.java
+++ b/libcore/luni/src/main/java/java/util/UnknownFormatConversionException.java
@@ -22,7 +22,6 @@
  * conversion is unknown.
  * 
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class UnknownFormatConversionException extends IllegalFormatException {
     private static final long serialVersionUID = 19060418L;
diff --git a/libcore/luni/src/main/java/java/util/UnknownFormatFlagsException.java b/libcore/luni/src/main/java/java/util/UnknownFormatFlagsException.java
index 837328a..2a1b075 100644
--- a/libcore/luni/src/main/java/java/util/UnknownFormatFlagsException.java
+++ b/libcore/luni/src/main/java/java/util/UnknownFormatFlagsException.java
@@ -23,7 +23,6 @@
  * an unknown flag.
  * 
  * @see java.lang.RuntimeException
- * @since Android 1.0
  */
 public class UnknownFormatFlagsException extends IllegalFormatException {
 
diff --git a/libcore/luni/src/main/java/java/util/Vector.java b/libcore/luni/src/main/java/java/util/Vector.java
index 7a5c775..6a4060a 100644
--- a/libcore/luni/src/main/java/java/util/Vector.java
+++ b/libcore/luni/src/main/java/java/util/Vector.java
@@ -17,7 +17,6 @@
 
 package java.util;
 
-
 import java.io.IOException;
 import java.io.ObjectOutputStream;
 import java.io.Serializable;
@@ -36,26 +35,21 @@
  * The capacity of a vector may be specified when the vector is created. If the
  * capacity of the vector is exceeded, the capacity is increased (doubled by
  * default).
- * 
+ *
  * @see java.lang.StringBuffer
- * @since Android 1.0
  */
-public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess,
-        Cloneable, Serializable {
-    
+public class Vector<E> extends AbstractList<E> implements List<E>,
+        RandomAccess, Cloneable, Serializable {
+
     private static final long serialVersionUID = -2767605614048989439L;
 
     /**
      * The number of elements or the size of the vector.
-     * 
-     * @since Android 1.0
      */
     protected int elementCount;
 
     /**
      * The elements of the vector.
-     * 
-     * @since Android 1.0
      */
     protected Object[] elementData;
 
@@ -63,8 +57,6 @@
      * How many elements should be added to the vector when it is detected that
      * it needs to grow to accommodate extra entries. If this value is zero or
      * negative the size will be doubled if an increase is needed.
-     * 
-     * @since Android 1.0
      */
     protected int capacityIncrement;
 
@@ -72,8 +64,6 @@
 
     /**
      * Constructs a new vector using the default capacity.
-     * 
-     * @since Android 1.0
      */
     public Vector() {
         this(DEFAULT_SIZE, 0);
@@ -81,12 +71,11 @@
 
     /**
      * Constructs a new vector using the specified capacity.
-     * 
+     *
      * @param capacity
      *            the initial capacity of the new vector.
      * @throws IllegalArgumentException
      *             if {@code capacity} is negative.
-     * @since Android 1.0
      */
     public Vector(int capacity) {
         this(capacity, 0);
@@ -95,22 +84,20 @@
     /**
      * Constructs a new vector using the specified capacity and capacity
      * increment.
-     * 
+     *
      * @param capacity
      *            the initial capacity of the new vector.
      * @param capacityIncrement
      *            the amount to increase the capacity when this vector is full.
      * @throws IllegalArgumentException
      *             if {@code capacity} is negative.
-     * @since Android 1.0
      */
     public Vector(int capacity, int capacityIncrement) {
-        elementCount = 0;
-        try {
-            elementData = newElementArray(capacity);
-        } catch (NegativeArraySizeException e) {
+        if (capacity < 0) {
             throw new IllegalArgumentException();
         }
+        elementData = newElementArray(capacity);
+        elementCount = 0;
         this.capacityIncrement = capacityIncrement;
     }
 
@@ -118,10 +105,9 @@
      * Constructs a new instance of {@code Vector} containing the elements in
      * {@code collection}. The order of the elements in the new {@code Vector}
      * is dependent on the iteration order of the seed collection.
-     * 
+     *
      * @param collection
      *            the collection of elements to add.
-     * @since Android 1.0
      */
     public Vector(Collection<? extends E> collection) {
         this(collection.size(), 0);
@@ -130,10 +116,10 @@
             elementData[elementCount++] = it.next();
         }
     }
-    
+
     @SuppressWarnings("unchecked")
     private E[] newElementArray(int size) {
-        return (E[])new Object[size];
+        return (E[]) new Object[size];
     }
 
     /**
@@ -141,16 +127,15 @@
      * object is inserted before any element with the same or a higher index
      * increasing their index by 1. If the location is equal to the size of this
      * vector, the object is added at the end.
-     * 
+     *
      * @param location
      *            the index at which to insert the element.
      * @param object
      *            the object to insert in this vector.
-     * @exception ArrayIndexOutOfBoundsException
-     *                when {@code location < 0 || location > size()}.
+     * @throws ArrayIndexOutOfBoundsException
+     *                if {@code location < 0 || location > size()}.
      * @see #addElement
      * @see #size
-     * @since Android 1.0
      */
     @Override
     public void add(int location, E object) {
@@ -159,15 +144,18 @@
 
     /**
      * Adds the specified object at the end of this vector.
-     * 
+     *
      * @param object
      *            the object to add to the vector.
      * @return {@code true}
-     * @since Android 1.0
      */
     @Override
-    public boolean add(E object) {
-        addElement(object);
+    public synchronized boolean add(E object) {
+        if (elementCount == elementData.length) {
+            growByOne();
+        }
+        elementData[elementCount++] = object;
+        modCount++;
         return true;
     }
 
@@ -177,18 +165,18 @@
      * returned from the Collection iterator. The elements with an index equal
      * or higher than {@code location} have their index increased by the size of
      * the added collection.
-     * 
+     *
      * @param location
      *            the location to insert the objects.
      * @param collection
      *            the collection of objects.
      * @return {@code true} if this vector is modified, {@code false} otherwise.
-     * @exception ArrayIndexOutOfBoundsException
-     *                when {@code location < 0} or {@code location > size()}.
-     * @since Android 1.0
+     * @throws ArrayIndexOutOfBoundsException
+     *                if {@code location < 0} or {@code location > size()}.
      */
     @Override
-    public synchronized boolean addAll(int location, Collection<? extends E> collection) {
+    public synchronized boolean addAll(int location,
+            Collection<? extends E> collection) {
         if (0 <= location && location <= elementCount) {
             int size = collection.size();
             if (size == 0) {
@@ -216,11 +204,10 @@
 
     /**
      * Adds the objects in the specified collection to the end of this vector.
-     * 
+     *
      * @param collection
      *            the collection of objects.
      * @return {@code true} if this vector is modified, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public synchronized boolean addAll(Collection<? extends E> collection) {
@@ -229,10 +216,9 @@
 
     /**
      * Adds the specified object at the end of this vector.
-     * 
+     *
      * @param object
      *            the object to add to the vector.
-     * @since Android 1.0
      */
     public synchronized void addElement(E object) {
         if (elementCount == elementData.length) {
@@ -244,11 +230,10 @@
 
     /**
      * Returns the number of elements this vector can hold without growing.
-     * 
+     *
      * @return the capacity of this vector.
      * @see #ensureCapacity
      * @see #size
-     * @since Android 1.0
      */
     public synchronized int capacity() {
         return elementData.length;
@@ -256,10 +241,9 @@
 
     /**
      * Removes all elements from this vector, leaving it empty.
-     * 
+     *
      * @see #isEmpty
      * @see #size
-     * @since Android 1.0
      */
     @Override
     public void clear() {
@@ -269,10 +253,9 @@
     /**
      * Returns a new vector with the same elements, size, capacity and capacity
      * increment as this vector.
-     * 
+     *
      * @return a shallow copy of this vector.
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
@@ -288,7 +271,7 @@
 
     /**
      * Searches this vector for the specified object.
-     * 
+     *
      * @param object
      *            the object to look for in this vector.
      * @return {@code true} if object is an element of this vector,
@@ -296,7 +279,6 @@
      * @see #indexOf(Object)
      * @see #indexOf(Object, int)
      * @see java.lang.Object#equals
-     * @since Android 1.0
      */
     @Override
     public boolean contains(Object object) {
@@ -305,12 +287,11 @@
 
     /**
      * Searches this vector for all objects in the specified collection.
-     * 
+     *
      * @param collection
      *            the collection of objects.
      * @return {@code true} if all objects in the specified collection are
      *         elements of this vector, {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public synchronized boolean containsAll(Collection<?> collection) {
@@ -320,14 +301,13 @@
     /**
      * Attempts to copy elements contained by this {@code Vector} into the
      * corresponding elements of the supplied {@code Object} array.
-     * 
+     *
      * @param elements
      *            the {@code Object} array into which the elements of this
      *            vector are copied.
      * @throws IndexOutOfBoundsException
      *             if {@code elements} is not big enough.
      * @see #clone
-     * @since Android 1.0
      */
     public synchronized void copyInto(Object[] elements) {
         System.arraycopy(elementData, 0, elements, 0, elementCount);
@@ -335,18 +315,18 @@
 
     /**
      * Returns the element at the specified location in this vector.
-     * 
+     *
      * @param location
      *            the index of the element to return in this vector.
      * @return the element at the specified location.
-     * @exception ArrayIndexOutOfBoundsException
-     *                when {@code location < 0 || location >= size()}.
+     * @throws ArrayIndexOutOfBoundsException
+     *                if {@code location < 0 || location >= size()}.
      * @see #size
-     * @since Android 1.0
      */
+    @SuppressWarnings("unchecked")
     public synchronized E elementAt(int location) {
         if (location < elementCount) {
-            return (E)elementData[location];
+            return (E) elementData[location];
         }
         throw new ArrayIndexOutOfBoundsException(location);
     }
@@ -354,26 +334,24 @@
     /**
      * Returns an enumeration on the elements of this vector. The results of the
      * enumeration may be affected if the contents of this vector is modified.
-     * 
+     *
      * @return an enumeration of the elements of this vector.
      * @see #elementAt
      * @see Enumeration
-     * @since Android 1.0
      */
     public Enumeration<E> elements() {
         return new Enumeration<E>() {
             int pos = 0;
 
             public boolean hasMoreElements() {
-                synchronized (Vector.this) {
-                    return pos < elementCount;
-                }
+                return pos < elementCount;
             }
 
+            @SuppressWarnings("unchecked")
             public E nextElement() {
                 synchronized (Vector.this) {
                     if (pos < elementCount) {
-                        return (E)elementData[pos++];
+                        return (E) elementData[pos++];
                     }
                 }
                 throw new NoSuchElementException();
@@ -384,12 +362,11 @@
     /**
      * Ensures that this vector can hold the specified number of elements
      * without growing.
-     * 
+     *
      * @param minimumCapacity
      *            the minimum number of elements that this vector will hold
      *            before growing.
      * @see #capacity
-     * @since Android 1.0
      */
     public synchronized void ensureCapacity(int minimumCapacity) {
         if (elementData.length < minimumCapacity) {
@@ -404,13 +381,12 @@
      * Compares the specified object to this vector and returns if they are
      * equal. The object must be a List which contains the same objects in the
      * same order.
-     * 
+     *
      * @param object
      *            the object to compare with this object
      * @return {@code true} if the specified object is equal to this vector,
      *         {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public synchronized boolean equals(Object object) {
@@ -418,8 +394,8 @@
             return true;
         }
         if (object instanceof List) {
-            List<?> list = (List) object;
-            if (list.size() != size()) {
+            List<?> list = (List<?>) object;
+            if (list.size() != elementCount) {
                 return false;
             }
 
@@ -438,35 +414,34 @@
 
     /**
      * Returns the first element in this vector.
-     * 
+     *
      * @return the element at the first position.
-     * @exception NoSuchElementException
-     *                when this vector is empty.
+     * @throws NoSuchElementException
+     *                if this vector is empty.
      * @see #elementAt
      * @see #lastElement
      * @see #size
-     * @since Android 1.0
      */
+    @SuppressWarnings("unchecked")
     public synchronized E firstElement() {
         if (elementCount > 0) {
-            return (E)elementData[0];
+            return (E) elementData[0];
         }
         throw new NoSuchElementException();
     }
 
     /**
      * Returns the element at the specified location in this vector.
-     * 
+     *
      * @param location
      *            the index of the element to return in this vector.
      * @return the element at the specified location.
-     * @exception ArrayIndexOutOfBoundsException
-     *                when {@code location < 0 || location >= size()}.
+     * @throws ArrayIndexOutOfBoundsException
+     *                if {@code location < 0 || location >= size()}.
      * @see #size
-     * @since Android 1.0
      */
     @Override
-    public synchronized E get(int location) {
+    public E get(int location) {
         return elementAt(location);
     }
 
@@ -474,7 +449,7 @@
         E[] newData = newElementArray(newCapacity);
         // Assumes elementCount is <= newCapacity
         assert elementCount <= newCapacity;
-        System.arraycopy(elementData, 0, newData, 0, elementCount); 
+        System.arraycopy(elementData, 0, newData, 0, elementCount);
         elementData = newData;
     }
 
@@ -519,10 +494,9 @@
     /**
      * Returns an integer hash code for the receiver. Objects which are equal
      * return the same value for this method.
-     * 
+     *
      * @return the receiver's hash.
      * @see #equals
-     * @since Android 1.0
      */
     @Override
     public synchronized int hashCode() {
@@ -538,7 +512,7 @@
      * Searches in this vector for the index of the specified object. The search
      * for the object starts at the beginning and moves towards the end of this
      * vector.
-     * 
+     *
      * @param object
      *            the object to find in this vector.
      * @return the index in this vector of the specified element, -1 if the
@@ -546,7 +520,6 @@
      * @see #contains
      * @see #lastIndexOf(Object)
      * @see #lastIndexOf(Object, int)
-     * @since Android 1.0
      */
     @Override
     public int indexOf(Object object) {
@@ -557,19 +530,18 @@
      * Searches in this vector for the index of the specified object. The search
      * for the object starts at the specified location and moves towards the end
      * of this vector.
-     * 
+     *
      * @param object
      *            the object to find in this vector.
      * @param location
      *            the index at which to start searching.
      * @return the index in this vector of the specified element, -1 if the
      *         element isn't found.
-     * @exception ArrayIndexOutOfBoundsException
-     *                when {@code location < 0}.
+     * @throws ArrayIndexOutOfBoundsException
+     *                if {@code location < 0}.
      * @see #contains
      * @see #lastIndexOf(Object)
      * @see #lastIndexOf(Object, int)
-     * @since Android 1.0
      */
     public synchronized int indexOf(Object object, int location) {
         if (object != null) {
@@ -594,16 +566,15 @@
      * location. All elements with an index equal or greater than
      * {@code location} have their index increased by 1. If the location is
      * equal to the size of this vector, the object is added at the end.
-     * 
+     *
      * @param object
      *            the object to insert in this vector.
      * @param location
      *            the index at which to insert the element.
-     * @exception ArrayIndexOutOfBoundsException
-     *                when {@code location < 0 || location > size()}.
+     * @throws ArrayIndexOutOfBoundsException
+     *                if {@code location < 0 || location > size()}.
      * @see #addElement
      * @see #size
-     * @since Android 1.0
      */
     public synchronized void insertElementAt(E object, int location) {
         if (0 <= location && location <= elementCount) {
@@ -625,11 +596,10 @@
 
     /**
      * Returns if this vector has no elements, a size of zero.
-     * 
+     *
      * @return {@code true} if this vector has no elements, {@code false}
      *         otherwise.
      * @see #size
-     * @since Android 1.0
      */
     @Override
     public synchronized boolean isEmpty() {
@@ -638,18 +608,18 @@
 
     /**
      * Returns the last element in this vector.
-     * 
+     *
      * @return the element at the last position.
-     * @exception NoSuchElementException
-     *                when this vector is empty.
+     * @throws NoSuchElementException
+     *                if this vector is empty.
      * @see #elementAt
      * @see #firstElement
      * @see #size
-     * @since Android 1.0
      */
+    @SuppressWarnings("unchecked")
     public synchronized E lastElement() {
         try {
-            return (E)elementData[elementCount - 1];
+            return (E) elementData[elementCount - 1];
         } catch (IndexOutOfBoundsException e) {
             throw new NoSuchElementException();
         }
@@ -659,7 +629,7 @@
      * Searches in this vector for the index of the specified object. The search
      * for the object starts at the end and moves towards the start of this
      * vector.
-     * 
+     *
      * @param object
      *            the object to find in this vector.
      * @return the index in this vector of the specified element, -1 if the
@@ -667,7 +637,6 @@
      * @see #contains
      * @see #indexOf(Object)
      * @see #indexOf(Object, int)
-     * @since Android 1.0
      */
     @Override
     public synchronized int lastIndexOf(Object object) {
@@ -678,19 +647,18 @@
      * Searches in this vector for the index of the specified object. The search
      * for the object starts at the specified location and moves towards the
      * start of this vector.
-     * 
+     *
      * @param object
      *            the object to find in this vector.
      * @param location
      *            the index at which to start searching.
      * @return the index in this vector of the specified element, -1 if the
      *         element isn't found.
-     * @exception ArrayIndexOutOfBoundsException
-     *                when {@code location >= size()}.
+     * @throws ArrayIndexOutOfBoundsException
+     *                if {@code location >= size()}.
      * @see #contains
      * @see #indexOf(Object)
      * @see #indexOf(Object, int)
-     * @since Android 1.0
      */
     public synchronized int lastIndexOf(Object object, int location) {
         if (location < elementCount) {
@@ -716,18 +684,18 @@
      * Removes the object at the specified location from this vector. All
      * elements with an index bigger than {@code location} have their index
      * decreased by 1.
-     * 
+     *
      * @param location
      *            the index of the object to remove.
      * @return the removed object.
-     * @exception IndexOutOfBoundsException
-     *                when {@code location < 0 || location >= size()}.
-     * @since Android 1.0
+     * @throws IndexOutOfBoundsException
+     *                if {@code location < 0 || location >= size()}.
      */
+    @SuppressWarnings("unchecked")
     @Override
     public synchronized E remove(int location) {
         if (location < elementCount) {
-            E result = (E)elementData[location];
+            E result = (E) elementData[location];
             elementCount--;
             int size = elementCount - location;
             if (size > 0) {
@@ -746,7 +714,7 @@
      * towards the end, of the specified object from this vector. All elements
      * with an index bigger than the element that gets removed have their index
      * decreased by 1.
-     * 
+     *
      * @param object
      *            the object to remove from this vector.
      * @return {@code true} if the specified object was found, {@code false}
@@ -754,7 +722,6 @@
      * @see #removeAllElements
      * @see #removeElementAt
      * @see #size
-     * @since Android 1.0
      */
     @Override
     public boolean remove(Object object) {
@@ -764,13 +731,12 @@
     /**
      * Removes all occurrences in this vector of each object in the specified
      * Collection.
-     * 
+     *
      * @param collection
      *            the collection of objects to remove.
      * @return {@code true} if this vector is modified, {@code false} otherwise.
      * @see #remove(Object)
      * @see #contains(Object)
-     * @since Android 1.0
      */
     @Override
     public synchronized boolean removeAll(Collection<?> collection) {
@@ -780,13 +746,14 @@
     /**
      * Removes all elements from this vector, leaving the size zero and the
      * capacity unchanged.
-     * 
+     *
      * @see #isEmpty
      * @see #size
-     * @since Android 1.0
      */
     public synchronized void removeAllElements() {
-        Arrays.fill(elementData, 0, elementCount, null);
+        for (int i = 0; i < elementCount; i++) {
+            elementData[i] = null;
+        }
         modCount++;
         elementCount = 0;
     }
@@ -796,7 +763,7 @@
      * towards the end, of the specified object from this vector. All elements
      * with an index bigger than the element that gets removed have their index
      * decreased by 1.
-     * 
+     *
      * @param object
      *            the object to remove from this vector.
      * @return {@code true} if the specified object was found, {@code false}
@@ -804,7 +771,6 @@
      * @see #removeAllElements
      * @see #removeElementAt
      * @see #size
-     * @since Android 1.0
      */
     public synchronized boolean removeElement(Object object) {
         int index;
@@ -819,15 +785,14 @@
      * Removes the element found at index position {@code location} from
      * this {@code Vector}. All elements with an index bigger than
      * {@code location} have their index decreased by 1.
-     * 
+     *
      * @param location
      *            the index of the element to remove.
-     * @exception ArrayIndexOutOfBoundsException
-     *                when {@code location < 0 || location >= size()}.
+     * @throws ArrayIndexOutOfBoundsException
+     *                if {@code location < 0 || location >= size()}.
      * @see #removeElement
      * @see #removeAllElements
      * @see #size
-     * @since Android 1.0
      */
     public synchronized void removeElementAt(int location) {
         if (0 <= location && location < elementCount) {
@@ -848,19 +813,18 @@
      * Removes the objects in the specified range from the start to the, but not
      * including, end index. All elements with an index bigger than or equal to
      * {@code end} have their index decreased by {@code end - start}.
-     * 
+     *
      * @param start
      *            the index at which to start removing.
      * @param end
      *            the index one past the end of the range to remove.
-     * @exception IndexOutOfBoundsException
-     *                when {@code start < 0, start > end} or
+     * @throws IndexOutOfBoundsException
+     *                if {@code start < 0, start > end} or
      *                {@code end > size()}.
-     * @since Android 1.0
      */
     @Override
     protected void removeRange(int start, int end) {
-        if (start >= 0 && start <= end && end <= size()) {
+        if (start >= 0 && start <= end && end <= elementCount) {
             if (start == end) {
                 return;
             }
@@ -883,12 +847,11 @@
     /**
      * Removes all objects from this vector that are not contained in the
      * specified collection.
-     * 
+     *
      * @param collection
      *            the collection of objects to retain.
      * @return {@code true} if this vector is modified, {@code false} otherwise.
      * @see #remove(Object)
-     * @since Android 1.0
      */
     @Override
     public synchronized boolean retainAll(Collection<?> collection) {
@@ -898,21 +861,21 @@
     /**
      * Replaces the element at the specified location in this vector with the
      * specified object.
-     * 
+     *
      * @param location
      *            the index at which to put the specified object.
      * @param object
      *            the object to add to this vector.
      * @return the previous element at the location.
-     * @exception ArrayIndexOutOfBoundsException
-     *                when {@code location < 0 || location >= size()}.
+     * @throws ArrayIndexOutOfBoundsException
+     *                if {@code location < 0 || location >= size()}.
      * @see #size
-     * @since Android 1.0
      */
+    @SuppressWarnings("unchecked")
     @Override
     public synchronized E set(int location, E object) {
         if (location < elementCount) {
-            E result = (E)elementData[location];
+            E result = (E) elementData[location];
             elementData[location] = object;
             return result;
         }
@@ -922,15 +885,14 @@
     /**
      * Replaces the element at the specified location in this vector with the
      * specified object.
-     * 
+     *
      * @param object
      *            the object to add to this vector.
      * @param location
      *            the index at which to put the specified object.
-     * @exception ArrayIndexOutOfBoundsException
-     *                when {@code location < 0 || location >= size()}.
+     * @throws ArrayIndexOutOfBoundsException
+     *                if {@code location < 0 || location >= size()}.
      * @see #size
-     * @since Android 1.0
      */
     public synchronized void setElementAt(E object, int location) {
         if (location < elementCount) {
@@ -945,11 +907,10 @@
      * than length elements in this vector, the elements at end are lost. If
      * there are less than length elements in the vector, the additional
      * elements contain null.
-     * 
+     *
      * @param length
      *            the new size of this vector.
      * @see #size
-     * @since Android 1.0
      */
     public synchronized void setSize(int length) {
         if (length == elementCount) {
@@ -965,11 +926,10 @@
 
     /**
      * Returns the number of elements in this vector.
-     * 
+     *
      * @return the number of elements in this vector.
      * @see #elementCount
      * @see #lastElement
-     * @since Android 1.0
      */
     @Override
     public synchronized int size() {
@@ -980,29 +940,27 @@
      * Returns a List of the specified portion of this vector from the start
      * index to one less than the end index. The returned List is backed by this
      * vector so changes to one are reflected by the other.
-     * 
+     *
      * @param start
      *            the index at which to start the sublist.
      * @param end
      *            the index one past the end of the sublist.
      * @return a List of a portion of this vector.
-     * @exception IndexOutOfBoundsException
-     *                when {@code start < 0} or {@code end > size()}.
-     * @exception IllegalArgumentException
-     *                when {@code start > end}.
-     * @since Android 1.0
+     * @throws IndexOutOfBoundsException
+     *                if {@code start < 0} or {@code end > size()}.
+     * @throws IllegalArgumentException
+     *                if {@code start > end}.
      */
     @Override
     public synchronized List<E> subList(int start, int end) {
-        return new Collections.SynchronizedRandomAccessList<E>(
-                super.subList(start, end), this);
+        return new Collections.SynchronizedRandomAccessList<E>(super.subList(
+                start, end), this);
     }
 
     /**
      * Returns a new array containing all elements contained in this vector.
-     * 
+     *
      * @return an array of the elements from this vector.
-     * @since Android 1.0
      */
     @Override
     public synchronized Object[] toArray() {
@@ -1017,14 +975,13 @@
      * is used, otherwise an array of the same type is created. If the specified
      * array is used and is larger than this vector, the array element following
      * the collection elements is set to null.
-     * 
+     *
      * @param contents
      *            the array to fill.
      * @return an array of the elements from this vector.
-     * @exception ArrayStoreException
-     *                when the type of an element in this vector cannot be
+     * @throws ArrayStoreException
+     *                if the type of an element in this vector cannot be
      *                stored in the type of the specified array.
-     * @since Android 1.0
      */
     @Override
     @SuppressWarnings("unchecked")
@@ -1042,29 +999,28 @@
 
     /**
      * Returns the string representation of this vector.
-     * 
+     *
      * @return the string representation of this vector.
      * @see #elements
-     * @since Android 1.0
      */
     @Override
     public synchronized String toString() {
         if (elementCount == 0) {
-            return "[]";
+            return "[]"; //$NON-NLS-1$
         }
         int length = elementCount - 1;
-        StringBuffer buffer = new StringBuffer(size() * 16);
+        StringBuilder buffer = new StringBuilder(elementCount * 16);
         buffer.append('[');
         for (int i = 0; i < length; i++) {
             if (elementData[i] == this) {
-                buffer.append("(this Collection)");
+                buffer.append("(this Collection)"); //$NON-NLS-1$
             } else {
                 buffer.append(elementData[i]);
             }
-            buffer.append(", ");
+            buffer.append(", "); //$NON-NLS-1$
         }
         if (elementData[length] == this) {
-            buffer.append("(this Collection)");
+            buffer.append("(this Collection)"); //$NON-NLS-1$
         } else {
             buffer.append(elementData[length]);
         }
@@ -1074,11 +1030,10 @@
 
     /**
      * Sets the capacity of this vector to be the same as the size.
-     * 
+     *
      * @see #capacity
      * @see #ensureCapacity
      * @see #size
-     * @since Android 1.0
      */
     public synchronized void trimToSize() {
         if (elementData.length != elementCount) {
diff --git a/libcore/luni/src/main/java/java/util/WeakHashMap.java b/libcore/luni/src/main/java/java/util/WeakHashMap.java
index e0228e2..01e15af 100644
--- a/libcore/luni/src/main/java/java/util/WeakHashMap.java
+++ b/libcore/luni/src/main/java/java/util/WeakHashMap.java
@@ -26,10 +26,10 @@
  * optional operations (adding and removing) are supported. Keys and values can
  * be any objects. Note that the garbage collector acts similar to a second
  * thread on this collection, possibly removing keys.
- * 
+ *
+ * @since 1.2
  * @see HashMap
  * @see WeakReference
- * @since Android 1.0
  */
 public class WeakHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> {
 
@@ -127,7 +127,7 @@
         }
 
         public boolean hasNext() {
-            if (nextEntry != null) {
+            if (nextEntry != null && (nextKey != null || nextEntry.isNull)) {
                 return true;
             }
             while (true) {
@@ -183,8 +183,6 @@
 
     /**
      * Constructs a new empty {@code WeakHashMap} instance.
-     * 
-     * @since Android 1.0
      */
     public WeakHashMap() {
         this(DEFAULT_SIZE);
@@ -193,12 +191,11 @@
     /**
      * Constructs a new {@code WeakHashMap} instance with the specified
      * capacity.
-     * 
+     *
      * @param capacity
      *            the initial capacity of this map.
      * @throws IllegalArgumentException
      *                if the capacity is less than zero.
-     * @since Android 1.0
      */
     public WeakHashMap(int capacity) {
         if (capacity >= 0) {
@@ -215,7 +212,7 @@
     /**
      * Constructs a new {@code WeakHashMap} instance with the specified capacity
      * and load factor.
-     * 
+     *
      * @param capacity
      *            the initial capacity of this map.
      * @param loadFactor
@@ -223,7 +220,6 @@
      * @throws IllegalArgumentException
      *             if the capacity is less than zero or the load factor is less
      *             or equal to zero.
-     * @since Android 1.0
      */
     public WeakHashMap(int capacity, float loadFactor) {
         if (capacity >= 0 && loadFactor > 0) {
@@ -240,10 +236,9 @@
     /**
      * Constructs a new {@code WeakHashMap} instance containing the mappings
      * from the specified map.
-     * 
+     *
      * @param map
      *            the mappings to add.
-     * @since Android 1.0
      */
     public WeakHashMap(Map<? extends K, ? extends V> map) {
         this(map.size() < 6 ? 11 : map.size() * 2);
@@ -252,10 +247,9 @@
 
     /**
      * Removes all mappings from this map, leaving it empty.
-     * 
+     *
      * @see #isEmpty()
      * @see #size()
-     * @since Android 1.0
      */
     @Override
     public void clear() {
@@ -275,12 +269,11 @@
 
     /**
      * Returns whether this map contains the specified key.
-     * 
+     *
      * @param key
      *            the key to search for.
      * @return {@code true} if this map contains the specified key,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean containsKey(Object key) {
@@ -292,9 +285,8 @@
      * an instance of {@link Map.Entry}. As the set is backed by this map,
      * changes in one will be reflected in the other. It does not support adding
      * operations.
-     * 
+     *
      * @return a set of the mappings.
-     * @since Android 1.0
      */
     @Override
     public Set<Map.Entry<K, V>> entrySet() {
@@ -351,9 +343,8 @@
      * Returns a set of the keys contained in this map. The set is backed by
      * this map so changes to one are reflected by the other. The set does not
      * support adding.
-     * 
+     *
      * @return a set of the keys.
-     * @since Android 1.0
      */
     @Override
     public Set<K> keySet() {
@@ -392,6 +383,26 @@
                         }
                     });
                 }
+
+                @Override
+                public Object[] toArray() {
+                    Collection<K> coll = new ArrayList<K>(size());
+
+                    for (Iterator<K> iter = iterator(); iter.hasNext();) {
+                        coll.add(iter.next());
+                    }
+                    return coll.toArray();
+                }
+
+                @Override
+                public <T> T[] toArray(T[] contents) {
+                    Collection<K> coll = new ArrayList<K>(size());
+
+                    for (Iterator<K> iter = iterator(); iter.hasNext();) {
+                        coll.add(iter.next());
+                    }
+                    return coll.toArray(contents);
+                }
             };
         }
         return keySet;
@@ -408,16 +419,13 @@
      * "wrapper object" over the iterator of map's entrySet(). The size method
      * wraps the map's size method and the contains method wraps the map's
      * containsValue method.
-     * </p>
      * <p>
      * The collection is created when this method is called at first time and
      * returned in response to all subsequent calls. This method may return
      * different Collection when multiple calls to this method, since it has no
      * synchronization performed.
-     * </p>
-     * 
+     *
      * @return a collection of the values contained in this map.
-     * @since Android 1.0
      */
     @Override
     public Collection<V> values() {
@@ -454,12 +462,11 @@
 
     /**
      * Returns the value of the mapping with the specified key.
-     * 
+     *
      * @param key
      *            the key.
      * @return the value of the mapping with the specified key, or {@code null}
      *         if no mapping for the specified key is found.
-     * @since Android 1.0
      */
     @Override
     public V get(Object key) {
@@ -510,12 +517,11 @@
 
     /**
      * Returns whether this map contains the specified value.
-     * 
+     *
      * @param value
      *            the value to search for.
      * @return {@code true} if this map contains the specified value,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean containsValue(Object value) {
@@ -549,9 +555,8 @@
 
     /**
      * Returns the number of elements in this map.
-     * 
+     *
      * @return the number of elements in this map.
-     * @since Android 1.0
      */
     @Override
     public boolean isEmpty() {
@@ -590,14 +595,13 @@
 
     /**
      * Maps the specified key to the specified value.
-     * 
+     *
      * @param key
      *            the key.
      * @param value
      *            the value.
      * @return the value of any previous mapping with the specified key or
      *         {@code null} if there was no mapping.
-     * @since Android 1.0
      */
     @Override
     public V put(K key, V value) {
@@ -658,10 +662,11 @@
      * Copies all the mappings in the given map to this map. These mappings will
      * replace all mappings that this map had for any of the keys currently in
      * the given map.
-     * 
+     *
      * @param map
      *            the map to copy mappings from.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *             if {@code map} is {@code null}.
      */
     @Override
     public void putAll(Map<? extends K, ? extends V> map) {
@@ -670,12 +675,11 @@
 
     /**
      * Removes the mapping with the specified key from this map.
-     * 
+     *
      * @param key
      *            the key of the mapping to remove.
      * @return the value of the removed mapping or {@code null} if no mapping
      *         for the specified key was found.
-     * @since Android 1.0
      */
     @Override
     public V remove(Object key) {
@@ -711,9 +715,8 @@
 
     /**
      * Returns the number of elements in this map.
-     * 
+     *
      * @return the number of elements in this map.
-     * @since Android 1.0
      */
     @Override
     public int size() {
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
new file mode 100644
index 0000000..e3ea7b5
--- /dev/null
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/io/FileCanonPathCache.java
@@ -0,0 +1,136 @@
+/*
+ *  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.luni.internal.io;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+
+/**
+ * A simple cache implementation for file's canonical path. The cache has fixed
+ * size <code> CACHE_SIZE </code> and cached elements would be expired. If
+ * <code>put<code> method is invoked when cache is full, the oldest element will be removed.
+ *
+ */
+public class FileCanonPathCache {
+
+    static private class CacheElement {
+        String canonicalPath;
+
+        long timestamp;
+
+        public CacheElement(String path) {
+            this.canonicalPath = path;
+            this.timestamp = System.currentTimeMillis();
+        }
+    }
+
+    /**
+     * Max elemnts could be hold in the cache.
+     */
+    public static final int CACHE_SIZE = 256;
+
+    private static HashMap<String, CacheElement> cache = new HashMap<String, CacheElement>(
+            CACHE_SIZE);
+
+    /**
+     * FIFO queue for tracking age of elements.
+     */
+    private static LinkedList<String> list = new LinkedList<String>();
+
+    private static Object lock = new Object();
+
+    /**
+     * Expired time.
+     */
+    private static long timeout = 600000;
+
+    /**
+     * Retrieve element from cache.
+     * 
+     * @param path
+     *            absolute path.
+     * @return canonical path of <code>path</code> if it's in cache.
+     * 
+     */
+    public static String get(String path) {
+        CacheElement element = null;
+        synchronized (lock) {
+            element = cache.get(path);
+        }
+
+        if (element == null) {
+            return null;
+        }
+
+        long time = System.currentTimeMillis();
+        if (time - element.timestamp > timeout) {
+            // remove all elements older than this one
+            synchronized (lock) {
+                if (cache.get(path) != null) {
+                    String oldest = null;
+                    do {
+                        oldest = list.removeFirst();
+                        cache.remove(path);
+                    } while (!path.equals(oldest));
+                }
+            }
+            return null;
+        }
+
+        return element.canonicalPath;
+    }
+
+    /**
+     * Put element to cache.
+     * 
+     * @param path
+     *            absolute path.
+     * @param canonicalPath
+     *            the canonical path of <code>path</code>.
+     */
+    public static void put(String path, String canonicalPath) {
+        CacheElement element = new CacheElement(canonicalPath);
+        synchronized (lock) {
+            if (cache.size() >= CACHE_SIZE) {
+                // cache is full
+                String oldest = list.removeFirst();
+                cache.remove(oldest);
+            }
+            cache.put(path, element);
+            list.addLast(path);
+        }
+    }
+
+    /**
+     * Remove all elements from cache.
+     */
+    public static void clear() {
+        synchronized (lock) {
+            cache.clear();
+            list.clear();
+        }
+    }
+
+    public static long getTimeout() {
+        return timeout;
+    }
+
+    public static void setTimeout(long timeout) {
+        FileCanonPathCache.timeout = timeout;
+    }
+}
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/MimeTable.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/MimeTable.java
index e288f1a..be6da05 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/MimeTable.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/MimeTable.java
@@ -51,7 +51,7 @@
     }
 
     /**
-     * Contructs a MIME table using the default values defined in this class.
+     * Constructs a MIME table using the default values defined in this class.
      * 
      * It then augments this table by reading pairs of extensions and
      * corresponding content types from the file "content-types.properties",
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/file/FileURLConnection.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/file/FileURLConnection.java
index 07357be..7f738d3 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/file/FileURLConnection.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/file/FileURLConnection.java
@@ -59,16 +59,9 @@
     public FileURLConnection(URL url) {
         super(url);
         fileName = url.getFile();
-        if (url.getRef() != null) {
-            fileName += "#" + url.getRef(); //$NON-NLS-1$
-        }
         if (fileName == null) {
             fileName = ""; //$NON-NLS-1$
         }
-        String host = url.getHost();
-        if (host != null && host.length() > 0) {
-            fileName = "//" + host + fileName; //$NON-NLS-1$
-        }
         fileName = Util.decode(fileName, false);
     }
 
@@ -131,13 +124,23 @@
             return MimeTable.UNKNOWN;
         }
         if (isDir) {
-            return "text/html"; //$NON-NLS-1$
+            return "text/plain"; //$NON-NLS-1$
         }
         String result = guessContentTypeFromName(url.getFile());
-        if (result == null) {
-            return MimeTable.UNKNOWN;
+        if (result != null) {
+            return result;
         }
-        return result;
+
+        try {
+            result = guessContentTypeFromStream(is);
+        } catch (IOException e) {
+            // Ignore
+        }
+        if (result != null) {
+            return result;
+        }
+
+        return MimeTable.UNKNOWN;
     }
 
     /**
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/file/Handler.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/file/Handler.java
index 909e611..1b5bfb9 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/file/Handler.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/file/Handler.java
@@ -41,15 +41,15 @@
      * 
      */
     @Override
-    public URLConnection openConnection(URL url) {
-        return new FileURLConnection(url);
+    public URLConnection openConnection(URL url) throws IOException {
+        return openConnection(url, null);
     }
 
     /**
      * The behaviour of this method is the same as openConnection(URL).
      * <code>proxy</code> is not used in FileURLConnection.
      * 
-     * @param u
+     * @param url
      *            the URL which the connection is pointing to
      * @param proxy
      *            Proxy
@@ -58,18 +58,28 @@
      * @throws IOException
      *             if this handler fails to establish a connection.
      * @throws IllegalArgumentException
-     *             if any argument is null or of an invalid type.
+     *             if the url argument is null.
      * @throws UnsupportedOperationException
      *             if the protocol handler doesn't support this method.
      */
     @Override
     public URLConnection openConnection(URL url, Proxy proxy)
             throws IOException {
-        if (null == url || null == proxy) {
+        if (null == url) {
             // K034b=url and proxy can not be null
             throw new IllegalArgumentException(Msg.getString("K034b")); //$NON-NLS-1$
         }
-        return new FileURLConnection(url);
+
+        String host = url.getHost();
+        if (host == null || host.length() == 0
+                || host.equalsIgnoreCase("localhost")) { //$NON-NLS-1$
+            return new FileURLConnection(url);
+        }
+
+        // If a hostname is specified try to get the resource using FTP
+        URL ftpURL = new URL("ftp", host, url.getFile()); //$NON-NLS-1$
+        return (proxy == null) ? ftpURL.openConnection() : ftpURL
+                .openConnection(proxy);
     }
 
     /**
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/ftp/FtpURLConnection.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/ftp/FtpURLConnection.java
index 2d4ab0d..3c361bf 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/ftp/FtpURLConnection.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/ftp/FtpURLConnection.java
@@ -183,22 +183,24 @@
             ProxySelector selector = ProxySelector.getDefault();
             Iterator<Proxy> iter = proxyList.iterator();
             boolean connectOK = false;
+            String failureReason = ""; //$NON-NLS-1$
             while (iter.hasNext() && !connectOK) {
                 currentProxy = iter.next();
                 try {
                     connectInternal();
                     connectOK = true;
                 } catch (IOException ioe) {
+                    failureReason = ioe.getLocalizedMessage();
                     // If connect failed, callback "connectFailed"
                     // should be invoked.
                     if (null != selector && Proxy.NO_PROXY != currentProxy) {
-                        selector
-                                .connectFailed(uri, currentProxy.address(), ioe);
+                        selector.connectFailed(uri, currentProxy.address(), ioe);
                     }
                 }
             }
             if (!connectOK) {
-                throw new IOException(Msg.getString("K0097")); //$NON-NLS-1$
+                // K0097=Unable to connect to server\: {0}
+                throw new IOException(Msg.getString("K0097", failureReason)); //$NON-NLS-1$
             }
         }
     }
@@ -397,7 +399,7 @@
      * Read a line of text and return it for possible parsing
      */
     private String readLine() throws IOException {
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         int c;
         while ((c = ctrlInput.read()) != '\n') {
             sb.append((char) c);
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java
index 1f7589d..24be092 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/Header.java
@@ -118,7 +118,7 @@
     /**
      * Set a field with the specified value. If the field is not found, it is
      * added. If the field is found, the existing value(s) are overwritten.
-     * 
+     *
      * @param key
      * @param value
      */
@@ -148,8 +148,10 @@
      * Provides an unmodifiable map with all String header names mapped to their
      * String values. The map keys are Strings and the values are unmodifiable
      * Lists of Strings.
-     * 
+     *
      * @return an unmodifiable map of the headers
+     *
+     * @since 1.4
      */
     public Map<String, List<String>> getFieldMap() {
         Map<String, List<String>> result = new HashMap<String, List<String>>(
@@ -164,7 +166,7 @@
     /**
      * Returns the element at <code>pos</code>, null if no such element
      * exist.
-     * 
+     *
      * @return java.lang.String the value of the key
      * @param pos
      *            int the position to look for
@@ -179,8 +181,8 @@
     /**
      * Returns the key of this header at <code>pos</code>, null if there are
      * fewer keys in the header
-     * 
-     * 
+     *
+     *
      * @return the key the desired position
      * @param pos
      *            the position to look for
@@ -193,11 +195,12 @@
     }
 
     /**
-     * Returns the value corresponding to the specified key, null if no such key
-     * exists.
-     * 
+     * Returns the value corresponding to the specified key.
+     *
      * @param key
-     * @return
+     *            the key to look up.
+     * @return Answers the value for the given key, or <code>null</code> if no
+     *         such key exists.
      */
     public String get(String key) {
         LinkedList<String> result = keyTable.get(key.toLowerCase());
@@ -209,8 +212,8 @@
 
     /**
      * Returns the number of keys stored in this header
-     * 
-     * @return
+     *
+     * @return the number of keys.
      */
     public int length() {
         return props.size() / 2;
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConfiguration.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConfiguration.java
index 6a26365..55d762d 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConfiguration.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConfiguration.java
@@ -14,12 +14,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-
-// BEGIN android-note
-// This class was copied from a newer version of harmony
-// to improve reusability of URLConnections
-// END android-note
-
 package org.apache.harmony.luni.internal.net.www.protocol.http;
 
 import java.net.InetSocketAddress;
@@ -141,4 +135,4 @@
         return uri.hashCode();
     }
 
-}
+}
\ No newline at end of file
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnection.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnection.java
index f7c8d96..4c51bdc 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnection.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnection.java
@@ -14,12 +14,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-
-// BEGIN android-note
-// This class was copied from a newer version of harmony
-// to improve reusability of URLConnections
-// END android-note
-
 package org.apache.harmony.luni.internal.net.www.protocol.http;
 
 import java.io.IOException;
@@ -42,6 +36,7 @@
  * various utility methods to access that connection.
  */
 public class HttpConnection {
+
     private boolean usingSecureSocket = false;
 
     private Socket socket;
@@ -233,7 +228,7 @@
      * Returns whether this connection is eligible to be recycled. This
      * is like {@link #isStale} except that it doesn't try to actually
      * perform any I/O.
-     * 
+     *
      * @return <code>true</code> if the connection is eligible to be
      * recycled
      */
@@ -272,4 +267,5 @@
             return null;
         }
     }
-}
+
+}
\ No newline at end of file
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnectionManager.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnectionManager.java
index 9a90612..61d7cbe 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnectionManager.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpConnectionManager.java
@@ -14,12 +14,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-
-// BEGIN android-note
-// This class was copied from a newer version of harmony
-// to improve reusability of URLConnections
-// END android-note
-
 package org.apache.harmony.luni.internal.net.www.protocol.http;
 
 import java.io.IOException;
@@ -179,4 +173,4 @@
         pool.clear();
     }
 
-}
+}
\ No newline at end of file
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/HttpURLConnection.java
index 6f5a2be..2dea92b 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/HttpURLConnection.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-// BEGIN android-note
-// This class and some helper classes where copied from a newer version of harmony
-// to improve reusability of URLConnections
-// END android-note
-
 package org.apache.harmony.luni.internal.net.www.protocol.http;
 
 import java.io.ByteArrayOutputStream;
@@ -185,7 +180,7 @@
 
             return is.skip(n);
         }
-        
+
         public int available() throws IOException {
             if (closed) {
                 throwClosed();
@@ -222,9 +217,9 @@
         private void throwClosed() throws IOException {
             throw new IOException("stream closed");
         }
-    }    
+    }
     // END android-added
-    
+
     private class LimitedInputStream extends InputStream {
         int bytesRemaining;
 
@@ -523,7 +518,7 @@
          * size minus chunk head (which writes chunk data size in HEX and
          * "\r\n") size. For example, a string "abcd" use chunk whose size is 5
          * must be written to socket as "2\r\nab","2\r\ncd" ...
-         * 
+         *
          */
         private int calculateChunkDataLength() {
             /*
@@ -691,7 +686,7 @@
     /**
      * Creates an instance of the <code>HttpURLConnection</code> using default
      * port 80.
-     * 
+     *
      * @param url
      *            URL The URL this connection is connecting
      */
@@ -701,7 +696,7 @@
 
     /**
      * Creates an instance of the <code>HttpURLConnection</code>
-     * 
+     *
      * @param url
      *            URL The URL this connection is connecting
      * @param port
@@ -711,7 +706,7 @@
         super(url);
         defaultPort = port;
         reqHeader = (Header) defaultReqHeader.clone();
-        
+
         try {
             uri = url.toURI();
         } catch (URISyntaxException e) {
@@ -727,7 +722,7 @@
 
     /**
      * Creates an instance of the <code>HttpURLConnection</code>
-     * 
+     *
      * @param url
      *            URL The URL this connection is connecting
      * @param port
@@ -742,12 +737,12 @@
 
     /**
      * Establishes the connection to the remote HTTP server
-     * 
+     *
      * Any methods that requires a valid connection to the resource will call
      * this method implicitly. After the connection is established,
      * <code>connected</code> is set to true.
-     * 
-     * 
+     *
+     *
      * @see #connected
      * @see java.io.IOException
      * @see URLStreamHandler
@@ -762,9 +757,9 @@
         }
         // BEGIN android-changed
         // url.toURI(); throws an URISyntaxException if the url contains
-        // illegal characters in e.g. the query. 
-        // Since the query is not needed for proxy selection, we just create an 
-        // URI that only contains the necessary information. 
+        // illegal characters in e.g. the query.
+        // Since the query is not needed for proxy selection, we just create an
+        // URI that only contains the necessary information.
         try {
             uri = new URI(url.getProtocol(),
                           null,
@@ -817,7 +812,7 @@
     }
 
     /**
-     * Returns connected socket to be used for this HTTP connection. 
+     * Returns connected socket to be used for this HTTP connection.
      */
     protected HttpConnection getHTTPConnection(Proxy proxy) throws IOException {
         HttpConnection connection;
@@ -832,7 +827,7 @@
 
     /**
      * Sets up the data streams used to send request[s] and read response[s].
-     * 
+     *
      * @param connection
      *            HttpConnection to be used
      */
@@ -882,8 +877,8 @@
 
     /**
      * Closes the connection with the HTTP server
-     * 
-     * 
+     *
+     *
      * @see URLConnection#connect()
      */
     @Override
@@ -940,7 +935,7 @@
      * <p>
      * If the content type is not what stated above,
      * <code>FileNotFoundException</code> is thrown.
-     * 
+     *
      * @return InputStream the error input stream returned by the server.
      */
     @Override
@@ -978,14 +973,14 @@
     /**
      * Returns the value of the field corresponding to the <code>key</code>
      * Returns <code>null</code> if there is no such field.
-     * 
+     *
      * If there are multiple fields with that key, the last field value is
      * returned.
-     * 
+     *
      * @return java.lang.String The value of the header field
      * @param key
      *            java.lang.String the name of the header field
-     * 
+     *
      * @see #getHeaderField(int)
      * @see #getHeaderFieldKey
      */
@@ -1019,8 +1014,10 @@
      * Provides an unmodifiable map of the connection header values. The map
      * keys are the String header field names. Each map value is a list of the
      * header field values associated with that key name.
-     * 
+     *
      * @return the mapping of header field names to values
+     *
+     * @since 1.4
      */
     @Override
     public Map<String, List<String>> getHeaderFields() {
@@ -1172,12 +1169,12 @@
 
     /**
      * Returns a line read from the input stream. Does not include the \n
-     * 
+     *
      * @return The line that was read.
      */
     String readln() throws IOException {
         boolean lastCr = false;
-        StringBuffer result = new StringBuffer(80);
+        StringBuilder result = new StringBuilder(80);
         int c = is.read();
         if (c < 0) {
             return null;
@@ -1215,7 +1212,7 @@
      * Sends the request header to the remote HTTP server Not all of them are
      * guaranteed to have any effect on the content the server will return,
      * depending on if the server supports that field.
-     * 
+     *
      * Examples : Accept: text/*, text/html, text/html;level=1, Accept-Charset:
      * iso-8859-5, unicode-1-1;q=0.8
      */
@@ -1327,6 +1324,45 @@
         } else {
             output.append("1\r\n"); //$NON-NLS-1$
         }
+        // add user-specified request headers if any
+        boolean hasContentLength = false;
+        for (int i = 0; i < reqHeader.length(); i++) {
+            String key = reqHeader.getKey(i);
+            if (key != null) {
+                String lKey = key.toLowerCase();
+                if ((os != null && !os.isChunked())
+                        || (!lKey.equals("transfer-encoding") && !lKey //$NON-NLS-1$
+                                .equals("content-length"))) { //$NON-NLS-1$
+                    output.append(key);
+                    String value = reqHeader.get(i);
+                    /*
+                     * duplicates are allowed under certain conditions see
+                     * http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
+                     */
+                    if (lKey.equals("content-length")) { //$NON-NLS-1$
+                        hasContentLength = true;
+                        /*
+                         * if both setFixedLengthStreamingMode and
+                         * content-length are set, use fixedContentLength first
+                         */
+                        if(fixedContentLength >= 0){
+                            value = String.valueOf(fixedContentLength);
+                        }
+                    }
+                    if (value != null) {
+                        output.append(": "); //$NON-NLS-1$
+                        output.append(value);
+                    }
+                    output.append("\r\n"); //$NON-NLS-1$
+                }
+            }
+        }
+        if (fixedContentLength >= 0 && !hasContentLength) {
+            output.append("content-length: "); //$NON-NLS-1$
+            output.append(String.valueOf(fixedContentLength));
+            output.append("\r\n"); //$NON-NLS-1$
+        }
+
         if (reqHeader.get("User-Agent") == null) { //$NON-NLS-1$
             output.append("User-Agent: "); //$NON-NLS-1$
             String agent = getSystemProperty("http.agent"); //$NON-NLS-1$
@@ -1348,6 +1384,11 @@
             }
             output.append("\r\n"); //$NON-NLS-1$
         }
+        if (reqHeader.get("Accept") == null) { //$NON-NLS-1$
+            // BEGIN android-changed
+            output.append("Accept: *, */*\r\n"); //$NON-NLS-1$
+            // END android-changed
+        }
         if (httpVersion > 0 && reqHeader.get("Connection") == null) { //$NON-NLS-1$
             output.append("Connection: Keep-Alive\r\n"); //$NON-NLS-1$
         }
@@ -1367,43 +1408,6 @@
                 output.append("Transfer-Encoding: chunked\r\n"); //$NON-NLS-1$
             }
         }
-
-        boolean hasContentLength = false;
-        // then the user-specified request headers, if any
-        for (int i = 0; i < reqHeader.length(); i++) {
-            String key = reqHeader.getKey(i);
-            if (key != null) {
-                String lKey = key.toLowerCase();
-                if ((os != null && !os.isChunked())
-                        || (!lKey.equals("transfer-encoding") && !lKey //$NON-NLS-1$
-                                .equals("content-length"))) { //$NON-NLS-1$
-                    output.append(key);
-                    output.append(": "); //$NON-NLS-1$
-                    /*
-                     * duplicates are allowed under certain conditions see
-                     * http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
-                     */
-                    if (lKey.equals("content-length")) { //$NON-NLS-1$
-                        hasContentLength = true;
-                        /*
-                         * if both setFixedLengthStreamingMode and
-                         * content-length are set, use fixedContentLength first
-                         */
-                        output.append((fixedContentLength >= 0) ? String
-                                        .valueOf(fixedContentLength)
-                                        : reqHeader.get(i));
-                    } else {
-                        output.append(reqHeader.get(i));
-                    }
-                    output.append("\r\n"); //$NON-NLS-1$
-                }
-            }
-        }
-        if (fixedContentLength >= 0 && !hasContentLength) {
-            output.append("content-length: "); //$NON-NLS-1$
-            output.append(String.valueOf(fixedContentLength));
-            output.append("\r\n"); //$NON-NLS-1$
-        }
         // end the headers
         output.append("\r\n"); //$NON-NLS-1$
         return output.toString().getBytes("ISO8859_1"); //$NON-NLS-1$
@@ -1412,7 +1416,7 @@
     /**
      * Sets the default request header fields to be sent to the remote server.
      * This does not affect the current URL Connection, only newly created ones.
-     * 
+     *
      * @param field
      *            java.lang.String The name of the field to be changed
      * @param value
@@ -1427,11 +1431,11 @@
      * <code>setIfModifiedSince()</code> Since this HTTP impl supports
      * IfModifiedSince as one of the header field, the request header is updated
      * with the new value.
-     * 
-     * 
+     *
+     *
      * @param newValue
      *            the number of millisecond since epoch
-     * 
+     *
      * @throws IllegalStateException
      *             if already connected.
      */
@@ -1655,7 +1659,7 @@
     /**
      * Returns the authorization credentials on the base of provided
      * authorization challenge
-     * 
+     *
      * @param challenge
      * @return authorization credentials
      * @throws IOException
@@ -1707,4 +1711,4 @@
             }
         }
     }
-}
+}
\ No newline at end of file
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/HttpsURLConnection.java
index 31c1198..4d0aff7 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/HttpsURLConnection.java
@@ -14,7 +14,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-
 package org.apache.harmony.luni.internal.net.www.protocol.https;
 
 import java.io.IOException;
@@ -22,10 +21,6 @@
 import java.io.OutputStream;
 import java.net.ProtocolException;
 import java.net.Proxy;
-// BEGIN andorid-removed
-// copied from newer version of harmony
-// import java.net.Socket;
-// END android-removed
 import java.net.URL;
 import java.security.Permission;
 import java.security.Principal;
@@ -390,10 +385,7 @@
                             responseMessage, responseCode));
                 }
                 // if there are some remaining data in the stream - read it out
-                // BEGIN andorid-changed
-                // copied from newer version of harmony
                 InputStream is = connection.getInputStream();
-                // END android-changed
                 while (is.available() != 0) {
                     is.read();
                 }
@@ -403,11 +395,8 @@
                 super.connect();
             }
             if (!makingSSLTunnel) {
-                // BEGIN andorid-changed
-                // copied from newer version of harmony
                 sslSocket = connection.getSecureSocket(getSSLSocketFactory(), getHostnameVerifier());
                 setUpTransportIO(connection);
-                // END android-changed
             }
         }
 
@@ -430,23 +419,5 @@
             return super.requestString();
         }
 
-        // BEGIN android-removed
-        // /**
-        //  * Create the secure socket over the connected socket and verify remote
-        //  * hostname.
-        //  */
-        // private Socket wrapConnection(Socket socket) throws IOException {
-        //     String hostname = url.getHost();
-        //     // create the wrapper over connected socket
-        //     sslSocket = (SSLSocket) getSSLSocketFactory().createSocket(socket,
-        //             hostname, url.getPort(), true);
-        //     sslSocket.setUseClientMode(true);
-        //     sslSocket.startHandshake();
-        //     if (!getHostnameVerifier().verify(hostname, sslSocket.getSession())) {
-        //         throw new IOException(Messages.getString("luni.02", hostname)); //$NON-NLS-1$
-        //     }
-        //     return sslSocket;
-        // }
-        // END android-removed
     }
 }
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 da34969..4db9910 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
@@ -36,8 +36,9 @@
      * @param u
      *            java.net.URL The URL to which the connection is pointing to
      * 
-     * @thows IOException thrown if an IO error occurs when this method tries to
-     *        establish connection.
+     * @throws IOException
+     *             thrown if an IO error occurs when this method tries to
+     *             establish connection.
      */
     @Override
     protected URLConnection openConnection(URL u) throws IOException {
@@ -75,7 +76,8 @@
             file = file.substring(0, file.indexOf('!') + 1) + spec;
         } else {
             int idx = file.indexOf('!');
-            String tmpFile = file.substring(idx + 1, file.lastIndexOf('/') + 1) + spec;
+            String tmpFile = file.substring(idx + 1, file.lastIndexOf('/') + 1)
+                    + spec;
             tmpFile = URLUtil.canonicalizePath(tmpFile);
             file = file.substring(0, idx + 1) + tmpFile;
         }
@@ -97,7 +99,7 @@
      */
     @Override
     protected String toExternalForm(URL url) {
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         sb.append("jar:"); //$NON-NLS-1$
         sb.append(url.getFile());
         String ref = url.getRef();
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/JarURLConnection.java
index 5f4896a..34e7d07 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/JarURLConnection.java
@@ -23,8 +23,6 @@
 import java.io.FilterInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.WeakReference;
 import java.net.ContentHandler;
 import java.net.ContentHandlerFactory;
 import java.net.MalformedURLException;
@@ -32,120 +30,38 @@
 import java.security.AccessController;
 import java.security.Permission;
 import java.security.PrivilegedAction;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.TreeSet;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 import java.util.zip.ZipFile;
 
-// BEGIN android-removed
-// import org.apache.harmony.kernel.vm.VM;
-// END android-removed
 import org.apache.harmony.luni.util.Msg;
 import org.apache.harmony.luni.util.Util;
 
 /**
  * This subclass extends <code>URLConnection</code>.
  * <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.
  */
 public class JarURLConnection extends java.net.JarURLConnection {
 
-    static Hashtable<String, CacheEntry<? extends JarFile>> jarCache = new Hashtable<String, CacheEntry<?>>();
+    static HashMap<URL, JarFile> jarCache = new HashMap<URL, JarFile>();
 
-    InputStream jarInput;
+    private URL jarFileURL;
+
+    private InputStream jarInput;
 
     private JarFile jarFile;
 
     private JarEntry jarEntry;
-    
+
     private boolean closed;
 
-    ReferenceQueue<JarFile> cacheQueue = new ReferenceQueue<JarFile>();
-
-    static TreeSet<LRUKey> lru = new TreeSet<LRUKey>(
-            new LRUComparator<LRUKey>());
-
-    static int Limit;
-
-    static {
-        Limit = AccessController.doPrivileged(new PrivilegedAction<Integer>() {
-            public Integer run() {
-                return Integer.getInteger("jar.cacheSize", 500); //$NON-NLS-1$
-            }
-        });
-        // BEGIN android-removed
-        // TODO this needs to be implemented once this is available.
-        // VM.closeJars();
-        // END android-removed
-    }
-
-    static final class CacheEntry<T extends JarFile> extends WeakReference<T> {
-        Object key;
-
-        CacheEntry(T jar, String key, ReferenceQueue<JarFile> queue) {
-            super(jar, queue);
-            this.key = key;
-        }
-    }
-
-    static final class LRUKey {
-        JarFile jar;
-
-        long ts;
-
-        LRUKey(JarFile file, long time) {
-            jar = file;
-            ts = time;
-        }
-
-        /**
-         * @see java.lang.Object#equals(java.lang.Object)
-         */
-        @Override
-        public boolean equals(Object obj) {
-            return (obj instanceof LRUKey) &&
-                (jar == ((LRUKey) obj).jar);
-        }
-
-        @Override
-        public int hashCode() {
-            return jar.hashCode();
-        }
-    }
-
-    static final class LRUComparator<T> implements Comparator<LRUKey> {
-
-        LRUComparator() {
-        }
-
-        /**
-         * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
-         */
-        public int compare(LRUKey o1, LRUKey o2) {
-            if ((o1).ts > (o2).ts) {
-                return 1;
-            }
-            return (o1).ts == (o2).ts ? 0 : -1;
-        }
-
-        /**
-         * @param o1
-         *            an object to compare
-         * @param o2
-         *            an object to compare
-         * @return <code>true</code> if the objects are equal,
-         *         <code>false</code> otherwise.
-         */
-        public boolean equals(Object o1, Object o2) {
-            return o1.equals(o2);
-        }
-    }
 
     /**
      * @param url
@@ -153,8 +69,10 @@
      * @throws MalformedURLException
      *             if the URL is malformed
      */
-    public JarURLConnection(java.net.URL url) throws MalformedURLException {
+    public JarURLConnection(java.net.URL url) throws MalformedURLException, IOException {
         super(url);
+        jarFileURL = getJarFileURL();
+        jarFileURLConnection = jarFileURL.openConnection();
     }
 
     /**
@@ -162,77 +80,76 @@
      */
     @Override
     public void connect() throws IOException {
-        jarFileURLConnection = getJarFileURL().openConnection();
-        findJarFile(); // ensure the file can be found
-        findJarEntry(); // ensure the entry, if any, can be found
-        connected = true;
+        if (!connected) {
+            findJarFile(); // ensure the file can be found
+            findJarEntry(); // ensure the entry, if any, can be found
+            connected = true;
+        }
     }
 
     /**
      * Returns the Jar file refered by this <code>URLConnection</code>
-     * 
+     *
      * @return the JAR file referenced by this connection
-     * 
+     *
      * @throws IOException
      *             thrown if an IO error occurs while connecting to the
      *             resource.
      */
     @Override
     public JarFile getJarFile() throws IOException {
-        if (!connected) {
-            connect();
-        }
+        connect();
         return jarFile;
     }
 
     /**
      * Returns the Jar file refered by this <code>URLConnection</code>
-     * 
+     *
      * @throws IOException
      *             if an IO error occurs while connecting to the resource.
      */
     private void findJarFile() throws IOException {
-        URL jarFileURL = getJarFileURL();
-        if (jarFileURL.getProtocol().equals("file")) { //$NON-NLS-1$
-            String fileName = jarFileURL.getFile();
-            if(!new File(Util.decode(fileName,false)).exists()){
-                // KA026=JAR entry {0} not found in {1}
-                throw new FileNotFoundException(Msg.getString("KA026", //$NON-NLS-1$
-                        getEntryName(), fileName));
+        JarFile jar = null;
+        if (getUseCaches()) {
+            synchronized(jarCache){
+                jarFile = jarCache.get(jarFileURL);
             }
-            String host = jarFileURL.getHost();
-            if (host != null && host.length() > 0) {
-                fileName = "//" + host + fileName; //$NON-NLS-1$
-            }
-            jarFile = openJarFile(fileName, fileName, false);
-            return;
-        }
-
-        final String externalForm = jarFileURLConnection.getURL()
-                .toExternalForm();
-        jarFile = AccessController
-                .doPrivileged(new PrivilegedAction<JarFile>() {
-                    public JarFile run() {
-                        try {
-                            return openJarFile(null, externalForm, false);
-                        } catch (IOException e) {
-                            return null;
-                        }
+            if (jarFile == null) {
+                jar = openJarFile();
+                synchronized(jarCache){
+                    jarFile = jarCache.get(jarFileURL);
+                    if (jarFile == null){
+                        jarCache.put(jarFileURL, jar);
+                        jarFile = jar;
+                    }else{
+                        jar.close();
                     }
-                });
-        if (jarFile != null) {
-            return;
+                }
+            }
+        }else{
+            jarFile = openJarFile();
         }
 
-        // Build a temp jar file
-        final InputStream is = jarFileURLConnection.getInputStream();
-        try {
-            jarFile = AccessController
+        if (jarFile == null) {
+            throw new IOException();
+        }
+    }
+
+    JarFile openJarFile() throws IOException {
+        JarFile jar = null;
+        if (jarFileURL.getProtocol().equals("file")) { //$NON-NLS-1$
+            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];
@@ -241,79 +158,33 @@
                                     fos.write(buf, 0, nbytes);
                                 }
                                 fos.close();
-                                String path = tempJar.getPath();
-                                return openJarFile(path, externalForm, true);
+                                return new JarFile(tempJar,
+                                        true, ZipFile.OPEN_READ | ZipFile.OPEN_DELETE);
                             } catch (IOException e) {
                                 return null;
                             }
                         }
                     });
-        } finally {
-            is.close();
-        }
-        if (jarFile == null) {
-            throw new IOException();
-        }
-    }
-
-    JarFile openJarFile(String fileString, String key, boolean temp)
-            throws IOException {
-
-        JarFile jar = null;
-        if (useCaches) {
-            CacheEntry<? extends JarFile> entry;
-            while ((entry = (CacheEntry<? extends JarFile>) cacheQueue.poll()) != null) {
-                jarCache.remove(entry.key);
+            } finally {
+                if (is != null) is.close();
             }
-            entry = jarCache.get(key);
-            if (entry != null) {
-                jar = entry.get();
-            }
-            if (jar == null && fileString != null) {
-                int flags = ZipFile.OPEN_READ
-                        + (temp ? ZipFile.OPEN_DELETE : 0);
-                jar = new JarFile(new File(Util.decode(fileString, false)),
-                        true, flags);
-                jarCache
-                        .put(key, new CacheEntry<JarFile>(jar, key, cacheQueue));
-            } else {
-                SecurityManager security = System.getSecurityManager();
-                if (security != null) {
-                    security.checkPermission(getPermission());
-                }
-                if (temp) {
-                    lru.remove(new LRUKey(jar, 0));
-                }
-            }
-        } else if (fileString != null) {
-            int flags = ZipFile.OPEN_READ + (temp ? ZipFile.OPEN_DELETE : 0);
-            jar = new JarFile(new File(Util.decode(fileString, false)), true,
-                    flags);
         }
 
-        if (temp) {
-            lru.add(new LRUKey(jar, new Date().getTime()));
-            if (lru.size() > Limit) {
-                lru.remove(lru.first());
-            }
-        }
         return jar;
     }
 
     /**
      * Returns the JarEntry of the entry referenced by this
      * <code>URLConnection</code>.
-     * 
+     *
      * @return java.util.jar.JarEntry the JarEntry referenced
-     * 
+     *
      * @throws IOException
      *             if an IO error occurs while getting the entry
      */
     @Override
     public JarEntry getJarEntry() throws IOException {
-        if (!connected) {
-            connect();
-        }
+        connect();
         return jarEntry;
 
     }
@@ -334,20 +205,19 @@
 
     /**
      * Creates an input stream for reading from this URL Connection.
-     * 
+     *
      * @return the input stream
-     * 
+     *
      * @throws IOException
      *             if an IO error occurs while connecting to the resource.
      */
     @Override
     public InputStream getInputStream() throws IOException {
+
         if (closed) {
             throw new IllegalStateException(Msg.getString("KA027"));
         }
-        if (!connected) {
-            connect();
-        }
+        connect();
         if (jarInput != null) {
             return jarInput;
         }
@@ -359,39 +229,56 @@
     }
 
     /**
-     * Returns the content type of the resource. Test cases reveal that only if
-     * the URL is refering to a Jar file, that this method returns a non-null
-     * value - x-java/jar.
-     * 
+     * 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
     public String getContentType() {
-        // it could also return "x-java/jar" which jdk returns but here, we get
-        // it from the URLConnection
-        try {
-            if (url.getFile().endsWith("!/")) { //$NON-NLS-1$
-                return getJarFileURL().openConnection().getContentType();
+        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
+                }
             }
-        } catch (IOException ioe) {
-            // Ignore
+            if (cType == null) {
+                cType = "content/unknown"; //$NON-NLS-1$
+            }
+            return cType;
         }
-        // if there is an Jar Entry, get the content type from the name
-        return guessContentTypeFromName(url.getFile());
     }
 
     /**
      * 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
-     * returned by URLConnection. If not, it will return -1.
-     * 
+     * returned by URLConnection. For jar entry it should return it's size.
+     * Otherwise, it will return -1.
+     *
      * @return the content length
      */
     @Override
     public int getContentLength() {
         try {
-            if (url.getFile().endsWith("!/")) { //$NON-NLS-1$
-                return getJarFileURL().openConnection().getContentLength();
+            connect();
+            if (jarEntry == null) {
+                return jarFileURLConnection.getContentLength();
+            } else {
+                return (int) getJarEntry().getSize();
             }
         } catch (IOException e) {
             //Ignored
@@ -404,12 +291,12 @@
      * 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.
-     * 
+     *
      * @return a non-null object
-     * 
+     *
      * @throws IOException
      *             if an IO error occured
-     * 
+     *
      * @see ContentHandler
      * @see ContentHandlerFactory
      * @see java.io.IOException
@@ -417,9 +304,7 @@
      */
     @Override
     public Object getContent() throws IOException {
-        if (!connected) {
-            connect();
-        }
+        connect();
         // if there is no Jar Entry, return a JarFile
         if (jarEntry == null) {
             return jarFile;
@@ -431,37 +316,57 @@
      * Returns the permission, in this case the subclass, FilePermission object
      * which represents the permission necessary for this URLConnection to
      * establish the connection.
-     * 
+     *
      * @return the permission required for this URLConnection.
-     * 
+     *
      * @throws IOException
      *             thrown when an IO exception occurs while creating the
      *             permission.
      */
+
     @Override
     public Permission getPermission() throws IOException {
-        if (jarFileURLConnection != null) {
-            return jarFileURLConnection.getPermission();
-        }
-        return getJarFileURL().openConnection().getPermission();
+        return jarFileURLConnection.getPermission();
+    }
+
+    @Override
+    public boolean getUseCaches() {
+        return jarFileURLConnection.getUseCaches();
+    }
+
+    @Override
+    public void setUseCaches(boolean usecaches) {
+        jarFileURLConnection.setUseCaches(usecaches);
+    }
+
+    @Override
+    public boolean getDefaultUseCaches() {
+        return jarFileURLConnection.getDefaultUseCaches();
+    }
+
+    @Override
+    public void setDefaultUseCaches(boolean defaultusecaches) {
+        jarFileURLConnection.setDefaultUseCaches(defaultusecaches);
     }
 
     /**
      * Closes the cached files.
      */
     public static void closeCachedFiles() {
-        Enumeration<CacheEntry<? extends JarFile>> elemEnum = jarCache
-                .elements();
-        while (elemEnum.hasMoreElements()) {
-            try {
-                ZipFile zip = elemEnum.nextElement().get();
-                if (zip != null) {
-                    zip.close();
+        Set<Map.Entry<URL, JarFile>> s = jarCache.entrySet();
+        synchronized(jarCache){
+            Iterator<Map.Entry<URL, JarFile>> i = s.iterator();
+            while(i.hasNext()){
+                try {
+                    ZipFile zip = i.next().getValue();
+                    if (zip != null) {
+                        zip.close();
+                    }
+                } catch (IOException e) {
+                    // Ignored
                 }
-            } catch (IOException e) {
-                // Ignored
             }
-        }
+       }
     }
 
     private class JarURLConnectionInputStream extends FilterInputStream {
@@ -478,7 +383,7 @@
         @Override
         public void close() throws IOException {
             super.close();
-            if (!useCaches) {
+            if (!getUseCaches()) {
                 closed = true;
                 jarFile.close();
             }
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/nls/messages.properties b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/nls/messages.properties
index fe392b7..2ee09f7 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/nls/messages.properties
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/nls/messages.properties
@@ -21,8 +21,6 @@
 luni.04=this Map
 luni.05=Attempt to insert {0} element into collection with element type {1}
 luni.06=The string argument is null
-# // BEGIN android-added
-# // copied from newer version of harmony
+luni.07=The stream is corrupted
 luni.08=Invalid Unicode sequence: expected format \\uxxxx
 luni.09=Invalid Unicode sequence: illegal character
-# // END android-added
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyCharArrayCache.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyCharArrayCache.java
deleted file mode 100644
index a359b8b..0000000
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyCharArrayCache.java
+++ /dev/null
@@ -1,133 +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.luni.internal.reflect;
-
-class ProxyCharArrayCache {
-    static boolean equals(char[] first, char[] second) {
-        if (first == second) {
-            return true;
-        }
-        if (first == null || second == null) {
-            return false;
-        }
-        if (first.length != second.length) {
-            return false;
-        }
-
-        for (int i = first.length; --i >= 0;) {
-            if (first[i] != second[i]) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    // to avoid using Enumerations, walk the individual tables skipping nulls
-    private char[] keyTable[];
-
-    private int valueTable[];
-
-    // number of elements in the table
-    private int elementSize;
-
-    private int threshold;
-
-    ProxyCharArrayCache(int initialCapacity) {
-        if (initialCapacity < 13) {
-            initialCapacity = 13;
-        }
-        this.elementSize = 0;
-        this.threshold = (int) (initialCapacity * 0.66f);
-        this.keyTable = new char[initialCapacity][];
-        this.valueTable = new int[initialCapacity];
-    }
-
-    int get(char[] key) {
-        int index = hashCodeChar(key);
-        while (keyTable[index] != null) {
-            if (equals(keyTable[index], key)) {
-                return valueTable[index];
-            }
-            index = (index + 1) % keyTable.length;
-        }
-        return -1;
-    }
-
-    private int hashCodeChar(char[] val) {
-        int length = val.length;
-        int hash = 0;
-        int n = 2; // number of characters skipped
-        for (int i = 0; i < length; i += n) {
-            hash += val[i];
-        }
-        return (hash & 0x7FFFFFFF) % keyTable.length;
-    }
-
-    int put(char[] key, int value) {
-        int index = hashCodeChar(key);
-        while (keyTable[index] != null) {
-            if (equals(keyTable[index], key)) {
-                return valueTable[index] = value;
-            }
-            index = (index + 1) % keyTable.length;
-        }
-        keyTable[index] = key;
-        valueTable[index] = value;
-
-        // assumes the threshold is never equal to the size of the table
-        if (++elementSize > threshold) {
-            rehash();
-        }
-        return value;
-    }
-
-    private void rehash() {
-        ProxyCharArrayCache newHashtable = new ProxyCharArrayCache(
-                keyTable.length * 2);
-        for (int i = keyTable.length; --i >= 0;) {
-            if (keyTable[i] != null) {
-                newHashtable.put(keyTable[i], valueTable[i]);
-            }
-        }
-
-        this.keyTable = newHashtable.keyTable;
-        this.valueTable = newHashtable.valueTable;
-        this.threshold = newHashtable.threshold;
-    }
-
-    int size() {
-        return elementSize;
-    }
-
-    @Override
-    public String toString() {
-        int max = size();
-        StringBuilder buf = new StringBuilder();
-        buf.append("{"); //$NON-NLS-1$
-        for (int i = 0; i < max; ++i) {
-            if (keyTable[i] != null) {
-                buf.append(keyTable[i]).append("->").append(valueTable[i]); //$NON-NLS-1$
-            }
-            if (i < max) {
-                buf.append(", "); //$NON-NLS-1$
-            }
-        }
-        buf.append("}"); //$NON-NLS-1$
-        return buf.toString();
-    }
-}
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyClassFile.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyClassFile.java
deleted file mode 100644
index 43fa5a3..0000000
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyClassFile.java
+++ /dev/null
@@ -1,937 +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.luni.internal.reflect;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.lang.reflect.UndeclaredThrowableException;
-import java.util.ArrayList;
-import java.util.HashSet;
-
-public final class ProxyClassFile implements ProxyConstants {
-
-    private static final int INITIAL_CONTENTS_SIZE = 1000;
-
-    private static final int INITIAL_HEADER_SIZE = 500;
-
-    private static final int INCREMENT_SIZE = 250;
-
-    private static Method ObjectEqualsMethod;
-
-    private static Method ObjectHashCodeMethod;
-
-    private static Method ObjectToStringMethod;
-
-    private static Method ClassForNameMethod;
-
-    private static Method ClassGetMethod;
-
-    private static Method HandlerInvokeMethod;
-
-    private static Constructor<?> ProxyConstructor;
-
-    private static Constructor<?> UndeclaredThrowableExceptionConstructor;
-
-    private static Field ProxyHandlerField;
-
-    public static byte[] generateBytes(String typeName, Class[] interfaces) {
-        ProxyClassFile classFile = new ProxyClassFile(typeName, interfaces);
-        classFile.addFields();
-        classFile.findMethods(interfaces);
-        classFile.addMethods();
-        classFile.addAttributes();
-        return classFile.getBytes();
-    }
-
-    static char[] getConstantPoolName(Class<?> c) {
-        if (c.isArray()) {
-            // Array classes are named/ with their signature
-            return c.getName().replace('.', '/').toCharArray();
-        }
-
-        if (c.isPrimitive()) {
-            // Special cases for each base type.
-            if (c == void.class) {
-                return new char[] { 'V' };
-            }
-            if (c == int.class) {
-                return new char[] { 'I' };
-            }
-            if (c == boolean.class) {
-                return new char[] { 'Z' };
-            }
-            if (c == byte.class) {
-                return new char[] { 'B' };
-            }
-            if (c == char.class) {
-                return new char[] { 'C' };
-            }
-            if (c == short.class) {
-                return new char[] { 'S' };
-            }
-            if (c == long.class) {
-                return new char[] { 'J' };
-            }
-            if (c == float.class) {
-                return new char[] { 'F' };
-            }
-            if (c == double.class) {
-                return new char[] { 'D' };
-            }
-        }
-        return ("L" + c.getName().replace('.', '/') + ";").toCharArray();
-    }
-
-    static char[] getConstantPoolName(Constructor<?> method) /* (ILjava/lang/Thread;)V */{
-        Class[] parameters = method.getParameterTypes();
-        StringBuffer buffer = new StringBuffer(parameters.length + 1 * 20);
-        buffer.append('(');
-        for (Class<?> element : parameters) {
-            buffer.append(getConstantPoolName(element));
-        }
-        buffer.append(')');
-        buffer.append(getConstantPoolName(void.class));
-        return buffer.toString().toCharArray();
-    }
-
-    static char[] getConstantPoolName(Method method) /* (ILjava/lang/Thread;)Ljava/lang/Object; */{
-        Class[] parameters = method.getParameterTypes();
-        StringBuffer buffer = new StringBuffer(parameters.length + 1 * 20);
-        buffer.append('(');
-        for (Class<?> element : parameters) {
-            buffer.append(getConstantPoolName(element));
-        }
-        buffer.append(')');
-        buffer.append(getConstantPoolName(method.getReturnType()));
-        return buffer.toString().toCharArray();
-    }
-
-    private ProxyConstantPool constantPool;
-
-    // the header contains all the bytes till the end of the constant pool
-    byte[] header;
-
-    int headerOffset;
-
-    // that collection contains all the remaining bytes of the .class file
-    private byte[] contents;
-
-    private int contentsOffset;
-
-    private int constantPoolOffset;
-
-    private ProxyMethod[] proxyMethods;
-
-    ProxyClassFile(String typeName, Class[] interfaces) {
-        super();
-        header = new byte[INITIAL_HEADER_SIZE];
-        // generate the magic numbers inside the header
-        header[headerOffset++] = (byte) (0xCAFEBABEL >> 24);
-        header[headerOffset++] = (byte) (0xCAFEBABEL >> 16);
-        header[headerOffset++] = (byte) (0xCAFEBABEL >> 8);
-        header[headerOffset++] = (byte) (0xCAFEBABEL >> 0);
-        // Compatible with JDK 1.2
-        header[headerOffset++] = 0;
-        header[headerOffset++] = 0;
-        header[headerOffset++] = 0;
-        header[headerOffset++] = 46;
-        constantPoolOffset = headerOffset;
-        headerOffset += 2;
-        constantPool = new ProxyConstantPool(this);
-        contents = new byte[INITIAL_CONTENTS_SIZE];
-        // now we continue to generate the bytes inside the contents array
-        int accessFlags = AccPublic | AccFinal | AccSuper;
-        contents[contentsOffset++] = (byte) (accessFlags >> 8);
-        contents[contentsOffset++] = (byte) accessFlags;
-        int classNameIndex = constantPool.typeIndex(typeName);
-        contents[contentsOffset++] = (byte) (classNameIndex >> 8);
-        contents[contentsOffset++] = (byte) classNameIndex;
-        int superclassNameIndex = constantPool
-                .typeIndex("java/lang/reflect/Proxy");
-        contents[contentsOffset++] = (byte) (superclassNameIndex >> 8);
-        contents[contentsOffset++] = (byte) superclassNameIndex;
-        int interfacesCount = interfaces.length;
-        contents[contentsOffset++] = (byte) (interfacesCount >> 8);
-        contents[contentsOffset++] = (byte) interfacesCount;
-        for (int i = 0; i < interfacesCount; i++) {
-            int interfaceIndex = constantPool
-                    .typeIndex(interfaces[i].getName());
-            contents[contentsOffset++] = (byte) (interfaceIndex >> 8);
-            contents[contentsOffset++] = (byte) interfaceIndex;
-        }
-    }
-
-    private void addAttributes() {
-        writeUnsignedShort(0); // classFile does not have attributes of its own
-
-        // resynchronize all offsets of the classfile
-        header = constantPool.poolContent;
-        headerOffset = constantPool.currentOffset;
-        int constantPoolCount = constantPool.currentIndex;
-        header[constantPoolOffset++] = (byte) (constantPoolCount >> 8);
-        header[constantPoolOffset] = (byte) constantPoolCount;
-    }
-
-    private void addFields() {
-        writeUnsignedShort(0); // we have no fields
-    }
-
-    private void addMethods() {
-        int methodCount = proxyMethods.length;
-        writeUnsignedShort(methodCount + 1);
-
-        // save constructor
-        writeUnsignedShort(AccPublic);
-        writeUnsignedShort(constantPool.literalIndex(Init));
-        if (ProxyConstructor == null) {
-            try {
-                ProxyConstructor = Proxy.class
-                        .getDeclaredConstructor(new Class[] { InvocationHandler.class });
-            } catch (NoSuchMethodException e) {
-                throw new InternalError();
-            }
-        }
-        writeUnsignedShort(constantPool
-                .literalIndex(getConstantPoolName(ProxyConstructor)));
-        writeUnsignedShort(1); // store just the code attribute
-        writeUnsignedShort(constantPool.literalIndex(CodeName));
-        // save attribute_length(4), max_stack(2), max_locals(2), code_length(4)
-        int codeLength = 6;
-        writeUnsignedWord(12 + codeLength); // max_stack(2), max_locals(2),
-        // code_length(4), 2 zero shorts
-        writeUnsignedShort(2);
-        writeUnsignedShort(2);
-        writeUnsignedWord(codeLength);
-        writeUnsignedByte(OPC_aload_0);
-        writeUnsignedByte(OPC_aload_1);
-        writeUnsignedByte(OPC_invokespecial);
-        writeUnsignedShort(constantPool.literalIndex(ProxyConstructor));
-        writeUnsignedByte(OPC_return);
-        writeUnsignedShort(0); // no exceptions table
-        writeUnsignedShort(0); // there are no attributes for the code
-        // attribute
-
-        for (int i = 0; i < methodCount; i++) {
-            ProxyMethod pMethod = proxyMethods[i];
-            Method method = pMethod.method;
-            writeUnsignedShort(AccPublic | AccFinal);
-            writeUnsignedShort(constantPool.literalIndex(method.getName()
-                    .toCharArray()));
-            writeUnsignedShort(constantPool
-                    .literalIndex(getConstantPoolName(method)));
-            Class[] thrownsExceptions = pMethod.commonExceptions;
-            int eLength = thrownsExceptions.length;
-            if (eLength > 0) {
-                writeUnsignedShort(2); // store the exception & code attributes
-                // The method has a throw clause. So we need to add an exception
-                // attribute
-                writeUnsignedShort(constantPool.literalIndex(ExceptionsName));
-                // The attribute length = length * 2 + 2 in case of a exception
-                // attribute
-                writeUnsignedWord(eLength * 2 + 2);
-                writeUnsignedShort(eLength);
-                for (int e = 0; e < eLength; e++) {
-                    writeUnsignedShort(constantPool
-                            .typeIndex(thrownsExceptions[e].getName()));
-                }
-            } else {
-                writeUnsignedShort(1); // store just the code attribute
-            }
-            generateCodeAttribute(pMethod);
-        }
-    }
-
-    private void findMethods(Class[] interfaces) {
-        /*
-         * find all methods defined by the interfaces (including inherited
-         * interfaces) plus hashCode, equals & toString from Object build an
-         * array with the methods... no duplicates - check up to the array size
-         * when the interface's first method was added
-         */
-        if (ObjectEqualsMethod == null) {
-            try {
-                ObjectEqualsMethod = Object.class.getMethod("equals",
-                        new Class[] { Object.class });
-                ObjectHashCodeMethod = Object.class.getMethod("hashCode",
-                        new Class[0]);
-                ObjectToStringMethod = Object.class.getMethod("toString",
-                        new Class[0]);
-            } catch (NoSuchMethodException ex) {
-                throw new InternalError();
-            }
-        }
-
-        ArrayList<ProxyMethod> allMethods = new ArrayList<ProxyMethod>(25);
-        allMethods.add(new ProxyMethod(ObjectEqualsMethod));
-        allMethods.add(new ProxyMethod(ObjectHashCodeMethod));
-        allMethods.add(new ProxyMethod(ObjectToStringMethod));
-
-        HashSet<Class<?>> interfacesSeen = new HashSet<Class<?>>();
-        for (Class<?> element : interfaces) {
-            findMethods(element, allMethods, interfacesSeen);
-        }
-
-        proxyMethods = new ProxyMethod[allMethods.size()];
-        allMethods.toArray(proxyMethods);
-    }
-
-    private void findMethods(Class<?> nextInterface,
-            ArrayList<ProxyMethod> allMethods, HashSet<Class<?>> interfacesSeen) {
-        /*
-         * add the nextInterface's methods to allMethods if an equivalent method
-         * already exists then return types must be identical... don't replace
-         * it
-         */
-        if (interfacesSeen.contains(nextInterface)) {
-            return; // already walked it
-        }
-        interfacesSeen.add(nextInterface);
-
-        int existingMethodCount = allMethods.size();
-        Method[] methods = nextInterface.getMethods();
-        nextMethod: for (Method method : methods) {
-            for (int j = 0; j < existingMethodCount; j++) {
-                if (allMethods.get(j).matchMethod(method)) {
-                    continue nextMethod;
-                }
-            }
-            allMethods.add(new ProxyMethod(method));
-        }
-
-        Class<?>[] superInterfaces = nextInterface.getInterfaces();
-        for (Class<?> element : superInterfaces) {
-            // recursion should be minimal
-            findMethods(element, allMethods, interfacesSeen);
-        }
-    }
-
-    private void generateCodeAttribute(ProxyMethod pMethod) {
-        int codeAttributeOffset = contentsOffset;
-        int contentsLength = contents.length;
-        if (contentsOffset + 20 + 100 >= contentsLength) {
-            System.arraycopy(contents, 0, (contents = new byte[contentsLength
-                    + INCREMENT_SIZE]), 0, contentsLength);
-        }
-        writeUnsignedShort(constantPool.literalIndex(CodeName));
-        // leave space for attribute_length(4), max_stack(2), max_locals(2),
-        // code_length(4)
-        contentsOffset += 12;
-
-        /*
-         * to push the args for the call to invoke push the receiver field h 0
-         * aload0 1 getfield 33 java.lang.reflect.Proxy.h
-         * Ljava.lang.reflect.InvocationHandler; push the receiver as the first
-         * arg 4 aload0 push the method push the array of args call invoke 89
-         * invokeinterface 67
-         * java.lang.reflect.InvocationHandler.invoke(Ljava.lang.Object;Ljava.lang.reflect.Method;[Ljava.lang.Object;)Ljava.lang.Object;
-         * cast return result catch & convert exceptions if necessary
-         */
-
-        int codeStartOffset = contentsOffset;
-        writeUnsignedByte(OPC_aload_0);
-        writeUnsignedByte(OPC_getfield);
-        if (ProxyHandlerField == null) {
-            try {
-                ProxyHandlerField = Proxy.class.getDeclaredField("h");
-            } catch (NoSuchFieldException e) {
-                throw new InternalError();
-            }
-        }
-        writeUnsignedShort(constantPool.literalIndex(ProxyHandlerField));
-        writeUnsignedByte(OPC_aload_0);
-        Method method = pMethod.method;
-        Class[] argTypes = method.getParameterTypes();
-        genCallGetMethod(method.getDeclaringClass(), method.getName(), argTypes);
-        int maxLocals = genInvokeArgs(argTypes);
-        writeUnsignedByte(OPC_invokeinterface);
-        if (HandlerInvokeMethod == null) {
-            try {
-                HandlerInvokeMethod = InvocationHandler.class.getMethod(
-                        "invoke", new Class[] { Object.class, Method.class,
-                                Object[].class });
-            } catch (NoSuchMethodException e) {
-                throw new InternalError();
-            }
-        }
-        writeUnsignedShort(constantPool.literalIndex(HandlerInvokeMethod));
-        writeUnsignedByte(4); // invoke has 3 args
-        writeUnsignedByte(0); // 4th operand must be 0
-        genCastReturnType(method.getReturnType());
-        int codeLength = contentsOffset - codeStartOffset;
-
-        Class[] checkedExceptions = pMethod.getCheckedExceptions();
-        int checkedLength = checkedExceptions.length;
-        if (checkedLength > 0) {
-            int codeEndIndex = contentsOffset - codeStartOffset;
-            writeUnsignedByte(OPC_athrow); // re-throw the caught exception
-
-            genStoreArg(maxLocals);
-            writeUnsignedByte(OPC_new);
-            writeUnsignedShort(constantPool
-                    .typeIndex("java/lang/reflect/UndeclaredThrowableException"));
-            writeUnsignedByte(OPC_dup);
-            genLoadArg(maxLocals);
-            maxLocals++; // now expecting the exception
-            writeUnsignedByte(OPC_invokespecial);
-            if (UndeclaredThrowableExceptionConstructor == null) {
-                try {
-                    UndeclaredThrowableExceptionConstructor = UndeclaredThrowableException.class
-                            .getConstructor(new Class[] { Throwable.class });
-                } catch (NoSuchMethodException e) {
-                    throw new InternalError();
-                }
-            }
-            writeUnsignedShort(constantPool
-                    .literalIndex(UndeclaredThrowableExceptionConstructor));
-            writeUnsignedByte(OPC_athrow);
-
-            codeLength = contentsOffset - codeStartOffset;
-
-            // write the exception table
-            writeUnsignedShort(checkedLength + 1);
-            for (int i = 0; i < checkedLength; i++) {
-                writeUnsignedShort(0);
-                writeUnsignedShort(codeEndIndex);
-                writeUnsignedShort(codeEndIndex);
-                writeUnsignedShort(constantPool.typeIndex(checkedExceptions[i]
-                        .getName()));
-            }
-            writeUnsignedShort(0);
-            writeUnsignedShort(codeEndIndex);
-            writeUnsignedShort(codeEndIndex + 1); // starts after the first
-            // throw
-            writeUnsignedShort(constantPool.typeIndex("java/lang/Throwable"));
-        } else {
-            writeUnsignedShort(0); // no exceptions table
-        }
-        // there are no attributes for the code attribute
-        writeUnsignedShort(0);
-
-        /*
-         * Complete the creation of the code attribute by setting the
-         * attribute_length, max_stack max_locals, code_length & exception table
-         * codeAttributeOffset is the position inside contents byte array before
-         * we started to write That means that to write the attribute_length you
-         * need to offset by 2 the value of codeAttributeOffset to get the right
-         * position, 6 for the max_stack etc...
-         */
-        int codeAttributeLength = contentsOffset - (codeAttributeOffset + 6);
-        contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
-        contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
-        contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
-        contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
-
-        int maxStack = maxLocals + 10; // larger than the exact amount
-        contents[codeAttributeOffset + 6] = (byte) (maxStack >> 8);
-        contents[codeAttributeOffset + 7] = (byte) maxStack;
-        contents[codeAttributeOffset + 8] = (byte) (maxLocals >> 8);
-        contents[codeAttributeOffset + 9] = (byte) maxLocals;
-        contents[codeAttributeOffset + 10] = (byte) (codeLength >> 24);
-        contents[codeAttributeOffset + 11] = (byte) (codeLength >> 16);
-        contents[codeAttributeOffset + 12] = (byte) (codeLength >> 8);
-        contents[codeAttributeOffset + 13] = (byte) codeLength;
-    }
-
-    /**
-     * Perform call to Class.getMethod(String, Class[]) receiver 13 ldc 37
-     * (java.lang.String) "java.lang.Object" 15 invokestatic 43
-     * java.lang.Class.forName(Ljava.lang.String;)Ljava.lang.Class; selector 37
-     * ldc 55 (java.lang.String) "equals" plus method args 39 iconst0 40
-     * anewarray 39 java.lang.Class or 39 iconst1 40 anewarray 39
-     * java.lang.Class 43 dup 44 iconst0 53 ldc 37 (java.lang.String)
-     * "java.lang.Object" 55 invokestatic 43
-     * java.lang.Class.forName(Ljava.lang.String;)Ljava.lang.Class; 77 aastore
-     * or 39 iconst2 40 anewarray 39 java.lang.Class 43 dup 44 iconst0 45
-     * getstatic 102 java.lang.Integer.TYPE Ljava.lang.Class; 48 aastore 49 dup
-     * 50 iconst1 51 getstatic 104 java.lang.Boolean.TYPE Ljava.lang.Class; 54
-     * aastore then 78 invokevirtual 59
-     * java.lang.Class.getMethod(Ljava.lang.String;[Ljava.lang.Class;)Ljava.lang.reflect.Method;
-     */
-    private void genCallGetMethod(Class<?> receiverType, String selector,
-            Class[] argTypes) {
-        genCallClassForName(receiverType.getName());
-        writeLdc(selector);
-        int length = argTypes.length;
-        writeIntConstant(length);
-        writeUnsignedByte(OPC_anewarray);
-        writeUnsignedShort(constantPool.typeIndex("java/lang/Class"));
-        for (int i = 0; i < length; i++) {
-            writeUnsignedByte(OPC_dup);
-            writeIntConstant(i);
-            Class<?> type = argTypes[i];
-            if (type.isPrimitive()) {
-                writeUnsignedByte(OPC_getstatic);
-                writeUnsignedShort(constantPool.literalIndex(typeField(type)));
-            } else {
-                genCallClassForName(type.getName());
-            }
-            writeUnsignedByte(OPC_aastore);
-        }
-        writeUnsignedByte(OPC_invokevirtual);
-        if (ClassGetMethod == null) {
-            try {
-                ClassGetMethod = Class.class.getMethod("getMethod",
-                        new Class[] { String.class, Class[].class });
-            } catch (NoSuchMethodException e) {
-                throw new InternalError();
-            }
-        }
-        writeUnsignedShort(constantPool.literalIndex(ClassGetMethod));
-    }
-
-    /**
-     * Add argument array for call to InvocationHandler.invoke
-     * 
-     * 46 aconstnull or 81 iconst1 82 anewarray 61 java.lang.Object 85 dup 86
-     * iconst0 87 aload1 88 aastore or 58 iconst2 59 anewarray 61
-     * java.lang.Object 62 dup 63 iconst0 64 new 84 java.lang.Integer 67 dup 68
-     * iload1 69 invokespecial 107 java.lang.Integer.<init>(I)V 72 aastore 73
-     * dup 74 iconst1 75 new 69 java.lang.Boolean 78 dup 79 iload2 80
-     * invokespecial 110 java.lang.Boolean.<init>(Z)V 83 aastore
-     */
-    private int genInvokeArgs(Class[] argTypes) {
-        int argByteOffset = 1; // remember h is at position 0
-        int length = argTypes.length;
-        if (length == 0) {
-            writeUnsignedByte(OPC_aconst_null);
-        } else {
-            writeIntConstant(length);
-            writeUnsignedByte(OPC_anewarray);
-            writeUnsignedShort(constantPool.typeIndex("java/lang/Object"));
-            for (int i = 0; i < length; i++) {
-                writeUnsignedByte(OPC_dup);
-                writeIntConstant(i);
-                argByteOffset = genInvokeArg(argTypes[i], argByteOffset);
-                writeUnsignedByte(OPC_aastore);
-            }
-        }
-        return argByteOffset;
-    }
-
-    private int genInvokeArg(Class<?> type, int argByteOffset) {
-        // offset represents maxLocals in bytes
-        if (type.isPrimitive()) {
-            writeUnsignedByte(OPC_new);
-            writeUnsignedShort(constantPool.typeIndex(typeWrapperName(type)));
-            writeUnsignedByte(OPC_dup);
-            if (argByteOffset > 255) {
-                writeUnsignedByte(OPC_wide);
-            }
-            if (type == long.class) {
-                switch (argByteOffset) {
-                    case 0:
-                        writeUnsignedByte(OPC_lload_0);
-                        break;
-                    case 1:
-                        writeUnsignedByte(OPC_lload_1);
-                        break;
-                    case 2:
-                        writeUnsignedByte(OPC_lload_2);
-                        break;
-                    case 3:
-                        writeUnsignedByte(OPC_lload_3);
-                        break;
-                    default:
-                        writeUnsignedByte(OPC_lload);
-                        if (argByteOffset > 255) {
-                            writeUnsignedShort(argByteOffset);
-                        } else {
-                            writeUnsignedByte(argByteOffset);
-                        }
-                }
-                argByteOffset += 2;
-            } else if (type == float.class) {
-                switch (argByteOffset) {
-                    case 0:
-                        writeUnsignedByte(OPC_fload_0);
-                        break;
-                    case 1:
-                        writeUnsignedByte(OPC_fload_1);
-                        break;
-                    case 2:
-                        writeUnsignedByte(OPC_fload_2);
-                        break;
-                    case 3:
-                        writeUnsignedByte(OPC_fload_3);
-                        break;
-                    default:
-                        writeUnsignedByte(OPC_fload);
-                        if (argByteOffset > 255) {
-                            writeUnsignedShort(argByteOffset);
-                        } else {
-                            writeUnsignedByte(argByteOffset);
-                        }
-                }
-                argByteOffset++;
-            } else if (type == double.class) {
-                switch (argByteOffset) {
-                    case 0:
-                        writeUnsignedByte(OPC_dload_0);
-                        break;
-                    case 1:
-                        writeUnsignedByte(OPC_dload_1);
-                        break;
-                    case 2:
-                        writeUnsignedByte(OPC_dload_2);
-                        break;
-                    case 3:
-                        writeUnsignedByte(OPC_dload_3);
-                        break;
-                    default:
-                        writeUnsignedByte(OPC_dload);
-                        if (argByteOffset > 255) {
-                            writeUnsignedShort(argByteOffset);
-                        } else {
-                            writeUnsignedByte(argByteOffset);
-                        }
-                }
-                argByteOffset += 2;
-            } else { // handles int, short, byte, boolean & char
-                switch (argByteOffset) {
-                    case 0:
-                        writeUnsignedByte(OPC_iload_0);
-                        break;
-                    case 1:
-                        writeUnsignedByte(OPC_iload_1);
-                        break;
-                    case 2:
-                        writeUnsignedByte(OPC_iload_2);
-                        break;
-                    case 3:
-                        writeUnsignedByte(OPC_iload_3);
-                        break;
-                    default:
-                        writeUnsignedByte(OPC_iload);
-                        if (argByteOffset > 255) {
-                            writeUnsignedShort(argByteOffset);
-                        } else {
-                            writeUnsignedByte(argByteOffset);
-                        }
-                }
-                argByteOffset++;
-            }
-            writeUnsignedByte(OPC_invokespecial);
-            writeUnsignedShort(constantPool.literalIndex(typeInitMethod(type)));
-        } else {
-            genLoadArg(argByteOffset);
-            argByteOffset++;
-        }
-        return argByteOffset;
-    }
-
-    /**
-     * 94 checkcast 69 java.lang.Boolean 97 invokevirtual 73
-     * java.lang.Boolean.booleanValue()Z 100 ireturn or 52 checkcast 91
-     * java.lang.String 55 areturn
-     */
-    private void genCastReturnType(Class<?> type) {
-        if (type.isPrimitive()) {
-            if (type == void.class) {
-                writeUnsignedByte(OPC_pop);
-                writeUnsignedByte(OPC_return);
-            } else {
-                writeUnsignedByte(OPC_checkcast);
-                writeUnsignedShort(constantPool
-                        .typeIndex(typeWrapperName(type)));
-                writeUnsignedByte(OPC_invokevirtual);
-                writeUnsignedShort(constantPool
-                        .literalIndex(typeAccessMethod(type)));
-                if (type == long.class) {
-                    writeUnsignedByte(OPC_lreturn);
-                } else if (type == float.class) {
-                    writeUnsignedByte(OPC_freturn);
-                } else if (type == double.class) {
-                    writeUnsignedByte(OPC_dreturn);
-                } else { // handles int, short, byte, boolean & char
-                    writeUnsignedByte(OPC_ireturn);
-                }
-            }
-        } else {
-            writeUnsignedByte(OPC_checkcast);
-            writeUnsignedShort(constantPool.typeIndex(type.getName()));
-            writeUnsignedByte(OPC_areturn);
-        }
-    }
-
-    private void genCallClassForName(String typeName) {
-        writeLdc(typeName);
-        writeUnsignedByte(OPC_invokestatic);
-        if (ClassForNameMethod == null) {
-            try {
-                ClassForNameMethod = Class.class.getMethod("forName",
-                        new Class[] { String.class });
-            } catch (NoSuchMethodException e) {
-                throw new InternalError();
-            }
-        }
-        writeUnsignedShort(constantPool.literalIndex(ClassForNameMethod));
-    }
-
-    private void genLoadArg(int argByteOffset) {
-        if (argByteOffset > 255) {
-            writeUnsignedByte(OPC_wide);
-            writeUnsignedByte(OPC_aload);
-            writeUnsignedShort(argByteOffset);
-        } else {
-            switch (argByteOffset) {
-                case 0:
-                    writeUnsignedByte(OPC_aload_0);
-                    break;
-                case 1:
-                    writeUnsignedByte(OPC_aload_1);
-                    break;
-                case 2:
-                    writeUnsignedByte(OPC_aload_2);
-                    break;
-                case 3:
-                    writeUnsignedByte(OPC_aload_3);
-                    break;
-                default:
-                    writeUnsignedByte(OPC_aload);
-                    writeUnsignedByte(argByteOffset);
-            }
-        }
-    }
-
-    private void genStoreArg(int argByteOffset) {
-        if (argByteOffset > 255) {
-            writeUnsignedByte(OPC_wide);
-            writeUnsignedByte(OPC_astore);
-            writeUnsignedShort(argByteOffset);
-        } else {
-            switch (argByteOffset) {
-                case 0:
-                    writeUnsignedByte(OPC_astore_0);
-                    break;
-                case 1:
-                    writeUnsignedByte(OPC_astore_1);
-                    break;
-                case 2:
-                    writeUnsignedByte(OPC_astore_2);
-                    break;
-                case 3:
-                    writeUnsignedByte(OPC_astore_3);
-                    break;
-                default:
-                    writeUnsignedByte(OPC_astore);
-                    writeUnsignedByte(argByteOffset);
-            }
-        }
-    }
-
-    private byte[] getBytes() {
-        byte[] fullContents = new byte[headerOffset + contentsOffset];
-        System.arraycopy(header, 0, fullContents, 0, headerOffset);
-        System.arraycopy(contents, 0, fullContents, headerOffset,
-                contentsOffset);
-        return fullContents;
-    }
-
-    private Method typeAccessMethod(Class<?> baseType) {
-        try {
-            if (baseType == int.class) {
-                return Integer.class.getMethod("intValue", (Class[]) null);
-            }
-            if (baseType == short.class) {
-                return Short.class.getMethod("shortValue", (Class[]) null);
-            }
-            if (baseType == byte.class) {
-                return Byte.class.getMethod("byteValue", (Class[]) null);
-            }
-            if (baseType == boolean.class) {
-                return Boolean.class.getMethod("booleanValue", (Class[]) null);
-            }
-            if (baseType == char.class) {
-                return Character.class.getMethod("charValue", (Class[]) null);
-            }
-            if (baseType == long.class) {
-                return Long.class.getMethod("longValue", (Class[]) null);
-            }
-            if (baseType == float.class) {
-                return Float.class.getMethod("floatValue", (Class[]) null);
-            }
-            if (baseType == double.class) {
-                return Double.class.getMethod("doubleValue", (Class[]) null);
-            }
-        } catch (NoSuchMethodException e) {
-            throw new InternalError();
-        }
-        return null;
-    }
-
-    private Field typeField(Class<?> baseType) {
-        try {
-            if (baseType == int.class) {
-                return Integer.class.getField("TYPE");
-            }
-            if (baseType == short.class) {
-                return Short.class.getField("TYPE");
-            }
-            if (baseType == byte.class) {
-                return Byte.class.getField("TYPE");
-            }
-            if (baseType == boolean.class) {
-                return Boolean.class.getField("TYPE");
-            }
-            if (baseType == char.class) {
-                return Character.class.getField("TYPE");
-            }
-            if (baseType == long.class) {
-                return Long.class.getField("TYPE");
-            }
-            if (baseType == float.class) {
-                return Float.class.getField("TYPE");
-            }
-            if (baseType == double.class) {
-                return Double.class.getField("TYPE");
-            }
-        } catch (NoSuchFieldException e) {
-            throw new InternalError();
-        }
-        return null;
-    }
-
-    private Constructor<?> typeInitMethod(Class<?> baseType) {
-        try {
-            if (baseType == int.class) {
-                return Integer.class.getConstructor(new Class[] { int.class });
-            }
-            if (baseType == short.class) {
-                return Short.class.getConstructor(new Class[] { short.class });
-            }
-            if (baseType == byte.class) {
-                return Byte.class.getConstructor(new Class[] { byte.class });
-            }
-            if (baseType == boolean.class) {
-                return Boolean.class
-                        .getConstructor(new Class[] { boolean.class });
-            }
-            if (baseType == char.class) {
-                return Character.class
-                        .getConstructor(new Class[] { char.class });
-            }
-            if (baseType == long.class) {
-                return Long.class.getConstructor(new Class[] { long.class });
-            }
-            if (baseType == float.class) {
-                return Float.class.getConstructor(new Class[] { float.class });
-            }
-            if (baseType == double.class) {
-                return Double.class
-                        .getConstructor(new Class[] { double.class });
-            }
-        } catch (NoSuchMethodException e) {
-            throw new InternalError();
-        }
-        return null;
-    }
-
-    private String typeWrapperName(Class<?> baseType) {
-        if (baseType == int.class) {
-            return "java/lang/Integer";
-        }
-        if (baseType == short.class) {
-            return "java/lang/Short";
-        }
-        if (baseType == byte.class) {
-            return "java/lang/Byte";
-        }
-        if (baseType == boolean.class) {
-            return "java/lang/Boolean";
-        }
-        if (baseType == char.class) {
-            return "java/lang/Character";
-        }
-        if (baseType == long.class) {
-            return "java/lang/Long";
-        }
-        if (baseType == float.class) {
-            return "java/lang/Float";
-        }
-        if (baseType == double.class) {
-            return "java/lang/Double";
-        }
-        return null;
-    }
-
-    private void writeIntConstant(int b) {
-        switch (b) {
-            case 0:
-                writeUnsignedByte(OPC_iconst_0);
-                break;
-            case 1:
-                writeUnsignedByte(OPC_iconst_1);
-                break;
-            case 2:
-                writeUnsignedByte(OPC_iconst_2);
-                break;
-            case 3:
-                writeUnsignedByte(OPC_iconst_3);
-                break;
-            case 4:
-                writeUnsignedByte(OPC_iconst_4);
-                break;
-            case 5:
-                writeUnsignedByte(OPC_iconst_5);
-                break;
-            default:
-                writeUnsignedByte(OPC_bipush);
-                writeUnsignedByte(b);
-        }
-    }
-
-    private void writeLdc(String constant) {
-        int index = constantPool.literalIndexForLdc(constant.toCharArray());
-        if (index <= 0) {
-            throw new InternalError();
-        }
-        if (index > 255) {
-            writeUnsignedByte(OPC_ldc_w);
-            writeUnsignedShort(index);
-        } else {
-            writeUnsignedByte(OPC_ldc);
-            writeUnsignedByte(index);
-        }
-    }
-
-    private void writeUnsignedByte(int b) {
-        try {
-            contents[contentsOffset++] = (byte) b;
-        } catch (IndexOutOfBoundsException e) {
-            int actualLength = contents.length;
-            System.arraycopy(contents, 0, (contents = new byte[actualLength
-                    + INCREMENT_SIZE]), 0, actualLength);
-            contents[contentsOffset - 1] = (byte) b;
-        }
-    }
-
-    private void writeUnsignedShort(int b) {
-        writeUnsignedByte(b >>> 8);
-        writeUnsignedByte(b);
-    }
-
-    private void writeUnsignedWord(int b) {
-        writeUnsignedByte(b >>> 24);
-        writeUnsignedByte(b >>> 16);
-        writeUnsignedByte(b >>> 8);
-        writeUnsignedByte(b);
-    }
-}
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstantPool.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstantPool.java
deleted file mode 100644
index 3789730..0000000
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstantPool.java
+++ /dev/null
@@ -1,312 +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.luni.internal.reflect;
-
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-
-class ProxyConstantPool implements ProxyConstants {
-    public static final int UTF8_INITIAL_SIZE = 50;
-
-    public static final int STRING_INITIAL_SIZE = 21;
-
-    public static final int FIELD_INITIAL_SIZE = 7;
-
-    public static final int METHOD_INITIAL_SIZE = 21;
-
-    public static final int INTERFACE_INITIAL_SIZE = 21;
-
-    public static final int CLASS_INITIAL_SIZE = 21;
-
-    public static final int NAMEANDTYPE_INITIAL_SIZE = 21;
-
-    public static final int CONSTANTPOOL_INITIAL_SIZE = 500;
-
-    public static final int CONSTANTPOOL_GROW_SIZE = 1000;
-
-    ProxyCharArrayCache UTF8Cache;
-
-    ProxyCharArrayCache stringCache;
-
-    ProxyCharArrayCache classNameCache;
-
-    ProxyObjectCache fieldCache;
-
-    ProxyObjectCache methodCache;
-
-    ProxyObjectCache interfaceMethodCache;
-
-    ProxyNameAndTypeCache nameAndTypeCache;
-
-    byte[] poolContent;
-
-    int currentIndex;
-
-    int currentOffset;
-
-    ProxyConstantPool(ProxyClassFile classFile) {
-        UTF8Cache = new ProxyCharArrayCache(UTF8_INITIAL_SIZE);
-        stringCache = new ProxyCharArrayCache(STRING_INITIAL_SIZE);
-        classNameCache = new ProxyCharArrayCache(CLASS_INITIAL_SIZE);
-        fieldCache = new ProxyObjectCache(FIELD_INITIAL_SIZE);
-        methodCache = new ProxyObjectCache(METHOD_INITIAL_SIZE);
-        interfaceMethodCache = new ProxyObjectCache(INTERFACE_INITIAL_SIZE);
-        nameAndTypeCache = new ProxyNameAndTypeCache(NAMEANDTYPE_INITIAL_SIZE);
-        poolContent = classFile.header;
-        currentOffset = classFile.headerOffset;
-        currentIndex = 1;
-    }
-
-    int literalIndex(char[] utf8Constant) {
-        int index;
-        if ((index = UTF8Cache.get(utf8Constant)) < 0) {
-            writeU1(Utf8Tag);
-            int savedCurrentOffset = currentOffset;
-            if (currentOffset + 2 >= poolContent.length) {
-                int length = poolContent.length;
-                System.arraycopy(poolContent, 0, (poolContent = new byte[length
-                        + CONSTANTPOOL_GROW_SIZE]), 0, length);
-            }
-            currentOffset += 2;
-            int length = 0;
-            for (int i = 0; i < utf8Constant.length; i++) {
-                char current = utf8Constant[i];
-                if ((current >= 0x0001) && (current <= 0x007F)) {
-                    // we only need one byte: ASCII table
-                    writeU1(current);
-                    length++;
-                } else if (current > 0x07FF) {
-                    // we need 3 bytes
-                    length += 3;
-                    writeU1(0xE0 | ((current >> 12) & 0x0F)); // 0xE0 = 1110
-                                                                // 0000
-                    writeU1(0x80 | ((current >> 6) & 0x3F)); // 0x80 = 1000
-                                                                // 0000
-                    writeU1(0x80 | (current & 0x3F)); // 0x80 = 1000 0000
-                } else {
-                    // we can be 0 or between 0x0080 and 0x07FF
-                    // In that case we only need 2 bytes
-                    length += 2;
-                    writeU1(0xC0 | ((current >> 6) & 0x1F)); // 0xC0 = 1100
-                                                                // 0000
-                    writeU1(0x80 | (current & 0x3F)); // 0x80 = 1000 0000
-                }
-            }
-            if (length >= 65535) {
-                currentOffset = savedCurrentOffset - 1;
-                return -1;
-            }
-            index = UTF8Cache.put(utf8Constant, currentIndex++);
-            // Now we know the length that we have to write in the constant pool
-            // we use savedCurrentOffset to do that
-            poolContent[savedCurrentOffset] = (byte) (length >> 8);
-            poolContent[savedCurrentOffset + 1] = (byte) length;
-        }
-        return index;
-    }
-
-    int literalIndex(Field aField) {
-        int index;
-        if ((index = fieldCache.get(aField)) < 0) {
-            int classIndex = typeIndex(aField.getDeclaringClass().getName());
-            int nameAndTypeIndex = literalIndexForNameAndType(
-                    literalIndex(aField.getName().toCharArray()),
-                    literalIndex(ProxyClassFile.getConstantPoolName(aField
-                            .getType())));
-            index = fieldCache.put(aField, currentIndex++);
-            writeU1(FieldRefTag);
-            writeU2(classIndex);
-            writeU2(nameAndTypeIndex);
-        }
-        return index;
-    }
-
-    int literalIndex(Constructor<?> aMethod) {
-        int index;
-        if ((index = methodCache.get(aMethod)) < 0) {
-            int classIndex = typeIndex(aMethod.getDeclaringClass().getName());
-            int nameAndTypeIndex = literalIndexForNameAndType(
-                    literalIndex(Init), literalIndex(ProxyClassFile
-                            .getConstantPoolName(aMethod)));
-            index = methodCache.put(aMethod, currentIndex++);
-            writeU1(MethodRefTag);
-            writeU2(classIndex);
-            writeU2(nameAndTypeIndex);
-        }
-        return index;
-    }
-
-    int literalIndex(Method aMethod) {
-        int index;
-        if (aMethod.getDeclaringClass().isInterface()) {
-            if ((index = interfaceMethodCache.get(aMethod)) < 0) {
-                int classIndex = typeIndex(aMethod.getDeclaringClass()
-                        .getName());
-                int nameAndTypeIndex = literalIndexForNameAndType(
-                        literalIndex(aMethod.getName().toCharArray()),
-                        literalIndex(ProxyClassFile
-                                .getConstantPoolName(aMethod)));
-                index = interfaceMethodCache.put(aMethod, currentIndex++);
-                writeU1(InterfaceMethodRefTag);
-                writeU2(classIndex);
-                writeU2(nameAndTypeIndex);
-            }
-        } else if ((index = methodCache.get(aMethod)) < 0) {
-            int classIndex = typeIndex(aMethod.getDeclaringClass().getName());
-            int nameAndTypeIndex = literalIndexForNameAndType(
-                    literalIndex(aMethod.getName().toCharArray()),
-                    literalIndex(ProxyClassFile.getConstantPoolName(aMethod)));
-            index = methodCache.put(aMethod, currentIndex++);
-            writeU1(MethodRefTag);
-            writeU2(classIndex);
-            writeU2(nameAndTypeIndex);
-        }
-        return index;
-    }
-
-    int literalIndex(String stringConstant) {
-        int index;
-        char[] stringCharArray = stringConstant.toCharArray();
-        if ((index = stringCache.get(stringCharArray)) < 0) {
-            int stringIndex = literalIndex(stringCharArray);
-            index = stringCache.put(stringCharArray, currentIndex++);
-            writeU1(StringTag);
-            writeU2(stringIndex);
-        }
-        return index;
-    }
-
-    int literalIndexForLdc(char[] stringCharArray) {
-        int index;
-        if ((index = stringCache.get(stringCharArray)) < 0) {
-            int stringIndex;
-            if ((stringIndex = UTF8Cache.get(stringCharArray)) < 0) {
-                writeU1(Utf8Tag);
-                int savedCurrentOffset = currentOffset;
-                if (currentOffset + 2 >= poolContent.length) {
-                    int length = poolContent.length;
-                    System.arraycopy(poolContent, 0,
-                            (poolContent = new byte[length
-                                    + CONSTANTPOOL_GROW_SIZE]), 0, length);
-                }
-                currentOffset += 2;
-                int length = 0;
-                for (int i = 0; i < stringCharArray.length; i++) {
-                    char current = stringCharArray[i];
-                    if ((current >= 0x0001) && (current <= 0x007F)) {
-                        // we only need one byte: ASCII table
-                        writeU1(current);
-                        length++;
-                    } else if (current > 0x07FF) {
-                        // we need 3 bytes
-                        length += 3;
-                        writeU1(0xE0 | ((current >> 12) & 0x0F)); // 0xE0 =
-                                                                    // 1110 0000
-                        writeU1(0x80 | ((current >> 6) & 0x3F)); // 0x80 =
-                                                                    // 1000 0000
-                        writeU1(0x80 | (current & 0x3F)); // 0x80 = 1000 0000
-                    } else {
-                        // we can be 0 or between 0x0080 and 0x07FF
-                        // In that case we only need 2 bytes
-                        length += 2;
-                        writeU1(0xC0 | ((current >> 6) & 0x1F)); // 0xC0 =
-                                                                    // 1100 0000
-                        writeU1(0x80 | (current & 0x3F)); // 0x80 = 1000 0000
-                    }
-                }
-                if (length >= 65535) {
-                    currentOffset = savedCurrentOffset - 1;
-                    return -1;
-                }
-                stringIndex = UTF8Cache.put(stringCharArray, currentIndex++);
-                // Now we know the length that we have to write in the constant
-                // pool
-                // we use savedCurrentOffset to do that
-                if (length > 65535)
-                    return 0;
-                poolContent[savedCurrentOffset] = (byte) (length >> 8);
-                poolContent[savedCurrentOffset + 1] = (byte) length;
-            }
-            index = stringCache.put(stringCharArray, currentIndex++);
-            writeU1(StringTag);
-            writeU2(stringIndex);
-        }
-        return index;
-    }
-
-    private int literalIndexForNameAndType(int nameIndex, int typeIndex) {
-        int index;
-        int[] key = new int[] { nameIndex, typeIndex };
-        if ((index = nameAndTypeCache.get(key)) == -1) {
-            index = nameAndTypeCache.put(key, currentIndex++);
-            writeU1(NameAndTypeTag);
-            writeU2(nameIndex);
-            writeU2(typeIndex);
-        }
-        return index;
-    }
-
-    int typeIndex(String typeName) {
-        int index;
-        if (typeName.indexOf('.') != -1)
-            typeName = typeName.replace('.', '/');
-        char[] charArray = typeName.toCharArray();
-        if ((index = classNameCache.get(charArray)) < 0) {
-            int nameIndex = literalIndex(charArray);
-            index = classNameCache.put(charArray, currentIndex++);
-            writeU1(ClassTag);
-            writeU2(nameIndex);
-        }
-        return index;
-    }
-
-    private final void writeU1(int value) {
-        try {
-            poolContent[currentOffset++] = (byte) value;
-        } catch (IndexOutOfBoundsException e) {
-            // currentOffset has been ++ already (see the -1)
-            int length = poolContent.length;
-            System.arraycopy(poolContent, 0, (poolContent = new byte[length
-                    + CONSTANTPOOL_GROW_SIZE]), 0, length);
-            poolContent[currentOffset - 1] = (byte) value;
-        }
-    }
-
-    private final void writeU2(int value) {
-        try {
-            poolContent[currentOffset++] = (byte) (value >> 8);
-        } catch (IndexOutOfBoundsException e) {
-            // currentOffset has been ++ already (see the -1)
-            int length = poolContent.length;
-            System.arraycopy(poolContent, 0, (poolContent = new byte[length
-                    + CONSTANTPOOL_GROW_SIZE]), 0, length);
-            poolContent[currentOffset - 1] = (byte) (value >> 8);
-        }
-        try {
-            poolContent[currentOffset++] = (byte) value;
-        } catch (IndexOutOfBoundsException e) {
-            // currentOffset has been ++ already (see the -1)
-            int length = poolContent.length;
-            System.arraycopy(poolContent, 0, (poolContent = new byte[length
-                    + CONSTANTPOOL_GROW_SIZE]), 0, length);
-            poolContent[currentOffset - 1] = (byte) value;
-        }
-    }
-}
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstants.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstants.java
deleted file mode 100644
index 93db394..0000000
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyConstants.java
+++ /dev/null
@@ -1,464 +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.luni.internal.reflect;
-
-
-interface ProxyConstants {
-    final char[] CodeName = new char[] { 'C', 'o', 'd', 'e' };
-
-    final char[] ExceptionsName = new char[] { 'E', 'x', 'c', 'e', 'p', 't',
-            'i', 'o', 'n', 's' };
-
-    final char[] Init = new char[] { '<', 'i', 'n', 'i', 't', '>' };
-
-    final int AccPublic = 0x0001;
-
-    final int AccPrivate = 0x0002;
-
-    final int AccProtected = 0x0004;
-
-    final int AccStatic = 0x0008;
-
-    final int AccFinal = 0x0010;
-
-    final int AccSuper = 0x0020;
-
-    final int Utf8Tag = 1;
-
-    final int IntegerTag = 3;
-
-    final int FloatTag = 4;
-
-    final int LongTag = 5;
-
-    final int DoubleTag = 6;
-
-    final int ClassTag = 7;
-
-    final int StringTag = 8;
-
-    final int FieldRefTag = 9;
-
-    final int MethodRefTag = 10;
-
-    final int InterfaceMethodRefTag = 11;
-
-    final int NameAndTypeTag = 12;
-
-    final int OPC_nop = 0;
-
-    final int OPC_aconst_null = 1;
-
-    final int OPC_iconst_m1 = 2;
-
-    final int OPC_iconst_0 = 3;
-
-    final int OPC_iconst_1 = 4;
-
-    final int OPC_iconst_2 = 5;
-
-    final int OPC_iconst_3 = 6;
-
-    final int OPC_iconst_4 = 7;
-
-    final int OPC_iconst_5 = 8;
-
-    final int OPC_lconst_0 = 9;
-
-    final int OPC_lconst_1 = 10;
-
-    final int OPC_fconst_0 = 11;
-
-    final int OPC_fconst_1 = 12;
-
-    final int OPC_fconst_2 = 13;
-
-    final int OPC_dconst_0 = 14;
-
-    final int OPC_dconst_1 = 15;
-
-    final int OPC_bipush = 16;
-
-    final int OPC_sipush = 17;
-
-    final int OPC_ldc = 18;
-
-    final int OPC_ldc_w = 19;
-
-    final int OPC_ldc2_w = 20;
-
-    final int OPC_iload = 21;
-
-    final int OPC_lload = 22;
-
-    final int OPC_fload = 23;
-
-    final int OPC_dload = 24;
-
-    final int OPC_aload = 25;
-
-    final int OPC_iload_0 = 26;
-
-    final int OPC_iload_1 = 27;
-
-    final int OPC_iload_2 = 28;
-
-    final int OPC_iload_3 = 29;
-
-    final int OPC_lload_0 = 30;
-
-    final int OPC_lload_1 = 31;
-
-    final int OPC_lload_2 = 32;
-
-    final int OPC_lload_3 = 33;
-
-    final int OPC_fload_0 = 34;
-
-    final int OPC_fload_1 = 35;
-
-    final int OPC_fload_2 = 36;
-
-    final int OPC_fload_3 = 37;
-
-    final int OPC_dload_0 = 38;
-
-    final int OPC_dload_1 = 39;
-
-    final int OPC_dload_2 = 40;
-
-    final int OPC_dload_3 = 41;
-
-    final int OPC_aload_0 = 42;
-
-    final int OPC_aload_1 = 43;
-
-    final int OPC_aload_2 = 44;
-
-    final int OPC_aload_3 = 45;
-
-    final int OPC_iaload = 46;
-
-    final int OPC_laload = 47;
-
-    final int OPC_faload = 48;
-
-    final int OPC_daload = 49;
-
-    final int OPC_aaload = 50;
-
-    final int OPC_baload = 51;
-
-    final int OPC_caload = 52;
-
-    final int OPC_saload = 53;
-
-    final int OPC_istore = 54;
-
-    final int OPC_lstore = 55;
-
-    final int OPC_fstore = 56;
-
-    final int OPC_dstore = 57;
-
-    final int OPC_astore = 58;
-
-    final int OPC_istore_0 = 59;
-
-    final int OPC_istore_1 = 60;
-
-    final int OPC_istore_2 = 61;
-
-    final int OPC_istore_3 = 62;
-
-    final int OPC_lstore_0 = 63;
-
-    final int OPC_lstore_1 = 64;
-
-    final int OPC_lstore_2 = 65;
-
-    final int OPC_lstore_3 = 66;
-
-    final int OPC_fstore_0 = 67;
-
-    final int OPC_fstore_1 = 68;
-
-    final int OPC_fstore_2 = 69;
-
-    final int OPC_fstore_3 = 70;
-
-    final int OPC_dstore_0 = 71;
-
-    final int OPC_dstore_1 = 72;
-
-    final int OPC_dstore_2 = 73;
-
-    final int OPC_dstore_3 = 74;
-
-    final int OPC_astore_0 = 75;
-
-    final int OPC_astore_1 = 76;
-
-    final int OPC_astore_2 = 77;
-
-    final int OPC_astore_3 = 78;
-
-    final int OPC_iastore = 79;
-
-    final int OPC_lastore = 80;
-
-    final int OPC_fastore = 81;
-
-    final int OPC_dastore = 82;
-
-    final int OPC_aastore = 83;
-
-    final int OPC_bastore = 84;
-
-    final int OPC_castore = 85;
-
-    final int OPC_sastore = 86;
-
-    final int OPC_pop = 87;
-
-    final int OPC_pop2 = 88;
-
-    final int OPC_dup = 89;
-
-    final int OPC_dup_x1 = 90;
-
-    final int OPC_dup_x2 = 91;
-
-    final int OPC_dup2 = 92;
-
-    final int OPC_dup2_x1 = 93;
-
-    final int OPC_dup2_x2 = 94;
-
-    final int OPC_swap = 95;
-
-    final int OPC_iadd = 96;
-
-    final int OPC_ladd = 97;
-
-    final int OPC_fadd = 98;
-
-    final int OPC_dadd = 99;
-
-    final int OPC_isub = 100;
-
-    final int OPC_lsub = 101;
-
-    final int OPC_fsub = 102;
-
-    final int OPC_dsub = 103;
-
-    final int OPC_imul = 104;
-
-    final int OPC_lmul = 105;
-
-    final int OPC_fmul = 106;
-
-    final int OPC_dmul = 107;
-
-    final int OPC_idiv = 108;
-
-    final int OPC_ldiv = 109;
-
-    final int OPC_fdiv = 110;
-
-    final int OPC_ddiv = 111;
-
-    final int OPC_irem = 112;
-
-    final int OPC_lrem = 113;
-
-    final int OPC_frem = 114;
-
-    final int OPC_drem = 115;
-
-    final int OPC_ineg = 116;
-
-    final int OPC_lneg = 117;
-
-    final int OPC_fneg = 118;
-
-    final int OPC_dneg = 119;
-
-    final int OPC_ishl = 120;
-
-    final int OPC_lshl = 121;
-
-    final int OPC_ishr = 122;
-
-    final int OPC_lshr = 123;
-
-    final int OPC_iushr = 124;
-
-    final int OPC_lushr = 125;
-
-    final int OPC_iand = 126;
-
-    final int OPC_land = 127;
-
-    final int OPC_ior = 128;
-
-    final int OPC_lor = 129;
-
-    final int OPC_ixor = 130;
-
-    final int OPC_lxor = 131;
-
-    final int OPC_iinc = 132;
-
-    final int OPC_i2l = 133;
-
-    final int OPC_i2f = 134;
-
-    final int OPC_i2d = 135;
-
-    final int OPC_l2i = 136;
-
-    final int OPC_l2f = 137;
-
-    final int OPC_l2d = 138;
-
-    final int OPC_f2i = 139;
-
-    final int OPC_f2l = 140;
-
-    final int OPC_f2d = 141;
-
-    final int OPC_d2i = 142;
-
-    final int OPC_d2l = 143;
-
-    final int OPC_d2f = 144;
-
-    final int OPC_i2b = 145;
-
-    final int OPC_i2c = 146;
-
-    final int OPC_i2s = 147;
-
-    final int OPC_lcmp = 148;
-
-    final int OPC_fcmpl = 149;
-
-    final int OPC_fcmpg = 150;
-
-    final int OPC_dcmpl = 151;
-
-    final int OPC_dcmpg = 152;
-
-    final int OPC_ifeq = 153;
-
-    final int OPC_ifne = 154;
-
-    final int OPC_iflt = 155;
-
-    final int OPC_ifge = 156;
-
-    final int OPC_ifgt = 157;
-
-    final int OPC_ifle = 158;
-
-    final int OPC_if_icmpeq = 159;
-
-    final int OPC_if_icmpne = 160;
-
-    final int OPC_if_icmplt = 161;
-
-    final int OPC_if_icmpge = 162;
-
-    final int OPC_if_icmpgt = 163;
-
-    final int OPC_if_icmple = 164;
-
-    final int OPC_if_acmpeq = 165;
-
-    final int OPC_if_acmpne = 166;
-
-    final int OPC_goto = 167;
-
-    final int OPC_jsr = 168;
-
-    final int OPC_ret = 169;
-
-    final int OPC_tableswitch = 170;
-
-    final int OPC_lookupswitch = 171;
-
-    final int OPC_ireturn = 172;
-
-    final int OPC_lreturn = 173;
-
-    final int OPC_freturn = 174;
-
-    final int OPC_dreturn = 175;
-
-    final int OPC_areturn = 176;
-
-    final int OPC_return = 177;
-
-    final int OPC_getstatic = 178;
-
-    final int OPC_putstatic = 179;
-
-    final int OPC_getfield = 180;
-
-    final int OPC_putfield = 181;
-
-    final int OPC_invokevirtual = 182;
-
-    final int OPC_invokespecial = 183;
-
-    final int OPC_invokestatic = 184;
-
-    final int OPC_invokeinterface = 185;
-
-    final int OPC_new = 187;
-
-    final int OPC_newarray = 188;
-
-    final int OPC_anewarray = 189;
-
-    final int OPC_arraylength = 190;
-
-    final int OPC_athrow = 191;
-
-    final int OPC_checkcast = 192;
-
-    final int OPC_instanceof = 193;
-
-    final int OPC_monitorenter = 194;
-
-    final int OPC_monitorexit = 195;
-
-    final int OPC_wide = 196;
-
-    final int OPC_multianewarray = 197;
-
-    final int OPC_ifnull = 198;
-
-    final int OPC_ifnonnull = 199;
-
-    final int OPC_goto_w = 200;
-
-    final int OPC_jsr_w = 201;
-}
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyMethod.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyMethod.java
deleted file mode 100644
index cd112b5..0000000
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyMethod.java
+++ /dev/null
@@ -1,132 +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.luni.internal.reflect;
-
-import java.lang.reflect.Method;
-
-import org.apache.harmony.luni.util.Msg;
-
-class ProxyMethod {
-    Method method;
-
-    Class[] commonExceptions;
-
-    ProxyMethod(Method method) {
-        this.method = method;
-        this.commonExceptions = method.getExceptionTypes();
-    }
-
-    Class[] getCheckedExceptions() {
-        Class[] newExceptions = commonExceptions.clone();
-        int cLength = newExceptions.length;
-        for (int c = 0, cL = cLength; c < cL; c++) {
-            Class<?> ex = newExceptions[c];
-            if (Throwable.class == ex) {
-                // if Throwable is included then treat as if no exceptions are
-                // checked
-                return new Class[0];
-            }
-            if (Error.class.isAssignableFrom(ex) || RuntimeException.class.isAssignableFrom(ex)) {
-                newExceptions[c] = null;
-                cLength--;
-            }
-        }
-
-        // All errors & runtime exceptions are passed back without being wrapped
-        Class[] result = new Class[cLength + 2];
-        int index = 0;
-        result[index++] = Error.class;
-        result[index++] = RuntimeException.class;
-        for (Class<?> ex : newExceptions) {
-            if (ex != null) {
-                result[index++] = ex;
-            }
-        }
-        return result;
-    }
-
-    boolean matchMethod(Method otherMethod) {
-        if (!method.getName().equals(otherMethod.getName())) {
-            return false;
-        }
-
-        Class[] params1 = method.getParameterTypes();
-        Class[] params2 = otherMethod.getParameterTypes();
-        int p = params1.length;
-        if (p != params2.length) {
-            return false;
-        }
-        while (--p >= 0) {
-            if (params1[p] != params2[p]) {
-                return false;
-            }
-        }
-
-        Class<?> thisMethodReturnType = method.getReturnType();
-        Class<?> otherMethodReturnType = otherMethod.getReturnType();
-        if (!thisMethodReturnType.isAssignableFrom(otherMethodReturnType)) {
-            if (otherMethodReturnType.isAssignableFrom(thisMethodReturnType)) {
-                // substitute returnType of method with that of otherMethod
-                method = otherMethod;
-            } else {
-                throw new IllegalArgumentException(Msg.getString("K00f2",
-                        method.getName()));
-            }
-        }        
-        
-        if (commonExceptions.length != 0) {
-            Class[] otherExceptions = otherMethod.getExceptionTypes();
-            if (otherExceptions.length == 0) {
-                commonExceptions = otherExceptions;
-            } else {
-                int cLength = commonExceptions.length;
-                nextException: for (int c = 0, cL = cLength, oL = otherExceptions.length; c < cL; c++) {
-                    Class<?> cException = commonExceptions[c];
-                    for (int o = 0; o < oL; o++) {
-                        Class<?> oException = otherExceptions[o];
-                        if (cException == oException) {
-                            continue nextException;
-                        }
-                        if (oException.isAssignableFrom(cException)) {
-                            continue nextException; // cException is a subclass
-                        }
-                        if (cException.isAssignableFrom(oException)) {
-                            // oException is a subclass, keep it instead
-                            commonExceptions[c] = cException = oException;
-                            continue nextException;
-                        }
-                    }
-                    commonExceptions[c] = null;
-                    cLength--;
-                }
-                if (cLength != commonExceptions.length) {
-                    Class[] newExceptions = new Class[cLength];
-                    for (int i = 0, j = 0, length = commonExceptions.length; i < length; i++) {
-                        Class<?> ex = commonExceptions[i];
-                        if (ex != null) {
-                            newExceptions[j++] = ex;
-                        }
-                    }
-                    commonExceptions = newExceptions;
-                }
-            }
-        }
-        return true;
-    }
-
-}
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyNameAndTypeCache.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyNameAndTypeCache.java
deleted file mode 100644
index 09eb23e..0000000
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyNameAndTypeCache.java
+++ /dev/null
@@ -1,105 +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.luni.internal.reflect;
-
-class ProxyNameAndTypeCache {
-    int[][] keyTable;
-
-    int[] valueTable;
-
-    int elementSize;
-
-    int threshold;
-
-    ProxyNameAndTypeCache(int initialCapacity) {
-        if (initialCapacity < 13) {
-            initialCapacity = 13;
-        }
-        this.elementSize = 0;
-        this.threshold = (int) (initialCapacity * 0.66f);
-        this.keyTable = new int[initialCapacity][];
-        this.valueTable = new int[initialCapacity];
-    }
-
-    int get(int[] key) {
-        int index = hashCode(key);
-        while (keyTable[index] != null) {
-            if (keyTable[index][0] == key[0] && keyTable[index][1] == key[1]) {
-                return valueTable[index];
-            }
-            index = (index + 1) % keyTable.length;
-        }
-        return -1;
-    }
-
-    int hashCode(int[] key) {
-        return (key[0] + key[1]) % keyTable.length;
-    }
-
-    int put(int[] key, int value) {
-        int index = hashCode(key);
-        while (keyTable[index] != null) {
-            if (keyTable[index][0] == key[0] && keyTable[index][1] == key[1]) {
-                return valueTable[index] = value;
-            }
-            index = (index + 1) % keyTable.length;
-        }
-        keyTable[index] = key;
-        valueTable[index] = value;
-
-        // assumes the threshold is never equal to the size of the table
-        if (++elementSize > threshold) {
-            rehash();
-        }
-        return value;
-    }
-
-    private void rehash() {
-        ProxyNameAndTypeCache newHashtable = new ProxyNameAndTypeCache(keyTable.length * 2);
-        for (int i = keyTable.length; --i >= 0;) {
-            if (keyTable[i] != null) {
-                newHashtable.put(keyTable[i], valueTable[i]);
-            }
-        }
-
-        this.keyTable = newHashtable.keyTable;
-        this.valueTable = newHashtable.valueTable;
-        this.threshold = newHashtable.threshold;
-    }
-
-    int size() {
-        return elementSize;
-    }
-
-    @Override
-    public String toString() {
-        int max = size();
-        StringBuilder buf = new StringBuilder();
-        buf.append("{");
-        for (int i = 0; i < max; ++i) {
-            if (keyTable[i] != null) {
-                buf.append(keyTable[i]).append("->").append(valueTable[i]);
-            }
-            if (i < max) {
-                buf.append(", ");
-            }
-        }
-        buf.append("}");
-        return buf.toString();
-    }
-}
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyObjectCache.java b/libcore/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyObjectCache.java
deleted file mode 100644
index b3089c5..0000000
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/internal/reflect/ProxyObjectCache.java
+++ /dev/null
@@ -1,106 +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.luni.internal.reflect;
-
-class ProxyObjectCache {
-    Object keyTable[];
-
-    int valueTable[];
-
-    int elementSize;
-
-    int threshold;
-
-    ProxyObjectCache(int initialCapacity) {
-        if (initialCapacity < 13) {
-            initialCapacity = 13;
-        }
-        this.elementSize = 0;
-        this.threshold = (int) (initialCapacity * 0.66f);
-        this.keyTable = new Object[initialCapacity];
-        this.valueTable = new int[initialCapacity];
-    }
-
-    int get(Object key) {
-        int index = hashCode(key);
-        while (keyTable[index] != null) {
-            if (keyTable[index].equals(key)) {
-                return valueTable[index];
-            }
-            index = (index + 1) % keyTable.length;
-        }
-        return -1;
-    }
-
-    int hashCode(Object key) {
-        return (key.hashCode() & 0x7FFFFFFF) % keyTable.length;
-    }
-
-    int put(Object key, int value) {
-        int index = hashCode(key);
-        while (keyTable[index] != null) {
-            if (keyTable[index].equals(key)) {
-                return valueTable[index] = value;
-            }
-            index = (index + 1) % keyTable.length;
-        }
-        keyTable[index] = key;
-        valueTable[index] = value;
-
-        // assumes the threshold is never equal to the size of the table
-        if (++elementSize > threshold) {
-            rehash();
-        }
-        return value;
-    }
-
-    private void rehash() {
-        ProxyObjectCache newHashtable = new ProxyObjectCache(
-                keyTable.length * 2);
-        for (int i = keyTable.length; --i >= 0;) {
-            if (keyTable[i] != null) {
-                newHashtable.put(keyTable[i], valueTable[i]);
-            }
-        }
-
-        this.keyTable = newHashtable.keyTable;
-        this.valueTable = newHashtable.valueTable;
-        this.threshold = newHashtable.threshold;
-    }
-
-    int size() {
-        return elementSize;
-    }
-
-    @Override
-    public String toString() {
-        int max = size();
-        StringBuilder buf = new StringBuilder();
-        buf.append("{"); //$NON-NLS-1$
-        for (int i = 0; i < max; ++i) {
-            if (keyTable[i] != null) {
-                buf.append(keyTable[i]).append("->").append(valueTable[i]); //$NON-NLS-1$
-            }
-            if (i < max) {
-                buf.append(", "); //$NON-NLS-1$
-            }
-        }
-        buf.append("}"); //$NON-NLS-1$
-        return buf.toString();
-    }
-}
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 230df13..ac0c877 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
@@ -42,7 +42,7 @@
  * support security checks. Alternative types of DatagramSocketImpl's may be
  * used by setting the <code>impl.prefix</code> system property.
  */
-class PlainDatagramSocketImpl extends DatagramSocketImpl {
+public class PlainDatagramSocketImpl extends DatagramSocketImpl {
 
     static final int MULTICAST_IF = 1;
 
@@ -70,7 +70,8 @@
      */
     static final int REUSEADDR_AND_REUSEPORT = 10001;
 
-    private boolean bindToDevice;
+    // Ignored in native code
+    private boolean bindToDevice = false;
 
     private byte[] ipaddress = { 0, 0, 0, 0 };
 
@@ -116,7 +117,7 @@
     public void bind(int port, InetAddress addr) throws SocketException {
         String prop = AccessController.doPrivileged(new PriviAction<String>("bindToDevice")); //$NON-NLS-1$
         boolean useBindToDevice = prop != null && prop.toLowerCase().equals("true"); //$NON-NLS-1$
-        bindToDevice = netImpl.bind2(fd, port, useBindToDevice, addr);
+        netImpl.bind(fd, addr, port);
         if (0 != port) {
             localPort = port;
         } else {
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/net/PlainMulticastSocketImpl.java b/libcore/luni/src/main/java/org/apache/harmony/luni/net/PlainMulticastSocketImpl.java
deleted file mode 100644
index 7f5ac50..0000000
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/net/PlainMulticastSocketImpl.java
+++ /dev/null
@@ -1,38 +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.luni.net;
-
-import java.net.SocketException;
-
-import org.apache.harmony.luni.platform.Platform;
-
-/**
- * This class was added so we can create sockets with options that are needed
- * for server sockets. It just overrides create so that we call new natives
- * which only set the options required for server sockets. In order to preserve
- * behaviour of older versions the create PlainSocketImpl was left as is and
- * this new class was added. For newer versions an instance of this class is
- * used, for earlier versions the original PlainSocketImpl is used.
- */
-class PlainMulticastSocketImpl extends PlainDatagramSocketImpl {
-
-    @Override
-    public void create() throws SocketException {
-        Platform.getNetworkSystem().createMulticastSocket(fd, NetUtil.preferIPv4Stack());
-    }
-}
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/net/PlainServerSocketImpl.java b/libcore/luni/src/main/java/org/apache/harmony/luni/net/PlainServerSocketImpl.java
index de6cb8f..4343ffb 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/net/PlainServerSocketImpl.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/net/PlainServerSocketImpl.java
@@ -24,14 +24,10 @@
 import org.apache.harmony.luni.net.PlainSocketImpl;
 
 /**
- * This class was added so we can create sockets with options that are needed
- * for server sockets. It just overrides create so that we call new natives
- * which only set the options required for server sockets. In order to preserve
- * behaviour of older versions the create PlainSocketImpl was left as is and
- * this new class was added. For newer versions an instance of this class is
- * used, for earlier versions the original PlainSocketImpl is used.
+ * This class overrides create to call natives that set the options required
+ * for server sockets.
  */
-class PlainServerSocketImpl extends PlainSocketImpl {
+public class PlainServerSocketImpl extends PlainSocketImpl {
 
     public PlainServerSocketImpl() {
         super();
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl.java b/libcore/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl.java
index 4fb8b91..9a3ae6e 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl.java
@@ -43,7 +43,7 @@
 /**
  * A concrete connected-socket implementation.
  */
-class PlainSocketImpl extends SocketImpl {
+public class PlainSocketImpl extends SocketImpl {
 
     // Const copy from socket
 
@@ -89,6 +89,27 @@
         fd = new FileDescriptor();
     }
 
+    public PlainSocketImpl(FileDescriptor fd) {
+        super();
+        this.fd = fd;
+    }
+
+    /**
+     * creates an instance with specified proxy.
+     */
+    public PlainSocketImpl(Proxy proxy) {
+        this();
+        this.proxy = proxy;
+    }
+
+    public PlainSocketImpl(FileDescriptor fd, int localport, InetAddress addr, int port) {
+        super();
+        this.fd = fd;
+        this.localport = localport;
+        this.address = addr;
+        this.port = port;
+    }
+
     @Override
     protected void accept(SocketImpl newImpl) throws IOException {
         if (NetUtil.usingSocks(proxy)) {
@@ -160,7 +181,7 @@
 
     @Override
     protected void bind(InetAddress anAddr, int aPort) throws IOException {
-        netImpl.bind(fd, aPort, anAddr);
+        netImpl.bind(fd, anAddr, aPort);
         // PlainSocketImpl2.socketBindImpl2(fd, aPort, anAddr);
         address = anAddr;
         if (0 != aPort) {
@@ -201,7 +222,7 @@
 
     /**
      * Connects this socket to the specified remote host address/port.
-     * 
+     *
      * @param anAddr
      *            the remote host address to connect to
      * @param aPort
@@ -211,13 +232,10 @@
      * @throws IOException
      *             if an error occurs while connecting
      */
-    // BEGIN android-changed
-    // copied from a newer harmony revision
     private void connect(InetAddress anAddr, int aPort, int timeout)
             throws IOException {
-        InetAddress normalAddr = anAddr.isAnyLocalAddress() ? InetAddress
-                .getLocalHost() : anAddr;
 
+        InetAddress normalAddr = anAddr.isAnyLocalAddress() ? InetAddress.getLocalHost() : anAddr;
         try {
             if (streaming) {
                 if (NetUtil.usingSocks(proxy)) {
@@ -231,7 +249,7 @@
                     }
                 }
             } else {
-                netImpl.connectDatagram(fd, aPort, trafficClass, normalAddr);
+            	netImpl.connectDatagram(fd, aPort, trafficClass, normalAddr);
             }
         } catch (ConnectException e) {
             throw new ConnectException(anAddr + ":" + aPort + " - "
@@ -240,16 +258,12 @@
         super.address = normalAddr;
         super.port = aPort;
     }
-    // END android-changed
 
     @Override
     protected void create(boolean streaming) throws IOException {
         this.streaming = streaming;
         if (streaming) {
-            // BEGIN android-changed
-            // call createSocket instead of createStreamSocket
-            netImpl.createSocket(fd, NetUtil.preferIPv4Stack());
-            // END android-changed
+            netImpl.createStreamSocket(fd, NetUtil.preferIPv4Stack());
         } else {
             netImpl.createDatagramSocket(fd, NetUtil.preferIPv4Stack());
         }
@@ -546,16 +560,19 @@
         if (shutdownInput) {
             return -1;
         }
-        try {
-            int read = netImpl.receiveStream(fd, buffer, offset, count,
-                    receiveTimeout);
-            if (read == -1) {
-                shutdownInput = true;
-            }
-            return read;
-        } catch (InterruptedIOException e) {
-            throw new SocketTimeoutException(e.getMessage());
+        // BEGIN android-changed
+        // call receiveStream() instead of read()
+        int read = netImpl.receiveStream(fd, buffer, offset, count, receiveTimeout);
+        // END android-changed
+        // Return of zero bytes for a blocking socket means a timeout occurred
+        if (read == 0) {
+            throw new SocketTimeoutException();
         }
+        // Return of -1 indicates the peer was closed
+        if (read == -1) {
+            shutdownInput = true;
+        }
+        return read;
     }
 
     int write(byte[] buffer, int offset, int count) throws IOException {
@@ -563,6 +580,9 @@
             return netImpl.sendDatagram2(fd, buffer, offset, count, port,
                     address);
         }
+        // BEGIN android-changed
+        // call sendStream() instead of write()
         return netImpl.sendStream(fd, buffer, offset, count);
+        // END android-changed
     }
 }
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl2.java b/libcore/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl2.java
deleted file mode 100644
index 160de7c..0000000
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl2.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.luni.net;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.Proxy;
-
-/**
- * This class was added so we can create sockets without options that were
- * needed for server sockets. It just overrides create so that we call new
- * natives which only set the options required for plain sockets. In order to
- * preserve behaviour of older versions the create PlainSocketImpl was left as
- * is and this new class was added. For newer versions an instance of this class
- * is used, for earlier versions the original PlainSocketImpl is used.
- */
-class PlainSocketImpl2 extends PlainSocketImpl {
-
-    public PlainSocketImpl2(FileDescriptor fd, int localport, InetAddress addr, int port) {
-        super();
-        super.fd = fd;
-        super.localport = localport;
-        super.address = addr;
-        super.port = port;
-    }
-
-    public PlainSocketImpl2() {
-        super();
-    }
-
-    /**
-     * creates an instance with specified proxy.
-     */
-    public PlainSocketImpl2(Proxy proxy) {
-        super();
-        this.proxy = proxy;
-    }
-
-    @Override
-    protected void create(boolean isStreaming) throws IOException {
-        streaming = isStreaming;
-        if (isStreaming) {
-            netImpl.createSocket(fd, NetUtil.preferIPv4Stack());
-        } else {
-            netImpl.createDatagramSocket(fd, NetUtil.preferIPv4Stack());
-        }
-    }
-}
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/net/SocketImplProvider.java b/libcore/luni/src/main/java/org/apache/harmony/luni/net/SocketImplProvider.java
deleted file mode 100644
index e8e7dc3..0000000
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/net/SocketImplProvider.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.luni.net;
-
-import java.io.FileDescriptor;
-import java.net.DatagramSocketImpl;
-import java.net.InetAddress;
-import java.net.Proxy;
-import java.net.SocketImpl;
-
-public class SocketImplProvider {
-
-    public static SocketImpl getSocketImpl() {
-        return new PlainSocketImpl2();
-    }
-
-    /**
-     * gets a SocketImpl with specified proxy.
-     */
-    public static SocketImpl getSocketImpl(Proxy proxy) {
-        return new PlainSocketImpl2(proxy);
-    }
-
-    public static SocketImpl getSocketImpl(FileDescriptor fd, int localport, InetAddress addr,
-            int port) {
-        return new PlainSocketImpl2(fd, localport, addr, port);
-    }
-
-    public static SocketImpl getServerSocketImpl() {
-        return new PlainServerSocketImpl();
-    }
-
-    public static SocketImpl getServerSocketImpl(FileDescriptor fd) {
-        return new PlainServerSocketImpl(fd);
-    }
-
-    public static DatagramSocketImpl getDatagramSocketImpl() {
-        return new PlainDatagramSocketImpl();
-    }
-
-    public static DatagramSocketImpl getMulticastSocketImpl() {
-        return new PlainMulticastSocketImpl();
-    }
-
-    public static DatagramSocketImpl getDatagramSocketImpl(FileDescriptor fd, int localPort) {
-        return new PlainDatagramSocketImpl(fd, localPort);
-    }
-
-}
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/AbstractMemorySpy.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/AbstractMemorySpy.java
index 130454f..5462cf0 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/AbstractMemorySpy.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/AbstractMemorySpy.java
@@ -30,84 +30,82 @@
  */
 abstract class AbstractMemorySpy implements IMemorySpy {
 
-    // TODO: figure out how to prevent this being a synchronization bottleneck
-    protected Map<PlatformAddress,AddressWrapper> memoryInUse = new HashMap<PlatformAddress, AddressWrapper>(); // Shadow to Wrapper
+	// TODO: figure out how to prevent this being a synchronization bottleneck
+	protected Map<PlatformAddress,AddressWrapper> memoryInUse = new HashMap<PlatformAddress, AddressWrapper>(); // Shadow to Wrapper
 
-    protected Map<Reference,PlatformAddress> refToShadow = new HashMap<Reference, PlatformAddress>(); // Reference to Shadow
+	protected Map<Reference,PlatformAddress> refToShadow = new HashMap<Reference, PlatformAddress>(); // Reference to Shadow
 
-    protected ReferenceQueue<Object> notifyQueue = new ReferenceQueue<Object>();
+	protected ReferenceQueue<Object> notifyQueue = new ReferenceQueue<Object>();
 
-       final class AddressWrapper {
-        final PlatformAddress shadow;
+   	final class AddressWrapper {
+		final PlatformAddress shadow;
 
-        final PhantomReference<PlatformAddress> wrAddress;
+		final PhantomReference<PlatformAddress> wrAddress;
 
-        volatile boolean autoFree = false;
+		volatile boolean autoFree = false;
 
-        AddressWrapper(PlatformAddress address) {
-            super();
-            this.shadow = address.duplicate();
-            this.wrAddress = new PhantomReference<PlatformAddress>(address, notifyQueue);
-        }
-    }
+		AddressWrapper(PlatformAddress address) {
+			super();
+			this.shadow = address.duplicate();
+			this.wrAddress = new PhantomReference<PlatformAddress>(address, notifyQueue);
+		}
+	}
 
-    public AbstractMemorySpy() {
-        super();
-    }
+	public AbstractMemorySpy() {
+		super();
+	}
 
-    public void alloc(PlatformAddress address) {
-        AddressWrapper wrapper = new AddressWrapper(address);
-        synchronized (this) {
-            memoryInUse.put(wrapper.shadow, wrapper);
-            refToShadow.put(wrapper.wrAddress, wrapper.shadow);
-        }
-    }
+	public void alloc(PlatformAddress address) {
+		AddressWrapper wrapper = new AddressWrapper(address);
+		synchronized (this) {
+			memoryInUse.put(wrapper.shadow, wrapper);
+			refToShadow.put(wrapper.wrAddress, wrapper.shadow);
+		}
+	}
 
-    public boolean free(PlatformAddress address) {
-        AddressWrapper wrapper;
-        synchronized (this) {
-            wrapper = memoryInUse.remove(address);
+	public boolean free(PlatformAddress address) {
+		AddressWrapper wrapper;
+		synchronized (this) {
+			wrapper = memoryInUse.remove(address);
             // BEGIN android-added
             if (wrapper != null) {
                 refToShadow.remove(wrapper.wrAddress);
             }
             // END android-added
-        }
-        if (wrapper == null) {
-            // Attempt to free memory we didn't alloc
-            System.err
-                    .println("Memory Spy! Fixed attempt to free memory that was not allocated " + address); //$NON-NLS-1$
-        }
-        return wrapper != null;
-    }
+		}
+		if (wrapper == null) {
+			// Attempt to free memory we didn't alloc
+			System.err
+					.println("Memory Spy! Fixed attempt to free memory that was not allocated " + address); //$NON-NLS-1$
+		}
+		return wrapper != null;
+	}
 
-    public void rangeCheck(PlatformAddress address, int offset, int length)
-            throws IndexOutOfBoundsException {
-        // Do nothing
-    }
+	public void rangeCheck(PlatformAddress address, int offset, int length)
+			throws IndexOutOfBoundsException {
+		// Do nothing
+	}
 
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.apache.harmony.luni.platform.struct.IMemorySpy#autoFree(org.apache.harmony.luni.platform.struct.PlatformAddress)
-     */
-    public void autoFree(PlatformAddress address) {
-        AddressWrapper wrapper;
-        synchronized (this) {
-            wrapper = memoryInUse.get(address);
-        }
-        if (wrapper != null) {
-            wrapper.autoFree = true;
-        }
-    }
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.apache.harmony.luni.platform.struct.IMemorySpy#autoFree(org.apache.harmony.luni.platform.struct.PlatformAddress)
+	 */
+	public void autoFree(PlatformAddress address) {
+		AddressWrapper wrapper;
+		synchronized (this) {
+			wrapper = memoryInUse.get(address);
+		}
+		if (wrapper != null) {
+			wrapper.autoFree = true;
+		}
+	}
 
-    protected void orphanedMemory(Reference ref) {
-        AddressWrapper wrapper;
-        // BEGIN android-changed
-        // copied from newer version of harmony
-        synchronized (this) {
-            PlatformAddress shadow = refToShadow.remove(ref);
-            wrapper = memoryInUse.get(shadow);
+	protected void orphanedMemory(Reference ref) {
+		AddressWrapper wrapper;
+		synchronized (this) {
+			PlatformAddress shadow = refToShadow.remove(ref);
+			wrapper = memoryInUse.get(shadow);
             if (wrapper != null) {
                 // There is a leak if we were not auto-freeing this memory.
                 if (!wrapper.autoFree) {
@@ -116,8 +114,7 @@
                 }
                 wrapper.shadow.free();
             }
-        }
+		}
         ref.clear();
-        // END android-changed
-    }
+	}
 }
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/AdapterManager.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/AdapterManager.java
deleted file mode 100644
index 2380fbc..0000000
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/AdapterManager.java
+++ /dev/null
@@ -1,79 +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.luni.platform;
-
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * Adapter Manager
- *  
- */
-final class AdapterManager implements IAdapterManager {
-
-    /*
-     * key is adaptable type, and value is list of adapter factories for that
-     * type.
-     */
-    private final HashMap<Class, List<IAdapterFactory>> factories = new HashMap<Class, List<IAdapterFactory>>();
-
-    public Object getAdapter(IAdaptable adaptable, Class adapterType) {
-        List factoryList = factories.get(adapterType);
-        if (factoryList != null) {
-            for (Iterator factoryItr = factoryList.iterator(); factoryItr
-                    .hasNext();) {
-                IAdapterFactory factory = (IAdapterFactory) factoryItr.next();
-                Object adapter = factory.getAdapter(adaptable, adapterType);
-                if (adapter != null) {
-                    return adapter;
-                }
-            }
-        }
-        return null;
-    }
-
-    public boolean hasAdapter(IAdaptable adaptable, Class adapterType) {
-        return null == getAdapter(adaptable, adapterType);
-    }
-
-    public void registerAdapters(IAdapterFactory factory, Class adaptable) {
-        List<IAdapterFactory> factoryList = factories.get(adaptable);
-        if (factoryList == null) {
-            factoryList = new ArrayList<IAdapterFactory>();
-            factories.put(adaptable, factoryList);
-        }
-        factoryList.add(factory);
-    }
-
-    public void unregisterAdapters(IAdapterFactory factory, Class adaptable) {
-        List factoryList = factories.get(adaptable);
-        if (factoryList != null) {
-            factoryList.remove(factory);
-        }
-    }
-
-    public void unregisterAdapters(IAdapterFactory factory) {
-        for (Iterator<Class> knownAdaptablesItr = factories.keySet().iterator(); knownAdaptablesItr
-                .hasNext();) {
-            Class adaptable = knownAdaptablesItr.next();
-            unregisterAdapters(factory, adaptable);
-        }
-    }
-}
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IAdaptable.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IAdaptable.java
deleted file mode 100644
index e4c72ea..0000000
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IAdaptable.java
+++ /dev/null
@@ -1,54 +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.luni.platform;
-
-
-/**
- * The interface to extensible objects.
- * <p>
- * Classes can implement this interface (a single method) to provide interfaces
- * that are not API -- each interface type has to be handled in the
- * implementation of <code>getAdapter(Class)</code>. This is a good way to
- * extend the class without breaking existing API.
- * </p>
- * <p>
- * In addition, classes can be augmented by interfaces that are defined by other
- * classes (which requires the <code>getAdapter(Class)</code> to be
- * implemented by a factory.
- * 
- */
-public interface IAdaptable {
-
-    /**
-     * Returns the adapter corresponding to the given class.
-     * <p>
-     * The adapter is typically obtained using the class literal, like this:
-     * 
-     * <pre>
-     *    ...
-     *    IAdaptable = (IAdaptable) foo;
-     *    IMyInterface bar = (IMyInterface)foo.getAdapter(IMyInterface.class);
-     *    bar.doMyThing();
-     *    ...
-     * </pre>
-     * 
-     * @param adapter
-     *            the type of adapter requested
-     * @return the adapter
-     */
-    public Object getAdapter(Class adapter);
-}
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IAdapterFactory.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IAdapterFactory.java
deleted file mode 100644
index 49fcd15..0000000
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IAdapterFactory.java
+++ /dev/null
@@ -1,43 +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.luni.platform;
-
-
-/**
- * IAdapterFactory
- * 
- */
-public interface IAdapterFactory {
-
-    /**
-     * Answer the adapter of the given type for the given object.
-     * 
-     * @param adaptableObject
-     *            the object that implements IAdaptable.
-     * @param adapterType
-     *            the type of adapter to return.
-     * @return the adapter of the requested type.
-     */
-    public Object getAdapter(IAdaptable adaptableObject, Class adapterType);
-
-    /**
-     * Returns the adapters that this factory provides.
-     * 
-     * @return the list of adapters as an array of classes.
-     */
-    public Class[] getAdapterList();
-}
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IAdapterManager.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IAdapterManager.java
deleted file mode 100644
index 886dda7..0000000
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IAdapterManager.java
+++ /dev/null
@@ -1,34 +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.luni.platform;
-
-
-/**
- * IAdapterManager
- * 
- */
-public interface IAdapterManager {
-    public Object getAdapter(IAdaptable adaptable, Class adapterType);
-
-    public boolean hasAdapter(IAdaptable adaptable, Class adapterType);
-
-    public void registerAdapters(IAdapterFactory factory, Class adaptable);
-
-    public void unregisterAdapters(IAdapterFactory factory);
-
-    public void unregisterAdapters(IAdapterFactory factory, Class adaptable);
-}
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 fb2ff9d..7613f0e 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
@@ -29,7 +29,7 @@
  * TODO Type description
  * 
  */
-public interface IFileSystem extends ISystemComponent {
+public interface IFileSystem {
 
     public final int SHARED_LOCK_TYPE = 1;
 
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IMemorySystem.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IMemorySystem.java
index b765c7d..6e8028a 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IMemorySystem.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IMemorySystem.java
@@ -30,10 +30,22 @@
  */
 public interface IMemorySystem {
 
+    /**
+     * The constant representing read-only access to data in a memory map
+     * request.
+     */
     public final int MMAP_READ_ONLY = 1;
 
+    /**
+     * The constant representing read-write access to data in a memory map
+     * request.
+     */
     public final int MMAP_READ_WRITE = 2;
 
+    /**
+     * The constant representing copy-on-write access to data in a memory map
+     * request.
+     */
     public final int MMAP_WRITE_COPY = 4;
 
     /**
@@ -243,7 +255,17 @@
             throws NullPointerException, IndexOutOfBoundsException;
     // END android-added
 
-    // Primitive get & set methods
+    /**
+     * Returns the value of a single byte at the given address.
+     * <p>
+     * The behavior is unspecified if <code>address</code> is not in the range
+     * that was previously allocated using <code>malloc()</code>.
+     * </p>
+     *
+     * @param address
+     *            the address at which to get the byte value.
+     * @return the value of the byte.
+     */
     public byte getByte(int address);
 
     /**
@@ -275,6 +297,21 @@
      */
     public short getShort(int address);
 
+    /**
+     * Gets the value of the signed two-byte integer stored in the given byte
+     * order at the given address.
+     * <p>
+     * The behavior is unspecified if <code>(address ... address + 2)</code> is
+     * not wholly within the range that was previously allocated using
+     * <code>malloc()</code>.
+     * </p>
+     *
+     * @param address
+     *            the platform address of the start of the two-byte value.
+     * @param endianness
+     *            the required interpretation of the short endianness.
+     * @return the value of the two-byte integer as a Java <code>short</code>.
+     */
     public short getShort(int address, Endianness endianness);
 
     /**
@@ -474,17 +511,25 @@
     public void setAddress(int address, int value);
 
     /**
-     * TODO: JavaDoc
-     * 
+     * Map file content into memory.
+     *
      * @param fileDescriptor
+     *            a handle to the file that is to be memory mapped.
      * @param alignment
+     *            the offset in the file where the mapping should begin.
      * @param size
+     *            the number of bytes that are requested to map.
      * @param mapMode
-     * @return
+     *            the desired access mode as defined by one of the constants
+     *            {@link IMemorySystem#MMAP_READ_ONLY},
+     *            {@link IMemorySystem#MMAP_READ_WRITE},
+     *            {@link IMemorySystem#MMAP_WRITE_COPY}
+     * @return the start address of the mapped memory area.
      * @throws IOException
+     *             if an exception occurs mapping the file into memory.
      */
-    public int mmap(int fileDescriptor, long alignment, long size,
-            int mapMode) throws IOException;
+    public int mmap(int fileDescriptor, long alignment, long size,  int mapMode)
+            throws IOException;
 
     /**
      * TODO: JavaDoc
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 9f70515..fb47f0d 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
@@ -29,17 +29,12 @@
 import java.net.SocketImpl;
 import java.net.UnknownHostException;
 import java.nio.channels.Channel;
-import java.nio.channels.SelectableChannel;
 
 /*
  * The interface for network methods.
  */
 public interface INetworkSystem {
 
-    // -----------------------------------------------
-    // Class Const
-    // -----------------------------------------------
-
     /*
      * Socket connect Step start
      */
@@ -50,34 +45,24 @@
      */
     public final int SOCKET_CONNECT_STEP_CHECK = 1;
 
-    // -----------------------------------------------
-    // Methods
-    // -----------------------------------------------
-
     /*
      * socket accept
      */
     public void accept(FileDescriptor fdServer, SocketImpl newSocket,
             FileDescriptor fdnewSocket, int timeout) throws IOException;
 
-    public void bind(FileDescriptor aFD, int port, InetAddress inetAddress)
+    public void bind(FileDescriptor aFD, InetAddress inetAddress, int port)
             throws SocketException;
 
-    public boolean bind2(FileDescriptor aFD, int port, boolean bindToDevice,
-            InetAddress inetAddress) throws SocketException;
-
-    public void createSocket(FileDescriptor fd, boolean preferIPv4Stack)
-            throws IOException;
-
     public int read(FileDescriptor aFD, byte[] data, int offset, int count,
             int timeout) throws IOException;
-    
+
     public int readDirect(FileDescriptor aFD, int address, int offset, int count,
             int timeout) throws IOException;
 
     public int write(FileDescriptor fd, byte[] data, int offset, int count)
             throws IOException;
-    
+
     public int writeDirect(FileDescriptor fd, int address, int offset, int count)
             throws IOException;
 
@@ -96,7 +81,7 @@
     public int sendDatagram(FileDescriptor fd, byte[] data, int offset,
             int length, int port, boolean bindToDevice, int trafficClass,
             InetAddress inetAddress) throws IOException;
-    
+
     public int sendDatagramDirect(FileDescriptor fd, int address, int offset,
             int length, int port, boolean bindToDevice, int trafficClass,
             InetAddress inetAddress) throws IOException;
@@ -104,7 +89,7 @@
     public int receiveDatagram(FileDescriptor aFD, DatagramPacket packet,
             byte[] data, int offset, int length, int receiveTimeout,
             boolean peek) throws IOException;
-    
+
     public int receiveDatagramDirect(FileDescriptor aFD, DatagramPacket packet,
             int address, int offset, int length, int receiveTimeout,
             boolean peek) throws IOException;
@@ -112,17 +97,17 @@
     public int recvConnectedDatagram(FileDescriptor aFD, DatagramPacket packet,
             byte[] data, int offset, int length, int receiveTimeout,
             boolean peek) throws IOException;
-    
+
     public int recvConnectedDatagramDirect(FileDescriptor aFD,
             DatagramPacket packet, int address, int offset, int length,
             int receiveTimeout, boolean peek) throws IOException;
-    
+
     public int peekDatagram(FileDescriptor aFD, InetAddress sender,
             int receiveTimeout) throws IOException;
 
     public int sendConnectedDatagram(FileDescriptor fd, byte[] data,
             int offset, int length, boolean bindToDevice) throws IOException;
-    
+
     public int sendConnectedDatagramDirect(FileDescriptor fd, int address,
             int offset, int length, boolean bindToDevice) throws IOException;
 
@@ -134,17 +119,17 @@
     public void connectDatagram(FileDescriptor aFD, int port, int trafficClass,
             InetAddress inetAddress) throws SocketException;
 
-    public void createMulticastSocket(FileDescriptor aFD,
-            boolean preferIPv4Stack) throws SocketException;
-
-    public void createServerStreamSocket(FileDescriptor aFD,
-            boolean preferIPv4Stack) throws SocketException;
-
+    /**
+     * @deprecated Use {@link #read(FileDescriptor, byte[], int, int, int)}
+     */
+    @Deprecated
     public int receiveStream(FileDescriptor aFD, byte[] data, int offset,
             int count, int timeout) throws IOException;
 
+    // BEGIN android-added
     public int sendStream(FileDescriptor fd, byte[] data, int offset, int count)
             throws IOException;
+    // END android-added
 
     public void shutdownInput(FileDescriptor descriptor) throws IOException;
 
@@ -160,11 +145,14 @@
     // public void acceptStreamSocket(FileDescriptor fdServer,
     //         SocketImpl newSocket, FileDescriptor fdnewSocket, int timeout)
     //         throws IOException;
-    // 
-    // public void createStreamSocket(FileDescriptor aFD, boolean preferIPv4Stack)
-    //         throws SocketException;
     // END android-removed
 
+    public void createServerStreamSocket(FileDescriptor aFD, boolean preferIPv4Stack)
+            throws SocketException;
+
+    public void createStreamSocket(FileDescriptor aFD, boolean preferIPv4Stack)
+            throws SocketException;
+
     public void listenStreamSocket(FileDescriptor aFD, int backlog)
             throws SocketException;
 
@@ -184,7 +172,7 @@
 
     /*
      * Query the IP stack for the local port to which this socket is bound.
-     * 
+     *
      * @param aFD the socket descriptor @param preferIPv6Addresses address
      * preference for nodes that support both IPv4 and IPv6 @return int the
      * local port to which the socket is bound
@@ -194,10 +182,10 @@
 
     /*
      * Query the IP stack for the nominated socket option.
-     * 
+     *
      * @param aFD the socket descriptor @param opt the socket option type
      * @return the nominated socket option value
-     * 
+     *
      * @throws SocketException if the option is invalid
      */
     public Object getSocketOption(FileDescriptor aFD, int opt)
@@ -205,10 +193,10 @@
 
     /*
      * Set the nominated socket option in the IP stack.
-     * 
+     *
      * @param aFD the socket descriptor @param opt the option selector @param
      * optVal the nominated option value
-     * 
+     *
      * @throws SocketException if the option is invalid or cannot be set
      */
     public void setSocketOption(FileDescriptor aFD, int opt, Object optVal)
@@ -218,7 +206,7 @@
 
     /*
      * Close the socket in the IP stack.
-     * 
+     *
      * @param aFD the socket descriptor
      */
     public void socketClose(FileDescriptor aFD) throws IOException;
@@ -229,12 +217,20 @@
             throws UnknownHostException;
 
     public void setInetAddress(InetAddress sender, byte[] address);
-    
+
+    // BEGIN android-added
+    public String byteArrayToIpString(byte[] address)
+            throws UnknownHostException;
+
+    public byte[] ipStringToByteArray(String address)
+            throws UnknownHostException;
+    // END android-added
+
     // BEGIN android-removed
     // public boolean isReachableByICMP(InetAddress dest,InetAddress source,int ttl,int timeout);
     // END android-removed
-    
+
     public Channel inheritedChannel();
-    
+
     public void oneTimeInitialization(boolean jcl_supports_ipv6);
 }
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/ISystemComponent.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/ISystemComponent.java
deleted file mode 100644
index 29cf555..0000000
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/ISystemComponent.java
+++ /dev/null
@@ -1,26 +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.luni.platform;
-
-
-/**
- * ISystemComponent
- * 
- */
-public interface ISystemComponent extends IAdaptable {
-    /*empty*/
-}
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSComponent.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSComponent.java
deleted file mode 100644
index b5f14f2..0000000
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSComponent.java
+++ /dev/null
@@ -1,51 +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.luni.platform;
-
-
-//BEGIN android-changed
-import dalvik.system.VMStack;
-// END android-changed
-
-/**
- * OSComponent
- * 
- */
-class OSComponent implements IAdaptable {
-
-    /**
-     * 
-     */
-    public OSComponent() {
-        super();
-        // BEGIN android-changed
-        if (VMStack.getCallingClassLoader() != null) {
-            throw new SecurityException();
-        }
-        // END android-changed
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.apache.harmony.luni.platform.IAdaptable#getAdapter(java.lang.Class)
-     */
-    public Object getAdapter(Class adapter) {
-        return Platform.getAdapterManager().getAdapter(this, adapter);
-    }
-
-}
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSComponentFactory.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSComponentFactory.java
deleted file mode 100644
index a883ee0..0000000
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSComponentFactory.java
+++ /dev/null
@@ -1,49 +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.luni.platform;
-
-
-/**
- * OSComponentFactory
- * 
- */
-class OSComponentFactory {
-
-    /**
-     * @return OSFileSystem
-     */
-    public static IFileSystem getFileSystem() {
-        //  Auto-generated method stub
-        return new OSFileSystem();
-    }
-
-    /**
-     * @return OSMemory
-     */
-    public static IMemorySystem getMemorySystem() {
-        // Auto-generated method stub
-        return new OSMemory();
-    }
-
-    /**
-     * @return OSNetwork
-     */
-    public static INetworkSystem getNetworkSystem() {
-        return OSNetworkSystem.getOSNetworkSystem();
-    }
-
-}
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 2759d6b..08bdac6 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
@@ -24,17 +24,21 @@
 import java.io.FileDescriptor;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.io.UnsupportedEncodingException;
 
 /**
  * This is the portable implementation of the file system interface.
- * 
+ *
  */
-class OSFileSystem extends OSComponent implements IFileSystem {
+class OSFileSystem implements IFileSystem {
 
-    /**
-     * 
-     */
-    public OSFileSystem() {
+    private static final OSFileSystem singleton = new OSFileSystem();
+
+    public static OSFileSystem getOSFileSystem() {
+        return singleton;
+    }
+
+    private OSFileSystem() {
         super();
     }
 
@@ -153,6 +157,14 @@
         }
         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;
@@ -203,7 +215,7 @@
 
     /*
      * (non-Javadoc)
-     * 
+     *
      * @see org.apache.harmony.luni.platform.IFileSystem#close(long)
      */
     public void close(int fileDescriptor) throws IOException {
@@ -228,7 +240,14 @@
         }
         int handler = openImpl(fileName, mode);
         if (handler < 0) {
-            throw new FileNotFoundException(new String(fileName));
+            try {
+                throw new FileNotFoundException(new String(fileName, "UTF-8"));
+            } catch (java.io.UnsupportedEncodingException e) {
+                // UTF-8 should always be supported, so throw an assertion
+                FileNotFoundException fnfe = new FileNotFoundException(new String(fileName));
+                e.initCause(fnfe);
+                throw new AssertionError(e);
+            }
         }
         return handler;
     }
@@ -238,7 +257,8 @@
     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();
+        if (result < 0)
+                throw new IOException();
         return result;
     }
 
@@ -268,7 +288,7 @@
     }
 
     private native long ttyReadImpl(byte[] bytes, int offset, int length);
-    
+
     // BEGIN android-added
     public native int ioctlAvailable(int fileDescriptor) throws IOException;
     // END android-added
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 e3e7c46..0061d2a 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
@@ -43,7 +43,7 @@
  * above.
  * </p>
  */
-final class OSMemory extends OSComponent implements IMemorySystem {
+final class OSMemory implements IMemorySystem {
 
     /**
      * Defines the size, in bytes, of a native pointer type for the underlying
@@ -74,142 +74,150 @@
     }
 
     /**
-     * This class is not designed to be publically instantiated.
-     * 
+     * This class is not designed to be publicly instantiated.
+     *
      * @see #getOSMemory()
      */
-    OSMemory() {
+    private OSMemory() {
         super();
     }
 
-    // BEGIN android-note
-    // changed to private
-    // END android-note
     /**
      * 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.
+     *
+	 * @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();
     }
 
-    /**
-     * Returns the natural byte order for this machine.
-     * 
-     * @return the native byte order for the current platform.
-     */
-    public Endianness getNativeOrder() {
-        return NATIVE_ORDER;
-    }
+	/**
+	 * Returns the natural byte order for this machine.
+	 *
+	 * @return the native byte order for the current platform.
+	 */
+	public Endianness getNativeOrder() {
+		return NATIVE_ORDER;
+	}
 
-    /**
-     * Returns the size of a native pointer type for the underlying platform.
-     * 
-     * @return the size of a pointer, in bytes.
-     */
-    private static native int getPointerSizeImpl();
+	/**
+	 * Returns the size of a native pointer type for the underlying platform.
+	 *
+	 * @return the size of a pointer, in bytes.
+	 */
+	private static native int getPointerSizeImpl();
 
-    public int getPointerSize() {
-        return POINTER_SIZE;
-    }
+	public int getPointerSize() {
+		return POINTER_SIZE;
+	}
 
     /**
      * Allocates and returns a pointer to space for a memory block of
      * <code>length</code> bytes. The space is uninitialized and may be larger
      * than the number of bytes requested; however, the guaranteed usable memory
      * block is exactly <code>length</code> bytes int.
-     * 
-     * @param length
-     *            number of bytes requested.
+     *
+	 * @param length
+	 *            number of bytes requested.
      * @return the address of the start of the memory block.
-     * @throws OutOfMemoryError
-     *             if the request cannot be satisfied.
+	 * @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
      * call to {@link #malloc(int) malloc(int)}. The number of bytes freed is
      * identical to the number of bytes acquired when the memory block was
-     * allocated. If <code>address</code> is zero the method does nothing.
-     * <p>
+	 * allocated. If <code>address</code> is zero the method does nothing.
+	 * <p>
      * Freeing a pointer to a memory block that was not allocated by
-     * <code>malloc()</code> has unspecified effect.
-     * </p>
-     * 
-     * @param address
-     *            the address of the memory block to deallocate.
+	 * <code>malloc()</code> has unspecified effect.
+	 * </p>
+     *
+	 * @param address
+	 *            the address of the memory block to deallocate.
      */
     public native void free(int address);
 
     /**
      * Places <code>value</code> into first <code>length</code> bytes of the
-     * memory block starting at <code>address</code>.
-     * <p>
-     * The behavior is unspecified if
-     * <code>(address ... address + length)</code> is not wholly within the
-     * range that was previously allocated using <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the address of the first memory location.
-     * @param value
-     *            the byte value to set at each location.
-     * @param length
-     *            the number of byte-length locations to set.
+	 * memory block starting at <code>address</code>.
+	 * <p>
+	 * The behavior is unspecified if
+	 * <code>(address ... address + length)</code> is not wholly within the
+	 * range that was previously allocated using <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the address of the first memory location.
+	 * @param value
+	 *            the byte value to set at each location.
+	 * @param length
+	 *            the number of byte-length locations to set.
      */
     public native void memset(int address, byte value, long length);
 
     /**
      * Copies <code>length</code> bytes from <code>srcAddress</code> to
-     * <code>destAddress</code>. Where any part of the source memory block
-     * and the destination memory block overlap <code>memmove()</code> ensures
-     * that the original source bytes in the overlapping region are copied
-     * before being overwritten.
-     * <p>
-     * The behavior is unspecified if
-     * <code>(srcAddress ... srcAddress + length)</code> and
-     * <code>(destAddress ... destAddress + length)</code> are not both wholly
-     * within the range that was previously allocated using
-     * <code>malloc()</code>.
-     * </p>
-     * 
-     * @param destAddress
-     *            the address of the destination memory block.
-     * @param srcAddress
-     *            the address of the source memory block.
-     * @param length
-     *            the number of bytes to move.
+	 * <code>destAddress</code>. Where any part of the source memory block
+	 * and the destination memory block overlap <code>memmove()</code> ensures
+	 * that the original source bytes in the overlapping region are copied
+	 * before being overwritten.
+	 * <p>
+	 * The behavior is unspecified if
+	 * <code>(srcAddress ... srcAddress + length)</code> and
+	 * <code>(destAddress ... destAddress + length)</code> are not both wholly
+	 * within the range that was previously allocated using
+	 * <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param destAddress
+	 *            the address of the destination memory block.
+	 * @param srcAddress
+	 *            the address of the source memory block.
+	 * @param length
+	 *            the number of bytes to move.
      */
     public native void memmove(int destAddress, int srcAddress, long length);
 
     /**
      * Copies <code>length</code> bytes from the memory block at
-     * <code>address</code> into the byte array <code>bytes</code> starting
-     * at element <code>offset</code> within the byte array.
-     * <p>
-     * The behavior of this method is undefined if the range
-     * <code>(address ... address + length)</code> is not within a memory
+	 * <code>address</code> into the byte array <code>bytes</code> starting
+	 * at element <code>offset</code> within the byte array.
+	 * <p>
+	 * The behavior of this method is undefined if the range
+	 * <code>(address ... address + length)</code> is not within a memory
      * block that was allocated using {@link #malloc(int) malloc(int)}.
-     * </p>
-     * 
-     * @param address
-     *            the address of the OS memory block from which to copy bytes.
-     * @param bytes
-     *            the byte array into which to copy the bytes.
-     * @param offset
-     *            the index of the first element in <code>bytes</code> that
-     *            will be overwritten.
-     * @param length
-     *            the total number of bytes to copy into the byte array.
-     * @throws NullPointerException
-     *             if <code>bytes</code> is <code>null</code>.
-     * @throws IndexOutOfBoundsException
-     *             if <code>offset + length > bytes.length</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the address of the OS memory block from which to copy bytes.
+	 * @param bytes
+	 *            the byte array into which to copy the bytes.
+	 * @param offset
+	 *            the index of the first element in <code>bytes</code> that
+	 *            will be overwritten.
+	 * @param length
+	 *            the total number of bytes to copy into the byte array.
+	 * @throws NullPointerException
+	 *             if <code>bytes</code> is <code>null</code>.
+	 * @throws IndexOutOfBoundsException
+	 *             if <code>offset + length > bytes.length</code>.
      */
     public native void getByteArray(int address, byte[] bytes, int offset,
             int length) throws NullPointerException, IndexOutOfBoundsException;
@@ -217,32 +225,32 @@
     /**
      * Copies <code>length</code> bytes from the byte array <code>bytes</code>
      * into the memory block at <code>address</code>, starting at element
-     * <code>offset</code> within the byte array.
-     * <p>
-     * The behavior of this method is undefined if the range
-     * <code>(address ... address + length)</code> is not within a memory
+	 * <code>offset</code> within the byte array.
+	 * <p>
+	 * The behavior of this method is undefined if the range
+	 * <code>(address ... address + length)</code> is not within a memory
      * block that was allocated using {@link #malloc(int) malloc(int)}.
-     * </p>
-     * 
-     * @param address
-     *            the address of the OS memory block into which to copy the
-     *            bytes.
-     * @param bytes
-     *            the byte array from which to copy the bytes.
-     * @param offset
-     *            the index of the first element in <code>bytes</code> that
-     *            will be read.
-     * @param length
-     *            the total number of bytes to copy from <code>bytes</code>
-     *            into the memory block.
-     * @throws NullPointerException
-     *             if <code>bytes</code> is <code>null</code>.
-     * @throws IndexOutOfBoundsException
-     *             if <code>offset + length > bytes.length</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the address of the OS memory block into which to copy the
+	 *            bytes.
+	 * @param bytes
+	 *            the byte array from which to copy the bytes.
+	 * @param offset
+	 *            the index of the first element in <code>bytes</code> that
+	 *            will be read.
+	 * @param length
+	 *            the total number of bytes to copy from <code>bytes</code>
+	 *            into the memory block.
+	 * @throws NullPointerException
+	 *             if <code>bytes</code> is <code>null</code>.
+	 * @throws IndexOutOfBoundsException
+	 *             if <code>offset + length > bytes.length</code>.
      */
     public native void setByteArray(int address, byte[] bytes, int offset,
             int length) throws NullPointerException, IndexOutOfBoundsException;
-    
+
     // BEGIN android-added
     /**
      * Copies <code>length</code> shorts from the short array <code>shorts</code>
@@ -253,7 +261,7 @@
      * <code>(address ... address + 2*length)</code> is not within a memory
      * block that was allocated using {@link #malloc(int) malloc(int)}.
      * </p>
-     * 
+     *
      * @param address
      *            the address of the OS memory block into which to copy the
      *            shorts.
@@ -285,7 +293,7 @@
      * <code>(address ... address + 2*length)</code> is not within a memory
      * block that was allocated using {@link #malloc(int) malloc(int)}.
      * </p>
-     * 
+     *
      * @param address
      *            the address of the OS memory block into which to copy the
      *            ints.
@@ -312,43 +320,43 @@
     // Primitive get & set methods
 
     /**
-     * Gets the value of the single byte at the given address.
-     * <p>
-     * The behavior is unspecified if <code>address</code> is not in the range
-     * that was previously allocated using <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the platform address of the byte.
+	 * Gets the value of the single byte at the given address.
+	 * <p>
+	 * The behavior is unspecified if <code>address</code> is not in the range
+	 * that was previously allocated using <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the platform address of the byte.
      * @return the byte value.
      */
     public native byte getByte(int address);
 
     /**
-     * Sets the given single byte value at the given address.
-     * <p>
-     * The behavior is unspecified if <code>address</code> is not in the range
-     * that was previously allocated using <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the address at which to set the byte value.
-     * @param value
-     *            the value to set.
+	 * Sets the given single byte value at the given address.
+	 * <p>
+	 * The behavior is unspecified if <code>address</code> is not in the range
+	 * that was previously allocated using <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the address at which to set the byte value.
+	 * @param value
+	 *            the value to set.
      */
     public native void setByte(int address, byte value);
 
     /**
      * Gets the value of the signed two-byte integer stored in platform byte
-     * order at the given address.
-     * <p>
-     * The behavior is unspecified if <code>(address ... address + 2)</code>
-     * is not wholly within the range that was previously allocated using
-     * <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the platform address of the start of the two-byte value.
+	 * order at the given address.
+	 * <p>
+	 * The behavior is unspecified if <code>(address ... address + 2)</code>
+	 * is not wholly within the range that was previously allocated using
+	 * <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the platform address of the start of the two-byte value.
      * @return the value of the two-byte integer as a Java <code>short</code>.
      */
     public native short getShort(int address);
@@ -360,17 +368,17 @@
 
     /**
      * Sets the value of the signed two-byte integer at the given address in
-     * platform byte order.
-     * <p>
-     * The behavior is unspecified if <code>(address ... address + 2)</code>
-     * is not wholly within the range that was previously allocated using
-     * <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the platform address of the start of the two-byte value.
-     * @param value
-     *            the value of the two-byte integer as a Java <code>short</code>.
+	 * platform byte order.
+	 * <p>
+	 * The behavior is unspecified if <code>(address ... address + 2)</code>
+	 * is not wholly within the range that was previously allocated using
+	 * <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the platform address of the start of the two-byte value.
+	 * @param value
+	 *            the value of the two-byte integer as a Java <code>short</code>.
      */
     public native void setShort(int address, short value);
 
@@ -384,15 +392,15 @@
 
     /**
      * Gets the value of the signed four-byte integer stored in platform
-     * byte-order at the given address.
-     * <p>
-     * The behavior is unspecified if <code>(address ... address + 4)</code>
-     * is not wholly within the range that was previously allocated using
-     * <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the platform address of the start of the four-byte value.
+	 * byte-order at the given address.
+	 * <p>
+	 * The behavior is unspecified if <code>(address ... address + 4)</code>
+	 * is not wholly within the range that was previously allocated using
+	 * <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the platform address of the start of the four-byte value.
      * @return the value of the four-byte integer as a Java <code>int</code>.
      */
     public native int getInt(int address);
@@ -404,17 +412,17 @@
 
     /**
      * Sets the value of the signed four-byte integer at the given address in
-     * platform byte order.
-     * <p>
-     * The behavior is unspecified if <code>(address ... address + 4)</code>
-     * is not wholly within the range that was previously allocated using
-     * <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the platform address of the start of the four-byte value.
-     * @param value
-     *            the value of the four-byte integer as a Java <code>int</code>.
+	 * platform byte order.
+	 * <p>
+	 * The behavior is unspecified if <code>(address ... address + 4)</code>
+	 * is not wholly within the range that was previously allocated using
+	 * <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the platform address of the start of the four-byte value.
+	 * @param value
+	 *            the value of the four-byte integer as a Java <code>int</code>.
      */
     public native void setInt(int address, int value);
 
@@ -428,15 +436,15 @@
 
     /**
      * Gets the value of the signed eight-byte integer stored in platform byte
-     * order at the given address.
-     * <p>
-     * The behavior is unspecified if <code>(address ... address + 8)</code>
-     * is not wholly within the range that was previously allocated using
-     * <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the platform address of the start of the eight-byte value.
+	 * order at the given address.
+	 * <p>
+	 * The behavior is unspecified if <code>(address ... address + 8)</code>
+	 * is not wholly within the range that was previously allocated using
+	 * <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the platform address of the start of the eight-byte value.
      * @return the value of the eight-byte integer as a Java <code>long</code>.
      */
     public native long getLong(int address);
@@ -448,17 +456,17 @@
 
     /**
      * Sets the value of the signed eight-byte integer at the given address in
-     * the platform byte order.
-     * <p>
-     * The behavior is unspecified if <code>(address ... address + 8)</code>
-     * is not wholly within the range that was previously allocated using
-     * <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the platform address of the start of the eight-byte value.
-     * @param value
-     *            the value of the eight-byte integer as a Java
+	 * the platform byte order.
+	 * <p>
+	 * The behavior is unspecified if <code>(address ... address + 8)</code>
+	 * is not wholly within the range that was previously allocated using
+	 * <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the platform address of the start of the eight-byte value.
+	 * @param value
+	 *            the value of the eight-byte integer as a Java
      *            <code>long</code>.
      */
     public native void setLong(int address, long value);
@@ -473,15 +481,15 @@
 
     /**
      * Gets the value of the IEEE754-format four-byte float stored in platform
-     * byte order at the given address.
-     * <p>
-     * The behavior is unspecified if <code>(address ... address + 4)</code>
-     * is not wholly within the range that was previously allocated using
-     * <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the platform address of the start of the eight-byte value.
+	 * byte order at the given address.
+	 * <p>
+	 * The behavior is unspecified if <code>(address ... address + 4)</code>
+	 * is not wholly within the range that was previously allocated using
+	 * <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the platform address of the start of the eight-byte value.
      * @return the value of the four-byte float as a Java <code>float</code>.
      */
     public native float getFloat(int address);
@@ -496,17 +504,17 @@
 
     /**
      * Sets the value of the IEEE754-format four-byte float stored in platform
-     * byte order at the given address.
-     * <p>
-     * The behavior is unspecified if <code>(address ... address + 4)</code>
-     * is not wholly within the range that was previously allocated using
-     * <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the platform address of the start of the eight-byte value.
-     * @param value
-     *            the value of the four-byte float as a Java <code>float</code>.
+	 * byte order at the given address.
+	 * <p>
+	 * The behavior is unspecified if <code>(address ... address + 4)</code>
+	 * is not wholly within the range that was previously allocated using
+	 * <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the platform address of the start of the eight-byte value.
+	 * @param value
+	 *            the value of the four-byte float as a Java <code>float</code>.
      */
     public native void setFloat(int address, float value);
 
@@ -521,15 +529,15 @@
 
     /**
      * Gets the value of the IEEE754-format eight-byte float stored in platform
-     * byte order at the given address.
-     * <p>
-     * The behavior is unspecified if <code>(address ... address + 8)</code>
-     * is not wholly within the range that was previously allocated using
-     * <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the platform address of the start of the eight-byte value.
+	 * byte order at the given address.
+	 * <p>
+	 * The behavior is unspecified if <code>(address ... address + 8)</code>
+	 * is not wholly within the range that was previously allocated using
+	 * <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the platform address of the start of the eight-byte value.
      * @return the value of the eight-byte float as a Java <code>double</code>.
      */
     public native double getDouble(int address);
@@ -544,17 +552,17 @@
 
     /**
      * Sets the value of the IEEE754-format eight-byte float store in platform
-     * byte order at the given address.
-     * <p>
-     * The behavior is unspecified if <code>(address ... address + 8)</code>
-     * is not wholly within the range that was previously allocated using
-     * <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the platform address of the start of the eight-byte value.
-     * @param value
-     *            the value of the eight-byte float as a Java
+	 * byte order at the given address.
+	 * <p>
+	 * The behavior is unspecified if <code>(address ... address + 8)</code>
+	 * is not wholly within the range that was previously allocated using
+	 * <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the platform address of the start of the eight-byte value.
+	 * @param value
+	 *            the value of the eight-byte float as a Java
      *            <code>double</code>.
      */
     public native void setDouble(int address, double value);
@@ -569,44 +577,44 @@
     }
 
     /**
-     * Gets the value of the platform pointer at the given address.
-     * <p>
-     * The length of the platform pointer is defined by
-     * <code>POINTER_SIZE</code>.
-     * </p>
-     * The behavior is unspecified if
-     * <code>(address ... address + POINTER_SIZE)</code> is not wholly within
-     * the range that was previously allocated using <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the platform address of the start of the platform pointer.
+	 * Gets the value of the platform pointer at the given address.
+	 * <p>
+	 * The length of the platform pointer is defined by
+	 * <code>POINTER_SIZE</code>.
+	 * </p>
+	 * The behavior is unspecified if
+	 * <code>(address ... address + POINTER_SIZE)</code> is not wholly within
+	 * the range that was previously allocated using <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the platform address of the start of the platform pointer.
      * @return the value of the platform pointer as a Java <code>int</code>.
      */
     public native int getAddress(int address);
 
     /**
-     * Sets the value of the platform pointer at the given address.
-     * <p>
-     * The length of the platform pointer is defined by
-     * <code>POINTER_SIZE</code>. This method only sets
-     * <code>POINTER_SIZE</code> bytes at the given address.
-     * </p>
-     * The behavior is unspecified if
-     * <code>(address ... address + POINTER_SIZE)</code> is not wholly within
-     * the range that was previously allocated using <code>malloc()</code>.
-     * </p>
-     * 
-     * @param address
-     *            the platform address of the start of the platform pointer.
-     * @param value
+	 * Sets the value of the platform pointer at the given address.
+	 * <p>
+	 * The length of the platform pointer is defined by
+	 * <code>POINTER_SIZE</code>. This method only sets
+	 * <code>POINTER_SIZE</code> bytes at the given address.
+	 * </p>
+	 * The behavior is unspecified if
+	 * <code>(address ... address + POINTER_SIZE)</code> is not wholly within
+	 * the range that was previously allocated using <code>malloc()</code>.
+	 * </p>
+     *
+	 * @param address
+	 *            the platform address of the start of the platform pointer.
+	 * @param value
      *            the value of the platform pointer as a Java <code>int</code>.
      */
     public native void setAddress(int address, int value);
 
     /*
-     * Memory mapped file
-     */
+         * Memory mapped file
+         */
     private native int mmapImpl(int fileDescriptor, long alignment,
             long size, int mapMode);
 
@@ -632,39 +640,48 @@
     private native int loadImpl(int l, long size);
 
     public boolean isLoaded(int addr, long size) {
-        return size == 0 ? true : isLoadedImpl(addr, size);
-    }
+		return size == 0 ? true : isLoadedImpl(addr, size);
+	}
 
     private native boolean isLoadedImpl(int l, long size);
 
     public void flush(int addr, long size) {
-        flushImpl(addr, size);
-    }
+		flushImpl(addr, size);
+	}
 
     private native int flushImpl(int l, long size);
 
-    /*
-     * Helper methods to change byte order.
-     */
-    private short swap(short value) {
-        int topEnd = value << 8;
-        int btmEnd = (value >> 8) & 0xFF;
-        return (short) (topEnd | btmEnd);
-    }
+	/*
+	 * Helper methods to change byte order.
+	 */
+	private short swap(short value) {
+        // BEGIN android-note
+        // is Integer.reverseBytes() >>> 16 be faster?
+        // END android-note
+		int topEnd = value << 8;
+		int btmEnd = (value >> 8) & 0xFF;
+		return (short) (topEnd | btmEnd);
+	}
 
-    private int swap(int value) {
-        short left = (short) (value >> 16);
-        short right = (short) value;
-        int topEnd = swap(right) << 16;
-        int btmEnd = swap(left) & 0xFFFF;
-        return topEnd | btmEnd;
-    }
+	private int swap(int value) {
+        // BEGIN android-note
+        // is Integer.reverseBytes() be faster?
+        // END android-note
+		short left = (short) (value >> 16);
+		short right = (short) value;
+		int topEnd = swap(right) << 16;
+		int btmEnd = swap(left) & 0xFFFF;
+		return topEnd | btmEnd;
+	}
 
-    private long swap(long value) {
-        int left = (int) (value >> 32);
-        int right = (int) value;
-        long topEnd = ((long) swap(right)) << 32;
-        long btmEnd = swap(left) & 0xFFFFFFFFL;
-        return topEnd | btmEnd;
-    }
+	private long swap(long value) {
+        // BEGIN android-note
+        // is Long.reverseBytes() be faster?
+        // END android-note
+		int left = (int) (value >> 32);
+		int right = (int) value;
+		long topEnd = ((long) swap(right)) << 32;
+		long btmEnd = swap(left) & 0xFFFFFFFFL;
+		return topEnd | btmEnd;
+	}
 }
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 c153428..bd6a609 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
@@ -16,7 +16,10 @@
  */
 
 // BEGIN android-note
-// address length was changed from long to int for performance reasons.
+// Address length was changed from long to int for performance reasons.
+// Harmony implements INetworkSystem's methods with native methods; Android
+// implements them with Java that call through to native wrappers.
+// TODO: change the native code to eliminate the wrappers
 // END android-note
 
 package org.apache.harmony.luni.platform;
@@ -32,123 +35,33 @@
 // BEGIN android-removed
 // import java.nio.channels.SelectableChannel;
 // END android-removed
-/*
- * 
- * This Class is used for native code wrap, the implement class of
- * INetworkSystem.
- * 
+
+/**
+ * This wraps native code that implements the INetworkSystem interface.
  */
 final class OSNetworkSystem implements INetworkSystem {
 
-    // ----------------------------------------------------
-    // Class Variables
-    // ----------------------------------------------------
-
     private static final int ERRORCODE_SOCKET_TIMEOUT = -209;
+    private static final int ERRORCODE_SOCKET_INTERRUPTED = -208;
 
-    private static OSNetworkSystem ref = new OSNetworkSystem();
-    
     private static final int INETADDR_REACHABLE = 0;
-    
+
     private static boolean isNetworkInited = false;
-    
 
-    // ----------------------------------------------------
-    // Class Constructor
-    // ----------------------------------------------------
+    private static OSNetworkSystem singleton = new OSNetworkSystem();
 
-    // can not be instantiated.
-    private OSNetworkSystem() {
-        super();
-    }
-
-    /*
-     * @return a static ref of this class
+    /**
+     * Answers the unique instance of the OSNetworkSystem.
+     *
+     * @return the network system interface instance
      */
     public static OSNetworkSystem getOSNetworkSystem() {
-        return ref;
+        return singleton;
     }
 
-    // Useing when cache set/get is OK
-    // public static native void oneTimeInitializationDatagram(
-    // boolean jcl_IPv6_support);
-    //
-    // public static native void oneTimeInitializationSocket(
-    // boolean jcl_IPv6_support);
-
-    // --------------------------------------------------
-    // java codes that wrap native codes
-    // --------------------------------------------------
-
-    public void createSocket(FileDescriptor fd, boolean preferIPv4Stack)
-            throws IOException {
-        createSocketImpl(fd, preferIPv4Stack);
-    }
-
-    public void createDatagramSocket(FileDescriptor fd, boolean preferIPv4Stack)
-            throws SocketException {
-        createDatagramSocketImpl(fd, preferIPv4Stack);
-    }
-
-    public int read(FileDescriptor aFD, byte[] data, int offset, int count,
-            int timeout) throws IOException {
-        return readSocketImpl(aFD, data, offset, count, timeout);
-    }
-    
-    public int readDirect(FileDescriptor aFD, int address, int offset, int count,
-            int timeout) throws IOException {
-        return readSocketDirectImpl(aFD, address, offset, count, timeout);
-    }
-
-    public int write(FileDescriptor aFD, byte[] data, int offset, int count)
-            throws IOException {
-        return writeSocketImpl(aFD, data, offset, count);
-    }
-    
-    public int writeDirect(FileDescriptor aFD, int address, int offset,
-            int count) throws IOException {
-        return writeSocketDirectImpl(aFD, address, offset, count);
-    }
-
-    public void setNonBlocking(FileDescriptor aFD, boolean block)
-            throws IOException {
-        setNonBlockingImpl(aFD, block);
-    }
-
-    public void connectDatagram(FileDescriptor aFD, int port, int trafficClass,
-            InetAddress inetAddress) throws SocketException {
-        connectDatagramImpl2(aFD, port, trafficClass, inetAddress);
-    }
-
-    public int connect(FileDescriptor aFD, int trafficClass,
-            InetAddress inetAddress, int port)  throws IOException{
-        return connectSocketImpl(aFD, trafficClass, inetAddress, port);
-    }
-
-    // BEGIN android-changed
-    public int connectWithTimeout(FileDescriptor aFD, int timeout,
-            int trafficClass, InetAddress inetAddress, int port, int step,
-            byte[] context)  throws IOException{
-        return connectWithTimeoutSocketImpl(aFD, timeout, trafficClass,
-                inetAddress, port, step, context);
-    }
-    // END android-changed
-
-    public void connectStreamWithTimeoutSocket(FileDescriptor aFD, int aport,
-            int timeout, int trafficClass, InetAddress inetAddress)
-            throws IOException {
-        connectStreamWithTimeoutSocketImpl(aFD, aport, timeout, trafficClass,
-                inetAddress);
-    }
-
-    public void bind(FileDescriptor aFD, int port, InetAddress inetAddress)
-            throws SocketException {
-        socketBindImpl(aFD, port, inetAddress);
-    }
-
-    public boolean bind2(FileDescriptor aFD, int port, boolean bindToDevice,
-            InetAddress inetAddress) throws SocketException {
-        return socketBindImpl2(aFD, port, bindToDevice, inetAddress);
+    // Can not be instantiated.
+    private OSNetworkSystem() {
+        super();
     }
 
     public void accept(FileDescriptor fdServer, SocketImpl newSocket,
@@ -156,110 +69,9 @@
         acceptSocketImpl(fdServer, newSocket, fdnewSocket, timeout);
     }
 
-    public int sendDatagram(FileDescriptor fd, byte[] data, int offset,
-            int length, int port, boolean bindToDevice, int trafficClass,
-            InetAddress inetAddress) throws IOException {
-        return sendDatagramImpl(fd, data, offset, length, port, bindToDevice,
-                trafficClass, inetAddress);
-    }
-    
-    public int sendDatagramDirect(FileDescriptor fd, int address, int offset,
-            int length, int port, boolean bindToDevice, int trafficClass,
-            InetAddress inetAddress) throws IOException {
-        return sendDatagramDirectImpl(fd, address, offset, length, port, bindToDevice,
-                trafficClass, inetAddress);
-    }
-
-    public int sendDatagram2(FileDescriptor fd, byte[] data, int offset,
-            int length, int port, InetAddress inetAddress) throws IOException {
-        return sendDatagramImpl2(fd, data, offset, length, port, inetAddress);
-    }
-
-    public int receiveDatagram(FileDescriptor aFD, DatagramPacket packet,
-            byte[] data, int offset, int length, int receiveTimeout,
-            boolean peek) throws IOException {
-        return receiveDatagramImpl(aFD, packet, data, offset, length,
-                receiveTimeout, peek);
-    }
-    
-    public int receiveDatagramDirect(FileDescriptor aFD, DatagramPacket packet,
-            int address, int offset, int length, int receiveTimeout,
-            boolean peek) throws IOException {
-        return receiveDatagramDirectImpl(aFD, packet, address, offset, length,
-                receiveTimeout, peek);
-    }
-
-    public int recvConnectedDatagram(FileDescriptor aFD, DatagramPacket packet,
-            byte[] data, int offset, int length, int receiveTimeout,
-            boolean peek) throws IOException {
-        return recvConnectedDatagramImpl(aFD, packet, data, offset, length,
-                receiveTimeout, peek);
-    }
-    
-    public int recvConnectedDatagramDirect(FileDescriptor aFD, DatagramPacket packet, int address,
-             int offset, int length, int receiveTimeout, boolean peek)
-            throws IOException {
-        return recvConnectedDatagramDirectImpl(aFD, packet, address, offset, length, receiveTimeout, peek);
-    }
-
-    public int peekDatagram(FileDescriptor aFD, InetAddress sender,
-            int receiveTimeout) throws IOException {
-        return peekDatagramImpl(aFD, sender, receiveTimeout);
-    }
-
-    public int sendConnectedDatagram(FileDescriptor fd, byte[] data,
-            int offset, int length, boolean bindToDevice) throws IOException {
-        return sendConnectedDatagramImpl(fd, data, offset, length, bindToDevice);
-    }
-    
-    public int sendConnectedDatagramDirect(FileDescriptor fd, int address,
-            int offset, int length, boolean bindToDevice) throws IOException {
-        return sendConnectedDatagramDirectImpl(fd, address, offset, length, bindToDevice);
-    }
-
-    public void disconnectDatagram(FileDescriptor aFD) throws SocketException {
-        disconnectDatagramImpl(aFD);
-    }
-
-    public void createMulticastSocket(FileDescriptor aFD,
-            boolean preferIPv4Stack) throws SocketException {
-        createMulticastSocketImpl(aFD, preferIPv4Stack);
-    }
-
-    public void createServerStreamSocket(FileDescriptor aFD,
-            boolean preferIPv4Stack) throws SocketException {
-        createServerStreamSocketImpl(aFD, preferIPv4Stack);
-    }
-
-    public int receiveStream(FileDescriptor aFD, byte[] data, int offset,
-            int count, int timeout) throws IOException {
-        return receiveStreamImpl(aFD, data, offset, count, timeout);
-    }
-
-    public int sendStream(FileDescriptor fd, byte[] data, int offset, int count)
-            throws IOException {
-        return sendStreamImpl(fd, data, offset, count);
-    }
-
-    public void shutdownInput(FileDescriptor descriptor) throws IOException {
-        shutdownInputImpl(descriptor);
-    }
-
-    public void shutdownOutput(FileDescriptor descriptor) throws IOException {
-        shutdownOutputImpl(descriptor);
-    }
-
-    public boolean supportsUrgentData(FileDescriptor fd) {
-        return supportsUrgentDataImpl(fd);
-    }
-
-    public void sendUrgentData(FileDescriptor fd, byte value) {
-        sendUrgentDataImpl(fd, value);
-    }
-
-    public int availableStream(FileDescriptor aFD) throws SocketException {
-        return availableStreamImpl(aFD);
-    }
+    static native void acceptSocketImpl(FileDescriptor fdServer,
+            SocketImpl newSocket, FileDescriptor fdnewSocket, int timeout)
+            throws IOException;
 
     // BEGIN android-removed
     // public void acceptStreamSocket(FileDescriptor fdServer,
@@ -267,41 +79,498 @@
     //         throws IOException {
     //     acceptStreamSocketImpl(fdServer, newSocket, fdnewSocket, timeout);
     // }
-    // 
-    // public void createStreamSocket(FileDescriptor aFD, boolean preferIPv4Stack)
-    //         throws SocketException {
-    //     createStreamSocketImpl(aFD, preferIPv4Stack);
+
+    // static native void acceptStreamSocketImpl(FileDescriptor fdServer,
+    //         SocketImpl newSocket, FileDescriptor fdnewSocket, int timeout)
+    //         throws IOException;
+    // END android-removed
+
+    public int availableStream(FileDescriptor fd) throws SocketException {
+        return availableStreamImpl(fd);
+    }
+
+    static native int availableStreamImpl(FileDescriptor aFD) throws SocketException;
+
+    /**
+     * Associates a local address with a socket.
+     *
+     * @param fd
+     *            the socket descriptor
+     * @param port
+     *            the port number
+     * @param inetAddress
+     *            address to bind
+     * @throws SocketException
+     *             thrown if bind operation fails
+     */
+    public void bind(FileDescriptor fd, InetAddress inetAddress, int port) throws SocketException {
+        socketBindImpl(fd, port, inetAddress);
+    }
+
+    static native void socketBindImpl(FileDescriptor aFD, int port, InetAddress inetAddress) throws SocketException;
+
+    public int connect(FileDescriptor fd, int trafficClass,
+            InetAddress inetAddress, int port) throws IOException{
+        return connectSocketImpl(fd, trafficClass, inetAddress, port);
+    }
+
+    static native int connectSocketImpl(FileDescriptor aFD,
+            int trafficClass, InetAddress inetAddress, int port);
+
+    public void connectDatagram(FileDescriptor fd, int port,
+            int trafficClass, InetAddress inetAddress) throws SocketException {
+        connectDatagramImpl2(fd, port, trafficClass, inetAddress);
+    }
+
+    static native void connectDatagramImpl2(FileDescriptor aFD, int port,
+            int trafficClass, InetAddress inetAddress) throws SocketException;
+
+    public void connectStreamWithTimeoutSocket(FileDescriptor aFD,
+            int aport, int timeout, int trafficClass, InetAddress inetAddress)
+            throws IOException {
+        connectStreamWithTimeoutSocketImpl(aFD, aport, timeout, trafficClass,
+                inetAddress);
+    }
+
+    static native void connectStreamWithTimeoutSocketImpl(FileDescriptor aFD,
+            int aport, int timeout, int trafficClass, InetAddress inetAddress)
+            throws IOException;
+
+    // BEGIN android-changed
+    // changed context from Long to byte[]
+    public int connectWithTimeout(FileDescriptor fd, int timeout,
+            int trafficClass, InetAddress inetAddress, int port, int step,
+            byte[] context) throws IOException {
+        return connectWithTimeoutSocketImpl(fd, timeout, trafficClass,
+                inetAddress, port, step, context);
+    }
+
+    static native int connectWithTimeoutSocketImpl(FileDescriptor aFD,
+            int timeout, int trafficClass, InetAddress hostname, int port, int step,
+            byte[] context);
+    // END android-changed
+
+    public void createDatagramSocket(FileDescriptor fd,
+            boolean preferIPv4Stack) throws SocketException {
+        createDatagramSocketImpl(fd, preferIPv4Stack);
+    }
+
+    /*
+    * Allocate a datagram socket in the IP stack. The socket is associated with
+    * the <code>aFD</code>.
+    *
+    * @param aFD the FileDescriptor to associate with the socket @param
+    * preferIPv4Stack IP stack preference if underlying platform is V4/V6
+    * @exception SocketException upon an allocation error
+    */
+    static native void createDatagramSocketImpl(FileDescriptor aFD,
+            boolean preferIPv4Stack) throws SocketException;
+
+    public void createServerStreamSocket(FileDescriptor fd,
+            boolean preferIPv4Stack) throws SocketException {
+        createServerStreamSocketImpl(fd, preferIPv4Stack);
+    }
+
+    /*
+     * Answer the result of attempting to create a server stream socket in the
+     * IP stack. Any special options required for server sockets will be set by
+     * this method.
+     *
+     * @param aFD the socket FileDescriptor @param preferIPv4Stack if use IPV4
+     * @exception SocketException if an error occurs while creating the socket
+     */
+    static native void createServerStreamSocketImpl(FileDescriptor aFD,
+            boolean preferIPv4Stack) throws SocketException;
+
+    public void createStreamSocket(FileDescriptor fd,
+            boolean preferIPv4Stack) throws SocketException {
+        createStreamSocketImpl(fd, preferIPv4Stack);
+    }
+
+    static native void createStreamSocketImpl(FileDescriptor aFD,
+            boolean preferIPv4Stack) throws SocketException;
+
+    /**
+     * Disconnect the socket to a port and address
+     *a
+     * @param fd
+     *            the FileDescriptor associated with the socket
+     *
+     * @throws SocketException
+     *             if the disconnect fails
+     */
+    public void disconnectDatagram(FileDescriptor fd)
+            throws SocketException {
+        disconnectDatagramImpl(fd);
+    }
+
+    static native void disconnectDatagramImpl(FileDescriptor aFD)
+            throws SocketException;
+
+    public InetAddress getHostByAddr(byte[] ipAddress)
+            throws UnknownHostException {
+        // BEGIN android-changed
+        // Wallpaper fix for http://b/1851257. This  is a layering violation,
+        // but at least the method has the right return type.
+        // TODO: Fix the socket code to remove this method altogether.
+        return InetAddress.getByAddress(ipAddress);
+        // END android-changed
+    }
+    // BEGIN android-removed
+    // static native InetAddress getHostByAddrImpl(byte[] addr)
+    //         throws UnknownHostException;
+    // END android-removed
+
+    // BEGIN android-removed
+    public InetAddress getHostByName(String hostName,
+            boolean preferIPv6Addresses) throws UnknownHostException {
+        // BEGIN android-changed
+        // Wallpaper fix for http://b/1851257.
+        return InetAddress.getByName(hostName);
+        // END android-changed
+    }
+
+    // BEGIN android-removed
+    // static native InetAddress getHostByNameImpl(String addr,
+    //         boolean preferIPv6Addresses) throws UnknownHostException;
+    // END android-removed
+
+    public int getSocketFlags() {
+        return getSocketFlagsImpl();
+    }
+
+    public native String byteArrayToIpString(byte[] address)
+            throws UnknownHostException;
+
+    public native byte[] ipStringToByteArray(String address)
+            throws UnknownHostException;
+
+    static native int getSocketFlagsImpl();
+
+    public InetAddress getSocketLocalAddress(FileDescriptor fd,
+            boolean preferIPv6Addresses) {
+        return getSocketLocalAddressImpl(fd, preferIPv6Addresses);
+    }
+    static native InetAddress getSocketLocalAddressImpl(FileDescriptor aFD,
+            boolean preferIPv6Addresses);
+
+    /**
+     * Query the IP stack for the local port to which this socket is bound.
+     *
+     * @param aFD
+     *            the socket descriptor
+     * @param preferIPv6Addresses
+     *            address preference for nodes that support both IPv4 and IPv6
+     * @return the local port to which the socket is bound
+     */
+    public int getSocketLocalPort(FileDescriptor aFD,
+            boolean preferIPv6Addresses) {
+        return getSocketLocalPortImpl(aFD, preferIPv6Addresses);
+    }
+
+    static native int getSocketLocalPortImpl(FileDescriptor aFD,
+            boolean preferIPv6Addresses);
+
+    /**
+     * Query the IP stack for the nominated socket option.
+     *
+     * @param fd
+     *            the socket descriptor
+     * @param opt
+     *            the socket option type
+     * @return the nominated socket option value
+     * @throws SocketException
+     *             if the option is invalid
+     */
+    public Object getSocketOption(FileDescriptor fd, int opt)
+            throws SocketException {
+        return getSocketOptionImpl(fd, opt);
+    }
+
+    static native Object getSocketOptionImpl(FileDescriptor aFD, int opt)
+            throws SocketException;
+
+    public Channel inheritedChannel() {
+        return inheritedChannelImpl();
+    }
+
+    native Channel inheritedChannelImpl();
+
+    // BEGIN android-removed
+    // public boolean isReachableByICMP(final InetAddress dest,
+    //         InetAddress source, final int ttl, final int timeout) {
+    //     return INETADDR_REACHABLE == isReachableByICMPImpl(dest, source, ttl,
+    //     timeout);
     // }
+
+    // native int isReachableByICMPImpl(InetAddress addr,
+    //         InetAddress local, int ttl, int timeout);
     // END android-removed
 
     public void listenStreamSocket(FileDescriptor aFD, int backlog)
             throws SocketException {
         listenStreamSocketImpl(aFD, backlog);
     }
-    
-    // BEGIN android-removed
-    // public boolean isReachableByICMP(final InetAddress dest,
-    //         InetAddress source, final int ttl, final int timeout) {
-    //     return INETADDR_REACHABLE == isReachableByICMPImpl(dest, source, ttl,
-    //             timeout);
-    // }
-    // END android-removed
 
-    /*
-     * 
-     * @param 
-     *      readChannels all channels interested in read and accept 
-     * @param
-     *      writeChannels all channels interested in write and connect 
-     * @param timeout
-     *      timeout in millis @return a set of channels that are ready for operation
-     * @throws 
-     *      SocketException @return int array, each int approve one of the     * channel if OK
+    static native void listenStreamSocketImpl(FileDescriptor aFD, int backlog)
+            throws SocketException;
+
+    public void oneTimeInitialization(boolean jcl_supports_ipv6) {
+        if (!isNetworkInited) {
+            oneTimeInitializationImpl(jcl_supports_ipv6);
+            isNetworkInited = true;
+        }
+    }
+
+    native void oneTimeInitializationImpl (boolean jcl_supports_ipv6);
+
+    /**
+     * Peek on the socket, update <code>sender</code> address and answer the
+     * sender port.
+     *
+     * @param fd
+     *            the socket FileDescriptor
+     * @param sender
+     *            an InetAddress, to be updated with the sender's address
+     * @param receiveTimeout
+     *            the maximum length of time the socket should block, reading
+     * @return the sender port
+     *
+     * @throws IOException
+     *             upon an read error or timeout
      */
+    public int peekDatagram(FileDescriptor fd, InetAddress sender,
+            int receiveTimeout) throws IOException {
+        return peekDatagramImpl(fd, sender, receiveTimeout);
+    }
 
-    public int[] select(FileDescriptor[] readFDs,
-            FileDescriptor[] writeFDs, long timeout)
-            throws SocketException {
+    static native int peekDatagramImpl(FileDescriptor aFD,
+            InetAddress sender, int receiveTimeout) throws IOException;
+
+    /**
+     * Read available bytes from the given file descriptor into a byte array.
+     *
+     * The read has an optional timeout parameter, which if non-zero is the
+     * length of time that the read will wait on a select call to see if any
+     * bytes are available for reading. If the timeout expires the method
+     * returns zero to indicate no bytes were read.
+     *
+     * @param fd
+     *            the socket file descriptor to read
+     * @param data
+     *            the byte array in which to store the results
+     * @param offset
+     *            the offset into the byte array in which to start reading the
+     *            results
+     * @param count
+     *            the maximum number of bytes to read
+     * @param timeout
+     *            the length of time to wait for the bytes, in milliseconds; or
+     *            zero to indicate no timeout applied. When there is no timeout
+     *            applied the read may block based upon socket options.
+     * @return number of bytes read, or zero if there were no bytes available
+     *         before the timeout occurred, or -1 to indicate the socket is
+     *         closed
+     * @throws IOException
+     *             if an underlying socket exception occurred
+     */
+    public int read(FileDescriptor fd, byte[] data, int offset, int count,
+            int timeout) throws IOException {
+        return readSocketImpl(fd, data, offset, count, timeout);
+    }
+
+    static native int readSocketImpl(FileDescriptor aFD, byte[] data,
+            int offset, int count, int timeout) throws IOException;
+
+    /**
+     * Read available bytes from the given file descriptor into OS memory at a
+     * given address.
+     *
+     * @param fd
+     *            the socket file descriptor to read
+     * @param address
+     *            the address of the memory in which to store the results
+     * @param count
+     *            the maximum number of bytes to read
+     * @param timeout
+     *            the length of time to wait for the bytes, in milliseconds
+     * @return number of bytes read, or zero if there were no bytes available
+     *         before the timeout occurred, or -1 to indicate the socket is
+     *         closed
+     * @throws IOException
+     *             if an underlying socket exception occurred
+     */
+    public int readDirect(FileDescriptor fd, int address, int offset, int count,
+            int timeout) throws IOException {
+        return readSocketDirectImpl(fd, address, offset, count, timeout);
+    }
+
+    static native int readSocketDirectImpl(FileDescriptor aFD, int address, int offset, int count,
+            int timeout) throws IOException;
+
+    /**
+     * Receive data on the socket into the specified buffer. The packet fields
+     * <code>data</code> & <code>length</code> are passed in addition to
+     * <code>packet</code> to eliminate the JNI field access calls.
+     *
+     * @param fd
+     *            the socket FileDescriptor
+     * @param packet
+     *            the DatagramPacket to receive into
+     * @param data
+     *            the data buffer of the packet
+     * @param offset
+     *            the offset in the data buffer
+     * @param length
+     *            the length of the data buffer in the packet
+     * @param receiveTimeout
+     *            the maximum length of time the socket should block, reading
+     * @param peek
+     *            indicates to peek at the data
+     * @return number of data received
+     * @throws IOException
+     *             upon an read error or timeout
+     */
+    public int receiveDatagram(FileDescriptor fd, DatagramPacket packet,
+            byte[] data, int offset, int length, int receiveTimeout,
+            boolean peek) throws IOException {
+        return receiveDatagramImpl(fd, packet, data, offset, length,
+                receiveTimeout, peek);
+    }
+
+    static native int receiveDatagramImpl(FileDescriptor aFD,
+            DatagramPacket packet, byte[] data, int offset, int length,
+            int receiveTimeout, boolean peek) throws IOException;
+
+    public int receiveDatagramDirect(FileDescriptor fd,
+            DatagramPacket packet, int address, int offset, int length,
+            int receiveTimeout, boolean peek) throws IOException {
+        return receiveDatagramDirectImpl(fd, packet, address, offset, length,
+                receiveTimeout, peek);
+    }
+
+    static native int receiveDatagramDirectImpl(FileDescriptor aFD,
+            DatagramPacket packet, int address, int offset, int length,
+            int receiveTimeout, boolean peek) throws IOException;
+
+    /**
+     * Receive at most <code>count</code> bytes into the buffer
+     * <code>data</code> at the <code>offset</code> on the socket.
+     *
+     * @param aFD
+     *            the socket FileDescriptor
+     * @param data
+     *            the receive buffer
+     * @param offset
+     *            the offset into the buffer
+     * @param count
+     *            the max number of bytes to receive
+     * @param timeout
+     *            the max time the read operation should block waiting for data
+     * @return the actual number of bytes read
+     * @throws IOException
+     * @throws SocketException
+     *             if an error occurs while reading
+     * @deprecated use {@link #read(FileDescriptor, byte[], int, int, int)}
+     */
+    public int receiveStream(FileDescriptor aFD, byte[] data,
+            int offset, int count, int timeout) throws IOException {
+        return receiveStreamImpl(aFD, data, offset, count, timeout);
+    }
+
+    static native int receiveStreamImpl(FileDescriptor aFD, byte[] data,
+            int offset, int count, int timeout) throws IOException;
+
+    // BEGIN android-added
+    /**
+     * Send <code>count</code> bytes from the buffer <code>data</code> at
+     * the <code>offset</code>, on the socket.
+     *
+     * @param fd
+     *
+     * @param data the send buffer @param offset the offset into the buffer
+     * @param count the number of bytes to receive @return int the actual number
+     * of bytes sent @throws IOException @exception SocketException if an error
+     * occurs while writing
+     */
+    public int sendStream(FileDescriptor fd, byte[] data, int offset, int count)
+            throws IOException {
+        return sendStreamImpl(fd, data, offset, count);
+    }
+
+    static native int sendStreamImpl(FileDescriptor fd, byte[] data,
+            int offset, int count) throws IOException;
+    // END android-added
+
+    /**
+     * Recieve data on the connected socket into the specified buffer. The
+     * packet fields <code>data</code> and <code>length</code> are passed in
+     * addition to <code>packet</code> to eliminate the JNI field access calls.
+     *
+     * @param fd
+     *            the socket FileDescriptor
+     * @param packet
+     *            the DatagramPacket to receive into
+     * @param data
+     *            the data buffer of the packet
+     * @param offset
+     *            the offset in the data buffer
+     * @param length
+     *            the length of the data buffer in the packet
+     * @param receiveTimeout
+     *            the maximum length of time the socket should block, reading
+     * @param peek
+     *            indicates to peek at the data
+     * @return number of data received
+     * @throws IOException
+     *             upon an read error or timeout
+     */
+    public int recvConnectedDatagram(FileDescriptor fd,
+            DatagramPacket packet, byte[] data, int offset, int length,
+            int receiveTimeout, boolean peek) throws IOException {
+        return recvConnectedDatagramImpl(fd, packet, data, offset, length,
+                receiveTimeout, peek);
+    }
+
+    static native int recvConnectedDatagramImpl(FileDescriptor aFD,
+            DatagramPacket packet, byte[] data, int offset, int length,
+            int receiveTimeout, boolean peek) throws IOException;
+
+    public int recvConnectedDatagramDirect(FileDescriptor aFD, DatagramPacket packet, int address,
+            int offset, int length, int receiveTimeout, boolean peek)
+            throws IOException {
+        return recvConnectedDatagramDirectImpl(aFD, packet, address, offset, length, receiveTimeout, peek);
+    }
+
+    static native int recvConnectedDatagramDirectImpl(FileDescriptor aFD,
+            DatagramPacket packet, int address, int offset, int length,
+            int receiveTimeout, boolean peek) throws IOException;
+
+    /**
+     * Select the given file descriptors for read and write operations.
+     *
+     * The file descriptors passed in as readFDs will be selected for read-ready
+     * operations, and those in the writeFDs will be selected for write-ready
+     * operations. A file descriptor can appear in either or both array, and
+     * must not be <code>null</code>. If the file descriptor is closed during
+     * the select the behavior depends upon the underlying OS.
+     *
+     * Upon return the result is a single array of length
+     * <code>readFDs.length</code> + <code>writeFDs.length</code> laid out as
+     * the result of the select operation on the corresponding file descriptors.
+     *
+     * @param readFDs
+     *            all sockets interested in read and accept
+     * @param writeFDs
+     *            all sockets interested in write and connect
+     * @param timeout
+     *            timeout in milliseconds
+     * @return each element describes the corresponding state of the descriptor
+     *         in the read and write arrays.
+     * @throws SocketException
+     */
+    public int[] select(FileDescriptor[] readFDs, FileDescriptor[] writeFDs,
+            long timeout) throws SocketException {
         int countRead = readFDs.length;
         int countWrite = writeFDs.length;
         int result = 0;
@@ -310,6 +579,8 @@
         }
         int[] flags = new int[countRead + countWrite];
 
+        assert validateFDs(readFDs, writeFDs) : "Invalid file descriptor arrays"; //$NON-NLS-1$
+
         // handle timeout in native
         result = selectImpl(readFDs, writeFDs, countRead, countWrite, flags,
                 timeout);
@@ -317,430 +588,245 @@
         if (0 <= result) {
             return flags;
         }
-        if (ERRORCODE_SOCKET_TIMEOUT == result) {
+        if (ERRORCODE_SOCKET_TIMEOUT == result ||
+                ERRORCODE_SOCKET_INTERRUPTED == result) {
             return new int[0];
         }
         throw new SocketException();
-
     }
 
-    public InetAddress getSocketLocalAddress(FileDescriptor aFD,
-            boolean preferIPv6Addresses) {
-        return getSocketLocalAddressImpl(aFD, preferIPv6Addresses);
-    }
-
-    /*
-     * Query the IP stack for the local port to which this socket is bound.
-     * 
-     * @param aFD the socket descriptor @param preferIPv6Addresses address
-     * preference for nodes that support both IPv4 and IPv6 @return int the
-     * local port to which the socket is bound
-     */
-    public int getSocketLocalPort(FileDescriptor aFD,
-            boolean preferIPv6Addresses) {
-        return getSocketLocalPortImpl(aFD, preferIPv6Addresses);
-    }
-
-    /*
-     * Query the IP stack for the nominated socket option.
-     * 
-     * @param aFD the socket descriptor @param opt the socket option type
-     * @return the nominated socket option value
-     * 
-     * @throws SocketException if the option is invalid
-     */
-    public Object getSocketOption(FileDescriptor aFD, int opt)
-            throws SocketException {
-        return getSocketOptionImpl(aFD, opt);
-    }
-
-    /*
-     * Set the nominated socket option in the IP stack.
-     * 
-     * @param aFD the socket descriptor @param opt the option selector @param
-     * optVal the nominated option value
-     * 
-     * @throws SocketException if the option is invalid or cannot be set
-     */
-    public void setSocketOption(FileDescriptor aFD, int opt, Object optVal)
-            throws SocketException {
-        setSocketOptionImpl(aFD, opt, optVal);
-    }
-
-    public int getSocketFlags() {
-        return getSocketFlagsImpl();
-    }
-
-    /*
-     * Close the socket in the IP stack.
-     * 
-     * @param aFD the socket descriptor
-     */
-    public void socketClose(FileDescriptor aFD) throws IOException {
-        socketCloseImpl(aFD);
-    }
-
-    public InetAddress getHostByAddr(byte[] addr) throws UnknownHostException {
-        return getHostByAddrImpl(addr);
-    }
-
-    public InetAddress getHostByName(String addr, boolean preferIPv6Addresses)
-            throws UnknownHostException {
-        return getHostByNameImpl(addr, preferIPv6Addresses);
-    }
-
-    public void setInetAddress(InetAddress sender, byte[] address) {
-        setInetAddressImpl(sender, address);
-    }
-
-    // ---------------------------------------------------
-    // Native Codes
-    // ---------------------------------------------------
-
-    static native void createSocketImpl(FileDescriptor fd,
-            boolean preferIPv4Stack);
-
-    /*
-     * Allocate a datagram socket in the IP stack. The socket is associated with
-     * the <code>aFD</code>.
-     * 
-     * @param aFD the FileDescriptor to associate with the socket @param
-     * preferIPv4Stack IP stack preference if underlying platform is V4/V6
-     * @exception SocketException upon an allocation error
-     */
-    static native void createDatagramSocketImpl(FileDescriptor aFD,
-            boolean preferIPv4Stack) throws SocketException;
-
-    static native int readSocketImpl(FileDescriptor aFD, byte[] data,
-            int offset, int count, int timeout) throws IOException;
-    
-    static native int readSocketDirectImpl(FileDescriptor aFD, int address,
-            int offset, int count, int timeout) throws IOException;
-
-    static native int writeSocketImpl(FileDescriptor fd, byte[] data,
-            int offset, int count) throws IOException;
-    
-    static native int writeSocketDirectImpl(FileDescriptor fd, int address,
-            int offset, int count) throws IOException;
-
-    static native void setNonBlockingImpl(FileDescriptor aFD,
-            boolean block);
-
-    static native int connectSocketImpl(FileDescriptor aFD,
-            int trafficClass, InetAddress inetAddress, int port);
-
-    // BEGIN android-changed
-    static native int connectWithTimeoutSocketImpl(
-            FileDescriptor aFD, int timeout, int trafficClass,
-            InetAddress hostname, int port, int step, byte[] context);
-    // END android-changed
-
-    static native void connectStreamWithTimeoutSocketImpl(FileDescriptor aFD,
-            int aport, int timeout, int trafficClass, InetAddress inetAddress)
-            throws IOException;
-
-    static native void socketBindImpl(FileDescriptor aFD, int port,
-            InetAddress inetAddress) throws SocketException;
-
-    static native void listenStreamSocketImpl(FileDescriptor aFD, int backlog)
-            throws SocketException;
-
-    static native int availableStreamImpl(FileDescriptor aFD)
-            throws SocketException;
-
-    static native void acceptSocketImpl(FileDescriptor fdServer,
-            SocketImpl newSocket, FileDescriptor fdnewSocket, int timeout)
-            throws IOException;
-
-    static native boolean supportsUrgentDataImpl(FileDescriptor fd);
-
-    static native void sendUrgentDataImpl(FileDescriptor fd, byte value);
-
-    /*
-     * Connect the socket to a port and address
-     * 
-     * @param aFD the FileDescriptor to associate with the socket @param port
-     * the port to connect to @param trafficClass the traffic Class to be used
-     * then the connection is made @param inetAddress address to connect to.
-     * 
-     * @exception SocketException if the connect fails
-     */
-    static native void connectDatagramImpl2(FileDescriptor aFD,
-            int port, int trafficClass, InetAddress inetAddress)
-            throws SocketException;
-
-    /*
-     * Disconnect the socket to a port and address
-     * 
-     * @param aFD the FileDescriptor to associate with the socket
-     * 
-     * @exception SocketException if the disconnect fails
-     */
-    static native void disconnectDatagramImpl(FileDescriptor aFD)
-            throws SocketException;
-
-    /*
-     * Allocate a datagram socket in the IP stack. The socket is associated with
-     * the <code>aFD</code>.
-     * 
-     * @param aFD the FileDescriptor to associate with the socket @param
-     * preferIPv4Stack IP stack preference if underlying platform is V4/V6
-     * @exception SocketException upon an allocation error
-     */
-
-    /*
-     * Bind the socket to the port/localhost in the IP stack.
-     * 
-     * @param aFD the socket descriptor @param port the option selector @param
-     * bindToDevice bind the socket to the specified interface @param
-     * inetAddress address to connect to. @return if bind successful @exception
-     * SocketException thrown if bind operation fails
-     */
-    static native boolean socketBindImpl2(FileDescriptor aFD,
-            int port, boolean bindToDevice, InetAddress inetAddress)
-            throws SocketException;
-
-    /*
-     * Peek on the socket, update <code>sender</code> address and answer the
-     * sender port.
-     * 
-     * @param aFD the socket FileDescriptor @param sender an InetAddress, to be
-     * updated with the sender's address @param receiveTimeout the maximum
-     * length of time the socket should block, reading @return int the sender
-     * port
-     * 
-     * @exception IOException upon an read error or timeout
-     */
-    static native int peekDatagramImpl(FileDescriptor aFD,
-            InetAddress sender, int receiveTimeout) throws IOException;
-
-    /*
-     * Recieve data on the socket into the specified buffer. The packet fields
-     * <code>data</code> & <code>length</code> are passed in addition to
-     * <code>packet</code> to eliminate the JNI field access calls.
-     * 
-     * @param aFD the socket FileDescriptor @param packet the DatagramPacket to
-     * receive into @param data the data buffer of the packet @param offset the
-     * offset in the data buffer @param length the length of the data buffer in
-     * the packet @param receiveTimeout the maximum length of time the socket
-     * should block, reading @param peek indicates to peek at the data @return
-     * number of data received @exception IOException upon an read error or
-     * timeout
-     */
-    static native int receiveDatagramImpl(FileDescriptor aFD,
-            DatagramPacket packet, byte[] data, int offset, int length,
-            int receiveTimeout, boolean peek) throws IOException;
-    
-    static native int receiveDatagramDirectImpl(FileDescriptor aFD,
-            DatagramPacket packet, int address, int offset, int length,
-            int receiveTimeout, boolean peek) throws IOException;
-
-    /*
-     * Recieve data on the connected socket into the specified buffer. The
-     * packet fields <code>data</code> & <code>length</code> are passed in
-     * addition to <code>packet</code> to eliminate the JNI field access
-     * calls.
-     * 
-     * @param aFD the socket FileDescriptor @param packet the DatagramPacket to
-     * receive into @param data the data buffer of the packet @param offset the
-     * offset in the data buffer @param length the length of the data buffer in
-     * the packet @param receiveTimeout the maximum length of time the socket
-     * should block, reading @param peek indicates to peek at the data @return
-     * number of data received @exception IOException upon an read error or
-     * timeout
-     */
-    static native int recvConnectedDatagramImpl(FileDescriptor aFD,
-            DatagramPacket packet, byte[] data, int offset, int length,
-            int receiveTimeout, boolean peek) throws IOException;
-    
-    static native int recvConnectedDatagramDirectImpl(FileDescriptor aFD,
-            DatagramPacket packet, int address, int offset, int length,
-            int receiveTimeout, boolean peek) throws IOException;
-
-    /*
-     * Send the <code>data</code> to the nominated target <code>address</code>
-     * and <code>port</code>. These values are derived from the
-     * DatagramPacket to reduce the field calls within JNI.
-     * 
-     * @param fd the socket FileDescriptor @param data the data buffer of the
-     * packet @param offset the offset in the data buffer @param length the
-     * length of the data buffer in the packet @param port the target host port
-     * @param bindToDevice if bind to device @param trafficClass the traffic
-     * class to be used when the datagram is sent @param inetAddress address to
-     * connect to. @return number of data send
-     * 
-     * @exception IOException upon an read error or timeout
-     */
-    static native int sendDatagramImpl(FileDescriptor fd,
-            byte[] data, int offset, int length, int port,
-            boolean bindToDevice, int trafficClass, InetAddress inetAddress)
-            throws IOException;
-    
-    static native int sendDatagramDirectImpl(FileDescriptor fd,
-            int address, int offset, int length, int port,
-            boolean bindToDevice, int trafficClass, InetAddress inetAddress)
-            throws IOException;
-
-    /*
-     * Send the <code>data</code> to the address and port to which the was
-     * connnected and <code>port</code>.
-     * 
-     * @param fd the socket FileDescriptor @param data the data buffer of the
-     * packet @param offset the offset in the data buffer @param length the
-     * length of the data buffer in the packet @param bindToDevice not used,
-     * current kept in case needed as was the case for sendDatagramImpl @return
-     * number of data send @exception IOException upon an read error or timeout
-     */
-    static native int sendConnectedDatagramImpl(FileDescriptor fd,
-            byte[] data, int offset, int length, boolean bindToDevice)
-            throws IOException;
-    
-    static native int sendConnectedDatagramDirectImpl(FileDescriptor fd,
-            int address, int offset, int length, boolean bindToDevice)
-            throws IOException;
-
-    /*
-     * Answer the result of attempting to create a server stream socket in the
-     * IP stack. Any special options required for server sockets will be set by
-     * this method.
-     * 
-     * @param aFD the socket FileDescriptor @param preferIPv4Stack if use IPV4
-     * @exception SocketException if an error occurs while creating the socket
-     */
-    static native void createServerStreamSocketImpl(FileDescriptor aFD,
-            boolean preferIPv4Stack) throws SocketException;
-
-    /*
-     * Answer the result of attempting to create a multicast socket in the IP
-     * stack. Any special options required for server sockets will be set by
-     * this method.
-     * 
-     * @param aFD the socket FileDescriptor @param preferIPv4Stack if use IPV4
-     * @exception SocketException if an error occurs while creating the socket
-     */
-    static native void createMulticastSocketImpl(FileDescriptor aFD,
-            boolean preferIPv4Stack) throws SocketException;
-
-    /*
-     * Recieve at most <code>count</code> bytes into the buffer <code>data</code>
-     * at the <code>offset</code> on the socket.
-     * 
-     * @param aFD the socket FileDescriptor @param data the receive buffer
-     * @param offset the offset into the buffer @param count the max number of
-     * bytes to receive @param timeout the max time the read operation should
-     * block waiting for data @return int the actual number of bytes read
-     * @throws IOException @exception SocketException if an error occurs while
-     * reading
-     */
-    static native int receiveStreamImpl(FileDescriptor aFD, byte[] data,
-            int offset, int count, int timeout) throws IOException;
-
-    /*
-     * Send <code>count</code> bytes from the buffer <code>data</code> at
-     * the <code>offset</code>, on the socket.
-     * 
-     * @param fd
-     * 
-     * @param data the send buffer @param offset the offset into the buffer
-     * @param count the number of bytes to receive @return int the actual number
-     * of bytes sent @throws IOException @exception SocketException if an error
-     * occurs while writing
-     */
-    static native int sendStreamImpl(FileDescriptor fd, byte[] data,
-            int offset, int count) throws IOException;
-
-    private native void shutdownInputImpl(FileDescriptor descriptor)
-            throws IOException;
-
-    private native void shutdownOutputImpl(FileDescriptor descriptor)
-            throws IOException;
-
-    // BEGIN android-removed
-    // static native void acceptStreamSocketImpl(FileDescriptor fdServer,
-    //         SocketImpl newSocket, FileDescriptor fdnewSocket, int timeout)
-    //         throws IOException;
-    // 
-    // static native void createStreamSocketImpl(FileDescriptor aFD,
-    //         boolean preferIPv4Stack) throws SocketException;
-    // END android-removed
-
-    static native int sendDatagramImpl2(FileDescriptor fd, byte[] data,
-            int offset, int length, int port, InetAddress inetAddress)
-            throws IOException;
-
     static native int selectImpl(FileDescriptor[] readfd,
             FileDescriptor[] writefd, int cread, int cwirte, int[] flags,
             long timeout);
 
-    static native InetAddress getSocketLocalAddressImpl(FileDescriptor aFD,
-            boolean preferIPv6Addresses);
-
-    /*
-     * Query the IP stack for the local port to which this socket is bound.
-     * 
-     * @param aFD the socket descriptor @param preferIPv6Addresses address
-     * preference for nodes that support both IPv4 and IPv6 @return int the
-     * local port to which the socket is bound
+    /**
+     * Send the <code>data</code> to the address and port to which the was
+     * connected and <code>port</code>.
+     *
+     * @param fd
+     *            the socket FileDescriptor
+     * @param data
+     *            the data buffer of the packet
+     * @param offset
+     *            the offset in the data buffer
+     * @param length
+     *            the length of the data buffer in the packet
+     * @param bindToDevice
+     *            not used, current kept in case needed as was the case for
+     *            sendDatagramImpl
+     * @return number of data send
+     * @throws IOException
+     *             upon an read error or timeout
      */
-    static native int getSocketLocalPortImpl(FileDescriptor aFD,
-            boolean preferIPv6Addresses);
+    public int sendConnectedDatagram(FileDescriptor fd, byte[] data,
+            int offset, int length, boolean bindToDevice) throws IOException {
+        return sendConnectedDatagramImpl(fd, data, offset, length, bindToDevice);
+    }
 
-    /*
-     * Query the IP stack for the nominated socket option.
-     * 
-     * @param aFD the socket descriptor @param opt the socket option type
-     * @return the nominated socket option value
-     * 
-     * @throws SocketException if the option is invalid
+    static native int sendConnectedDatagramImpl(FileDescriptor fd,
+            byte[] data, int offset, int length, boolean bindToDevice)
+            throws IOException;
+
+    public int sendConnectedDatagramDirect(FileDescriptor fd,
+            int address, int offset, int length, boolean bindToDevice)
+            throws IOException {
+        return sendConnectedDatagramDirectImpl(fd, address, offset, length, bindToDevice);
+    }
+    static native int sendConnectedDatagramDirectImpl(FileDescriptor fd,
+            int address, int offset, int length, boolean bindToDevice)
+            throws IOException;
+
+    /**
+     * Send the <code>data</code> to the nominated target <code>address</code>
+     * and <code>port</code>. These values are derived from the DatagramPacket
+     * to reduce the field calls within JNI.
+     *
+     * @param fd
+     *            the socket FileDescriptor
+     * @param data
+     *            the data buffer of the packet
+     * @param offset
+     *            the offset in the data buffer
+     * @param length
+     *            the length of the data buffer in the packet
+     * @param port
+     *            the target host port
+     * @param bindToDevice
+     *            if bind to device
+     * @param trafficClass
+     *            the traffic class to be used when the datagram is sent
+     * @param inetAddress
+     *            address to connect to.
+     * @return number of data send
+     *
+     * @throws IOException
+     *             upon an read error or timeout
      */
-    static native Object getSocketOptionImpl(FileDescriptor aFD, int opt)
-            throws SocketException;
+    public int sendDatagram(FileDescriptor fd, byte[] data, int offset,
+            int length, int port, boolean bindToDevice, int trafficClass,
+            InetAddress inetAddress) throws IOException {
+        return sendDatagramImpl(fd, data, offset, length, port, bindToDevice,
+                trafficClass, inetAddress);
+    }
 
-    /*
-     * Set the nominated socket option in the IP stack.
-     * 
-     * @param aFD the socket descriptor @param opt the option selector @param
-     * optVal the nominated option value
-     * 
-     * @throws SocketException if the option is invalid or cannot be set
-     */
-    static native void setSocketOptionImpl(FileDescriptor aFD, int opt,
-            Object optVal) throws SocketException;
+    static native int sendDatagramImpl(FileDescriptor fd, byte[] data, int offset,
+            int length, int port, boolean bindToDevice, int trafficClass,
+            InetAddress inetAddress) throws IOException;
 
-    static native int getSocketFlagsImpl();
+    public int sendDatagram2(FileDescriptor fd, byte[] data, int offset,
+            int length, int port, InetAddress inetAddress) throws IOException {
+        return sendDatagramImpl2(fd, data, offset, length, port, inetAddress);
+    }
 
-    /*
-     * Close the socket in the IP stack.
-     * 
-     * @param aFD the socket descriptor
-     */
-    static native void socketCloseImpl(FileDescriptor aFD);
+    static native int sendDatagramImpl2(FileDescriptor fd, byte[] data,
+            int offset, int length, int port, InetAddress inetAddress) throws IOException;
 
-    static native InetAddress getHostByAddrImpl(byte[] addr)
-            throws UnknownHostException;
 
-    static native InetAddress getHostByNameImpl(String addr,
-            boolean preferIPv6Addresses) throws UnknownHostException;
+    public int sendDatagramDirect(FileDescriptor fd, int address,
+            int offset, int length, int port, boolean bindToDevice,
+            int trafficClass, InetAddress inetAddress) throws IOException {
+        return sendDatagramDirectImpl(fd, address, offset, length, port, bindToDevice,
+                trafficClass, inetAddress);
+    }
+
+    static native int sendDatagramDirectImpl(FileDescriptor fd, int address,
+            int offset, int length, int port, boolean bindToDevice,
+            int trafficClass, InetAddress inetAddress) throws IOException;
+
+    public void sendUrgentData(FileDescriptor fd, byte value) {
+        sendUrgentDataImpl(fd, value);
+    }
+
+    static native void sendUrgentDataImpl(FileDescriptor fd, byte value);
+
+    public void setInetAddress(InetAddress sender, byte[] address) {
+        setInetAddressImpl(sender, address);
+    }
 
     native void setInetAddressImpl(InetAddress sender, byte[] address);
 
-    // BEGIN android-removed
-    // native int isReachableByICMPImpl(InetAddress addr, InetAddress local,
-    //         int ttl, int timeout);
-    // END android-removed
-    
-    native Channel inheritedChannelImpl();
+    public void setNonBlocking(FileDescriptor fd, boolean block)
+            throws IOException {
+        setNonBlockingImpl(fd, block);
+    }
 
-    public Channel inheritedChannel() {
-        return inheritedChannelImpl();
+    static native void setNonBlockingImpl(FileDescriptor aFD, boolean block);
+
+    /**
+     * Set the nominated socket option in the IP stack.
+     *
+     * @param aFD
+     *            the socket descriptor @param opt the option selector @param
+     *            optVal the nominated option value
+     *
+     * @throws SocketException
+     *             if the option is invalid or cannot be set
+     */
+    public void setSocketOption(FileDescriptor aFD, int opt,
+            Object optVal) throws SocketException {
+        setSocketOptionImpl(aFD, opt, optVal);
     }
-    
-    public void oneTimeInitialization(boolean jcl_supports_ipv6){
-        if (!isNetworkInited){
-            oneTimeInitializationImpl(jcl_supports_ipv6);
-            isNetworkInited = true;
-        } 
+
+    static native void setSocketOptionImpl(FileDescriptor aFD, int opt,
+            Object optVal) throws SocketException;
+
+    public void shutdownInput(FileDescriptor descriptor) throws IOException {
+        shutdownInputImpl(descriptor);
     }
-    
-    native void oneTimeInitializationImpl (boolean jcl_supports_ipv6);
+
+    private native void shutdownInputImpl(FileDescriptor descriptor)
+            throws IOException;
+
+    public void shutdownOutput(FileDescriptor fd) throws IOException {
+        shutdownOutputImpl(fd);
+    }
+
+    private native void shutdownOutputImpl(FileDescriptor descriptor)
+            throws IOException;
+    /**
+     * Close the socket in the IP stack.
+     *
+     * @param fd
+     *            the socket descriptor
+     */
+    public void socketClose(FileDescriptor fd) throws IOException {
+        socketCloseImpl(fd);
+    }
+
+    static native void socketCloseImpl(FileDescriptor fD);
+
+    public boolean supportsUrgentData(FileDescriptor fd) {
+        return supportsUrgentDataImpl(fd);
+    }
+
+    static native boolean supportsUrgentDataImpl(FileDescriptor fd);
+
+    /*
+    * Used to check if the file descriptor arrays are valid before passing them
+    * into the select native call.
+    */
+    private boolean validateFDs(FileDescriptor[] readFDs,
+            FileDescriptor[] writeFDs) {
+        for (FileDescriptor fd : readFDs) {
+            // Also checks fd not null
+            if (!fd.valid()) {
+                return false;
+            }
+        }
+        for (FileDescriptor fd : writeFDs) {
+            if (!fd.valid()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Write bytes from a byte array to a socket.
+     *
+     * @param fd
+     *            the socket on which to write the bytes
+     * @param data
+     *            the array containing the bytes to be written
+     * @param offset
+     *            the offset in the byte array from which to take the bytes
+     * @param count
+     *            the maximum number of bytes to be written. Callers are trusted
+     *            not to send values of length+count that are larger than
+     *            data.length
+     * @return the actual number of bytes written, which will be between zero
+     *         and count
+     * @throws IOException
+     *             if there is an underlying socket problem
+     */
+    public int write(FileDescriptor fd, byte[] data, int offset, int count)
+            throws IOException {
+        return writeSocketImpl(fd, data, offset, count);
+    }
+
+    static native int writeSocketImpl(FileDescriptor fd, byte[] data, int offset,
+            int count) throws IOException;
+
+
+    /**
+     * Write bytes from the given address to a socket.
+     *
+     * @param fd
+     *            the socket on which to write the bytes
+     * @param address
+     *            the start address of the bytes to be written
+     * @param count
+     *            the maximum number of bytes to be written
+     * @return the actual number of bytes written, which will be between zero
+     *         and count
+     * @throws IOException
+     *             if there is an underlying socket problem
+     */
+    public int writeDirect(FileDescriptor fd, int address, int offset, int count)
+            throws IOException {
+        return writeSocketDirectImpl(fd, address, offset, count);
+    }
+
+    static native int writeSocketDirectImpl(FileDescriptor fd, int address, int offset, int count)
+            throws IOException;
 }
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/Platform.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/Platform.java
index 68d2515..ab71a00 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/Platform.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/Platform.java
@@ -21,25 +21,33 @@
 // END android-changed
 
 /**
- * Platform
- *  
+ * The Platform class gives access to the low-level underlying capabilities of
+ * the operating system.
+ *
+ * The platform is structured into operations on the process heap memory,
+ * network subsystem, and file system through different OS components.
+ *
+ * OS components are 'dangerous' in that they pass through the calls and
+ * arguments to the OS with very little checking, and as such may cause fatal
+ * exceptions in the runtime. Access to the OS components is restricted to
+ * trusted code running on the system classpath.
+ *
+ * @see IFileSystem
+ * @see INetworkSystem
+ * @see IMemorySystem
  */
 public class Platform {
 
-    static final IAdapterManager ADAPTER_MANAGER = new AdapterManager();
+    static final IFileSystem FILE_SYSTEM = OSFileSystem.getOSFileSystem();
 
-    static final IFileSystem FILE_SYSTEM = OSComponentFactory.getFileSystem();
+    static final IMemorySystem MEMORY_SYSTEM = OSMemory.getOSMemory();
 
-    static final IMemorySystem MEMORY_SYSTEM = OSComponentFactory
-            .getMemorySystem();
+    static final INetworkSystem NETWORK_SYSTEM = OSNetworkSystem.getOSNetworkSystem();
 
-    static final INetworkSystem NETWORK_SYSTEM = OSComponentFactory
-            .getNetworkSystem();
-
-    public static IAdapterManager getAdapterManager() {
-        return ADAPTER_MANAGER;
-    }
-
+    /**
+     * Checks to ensure that whoever is asking for the OS component is running
+     * on the system classpath.
+     */
     private static final void accessCheck() {
         // BEGIN android-changed
         if (VMStack.getCallingClassLoader() != null) {
@@ -48,16 +56,31 @@
         // END android-changed
     }
 
+    /**
+     * Answers the instance that interacts directly with the OS file system.
+     *
+     * @return a low-level file system interface.
+     */
     public static IFileSystem getFileSystem() {
         accessCheck();
         return FILE_SYSTEM;
     }
 
+    /**
+     * Answers the instance that interacts directly with the OS memory system.
+     *
+     * @return a low-level memory system interface.
+     */
     public static IMemorySystem getMemorySystem() {
         accessCheck();
         return MEMORY_SYSTEM;
     }
 
+    /**
+     * Answers the instance that interacts directly with the OS network system.
+     *
+     * @return a low-level network system interface.
+     */
     public static INetworkSystem getNetworkSystem() {
         accessCheck();
         return NETWORK_SYSTEM;
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/RuntimeMemorySpy.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/RuntimeMemorySpy.java
index e897506..3692819 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/RuntimeMemorySpy.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/RuntimeMemorySpy.java
@@ -20,17 +20,18 @@
 
 final class RuntimeMemorySpy extends AbstractMemorySpy {
 
-    public RuntimeMemorySpy() {
-        super();
-    }
+	public RuntimeMemorySpy() {
+		super();
+	}
 
-    public void alloc(PlatformAddress address) {
+	public void alloc(PlatformAddress address) {
+		// Pay a tax on the allocation to see if there are any frees pending.
+		Reference ref = notifyQueue.poll(); // non-blocking check
+		while (ref != null) {
+			orphanedMemory(ref);
+			ref = notifyQueue.poll();
+		}
+
         super.alloc(address);
-        // Pay a tax on the allocation to see if there are any frees pending.
-        Reference ref = notifyQueue.poll(); // non-blocking check
-        while (ref != null) {
-            orphanedMemory(ref);
-            ref = notifyQueue.poll();
-        }
-    }
+	}
 }
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/util/DeleteOnExit.java b/libcore/luni/src/main/java/org/apache/harmony/luni/util/DeleteOnExit.java
new file mode 100644
index 0000000..ac3275e
--- /dev/null
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/util/DeleteOnExit.java
@@ -0,0 +1,80 @@
+/*
+ *  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.luni.util;
+
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+
+// BEGIN android-changed
+/**
+ * Implements the actual DeleteOnExit mechanism. Is registered as a shutdown
+ * hook in the Runtime, once it is actually being used.
+ */
+public class DeleteOnExit extends Thread {
+
+    /**
+     * Our singleton instance.
+     */
+    private static DeleteOnExit instance;
+
+    /**
+     * Our list of files scheduled for deletion.
+     */
+    private ArrayList<String> files = new ArrayList<String>();
+
+    /**
+     * Returns our singleton instance, creating it if necessary.
+     */
+    public static synchronized DeleteOnExit getInstance() {
+        if (instance == null) {
+            instance = new DeleteOnExit();
+            Runtime.getRuntime().addShutdownHook(instance);
+        }
+
+        return instance;
+    }
+
+    /**
+     * Schedules a file for deletion.
+     *
+     * @param filename The file to delete.
+     */
+    public void addFile(String filename) {
+        synchronized(files) {
+            if (!files.contains(filename)) {
+                files.add(filename);
+            }
+        }
+    }
+
+    /**
+     * Does the actual work. Note we (a) first sort the files lexicographically
+     * and then (b) delete them in reverse order. This is to make sure files
+     * get deleted before their parent directories.
+     */
+    @Override
+    public void run() {
+        Collections.sort(files);
+        for (int i = files.size() - 1; i >= 0; i--) {
+            new File(files.get(i)).delete();
+        }
+    }
+}
+// END android-changed
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/util/ExposedByteArrayInputStream.java b/libcore/luni/src/main/java/org/apache/harmony/luni/util/ExposedByteArrayInputStream.java
new file mode 100644
index 0000000..0ff073c
--- /dev/null
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/util/ExposedByteArrayInputStream.java
@@ -0,0 +1,57 @@
+/*
+ *  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.luni.util;
+
+import java.io.ByteArrayInputStream;
+
+/**
+ * The extension of <code>ByteArrayInputStream</code> which exposes an
+ * underlying buffer.
+ */
+public class ExposedByteArrayInputStream extends ByteArrayInputStream {
+
+    /**
+     * @see java.io.ByteArrayInputStream(byte[])
+     */
+    public ExposedByteArrayInputStream(byte buf[]) {
+        super(buf);
+    }
+
+    /**
+     * @see java.io.ByteArrayInputStream(byte[], int, int)
+     */
+    public ExposedByteArrayInputStream(byte buf[], int offset, int length) {
+        super(buf, offset, length);
+    }
+
+    /**
+     * Reads the whole stream and returns the stream snapshot.
+     */
+    public synchronized byte[] expose() {
+        if (pos == 0 && count == buf.length) {
+            skip(count);
+            return buf;
+        }
+
+        final int available = available();
+        final byte[] buffer = new byte[available];
+        System.arraycopy(buf, pos, buffer, 0, available);
+        skip(available);
+        return buffer;
+    }
+}
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 bc1688f..280a8f5 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
@@ -61,8 +61,8 @@
 K0046=Local port declared out of range
 K0047=buffer is null
 K0048=Invalid action specified\: {0}
-K0049=MinPort is greater than MaxPort
-K004a=Invalid port number specified
+K0049=MinPort is greater than MaxPort\: {0}
+K004a=Invalid port number specified\: {0}
 K004b=Attempt to set factory more than once.
 K004c=Package is sealed
 K004d=Does not support writing to the input stream
@@ -288,6 +288,7 @@
 K034d=method has not been implemented yet
 K034e=Build rules empty
 K0351=format is null
+K0352=package is sealed
 KA000=Line too long
 KA001=Argument must not be null
 KA002=Unshared read of back reference
@@ -322,3 +323,6 @@
 KA025=Method has not been implemented
 KA026=JAR entry {0} not found in {1}
 KA027=Inputstream of the JarURLConnection has been closed
+KA028=Cannot set protocol version when stream in use
+KA029=Can't find resource for bundle {0}, key {1}
+KA030=Write end dead
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/util/FloatingPointParser.java b/libcore/luni/src/main/java/org/apache/harmony/luni/util/FloatingPointParser.java
index 820de0f..8734039 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/util/FloatingPointParser.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/util/FloatingPointParser.java
@@ -17,8 +17,6 @@
 
 package org.apache.harmony.luni.util;
 
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 /**
  * Used to parse a string and return either a single or double precision
@@ -26,94 +24,94 @@
  */
 public final class FloatingPointParser {
 
-    private static final class StringExponentPair {
-        String s;
+	private static final class StringExponentPair {
+		String s;
 
-        int e;
+		int e;
 
-        boolean negative;
+		boolean negative;
 
-        StringExponentPair(String s, int e, boolean negative) {
-            this.s = s;
-            this.e = e;
-            this.negative = negative;
-        }
-    }
+		StringExponentPair(String s, int e, boolean negative) {
+			this.s = s;
+			this.e = e;
+			this.negative = negative;
+		}
+	}
 
-    /**
-     * Takes a String and an integer exponent. The String should hold a positive
-     * integer value (or zero). The exponent will be used to calculate the
-     * floating point number by taking the positive integer the String
-     * represents and multiplying by 10 raised to the power of the of the
-     * exponent. Returns the closest double value to the real number
-     * 
-     * @param s
-     *            the String that will be parsed to a floating point
-     * @param e
-     *            an int represent the 10 to part
-     * @return the double closest to the real number
-     * 
-     * @exception NumberFormatException
-     *                if the String doesn't represent a positive integer value
-     */
-    private static native double parseDblImpl(String s, int e);
+	/**
+	 * Takes a String and an integer exponent. The String should hold a positive
+	 * integer value (or zero). The exponent will be used to calculate the
+	 * floating point number by taking the positive integer the String
+	 * represents and multiplying by 10 raised to the power of the of the
+	 * exponent. Returns the closest double value to the real number
+	 * 
+	 * @param s
+	 *            the String that will be parsed to a floating point
+	 * @param e
+	 *            an int represent the 10 to part
+	 * @return the double closest to the real number
+	 * 
+	 * @exception NumberFormatException
+	 *                if the String doesn't represent a positive integer value
+	 */
+	private static native double parseDblImpl(String s, int e);
 
-    /**
-     * Takes a String and an integer exponent. The String should hold a positive
-     * integer value (or zero). The exponent will be used to calculate the
-     * floating point number by taking the positive integer the String
-     * represents and multiplying by 10 raised to the power of the of the
-     * exponent. Returns the closest float value to the real number
-     * 
-     * @param s
-     *            the String that will be parsed to a floating point
-     * @param e
-     *            an int represent the 10 to part
-     * @return the float closest to the real number
-     * 
-     * @exception NumberFormatException
-     *                if the String doesn't represent a positive integer value
-     */
-    private static native float parseFltImpl(String s, int e);
+	/**
+	 * Takes a String and an integer exponent. The String should hold a positive
+	 * integer value (or zero). The exponent will be used to calculate the
+	 * floating point number by taking the positive integer the String
+	 * represents and multiplying by 10 raised to the power of the of the
+	 * exponent. Returns the closest float value to the real number
+	 * 
+	 * @param s
+	 *            the String that will be parsed to a floating point
+	 * @param e
+	 *            an int represent the 10 to part
+	 * @return the float closest to the real number
+	 * 
+	 * @exception NumberFormatException
+	 *                if the String doesn't represent a positive integer value
+	 */
+	private static native float parseFltImpl(String s, int e);
 
-    /**
-     * Takes a String and does some initial parsing. Should return a
-     * StringExponentPair containing a String with no leading or trailing white
-     * space and trailing zeroes eliminated. The exponent of the
-     * StringExponentPair will be used to calculate the floating point number by
-     * taking the positive integer the String represents and multiplying by 10
-     * raised to the power of the of the exponent.
-     * 
-     * @param s
-     *            the String that will be parsed to a floating point
-     * @param length
-     *            the length of s
-     * @return a StringExponentPair with necessary values
-     * 
-     * @exception NumberFormatException
-     *                if the String doesn't pass basic tests
-     */
-    private static StringExponentPair initialParse(String s, int length) {
-        boolean negative = false;
-        char c;
-        int start, end, decimal;
-        int e = 0;
+	/**
+	 * Takes a String and does some initial parsing. Should return a
+	 * StringExponentPair containing a String with no leading or trailing white
+	 * space and trailing zeroes eliminated. The exponent of the
+	 * StringExponentPair will be used to calculate the floating point number by
+	 * taking the positive integer the String represents and multiplying by 10
+	 * raised to the power of the of the exponent.
+	 * 
+	 * @param s
+	 *            the String that will be parsed to a floating point
+	 * @param length
+	 *            the length of s
+	 * @return a StringExponentPair with necessary values
+	 * 
+	 * @exception NumberFormatException
+	 *                if the String doesn't pass basic tests
+	 */
+	private static StringExponentPair initialParse(String s, int length) {
+		boolean negative = false;
+		char c;
+		int start, end, decimal;
+		int e = 0;
 
-        start = 0;
-        if (length == 0)
-            throw new NumberFormatException(s);
+		start = 0;
+		if (length == 0)
+			throw new NumberFormatException(s);
 
-        c = s.charAt(length - 1);
-        if (c == 'D' || c == 'd' || c == 'F' || c == 'f') {
-            length--;
-            if (length == 0)
-                throw new NumberFormatException(s);
-        }
+		c = s.charAt(length - 1);
+		if (c == 'D' || c == 'd' || c == 'F' || c == 'f') {
+			length--;
+			if (length == 0)
+				throw new NumberFormatException(s);
+		}
 
-        end = Math.max(s.indexOf('E'), s.indexOf('e'));
-        if (end > -1) {
-            if (end + 1 == length)
-                throw new NumberFormatException(s);
+		end = Math.max(s.indexOf('E'), s.indexOf('e'));
+		if (end > -1) {
+			if (end + 1 == length)
+				throw new NumberFormatException(s);
 
                         int exponent_offset = end + 1;
                         if (s.charAt(exponent_offset) == '+') {
@@ -122,197 +120,208 @@
                                 }
                                 exponent_offset++; // skip the plus sign
                         }
-            try {
-                e = Integer.parseInt(s.substring(exponent_offset,
+			try {
+				e = Integer.parseInt(s.substring(exponent_offset,
                                                                  length));
                         } catch (NumberFormatException ex) {
                                 // ex contains the exponent substring
                                 // only so throw a new exception with
                                 // the correct string
-                throw new NumberFormatException(s);
+				throw new NumberFormatException(s);
                         }                            
                                     
-        } else {
-            end = length;
-        }
-        if (length == 0)
-            throw new NumberFormatException(s);
+		} else {
+			end = length;
+		}
+		if (length == 0)
+			throw new NumberFormatException(s);
 
-        c = s.charAt(start);
-        if (c == '-') {
-            ++start;
-            --length;
-            negative = true;
-        } else if (c == '+') {
-            ++start;
-            --length;
-        }
-        if (length == 0)
-            throw new NumberFormatException(s);
+		c = s.charAt(start);
+		if (c == '-') {
+			++start;
+			--length;
+			negative = true;
+		} else if (c == '+') {
+			++start;
+			--length;
+		}
+		if (length == 0)
+			throw new NumberFormatException(s);
 
-        decimal = s.indexOf('.');
-        if (decimal > -1) {
-            e -= end - decimal - 1;
-            s = s.substring(start, decimal) + s.substring(decimal + 1, end);
-        } else {
-            s = s.substring(start, end);
+		decimal = s.indexOf('.');
+		if (decimal > -1) {
+			e -= end - decimal - 1;
+			s = s.substring(start, decimal) + s.substring(decimal + 1, end);
+		} else {
+			s = s.substring(start, end);
+		}
+
+		if ((length = s.length()) == 0)
+			throw new NumberFormatException();
+
+		end = length;
+		while (end > 1 && s.charAt(end - 1) == '0')
+			--end;
+
+		start = 0;
+		while (start < end - 1 && s.charAt(start) == '0')
+			start++;
+
+		if (end != length || start != 0) {
+			e += length - end;
+			s = s.substring(start, end);
+		}
+
+        // Trim the length of very small numbers, natives can only handle down
+        // to E-309
+        final int APPROX_MIN_MAGNITUDE = -359;
+        final int MAX_DIGITS = 52;
+        length = s.length();
+        if (length > MAX_DIGITS && e < APPROX_MIN_MAGNITUDE) {
+            int d = Math.min(APPROX_MIN_MAGNITUDE - e, length - 1);
+            s = s.substring(0, length - d);
+            e += d;
         }
 
-        if ((length = s.length()) == 0)
-            throw new NumberFormatException();
+		return new StringExponentPair(s, e, negative);
+	}
 
-        end = length;
-        while (end > 1 && s.charAt(end - 1) == '0')
-            --end;
+	/*
+	 * Assumes the string is trimmed.
+	 */
+	private static double parseDblName(String namedDouble, int length) {
+		// Valid strings are only +Nan, NaN, -Nan, +Infinity, Infinity,
+		// -Infinity.
+		if ((length != 3) && (length != 4) && (length != 8) && (length != 9)) {
+			throw new NumberFormatException();
+		}
 
-        start = 0;
-        while (start < end - 1 && s.charAt(start) == '0')
-            start++;
+		boolean negative = false;
+		int cmpstart = 0;
+		switch (namedDouble.charAt(0)) {
+		case '-':
+			negative = true; // fall through
+		case '+':
+			cmpstart = 1;
+		default:
+		}
 
-        if (end != length || start != 0) {
-            e += length - end;
-            s = s.substring(start, end);
-        }
+		if (namedDouble.regionMatches(false, cmpstart, "Infinity", 0, 8)) {
+			return negative ? Double.NEGATIVE_INFINITY
+					: Float.POSITIVE_INFINITY;
+		}
 
-        return new StringExponentPair(s, e, negative);
-    }
+		if (namedDouble.regionMatches(false, cmpstart, "NaN", 0, 3)) {
+			return Double.NaN;
+		}
 
-    /*
-     * Assumes the string is trimmed.
-     */
-    private static double parseDblName(String namedDouble, int length) {
-        // Valid strings are only +Nan, NaN, -Nan, +Infinity, Infinity,
-        // -Infinity.
-        if ((length != 3) && (length != 4) && (length != 8) && (length != 9)) {
-            throw new NumberFormatException();
-        }
+		throw new NumberFormatException();
+	}
 
-        boolean negative = false;
-        int cmpstart = 0;
-        switch (namedDouble.charAt(0)) {
-        case '-':
-            negative = true; // fall through
-        case '+':
-            cmpstart = 1;
-        default:
-        }
+	/*
+	 * Assumes the string is trimmed.
+	 */
+	private static float parseFltName(String namedFloat, int length) {
+		// Valid strings are only +Nan, NaN, -Nan, +Infinity, Infinity,
+		// -Infinity.
+		if ((length != 3) && (length != 4) && (length != 8) && (length != 9)) {
+			throw new NumberFormatException();
+		}
 
-        if (namedDouble.regionMatches(false, cmpstart, "Infinity", 0, 8)) {
-            return negative ? Double.NEGATIVE_INFINITY
-                    : Float.POSITIVE_INFINITY;
-        }
+		boolean negative = false;
+		int cmpstart = 0;
+		switch (namedFloat.charAt(0)) {
+		case '-':
+			negative = true; // fall through
+		case '+':
+			cmpstart = 1;
+		default:
+		}
 
-        if (namedDouble.regionMatches(false, cmpstart, "NaN", 0, 3)) {
-            return Double.NaN;
-        }
+		if (namedFloat.regionMatches(false, cmpstart, "Infinity", 0, 8)) {
+			return negative ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
+		}
 
-        throw new NumberFormatException();
-    }
+		if (namedFloat.regionMatches(false, cmpstart, "NaN", 0, 3)) {
+			return Float.NaN;
+		}
 
-    /*
-     * Assumes the string is trimmed.
-     */
-    private static float parseFltName(String namedFloat, int length) {
-        // Valid strings are only +Nan, NaN, -Nan, +Infinity, Infinity,
-        // -Infinity.
-        if ((length != 3) && (length != 4) && (length != 8) && (length != 9)) {
-            throw new NumberFormatException();
-        }
+		throw new NumberFormatException();
+	}
 
-        boolean negative = false;
-        int cmpstart = 0;
-        switch (namedFloat.charAt(0)) {
-        case '-':
-            negative = true; // fall through
-        case '+':
-            cmpstart = 1;
-        default:
-        }
+	/**
+	 * Returns the closest double value to the real number in the string.
+	 * 
+	 * @param s
+	 *            the String that will be parsed to a floating point
+	 * @return the double closest to the real number
+	 * 
+	 * @exception NumberFormatException
+	 *                if the String doesn't represent a double
+	 */
+	public static double parseDouble(String s) {
+		s = s.trim();
+		int length = s.length();
 
-        if (namedFloat.regionMatches(false, cmpstart, "Infinity", 0, 8)) {
-            return negative ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
-        }
+		if (length == 0) {
+			throw new NumberFormatException(s);
+		}
 
-        if (namedFloat.regionMatches(false, cmpstart, "NaN", 0, 3)) {
-            return Float.NaN;
-        }
-
-        throw new NumberFormatException();
-    }
-
-    /**
-     * Returns the closest double value to the real number in the string.
-     * 
-     * @param s
-     *            the String that will be parsed to a floating point
-     * @return the double closest to the real number
-     * 
-     * @exception NumberFormatException
-     *                if the String doesn't represent a double
-     */
-    public static double parseDouble(String s) {
-        s = s.trim();
-        int length = s.length();
-
-        if (length == 0) {
-            throw new NumberFormatException(s);
-        }
-
-        // See if this could be a named double
-        char last = s.charAt(length - 1);
-        if ((last == 'y') || (last == 'N')) {
-            return parseDblName(s, length);
-        }
+		// See if this could be a named double
+		char last = s.charAt(length - 1);
+		if ((last == 'y') || (last == 'N')) {
+			return parseDblName(s, length);
+		}
         
         // See if it could be a hexadecimal representation
         if (s.toLowerCase().indexOf("0x") != -1) { //$NON-NLS-1$
             return HexStringParser.parseDouble(s);
         }
         
-        StringExponentPair info = initialParse(s, length);
+		StringExponentPair info = initialParse(s, length);
 
-        double result = parseDblImpl(info.s, info.e);
-        if (info.negative)
-            result = -result;
+		double result = parseDblImpl(info.s, info.e);
+		if (info.negative)
+			result = -result;
 
-        return result;
-    }
+		return result;
+	}
 
-    /**
-     * Returns the closest float value to the real number in the string.
-     * 
-     * @param s
-     *            the String that will be parsed to a floating point
-     * @return the float closest to the real number
-     * 
-     * @exception NumberFormatException
-     *                if the String doesn't represent a float
-     */
-    public static float parseFloat(String s) {
-        s = s.trim();
-        int length = s.length();
+	/**
+	 * Returns the closest float value to the real number in the string.
+	 * 
+	 * @param s
+	 *            the String that will be parsed to a floating point
+	 * @return the float closest to the real number
+	 * 
+	 * @exception NumberFormatException
+	 *                if the String doesn't represent a float
+	 */
+	public static float parseFloat(String s) {
+		s = s.trim();
+		int length = s.length();
 
-        if (length == 0) {
-            throw new NumberFormatException(s);
-        }
+		if (length == 0) {
+			throw new NumberFormatException(s);
+		}
 
-        // See if this could be a named float
-        char last = s.charAt(length - 1);
-        if ((last == 'y') || (last == 'N')) {
-            return parseFltName(s, length);
-        }
+		// See if this could be a named float
+		char last = s.charAt(length - 1);
+		if ((last == 'y') || (last == 'N')) {
+			return parseFltName(s, length);
+		}
         
         // See if it could be a hexadecimal representation
         if (s.toLowerCase().indexOf("0x") != -1) { //$NON-NLS-1$
             return HexStringParser.parseFloat(s);
         }
         
-        StringExponentPair info = initialParse(s, length);
+		StringExponentPair info = initialParse(s, length);
 
-        float result = parseFltImpl(info.s, info.e);
-        if (info.negative)
-            result = -result;
+		float result = parseFltImpl(info.s, info.e);
+		if (info.negative)
+			result = -result;
 
-        return result;
-    }
+		return result;
+	}
 }
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/util/HexStringParser.java b/libcore/luni/src/main/java/org/apache/harmony/luni/util/HexStringParser.java
index 93bd9da..8072165 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/util/HexStringParser.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/util/HexStringParser.java
@@ -304,13 +304,13 @@
     private int getOffset(String strIntegerPart, String strDecimalPart) {
         strIntegerPart = strIntegerPart.replaceFirst("^0+", ""); //$NON-NLS-1$ //$NON-NLS-2$
         
-        //If the Interger part is a nonzero number.
+        //If the Integer part is a nonzero number.
         if (strIntegerPart.length() != 0) {
             String leadingNumber = strIntegerPart.substring(0, 1);
             return (strIntegerPart.length() - 1) * 4 + countBitsLength(Long.parseLong(leadingNumber,HEX_RADIX)) - 1;
         }
         
-        //If the Interger part is a zero number.
+        //If the Integer part is a zero number.
         int i;
         for (i = 0; i < strDecimalPart.length() && strDecimalPart.charAt(i) == '0'; i++);   
         if (i == strDecimalPart.length()) {
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/util/HistoricalNamesUtil.java b/libcore/luni/src/main/java/org/apache/harmony/luni/util/HistoricalNamesUtil.java
new file mode 100644
index 0000000..f32f976
--- /dev/null
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/util/HistoricalNamesUtil.java
@@ -0,0 +1,170 @@
+/*
+ *  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.luni.util;
+
+import java.util.HashMap;
+
+public class HistoricalNamesUtil {
+    private static HashMap<String, String> historicalNames = new HashMap<String, String>();
+
+    static {
+        historicalNames.put("Big5-HKSCS", "Big5_HKSCS");
+        historicalNames.put("EUC-JP", "EUC_JP");
+        historicalNames.put("EUC-KR", "EUC_KR");
+        historicalNames.put("GB2312", "EUC_CN");
+        historicalNames.put("IBM-Thai", "Cp838");
+        historicalNames.put("IBM00858", "Cp858");
+        historicalNames.put("IBM01140", "Cp1140");
+        historicalNames.put("IBM01141", "Cp1141");
+        historicalNames.put("IBM01142", "Cp1142");
+        historicalNames.put("IBM01143", "Cp1143");
+        historicalNames.put("IBM01144", "Cp1144");
+        historicalNames.put("IBM01145", "Cp1145");
+        historicalNames.put("IBM01146", "Cp1146");
+        historicalNames.put("IBM01147", "Cp1147");
+        historicalNames.put("IBM01148", "Cp1148");
+        historicalNames.put("IBM01149", "Cp1149");
+        historicalNames.put("IBM037", "Cp037");
+        historicalNames.put("IBM1026", "Cp1026");
+        historicalNames.put("IBM1047", "Cp1047");
+        historicalNames.put("IBM273", "Cp273");
+        historicalNames.put("IBM277", "Cp277");
+        historicalNames.put("IBM278", "Cp278");
+        historicalNames.put("IBM280", "Cp280");
+        historicalNames.put("IBM284", "Cp284");
+        historicalNames.put("IBM285", "Cp285");
+        historicalNames.put("IBM297", "Cp297");
+        historicalNames.put("IBM420", "Cp420");
+        historicalNames.put("IBM424", "Cp424");
+        historicalNames.put("IBM437", "Cp437");
+        historicalNames.put("IBM500", "Cp500");
+        historicalNames.put("IBM775", "Cp775");
+        historicalNames.put("IBM850", "Cp850");
+        historicalNames.put("IBM852", "Cp852");
+        historicalNames.put("IBM855", "Cp855");
+        historicalNames.put("IBM857", "Cp857");
+        historicalNames.put("IBM860", "Cp860");
+        historicalNames.put("IBM861", "Cp861");
+        historicalNames.put("IBM862", "Cp862");
+        historicalNames.put("IBM863", "Cp863");
+        historicalNames.put("IBM864", "Cp864");
+        historicalNames.put("IBM865", "Cp865");
+        historicalNames.put("IBM866", "Cp866");
+        historicalNames.put("IBM868", "Cp868");
+        historicalNames.put("IBM869", "Cp869");
+        historicalNames.put("IBM870", "Cp870");
+        historicalNames.put("IBM871", "Cp871");
+        historicalNames.put("IBM918", "Cp918");
+        historicalNames.put("ISO-2022-CN", "ISO2022CN");
+        historicalNames.put("ISO-2022-JP", "ISO2022JP");
+        historicalNames.put("ISO-2022-KR", "ISO2022KR");
+        historicalNames.put("ISO-8859-1", "ISO8859_1");
+        historicalNames.put("ISO-8859-13", "ISO8859_13");
+        historicalNames.put("ISO-8859-15", "ISO8859_15");
+        historicalNames.put("ISO-8859-2", "ISO8859_2");
+        historicalNames.put("ISO-8859-3", "ISO8859_3");
+        historicalNames.put("ISO-8859-4", "ISO8859_4");
+        historicalNames.put("ISO-8859-5", "ISO8859_5");
+        historicalNames.put("ISO-8859-6", "ISO8859_6");
+        historicalNames.put("ISO-8859-7", "ISO8859_7");
+        historicalNames.put("ISO-8859-8", "ISO8859_8");
+        historicalNames.put("ISO-8859-9", "ISO8859_9");
+        historicalNames.put("KOI8-R", "KOI8_R");
+        historicalNames.put("Shift_JIS", "SJIS");
+        historicalNames.put("TIS-620", "TIS620");
+        historicalNames.put("US-ASCII", "ASCII");
+        historicalNames.put("UTF-16BE", "UnicodeBigUnmarked");
+        historicalNames.put("UTF-16LE", "UnicodeLittleUnmarked");
+        historicalNames.put("UTF-8", "UTF8");
+        historicalNames.put("windows-1250", "Cp1250");
+        historicalNames.put("windows-1251", "Cp1251");
+        historicalNames.put("windows-1252", "Cp1252");
+        historicalNames.put("windows-1253", "Cp1253");
+        historicalNames.put("windows-1254", "Cp1254");
+        historicalNames.put("windows-1255", "Cp1255");
+        historicalNames.put("windows-1256", "Cp1256");
+        historicalNames.put("windows-1257", "Cp1257");
+        historicalNames.put("windows-1258", "Cp1258");
+        historicalNames.put("windows-31j", "MS932");
+        historicalNames.put("x-Big5-Solaris", "Big5_Solaris");
+        historicalNames.put("x-euc-jp-linux", "EUC_JP_LINUX");
+        historicalNames.put("x-EUC-TW", "EUC_TW");
+        historicalNames.put("x-eucJP-Open", "EUC_JP_Solaris");
+        historicalNames.put("x-IBM1006", "Cp1006");
+        historicalNames.put("x-IBM1025", "Cp1025");
+        historicalNames.put("x-IBM1046", "Cp1046");
+        historicalNames.put("x-IBM1097", "Cp1097");
+        historicalNames.put("x-IBM1098", "Cp1098");
+        historicalNames.put("x-IBM1112", "Cp1112");
+        historicalNames.put("x-IBM1122", "Cp1122");
+        historicalNames.put("x-IBM1123", "Cp1123");
+        historicalNames.put("x-IBM1124", "Cp1124");
+        historicalNames.put("x-IBM1381", "Cp1381");
+        historicalNames.put("x-IBM1383", "Cp1383");
+        historicalNames.put("x-IBM33722", "Cp33722");
+        historicalNames.put("x-IBM737", "Cp737");
+        historicalNames.put("x-IBM856", "Cp856");
+        historicalNames.put("x-IBM874", "Cp874");
+        historicalNames.put("x-IBM875", "Cp875");
+        historicalNames.put("x-IBM921", "Cp921");
+        historicalNames.put("x-IBM922", "Cp922");
+        historicalNames.put("x-IBM930", "Cp930");
+        historicalNames.put("x-IBM933", "Cp933");
+        historicalNames.put("x-IBM935", "Cp935");
+        historicalNames.put("x-IBM937", "Cp937");
+        historicalNames.put("x-IBM939", "Cp939");
+        historicalNames.put("x-IBM942", "Cp942");
+        historicalNames.put("x-IBM942C", "Cp942C");
+        historicalNames.put("x-IBM943", "Cp943");
+        historicalNames.put("x-IBM943C", "Cp943C");
+        historicalNames.put("x-IBM948", "Cp948");
+        historicalNames.put("x-IBM949", "Cp949");
+        historicalNames.put("x-IBM949C", "Cp949C");
+        historicalNames.put("x-IBM950", "Cp950");
+        historicalNames.put("x-IBM964", "Cp964");
+        historicalNames.put("x-IBM970", "Cp970");
+        historicalNames.put("x-ISCII91", "ISCII91");
+        historicalNames.put("x-ISO-2022-CN-CNS", "ISO2022CN");
+        historicalNames.put("x-ISO-2022-CN-GB", "ISO2022CN");
+        historicalNames.put("x-JISAutoDetect", "JISAutoDetect");
+        historicalNames.put("x-MacArabic", "MacArabic");
+        historicalNames.put("x-MacCentralEurope", "MacCentralEurope");
+        historicalNames.put("x-MacCroatian", "MacCroatian");
+        historicalNames.put("x-MacCyrillic", "MacCyrillic");
+        historicalNames.put("x-MacDingbat", "MacDingbat");
+        historicalNames.put("x-MacGreek", "MacGreek");
+        historicalNames.put("x-MacHebrew", "MacHebrew");
+        historicalNames.put("x-MacIceland", "MacIceland");
+        historicalNames.put("x-MacRoman", "MacRoman");
+        historicalNames.put("x-MacRomania", "MacRomania");
+        historicalNames.put("x-MacSymbol", "MacSymbol");
+        historicalNames.put("x-MacThai", "MacThai");
+        historicalNames.put("x-MacTurkish", "MacTurkish");
+        historicalNames.put("x-MacUkraine", "MacUkraine");
+        historicalNames.put("x-MS950-HKSCS", "MS950_HKSCS");
+        historicalNames.put("x-mswin-936", "MS936");
+        historicalNames.put("x-PCK", "PCK");
+        historicalNames.put("x-windows-874", "MS874");
+        historicalNames.put("x-windows-949", "MS949");
+        historicalNames.put("x-windows-950", "MS950");
+    }
+
+    public static String getHistoricalName(String name) {
+        return (!historicalNames.containsKey(name) ? name : historicalNames
+                .get(name));
+    }
+}
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/util/Inet6Util.java b/libcore/luni/src/main/java/org/apache/harmony/luni/util/Inet6Util.java
index 8c8257b..55914de 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/util/Inet6Util.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/util/Inet6Util.java
@@ -24,296 +24,7 @@
  */
 public class Inet6Util {
 
-    /**
-     * Creates an byte[] based on an ipAddressString. No error handling is
-     * performed here.
-     */
-    public static byte[] createByteArrayFromIPAddressString(
-            String ipAddressString) {
 
-        if (isValidIPV4Address(ipAddressString)) {
-            StringTokenizer tokenizer = new StringTokenizer(ipAddressString, ".");
-            String token = "";
-            int tempInt = 0;
-            byte[] byteAddress = new byte[4];
-            for (int i = 0; i < 4; i++) {
-                token = tokenizer.nextToken();
-                tempInt = Integer.parseInt(token);
-                byteAddress[i] = (byte) tempInt;
-            }
-
-            return byteAddress;
-        }
-        
-        if (ipAddressString.charAt(0) == '[') {
-            ipAddressString = ipAddressString.substring(1, ipAddressString.length() - 1);
-        }
-
-        StringTokenizer tokenizer = new StringTokenizer(ipAddressString, ":.", true);
-        ArrayList<String> hexStrings = new ArrayList<String>();
-        ArrayList<String> decStrings = new ArrayList<String>();
-        String token = "";
-        String prevToken = "";
-        // If a double colon exists, we need to insert 0s.
-        int doubleColonIndex = -1;
-
-        /*
-         * Go through the tokens, including the separators ':' and '.' When we
-         * hit a : or . the previous token will be added to either the hex list
-         * or decimal list. In the case where we hit a :: we will save the index
-         * of the hexStrings so we can add zeros in to fill out the string
-         */
-        while (tokenizer.hasMoreTokens()) {
-            prevToken = token;
-            token = tokenizer.nextToken();
-
-            if (token.equals(":")) {
-                if (prevToken.equals(":")) {
-                    doubleColonIndex = hexStrings.size();
-                } else if (!prevToken.equals("")) {
-                    hexStrings.add(prevToken);
-                }
-            } else if (token.equals(".")) {
-                decStrings.add(prevToken);
-            }
-        }
-
-        if (prevToken.equals(":")) {
-            if (token.equals(":")) {
-                doubleColonIndex = hexStrings.size();
-            } else {
-                hexStrings.add(token);
-            }
-        } else if (prevToken.equals(".")) {
-            decStrings.add(token);
-        }
-
-        // figure out how many hexStrings we should have
-        // also check if it is a IPv4 address
-        int hexStringsLength = 8;
-
-        // If we have an IPv4 address tagged on at the end, subtract
-        // 4 bytes, or 2 hex words from the total
-        if (decStrings.size() > 0) {
-            hexStringsLength -= 2;
-        }
-
-        // if we hit a double Colon add the appropriate hex strings
-        if (doubleColonIndex != -1) {
-            int numberToInsert = hexStringsLength - hexStrings.size();
-            for (int i = 0; i < numberToInsert; i++) {
-                hexStrings.add(doubleColonIndex, "0");
-            }
-        }
-
-        byte ipByteArray[] = new byte[16];
-
-        // Finally convert these strings to bytes...
-        for (int i = 0; i < hexStrings.size(); i++) {
-            convertToBytes(hexStrings.get(i), ipByteArray, i * 2);
-        }
-
-        // Now if there are any decimal values, we know where they go...
-        for (int i = 0; i < decStrings.size(); i++) {
-            ipByteArray[i + 12] = (byte) (Integer.parseInt(decStrings.get(i)) & 255);
-        }
-
-        // now check to see if this guy is actually and IPv4 address
-        // an ipV4 address is ::FFFF:d.d.d.d
-        boolean ipV4 = true;
-        for (int i = 0; i < 10; i++) {
-            if (ipByteArray[i] != 0) {
-                ipV4 = false;
-                break;
-            }
-        }
-
-        if (ipByteArray[10] != -1 || ipByteArray[11] != -1) {
-            ipV4 = false;
-        }
-
-        if (ipV4) {
-            byte ipv4ByteArray[] = new byte[4];
-            for (int i = 0; i < 4; i++) {
-                ipv4ByteArray[i] = ipByteArray[i + 12];
-            }
-            return ipv4ByteArray;
-        }
-        
-        return ipByteArray;
-
-    }
-
-    // BEGIN android-changed
-    static char[] hexCharacters = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
-            '9', 'a', 'b', 'c', 'd', 'e', 'f'};
-    // END android-changed
-
-    public static String createIPAddrStringFromByteArray(byte ipByteArray[]) {
-        if (ipByteArray.length == 4) {
-            return addressToString(bytesToInt(ipByteArray, 0));
-        }
-
-        if (ipByteArray.length == 16) {
-            if (isIPv4MappedAddress(ipByteArray)) {
-                byte ipv4ByteArray[] = new byte[4];
-                for (int i = 0; i < 4; i++) {
-                    ipv4ByteArray[i] = ipByteArray[i + 12];
-                }
-                return addressToString(bytesToInt(ipv4ByteArray, 0));
-            }
-            StringBuilder buffer = new StringBuilder();
-            // BEGIN android-changed
-            for (int i = 0; i < 8; i++) { // ipByteArray.length / 2
-
-                int num = (ipByteArray[2 * i] & 0xff) << 8;
-                num ^= ipByteArray[2 * i + 1] & 0xff;
-
-                // count the digits to display without leading 0
-                int count = 1, j = num;
-                while ((j >>>= 4) != 0) {
-                    count++;
-                }
-
-                char[] buf = new char[count];
-                do {
-                    int t = num & 0x0f;
-                    buf[--count] = hexCharacters[t];
-                    num >>>= 4;
-                } while (count > 0);
-
-                buffer.append(buf);
-                if ((i + 1) < 8) { // ipByteArray.length / 2
-                    buffer.append(":");
-                }
-            }
-            // END android-changed
-            return buffer.toString();
-        }
-        return null;
-    }
-
-    /** Converts a 4 character hex word into a 2 byte word equivalent */
-    public static void convertToBytes(String hexWord, byte ipByteArray[],
-            int byteIndex) {
-
-        int hexWordLength = hexWord.length();
-        int hexWordIndex = 0;
-        ipByteArray[byteIndex] = 0;
-        ipByteArray[byteIndex + 1] = 0;
-        int charValue;
-
-        // high order 4 bits of first byte
-        if (hexWordLength > 3) {
-            charValue = getIntValue(hexWord.charAt(hexWordIndex++));
-            ipByteArray[byteIndex] = (byte) (ipByteArray[byteIndex] | (charValue << 4));
-        }
-
-        // low order 4 bits of the first byte
-        if (hexWordLength > 2) {
-            charValue = getIntValue(hexWord.charAt(hexWordIndex++));
-            ipByteArray[byteIndex] = (byte) (ipByteArray[byteIndex] | charValue);
-        }
-
-        // high order 4 bits of second byte
-        if (hexWordLength > 1) {
-            charValue = getIntValue(hexWord.charAt(hexWordIndex++));
-            ipByteArray[byteIndex + 1] = (byte) (ipByteArray[byteIndex + 1] | (charValue << 4));
-        }
-
-        // low order 4 bits of the first byte
-        charValue = getIntValue(hexWord.charAt(hexWordIndex));
-        ipByteArray[byteIndex + 1] = (byte) (ipByteArray[byteIndex + 1] | charValue & 15);
-    }
-
-    static int getIntValue(char c) {
-
-        switch (c) {
-        case '0':
-            return 0;
-        case '1':
-            return 1;
-        case '2':
-            return 2;
-        case '3':
-            return 3;
-        case '4':
-            return 4;
-        case '5':
-            return 5;
-        case '6':
-            return 6;
-        case '7':
-            return 7;
-        case '8':
-            return 8;
-        case '9':
-            return 9;
-        }
-
-        c = Character.toLowerCase(c);
-        switch (c) {
-        case 'a':
-            return 10;
-        case 'b':
-            return 11;
-        case 'c':
-            return 12;
-        case 'd':
-            return 13;
-        case 'e':
-            return 14;
-        case 'f':
-            return 15;
-        }
-        return 0;
-    }
-
-    private static boolean isIPv4MappedAddress(byte ipAddress[]) {
-
-        // Check if the address matches ::FFFF:d.d.d.d
-        // The first 10 bytes are 0. The next to are -1 (FF).
-        // The last 4 bytes are varied.
-        for (int i = 0; i < 10; i++) {
-            if (ipAddress[i] != 0) {
-                return false;
-            }
-        }
-
-        if (ipAddress[10] != -1 || ipAddress[11] != -1) {
-            return false;
-        }
-
-        return true;
-
-    }
-
-    /**
-     * Takes the byte array and creates an integer out of four bytes starting at
-     * start as the high-order byte. This method makes no checks on the validity
-     * of the parameters.
-     */
-    public static int bytesToInt(byte bytes[], int start) {
-        // First mask the byte with 255, as when a negative
-        // signed byte converts to an integer, it has bits
-        // on in the first 3 bytes, we are only concerned
-        // about the right-most 8 bits.
-        // Then shift the rightmost byte to align with its
-        // position in the integer.
-        int value = ((bytes[start + 3] & 255))
-                | ((bytes[start + 2] & 255) << 8)
-                | ((bytes[start + 1] & 255) << 16)
-                | ((bytes[start] & 255) << 24);
-        return value;
-    }
-
-    public static String addressToString(int value) {
-        return ((value >> 24) & 0xff) + "." + ((value >> 16) & 0xff) + "."
-                + ((value >> 8) & 0xff) + "." + (value & 0xff);
-    }
-
-    // BEGIN android-added
-    // copied from a newer version of harmony
     public static boolean isIP6AddressInFullForm(String ipAddress) {
         if (isValidIP6Address(ipAddress)) {
             int doubleColonIndex = ipAddress.indexOf("::");
@@ -325,215 +36,214 @@
         }
         return false;
     }
-    // END android-added
 
-    public static boolean isValidIP6Address(String ipAddress) {
-        int length = ipAddress.length();
-        boolean doubleColon = false;
-        int numberOfColons = 0;
-        int numberOfPeriods = 0;
-        int numberOfPercent = 0;
-        String word = "";
-        char c = 0;
-        char prevChar = 0;
-        int offset = 0; // offset for [] IP addresses
+	public static boolean isValidIP6Address(String ipAddress) {
+		int length = ipAddress.length();
+		boolean doubleColon = false;
+		int numberOfColons = 0;
+		int numberOfPeriods = 0;
+		int numberOfPercent = 0;
+		String word = "";
+		char c = 0;
+		char prevChar = 0;
+		int offset = 0; // offset for [] IP addresses
 
-        if (length < 2) {
+		if (length < 2) {
             return false;
         }
 
-        for (int i = 0; i < length; i++) {
-            prevChar = c;
-            c = ipAddress.charAt(i);
-            switch (c) {
+		for (int i = 0; i < length; i++) {
+			prevChar = c;
+			c = ipAddress.charAt(i);
+			switch (c) {
 
-            // case for an open bracket [x:x:x:...x]
-            case '[':
-                if (i != 0) {
+			// case for an open bracket [x:x:x:...x]
+			case '[':
+				if (i != 0) {
                     return false; // must be first character
                 }
-                if (ipAddress.charAt(length - 1) != ']') {
+				if (ipAddress.charAt(length - 1) != ']') {
                     return false; // must have a close ]
                 }
-                offset = 1;
-                if (length < 4) {
+				offset = 1;
+				if (length < 4) {
                     return false;
                 }
-                break;
+				break;
 
-            // case for a closed bracket at end of IP [x:x:x:...x]
-            case ']':
-                if (i != length - 1) {
+			// case for a closed bracket at end of IP [x:x:x:...x]
+			case ']':
+				if (i != length - 1) {
                     return false; // must be last character
                 }
-                if (ipAddress.charAt(0) != '[') {
+				if (ipAddress.charAt(0) != '[') {
                     return false; // must have a open [
                 }
-                break;
+				break;
 
-            // case for the last 32-bits represented as IPv4 x:x:x:x:x:x:d.d.d.d
-            case '.':
-                numberOfPeriods++;
-                if (numberOfPeriods > 3) {
+			// case for the last 32-bits represented as IPv4 x:x:x:x:x:x:d.d.d.d
+			case '.':
+				numberOfPeriods++;
+				if (numberOfPeriods > 3) {
                     return false;
                 }
-                if (!isValidIP4Word(word)) {
+				if (!isValidIP4Word(word)) {
                     return false;
                 }
-                if (numberOfColons != 6 && !doubleColon) {
+				if (numberOfColons != 6 && !doubleColon) {
                     return false;
                 }
-                // a special case ::1:2:3:4:5:d.d.d.d allows 7 colons with an
-                // IPv4 ending, otherwise 7 :'s is bad
-                if (numberOfColons == 7 && ipAddress.charAt(0 + offset) != ':'
-                        && ipAddress.charAt(1 + offset) != ':') {
+				// a special case ::1:2:3:4:5:d.d.d.d allows 7 colons with an
+				// IPv4 ending, otherwise 7 :'s is bad
+				if (numberOfColons == 7 && ipAddress.charAt(0 + offset) != ':'
+						&& ipAddress.charAt(1 + offset) != ':') {
                     return false;
                 }
-                word = "";
-                break;
+				word = "";
+				break;
 
-            case ':':
-                numberOfColons++;
-                if (numberOfColons > 7) {
+			case ':':
+				numberOfColons++;
+				if (numberOfColons > 7) {
                     return false;
                 }
-                if (numberOfPeriods > 0) {
+				if (numberOfPeriods > 0) {
                     return false;
                 }
-                if (prevChar == ':') {
-                    if (doubleColon) {
+				if (prevChar == ':') {
+					if (doubleColon) {
                         return false;
                     }
-                    doubleColon = true;
-                }
-                word = "";
-                break;
-            case '%':
-                if (numberOfColons == 0) {
+					doubleColon = true;
+				}
+				word = "";
+				break;
+			case '%':
+				if (numberOfColons == 0) {
                     return false;
                 }
-                numberOfPercent++;
+				numberOfPercent++;
 
-                // validate that the stuff after the % is valid
-                if ((i + 1) >= length) {
-                    // in this case the percent is there but no number is
-                    // available
-                    return false;
-                }
-                try {
-                    Integer.parseInt(ipAddress.substring(i + 1));
-                } catch (NumberFormatException e) {
-                    // right now we just support an integer after the % so if
-                    // this is not
-                    // what is there then return
-                    return false;
-                }
-                break;
+				// validate that the stuff after the % is valid
+				if ((i + 1) >= length) {
+					// in this case the percent is there but no number is
+					// available
+					return false;
+				}
+				try {
+					Integer.parseInt(ipAddress.substring(i + 1));
+				} catch (NumberFormatException e) {
+					// right now we just support an integer after the % so if
+					// this is not
+					// what is there then return
+					return false;
+				}
+				break;
 
-            default:
-                if (numberOfPercent == 0) {
-                    if (word.length() > 3) {
+			default:
+				if (numberOfPercent == 0) {
+					if (word.length() > 3) {
                         return false;
                     }
-                    if (!isValidHexChar(c)) {
+					if (!isValidHexChar(c)) {
                         return false;
                     }
-                }
-                word += c;
-            }
-        }
+				}
+				word += c;
+			}
+		}
 
-        // Check if we have an IPv4 ending
-        if (numberOfPeriods > 0) {
-            if (numberOfPeriods != 3 || !isValidIP4Word(word)) {
+		// Check if we have an IPv4 ending
+		if (numberOfPeriods > 0) {
+			if (numberOfPeriods != 3 || !isValidIP4Word(word)) {
                 return false;
             }
-        } else {
-            // If we're at then end and we haven't had 7 colons then there is a
-            // problem unless we encountered a doubleColon
-            if (numberOfColons != 7 && !doubleColon) {
+		} else {
+			// If we're at then end and we haven't had 7 colons then there is a
+			// problem unless we encountered a doubleColon
+			if (numberOfColons != 7 && !doubleColon) {
+				return false;
+			}
+
+			// If we have an empty word at the end, it means we ended in either
+			// a : or a .
+			// If we did not end in :: then this is invalid
+			if (numberOfPercent == 0) {
+				if (word == "" && ipAddress.charAt(length - 1 - offset) == ':'
+						&& ipAddress.charAt(length - 2 - offset) != ':') {
+					return false;
+				}
+			}
+		}
+
+		return true;
+	}
+
+	public static boolean isValidIP4Word(String word) {
+		char c;
+		if (word.length() < 1 || word.length() > 3) {
+            return false;
+        }
+		for (int i = 0; i < word.length(); i++) {
+			c = word.charAt(i);
+			if (!(c >= '0' && c <= '9')) {
+                return false;
+            }
+		}
+		if (Integer.parseInt(word) > 255) {
+            return false;
+        }
+		return true;
+	}
+
+	static boolean isValidHexChar(char c) {
+
+		return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')
+				|| (c >= 'a' && c <= 'f');
+	}
+
+	/**
+	 * Takes a string and parses it to see if it is a valid IPV4 address.
+	 *
+	 * @return true, if the string represents an IPV4 address in dotted
+	 *         notation, false otherwise
+	 */
+	public static boolean isValidIPV4Address(String value) {
+            // BEGIN android-changed
+            // general test
+            if (!value.matches("\\p{Digit}+(\\.\\p{Digit}+)*")) {
                 return false;
             }
 
-            // If we have an empty word at the end, it means we ended in either
-            // a : or a .
-            // If we did not end in :: then this is invalid
-            if (numberOfPercent == 0) {
-                if (word == "" && ipAddress.charAt(length - 1 - offset) == ':'
-                        && ipAddress.charAt(length - 2 - offset) != ':') {
-                    return false;
-                }
-            }
-        }
-
-        return true;
-    }
-
-    public static boolean isValidIP4Word(String word) {
-        char c;
-        if (word.length() < 1 || word.length() > 3) {
-            return false;
-        }
-        for (int i = 0; i < word.length(); i++) {
-            c = word.charAt(i);
-            if (!(c >= '0' && c <= '9')) {
+            String[] parts = value.split("\\.");
+            int length = parts.length;
+            if (length < 1 || length > 4) {
                 return false;
             }
-        }
-        if (Integer.parseInt(word) > 255) {
-            return false;
-        }
-        return true;
-    }
 
-    static boolean isValidHexChar(char c) {
-
-        return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')
-                || (c >= 'a' && c <= 'f');
-    }
-
-    /**
-     * Takes a string and parses it to see if it is a valid IPV4 address.
-     * 
-     * @return true, if the string represents an IPV4 address in dotted
-     *         notation, false otherwise
-     */
-    public static boolean isValidIPV4Address(String value) {
-        // BEGIN android-changed
-        // general test
-        if (!value.matches("\\p{Digit}+(\\.\\p{Digit}+)*")) {
-            return false;
-        }
-
-        String[] parts = value.split("\\.");
-        int length = parts.length;
-        if (length < 1 || length > 4) {
-            return false;
-        }
-
-        if (length == 1) {
-            // One part decimal numeric address
-            long longValue = Long.parseLong(parts[0]);
-            return longValue <= 0xFFFFFFFFL;
-        } else {
-            // Test each part for inclusion in the correct range
-            for (int i = 0; i < length; i++) {
-                // For two part addresses, the second part expresses
-                // a 24-bit quantity; for three part addresses, the third
-                // part expresses a 16-bit quantity.
-                int max = 0xff;
-                if ((length == 2) && (i == 1)) {
-                    max = 0xffffff;
-                } else if ((length == 3) && (i == 2)) {
-                    max = 0xffff;
+            if (length == 1) {
+                // One part decimal numeric address
+                long longValue = Long.parseLong(parts[0]);
+                return longValue <= 0xFFFFFFFFL;
+            } else {
+                // Test each part for inclusion in the correct range
+                for (int i = 0; i < length; i++) {
+                    // For two part addresses, the second part expresses
+                    // a 24-bit quantity; for three part addresses, the third
+                    // part expresses a 16-bit quantity.
+                    int max = 0xff;
+                    if ((length == 2) && (i == 1)) {
+                        max = 0xffffff;
+                    } else if ((length == 3) && (i == 2)) {
+                        max = 0xffff;
+                    }
+                    if (Integer.parseInt(parts[i]) > max) {
+                        return false;
+                    }
                 }
-                if (Integer.parseInt(parts[i]) > max) {
-                    return false;
-                }
+                return true;
             }
-            return true;
-        }
-        // END android-changed
-    }
+            // END android-changed
+	}
 
 }
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/util/InputStreamExposer.java b/libcore/luni/src/main/java/org/apache/harmony/luni/util/InputStreamExposer.java
new file mode 100644
index 0000000..51a2d28
--- /dev/null
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/util/InputStreamExposer.java
@@ -0,0 +1,118 @@
+/*
+ *  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.luni.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * The class contains static {@link java.io.InputStream} utilities.
+ */
+public class InputStreamExposer {
+
+    /**
+     * Provides access to a protected underlying buffer of
+     * <code>ByteArrayInputStream</code>.
+     */
+    private static final Field BAIS_BUF;
+
+    /**
+     * Provides access to a protected position in the underlying buffer of
+     * <code>ByteArrayInputStream</code>.
+     */
+    private static final Field BAIS_POS;
+
+    static {
+        final Field[] f = new Field[2];
+        AccessController.doPrivileged(new PrivilegedAction<Object>() {
+            public Object run() {
+                try {
+                    f[0] = ByteArrayInputStream.class.getDeclaredField("buf");
+                    f[0].setAccessible(true);
+                    f[1] = ByteArrayInputStream.class.getDeclaredField("pos");
+                    f[1].setAccessible(true);
+                } catch (NoSuchFieldException nsfe) {
+                    throw new InternalError(nsfe.getLocalizedMessage());
+                }
+                return null;
+            }
+        });
+        BAIS_BUF = f[0];
+        BAIS_POS = f[1];
+    }
+
+    /**
+     * Reads all bytes from {@link java.io.ByteArrayInputStream} using its
+     * underlying buffer directly.
+     *
+     * @return an underlying buffer, if a current position is at the buffer
+     *         beginning, and an end position is at the buffer end, or a copy of
+     *         the underlying buffer part.
+     */
+    private static byte[] expose(ByteArrayInputStream bais) {
+        byte[] buffer, buf;
+        int pos;
+        synchronized (bais) {
+            int available = bais.available();
+            try {
+                buf = (byte[]) BAIS_BUF.get(bais);
+                pos = BAIS_POS.getInt(bais);
+            } catch (IllegalAccessException iae) {
+                throw new InternalError(iae.getLocalizedMessage());
+            }
+            if (pos == 0 && available == buf.length) {
+                buffer = buf;
+            } else {
+                buffer = new byte[available];
+                System.arraycopy(buf, pos, buffer, 0, available);
+            }
+            bais.skip(available);
+        }
+        return buffer;
+    }
+
+    /**
+     * The utility method for reading the whole input stream into a snapshot
+     * buffer. To speed up the access it works with an underlying buffer for a
+     * given {@link java.io.ByteArrayInputStream}.
+     *
+     * @param is
+     *            the stream to be read.
+     * @return the snapshot wrapping the buffer where the bytes are read to.
+     * @throws UnsupportedOperationException if the input stream data cannot be exposed
+     */
+    public static byte[] expose(InputStream is) throws IOException, UnsupportedOperationException {
+        // BEGIN android-changed
+        // if (is instanceof ExposedByteArrayInputStream) {
+        //     return ((ExposedByteArrayInputStream) is).expose();
+        // }
+        // END android-changed
+
+        if (is.getClass().equals(ByteArrayInputStream.class)) {
+            return expose((ByteArrayInputStream) is);
+        }
+
+        // We don't know how to do this
+        throw new UnsupportedOperationException();
+    }
+}
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/util/Sorter.java b/libcore/luni/src/main/java/org/apache/harmony/luni/util/Sorter.java
deleted file mode 100644
index 1a994b2..0000000
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/util/Sorter.java
+++ /dev/null
@@ -1,44 +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.luni.util;
-
-import java.util.Arrays;
-
-/**
- * Helper class with methods for sorting arrays.
- * @deprecated Use {@link Comparator} and {@link Arrays.sort()}
- */
-@Deprecated
-public final class Sorter {
-    public interface Comparator<T> extends java.util.Comparator<T> {
-    }
-
-    /**
-     * Sorts the array of objects using the default sorting algorithm.
-     * 
-     * @param objs
-     *            array of objects to be sorted
-     * @param comp
-     *            A Comparator to be used to sort the elements
-     * 
-     */
-    public static <T> void sort(T[] objs, Comparator<T> comp) {
-        Arrays.sort(objs, comp);
-    }
-
-}
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/util/ThreadLocalCache.java b/libcore/luni/src/main/java/org/apache/harmony/luni/util/ThreadLocalCache.java
new file mode 100644
index 0000000..cdfe0c8
--- /dev/null
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/util/ThreadLocalCache.java
@@ -0,0 +1,103 @@
+/*
+ *  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.luni.util;
+
+import java.lang.ref.SoftReference;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+
+/**
+ * The class extends the functionality of {@link java.lang.ThreadLocal} with
+ * possibility of discarding the thread local storage content when a heap is
+ * exhausted.
+ */
+public class ThreadLocalCache<T> {
+
+    private SoftReference<ThreadLocal<T>> storage = new SoftReference<ThreadLocal<T>>(
+            null);
+
+    private ThreadLocal<T> getThreadLocal() {
+        ThreadLocal<T> tls = storage.get();
+        if (tls == null) {
+            tls = new ThreadLocal<T>() {
+                public T initialValue() {
+                    return ThreadLocalCache.this.initialValue();
+                }
+            };
+            storage = new SoftReference<ThreadLocal<T>>(tls);
+        }
+        return tls;
+    }
+
+    /**
+     * Returns the initial value for the cache for the current thread.
+     */
+    protected T initialValue() {
+        return null;
+    }
+
+    /**
+     * Returns the thread local value of this object.
+     */
+    public T get() {
+        return getThreadLocal().get();
+    }
+
+    /**
+     * Sets the value of this variable for the current thread. Might be useful
+     * for expanding the thread local cache.
+     */
+    public void set(T value) {
+        getThreadLocal().set(value);
+    }
+
+    /**
+     * Discards the cache for all threads.
+     */
+    public void remove() {
+        storage.clear();
+    }
+
+    public static ThreadLocalCache<CharsetDecoder> utf8Decoder = new ThreadLocalCache<CharsetDecoder>() {
+        protected CharsetDecoder initialValue() {
+            return Charset.forName("UTF-8").newDecoder();
+        }
+    };
+
+    public static ThreadLocalCache<CharsetEncoder> utf8Encoder = new ThreadLocalCache<CharsetEncoder>() {
+        protected CharsetEncoder initialValue() {
+            return Charset.forName("UTF-8").newEncoder();
+        }
+    };
+
+    public static ThreadLocalCache<java.nio.ByteBuffer> byteBuffer = new ThreadLocalCache<java.nio.ByteBuffer>() {
+        protected java.nio.ByteBuffer initialValue() {
+            return java.nio.ByteBuffer.allocate(72); // >=
+            // Manifest.LINE_LENGTH_LIMIT
+        }
+    };
+
+    public static ThreadLocalCache<CharBuffer> charBuffer = new ThreadLocalCache<CharBuffer>() {
+        protected CharBuffer initialValue() {
+            return CharBuffer.allocate(72); // no specific requirement
+        }
+    };
+
+}
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/util/TwoKeyHashMap.java b/libcore/luni/src/main/java/org/apache/harmony/luni/util/TwoKeyHashMap.java
index 26e8d01..655d156 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/util/TwoKeyHashMap.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/util/TwoKeyHashMap.java
@@ -29,7 +29,7 @@
 import java.util.Set;
 
 /**
- *
+ * 
  * Reductive hash with two keys
  * 
  */
@@ -37,13 +37,13 @@
 
     static final float DEFAULT_LOAD_FACTOR = 0.75f;
     static final int DEFAULT_INITIAL_SIZE = 16;
-    
+
     private Set<Map.Entry<String, V>> entrySet;
     private Collection<V> values;
     private int size;
     private int arrSize;
     private int modCount;
-    
+
     private Entry<E, K, V>[] arr;
 
     private float loadFactor;
@@ -55,9 +55,10 @@
     public TwoKeyHashMap() {
         this(DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR);
     }
-    
+
     /**
      * Constructs an empty HashMap
+     * 
      * @param initialCapacity
      */
     public TwoKeyHashMap(int initialCapacity) {
@@ -65,16 +66,19 @@
     }
 
     /**
-     * Constructs an empty HashMap 
+     * Constructs an empty HashMap
+     * 
      * @param initialCapacity
      * @param initialLoadFactor
      */
+    @SuppressWarnings("unchecked")
     public TwoKeyHashMap(int initialCapacity, float initialLoadFactor) {
-         if (initialCapacity < 0) {
+        if (initialCapacity < 0) {
             throw new IllegalArgumentException("initialCapacity should be >= 0");
         }
         if (initialLoadFactor <= 0) {
-            throw new IllegalArgumentException("initialLoadFactor should be > 0");
+            throw new IllegalArgumentException(
+                    "initialLoadFactor should be > 0");
         }
         loadFactor = initialLoadFactor;
         if (initialCapacity == Integer.MAX_VALUE) {
@@ -84,9 +88,9 @@
         threshold = (int) (arrSize * loadFactor);
         arr = new Entry[arrSize + 1];
     }
-    
+
     /**
-     * Returns a collection view of the values 
+     * Returns a collection view of the values
      */
     public Collection<V> values() {
         if (values == null) {
@@ -94,9 +98,9 @@
         }
         return values;
     }
-    
+
     /**
-     * Returns a collection view of the mappings  
+     * Returns a collection view of the mappings
      */
     public Set<Map.Entry<String, V>> entrySet() {
         if (entrySet == null) {
@@ -104,7 +108,7 @@
         }
         return entrySet;
     }
-    
+
     /**
      * Clears the map
      */
@@ -116,6 +120,7 @@
 
     /**
      * Removes the mapping for the keys
+     * 
      * @param key1
      * @param key2
      * @return
@@ -124,9 +129,10 @@
         Entry<E, K, V> e = removeEntry(key1, key2);
         return null != e ? e.value : null;
     }
-    
+
     /**
      * Associates the specified value with the specified keys in this map
+     * 
      * @param key1
      * @param key2
      * @param value
@@ -152,7 +158,8 @@
         Entry<E, K, V> e = arr[index];
 
         while (e != null) {
-            if (hash == e.hash && key1.equals(e.getKey1()) && key2.equals(e.getKey2())) {
+            if (hash == e.hash && key1.equals(e.getKey1())
+                    && key2.equals(e.getKey2())) {
                 V oldValue = e.value;
                 e.value = value;
                 return oldValue;
@@ -172,8 +179,9 @@
 
     /**
      * Rehash the map
-     *
+     * 
      */
+    @SuppressWarnings("unchecked")
     void rehash() {
         int newArrSize = (arrSize + 1) * 2 + 1;
         if (newArrSize < 0) {
@@ -206,10 +214,12 @@
     }
 
     /**
-     * Returns true if this map contains a mapping for the specified keys
-     * @param key1
-     * @param key2
-     * @return
+     * Answers whether this map contains a mapping for the specified keys.
+     * 
+     * @param key1 first key
+     * @param key2 second key
+     * @return true if this map contains a mapping for the specified keys, and
+     *         false otherwise.
      */
     public boolean containsKey(Object key1, Object key2) {
         return findEntry(key1, key2) != null;
@@ -217,6 +227,7 @@
 
     /**
      * Return the value by keys
+     * 
      * @param key1
      * @param key2
      * @return
@@ -237,14 +248,15 @@
     }
 
     /**
-     * Returns the number of mappings 
+     * Returns the number of mappings
      */
     public int size() {
         return size;
     }
-    
+
     /**
-     *  Creates new entry
+     * Creates new entry
+     * 
      * @param hashCode
      * @param key1
      * @param key2
@@ -252,13 +264,14 @@
      * @param next
      * @return
      */
-    Entry<E, K, V> createEntry(int hashCode, E key1, K key2, 
-            V value, Entry<E, K, V> next) {
+    Entry<E, K, V> createEntry(int hashCode, E key1, K key2, V value,
+            Entry<E, K, V> next) {
         return new Entry<E, K, V>(hashCode, key1, key2, value, next);
     }
 
     /**
      * Creates entries iterator
+     * 
      * @return
      */
     Iterator<Map.Entry<String, V>> createEntrySetIterator() {
@@ -267,18 +280,18 @@
 
     /**
      * Creates values iterator
+     * 
      * @return
      */
     Iterator<V> createValueCollectionIterator() {
         return new ValueIteratorImpl();
     }
 
-    
     /**
      * Entry implementation for the TwoKeyHashMap class
      * 
      */
-    public static class Entry<E, K, V> implements Map.Entry<String, V> { 
+    public static class Entry<E, K, V> implements Map.Entry<String, V> {
         int hash;
         E key1;
         K key2;
@@ -292,7 +305,7 @@
             this.value = value;
             this.next = next;
         }
-        
+
         public String getKey() {
             return key1.toString() + key2.toString();
         }
@@ -300,7 +313,7 @@
         public E getKey1() {
             return key1;
         }
-        
+
         public K getKey2() {
             return key2;
         }
@@ -324,12 +337,11 @@
             Object getKey1 = e.getKey1();
             Object getKey2 = e.getKey2();
             Object getValue = e.getValue();
-            if ((key1 == null && getKey1 != null) || 
-                    (key2 == null && getKey2 != null) ||
-                    (value == null && getValue != null) ||
-                    !key1.equals(e.getKey1()) ||
-                    !key2.equals(e.getKey2()) ||
-                    !value.equals(getValue)) {
+            if ((key1 == null && getKey1 != null)
+                    || (key2 == null && getKey2 != null)
+                    || (value == null && getValue != null)
+                    || !key1.equals(e.getKey1()) || !key2.equals(e.getKey2())
+                    || !value.equals(getValue)) {
                 return false;
             }
             return true;
@@ -340,9 +352,9 @@
             int hash2 = (key2 == null ? 0 : key2.hashCode());
             return (hash1 + hash2) ^ (value == null ? 0 : value.hashCode());
         }
-        
+
     }
-    
+
     class EntrySetImpl extends AbstractSet<Map.Entry<String, V>> {
         public int size() {
             return size;
@@ -375,7 +387,7 @@
             if (!(obj instanceof Entry)) {
                 return false;
             }
-            return removeEntry(((Entry) obj).getKey1(), ((Entry)obj).getKey2()) != null;
+            return removeEntry(((Entry) obj).getKey1(), ((Entry) obj).getKey2()) != null;
         }
 
         public Iterator<Map.Entry<String, V>> iterator() {
@@ -425,14 +437,14 @@
             found = false;
             returned_index = curr;
             returned_entry = curr_entry;
-            return (Map.Entry<String, V>)curr_entry;
+            return (Map.Entry<String, V>) curr_entry;
         }
 
         public void remove() {
             if (returned_index == -1) {
                 throw new IllegalStateException();
             }
-            
+
             if (modCount != startModCount) {
                 throw new ConcurrentModificationException();
             }
@@ -454,7 +466,7 @@
             returned_index = -1;
         }
     }
-    
+
     private final Entry<E, K, V> findEntry(Object key1, Object key2) {
         if (key1 == null && key2 == null) {
             return arr[arrSize];
@@ -465,14 +477,15 @@
         Entry<E, K, V> e = arr[index];
 
         while (e != null) {
-            if (hash == e.hash && key1.equals(e.getKey1()) && key2.equals(e.getKey2())) {
+            if (hash == e.hash && key1.equals(e.getKey1())
+                    && key2.equals(e.getKey2())) {
                 return e;
             }
             e = e.next;
         }
         return null;
     }
-    
+
     // Removes entry
     private final Entry<E, K, V> removeEntry(Object key1, Object key2) {
         if (key1 == null && key2 == null) {
@@ -493,7 +506,8 @@
         Entry<E, K, V> e = arr[index];
         Entry<E, K, V> prev = e;
         while (e != null) {
-            if (hash == e.hash && key1.equals(e.getKey1()) && key2.equals(e.getKey2())) {
+            if (hash == e.hash && key1.equals(e.getKey1())
+                    && key2.equals(e.getKey2())) {
                 if (prev == e) {
                     arr[index] = e.next;
                 } else {
@@ -529,12 +543,12 @@
         public Iterator<V> iterator() {
             return createValueCollectionIterator();
         }
-        
+
         public boolean contains(Object obj) {
             return containsValue(obj);
         }
     }
-    
+
     class ValueIteratorImpl implements Iterator<V> {
         private EntryIteratorImpl itr;
 
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/util/Util.java b/libcore/luni/src/main/java/org/apache/harmony/luni/util/Util.java
index bfb0149..e4515ae 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/util/Util.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/util/Util.java
@@ -20,216 +20,262 @@
 
 import java.io.ByteArrayOutputStream;
 import java.io.UTFDataFormatException;
+import java.io.UnsupportedEncodingException;
 import java.util.Calendar;
 import java.util.TimeZone;
 
 public final class Util {
 
-    private static String[] WEEKDAYS = new String[] { "", "Sunday", "Monday",
-            "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
+	private static String[] WEEKDAYS = new String[] { "", "Sunday", "Monday",
+			"Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
 
-    private static String[] MONTHS = new String[] { "January", "February",
-            "March", "April", "May", "June", "July", "August", "September",
-            "October", "November", "December" };
+	private static String[] MONTHS = new String[] { "January", "February",
+			"March", "April", "May", "June", "July", "August", "September",
+			"October", "November", "December" };
 
-    private static final String defaultEncoding;
+	private static final String defaultEncoding;
 
-    static {
+	static {
         // BEGIN android-changed
         String encoding = System.getProperty("file.encoding");
         // END android-changed
-        if (encoding != null) {
-            try {
-                "".getBytes(encoding);
-            } catch (java.io.UnsupportedEncodingException e) {
+		if (encoding != null) {
+			try {
+				"".getBytes(encoding);
+            } catch (Throwable t) {
                 encoding = null;
-            }
-        }
+			}
+		}
         defaultEncoding = encoding;
-    }
-
-    public static byte[] getBytes(String name) {
-        if (defaultEncoding != null) {
-            try {
-                return name.getBytes(defaultEncoding);
-            } catch (java.io.UnsupportedEncodingException e) {
-            }
-        }
-        return name.getBytes();
-    }
-
-    public static String toString(byte[] bytes) {
-        if (defaultEncoding != null) {
-            try {
-                return new String(bytes, 0, bytes.length, defaultEncoding);
-            } catch (java.io.UnsupportedEncodingException e) {
-            }
-        }
-        return new String(bytes, 0, bytes.length);
-    }
-
-    public static String toString(byte[] bytes, int offset, int length) {
-        if (defaultEncoding != null) {
-            try {
-                return new String(bytes, offset, length, defaultEncoding);
-            } catch (java.io.UnsupportedEncodingException e) {
-            }
-        }
-        return new String(bytes, offset, length);
-    }
+	}
 
     /**
-     * Returns the millisecond value of the date and time parsed from the
-     * specified String. Many date/time formats are recognized
-     * 
-     * @param string
-     *            the String to parse
-     * @return the millisecond value parsed from the String
+     * Get bytes from String using default encoding; default encoding can
+     * be changed via "os.encoding" property
+     * @param name input String
+     * @return byte array
      */
-    public static long parseDate(String string) {
-        int offset = 0, length = string.length(), state = 0;
-        int year = -1, month = -1, date = -1;
-        int hour = -1, minute = -1, second = -1;
-        final int PAD = 0, LETTERS = 1, NUMBERS = 2;
-        StringBuffer buffer = new StringBuffer();
-
-        while (offset <= length) {
-            char next = offset < length ? string.charAt(offset) : '\r';
-            offset++;
-
-            int nextState;
-            if ((next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z'))
-                nextState = LETTERS;
-            else if (next >= '0' && next <= '9')
-                nextState = NUMBERS;
-            else if (" ,-:\r\t".indexOf(next) == -1)
-                throw new IllegalArgumentException();
-            else
-                nextState = PAD;
-
-            if (state == NUMBERS && nextState != NUMBERS) {
-                int digit = Integer.parseInt(buffer.toString());
-                buffer.setLength(0);
-                if (digit >= 70) {
-                    if (year != -1
-                            || (next != ' ' && next != ',' && next != '\r'))
-                        throw new IllegalArgumentException();
-                    year = digit;
-                } else if (next == ':') {
-                    if (hour == -1)
-                        hour = digit;
-                    else if (minute == -1)
-                        minute = digit;
-                    else
-                        throw new IllegalArgumentException();
-                } else if (next == ' ' || next == ',' || next == '-'
-                        || next == '\r') {
-                    if (hour != -1 && minute == -1)
-                        minute = digit;
-                    else if (minute != -1 && second == -1)
-                        second = digit;
-                    else if (date == -1)
-                        date = digit;
-                    else if (year == -1)
-                        year = digit;
-                    else
-                        throw new IllegalArgumentException();
-                } else if (year == -1 && month != -1 && date != -1)
-                    year = digit;
-                else
-                    throw new IllegalArgumentException();
-            } else if (state == LETTERS && nextState != LETTERS) {
-                String text = buffer.toString().toUpperCase();
-                buffer.setLength(0);
-                if (text.length() < 3)
-                    throw new IllegalArgumentException();
-                if (parse(text, WEEKDAYS) != -1) {
-                } else if (month == -1 && (month = parse(text, MONTHS)) != -1) {
-                } else if (text.equals("GMT")) {
-                } else
-                    throw new IllegalArgumentException();
-            }
-
-            if (nextState == LETTERS || nextState == NUMBERS)
-                buffer.append(next);
-            state = nextState;
+    public static byte[] getBytes(String name) {
+		if (defaultEncoding != null) {
+			try {
+				return name.getBytes(defaultEncoding);
+			} catch (java.io.UnsupportedEncodingException e) {
+			}
+		}      
+        return name.getBytes();
+	}
+    
+    /**
+     * Get bytes from String with UTF8 encoding
+     * @param name
+     *          input String
+     * @return byte array
+     */
+    public static byte[] getUTF8Bytes(String name) {
+        try {
+            return name.getBytes("UTF-8");
+        } catch (java.io.UnsupportedEncodingException e) {
+            return getBytes(name);
         }
-
-        if (year != -1 && month != -1 && date != -1) {
-            if (hour == -1)
-                hour = 0;
-            if (minute == -1)
-                minute = 0;
-            if (second == -1)
-                second = 0;
-            Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
-            int current = cal.get(Calendar.YEAR) - 80;
-            if (year < 100) {
-                year += current / 100 * 100;
-                if (year < current)
-                    year += 100;
-            }
-            cal.set(Calendar.YEAR, year);
-            cal.set(Calendar.MONTH, month);
-            cal.set(Calendar.DATE, date);
-            cal.set(Calendar.HOUR_OF_DAY, hour);
-            cal.set(Calendar.MINUTE, minute);
-            cal.set(Calendar.SECOND, second);
-            cal.set(Calendar.MILLISECOND, 0);
-            return cal.getTime().getTime();
-        }
-        throw new IllegalArgumentException();
     }
 
-    private static int parse(String string, String[] array) {
-        int length = string.length();
-        for (int i = 0; i < array.length; i++) {
-            if (string.regionMatches(true, 0, array[i], 0, length))
-                return i;
+	public static String toString(byte[] bytes) {
+		if (defaultEncoding != null) {
+			try {
+				return new String(bytes, 0, bytes.length, defaultEncoding);
+			} catch (java.io.UnsupportedEncodingException e) {
+			}
+		}
+		return new String(bytes, 0, bytes.length);
+	}
+
+    public static String toUTF8String(byte[] bytes) {
+        return toUTF8String(bytes, 0, bytes.length);
+    }    
+    
+	public static String toString(byte[] bytes, int offset, int length) {
+		if (defaultEncoding != null) {
+			try {
+				return new String(bytes, offset, length, defaultEncoding);
+			} catch (java.io.UnsupportedEncodingException e) {
+			}
+		}
+		return new String(bytes, offset, length);
+	}
+
+    public static String toUTF8String(byte[] bytes, int offset, int length) {
+        try {
+            return new String(bytes, offset, length, "UTF-8");
+        } catch (java.io.UnsupportedEncodingException e) {
+            return toString(bytes, offset, length);
         }
-        return -1;
     }
+    
+	/**
+	 * Answers the millisecond value of the date and time parsed from the
+	 * specified String. Many date/time formats are recognized
+	 * 
+	 * @param string
+	 *            the String to parse
+	 * @return the millisecond value parsed from the String
+	 */
+	public static long parseDate(String string) {
+		int offset = 0, length = string.length(), state = 0;
+		int year = -1, month = -1, date = -1;
+		int hour = -1, minute = -1, second = -1;
+		final int PAD = 0, LETTERS = 1, NUMBERS = 2;
+		StringBuilder buffer = new StringBuilder();
 
-    public static String convertFromUTF8(byte[] buf, int offset, int utfSize)
-            throws UTFDataFormatException {
-        return convertUTF8WithBuf(buf, new char[utfSize], offset, utfSize);
-    }
+		while (offset <= length) {
+			char next = offset < length ? string.charAt(offset) : '\r';
+			offset++;
 
-    public static String convertUTF8WithBuf(byte[] buf, char[] out, int offset,
-            int utfSize) throws UTFDataFormatException {
-        int count = 0, s = 0, a;
-        while (count < utfSize) {
-            if ((out[s] = (char) buf[offset + count++]) < '\u0080')
-                s++;
-            else if (((a = out[s]) & 0xe0) == 0xc0) {
-                if (count >= utfSize)
-                    throw new UTFDataFormatException(Msg.getString("K0062",
-                            count));
+			int nextState;
+			if ((next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z'))
+				nextState = LETTERS;
+			else if (next >= '0' && next <= '9')
+				nextState = NUMBERS;
+			else if (" ,-:\r\t".indexOf(next) == -1)
+				throw new IllegalArgumentException();
+			else
+				nextState = PAD;
+
+			if (state == NUMBERS && nextState != NUMBERS) {
+				int digit = Integer.parseInt(buffer.toString());
+				buffer.setLength(0);
+				if (digit >= 70) {
+					if (year != -1
+							|| (next != ' ' && next != ',' && next != '\r'))
+						throw new IllegalArgumentException();
+					year = digit;
+				} else if (next == ':') {
+					if (hour == -1)
+						hour = digit;
+					else if (minute == -1)
+						minute = digit;
+					else
+						throw new IllegalArgumentException();
+				} else if (next == ' ' || next == ',' || next == '-'
+						|| next == '\r') {
+					if (hour != -1 && minute == -1)
+						minute = digit;
+					else if (minute != -1 && second == -1)
+						second = digit;
+					else if (date == -1)
+						date = digit;
+					else if (year == -1)
+						year = digit;
+					else
+						throw new IllegalArgumentException();
+				} else if (year == -1 && month != -1 && date != -1)
+					year = digit;
+				else
+					throw new IllegalArgumentException();
+			} else if (state == LETTERS && nextState != LETTERS) {
+				String text = buffer.toString().toUpperCase();
+				buffer.setLength(0);
+				if (text.length() < 3)
+					throw new IllegalArgumentException();
+				if (parse(text, WEEKDAYS) != -1) {
+				} else if (month == -1 && (month = parse(text, MONTHS)) != -1) {
+				} else if (text.equals("GMT")) {
+				} else
+					throw new IllegalArgumentException();
+			}
+
+			if (nextState == LETTERS || nextState == NUMBERS)
+				buffer.append(next);
+			state = nextState;
+		}
+
+		if (year != -1 && month != -1 && date != -1) {
+			if (hour == -1)
+				hour = 0;
+			if (minute == -1)
+				minute = 0;
+			if (second == -1)
+				second = 0;
+			Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+			int current = cal.get(Calendar.YEAR) - 80;
+			if (year < 100) {
+				year += current / 100 * 100;
+				if (year < current)
+					year += 100;
+			}
+			cal.set(Calendar.YEAR, year);
+			cal.set(Calendar.MONTH, month);
+			cal.set(Calendar.DATE, date);
+			cal.set(Calendar.HOUR_OF_DAY, hour);
+			cal.set(Calendar.MINUTE, minute);
+			cal.set(Calendar.SECOND, second);
+			cal.set(Calendar.MILLISECOND, 0);
+			return cal.getTime().getTime();
+		}
+		throw new IllegalArgumentException();
+	}
+
+	private static int parse(String string, String[] array) {
+		int length = string.length();
+		for (int i = 0; i < array.length; i++) {
+			if (string.regionMatches(true, 0, array[i], 0, length))
+				return i;
+		}
+		return -1;
+	}
+
+	public static String convertFromUTF8(byte[] buf, int offset, int utfSize)
+			throws UTFDataFormatException {
+		return convertUTF8WithBuf(buf, new char[utfSize], offset, utfSize);
+	}
+
+	public static String convertUTF8WithBuf(byte[] buf, char[] out, int offset,
+			int utfSize) throws UTFDataFormatException {
+		int count = 0, s = 0, a;
+		while (count < utfSize) {
+			if ((out[s] = (char) buf[offset + count++]) < '\u0080')
+				s++;
+			else if (((a = out[s]) & 0xe0) == 0xc0) {
+				if (count >= utfSize)
+					throw new UTFDataFormatException(Msg.getString("K0062",
+							count));
                 // BEGIN android-changed
                 int b = buf[offset + count++];
                 // END android-changed
-                if ((b & 0xC0) != 0x80)
-                    throw new UTFDataFormatException(Msg.getString("K0062",
-                            (count - 1)));
-                out[s++] = (char) (((a & 0x1F) << 6) | (b & 0x3F));
-            } else if ((a & 0xf0) == 0xe0) {
-                if (count + 1 >= utfSize)
-                    throw new UTFDataFormatException(Msg.getString("K0063",
-                            (count + 1)));
+				if ((b & 0xC0) != 0x80)
+					throw new UTFDataFormatException(Msg.getString("K0062",
+							(count - 1)));
+				out[s++] = (char) (((a & 0x1F) << 6) | (b & 0x3F));
+			} else if ((a & 0xf0) == 0xe0) {
+				if (count + 1 >= utfSize)
+					throw new UTFDataFormatException(Msg.getString("K0063",
+							(count + 1)));
                 // BEGIN android-changed
                 int b = buf[offset + count++];
                 int c = buf[offset + count++];
                 // END android-changed
-                if (((b & 0xC0) != 0x80) || ((c & 0xC0) != 0x80))
-                    throw new UTFDataFormatException(Msg.getString("K0064",
-                            (count - 2)));
-                out[s++] = (char) (((a & 0x0F) << 12) | ((b & 0x3F) << 6) | (c & 0x3F));
-            } else {
-                throw new UTFDataFormatException(Msg.getString("K0065",
-                        (count - 1)));
-            }
-        }
-        return new String(out, 0, s);
+				if (((b & 0xC0) != 0x80) || ((c & 0xC0) != 0x80))
+					throw new UTFDataFormatException(Msg.getString("K0064",
+							(count - 2)));
+				out[s++] = (char) (((a & 0x0F) << 12) | ((b & 0x3F) << 6) | (c & 0x3F));
+			} else {
+				throw new UTFDataFormatException(Msg.getString("K0065",
+						(count - 1)));
+			}
+		}
+		return new String(out, 0, s);
+	}
+
+	/**
+	 * '%' and two following hex digit characters are converted to the
+	 * equivalent byte value. All other characters are passed through
+	 * unmodified. e.g. "ABC %24%25" -> "ABC $%"
+	 * 
+	 * @param s
+	 *            java.lang.String The encoded string.
+	 * @return java.lang.String The decoded version.
+	 */
+    public static String decode(String s, boolean convertPlus) {
+        return decode(s, convertPlus, null);
     }
 
     /**
@@ -239,12 +285,14 @@
      * 
      * @param s
      *            java.lang.String The encoded string.
+     * @param encoding
+     *            the specified encoding
      * @return java.lang.String The decoded version.
      */
-    public static String decode(String s, boolean convertPlus) {
+    public static String decode(String s, boolean convertPlus, String encoding) {
         if (!convertPlus && s.indexOf('%') == -1)
             return s;
-        StringBuffer result = new StringBuffer(s.length());
+        StringBuilder result = new StringBuilder(s.length());
         ByteArrayOutputStream out = new ByteArrayOutputStream();
         for (int i = 0; i < s.length();) {
             char c = s.charAt(i);
@@ -265,7 +313,15 @@
                     out.write((byte) ((d1 << 4) + d2));
                     i += 3;
                 } while (i < s.length() && s.charAt(i) == '%');
-                result.append(out.toString());
+                if (encoding == null) {
+                    result.append(out.toString());
+                } else {
+                    try {
+                        result.append(out.toString(encoding));
+                    } catch (UnsupportedEncodingException e) {
+                        throw new IllegalArgumentException(e);
+                    }
+                }
                 continue;
             } else
                 result.append(c);
@@ -273,32 +329,32 @@
         }
         return result.toString();
     }
-    
-    public static String toASCIILowerCase(String s) {
+	
+	public static String toASCIILowerCase(String s) {
+        int len = s.length();
+		StringBuilder buffer = new StringBuilder(len);
+		for (int i = 0; i < len; i++) {
+			char c = s.charAt(i);
+			if ('A' <= c && c <= 'Z') {
+				buffer.append((char) (c + ('a' - 'A')));
+			} else {
+				buffer.append(c);
+			}
+		}
+		return buffer.toString();
+	}
+	
+	public static String toASCIIUpperCase(String s) {
         int len = s.length();
         StringBuilder buffer = new StringBuilder(len);
         for (int i = 0; i < len; i++) {
-            char c = s.charAt(i);
-            if ('A' <= c && c <= 'Z') {
-                buffer.append((char) (c + ('a' - 'A')));
-            } else {
-                buffer.append(c);
-            }
-        }
-        return buffer.toString();
-    }
-    
-    public static String toASCIIUpperCase(String s) {
-        int len = s.length();
-        StringBuilder buffer = new StringBuilder(len);
-        for (int i = 0; i < len; i++) {
-            char c = s.charAt(i);
-            if ('a' <= c && c <= 'z') {
-                buffer.append((char) (c - ('a' - 'A')));
-            } else {
-                buffer.append(c);
-            }
-        }
-        return buffer.toString();
-    }
+			char c = s.charAt(i);
+	        if ('a' <= c && c <= 'z') {
+	        	buffer.append((char) (c - ('a' - 'A')));
+	        } else {
+				buffer.append(c);
+			}
+		}
+		return buffer.toString();
+	}
 }
diff --git a/libcore/luni/src/main/native/cbigint.c b/libcore/luni/src/main/native/cbigint.c
index 0f65ca0..d327940 100644
--- a/libcore/luni/src/main/native/cbigint.c
+++ b/libcore/luni/src/main/native/cbigint.c
@@ -18,7 +18,7 @@
 #include <string.h>
 #include "cbigint.h"
 
-#if defined(LINUX) || defined(FREEBSD)
+#if defined(LINUX) || defined(FREEBSD) || defined(ZOS) || defined(MACOSX) || defined(AIX)
 #define USE_LL
 #endif
 
@@ -665,7 +665,7 @@
      do {
      overflow = simpleAppendDecimalDigitHighPrecision(result, length, 0);
      if (overflow)
-     result[length++] = overflow; 
+     result[length++] = overflow;
      } while (--e);
    */
   return length;
@@ -686,12 +686,12 @@
      do {
      overflow = simpleAppendDecimalDigitHighPrecision(result, length, 0);
      if (overflow)
-     result[length++] = overflow; 
+     result[length++] = overflow;
      } while (--e);
    */
   /* Replace the current implementaion which performs a
    * "multiplication" by 10 e number of times with an actual
-   * mulitplication. 10e19 is the largest exponent to the power of ten
+   * multiplication. 10e19 is the largest exponent to the power of ten
    * that will fit in a 64-bit integer, and 10e9 is the largest exponent to
    * the power of ten that will fit in a 64-bit integer. Not sure where the
    * break-even point is between an actual multiplication and a
diff --git a/libcore/luni/src/main/native/java_io_FileDescriptor.c b/libcore/luni/src/main/native/java_io_FileDescriptor.c
index a5ec8b7..897e688 100644
--- a/libcore/luni/src/main/native/java_io_FileDescriptor.c
+++ b/libcore/luni/src/main/native/java_io_FileDescriptor.c
@@ -103,20 +103,6 @@
     }
 }
 
-/*
- * public native boolean valid()
- */
-static jboolean fd_valid(JNIEnv* env, jobject obj) {
-    int fd = getFd(env, obj);
-    struct stat sb;
-
-    if(fstat(fd, &sb) == 0) {
-        return JNI_TRUE;
-    } else {
-        return JNI_FALSE;
-    }
-}
-
 /* checks to see if class is inited and inits if needed, returning -1
  * on fail and 0 on success
  */
@@ -205,8 +191,7 @@
 static JNINativeMethod gMethods[] = {
     /* name, signature, funcPtr */
     { "oneTimeInitialization", "()V",              nativeClassInit },
-    { "syncImpl",           "()V",                 fd_sync },
-    { "valid",          "()Z",                     fd_valid }
+    { "syncImpl",           "()V",                 fd_sync }
 };
 int register_java_io_FileDescriptor(JNIEnv* env) {
     return jniRegisterNativeMethods(env, "java/io/FileDescriptor",
diff --git a/libcore/luni/src/main/native/java_net_InetAddress.cpp b/libcore/luni/src/main/native/java_net_InetAddress.cpp
index 508656f..d7b4931 100644
--- a/libcore/luni/src/main/native/java_net_InetAddress.cpp
+++ b/libcore/luni/src/main/native/java_net_InetAddress.cpp
@@ -100,7 +100,10 @@
             env->SetByteArrayRegion(byteArray, 0, 4, (jbyte*) &outaddr.s_addr);
             env->SetObjectArrayElement(addressArray, 1, byteArray);
         }
+    } else {
+        jniThrowException(env, "java/net/UnknownHostException", "adb error");
     }
+
     return addressArray;
 }
 
@@ -111,12 +114,8 @@
     jobjectArray addressArray = NULL;
 
     memset(&hints, 0, sizeof(hints));
-    /*
-     * IPv4 only for now until the socket code supports IPv6; otherwise, the
-     * resolver will create two separate requests, one for IPv4 and one,
-     * currently unnecessary, for IPv6.
-     */
-    hints.ai_family = AF_INET;
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_flags = AI_ADDRCONFIG;
     /*
      * If we don't specify a socket type, every address will appear twice, once
      * for SOCK_STREAM and one for SOCK_DGRAM. Since we do not return the family
@@ -193,8 +192,8 @@
             env, "java/lang/SecurityException",
             "Permission denied (maybe missing INTERNET permission)");
     } else {
-        // Do nothing. Return value will be null and the caller will throw an
-        // UnknownHostExeption.
+        jniThrowException(env, "java/net/UnknownHostException",
+                gai_strerror(result));
     }
 
     if (addressList) {
@@ -231,15 +230,19 @@
         out = getAllByNameUsingDns(env, name, preferIPv4Stack);
     }
 
-    if (!out) {
-        LOGI("Unknown host %s, throwing UnknownHostException", name);
-        jniThrowException(env, "java/net/UnknownHostException", name);
-    }
     env->ReleaseStringUTFChars(javaName, name);
     return out;
 }
 
 
+/**
+ * Looks up the name corresponding to an IP address.
+ *
+ * @param javaAddress: a byte array containing the raw IP address bytes. Must be
+ *         4 or 16 bytes long.
+ * @return the hostname.
+ * @throws UnknownHostException: the IP address has no associated hostname.
+ */
 static jstring InetAddress_gethostbyaddr(JNIEnv* env, jobject obj,
                                          jbyteArray javaAddress)
 {
@@ -256,57 +259,45 @@
     }
 
     // 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);
-            memset(sin, 0, sizeof(struct sockaddr_in));
             sin->sin_family = AF_INET;
-            memcpy(&sin->sin_addr.s_addr, rawAddress, 4);
+            memcpy(&sin->sin_addr.s_addr, rawAddress, addrlen);
             env->ReleaseByteArrayElements(javaAddress, rawAddress, JNI_ABORT);
             break;
         case 16:
             socklen = sizeof(struct sockaddr_in6);
-            memset(sin6, 0, sizeof(struct sockaddr_in6));
             sin6->sin6_family = AF_INET6;
-            memcpy(&sin6->sin6_addr.s6_addr, rawAddress, 16);
+            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);
-            jniThrowException(env, "java/net/UnknownHostException",
-                                   "Invalid address length");
             return NULL;
     }
 
-
-    // Convert the socket address structure to an IP string for logging.
-    int ret;
-    char ipstr[INET6_ADDRSTRLEN];
-    ret = getnameinfo((struct sockaddr *) &ss, socklen, ipstr, sizeof(ipstr),
-                      NULL, 0, NI_NUMERICHOST);
-    if (ret) {
-        LOGE("gethostbyaddr: getnameinfo: %s", gai_strerror(ret));
-        return NULL;
-    }
-
-    // Look up the IP address from the socket address structure.
-    jstring result = NULL;
+    // Look up the host name from the IP address.
     char name[NI_MAXHOST];
-    ret = getnameinfo((struct sockaddr *) &ss, socklen, name, sizeof(name),
-                      NULL, 0, 0);
     if (ret == 0) {
-        LOGI("gethostbyaddr: getnameinfo: %s = %s", ipstr, name);
-        result = env->NewStringUTF(name);
-    } else {
-        LOGE("gethostbyaddr: getnameinfo: unknown host %s: %s", ipstr,
-             gai_strerror(ret));
+        ret = getnameinfo((struct sockaddr *) &ss, socklen, name, sizeof(name),
+                          NULL, 0, NI_NAMEREQD);
     }
 
-    return result;
+    if (ret == 0) {
+        return env->NewStringUTF(name);
+    }
+
+    jniThrowException(env, "java/net/UnknownHostException", gai_strerror(ret));
+    return NULL;
 }
 
 /*
diff --git a/libcore/luni/src/main/native/java_net_NetworkInterface.c b/libcore/luni/src/main/native/java_net_NetworkInterface.c
index 379ccdf..db6d503 100644
--- a/libcore/luni/src/main/native/java_net_NetworkInterface.c
+++ b/libcore/luni/src/main/native/java_net_NetworkInterface.c
@@ -546,8 +546,9 @@
             /* 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.  This is only truely necessary on platforms that support IPV6 */
-                interfaces[currentAdapterIndex].index = 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);
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 c5e92bb..2e814cc 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
@@ -14,14 +14,26 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "OSMemory"
 #include "JNIHelp.h"
 #include "AndroidSystemNatives.h"
 #include "utils/misc.h"
+#include "utils/Log.h"
 #include <sys/mman.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
 
+/*
+ * Cached dalvik.system.VMRuntime pieces.
+ */
+static struct {
+    jmethodID method_trackExternalAllocation;
+    jmethodID method_trackExternalFree;
+
+    jobject runtimeInstance;
+} gIDCache;
+
 #undef MMAP_READ_ONLY
 #define MMAP_READ_ONLY 1L
 #undef MMAP_READ_WRITE
@@ -55,11 +67,28 @@
  * Signature: (I)I
  */
 static jint harmony_nio_mallocImpl(JNIEnv *_env, jobject _this, jint size) {
-    void *returnValue = malloc(size);
-    if(returnValue == NULL) {
-        jniThrowException(_env, "java.lang.OutOfMemoryError", "");
+    jboolean allowed = _env->CallBooleanMethod(gIDCache.runtimeInstance,
+        gIDCache.method_trackExternalAllocation, (jlong) size);
+    if (!allowed) {
+        LOGW("External allocation of %d bytes was rejected\n", size);
+        jniThrowException(_env, "java/lang/OutOfMemoryError", NULL);
+        return 0;
     }
-    return (jint)returnValue;
+
+    LOGV("OSMemory alloc %d\n", size);
+    void *returnValue = malloc(size + sizeof(jlong));
+    if (returnValue == NULL) {
+        jniThrowException(_env, "java/lang/OutOfMemoryError", NULL);
+        return 0;
+    }
+
+    /*
+     * Tuck a copy of the size at the head of the buffer.  We need this
+     * so harmony_nio_freeImpl() knows how much memory is being freed.
+     */
+    jlong* adjptr = (jlong*) returnValue;
+    *adjptr++ = size;
+    return (jint)adjptr;
 }
 
 /*
@@ -68,7 +97,12 @@
  * Signature: (I)V
  */
 static void harmony_nio_freeImpl(JNIEnv *_env, jobject _this, jint pointer) {
-    free((void *)pointer);
+    jlong* adjptr = (jlong*) pointer;
+    jint size = *--adjptr;
+    LOGV("OSMemory free %d\n", size);
+    _env->CallVoidMethod(gIDCache.runtimeInstance,
+        gIDCache.method_trackExternalFree, (jlong) size);
+    free((void *)adjptr);
 }
 
 /*
@@ -138,12 +172,10 @@
 }
 
 static void
-swapShorts(jshort *shorts, int numBytes) {
+swapShorts(jshort *shorts, int count) {
     jbyte *src = (jbyte *) shorts;
     jbyte *dst = src;
-    int i;
-    
-    for (i = 0; i < numBytes; i+=2) {
+    for (int i = 0; i < count; ++i) {
         jbyte b0 = *src++;
         jbyte b1 = *src++;
         *dst++ = b1;
@@ -152,11 +184,10 @@
 }
 
 static void
-swapInts(jint *ints, int numBytes) {
+swapInts(jint *ints, int count) {
     jbyte *src = (jbyte *) ints;
     jbyte *dst = src;
-    int i;   
-    for (i = 0; i < numBytes; i+=4) {
+    for (int i = 0; i < count; ++i) {
         jbyte b0 = *src++;
         jbyte b1 = *src++;
         jbyte b2 = *src++;
@@ -170,48 +201,30 @@
 
 /*
  * Class:     org_apache_harmony_luni_platform_OSMemory
- * Method:    putShortsImpl
+ * Method:    setShortArrayImpl
  * Signature: (I[SIIZ)V
  */
-static void harmony_nio_putShortsImpl(JNIEnv *_env, jobject _this,
+static void harmony_nio_setShortArrayImpl(JNIEnv *_env, jobject _this,
        jint pointer, jshortArray src, jint offset, jint length, jboolean swap) {
-       
-    offset = offset << 1;
-    length = length << 1;
-       
-    jshort *src_ =
-        (jshort *)_env->GetPrimitiveArrayCritical(src, (jboolean *)0);
+    jshort* dst = reinterpret_cast<jshort*>(static_cast<uintptr_t>(pointer));
+    _env->GetShortArrayRegion(src, offset, length, dst);
     if (swap) {
-        swapShorts(src_ + offset, length);
+        swapShorts(dst, length);
     }
-    memcpy((jbyte *)pointer, (jbyte *)src_ + offset, length);
-    if (swap) {
-        swapShorts(src_ + offset, length);
-    }
-    _env->ReleasePrimitiveArrayCritical(src, src_, JNI_ABORT);
 }
 
 /*
  * Class:     org_apache_harmony_luni_platform_OSMemory
- * Method:    putIntsImpl
+ * Method:    setIntArrayImpl
  * Signature: (I[IIIZ)V
  */
-static void harmony_nio_putIntsImpl(JNIEnv *_env, jobject _this,
+static void harmony_nio_setIntArrayImpl(JNIEnv *_env, jobject _this,
        jint pointer, jintArray src, jint offset, jint length, jboolean swap) {
-
-    offset = offset << 2;
-    length = length << 2;
-       
-    jint *src_ =
-        (jint *)_env->GetPrimitiveArrayCritical(src, (jboolean *)0);
+    jint* dst = reinterpret_cast<jint*>(static_cast<uintptr_t>(pointer));
+    _env->GetIntArrayRegion(src, offset, length, dst);
     if (swap) {
-        swapInts(src_ + offset, length);
+        swapInts(dst, length);
     }
-    memcpy((jbyte *)pointer, (jbyte *)src_ + offset, length);
-    if (swap) {
-        swapInts(src_ + offset, length);
-    }
-    _env->ReleasePrimitiveArrayCritical(src, src_, JNI_ABORT);
 }
 
 /*
@@ -554,8 +567,8 @@
     { "memmove",            "(IIJ)V",  (void*) harmony_nio_memmove },
     { "getByteArray",       "(I[BII)V",(void*) harmony_nio_getBytesImpl },
     { "setByteArray",       "(I[BII)V",(void*) harmony_nio_putBytesImpl },
-    { "setShortArray",     "(I[SIIZ)V",(void*) harmony_nio_putShortsImpl },
-    { "setIntArray",       "(I[IIIZ)V",(void*) harmony_nio_putIntsImpl },
+    { "setShortArray",     "(I[SIIZ)V",(void*) harmony_nio_setShortArrayImpl },
+    { "setIntArray",       "(I[IIIZ)V",(void*) harmony_nio_setIntArrayImpl },
     { "getByte",            "(I)B",    (void*) harmony_nio_getByteImpl },
     { "setByte",            "(IB)V",   (void*) harmony_nio_putByteImpl },
     { "getShort",           "(I)S",    (void*) harmony_nio_getShortImpl },
@@ -577,6 +590,45 @@
     { "flushImpl",          "(IJ)I",   (void*) harmony_nio_flushImpl }
 };
 int register_org_apache_harmony_luni_platform_OSMemory(JNIEnv *_env) {
-    return jniRegisterNativeMethods(_env, "org/apache/harmony/luni/platform/OSMemory",
+    /*
+     * We need to call VMRuntime.trackExternal{Allocation,Free}.  Cache
+     * method IDs and a reference to the singleton.
+     */
+    static const char* kVMRuntimeName = "dalvik/system/VMRuntime";
+    jmethodID method_getRuntime;
+    jclass clazz;
+
+    clazz = _env->FindClass(kVMRuntimeName);
+    if (clazz == NULL) {
+        LOGE("Unable to find class %s\n", kVMRuntimeName);
+        return -1;
+    }
+    gIDCache.method_trackExternalAllocation = _env->GetMethodID(clazz,
+        "trackExternalAllocation", "(J)Z");
+    gIDCache.method_trackExternalFree = _env->GetMethodID(clazz,
+        "trackExternalFree", "(J)V");
+    method_getRuntime = _env->GetStaticMethodID(clazz,
+        "getRuntime", "()Ldalvik/system/VMRuntime;");
+
+    if (gIDCache.method_trackExternalAllocation == NULL ||
+        gIDCache.method_trackExternalFree == NULL ||
+        method_getRuntime == NULL)
+    {
+        LOGE("Unable to find VMRuntime methods\n");
+        return -1;
+    }
+
+    jobject instance = _env->CallStaticObjectMethod(clazz, method_getRuntime);
+    if (instance == NULL) {
+        LOGE("Unable to obtain VMRuntime instance\n");
+        return -1;
+    }
+    gIDCache.runtimeInstance = _env->NewGlobalRef(instance);
+
+    /*
+     * Register methods.
+     */
+    return jniRegisterNativeMethods(_env,
+                "org/apache/harmony/luni/platform/OSMemory",
                 gMethods, NELEM(gMethods));
 }
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
old mode 100755
new mode 100644
index f79c019..7b6023a
--- 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
@@ -14,6 +14,13 @@
  * limitations under the License.
  */
 
+// BEGIN android-changed
+//
+// This file has been substantially reworked in order to provide more IPv6
+// support and to move functionality from Java to native code where it made
+// sense (e.g. when converting between IP addresses, socket structures, and
+// strings, for which there exist fast and robust native implementations).
+
 #define LOG_TAG "OSNetworkSystem"
 
 #include "JNIHelp.h"
@@ -26,6 +33,7 @@
 #include <netinet/in.h>
 #include <netinet/tcp.h>
 #include <netdb.h>
+#include <arpa/inet.h>
 #include <sys/time.h>
 #include <stdlib.h>
 #include <sys/ioctl.h>
@@ -33,9 +41,13 @@
 
 #include <cutils/properties.h>
 #include <cutils/adb_networking.h>
-#include <utils/LogSocket.h>
 #include "AndroidSystemNatives.h"
 
+// Temporary hack to build on systems that don't have up-to-date libc headers.
+#ifndef IPV6_TCLASS
+#define IPV6_TCLASS 67
+#endif
+
 /**
  * @name Socket Errors
  * Error codes for socket operations
@@ -145,12 +157,16 @@
 // wait for 500000 usec = 0.5 second
 #define SEND_RETRY_TIME 500000
 
+// Local constants for getOrSetSocketOption
+#define SOCKOPT_GET 1
+#define SOCKOPT_SET 2
 
 struct CachedFields {
     jfieldID fd_descriptor;
     jclass iaddr_class;
-    jmethodID iaddr_class_init;
     jmethodID iaddr_getbyaddress;
+    jclass i4addr_class;
+    jmethodID i4addr_class_init;
     jfieldID iaddr_ipaddress;
     jclass genericipmreq_class;
     jclass integer_class;
@@ -164,6 +180,7 @@
     jfieldID byte_class_value;
     jclass string_class;
     jmethodID string_class_init;
+    jclass socketimpl_class;
     jfieldID socketimpl_address;
     jfieldID socketimpl_port;
     jclass dpack_class;
@@ -208,60 +225,87 @@
 }
 
 /**
- * Converts a 4-byte array to a native address structure. Throws a
+ * Converts a native address structure to a Java 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.
+ *
+ * @param address the sockaddr_storage structure to convert
+ *
+ * @exception SocketException the address family is unknown, or out of memory
+ *
  */
-static int javaAddressToStructIn(
-        JNIEnv *env, jbyteArray java_address, struct in_addr *address) {
+static jbyteArray socketAddressToByteArray(JNIEnv *env,
+        struct sockaddr_storage *address) {
 
-    memset(address, 0, sizeof(address));
-
-    if (java_address == NULL) {
-        return -1;
+    void *rawAddress;
+    size_t addressLength;
+    if (address->ss_family == AF_INET) {
+        struct sockaddr_in *sin = (struct sockaddr_in *) address;
+        rawAddress = &sin->sin_addr.s_addr;
+        addressLength = 4;
+    } else if (address->ss_family == AF_INET6) {
+        struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) address;
+        rawAddress = &sin6->sin6_addr.s6_addr;
+        addressLength = 16;
+    } else {
+        throwSocketException(env, SOCKERR_BADAF);
+        return NULL;
     }
 
-    if (env->GetArrayLength(java_address) != sizeof(address->s_addr)) {
-        return -1;
+    jbyteArray byteArray = env->NewByteArray(addressLength);
+    if (byteArray == NULL) {
+        throwSocketException(env, SOCKERR_NOBUFFERS);
+        return NULL;
     }
+    env->SetByteArrayRegion(byteArray, 0, addressLength, (jbyte *) rawAddress);
 
-    jbyte * java_address_bytes
-        =  env->GetByteArrayElements(java_address, NULL);
-
-    memcpy(&(address->s_addr),
-        java_address_bytes,
-        sizeof(address->s_addr));
-
-    env->ReleaseByteArrayElements(java_address, java_address_bytes, JNI_ABORT);
-
-    return 0;
+    return byteArray;
 }
 
 /**
- * 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.
+ * Returns the port number in a sockaddr_storage structure.
+ *
+ * @param address the sockaddr_storage structure to get the port from
+ *
+ * @return the port number, or -1 if the address family is unknown.
  */
-static int structInToJavaAddress(
-        JNIEnv *env, struct in_addr *address, jbyteArray java_address) {
-
-    if (java_address == NULL) {
-        return -1;
+static int getSocketAddressPort(struct sockaddr_storage *address) {
+    switch (address->ss_family) {
+        case AF_INET:
+            return ntohs(((struct sockaddr_in *) address)->sin_port);
+        case AF_INET6:
+            return ntohs(((struct sockaddr_in6 *) address)->sin6_port);
+        default:
+            return -1;
     }
+}
 
-    if (env->GetArrayLength(java_address) != sizeof(address->s_addr)) {
-        return -1;
+/**
+ * Checks whether a socket address structure contains an IPv4-mapped address.
+ *
+ * @param address the socket address structure to check
+ * @return true if address contains an IPv4-mapped address, false otherwise.
+ */
+static bool isMappedAddress(sockaddr *address) {
+    if (! address || address->sa_family != AF_INET6) {
+        return false;
     }
+    in6_addr addr = ((sockaddr_in6 *) address)->sin6_addr;
+    return (addr.s6_addr32[0] == 0 &&
+            addr.s6_addr32[1] == 0 &&
+            addr.s6_addr32[2] == htonl(0xffff));
+}
 
-    jbyte *java_address_bytes;
-
-    java_address_bytes = env->GetByteArrayElements(java_address, NULL);
-
-    memcpy(java_address_bytes, &(address->s_addr), sizeof(address->s_addr));
-
-    env->ReleaseByteArrayElements(java_address, java_address_bytes, 0);
-
-    return 0;
+/**
+ * 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));
 }
 
 /**
@@ -269,68 +313,289 @@
  * 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.
+ *
+ * @param sockaddress the sockaddr_storage structure to convert
+ *
+ * @return a jobject representing an InetAddress
  */
-static int socketAddressToInetAddress(JNIEnv *env,
-        struct sockaddr_in *sockaddress, jobject inetaddress, int *port) {
+static jobject socketAddressToInetAddress(JNIEnv *env,
+        struct sockaddr_storage *sockaddress) {
 
-    jbyteArray ipaddress;
-    int result;
+    jbyteArray byteArray = socketAddressToByteArray(env, sockaddress);
+    if (byteArray == NULL)  // Exception has already been thrown.
+        return NULL;
 
-    ipaddress = (jbyteArray)env->GetObjectField(inetaddress,
-            gCachedFields.iaddr_ipaddress);
+    return env->CallStaticObjectMethod(gCachedFields.iaddr_class,
+            gCachedFields.iaddr_getbyaddress, byteArray);
+}
 
-    if (structInToJavaAddress(env, &sockaddress->sin_addr, ipaddress) < 0) {
-        return -1;
+/**
+ * Converts an IPv4-mapped IPv6 address to an IPv4 address. Performs no error
+ * checking.
+ *
+ * @param address the address to convert. Must contain an IPv4-mapped address.
+ * @param outputAddress the converted address. Will contain an IPv4 address.
+ */
+static void convertMappedToIpv4(sockaddr_in6 *sin6, sockaddr_in *sin) {
+  memset(sin, 0, sizeof(*sin));
+  sin->sin_family = AF_INET;
+  sin->sin_addr.s_addr = sin6->sin6_addr.s6_addr32[3];
+  sin->sin_port = sin6->sin6_port;
+}
+
+/**
+ * Converts an IPv4 address to an IPv4-mapped IPv6 address. Performs no error
+ * checking.
+ *
+ * @param address the address to convert. Must contain an IPv4 address.
+ * @param outputAddress the converted address. Will contain an IPv6 address.
+ * @param mapUnspecified if true, convert 0.0.0.0 to ::ffff:0:0; if false, to ::
+ */
+static void convertIpv4ToMapped(struct sockaddr_in *sin,
+        struct sockaddr_in6 *sin6, bool mapUnspecified) {
+  memset(sin6, 0, sizeof(*sin6));
+  sin6->sin6_family = AF_INET6;
+  sin6->sin6_addr.s6_addr32[3] = sin->sin_addr.s_addr;
+  if (sin->sin_addr.s_addr != 0  || mapUnspecified) {
+      sin6->sin6_addr.s6_addr32[2] = htonl(0xffff);
+  }
+  sin6->sin6_port = sin->sin_port;
+}
+
+/**
+ * Converts an InetAddress object and port number to a native address structure.
+ * Throws a NullPointerException or a SocketException in case of
+ * error. This is signaled by a return value of -1. The normal
+ * return value is 0.
+ *
+ * @param inetaddress the InetAddress object to convert
+ * @param port the port number
+ * @param sockaddress the sockaddr_storage structure to write to
+ *
+ * @return 0 on success, a system error code on failure
+ *
+ * @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;
     }
+    size_t addressLength = env->GetArrayLength(addressByteArray);
 
-    *port = ntohs(sockaddress->sin_port);
-
+    // Convert the IP address bytes to the proper IP address type.
+    if (addressLength == 4) {
+        // IPv4 address.
+        sockaddr_in *sin = (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);
+    } else if (addressLength == 16) {
+        // IPv6 address.
+        sockaddr_in6 *sin6 = (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);
+    } else {
+        // Unknown address family.
+        throwSocketException(env, SOCKERR_BADAF);
+        return EAFNOSUPPORT;
+    }
     return 0;
 }
 
 /**
- * Converts an InetAddress object to a native address structure.
- * Throws a NullPointerException or an IOException in case of
+ * Converts an InetAddress object and port number to a native address structure.
+ * Throws a NullPointerException or a SocketException in case of
  * error. This is signaled by a return value of -1. The normal
  * return value is 0.
+ *
+ * @param inetaddress the InetAddress object to convert
+ * @param port the port number
+ * @param sockaddress the sockaddr_storage structure to write to
+ *
+ * @return 0 on success, -1 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, struct sockaddr_in *sockaddress) {
+        jobject inetaddress, int port, sockaddr_storage *sockaddress) {
 
-    jbyteArray ipaddress;
-    int result;
-
-    ipaddress = (jbyteArray)env->GetObjectField(inetaddress,
+    // Get the byte array that stores the IP address bytes in the InetAddress.
+    jbyteArray addressByteArray;
+    addressByteArray = (jbyteArray)env->GetObjectField(inetaddress,
             gCachedFields.iaddr_ipaddress);
 
-    memset(sockaddress, 0, sizeof(sockaddress));
+    return byteArrayToSocketAddress(env, addressByteArray, port, sockaddress);
+}
 
-    sockaddress->sin_family = AF_INET;
-    sockaddress->sin_port = htons(port);
-
-    if (javaAddressToStructIn(env, ipaddress, &(sockaddress->sin_addr)) < 0) {
-        return -1;
+/**
+ * Convert a sockaddr_storage structure to a Java string.
+ *
+ * @param address pointer to sockaddr_storage structure to convert.
+ * @param withPort whether to include the port number in the output as well.
+ *
+ * @return 0 on success, a getnameinfo return code on failure.
+ *
+ * @throws SocketException the address family was unknown.
+ */
+static int socketAddressToString(sockaddr_storage *address, char *ipString,
+        int len, bool withPort) {
+    // TODO: getnameinfo seems to want its length parameter to be exactly
+    // sizeof(sockaddr_in) for an IPv4 address and sizeof (sockaddr_in6) for an
+    // IPv6 address. Fix getnameinfo so it accepts sizeof(sockaddr_storage), and
+    // then remove this hack.
+    int size;
+    if (address->ss_family == AF_INET) {
+        size = sizeof(sockaddr_in);
+    } else if (address->ss_family == AF_INET6) {
+        size = sizeof(sockaddr_in6);
+    } else {
+        errno = EAFNOSUPPORT;
+        return EAI_SYSTEM;
     }
 
+    char tmp[INET6_ADDRSTRLEN];
+    int result = getnameinfo((sockaddr *)address, size, tmp, sizeof(tmp), NULL,
+            0, NI_NUMERICHOST);
+    if (result != 0) {
+        return result;
+    }
+
+    int port;
+    if (withPort) {
+        if (address->ss_family == AF_INET6) {
+            sockaddr_in6 *sin6 = (sockaddr_in6 *) address;
+            port = ntohs(sin6->sin6_port);
+            snprintf(ipString, len, "[%s]:%d", tmp, port);
+        } else {
+            sockaddr_in *sin = (sockaddr_in *) address;
+            port = ntohs(sin->sin_port);
+            snprintf(ipString, len, "%s:%d", tmp, port);
+        }
+    } else {
+        strncpy(ipString, tmp, len);
+    }
     return 0;
 }
 
-static jobject structInToInetAddress(JNIEnv *env, struct in_addr *address) {
-    jbyteArray bytes;
-    int success;
-
-    bytes = env->NewByteArray(4);
-
-    if (bytes == NULL) {
+/**
+ * Convert a Java byte array representing an IP address to a Java string.
+ *
+ * @param addressByteArray the byte array to convert.
+ *
+ * @return a string with the textual representation of the address.
+ *
+ * @throws SocketException the address family was unknown.
+ */
+static jstring osNetworkSystem_byteArrayToIpString(JNIEnv *env, jclass clazz,
+        jbyteArray byteArray) {
+    // For compatibility, ensure that an UnknownHostException is thrown if the
+    // address is null.
+    if (byteArray == NULL) {
+        jniThrowException(env, "java/net/UnknownHostException",
+                strerror(EFAULT));
         return NULL;
     }
-
-    if (structInToJavaAddress(env, address, bytes) < 0) {
+    struct sockaddr_storage ss;
+    int ret = byteArrayToSocketAddress(env, byteArray, 0, &ss);
+    if (ret) {
+        jniThrowException(env, "java/net/UnknownHostException", strerror(ret));
         return NULL;
     }
+    char ipString[INET6_ADDRSTRLEN];
+    ret = socketAddressToString(&ss, ipString, sizeof(ipString), false);
+    if (ret) {
+        env->ExceptionClear();
+        jniThrowException(env, "java/net/UnknownHostException",
+                gai_strerror(ret));
+        return NULL;
+    }
+    return env->NewStringUTF(ipString);
+}
 
-    return env->CallStaticObjectMethod(gCachedFields.iaddr_class,
-            gCachedFields.iaddr_getbyaddress, bytes);
+/**
+ * Convert a Java string representing an IP address to a Java byte array.
+ * The formats accepted are:
+ * - IPv4:
+ *   - 1.2.3.4
+ *   - 1.2.4
+ *   - 1.4
+ *   - 4
+ * - IPv6
+ *   - Compressed form (2001:db8::1)
+ *   - Uncompressed form (2001:db8:0:0:0:0:0:1)
+ *   - IPv4-compatible (::192.0.2.0)
+ *   - With an embedded IPv4 address (2001:db8::192.0.2.0).
+ * IPv6 addresses may appear in square brackets.
+ *
+ * @param addressByteArray the byte array to convert.
+ *
+ * @return a string with the textual representation of the address.
+ *
+ * @throws UnknownHostException the IP address was invalid.
+ */
+static jbyteArray osNetworkSystem_ipStringToByteArray(JNIEnv *env, jclass clazz,
+        jstring javaString) {
+    if (javaString == NULL) {
+        throwNullPointerException(env);
+    }
+
+    char ipString[INET6_ADDRSTRLEN];
+    int stringLength = env->GetStringUTFLength(javaString);
+    env->GetStringUTFRegion(javaString, 0, stringLength, ipString);
+
+    // Accept IPv6 addresses (only) in square brackets for compatibility.
+    if (ipString[0] == '[' && ipString[stringLength - 1] == ']' &&
+            index(ipString, ':') != NULL) {
+        memmove(ipString, ipString + 1, stringLength - 2);
+        ipString[stringLength - 2] = '\0';
+    }
+
+    jbyteArray result = NULL;
+    sockaddr_in sin;
+    addrinfo hints, *res;
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_flags = AI_NUMERICHOST;
+    int ret = getaddrinfo(ipString, NULL, &hints, &res);
+    if (ret == 0 && res) {
+        // Convert mapped addresses to IPv4 addresses if necessary.
+        if (res->ai_family == AF_INET6 && isMappedAddress(res->ai_addr)) {
+            convertMappedToIpv4((sockaddr_in6 *) res->ai_addr, &sin);
+            result = socketAddressToByteArray(env, (sockaddr_storage *) &sin);
+        } else {
+            result = socketAddressToByteArray(env,
+                    (sockaddr_storage *) res->ai_addr);
+        }
+    } else {
+        // For backwards compatibility, deal with address formats that
+        // getaddrinfo does not support. For example, 1.2.3, 1.3, and even 3 are
+        // valid IPv4 addresses according to the Java API. If getaddrinfo fails,
+        // try to use inet_aton.
+        if (inet_aton(ipString, &sin.sin_addr)) {
+            sin.sin_port = 0;
+            sin.sin_family = AF_INET;
+            result = socketAddressToByteArray(env, (sockaddr_storage *) &sin);
+        }
+    }
+
+    if (res) {
+        freeaddrinfo(res);
+    }
+
+    if (! result) {
+        env->ExceptionClear();
+        jniThrowException(env, "java/net/UnknownHostException",
+                gai_strerror(ret));
+    }
+
+    return result;
 }
 
 /**
@@ -427,15 +692,34 @@
 }
 
 /**
- * check if the passed sockaddr_in struct contains a localhost address
+ * Check if the passed sockaddr_storage struct contains a localhost address
  *
- * @param[in] address pointer to the address to check
+ * @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_in *address) {
-    // return address == 127.0.0.1
-    return (unsigned int) address->sin_addr.s_addr == 16777343;
+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;
 }
 
 /**
@@ -728,7 +1012,6 @@
                 }
 
             } else if (0 > result) {
-                log_socket_close(handle, result);
                 throwSocketException(env, result);
             }
             poll = 0;
@@ -745,7 +1028,6 @@
 
                 continue; // try again
             } else if (0 > result) {
-                log_socket_close(handle, result);
                 throwSocketException(env, result);
             }
             poll = 0;
@@ -756,6 +1038,24 @@
 }
 
 /**
+ * Obtain the socket address family from an existing socket.
+ *
+ * @param socket the filedescriptor of the socket to examine
+ *
+ * @return an integer, the address family of the socket
+ */
+static int getSocketAddressFamily(int socket) {
+  struct sockaddr_storage ss;
+  socklen_t namelen = sizeof(ss);
+  int ret = getsockname(socket, (struct sockaddr*) &ss, &namelen);
+  if (ret != 0) {
+    return AF_UNSPEC;
+  } else {
+    return ss.ss_family;
+  }
+}
+
+/**
  * A helper method, to set the connect context to a Long object.
  *
  * @param env  pointer to the JNI library
@@ -802,6 +1102,59 @@
     return (unsigned short )(~sum);
 }
 
+
+/**
+ * Wrapper for connect() that converts IPv4 addresses to IPv4-mapped IPv6
+ * addresses if necessary.
+ *
+ * @param socket the filedescriptor of the socket to connect
+ * @param socketAddress the address to connect to
+ */
+static int doConnect(int socket, struct sockaddr_storage *socketAddress) {
+    sockaddr_storage mappedAddress;
+    sockaddr_storage *realAddress;
+    if (socketAddress->ss_family == AF_INET &&
+        getSocketAddressFamily(socket) == AF_INET6) {
+        convertIpv4ToMapped((sockaddr_in *) socketAddress,
+                (sockaddr_in6 *) &mappedAddress, true);
+        realAddress = &mappedAddress;
+    } else {
+        realAddress = socketAddress;
+    }
+    int ret;
+    do {
+        ret = connect(socket, (struct sockaddr *) realAddress,
+                sizeof(struct sockaddr_storage));
+    } while (ret < 0 && errno == EINTR);
+    return ret;
+}
+
+/**
+ * Wrapper for bind() that converts IPv4 addresses to IPv4-mapped IPv6
+ * addresses if necessary.
+ *
+ * @param socket the filedescriptor of the socket to connect
+ * @param socketAddress the address to connect to
+ */
+static int doBind(int socket, struct sockaddr_storage *socketAddress) {
+    struct sockaddr_storage mappedAddress;
+    struct sockaddr_storage *realAddress;
+    if (socketAddress->ss_family == AF_INET &&
+        getSocketAddressFamily(socket) == AF_INET6) {
+        convertIpv4ToMapped((sockaddr_in *) socketAddress,
+                (sockaddr_in6 *) &mappedAddress, false);
+        realAddress = &mappedAddress;
+    } else {
+        realAddress = socketAddress;
+    }
+    int ret;
+    do {
+        ret = bind(socket, (struct sockaddr *) realAddress,
+                sizeof(struct sockaddr_storage));
+    } while (ret < 0 && errno == EINTR);
+    return ret;
+}
+
 /**
  * Establish a connection to a peer with a timeout.  This function is called
  * repeatedly in order to carry out the connect and to allow other tasks to
@@ -823,7 +1176,7 @@
  *
  * @return 0, if no errors occurred, otherwise the (negative) error code.
  */
-static int sockConnectWithTimeout(int handle, struct sockaddr_in addr,
+static int sockConnectWithTimeout(int handle, struct sockaddr_storage addr,
         unsigned int timeout, unsigned int step, jbyte *ctxt) {
     int rc = 0;
     struct timeval passedTimeout;
@@ -838,16 +1191,14 @@
         context->sock = handle;
         context->nfds = handle + 1;
 
-        if (useAdbNetworking && !isLocalhost(&addr)) {
+        if (useAdbNetworkingForAddress(&addr)) {
 
             // LOGD("+connect to address 0x%08x (via adb)",
             //         addr.sin_addr.s_addr);
-            rc = adb_networking_connect_fd(handle, &addr);
+            rc = adb_networking_connect_fd(handle, (struct sockaddr_in *) &addr);
             // LOGD("-connect ret %d errno %d (via adb)", rc, errno);
 
         } else {
-            log_socket_connect(handle, ntohl(addr.sin_addr.s_addr),
-                    ntohs(addr.sin_port));
             /* set the socket to non-blocking */
             int block = JNI_TRUE;
             rc = ioctl(handle, FIONBIO, &block);
@@ -857,10 +1208,7 @@
 
             // LOGD("+connect to address 0x%08x (via normal) on handle %d",
             //         addr.sin_addr.s_addr, handle);
-            do {
-                rc = connect(handle, (struct sockaddr *) &addr,
-                        sizeof(struct sockaddr));
-            } while (rc < 0 && errno == EINTR);
+            rc = doConnect(handle, &addr);
             // LOGD("-connect to address 0x%08x (via normal) returned %d",
             //         addr.sin_addr.s_addr, (int) rc);
 
@@ -971,6 +1319,123 @@
     return SOCKERR_ARGSINVALID;
 }
 
+
+#if LOG_SOCKOPT
+/**
+ * Helper method to log getsockopt/getsockopt calls.
+ */
+static const char *sockoptLevelToString(int level) {
+    switch(level) {
+        case SOL_SOCKET:
+            return "SOL_SOCKET";
+        case SOL_IP:
+            return "SOL_IP";
+        case SOL_IPV6:
+            return "SOL_IPV6";
+        default:
+            return "SOL_???";
+    }
+}
+#endif
+
+/**
+ * Helper method to get or set socket options
+ *
+ * @param action SOCKOPT_GET to get an option, SOCKOPT_SET to set it
+ * @param socket the file descriptor of the socket to use
+ * @param ipv4Option the option value to use for an IPv4 socket
+ * @param ipv6Option the option value to use for an IPv6 socket
+ * @param optionValue the value of the socket option to get or set
+ * @param optionLength the length of the socket option to get or set
+ *
+ * @return the value of the socket call, or -1 on failure inside this function
+ *
+ * @note on internal failure, the errno variable will be set appropriately
+ */
+static int getOrSetSocketOption(int action, int socket, int ipv4Option,
+        int ipv6Option, void *optionValue, socklen_t *optionLength) {
+    int option;
+    int protocol;
+    int family = getSocketAddressFamily(socket);
+    switch (family) {
+        case AF_INET:
+            option = ipv4Option;
+            protocol = SOL_IP;
+            break;
+        case AF_INET6:
+            option = ipv6Option;
+            protocol = SOL_IPV6;
+            break;
+        default:
+            // TODO: throw Java exceptions from this method instead of just
+            // returning error codes.
+            errno = EAFNOSUPPORT;
+            return -1;
+    }
+
+    int ret;
+    if (action == SOCKOPT_GET) {
+        ret = getsockopt(socket, protocol, option, optionValue, optionLength);
+#if LOG_SOCKOPT
+        LOGI("getsockopt(%d, %s, %d, %p, [%d]) = %d %s",
+                socket, sockoptLevelToString(protocol), option, optionValue,
+                *optionLength, ret, (ret == -1) ? strerror(errno) : "");
+#endif
+    } else if (action == SOCKOPT_SET) {
+        ret = setsockopt(socket, protocol, option, optionValue, *optionLength);
+#if LOG_SOCKOPT
+        LOGI("setsockopt(%d, %s, %d, [%d], %d) = %d %s",
+                socket, sockoptLevelToString(protocol), option,
+                // Note: this only works for integer options.
+                // TODO: Use dvmPrintHexDump() to log non-integer options.
+                *(int *)optionValue, *optionLength, ret,
+                (ret == -1) ? strerror(errno) : "");
+#endif
+    } else {
+        errno = EINVAL;
+        ret = -1;
+    }
+    return ret;
+}
+
+/*
+ * Find the interface index that was set for this socket by the IP_MULTICAST_IF
+ * or IPV6_MULTICAST_IF socket option.
+ *
+ * @param socket the socket to examine
+ *
+ * @return the interface index, or -1 on failure
+ *
+ * @note on internal failure, the errno variable will be set appropriately
+ */
+static int interfaceIndexFromMulticastSocket(int socket) {
+    int family = getSocketAddressFamily(socket);
+    socklen_t requestLength;
+    int interfaceIndex;
+    int result;
+    if (family == AF_INET) {
+        // IP_MULTICAST_IF returns a pointer to a struct ip_mreqn.
+        struct ip_mreqn tempRequest;
+        requestLength = sizeof(tempRequest);
+        result = getsockopt(socket, SOL_IP, IP_MULTICAST_IF, &tempRequest,
+            &requestLength);
+        interfaceIndex = tempRequest.imr_ifindex;
+    } else if (family == AF_INET6) {
+        // IPV6_MULTICAST_IF returns a pointer to an integer.
+        requestLength = sizeof(interfaceIndex);
+        result = getsockopt(socket, SOL_IPV6, IPV6_MULTICAST_IF,
+                &interfaceIndex, &requestLength);
+    } else {
+        errno = EAFNOSUPPORT;
+        return -1;
+    }
+
+    if (result == 0)
+        return interfaceIndex;
+    else
+        return -1;
+}
+
 /**
  * Join/Leave the nominated multicast group on the specified socket.
  * Implemented by setting the multicast 'add membership'/'drop membership'
@@ -994,103 +1459,125 @@
  */
 static void mcastAddDropMembership (JNIEnv * env, int handle, jobject optVal,
         int ignoreIF, int setSockOptVal) {
+    struct sockaddr_storage sockaddrP;
     int result;
-    struct ip_mreq ipmreqP;
-    struct sockaddr_in sockaddrP;
-    int length = sizeof(struct ip_mreq);
-    socklen_t lengthIF = sizeof(struct sockaddr_in);
+    // By default, let the system decide which interface to use.
+    int interfaceIndex = 0;
 
     /*
-     * JNI objects needed to access the information in the optVal oject
-     * passed in. The object passed in is a GenericIPMreq object
-     */
-    jclass cls;
-    jfieldID multiaddrID;
-    jfieldID interfaceAddrID;
-    jobject multiaddr;
-    jobject interfaceAddr;
-
-    /*
-     * check whether we are getting an InetAddress or an Generic IPMreq, for now
-     * we support both so that we will not break the tests
+     * Check whether we are getting an InetAddress or an Generic IPMreq. For now
+     * we support both so that we will not break the tests. If an InetAddress
+     * is passed in, only support IPv4 as obtaining an interface from an
+     * InetAddress is complex and should be done by the Java caller.
      */
     if (env->IsInstanceOf (optVal, gCachedFields.iaddr_class)) {
+        /*
+         * optVal is an InetAddress. Construct a multicast request structure
+         * from this address. Support IPv4 only.
+         */
+        struct ip_mreqn multicastRequest;
+        socklen_t length = sizeof(multicastRequest);
+        memset(&multicastRequest, 0, length);
 
-        ipmreqP.imr_interface.s_addr = htonl(INADDR_ANY);
+        // If ignoreIF is false, determine the index of the interface to use.
         if (!ignoreIF) {
-
-            result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF, &sockaddrP,
-                    &lengthIF);
-
-            if (0 != result) {
-                throwSocketException (env, convertError(errno));
+            interfaceIndex = interfaceIndexFromMulticastSocket(handle);
+            multicastRequest.imr_ifindex = interfaceIndex;
+            if (interfaceIndex == -1) {
+                throwSocketException(env, convertError(errno));
                 return;
             }
-
-            memcpy(&(ipmreqP.imr_interface.s_addr), &(sockaddrP.sin_addr), 4);
         }
 
+        // Convert the inetAddress to an IPv4 address structure.
         result = inetAddressToSocketAddress(env, optVal, 0, &sockaddrP);
-
-        if (result < 0) {
-            throwSocketException(env, SOCKERR_BADSOCKET);
+        if (result < 0)  // Exception has already been thrown.
+            return;
+        if (sockaddrP.ss_family != AF_INET) {
+            throwSocketException(env, SOCKERR_BADAF);
             return;
         }
+        struct sockaddr_in *sin = (struct sockaddr_in *) &sockaddrP;
+        multicastRequest.imr_multiaddr = sin->sin_addr;
 
-        memcpy(&(ipmreqP.imr_multiaddr.s_addr), &(sockaddrP.sin_addr), 4);
-
-        result = setsockopt(handle, IPPROTO_IP, setSockOptVal, &ipmreqP, length);
+        result = setsockopt(handle, SOL_IP, setSockOptVal,
+                            &multicastRequest, length);
         if (0 != result) {
             throwSocketException (env, convertError(errno));
             return;
         }
-
     } else {
+        /*
+         * optVal is a GenericIPMreq object. Extract the relevant fields from
+         * it and construct a multicast request structure from these. Support
+         * both IPv4 and IPv6.
+         */
+        jclass cls;
+        jfieldID multiaddrID;
+        jfieldID interfaceIdxID;
+        jobject multiaddr;
 
-        /* we need the multicast address regardless of the type of address */
+        // Get the multicast address to join or leave.
         cls = env->GetObjectClass(optVal);
         multiaddrID = env->GetFieldID(cls, "multiaddr", "Ljava/net/InetAddress;");
         multiaddr = env->GetObjectField(optVal, multiaddrID);
 
-        result = inetAddressToSocketAddress(env, multiaddr, 0, &sockaddrP);
-
-        if (result < 0) {
-            throwSocketException(env, SOCKERR_BADSOCKET);
-            return;
+        // Get the interface index to use.
+        if (! ignoreIF) {
+            interfaceIdxID = env->GetFieldID(cls, "interfaceIdx", "I");
+            interfaceIndex = env->GetIntField(optVal, interfaceIdxID);
         }
 
-        memcpy(&(ipmreqP.imr_multiaddr.s_addr), &(sockaddrP.sin_addr), 4);
+        result = inetAddressToSocketAddress(env, multiaddr, 0, &sockaddrP);
+        if (result < 0)  // Exception has already been thrown.
+            return;
 
-        /* we need to use an IP_MREQ as it is an IPV4 address */
-        interfaceAddrID = env->GetFieldID(cls, "interfaceAddr",
-                "Ljava/net/InetAddress;");
-        interfaceAddr = env->GetObjectField(optVal, interfaceAddrID);
+        int family = getSocketAddressFamily(handle);
 
-        ipmreqP.imr_interface.s_addr = htonl(INADDR_ANY);
+        // Handle IPv4 multicast on an IPv6 socket.
+        if (family == AF_INET6 && sockaddrP.ss_family == AF_INET) {
+            family = AF_INET;
+        }
 
-        /*
-         * if an interfaceAddr was passed then use that value, otherwise set the
-         * interface to all 0 to indicate the system should select the interface
-         * used
-         */
-        if (!ignoreIF) {
-            if (NULL != interfaceAddr) {
-
-                result = inetAddressToSocketAddress(env, interfaceAddr, 0,
-                        &sockaddrP);
-
-                if (result < 0) {
-                    throwSocketException(env, SOCKERR_BADSOCKET);
-                    return;
+        struct ip_mreqn ipv4Request;
+        struct ipv6_mreq ipv6Request;
+        void *multicastRequest;
+        socklen_t requestLength;
+        int level;
+        switch (family) {
+            case AF_INET:
+                requestLength = sizeof(ipv4Request);
+                memset(&ipv4Request, 0, requestLength);
+                ipv4Request.imr_multiaddr =
+                        ((struct sockaddr_in *) &sockaddrP)->sin_addr;
+                ipv4Request.imr_ifindex = interfaceIndex;
+                multicastRequest = &ipv4Request;
+                level = SOL_IP;
+                break;
+            case AF_INET6:
+                // setSockOptVal is passed in by the caller and may be IPv4-only
+                if (setSockOptVal == IP_ADD_MEMBERSHIP) {
+                    setSockOptVal = IPV6_ADD_MEMBERSHIP;
                 }
-
-                memcpy(&(ipmreqP.imr_interface.s_addr), &(sockaddrP.sin_addr), 4);
-
-            }
+                if (setSockOptVal == IP_DROP_MEMBERSHIP) {
+                    setSockOptVal == IPV6_DROP_MEMBERSHIP;
+                }
+                requestLength = sizeof(ipv6Request);
+                memset(&ipv6Request, 0, requestLength);
+                ipv6Request.ipv6mr_multiaddr =
+                        ((struct sockaddr_in6 *) &sockaddrP)->sin6_addr;
+                ipv6Request.ipv6mr_interface = interfaceIndex;
+                multicastRequest = &ipv6Request;
+                level = SOL_IPV6;
+                break;
+           default:
+               throwSocketException (env, SOCKERR_BADAF);
+               return;
         }
 
         /* join/drop the multicast address */
-        result = setsockopt(handle, IPPROTO_IP, setSockOptVal, &ipmreqP, length);
+        result = setsockopt(handle, level, setSockOptVal, multicastRequest,
+                            requestLength);
         if (0 != result) {
             throwSocketException (env, convertError(errno));
             return;
@@ -1114,263 +1601,123 @@
     }
 
     memset(&gCachedFields, 0, sizeof(gCachedFields));
+    struct CachedFields *c = &gCachedFields;
 
-    // initializing InetAddress
-
-    jclass iaddrclass = env->FindClass("java/net/InetAddress");
-
-    if (iaddrclass == NULL) {
-        jniThrowException(env, "java/lang/ClassNotFoundException",
-                "java.net.InetAddress");
-        return;
+    struct classInfo {
+        jclass *clazz;
+        const char *name;
+    } classes[] = {
+        {&c->iaddr_class, "java/net/InetAddress"},
+        {&c->i4addr_class, "java/net/Inet4Address"},
+        {&c->genericipmreq_class, "org/apache/harmony/luni/net/GenericIPMreq"},
+        {&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"}
+    };
+    for (unsigned i = 0; i < sizeof(classes) / sizeof(classes[0]); i++) {
+        classInfo c = classes[i];
+        jclass tempClass = env->FindClass(c.name);
+        if (tempClass == NULL) return;
+        *c.clazz = (jclass) env->NewGlobalRef(tempClass);
     }
 
-    gCachedFields.iaddr_class = (jclass) env->NewGlobalRef(iaddrclass);
-
-    jmethodID iaddrclassinit = env->GetMethodID(iaddrclass, "<init>", "()V");
-
-    if (iaddrclassinit == NULL) {
-        jniThrowException(env, "java/lang/NoSuchMethodError", "InetAddress.<init>()");
-        return;
+    struct methodInfo {
+        jmethodID *method;
+        jclass clazz;
+        const char *name;
+        const char *signature;
+        bool isStatic;
+    } methods[] = {
+        {&c->i4addr_class_init, c->i4addr_class, "<init>", "([B)V", false},
+        {&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}
+    };
+    for (unsigned i = 0; i < sizeof(methods) / sizeof(methods[0]); i++) {
+        methodInfo m = methods[i];
+        if (m.isStatic) {
+            *m.method = env->GetStaticMethodID(m.clazz, m.name, m.signature);
+        } else {
+            *m.method = env->GetMethodID(m.clazz, m.name, m.signature);
+        }
+        if (*m.method == NULL) return;
     }
 
-    gCachedFields.iaddr_class_init = iaddrclassinit;
-
-    jmethodID iaddrgetbyaddress = env->GetStaticMethodID(iaddrclass,
-            "getByAddress", "([B)Ljava/net/InetAddress;");
-
-    if (iaddrgetbyaddress == NULL) {
-        jniThrowException(env, "java/lang/NoSuchMethodError",
-                "InetAddress.getByAddress(byte[] val)");
-        return;
+    struct fieldInfo {
+        jfieldID *field;
+        jclass clazz;
+        const char *name;
+        const char *type;
+    } fields[] = {
+        {&c->iaddr_ipaddress, c->iaddr_class, "ipaddress", "[B"},
+        {&c->integer_class_value, c->integer_class, "value", "I"},
+        {&c->boolean_class_value, c->boolean_class, "value", "Z"},
+        {&c->byte_class_value, c->byte_class, "value", "B"},
+        {&c->socketimpl_port, c->socketimpl_class, "port", "I"},
+        {&c->socketimpl_address, c->socketimpl_class, "address",
+                "Ljava/net/InetAddress;"},
+        {&c->dpack_address, c->dpack_class, "address",
+                "Ljava/net/InetAddress;"},
+        {&c->dpack_port, c->dpack_class, "port", "I"},
+        {&c->dpack_length, c->dpack_class, "length", "I"}
+    };
+    for (unsigned i = 0; i < sizeof(fields) / sizeof(fields[0]); i++) {
+        fieldInfo f = fields[i];
+        *f.field = env->GetFieldID(f.clazz, f.name, f.type);
+        if (*f.field == NULL) return;
     }
-
-    gCachedFields.iaddr_getbyaddress = iaddrgetbyaddress;
-
-    jfieldID iaddripaddress = env->GetFieldID(iaddrclass, "ipaddress", "[B");
-
-    if (iaddripaddress == NULL) {
-        jniThrowException(env, "java/lang/NoSuchFieldError",
-                "Can't find field InetAddress.ipaddress");
-        return;
-    }
-
-    gCachedFields.iaddr_ipaddress = iaddripaddress;
-
-    // get the GenericIPMreq class
-
-    jclass genericipmreqclass = env->FindClass("org/apache/harmony/luni/net/GenericIPMreq");
-
-    if (genericipmreqclass == NULL) {
-        jniThrowException(env, "java/lang/ClassNotFoundException",
-                "org.apache.harmony.luni.net.GenericIPMreq");
-        return;
-    }
-
-    gCachedFields.genericipmreq_class = (jclass) env->NewGlobalRef(genericipmreqclass);
-
-    // initializing Integer
-
-    jclass integerclass = env->FindClass("java/lang/Integer");
-
-    if (integerclass == NULL) {
-        jniThrowException(env, "java/lang/ClassNotFoundException",
-                "java.lang.Integer");
-        return;
-    }
-
-    jmethodID integerclassinit = env->GetMethodID(integerclass, "<init>", "(I)V");
-
-    if (integerclassinit == NULL) {
-        jniThrowException(env, "java/lang/NoSuchMethodError",
-                "Integer.<init>(int val)");
-        return;
-    }
-
-    jfieldID integerclassvalue = env->GetFieldID(integerclass, "value", "I");
-
-    if (integerclassvalue == NULL) {
-        jniThrowException(env, "java/lang/NoSuchMethodError", "Integer.value");
-        return;
-    }
-
-    gCachedFields.integer_class = (jclass) env->NewGlobalRef(integerclass);
-    gCachedFields.integer_class_init = integerclassinit;
-    gCachedFields.integer_class_value = integerclassvalue;
-
-    // initializing Boolean
-
-    jclass booleanclass = env->FindClass("java/lang/Boolean");
-
-    if (booleanclass == NULL) {
-        jniThrowException(env, "java/lang/ClassNotFoundException",
-                "java.lang.Boolean");
-        return;
-    }
-
-    jmethodID booleanclassinit = env->GetMethodID(booleanclass, "<init>", "(Z)V");
-
-    if (booleanclassinit == NULL) {
-        jniThrowException(env, "java/lang/NoSuchMethodError",
-                "Boolean.<init>(boolean val)");
-        return;
-    }
-
-    jfieldID booleanclassvalue = env->GetFieldID(booleanclass, "value", "Z");
-
-    if (booleanclassvalue == NULL) {
-        jniThrowException(env, "java/lang/NoSuchMethodError", "Boolean.value");
-        return;
-    }
-
-    gCachedFields.boolean_class = (jclass) env->NewGlobalRef(booleanclass);
-    gCachedFields.boolean_class_init = booleanclassinit;
-    gCachedFields.boolean_class_value = booleanclassvalue;
-
-    // initializing Byte
-
-    jclass byteclass = env->FindClass("java/lang/Byte");
-
-    if (byteclass == NULL) {
-        jniThrowException(env, "java/lang/ClassNotFoundException",
-                "java.lang.Byte");
-        return;
-    }
-
-    jmethodID byteclassinit = env->GetMethodID(byteclass, "<init>", "(B)V");
-
-    if (byteclassinit == NULL) {
-        jniThrowException(env, "java/lang/NoSuchMethodError",
-                "Byte.<init>(byte val)");
-        return;
-    }
-
-    jfieldID byteclassvalue = env->GetFieldID(byteclass, "value", "B");
-
-    if (byteclassvalue == NULL) {
-        jniThrowException(env, "java/lang/NoSuchMethodError", "Byte.value");
-        return;
-    }
-
-    gCachedFields.byte_class = (jclass) env->NewGlobalRef(byteclass);
-    gCachedFields.byte_class_init = byteclassinit;
-    gCachedFields.byte_class_value = byteclassvalue;
-
-    // initializing String
-
-    jclass stringclass = env->FindClass("java/lang/String");
-
-    if (stringclass == NULL) {
-        jniThrowException(env, "java/lang/ClassNotFoundException",
-                "java.lang.String");
-        return;
-    }
-
-    jmethodID stringclassinit = env->GetMethodID(stringclass, "<init>", "([B)V");
-
-    if (stringclassinit == NULL) {
-        jniThrowException(env, "java/lang/NoSuchMethodError",
-                "String.<init>(byte[] val)");
-        return;
-    }
-
-    gCachedFields.string_class = (jclass) env->NewGlobalRef(stringclass);
-    gCachedFields.string_class_init = stringclassinit;
-
-    // initializing ScoketImpl
-
-    jclass socketimplclass = env->FindClass("java/net/SocketImpl");
-
-    if (socketimplclass == NULL) {
-        jniThrowException(env, "java/lang/ClassNotFoundException",
-                "java.net.SocketImpl");
-        return;
-    }
-
-    jfieldID socketimplport = env->GetFieldID(socketimplclass, "port", "I");
-
-    if (socketimplport == NULL) {
-        jniThrowException(env, "java/lang/NoSuchFieldError", "SocketImpl.port");
-        return;
-    }
-
-    jfieldID socketimpladdress = env->GetFieldID(socketimplclass, "address",
-            "Ljava/net/InetAddress;");
-
-    if (socketimpladdress == NULL) {
-        jniThrowException(env, "java/lang/NoSuchFieldError",
-                "SocketImpl.address");
-        return;
-    }
-
-    gCachedFields.socketimpl_address = socketimpladdress;
-    gCachedFields.socketimpl_port = socketimplport;
-
-    gCachedFields.dpack_class = env->FindClass("java/net/DatagramPacket");
-    if (gCachedFields.dpack_class == NULL) {
-        jniThrowException(env, "java/lang/ClassNotFoundException",
-                "java.net.DatagramPacket");
-        return;
-    }
-
-    gCachedFields.dpack_address = env->GetFieldID(gCachedFields.dpack_class,
-            "address", "Ljava/net/InetAddress;");
-    if (gCachedFields.dpack_address == NULL) {
-        jniThrowException(env, "java/lang/NoSuchFieldError",
-                "DatagramPacket.address");
-        return;
-    }
-
-    gCachedFields.dpack_port = env->GetFieldID(gCachedFields.dpack_class,
-            "port", "I");
-    if (gCachedFields.dpack_port == NULL) {
-        jniThrowException(env, "java/lang/NoSuchFieldError",
-                "DatagramPacket.port");
-        return;
-    }
-
-    gCachedFields.dpack_length = env->GetFieldID(gCachedFields.dpack_class,
-            "length", "I");
-    if (gCachedFields.dpack_length == NULL) {
-        jniThrowException(env, "java/lang/NoSuchFieldError",
-                "DatagramPacket.length");
-        return;
-    }
-
 }
 
-static void osNetworkSystem_createSocketImpl(JNIEnv* env, jclass clazz,
-        jobject fileDescriptor, jboolean preferIPv4Stack) {
-    // LOGD("ENTER createSocketImpl");
-
-    int ret = socket(PF_INET, SOCK_STREAM, 0);
-
-    if (ret < 0) {
-        int err = convertError(errno);
-        throwSocketException(env, err);
-        return;
+/**
+ * Helper function to create a socket of the specified type and bind it to a
+ * Java file descriptor.
+ *
+ * @param fileDescriptor the file descriptor to bind the socket to
+ * @param type the socket type to create, e.g., SOCK_STREAM
+ * @throws SocketException an error occurred when creating the socket
+ *
+ * @return the socket file descriptor. On failure, an exception is thrown and
+ *         a negative value is returned.
+ *
+ */
+static int createSocketFileDescriptor(JNIEnv* env, jobject fileDescriptor,
+                                      int type) {
+    if (fileDescriptor == NULL) {
+        throwNullPointerException(env);
+        errno = EBADF;
+        return -1;
     }
 
-    jniSetFileDescriptorOfFD(env, fileDescriptor, ret);
+    int sock;
+    sock = socket(PF_INET6, type, 0);
+    if (sock < 0 && errno == EAFNOSUPPORT) {
+        sock = socket(PF_INET, type, 0);
+    }
+    if (sock < 0) {
+        int err = convertError(errno);
+        throwSocketException(env, err);
+        return sock;
+    }
+    jniSetFileDescriptorOfFD(env, fileDescriptor, sock);
+    return sock;
+}
 
-    return;
+static void osNetworkSystem_createStreamSocketImpl(JNIEnv* env, jclass clazz,
+        jobject fileDescriptor, jboolean preferIPv4Stack) {
+    // LOGD("ENTER createSocketImpl");
+    createSocketFileDescriptor(env, fileDescriptor, SOCK_STREAM);
 }
 
 static void osNetworkSystem_createDatagramSocketImpl(JNIEnv* env, jclass clazz,
         jobject fileDescriptor, jboolean preferIPv4Stack) {
     // LOGD("ENTER createDatagramSocketImpl");
-
-    int ret = socket(PF_INET, SOCK_DGRAM, 0);
-
-    if (ret < 0) {
-        int err = convertError(errno);
-        throwSocketException(env, err);
-        return;
-    }
-
-    jniSetFileDescriptorOfFD(env, fileDescriptor, ret);
-
-    return;
+    createSocketFileDescriptor(env, fileDescriptor, SOCK_DGRAM);
 }
 
 static jint osNetworkSystem_readSocketDirectImpl(JNIEnv* env, jclass clazz,
@@ -1379,7 +1726,7 @@
     // LOGD("ENTER readSocketDirectImpl");
 
     int handle;
-    jbyte *message = (jbyte *)address;
+    jbyte *message = (jbyte *)address + offset;
     int result, ret, localCount;
 
     handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
@@ -1405,11 +1752,9 @@
         return -1;
     } else if (ret == -1) {
         int err = convertError(errno);
-        log_socket_close(handle, err);
         throwSocketException(env, err);
         return 0;
     }
-    add_recv_stats(handle, ret);
     return ret;
 }
 
@@ -1437,7 +1782,7 @@
     }
 
     result = osNetworkSystem_readSocketDirectImpl(env, clazz, fileDescriptor,
-            (jint) message, offset, count, timeout);
+            (jint) message, 0, localCount, timeout);
 
     if (result > 0) {
         env->SetByteArrayRegion(data, offset, result, (jbyte *)message);
@@ -1455,7 +1800,7 @@
     // LOGD("ENTER writeSocketDirectImpl");
 
     int handle;
-    jbyte *message = (jbyte *)address;
+    jbyte *message = (jbyte *)address + offset;
     int result = 0, sent = 0;
 
     if (count <= 0) {
@@ -1472,7 +1817,6 @@
     result = send(handle, (jbyte *) message, (int) count, SOCKET_NOFLAGS);
     if (result < 0) {
         int err = convertError(errno);
-        log_socket_close(handle, err);
 
         if (SOCKERR_WOULDBLOCK == err){
             jclass socketExClass,errorCodeExClass;
@@ -1499,7 +1843,7 @@
             if (!socketExConstructor) {
                 return 0;
             }
-            socketEx = env->NewObject(socketExClass, socketExConstructor, errorMessageString); 
+            socketEx = env->NewObject(socketExClass, socketExConstructor, errorMessageString);
             socketExCauseMethod = env->GetMethodID(socketExClass,"initCause","(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
             env->CallObjectMethod(socketEx,socketExCauseMethod,errorCodeEx);
             env->Throw((jthrowable)socketEx);
@@ -1509,7 +1853,6 @@
         return 0;
     }
 
-    add_send_stats(handle, result);
     return result;
 }
 
@@ -1539,13 +1882,13 @@
     env->GetByteArrayRegion(data, offset, count, message);
 
     result = osNetworkSystem_writeSocketDirectImpl(env, clazz, fileDescriptor,
-            (jint) message, offset, count);
+            (jint) message, 0, count);
 
     if (( jbyte *)message != internalBuffer) {
-      free(( jbyte *)message);
+        free(( jbyte *)message);
     }
 #undef INTERNAL_SEND_BUFFER_MAX
-   return result;
+    return result;
 }
 
 static void osNetworkSystem_setNonBlockingImpl(JNIEnv* env, jclass clazz,
@@ -1581,36 +1924,25 @@
 
     int handle;
     int result = 0;
-    struct sockaddr_in address;
+    struct sockaddr_storage address;
     jbyte *context = NULL;
 
-    memset(&address, 0, sizeof(address));
-
-    address.sin_family = AF_INET;
-
-    result = inetAddressToSocketAddress(env, inetAddr, port,
-            (struct sockaddr_in *) &address);
-
-    if (result < 0) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
+    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 (useAdbNetworking && !isLocalhost(&address)) {
+    if (useAdbNetworkingForAddress(&address)) {
         return osNetworkSystem_connectSocketImpl(env, clazz, fileDescriptor,
                 trafficClass, inetAddr, port);
     }
 
     handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
     if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
+        throwSocketException(env, SOCKERR_BADDESC);
         return -1;
     }
 
-    address.sin_port = htons(port);
-
     context = (jbyte *)env->GetPrimitiveArrayCritical(passContext, NULL);
 
     switch (step) {
@@ -1651,7 +1983,7 @@
 
     int result = 0;
     int handle;
-    struct sockaddr_in address;
+    struct sockaddr_storage address;
     jbyte *context = NULL;
     int remainingTimeout = timeout;
     int passedTimeout = 0;
@@ -1664,53 +1996,117 @@
         finishTime = time_msec_clock() + (int) timeout;
     }
 
-
     handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
     if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
+        throwSocketException(env, SOCKERR_BADDESC);
         return;
-    } else {
-        result = inetAddressToSocketAddress(env, inetAddr, remotePort,
-                (struct sockaddr_in *) &address);
+    }
 
-        if (result < 0) {
+    result = inetAddressToSocketAddress(env, inetAddr, remotePort, &address);
+    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;
         }
+        return;
+    }
 
-        // Check if we're using adb networking and redirect in case it is used.
-        if (useAdbNetworking && !isLocalhost(&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
+     */
+    context =(jbyte *) malloc(sizeof(struct selectFDSet));
+    if (NULL == context) {
+        throwSocketException(env, SOCKERR_NOBUFFERS);
+        return;
+    }
+
+    result = sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_START, context);
+    if (0 == result) {
+        /* ok we connected right away so we are done */
+        sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE, context);
+        goto bail;
+    } else if (result != SOCKERR_NOTCONNECTED) {
+        sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE,
+                               context);
+        /* we got an error other than NOTCONNECTED so we cannot continue */
+        if (SOCKERR_EACCES == result) {
+            jniThrowException(env, "java/lang/SecurityException",
+                              netLookupErrorString(result));
+        } else {
+            throwSocketException(env, result);
+        }
+        goto bail;
+    }
+
+    while (SOCKERR_NOTCONNECTED == result) {
+        passedTimeout = remainingTimeout;
+
+        /*
+         * ok now try and connect. Depending on the platform this may sleep
+         * for up to passedTimeout milliseconds
+         */
+        result = sockConnectWithTimeout(handle, address, passedTimeout,
+                SOCKET_STEP_CHECK, context);
+
+        /*
+         * now check if the socket is still connected.
+         * Do it here as some platforms seem to think they
+         * are connected if the socket is closed on them.
+         */
+        handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
+        if (handle == 0 || handle == -1) {
+            sockConnectWithTimeout(handle, address, 0,
+                    SOCKET_STEP_DONE, context);
+            throwSocketException(env, SOCKERR_BADSOCKET);
+            goto bail;
         }
 
         /*
-         * we will be looping checking for when we are connected so allocate
-         * the descriptor sets that we will use
+         * check if we are now connected,
+         * if so we can finish the process and return
          */
-        context =(jbyte *) malloc(sizeof(struct selectFDSet));
-
-        if (NULL == context) {
-            throwSocketException(env, SOCKERR_NOBUFFERS);
-            return;
+        if (0 == result) {
+            sockConnectWithTimeout(handle, address, 0,
+                    SOCKET_STEP_DONE, context);
+            goto bail;
         }
 
-        result = sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_START, context);
-        if (0 == result) {
-            /* ok we connected right away so we are done */
-            sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE, context);
-            goto bail;
-        } else if (result != SOCKERR_NOTCONNECTED) {
-            log_socket_close(handle, result);
-            sockConnectWithTimeout(handle, address, 0, SOCKET_STEP_DONE,
-                                   context);
-            /* we got an error other than NOTCONNECTED so we cannot continue */
-            if (SOCKERR_EACCES == result) {
+        /*
+         * if the error is SOCKERR_NOTCONNECTED then we have not yet
+         * connected and we may not be done yet
+         */
+        if (SOCKERR_NOTCONNECTED == result) {
+            /* check if the timeout has expired */
+            if (hasTimeout) {
+                remainingTimeout = finishTime - time_msec_clock();
+                if (remainingTimeout <= 0) {
+                    sockConnectWithTimeout(handle, address, 0,
+                            SOCKET_STEP_DONE, context);
+                    jniThrowException(env,
+                            "java/net/SocketTimeoutException",
+                            netLookupErrorString(result));
+                    goto bail;
+                }
+            } else {
+                remainingTimeout = 100;
+            }
+        } else {
+            sockConnectWithTimeout(handle, address, remainingTimeout,
+                                   SOCKET_STEP_DONE, context);
+            if ((SOCKERR_CONNRESET == result) ||
+                (SOCKERR_CONNECTION_REFUSED == result) ||
+                (SOCKERR_ADDRNOTAVAIL == result) ||
+                (SOCKERR_ADDRINUSE == result) ||
+                (SOCKERR_ENETUNREACH == result)) {
+                jniThrowException(env, "java/net/ConnectException",
+                                  netLookupErrorString(result));
+            } else if (SOCKERR_EACCES == result) {
                 jniThrowException(env, "java/lang/SecurityException",
                                   netLookupErrorString(result));
             } else {
@@ -1718,81 +2114,6 @@
             }
             goto bail;
         }
-
-        while (SOCKERR_NOTCONNECTED == result) {
-            passedTimeout = remainingTimeout;
-
-            /*
-             * ok now try and connect. Depending on the platform this may sleep
-             * for up to passedTimeout milliseconds
-             */
-            result = sockConnectWithTimeout(handle, address, passedTimeout,
-                    SOCKET_STEP_CHECK, context);
-
-            /*
-             * now check if the socket is still connected.
-             * Do it here as some platforms seem to think they
-             * are connected if the socket is closed on them.
-             */
-            handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
-            if (handle == 0 || handle == -1) {
-                sockConnectWithTimeout(handle, address, 0,
-                        SOCKET_STEP_DONE, context);
-                throwSocketException(env, SOCKERR_BADSOCKET);
-                goto bail;
-            }
-
-            /*
-             * check if we are now connected,
-             * if so we can finish the process and return
-             */
-            if (0 == result) {
-                sockConnectWithTimeout(handle, address, 0,
-                        SOCKET_STEP_DONE, context);
-                goto bail;
-            }
-
-            /*
-             * if the error is SOCKERR_NOTCONNECTED then we have not yet
-             * connected and we may not be done yet
-             */
-            if (SOCKERR_NOTCONNECTED == result) {
-                /* check if the timeout has expired */
-                if (hasTimeout) {
-                    remainingTimeout = finishTime - time_msec_clock();
-                    if (remainingTimeout <= 0) {
-                        log_socket_close(handle, result);
-                        sockConnectWithTimeout(handle, address, 0,
-                                SOCKET_STEP_DONE, context);
-                        jniThrowException(env,
-                                "java/net/SocketTimeoutException",
-                                netLookupErrorString(result));
-                        goto bail;
-                     }
-                } else {
-                    remainingTimeout = 100;
-                }
-            } else {
-                log_socket_close(handle, result);
-                sockConnectWithTimeout(handle, address, remainingTimeout,
-                                       SOCKET_STEP_DONE, context);
-                if ((SOCKERR_CONNRESET == result) ||
-                    (SOCKERR_CONNECTION_REFUSED == result) ||
-                    (SOCKERR_ADDRNOTAVAIL == result) ||
-                    (SOCKERR_ADDRINUSE == result) ||
-                    (SOCKERR_ENETUNREACH == result)) {
-                    jniThrowException(env, "java/net/ConnectException",
-                                      netLookupErrorString(result));
-                } else if (SOCKERR_EACCES == result) {
-                    jniThrowException(env, "java/lang/SecurityException",
-                                      netLookupErrorString(result));
-                } else {
-                    throwSocketException(env, result);
-                }
-                goto bail;
-            }
-        }
     }
 
 bail:
@@ -1807,37 +2128,25 @@
         jobject fileDescriptor, jint trafficClass, jobject inetAddr, jint port) {
     //LOGD("ENTER direct-call connectSocketImpl\n");
 
-    struct sockaddr_in address;
+    struct sockaddr_storage address;
     int ret;
     int handle;
-    jbyteArray java_in_addr;
 
-    memset(&address, 0, sizeof(address));
-
-    address.sin_family = AF_INET;
-
-    ret = inetAddressToSocketAddress(env, inetAddr, port,
-            (struct sockaddr_in *) &address);
-
-    if (ret < 0) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
+    ret = inetAddressToSocketAddress(env, inetAddr, port, &address);
+    if (ret < 0)
         return ret;
-    }
 
     handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
     if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
+        throwSocketException(env, SOCKERR_BADDESC);
         return -1;
     }
 
-    address.sin_port = htons(port);
-
-    if (useAdbNetworking && !isLocalhost(&address)) {
+    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, &address);
+        ret = adb_networking_connect_fd(handle, (struct sockaddr_in *) &address);
         // LOGD("-connect ret %d errno %d (via adb)", ret, errno);
 
     } else {
@@ -1866,27 +2175,21 @@
         jobject fileDescriptor, jint port, jobject inetAddress) {
     // LOGD("ENTER socketBindImpl");
 
-    struct sockaddr_in sockaddress;
+    struct sockaddr_storage sockaddress;
     int ret;
     int handle;
 
-    ret = inetAddressToSocketAddress(env, inetAddress, port,
-            (struct sockaddr_in *) &sockaddress);
-
-    if (ret < 0) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
+    ret = inetAddressToSocketAddress(env, inetAddress, port, &sockaddress);
+    if (ret < 0)
         return;
-    }
 
     handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
     if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
+        throwSocketException(env, SOCKERR_BADDESC);
         return;
     }
 
-    ret = bind(handle, (const sockaddr*)&sockaddress, sizeof(sockaddress));
-
+    ret = doBind(handle, &sockaddress);
     if (ret < 0) {
         jniThrowException(env, "java/net/BindException",
                 netLookupErrorString(convertError(errno)));
@@ -1912,7 +2215,6 @@
 
     if (ret < 0) {
         int err = convertError(errno);
-        log_socket_close(handle, err);
         throwSocketException(env, err);
         return;
     }
@@ -1928,9 +2230,8 @@
     int result;
 
     handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
     if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
+        throwSocketException(env, SOCKERR_BADDESC);
         return 0;
     }
 
@@ -1943,7 +2244,6 @@
         } else if (SOCKERR_INTERRUPTED == result) {
             continue;
         } else if (0 > result) {
-            log_socket_close(handle, result);
             throwSocketException(env, result);
             return 0;
         }
@@ -1953,11 +2253,9 @@
 
     if (0 > result) {
         int err = convertError(errno);
-        log_socket_close(handle, err);
         throwSocketException(env, err);
         return 0;
     }
-    add_recv_stats(handle, result);
     return result;
 }
 
@@ -1965,10 +2263,7 @@
         jobject fdServer, jobject newSocket, jobject fdnewSocket, jint timeout) {
     // LOGD("ENTER acceptSocketImpl");
 
-    union {
-        struct sockaddr address;
-        struct sockaddr_in in_address;
-    } sa;
+    struct sockaddr_storage sa;
 
     int ret;
     int retFD;
@@ -1982,55 +2277,47 @@
     }
 
     result = pollSelectWait(env, fdServer, timeout, SELECT_READ_TYPE);
-
     if (0 > result) {
         return;
     }
 
     handle = jniGetFDFromFileDescriptor(env, fdServer);
-
     if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
+        throwSocketException(env, SOCKERR_BADDESC);
         return;
     }
 
     do {
         addrlen = sizeof(sa);
-        ret = accept(handle, &(sa.address), &addrlen);
+        ret = accept(handle, (struct sockaddr *) &sa, &addrlen);
     } while (ret < 0 && errno == EINTR);
 
     if (ret < 0) {
         int err = convertError(errno);
-        log_socket_close(handle, err);
         throwSocketException(env, err);
         return;
     }
 
     retFD = ret;
 
-    /* For AF_INET / inetOrLocal == true only: put
-     * peer address and port in instance variables
-     * We don't bother for UNIX domain sockets, since most peers are
-     * anonymous anyway
+    /*
+     * For network sockets, put the peer address and port in instance variables.
+     * We don't bother to do this for UNIX domain sockets, since most peers are
+     * anonymous anyway.
      */
-    if (sa.address.sa_family == AF_INET) {
-        // inetOrLocal should also be true
-
-        jobject inetAddress;
-
-        inetAddress = structInToInetAddress(env, &(sa.in_address.sin_addr));
-
-        if (inetAddress == NULL) {
+    if (sa.ss_family == AF_INET || sa.ss_family == AF_INET6) {
+        jobject inetAddress =  socketAddressToInetAddress(env, &sa);
+        if (ret == -1) {
             close(retFD);
-            newSocket = NULL;
+            newSocket = NULL;  // Exception has already been thrown.
             return;
         }
 
         env->SetObjectField(newSocket,
                 gCachedFields.socketimpl_address, inetAddress);
 
-        env->SetIntField(newSocket, gCachedFields.socketimpl_port,
-                ntohs(sa.in_address.sin_port));
+        int port = getSocketAddressPort(&sa);
+        env->SetIntField(newSocket, gCachedFields.socketimpl_port, port);
     }
 
     jniSetFileDescriptorOfFD(env, fdnewSocket, retFD);
@@ -2066,7 +2353,6 @@
     result = send(handle, (jbyte *) &value, 1, MSG_OOB);
     if (result < 0) {
         int err = convertError(errno);
-        log_socket_close(handle, err);
         throwSocketException(env, err);
     }
 }
@@ -2077,20 +2363,16 @@
 
     int handle = jniGetFDFromFileDescriptor(env, fd);
 
-    struct sockaddr_in sockAddr;
+    struct sockaddr_storage sockAddr;
     int ret;
 
     ret = inetAddressToSocketAddress(env, inetAddress, port, &sockAddr);
-
-    if (ret < 0) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
+    if (ret < 0)  // Exception has already been thrown.
         return;
-    }
-    log_socket_connect(handle, ntohl(sockAddr.sin_addr.s_addr), port);
-    int result = connect(handle, (struct sockaddr *)&sockAddr, sizeof(sockAddr));
-    if (result < 0) {
+
+    ret = doConnect(handle, &sockAddr);
+    if (ret < 0) {
         int err = convertError(errno);
-        log_socket_close(handle, err);
         throwSocketException(env, err);
     }
 }
@@ -2101,57 +2383,17 @@
 
     int handle = jniGetFDFromFileDescriptor(env, fd);
 
-    struct sockaddr_in *sockAddr;
-    socklen_t sockAddrLen = sizeof(struct sockaddr_in);
-    sockAddr = (struct sockaddr_in *) malloc(sockAddrLen);
-    memset(sockAddr, 0, sockAddrLen);
+    struct sockaddr_storage sockAddr;
+    memset(&sockAddr, 0, sizeof(sockAddr));
+    sockAddr.ss_family = AF_UNSPEC;
 
-    sockAddr->sin_family = AF_UNSPEC;
-    int result = connect(handle, (struct sockaddr *)sockAddr, sockAddrLen);
-    free(sockAddr);
-
+    int result = doConnect(handle, &sockAddr);
     if (result < 0) {
         int err = convertError(errno);
-        log_socket_close(handle, err);
         throwSocketException(env, err);
     }
 }
 
-static jboolean osNetworkSystem_socketBindImpl2(JNIEnv* env, jclass clazz,
-        jobject fileDescriptor, jint port, jboolean bindToDevice,
-        jobject inetAddress) {
-    // LOGD("ENTER socketBindImpl2");
-
-    struct sockaddr_in sockaddress;
-    int ret;
-    int handle;
-
-    ret = inetAddressToSocketAddress(env, inetAddress, port,
-            (struct sockaddr_in *) &sockaddress);
-
-    if (ret < 0) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
-        return 0;
-    }
-
-    handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-    if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
-        return 0;
-    }
-
-    ret = bind(handle, (const sockaddr*)&sockaddress, sizeof(sockaddress));
-
-    if (ret < 0) {
-        int err = convertError(errno);
-        log_socket_close(handle, err);
-        jniThrowException(env, "java/net/BindException", netLookupErrorString(err));
-        return 0;
-    }
-
-    return 0;
-}
-
 static jint osNetworkSystem_peekDatagramImpl(JNIEnv* env, jclass clazz,
         jobject fd, jobject sender, jint receiveTimeout) {
     // LOGD("ENTER peekDatagramImpl");
@@ -2164,30 +2406,29 @@
     }
 
     int handle = jniGetFDFromFileDescriptor(env, fd);
-
     if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
+        throwSocketException(env, SOCKERR_BADDESC);
         return 0;
     }
 
-    struct sockaddr_in sockAddr;
+    struct sockaddr_storage sockAddr;
     socklen_t sockAddrLen = sizeof(sockAddr);
-
-    int length = recvfrom(handle, NULL, 0, MSG_PEEK,
-            (struct sockaddr *)&sockAddr, &sockAddrLen);
-
+    ssize_t length;
+    do {
+        length = recvfrom(handle, NULL, 0, MSG_PEEK,
+                (struct sockaddr *)&sockAddr, &sockAddrLen);
+    } while (length < 0 && errno == EINTR);
     if (length < 0) {
         int err = convertError(errno);
-        log_socket_close(handle, err);
         throwSocketException(env, err);
         return 0;
     }
 
-    if (socketAddressToInetAddress(env, &sockAddr, sender, &port) < 0) {
-        throwIOExceptionStr(env, "Address conversion failed");
+    sender = socketAddressToInetAddress(env, &sockAddr);
+    if (sender == NULL)  // Exception has already been thrown.
         return -1;
-    }
-    add_recv_stats(handle, length);
+
+    port = getSocketAddressPort(&sockAddr);
     return port;
 }
 
@@ -2202,44 +2443,41 @@
     }
 
     int handle = jniGetFDFromFileDescriptor(env, fd);
-
     if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
+        throwSocketException(env, SOCKERR_BADDESC);
         return 0;
     }
 
-    struct sockaddr_in sockAddr;
+    struct sockaddr_storage sockAddr;
     socklen_t sockAddrLen = sizeof(sockAddr);
 
     int mode = peek ? MSG_PEEK : 0;
 
-    int actualLength = recvfrom(handle, (char*)(address + offset), length, mode,
-            (struct sockaddr *)&sockAddr, &sockAddrLen);
-
+    ssize_t actualLength;
+    do {
+        actualLength = recvfrom(handle, (char*)(address + offset), length, mode,
+                (struct sockaddr *)&sockAddr, &sockAddrLen);
+    } while (actualLength < 0 && errno == EINTR);
     if (actualLength < 0) {
         int err = convertError(errno);
-        log_socket_close(handle, err);
         throwSocketException(env, err);
         return 0;
     }
 
     if (packet != NULL) {
-        int port = ntohs(sockAddr.sin_port);
-        jbyteArray addr = env->NewByteArray(sizeof(struct in_addr));
-        if ((structInToJavaAddress(env, &sockAddr.sin_addr, addr)) < 0) {
-            jniThrowException(env, "java/net/SocketException",
-                    "Could not set address of packet.");
+        jbyteArray addr = socketAddressToByteArray(env, &sockAddr);
+        if (addr == NULL)  // Exception has already been thrown.
             return 0;
-        }
+        int port = getSocketAddressPort(&sockAddr);
         jobject sender = env->CallStaticObjectMethod(
                 gCachedFields.iaddr_class, gCachedFields.iaddr_getbyaddress,
                 addr);
         env->SetObjectField(packet, gCachedFields.dpack_address, sender);
         env->SetIntField(packet, gCachedFields.dpack_port, port);
-        env->SetIntField(packet, gCachedFields.dpack_length, actualLength);
+        env->SetIntField(packet, gCachedFields.dpack_length,
+                (jint) actualLength);
     }
-    add_recv_stats(handle, actualLength);
-    return actualLength;
+    return (jint) actualLength;
 }
 
 static jint osNetworkSystem_receiveDatagramImpl(JNIEnv* env, jclass clazz,
@@ -2256,7 +2494,7 @@
     }
 
     int actualLength = osNetworkSystem_receiveDatagramDirectImpl(env, clazz, fd,
-            packet, (jint)bytes, offset, localLength, receiveTimeout, peek);
+            packet, (jint)bytes, 0, localLength, receiveTimeout, peek);
 
     if (actualLength > 0) {
         env->SetByteArrayRegion(data, offset, actualLength, bytes);
@@ -2297,7 +2535,6 @@
     if ( packet != NULL) {
         env->SetIntField(packet, gCachedFields.dpack_length, actualLength);
     }
-    add_recv_stats(handle, actualLength);
     return actualLength;
 }
 
@@ -2315,7 +2552,7 @@
     }
 
     int actualLength = osNetworkSystem_recvConnectedDatagramDirectImpl(env,
-            clazz, fd, packet, (jint)bytes, offset, localLength,
+            clazz, fd, packet, (jint)bytes, 0, localLength,
             receiveTimeout, peek);
 
     if (actualLength > 0) {
@@ -2331,8 +2568,6 @@
         jboolean bindToDevice, jint trafficClass, jobject inetAddress) {
     // LOGD("ENTER sendDatagramDirectImpl");
 
-    int result = 0;
-
     int handle = jniGetFDFromFileDescriptor(env, fd);
 
     if (handle == 0 || handle == -1) {
@@ -2340,29 +2575,28 @@
         return 0;
     }
 
-    struct sockaddr_in receiver;
-
+    struct sockaddr_storage receiver;
     if (inetAddressToSocketAddress(env, inetAddress, port, &receiver) < 0) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
+        // Exception has already been thrown.
         return 0;
     }
 
-    result = sendto(handle, (char*)(address + offset), length, SOCKET_NOFLAGS,
-            (struct sockaddr*)&receiver, sizeof(receiver));
-
+    ssize_t result = 0;
+    do {
+        result = sendto(handle, (char*)(address + offset), length,
+                SOCKET_NOFLAGS, (struct sockaddr*)&receiver, sizeof(receiver));
+    } while (result < 0 && errno == EINTR);
     if (result < 0) {
         int err = convertError(errno);
         if ((SOCKERR_CONNRESET == err)
                 || (SOCKERR_CONNECTION_REFUSED == err)) {
             return 0;
         } else {
-            log_socket_close(handle, err);
             throwSocketException(env, err);
             return 0;
         }
     }
-    add_send_stats(handle, result);
-    return result;
+    return (jint) result;
 }
 
 static jint osNetworkSystem_sendDatagramImpl(JNIEnv* env, jclass clazz,
@@ -2398,12 +2632,10 @@
         if ((SOCKERR_CONNRESET == err) || (SOCKERR_CONNECTION_REFUSED == err)) {
             return 0;
         } else {
-            log_socket_close(handle, err);
             throwSocketException(env, err);
             return 0;
         }
     }
-    add_send_stats(handle, length);
     return result;
 }
 
@@ -2424,43 +2656,11 @@
         jclass clazz, jobject fileDescriptor, jboolean preferIPv4Stack) {
     // LOGD("ENTER createServerStreamSocketImpl");
 
-    if (fileDescriptor == NULL) {
-        throwNullPointerException(env);
+    int handle = createSocketFileDescriptor(env, fileDescriptor, SOCK_STREAM);
+    if (handle < 0)
         return;
-    }
-
-    int handle = socket(PF_INET, SOCK_STREAM, 0);
-
-    if (handle < 0) {
-        int err = convertError(errno);
-        throwSocketException(env, err);
-        return;
-    }
-
-    jniSetFileDescriptorOfFD(env, fileDescriptor, handle);
 
     int value = 1;
-
-    setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int));
-}
-
-static void osNetworkSystem_createMulticastSocketImpl(JNIEnv* env,
-        jclass clazz, jobject fileDescriptor, jboolean preferIPv4Stack) {
-    // LOGD("ENTER createMulticastSocketImpl");
-
-    int handle = socket(PF_INET, SOCK_DGRAM, 0);
-
-    if (handle < 0) {
-        int err = convertError(errno);
-        throwSocketException(env, err);
-        return;
-    }
-
-    jniSetFileDescriptorOfFD(env, fileDescriptor, handle);
-
-    int value = 1;
-
-    // setsockopt(handle, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(jbyte));
     setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int));
 }
 
@@ -2505,7 +2705,6 @@
      * to the Java input stream
      */
     if (0 < result) {
-        add_recv_stats(handle, result);
         return result;
     } else if (0 == result) {
         return -1;
@@ -2516,7 +2715,6 @@
                               netLookupErrorString(SOCKERR_TIMEOUT));
         } else {
             int err = convertError(errno);
-            log_socket_close(handle, err);
             throwSocketException(env, err);
         }
         return 0;
@@ -2560,7 +2758,6 @@
             }
             env->ReleaseByteArrayElements(data, message, 0);
             int err = convertError(result);
-            log_socket_close(handle, err);
             throwSocketException(env, err);
             return 0;
         }
@@ -2568,7 +2765,6 @@
     }
 
     env->ReleaseByteArrayElements(data, message, 0);
-    add_send_stats(handle, sent);
     return sent;
 }
 
@@ -2590,7 +2786,6 @@
 
     if (ret < 0) {
         int err = convertError(errno);
-        log_socket_close(handle, err);
         throwSocketException(env, err);
         return;
     }
@@ -2613,7 +2808,6 @@
 
     if (ret < 0) {
         int err = convertError(errno);
-        log_socket_close(handle, err);
         throwSocketException(env, err);
         return;
     }
@@ -2625,26 +2819,19 @@
     // LOGD("ENTER sendDatagramImpl2");
 
     jbyte *message;
-    jbyte nhostAddrBytes[4];
     unsigned short nPort;
-    int result = 0, sent = 0;
+    int ret = 0, sent = 0;
     int handle = 0;
-    struct sockaddr_in sockaddrP;
+    struct sockaddr_storage sockaddrP;
 
     if (inetAddress != NULL) {
-
-        result = inetAddressToSocketAddress(env, inetAddress, port,
-                (struct sockaddr_in *) &sockaddrP);
-
-        if (result < 0) {
-            throwSocketException(env, SOCKERR_BADSOCKET);
+        ret = inetAddressToSocketAddress(env, inetAddress, port, &sockaddrP);
+        if (ret < 0)  // Exception has already been thrown.
             return 0;
-        }
 
         handle = jniGetFDFromFileDescriptor(env, fd);
-
         if (handle == 0 || handle == -1) {
-            throwSocketException(env, SOCKERR_BADSOCKET);
+            throwSocketException(env, SOCKERR_BADDESC);
             return 0;
         }
     }
@@ -2663,18 +2850,19 @@
 
         if (handle == 0 || handle == -1) {
             throwSocketException(env,
-                    sent == 0 ? SOCKERR_BADSOCKET : SOCKERR_INTERRUPTED);
+                    sent == 0 ? SOCKERR_BADDESC : SOCKERR_INTERRUPTED);
             free(message);
             return 0;
         }
 
-        result = sendto(handle, (char *) (message + sent),
-                (int) (length - sent), SOCKET_NOFLAGS,
-                (struct sockaddr *) &sockaddrP, sizeof(sockaddrP));
-
+        ssize_t result;
+        do {
+            result = sendto(handle, (char *) (message + sent),
+                    (int) (length - sent), SOCKET_NOFLAGS,
+                    (struct sockaddr *) &sockaddrP, sizeof(sockaddrP));
+        } while (result < 0 && errno == EINTR);
         if (result < 0) {
             int err = convertError(errno);
-            log_socket_close(handle, err);
             throwSocketException(env, err);
             free(message);
             return 0;
@@ -2684,7 +2872,6 @@
     }
 
     free(message);
-    add_send_stats(handle, sent);
     return sent;
 }
 
@@ -2757,10 +2944,10 @@
     }
 
     if (0 < result) {
-       /*output the result to a int array*/
-       flagArray = env->GetIntArrayElements(outFlags, &isCopy);
+        /*output the result to a int array*/
+        flagArray = env->GetIntArrayElements(outFlags, &isCopy);
 
-       for (val=0; val<countReadC; val++) {
+        for (val=0; val<countReadC; val++) {
             gotFD = env->GetObjectArrayElement(readFDArray,val);
 
             handle = jniGetFDFromFileDescriptor(env, gotFD);
@@ -2799,33 +2986,30 @@
         jclass clazz, jobject fileDescriptor, jboolean preferIPv6Addresses) {
     // LOGD("ENTER getSocketLocalAddressImpl");
 
-    struct sockaddr_in addr;
+    struct sockaddr_storage addr;
     socklen_t addrLen = sizeof(addr);
 
     memset(&addr, 0, addrLen);
 
+
     int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
-    int result;
-
     if (handle == 0 || handle == -1) {
         throwSocketException(env, SOCKERR_UNKNOWNSOCKET);
         return NULL;
     }
 
+    int result;
     result = getsockname(handle, (struct sockaddr *)&addr, &addrLen);
 
     // Spec says ignore all errors
-
-    return structInToInetAddress(env, &(addr.sin_addr));
-
+    return socketAddressToInetAddress(env, &addr);
 }
 
 static jint osNetworkSystem_getSocketLocalPortImpl(JNIEnv* env, jclass clazz,
         jobject fileDescriptor, jboolean preferIPv6Addresses) {
     // LOGD("ENTER getSocketLocalPortImpl");
 
-    struct sockaddr_in addr;
+    struct sockaddr_storage addr;
     socklen_t addrLen = sizeof(addr);
 
     int handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
@@ -2842,7 +3026,7 @@
         // The java spec does not indicate any exceptions on this call
         return 0;
     } else {
-        return ntohs(addr.sin_port);
+        return getSocketAddressPort(&addr);
     }
 }
 
@@ -2856,12 +3040,12 @@
     unsigned char byteValue = 0;
     socklen_t byteSize = sizeof(unsigned char);
     int result;
-    struct sockaddr_in sockVal;
+    struct sockaddr_storage sockVal;
     socklen_t sockSize = sizeof(sockVal);
 
     handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
     if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
+        throwSocketException(env, SOCKERR_BADDESC);
         return NULL;
     }
 
@@ -2896,23 +3080,61 @@
             if ((anOption >> 16) & BROKEN_MULTICAST_TTL) {
                 return newJavaLangByte(env, 0);
             }
-            result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_TTL, &byteValue, &byteSize);
+            // Java uses a byte to store the TTL, but the kernel uses an int.
+            result = getOrSetSocketOption(SOCKOPT_GET, handle, IP_MULTICAST_TTL,
+                                          IPV6_MULTICAST_HOPS, &intValue,
+                                          &intSize);
             if (0 != result) {
                 throwSocketException(env, convertError(errno));
                 return NULL;
             }
-            return newJavaLangByte(env, (jbyte)(byteValue & 0xFF));
+            return newJavaLangByte(env, (jbyte)(intValue & 0xFF));
         }
         case JAVASOCKOPT_MCAST_INTERFACE: {
             if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
                 return NULL;
             }
-            result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF, &sockVal, &sockSize);
+            result = getsockopt(handle, SOL_IP, IP_MULTICAST_IF, &sockVal, &sockSize);
             if (0 != result) {
                 throwSocketException(env, convertError(errno));
                 return NULL;
             }
-            return structInToInetAddress(env, &(sockVal.sin_addr));
+            // This option is IPv4-only.
+            sockVal.ss_family = AF_INET;
+            return socketAddressToInetAddress(env, &sockVal);
+        }
+        case JAVASOCKOPT_IP_MULTICAST_IF2: {
+            if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
+                return NULL;
+            }
+            struct ip_mreqn multicastRequest;
+            int interfaceIndex;
+            socklen_t optionLength;
+            int addressFamily = getSocketAddressFamily(handle);
+            switch (addressFamily) {
+                case AF_INET:
+                    optionLength = sizeof(multicastRequest);
+                    result = getsockopt(handle, SOL_IP, IP_MULTICAST_IF,
+                                        &multicastRequest, &optionLength);
+                    if (result == 0)
+                        interfaceIndex = multicastRequest.imr_ifindex;
+                    break;
+                case AF_INET6:
+                    optionLength = sizeof(interfaceIndex);
+                    result = getsockopt(handle, SOL_IPV6, IPV6_MULTICAST_IF,
+                                        &interfaceIndex, &optionLength);
+                    break;
+                default:
+                    throwSocketException(env, SOCKERR_BADAF);
+                    return NULL;
+            }
+
+            if (0 != result) {
+                throwSocketException(env, convertError(errno));
+                return NULL;
+            }
+
+            return newJavaLangInteger(env, interfaceIndex);
         }
         case JAVASOCKOPT_SO_SNDBUF: {
             result = getsockopt(handle, SOL_SOCKET, SO_SNDBUF, &intValue, &intSize);
@@ -2963,7 +3185,10 @@
             return newJavaLangBoolean(env, intValue);
         }
         case JAVASOCKOPT_IP_MULTICAST_LOOP: {
-            result = getsockopt(handle, IPPROTO_IP, IP_MULTICAST_LOOP, &intValue, &intSize);
+            result = getOrSetSocketOption(SOCKOPT_GET, handle,
+                                          IP_MULTICAST_LOOP,
+                                          IPV6_MULTICAST_LOOP, &intValue,
+                                          &intSize);
             if (0 != result) {
                 throwSocketException(env, convertError(errno));
                 return NULL;
@@ -2971,7 +3196,8 @@
             return newJavaLangBoolean(env, intValue);
         }
         case JAVASOCKOPT_IP_TOS: {
-            result = getsockopt(handle, IPPROTO_IP, IP_TOS, &intValue, &intSize);
+            result = getOrSetSocketOption(SOCKOPT_GET, handle, IP_TOS,
+                                          IPV6_TCLASS, &intValue, &intSize);
             if (0 != result) {
                 throwSocketException(env, convertError(errno));
                 return NULL;
@@ -3001,9 +3227,11 @@
     // LOGD("ENTER setSocketOptionImpl");
 
     int handle, result;
-    int intVal, intSize = sizeof(int);
-    unsigned char byteVal, byteSize = sizeof(unsigned char);
-    struct sockaddr_in sockVal;
+    int intVal;
+    socklen_t intSize = sizeof(int);
+    unsigned char byteVal;
+    socklen_t byteSize = sizeof(unsigned char);
+    struct sockaddr_storage sockVal;
     int sockSize = sizeof(sockVal);
 
     if (env->IsInstanceOf(optVal, gCachedFields.integer_class)) {
@@ -3014,7 +3242,7 @@
         byteVal = (int) env->GetByteField(optVal, gCachedFields.byte_class_value);
     } else if (env->IsInstanceOf(optVal, gCachedFields.iaddr_class)) {
         if (inetAddressToSocketAddress(env, optVal, 0, &sockVal) < 0) {
-            throwSocketException(env, SOCKERR_BADSOCKET);
+            // Exception has already been thrown.
             return;
         }
     } else if (env->IsInstanceOf(optVal, gCachedFields.genericipmreq_class)) {
@@ -3026,7 +3254,7 @@
 
     handle = jniGetFDFromFileDescriptor(env, fileDescriptor);
     if (handle == 0 || handle == -1) {
-        throwSocketException(env, SOCKERR_BADSOCKET);
+        throwSocketException(env, SOCKERR_BADDESC);
         return;
     }
 
@@ -3056,11 +3284,15 @@
             break;
         }
 
-      case JAVASOCKOPT_MCAST_TTL: {
+        case JAVASOCKOPT_MCAST_TTL: {
             if ((anOption >> 16) & BROKEN_MULTICAST_TTL) {
                 return;
             }
-            result = setsockopt(handle, IPPROTO_IP, IP_MULTICAST_TTL, &byteVal, byteSize);
+            // Java uses a byte to store the TTL, but the kernel uses an int.
+            intVal = byteVal;
+            result = getOrSetSocketOption(SOCKOPT_SET, handle, IP_MULTICAST_TTL,
+                                          IPV6_MULTICAST_HOPS, &intVal,
+                                          &intSize);
             if (0 != result) {
                 throwSocketException(env, convertError(errno));
                 return;
@@ -3071,24 +3303,30 @@
         case JAVASOCKOPT_MCAST_ADD_MEMBERSHIP: {
             mcastAddDropMembership(env, handle, optVal,
                     (anOption >> 16) & BROKEN_MULTICAST_IF, IP_ADD_MEMBERSHIP);
-            return;
+            break;
         }
 
         case JAVASOCKOPT_MCAST_DROP_MEMBERSHIP: {
             mcastAddDropMembership(env, handle, optVal,
                     (anOption >> 16) & BROKEN_MULTICAST_IF, IP_DROP_MEMBERSHIP);
-            return;
+            break;
         }
 
         case JAVASOCKOPT_MCAST_INTERFACE: {
             if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
                 return;
             }
+            // This call is IPv4 only. The socket may be IPv6, but the address
+            // that identifies the interface to join must be an IPv4 address.
+            if (sockVal.ss_family != AF_INET) {
+                throwSocketException(env, SOCKERR_BADAF);
+                return;
+            }
             struct ip_mreqn mcast_req;
             memset(&mcast_req, 0, sizeof(mcast_req));
-            memcpy(&(mcast_req.imr_address), &(sockVal.sin_addr),
-                   sizeof(struct in_addr));
-            result = setsockopt(handle, IPPROTO_IP, IP_MULTICAST_IF,
+            struct sockaddr_in *sin = (struct sockaddr_in *) &sockVal;
+            mcast_req.imr_address = sin->sin_addr;
+            result = setsockopt(handle, SOL_IP, IP_MULTICAST_IF,
                                 &mcast_req, sizeof(mcast_req));
             if (0 != result) {
                 throwSocketException(env, convertError(errno));
@@ -3097,6 +3335,42 @@
             break;
         }
 
+        case JAVASOCKOPT_IP_MULTICAST_IF2: {
+            if ((anOption >> 16) & BROKEN_MULTICAST_IF) {
+                return;
+            }
+            int addressFamily = getSocketAddressFamily(handle);
+            int interfaceIndex = intVal;
+            void *optionValue;
+            socklen_t optionLength;
+            struct ip_mreqn multicastRequest;
+            switch (addressFamily) {
+                case AF_INET:
+                    // IP_MULTICAST_IF expects a pointer to a struct ip_mreqn.
+                    memset(&multicastRequest, 0, sizeof(multicastRequest));
+                    multicastRequest.imr_ifindex = interfaceIndex;
+                    optionValue = &multicastRequest;
+                    optionLength = sizeof(multicastRequest);
+                    break;
+                case AF_INET6:
+                    // IPV6_MULTICAST_IF expects a pointer to an integer.
+                    optionValue = &interfaceIndex;
+                    optionLength = sizeof(interfaceIndex);
+                    break;
+                default:
+                    throwSocketException(env, SOCKERR_BADAF);
+                    return;
+            }
+            result = getOrSetSocketOption(SOCKOPT_SET, handle,
+                    IP_MULTICAST_IF, IPV6_MULTICAST_IF, optionValue,
+                    &optionLength);
+            if (0 != result) {
+                throwSocketException(env, convertError(errno));
+                return;
+            }
+            break;
+        }
+
         case JAVASOCKOPT_SO_SNDBUF: {
             result = setsockopt(handle, SOL_SOCKET, SO_SNDBUF, &intVal, intSize);
             if (0 != result) {
@@ -3151,7 +3425,10 @@
         }
 
         case JAVASOCKOPT_IP_MULTICAST_LOOP: {
-            result = setsockopt(handle, IPPROTO_IP, IP_MULTICAST_LOOP, &intVal, intSize);
+            result = getOrSetSocketOption(SOCKOPT_SET, handle,
+                                          IP_MULTICAST_LOOP,
+                                          IPV6_MULTICAST_LOOP, &intVal,
+                                          &intSize);
             if (0 != result) {
                 throwSocketException(env, convertError(errno));
                 return;
@@ -3160,7 +3437,8 @@
         }
 
         case JAVASOCKOPT_IP_TOS: {
-            result = setsockopt(handle, IPPROTO_IP, IP_TOS, &intVal, intSize);
+            result = getOrSetSocketOption(SOCKOPT_SET, handle, IP_TOS,
+                                          IPV6_TCLASS, &intVal, &intSize);
             if (0 != result) {
                 throwSocketException(env, convertError(errno));
                 return;
@@ -3215,95 +3493,11 @@
         return;
     }
 
-    log_socket_close(handle, SOCKET_CLOSE_LOCAL);
-
     jniSetFileDescriptorOfFD(env, fileDescriptor, -1);
 
     close(handle);
 }
 
-static jobject osNetworkSystem_getHostByAddrImpl(JNIEnv* env, jclass clazz,
-        jbyteArray addrStr) {
-    // LOGD("ENTER getHostByAddrImpl");
-
-    if (addrStr == NULL) {
-        throwNullPointerException(env);
-        return JNI_FALSE;
-    }
-
-    jstring address = (jstring)newJavaLangString(env, addrStr);
-    jstring result;
-    const char* addr = env->GetStringUTFChars(address, NULL);
-
-    struct hostent* ent = gethostbyaddr(addr, strlen(addr), AF_INET);
-
-    if (ent != NULL  && ent->h_name != NULL) {
-        result = env->NewStringUTF(ent->h_name);
-    } else {
-        result = NULL;
-    }
-
-    env->ReleaseStringUTFChars(address, addr);
-
-    return result;
-}
-
-static jobject osNetworkSystem_getHostByNameImpl(JNIEnv* env, jclass clazz,
-        jstring nameStr, jboolean preferIPv6Addresses) {
-    // LOGD("ENTER getHostByNameImpl");
-
-    if (nameStr == NULL) {
-        throwNullPointerException(env);
-        return NULL;
-    }
-
-    const char* name = env->GetStringUTFChars(nameStr, NULL);
-
-    if (useAdbNetworking) {
-
-        union {
-            struct in_addr a;
-            jbyte j[4];
-        } outaddr;
-
-        // LOGD("ADB networking: +gethostbyname '%s'", name);
-        int err;
-        err = adb_networking_gethostbyname(name, &(outaddr.a));
-
-        env->ReleaseStringUTFChars(nameStr, name);
-#if 0
-        LOGD("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 (err < 0) {
-            return NULL;
-        } else {
-            jbyteArray addr = env->NewByteArray(4);
-            env->SetByteArrayRegion(addr, 0, 4, outaddr.j);
-            return addr;
-        }
-    } else {
-
-        // normal case...no adb networking
-        struct hostent* ent = gethostbyname(name);
-
-        env->ReleaseStringUTFChars(nameStr, name);
-
-        if (ent != NULL  && ent->h_length > 0) {
-            jbyteArray addr = env->NewByteArray(4);
-            jbyte v[4];
-            memcpy(v, ent->h_addr, 4);
-            env->SetByteArrayRegion(addr, 0, 4, v);
-            return addr;
-        } else {
-            return NULL;
-        }
-    }
-}
-
 static void osNetworkSystem_setInetAddressImpl(JNIEnv* env, jobject obj,
         jobject sender, jbyteArray address) {
     // LOGD("ENTER setInetAddressImpl");
@@ -3311,6 +3505,7 @@
     env->SetObjectField(sender, gCachedFields.iaddr_ipaddress, address);
 }
 
+// TODO: rewrite this method in Java and make it support IPv6.
 static jobject osNetworkSystem_inheritedChannelImpl(JNIEnv* env, jobject obj) {
     // LOGD("ENTER inheritedChannelImpl");
 
@@ -3402,8 +3597,10 @@
                     ntohs(local_addr.sin_port));
 
             // new and set remote addr
-            addr_object = env->NewObject(gCachedFields.iaddr_class,
-                    gCachedFields.iaddr_class_init);
+            addr_array = env->NewByteArray((jsize)4);
+            env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, address);
+            addr_object = env->NewObject(gCachedFields.i4addr_class,
+                    gCachedFields.i4addr_class_init, addr_array);
             if (NULL == addr_object) {
                 goto clean;
             }
@@ -3415,13 +3612,6 @@
             if (NULL == socketaddr_object) {
                 goto clean;
             }
-            addr_field = env->GetFieldID(socketaddr_class, "addr",
-                    "Ljava/net/InetAddress;");
-            env->SetObjectField(socketaddr_object, addr_field, addr_object);
-            addr_array = env->NewByteArray((jsize)4);
-            env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, address);
-            env->SetObjectField(addr_object, gCachedFields.iaddr_ipaddress,
-                     addr_array);
 
             // localAddr
             socketaddr_class = env->FindClass("java/net/InetSocketAddress");
@@ -3431,9 +3621,11 @@
                      socketaddr_field);
 
             localAddr_field = env->GetFieldID(channel_class, "localAddress",
-                     "Ljava/net/InetAddress;");
-            localAddr_object = env->NewObject(gCachedFields.iaddr_class,
-                     gCachedFields.iaddr_class_init);
+                     "Ljava/net/Inet4Address;");
+            addr_array = env->NewByteArray((jsize)4);
+            env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, localAddr);
+            localAddr_object = env->NewObject(gCachedFields.i4addr_class,
+                     gCachedFields.i4addr_class_init, addr_array);
             jfieldID socketaddr_field = env->GetFieldID(channel_class,
                      "connectAddress", "Ljava/net/InetSocketAddress;");
             jobject socketaddr_object = env->GetObjectField(channel_object,
@@ -3443,10 +3635,6 @@
             if (NULL == localAddr_object) {
                 goto clean;
             }
-            addr_array = env->NewByteArray((jsize)4);
-            env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, localAddr);
-            env->SetObjectField(localAddr_object, gCachedFields.iaddr_ipaddress,
-                    addr_array);
 
 
             // set port
@@ -3499,10 +3687,13 @@
                  goto clean;
             }
 
+            addr_array = env->NewByteArray((jsize)4);
             localAddr_field = env->GetFieldID(channel_class, "localAddress",
                     "Ljava/net/InetAddress;");
-            localAddr_object = env->NewObject(gCachedFields.iaddr_class,
-                    gCachedFields.iaddr_class_init);
+            memset(address, 0, 4);
+            env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, address);
+            localAddr_object = env->NewObject(gCachedFields.i4addr_class,
+                    gCachedFields.i4addr_class_init, addr_array);
             if (NULL == localAddr_object) {
                  goto clean;
             }
@@ -3549,8 +3740,10 @@
         env->SetIntField(channel_object, port_field, ntohs(local_addr.sin_port));
 
         // new and set remote addr
+        addr_array = env->NewByteArray((jsize)4);
+        env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, address);
         addr_object = env->NewObject(gCachedFields.iaddr_class,
-                gCachedFields.iaddr_class_init);
+                gCachedFields.i4addr_class_init, addr_array);
         if (NULL == addr_object) {
             goto clean;
         }
@@ -3561,12 +3754,6 @@
         if (NULL == socketaddr_object) {
             goto clean;
         }
-        addr_field = env->GetFieldID(socketaddr_class, "addr",
-                "Ljava/net/InetAddress;");
-        env->SetObjectField(socketaddr_object, addr_field, addr_object);
-        addr_array = env->NewByteArray((jsize)4);
-        env->SetByteArrayRegion(addr_array, (jsize)0, (jsize)4, address);
-        env->SetObjectField(addr_object, gCachedFields.iaddr_ipaddress, addr_array);
 
         // set bound
         if (0 != local_addr.sin_port) {
@@ -3586,7 +3773,7 @@
 static JNINativeMethod gMethods[] = {
     /* name, signature, funcPtr */
     { "oneTimeInitializationImpl",         "(Z)V",                                                                     (void*) osNetworkSystem_oneTimeInitializationImpl          },
-    { "createSocketImpl",                  "(Ljava/io/FileDescriptor;Z)V",                                             (void*) osNetworkSystem_createSocketImpl                   },
+    { "createStreamSocketImpl",            "(Ljava/io/FileDescriptor;Z)V",                                             (void*) osNetworkSystem_createStreamSocketImpl             },
     { "createDatagramSocketImpl",          "(Ljava/io/FileDescriptor;Z)V",                                             (void*) osNetworkSystem_createDatagramSocketImpl           },
     { "readSocketImpl",                    "(Ljava/io/FileDescriptor;[BIII)I",                                         (void*) osNetworkSystem_readSocketImpl                     },
     { "readSocketDirectImpl",              "(Ljava/io/FileDescriptor;IIII)I",                                          (void*) osNetworkSystem_readSocketDirectImpl               },
@@ -3604,7 +3791,6 @@
     { "sendUrgentDataImpl",                "(Ljava/io/FileDescriptor;B)V",                                             (void*) osNetworkSystem_sendUrgentDataImpl                 },
     { "connectDatagramImpl2",              "(Ljava/io/FileDescriptor;IILjava/net/InetAddress;)V",                      (void*) osNetworkSystem_connectDatagramImpl2               },
     { "disconnectDatagramImpl",            "(Ljava/io/FileDescriptor;)V",                                              (void*) osNetworkSystem_disconnectDatagramImpl             },
-    { "socketBindImpl2",                   "(Ljava/io/FileDescriptor;IZLjava/net/InetAddress;)Z",                      (void*) osNetworkSystem_socketBindImpl2                    },
     { "peekDatagramImpl",                  "(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)I",                       (void*) osNetworkSystem_peekDatagramImpl                   },
     { "receiveDatagramImpl",               "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;[BIIIZ)I",               (void*) osNetworkSystem_receiveDatagramImpl                },
     { "receiveDatagramDirectImpl",         "(Ljava/io/FileDescriptor;Ljava/net/DatagramPacket;IIIIZ)I",                (void*) osNetworkSystem_receiveDatagramDirectImpl          },
@@ -3615,7 +3801,6 @@
     { "sendConnectedDatagramImpl",         "(Ljava/io/FileDescriptor;[BIIZ)I",                                         (void*) osNetworkSystem_sendConnectedDatagramImpl          },
     { "sendConnectedDatagramDirectImpl",   "(Ljava/io/FileDescriptor;IIIZ)I",                                          (void*) osNetworkSystem_sendConnectedDatagramDirectImpl    },
     { "createServerStreamSocketImpl",      "(Ljava/io/FileDescriptor;Z)V",                                             (void*) osNetworkSystem_createServerStreamSocketImpl       },
-    { "createMulticastSocketImpl",         "(Ljava/io/FileDescriptor;Z)V",                                             (void*) osNetworkSystem_createMulticastSocketImpl          },
     { "receiveStreamImpl",                 "(Ljava/io/FileDescriptor;[BIII)I",                                         (void*) osNetworkSystem_receiveStreamImpl                  },
     { "sendStreamImpl",                    "(Ljava/io/FileDescriptor;[BII)I",                                          (void*) osNetworkSystem_sendStreamImpl                     },
     { "shutdownInputImpl",                 "(Ljava/io/FileDescriptor;)V",                                              (void*) osNetworkSystem_shutdownInputImpl                  },
@@ -3628,10 +3813,10 @@
     { "setSocketOptionImpl",               "(Ljava/io/FileDescriptor;ILjava/lang/Object;)V",                           (void*) osNetworkSystem_setSocketOptionImpl                },
     { "getSocketFlagsImpl",                "()I",                                                                      (void*) osNetworkSystem_getSocketFlagsImpl                 },
     { "socketCloseImpl",                   "(Ljava/io/FileDescriptor;)V",                                              (void*) osNetworkSystem_socketCloseImpl                    },
-    { "getHostByAddrImpl",                 "([B)Ljava/net/InetAddress;",                                               (void*) osNetworkSystem_getHostByAddrImpl                  },
-    { "getHostByNameImpl",                 "(Ljava/lang/String;Z)Ljava/net/InetAddress;",                              (void*) osNetworkSystem_getHostByNameImpl                  },
     { "setInetAddressImpl",                "(Ljava/net/InetAddress;[B)V",                                              (void*) osNetworkSystem_setInetAddressImpl                 },
     { "inheritedChannelImpl",              "()Ljava/nio/channels/Channel;",                                            (void*) osNetworkSystem_inheritedChannelImpl               },
+    { "byteArrayToIpString",               "([B)Ljava/lang/String;",                                                   (void*) osNetworkSystem_byteArrayToIpString                },
+    { "ipStringToByteArray",               "(Ljava/lang/String;)[B",                                                   (void*) osNetworkSystem_ipStringToByteArray                },
 };
 
 int register_org_apache_harmony_luni_platform_OSNetworkSystem(JNIEnv* env) {
@@ -3640,3 +3825,4 @@
             gMethods,
             NELEM(gMethods));
 }
+// END android-changed
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 d8a1e68..e92b776 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
@@ -22,7 +22,7 @@
 #include "commonDblParce.h"
 #include "cbigint.h"
 
-#if defined(LINUX)
+#if defined(LINUX) || defined(FREEBSD) || defined(ZOS)
 #define USE_LL
 #endif
 
diff --git a/libcore/luni/src/test/java/com/google/coretests/CoreTestResult.java b/libcore/luni/src/test/java/com/google/coretests/CoreTestResult.java
index 9a821cd..802eff8 100644
--- a/libcore/luni/src/test/java/com/google/coretests/CoreTestResult.java
+++ b/libcore/luni/src/test/java/com/google/coretests/CoreTestResult.java
@@ -131,6 +131,7 @@
                         // Ignored
                     }
                     if (thread.isAlive()) {
+                        StackTraceElement[] trace = thread.getStackTrace();
                         runnable.stop();
                         thread.stop();
                         try {
@@ -138,8 +139,10 @@
                         } catch (InterruptedException ex) {
                             // Ignored
                         }
-        
-                        addError(test, new CoreTestTimeout("Test timed out"));
+
+                        CoreTestTimeout timeout = new CoreTestTimeout("Test timed out");
+                        timeout.setStackTrace(trace);
+                        addError(test, timeout);
                     }
                 } else {
                     runnable.run();
diff --git a/libcore/luni/src/test/java/com/google/coretests/CoreTestRunnable.java b/libcore/luni/src/test/java/com/google/coretests/CoreTestRunnable.java
index ab49e47..ed7797e 100644
--- a/libcore/luni/src/test/java/com/google/coretests/CoreTestRunnable.java
+++ b/libcore/luni/src/test/java/com/google/coretests/CoreTestRunnable.java
@@ -137,18 +137,18 @@
         Throwable throwable = null;
         
         File file = File.createTempFile("isolation", ".tmp");
-        
-        fProcess = Runtime.getRuntime().exec(
-                (IS_DALVIK ? "dalvikvm" : "java") +
+
+        String program = (IS_DALVIK ? "dalvikvm" : "java") +
                 " -classpath " + System.getProperty("java.class.path") +
                 " -Djava.home=" + System.getProperty("java.home") +
                 " -Duser.home=" + System.getProperty("user.home") +
-                " -Djava.io.tmpdir=" + System.getProperty("user.home") +
+                " -Djava.io.tmpdir=" + System.getProperty("java.io.tmpdir") +
                 " com.google.coretests.CoreTestIsolator" +
                 " " + fTest.getClass().getName() +
                 " " + fTest.getName() +
-                " " + file.getAbsolutePath());
-        
+                " " + file.getAbsolutePath();
+        fProcess = Runtime.getRuntime().exec(program);
+
         int result = fProcess.waitFor();
         
         if (result != TestRunner.SUCCESS_EXIT) {
@@ -158,7 +158,7 @@
                 throwable = (Throwable)ois.readObject();
                 ois.close();
             } catch (Exception ex) {
-                throwable = new RuntimeException("Error isolating test", ex);
+                throwable = new RuntimeException("Error isolating test: " + program, ex);
             }
         }
         
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/platform/AllTests.java b/libcore/luni/src/test/java/org/apache/harmony/luni/platform/AllTests.java
new file mode 100644
index 0000000..be28d419
--- /dev/null
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/platform/AllTests.java
@@ -0,0 +1,36 @@
+/*
+ * 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.luni.platform;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+public class AllTests {
+    public static void run() {
+        TestRunner.main(new String[] { AllTests.class.getName() });
+    }
+    
+    public static final Test suite() {
+        TestSuite suite = tests.TestSuiteFactory.createTestSuite("Tests for org.apache.harmony.luni.platform");
+        
+        suite.addTestSuite(OSMemoryTest.class);
+        
+        return suite;
+    }
+}
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/platform/OSMemoryTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/platform/OSMemoryTest.java
new file mode 100644
index 0000000..a546289
--- /dev/null
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/platform/OSMemoryTest.java
@@ -0,0 +1,164 @@
+/* 
+ * 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.luni.platform;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.AndroidOnly;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests org.apache.harmony.luni.platform.OSMemory (via IMemorySystem).
+ */
+@TestTargetClass(org.apache.harmony.luni.platform.OSMemory.class)
+public class OSMemoryTest extends TestCase {
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "",
+        method = "memset",
+        args = {}
+    )
+    public void testMemset() {
+        IMemorySystem memory = Platform.getMemorySystem();
+        
+        int byteCount = 32;
+        int ptr = memory.malloc(byteCount);
+        try {
+            // Ensure our newly-allocated block isn't zeroed.
+            memory.setByte(ptr, (byte) 1);
+            assertEquals((byte) 1, memory.getByte(ptr));
+            // Check that we can clear memory.
+            memory.memset(ptr, (byte) 0, byteCount);
+            assertBytesEqual((byte) 0, ptr, byteCount);
+            // Check that we can set an arbitrary value.
+            memory.memset(ptr, (byte) 1, byteCount);
+            assertBytesEqual((byte) 1, ptr, byteCount);
+        } finally {
+            memory.free(ptr);
+        }
+    }
+    
+    void assertBytesEqual(byte value, int ptr, int byteCount) {
+        IMemorySystem memory = Platform.getMemorySystem();
+        for (int i = 0; i < byteCount; ++i) {
+            assertEquals(value, memory.getByte(ptr + i));
+        }
+    }
+    
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "",
+        method = "setIntArray",
+        args = {}
+    )
+    public void testSetIntArray() {
+        IMemorySystem memory = Platform.getMemorySystem();
+        
+        int[] values = { 3, 7, 31, 127, 8191, 131071, 524287, 2147483647 };
+        int[] swappedValues = new int[values.length];
+        for (int i = 0; i < values.length; ++i) {
+            swappedValues[i] = swapInt(values[i]);
+        }
+        
+        int scale = ICommonDataTypes.SIZEOF_JINT;
+        int ptr = memory.malloc(scale * values.length);
+        try {
+            // Regular copy. Memset first so we start from a known state.
+            memory.memset(ptr, (byte) 0, scale * values.length);
+            memory.setIntArray(ptr, values, 0, values.length, false);
+            assertIntsEqual(values, ptr);
+            
+            // Swapped copy.
+            memory.memset(ptr, (byte) 0, scale * values.length);
+            memory.setIntArray(ptr, values, 0, values.length, true);
+            assertIntsEqual(swappedValues, ptr);
+            
+            // Swapped copies of slices (to ensure we test non-zero offsets).
+            memory.memset(ptr, (byte) 0, scale * values.length);
+            for (int i = 0; i < values.length; ++i) {
+                memory.setIntArray(ptr + i * scale, values, i, 1, true);
+            }
+            assertIntsEqual(swappedValues, ptr);
+        } finally {
+            memory.free(ptr);
+        }
+    }
+    
+    private void assertIntsEqual(int[] expectedValues, int ptr) {
+        IMemorySystem memory = Platform.getMemorySystem();
+        for (int i = 0; i < expectedValues.length; ++i) {
+            assertEquals(expectedValues[i], memory.getInt(ptr + ICommonDataTypes.SIZEOF_JINT * i));
+        }
+    }
+    
+    private static int swapInt(int n) {
+        return (((n >>  0) & 0xff) << 24) |
+               (((n >>  8) & 0xff) << 16) |
+               (((n >> 16) & 0xff) <<  8) |
+               (((n >> 24) & 0xff) <<  0);
+    }
+    
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "",
+        method = "setShortArray",
+        args = {}
+    )
+    public void testSetShortArray() {
+        IMemorySystem memory = Platform.getMemorySystem();
+        
+        short[] values = { 0x0001, 0x0020, 0x0300, 0x4000 };
+        short[] swappedValues = { 0x0100, 0x2000, 0x0003, 0x0040 };
+        
+        int scale = ICommonDataTypes.SIZEOF_JSHORT;
+        int ptr = memory.malloc(scale * values.length);
+        try {
+            // Regular copy. Memset first so we start from a known state.
+            memory.memset(ptr, (byte) 0, scale * values.length);
+            memory.setShortArray(ptr, values, 0, values.length, false);
+            assertShortsEqual(values, ptr);
+            
+            // Swapped copy.
+            memory.memset(ptr, (byte) 0, scale * values.length);
+            memory.setShortArray(ptr, values, 0, values.length, true);
+            assertShortsEqual(swappedValues, ptr);
+            
+            // Swapped copies of slices (to ensure we test non-zero offsets).
+            memory.memset(ptr, (byte) 0, scale * values.length);
+            for (int i = 0; i < values.length; ++i) {
+                memory.setShortArray(ptr + i * scale, values, i, 1, true);
+            }
+            assertShortsEqual(swappedValues, ptr);
+        } finally {
+            memory.free(ptr);
+        }
+    }
+    
+    private void assertShortsEqual(short[] expectedValues, int ptr) {
+        IMemorySystem memory = Platform.getMemorySystem();
+        for (int i = 0; i < expectedValues.length; ++i) {
+            assertEquals(expectedValues[i], memory.getShort(ptr + ICommonDataTypes.SIZEOF_JSHORT * i));
+        }
+    }
+    
+    private static short swapShort(short n) {
+        return (short) ((((n >>  0) & 0xff) << 8) | (((n >>  8) & 0xff) << 0));
+    }
+}
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/io/AllTests.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/io/AllTests.java
index 778e527..056b521 100644
--- a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/io/AllTests.java
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/io/AllTests.java
@@ -34,6 +34,7 @@
         TestSuite suite = tests.TestSuiteFactory.createTestSuite("Tests for java.io");
 
         suite.addTestSuite(BufferedReaderTest.class);
+        suite.addTestSuite(FileCanonPathCacheTest.class);
         suite.addTestSuite(FilePermissionTest.class);
         suite.addTestSuite(FileTest.class);
         suite.addTestSuite(InputStreamReaderTest.class);
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileCanonPathCacheTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileCanonPathCacheTest.java
new file mode 100644
index 0000000..f2ac7f3
--- /dev/null
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileCanonPathCacheTest.java
@@ -0,0 +1,120 @@
+/*
+ *  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.luni.tests.java.io;
+
+import java.io.File;
+
+import org.apache.harmony.luni.internal.io.FileCanonPathCache;
+
+import junit.framework.TestCase;
+
+public class FileCanonPathCacheTest extends TestCase {
+
+    private static int DEFAULT_TIMEOUT = 600000;
+
+    @Override
+    public void setUp() throws Exception {
+        FileCanonPathCache.clear();
+        FileCanonPathCache.setTimeout(DEFAULT_TIMEOUT);
+    }
+
+    public void testGetSet() throws Exception {
+        File file1 = new File("test/hello~1");
+        assertNull(FileCanonPathCache.get(file1.getAbsolutePath()));
+        FileCanonPathCache.put(file1.getAbsolutePath(), file1
+                .getCanonicalPath());
+        assertEquals(file1.getCanonicalPath(), FileCanonPathCache.get(file1
+                .getAbsolutePath()));
+
+        File file2 = new File("test/world~1");
+        assertNull(FileCanonPathCache.get(file2.getAbsolutePath()));
+        FileCanonPathCache.put(file2.getAbsolutePath(), file2
+                .getCanonicalPath());
+        assertEquals(file2.getCanonicalPath(), FileCanonPathCache.get(file2
+                .getAbsolutePath()));
+
+        assertNull(FileCanonPathCache.get("notexist"));
+    }
+
+    public void testGetTimeout01() throws Exception {
+        FileCanonPathCache.setTimeout(10);
+
+        File file1 = new File("test/hello~1");
+        assertNull(FileCanonPathCache.get(file1.getAbsolutePath()));
+        FileCanonPathCache.put(file1.getAbsolutePath(), file1
+                .getCanonicalPath());
+        Thread.sleep(50);
+        assertNull(FileCanonPathCache.get(file1.getAbsolutePath()));
+    }
+
+    public void testGetTimeout02() throws Exception {
+        FileCanonPathCache.setTimeout(10);
+
+        File file1 = new File("test/hello~1");
+        assertNull(FileCanonPathCache.get(file1.getAbsolutePath()));
+        FileCanonPathCache.put(file1.getAbsolutePath(), file1
+                .getCanonicalPath());
+        File file2 = new File("test/hello~2");
+        assertNull(FileCanonPathCache.get(file2.getAbsolutePath()));
+        FileCanonPathCache.put(file2.getAbsolutePath(), file2
+                .getCanonicalPath());
+        File file3 = new File("test/hello~3");
+        assertNull(FileCanonPathCache.get(file3.getAbsolutePath()));
+        FileCanonPathCache.put(file3.getAbsolutePath(), file3
+                .getCanonicalPath());
+        File file4 = new File("test/hello~4");
+        assertNull(FileCanonPathCache.get(file4.getAbsolutePath()));
+        FileCanonPathCache.put(file4.getAbsolutePath(), file4
+                .getCanonicalPath());
+        File file5 = new File("test/hello~5");
+        assertNull(FileCanonPathCache.get(file5.getAbsolutePath()));
+        FileCanonPathCache.put(file5.getAbsolutePath(), file5
+                .getCanonicalPath());
+
+        Thread.sleep(50);
+
+        assertNull(FileCanonPathCache.get(file1.getAbsolutePath()));
+        assertNull(FileCanonPathCache.get(file2.getAbsolutePath()));
+        assertNull(FileCanonPathCache.get(file3.getAbsolutePath()));
+        assertNull(FileCanonPathCache.get(file4.getAbsolutePath()));
+        assertNull(FileCanonPathCache.get(file5.getAbsolutePath()));
+    }
+
+    public void testCacheFull() throws Exception {
+        int cacheSize = FileCanonPathCache.CACHE_SIZE;
+        File[] files = new File[cacheSize];
+        for (int i = 0; i < cacheSize; ++i) {
+            files[i] = new File("test/world" + i);
+            FileCanonPathCache.put(files[i].getAbsolutePath(), files[i]
+                    .getCanonicalPath());
+        }
+
+        for (int i = cacheSize; i < files.length; ++i) {
+            assertEquals(files[i - cacheSize].getCanonicalPath(),
+                    FileCanonPathCache.get(files[i - cacheSize]
+                            .getAbsolutePath()));
+            files[i] = new File("test/world" + i);
+            FileCanonPathCache.put(files[i].getAbsolutePath(), files[i]
+                    .getCanonicalPath());
+            assertEquals(files[i].getCanonicalPath(), FileCanonPathCache
+                    .get(files[i].getAbsolutePath()));
+            assertNull(FileCanonPathCache.get(files[i - cacheSize]
+                    .getAbsolutePath()));
+        }
+    }
+}
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileTest.java
index ed81162..84cddf2 100644
--- a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileTest.java
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/io/FileTest.java
@@ -45,8 +45,9 @@
         File file = new File(root, "/dir/file");
         assertEquals("Assert 1: wrong path result ", path.getPath(), file
                 .getPath());
-        assertTrue("Assert 1.1: path not absolute ", new File("\\\\\\a\b").isAbsolute());
-        
+        assertFalse("Assert 1.1: path absolute ", new File("\\\\\\a\b").isAbsolute());
+        assertTrue("Assert 1.1: path absolute ", new File("///a/b").isAbsolute());
+
         // Test data used in a few places below
         String dirName = System.getProperty("java.io.tmpdir");
         String fileName = "input.tst";
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassLoaderTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassLoaderTest.java
index 9b5b17e..43a73ed 100644
--- a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassLoaderTest.java
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassLoaderTest.java
@@ -45,6 +45,7 @@
 @TestTargetClass(ClassLoader.class) 
 public class ClassLoaderTest extends TestCase {
     
+    private static final String SYSTEM_RESOURCE_PATH = "META-INF/MANIFEST.MF";
     public static volatile int flag;
 
     @TestTargetNew(
@@ -605,7 +606,7 @@
         // java.lang.ClassLoader.getSystemClassLoader()
         ClassLoader cl = ClassLoader.getSystemClassLoader();
 
-        java.io.InputStream is = cl.getResourceAsStream("classes.dex");
+        java.io.InputStream is = cl.getResourceAsStream(SYSTEM_RESOURCE_PATH);
         assertNotNull("Failed to find resource from system classpath", is);
         try {
             is.close();
@@ -674,8 +675,8 @@
         //assertNotNull("Failed to find resource: " + classResource, 
         //        ClassLoader.getSystemResource(classResource));   
         
-        URL url = getClass().getClassLoader().getSystemResource("classes.dex");
-        assertNotNull("Failed to find resource: classes.dex", url);
+        URL url = getClass().getClassLoader().getSystemResource(SYSTEM_RESOURCE_PATH);
+        assertNotNull(String.format("Failed to find resource: %s", SYSTEM_RESOURCE_PATH), url);
         java.io.InputStream is = url.openStream();
 
         assertTrue("System resource not found", is.available() > 0);
@@ -701,8 +702,8 @@
         //            ClassLoader.getSystemResourceAsStream(classResource));   
 
         java.io.InputStream is = getClass().getClassLoader()
-                .getSystemResourceAsStream("classes.dex");
-        assertNotNull("Failed to find resource: classes.dex", is);
+                .getSystemResourceAsStream(SYSTEM_RESOURCE_PATH);
+        assertNotNull(String.format("Failed to find resource: %s", SYSTEM_RESOURCE_PATH), is);
         
         assertTrue("System resource not found", is.available() > 0);
         
@@ -720,7 +721,7 @@
             + "that is sure to exist.")
     public void test_getSystemResources() {
         
-        String textResource = "classes.dex";
+        String textResource = SYSTEM_RESOURCE_PATH;
         
         try {
             Enumeration<URL> urls = ClassLoader.getSystemResources(textResource);
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassTest.java
index 14ca1ad..2b492b1 100644
--- a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassTest.java
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ClassTest.java
@@ -838,7 +838,6 @@
         args = {}
     )
     public void test_getClassLoader() {
-
         assertEquals(ExtendTestClass.class.getClassLoader(),
                          PublicTestClass.class.getClassLoader());
 
@@ -859,8 +858,8 @@
         System.setSecurityManager(sm);
         try {
             System.class.getClassLoader();
-        } catch (SecurityException e) {
-            fail("SecurityException should not be thrown.");
+            fail("SecurityException should be thrown.");
+        } catch (SecurityException expected) {
         } finally {
             System.setSecurityManager(oldSm);
         }
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/FloatTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/FloatTest.java
index 2b03e5a..b1ad88a 100644
--- a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/FloatTest.java
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/FloatTest.java
@@ -1091,8 +1091,6 @@
             fail("Expected Float.valueOf(null) to throw NPE.");
         } catch (NullPointerException ex) {
             // expected
-        } catch (Exception ex) {
-            fail("Expected Float.valueOf(null) to throw NPE not " + ex.getClass().getName());
         }
 
         try {
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/IntegerTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/IntegerTest.java
index 9151068..ea71009 100644
--- a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/IntegerTest.java
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/IntegerTest.java
@@ -169,6 +169,56 @@
             exception = true;
         }
         assertTrue("Failed to throw exception for 9999999999", exception);
+
+        try {
+            Integer.decode("-");
+            fail("Expected exception for -");
+        } catch (NumberFormatException e) {
+            // Expected
+        }
+
+        try {
+            Integer.decode("0x");
+            fail("Expected exception for 0x");
+        } catch (NumberFormatException e) {
+            // Expected
+        }
+
+        try {
+            Integer.decode("#");
+            fail("Expected exception for #");
+        } catch (NumberFormatException e) {
+            // Expected
+        }
+
+        try {
+            Integer.decode("x123");
+            fail("Expected exception for x123");
+        } catch (NumberFormatException e) {
+            // Expected
+        }
+
+        try {
+            Integer.decode(null);
+            fail("Expected exception for null");
+        } catch (NullPointerException e) {
+            // Expected
+        }
+
+        try {
+            Integer.decode("");
+            fail("Expected exception for empty string");
+        } catch (NumberFormatException ex) {
+            // Expected
+        }
+
+        try {
+            Integer.decode(" ");
+            fail("Expected exception for single space");
+        } catch (NumberFormatException ex) {
+            // Expected
+        }
+
     }
 
     /**
@@ -591,6 +641,15 @@
                 -Integer.MAX_VALUE));
         assertEquals("Returned incorrect octal string", "-2147483648", Integer.toString(
                 Integer.MIN_VALUE));
+        
+        // Test for HARMONY-6068
+        assertEquals("Returned incorrect octal String", "-1000", Integer.toString(-1000));
+        assertEquals("Returned incorrect octal String", "1000", Integer.toString(1000));
+        assertEquals("Returned incorrect octal String", "0", Integer.toString(0));
+        assertEquals("Returned incorrect octal String", "708", Integer.toString(708));
+        assertEquals("Returned incorrect octal String", "-100", Integer.toString(-100));
+        assertEquals("Returned incorrect octal String", "-1000000008", Integer.toString(-1000000008));
+        assertEquals("Returned incorrect octal String", "2000000008", Integer.toString(2000000008));
     }
 
     /**
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/MathTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/MathTest.java
index 02bed3c..330e0b5 100644
--- a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/MathTest.java
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/MathTest.java
@@ -17,9 +17,10 @@
 
 package org.apache.harmony.luni.tests.java.lang;
 
+import dalvik.annotation.KnownFailure;
 import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
 
 @TestTargetClass(Math.class) 
 public class MathTest extends junit.framework.TestCase {
@@ -1103,6 +1104,7 @@
         method = "tanh",
         args = {double.class}
     )
+    @KnownFailure(value = "bug 2139334")
     public void test_tanh_D() {
         // Test for special situations
         assertTrue("Should return NaN", Double.isNaN(Math.tanh(Double.NaN)));
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ObjectTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ObjectTest.java
index e2b72be..758428e 100644
--- a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ObjectTest.java
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ObjectTest.java
@@ -23,6 +23,7 @@
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.BrokenTest;
+import dalvik.annotation.SideEffect;
 
 @TestTargetClass(Object.class) 
 public class ObjectTest extends junit.framework.TestCase {
@@ -79,6 +80,7 @@
         method = "finalize",
         args = {}
     )
+    @SideEffect("Causes OutOfMemoryError to test finalization")
     public void test_finalize() {
         isCalled = false;
         class TestObject extends Object {
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ProcessBuilderTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ProcessBuilderTest.java
index 93561bf..d35f50b 100644
--- a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ProcessBuilderTest.java
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ProcessBuilderTest.java
@@ -228,6 +228,16 @@
         Process process = pb.start();
         InputStream in = process.getInputStream();
         InputStream err = process.getErrorStream();
+
+        while (true) {
+            try {
+                process.waitFor();
+                break;
+            } catch (InterruptedException e) {
+                // Ignored
+            }
+        }
+
         byte[] buf = new byte[1024];
         if (in.available() > 0) {
             assertTrue(in.read(buf) > 0);
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/SecurityManagerTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/SecurityManagerTest.java
index be5aa41..0bd0c1f 100644
--- a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/SecurityManagerTest.java
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/SecurityManagerTest.java
@@ -16,14 +16,11 @@
 
 package org.apache.harmony.luni.tests.java.lang;
 
-import dalvik.annotation.TestTargets;
 import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargetClass;
-
+import dalvik.annotation.TestTargetNew;
 import junit.framework.TestCase;
 
-import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FilePermission;
 import java.io.IOException;
@@ -41,8 +38,6 @@
 import java.security.Security;
 import java.security.SecurityPermission;
 
-import tests.support.Support_Exec;
-
 /**
  * Test case for java.lang.SecurityManager
  */
@@ -230,14 +225,14 @@
             }
             
             try {
-                mutableSM.checkMemberAccess(Object.class, Member.DECLARED);
+                delegateCallToCheckMemberAccess2(Object.class, Member.DECLARED);
                 fail("SecurityException was not thrown.");
             } catch(SecurityException se) {
                 //expected
             }
             
             try {
-                mutableSM.checkMemberAccess(null, Member.PUBLIC);
+                delegateCallToCheckMemberAccess2(null, Member.PUBLIC);
                 fail("NullPointerException was not thrown.");
             } catch(NullPointerException npe) {
                 //expected
@@ -248,6 +243,23 @@
     }
 
     /**
+     * Don't call checkMemberAccess directly, since we're checking our caller
+     * (and not ourselves). This is necessary for unit tests, since JUnit's
+     * TestCase is usually in the boot classpath for dalvik. This delegating
+     * method corresponds to Class.getDeclared*();
+     */
+    private void delegateCallToCheckMemberAccess2(Class<Object> cls, int type) {
+        delegateCallToCheckMemberAccess1(cls, type);
+    }
+
+    /**
+     * This delegating method corresponds to Class.checkMemberAccess().
+     */
+    private void delegateCallToCheckMemberAccess1(Class<Object> cls, int type) {
+        mutableSM.checkMemberAccess(cls, type);
+    }
+
+    /**
      * @tests java.lang.SecurityManager#checkPermission(java.security.Permission)
      */
     @TestTargetNew(
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/StrictMathTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/StrictMathTest.java
index 137676c..c6edeb2 100644
--- a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/StrictMathTest.java
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/StrictMathTest.java
@@ -17,10 +17,11 @@
 
 package org.apache.harmony.luni.tests.java.lang;
 
-import dalvik.annotation.TestTargets;
+import dalvik.annotation.KnownFailure;
 import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
 
 @TestTargetClass(StrictMath.class) 
 public class StrictMathTest extends junit.framework.TestCase {
@@ -1292,6 +1293,7 @@
         method = "tanh",
         args = {double.class}
     )
+    @KnownFailure(value = "bug 2139334")
     public void test_tanh_D() {
         // Test for special situations
         assertTrue(Double.isNaN(StrictMath.tanh(Double.NaN)));
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/StringBuffer2Test.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/StringBuffer2Test.java
index 8b03ced..6bc1939 100644
--- a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/StringBuffer2Test.java
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/StringBuffer2Test.java
@@ -414,7 +414,6 @@
         method = "ensureCapacity",
         args = {int.class}
     )
-    @KnownFailure("Google TODO 1481226") 
     public void test_ensureCapacityI() {
         // Test for method void java.lang.StringBuffer.ensureCapacity(int)
         StringBuffer sb = new StringBuffer(10);
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadLocalTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadLocalTest.java
index bcb94c7..48fddfe 100644
--- a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadLocalTest.java
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadLocalTest.java
@@ -37,11 +37,7 @@
         args = {}
     )
     public void test_Constructor() {
-        try {
-            new ThreadLocal<Object>();
-        } catch (Exception e) {
-            fail("unexpected exception: " + e.toString());
-        }
+        new ThreadLocal<Object>();
     }
     
     /**
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadTest.java
index 47eb166..a24f457 100644
--- a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadTest.java
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadTest.java
@@ -23,9 +23,10 @@
 import java.security.Permission;
 import java.util.Map;
 import java.util.concurrent.Semaphore;
+import java.util.concurrent.locks.LockSupport;
+import java.util.concurrent.atomic.AtomicReference;
 
 import dalvik.annotation.AndroidOnly;
-import dalvik.annotation.KnownFailure;
 import dalvik.annotation.TestLevel;
 import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
@@ -913,7 +914,7 @@
         } catch (InterruptedException e) {
             fail("Join failed ");
         }
-        assertTrue("Joined thread is still alive", !st.isAlive());
+        assertFalse("Joined thread is still alive", st.isAlive());
         boolean result = true;
         Thread th = new Thread("test");
         try {
@@ -938,6 +939,44 @@
         st.start();        
     }
 
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "Regression test for when join() failed due to spurious wakeups",
+            method = "join",
+            args = {long.class, int.class}
+    )
+    public void test_joinWithSpuriousInterruption() throws InterruptedException {
+        final Thread parker = new Thread() {
+            @Override
+            public void run() {
+                for (int i = 0; i < 10; i++) {
+                    // we used to get spurious wakeups upon unparking
+                    LockSupport.park();
+                }
+            }
+        };
+        Thread unparker = new Thread() {
+            @Override
+            public void run() {
+                for (int i = 0; i < 10; i++) {
+                    try {
+                        Thread.sleep(100);
+                        LockSupport.unpark(parker);
+                    } catch (InterruptedException ignored) {
+                    }
+                }
+            }
+        };
+
+        long startNanos = System.nanoTime();
+        parker.start();
+        unparker.start();
+        parker.join(500, 500000);
+        long netWaitTime = System.nanoTime() - startNanos;
+        assertTrue("Expected to wait at least 500000000ns, but was " + netWaitTime + "ns",
+                netWaitTime > 500000000);
+    }
+
     /**
      * @tests java.lang.Thread#join(long)
      */
@@ -1919,23 +1958,33 @@
             public void run() {
                   while (!sem.hasQueuedThreads()) {}
                   sem.release();
+
+                  // RUNNABLE
                   while (run) {}
+
                   try {
+                      // WAITING
                       sem.acquire();
                   } catch (InterruptedException e) {
                       fail("InterruptedException was thrown.");
                   }
+
+                  // BLOCKED
                   synchronized (lock) {
                       lock.equals(new Object());
                   }
                   synchronized (lock) {
                       try {
                         sem.release();
+
+                        // TIMED_WAITING
                         lock.wait(Long.MAX_VALUE);
                       } catch (InterruptedException e) {
                           // expected
                       }
                   }
+
+                  // TERMINATED upon return
             }
         };
         assertEquals(Thread.State.NEW, th.getState());
@@ -1976,7 +2025,7 @@
         }
         assertEquals(Thread.State.TERMINATED, th.getState());
     }
-    boolean run = true;
+    volatile boolean run = true;
     
     /**
      * @tests java.lang.Thread#getUncaughtExceptionHandler
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/net/ContentHandlerFactoryTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/net/ContentHandlerFactoryTest.java
index d00968f..bdbfbd4 100644
--- a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/net/ContentHandlerFactoryTest.java
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/net/ContentHandlerFactoryTest.java
@@ -67,8 +67,7 @@
                 assertTrue(isCreateContentHandlerCalled);
                 assertTrue(isGetContentCalled);
             } catch (Exception e) {
-                fail("Exception during test : " + e.getMessage());
-            
+                throw new RuntimeException(e);
             }
             
             isGetContentCalled = false;
@@ -77,8 +76,7 @@
                 con.getContent(new Class[] {});
                 assertTrue(isGetContentCalled);
             } catch (Exception e) {
-                fail("Exception during test : " + e.getMessage());
-            
+                throw new RuntimeException(e);
             }
             
             try {
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/net/Inet6AddressTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/net/Inet6AddressTest.java
index 498c486..98ae45e 100644
--- a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/net/Inet6AddressTest.java
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/net/Inet6AddressTest.java
@@ -1193,7 +1193,9 @@
                 0x25, (byte) 0xFF, (byte) 0xFE, (byte) 0xF8, (byte) 0x7C,
                 (byte) 0xB2 };
         aAddr = Inet6Address.getByAddress(bAddr);
-        assertEquals("fe80:0:0:0:211:25ff:fef8:7cb2", aAddr.getHostAddress());
+        String aString = aAddr.getHostAddress();
+        assertTrue(aString.equals("fe80:0:0:0:211:25ff:fef8:7cb2") ||
+                   aString.equals("fe80::211:25ff:fef8:7cb2"));
 
         byte[] cAddr = { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
                 (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
@@ -1207,7 +1209,9 @@
                 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
                 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};
         aAddr = Inet6Address.getByAddress(dAddr);
-        assertEquals("0:0:0:0:0:0:0:0", aAddr.getHostAddress());
+        aString = aAddr.getHostAddress();
+        assertTrue(aString.equals("0:0:0:0:0:0:0:0") ||
+                   aString.equals("::"));
 
         byte[] eAddr = { (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03,
                 (byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07,
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/net/InetAddressTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/net/InetAddressTest.java
index fa7dd26..5635ecb 100644
--- a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/net/InetAddressTest.java
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/net/InetAddressTest.java
@@ -228,11 +228,14 @@
             System.setSecurityManager(oldman);
         }
         
-        //Regression for HARMONY-56
-        InetAddress[] ia = InetAddress.getAllByName(null);
-        assertEquals("Assert 0: No loopback address", 1, ia.length);
-        assertTrue("Assert 1: getAllByName(null) not loopback",
-                ia[0].isLoopbackAddress());
+        // Regression for HARMONY-56
+        InetAddress[] addresses = InetAddress.getAllByName(null);
+        assertTrue("getAllByName(null): no results", addresses.length > 0);
+        for (int i = 0; i < addresses.length; i++) {
+            InetAddress address = addresses[i];
+            assertTrue("Assert 1: getAllByName(null): " + address +
+                    " is not loopback", address.isLoopbackAddress());
+        }
         
         try {
             InetAddress.getAllByName("unknown.host");
@@ -478,17 +481,25 @@
         method = "hashCode",
         args = {}
     )
-    public void test_hashCode() {
-        // Test for method int java.net.InetAddress.hashCode()
+    int getHashCode(String literal) {
+        InetAddress host = null;
         try {
-            InetAddress host = InetAddress
-                    .getByName(Support_Configuration.InetTestAddress);
-            int hashcode = host.hashCode();
-            assertTrue("Incorrect hash returned: " + hashcode + " from host: "
-                    + host, hashcode == Support_Configuration.InetTestHashcode);
-        } catch (java.net.UnknownHostException e) {
-            fail("Exception during test : " + e.getMessage());
+            host = InetAddress.getByName(literal);
+        } catch(UnknownHostException e) {
+            fail("Exception during hashCode test : " + e.getMessage());
         }
+        return host.hashCode();
+    }
+
+    public void test_hashCode() {
+        int hashCode = getHashCode(Support_Configuration.InetTestIP);
+        int ip6HashCode = getHashCode(Support_Configuration.InetTestIP6);
+        int ip6LOHashCode = getHashCode(Support_Configuration.InetTestIP6LO);
+        assertFalse("Hash collision", hashCode == ip6HashCode);
+        assertFalse("Hash collision", ip6HashCode == ip6LOHashCode);
+        assertFalse("Hash collision", hashCode == ip6LOHashCode);
+        assertFalse("Hash collision", ip6LOHashCode == 0);
+        assertFalse("Hash collision", ip6LOHashCode == 1);
     }
 
     /**
@@ -503,9 +514,18 @@
     public void test_isMulticastAddress() {
         // Test for method boolean java.net.InetAddress.isMulticastAddress()
         try {
+            InetAddress ia1 = InetAddress.getByName("ff02::1");
+            assertTrue("isMulticastAddress returned incorrect result", ia1
+                    .isMulticastAddress());
             InetAddress ia2 = InetAddress.getByName("239.255.255.255");
             assertTrue("isMulticastAddress returned incorrect result", ia2
                     .isMulticastAddress());
+            InetAddress ia3 = InetAddress.getByName("fefb::");
+            assertFalse("isMulticastAddress returned incorrect result", ia3
+                    .isMulticastAddress());
+            InetAddress ia4 = InetAddress.getByName("10.0.0.1");
+            assertFalse("isMulticastAddress returned incorrect result", ia4
+                    .isMulticastAddress());
         } catch (Exception e) {
             fail("Exception during isMulticastAddress test : " + e.getMessage());
         }
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/net/InetSocketAddressTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/net/InetSocketAddressTest.java
index b979628..b91ad5f 100644
--- a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/net/InetSocketAddressTest.java
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/net/InetSocketAddressTest.java
@@ -324,7 +324,6 @@
         method = "!SerializationGolden",
         args = {}
     )
-    @KnownFailure("Problem with deserialization of Localhost vs. localhost")
     public void testSerializationCompatibility() throws Exception {
 
         Object[] testCases = {
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java
index c803d3b..6077d53 100644
--- a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/net/URLConnectionTest.java
@@ -22,9 +22,7 @@
 import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargets;
-
 import junit.framework.TestCase;
-
 import tests.support.Support_Configuration;
 import tests.support.Support_PortManager;
 import tests.support.Support_TestWebData;
@@ -59,7 +57,6 @@
 import java.net.URLStreamHandler;
 import java.net.UnknownServiceException;
 import java.security.Permission;
-import java.text.DateFormat;
 import java.text.ParseException;
 import java.util.Arrays;
 import java.util.Calendar;
@@ -463,6 +460,29 @@
         }
     }
 
+    @KnownFailure(value="bug 2002061")
+    public void testHttpPostHeaders() throws IOException {
+        String path = "/" + Math.random();
+        HttpURLConnection connection = (HttpURLConnection)
+                new URL("http://localhost:" + port + path).openConnection();
+
+        // post a request
+        connection.setDoOutput(true);
+        OutputStreamWriter writer
+                = new OutputStreamWriter(connection.getOutputStream());
+        writer.write("hello");
+        writer.flush();
+        assertEquals(200, connection.getResponseCode());
+
+        // validate the request by asking the server what was received
+        Map<String, String> headers = server.pathToRequest().get(path).getHeaders();
+        assertEquals("*, */*", headers.get("Accept"));
+        assertEquals("application/x-www-form-urlencoded", headers.get("Content-Type"));
+        assertEquals("5", headers.get("Content-Length"));
+        assertEquals("localhost:" + port, headers.get("Host"));
+        // TODO: test User-Agent?
+    }
+
     /**
      * @throws IOException 
      * @tests {@link java.net.URLConnection#getAllowUserInteraction()}
@@ -1069,8 +1089,6 @@
         method = "getHeaderFieldDate",
         args = {java.lang.String.class, long.class}
     )
-    @KnownFailure("getHeaderFieldDate on Content-Length throws an exception."
-            + " The RI just returns the default value")
     public void test_getHeaderFieldDateLjava_lang_StringJ() {
         Support_TestWebData params = Support_TestWebData.testParams[0];
 
@@ -1612,7 +1630,6 @@
         method = "guessContentTypeFromStream",
         args = {java.io.InputStream.class}
     )
-    @KnownFailure("'<?xml' recognised as text/html instead of application/xml")
     public void test_guessContentTypeFromStreamLjava_io_InputStream()
             throws IOException {
         assertContentTypeEquals("ASCII", "text/html", "<html>");
diff --git a/libcore/luni/src/test/java/tests/AllTests.java b/libcore/luni/src/test/java/tests/AllTests.java
index 9ef1aa8..893cdf0 100644
--- a/libcore/luni/src/test/java/tests/AllTests.java
+++ b/libcore/luni/src/test/java/tests/AllTests.java
@@ -49,10 +49,13 @@
         suite.addTest(tests.regex.AllTests.suite());
         suite.addTest(tests.security.AllTests.suite());
         suite.addTest(tests.sql.AllTests.suite());
+        suite.addTest(tests.suncompat.AllTests.suite());
         suite.addTest(tests.text.AllTests.suite());
         suite.addTest(tests.xml.AllTests.suite());
         suite.addTest(tests.xnet.AllTests.suite());
 
+        suite.addTest(org.apache.harmony.luni.platform.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 bde5766..81f14e0 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
@@ -217,8 +217,6 @@
         method = "File",
         args = {java.lang.String.class, java.lang.String.class}
     )
-    @AndroidOnly("Test 3 incorrectly fails on the RI; Android is more " +
-            "better at resolving path names.")
     public void test_ConstructorLjava_lang_StringLjava_lang_String_112270() {
         File ref1 = new File("/dir1/file1");
 
@@ -230,10 +228,10 @@
                 ref1.getPath()));
         File file3 = new File("\\", "\\dir1\\file1");
         assertTrue("wrong result 3: " + file3, file3.getPath().equals(
-                ref1.getPath()));
+                "\\/\\dir1\\file1"));
         File file4 = new File("\\", "\\\\dir1\\file1");
         assertTrue("wrong result 4: " + file4, file4.getPath().equals(
-                ref1.getPath()));
+                "\\/\\\\dir1\\file1"));
 
         File ref2 = new File("/lib/content-types.properties");
         File file5 = new File("/", "lib/content-types.properties");
@@ -250,8 +248,6 @@
         method = "File",
         args = {java.io.File.class, java.lang.String.class}
     )    
-    @AndroidOnly("Test 3 incorrectly fails on the RI; Android is more " +
-            "better at resolving path names.")
     public void test_ConstructorLjava_io_FileLjava_lang_String_112270() {
         File ref1 = new File("/dir1/file1");
 
@@ -264,10 +260,10 @@
                 ref1.getPath()));
         File file3 = new File(root, "\\dir1\\file1");
         assertTrue("wrong result 3: " + file3, file3.getPath().equals(
-                ref1.getPath()));
+                "/\\dir1\\file1"));
         File file4 = new File(root, "\\\\dir1\\file1");
         assertTrue("wrong result 4: " + file4, file4.getPath().equals(
-                ref1.getPath()));
+                "/\\\\dir1\\file1"));
 
         File ref2 = new File("/lib/content-types.properties");
         File file5 = new File(root, "lib/content-types.properties");
@@ -692,8 +688,9 @@
         method = "delete",
         args = {}
     )
-    @KnownFailure("Non empty directories are deleted on Android.")
     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
diff --git a/libcore/luni/src/test/java/tests/api/java/io/InputStreamReaderTest.java b/libcore/luni/src/test/java/tests/api/java/io/InputStreamReaderTest.java
index bb3f8f5..748105a 100644
--- a/libcore/luni/src/test/java/tests/api/java/io/InputStreamReaderTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/io/InputStreamReaderTest.java
@@ -726,10 +726,12 @@
             char[] chars = new char[8192];
             int at = 0;
 
-            outer:
             for (;;) {
                 int amt = isr.read(chars);
-                if (amt <= 0) break;
+                if (amt <= 0) {
+                    break;
+                }
+
                 for (int i = 0; i < amt; i++) {
                     char c = chars[i];
                     if (at < prefixLength) {
diff --git a/libcore/luni/src/test/java/tests/api/java/io/OutputStreamWriterTest.java b/libcore/luni/src/test/java/tests/api/java/io/OutputStreamWriterTest.java
index cd17907..22e1af7 100644
--- a/libcore/luni/src/test/java/tests/api/java/io/OutputStreamWriterTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/io/OutputStreamWriterTest.java
@@ -17,7 +17,6 @@
 
 package tests.api.java.io;
 
-import dalvik.annotation.KnownFailure;
 import dalvik.annotation.TestTargets;
 import dalvik.annotation.TestLevel;
 import dalvik.annotation.TestTargetNew;
@@ -425,7 +424,6 @@
                 clazz = InputStreamReader.class
         )
     })
-    @KnownFailure("Error when reading bytes in UTF-8 expected:<8916> but was:<8907> ")
     public void test_write$C() throws Exception {
         int upper;
         InputStreamReader isr = null;
@@ -470,7 +468,7 @@
                         j = 0;
                     }
                     assertEquals("Error when reading bytes in "
-                            + MINIMAL_CHARSETS[i], expected++, largeBuffer[j++]);
+                            + MINIMAL_CHARSETS[i] + " at " + j, expected++, largeBuffer[j++]);
                 }
             } finally {
                 try {
@@ -485,6 +483,99 @@
         }
     }
 
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "",
+            method = "write",
+            args = {char[].class}
+    )
+    public void test_write_US_ASCII() throws Exception {
+        testEncodeCharset("US-ASCII", 128);
+    }
+
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "",
+            method = "write",
+            args = {char[].class}
+    )
+    public void test_write_ISO_8859_1() throws Exception {
+        testEncodeCharset("ISO-8859-1", 256);
+    }
+
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "",
+            method = "write",
+            args = {char[].class}
+    )
+    public void test_write_UTF_16BE() throws Exception {
+        testEncodeCharset("UTF-16BE", 0xd800);
+    }
+
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "",
+            method = "write",
+            args = {char[].class}
+    )
+    public void test_write_UTF_16LE() throws Exception {
+        testEncodeCharset("UTF-16LE", 0xd800);
+    }
+
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "",
+            method = "write",
+            args = {char[].class}
+    )
+    public void test_write_UTF_16() throws Exception {
+        testEncodeCharset("UTF-16", 0xd800);
+    }
+
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "",
+            method = "write",
+            args = {char[].class}
+    )
+    public void test_write_UTF_8() throws Exception {
+        testEncodeCharset("UTF-8", 0xd800);
+    }
+
+    private void testEncodeCharset(String charset, int maxChar) throws Exception {
+        char[] chars = new char[maxChar];
+        for (int i = 0; i < maxChar; i++) {
+            chars[i] = (char) i;
+        }
+
+        // to byte array
+        ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
+        OutputStreamWriter charsOut = new OutputStreamWriter(bytesOut, charset);
+        charsOut.write(chars);
+        charsOut.flush();
+
+        // decode from byte array, one character at a time
+        ByteArrayInputStream bytesIn = new ByteArrayInputStream(bytesOut.toByteArray());
+        InputStreamReader charsIn = new InputStreamReader(bytesIn, charset);
+        for (int i = 0; i < maxChar; i++) {
+            assertEquals(i, charsIn.read());
+        }
+        assertEquals(-1, charsIn.read());
+
+        // decode from byte array, using byte buffers
+        bytesIn = new ByteArrayInputStream(bytesOut.toByteArray());
+        charsIn = new InputStreamReader(bytesIn, charset);
+        char[] decoded = new char[maxChar];
+        for (int r = 0; r < maxChar; ) {
+            r += charsIn.read(decoded, r, maxChar - r);
+        }
+        assertEquals(-1, charsIn.read());
+        for (int i = 0; i < maxChar; i++) {
+            assertEquals(i, decoded[i]);
+        }
+    }
+
     /**
      * @tests java.io.OutputStreamWriter#getEncoding()
      */
@@ -784,5 +875,4 @@
             fail("UTF-8 not supported");
         }
     }
-
 }
diff --git a/libcore/luni/src/test/java/tests/api/java/io/PipedInputStreamTest.java b/libcore/luni/src/test/java/tests/api/java/io/PipedInputStreamTest.java
index 671bfe9..a6b71ed 100644
--- a/libcore/luni/src/test/java/tests/api/java/io/PipedInputStreamTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/io/PipedInputStreamTest.java
@@ -20,6 +20,7 @@
 import java.io.PipedInputStream;
 import java.io.PipedOutputStream;
 
+import dalvik.annotation.BrokenTest;
 import dalvik.annotation.TestLevel;
 import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.TestTargetNew;
@@ -414,6 +415,7 @@
         method = "receive",
         args = {int.class}
     )
+    @BrokenTest(value="bug 2002061")
     public void test_receive() throws IOException {
         pis = new PipedInputStream();
         pos = new PipedOutputStream();
diff --git a/libcore/luni/src/test/java/tests/api/java/io/SerializationStressTest4.java b/libcore/luni/src/test/java/tests/api/java/io/SerializationStressTest4.java
index 9b589c5..99ea619 100644
--- a/libcore/luni/src/test/java/tests/api/java/io/SerializationStressTest4.java
+++ b/libcore/luni/src/test/java/tests/api/java/io/SerializationStressTest4.java
@@ -44,6 +44,7 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.TimeZone;
+import java.util.Collections;
 
 import tests.support.Support_Configuration;
 import tests.support.Support_Proxy_I1;
@@ -2666,50 +2667,28 @@
         method = "!Serialization",
         args = {}
     )
-    @KnownFailure("Proxy support broken when user classloader involved")
-    public void test_writeObject_Proxy() {
-        // Test for method void
-        // java.io.ObjectOutputStream.writeObject(java.security.GuardedObject)
+    @KnownFailure(value="bug 2188225")
+    public void test_writeObject_Proxy()
+            throws ClassNotFoundException, IOException {
 
-        Object objToSave = null;
-        Object objLoaded = null;
+        // serialize class
+        Class<?> proxyClass = Proxy.getProxyClass(Support_Proxy_I1.class
+                .getClassLoader(), new Class[]{Support_Proxy_I1.class});
+        Class<?> proxyClassOut = (Class<?>) dumpAndReload(proxyClass);
 
-        try {
-            objToSave = Proxy.getProxyClass(Support_Proxy_I1.class
-                    .getClassLoader(), new Class[] { Support_Proxy_I1.class });
-            if (DEBUG)
-                System.out.println("Obj = " + objToSave);
-            objLoaded = dumpAndReload(objToSave);
+        assertTrue(Proxy.isProxyClass(proxyClassOut));
+        assertEquals(Collections.<Class>singletonList(Support_Proxy_I1.class),
+                Arrays.asList(proxyClassOut.getInterfaces()));
 
-            assertTrue(MSG_TEST_FAILED + "not a proxy class", Proxy
-                    .isProxyClass((Class) objLoaded));
-            Class[] interfaces = ((Class) objLoaded).getInterfaces();
-            assertTrue(MSG_TEST_FAILED + "wrong interfaces length",
-                    interfaces.length == 1);
-            assertTrue(MSG_TEST_FAILED + "wrong interface",
-                    interfaces[0] == Support_Proxy_I1.class);
+        // serialize instance
+        InvocationHandler handler = new MyInvocationHandler();
+        Object proxyInstance = Proxy.newProxyInstance(Support_Proxy_I1.class
+                .getClassLoader(), new Class[] { Support_Proxy_I1.class },
+                handler);
 
-            InvocationHandler handler = new MyInvocationHandler();
-            objToSave = Proxy.newProxyInstance(Support_Proxy_I1.class
-                    .getClassLoader(), new Class[] { Support_Proxy_I1.class },
-                    handler);
-            if (DEBUG)
-                System.out.println("Obj = " + objToSave);
-            objLoaded = dumpAndReload(objToSave);
-
-            boolean equals = Proxy.getInvocationHandler(objLoaded).getClass() == MyInvocationHandler.class;
-            assertTrue(MSG_TEST_FAILED + objToSave, equals);
-
-        } catch (IOException e) {
-            fail("Exception serializing " + objToSave + " : " + e.getMessage());
-        } catch (ClassNotFoundException e) {
-            fail("ClassNotFoundException reading Object type: "
-                    + e.getMessage());
-        } catch (Error err) {
-            System.out.println("Error when obj = " + objToSave);
-            // err.printStackTrace();
-            throw err;
-        }
+        Object proxyInstanceOut = dumpAndReload(proxyInstance);
+        assertEquals(MyInvocationHandler.class,
+                Proxy.getInvocationHandler(proxyInstanceOut).getClass());
     }
 
     @TestTargetNew(
diff --git a/libcore/luni/src/test/java/tests/api/java/lang/ref/SoftReferenceTest.java b/libcore/luni/src/test/java/tests/api/java/lang/ref/SoftReferenceTest.java
index 4c67241..d890f38 100644
--- a/libcore/luni/src/test/java/tests/api/java/lang/ref/SoftReferenceTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/lang/ref/SoftReferenceTest.java
@@ -21,6 +21,7 @@
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargetClass;
 import dalvik.annotation.BrokenTest;
+import dalvik.annotation.SideEffect;
 
 import java.lang.ref.Reference;
 import java.lang.ref.ReferenceQueue;
@@ -107,6 +108,7 @@
         method = "get",
         args = {}
     )
+    @SideEffect("Causes OutOfMemoryError to test finalization")
     public void test_get_SoftReference() {
 
         class TestObject {
diff --git a/libcore/luni/src/test/java/tests/api/java/lang/reflect/ConstructorTest.java b/libcore/luni/src/test/java/tests/api/java/lang/reflect/ConstructorTest.java
index 6bdb55a..e9554dd 100644
--- a/libcore/luni/src/test/java/tests/api/java/lang/reflect/ConstructorTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/lang/reflect/ConstructorTest.java
@@ -104,7 +104,11 @@
         public GenericConstructorTestHelper(T t, S s) {}
         public GenericConstructorTestHelper() throws E{}
     }
- 
+    
+    static class NoPublicConstructorTestHelper {
+        // This class has no public constructor.
+    }
+    
 //    Used to test synthetic constructor.
 //    
 //    static class Outer {
@@ -479,7 +483,6 @@
         } catch (Exception e) {
             fail("Exception during getGenericExceptionTypes test:" + e.toString());
         }
-        System.out.println(Arrays.toString(types));
         assertEquals("Wrong number of exception types returned", 1, types.length);
        
         
@@ -555,7 +558,35 @@
                         .equals(
                                 "public tests.api.java.lang.reflect.ConstructorTest$ConstructorTestHelper(java.lang.Object)"));
     }
-
+    
+    /**
+     * @tests java.lang.reflect.Constructor#getConstructor((Class[]) null)
+     */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "getConstructor",
+        args = {}
+    )
+    public void test_getConstructor() throws Exception {
+        // Passing new Class[0] should be equivalent to (Class[]) null.
+        Class<ConstructorTestHelper> c2 = ConstructorTestHelper.class;
+        assertEquals(c2.getConstructor(new Class[0]), c2.getConstructor((Class[]) null));
+        assertEquals(c2.getDeclaredConstructor(new Class[0]),
+                     c2.getDeclaredConstructor((Class[]) null));
+        
+        // We can get a non-public constructor via getDeclaredConstructor...
+        Class<NoPublicConstructorTestHelper> c1 = NoPublicConstructorTestHelper.class;
+        c1.getDeclaredConstructor((Class[]) null);
+        // ...but not with getConstructor (which only returns public constructors).
+        try {
+            c1.getConstructor((Class[]) null);
+            fail("Should throw NoSuchMethodException");
+        } catch (NoSuchMethodException ex) {
+            // Expected.
+        }
+    }
+    
     /**
      * Sets up the fixture, for example, open a network connection. This method
      * is called before a test is executed.
@@ -570,4 +601,3 @@
     protected void tearDown() {
     }
 }
-
diff --git a/libcore/luni/src/test/java/tests/api/java/lang/reflect/GenericReflectionCornerCases.java b/libcore/luni/src/test/java/tests/api/java/lang/reflect/GenericReflectionCornerCases.java
index 31dfaa5..8919652 100644
--- a/libcore/luni/src/test/java/tests/api/java/lang/reflect/GenericReflectionCornerCases.java
+++ b/libcore/luni/src/test/java/tests/api/java/lang/reflect/GenericReflectionCornerCases.java
@@ -169,8 +169,6 @@
         )
     })
     @SuppressWarnings("unchecked")
-    @KnownFailure("Class MultipleBoundedWildcardUnEquality can not be found, "
-            + "maybe the wrong class loader is used to get the raw type?")
     public void testMultipleBoundedWildcardUnEquality() throws Exception {
         Class<? extends MultipleBoundedWildcardUnEquality> clazz = MultipleBoundedWildcardUnEquality.class;
 
@@ -240,8 +238,6 @@
         )
     })
     @SuppressWarnings("unchecked")
-    @KnownFailure("Class MultipleBoundedWildcardEquality can not be found, "
-            + "maybe the wrong class loader is used to get the raw type?")
     public void testMultipleBoundedWildcard() throws Exception {
         Class<? extends MultipleBoundedWildcardEquality> clazz = MultipleBoundedWildcardEquality.class;
 
diff --git a/libcore/luni/src/test/java/tests/api/java/lang/reflect/GenericTypesTest.java b/libcore/luni/src/test/java/tests/api/java/lang/reflect/GenericTypesTest.java
index c9255b2..7db5dbe 100644
--- a/libcore/luni/src/test/java/tests/api/java/lang/reflect/GenericTypesTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/lang/reflect/GenericTypesTest.java
@@ -201,8 +201,6 @@
         args = {}
     )
     @SuppressWarnings("unchecked")
-    @KnownFailure("Class GenericType can not be found, "
-            + "maybe the wrong class loader is used to get the raw type?")
     public void testSimpleInheritance() throws Exception {
         Class<? extends SimpleInheritance> clazz = SimpleInheritance.class;
         TypeVariable<Class> subTypeVariable = getTypeParameter(clazz);
diff --git a/libcore/luni/src/test/java/tests/api/java/lang/reflect/MethodTest.java b/libcore/luni/src/test/java/tests/api/java/lang/reflect/MethodTest.java
index 884bc8c..506d173 100644
--- a/libcore/luni/src/test/java/tests/api/java/lang/reflect/MethodTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/lang/reflect/MethodTest.java
@@ -226,7 +226,41 @@
         }
         assertTrue("Inherited method returned not-equal", m1.equals(m2));
     }
-
+    
+    /**
+     * @tests java.lang.Class#getMethod(java.lang.String, java.lang.Class[])
+     */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "getMethod",
+        args = {java.lang.String.class, java.lang.Class[].class},
+        clazz = java.lang.Class.class
+    )
+    public void test_getMethod() throws NoSuchMethodException, SecurityException {
+        // Check that getMethod treats null parameterTypes the same as an empty array.
+        Method m1 = TestMethod.class.getMethod("invokeInstanceTest", new Class[0]);
+        Method m2 = TestMethod.class.getMethod("invokeInstanceTest", (Class[]) null);
+        assertEquals(m1, m2);
+    }
+    
+    /**
+     * @tests java.lang.Class#getDeclaredMethod(java.lang.String, java.lang.Class[])
+     */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "getDeclaredMethod",
+        args = {java.lang.String.class, java.lang.Class[].class},
+        clazz = java.lang.Class.class
+    )
+    public void test_getDeclaredMethod() throws NoSuchMethodException, SecurityException {
+        // Check that getDeclaredMethod treats null parameterTypes the same as an empty array.
+        Method m1 = TestMethod.class.getDeclaredMethod("invokeInstanceTest", new Class[0]);
+        Method m2 = TestMethod.class.getDeclaredMethod("invokeInstanceTest", (Class[]) null);
+        assertEquals(m1, m2);
+    }
+    
     /**
      * @tests java.lang.reflect.Method#getDeclaringClass()
      */
diff --git a/libcore/luni/src/test/java/tests/api/java/lang/reflect/ParameterizedTypeTest.java b/libcore/luni/src/test/java/tests/api/java/lang/reflect/ParameterizedTypeTest.java
index eaff7c8..bf3698e 100644
--- a/libcore/luni/src/test/java/tests/api/java/lang/reflect/ParameterizedTypeTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/lang/reflect/ParameterizedTypeTest.java
@@ -55,8 +55,6 @@
             args = {}
         )
     })
-    @KnownFailure("Class A can not be found, "
-            + "maybe the wrong class loader is used to get the raw type?")
     public void testStringParameterizedSuperClass() {
         Class<? extends B> clazz = B.class;
         Type genericSuperclass = clazz.getGenericSuperclass();
@@ -93,8 +91,6 @@
             args = {}
         )
     })
-    @KnownFailure("Class C can not be found, "
-            + "maybe the wrong class loader is used to get the raw type?")
     public void testTypeParameterizedSuperClass() {
         Class<? extends D> clazz = D.class;
         Type genericSuperclass = clazz.getGenericSuperclass();
diff --git a/libcore/luni/src/test/java/tests/api/java/net/JarURLConnectionTest.java b/libcore/luni/src/test/java/tests/api/java/net/JarURLConnectionTest.java
index 8303db3..7a67bf8 100644
--- a/libcore/luni/src/test/java/tests/api/java/net/JarURLConnectionTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/net/JarURLConnectionTest.java
@@ -34,6 +34,8 @@
 import java.util.Collection;
 import java.util.Map;
 import java.util.Set;
+import java.util.Arrays;
+import java.util.HashSet;
 import java.util.jar.Attributes;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
@@ -151,8 +153,7 @@
       args = {}
     )
     public void test_getManifest() throws Exception {
-        
-        String [] expected = {"plus.bmp", "swt.dll"};
+
         //URL u = new URL("jar:"
         //        + BASE.toString()+"/lf.jar!/swt.dll");
         
@@ -161,15 +162,9 @@
         juc = (JarURLConnection) u.openConnection();
         Manifest manifest = juc.getManifest();
         Map<String, Attributes> attr = manifest.getEntries();
-        assertEquals(expected.length, attr.size());
-        Set<String> keys = attr.keySet();
-        String [] result = new String[expected.length];
-        keys.toArray(result);
+        assertEquals(new HashSet<String>(Arrays.asList("plus.bmp", "swt.dll")),
+                attr.keySet());
 
-        for(int i = 0; i < result.length; i++) {
-            assertEquals(expected[i], result[i]);
-        }
-        
         //URL invURL = new URL("jar:"
         //        + BASE.toString()+"/InvalidJar.jar!/Test.class");
         
diff --git a/libcore/luni/src/test/java/tests/api/java/net/MulticastSocketTest.java b/libcore/luni/src/test/java/tests/api/java/net/MulticastSocketTest.java
index 86e298c..8c3e7f3 100644
--- a/libcore/luni/src/test/java/tests/api/java/net/MulticastSocketTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/net/MulticastSocketTest.java
@@ -36,6 +36,9 @@
 import java.net.UnknownHostException;
 import java.security.Permission;
 import java.util.Enumeration;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.TimeUnit;
 
 import tests.support.Support_NetworkInterface;
 import tests.support.Support_PortManager;
@@ -64,23 +67,24 @@
 
         public MulticastSocket ms;
 
-        boolean running = true;
+        volatile boolean running = true;
 
-        volatile public byte[] rbuf = new byte[512];
-
-        volatile DatagramPacket rdp = null;
+        private final BlockingQueue<DatagramPacket> queue
+                = new ArrayBlockingQueue<DatagramPacket>(1);
 
         public void run() {
             try {
                 while (running) {
                     try {
+                        byte[] rbuf = new byte[512];
+                        rbuf[0] = -1;
+                        DatagramPacket rdp = new DatagramPacket(rbuf, rbuf.length);
                         ms.receive(rdp);
+                        queue.put(rdp);
                     } catch (java.io.InterruptedIOException e) {
-                        Thread.yield();
+                    } catch (InterruptedException e) {
                     }
-                    ;
                 }
-                ;
             } catch (java.io.IOException e) {
                 System.out.println("Multicast server failed: " + e);
             } finally {
@@ -93,15 +97,8 @@
             ms.leaveGroup(aGroup);
         }
 
-        public void stopServer() {
-            running = false;
-        }
-
         public MulticastServer(InetAddress anAddress, int aPort)
                 throws java.io.IOException {
-            rbuf = new byte[512];
-            rbuf[0] = -1;
-            rdp = new DatagramPacket(rbuf, rbuf.length);
             ms = new MulticastSocket(aPort);
             ms.setSoTimeout(2000);
             ms.joinGroup(anAddress);
@@ -109,13 +106,20 @@
 
         public MulticastServer(SocketAddress anAddress, int aPort,
                 NetworkInterface netInterface) throws java.io.IOException {
-            rbuf = new byte[512];
-            rbuf[0] = -1;
-            rdp = new DatagramPacket(rbuf, rbuf.length);
             ms = new MulticastSocket(aPort);
             ms.setSoTimeout(2000);
             ms.joinGroup(anAddress, netInterface);
         }
+
+        public DatagramPacket receive() throws InterruptedException {
+            return queue.poll(1000, TimeUnit.MILLISECONDS);
+        }
+
+        public void stopServer() throws InterruptedException {
+            running = false;
+            interrupt();
+            join();
+        }
     }
 
     /**
@@ -458,7 +462,7 @@
         method = "joinGroup",
         args = {java.net.InetAddress.class}
     )
-    public void test_joinGroupLjava_net_InetAddress() {
+    public void test_joinGroupLjava_net_InetAddress() throws InterruptedException {
         // Test for method void
         // java.net.MulticastSocket.joinGroup(java.net.InetAddress)
         String msg = null;
@@ -476,8 +480,7 @@
                     .length(), group, groupPort);
             mss.joinGroup(group);
             mss.send(sdp, (byte) 10);
-            Thread.sleep(1000);
-            
+
             SecurityManager sm = new SecurityManager() {
 
                 public void checkPermission(Permission perm) {
@@ -514,8 +517,10 @@
         } catch (Exception e) {
             fail("Exception during joinGroup test: " + e.toString());
         }
-        assertTrue("Group member did not recv data: ", new String(server.rdp
-                .getData(), 0, server.rdp.getLength()).equals(msg));
+        DatagramPacket rdb = server.receive();
+
+        assertEquals("Group member did not recv data: ", msg,
+                new String(rdb.getData(), 0, rdb.getLength()));
 
     }
 
@@ -531,6 +536,7 @@
         method = "joinGroup",
         args = {java.net.SocketAddress.class, java.net.NetworkInterface.class}
     )
+    @KnownFailure(value="bug 2155705")
     public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface() 
                                     throws IOException, InterruptedException {
         // security manager that allows us to check that we only return the
@@ -608,11 +614,11 @@
                     .length(), group, serverPort);
             mss.setTimeToLive(2);
             mss.send(sdp);
-            Thread.sleep(1000);
+            DatagramPacket rdp = server.receive();
+
             // now vaildate that we received the data as expected
-            assertTrue("Group member did not recv data: ", new String(
-                    server.rdp.getData(), 0, server.rdp.getLength())
-                    .equals(msg));
+            assertEquals("Group member did not recv data: ", msg,
+                    new String(rdp.getData(), 0, rdp.getLength()));
             server.stopServer();
 
             // now validate that we handled the case were we join a
@@ -633,11 +639,9 @@
             sdp = new DatagramPacket(msg.getBytes(), msg.length(), group2,
                     serverPort);
             mss.send(sdp);
-            Thread.sleep(1000);
-            assertFalse(
-                    "Group member received data when sent on different group: ",
-                    new String(server.rdp.getData(), 0, server.rdp.getLength())
-                            .equals(msg));
+            rdp = server.receive();
+            assertNull("Group member received data when sent on different group",
+                    rdp);
             server.stopServer();
 
             // if there is more than one network interface then check that
@@ -717,20 +721,20 @@
                         sdp = new DatagramPacket(msg.getBytes(), msg.length(),
                                 group, serverPort);
                         mss.send(sdp);
-                        Thread.sleep(1000);
+                        rdp = server.receive();
+
                         if (thisInterface.equals(sendingInterface)) {
-                            assertTrue(
+                            assertEquals(
                                     "Group member did not recv data when " +
-                                    "bound on specific interface: ",
-                                    new String(server.rdp.getData(), 0,
-                                            server.rdp.getLength()).equals(msg));
+                                    "bound on specific interface: ", msg,
+                                    new String(rdp.getData(), 0, rdp.getLength()));
                         } else {
                             assertFalse(
                                     "Group member received data on other " +
                                     "interface when only asked for it on one " +
                                     "interface: ",
-                                    new String(server.rdp.getData(), 0,
-                                            server.rdp.getLength()).equals(msg));
+                                    new String(rdp.getData(), 0,
+                                            rdp.getLength()).equals(msg));
                         }
 
                         server.stopServer();
@@ -829,6 +833,7 @@
         method = "leaveGroup",
         args = {java.net.SocketAddress.class, java.net.NetworkInterface.class}
     )
+    @KnownFailure(value="bug 2155705")
     public void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface() {
         // security manager that allows us to check that we only return the
         // addresses that we should
@@ -942,7 +947,7 @@
         method = "send",
         args = {java.net.DatagramPacket.class, byte.class}
     )
-    public void test_sendLjava_net_DatagramPacketB() {
+    public void test_sendLjava_net_DatagramPacketB() throws InterruptedException {
         // Test for method void
         // java.net.MulticastSocket.send(java.net.DatagramPacket, byte)
 
@@ -1015,11 +1020,10 @@
         } catch(IOException ioe) {
             //expected
         }
-        
-        byte[] data = server.rdp.getData();
-        int length = server.rdp.getLength();
-        assertTrue("Failed to send data. Received " + length, new String(data,
-                0, length).equals(msg));
+
+        DatagramPacket rdp = server.receive();
+        assertEquals("Failed to send data. Received " + rdp.getLength(), msg,
+                new String(rdp.getData(), 0, rdp.getLength()));
     }
 
     /**
@@ -1097,7 +1101,6 @@
         method = "setNetworkInterface",
         args = {java.net.NetworkInterface.class}
     )
-    @KnownFailure("No interfaces if there's no debugger connected")
     public void test_setNetworkInterfaceLjava_net_NetworkInterface() 
                                     throws IOException, InterruptedException {
         String msg = null;
@@ -1162,24 +1165,13 @@
                         DatagramPacket sdp = new DatagramPacket(theBytes,
                                 theBytes.length, group, serverPort);
                         mss.send(sdp);
-                        Thread.sleep(1000);
-                        String receivedMessage = new String(server.rdp
-                                .getData(), 0, server.rdp.getLength());
-                        assertTrue(
-                                "Group member did not recv data when send on " +
-                                "a specific interface: ",
-                                receivedMessage.equals(msg));
-                        assertTrue(
-                                "Datagram was not received from expected " +
-                                "interface expected["
-                                        + thisInterface
-                                        + "] got ["
-                                        + NetworkInterface
-                                                .getByInetAddress(server.rdp
-                                                        .getAddress()) + "]",
-                                NetworkInterface.getByInetAddress(
-                                        server.rdp.getAddress()).equals(
-                                        thisInterface));
+                        DatagramPacket rdp = server.receive();
+
+                        String receivedMessage = new String(rdp.getData(), 0, rdp.getLength());
+                        assertEquals("Group member did not recv data when send on "
+                                + "a specific interface: ", msg, receivedMessage);
+                        assertEquals("Datagram was not received as expected.",
+                                thisInterface, NetworkInterface.getByInetAddress(rdp.getAddress()));
 
                         // stop the server
                         server.stopServer();
@@ -1597,7 +1589,7 @@
      * Tears down the fixture, for example, close a network connection. This
      * method is called after a test is executed.
      */
-    protected void tearDown() {
+    protected void tearDown() throws InterruptedException {
 
         if (t != null)
             t.interrupt();
diff --git a/libcore/luni/src/test/java/tests/api/java/net/SocketTest.java b/libcore/luni/src/test/java/tests/api/java/net/SocketTest.java
index 3d6fbeb..7cc31a0 100644
--- a/libcore/luni/src/test/java/tests/api/java/net/SocketTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/net/SocketTest.java
@@ -158,7 +158,14 @@
         Socket socket = null;
         try {
             socket = new Socket(InetAddress.getByName(null), sport);
-            assertEquals(InetAddress.getByName("127.0.0.1"), socket.getLocalAddress());
+            InetAddress address = socket.getLocalAddress();
+            if (Boolean.getBoolean("java.net.preferIPv6Addresses")) {
+                assertTrue(
+                    address.equals(InetAddress.getByName("::1")) ||
+                    address.equals(InetAddress.getByName("0:0:0:0:0:0:0:1")));
+            } else {
+                assertEquals(address, InetAddress.getByName("127.0.0.1"));
+            }
         } finally {
             try {
                 socket.close();
diff --git a/libcore/luni/src/test/java/tests/api/java/net/UnknownServiceExceptionTest.java b/libcore/luni/src/test/java/tests/api/java/net/UnknownServiceExceptionTest.java
index 9fc287c..463532f 100644
--- a/libcore/luni/src/test/java/tests/api/java/net/UnknownServiceExceptionTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/net/UnknownServiceExceptionTest.java
@@ -40,7 +40,7 @@
     public void test_Constructor() {
         // Test for method java.net.UnknownServiceException()
         try {
-            new URL("file://moo.txt").openConnection().getOutputStream();
+            new URL("file:///moo.txt").openConnection().getOutputStream();
         } catch (UnknownServiceException e) {
             // correct
             return;
diff --git a/libcore/luni/src/test/java/tests/api/java/util/AbstractSequentialListTest.java b/libcore/luni/src/test/java/tests/api/java/util/AbstractSequentialListTest.java
index 169afe3..e2c47b8 100644
--- a/libcore/luni/src/test/java/tests/api/java/util/AbstractSequentialListTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/util/AbstractSequentialListTest.java
@@ -85,7 +85,7 @@
         }
 
         public boolean hasNext() {
-            return false;
+            return true;
         }
 
         public boolean hasPrevious() {
diff --git a/libcore/luni/src/test/java/tests/api/java/util/BitSetTest.java b/libcore/luni/src/test/java/tests/api/java/util/BitSetTest.java
index c0e6f2a..34ec49a 100644
--- a/libcore/luni/src/test/java/tests/api/java/util/BitSetTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/util/BitSetTest.java
@@ -252,7 +252,7 @@
         initialSize = bs.size();
         bs.set(0, initialSize);
         bs.clear(7, 64);
-        assertEquals("Failed to grow BitSet", 128, bs.size());
+        assertEquals("Failed to grow BitSet", 64, bs.size());
         for (int i = 0; i < 7; i++)
             assertTrue("Shouldn't have cleared bit " + i, bs.get(i));
         for (int i = 7; i < 64; i++)
@@ -624,7 +624,7 @@
         // pos1 and pos2 is in the same bitset element, boundary testing
         bs = new BitSet(16);
         bs.set(7, 64);
-        assertEquals("Failed to grow BitSet", 128, bs.size());
+        assertEquals("Failed to grow BitSet", 64, bs.size());
         for (int i = 0; i < 7; i++)
             assertTrue("Shouldn't have set bit " + i, !bs.get(i));
         for (int i = 7; i < 64; i++)
@@ -858,7 +858,7 @@
         bs.set(7);
         bs.set(10);
         bs.flip(7, 64);
-        assertEquals("Failed to grow BitSet", 128, bs.size());
+        assertEquals("Failed to grow BitSet", 64, bs.size());
         for (int i = 0; i < 7; i++)
             assertTrue("Shouldn't have flipped bit " + i, !bs.get(i));
         assertTrue("Failed to flip bit 7", !bs.get(7));
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 b75898b..2b1b47e 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
@@ -1435,11 +1435,7 @@
                 .indexOfSubList(src, sub2));
     }
 
-    /**
-     * @param string2
-     * @param string1
-     * @param index
-     */
+
     private void testwithCharList(int count, String string1, String string2,
             boolean first) {
         char[] chars = string1.toCharArray();
@@ -2379,9 +2375,11 @@
         m.put("one", "1");
         m.put("two", "2");
         Map um = Collections.unmodifiableMap(m);
-        assertEquals("{one=1, two=2}", um.toString());
+        assertTrue("{one=1, two=2}".equals(um.toString()) ||
+                   "{two=2, one=1}".equals(um.toString())); 
     }
 
+
     @TestTargetNew(
         level = TestLevel.COMPLETE,
         notes = "",
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 636f1bd..b2030c9 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
@@ -4705,7 +4705,7 @@
         bw.close();
 
         readOnly = File.createTempFile("readonly", null);
-        readOnly.setReadOnly();
+        assertTrue(readOnly.setReadOnly());
 
         secret = File.createTempFile("secret", null);
         
diff --git a/libcore/luni/src/test/java/tests/api/java/util/HashMapTest.java b/libcore/luni/src/test/java/tests/api/java/util/HashMapTest.java
index 1d726ea..af73c0a 100644
--- a/libcore/luni/src/test/java/tests/api/java/util/HashMapTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/util/HashMapTest.java
@@ -20,17 +20,9 @@
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargets;
 import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetClass; 
+import dalvik.annotation.TestTargetClass;
 
-import java.util.AbstractMap;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
+import java.util.*;
 
 import tests.support.Support_MapTest2;
 import tests.support.Support_UnmodifiableCollectionTest;
@@ -39,7 +31,7 @@
 public class HashMapTest extends junit.framework.TestCase {
     class MockMap extends AbstractMap {
         public Set entrySet() {
-            return null;
+            return Collections.EMPTY_SET;
         }
         public int size(){
             return 0;
@@ -151,14 +143,10 @@
         for (int counter = 0; counter < hmSize; counter++)
             assertTrue("Failed to construct correct HashMap", hm
                     .get(objArray2[counter]) == hm2.get(objArray2[counter]));
-        
-        try {
-            Map mockMap = new MockMap();
-            hm = new HashMap(mockMap);
-            fail("Should throw NullPointerException");
-        } catch (NullPointerException e) {
-            //empty
-        }
+
+        Map mockMap = new MockMap();
+        hm = new HashMap(mockMap);
+        assertEquals(hm, mockMap);
     }
 
     /**
@@ -296,6 +284,40 @@
     }
 
     /**
+     * @tests java.util.HashMap#entrySet()
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "",
+        method = "entrySet",
+        args = {}
+    )
+    public void test_entrySetEquals() {
+        Set s1 = hm.entrySet();
+        Set s2 = new HashMap(hm).entrySet();
+        assertEquals(s1, s2);
+    }
+
+    /**
+     * @tests java.util.HashMap#entrySet()
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "",
+        method = "entrySet",
+        args = {}
+    )
+    public void test_removeFromViews() {
+        hm.put("A", null);
+        hm.put("B", null);
+        assertTrue(hm.keySet().remove("A"));
+
+        Map<String, String> m2 = new HashMap<String, String>();
+        m2.put("B", null);
+        assertTrue(hm.entrySet().remove(m2.entrySet().iterator().next()));
+    }
+
+    /**
      * @tests java.util.HashMap#get(java.lang.Object)
      */
     @TestTargetNew(
@@ -479,7 +501,39 @@
         } catch (NullPointerException e) {
             // expected.
         }
-    } 
+    }
+
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "Checks putAll that causes map to resize",
+            method = "putAll",
+            args = {java.util.Map.class}
+    )
+    public void test_putAllLjava_util_Map_Resize() {
+        Random rnd = new Random(666);
+
+        Map<Integer,Integer> m1 = new HashMap<Integer, Integer>();
+        int MID = 10000;
+        for (int i = 0; i < MID; i++) {
+            Integer j = rnd.nextInt();
+            m1.put(j, j);
+        }
+
+        Map<Integer,Integer> m2 = new HashMap<Integer, Integer>();
+        int HI = 30000;
+        for (int i = MID; i < HI; i++) {
+            Integer j = rnd.nextInt();
+            m2.put(j, j);
+        }
+        
+        m1.putAll(m2);
+
+        rnd = new Random(666);
+        for (int i = 0; i < HI; i++) {
+            Integer j = rnd.nextInt();
+            assertEquals(j, m1.get(j));
+        }
+    }
 
     /**
      * @tests java.util.HashMap#remove(java.lang.Object)
diff --git a/libcore/luni/src/test/java/tests/api/java/util/HashtableTest.java b/libcore/luni/src/test/java/tests/api/java/util/HashtableTest.java
index bbdad50..6c50f1b 100644
--- a/libcore/luni/src/test/java/tests/api/java/util/HashtableTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/util/HashtableTest.java
@@ -35,6 +35,7 @@
 import java.util.Set;
 import java.util.TreeMap;
 import java.util.Vector;
+import java.util.Collections;
 
 import tests.api.java.util.HashMapTest.ReusableKey;
 import tests.support.Support_MapTest2;
@@ -166,6 +167,24 @@
     }
 
     /**
+     * @tests java.util.Hashtable#Hashtable(java.util.Map)
+     */
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "",
+        method = "Hashtable",
+        args = {java.util.Map.class}
+    )
+    public void test_ConversionConstructorNullValue() {
+        Map<String, Void> map = Collections.singletonMap("Dog", null);
+        try {
+            new Hashtable<String, Void>(map);
+            fail("NullPointerException expected");
+        } catch (NullPointerException e) {
+            //expected
+        }
+    }
+    /**
      * @tests java.util.Hashtable#clear()
      */
     @TestTargetNew(
@@ -310,46 +329,49 @@
         assertEquals("All keys not retrieved", 10, ht10.size());
     }
 
-    /**
-     * @tests java.util.Hashtable#elements()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "elements",
-        args = {}
-    )
-    public void test_elements_subtest0() {
-        // this is the reference implementation behavior
-        final Hashtable ht = new Hashtable(7);
-        ht.put("1", "a");
-        // these three elements hash to the same bucket in a 7 element Hashtable
-        ht.put("2", "b");
-        ht.put("9", "c");
-        ht.put("12", "d");
-        // Hashtable looks like:
-        // 0: "1"
-        // 1: "12" -> "9" -> "2"
-        Enumeration en = ht.elements();
-        // cache the first entry
-        en.hasMoreElements();
-        ht.remove("12");
-        ht.remove("9");
-        boolean exception = false;
-        try {
-            // cached "12"
-            Object result = en.nextElement();
-            assertNull("unexpected: " + result, result);
-            // next is removed "9"
-            result = en.nextElement();
-            assertNull("unexpected: " + result, result);
-            result = en.nextElement();
-            assertTrue("unexpected: " + result, "b".equals(result));
-        } catch (NoSuchElementException e) {
-            exception = true;
-        }
-        assertTrue("unexpected NoSuchElementException", !exception);
-    }
+// BEGIN android-removed
+// implementation dependent
+//    /**
+//     * @tests java.util.Hashtable#elements()
+//     */
+//    @TestTargetNew(
+//        level = TestLevel.COMPLETE,
+//        notes = "",
+//        method = "elements",
+//        args = {}
+//    )
+//    public void test_elements_subtest0() {
+//        // this is the reference implementation behavior
+//        final Hashtable ht = new Hashtable(7);
+//        ht.put("1", "a");
+//        // these three elements hash to the same bucket in a 7 element Hashtable
+//        ht.put("2", "b");
+//        ht.put("9", "c");
+//        ht.put("12", "d");
+//        // Hashtable looks like:
+//        // 0: "1"
+//        // 1: "12" -> "9" -> "2"
+//        Enumeration en = ht.elements();
+//        // cache the first entry
+//        en.hasMoreElements();
+//        ht.remove("12");
+//        ht.remove("9");
+//        boolean exception = false;
+//        try {
+//            // cached "12"
+//            Object result = en.nextElement();
+//            assertNull("unexpected: " + result, result);
+//            // next is removed "9"
+//            result = en.nextElement();
+//            assertNull("unexpected: " + result, result);
+//            result = en.nextElement();
+//            assertTrue("unexpected: " + result, "b".equals(result));
+//        } catch (NoSuchElementException e) {
+//            exception = true;
+//        }
+//        assertTrue("unexpected NoSuchElementException", !exception);
+//    }
+// END android-removed
 
     /**
      * @tests java.util.Hashtable#entrySet()
@@ -371,9 +393,11 @@
         while (e.hasMoreElements())
             assertTrue("Returned incorrect entry set", s2.contains(e
                     .nextElement()));
-
-        assertEquals("Not synchronized", 
-                "java.util.Collections$SynchronizedSet", s.getClass().getName());
+// BEGIN android-removed
+// implementation dependent
+//        assertEquals("Not synchronized",
+//                "java.util.Collections$SynchronizedSet", s.getClass().getName());
+// END android-removed
 
         boolean exception = false;
         try {
@@ -417,26 +441,28 @@
         Hashtable h = hashtableClone(htfull);
         assertEquals("Could not retrieve element", "FVal 2", ((String) h.get("FKey 2"))
                 );
-        
-        
-        // Regression for HARMONY-262
-        ReusableKey k = new ReusableKey();
-        Hashtable h2 = new Hashtable();
-        k.setKey(1);
-        h2.put(k, "value1");
 
-        k.setKey(13);
-        assertNull(h2.get(k));
-
-        k.setKey(12);
-        assertNull(h2.get(k));
-
-        try {
-            h2.get(null);
-            fail("NullPointerException expected");
-        } catch (NullPointerException e) {
-            //expected
-        }
+// BEGIN android-removed
+// implementation dependent
+//        // Regression for HARMONY-262
+//        ReusableKey k = new ReusableKey();
+//        Hashtable h2 = new Hashtable();
+//        k.setKey(1);
+//        h2.put(k, "value1");
+//
+//        k.setKey(13);
+//        assertNull(h2.get(k));
+//
+//        k.setKey(12);
+//        assertNull(h2.get(k));
+//        
+//        try {
+//            h2.get(null);
+//            fail("NullPointerException expected");
+//        } catch (NullPointerException e) {
+//            //expected
+//        }
+// END android-removed
     }
 
     /**
@@ -569,9 +595,12 @@
             assertTrue("Returned incorrect key set", s
                     .contains(e.nextElement()));
 
-        assertEquals("Not synchronized", 
-                "java.util.Collections$SynchronizedSet", s.getClass().getName());
-
+// BEGIN android-removed
+// implementation dependent
+//        assertEquals("Not synchronized",
+//                "java.util.Collections$SynchronizedSet", s.getClass().getName());
+// END android-removed
+        
         Map map = new Hashtable(101);
         map.put(new Integer(1), "1");
         map.put(new Integer(102), "102");
@@ -651,54 +680,57 @@
         }
     }
 
-    /**
-     * @tests java.util.Hashtable#keySet()
-     */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL_COMPLETE,
-        notes = "",
-        method = "keySet",
-        args = {}
-    )
-    public void test_keySet_subtest1() {
-        // this is the reference implementation behavior
-        final Hashtable ht = new Hashtable(7);
-        ht.put("1", "a");
-        // these three elements hash to the same bucket in a 7 element Hashtable
-        ht.put("2", "b");
-        ht.put("9", "c");
-        ht.put("12", "d");
-        // Hashtable looks like:
-        // 0: "1"
-        // 1: "12" -> "9" -> "2"
-        Enumeration en = ht.elements();
-        // cache the first entry
-        en.hasMoreElements();
-        Iterator it = ht.keySet().iterator();
-        // this is mostly a copy of the test in test_elements_subtest0()
-        // test removing with the iterator does not null the values
-        while (it.hasNext()) {
-            String key = (String) it.next();
-            if ("12".equals(key) || "9".equals(key)) {
-                it.remove();
-            }
-        }
-        it.remove();
-        boolean exception = false;
-        try {
-            // cached "12"
-            Object result = en.nextElement();
-            assertTrue("unexpected: " + result, "d".equals(result));
-            // next is removed "9"
-            result = en.nextElement();
-            assertTrue("unexpected: " + result, "c".equals(result));
-            result = en.nextElement();
-            assertTrue("unexpected: " + result, "b".equals(result));
-        } catch (NoSuchElementException e) {
-            exception = true;
-        }
-        assertTrue("unexpected NoSuchElementException", !exception);
-    }
+// BEGIN android-removed
+// implementation dependent
+//    /**
+//     * @tests java.util.Hashtable#keySet()
+//     */
+//    @TestTargetNew(
+//        level = TestLevel.PARTIAL_COMPLETE,
+//        notes = "",
+//        method = "keySet",
+//        args = {}
+//    )
+//    public void test_keySet_subtest1() {
+//        // this is the reference implementation behavior
+//        final Hashtable ht = new Hashtable(7);
+//        ht.put("1", "a");
+//        // these three elements hash to the same bucket in a 7 element Hashtable
+//        ht.put("2", "b");
+//        ht.put("9", "c");
+//        ht.put("12", "d");
+//        // Hashtable looks like:
+//        // 0: "1"
+//        // 1: "12" -> "9" -> "2"
+//        Enumeration en = ht.elements();
+//        // cache the first entry
+//        en.hasMoreElements();
+//        Iterator it = ht.keySet().iterator();
+//        // this is mostly a copy of the test in test_elements_subtest0()
+//        // test removing with the iterator does not null the values
+//        while (it.hasNext()) {
+//            String key = (String) it.next();
+//            if ("12".equals(key) || "9".equals(key)) {
+//                it.remove();
+//            }
+//        }
+//        it.remove();
+//        boolean exception = false;
+//        try {
+//            // cached "12"
+//            Object result = en.nextElement();
+//            assertTrue("unexpected: " + result, "d".equals(result));
+//            // next is removed "9"
+//            result = en.nextElement();
+//            assertTrue("unexpected: " + result, "c".equals(result));
+//            result = en.nextElement();
+//            assertTrue("unexpected: " + result, "b".equals(result));
+//        } catch (NoSuchElementException e) {
+//            exception = true;
+//        }
+//        assertTrue("unexpected NoSuchElementException", !exception);
+//    }
+// END android-removed
 
     /**
      * @tests java.util.Hashtable#put(java.lang.Object, java.lang.Object)
@@ -871,9 +903,12 @@
         while (e.hasMoreElements())
             assertTrue("Returned incorrect values", c.contains(e.nextElement()));
 
-        assertEquals("Not synchronized", 
-                "java.util.Collections$SynchronizedCollection", c.getClass().getName());
-
+// BEGIN android-removed
+// implementation dependent
+//        assertEquals("Not synchronized",
+//                "java.util.Collections$SynchronizedCollection", c.getClass().getName());
+// END android-removed
+        
         Hashtable myHashtable = new Hashtable();
         for (int i = 0; i < 100; i++)
             myHashtable.put(new Integer(i), new Integer(i));
diff --git a/libcore/luni/src/test/java/tests/api/java/util/LinkedHashMapTest.java b/libcore/luni/src/test/java/tests/api/java/util/LinkedHashMapTest.java
index bfa474b..d5223fe 100644
--- a/libcore/luni/src/test/java/tests/api/java/util/LinkedHashMapTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/util/LinkedHashMapTest.java
@@ -20,7 +20,7 @@
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargets;
 import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetClass; 
+import dalvik.annotation.TestTargetClass;
 
 import java.util.AbstractMap;
 import java.util.ArrayList;
@@ -38,7 +38,7 @@
 /**
  * @tests java.util.LinkedHashMap
  */
-@TestTargetClass(LinkedHashMap.class) 
+@TestTargetClass(LinkedHashMap.class)
 public class LinkedHashMapTest extends junit.framework.TestCase {
 
     LinkedHashMap hm;
@@ -48,13 +48,13 @@
     Object[] objArray;
 
     Object[] objArray2;
-    
+
     static final class CacheMap extends LinkedHashMap {
         protected boolean removeEldestEntry(Map.Entry e) {
             return size() > 5;
         }
     }
-    
+
     private static class MockMapNull extends AbstractMap {
         @Override
         public Set entrySet() {
@@ -131,7 +131,7 @@
         } catch (IllegalArgumentException e) {
             //expected
         }
-    
+
         LinkedHashMap empty = new LinkedHashMap(0, 0.75f);
         assertNull("Empty hashtable access", empty.get("nothing"));
         empty.put("something", "here");
@@ -196,7 +196,7 @@
         // Test for method java.lang.Object
         // java.util.LinkedHashMap.put(java.lang.Object, java.lang.Object)
         hm.put("KEY", "VALUE");
-        assertEquals("Failed to install key/value pair", 
+        assertEquals("Failed to install key/value pair",
                 "VALUE", hm.get("KEY"));
 
         LinkedHashMap m = new LinkedHashMap();
@@ -209,6 +209,26 @@
                 new Integer(0)));
     }
 
+
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "test that put on an already present key causes entry to move to tail.",
+        method = "put",
+        args = {java.lang.Object.class, java.lang.Object.class}
+    )
+    public void test_putPresent() {
+        Map<String, String> m = new LinkedHashMap<String, String>(8, .75f, true);
+        m.put("KEY", "VALUE");
+        m.put("WOMBAT", "COMBAT");
+        m.put("KEY", "VALUE");
+        Map.Entry newest = null;
+        for (Map.Entry<String, String> e : m.entrySet()) {
+            newest = e;
+        }
+        assertEquals("KEY", newest.getKey());
+        assertEquals("VALUE", newest.getValue());
+    }
+
     /**
      * @tests java.util.LinkedHashMap#putAll(java.util.Map)
      */
@@ -217,7 +237,7 @@
         notes = "",
         method = "putAll",
         args = {java.util.Map.class}
-    )    
+    )
     public void test_putAllLjava_util_Map() {
         // Test for method void java.util.LinkedHashMap.putAll(java.util.Map)
         LinkedHashMap hm2 = new LinkedHashMap();
@@ -251,7 +271,7 @@
         } catch (NullPointerException e) {
             // expected.
         }
-    } 
+    }
 
     /**
      * @tests java.util.LinkedHashMap#entrySet()
@@ -275,6 +295,26 @@
         }
     }
 
+    @TestTargetNew(
+        level = TestLevel.COMPLETE,
+        notes = "Test that remove removes the entry from the linked list",
+        method = "entrySet",
+        args = {}
+    )
+    public void test_entrySetRemove() {
+        entrySetRemoveHelper("military", "intelligence");
+        entrySetRemoveHelper(null, "hypothesis");
+    }
+    private void entrySetRemoveHelper(String key, String value) {
+        Map<String, String> m1 = new LinkedHashMap<String, String>();
+        m1.put(key, value);
+        m1.put("jumbo", "shrimp");
+        LinkedHashMap<String, String> m2 = new LinkedHashMap<String, String>(m1);
+        Set<Map.Entry<String, String>> s1 = m1.entrySet();
+        s1.remove(m2.entrySet().iterator().next());
+        assertEquals("jumbo", s1.iterator().next().getKey());
+    }
+
     /**
      * @tests java.util.LinkedHashMap#keySet()
      */
@@ -435,23 +475,23 @@
         // get the keySet() and values() on the original Map
         Set keys = map.keySet();
         Collection values = map.values();
-        assertEquals("values() does not work", 
+        assertEquals("values() does not work",
                 "value", values.iterator().next());
-        assertEquals("keySet() does not work", 
+        assertEquals("keySet() does not work",
                 "key", keys.iterator().next());
         AbstractMap map2 = (AbstractMap) map.clone();
         map2.put("key", "value2");
         Collection values2 = map2.values();
         assertTrue("values() is identical", values2 != values);
-        
+
         // values() and keySet() on the cloned() map should be different
-        assertEquals("values() was not cloned", 
+        assertEquals("values() was not cloned",
                 "value2", values2.iterator().next());
         map2.clear();
         map2.put("key2", "value3");
         Set key2 = map2.keySet();
         assertTrue("keySet() is identical", key2 != keys);
-        assertEquals("keySet() was not cloned", 
+        assertEquals("keySet() was not cloned",
                 "key2", key2.iterator().next());
     }
 
@@ -472,10 +512,10 @@
         hm1.put("c", "c");
         LinkedHashMap<String, String> hm2 = (LinkedHashMap<String, String>) hm1.clone();
         hm1.get("a");
-        
+
         Map.Entry<String, String>[] set = new Map.Entry[3];
         Iterator<Map.Entry<String,String>> iterator = hm1.entrySet().iterator();
-        
+
         assertEquals("b", iterator.next().getKey());
         assertEquals("c", iterator.next().getKey());
         assertEquals("a", iterator.next().getKey());
@@ -491,7 +531,7 @@
         notes = "Regression test.",
         method = "clone",
         args = {}
-    )   
+    )
     // regresion test for HARMONY-4603
     public void test_clone_Mock() {
         LinkedHashMap hashMap = new MockMap();
@@ -517,7 +557,30 @@
         protected boolean removeEldestEntry(Map.Entry e) {
             return num > 1;
         }
-    } 
+    }
+
+    /**
+     * @tests put/get interaction in access-order map where removeEldest
+     * returns true.
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "Regression for bug Google Bug 2121546",
+        method = "get",
+        args = {java.lang.Object.class}
+    )
+    public void test_removeEldestFromSameBucketAsNewEntry() {
+        LinkedHashMap<String, String> map
+                = new LinkedHashMap<String, String>(6, 0.75F, true) {
+            @Override
+            protected boolean removeEldestEntry(Entry<String, String> e) {
+                return true;
+            }
+        };
+        map.put("N", "E");
+        map.put("F", "I");
+        assertEquals(null, map.get("N"));
+    }
 
     /**
      * @tests java.util.LinkedHashMap#containsKey(java.lang.Object)
diff --git a/libcore/luni/src/test/java/tests/api/java/util/TreeMapTest.java b/libcore/luni/src/test/java/tests/api/java/util/TreeMapTest.java
index 7ea4c9e..0e7f6a1 100644
--- a/libcore/luni/src/test/java/tests/api/java/util/TreeMapTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/util/TreeMapTest.java
@@ -83,6 +83,9 @@
             if (null == o1) {
                 return -1;
             }
+            if (null == o2) {
+                return 1;
+            }
             return o1.compareTo(o2);
         }
     }
@@ -844,8 +847,6 @@
         method = "equals",
         args = {java.lang.Object.class}
     )
-    @KnownFailure("equals(Onject o) method throws java.lang.ClassCastException " +
-            "for TreeMap objects with different key objects.")
     public void test_equals() throws Exception {
         // comparing TreeMaps with different object types
         Map m1 = new TreeMap();
diff --git a/libcore/math/src/main/java/java/math/BigDecimal.java b/libcore/math/src/main/java/java/math/BigDecimal.java
index 6fa1f34..6c00560 100644
--- a/libcore/math/src/main/java/java/math/BigDecimal.java
+++ b/libcore/math/src/main/java/java/math/BigDecimal.java
@@ -25,51 +25,48 @@
 import org.apache.harmony.math.internal.nls.Messages;
 
 /**
- * This class represents immutable arbitrary precision decimal numbers. Each
- * {@code BigDecimal} instance is represented with a unscaled arbitrary
- * precision mantissa (the unscaled value) and a scale. The value of the {@code
- * BigDecimal} is {@code unscaledValue} 10^(-{@code scale}).
- * 
- * @since Android 1.0
+ * This class represents immutable integer numbers of arbitrary length. Large
+ * numbers are typically used in security applications and therefore BigIntegers
+ * offer dedicated functionality like the generation of large prime numbers or
+ * the computation of modular inverse.
+ * <p>
+ * Since the class was modeled to offer all the functionality as the {@link Integer}
+ * class does, it provides even methods that operate bitwise on a two's
+ * complement representation of large integers. Note however that the
+ * implementations favors an internal representation where magnitude and sign
+ * are treated separately. Hence such operations are inefficient and should be
+ * discouraged. In simple words: Do NOT implement any bit fields based on
+ * BigInteger.
  */
 public class BigDecimal extends Number implements Comparable<BigDecimal>, Serializable {
-    /* Static Fields */
 
     /**
      * The constant zero as a {@code BigDecimal}.
-     * 
-     * @since Android 1.0
      */
     public static final BigDecimal ZERO = new BigDecimal(0, 0);
 
     /**
      * The constant one as a {@code BigDecimal}.
-     * 
-     * @since Android 1.0
      */
     public static final BigDecimal ONE = new BigDecimal(1, 0);
 
     /**
      * The constant ten as a {@code BigDecimal}.
-     * 
-     * @since Android 1.0
      */
     public static final BigDecimal TEN = new BigDecimal(10, 0);
 
     /**
      * Rounding mode where positive values are rounded towards positive infinity
      * and negative values towards negative infinity.
-     * 
+     *
      * @see RoundingMode#UP
-     * @since Android 1.0
      */
     public static final int ROUND_UP = 0;
 
     /**
      * Rounding mode where the values are rounded towards zero.
-     * 
+     *
      * @see RoundingMode#DOWN
-     * @since Android 1.0
      */
     public static final int ROUND_DOWN = 1;
 
@@ -77,9 +74,8 @@
      * Rounding mode to round towards positive infinity. For positive values
      * this rounding mode behaves as {@link #ROUND_UP}, for negative values as
      * {@link #ROUND_DOWN}.
-     * 
+     *
      * @see RoundingMode#CEILING
-     * @since Android 1.0
      */
     public static final int ROUND_CEILING = 2;
 
@@ -87,36 +83,32 @@
      * Rounding mode to round towards negative infinity. For positive values
      * this rounding mode behaves as {@link #ROUND_DOWN}, for negative values as
      * {@link #ROUND_UP}.
-     * 
+     *
      * @see RoundingMode#FLOOR
-     * @since Android 1.0
      */
     public static final int ROUND_FLOOR = 3;
 
     /**
      * Rounding mode where values are rounded towards the nearest neighbor.
      * Ties are broken by rounding up.
-     * 
+     *
      * @see RoundingMode#HALF_UP
-     * @since Android 1.0
      */
     public static final int ROUND_HALF_UP = 4;
 
     /**
      * Rounding mode where values are rounded towards the nearest neighbor.
      * Ties are broken by rounding down.
-     * 
+     *
      * @see RoundingMode#HALF_DOWN
-     * @since Android 1.0
      */
     public static final int ROUND_HALF_DOWN = 5;
 
     /**
      * Rounding mode where values are rounded towards the nearest neighbor.
      * Ties are broken by rounding to the even neighbor.
-     * 
+     *
      * @see RoundingMode#HALF_EVEN
-     * @since Android 1.0
      */
     public static final int ROUND_HALF_EVEN = 6;
 
@@ -124,14 +116,11 @@
      * Rounding mode where the rounding operations throws an {@code
      * ArithmeticException} for the case that rounding is necessary, i.e. for
      * the case that the value cannot be represented exactly.
-     * 
+     *
      * @see RoundingMode#UNNECESSARY
-     * @since Android 1.0
      */
     public static final int ROUND_UNNECESSARY = 7;
 
-    /* Private Fields */
-
     /** This is the serialVersionUID used by the sun implementation. */
     private static final long serialVersionUID = 6108874887143696463L;
 
@@ -180,8 +169,8 @@
         10000000000000000L,
         100000000000000000L,
         1000000000000000000L, };
-    
-    
+
+
     private static final long[] LONG_FIVE_POW = new long[]
     {   1L,
         5L,
@@ -211,10 +200,10 @@
         298023223876953125L,
         1490116119384765625L,
         7450580596923828125L, };
-    
+
     private static final int[] LONG_FIVE_POW_BIT_LENGTH = new int[LONG_FIVE_POW.length];
     private static final int[] LONG_TEN_POW_BIT_LENGTH = new int[LONG_TEN_POW.length];
-    
+
     private static final int BI_SCALED_BY_ZERO_LENGTH = 11;
 
     /**
@@ -241,7 +230,7 @@
             ZERO_SCALED_BY[i] = new BigDecimal(0, i);
             CH_ZEROS[i] = '0';
         }
-        
+
         for (; i < CH_ZEROS.length; i++) {
             CH_ZEROS[i] = '0';
         }
@@ -251,7 +240,7 @@
         for(int j=0; j<LONG_TEN_POW_BIT_LENGTH.length; j++) {
             LONG_TEN_POW_BIT_LENGTH[j] = bitLength(LONG_TEN_POW[j]);
         }
-        
+
         // Taking the references of useful powers.
         TEN_POW = Multiplication.bigTenPows;
         FIVE_POW = Multiplication.bigFivePows;
@@ -262,13 +251,13 @@
      * representation of {@code BigDecimal}.
      */
     private BigInteger intVal;
-    
+
     private transient int bitLength;
-    
+
     private transient long smallValue;
 
-    /** 
-     * The 32-bit integer scale in the internal representation of {@code BigDecimal}. 
+    /**
+     * The 32-bit integer scale in the internal representation of {@code BigDecimal}.
      */
     private int scale;
 
@@ -277,20 +266,18 @@
      * precision is calculated the first time, and used in the following calls
      * of method <code>precision()</code>. Note that some call to the private
      * method <code>inplaceRound()</code> could update this field.
-     * 
+     *
      * @see #precision()
      * @see #inplaceRound(MathContext)
      */
     private transient int precision = 0;
 
-    /* Constructors */
-
     private BigDecimal(long smallValue, int scale){
         this.smallValue = smallValue;
         this.scale = scale;
         this.bitLength = bitLength(smallValue);
     }
-    
+
     private BigDecimal(int smallValue, int scale){
         this.smallValue = smallValue;
         this.scale = scale;
@@ -300,7 +287,7 @@
     /**
      * Constructs a new {@code BigDecimal} instance from a string representation
      * given as a character array.
-     * 
+     *
      * @param in
      *            array of characters containing the string representation of
      *            this {@code BigDecimal}.
@@ -316,7 +303,6 @@
      * @throws NumberFormatException
      *             if in does not contain a valid string representation of a big
      *             decimal.
-     * @since Android 1.0
      */
     public BigDecimal(char[] in, int offset, int len) {
         int begin = offset; // first index to be copied
@@ -347,9 +333,9 @@
                 if (in[offset] == '0') {
                     counter++;
                 } else {
-                    wasNonZero = true;    
-                }                
-            };
+                    wasNonZero = true;
+                }
+            }
 
         }
         unscaledBuffer.append(in, begin, offset - begin);
@@ -365,9 +351,9 @@
                     if (in[offset] == '0') {
                         counter++;
                     } else {
-                        wasNonZero = true;    
-                    }                
-                };
+                        wasNonZero = true;
+                    }
+                }
             }
             scale = offset - begin;
             bufLength +=scale;
@@ -388,7 +374,7 @@
             }
             // Accumulating all remaining digits
             scaleString = String.valueOf(in, begin, last + 1 - begin);
-            // Checking if the scale is defined            
+            // Checking if the scale is defined
             newScale = (long)scale - Integer.parseInt(scaleString);
             scale = (int)newScale;
             if (newScale != scale) {
@@ -402,17 +388,17 @@
             bitLength = bitLength(smallValue);
         } else {
             setUnscaledValue(new BigInteger(unscaledBuffer.toString()));
-        }        
+        }
         precision = unscaledBuffer.length() - counter;
         if (unscaledBuffer.charAt(0) == '-') {
             precision --;
-        }    
+        }
     }
 
     /**
      * Constructs a new {@code BigDecimal} instance from a string representation
      * given as a character array.
-     * 
+     *
      * @param in
      *            array of characters containing the string representation of
      *            this {@code BigDecimal}.
@@ -434,7 +420,6 @@
      *             if {@code mc.precision > 0} and {@code mc.roundingMode ==
      *             UNNECESSARY} and the new big decimal cannot be represented
      *             within the given precision without rounding.
-     * @since Android 1.0
      */
     public BigDecimal(char[] in, int offset, int len, MathContext mc) {
         this(in, offset, len);
@@ -444,7 +429,7 @@
     /**
      * Constructs a new {@code BigDecimal} instance from a string representation
      * given as a character array.
-     * 
+     *
      * @param in
      *            array of characters containing the string representation of
      *            this {@code BigDecimal}.
@@ -453,7 +438,6 @@
      * @throws NumberFormatException
      *             if {@code in} does not contain a valid string representation
      *             of a big decimal.
-     * @since Android 1.0
      */
     public BigDecimal(char[] in) {
         this(in, 0, in.length);
@@ -463,7 +447,7 @@
      * Constructs a new {@code BigDecimal} instance from a string representation
      * given as a character array. The result is rounded according to the
      * specified math context.
-     * 
+     *
      * @param in
      *            array of characters containing the string representation of
      *            this {@code BigDecimal}.
@@ -478,7 +462,6 @@
      *             if {@code mc.precision > 0} and {@code mc.roundingMode ==
      *             UNNECESSARY} and the new big decimal cannot be represented
      *             within the given precision without rounding.
-     * @since Android 1.0
      */
     public BigDecimal(char[] in, MathContext mc) {
         this(in, 0, in.length);
@@ -488,14 +471,13 @@
     /**
      * Constructs a new {@code BigDecimal} instance from a string
      * representation.
-     * 
+     *
      * @param val
      *            string containing the string representation of this {@code
      *            BigDecimal}.
      * @throws NumberFormatException
      *             if {@code val} does not contain a valid string representation
      *             of a big decimal.
-     * @since Android 1.0
      */
     public BigDecimal(String val) {
         this(val.toCharArray(), 0, val.length());
@@ -505,7 +487,7 @@
      * Constructs a new {@code BigDecimal} instance from a string
      * representation. The result is rounded according to the specified math
      * context.
-     * 
+     *
      * @param val
      *            string containing the string representation of this {@code
      *            BigDecimal}.
@@ -518,7 +500,6 @@
      *             if {@code mc.precision > 0} and {@code mc.roundingMode ==
      *             UNNECESSARY} and the new big decimal cannot be represented
      *             within the given precision without rounding.
-     * @since Android 1.0
      */
     public BigDecimal(String val, MathContext mc) {
         this(val.toCharArray(), 0, val.length());
@@ -534,12 +515,11 @@
      * <p>
      * To generate a big decimal instance which is equivalent to {@code 0.1} use
      * the {@code BigDecimal(String)} constructor.
-     * 
+     *
      * @param val
      *            double value to be converted to a {@code BigDecimal} instance.
      * @throws NumberFormatException
      *             if {@code val} is infinity or not a number.
-     * @since Android 1.0
      */
     public BigDecimal(double val) {
         if (Double.isInfinite(val) || Double.isNaN(val)) {
@@ -558,7 +538,7 @@
             scale = 0;
             precision = 1;
         }
-        // To simplify all factors '2' in the mantisa 
+        // To simplify all factors '2' in the mantisa
         if (scale > 0) {
             trailingZeros = Math.min(scale, Long.numberOfTrailingZeros(mantisa));
             mantisa >>>= trailingZeros;
@@ -606,7 +586,7 @@
      * <p>
      * To generate a big decimal instance which is equivalent to {@code 0.1} use
      * the {@code BigDecimal(String)} constructor.
-     * 
+     *
      * @param val
      *            double value to be converted to a {@code BigDecimal} instance.
      * @param mc
@@ -617,7 +597,6 @@
      *             if {@code mc.precision > 0} and {@code mc.roundingMode ==
      *             UNNECESSARY} and the new big decimal cannot be represented
      *             within the given precision without rounding.
-     * @since Android 1.0
      */
     public BigDecimal(double val, MathContext mc) {
         this(val);
@@ -627,11 +606,10 @@
     /**
      * Constructs a new {@code BigDecimal} instance from the given big integer
      * {@code val}. The scale of the result is {@code 0}.
-     * 
+     *
      * @param val
      *            {@code BigInteger} value to be converted to a {@code
      *            BigDecimal} instance.
-     * @since Android 1.0
      */
     public BigDecimal(BigInteger val) {
         this(val, 0);
@@ -640,7 +618,7 @@
     /**
      * Constructs a new {@code BigDecimal} instance from the given big integer
      * {@code val}. The scale of the result is {@code 0}.
-     * 
+     *
      * @param val
      *            {@code BigInteger} value to be converted to a {@code
      *            BigDecimal} instance.
@@ -650,7 +628,6 @@
      *             if {@code mc.precision > 0} and {@code mc.roundingMode ==
      *             UNNECESSARY} and the new big decimal cannot be represented
      *             within the given precision without rounding.
-     * @since Android 1.0
      */
     public BigDecimal(BigInteger val, MathContext mc) {
         this(val);
@@ -661,7 +638,7 @@
      * Constructs a new {@code BigDecimal} instance from a given unscaled value
      * {@code unscaledVal} and a given scale. The value of this instance is
      * {@code unscaledVal} 10^(-{@code scale}).
-     * 
+     *
      * @param unscaledVal
      *            {@code BigInteger} representing the unscaled value of this
      *            {@code BigDecimal} instance.
@@ -669,7 +646,6 @@
      *            scale of this {@code BigDecimal} instance.
      * @throws NullPointerException
      *             if {@code unscaledVal == null}.
-     * @since Android 1.0
      */
     public BigDecimal(BigInteger unscaledVal, int scale) {
         if (unscaledVal == null) {
@@ -684,7 +660,7 @@
      * {@code unscaledVal} and a given scale. The value of this instance is
      * {@code unscaledVal} 10^(-{@code scale}). The result is rounded according
      * to the specified math context.
-     * 
+     *
      * @param unscaledVal
      *            {@code BigInteger} representing the unscaled value of this
      *            {@code BigDecimal} instance.
@@ -698,7 +674,6 @@
      *             within the given precision without rounding.
      * @throws NullPointerException
      *             if {@code unscaledVal == null}.
-     * @since Android 1.0
      */
     public BigDecimal(BigInteger unscaledVal, int scale, MathContext mc) {
         this(unscaledVal, scale);
@@ -708,10 +683,9 @@
     /**
      * Constructs a new {@code BigDecimal} instance from the given int
      * {@code val}. The scale of the result is 0.
-     * 
+     *
      * @param val
      *            int value to be converted to a {@code BigDecimal} instance.
-     * @since Android 1.0
      */
     public BigDecimal(int val) {
         this(val,0);
@@ -721,7 +695,7 @@
      * Constructs a new {@code BigDecimal} instance from the given int {@code
      * val}. The scale of the result is {@code 0}. The result is rounded
      * according to the specified math context.
-     * 
+     *
      * @param val
      *            int value to be converted to a {@code BigDecimal} instance.
      * @param mc
@@ -730,7 +704,6 @@
      *             if {@code mc.precision > 0} and {@code c.roundingMode ==
      *             UNNECESSARY} and the new big decimal cannot be represented
      *             within the given precision without rounding.
-     * @since Android 1.0
      */
     public BigDecimal(int val, MathContext mc) {
         this(val,0);
@@ -740,10 +713,9 @@
     /**
      * Constructs a new {@code BigDecimal} instance from the given long {@code
      * val}. The scale of the result is {@code 0}.
-     * 
+     *
      * @param val
      *            long value to be converted to a {@code BigDecimal} instance.
-     * @since Android 1.0
      */
     public BigDecimal(long val) {
         this(val,0);
@@ -753,7 +725,7 @@
      * Constructs a new {@code BigDecimal} instance from the given long {@code
      * val}. The scale of the result is {@code 0}. The result is rounded
      * according to the specified math context.
-     * 
+     *
      * @param val
      *            long value to be converted to a {@code BigDecimal} instance.
      * @param mc
@@ -762,7 +734,6 @@
      *             if {@code mc.precision > 0} and {@code mc.roundingMode ==
      *             UNNECESSARY} and the new big decimal cannot be represented
      *             within the given precision without rounding.
-     * @since Android 1.0
      */
     public BigDecimal(long val, MathContext mc) {
         this(val);
@@ -775,7 +746,7 @@
      * Returns a new {@code BigDecimal} instance whose value is equal to {@code
      * unscaledVal} 10^(-{@code scale}). The scale of the result is {@code
      * scale}, and its unscaled value is {@code unscaledVal}.
-     * 
+     *
      * @param unscaledVal
      *            unscaled value to be used to construct the new {@code
      *            BigDecimal}.
@@ -783,7 +754,6 @@
      *            scale to be used to construct the new {@code BigDecimal}.
      * @return {@code BigDecimal} instance with the value {@code unscaledVal}*
      *         10^(-{@code unscaledVal}).
-     * @since Android 1.0
      */
     public static BigDecimal valueOf(long unscaledVal, int scale) {
         if (scale == 0) {
@@ -800,11 +770,10 @@
      * Returns a new {@code BigDecimal} instance whose value is equal to {@code
      * unscaledVal}. The scale of the result is {@code 0}, and its unscaled
      * value is {@code unscaledVal}.
-     * 
+     *
      * @param unscaledVal
      *            value to be converted to a {@code BigDecimal}.
      * @return {@code BigDecimal} instance with the value {@code unscaledVal}.
-     * @since Android 1.0
      */
     public static BigDecimal valueOf(long unscaledVal) {
         if ((unscaledVal >= 0) && (unscaledVal < BI_SCALED_BY_ZERO_LENGTH)) {
@@ -815,23 +784,21 @@
 
     /**
      * Returns a new {@code BigDecimal} instance whose value is equal to {@code
-     * unscaledVal}. The new decimal is constructed as if the {@code
-     * BigDecimal(String)} constructor is called with an argument which is equal
-     * to {@code Double.toString(val)}. For example, {@code valueOf(0.1)} is
-     * converted to (unscaled=1, scale=1), although the double {@code 0.1}
-     * cannot be represented exactly as a double value. In contrast to that, a
-     * new {@code BigDecimal(0.1)} instance has the value {@code
+     * val}. The new decimal is constructed as if the {@code BigDecimal(String)}
+     * constructor is called with an argument which is equal to {@code
+     * Double.toString(val)}. For example, {@code valueOf("0.1")} is converted to
+     * (unscaled=1, scale=1), although the double {@code 0.1} cannot be
+     * represented exactly as a double value. In contrast to that, a new {@code
+     * BigDecimal(0.1)} instance has the value {@code
      * 0.1000000000000000055511151231257827021181583404541015625} with an
-     * unscaled value {@code
-     * 1000000000000000055511151231257827021181583404541015625} and the scale
-     * {@code 55}.
-     * 
+     * unscaled value {@code 1000000000000000055511151231257827021181583404541015625}
+     * and the scale {@code 55}.
+     *
      * @param val
      *            double value to be converted to a {@code BigDecimal}.
      * @return {@code BigDecimal} instance with the value {@code val}.
      * @throws NumberFormatException
      *             if {@code val} is infinite or {@code val} is not a number
-     * @since Android 1.0
      */
     public static BigDecimal valueOf(double val) {
         if (Double.isInfinite(val) || Double.isNaN(val)) {
@@ -845,13 +812,12 @@
      * Returns a new {@code BigDecimal} whose value is {@code this + augend}.
      * The scale of the result is the maximum of the scales of the two
      * arguments.
-     * 
+     *
      * @param augend
      *            value to be added to {@code this}.
      * @return {@code this + augend}.
      * @throws NullPointerException
      *             if {@code augend == null}.
-     * @since Android 1.0
      */
     public BigDecimal add(BigDecimal augend) {
         int diffScale = this.scale - augend.scale;
@@ -895,11 +861,11 @@
         }
         // END android-changed
     }
-    
+
     /**
      * Returns a new {@code BigDecimal} whose value is {@code this + augend}.
      * The result is rounded according to the passed context {@code mc}.
-     * 
+     *
      * @param augend
      *            value to be added to {@code this}.
      * @param mc
@@ -907,7 +873,6 @@
      * @return {@code this + augend}.
      * @throws NullPointerException
      *             if {@code augend == null} or {@code mc == null}.
-     * @since Android 1.0
      */
     public BigDecimal add(BigDecimal augend, MathContext mc) {
         BigDecimal larger; // operand with the largest unscaled value
@@ -915,7 +880,7 @@
         BigInteger tempBI;
         long diffScale = (long)this.scale - augend.scale;
         int largerSignum;
-        // Some operand is zero or the precision is infinity  
+        // Some operand is zero or the precision is infinity
         if ((augend.isZero()) || (this.isZero())
                 || (mc.getPrecision() == 0)) {
             return add(augend).round(mc);
@@ -927,14 +892,14 @@
         } else if (augend.aproxPrecision() < -diffScale - 1) {
             larger = this;
             smaller = augend;
-        } else {// No optimization is done 
+        } else {// No optimization is done
             return add(augend).round(mc);
         }
         if (mc.getPrecision() >= larger.aproxPrecision()) {
             // No optimization is done
             return add(augend).round(mc);
         }
-        // Cases where it's unnecessary to add two numbers with very different scales 
+        // Cases where it's unnecessary to add two numbers with very different scales
         largerSignum = larger.signum();
         if (largerSignum == smaller.signum()) {
             tempBI = Multiplication.multiplyByPositiveInt(larger.getUnscaledValue(),10)
@@ -945,22 +910,20 @@
             tempBI = Multiplication.multiplyByPositiveInt(tempBI,10)
             .add(BigInteger.valueOf(largerSignum * 9));
         }
-        // Rounding the improved adding 
+        // Rounding the improved adding
         larger = new BigDecimal(tempBI, larger.scale + 1);
         return larger.round(mc);
     }
 
     /**
-     * Returns a new {@code BigDecimal} whose value is {@code this - subtrahend}
-     * . The scale of the result is the maximum of the scales of the two
-     * arguments.
-     * 
+     * Returns a new {@code BigDecimal} whose value is {@code this - subtrahend}.
+     * The scale of the result is the maximum of the scales of the two arguments.
+     *
      * @param subtrahend
      *            value to be subtracted from {@code this}.
      * @return {@code this - subtrahend}.
      * @throws NullPointerException
      *             if {@code subtrahend == null}.
-     * @since Android 1.0
      */
     public BigDecimal subtract(BigDecimal subtrahend) {
         int diffScale = this.scale - subtrahend.scale;
@@ -1006,7 +969,7 @@
     /**
      * Returns a new {@code BigDecimal} whose value is {@code this - subtrahend}.
      * The result is rounded according to the passed context {@code mc}.
-     * 
+     *
      * @param subtrahend
      *            value to be subtracted from {@code this}.
      * @param mc
@@ -1014,14 +977,13 @@
      * @return {@code this - subtrahend}.
      * @throws NullPointerException
      *             if {@code subtrahend == null} or {@code mc == null}.
-     * @since Android 1.0
      */
     public BigDecimal subtract(BigDecimal subtrahend, MathContext mc) {
         long diffScale = subtrahend.scale - (long)this.scale;
         int thisSignum;
-        BigDecimal leftOperand; // it will be only the left operand (this) 
+        BigDecimal leftOperand; // it will be only the left operand (this)
         BigInteger tempBI;
-        // Some operand is zero or the precision is infinity  
+        // Some operand is zero or the precision is infinity
         if ((subtrahend.isZero()) || (this.isZero())
                 || (mc.getPrecision() == 0)) {
             return subtract(subtrahend).round(mc);
@@ -1052,13 +1014,12 @@
      * Returns a new {@code BigDecimal} whose value is {@code this *
      * multiplicand}. The scale of the result is the sum of the scales of the
      * two arguments.
-     * 
+     *
      * @param multiplicand
      *            value to be multiplied with {@code this}.
      * @return {@code this * multiplicand}.
      * @throws NullPointerException
      *             if {@code multiplicand == null}.
-     * @since Android 1.0
      */
     public BigDecimal multiply(BigDecimal multiplicand) {
         long newScale = (long)this.scale + multiplicand.scale;
@@ -1079,7 +1040,7 @@
      * Returns a new {@code BigDecimal} whose value is {@code this *
      * multiplicand}. The result is rounded according to the passed context
      * {@code mc}.
-     * 
+     *
      * @param multiplicand
      *            value to be multiplied with {@code this}.
      * @param mc
@@ -1087,7 +1048,6 @@
      * @return {@code this * multiplicand}.
      * @throws NullPointerException
      *             if {@code multiplicand == null} or {@code mc == null}.
-     * @since Android 1.0
      */
     public BigDecimal multiply(BigDecimal multiplicand, MathContext mc) {
         BigDecimal result = multiply(multiplicand);
@@ -1101,7 +1061,7 @@
      * As scale of the result the parameter {@code scale} is used. If rounding
      * is required to meet the specified scale, then the specified rounding mode
      * {@code roundingMode} is applied.
-     * 
+     *
      * @param divisor
      *            value by which {@code this} is divided.
      * @param scale
@@ -1119,7 +1079,6 @@
      * @throws ArithmeticException
      *             if {@code roundingMode == ROUND_UNNECESSARY} and rounding is
      *             necessary according to the given scale.
-     * @since Android 1.0
      */
     public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) {
         return divide(divisor, scale, RoundingMode.valueOf(roundingMode));
@@ -1130,7 +1089,7 @@
      * As scale of the result the parameter {@code scale} is used. If rounding
      * is required to meet the specified scale, then the specified rounding mode
      * {@code roundingMode} is applied.
-     * 
+     *
      * @param divisor
      *            value by which {@code this} is divided.
      * @param scale
@@ -1147,7 +1106,6 @@
      *             if {@code roundingMode == RoundingMode.UNNECESSAR}Y and
      *             rounding is necessary according to the given scale and given
      *             precision.
-     * @since Android 1.0
      */
     public BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode) {
         // Let be: this = [u1,s1]  and  divisor = [u2,s2]
@@ -1158,7 +1116,7 @@
             // math.04=Division by zero
             throw new ArithmeticException(Messages.getString("math.04")); //$NON-NLS-1$
         }
-        
+
         long diffScale = ((long)this.scale - divisor.scale) - scale;
         if(this.bitLength < 64 && divisor.bitLength < 64 ) {
             if(diffScale == 0) {
@@ -1182,12 +1140,12 @@
                             scale,
                             roundingMode);
                 }
-                
+
             }
         }
         BigInteger scaledDividend = this.getUnscaledValue();
         BigInteger scaledDivisor = divisor.getUnscaledValue(); // for scaling of 'u2'
-        
+
         if (diffScale > 0) {
             // Multiply 'u2'  by:  10^((s1 - s2) - scale)
             scaledDivisor = Multiplication.multiplyByTenPow(scaledDivisor, (int)diffScale);
@@ -1197,9 +1155,9 @@
         }
         return divideBigIntegers(scaledDividend, scaledDivisor, scale, roundingMode);
         }
-    
+
     private static BigDecimal divideBigIntegers(BigInteger scaledDividend, BigInteger scaledDivisor, int scale, RoundingMode roundingMode) {
-        
+
         BigInteger[] quotAndRem = scaledDividend.divideAndRemainder(scaledDivisor);  // quotient and remainder
         // If after division there is a remainder...
         BigInteger quotient = quotAndRem[0];
@@ -1216,10 +1174,10 @@
             // To look if there is a carry
             compRem = roundingBehavior(quotient.testBit(0) ? 1 : 0,
                     sign * (5 + compRem), roundingMode);
-            
+
         } else {
-            // Checking if:  remainder * 2 >= scaledDivisor 
-            compRem = remainder.abs().shiftLeft(1).compareTo(scaledDivisor.abs());
+            // Checking if:  remainder * 2 >= scaledDivisor
+            compRem = remainder.abs().shiftLeftOneBit().compareTo(scaledDivisor.abs());
             compRem = roundingBehavior(quotient.testBit(0) ? 1 : 0,
                     sign * (5 + compRem), roundingMode);
         }
@@ -1233,7 +1191,7 @@
         // Constructing the result with the appropriate unscaled value
         return new BigDecimal(quotient, scale);
     }
-    
+
     private static BigDecimal dividePrimitiveLongs(long scaledDividend, long scaledDivisor, int scale, RoundingMode roundingMode) {
         long quotient = scaledDividend / scaledDivisor;
         long remainder = scaledDividend % scaledDivisor;
@@ -1256,7 +1214,7 @@
      * The scale of the result is the scale of {@code this}. If rounding is
      * required to meet the specified scale, then the specified rounding mode
      * {@code roundingMode} is applied.
-     * 
+     *
      * @param divisor
      *            value by which {@code this} is divided.
      * @param roundingMode
@@ -1272,7 +1230,6 @@
      * @throws ArithmeticException
      *             if {@code roundingMode == ROUND_UNNECESSARY} and rounding is
      *             necessary according to the scale of this.
-     * @since Android 1.0
      */
     public BigDecimal divide(BigDecimal divisor, int roundingMode) {
         return divide(divisor, scale, RoundingMode.valueOf(roundingMode));
@@ -1283,7 +1240,7 @@
      * The scale of the result is the scale of {@code this}. If rounding is
      * required to meet the specified scale, then the specified rounding mode
      * {@code roundingMode} is applied.
-     * 
+     *
      * @param divisor
      *            value by which {@code this} is divided.
      * @param roundingMode
@@ -1297,7 +1254,6 @@
      * @throws ArithmeticException
      *             if {@code roundingMode == RoundingMode.UNNECESSARY} and
      *             rounding is necessary according to the scale of this.
-     * @since Android 1.0
      */
     public BigDecimal divide(BigDecimal divisor, RoundingMode roundingMode) {
         return divide(divisor, scale, roundingMode);
@@ -1309,7 +1265,7 @@
      * and {@code divisor}. If the exact result requires more digits, then the
      * scale is adjusted accordingly. For example, {@code 1/128 = 0.0078125}
      * which has a scale of {@code 7} and precision {@code 5}.
-     * 
+     *
      * @param divisor
      *            value by which {@code this} is divided.
      * @return {@code this / divisor}.
@@ -1319,7 +1275,6 @@
      *             if {@code divisor == 0}.
      * @throws ArithmeticException
      *             if the result cannot be represented exactly.
-     * @since Android 1.0
      */
     public BigDecimal divide(BigDecimal divisor) {
         BigInteger p = this.getUnscaledValue();
@@ -1376,7 +1331,7 @@
         newScale = toIntScale(diffScale + Math.max(k, l));
         // k >= 0  and  l >= 0  implies that  k - l  is in the 32-bit range
         i = k - l;
-        
+
         p = (i > 0) ? Multiplication.multiplyByFivePow(p, i)
         : p.shiftLeft(-i);
         return new BigDecimal(p, newScale);
@@ -1387,7 +1342,7 @@
      * The result is rounded according to the passed context {@code mc}. If the
      * passed math context specifies precision {@code 0}, then this call is
      * equivalent to {@code this.divide(divisor)}.
-     * 
+     *
      * @param divisor
      *            value by which {@code this} is divided.
      * @param mc
@@ -1400,7 +1355,6 @@
      * @throws ArithmeticException
      *             if {@code mc.getRoundingMode() == UNNECESSARY} and rounding
      *             is necessary according {@code mc.getPrecision()}.
-     * @since Android 1.0
      */
     public BigDecimal divide(BigDecimal divisor, MathContext mc) {
         /* Calculating how many zeros must be append to 'dividend'
@@ -1410,7 +1364,7 @@
         long diffScale = (long)scale - divisor.scale;
         long newScale = diffScale; // scale of the final quotient
         int compRem; // to compare the remainder
-        int i = 1; // index   
+        int i = 1; // index
         int lastPow = TEN_POW.length - 1; // last power of ten
         BigInteger integerQuot; // for temporal results
         BigInteger quotAndRem[] = {getUnscaledValue()};
@@ -1429,7 +1383,7 @@
         // Calculating the exact quotient with at least 'mc.precision()' digits
         if (quotAndRem[1].signum() != 0) {
             // Checking if:   2 * remainder >= divisor ?
-            compRem = quotAndRem[1].shiftLeft(1).compareTo( divisor.getUnscaledValue() );
+            compRem = quotAndRem[1].shiftLeftOneBit().compareTo( divisor.getUnscaledValue() );
             // quot := quot * 10 + r;     with 'r' in {-6,-5,-4, 0,+4,+5,+6}
             integerQuot = integerQuot.multiply(BigInteger.TEN)
             .add(BigInteger.valueOf(quotAndRem[0].signum() * (5 + compRem)));
@@ -1461,7 +1415,7 @@
      * Returns a new {@code BigDecimal} whose value is the integral part of
      * {@code this / divisor}. The quotient is rounded down towards zero to the
      * next integer. For example, {@code 0.5/0.2 = 2}.
-     * 
+     *
      * @param divisor
      *            value by which {@code this} is divided.
      * @return integral part of {@code this / divisor}.
@@ -1469,7 +1423,6 @@
      *             if {@code divisor == null}.
      * @throws ArithmeticException
      *             if {@code divisor == 0}.
-     * @since Android 1.0
      */
     public BigDecimal divideToIntegralValue(BigDecimal divisor) {
         BigInteger integralValue; // the integer of result
@@ -1528,7 +1481,7 @@
      * next integer. The rounding mode passed with the parameter {@code mc} is
      * not considered. But if the precision of {@code mc > 0} and the integral
      * part requires more digits, then an {@code ArithmeticException} is thrown.
-     * 
+     *
      * @param divisor
      *            value by which {@code this} is divided.
      * @param mc
@@ -1542,7 +1495,6 @@
      * @throws ArithmeticException
      *             if {@code mc.getPrecision() > 0} and the result requires more
      *             digits to be represented.
-     * @since Android 1.0
      */
     public BigDecimal divideToIntegralValue(BigDecimal divisor, MathContext mc) {
         int mcPrecision = mc.getPrecision();
@@ -1560,22 +1512,22 @@
         if (quotPrecision <= 0) {
             quotAndRem[0] = BigInteger.ZERO;
         } else if (diffScale == 0) {
-            // CASE s1 == s2:  to calculate   u1 / u2 
+            // CASE s1 == s2:  to calculate   u1 / u2
             quotAndRem[0] = this.getUnscaledValue().divide( divisor.getUnscaledValue() );
         } else if (diffScale > 0) {
-            // CASE s1 >= s2:  to calculate   u1 / (u2 * 10^(s1-s2)  
+            // CASE s1 >= s2:  to calculate   u1 / (u2 * 10^(s1-s2)
             quotAndRem[0] = this.getUnscaledValue().divide(
                     divisor.getUnscaledValue().multiply(Multiplication.powerOf10(diffScale)) );
             // To chose  10^newScale  to get a quotient with at least 'mc.precision()' digits
             newScale = Math.min(diffScale, Math.max(mcPrecision - quotPrecision + 1, 0));
             // To calculate: (u1 / (u2 * 10^(s1-s2)) * 10^newScale
             quotAndRem[0] = quotAndRem[0].multiply(Multiplication.powerOf10(newScale));
-        } else {// CASE s2 > s1:   
-            /* To calculate the minimum power of ten, such that the quotient 
+        } else {// CASE s2 > s1:
+            /* To calculate the minimum power of ten, such that the quotient
              *   (u1 * 10^exp) / u2   has at least 'mc.precision()' digits. */
             long exp = Math.min(-diffScale, Math.max((long)mcPrecision - diffPrecision, 0));
             long compRemDiv;
-            // Let be:   (u1 * 10^exp) / u2 = [q,r]  
+            // Let be:   (u1 * 10^exp) / u2 = [q,r]
             quotAndRem = this.getUnscaledValue().multiply(Multiplication.powerOf10(exp)).
                     divideAndRemainder(divisor.getUnscaledValue());
             newScale += exp; // To fix the scale
@@ -1640,7 +1592,7 @@
      * <p>
      * The remainder is defined as {@code this -
      * this.divideToIntegralValue(divisor) * divisor}.
-     * 
+     *
      * @param divisor
      *            value by which {@code this} is divided.
      * @return {@code this % divisor}.
@@ -1648,7 +1600,6 @@
      *             if {@code divisor == null}.
      * @throws ArithmeticException
      *             if {@code divisor == 0}.
-     * @since Android 1.0
      */
     public BigDecimal remainder(BigDecimal divisor) {
         return divideAndRemainder(divisor)[1];
@@ -1661,7 +1612,7 @@
      * this.divideToIntegralValue(divisor) * divisor}.
      * <p>
      * The specified rounding mode {@code mc} is used for the division only.
-     * 
+     *
      * @param divisor
      *            value by which {@code this} is divided.
      * @param mc
@@ -1675,7 +1626,6 @@
      *             if {@code mc.getPrecision() > 0} and the result of {@code
      *             this.divideToIntegralValue(divisor, mc)} requires more digits
      *             to be represented.
-     * @since Android 1.0
      */
     public BigDecimal remainder(BigDecimal divisor, MathContext mc) {
         return divideAndRemainder(divisor, mc)[1];
@@ -1686,7 +1636,7 @@
      * {@code this / divisor} at index 0 and the remainder {@code this %
      * divisor} at index 1. The quotient is rounded down towards zero to the
      * next integer.
-     * 
+     *
      * @param divisor
      *            value by which {@code this} is divided.
      * @return {@code [this.divideToIntegralValue(divisor),
@@ -1697,7 +1647,6 @@
      *             if {@code divisor == 0}.
      * @see #divideToIntegralValue
      * @see #remainder
-     * @since Android 1.0
      */
     public BigDecimal[] divideAndRemainder(BigDecimal divisor) {
         BigDecimal quotAndRem[] = new BigDecimal[2];
@@ -1714,7 +1663,7 @@
      * next integer. The rounding mode passed with the parameter {@code mc} is
      * not considered. But if the precision of {@code mc > 0} and the integral
      * part requires more digits, then an {@code ArithmeticException} is thrown.
-     * 
+     *
      * @param divisor
      *            value by which {@code this} is divided.
      * @param mc
@@ -1728,7 +1677,6 @@
      *             if {@code divisor == 0}.
      * @see #divideToIntegralValue
      * @see #remainder
-     * @since Android 1.0
      */
     public BigDecimal[] divideAndRemainder(BigDecimal divisor, MathContext mc) {
         BigDecimal quotAndRem[] = new BigDecimal[2];
@@ -1746,13 +1694,12 @@
      * <p>
      * Implementation Note: The implementation is based on the ANSI standard
      * X3.274-1996 algorithm.
-     * 
+     *
      * @param n
      *            exponent to which {@code this} is raised.
      * @return {@code this ^ n}.
      * @throws ArithmeticException
      *             if {@code n < 0} or {@code n > 999999999}.
-     * @since Android 1.0
      */
     public BigDecimal pow(int n) {
         if (n == 0) {
@@ -1775,7 +1722,7 @@
      * <p>
      * Implementation Note: The implementation is based on the ANSI standard
      * X3.274-1996 algorithm.
-     * 
+     *
      * @param n
      *            exponent to which {@code this} is raised.
      * @param mc
@@ -1783,7 +1730,6 @@
      * @return {@code this ^ n}.
      * @throws ArithmeticException
      *             if {@code n < 0} or {@code n > 999999999}.
-     * @since Android 1.0
      */
     public BigDecimal pow(int n, MathContext mc) {
         // The ANSI standard X3.274-1996 algorithm
@@ -1807,7 +1753,7 @@
             newPrecision = new MathContext( mcPrecision + elength + 1,
                     mc.getRoundingMode());
         }
-        // The result is calculated as if 'n' were positive        
+        // The result is calculated as if 'n' were positive
         accum = round(newPrecision);
         oneBitMask = Integer.highestOneBit(m) >> 1;
 
@@ -1830,9 +1776,8 @@
     /**
      * Returns a new {@code BigDecimal} whose value is the absolute value of
      * {@code this}. The scale of the result is the same as the scale of this.
-     * 
+     *
      * @return {@code abs(this)}
-     * @since Android 1.0
      */
     public BigDecimal abs() {
         return ((signum() < 0) ? negate() : this);
@@ -1842,11 +1787,10 @@
      * Returns a new {@code BigDecimal} whose value is the absolute value of
      * {@code this}. The result is rounded according to the passed context
      * {@code mc}.
-     * 
+     *
      * @param mc
      *            rounding mode and precision for the result of this operation.
      * @return {@code abs(this)}
-     * @since Android 1.0
      */
     public BigDecimal abs(MathContext mc) {
         // BEGIN android-changed
@@ -1859,9 +1803,8 @@
     /**
      * Returns a new {@code BigDecimal} whose value is the {@code -this}. The
      * scale of the result is the same as the scale of this.
-     * 
+     *
      * @return {@code -this}
-     * @since Android 1.0
      */
     public BigDecimal negate() {
         if(bitLength < 63 || (bitLength == 63 && smallValue!=Long.MIN_VALUE)) {
@@ -1873,11 +1816,10 @@
     /**
      * Returns a new {@code BigDecimal} whose value is the {@code -this}. The
      * result is rounded according to the passed context {@code mc}.
-     * 
+     *
      * @param mc
      *            rounding mode and precision for the result of this operation.
      * @return {@code -this}
-     * @since Android 1.0
      */
     public BigDecimal negate(MathContext mc) {
         // BEGIN android-changed
@@ -1890,9 +1832,8 @@
     /**
      * Returns a new {@code BigDecimal} whose value is {@code +this}. The scale
      * of the result is the same as the scale of this.
-     * 
+     *
      * @return {@code this}
-     * @since Android 1.0
      */
     public BigDecimal plus() {
         return this;
@@ -1901,11 +1842,10 @@
     /**
      * Returns a new {@code BigDecimal} whose value is {@code +this}. The result
      * is rounded according to the passed context {@code mc}.
-     * 
+     *
      * @param mc
      *            rounding mode and precision for the result of this operation.
-     * @return {@code this}
-     * @since Android 1.0
+     * @return {@code this}, rounded
      */
     public BigDecimal plus(MathContext mc) {
         return round(mc);
@@ -1913,19 +1853,17 @@
 
     /**
      * Returns the sign of this {@code BigDecimal}.
-     * 
-     * @return {@code -1} if {@code this < 0}, 
+     *
+     * @return {@code -1} if {@code this < 0},
      *         {@code 0} if {@code this == 0},
-     *         {@code 1} if {@code this > 0}.
-     * @since Android 1.0
-     */
+     *         {@code 1} if {@code this > 0}.     */
     public int signum() {
         if( bitLength < 64) {
             return Long.signum( this.smallValue );
         }
         return getUnscaledValue().signum();
     }
-    
+
     private boolean isZero() {
         //Watch out: -1 has a bitLength=0
         return bitLength == 0 && this.smallValue != -1;
@@ -1936,9 +1874,8 @@
      * digits behind the decimal point. The value of this {@code BigDecimal} is
      * the unsignedValue * 10^(-scale). If the scale is negative, then this
      * {@code BigDecimal} represents a big integer.
-     * 
+     *
      * @return the scale of this {@code BigDecimal}.
-     * @since Android 1.0
      */
     public int scale() {
         return scale;
@@ -1949,9 +1886,8 @@
      * number of decimal digits used to represent this decimal. It is equivalent
      * to the number of digits of the unscaled value. The precision of {@code 0}
      * is {@code 1} (independent of the scale).
-     * 
+     *
      * @return the precision of this {@code BigDecimal}.
-     * @since Android 1.0
      */
     public int precision() {
         // Checking if the precision already was calculated
@@ -1987,9 +1923,8 @@
      * Returns the unscaled value (mantissa) of this {@code BigDecimal} instance
      * as a {@code BigInteger}. The unscaled value can be computed as {@code
      * this} 10^(scale).
-     * 
+     *
      * @return unscaled value (this * 10^(scale)).
-     * @since Android 1.0
      */
     public BigInteger unscaledValue() {
         return getUnscaledValue();
@@ -2004,7 +1939,7 @@
      * If {@code mc.precision > 0} and {@code mc.roundingMode == UNNECESSARY},
      * then an {@code ArithmeticException} is thrown if the result cannot be
      * represented exactly within the given precision.
-     * 
+     *
      * @param mc
      *            rounding mode and precision for the result of this operation.
      * @return {@code this} rounded according to the passed context.
@@ -2012,7 +1947,6 @@
      *             if {@code mc.precision > 0} and {@code mc.roundingMode ==
      *             UNNECESSARY} and this cannot be represented within the given
      *             precision.
-     * @since Android 1.0
      */
     public BigDecimal round(MathContext mc) {
         BigDecimal thisBD = new BigDecimal(getUnscaledValue(), scale);
@@ -2031,7 +1965,7 @@
      * removed. If these trailing digits are not zero, then the remaining
      * unscaled value has to be rounded. For this rounding operation the
      * specified rounding mode is used.
-     * 
+     *
      * @param newScale
      *            scale of the result returned.
      * @param roundingMode
@@ -2042,14 +1976,13 @@
      * @throws ArithmeticException
      *             if {@code roundingMode == ROUND_UNNECESSARY} and rounding is
      *             necessary according to the given scale.
-     * @since Android 1.0
      */
     public BigDecimal setScale(int newScale, RoundingMode roundingMode) {
         if (roundingMode == null) {
             throw new NullPointerException();
         }
         long diffScale = newScale - (long)scale;
-        // Let be:  'this' = [u,s]        
+        // Let be:  'this' = [u,s]
         if(diffScale == 0) {
             return this;
         }
@@ -2079,7 +2012,7 @@
      * removed. If these trailing digits are not zero, then the remaining
      * unscaled value has to be rounded. For this rounding operation the
      * specified rounding mode is used.
-     * 
+     *
      * @param newScale
      *            scale of the result returned.
      * @param roundingMode
@@ -2090,7 +2023,6 @@
      * @throws ArithmeticException
      *             if {@code roundingMode == ROUND_UNNECESSARY} and rounding is
      *             necessary according to the given scale.
-     * @since Android 1.0
      */
     public BigDecimal setScale(int newScale, int roundingMode) {
         return setScale(newScale, RoundingMode.valueOf(roundingMode));
@@ -2105,13 +2037,12 @@
      * <p>
      * If no exception is thrown, then the following equation holds: {@code
      * x.setScale(s).compareTo(x) == 0}.
-     * 
+     *
      * @param newScale
      *            scale of the result returned.
      * @return a new {@code BigDecimal} instance with the specified scale.
      * @throws ArithmeticException
      *             if rounding would be necessary.
-     * @since Android 1.0
      */
     public BigDecimal setScale(int newScale) {
         return setScale(newScale, RoundingMode.UNNECESSARY);
@@ -2128,11 +2059,10 @@
      * <p>
      * Note, that {@code movePointLeft(0)} returns a result which is
      * mathematically equivalent, but which has {@code scale >= 0}.
-     * 
+     *
      * @param n
      *            number of placed the decimal point has to be moved.
-     * @return {@code this} 10^({@code -n}).
-     * @since Android 1.0
+     * @return {@code this * 10^(-n}).
      */
     public BigDecimal movePointLeft(int n) {
         return movePoint(scale + (long)n);
@@ -2170,11 +2100,10 @@
      * <p>
      * Note, that {@code movePointRight(0)} returns a result which is
      * mathematically equivalent, but which has scale >= 0.
-     * 
+     *
      * @param n
      *            number of placed the decimal point has to be moved.
-     * @return {@code this} 10^{@code n}.
-     * @since Android 1.0
+     * @return {@code this * 10^n}.
      */
     public BigDecimal movePointRight(int n) {
         return movePoint(scale - (long)n);
@@ -2182,16 +2111,15 @@
 
     /**
      * Returns a new {@code BigDecimal} whose value is {@code this} 10^{@code n}.
-     * The scale of the result is {@code this.scale()} - {@code n}. 
+     * The scale of the result is {@code this.scale()} - {@code n}.
      * The precision of the result is the precision of {@code this}.
      * <p>
      * This method has the same effect as {@link #movePointRight}, except that
      * the precision is not changed.
-     * 
+     *
      * @param n
      *            number of places the decimal point has to be moved.
-     * @return {@code this} 10^{@code n}
-     * @since Android 1.0
+     * @return {@code this * 10^n}
      */
     public BigDecimal scaleByPowerOfTen(int n) {
         long newScale = scale - (long)n;
@@ -2210,10 +2138,9 @@
      * this} but with a unscaled value where the trailing zeros have been
      * removed. If the unscaled value of {@code this} has n trailing zeros, then
      * the scale and the precision of the result has been reduced by n.
-     * 
+     *
      * @return a new {@code BigDecimal} instance equivalent to this where the
      *         trailing zeros of the unscaled value have been removed.
-     * @since Android 1.0
      */
     public BigDecimal stripTrailingZeros() {
         int i = 1; // 1 <= i <= 18
@@ -2221,13 +2148,11 @@
         long newScale = scale;
 
         if (isZero()) {
-            // BEGIN android-changed
             return new BigDecimal("0");
-            // END android-changed
         }
         BigInteger strippedBI = getUnscaledValue();
         BigInteger[] quotAndRem;
-        
+
         // while the number is even...
         while (!strippedBI.testBit(0)) {
             // To divide by 10^i
@@ -2261,14 +2186,13 @@
      * difference is 0 then 0 is returned. This means, that if two decimal
      * instances are compared which are equal in value but differ in scale, then
      * these two instances are considered as equal.
-     * 
+     *
      * @param val
      *            value to be compared with {@code this}.
      * @return {@code 1} if {@code this > val}, {@code -1} if {@code this < val},
      *         {@code 0} if {@code this == val}.
      * @throws NullPointerException
      *             if {@code val == null}.
-     * @since Android 1.0
      */
     public int compareTo(BigDecimal val) {
         int thisSign = signum();
@@ -2308,37 +2232,35 @@
      * their unscaled value and their scale is equal. For example, 1.0
      * (10*10^(-1)) is not equal to 1.00 (100*10^(-2)). Similarly, zero
      * instances are not equal if their scale differs.
-     * 
+     *
      * @param x
      *            object to be compared with {@code this}.
      * @return true if {@code x} is a {@code BigDecimal} and {@code this == x}.
-     * @since Android 1.0
      */
     @Override
-    public boolean equals(Object x) {        
+    public boolean equals(Object x) {
         if (this == x) {
             return true;
         }
         if (x instanceof BigDecimal) {
-            BigDecimal x1 = (BigDecimal) x;            
-            return x1.scale == scale                   
+            BigDecimal x1 = (BigDecimal) x;
+            return x1.scale == scale
                    && (bitLength < 64 ? (x1.smallValue == smallValue)
                     : intVal.equals(x1.intVal));
-                        
-             
-        } 
-        return false;       
-    }   
+
+
+        }
+        return false;
+    }
 
     /**
      * Returns the minimum of this {@code BigDecimal} and {@code val}.
-     * 
+     *
      * @param val
      *            value to be used to compute the minimum with this.
      * @return {@code min(this, val}.
      * @throws NullPointerException
      *             if {@code val == null}.
-     * @since Android 1.0
      */
     public BigDecimal min(BigDecimal val) {
         return ((compareTo(val) <= 0) ? this : val);
@@ -2346,13 +2268,12 @@
 
     /**
      * Returns the maximum of this {@code BigDecimal} and {@code val}.
-     * 
+     *
      * @param val
      *            value to be used to compute the maximum with this.
      * @return {@code max(this, val}.
      * @throws NullPointerException
      *             if {@code val == null}.
-     * @since Android 1.0
      */
     public BigDecimal max(BigDecimal val) {
         return ((compareTo(val) >= 0) ? this : val);
@@ -2360,23 +2281,22 @@
 
     /**
      * Returns a hash code for this {@code BigDecimal}.
-     * 
+     *
      * @return hash code for {@code this}.
-     * @since Android 1.0
      */
     @Override
-    public int hashCode() {        
+    public int hashCode() {
         if (hashCode != 0) {
             return hashCode;
         }
         if (bitLength < 64) {
             hashCode = (int)(smallValue & 0xffffffff);
             hashCode = 33 * hashCode +  (int)((smallValue >> 32) & 0xffffffff);
-            hashCode = 17 * hashCode + scale;           
+            hashCode = 17 * hashCode + scale;
             return hashCode;
         }
-        hashCode = 17 * intVal.hashCode() + scale;        
-        return hashCode;        
+        hashCode = 17 * intVal.hashCode() + scale;
+        return hashCode;
     }
 
     /**
@@ -2386,10 +2306,9 @@
      * <p>
      * If the scale is negative or if {@code scale - precision >= 6} then
      * scientific notation is used.
-     * 
+     *
      * @return a string representation of {@code this} in scientific notation if
      *         necessary.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -2440,10 +2359,9 @@
      * engineering notation is used. Engineering notation is similar to the
      * scientific notation except that the exponent is made to be a multiple of
      * 3 such that the integer part is >= 1 and < 1000.
-     * 
+     *
      * @return a string representation of {@code this} in engineering notation
      *         if necessary.
-     * @since Android 1.0
      */
     public String toEngineeringString() {
         String intString = getUnscaledValue().toString();
@@ -2511,9 +2429,8 @@
      * {@code false}.
      * <p>
      * {@code x.compareTo(new BigDecimal(x.toPlainString())} returns {@code 0}.
-     * 
+     *
      * @return a string representation of {@code this} without exponent part.
-     * @since Android 1.0
      */
     public String toPlainString() {
         String intStr = getUnscaledValue().toString();
@@ -2526,7 +2443,7 @@
         StringBuffer result = new StringBuffer(intStr.length() + 1 + Math.abs(scale));
 
         if (begin == 1) {
-            // If the number is negative, we insert a '-' character at front 
+            // If the number is negative, we insert a '-' character at front
             result.append('-');
         }
         if (scale > 0) {
@@ -2559,9 +2476,8 @@
     /**
      * Returns this {@code BigDecimal} as a big integer instance. A fractional
      * part is discarded.
-     * 
+     *
      * @return this {@code BigDecimal} as a big integer instance.
-     * @since Android 1.0
      */
     public BigInteger toBigInteger() {
         if ((scale == 0) || (isZero())) {
@@ -2577,11 +2493,10 @@
      * Returns this {@code BigDecimal} as a big integer instance if it has no
      * fractional part. If this {@code BigDecimal} has a fractional part, i.e.
      * if rounding would be necessary, an {@code ArithmeticException} is thrown.
-     * 
+     *
      * @return this {@code BigDecimal} as a big integer value.
      * @throws ArithmeticException
      *             if rounding is necessary.
-     * @since Android 1.0
      */
     public BigInteger toBigIntegerExact() {
         if ((scale == 0) || (isZero())) {
@@ -2597,7 +2512,7 @@
             }
             integerAndFraction = getUnscaledValue().divideAndRemainder(Multiplication.powerOf10(scale));
             if (integerAndFraction[1].signum() != 0) {
-                // It exists a non-zero fractional part 
+                // It exists a non-zero fractional part
                 // math.08=Rounding necessary
                 throw new ArithmeticException(Messages.getString("math.08")); //$NON-NLS-1$
             }
@@ -2609,9 +2524,8 @@
      * Returns this {@code BigDecimal} as an long value. Any fractional part is
      * discarded. If the integral part of {@code this} is too big to be
      * represented as an long, then {@code this} % 2^64 is returned.
-     * 
+     *
      * @return this {@code BigDecimal} as a long value.
-     * @since Android 1.0
      */
     @Override
     public long longValue() {
@@ -2628,11 +2542,10 @@
      * Returns this {@code BigDecimal} as a long value if it has no fractional
      * part and if its value fits to the int range ([-2^{63}..2^{63}-1]). If
      * these conditions are not met, an {@code ArithmeticException} is thrown.
-     * 
+     *
      * @return this {@code BigDecimal} as a long value.
      * @throws ArithmeticException
      *             if rounding is necessary or the number doesn't fit in a long.
-     * @since Android 1.0
      */
     public long longValueExact() {
         return valueExact(64);
@@ -2642,9 +2555,8 @@
      * Returns this {@code BigDecimal} as an int value. Any fractional part is
      * discarded. If the integral part of {@code this} is too big to be
      * represented as an int, then {@code this} % 2^32 is returned.
-     * 
+     *
      * @return this {@code BigDecimal} as a int value.
-     * @since Android 1.0
      */
     @Override
     public int intValue() {
@@ -2662,11 +2574,10 @@
      * Returns this {@code BigDecimal} as a int value if it has no fractional
      * part and if its value fits to the int range ([-2^{31}..2^{31}-1]). If
      * these conditions are not met, an {@code ArithmeticException} is thrown.
-     * 
+     *
      * @return this {@code BigDecimal} as a int value.
      * @throws ArithmeticException
      *             if rounding is necessary or the number doesn't fit in a int.
-     * @since Android 1.0
      */
     public int intValueExact() {
         return (int)valueExact(32);
@@ -2676,12 +2587,11 @@
      * Returns this {@code BigDecimal} as a short value if it has no fractional
      * part and if its value fits to the short range ([-2^{15}..2^{15}-1]). If
      * these conditions are not met, an {@code ArithmeticException} is thrown.
-     * 
+     *
      * @return this {@code BigDecimal} as a short value.
      * @throws ArithmeticException
      *             if rounding is necessary of the number doesn't fit in a
      *             short.
-     * @since Android 1.0
      */
     public short shortValueExact() {
         return (short)valueExact(16);
@@ -2691,11 +2601,10 @@
      * Returns this {@code BigDecimal} as a byte value if it has no fractional
      * part and if its value fits to the byte range ([-128..127]). If these
      * conditions are not met, an {@code ArithmeticException} is thrown.
-     * 
+     *
      * @return this {@code BigDecimal} as a byte value.
      * @throws ArithmeticException
      *             if rounding is necessary or the number doesn't fit in a byte.
-     * @since Android 1.0
      */
     public byte byteValueExact() {
         return (byte)valueExact(8);
@@ -2716,9 +2625,8 @@
      * <p>
      * Similarly, if the instance {@code new BigDecimal(16777217)} is converted
      * to a float, the result is {@code 1.6777216E}7.
-     * 
+     *
      * @return this {@code BigDecimal} as a float value.
-     * @since Android 1.0
      */
     @Override
     public float floatValue() {
@@ -2754,9 +2662,8 @@
      * Similarly, if the instance {@code new BigDecimal(9007199254740993L)} is
      * converted to a double, the result is {@code 9.007199254740992E15}.
      * <p>
-     * 
+     *
      * @return this {@code BigDecimal} as a double value.
-     * @since Android 1.0
      */
     @Override
     public double doubleValue() {
@@ -2766,14 +2673,14 @@
         int discardedSize;
         long powerOfTwo = this.bitLength - (long)(scale / LOG10_2);
         long bits; // IEEE-754 Standard
-        long tempBits; // for temporal calculations     
+        long tempBits; // for temporal calculations
         BigInteger mantisa;
 
         if ((powerOfTwo < -1074) || (sign == 0)) {
-            // Cases which 'this' is very small            
+            // Cases which 'this' is very small
             return (sign * 0.0d);
         } else if (powerOfTwo > 1025) {
-            // Cases which 'this' is very large            
+            // Cases which 'this' is very large
             return (sign * Double.POSITIVE_INFINITY);
         }
         mantisa = getUnscaledValue().abs();
@@ -2796,7 +2703,7 @@
             // Computing (mantisa * 2^k) / 10^s
             quotAndRem = mantisa.divideAndRemainder(powerOfTen);
             // To check if the fractional part >= 0.5
-            compRem = quotAndRem[1].shiftLeft(1).compareTo(powerOfTen);
+            compRem = quotAndRem[1].shiftLeftOneBit().compareTo(powerOfTen);
             // To add two rounded bits at end of mantisa
             mantisa = quotAndRem[0].shiftLeft(2).add(
                     BigInteger.valueOf((compRem * (compRem + 3)) / 2 + 1));
@@ -2808,13 +2715,13 @@
             // mantisa = (abs(u) * 10^s) >> (n - 54)
             bits = mantisa.shiftRight(discardedSize).longValue();
             tempBits = bits;
-            // #bits = 54, to check if the discarded fraction produces a carry             
+            // #bits = 54, to check if the discarded fraction produces a carry
             if ((((bits & 1) == 1) && (lowestSetBit < discardedSize))
                     || ((bits & 3) == 3)) {
                 bits += 2;
             }
         } else {// (n <= 54)
-            // mantisa = (abs(u) * 10^s) << (54 - n)                
+            // mantisa = (abs(u) * 10^s) << (54 - n)
             bits = mantisa.longValue() << -discardedSize;
             tempBits = bits;
             // #bits = 54, to check if the discarded fraction produces a carry:
@@ -2832,7 +2739,7 @@
             bits >>= 2;
             exponent += discardedSize + 1;
         }
-        // To test if the 53-bits number fits in 'double'            
+        // To test if the 53-bits number fits in 'double'
         if (exponent > 2046) {// (exponent - bias > 1023)
             return (sign * Double.POSITIVE_INFINITY);
         } else if (exponent <= 0) {// (exponent - bias <= -1023)
@@ -2840,7 +2747,7 @@
             if (exponent < -53) {// exponent - bias < -1076
                 return (sign * 0.0d);
             }
-            // -1076 <= exponent - bias <= -1023 
+            // -1076 <= exponent - bias <= -1023
             // To discard '- exponent + 1' bits
             bits = tempBits >> 1;
             tempBits = bits & (-1L >>> (63 + exponent));
@@ -2871,9 +2778,8 @@
      * For class {@code BigDecimal}, the ULP of a number is simply 10^(-scale).
      * <p>
      * For example, {@code new BigDecimal(0.1).ulp()} returns {@code 1E-55}.
-     * 
+     *
      * @return unit in the last place (ULP) of this {@code BigDecimal} instance.
-     * @since Android 1.0
      */
     public BigDecimal ulp() {
         return valueOf(1, scale);
@@ -2885,7 +2791,7 @@
      * It does all rounding work of the public method
      * {@code round(MathContext)}, performing an inplace rounding
      * without creating a new object.
-     * 
+     *
      * @param mc
      *            the {@code MathContext} for perform the rounding.
      * @see #round(MathContext)
@@ -2916,7 +2822,7 @@
         // If the discarded fraction is non-zero, perform rounding
         if (integerAndFraction[1].signum() != 0) {
             // To check if the discarded fraction >= 0.5
-            compRem = (integerAndFraction[1].abs().shiftLeft(1).compareTo(sizeOfFraction));
+            compRem = (integerAndFraction[1].abs().shiftLeftOneBit().compareTo(sizeOfFraction));
             // To look if there is a carry
             compRem =  roundingBehavior( integerAndFraction[0].testBit(0) ? 1 : 0,
                     integerAndFraction[1].signum() * (5 + compRem),
@@ -2943,7 +2849,7 @@
     /**
      * This method implements an efficient rounding for numbers which unscaled
      * value fits in the type {@code long}.
-     * 
+     *
      * @param mc
      *            the context to use
      * @param discardedPrecision
@@ -2983,7 +2889,7 @@
     /**
      * Return an increment that can be -1,0 or 1, depending of
      * {@code roundingMode}.
-     * 
+     *
      * @param parityBit
      *            can be 0 or 1, it's only used in the case
      *            {@code HALF_EVEN}
@@ -3039,7 +2945,7 @@
      * the range of the primitive type. If the number fits in the primitive type
      * returns this number as {@code long}, otherwise throws an
      * exception.
-     * 
+     *
      * @param bitLengthOfType
      *            number of bits of the type whose value will be calculated
      *            exactly
@@ -3064,7 +2970,7 @@
      * it calculates a very good approximation efficiently . Note that this
      * value will be {@code precision()} or {@code precision()-1}
      * in the worst case.
-     * 
+     *
      * @return an approximation of {@code precision()} value
      */
     private int aproxPrecision() {
@@ -3079,7 +2985,7 @@
      * It tests if a scale of type {@code long} fits in 32 bits. It
      * returns the same scale being casted to {@code int} type when is
      * possible, otherwise throws an exception.
-     * 
+     *
      * @param longScale
      *            a 64 bit scale
      * @return a 32 bit scale when is possible
@@ -3106,7 +3012,7 @@
      * {@code longScale < Integer.MIN_VALUE} the scale will be
      * {@code Integer.MIN_VALUE}; otherwise {@code longScale} is
      * casted to the type {@code int}.
-     * 
+     *
      * @param longScale
      *            the scale to which the value 0 will be scaled.
      * @return the value 0 scaled by the closer scale of type {@code int}.
@@ -3152,7 +3058,7 @@
         }
         return intVal;
     }
-    
+
     private void setUnscaledValue(BigInteger unscaledValue) {
         this.intVal = unscaledValue;
         this.bitLength = unscaledValue.bitLength();
@@ -3160,19 +3066,19 @@
             this.smallValue = unscaledValue.longValue();
         }
     }
-    
+
     private static int bitLength(long smallValue) {
         if(smallValue < 0) {
             smallValue = ~smallValue;
         }
         return 64 - Long.numberOfLeadingZeros(smallValue);
     }
-    
+
     private static int bitLength(int smallValue) {
         if(smallValue < 0) {
             smallValue = ~smallValue;
         }
         return 32 - Integer.numberOfLeadingZeros(smallValue);
     }
-    
+
 }
diff --git a/libcore/math/src/main/java/java/math/BigInteger.java b/libcore/math/src/main/java/java/math/BigInteger.java
index aece078..c463b48 100644
--- a/libcore/math/src/main/java/java/math/BigInteger.java
+++ b/libcore/math/src/main/java/java/math/BigInteger.java
@@ -14,21 +14,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
 
 // BEGIN android-note
 // Since the original Harmony Code of the BigInteger class was strongly modified,
@@ -63,8 +48,6 @@
  * <b>Implementation Note:</b> <br>
  * The native OpenSSL library with its BIGNUM operations covers all the
  * meaningful functionality (everything but bit level operations).
- * 
- * @since Android 1.0
  */
 public class BigInteger extends Number implements Comparable<BigInteger>,
         Serializable {
@@ -139,34 +122,24 @@
     /** The magnitude of this in the little-endian representation. */
     transient int digits[];
 
-    /**
-     * The length of this in measured in ints. Can be less than digits.length().
-     */
+    /** The length of this in measured in ints. Can be less than digits.length(). */
     transient int numberLength;
 
     /** The sign of this. */
     transient int sign;
 
-    /* Static Fields */
-
     /**
      * The {@code BigInteger} constant 0.
-     * 
-     * @since Android 1.0
      */
     public static final BigInteger ZERO = new BigInteger(0, 0);
 
     /**
      * The {@code BigInteger} constant 1.
-     * 
-     * @since Android 1.0
      */
     public static final BigInteger ONE = new BigInteger(1, 1);
 
     /**
      * The {@code BigInteger} constant 10.
-     * 
-     * @since Android 1.0
      */
     public static final BigInteger TEN = new BigInteger(1, 10);
 
@@ -191,8 +164,6 @@
     /**/
     private transient int firstNonzeroDigit = -2;
     
-    /* Serialized Fields */
-
     /** sign field, used for serialization. */
     private int signum;
 
@@ -202,9 +173,6 @@
     /** Cache for the hash code. */
     private transient int hashCode = 0;
 
-
-    /* Package Constructors */
-
     BigInteger(BigInt a) {
         bigInt = a;
         bigIntIsValid = true;
@@ -239,9 +207,6 @@
         withNewRepresentation("BigInteger(int sign, int numberLength, int[] digits)");
     }
 
-
-    /* Public Constructors */
-
     /**
      * Constructs a random non-negative {@code BigInteger} instance in the range
      * [0, 2^(numBits)-1].
@@ -252,8 +217,6 @@
      *            is an optional random generator to be used.
      * @throws IllegalArgumentException
      *             if {@code numBits} < 0.
-     * 
-     * @since Android 1.0
      */
     public BigInteger(int numBits, Random rnd) {
         if (numBits < 0) {
@@ -299,8 +262,6 @@
      *            is an optional random generator to be used.
      * @throws ArithmeticException
      *             if {@code bitLength} < 2.
-     * 
-     * @since Android 1.0
      */
     public BigInteger(int bitLength, int certainty, Random rnd) {
         if (bitLength < 2) {
@@ -324,8 +285,6 @@
      * @throws NumberFormatException
      *             if {@code val} is not a valid representation of a {@code
      *             BigInteger}.
-     * 
-     * @since Android 1.0
      */
     public BigInteger(String val) {
         bigInt = new BigInt();
@@ -351,8 +310,6 @@
      *             if {@code val} is not a valid representation of a {@code
      *             BigInteger} or if {@code radix < Character.MIN_RADIX} or
      *             {@code radix > Character.MAX_RADIX}.
-     *             
-     * @since Android 1.0
      */
     public BigInteger(String val, int radix) {
         if (val == null) {
@@ -399,8 +356,6 @@
      * @throws NumberFormatException
      *             if the sign is not one of -1, 0, 1 or if the sign is zero and
      *             the magnitude contains non-zero entries.
-     *             
-     * @since Android 1.0
      */
     public BigInteger(int signum, byte[] magnitude) {
         if (magnitude == null) {
@@ -435,8 +390,6 @@
      *             if {@code val == null}.
      * @throws NumberFormatException
      *             if the length of {@code val} is zero.
-     *             
-     * @since Android 1.0
      */
     public BigInteger(byte[] val) {
         if (val.length == 0) {
@@ -449,8 +402,6 @@
     }
 
 
-    /* Public Methods */
-
     /**
      * Creates a new {@code BigInteger} whose value is equal to the specified
      * {@code long} argument.
@@ -458,8 +409,6 @@
      * @param val
      *            the value of the new {@code BigInteger}.
      * @return {@code BigInteger} instance with the value {@code val}.
-     * 
-     * @since Android 1.0
      */
     public static BigInteger valueOf(long val) {
         if (val < 0) {
@@ -479,8 +428,6 @@
      * array.
      * 
      * @return two's complement representation of {@code this}.
-     * 
-     * @since Android 1.0
      */
     public byte[] toByteArray() {
         return twosComplement();
@@ -491,8 +438,6 @@
      * {@code this}.
      * 
      * @return {@code abs(this)}.
-     * 
-     * @since Android 1.0
      */
     public BigInteger abs() {
         validate1("abs()", this);
@@ -508,8 +453,6 @@
      * Returns a new {@code BigInteger} whose value is the {@code -this}.
      * 
      * @return {@code -this}.
-     * 
-     * @since Android 1.0
      */
     public BigInteger negate() {
         validate1("negate()", this);
@@ -530,8 +473,6 @@
      * @return {@code this + val}.
      * @throws NullPointerException
      *             if {@code val == null}.
-     *             
-     * @since Android 1.0
      */
     public BigInteger add(BigInteger val) {
         validate2("add", this, val);
@@ -548,8 +489,6 @@
      * @return {@code this - val}.
      * @throws NullPointerException
      *             if {@code val == null}.
-     *             
-     * @since Android 1.0
      */
     public BigInteger subtract(BigInteger val) {
         validate2("subtract", this, val);
@@ -563,8 +502,6 @@
      * @return {@code -1} if {@code this < 0}, 
      *         {@code 0} if {@code this == 0},
      *         {@code 1} if {@code this > 0}.
-     *         
-     * @since Android 1.0
      */
     public int signum() {
      // Optimization to avoid unnecessary duplicate representation:
@@ -586,8 +523,6 @@
      *            shift distance
      * @return {@code this >> n} if {@code n >= 0}; {@code this << (-n)}
      *         otherwise
-     *         
-     * @since Android 1.0
      */
     public BigInteger shiftRight(int n) {
         return shiftLeft(-n);
@@ -606,8 +541,6 @@
      *            shift distance.
      * @return {@code this << n} if {@code n >= 0}; {@code this >> (-n)}.
      *         otherwise
-     * 
-     * @since Android 1.0
      */
     public BigInteger shiftLeft(int n) {
         if (n == 0) return this;
@@ -626,6 +559,10 @@
         }
     }
 
+    BigInteger shiftLeftOneBit() {
+        return (signum() == 0) ? this : BitLevel.shiftLeftOneBit(this);
+    }
+
     /**
      * Returns the length of the value's two's complement representation without
      * leading zeros for positive numbers / without leading ones for negative
@@ -639,8 +576,6 @@
      * 
      * @return the length of the minimal two's complement representation for
      *         {@code this} without the sign bit.
-     * 
-     * @since Android 1.0
      */
     public int bitLength() {
      // Optimization to avoid unnecessary duplicate representation:
@@ -662,8 +597,6 @@
      * @return {@code this & (2^n) != 0}.
      * @throws ArithmeticException
      *             if {@code n < 0}.
-     * 
-     * @since Android 1.0
      */
     public boolean testBit(int n) {
         if (n < 0) {
@@ -717,8 +650,6 @@
      * @return {@code this | 2^n}.
      * @throws ArithmeticException
      *             if {@code n < 0}.
-     * 
-     * @since Android 1.0
      */
     public BigInteger setBit(int n) {
         establishOldRepresentation("setBit");
@@ -742,8 +673,6 @@
      * @return {@code this & ~(2^n)}.
      * @throws ArithmeticException
      *             if {@code n < 0}.
-     * 
-     * @since Android 1.0
      */
     public BigInteger clearBit(int n) {
         establishOldRepresentation("clearBit");
@@ -767,8 +696,6 @@
      * @return {@code this ^ 2^n}.
      * @throws ArithmeticException
      *             if {@code n < 0}.
-     * 
-     * @since Android 1.0
      */
     public BigInteger flipBit(int n) {
         establishOldRepresentation("flipBit");
@@ -788,8 +715,6 @@
      * the current implementation is not efficient.
      * 
      * @return position of lowest bit if {@code this != 0}, {@code -1} otherwise
-     * 
-     * @since Android 1.0
      */
     public int getLowestSetBit() {
         establishOldRepresentation("getLowestSetBit");
@@ -816,8 +741,6 @@
      * 
      * @return number of bits in the binary representation of {@code this} which
      *         differ from the sign bit
-     * 
-     * @since Android 1.0
      */
     public int bitCount() {
         establishOldRepresentation("bitCount");
@@ -832,8 +755,6 @@
      * the current implementation is not efficient.
      * 
      * @return {@code ~this}.
-     * 
-     * @since Android 1.0
      */
     public BigInteger not() {
         this.establishOldRepresentation("not");
@@ -851,8 +772,6 @@
      * @return {@code this & val}.
      * @throws NullPointerException
      *             if {@code val == null}.
-     * 
-     * @since Android 1.0
      */
     public BigInteger and(BigInteger val) {
         this.establishOldRepresentation("and1");
@@ -871,8 +790,6 @@
      * @return {@code this | val}.
      * @throws NullPointerException
      *             if {@code val == null}.
-     * 
-     * @since Android 1.0
      */
     public BigInteger or(BigInteger val) {
         this.establishOldRepresentation("or1");
@@ -891,8 +808,6 @@
      * @return {@code this ^ val}
      * @throws NullPointerException
      *             if {@code val == null}
-     * 
-     * @since Android 1.0
      */
     public BigInteger xor(BigInteger val) {
         this.establishOldRepresentation("xor1");
@@ -913,8 +828,6 @@
      * @return {@code this & ~val}.
      * @throws NullPointerException
      *             if {@code val == null}.
-     * 
-     * @since Android 1.0
      */
     public BigInteger andNot(BigInteger val) {
         this.establishOldRepresentation("andNot1");
@@ -927,8 +840,6 @@
      * big to be represented as an int, then {@code this} % 2^32 is returned.
      * 
      * @return this {@code BigInteger} as an int value.
-     * 
-     * @since Android 1.0
      */
     @Override
     public int intValue() {
@@ -946,8 +857,6 @@
      * big to be represented as an long, then {@code this} % 2^64 is returned.
      * 
      * @return this {@code BigInteger} as a long value.
-     * 
-     * @since Android 1.0
      */
     @Override
     public long longValue() {
@@ -972,8 +881,6 @@
      * 24. For example, 2^24+1 = 16777217 is returned as float 16777216.0.
      * 
      * @return this {@code BigInteger} as a float value.
-     *
-     * @since Android 1.0
      */
     @Override
     public float floatValue() {
@@ -991,8 +898,6 @@
      * 9007199254740993 is returned as double 9007199254740992.0.
      * 
      * @return this {@code BigInteger} as a double value
-     * 
-     * @since Android 1.0
      */
     @Override
     public double doubleValue() {
@@ -1010,8 +915,6 @@
      *         , {@code 0} if {@code this == val}.
      * @throws NullPointerException
      *             if {@code val == null}.
-     * 
-     * @since Android 1.0
      */
     public int compareTo(BigInteger val) {
         validate2("compareTo", this, val);
@@ -1026,8 +929,6 @@
      * @return {@code min(this, val)}.
      * @throws NullPointerException
      *             if {@code val == null}.
-     * 
-     * @since Android 1.0
      */
     public BigInteger min(BigInteger val) {
         return ((this.compareTo(val) == -1) ? this : val);
@@ -1041,8 +942,6 @@
      * @return {@code max(this, val)}
      * @throws NullPointerException
      *             if {@code val == null}
-     * 
-     * @since Android 1.0
      */
     public BigInteger max(BigInteger val) {
         return ((this.compareTo(val) == 1) ? this : val);
@@ -1052,8 +951,6 @@
      * Returns a hash code for this {@code BigInteger}.
      * 
      * @return hash code for {@code this}.
-     * 
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -1077,8 +974,6 @@
      *            object to be compared with {@code this}.
      * @return true if {@code x} is a BigInteger and {@code this == x}, 
      *          {@code false} otherwise.
-     * 
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object x) {
@@ -1096,8 +991,6 @@
      * form.
      * 
      * @return a string representation of {@code this} in decimal form.
-     * 
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -1115,8 +1008,6 @@
      * @param radix
      *            base to be used for the string representation.
      * @return a string representation of this with radix 10.
-     * 
-     * @since Android 1.0
      */
     public String toString(int radix) {
         validate1("toString(int radix)", this);
@@ -1140,8 +1031,6 @@
      * @return {@code gcd(this, val)}.
      * @throws NullPointerException
      *             if {@code val == null}.
-     * 
-     * @since Android 1.0
      */
     public BigInteger gcd(BigInteger val) {
         validate2("gcd", this, val);
@@ -1156,8 +1045,6 @@
      * @return {@code this * val}.
      * @throws NullPointerException
      *             if {@code val == null}.
-     * 
-     * @since Android 1.0
      */
     public BigInteger multiply(BigInteger val) {
         validate2("multiply", this, val);
@@ -1172,8 +1059,6 @@
      * @return {@code this ^ exp}.
      * @throws ArithmeticException
      *             if {@code exp < 0}.
-     * 
-     * @since Android 1.0
      */
     public BigInteger pow(int exp) {
         if (exp < 0) {
@@ -1197,8 +1082,6 @@
      *             if {@code divisor == 0}.
      * @see #divide
      * @see #remainder
-     *
-@since Android 1.0
      */
     public BigInteger[] divideAndRemainder(BigInteger divisor) {
         validate2("divideAndRemainder", this, divisor);
@@ -1223,8 +1106,6 @@
      *             if {@code divisor == null}.
      * @throws ArithmeticException
      *             if {@code divisor == 0}.
-     * 
-     * @since Android 1.0
      */
     public BigInteger divide(BigInteger divisor) {
         validate2("divide", this, divisor);
@@ -1245,8 +1126,6 @@
      *             if {@code divisor == null}.
      * @throws ArithmeticException
      *             if {@code divisor == 0}.
-     * 
-     * @since Android 1.0
      */
     public BigInteger remainder(BigInteger divisor) {
         validate2("remainder", this, divisor);
@@ -1269,8 +1148,6 @@
      * @throws ArithmeticException
      *             if {@code m < 0 or} if {@code this} is not relatively prime
      *             to {@code m}
-     * 
-     * @since Android 1.0
      */
     public BigInteger modInverse(BigInteger m) {
         if (m.signum() <= 0) {
@@ -1299,8 +1176,6 @@
      * @throws ArithmeticException
      *             if {@code m < 0} or if {@code exponent<0} and this is not
      *             relatively prime to {@code m}.
-     * 
-     * @since Android 1.0
      */
     public BigInteger modPow(BigInteger exponent, BigInteger m) {
         if (m.signum() <= 0) {
@@ -1332,8 +1207,6 @@
      *             if {@code m == null}.
      * @throws ArithmeticException
      *             if {@code m < 0}.
-     * 
-     * @since Android 1.0
      */
     public BigInteger mod(BigInteger m) {
         if (m.signum() <= 0) {
@@ -1355,8 +1228,6 @@
      *            tolerated primality uncertainty.
      * @return {@code true}, if {@code this} is probably prime, {@code false}
      *         otherwise.
-     * 
-     * @since Android 1.0
      */
     public boolean isProbablePrime(int certainty) {
         validate1("isProbablePrime", this);
@@ -1371,8 +1242,6 @@
      * @return smallest integer > {@code this} which is robably prime.
      * @throws ArithmeticException
      *             if {@code this < 0}.
-     * 
-     * @since Android 1.0
      */
     public BigInteger nextProbablePrime() {
         if (sign < 0) {
@@ -1396,14 +1265,11 @@
      * @return probably prime random {@code BigInteger} instance.
      * @throws IllegalArgumentException
      *             if {@code bitLength < 2}.
-     * 
-     * @since Android 1.0
      */
     public static BigInteger probablePrime(int bitLength, Random rnd) {
         return new BigInteger(bitLength, 100, rnd);
     }
 
-
     /* Private Methods */
 
     /**
diff --git a/libcore/math/src/main/java/java/math/BitLevel.java b/libcore/math/src/main/java/java/math/BitLevel.java
index ab4f9cc..22a486c 100644
--- a/libcore/math/src/main/java/java/math/BitLevel.java
+++ b/libcore/math/src/main/java/java/math/BitLevel.java
@@ -31,16 +31,12 @@
  * </ul>
  * All operations are provided in immutable way, and some in both mutable and
  * immutable.
- * 
- * @author Intel Middleware Product Division
- * @author Instituto Tecnologico de Cordoba
  */
 class BitLevel {
 
     /** Just to denote that this class can't be instantiated. */
     private BitLevel() {}
 
-
     /** @see BigInteger#bitLength() */
     static int bitLength(BigInteger val) {
         // BEGIN android-added
@@ -180,6 +176,31 @@
     // }
     // END android-removed
 
+    static void shiftLeftOneBit(int result[], int source[], int srcLen) {
+        int carry = 0;
+        for(int i = 0; i < srcLen; i++) {
+            int val = source[i];
+            result[i] = (val << 1) | carry;
+            carry = val >>> 31;
+        }
+        if(carry != 0) {
+            result[srcLen] = carry;
+        }
+    }
+
+    static BigInteger shiftLeftOneBit(BigInteger source) {
+        // BEGIN android-added
+        source.establishOldRepresentation("BitLevel.shiftLeftOneBit");
+        // END android-added
+        int srcLen = source.numberLength;
+        int resLen = srcLen + 1;
+        int resDigits[] = new int[resLen];
+        shiftLeftOneBit(resDigits, source.digits, srcLen);
+        BigInteger result = new BigInteger(source.sign, resLen, resDigits);
+        result.cutOffLeadingZeroes();
+        return result;
+    }
+
     /** @see BigInteger#shiftRight(int) */
     static BigInteger shiftRight(BigInteger source, int count) {
         // BEGIN android-added
diff --git a/libcore/math/src/main/java/java/math/Conversion.java b/libcore/math/src/main/java/java/math/Conversion.java
index 65fc896..a02edb5 100644
--- a/libcore/math/src/main/java/java/math/Conversion.java
+++ b/libcore/math/src/main/java/java/math/Conversion.java
@@ -20,9 +20,6 @@
 /**
  * Static library that provides {@link BigInteger} base conversion from/to any
  * integer represented in an {@link java.lang.String} Object.
- * 
- * @author Intel Middleware Product Division
- * @author Instituto Tecnologico de Cordoba
  */
 class Conversion {
 
diff --git a/libcore/math/src/main/java/java/math/Division.java b/libcore/math/src/main/java/java/math/Division.java
index 35e3650..ce2519d 100644
--- a/libcore/math/src/main/java/java/math/Division.java
+++ b/libcore/math/src/main/java/java/math/Division.java
@@ -25,7 +25,7 @@
  * Static library that provides all operations related with division and modular
  * arithmetic to {@link BigInteger}. Some methods are provided in both mutable
  * and immutable way. There are several variants provided listed below:
- * 
+ *
  * <ul type="circle">
  * <li> <b>Division</b>
  * <ul type="circle">
@@ -41,9 +41,6 @@
  * </ul>
  * </li>
  *</ul>
- * 
- * @author Intel Middleware Product Division
- * @author Instituto Tecnologico de Cordoba
  */
 class Division {
 
@@ -55,7 +52,7 @@
     /**
      * Divides an array by an integer value. Implements the Knuth's division
      * algorithm. See D. Knuth, The Art of Computer Programming, vol. 2.
-     * 
+     *
      * @param dest the quotient
      * @param src the dividend
      * @param srcLength the length of the dividend
@@ -108,7 +105,7 @@
     /**
      * Divides an array by an integer value. Implements the Knuth's division
      * algorithm. See D. Knuth, The Art of Computer Programming, vol. 2.
-     * 
+     *
      * @param src the dividend
      * @param srcLength the length of the dividend
      * @param divisor the divisor
@@ -130,7 +127,7 @@
     /**
      * Divides a <code>BigInteger</code> by a signed <code>int</code> and
      * returns the remainder.
-     * 
+     *
      * @param dividend the BigInteger to be divided. Must be non-negative.
      * @param divisor a signed int
      * @return divide % divisor
@@ -146,7 +143,7 @@
     /**
      * Divides an unsigned long a by an unsigned int b. It is supposed that the
      * most significant bit of b is set to 1, i.e. b < 0
-     * 
+     *
      * @param a the dividend
      * @param b the divisor
      * @return the long value containing the unsigned integer remainder in the
@@ -191,7 +188,7 @@
     /**
      * Computes the quotient and the remainder after a division by an {@code int}
      * number.
-     * 
+     *
      * @return an array of the form {@code [quotient, remainder]}.
      */
     static BigInteger[] divideAndRemainderByInteger(BigInteger val,
diff --git a/libcore/math/src/main/java/java/math/Logical.java b/libcore/math/src/main/java/java/math/Logical.java
index a4c61e5..677f7f0 100644
--- a/libcore/math/src/main/java/java/math/Logical.java
+++ b/libcore/math/src/main/java/java/math/Logical.java
@@ -27,13 +27,11 @@
  * <li>or</li>
  * <li>xor</li>
  * </ul>
- * @author Intel Middleware Product Division
- * @author Instituto Tecnologico de Cordoba
  */
 class Logical {
 
     /** Just to denote that this class can't be instantiated. */
-    
+
     private Logical() {}
 
 
@@ -91,7 +89,7 @@
         if (val.equals(BigInteger.MINUS_ONE)) {
             return that;
         }
-        
+
         if (val.sign > 0) {
             if (that.sign > 0) {
                 return andPositive(val, that);
@@ -108,22 +106,22 @@
             }
         }
     }
-    
+
     /** @return sign = 1, magnitude = val.magnitude & that.magnitude*/
     static BigInteger andPositive(BigInteger val, BigInteger that) {
         // PRE: both arguments are positive
         int resLength = Math.min(val.numberLength, that.numberLength);
         int i = Math.max(val.getFirstNonzeroDigit(), that.getFirstNonzeroDigit());
-        
+
         if (i >= resLength) {
             return BigInteger.ZERO;
         }
-        
+
         int resDigits[] = new int[resLength];
         for ( ; i < resLength; i++) {
             resDigits[i] = val.digits[i] & that.digits[i];
         }
-        
+
         BigInteger result = new BigInteger(1, resLength, resDigits);
         result.cutOffLeadingZeroes();
         return result;
@@ -134,7 +132,7 @@
         // PRE: positive is positive and negative is negative
         int iPos = positive.getFirstNonzeroDigit();
         int iNeg = negative.getFirstNonzeroDigit();
-        
+
         // Look if the trailing zeros of the negative will "blank" all
         // the positive digits
         if (iNeg >= positive.numberLength) {
@@ -142,7 +140,7 @@
         }
         int resLength = positive.numberLength;
         int resDigits[] = new int[resLength];
-        
+
         // Must start from max(iPos, iNeg)
         int i = Math.max(iPos, iNeg);
         if (i == iNeg) {
@@ -160,24 +158,24 @@
                 resDigits[i] = positive.digits[i];
             }
         } // else positive ended and must "copy" virtual 0's, do nothing then
-        
+
         BigInteger result = new BigInteger(1, resLength, resDigits);
         result.cutOffLeadingZeroes();
         return result;
     }
-    
+
     /** @return sign = -1, magnitude = -(-longer.magnitude & -shorter.magnitude)*/
     static BigInteger andNegative(BigInteger longer, BigInteger shorter) {
         // PRE: longer and shorter are negative
         // PRE: longer has at least as many digits as shorter
         int iLonger = longer.getFirstNonzeroDigit();
         int iShorter = shorter.getFirstNonzeroDigit();
-        
+
         // Does shorter matter?
         if (iLonger >= shorter.numberLength) {
             return longer;
         }
-        
+
         int resLength;
         int resDigits[];
         int i = Math.max(iShorter, iLonger);
@@ -217,15 +215,13 @@
         for( ; i < longer.numberLength; i++){
             resDigits[i] = longer.digits[i];
         }
-        
+
         BigInteger result = new BigInteger(-1, resLength, resDigits);
         return result;
     }
-    
+
     /** @see BigInteger#andNot(BigInteger) */
     static BigInteger andNot(BigInteger val, BigInteger that) {
-        // BEGIN android-changed
-        // copied from newer version of harmony
         if (that.sign == 0 ) {
             return val;
         }
@@ -238,10 +234,10 @@
         if (that.equals(BigInteger.MINUS_ONE)){
             return BigInteger.ZERO;
         }
-        
+
         //if val == that, return 0
-        
-        if (val.sign > 0) {
+
+       if (val.sign > 0) {
             if (that.sign > 0) {
                 return andNotPositive(val, that);
             } else {
@@ -254,7 +250,6 @@
                 return andNotNegative(val, that);
             }
         }
-        // END android-changed
     }
     
     /** @return sign = 1, magnitude = val.magnitude & ~that.magnitude*/
diff --git a/libcore/math/src/main/java/java/math/MathContext.java b/libcore/math/src/main/java/java/math/MathContext.java
index 9e1314f..cf1d4eb 100644
--- a/libcore/math/src/main/java/java/math/MathContext.java
+++ b/libcore/math/src/main/java/java/math/MathContext.java
@@ -27,23 +27,13 @@
 /**
  * Immutable objects describing settings such as rounding mode and digit
  * precision for the numerical operations provided by class {@link BigDecimal}.
- * 
- * @since Android 1.0
  */
 public final class MathContext implements Serializable {
-    // BEGIN android-note
-    // copied from newer version of harmony
-    // added final modifier
-    // END android-note
-
-    /* Fields */
 
     /**
      * A {@code MathContext} which corresponds to the IEEE 754r quadruple
      * decimal precision format: 34 digit precision and
      * {@link RoundingMode#HALF_EVEN} rounding.
-     * 
-     * @since Android 1.0
      */
     public static final MathContext DECIMAL128 = new MathContext(34,
             RoundingMode.HALF_EVEN);
@@ -52,8 +42,6 @@
      * A {@code MathContext} which corresponds to the IEEE 754r single decimal
      * precision format: 7 digit precision and {@link RoundingMode#HALF_EVEN}
      * rounding.
-     * 
-     * @since Android 1.0
      */
     public static final MathContext DECIMAL32 = new MathContext(7,
             RoundingMode.HALF_EVEN);
@@ -62,8 +50,6 @@
      * A {@code MathContext} which corresponds to the IEEE 754r double decimal
      * precision format: 16 digit precision and {@link RoundingMode#HALF_EVEN}
      * rounding.
-     * 
-     * @since Android 1.0
      */
     public static final MathContext DECIMAL64 = new MathContext(16,
             RoundingMode.HALF_EVEN);
@@ -71,8 +57,6 @@
     /**
      * A {@code MathContext} for unlimited precision with
      * {@link RoundingMode#HALF_UP} rounding.
-     * 
-     * @since Android 1.0
      */
     public static final MathContext UNLIMITED = new MathContext(0,
             RoundingMode.HALF_UP);
@@ -96,7 +80,7 @@
      * An array of {@code char} containing: {@code
      * 'p','r','e','c','i','s','i','o','n','='}. It's used to improve the
      * methods related to {@code String} conversion.
-     * 
+     *
      * @see #MathContext(String)
      * @see #toString()
      */
@@ -107,32 +91,25 @@
      * An array of {@code char} containing: {@code
      * 'r','o','u','n','d','i','n','g','M','o','d','e','='}. It's used to
      * improve the methods related to {@code String} conversion.
-     * 
+     *
      * @see #MathContext(String)
      * @see #toString()
      */
     private final static char[] chRoundingMode = { 'r', 'o', 'u', 'n', 'd',
             'i', 'n', 'g', 'M', 'o', 'd', 'e', '=' };
 
-    /* Constructors */
-
     /**
      * Constructs a new {@code MathContext} with the specified precision and
      * with the rounding mode {@link RoundingMode#HALF_UP HALF_UP}. If the
      * precision passed is zero, then this implies that the computations have to
      * be performed exact, the rounding mode in this case is irrelevant.
-     * 
+     *
      * @param precision
      *            the precision for the new {@code MathContext}.
      * @throws IllegalArgumentException
      *             if {@code precision < 0}.
-     * 
-     * @since Android 1.0
      */
     public MathContext(int precision) {
-        // BEGIN android-note
-        // parameter names changed.
-        // END android-note
         this(precision, RoundingMode.HALF_UP);
     }
 
@@ -141,7 +118,7 @@
      * with the specified rounding mode. If the precision passed is zero, then
      * this implies that the computations have to be performed exact, the
      * rounding mode in this case is irrelevant.
-     * 
+     *
      * @param precision
      *            the precision for the new {@code MathContext}.
      * @param roundingMode
@@ -150,13 +127,8 @@
      *             if {@code precision < 0}.
      * @throws NullPointerException
      *             if {@code roundingMode} is {@code null}.
-     * 
-     * @since Android 1.0
      */
     public MathContext(int precision, RoundingMode roundingMode) {
-        // BEGIN android-note
-        // parameter names changed.
-        // END android-note
         if (precision < 0) {
             // math.0C=Digits < 0
             throw new IllegalArgumentException(Messages.getString("math.0C")); //$NON-NLS-1$
@@ -175,15 +147,13 @@
      * the following syntax: "precision=&lt;precision&gt; roundingMode=&lt;roundingMode&gt;"
      * This is the same form as the one returned by the {@link #toString}
      * method.
-     * 
+     *
      * @param val
      *            a string describing the precision and rounding mode for the
      *            new {@code MathContext}.
      * @throws IllegalArgumentException
      *             if the string is not in the correct format or if the
      *             precision specified is < 0.
-     * 
-     * @since Android 1.0
      */
     public MathContext(String val) {
         char[] charVal = val.toCharArray();
@@ -258,10 +228,8 @@
      * guaranteed to be non negative. If the precision is zero, then the
      * computations have to be performed exact, results are not rounded in this
      * case.
-     * 
+     *
      * @return the precision.
-     * 
-     * @since Android 1.0
      */
     public int getPrecision() {
         return precision;
@@ -270,20 +238,18 @@
     /**
      * Returns the rounding mode. The rounding mode is the strategy to be used
      * to round results.
-     * <p> 
-     * The rounding mode is one of 
+     * <p>
+     * The rounding mode is one of
      * {@link RoundingMode#UP},
-     * {@link RoundingMode#DOWN}, 
-     * {@link RoundingMode#CEILING}, 
+     * {@link RoundingMode#DOWN},
+     * {@link RoundingMode#CEILING},
      * {@link RoundingMode#FLOOR},
-     * {@link RoundingMode#HALF_UP}, 
-     * {@link RoundingMode#HALF_DOWN}, 
+     * {@link RoundingMode#HALF_UP},
+     * {@link RoundingMode#HALF_DOWN},
      * {@link RoundingMode#HALF_EVEN}, or
      * {@link RoundingMode#UNNECESSARY}.
-     * 
+     *
      * @return the rounding mode.
-     * 
-     * @since Android 1.0
      */
     public RoundingMode getRoundingMode() {
         return roundingMode;
@@ -292,13 +258,11 @@
     /**
      * Returns true if x is a {@code MathContext} with the same precision
      * setting and the same rounding mode as this {@code MathContext} instance.
-     * 
+     *
      * @param x
      *            object to be compared.
      * @return {@code true} if this {@code MathContext} instance is equal to the
      *         {@code x} argument; {@code false} otherwise.
-     * 
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object x) {
@@ -309,10 +273,8 @@
 
     /**
      * Returns the hash code for this {@code MathContext} instance.
-     * 
+     *
      * @return the hash code for this {@code MathContext}.
-     * 
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -322,15 +284,14 @@
 
     /**
      * Returns the string representation for this {@code MathContext} instance.
-     * The string has the form 
+     * The string has the form
      * {@code
      * "precision=&lt;precision&gt; roundingMode=&lt;roundingMode&gt;"
-     * } where {@code &lt;precision&gt;} is an integer describing the number 
+     * } where {@code &lt;precision&gt;} is an integer describing the number
      * of digits used for operations and {@code &lt;roundingMode&gt;} is the
      * string representation of the rounding mode.
-     * 
+     *
      * @return a string representation for this {@code MathContext} instance
-     * @since Android 1.0
      */
     @Override
     public String toString() {
@@ -347,7 +308,7 @@
     /**
      * Makes checks upon deserialization of a {@code MathContext} instance.
      * Checks whether {@code precision >= 0} and {@code roundingMode != null}
-     * 
+     *
      * @throws StreamCorruptedException
      *             if {@code precision < 0}
      * @throws StreamCorruptedException
diff --git a/libcore/math/src/main/java/java/math/Multiplication.java b/libcore/math/src/main/java/java/math/Multiplication.java
index ec22207..05c4605 100644
--- a/libcore/math/src/main/java/java/math/Multiplication.java
+++ b/libcore/math/src/main/java/java/math/Multiplication.java
@@ -21,9 +21,6 @@
 
 /**
  * Static library that provides all multiplication of {@link BigInteger} methods.
- *
- * @author Intel Middleware Product Division
- * @author Instituto Tecnologico de Cordoba
  */
 class Multiplication {
 
@@ -45,7 +42,7 @@
     static final int tenPows[] = {
         1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000
     };
-    
+
     /**
      * An array with powers of five that fit in the type {@code int}.
      * ({@code 5^0,5^1,...,5^13})
@@ -66,13 +63,13 @@
      * ({@code 5^0,5^1,...,5^31})
      */
     static final BigInteger bigFivePows[] = new BigInteger[32];
-    
-    
+
+
 
     static {
         int i;
         long fivePow = 1L;
-        
+
         for (i = 0; i <= 18; i++) {
             bigFivePows[i] = BigInteger.valueOf(fivePow);
             bigTenPows[i] = BigInteger.valueOf(fivePow << i);
@@ -115,7 +112,7 @@
         ? multiplyByPositiveInt(val, tenPows[(int)exp])
         : val.multiply(powerOf10(exp)));
     }
-    
+
     /**
      * It calculates a power of ten, which exponent could be out of 32-bit range.
      * Note that internally this method will be used in the worst case with
@@ -143,7 +140,7 @@
          * estimated size, measured in bytes: 1 + [exp / log10(2)]
          */
         long byteArraySize = 1 + (long)(exp / 2.4082399653118496);
-        
+
         if (byteArraySize > Runtime.getRuntime().freeMemory()) {
             // math.01=power of ten too big
             throw new OutOfMemoryError(Messages.getString("math.01")); //$NON-NLS-1$
@@ -154,7 +151,7 @@
         }
         /*
          * "HUGE POWERS"
-         * 
+         *
          * This branch probably won't be executed since the power of ten is too
          * big.
          */
@@ -162,7 +159,7 @@
         BigInteger powerOfFive = bigFivePows[1].pow(Integer.MAX_VALUE);
         BigInteger res = powerOfFive;
         long longExp = exp - Integer.MAX_VALUE;
-        
+
         intExp = (int)(exp % Integer.MAX_VALUE);
         while (longExp > Integer.MAX_VALUE) {
             res = res.multiply(powerOfFive);
@@ -179,7 +176,7 @@
         res = res.shiftLeft(intExp);
         return res;
     }
-    
+
     /**
      * Multiplies a number by a power of five.
      * This method is used in {@code BigDecimal} class.
diff --git a/libcore/math/src/main/java/java/math/Primality.java b/libcore/math/src/main/java/java/math/Primality.java
index fd06b3b..48557a6 100644
--- a/libcore/math/src/main/java/java/math/Primality.java
+++ b/libcore/math/src/main/java/java/math/Primality.java
@@ -14,21 +14,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
 
 // BEGIN android-note
 // Since the original Harmony Code of the BigInteger class was strongly modified,
@@ -40,13 +25,14 @@
 
 import java.util.Arrays;
 
+/**
+ * Provides primality probabilistic methods.
+ */
 class Primality {
 
     /** Just to denote that this class can't be instantiated. */
     private Primality() {}
 
-    /* Private Fields */
-
     /** All prime numbers with bit length lesser than 10 bits. */
     private static final int primes[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
             31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101,
@@ -94,14 +80,12 @@
         }
     }
 
-    /* Package Methods */
-
     /**
      * It uses the sieve of Eratosthenes to discard several composite numbers in
      * some appropriate range (at the moment {@code [this, this + 1024]}). After
      * this process it applies the Miller-Rabin test to the numbers that were
      * not discarded in the sieve.
-     * 
+     *
      * @see BigInteger#nextProbablePrime()
      * @see #millerRabin(BigInteger, int)
      */
diff --git a/libcore/math/src/main/java/java/math/RoundingMode.java b/libcore/math/src/main/java/java/math/RoundingMode.java
index 84dcc52..b51564f 100644
--- a/libcore/math/src/main/java/java/math/RoundingMode.java
+++ b/libcore/math/src/main/java/java/math/RoundingMode.java
@@ -22,8 +22,6 @@
 /**
  * Specifies the rounding behavior for operations whose results cannot be
  * represented exactly.
- * 
- * @since Android 1.0
  */
 public enum RoundingMode {
 
@@ -32,8 +30,6 @@
      * and negative values towards negative infinity.
      * <br>
      * Rule: {@code x.round().abs() >= x.abs()}
-     * 
-     * @since Android 1.0
      */
     UP(BigDecimal.ROUND_UP),
 
@@ -41,8 +37,6 @@
      * Rounding mode where the values are rounded towards zero.
      * <br>
      * Rule: {@code x.round().abs() <= x.abs()}
-     * 
-     * @since Android 1.0
      */
     DOWN(BigDecimal.ROUND_DOWN),
 
@@ -52,8 +46,6 @@
      * {@link #DOWN}.
      * <br>
      * Rule: {@code x.round() >= x}
-     * 
-     * @since Android 1.0
      */
     CEILING(BigDecimal.ROUND_CEILING),
 
@@ -63,32 +55,24 @@
      * {@link #UP}.
      * <br>
      * Rule: {@code x.round() <= x}
-     * 
-     * @since Android 1.0
      */
     FLOOR(BigDecimal.ROUND_FLOOR),
 
     /**
      * Rounding mode where values are rounded towards the nearest neighbor. Ties
      * are broken by rounding up.
-     * 
-     * @since Android 1.0
      */
     HALF_UP(BigDecimal.ROUND_HALF_UP),
 
     /**
      * Rounding mode where values are rounded towards the nearest neighbor. Ties
      * are broken by rounding down.
-     * 
-     * @since Android 1.0
      */
     HALF_DOWN(BigDecimal.ROUND_HALF_DOWN),
 
     /**
      * Rounding mode where values are rounded towards the nearest neighbor. Ties
      * are broken by rounding to the even neighbor.
-     * 
-     * @since Android 1.0
      */
     HALF_EVEN(BigDecimal.ROUND_HALF_EVEN),
 
@@ -96,8 +80,6 @@
      * Rounding mode where the rounding operations throws an ArithmeticException
      * for the case that rounding is necessary, i.e. for the case that the value
      * cannot be represented exactly.
-     * 
-     * @since Android 1.0
      */
     UNNECESSARY(BigDecimal.ROUND_UNNECESSARY);
 
@@ -112,17 +94,12 @@
     /**
      * Converts rounding mode constants from class {@code BigDecimal} into
      * {@code RoundingMode} values.
-     * 
+     *
      * @param mode
      *            rounding mode constant as defined in class {@code BigDecimal}
      * @return corresponding rounding mode object
-     * 
-     * @since Android 1.0
      */
     public static RoundingMode valueOf(int mode) {
-        // BEGIN android-note
-        // parameter name changed.
-        // END android-note
         switch (mode) {
             case BigDecimal.ROUND_CEILING:
                 return CEILING;
diff --git a/libcore/math/src/test/java/tests/api/java/math/BigDecimalTest.java b/libcore/math/src/test/java/tests/api/java/math/BigDecimalTest.java
index 47e5b31..572f2c1 100644
--- a/libcore/math/src/test/java/tests/api/java/math/BigDecimalTest.java
+++ b/libcore/math/src/test/java/tests/api/java/math/BigDecimalTest.java
@@ -30,6 +30,7 @@
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.math.RoundingMode;
+import java.math.MathContext;
 
 @TestTargetClass(BigDecimal.class)
 public class BigDecimalTest extends junit.framework.TestCase {
@@ -1310,6 +1311,41 @@
         BigDecimal zerotest = new BigDecimal("0.0000");
         assertEquals("stripTrailingZero failed for 0.0000",
                 0, (zerotest.stripTrailingZeros()).scale() );        
-    }    
+    }
 
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "",
+            method = "abs",
+            args = {MathContext.class}
+    )
+    public void testMathContextConstruction() {
+        String a = "-12380945E+61";
+        BigDecimal aNumber = new BigDecimal(a);
+        int precision = 6;
+        RoundingMode rm = RoundingMode.HALF_DOWN;
+        MathContext mcIntRm = new MathContext(precision, rm);
+        MathContext mcStr = new MathContext("precision=6 roundingMode=HALF_DOWN");
+        MathContext mcInt = new MathContext(precision);
+        BigDecimal res = aNumber.abs(mcInt);
+        assertEquals("MathContext Constructor with int precision failed",
+                res,
+                new BigDecimal("1.23809E+68"));
+
+        assertEquals("Equal MathContexts are not Equal ",
+                mcIntRm,
+                mcStr);
+
+        assertEquals("Different MathContext are reported as Equal ",
+                mcInt.equals(mcStr),
+                false);
+
+        assertEquals("Equal MathContexts have different hashcodes ",
+                mcIntRm.hashCode(),
+                mcStr.hashCode());
+
+        assertEquals("MathContext.toString() returning incorrect value",
+                mcIntRm.toString(),
+                "precision=6 roundingMode=HALF_DOWN");
+    }
 }
diff --git a/libcore/math/src/test/java/tests/api/java/math/BigIntegerTest.java b/libcore/math/src/test/java/tests/api/java/math/BigIntegerTest.java
index c640638..d04f742 100644
--- a/libcore/math/src/test/java/tests/api/java/math/BigIntegerTest.java
+++ b/libcore/math/src/test/java/tests/api/java/math/BigIntegerTest.java
@@ -1266,6 +1266,16 @@
                         (i1.testBit(i) && !i2.testBit(i)) == res.testBit(i));
             }
         }
+
+        //regression for HARMONY-4653
+        try{
+            BigInteger.ZERO.andNot(null);
+            fail("should throw NPE");
+        }catch(Exception e){
+            //expected
+        }
+        BigInteger bi = new BigInteger(0, new byte[]{});
+        assertEquals(BigInteger.ZERO, bi.andNot(BigInteger.ZERO));
     }
     
 
diff --git a/libcore/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java b/libcore/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java
index ddd56e5..ac8f77b 100644
--- a/libcore/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java
+++ b/libcore/nio/src/main/java/org/apache/harmony/nio/internal/DatagramChannelImpl.java
@@ -15,14 +15,13 @@
  *  limitations under the License.
  */
 
-/*
- * Android Notice 
- * In this class the address length was changed from long to int.
- * This is due to performance optimizations for the device.
- */
-
 package org.apache.harmony.nio.internal;
 
+// BEGIN android-note
+// Copied from a newer version of Harmony.
+// In this class the address length was changed from long to int.
+// END android-note
+
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.InterruptedIOException;
@@ -43,7 +42,7 @@
 import java.nio.channels.spi.SelectorProvider;
 
 import org.apache.harmony.luni.net.NetUtil;
-import org.apache.harmony.luni.net.SocketImplProvider;
+import org.apache.harmony.luni.net.PlainDatagramSocketImpl;
 import org.apache.harmony.luni.platform.FileDescriptorHandler;
 import org.apache.harmony.luni.platform.INetworkSystem;
 import org.apache.harmony.luni.platform.Platform;
@@ -52,15 +51,10 @@
 
 /*
  * The default implementation class of java.nio.channels.DatagramChannel.
- * 
  */
 class DatagramChannelImpl extends DatagramChannel implements
         FileDescriptorHandler {
 
-    // -------------------------------------------------------------------
-    // Class variables
-    // -------------------------------------------------------------------
-
     // The singleton to do the native network operation.
     private static final INetworkSystem networkSystem = Platform
             .getNetworkSystem();
@@ -72,10 +66,6 @@
     
     private static final byte[] stubArray = new byte[0];
 
-    // -------------------------------------------------------------------
-    // Instance variables
-    // -------------------------------------------------------------------
-
     // The fd to interact with native code
     private FileDescriptor fd;
 
@@ -94,19 +84,17 @@
     // whether the socket is bound
     boolean isBound = false;
 
-    private final Object readLock = new Object();
+    private static class ReadLock {}
+    private final Object readLock = new ReadLock();
 
-    private final Object writeLock = new Object();
+    private static class WriteLock {}
+    private final Object writeLock = new WriteLock();
 
     // used to store the trafficClass value which is simply returned
     // as the value that was set. We also need it to pass it to methods
     // that specify an address packets are going to be sent to
     private int trafficClass = 0;
 
-    // -------------------------------------------------------------------
-    // Constructor
-    // -------------------------------------------------------------------
-
     /*
      * Constructor
      */
@@ -120,16 +108,13 @@
     /*
      * for native call
      */
-    private DatagramChannelImpl(){
+    @SuppressWarnings("unused")
+    private DatagramChannelImpl() {
         super(SelectorProvider.provider());
         fd = new FileDescriptor();
         connectAddress = new InetSocketAddress(0);
     }
 
-    // -------------------------------------------------------------------
-    // Methods for getting internal DatagramSocket.
-    // -------------------------------------------------------------------
-
     /*
      * Getting the internal DatagramSocket If we have not the socket, we create
      * a new one.
@@ -137,8 +122,8 @@
     @Override
     synchronized public DatagramSocket socket() {
         if (null == socket) {
-            socket = new DatagramSocketAdapter(SocketImplProvider
-                    .getDatagramSocketImpl(fd, localPort), this);
+            socket = new DatagramSocketAdapter(
+                    new PlainDatagramSocketImpl(fd, localPort), this);
         }
         return socket;
     }
@@ -155,12 +140,7 @@
                 .preferIPv6Addresses());
     }
 
-    // -------------------------------------------------------------------
-    // Methods for connect and disconnect
-    // -------------------------------------------------------------------
-
-    /*
-     * 
+    /**
      * @see java.nio.channels.DatagramChannel#isConnected()
      */
     @Override
@@ -168,8 +148,7 @@
         return connected;
     }
 
-    /*
-     * 
+    /**
      * @see java.nio.channels.DatagramChannel#connect(java.net.SocketAddress)
      */
     @Override
@@ -214,8 +193,7 @@
         return this;
     }
 
-    /*
-     * 
+    /**
      * @see java.nio.channels.DatagramChannel#disconnect()
      */
     @Override
@@ -232,12 +210,7 @@
         return this;
     }
 
-    // -------------------------------------------------------------------
-    // Methods for send and receive
-    // -------------------------------------------------------------------
-
-    /*
-     * 
+    /**
      * @see java.nio.channels.DatagramChannel#receive(java.nio.ByteBuffer)
      */
     @Override
@@ -284,14 +257,15 @@
                     .position()
                     + target.arrayOffset(), target.remaining());
         } else {        
-            receivePacket = new DatagramPacket(new byte[target.remaining()], target.remaining());
+            receivePacket = new DatagramPacket(new byte[target.remaining()],
+                    target.remaining());
         }
         do {
             if (isConnected()) {
-                received = networkSystem.recvConnectedDatagram(fd, receivePacket,
-                        receivePacket.getData(), receivePacket.getOffset(),
-                        receivePacket.getLength(), isBlocking() ? 0
-                                : DEFAULT_TIMEOUT, false);
+                received = networkSystem.recvConnectedDatagram(fd,
+                        receivePacket, receivePacket.getData(), receivePacket
+                                .getOffset(), receivePacket.getLength(),
+                        isBlocking() ? 0 : DEFAULT_TIMEOUT, false);
             } else {
                 received = networkSystem.receiveDatagram(fd, receivePacket,
                         receivePacket.getData(), receivePacket.getOffset(),
@@ -327,24 +301,23 @@
         return retAddr;
     }
     
-    private SocketAddress receiveDirectImpl(ByteBuffer target, boolean loop) throws IOException
-    {
-        SocketAddress retAddr = null;  
-        DatagramPacket receivePacket = new DatagramPacket(
-                stubArray, 0);
+    private SocketAddress receiveDirectImpl(ByteBuffer target, boolean loop)
+            throws IOException {
+        SocketAddress retAddr = null;
+        DatagramPacket receivePacket = new DatagramPacket(stubArray, 0);
         int oldposition = target.position();
         int received = 0;
         do {
             int address = AddressUtil.getDirectBufferAddress(target);
             if (isConnected()) {
-                received = networkSystem.recvConnectedDatagramDirect(fd, receivePacket,
-                        address, target.position(),
-                        target.remaining(), isBlocking() ? 0
+                received = networkSystem.recvConnectedDatagramDirect(fd,
+                        receivePacket, address, target.position(), target
+                                .remaining(), isBlocking() ? 0
                                 : DEFAULT_TIMEOUT, false);
             } else {
-                received = networkSystem.receiveDatagramDirect(fd, receivePacket,
-                        address, target.position(),
-                        target.remaining(), isBlocking() ? 0
+                received = networkSystem.receiveDatagramDirect(fd,
+                        receivePacket, address, target.position(), target
+                                .remaining(), isBlocking() ? 0
                                 : DEFAULT_TIMEOUT, false);
             }
 
@@ -352,15 +325,14 @@
             SecurityManager sm = System.getSecurityManager();
             if (!isConnected() && null != sm) {
                 try {
-                    sm.checkAccept(receivePacket.getAddress()
-                            .getHostAddress(), receivePacket.getPort());
+                    sm.checkAccept(receivePacket.getAddress().getHostAddress(),
+                            receivePacket.getPort());
                 } catch (SecurityException e) {
                     // do discard the datagram packet
                     receivePacket = null;
                 }
             }
-            if (null != receivePacket
-                    && null != receivePacket.getAddress()) {
+            if (null != receivePacket && null != receivePacket.getAddress()) {
                 // copy the data of received packet
                 if (received > 0) {
                     target.position(oldposition + received);
@@ -372,7 +344,7 @@
         return retAddr;
     }
 
-    /*
+    /**
      * @see java.nio.channels.DatagramChannel#send(java.nio.ByteBuffer,
      *      java.net.SocketAddress)
      */
@@ -445,12 +417,7 @@
         }
     }
 
-    // -------------------------------------------------------------------
-    // Methods for read and write.
-    // -------------------------------------------------------------------
-
-    /*
-     * 
+    /**
      * @see java.nio.channels.DatagramChannel#read(java.nio.ByteBuffer)
      */
     @Override
@@ -467,10 +434,10 @@
             return 0;
         }
 
-        int readCount  = 0;
+        int readCount = 0;
         if (target.isDirect() || target.hasArray()) {
             readCount = readImpl(target);
-            if(readCount > 0){
+            if (readCount > 0) {
                 target.position(target.position() + readCount);
             }
 
@@ -478,15 +445,14 @@
             byte[] readArray = new byte[target.remaining()];
             ByteBuffer readBuffer = ByteBuffer.wrap(readArray);
             readCount = readImpl(readBuffer);
-            if(readCount > 0){
+            if (readCount > 0) {
                 target.put(readArray, 0, readCount);
             }
         }
         return readCount;
     }
 
-    /*
-     * 
+    /**
      * @see java.nio.channels.DatagramChannel#read(java.nio.ByteBuffer[], int,
      *      int)
      */
@@ -530,7 +496,7 @@
      * read from channel, and store the result in the target.
      */
     private int readImpl(ByteBuffer readBuffer) throws IOException {
-        synchronized(readLock){
+        synchronized (readLock) {
             int readCount = 0;
             try {
                 begin();
@@ -542,8 +508,9 @@
                 if (readBuffer.isDirect()) {
                     int address = AddressUtil.getDirectBufferAddress(readBuffer);
                     if (isConnected()) {
-                        readCount = networkSystem.recvConnectedDatagramDirect(fd,
-                                null, address, start, length, timeout, false);
+                        readCount = networkSystem.recvConnectedDatagramDirect(
+                                fd, null, address, start, length, timeout,
+                                false);
                     } else {
                         readCount = networkSystem.receiveDatagramDirect(fd,
                                 null, address, start, length, timeout, false);
@@ -553,11 +520,11 @@
                     byte[] target = readBuffer.array();
                     start += readBuffer.arrayOffset();
                     if (isConnected()) {
-                        readCount = networkSystem.recvConnectedDatagram(fd, null,
-                                target, start, length, timeout, false);
+                        readCount = networkSystem.recvConnectedDatagram(fd,
+                                null, target, start, length, timeout, false);
                     } else {
-                        readCount = networkSystem.receiveDatagram(fd, null, target,
-                                start, length, timeout, false);
+                        readCount = networkSystem.receiveDatagram(fd, null,
+                                target, start, length, timeout, false);
                     }
                 }
                 return readCount;
@@ -570,7 +537,7 @@
         }
     }
 
-    /*
+    /**
      * @see java.nio.channels.DatagramChannel#write(java.nio.ByteBuffer)
      */
     @Override
@@ -602,7 +569,7 @@
         return result;
     }
 
-    /*
+    /**
      * @see java.nio.channels.DatagramChannel#write(java.nio.ByteBuffer[], int,
      *      int)
      */
@@ -621,7 +588,7 @@
             return 0;
         }
         ByteBuffer writeBuf = ByteBuffer.allocate(count);
-        for (int val = offset; val < length+offset; val++) {
+        for (int val = offset; val < length + offset; val++) {
             ByteBuffer source = sources[val];
             int oldPosition = source.position();
             writeBuf.put(source);
@@ -642,10 +609,10 @@
     }
 
     /*
-     * write the source. return the count of bytes written.
+     * Write the source. Return the count of bytes written.
      */
     private int writeImpl(ByteBuffer buf) throws IOException {
-        synchronized(writeLock){
+        synchronized (writeLock) {
             int result = 0;
             try {
                 begin();
@@ -654,13 +621,13 @@
     
                 if (buf.isDirect()) {
                     int address = AddressUtil.getDirectBufferAddress(buf);
-                    result = networkSystem.sendConnectedDatagramDirect(fd, address,
-                            start, length, isBound);
+                    result = networkSystem.sendConnectedDatagramDirect(fd,
+                            address, start, length, isBound);
                 } else {
                     // buf is assured to have array.
                     start += buf.arrayOffset();
-                    result = networkSystem.sendConnectedDatagram(fd, buf.array(),
-                            start, length, isBound);
+                    result = networkSystem.sendConnectedDatagram(fd, buf
+                            .array(), start, length, isBound);
                 }
                 return result;
             } catch (SocketException e) {
@@ -677,12 +644,8 @@
         }
     }
 
-    // -------------------------------------------------------------------
-    // Protected Inherited methods
-    // -------------------------------------------------------------------
-
     /*
-     * do really closing action here
+     * Do really closing action here.
      */
     @Override
     synchronized protected void implCloseSelectableChannel() throws IOException {
@@ -694,8 +657,7 @@
         }
     }
 
-    /*
-     * 
+    /**
      * @see java.nio.channels.spi.AbstractSelectableChannel#implConfigureBlocking(boolean)
      */
     @Override
@@ -707,12 +669,8 @@
         // decided by isBlocking() method.
     }
 
-    // -------------------------------------------------------------------
-    // Share methods for checking.
-    // -------------------------------------------------------------------
-
     /*
-     * status check, must be open.
+     * Status check, must be open.
      */
     private void checkOpen() throws IOException {
         if (!isOpen()) {
@@ -721,7 +679,7 @@
     }
 
     /*
-     * status check, must be open and connected, for read and write.
+     * Status check, must be open and connected, for read and write.
      */
     private void checkOpenConnected() throws IOException {
         checkOpen();
@@ -731,7 +689,7 @@
     }
 
     /*
-     * buffer check, must not null
+     * Buffer check, must not null
      */
     private void checkNotNull(ByteBuffer source) {
         if (null == source) {
@@ -740,7 +698,7 @@
     }
 
     /*
-     * buffer check, must not null and not read only buffer, for read and
+     * Buffer check, must not null and not read only buffer, for read and
      * receive.
      */
     private void checkWritable(ByteBuffer target) {
@@ -750,12 +708,8 @@
         }
     }
 
-    // -------------------------------------------------------------------
-    // Adapter classes for internal socket.
-    // -------------------------------------------------------------------
-
     /*
-     * get the fd for internal use.
+     * Get the fd for internal use.
      */
     public FileDescriptor getFD() {
         return fd;
@@ -781,7 +735,7 @@
         private DatagramChannelImpl channelImpl;
 
         /*
-         * init the datagramSocketImpl and datagramChannelImpl
+         * Constructor initialize the datagramSocketImpl and datagramChannelImpl
          */
         DatagramSocketAdapter(DatagramSocketImpl socketimpl,
                 DatagramChannelImpl channelImpl) {
@@ -790,14 +744,14 @@
         }
 
         /*
-         * get the internal datagramChannelImpl
+         * Get the internal datagramChannelImpl
          */
         @Override
         public DatagramChannel getChannel() {
             return channelImpl;
         }
 
-        /*
+        /**
          * @see java.net.DatagramSocket#isBound()
          */
         @Override
@@ -805,7 +759,7 @@
             return channelImpl.isBound;
         }
 
-        /*
+        /**
          * @see java.net.DatagramSocket#isConnected()
          */
         @Override
@@ -813,7 +767,7 @@
             return channelImpl.isConnected();
         }
 
-        /*
+        /**
          * @see java.net.DatagramSocket#getInetAddress()
          */
         @Override
@@ -824,7 +778,7 @@
             return channelImpl.connectAddress.getAddress();
         }
 
-        /*
+        /**
          * @see java.net.DatagramSocket#getLocalAddress()
          */
         @Override
@@ -832,7 +786,7 @@
             return channelImpl.getLocalAddress();
         }
 
-        /*
+        /**
          * @see java.net.DatagramSocket#getPort()
          */
         @Override
@@ -843,7 +797,7 @@
             return channelImpl.connectAddress.getPort();
         }
 
-        /*
+        /**
          * @see java.net.DatagramSocket#bind(java.net.SocketAddress)
          */
         @Override
@@ -855,7 +809,7 @@
             channelImpl.isBound = true;
         }
 
-        /*
+        /**
          * @see java.net.DatagramSocket#receive(java.net.DatagramPacket)
          */
         @Override
@@ -866,7 +820,7 @@
             super.receive(packet);
         }
 
-        /*
+        /**
          * @see java.net.DatagramSocket#send(java.net.DatagramPacket)
          */
         @Override
@@ -877,7 +831,7 @@
             super.send(packet);
         }
 
-        /*
+        /**
          * @see java.net.DatagramSocket#close()
          */
         @Override
@@ -894,7 +848,7 @@
             }
         }
 
-        /*
+        /**
          * @see java.net.DatagramSocket#disconnect()
          */
         @Override
diff --git a/libcore/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java b/libcore/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java
index 3bc368f..dbef656 100644
--- a/libcore/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java
+++ b/libcore/nio/src/main/java/org/apache/harmony/nio/internal/ServerSocketChannelImpl.java
@@ -17,6 +17,10 @@
 
 package org.apache.harmony.nio.internal;
 
+// BEGIN android-note
+// Copied from a newer version of Harmony.
+// END android-note
+
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.net.ServerSocket;
@@ -27,13 +31,12 @@
 import java.nio.channels.ClosedChannelException;
 import java.nio.channels.IllegalBlockingModeException;
 import java.nio.channels.NotYetBoundException;
-import java.nio.channels.SelectableChannel;
 import java.nio.channels.ServerSocketChannel;
 import java.nio.channels.SocketChannel;
 import java.nio.channels.spi.SelectorProvider;
 
 import org.apache.harmony.luni.net.NetUtil;
-import org.apache.harmony.luni.net.SocketImplProvider;
+import org.apache.harmony.luni.net.PlainServerSocketImpl;
 import org.apache.harmony.luni.platform.FileDescriptorHandler;
 import org.apache.harmony.luni.platform.Platform;
 
@@ -43,10 +46,6 @@
 public class ServerSocketChannelImpl extends ServerSocketChannel implements
         FileDescriptorHandler {
 
-    // ----------------------------------------------------
-    // Class variables
-    // ----------------------------------------------------
-
     // status un-init, not initialized.
     private static final int SERVER_STATUS_UNINIT = -1;
 
@@ -56,10 +55,6 @@
     // status closed.
     private static final int SERVER_STATUS_CLOSED = 1;
 
-    // -------------------------------------------------------------------
-    // Instance variables
-    // -------------------------------------------------------------------
-
     // The fd to interact with native code
     private final FileDescriptor fd;
 
@@ -74,13 +69,9 @@
     boolean isBound = false;
 
     // lock for accept
-    private class AcceptLock {}
+    private static class AcceptLock {}
     private final Object acceptLock = new AcceptLock();
 
-    // ----------------------------------------------------
-    // Constructor
-    // ----------------------------------------------------
-
     /*
      * Constructor
      */
@@ -88,26 +79,23 @@
         super(sp);
         status = SERVER_STATUS_OPEN;
         fd = new FileDescriptor();
-        Platform.getNetworkSystem().createServerStreamSocket(fd,
+        Platform.getNetworkSystem().createStreamSocket(fd,
                 NetUtil.preferIPv4Stack());
-        impl = SocketImplProvider.getServerSocketImpl(fd);
+        impl = new PlainServerSocketImpl(fd);
         socket = new ServerSocketAdapter(impl, this);
     }
     
     // for native call
+    @SuppressWarnings("unused")
     private ServerSocketChannelImpl() throws IOException {
         super(SelectorProvider.provider());
         status = SERVER_STATUS_OPEN;
         fd = new FileDescriptor();
-        impl = SocketImplProvider.getServerSocketImpl(fd);        
+        impl = new PlainServerSocketImpl(fd);
         socket = new ServerSocketAdapter(impl, this);
         isBound = false;
     }
 
-    // ----------------------------------------------------
-    // Methods
-    // ----------------------------------------------------
-
     /*
      * Getting the internal Socket If we have not the socket, we create a new
      * one.
@@ -128,7 +116,7 @@
             throw new NotYetBoundException();
         }
 
-        SocketChannel sockChannel = SocketChannel.open();
+        SocketChannel sockChannel = new SocketChannelImpl(SelectorProvider.provider(), false);
         Socket socketGot = sockChannel.socket();
 
         try {
@@ -168,10 +156,6 @@
         return sockChannel;
     }
 
-    // -------------------------------------------------------------------
-    // Protected inherited methods
-    // -------------------------------------------------------------------
-
     /*
      * @see java.nio.channels.spi.AbstractSelectableChannel#implConfigureBlocking
      * 
@@ -202,10 +186,6 @@
         return fd;
     }
 
-    // ----------------------------------------------------
-    // Adapter classes.
-    // ----------------------------------------------------
-
     /*
      * The adapter class of ServerSocket.
      */
@@ -264,10 +244,7 @@
                 synchronized (this) {
                     super.implAccept(aSocket);
                     sockChannel.setConnected();
-                    // BEGIN android-added
-                    // copied from a newer version of harmony
                     sockChannel.setBound(true);
-                    // END android-added
                 }
                 SecurityManager sm = System.getSecurityManager();
                 if (sm != null) {
diff --git a/libcore/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java b/libcore/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java
index 8e6c52f..1affb21 100644
--- a/libcore/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java
+++ b/libcore/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java
@@ -17,6 +17,11 @@
 
 package org.apache.harmony.nio.internal;
 
+// BEGIN android-note
+// Copied from a newer version of Harmony.
+// In this class the address length was changed from long to int.
+// END android-note
+
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.InputStream;
@@ -42,25 +47,20 @@
 import java.nio.channels.UnsupportedAddressTypeException;
 import java.nio.channels.spi.SelectorProvider;
 
-import org.apache.harmony.luni.net.SocketImplProvider;
+import org.apache.harmony.luni.net.PlainSocketImpl;
 import org.apache.harmony.luni.platform.FileDescriptorHandler;
 import org.apache.harmony.luni.platform.INetworkSystem;
 import org.apache.harmony.luni.platform.Platform;
 import org.apache.harmony.luni.util.ErrorCodeException;
+import org.apache.harmony.luni.util.Msg;
 import org.apache.harmony.nio.AddressUtil;
 import org.apache.harmony.nio.internal.nls.Messages;
 
 /*
- * 
  * The default implementation class of java.nio.channels.SocketChannel.
- * 
  */
 class SocketChannelImpl extends SocketChannel implements FileDescriptorHandler {
 
-    // -------------------------------------------------------------------
-    // Class variables
-    // -------------------------------------------------------------------
-
     private static final int EOF = -1;
 
     private static final int ERRCODE_SOCKET_NONBLOCKING_WOULD_BLOCK = -211;
@@ -68,41 +68,37 @@
     // The singleton to do the native network operation.
     static final INetworkSystem networkSystem = Platform.getNetworkSystem();
 
-    // status un-init, not initialized.
+    // Status un-init, not initialized.
     static final int SOCKET_STATUS_UNINIT = EOF;
 
-    // status before connect.
+    // Status before connect.
     static final int SOCKET_STATUS_UNCONNECTED = 0;
 
-    // status connection pending
+    // Status connection pending.
     static final int SOCKET_STATUS_PENDING = 1;
 
-    // status after connection success
+    // Status after connection success.
     static final int SOCKET_STATUS_CONNECTED = 2;
 
-    // status closed.
+    // Status closed.
     static final int SOCKET_STATUS_CLOSED = 3;
 
-    // timeout used for non-block mode.
+    // Timeout used for non-block mode.
     private static final int TIMEOUT_NONBLOCK = 0;
 
-    // timeout used for block mode.
+    // Timeout used for block mode.
     private static final int TIMEOUT_BLOCK = EOF;
 
-    // step used for connect
+    // Step used for connect.
     private static final int HY_SOCK_STEP_START = 0;
 
-    // step used for finishConnect
+    // Step used for finishConnect.
     private static final int HY_PORT_SOCKET_STEP_CHECK = 1;
 
-    // connect success
+    // Connect success.
     private static final int CONNECT_SUCCESS = 0;
 
-    // -------------------------------------------------------------------
-    // Instance Variables
-    // -------------------------------------------------------------------
-
-    // The fd to interact with native code
+    // The descriptor to interact with native code.
     FileDescriptor fd;
 
     // Our internal Socket.
@@ -111,24 +107,23 @@
     // The address to be connected.
     InetSocketAddress connectAddress = null;
 
-    // Local address of the this socket (package private for adapter)
+    // Local address of the this socket (package private for adapter).
     InetAddress localAddress = null;
 
-    // local port
+    // Local port number.
     int localPort;
 
     // At first, uninitialized.
     int status = SOCKET_STATUS_UNINIT;
 
-    // BEGIN android-changed
-    // copied from a newer version of harmony
-    // whether the socket is bound
+    // Whether the socket is bound.
     volatile boolean isBound = false;
-    // END adroid-changed
 
-    private final Object readLock = new Object();
+    private static class ReadLock {}
+    private final Object readLock = new ReadLock();
 
-    private final Object writeLock = new Object();
+    private static class WriteLock {}
+    private final Object writeLock = new WriteLock();
 
     // BEGIN android-changed
     // this content is a struct used in connect_withtimeout().
@@ -136,30 +131,37 @@
     private byte[] connectContext = new byte[392];
     // END android-changed
 
-    // used to store the trafficClass value which is simply returned
+    // Used to store the trafficClass value which is simply returned
     // as the value that was set. We also need it to pass it to methods
-    // that specify an address packets are going to be sent to
+    // that specify an address packets are going to be sent to.
     private int trafficClass = 0;
 
-    // -------------------------------------------------------------------
-    // Constructor
-    // -------------------------------------------------------------------
-
     /*
-     * Constructor
+     * Constructor for creating a connected socket channel.
      */
     public SocketChannelImpl(SelectorProvider selectorProvider)
             throws IOException {
+        this(selectorProvider, true);
+    }
+
+    /*
+     * Constructor for creating an optionally connected socket channel.
+     */
+    public SocketChannelImpl(SelectorProvider selectorProvider, boolean connect)
+            throws IOException {
         super(selectorProvider);
         fd = new FileDescriptor();
         status = SOCKET_STATUS_UNCONNECTED;
-        networkSystem.createSocket(fd, true);
+        if (connect) {
+            networkSystem.createStreamSocket(fd, true);
+        }
     }
 
     /*
-     * for native call
+     * For native call.
      */
-    private SocketChannelImpl(){
+    @SuppressWarnings("unused")
+    private SocketChannelImpl() {
         super(SelectorProvider.provider());
         fd = new FileDescriptor();
         connectAddress = new InetSocketAddress(0);
@@ -186,10 +188,6 @@
         status = SOCKET_STATUS_UNCONNECTED;
     }
 
-    // -------------------------------------------------------------------
-    // Methods for getting internal Socket.
-    // -------------------------------------------------------------------
-
     /*
      * Getting the internal Socket If we have not the socket, we create a new
      * one.
@@ -204,8 +202,8 @@
                     addr = connectAddress.getAddress();
                     port = connectAddress.getPort();
                 }
-                socket = new SocketAdapter(SocketImplProvider.getSocketImpl(fd,
-                        localPort, addr, port), this);
+                socket = new SocketAdapter(
+                        new PlainSocketImpl(fd, localPort, addr, port), this);
             } catch (SocketException e) {
                 return null;
             }
@@ -213,11 +211,7 @@
         return socket;
     }
 
-    // -------------------------------------------------------------------
-    // Methods for connect and finishConnect
-    // -------------------------------------------------------------------
-
-    /*
+    /**
      * @see java.nio.channels.SocketChannel#isConnected()
      */
     @Override
@@ -226,20 +220,17 @@
     }
 
     /*
-     * status setting used by other class.
+     * Status setting used by other class.
      */
     synchronized void setConnected() {
         status = SOCKET_STATUS_CONNECTED;
     }
 
-    // BEGIN android-added
-    // copied from a newer version of harmony
     void setBound(boolean flag) {
         isBound = flag;
     }
-    // END android-added
 
-    /*
+    /**
      * @see java.nio.channels.SocketChannel#isConnectionPending()
      */
     @Override
@@ -247,7 +238,7 @@
         return status == SOCKET_STATUS_PENDING;
     }
 
-    /*
+    /**
      * @see java.nio.channels.SocketChannel#connect(java.net.SocketAddress)
      */
     @Override
@@ -257,9 +248,15 @@
 
         // check the address
         InetSocketAddress inetSocketAddress = validateAddress(socketAddress);
+        InetAddress normalAddr = inetSocketAddress.getAddress();
+
+        // When connecting, map ANY address to Localhost
+        if (normalAddr.isAnyLocalAddress()) {
+            normalAddr = InetAddress.getLocalHost();
+        }
 
         int port = inetSocketAddress.getPort();
-        String hostName = inetSocketAddress.getAddress().getHostName();
+        String hostName = normalAddr.getHostName();
         // security check
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
@@ -271,23 +268,12 @@
         boolean finished = false;
 
         try {
-            if (!isBound) {
-                // bind
-                networkSystem.bind2(fd, 0, true, InetAddress
-                        .getByAddress(new byte[] { 0, 0, 0, 0 }));
-                isBound = true;
-            }
-
             if (isBlocking()) {
                 begin();
-                result = networkSystem.connect(fd, trafficClass,
-                        inetSocketAddress.getAddress(), inetSocketAddress
-                                .getPort());
-
+                result = networkSystem.connect(fd, trafficClass, normalAddr, port);
             } else {
                 result = networkSystem.connectWithTimeout(fd, 0, trafficClass,
-                        inetSocketAddress.getAddress(), inetSocketAddress
-                                .getPort(), HY_SOCK_STEP_START, connectContext);
+                        normalAddr, port, HY_SOCK_STEP_START, connectContext);
                 // set back to nonblocking to work around with a bug in portlib
                 if (!this.isBlocking()) {
                     networkSystem.setNonBlocking(fd, true);
@@ -328,7 +314,7 @@
         return finished;
     }
 
-    /*
+    /**
      * @see java.nio.channels.SocketChannel#finishConnect()
      */
     @Override
@@ -372,14 +358,13 @@
         synchronized (this) {
             status = (finished ? SOCKET_STATUS_CONNECTED : status);
             isBound = finished;
+            // TPE: Workaround for bug that turns socket back to blocking
+            if (!isBlocking()) implConfigureBlocking(false);
         }
         return finished;
     }
 
-    // -------------------------------------------------------------------
-    // Methods for read and write
-    // -------------------------------------------------------------------
-    /*
+    /**
      * @see java.nio.channels.SocketChannel#read(java.nio.ByteBuffer)
      */
     @Override
@@ -411,7 +396,7 @@
         return readCount;
     }
 
-    /*
+    /**
      * @see java.nio.channels.SocketChannel#read(java.nio.ByteBuffer[], int,
      *      int)
      */
@@ -449,16 +434,17 @@
 
     private boolean isIndexValid(ByteBuffer[] targets, int offset, int length) {
         return (length >= 0) && (offset >= 0)
-                && ((long)length + (long)offset <= targets.length);
+                && ((long) length + (long) offset <= targets.length);
     }
 
-    /*
-     * read from channel, and store the result in the target.
+    /**
+     * Read from channel, and store the result in the target.
      * 
-     * @param target output parameter
+     * @param target
+     *            output parameter
      */
     private int readImpl(ByteBuffer target) throws IOException {
-        synchronized(readLock){
+        synchronized (readLock) {
             int readCount = 0;
             try {
                 if (isBlocking()) {
@@ -467,10 +453,13 @@
                 int offset = target.position();
                 int length = target.remaining();
                 if (target.isDirect()) {
+                    // BEGIN android-changed
+                    // changed address from long to int; split address and offset paramters
                     int address = AddressUtil.getDirectBufferAddress(target);
                     readCount = networkSystem.readDirect(fd, address, offset,
                             length, (isBlocking() ? TIMEOUT_BLOCK
                                     : TIMEOUT_NONBLOCK));
+                    // END android-changed
                 } else {
                     // target is assured to have array.
                     byte[] array = target.array();
@@ -487,8 +476,7 @@
         }
     }
 
-    /*
-     * 
+    /**
      * @see java.nio.channels.SocketChannel#write(java.nio.ByteBuffer)
      */
     @Override
@@ -503,7 +491,7 @@
         return writeImpl(source);
     }
 
-    /*
+    /**
      * @see java.nio.channels.SocketChannel#write(java.nio.ByteBuffer[], int,
      *      int)
      */
@@ -520,7 +508,7 @@
             return 0;
         }
         ByteBuffer writeBuf = ByteBuffer.allocate(count);
-        for (int val = offset; val < length+offset; val++) {
+        for (int val = offset; val < length + offset; val++) {
             ByteBuffer source = sources[val];
             int oldPosition = source.position();
             writeBuf.put(source);
@@ -550,10 +538,10 @@
     }
 
     /*
-     * write the source. return the count of bytes written.
+     * Write the source. return the count of bytes written.
      */
     private int writeImpl(ByteBuffer source) throws IOException {
-        synchronized(writeLock){
+        synchronized (writeLock) {
             if (!source.hasRemaining()) {
                 return 0;
             }
@@ -565,9 +553,12 @@
                     begin();
                 }
                 if (source.isDirect()) {
+                    // BEGIN android-changed
+                    // changed address from long to int; split address and pos parameters
                     int address = AddressUtil.getDirectBufferAddress(source);
-                    writeCount = networkSystem
-                            .writeDirect(fd, address, pos, length);
+                    writeCount = networkSystem.writeDirect(fd, address, pos,
+                            length);
+                    // END android-changed
                 } else if (source.hasArray()) {
                     pos += source.arrayOffset();
                     writeCount = networkSystem.write(fd, source.array(), pos,
@@ -595,12 +586,8 @@
         }
     }
 
-    // -------------------------------------------------------------------
-    // Shared methods
-    // -------------------------------------------------------------------
-
     /*
-     * status check, open and "connected", when read and write.
+     * Status check, open and "connected", when read and write.
      */
     synchronized private void checkOpenConnected()
             throws ClosedChannelException {
@@ -613,7 +600,7 @@
     }
 
     /*
-     * status check, open and "unconnected", before connection.
+     * Status check, open and "unconnected", before connection.
      */
     synchronized private void checkUnconnected() throws IOException {
         if (!isOpen()) {
@@ -628,7 +615,7 @@
     }
 
     /*
-     * shared by this class and DatagramChannelImpl, to do the address transfer
+     * Shared by this class and DatagramChannelImpl, to do the address transfer
      * and check.
      */
     static InetSocketAddress validateAddress(SocketAddress socketAddress) {
@@ -646,7 +633,7 @@
     }
 
     /*
-     * get local address
+     * Get local address.
      */
     public InetAddress getLocalAddress() throws UnknownHostException {
         byte[] any_bytes = { 0, 0, 0, 0 };
@@ -656,11 +643,8 @@
         return localAddress;
     }
 
-    // -------------------------------------------------------------------
-    // Protected inherited methods
-    // -------------------------------------------------------------------
     /*
-     * do really closing action here
+     * Do really closing action here.
      */
     @Override
     synchronized protected void implCloseSelectableChannel() throws IOException {
@@ -674,7 +658,7 @@
         }
     }
 
-    /*
+    /**
      * @see java.nio.channels.spi.AbstractSelectableChannel#implConfigureBlocking(boolean)
      */
     @Override
@@ -685,30 +669,21 @@
     }
 
     /*
-     * get the fd
+     * Get the fd.
      */
     public FileDescriptor getFD() {
         return fd;
     }
 
-    // -------------------------------------------------------------------
-    // Adapter classes for internal socket.
-    // -------------------------------------------------------------------
-
+    /*
+     * Adapter classes for internal socket.
+     */
     private static class SocketAdapter extends Socket {
 
-        // ----------------------------------------------------
-        // Class Variables
-        // ----------------------------------------------------
-
         SocketChannelImpl channel;
 
         SocketImpl socketImpl;
 
-        // ----------------------------------------------------
-        // Methods
-        // ----------------------------------------------------
-
         SocketAdapter(SocketImpl socketimpl, SocketChannelImpl channel)
                 throws SocketException {
             super(socketimpl);
@@ -716,8 +691,7 @@
             this.channel = channel;
         }
 
-        /*
-         * 
+        /**
          * @see java.net.Socket#getChannel()
          */
         @Override
@@ -725,8 +699,7 @@
             return channel;
         }
 
-        /*
-         * 
+        /**
          * @see java.net.Socket#isBound()
          */
         @Override
@@ -734,8 +707,7 @@
             return channel.isBound;
         }
 
-        /*
-         * 
+        /**
          * @see java.net.Socket#isConnected()
          */
         @Override
@@ -743,8 +715,7 @@
             return channel.isConnected();
         }
 
-        /*
-         * 
+        /**
          * @see java.net.Socket#getLocalAddress()
          */
         @Override
@@ -756,8 +727,7 @@
             }
         }
 
-        /*
-         * 
+        /**
          * @see java.net.Socket#connect(java.net.SocketAddress, int)
          */
         @Override
@@ -778,8 +748,7 @@
             }
         }
 
-        /*
-         * 
+        /**
          * @see java.net.Socket#bind(java.net.SocketAddress)
          */
         @Override
@@ -798,8 +767,7 @@
 
         }
 
-        /*
-         * 
+        /**
          * @see java.net.Socket#close()
          */
         @Override
@@ -849,8 +817,7 @@
                     .intValue();
         }
 
-        /*
-         * 
+        /**
          * @see java.net.Socket#getKeepAlive()
          */
         @Override
@@ -860,8 +827,7 @@
                     .booleanValue();
         }
 
-        /*
-         * 
+        /**
          * @see java.net.Socket#getOOBInline()
          */
         @Override
@@ -871,8 +837,7 @@
                     .booleanValue();
         }
 
-        /*
-         * 
+        /**
          * @see java.net.Socket#getSoLinger()
          */
         @Override
@@ -882,7 +847,7 @@
                     .intValue();
         }
 
-        /*
+        /**
          * @see java.net.Socket#getTcpNoDelay()
          */
         @Override
@@ -892,7 +857,82 @@
                     .booleanValue();
         }
 
-        /*
+        @Override
+        public void setKeepAlive(boolean value) throws SocketException {
+            checkOpen();
+            socketImpl.setOption(SocketOptions.SO_KEEPALIVE, value ? Boolean.TRUE
+                    : Boolean.FALSE);
+        }
+
+        @Override
+        public void setOOBInline(boolean oobinline) throws SocketException {
+            checkOpen();
+            socketImpl.setOption(SocketOptions.SO_OOBINLINE, oobinline ? Boolean.TRUE
+                    : Boolean.FALSE);
+        }
+
+        @Override
+        public synchronized void setReceiveBufferSize(int size)
+                throws SocketException {
+            checkOpen();
+            if (size < 1) {
+                throw new IllegalArgumentException(Msg.getString("K0035")); //$NON-NLS-1$
+            }
+            socketImpl
+                    .setOption(SocketOptions.SO_RCVBUF, Integer.valueOf(size));
+        }
+
+        @Override
+        public void setReuseAddress(boolean reuse) throws SocketException {
+            checkOpen();
+            socketImpl.setOption(SocketOptions.SO_REUSEADDR, reuse ? Boolean.TRUE
+                    : Boolean.FALSE);
+        }
+
+        @Override
+        public synchronized void setSendBufferSize(int size) throws SocketException {
+            checkOpen();
+            if (size < 1) {
+                throw new IllegalArgumentException(Msg.getString("K0035")); //$NON-NLS-1$
+            }
+            socketImpl.setOption(SocketOptions.SO_SNDBUF, Integer.valueOf(size));
+        }
+
+        @Override
+        public void setSoLinger(boolean on, int timeout) throws SocketException {
+            checkOpen();
+            if (on && timeout < 0) {
+                throw new IllegalArgumentException(Msg.getString("K0045")); //$NON-NLS-1$
+            }
+            int val = on ? (65535 < timeout ? 65535 : timeout) : -1;
+            socketImpl.setOption(SocketOptions.SO_LINGER, Integer.valueOf(val));
+        }
+
+        @Override
+        public synchronized void setSoTimeout(int timeout) throws SocketException {
+            checkOpen();
+            if (timeout < 0) {
+                throw new IllegalArgumentException(Msg.getString("K0036")); //$NON-NLS-1$
+            }
+            socketImpl.setOption(SocketOptions.SO_TIMEOUT, Integer.valueOf(timeout));
+        }
+
+        @Override
+        public void setTcpNoDelay(boolean on) throws SocketException {
+            checkOpen();
+            socketImpl.setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on));
+        }
+
+        @Override
+        public void setTrafficClass(int value) throws SocketException {
+            checkOpen();
+            if (value < 0 || value > 255) {
+                throw new IllegalArgumentException();
+            }
+            socketImpl.setOption(SocketOptions.IP_TOS, Integer.valueOf(value));
+        }
+
+        /**
          * @see java.net.Socket#getOutputStream()
          */
         @Override
@@ -912,8 +952,7 @@
             return new SocketChannelOutputStream(channel);
         }
 
-        /*
-         * 
+        /**
          * @see java.net.Socket#getInputStream()
          */
         @Override
@@ -934,7 +973,7 @@
         }
 
         /*
-         * Checks whether the channel is open
+         * Checks whether the channel is open.
          */
         private void checkOpen() throws SocketException {
             if (isClosed()) {
@@ -944,7 +983,7 @@
         }
 
         /*
-         * used for net and nio exchange
+         * Used for net and nio exchange.
          */
         public SocketImpl getImpl() {
             return socketImpl;
@@ -964,7 +1003,7 @@
         }
 
         /*
-         * Closes this stream and channel
+         * Closes this stream and channel.
          * 
          * @exception IOException thrown if an error occurs during the close
          */
@@ -973,7 +1012,7 @@
             channel.close();
         }
 
-        /*
+        /**
          * @see java.io.OutputStream#write(byte[], int, int)
          */
         @Override
@@ -989,7 +1028,7 @@
             channel.write(buf);
         }
 
-        /*
+        /**
          * @see java.io.OutputStream#write(int)
          */
         @Override
@@ -1023,7 +1062,7 @@
             channel.close();
         }
 
-        /*
+        /**
          * @see java.io.InputStream#read()
          */
         @Override
@@ -1038,7 +1077,7 @@
             // END android-changed
         }
 
-        /*
+        /**
          * @see java.io.InputStream#read(byte[], int, int)
          */
         @Override
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..8a77b9d 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
@@ -17,6 +17,7 @@
 
 package org.apache.harmony.nio.tests.java.nio.channels;
 
+import dalvik.annotation.KnownFailure;
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargets;
 import dalvik.annotation.TestLevel;
@@ -666,6 +667,7 @@
         method = "socket",
         args = {}
     )
+    @KnownFailure(value="bug 2155708")
     public void testSocket_BasicStatusBeforeConnect() throws SocketException {
         assertFalse(this.channel1.isConnected());// not connected
         DatagramSocket s1 = this.channel1.socket();
diff --git a/libcore/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SocketChannelTest.java b/libcore/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SocketChannelTest.java
index b7a1012..ce34dba 100755
--- a/libcore/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SocketChannelTest.java
+++ b/libcore/nio/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SocketChannelTest.java
@@ -29,6 +29,8 @@
 import java.io.OutputStream;
 import java.net.BindException;
 import java.net.ConnectException;
+import java.net.Inet4Address;
+import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.ServerSocket;
 import java.net.Socket;
@@ -4114,6 +4116,95 @@
         }
     }
 
+    /**
+     * @throws IOException 
+     * @tests java.nio.channels.SocketChannel#read(ByteBuffer)
+     */
+    @TestTargetNew(
+        level = TestLevel.PARTIAL_COMPLETE,
+        notes = "",
+        method = "read",
+        args = {java.nio.ByteBuffer[].class}
+    ) 
+    public void test_socketChannel_read_DirectByteBuffer() throws InterruptedException, IOException {
+
+        ServerThread server = new ServerThread();
+        server.start();
+        Thread.currentThread().sleep(1000);
+
+        InetSocketAddress address = new InetSocketAddress(InetAddress
+                .getByName("localhost"), port);
+
+        // First test with array based byte buffer
+        SocketChannel sc = SocketChannel.open();
+        sc.connect(address);
+
+        ByteBuffer buf = ByteBuffer.allocate(data.length);
+        buf.limit(data.length / 2);
+        sc.read(buf);
+
+        buf.limit(buf.capacity());
+        sc.read(buf);
+        sc.close();
+
+        // Make sure the buffer is filled correctly
+        buf.rewind();
+        assertSameContent(data, buf);
+
+        // Now test with direct byte buffer
+        sc = SocketChannel.open();
+        sc.connect(address);
+
+        buf = ByteBuffer.allocateDirect(data.length);
+        buf.limit(data.length / 2);
+        sc.read(buf);
+
+        buf.limit(buf.capacity());
+        sc.read(buf);
+        sc.close();
+
+        // Make sure the buffer is filled correctly
+        buf.rewind();
+        assertSameContent(data, buf);
+    }
+
+    private void assertSameContent(byte[] data, ByteBuffer buf) {
+        for (byte b : data) {
+            if (b != buf.get()) {
+                int pos = buf.position() - 1;
+                fail("Content not equal. Buffer position: " +
+                        (pos) + " expected: " + b + " was: " + buf.get(pos));
+            }
+        }
+    }
+
+    public static boolean done = false;
+    public static int port = Support_PortManager.getNextPort();
+    public static byte[] data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+
+    static class ServerThread extends Thread {
+        @Override
+        public void run() {
+            try {
+                ServerSocketChannel ssc = ServerSocketChannel.open();
+                InetSocketAddress addr = new InetSocketAddress(InetAddress
+                        .getByAddress(new byte[] {0, 0, 0, 0}), port);
+                ssc.socket().bind(addr, 0);
+
+                ByteBuffer buf = ByteBuffer.allocate(10);
+                buf.put(data);
+
+                while (!done) {
+                    SocketChannel sc = ssc.accept();
+                    buf.rewind();
+                    sc.write(buf);
+                }
+            } catch (Exception e) {
+                // ignore
+            }
+        }
+    }
+
     class MockSocketChannel extends SocketChannel {
 
         private boolean isWriteCalled = false;
diff --git a/libcore/nio_char/src/test/java/tests/api/java/nio/charset/CharsetProviderTest.java b/libcore/nio_char/src/test/java/tests/api/java/nio/charset/CharsetProviderTest.java
index 6bcdaef..903c689 100644
--- a/libcore/nio_char/src/test/java/tests/api/java/nio/charset/CharsetProviderTest.java
+++ b/libcore/nio_char/src/test/java/tests/api/java/nio/charset/CharsetProviderTest.java
@@ -266,8 +266,6 @@
         method = "charsetForName",
         args = {String.class}
     )
-    @KnownFailure("Android throws Error in case of insufficient privileges, " +
-            "RI throws SecurityException")
     public void testIsSupported_InsufficientPrivilege() throws Exception {
         SecurityManager oldMan = System.getSecurityManager();
         System.setSecurityManager(new MockSecurityManager());
@@ -301,8 +299,6 @@
         method = "charsetForName",
         args = {String.class}
     )
-    @KnownFailure("Android throws Error in case of insufficient privileges, " +
-            "RI throws SecurityException")
     public void testForName_InsufficientPrivilege() throws Exception {
         SecurityManager oldMan = System.getSecurityManager();
         System.setSecurityManager(new MockSecurityManager());
diff --git a/libcore/prefs/src/main/java/java/util/prefs/AbstractPreferences.java b/libcore/prefs/src/main/java/java/util/prefs/AbstractPreferences.java
index 711cc01..3264569 100644
--- a/libcore/prefs/src/main/java/java/util/prefs/AbstractPreferences.java
+++ b/libcore/prefs/src/main/java/java/util/prefs/AbstractPreferences.java
@@ -20,6 +20,7 @@
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
+import java.util.Collection;
 import java.util.EventListener;
 import java.util.EventObject;
 import java.util.HashMap;
@@ -27,7 +28,6 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
-import java.util.StringTokenizer;
 import java.util.TreeSet;
 
 import org.apache.harmony.luni.util.Base64;
@@ -38,8 +38,9 @@
  * Preferences, which can be used to simplify {@code Preferences} provider's
  * implementation. This class defines nine abstract SPI methods, which must be
  * implemented by a preference provider.
- * 
- * @since Android 1.0
+ *
+ * @since 1.4
+ * @see Preferences
  */
 public abstract class AbstractPreferences extends Preferences {
     /*
@@ -47,14 +48,9 @@
      * Class fields
      * -----------------------------------------------------------
      */
-    /**
-     * The unhandled events collection.
-     */
+    /** the unhandled events collection */
     private static final List<EventObject> events = new LinkedList<EventObject>();
-
-    /**
-     * The event dispatcher thread.
-     */
+    /** the event dispatcher thread */
     private static final EventDispatcher dispatcher = new EventDispatcher("Preference Event Dispatcher"); //$NON-NLS-1$
 
     /*
@@ -72,11 +68,13 @@
                 Preferences sroot = Preferences.systemRoot();
                 try {
                     uroot.flush();
-                } catch (BackingStoreException e) {//ignore
+                } catch (BackingStoreException e) {
+                    // ignore
                 }
                 try {
                     sroot.flush();
-                } catch (BackingStoreException e) {//ignore
+                } catch (BackingStoreException e) {
+                    // ignore
                 }
             }
         });
@@ -87,9 +85,7 @@
      * Instance fields (package-private)
      * -----------------------------------------------------------
      */
-    /**
-     * True, if this node is in user preference hierarchy.
-     */
+    /** true if this node is in user preference hierarchy */
     boolean userNode;
 
     /*
@@ -97,16 +93,11 @@
      * Instance fields (private)
      * -----------------------------------------------------------
      */
-    /**
-     * Marker class for 'lock' field.
-     */
-    private static class Lock {
-    }
+    /** Marker class for 'lock' field. */
+    private static class Lock {}
 
     /**
      * The object used to lock this node.
-     * 
-     * @since Android 1.0
      */
     protected final Object lock;
     
@@ -115,14 +106,10 @@
      * backing store. This field's default value is false, and it is checked
      * when the node creation is completed, and if it is true, the node change
      * event will be fired for this node's parent.
-     * 
-     * @since Android 1.0
      */
     protected boolean newNode;
 
-    /**
-     * Cached child nodes
-     */
+    /** cached child nodes */
     private Map<String, AbstractPreferences> cachedNode;
 
     //the collections of listeners
@@ -147,9 +134,9 @@
      * -----------------------------------------------------------
      */
     /**
-     * Constructs a new {@code AbstractPreferences} instance using the given parent node
-     * and node name.
-     * 
+     * Constructs a new {@code AbstractPreferences} instance using the given
+     * parent node and node name.
+     *
      * @param parent
      *            the parent node of the new node or {@code null} to indicate
      *            that the new node is a root node.
@@ -159,7 +146,6 @@
      * @throws IllegalArgumentException
      *             if the name contains a slash character or is empty if {@code
      *             parent} is not {@code null}.
-     * @since Android 1.0
      */
     protected AbstractPreferences(AbstractPreferences parent, String name) {
         if ((null == parent ^ name.length() == 0) || name.indexOf("/") >= 0) { //$NON-NLS-1$
@@ -185,7 +171,6 @@
      * Returns an array of all cached child nodes.
      * 
      * @return the array of cached child nodes.
-     * @since Android 1.0
      */
     protected final AbstractPreferences[] cachedChildren() {
         return cachedNode.values().toArray(new AbstractPreferences[cachedNode.size()]);
@@ -193,9 +178,10 @@
 
     /**
      * Returns the child node with the specified name or {@code null} if it
-     * doesn't exist. Implementers can assume that the name supplied to this method 
-     * will be a valid node name string (conforming to the node naming format) and 
-     * will not correspond to a node that has been cached or removed.
+     * doesn't exist. Implementers can assume that the name supplied to this
+     * method will be a valid node name string (conforming to the node naming
+     * format) and will not correspond to a node that has been cached or
+     * removed.
      * 
      * @param name
      *            the name of the desired child node.
@@ -204,7 +190,6 @@
      * @throws BackingStoreException
      *             if the backing store is unavailable or causes an operation
      *             failure.
-     * @since Android 1.0
      */
     protected AbstractPreferences getChild(String name)
             throws BackingStoreException {
@@ -226,10 +211,9 @@
     /**
      * Returns whether this node has been removed by invoking the method {@code
      * removeNode()}.
-     * 
+     *
      * @return {@code true}, if this node has been removed, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     protected boolean isRemoved() {
         synchronized (lock) {
@@ -240,33 +224,31 @@
     /**
      * Flushes changes of this node to the backing store. This method should
      * only flush this node and should not include the descendant nodes. Any
-     * implementation that wants to provide functionality to flush all nodes 
+     * implementation that wants to provide functionality to flush all nodes
      * at once should override the method {@link #flush() flush()}.
-     * 
+     *
      * @throws BackingStoreException
      *             if the backing store is unavailable or causes an operation
      *             failure.
-     * @since Android 1.0
      */
     protected abstract void flushSpi() throws BackingStoreException;
     
     /**
-     * Returns the names of all of the child nodes of this node or an empty array if
-     * this node has no children. The names of cached children are not required to be
-     * returned.
-     * 
+     * Returns the names of all of the child nodes of this node or an empty
+     * array if this node has no children. The names of cached children are not
+     * required to be returned.
+     *
      * @return the names of this node's children.
      * @throws BackingStoreException
      *             if the backing store is unavailable or causes an operation
      *             failure.
-     * @since Android 1.0
      */
     protected abstract String[] childrenNamesSpi() throws BackingStoreException;
 
     /**
      * Returns the child preference node with the given name, creating it
      * if it does not exist. The caller of this method should ensure that the
-     * given name is valid and that this node has not been removed or cached. 
+     * given name is valid and that this node has not been removed or cached.
      * If the named node has just been removed, the implementation
      * of this method must create a new one instead of reactivating the removed
      * one.
@@ -278,7 +260,6 @@
      * @param name
      *            the name of the child preference to be returned.
      * @return the child preference node.
-     * @since Android 1.0
      */
     protected abstract AbstractPreferences childSpi(String name);
 
@@ -287,39 +268,37 @@
      * Puts the given key-value pair into this node. Caller of this method
      * should ensure that both of the given values are valid and that this
      * node has not been removed.
-     * 
+     *
      * @param name
      *            the given preference key.
      * @param value
      *            the given preference value.
-     * @since Android 1.0
      */
     protected abstract void putSpi(String name, String value);
 
     /**
-     * Gets the preference value mapped to the given key. The caller of this method
-     * should ensure that the given key is valid and that this node has not been
-     * removed. This method should not throw any exceptions but if it does, the
-     * caller will ignore the exception, regarding it as a {@code null} return value.
-     * 
+     * Gets the preference value mapped to the given key. The caller of this
+     * method should ensure that the given key is valid and that this node has
+     * not been removed. This method should not throw any exceptions but if it
+     * does, the caller will ignore the exception, regarding it as a {@code
+     * null} return value.
+     *
      * @param key
      *            the given key to be searched for.
      * @return the preference value mapped to the given key.
-     * @since Android 1.0
      */
     protected abstract String getSpi(String key);
 
 
     /**
      * Returns an array of all preference keys of this node or an empty array if
-     * no preferences have been found. The caller of this method should ensure that
-     * this node has not been removed.
-     * 
+     * no preferences have been found. The caller of this method should ensure
+     * that this node has not been removed.
+     *
      * @return the array of all preference keys.
      * @throws BackingStoreException
      *             if the backing store is unavailable or causes an operation
      *             failure.
-     * @since Android 1.0
      */
     protected abstract String[] keysSpi() throws BackingStoreException;
 
@@ -329,11 +308,10 @@
      * method {@link Preferences#removeNode() Preferences.removeNode()} should
      * invoke this method multiple-times in bottom-up pattern. The removal is
      * not required to be persisted until after it is flushed.
-     * 
+     *
      * @throws BackingStoreException
      *             if the backing store is unavailable or causes an operation
      *             failure.
-     * @since Android 1.0
      */
     protected abstract void removeNodeSpi() throws BackingStoreException;
 
@@ -344,20 +322,18 @@
      * 
      * @param key
      *            the key of the preference that is to be removed.
-     * @since Android 1.0
      */
     protected abstract void removeSpi(String key);
 
     /**
      * Synchronizes this node with the backing store. This method should only
      * synchronize this node and should not include the descendant nodes. An
-     * implementation that wants to provide functionality to synchronize all nodes at once should
-     * override the method {@link #sync() sync()}.
+     * implementation that wants to provide functionality to synchronize all
+     * nodes at once should override the method {@link #sync() sync()}.
      * 
      * @throws BackingStoreException
      *             if the backing store is unavailable or causes an operation
      *             failure.
-     * @since Android 1.0
      */
     protected abstract void syncSpi() throws BackingStoreException;
 
@@ -385,7 +361,7 @@
             for (int i = 0; i < names.length; i++) {
                 result.add(names[i]);
             }
-            return result.toArray(new String[0]);
+            return result.toArray(new String[result.size()]);
         }
     }
 
@@ -439,13 +415,13 @@
         if (key == null) {
             throw new NullPointerException();
         }
-        String result;
+        String result = null;
         synchronized (lock) {
             checkState();
             try {
                 result = getSpi(key);
             } catch (Exception e) {
-                result = null;
+                // ignored
             }
         }
         return (result == null ? deflt : result);
@@ -456,9 +432,10 @@
         String result = get(key, null);
         if (result == null) {
             return deflt;
-        } else if (result.equalsIgnoreCase("true")) { //$NON-NLS-1$
+        }
+        if ("true".equalsIgnoreCase(result)) { //$NON-NLS-1$
             return true;
-        } else if (result.equalsIgnoreCase("false")) { //$NON-NLS-1$
+        } else if ("false".equalsIgnoreCase(result)) { //$NON-NLS-1$
             return false;
         } else {
             return deflt;
@@ -474,17 +451,15 @@
         if (svalue.length() == 0) { 
             return new byte[0];
         }
-        byte[] dres;
         try {
             byte[] bavalue = svalue.getBytes("US-ASCII"); //$NON-NLS-1$
             if (bavalue.length % 4 != 0) {
                 return deflt;
             }
-            dres = Base64.decode(bavalue);
+            return Base64.decode(bavalue);
         } catch (Exception e) {
-            dres = deflt;
+            return deflt;
         }
-        return dres;
     }
 
     @Override
@@ -493,13 +468,11 @@
         if (result == null) {
             return deflt;
         }
-        double dres;
         try {
-            dres = Double.parseDouble(result);
+            return Double.parseDouble(result);
         } catch (NumberFormatException e) {
-            dres = deflt;
+            return deflt;
         }
-        return dres;
     }
 
     @Override
@@ -508,13 +481,11 @@
         if (result == null) {
             return deflt;
         }
-        float fres;
         try {
-            fres = Float.parseFloat(result);
+            return Float.parseFloat(result);
         } catch (NumberFormatException e) {
-            fres = deflt;
+            return deflt;
         }
-        return fres;
     }
 
     @Override
@@ -523,13 +494,11 @@
         if (result == null) {
             return deflt;
         }
-        int ires;
         try {
-            ires = Integer.parseInt(result);
+            return Integer.parseInt(result);
         } catch (NumberFormatException e) {
-            ires = deflt;
+            return deflt;
         }
-        return ires;
     }
 
     @Override
@@ -538,13 +507,11 @@
         if (result == null) {
             return deflt;
         }
-        long lres;
         try {
-            lres = Long.parseLong(result);
+            return Long.parseLong(result);
         } catch (NumberFormatException e) {
-            lres = deflt;
+            return deflt;
         }
-        return lres;
     }
 
     @Override
@@ -583,42 +550,44 @@
                 startNode = this;
             }
         }
-        Preferences result = null;
         try {
-            result = startNode.nodeImpl(name, true);
+            return startNode.nodeImpl(name, true);
         } catch (BackingStoreException e) {
-            //should not happen
+            // should not happen
+            return null;
         }
-        return result;
     }
 
     private void validateName(String name) {
         if (name.endsWith("/") && name.length() > 1) { //$NON-NLS-1$
             // prefs.6=Name cannot end with '/'\!
-            throw new IllegalArgumentException(Messages.getString("prefs.6"));  //$NON-NLS-1$
+            throw new IllegalArgumentException(Messages.getString("prefs.6")); //$NON-NLS-1$
         }
         if (name.indexOf("//") >= 0) { //$NON-NLS-1$
             // prefs.7=Name cannot contains consecutive '/'\!
-            throw new IllegalArgumentException(
-                    Messages.getString("prefs.7"));  //$NON-NLS-1$
+            throw new IllegalArgumentException(Messages.getString("prefs.7")); //$NON-NLS-1$
         }
     }
 
     private AbstractPreferences nodeImpl(String path, boolean createNew)
             throws BackingStoreException {
-        StringTokenizer st = new StringTokenizer(path, "/"); //$NON-NLS-1$
+        String[] names = path.split("/");//$NON-NLS-1$
         AbstractPreferences currentNode = this;
         AbstractPreferences temp = null;
-        while (st.hasMoreTokens() && null != currentNode) {
-            String name = st.nextToken();
-            synchronized (currentNode.lock) {
-                temp = currentNode.cachedNode.get(name);
-                if (temp == null) {
-                    temp = getNodeFromBackend(createNew, currentNode, name);
+        if (null != currentNode) {
+            for (int i = 0; i < names.length; i++) {
+                String name = names[i];
+                synchronized (currentNode.lock) {
+                    temp = currentNode.cachedNode.get(name);
+                    if (temp == null) {
+                        temp = getNodeFromBackend(createNew, currentNode, name);
+                    }
+                }
+                currentNode = temp;
+                if (null == currentNode) {
+                    break;
                 }
             }
-
-            currentNode = temp;
         }
         return currentNode;
     }
@@ -626,12 +595,12 @@
     private AbstractPreferences getNodeFromBackend(boolean createNew,
             AbstractPreferences currentNode, String name)
             throws BackingStoreException {
-        AbstractPreferences temp;
         if (name.length() > MAX_NAME_LENGTH) {
             // prefs.8=Name length is too long: {0}
-            throw new IllegalArgumentException(Messages.getString("prefs.8",  //$NON-NLS-1$
+            throw new IllegalArgumentException(Messages.getString("prefs.8", //$NON-NLS-1$
                     name));
         }
+        AbstractPreferences temp;
         if (createNew) {
             temp = currentNode.childSpi(name);
             currentNode.cachedNode.put(name, temp);
@@ -646,6 +615,9 @@
 
     @Override
     public boolean nodeExists(String name) throws BackingStoreException {
+        if (null == name) {
+            throw new NullPointerException();
+        }
         AbstractPreferences startNode = null;
         synchronized (lock) {
             if (isRemoved()) {
@@ -771,10 +743,11 @@
                     cachedNode.put(childrenNames[i], child);
                 }
             }
-            AbstractPreferences[] children = cachedNode
-                    .values().toArray(new AbstractPreferences[0]);
-            for (int i = 0; i < children.length; i++) {
-                children[i].removeNodeImpl();
+            
+            final Collection<AbstractPreferences> values = cachedNode.values();
+            final AbstractPreferences[] children = values.toArray(new AbstractPreferences[values.size()]);
+            for (AbstractPreferences child : children) {
+                child.removeNodeImpl();
             }
             removeNodeSpi();
             isRemoved = true;
diff --git a/libcore/prefs/src/main/java/java/util/prefs/BackingStoreException.java b/libcore/prefs/src/main/java/java/util/prefs/BackingStoreException.java
index e8a805c..553d7ab 100644
--- a/libcore/prefs/src/main/java/java/util/prefs/BackingStoreException.java
+++ b/libcore/prefs/src/main/java/java/util/prefs/BackingStoreException.java
@@ -17,40 +17,35 @@
 
 package java.util.prefs;
 
-
 /**
  * An exception to indicate that an error was encountered while accessing the
  * backing store.
- * 
- * @since Android 1.0
+ *
+ * @since 1.4
  */
 public class BackingStoreException extends Exception {
-    
+
     private static final long serialVersionUID = 859796500401108469L;
-    
+
     /**
-     * Constructs a new {@code BackingStoreException} instance with a detailed exception
-     * message.
+     * Constructs a new {@code BackingStoreException} instance with a detailed
+     * exception message.
      * 
      * @param s
      *            the detailed exception message.
-     * @since Android 1.0
      */
     public BackingStoreException (String s) {
         super(s);
     }
 
     /**
-     * Constructs a new {@code BackingStoreException} instance with a nested {@code Throwable}.
-     * 
+     * Constructs a new {@code BackingStoreException} instance with a nested
+     * {@code Throwable}.
+     *
      * @param t
      *            the nested {@code Throwable}.
-     * @since Android 1.0
      */
     public BackingStoreException (Throwable t) {
         super(t);
     }
 }
-
-
-
diff --git a/libcore/prefs/src/main/java/java/util/prefs/FilePreferencesFactoryImpl.java b/libcore/prefs/src/main/java/java/util/prefs/FilePreferencesFactoryImpl.java
index cc68e62..69eaa01 100644
--- a/libcore/prefs/src/main/java/java/util/prefs/FilePreferencesFactoryImpl.java
+++ b/libcore/prefs/src/main/java/java/util/prefs/FilePreferencesFactoryImpl.java
@@ -17,10 +17,10 @@
 package java.util.prefs;
 
 /**
- * The default implementation of <code>PreferencesFactory</code> for the Linux 
+ * The default implementation of <code>PreferencesFactory</code> for the Linux
  * platform, using the file system as its back end.
- * 
- * @since Android 1.0
+ *
+ * @since 1.4
  */
 class FilePreferencesFactoryImpl implements PreferencesFactory {
     //  user root preferences
diff --git a/libcore/prefs/src/main/java/java/util/prefs/FilePreferencesImpl.java b/libcore/prefs/src/main/java/java/util/prefs/FilePreferencesImpl.java
index cf85fa0..f6e5e8f 100644
--- a/libcore/prefs/src/main/java/java/util/prefs/FilePreferencesImpl.java
+++ b/libcore/prefs/src/main/java/java/util/prefs/FilePreferencesImpl.java
@@ -28,12 +28,12 @@
 import org.apache.harmony.prefs.internal.nls.Messages;
 
 /**
- * The default implementation of <code>AbstractPreferences</code> for the Linux platform,
- * using the file system as its back end.
- * 
+ * The default implementation of <code>AbstractPreferences</code> for the Linux
+ * platform, using the file system as its back end.
+ *
  * TODO some sync mechanism with backend, Performance - check file edit date
- * 
- * @since Android 1.0
+ *
+ * @since 1.4
  */
 class FilePreferencesImpl extends AbstractPreferences {
 
@@ -64,7 +64,6 @@
                 SYSTEM_HOME = System.getProperty("java.home") + "/.systemPrefs";//$NON-NLS-1$//$NON-NLS-2$
                 return null;
             }
-
         });
     }
 
@@ -97,9 +96,9 @@
      * Constructors
      * --------------------------------------------------------------
      */
-    
+
     /**
-     * Construct root <code>FilePreferencesImpl</code> instance, construct 
+     * Construct root <code>FilePreferencesImpl</code> instance, construct
      * user root if userNode is true, system root otherwise
      */
     FilePreferencesImpl(boolean userNode) {
@@ -108,9 +107,9 @@
         path = userNode ? USER_HOME : SYSTEM_HOME;
         initPrefs();
     }
-    
+
     /**
-     * Construct a prefs using given parent and given name 
+     * Construct a prefs using given parent and given name
      */
     private FilePreferencesImpl(AbstractPreferences parent, String name) {
         super(parent, name);
@@ -132,16 +131,16 @@
     @Override
     protected String[] childrenNamesSpi() throws BackingStoreException {
         String[] names = AccessController
-                .doPrivileged(new PrivilegedAction<String[]>() {
-                    public String[] run() {
-                        return dir.list(new FilenameFilter() {
-                            public boolean accept(File parent, String name) {
-                                return new File(path + File.separator + name).isDirectory(); 
-                            }
-                        });
-
+        .doPrivileged(new PrivilegedAction<String[]>() {
+            public String[] run() {
+                return dir.list(new FilenameFilter() {
+                    public boolean accept(File parent, String name) {
+                        return new File(path + File.separator + name).isDirectory();
                     }
                 });
+
+            }
+        });
         if (null == names) {// file is not a directory, exception case
             // prefs.3=Cannot get children names for {0}!
             throw new BackingStoreException(
@@ -192,14 +191,16 @@
                 prefs = XMLParser.loadFilePrefs(prefsFile);
             }
             return prefs.getProperty(key);
-        } catch (Exception e) {// if Exception happened, return null
+        } catch (Exception e) {
+            // if Exception happened, return null
             return null;
         }
     }
 
     @Override
     protected String[] keysSpi() throws BackingStoreException {
-        return prefs.keySet().toArray(new String[0]);
+        final Set<Object> ks = prefs.keySet();
+        return ks.toArray(new String[ks.size()]);
     }
 
     @Override
diff --git a/libcore/prefs/src/main/java/java/util/prefs/InvalidPreferencesFormatException.java b/libcore/prefs/src/main/java/java/util/prefs/InvalidPreferencesFormatException.java
index b31b3a1..ba8940b 100644
--- a/libcore/prefs/src/main/java/java/util/prefs/InvalidPreferencesFormatException.java
+++ b/libcore/prefs/src/main/java/java/util/prefs/InvalidPreferencesFormatException.java
@@ -21,51 +21,43 @@
  * An exception to indicate that the input XML file is not well-formed or could
  * not be validated against the appropriate document type (specified by
  * in the {@code Preferences}).
- * 
- * @since Android 1.0
  */
 public class InvalidPreferencesFormatException extends Exception {
-    
+
     private static final long serialVersionUID = -791715184232119669L;
-    
+
     /**
-     * Constructs a new {@code InvalidPreferencesFormatException} instance with a
-     * detailed exception message.
+     * Constructs a new {@code InvalidPreferencesFormatException} instance with
+     * a detailed exception message.
      * 
      * @param s
      *            the detailed exception message.
-     * @since Android 1.0
      */
     public InvalidPreferencesFormatException (String s) {
         super(s);
     }
 
     /**
-     * Constructs a new {@code InvalidPreferencesFormatException} instance with a
-     * detailed exception message and a nested {@code Throwable}.
+     * Constructs a new {@code InvalidPreferencesFormatException} instance with
+     * a detailed exception message and a nested {@code Throwable}.
      * 
      * @param s
      *            the detailed exception message.
      * @param t
      *            the nested {@code Throwable}.
-     * @since Android 1.0
      */
     public InvalidPreferencesFormatException (String s, Throwable t) {
         super(s,t);
     }
 
     /**
-     * Constructs a new {@code InvalidPreferencesFormatException} instance with a nested
-     * {@code Throwable}.
-     * 
+     * Constructs a new {@code InvalidPreferencesFormatException} instance with
+     * a nested {@code Throwable}.
+     *
      * @param t
      *            the nested {@code Throwable}.
-     * @since Android 1.0
      */
     public InvalidPreferencesFormatException (Throwable t) {
         super(t);
     }
 }
-
-
-
diff --git a/libcore/prefs/src/main/java/java/util/prefs/NodeChangeEvent.java b/libcore/prefs/src/main/java/java/util/prefs/NodeChangeEvent.java
index e9824bc..3e23f5a 100644
--- a/libcore/prefs/src/main/java/java/util/prefs/NodeChangeEvent.java
+++ b/libcore/prefs/src/main/java/java/util/prefs/NodeChangeEvent.java
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-
 package java.util.prefs;
 
 import java.io.Serializable;
@@ -28,19 +27,22 @@
  * This is the event class to indicate that one child of the preference node has
  * been added or deleted.
  * <p>
- * Please note that the serialization functionality has not yet been implemented, so
- * the serialization methods do nothing but throw a {@code NotSerializableException}.
- * </p>
+ * Please note that although the class is marked as {@code Serializable} by
+ * inheritance from {@code EventObject}, this type is not intended to be serialized
+ * so the serialization methods do nothing but throw a {@code NotSerializableException}.
  * 
- * @since Android 1.0
+ * @see java.util.prefs.Preferences
+ * @see java.util.prefs.NodeChangeListener
+ * 
+ * @since 1.4
  */
 public class NodeChangeEvent extends EventObject implements Serializable {
-    
+
     private static final long serialVersionUID = 8068949086596572957L;
-    
+
     private final Preferences parent;
     private final Preferences child;
-    
+
     /**
      * Constructs a new {@code NodeChangeEvent} instance.
      * 
@@ -49,43 +51,40 @@
      *            considered as the event source.
      * @param c
      *            the child {@code Preferences} instance that was added or deleted.
-     * @since Android 1.0
      */
     public NodeChangeEvent (Preferences p, Preferences c) {
         super(p);
         parent = p;
         child = c;
     }
-    
+
     /**
      * Gets the {@code Preferences} instance that fired this event.
      * 
      * @return the {@code Preferences} instance that fired this event.
-     * @since Android 1.0
      */
     public Preferences getParent() {
         return parent;
     }
-    
+
     /**
      * Gets the child {@code Preferences} node that was added or removed.
      * 
      * @return the added or removed child {@code Preferences} node.
-     * @since Android 1.0
      */
     public Preferences getChild() {
         return child;
     }
-    
-    /*
+
+    /**
      * This method always throws a <code>NotSerializableException</code>,
      * because this object cannot be serialized,
      */
     private void writeObject (ObjectOutputStream out) throws IOException {
         throw new NotSerializableException();
     }
-    
-    /*
+
+    /**
      * This method always throws a <code>NotSerializableException</code>,
      * because this object cannot be serialized,
      */
@@ -93,7 +92,3 @@
         throw new NotSerializableException();
     }
 }
-
-
-
- 
diff --git a/libcore/prefs/src/main/java/java/util/prefs/NodeChangeListener.java b/libcore/prefs/src/main/java/java/util/prefs/NodeChangeListener.java
index f16b206..41da23e 100644
--- a/libcore/prefs/src/main/java/java/util/prefs/NodeChangeListener.java
+++ b/libcore/prefs/src/main/java/java/util/prefs/NodeChangeListener.java
@@ -14,41 +14,36 @@
  * limitations under the License.
  */
 
-
 package java.util.prefs;
 
 import java.util.EventListener;
 import java.util.prefs.NodeChangeEvent;
 
 /**
- * This interface is used to handle preference node change events.
- * The implementation of this interface can be installed by the {@code Preferences} instance.
+ * This interface is used to handle preference node change events. The
+ * implementation of this interface can be installed by the {@code Preferences}
+ * instance.
  * 
+ * @see Preferences
  * @see NodeChangeEvent
  * 
- * @since Android 1.0
+ * @since 1.4
  */
 public interface NodeChangeListener extends EventListener {
-
     /**
      * This method gets called whenever a child node is added to another node.
      * 
      * @param e
      *            the node change event.
-     * @since Android 1.0
      */
     public void childAdded (NodeChangeEvent e);
-    
+
     /**
      * This method gets called whenever a child node is removed from another
      * node.
      * 
      * @param e
      *            the node change event.
-     * @since Android 1.0
      */
     public void childRemoved (NodeChangeEvent e);
 }
-
-
- 
diff --git a/libcore/prefs/src/main/java/java/util/prefs/PreferenceChangeEvent.java b/libcore/prefs/src/main/java/java/util/prefs/PreferenceChangeEvent.java
index f0f0787..d355f4e 100644
--- a/libcore/prefs/src/main/java/java/util/prefs/PreferenceChangeEvent.java
+++ b/libcore/prefs/src/main/java/java/util/prefs/PreferenceChangeEvent.java
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-
 package java.util.prefs;
 
 import java.io.IOException;
@@ -28,16 +27,19 @@
  * This is the event class to indicate that a preference has been added, deleted
  * or updated.
  * <p>
- * Please note that the serialization functionality has not yet been implemented, so
- * the serialization methods do nothing but throw a {@code NotSerializableException}.
- * </p>
+ * Please note that although the class is marked as {@code Serializable} by
+ * inheritance from {@code EventObject}, this type is not intended to be serialized
+ * so the serialization methods do nothing but throw a {@code NotSerializableException}.
  * 
- * @since Android 1.0
+ * @see java.util.prefs.Preferences
+ * @see java.util.prefs.PreferenceChangeListener
+ * 
+ * @since 1.4
  */
 public class PreferenceChangeEvent extends EventObject implements Serializable {
 
     private static final long serialVersionUID = 793724513368024975L;
-    
+
     private final Preferences node;
 
     private final String key;
@@ -55,7 +57,6 @@
      * @param v
      *            the new value of the changed preference, this value can be
      *            {@code null}, which means the preference has been removed.
-     * @since Android 1.0
      */
     public PreferenceChangeEvent(Preferences p, String k, String v) {
         super(p);
@@ -68,7 +69,6 @@
      * Gets the key of the changed preference.
      * 
      * @return the changed preference's key.
-     * @since Android 1.0
      */
     public String getKey() {
         return key;
@@ -78,9 +78,8 @@
      * Gets the new value of the changed preference or {@code null} if the
      * preference has been removed.
      * 
-     * @return the new value of the changed preference or null if the preference
-     *         has been removed.
-     * @since Android 1.0
+     * @return the new value of the changed preference or {@code null} if the
+     *         preference has been removed.
      */
     public String getNewValue() {
         return value;
@@ -90,13 +89,12 @@
      * Gets the {@code Preferences} instance that fired this event.
      * 
      * @return the {@code Preferences} instance that fired this event.
-     * @since Android 1.0
      */
     public Preferences getNode() {
         return node;
     }
 
-    /*
+    /**
      * This method always throws a <code>NotSerializableException</code>,
      * because this object cannot be serialized,
      */
@@ -104,7 +102,7 @@
         throw new NotSerializableException();
     }
 
-    /*
+    /**
      * This method always throws a <code>NotSerializableException</code>,
      * because this object cannot be serialized,
      */
@@ -112,5 +110,3 @@
         throw new NotSerializableException();
     }
 }
-
-
diff --git a/libcore/prefs/src/main/java/java/util/prefs/PreferenceChangeListener.java b/libcore/prefs/src/main/java/java/util/prefs/PreferenceChangeListener.java
index 28bb763..97aeced 100644
--- a/libcore/prefs/src/main/java/java/util/prefs/PreferenceChangeListener.java
+++ b/libcore/prefs/src/main/java/java/util/prefs/PreferenceChangeListener.java
@@ -14,21 +14,23 @@
  * limitations under the License.
  */
 
-
 package java.util.prefs;
 
 import java.util.EventListener;
 
 /**
- * This interface is used to handle preferences change events. The implementation of
- * this interface can be installed by the {@code Preferences} instance.
+ * This interface is used to handle preferences change events. The
+ * implementation of this interface can be installed by the {@code Preferences}
+ * instance.
  * 
+ * @see Preferences
  * @see PreferenceChangeEvent
+ *
  * 
- * @since Android 1.0
+ * @since 1.4
  */
 public interface PreferenceChangeListener extends EventListener {
-    
+
     /**
      * This method gets invoked whenever a preference is added, deleted or
      * updated.
@@ -36,10 +38,6 @@
      * @param pce
      *            the event instance which describes the changed {@code Preferences}
      *            instance and the preference value.
-     * @since Android 1.0
      */
     void preferenceChange (PreferenceChangeEvent pce);
 }
-
-
- 
diff --git a/libcore/prefs/src/main/java/java/util/prefs/Preferences.java b/libcore/prefs/src/main/java/java/util/prefs/Preferences.java
index b7a0c70..8b961e4 100644
--- a/libcore/prefs/src/main/java/java/util/prefs/Preferences.java
+++ b/libcore/prefs/src/main/java/java/util/prefs/Preferences.java
@@ -30,89 +30,83 @@
 import java.net.MalformedURLException;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.util.Locale;
 
 import org.apache.harmony.prefs.internal.nls.Messages;
 
 /**
- * An instance of the class {@code Preferences} represents one node in a preference tree,
- * which provides a mechanism to store and access configuration data in a
- * hierarchical way. Two hierarchy trees are maintained, one for system
- * preferences shared by all users and the other for user preferences 
+ * An instance of the class {@code Preferences} represents one node in a
+ * preference tree, which provides a mechanism to store and access configuration
+ * data in a hierarchical way. Two hierarchy trees are maintained, one for
+ * system preferences shared by all users and the other for user preferences
  * specific to the user. {@code Preferences} hierarchy trees and data are stored
  * in an implementation-dependent back-end.
  * <p>
- * Every node has one name and one unique absolute path following the same 
- * notational conventions as directories in a file system. The root node's 
- * name is "", and other node name strings cannot contain the slash character 
- * and cannot be empty. The root node's absolute path is "/", and all other 
- * nodes' absolute paths are constructed in the standard way: &lt;parent's absolute
- * path&gt; + "/" + &lt;node's name&gt;. Since the set of nodes forms a tree with 
- * the root node at its base, all absolute paths start with the slash character.
- * Every node has one relative path to each of its ancestors. The relative path
- * doesn't start with slash: it equals the node's absolute path with leading 
- * substring removed corresponding to the ancestor's absolute path and a slash.
- * </p>
+ * Every node has one name and one unique absolute path following the same
+ * notational conventions as directories in a file system. The root node's
+ * name is "", and other node name strings cannot contain the slash character
+ * and cannot be empty. The root node's absolute path is "/", and all other
+ * nodes' absolute paths are constructed in the standard way: &lt;parent's
+ * absolute path&gt; + "/" + &lt;node's name&gt;. Since the set of nodes forms a
+ * tree with the root node at its base, all absolute paths start with the slash
+ * character. Every node has one relative path to each of its ancestors. The
+ * relative path doesn't start with slash: it equals the node's absolute path
+ * with leading substring removed corresponding to the ancestor's absolute path
+ * and a slash.
  * <p>
- * Modification to preferences data may be asynchronous, which means that 
- * preference update method calls may return immediately instead of blocking. 
- * The {@code flush()} and {@code sync()} methods force the back-end to 
- * synchronously perform all pending updates, but the implementation is 
- * permitted to perform the modifications on the underlying back-end data 
- * at any time between the moment the request is made and the moment the 
- * {@code flush()} or {@code sync()} method returns.
- * Please note that if JVM exit normally, the implementation must assure all
- * modifications are persisted implicitly.
- * </p>
+ * Modification to preferences data may be asynchronous, which means that
+ * preference update method calls may return immediately instead of blocking.
+ * The {@code flush()} and {@code sync()} methods force the back-end to
+ * synchronously perform all pending updates, but the implementation is
+ * permitted to perform the modifications on the underlying back-end data
+ * at any time between the moment the request is made and the moment the
+ * {@code flush()} or {@code sync()} method returns. Please note that if the JVM
+ * exits normally, the implementation must assure all modifications are
+ * persisted implicitly.
  * <p>
- * When invoking a method that retrieves preferences, the user must provide 
- * a default value. The default value is returned when the preferences cannot 
- * be found or the back-end is unavailable. Some other methods will throw 
+ * When invoking a method that retrieves preferences, the user must provide
+ * a default value. The default value is returned when the preferences cannot
+ * be found or the back-end is unavailable. Some other methods will throw
  * {@code BackingStoreException} when the back-end is unavailable.
  * </p>
  * <p>
- * Preferences can be exported to and imported from an XML files.
+ * Preferences can be exported to and imported from an XML files. These
+ * documents must have an XML DOCTYPE declaration:
+ * <pre>{@code
+ * <!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd">
+ * }</pre>
+ * This system URI is not really accessed by network, it is only a
+ * identification string. Visit the DTD location to see the actual format
+ * permitted.
  * <p>
  * There must be a concrete {@code PreferencesFactory} type for every concrete
- * {@code Preferences} type developed. Every J2SE implementation must provide a default
- * implementation for every supported platform, and must also provide a means of
- * replacing the default implementation. This implementation uses the system property
- * {@code java.util.prefs.PreferencesFactory} to detemine which preferences 
- * implementation to use.
- * </p>
+ * {@code Preferences} type developed. Every J2SE implementation must provide a
+ * default implementation for every supported platform, and must also provide a
+ * means of replacing the default implementation. This implementation uses the
+ * system property {@code java.util.prefs.PreferencesFactory} to detemine which
+ * preferences implementation to use.
  * <p>
- * The methods of this class are thread-safe. If multiple JVMs are using the same
- * back-end concurrently, the back-end won't be corrupted, but no other
+ * The methods of this class are thread-safe. If multiple JVMs are using the
+ * same back-end concurrently, the back-end won't be corrupted, but no other
  * behavior guarantees are made.
- * </p>
+ *
+ * @see PreferencesFactory
  * 
- * @since Android 1.0
+ * @since 1.4
  */
 public abstract class Preferences {
-    
-    /*
-     * ---------------------------------------------------------
-     * Class fields 
-     * ---------------------------------------------------------
-     */
-    
     /**
      * Maximum size in characters allowed for a preferences key.
-     * 
-     * @since Android 1.0
      */
     public static final int MAX_KEY_LENGTH = 80;
-    
+
     /**
      * Maximum size in characters allowed for a preferences name.
-     * 
-     * @since Android 1.0
      */
     public static final int MAX_NAME_LENGTH = 80;
-    
+
     /**
      * Maximum size in characters allowed for a preferences value.
-     * 
-     * @since Android 1.0
      */
     public static final int MAX_VALUE_LENGTH = 8192;
 
@@ -137,36 +131,53 @@
 
     //permission
     private static final RuntimePermission PREFS_PERM = new RuntimePermission("preferences"); //$NON-NLS-1$
-    
+
     //factory used to get user/system prefs root
     private static final PreferencesFactory factory;
-    
-    /**
-     * ---------------------------------------------------------
-     * Class initializer
-     * ---------------------------------------------------------
-     */        
-    static{
+
+    // BEGIN android-removed
+    // // default provider factory name for Windows
+    // private static final String DEFAULT_FACTORY_NAME_WIN = "java.util.prefs.RegistryPreferencesFactoryImpl"; //$NON-NLS-1$
+    //
+    // // default provider factory name for Unix
+    // private static final String DEFAULT_FACTORY_NAME_UNIX = "java.util.prefs.FilePreferencesFactoryImpl"; //$NON-NLS-1$
+    // END android-removed
+
+    static {
         String factoryClassName = AccessController.doPrivileged(new PrivilegedAction<String>() {
             public String run() {
                 return System.getProperty("java.util.prefs.PreferencesFactory"); //$NON-NLS-1$
             }
         });
         // BEGIN android-removed
-        // if(factoryClassName != null) {
+        // // set default provider
+        // if (factoryClassName == null) {
+        //     String osName = AccessController.doPrivileged(new PrivilegedAction<String>() {
+        //         public String run() {
+        //             return System.getProperty("os.name"); //$NON-NLS-1$
+        //         }
+        //     });
+        //
+        //     // only comparing ASCII, so assume english locale
+        //     osName = (osName == null ? null : osName.toLowerCase(Locale.ENGLISH));
+        //
+        //     if (osName != null && osName.startsWith("windows")) {
+        //         factoryClassName = DEFAULT_FACTORY_NAME_WIN;
+        //     } else {
+        //         factoryClassName = DEFAULT_FACTORY_NAME_UNIX;
+        //     }
+        // }
         // try {
-        // ClassLoader loader = Thread.currentThread().getContextClassLoader();
-        // if(loader == null){
-        // loader = ClassLoader.getSystemClassLoader();
-        // }
-        // Class<?> factoryClass = loader.loadClass(factoryClassName);
-        // factory = (PreferencesFactory) factoryClass.newInstance();
+        //     ClassLoader loader = Thread.currentThread().getContextClassLoader();
+        //     if(loader == null){
+        //         loader = ClassLoader.getSystemClassLoader();
+        //     }
+        //     Class<?> factoryClass = loader.loadClass(factoryClassName);
+        //     factory = (PreferencesFactory) factoryClass.newInstance();
         // } catch (Exception e) {
-        // // prefs.10=Cannot initiate PreferencesFactory: {0}. Caused by {1}
-        //         throw new InternalError(Messages.getString("prefs.10", factoryClassName, e));   //$NON-NLS-1$
+        //     // prefs.10=Cannot initiate PreferencesFactory: {0}. Caused by {1}
+        //     throw new InternalError(Messages.getString("prefs.10", factoryClassName, e));   //$NON-NLS-1$
         // }
-        // }
-        // END android-removed
         // BEGIN android-added
         ClassLoader loader = Thread.currentThread().getContextClassLoader();
         if (loader == null) {
@@ -182,10 +193,8 @@
                     try {
                         InputStream is = en.nextElement().openStream();
                         // Read each line for charset provider class names
-                        // BEGIN android-modified
                         reader = new BufferedReader(new InputStreamReader(is,
                                 CONFIGURATION_FILE_ENCODING), 8192);
-                        // END android-modified
                         factoryClassName = reader.readLine();
                         commentIndex = factoryClassName.indexOf(CONFIGURATION_FILE_COMMENT);
                         if (commentIndex > 0) {
@@ -215,42 +224,27 @@
             factory = (PreferencesFactory)c.newInstance();
         } catch (Exception e) {
             // prefs.10=Cannot initiate PreferencesFactory: {0}. Caused by {1}
-            throw new InternalError(Messages.getString("prefs.10", factoryClassName, e)); //$NON-NLS-1$  
+            throw new InternalError(Messages.getString("prefs.10", factoryClassName, e)); //$NON-NLS-1$
         }
         // END android-added
     }
-    
-    /*
-     * ---------------------------------------------------------
-     * Constructors
-     * ---------------------------------------------------------
-     */
-    
+
     /**
      * Default constructor, for use by subclasses only.
-     * 
-     * @since Android 1.0
      */
     protected Preferences() {
         super();
     }
-    
-    /*
-     * ---------------------------------------------------------
-     * Methods
-     * ---------------------------------------------------------
-     */
-    
+
     /**
      * Gets the absolute path string of this preference node.
      * 
      * @return the preference node's absolute path string.
-     * @since Android 1.0
      */
     public abstract String absolutePath();
-    
+
     /**
-     * Returns the names of all children of this node or an empty string if this
+     * Returns the names of all children of this node or an empty array if this
      * node has no children.
      * 
      * @return the names of all children of this node.
@@ -259,10 +253,9 @@
      *             failure.
      * @throws IllegalStateException
      *             if this node has been removed.
-     * @since Android 1.0
      */
     public abstract String[] childrenNames() throws BackingStoreException;
-    
+
     /**
      * Removes all preferences of this node.
      * 
@@ -271,13 +264,12 @@
      *             failure.
      * @throws IllegalStateException
      *             if this node has been removed.
-     * @since Android 1.0
      */
     public abstract void clear() throws BackingStoreException;
-    
+
     /**
-     * Exports all of the preferences of this node to a XML document using the given
-     * output stream.
+     * Exports all of the preferences of this node to a XML document using the
+     * given output stream.
      * <p>
      * This XML document uses the UTF-8 encoding and is written according to the
      * DTD in its DOCTYPE declaration, which is the following:
@@ -286,7 +278,8 @@
      * &lt;!DOCTYPE preferences SYSTEM &quot;http://java.sun.com/dtd/preferences.dtd&quot;&gt;
      * </pre>
      * 
-     * <i>Please note that (unlike the methods of this class that don't concern serialization), this call is not thread-safe.</i>
+     * <i>Please note that (unlike the methods of this class that don't concern
+     * serialization), this call is not thread-safe.</i>
      * </p>
      * 
      * @param ostream
@@ -298,13 +291,12 @@
      *             failure.
      * @throws IllegalStateException
      *             if this node has been removed.
-     * @since Android 1.0
      */
-    public abstract void exportNode (OutputStream ostream) throws IOException, BackingStoreException;
-    
+    public abstract void exportNode(OutputStream ostream) throws IOException, BackingStoreException;
+
     /**
-     * Exports all of the preferences of this node and all its descendants to a XML
-     * document using the given output stream.
+     * Exports all of the preferences of this node and all its descendants to a
+     * XML document using the given output stream.
      * <p>
      * This XML document uses the UTF-8 encoding and is written according to the
      * DTD in its DOCTYPE declaration, which is the following:
@@ -313,7 +305,8 @@
      * &lt;!DOCTYPE preferences SYSTEM &quot;http://java.sun.com/dtd/preferences.dtd&quot;&gt;
      * </pre>
      * 
-     * <i>Please note that (unlike the methods of this class that don't concern serialization), this call is not thread-safe.</i>
+     * <i>Please note that (unlike the methods of this class that don't concern
+     * serialization), this call is not thread-safe.</i>
      * </p>
      * 
      * @param ostream
@@ -325,12 +318,12 @@
      *             failure.
      * @throws IllegalStateException
      *             if this node has been removed.
-     * @since Android 1.0
      */
-    public abstract void exportSubtree (OutputStream ostream) throws IOException, BackingStoreException;
-    
+    public abstract void exportSubtree(OutputStream ostream) throws IOException,
+            BackingStoreException;
+
     /**
-     * Forces all pending updates to this node and its descendants to be 
+     * Forces all pending updates to this node and its descendants to be
      * persisted in the backing store.
      * <p>
      * If this node has been removed, the invocation of this method only flushes
@@ -340,13 +333,12 @@
      * @throws BackingStoreException
      *             if the backing store is unavailable or causes an operation
      *             failure.
-     * @since Android 1.0
      */
     public abstract void flush() throws BackingStoreException;
-    
+
     /**
-     * Gets the {@code String} value mapped to the given key or its default value if no
-     * value is mapped or no backing store is available.
+     * Gets the {@code String} value mapped to the given key or its default
+     * value if no value is mapped or no backing store is available.
      * <p>
      * Some implementations may store default values in backing stores. In this
      * case, if there is no value mapped to the given key, the stored default
@@ -363,16 +355,16 @@
      *             if this node has been removed.
      * @throws NullPointerException
      *             if the parameter {@code key} is {@code null}.
-     * @since Android 1.0
      */
-    public abstract String get (String key, String deflt);
-    
+    public abstract String get(String key, String deflt);
+
     /**
-     * Gets the {@code boolean} value mapped to the given key or its default value if no
-     * value is mapped, if the backing store is unavailable, or if the value is invalid.
+     * Gets the {@code boolean} value mapped to the given key or its default
+     * value if no value is mapped, if the backing store is unavailable, or if
+     * the value is invalid.
      * <p>
-     * The only valid values are the {@code String} "true", which represents {@code true} and
-     * "false", which represents {@code false}, ignoring case.
+     * The only valid values are the {@code String} "true", which represents
+     * {@code true} and "false", which represents {@code false}, ignoring case.
      * </p>
      * <p>
      * Some implementations may store default values in backing stores. In this
@@ -384,25 +376,24 @@
      *            the preference key.
      * @param deflt
      *            the default value, which will be returned if no value is
-     *            mapped to the given key, if the backing store is unavailable, or if the
-     *            value is invalid.
+     *            mapped to the given key, if the backing store is unavailable,
+     *            or if the value is invalid.
      * @return the boolean value mapped to the given key.
      * @throws IllegalStateException
      *             if this node has been removed.
      * @throws NullPointerException
      *             if the parameter {@code key} is {@code null}.
-     * @since Android 1.0
      */
-    public abstract boolean getBoolean (String key, boolean deflt);
-    
+    public abstract boolean getBoolean(String key, boolean deflt);
+
     /**
-     * Gets the {@code byte} array value mapped to the given key or its default value if
-     * no value is mapped, if the backing store is unavailable, or if the value is an
-     * invalid string.
+     * Gets the {@code byte} array value mapped to the given key or its default
+     * value if no value is mapped, if the backing store is unavailable, or if
+     * the value is an invalid string.
      * <p>
-     * To be valid, the value string must be Base64-encoded binary data. The Base64 encoding
-     * is as defined in <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC
-     * 2045</a>, section 6.8.
+     * To be valid, the value string must be Base64-encoded binary data. The
+     * Base64 encoding is as defined in <a
+     * href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>, section 6.8.
      * </p>
      * <p>
      * Some implementations may store default values in backing stores. In this
@@ -414,25 +405,24 @@
      *            the preference key.
      * @param deflt
      *            the default value, which will be returned if no value is
-     *            mapped to the given key, if the backing store is unavailable, or if the
-     *            value is invalid.
+     *            mapped to the given key, if the backing store is unavailable,
+     *            or if the value is invalid.
      * @return the byte array value mapped to the given key.
      * @throws IllegalStateException
      *             if this node has been removed.
      * @throws NullPointerException
      *             if the parameter {@code key} is {@code null}.
-     * @since Android 1.0
      */
-    public abstract byte[] getByteArray (String key, byte[] deflt);
-    
+    public abstract byte[] getByteArray(String key, byte[] deflt);
+
     /**
-     * Gets the {@code double} value mapped to the given key or its default value if no
-     * value is mapped, if the backing store is unavailable, or if the value is an invalid
-     * string.
+     * Gets the {@code double} value mapped to the given key or its default
+     * value if no value is mapped, if the backing store is unavailable, or if
+     * the value is an invalid string.
      * <p>
-     * To be valid, the value string must be a string that can be converted to a {@code double} by
-     * {@link Double#parseDouble(String) Double.parseDouble(String)}.
-     * </p>
+     * To be valid, the value string must be a string that can be converted to a
+     * {@code double} by {@link Double#parseDouble(String)
+     * Double.parseDouble(String)}.
      * <p>
      * Some implementations may store default values in backing stores. In this
      * case, if there is no value mapped to the given key, the stored default
@@ -450,17 +440,17 @@
      *             if this node has been removed.
      * @throws NullPointerException
      *             if the parameter {@code key} is {@code null}.
-     * @since Android 1.0
      */
-    public abstract double getDouble (String key, double deflt);
-    
+    public abstract double getDouble(String key, double deflt);
+
     /**
-     * Gets the {@code float} value mapped to the given key or its default value if no
-     * value is mapped, if the backing store is unavailable, or if the value is an invalid
-     * string.
+     * Gets the {@code float} value mapped to the given key or its default value
+     * if no value is mapped, if the backing store is unavailable, or if the
+     * value is an invalid string.
      * <p>
-     * To be valid, the value string must be a string that can be converted to a {@code float} by
-     * {@link Float#parseFloat(String) Float.parseFloat(String)}.
+     * To be valid, the value string must be a string that can be converted to a
+     * {@code float} by {@link Float#parseFloat(String)
+     * Float.parseFloat(String)}.
      * </p>
      * <p>
      * Some implementations may store default values in backing stores. In this
@@ -479,17 +469,17 @@
      *             if this node has been removed.
      * @throws NullPointerException
      *             if the parameter {@code key} is {@code null}.
-     * @since Android 1.0
      */
-    public abstract float getFloat (String key, float deflt);
-    
+    public abstract float getFloat(String key, float deflt);
+
     /**
-     * Gets the {@code int} value mapped to the given key or its default value if no
-     * value is mapped, if the backing store is unavailable, or if the value is an invalid
-     * string.
+     * Gets the {@code int} value mapped to the given key or its default value
+     * if no value is mapped, if the backing store is unavailable, or if the
+     * value is an invalid string.
      * <p>
-     * To be valid, the value string must be a string that can be converted to an {@code int} by
-     * {@link Integer#parseInt(String) Integer.parseInt(String)}.
+     * To be valid, the value string must be a string that can be converted to
+     * an {@code int} by {@link Integer#parseInt(String)
+     * Integer.parseInt(String)}.
      * </p>
      * <p>
      * Some implementations may store default values in backing stores. In this
@@ -501,24 +491,23 @@
      *            the preference key.
      * @param deflt
      *            the default value, which will be returned if no value is
-     *            mapped to the given key, if the backing store is unavailable, or if the
-     *            value is invalid.
+     *            mapped to the given key, if the backing store is unavailable,
+     *            or if the value is invalid.
      * @return the integer value mapped to the given key.
      * @throws IllegalStateException
      *             if this node has been removed.
      * @throws NullPointerException
      *             if the parameter {@code key} is {@code null}.
-     * @since Android 1.0
      */
-    public abstract int getInt (String key, int deflt);
-    
+    public abstract int getInt(String key, int deflt);
+
     /**
-     * Gets the {@code long} value mapped to the given key or its default value if no
-     * value is mapped, if the backing store is unavailable, or if the value is an invalid
-     * string.
+     * Gets the {@code long} value mapped to the given key or its default value
+     * if no value is mapped, if the backing store is unavailable, or if the
+     * value is an invalid string.
      * <p>
-     * To be valid, the value string must be a string that can be converted to a {@code long} by
-     * {@link Long#parseLong(String) Long.parseLong(String)}.
+     * To be valid, the value string must be a string that can be converted to a
+     * {@code long} by {@link Long#parseLong(String) Long.parseLong(String)}.
      * </p>
      * <p>
      * Some implementations may store default values in backing stores. In this
@@ -530,29 +519,29 @@
      *            the preference key.
      * @param deflt
      *            the default value, which will be returned if no value is
-     *            mapped to the given key, if the backing store is unavailable, or if the
-     *            value is invalid.
+     *            mapped to the given key, if the backing store is unavailable,
+     *            or if the value is invalid.
      * @return the long value mapped to the given key.
      * @throws IllegalStateException
      *             if this node has been removed.
      * @throws NullPointerException
      *             if the parameter {@code key} is {@code null}.
-     * @since Android 1.0
      */
-    public abstract long getLong (String key, long deflt);
-    
+    public abstract long getLong(String key, long deflt);
+
     /**
      * Imports all the preferences from an XML document using the given input
      * stream.
      * <p>
-     * This XML document uses the UTF-8 encoding and must be written according to the
-     * DTD in its DOCTYPE declaration, which must be the following:
+     * This XML document uses the UTF-8 encoding and must be written according
+     * to the DTD in its DOCTYPE declaration, which must be the following:
      * 
      * <pre>
      * &lt;!DOCTYPE preferences SYSTEM &quot;http://java.sun.com/dtd/preferences.dtd&quot;&gt;
      * </pre>
      * 
-     * <i>Please note that (unlike the methods of this class that don't concern serialization), this call is not thread-safe.</i>
+     * <i>Please note that (unlike the methods of this class that don't concern
+     * serialization), this call is not thread-safe.</i>
      * </p>
      * 
      * @param istream
@@ -565,7 +554,6 @@
      * @throws SecurityException
      *             if {@code RuntimePermission("preferences")} is denied by a
      *             SecurityManager.
-     * @since Android 1.0
      */
     public static void importPreferences (InputStream istream) throws InvalidPreferencesFormatException, IOException {
         checkSecurity();
@@ -575,16 +563,15 @@
         }
         XMLParser.importPrefs(istream);
     }
-    
+
     /**
      * Returns whether this is a user preference node.
      * 
      * @return {@code true}, if this is a user preference node, {@code false} if
      *         this is a system preference node.
-     * @since Android 1.0
      */
     public abstract boolean isUserNode();
-    
+
     /**
      * Returns all preference keys stored in this node or an empty array if no
      * key was found.
@@ -595,18 +582,16 @@
      *             failure.
      * @throws IllegalStateException
      *             if this node has been removed.
-     * @since Android 1.0
      */
     public abstract String[] keys() throws BackingStoreException;
-    
+
     /**
      * Returns the name of this node.
      * 
      * @return the name of this node.
-     * @since Android 1.0
      */
     public abstract String name();
-    
+
     /**
      * Returns the preference node with the given path name. The path name can
      * be relative or absolute. The requested node and its ancestors will
@@ -625,10 +610,9 @@
      *             if the path name is invalid.
      * @throws NullPointerException
      *             if the given path is {@code null}.
-     * @since Android 1.0
      */
-    public abstract Preferences node (String path);
-    
+    public abstract Preferences node(String path);
+
     /**
      * Returns whether the preference node with the given path name exists. The
      * path is treated as relative to this node if it doesn't start with a slash,
@@ -653,10 +637,9 @@
      * @throws BackingStoreException
      *             if the backing store is unavailable or causes an operation
      *             failure.
-     * @since Android 1.0
      */
-    public abstract boolean nodeExists (String path) throws BackingStoreException;
-    
+    public abstract boolean nodeExists(String path) throws BackingStoreException;
+
     /**
      * Returns the parent preference node of this node or {@code null} if this
      * node is the root node.
@@ -664,10 +647,9 @@
      * @return the parent preference node of this node.
      * @throws IllegalStateException
      *             if this node has been removed.
-     * @since Android 1.0
      */
     public abstract Preferences parent();
-    
+
     /**
      * Adds a new preference to this node using the given key and value or
      * updates the value if a preference with the given key already exists.
@@ -684,14 +666,13 @@
      *             MAX_VALUE_LENGTH}.
      * @throws IllegalStateException
      *             if this node has been removed.
-     * @since Android 1.0
      */
-    public abstract void put (String key, String value);
-    
+    public abstract void put(String key, String value);
+
     /**
-     * Adds a new preference with a {@code boolean} value to this node using the given
-     * key and value or updates the value if a preference with the given key
-     * already exists.
+     * Adds a new preference with a {@code boolean} value to this node using the
+     * given key and value or updates the value if a preference with the given
+     * key already exists.
      * 
      * @param key
      *            the preference key to be added or updated.
@@ -704,10 +685,9 @@
      *             MAX_KEY_LENGTH}.
      * @throws IllegalStateException
      *             if this node has been removed.
-     * @since Android 1.0
      */
-    public abstract void putBoolean (String key, boolean value);
-    
+    public abstract void putBoolean(String key, boolean value);
+
     /**
      * Adds a new preference to this node using the given key and the string
      * form of the given value or updates the value if a preference with the
@@ -730,10 +710,9 @@
      *             quarters of {@code MAX_KEY_LENGTH}.
      * @throws IllegalStateException
      *             if this node has been removed.
-     * @since Android 1.0
      */
-    public abstract void putByteArray (String key, byte[] value);
-    
+    public abstract void putByteArray(String key, byte[] value);
+
     /**
      * Adds a new preference to this node using the given key and {@code double}
      * value or updates the value if a preference with the
@@ -754,12 +733,11 @@
      *             MAX_KEY_LENGTH}.
      * @throws IllegalStateException
      *             if this node has been removed.
-     * @since Android 1.0
      */
-    public abstract void putDouble (String key, double value);
-    
+    public abstract void putDouble(String key, double value);
+
     /**
-     * Adds a new preference to this node using the given key and {@code float} 
+     * Adds a new preference to this node using the given key and {@code float}
      * value or updates the value if a preference with the
      * given key already exists.
      * <p>
@@ -778,12 +756,11 @@
      *             MAX_KEY_LENGTH}.
      * @throws IllegalStateException
      *             if this node has been removed.
-     * @since Android 1.0
      */
-    public abstract void putFloat (String key, float value);
-    
+    public abstract void putFloat(String key, float value);
+
     /**
-     * Adds a new preference to this node using the given key and {@code int} 
+     * Adds a new preference to this node using the given key and {@code int}
      * value or updates the value if a preference with the
      * given key already exists.
      * <p>
@@ -802,12 +779,11 @@
      *             MAX_KEY_LENGTH}.
      * @throws IllegalStateException
      *             if this node has been removed.
-     * @since Android 1.0
      */
-    public abstract void putInt (String key, int value);
-    
+    public abstract void putInt(String key, int value);
+
     /**
-     * Adds a new preference to this node using the given key and {@code long} 
+     * Adds a new preference to this node using the given key and {@code long}
      * value or updates the value if a preference with the
      * given key already exists.
      * <p>
@@ -826,9 +802,8 @@
      *             MAX_KEY_LENGTH}.
      * @throws IllegalStateException
      *             if this node has been removed.
-     * @since Android 1.0
      */
-    public abstract void putLong (String key, long value);
+    public abstract void putLong(String key, long value);
 
     /**
      * Removes the preference mapped to the given key from this node.
@@ -839,13 +814,12 @@
      *             if the given key is {@code null}.
      * @throws IllegalStateException
      *             if this node has been removed.
-     * @since Android 1.0
      */
-    public abstract void remove (String key);
-    
+    public abstract void remove(String key);
+
     /**
-     * Removes this preference node with all its descendants. The removal 
-     * won't necessarily be persisted until the method {@code flush()} is invoked.
+     * Removes this preference node with all its descendants. The removal won't
+     * necessarily be persisted until the method {@code flush()} is invoked.
      * 
      * @throws BackingStoreException
      *             if the backing store is unavailable or causes an operation
@@ -854,14 +828,13 @@
      *             if this node has been removed.
      * @throws UnsupportedOperationException
      *             if this is a root node.
-     * @since Android 1.0
      */
     public abstract void removeNode() throws BackingStoreException;
-    
+
     /**
-     * Registers a {@code NodeChangeListener} instance for this node, which will handle
-     * {@code NodeChangeEvent}s. {@code NodeChangeEvent}s will be fired when a child node has
-     * been added to or removed from this node.
+     * Registers a {@code NodeChangeListener} instance for this node, which will
+     * handle {@code NodeChangeEvent}s. {@code NodeChangeEvent}s will be fired
+     * when a child node has been added to or removed from this node.
      * 
      * @param ncl
      *            the listener to be registered.
@@ -869,25 +842,24 @@
      *             if the given listener is {@code null}.
      * @throws IllegalStateException
      *             if this node has been removed.
-     * @since Android 1.0
      */
-    public abstract void addNodeChangeListener (NodeChangeListener ncl);
-    
+    public abstract void addNodeChangeListener(NodeChangeListener ncl);
+
     /**
-     * Registers a {@code PreferenceChangeListener} instance for this node, which will
-     * handle {@code PreferenceChangeEvent}s. {@code PreferenceChangeEvent}s will be fired when
-     * a preference has been added to, removed from, or updated for this node.
-     * 
+     * Registers a {@code PreferenceChangeListener} instance for this node,
+     * which will handle {@code PreferenceChangeEvent}s. {@code
+     * PreferenceChangeEvent}s will be fired when a preference has been added
+     * to, removed from, or updated for this node.
+     *
      * @param pcl
      *            the listener to be registered.
      * @throws NullPointerException
      *             if the given listener is {@code null}.
      * @throws IllegalStateException
      *             if this node has been removed.
-     * @since Android 1.0
      */
     public abstract void addPreferenceChangeListener (PreferenceChangeListener pcl);
-    
+
     /**
      * Removes the given {@code NodeChangeListener} instance from this node.
      * 
@@ -897,12 +869,12 @@
      *             if the given listener is {@code null}.
      * @throws IllegalStateException
      *             if this node has been removed.
-     * @since Android 1.0
      */
     public abstract void removeNodeChangeListener (NodeChangeListener ncl);
-    
+
     /**
-     * Removes the given {@code PreferenceChangeListener} instance from this node.
+     * Removes the given {@code PreferenceChangeListener} instance from this
+     * node.
      * 
      * @param pcl
      *            the listener to be removed.
@@ -910,36 +882,34 @@
      *             if the given listener is {@code null}.
      * @throws IllegalStateException
      *             if this node has been removed.
-     * @since Android 1.0
      */
     public abstract void removePreferenceChangeListener (PreferenceChangeListener pcl);
-    
+
     /**
      * Synchronizes the data of this preference node and its descendants with
-     * the back-end preference store. Any changes found in the back-end data should be reflected
-     * in this node and its descendants, and at the same time any local changes to this node and
-     * descendants should be persisted.
+     * the back-end preference store. Any changes found in the back-end data
+     * should be reflected in this node and its descendants, and at the same
+     * time any local changes to this node and descendants should be persisted.
      * 
      * @throws BackingStoreException
      *             if the backing store is unavailable or causes an operation
      *             failure.
      * @throws IllegalStateException
      *             if this node has been removed.
-     * @since Android 1.0
      */
     public abstract void sync() throws BackingStoreException;
-    
+
     /**
      * Returns the system preference node for the package of the given class.
      * The absolute path of the returned node is one slash followed by the given
      * class's full package name, replacing each period character ('.') with
-     * a slash. For example, the absolute path of the preference associated with 
+     * a slash. For example, the absolute path of the preference associated with
      * the class Object would be "/java/lang". As a special case, the unnamed
      * package is associated with a preference node "/&lt;unnamed&gt;". This
      * method will create the node and its ancestors as needed. Any nodes created
-     * by this method won't necessarily be persisted until the method {@code flush()} is
-     * invoked.
-     * 
+     * by this method won't necessarily be persisted until the method {@code
+     * flush()} is invoked.
+     *
      * @param c
      *            the given class.
      * @return the system preference node for the package of the given class.
@@ -948,13 +918,12 @@
      * @throws SecurityException
      *             if the {@code RuntimePermission("preferences")} is denied by
      *             a SecurityManager.
-     * @since Android 1.0
      */
     public static Preferences systemNodeForPackage (Class<?> c) {
         checkSecurity();
         return factory.systemRoot().node(getNodeName(c));
     }
-    
+
     /**
      * Returns the root node of the system preference hierarchy.
      * 
@@ -962,33 +931,32 @@
      * @throws SecurityException
      *             if the {@code RuntimePermission("preferences")} is denied by
      *             a SecurityManager.
-     * @since Android 1.0
      */
     public static Preferences systemRoot() {
         checkSecurity();
         return factory.systemRoot();
     }
-    
+
     //check the RuntimePermission("preferences")
     private static void checkSecurity() {
         SecurityManager manager = System.getSecurityManager();
         if(null != manager){
             manager.checkPermission(PREFS_PERM);
         }
-        
+
     }
 
     /**
      * Returns the user preference node for the package of the given class.
      * The absolute path of the returned node is one slash followed by the given
      * class's full package name, replacing each period character ('.') with
-     * a slash. For example, the absolute path of the preference associated with 
+     * a slash. For example, the absolute path of the preference associated with
      * the class Object would be "/java/lang". As a special case, the unnamed
      * package is associated with a preference node "/&lt;unnamed&gt;". This
      * method will create the node and its ancestors as needed. Any nodes created
-     * by this method won't necessarily be persisted until the method {@code flush()} is
-     * invoked.
-     * 
+     * by this method won't necessarily be persisted until the method {@code
+     * flush()} is invoked.
+     *
      * @param c
      *            the given class.
      * @return the user preference node for the package of the given class.
@@ -997,24 +965,19 @@
      * @throws SecurityException
      *             if the {@code RuntimePermission("preferences")} is denied by
      *             a SecurityManager.
-     * @since Android 1.0
      */
     public static Preferences userNodeForPackage (Class<?> c) {
         checkSecurity();
         return factory.userRoot().node(getNodeName(c));
     }
-    
+
     //parse node's absolute path from class instance
     private static String getNodeName(Class<?> c){
-        // ??? PREFS TODO change back to harmony code once getPackage
-        // delivers the correct results
-        // Package p = c.getPackage();
-        // if(null == p){
-        //     return "/<unnamed>"; //$NON-NLS-1$
-        // }
-        // return "/"+p.getName().replace('.', '/'); //$NON-NLS-1$
-        int dotIndex = c.getName().lastIndexOf(".");
-        return "/" + c.getName().substring(0, dotIndex).replace(".", "/");
+        Package p = c.getPackage();
+        if(null == p){
+            return "/<unnamed>"; //$NON-NLS-1$
+        }
+        return "/"+p.getName().replace('.', '/'); //$NON-NLS-1$
     }
 
     /**
@@ -1024,7 +987,6 @@
      * @throws SecurityException
      *             if the {@code RuntimePermission("preferences")} is denied by
      *             a SecurityManager.
-     * @since Android 1.0
      */
     public static Preferences userRoot() {
         checkSecurity();
@@ -1036,7 +998,6 @@
      * Preference Node: " followed by this node's absolute path.
      * 
      * @return the string representation of this node.
-     * @since Android 1.0
      */
     @Override
     public abstract String toString();
diff --git a/libcore/prefs/src/main/java/java/util/prefs/PreferencesFactory.java b/libcore/prefs/src/main/java/java/util/prefs/PreferencesFactory.java
index e56dd95..3ac13e4 100644
--- a/libcore/prefs/src/main/java/java/util/prefs/PreferencesFactory.java
+++ b/libcore/prefs/src/main/java/java/util/prefs/PreferencesFactory.java
@@ -14,36 +14,30 @@
  * limitations under the License.
  */
 
-
 package java.util.prefs;
 
 /**
  * This interface is used by the {@link Preferences} class as factory class to
- * create {@code Preferences} instances. This interface can be implemented and installed
- * to replace the default preferences implementation.
+ * create {@code Preferences} instances. This interface can be implemented and
+ * installed to replace the default preferences implementation.
  * 
- * @since Android 1.0
+ * @see java.util.prefs.Preferences
+ * 
+ * @since 1.4
  */
 public interface PreferencesFactory {
-
     /**
      * Returns the root node of the preferences hierarchy for the calling user
      * context.
      * 
      * @return the user preferences hierarchy root node.
-     * @since Android 1.0
      */
     Preferences userRoot();
-    
+
     /**
      * Returns the root node of the system preferences hierarchy.
      * 
      * @return the system preferences hierarchy root node.
-     * @since Android 1.0
      */
     Preferences systemRoot();
 }
-
-
-
- 
diff --git a/libcore/prefs/src/main/java/java/util/prefs/XMLParser.java b/libcore/prefs/src/main/java/java/util/prefs/XMLParser.java
index 2edfc71..c5a234c 100644
--- a/libcore/prefs/src/main/java/java/util/prefs/XMLParser.java
+++ b/libcore/prefs/src/main/java/java/util/prefs/XMLParser.java
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-
 package java.util.prefs;
 
 import java.io.BufferedInputStream;
@@ -27,6 +26,7 @@
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.io.StringReader;
+import java.io.Writer;
 import java.nio.channels.FileChannel;
 import java.nio.channels.FileLock;
 import java.security.AccessController;
@@ -64,9 +64,7 @@
 // END android-added
 
 /**
- * Utility class for importing and exporting {@code Preferences} data from an XML file.
- * 
- * @since Android 1.0
+ * Utility class for the Preferences import/export from XML file.
  */
 class XMLParser {
 
@@ -79,15 +77,15 @@
      * Constant - the DTD string
      */
     static final String PREFS_DTD = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" //$NON-NLS-1$
-            + "    <!ELEMENT preferences (root)>" //$NON-NLS-1$
-            + "    <!ATTLIST preferences EXTERNAL_XML_VERSION CDATA \"0.0\" >" //$NON-NLS-1$
-            + "    <!ELEMENT root (map, node*) >" //$NON-NLS-1$
-            + "    <!ATTLIST root type (system|user) #REQUIRED >" //$NON-NLS-1$
-            + "    <!ELEMENT node (map, node*) >" //$NON-NLS-1$
-            + "    <!ATTLIST node name CDATA #REQUIRED >" //$NON-NLS-1$
-            + "    <!ELEMENT map (entry*) >" //$NON-NLS-1$
-            + "    <!ELEMENT entry EMPTY >" //$NON-NLS-1$
-            + "    <!ATTLIST entry key   CDATA #REQUIRED value CDATA #REQUIRED >"; //$NON-NLS-1$
+        + "    <!ELEMENT preferences (root)>" //$NON-NLS-1$
+        + "    <!ATTLIST preferences EXTERNAL_XML_VERSION CDATA \"0.0\" >" //$NON-NLS-1$
+        + "    <!ELEMENT root (map, node*) >" //$NON-NLS-1$
+        + "    <!ATTLIST root type (system|user) #REQUIRED >" //$NON-NLS-1$
+        + "    <!ELEMENT node (map, node*) >" //$NON-NLS-1$
+        + "    <!ATTLIST node name CDATA #REQUIRED >" //$NON-NLS-1$
+        + "    <!ELEMENT map (entry*) >" //$NON-NLS-1$
+        + "    <!ELEMENT entry EMPTY >" //$NON-NLS-1$
+        + "    <!ATTLIST entry key   CDATA #REQUIRED value CDATA #REQUIRED >"; //$NON-NLS-1$
 
     /*
      * Constant - the specified header
@@ -103,24 +101,24 @@
      * empty string array constant
      */
     private static final String[] EMPTY_SARRAY = new String[0];
-    
+
     /*
-     * Constant - used by FilePreferencesImpl, which is default implementation of Linux platform 
+     * Constant - used by FilePreferencesImpl, which is default implementation of Linux platform
      */
     private static final String FILE_PREFS = "<!DOCTYPE map SYSTEM 'http://java.sun.com/dtd/preferences.dtd'>"; //$NON-NLS-1$
 
     /*
      * Constant - specify the DTD version
      */
-    private static final float XML_VERSION = 1.0f;    
-    
+    private static final float XML_VERSION = 1.0f;
+
     /*
      * DOM builder
      */
     private static final DocumentBuilder builder;
 
     /*
-     * specify the indent level 
+     * specify the indent level
      */
     private static int indent = -1;
 
@@ -139,7 +137,7 @@
         }
         builder.setEntityResolver(new EntityResolver() {
             public InputSource resolveEntity(String publicId, String systemId)
-                    throws SAXException, IOException {
+            throws SAXException, IOException {
                 if (systemId.equals(PREFS_DTD_NAME)) {
                     InputSource result = new InputSource(new StringReader(
                             PREFS_DTD));
@@ -196,7 +194,7 @@
         flushEmptyElement("map", out); //$NON-NLS-1$
 
         StringTokenizer ancestors = new StringTokenizer(prefs.absolutePath(),
-                "/"); //$NON-NLS-1$
+        "/"); //$NON-NLS-1$
         exportNode(ancestors, prefs, withSubTree, out);
 
         flushEndTag("root", out); //$NON-NLS-1$
@@ -207,7 +205,7 @@
 
     private static void exportNode(StringTokenizer ancestors,
             Preferences prefs, boolean withSubTree, BufferedWriter out)
-            throws IOException, BackingStoreException {
+    throws IOException, BackingStoreException {
         if (ancestors.hasMoreTokens()) {
             String name = ancestors.nextToken();
             flushStartTag(
@@ -226,7 +224,7 @@
     }
 
     private static void exportSubTree(Preferences prefs, BufferedWriter out)
-            throws BackingStoreException, IOException {
+    throws BackingStoreException, IOException {
         String[] names = prefs.childrenNames();
         if (names.length > 0) {
             for (int i = 0; i < names.length; i++) {
@@ -241,7 +239,7 @@
     }
 
     private static void exportEntries(Preferences prefs, BufferedWriter out)
-            throws BackingStoreException, IOException {
+    throws BackingStoreException, IOException {
         String[] keys = prefs.keys();
         String[] values = new String[keys.length];
         for (int i = 0; i < keys.length; i++) {
@@ -267,7 +265,7 @@
     }
 
     private static void flushEndTag(String tagName, BufferedWriter out)
-            throws IOException {
+    throws IOException {
         flushIndent(indent--, out);
         out.write("</"); //$NON-NLS-1$
         out.write(tagName);
@@ -276,7 +274,7 @@
     }
 
     private static void flushEmptyElement(String tagName, BufferedWriter out)
-            throws IOException {
+    throws IOException {
         flushIndent(++indent, out);
         out.write("<"); //$NON-NLS-1$
         out.write(tagName);
@@ -308,7 +306,7 @@
     }
 
     private static void flushIndent(int ind, BufferedWriter out)
-            throws IOException {
+    throws IOException {
         for (int i = 0; i < ind; i++) {
             out.write("  "); //$NON-NLS-1$
         }
@@ -325,7 +323,7 @@
     }
 
     private static void flushStartTag(String tagName, BufferedWriter out)
-            throws IOException {
+    throws IOException {
         flushIndent(++indent, out);
         out.write("<"); //$NON-NLS-1$
         out.write(tagName);
@@ -365,7 +363,7 @@
      * utilities for Preferences import
      **************************************************************************/
     static void importPrefs(InputStream in) throws IOException,
-            InvalidPreferencesFormatException {
+    InvalidPreferencesFormatException {
         try {
             // load XML document
             Document doc = builder.parse(new InputSource(in));
@@ -382,7 +380,7 @@
 
             // check preferences root's type
             Element root = (Element) preferences
-                    .getElementsByTagName("root").item(0); //$NON-NLS-1$
+            .getElementsByTagName("root").item(0); //$NON-NLS-1$
             Preferences prefsRoot = null;
             String type = root.getAttribute("type"); //$NON-NLS-1$
             if (type.equals("user")) { //$NON-NLS-1$
@@ -445,15 +443,15 @@
     // TODO dirty implementation of a method from javax.xml.xpath
     // should be replaced with a call to a good impl of this method
     private static NodeList selectNodeList(Element documentElement, String string) {
-        
+
         NodeList result = null;
-                
+
         ArrayList<Node> input = new ArrayList<Node>();
-        
+
         String[] path = string.split("/");
-        
+
         NodeList childNodes = documentElement.getChildNodes();
-        
+
         if(path[0].equals("entry") || path[0].equals("node")) {
             for(int i = 0; i < childNodes.getLength(); i++) {
                 Object next = childNodes.item(i);
@@ -483,21 +481,21 @@
                 }
             }
         }
-        
+
         result = new NodeSet(input.iterator());
-        
+
         return result;
     }
     // END android-added
-    
+
     /***************************************************************************
      * utilities for FilePreferencesImpl, which is default implementation of Linux platform
      **************************************************************************/
     /**
      * load preferences from file, if cannot load, create a new one FIXME: need
      * lock or not?
-     * 
-     * @param file  the XML file to be read
+     *
+     * @param file	the XML file to be read
      * @return Properties instance which indicates the preferences key-value pairs
      */
     static Properties loadFilePrefs(final File file) {
@@ -506,14 +504,6 @@
                 return loadFilePrefsImpl(file);
             }
         });
-
-        // try {
-        // //FIXME: lines below can be deleted, because it is not required to
-        // persistent at the very beginning
-        // flushFilePrefs(file, result);
-        // } catch (IOException e) {
-        // e.printStackTrace();
-        // }
     }
 
     static Properties loadFilePrefsImpl(final File file) {
@@ -524,7 +514,6 @@
             InputStream in = null;
             FileLock lock = null;
             try {
-
                 FileInputStream istream = new FileInputStream(file);
                 // BEGIN android-modified
                 in = new BufferedInputStream(istream, 8192);
@@ -544,17 +533,16 @@
                     result.setProperty(key, value);
                 }
                 return result;
-            } catch (Exception e) {
-                e.printStackTrace();
+            } catch (IOException e) {
+            } catch (SAXException e) {
+            // BEGIN android-removed
+            // } catch (TransformerException e) {
+            //     // transform shouldn't fail for xpath call
+            //     throw new AssertionError(e);
+            // END android-removed
             } finally {
-                try {
-                    lock.release();
-                } catch (Exception e) {//ignore
-                }
-                try {
-                    in.close();
-                } catch (Exception e) {//ignore
-                }
+                releaseQuietly(lock);
+                closeQuietly(in);
             }
         } else {
             file.delete();
@@ -563,7 +551,7 @@
     }
 
     /**
-     * 
+     *
      * @param file
      * @param prefs
      * @throws PrivilegedActionException
@@ -576,7 +564,7 @@
             }
         });
     }
-    
+
     static void flushFilePrefsImpl(File file, Properties prefs) throws IOException {
         BufferedWriter out = null;
         FileLock lock = null;
@@ -604,18 +592,35 @@
             }
             out.flush();
         } finally {
-            try {
-                lock.release();
-            } catch (Exception e) {//ignore
-            }
-            try {
-                if (null != out) {
-                    out.close();
-                }
-            } catch (Exception e) {//ignore
-            }
+            releaseQuietly(lock);
+            closeQuietly(out);
         }
     }
+
+    private static void releaseQuietly(FileLock lock) {
+        if (lock == null) {
+            return;
+        }
+        try {
+            lock.release();
+        } catch (IOException e) {}
+    }
+
+    private static void closeQuietly(Writer out) {
+        if (out == null) {
+            return;
+        }
+        try {
+            out.close();
+        } catch (IOException e) {}
+    }
+
+    private static void closeQuietly(InputStream in) {
+        if (in == null) {
+            return;
+        }
+        try {
+            in.close();
+        } catch (IOException e) {}
+    }
 }
-
-
diff --git a/libcore/prefs/src/main/java/org/apache/harmony/prefs/internal/nls/Messages.java b/libcore/prefs/src/main/java/org/apache/harmony/prefs/internal/nls/Messages.java
index cfc7236..aaf5d8d 100644
--- a/libcore/prefs/src/main/java/org/apache/harmony/prefs/internal/nls/Messages.java
+++ b/libcore/prefs/src/main/java/org/apache/harmony/prefs/internal/nls/Messages.java
@@ -43,7 +43,7 @@
  * is looked up, or resource bundle support is not available, the key itself
  * will be returned as the associated message. This means that the <em>KEY</em>
  * should a reasonable human-readable (english) string.
- * 
+ *
  */
 public class Messages {
 
@@ -54,7 +54,7 @@
 
     /**
      * Retrieves a message which has no arguments.
-     * 
+     *
      * @param msg
      *            String the key to look up.
      * @return String the message for that key in the system message bundle.
@@ -67,7 +67,7 @@
 
     /**
      * Retrieves a message which takes 1 argument.
-     * 
+     *
      * @param msg
      *            String the key to look up.
      * @param arg
@@ -80,7 +80,7 @@
 
     /**
      * Retrieves a message which takes 1 integer argument.
-     * 
+     *
      * @param msg
      *            String the key to look up.
      * @param arg
@@ -93,7 +93,7 @@
 
     /**
      * Retrieves a message which takes 1 character argument.
-     * 
+     *
      * @param msg
      *            String the key to look up.
      * @param arg
@@ -106,7 +106,7 @@
 
     /**
      * Retrieves a message which takes 2 arguments.
-     * 
+     *
      * @param msg
      *            String the key to look up.
      * @param arg1
@@ -121,7 +121,7 @@
 
     /**
      * Retrieves a message which takes several arguments.
-     * 
+     *
      * @param msg
      *            String the key to look up.
      * @param args
diff --git a/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/AbstractPreferencesTest.java b/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/AbstractPreferencesTest.java
index 418e52d..76ef4e7 100644
--- a/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/AbstractPreferencesTest.java
+++ b/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/AbstractPreferencesTest.java
@@ -35,9 +35,13 @@
 import java.util.prefs.PreferenceChangeListener;
 import java.util.prefs.Preferences;
 
+import tests.util.PrefsTester;
+
 @TestTargetClass(AbstractPreferences.class)
 public class AbstractPreferencesTest extends TestCase {
 
+    private final PrefsTester prefsTester = new PrefsTester();
+
     AbstractPreferences pref;
 
     static AbstractPreferences root;
@@ -51,13 +55,8 @@
     
     protected void setUp() throws Exception {
         super.setUp();
+        prefsTester.setUp();
 
-        System.setProperty("user.home", System.getProperty("java.io.tmpdir"));
-        System.setProperty("java.home", System.getProperty("java.io.tmpdir"));
-        
-        Preferences.systemRoot().clear();
-        Preferences.userRoot().clear();
-        
         root = (AbstractPreferences) Preferences.userRoot();
         parent = (AbstractPreferences) Preferences.userNodeForPackage(this.getClass());
 
@@ -65,11 +64,7 @@
     }
 
     protected void tearDown() throws Exception {
-        parent.removeNode();
-        Preferences.systemRoot().clear();
-        Preferences.userRoot().clear();
-        System.setProperty("user.home", oldUserHome);
-        System.setProperty("java.home", oldJavaHome);
+        prefsTester.tearDown();
         super.tearDown();
     }
 
@@ -855,6 +850,31 @@
     }
 
     @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "",
+            method = "nodeExists",
+            args = {String.class}
+    )
+    public void test_nodeExists() throws BackingStoreException {
+        AbstractPreferences test = (AbstractPreferences) Preferences.userRoot()
+                .node("test");
+        try {
+            test.nodeExists(null);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // Expected
+        }
+
+        test.removeNode();
+        try {
+            test.nodeExists(null);
+            fail("should throw NullPointerException");
+        } catch (NullPointerException e) {
+            // Expected
+        }
+    }
+
+    @TestTargetNew(
         level = TestLevel.COMPLETE,
         notes = "",
         method = "parent",
diff --git a/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/FilePreferencesImplTest.java b/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/FilePreferencesImplTest.java
index dc2ec2e..0cb1975 100644
--- a/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/FilePreferencesImplTest.java
+++ b/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/FilePreferencesImplTest.java
@@ -28,19 +28,23 @@
 import java.util.prefs.Preferences;
 
 import junit.framework.TestCase;
+import tests.util.PrefsTester;
 
 @TestTargetClass(java.util.prefs.Preferences.class)
 public class FilePreferencesImplTest extends TestCase {
 
-    public FilePreferencesImplTest() {
-        super();
-    }
-    
+    private final PrefsTester prefsTester = new PrefsTester();
+
     @Override
-    protected void setUp(){
+    protected void setUp() throws Exception {
+        super.setUp();
+        prefsTester.setUp();
     }
+
     @Override
-    protected void tearDown(){
+    protected void tearDown() throws Exception {
+        prefsTester.tearDown();
+        super.tearDown();
     }
 
     @TestTargets({
@@ -303,6 +307,7 @@
             System.setSecurityManager(dflt);
         }
 
+        @Override
         public void checkPermission(Permission perm) {
             if (perm instanceof FilePermission) {
                 throw new SecurityException();
@@ -311,6 +316,7 @@
             }
         }
 
+        @Override
         public void checkPermission(Permission perm, Object ctx) {
             if (perm instanceof FilePermission) {
                 System.out.println(perm.getActions());
diff --git a/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/InvalidPreferencesFormatExceptionTest.java b/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/InvalidPreferencesFormatExceptionTest.java
index 28c953e..c7ff946 100644
--- a/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/InvalidPreferencesFormatExceptionTest.java
+++ b/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/InvalidPreferencesFormatExceptionTest.java
@@ -44,7 +44,7 @@
     )
     public void testInvalidPreferencesFormatExceptionString() {
         InvalidPreferencesFormatException e = new InvalidPreferencesFormatException(
-                "msg");
+        "msg");
         assertNull(e.getCause());
         assertEquals("msg", e.getMessage());
     }
@@ -99,7 +99,7 @@
     public void testSerializationSelf() throws Exception {
 
         SerializationTest.verifySelf(new InvalidPreferencesFormatException(
-                "msg"));
+        "msg"));
     }
 
     /**
diff --git a/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/MockAbstractPreferences.java b/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/MockAbstractPreferences.java
index 1820954..b149225 100644
--- a/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/MockAbstractPreferences.java
+++ b/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/MockAbstractPreferences.java
@@ -84,6 +84,7 @@
         return lock;
     }
 
+    @Override
     public String[] childrenNamesSpi() throws BackingStoreException {
         checkException();
         if (result == returnNull)
@@ -108,6 +109,7 @@
         return childSpi(name);
     }
 
+    @Override
     public AbstractPreferences childSpi(String name) {
         try {
             checkException();
@@ -123,11 +125,13 @@
         return r;
     }
 
+    @Override
     public void flushSpi() throws BackingStoreException {
         checkException();
         flushedTimes++;
     }
 
+    @Override
     public String getSpi(String key) {
         try {
             checkException();
@@ -139,6 +143,7 @@
         return result == returnNull ? null : attr.getProperty(key);
     }
 
+    @Override
     public String[] keysSpi() throws BackingStoreException {
         checkException();
         Set<Object> keys = attr.keySet();
@@ -147,6 +152,7 @@
         return result == returnNull ? null : results;
     }
 
+    @Override
     public void putSpi(String name, String value) {
         try {
             checkException();
@@ -158,11 +164,13 @@
         attr.put(name, value);
     }
 
+    @Override
     protected void removeNodeSpi() throws BackingStoreException {
         checkException();
         ((MockAbstractPreferences) parent()).childs.remove(name());
     }
 
+    @Override
     public void removeSpi(String key) {
         try {
             checkException();
@@ -174,6 +182,7 @@
         attr.remove(key);
     }
 
+    @Override
     public void syncSpi() throws BackingStoreException {
         checkException();
         syncTimes++;
diff --git a/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/MockSecurityManager.java b/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/MockSecurityManager.java
index e5a0bfd..d6047fb 100644
--- a/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/MockSecurityManager.java
+++ b/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/MockSecurityManager.java
@@ -39,6 +39,7 @@
         System.setSecurityManager(dflt);
     }
 
+    @Override
     public void checkPermission(Permission perm) {
         if (perm instanceof RuntimePermission
                 && perm.getName().equals("preferences")) {
@@ -48,6 +49,7 @@
         }
     }
 
+    @Override
     public void checkPermission(Permission perm, Object ctx) {
         if (perm instanceof RuntimePermission
                 && perm.getName().equals("preferences")) {
diff --git a/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/NodeChangeEventTest.java b/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/NodeChangeEventTest.java
index 3260a04..1afd755 100644
--- a/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/NodeChangeEventTest.java
+++ b/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/NodeChangeEventTest.java
@@ -30,6 +30,7 @@
 import junit.framework.TestCase;
 
 import org.apache.harmony.testframework.serialization.SerializationTest;
+import tests.util.PrefsTester;
 
 /**
  * 
@@ -37,8 +38,20 @@
 @TestTargetClass(NodeChangeEvent.class)
 public class NodeChangeEventTest extends TestCase {
 
+    private final PrefsTester prefsTester = new PrefsTester();
+
     NodeChangeEvent event;
 
+    protected void setUp() throws Exception {
+        super.setUp();
+        prefsTester.setUp();
+    }
+
+    protected void tearDown() throws Exception {
+        prefsTester.tearDown();
+        super.tearDown();
+    }
+
     @TestTargetNew(
         level = TestLevel.COMPLETE,
         notes = "",
diff --git a/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/NodeChangeListenerTest.java b/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/NodeChangeListenerTest.java
index c5e3252..3cdb4d9 100644
--- a/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/NodeChangeListenerTest.java
+++ b/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/NodeChangeListenerTest.java
@@ -26,6 +26,7 @@
 import java.util.prefs.Preferences;
 
 import junit.framework.TestCase;
+import tests.util.PrefsTester;
 
 /**
  * 
@@ -33,20 +34,26 @@
 @TestTargetClass(NodeChangeListener.class)
 public class NodeChangeListenerTest extends TestCase {
 
+    private final PrefsTester prefsTester = new PrefsTester();
+
     NodeChangeListener l;
 
     /*
      * @see TestCase#setUp()
      */
+    @Override
     protected void setUp() throws Exception {
         super.setUp();
+        prefsTester.setUp();
         l = new NodeChangeListenerImpl();
     }
 
     /*
      * @see TestCase#tearDown()
      */
+    @Override
     protected void tearDown() throws Exception {
+        prefsTester.tearDown();
         super.tearDown();
     }
 
diff --git a/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferenceChangeEventTest.java b/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferenceChangeEventTest.java
index 4030b89..dda1f6c 100644
--- a/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferenceChangeEventTest.java
+++ b/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferenceChangeEventTest.java
@@ -92,7 +92,7 @@
     )
     public void testConstructor() {
         event = new PreferenceChangeEvent(Preferences.userRoot(), "key",
-                "value");
+        "value");
         assertEquals("key", event.getKey());
         assertEquals("value", event.getNewValue());
         assertSame(Preferences.userRoot(), event.getNode());
@@ -107,7 +107,7 @@
     )
     public void testSerialization() throws Exception {
         event = new PreferenceChangeEvent(Preferences.userRoot(), "key",
-                "value");
+        "value");
         try {
             SerializationTest.copySerializable(event);
             fail("No expected NotSerializableException");
diff --git a/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferenceChangeListenerTest.java b/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferenceChangeListenerTest.java
index e4df9c4..7080aa5 100644
--- a/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferenceChangeListenerTest.java
+++ b/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferenceChangeListenerTest.java
@@ -38,6 +38,7 @@
     /*
      * @see TestCase#setUp()
      */
+    @Override
     protected void setUp() throws Exception {
         super.setUp();
         l = new PreferenceChangeListenerImpl();
diff --git a/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferencesFactoryTest.java b/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferencesFactoryTest.java
index 818d5ad..729bc05 100644
--- a/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferencesFactoryTest.java
+++ b/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferencesFactoryTest.java
@@ -37,6 +37,7 @@
     /*
      * @see TestCase#setUp()
      */
+    @Override
     protected void setUp() throws Exception {
         super.setUp();
         f = new PreferencesFactoryImpl();
@@ -49,7 +50,7 @@
         args = {}
     )
     public void testUserRoot() {
-        f.userRoot();
+        assertNull(f.userRoot());
     }
 
     @TestTargetNew(
@@ -59,7 +60,7 @@
         args = {}
     )
     public void testSystemRoot() {
-        f.systemRoot();
+        assertNull(f.systemRoot());
     }
 
     public static class PreferencesFactoryImpl implements PreferencesFactory {
diff --git a/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferencesTest.java b/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferencesTest.java
index 9d526d6..c9c74fd 100644
--- a/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferencesTest.java
+++ b/libcore/prefs/src/test/java/org/apache/harmony/prefs/tests/java/util/prefs/PreferencesTest.java
@@ -39,14 +39,15 @@
 import java.util.prefs.PreferenceChangeListener;
 import java.util.prefs.Preferences;
 
+import tests.util.PrefsTester;
+
 /**
  * 
  */
 @TestTargetClass(Preferences.class)
 public class PreferencesTest extends TestCase {
 
-    private String oldJavaHome;
-    private String oldUserHome;
+    private final PrefsTester prefsTester = new PrefsTester();
 
     MockSecurityManager manager = new MockSecurityManager();
 
@@ -74,39 +75,24 @@
     /*
      * @see TestCase#setUp()
      */
+    @Override
     protected void setUp() throws Exception {
         super.setUp();
         in = new ByteArrayInputStream(
                 "<!DOCTYPE preferences SYSTEM \"http://java.sun.com/dtd/preferences.dtd\"><preferences><root type=\"user\"><map></map></root></preferences>"
                         .getBytes("UTF-8"));
         stream = new MockInputStream(in);
-
-        Preferences.systemRoot().clear();
-        Preferences.userRoot().clear();
-
-        Preferences p = Preferences.userNodeForPackage(Preferences.class);
-        p.clear();
-        try {
-            p.removeNode();
-        } catch (BackingStoreException e) {
-        }
+        prefsTester.setUp();
     }
 
     /*
      * @see TestCase#tearDown()
      */
+    @Override
     protected void tearDown() throws Exception {
-        super.tearDown();
         stream.close();
-        Preferences p = Preferences.userNodeForPackage(Preferences.class);
-        p.clear();        
-        try {
-            p.removeNode();
-        } catch (BackingStoreException e) {
-        }
-
-        Preferences.systemRoot().clear();
-        Preferences.userRoot().clear();
+        prefsTester.tearDown();
+        super.tearDown();
     }
 
     @TestTargetNew(
@@ -1826,6 +1812,7 @@
             wrapper = in;
         }
 
+        @Override
         public int read() throws IOException {
             checkException();
             return wrapper.read();
@@ -1839,136 +1826,170 @@
             super();
         }
 
+        @Override
         public String absolutePath() {
             return null;
         }
 
+        @Override
         public String[] childrenNames() throws BackingStoreException {
             return null;
         }
 
+        @Override
         public void clear() throws BackingStoreException {
         }
 
+        @Override
         public void exportNode(OutputStream ostream) throws IOException,
                 BackingStoreException {
         }
 
+        @Override
         public void exportSubtree(OutputStream ostream) throws IOException,
                 BackingStoreException {
         }
 
+        @Override
         public void flush() throws BackingStoreException {
         }
 
+        @Override
         public String get(String key, String deflt) {
             return null;
         }
 
+        @Override
         public boolean getBoolean(String key, boolean deflt) {
             return false;
         }
 
+        @Override
         public byte[] getByteArray(String key, byte[] deflt) {
             return null;
         }
 
+        @Override
         public double getDouble(String key, double deflt) {
             return 0;
         }
 
+        @Override
         public float getFloat(String key, float deflt) {
             return 0;
         }
 
+        @Override
         public int getInt(String key, int deflt) {
             return 0;
         }
 
+        @Override
         public long getLong(String key, long deflt) {
             return 0;
         }
 
+        @Override
         public boolean isUserNode() {
             return false;
         }
 
+        @Override
         public String[] keys() throws BackingStoreException {
             return null;
         }
 
+        @Override
         public String name() {
             return null;
         }
 
+        @Override
         public Preferences node(String name) {
             return null;
         }
 
+        @Override
         public boolean nodeExists(String name) throws BackingStoreException {
             return false;
         }
 
+        @Override
         public Preferences parent() {
             return null;
         }
 
+        @Override
         public void put(String key, String value) {
 
         }
 
+        @Override
         public void putBoolean(String key, boolean value) {
 
         }
 
+        @Override
         public void putByteArray(String key, byte[] value) {
 
         }
 
+        @Override
         public void putDouble(String key, double value) {
 
         }
 
+        @Override
         public void putFloat(String key, float value) {
 
         }
 
+        @Override
         public void putInt(String key, int value) {
 
         }
 
+        @Override
         public void putLong(String key, long value) {
 
         }
 
+        @Override
         public void remove(String key) {
 
         }
 
+        @Override
         public void removeNode() throws BackingStoreException {
 
         }
 
+        @Override
         public void addNodeChangeListener(NodeChangeListener ncl) {
 
         }
 
+        @Override
         public void addPreferenceChangeListener(PreferenceChangeListener pcl) {
 
         }
 
+        @Override
         public void removeNodeChangeListener(NodeChangeListener ncl) {
 
         }
 
+        @Override
         public void removePreferenceChangeListener(PreferenceChangeListener pcl) {
 
         }
 
+        @Override
         public void sync() throws BackingStoreException {
 
         }
 
+        @Override
         public String toString() {
             return null;
         }
diff --git a/libcore/prefs/src/test/java/tests/prefs/AllTests.java b/libcore/prefs/src/test/java/tests/prefs/AllTests.java
index 843d733..b3f2ed6 100644
--- a/libcore/prefs/src/test/java/tests/prefs/AllTests.java
+++ b/libcore/prefs/src/test/java/tests/prefs/AllTests.java
@@ -20,7 +20,8 @@
 import junit.framework.TestSuite;
 
 /**
- * Test suite that includes all tests for the Math project.
+ * Test suite that includes all tests for the Prefs project.
+ *
  */
 public class AllTests {
 
diff --git a/libcore/prefs/src/test/resources/prefs/java/util/prefs/preferences.dtd b/libcore/prefs/src/test/resources/prefs/java/util/prefs/preferences.dtd
deleted file mode 100644
index a116015..0000000
--- a/libcore/prefs/src/test/resources/prefs/java/util/prefs/preferences.dtd
+++ /dev/null
@@ -1,56 +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.
- -->
-
-<!-- DTD for a Preferences tree. -->
-
-<!-- The preferences element is at the root of an XML document
-     representing a Preferences tree. -->
-<!ELEMENT preferences (root)>
-
-<!-- The preferences element contains an optional version attribute,
-      which specifies version of DTD. -->
-<!ATTLIST preferences EXTERNAL_XML_VERSION CDATA "0.0" >  
-
-<!-- The root element has a map representing the root's preferences
-     (if any), and one node for each child of the root (if any). -->
-<!ELEMENT root (map, node*) >
-
-<!-- Additionally, the root contains a type attribute, which
-     specifies whether it's the system or user root. -->
-<!ATTLIST root
-          type (system|user) #REQUIRED >
-
-<!-- Each node has a map representing its preferences (if any),
-     and one node for each child (if any). -->
-
-<!ELEMENT node (map, node*) >
-
-<!-- Additionally, each node has a name attribute -->
-<!ATTLIST node
-          name CDATA #REQUIRED >
-
-<!-- A map represents the preferences stored at a node (if any). -->
-<!ELEMENT map (entry*) >
-
-<!-- An entry represents a single preference, which is simply
-      a key-value pair. -->
-<!ELEMENT entry EMPTY >
-<!ATTLIST entry
-          key   CDATA #REQUIRED
-          value CDATA #REQUIRED >
\ No newline at end of file
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 c058db8..2853bbe 100644
--- a/libcore/regex/src/main/java/java/util/regex/Pattern.java
+++ b/libcore/regex/src/main/java/java/util/regex/Pattern.java
@@ -356,28 +356,33 @@
     }
 
     /**
-     * Splits the given input sequence around occurrences of the {@code Pattern}.
-     * The function first determines all occurrences of the {@code Pattern}
-     * inside the input sequence. It then builds an array of the
-     * &quot;remaining&quot; strings before, in-between, and after these
-     * occurrences. An additional parameter determines the maximal number of
-     * entries in the resulting array and the handling of trailing empty
-     * strings.
+     * 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 maximal number of entries in the resulting
-     *            array.
+     *            Determines the maximum number of entries in the resulting
+     *            array, and the treatment of trailing empty strings.
      *            <ul>
-     *            <li>For n &gt; 0, it is guaranteed that the resulting array
-     *            contains at most n entries.
+     *            <li>For n &gt; 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 &lt; 0, the length of the resulting array is
-     *            exactly the number of occurrences of the {@code Pattern} +1.
+     *            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 length of the resulting array is at most
-     *            the number of occurrences of the {@code Pattern} +1. Empty
-     *            strings at the end of the array are not included.
+     *            <li>For n == 0, the result is as for n &lt; 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.
@@ -385,6 +390,13 @@
      * @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();
@@ -393,14 +405,10 @@
         Matcher matcher = new Matcher(this, inputSeq);
         int savedPos = 0;
         
-        // Add text preceding each occurrence, if enough space. Only do this for
-        // non-empty input sequences, because otherwise we'd add the "trailing
-        // empty string" twice.
-        if (inputSeq.length() != 0) {
-            while(matcher.find() && list.size() + 1 < maxLength) {
-                list.add(input.substring(savedPos, matcher.start()));
-                savedPos = matcher.end();
-            }
+        // 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.
@@ -412,11 +420,10 @@
             }
         }
         
-        // Remove trailing spaces, if limit == 0 is requested.
+        // Remove trailing empty matches in the limit == 0 case.
         if (limit == 0) {
             int i = list.size() - 1;
-            // Don't remove 1st element, since array must not be empty.
-            while(i > 0 && "".equals(list.get(i))) {
+            while (i >= 0 && "".equals(list.get(i))) {
                 list.remove(i);
                 i--;
             }
diff --git a/libcore/regex/src/test/java/org/apache/harmony/regex/tests/java/util/regex/SplitTest.java b/libcore/regex/src/test/java/org/apache/harmony/regex/tests/java/util/regex/SplitTest.java
index ea615c0..894dfff 100644
--- a/libcore/regex/src/test/java/org/apache/harmony/regex/tests/java/util/regex/SplitTest.java
+++ b/libcore/regex/src/test/java/org/apache/harmony/regex/tests/java/util/regex/SplitTest.java
@@ -32,12 +32,62 @@
         Pattern p = Pattern.compile("/");
         String[] results = p.split("have/you/done/it/right");
         String[] expected = new String[] { "have", "you", "done", "it", "right" };
-        assertEquals(expected.length, results.length);
-        for (int i = 0; i < expected.length; i++) {
-            assertEquals(results[i], expected[i]);
-        }
+        assertArraysEqual(expected, results);
     }
 
+    @TestTargets({
+        @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "Verifies the basic functionality of split with empty matches.",
+            method = "split",
+            args = {java.lang.CharSequence.class}
+        )
+    })
+    public void testEmptySplits() {
+        // Trailing empty matches are removed.
+        assertArraysEqual(new String[0], "hello".split("."));
+        assertArraysEqual(new String[] { "1", "2" }, "1:2:".split(":"));
+        // ...including when that results in an empty result.
+        assertArraysEqual(new String[0], ":".split(":"));
+        // ...but not when limit < 0.
+        assertArraysEqual(new String[] { "1", "2", "" }, "1:2:".split(":", -1));
+        
+        // Leading empty matches are retained.
+        assertArraysEqual(new String[] { "", "", "o" }, "hello".split(".."));
+        
+        // A separator that doesn't occur in the input gets you the input.
+        assertArraysEqual(new String[] { "hello" }, "hello".split("not-present-in-test"));
+        // ...including when the input is the empty string.
+        // (Perl returns an empty list instead.)
+        assertArraysEqual(new String[] { "" }, "".split("not-present-in-test"));
+        assertArraysEqual(new String[] { "" }, "".split("A?"));
+        
+        // The limit argument controls the size of the result.
+        // If l == 0, the result is as long as needed, except trailing empty matches are dropped.
+        // If l < 0, the result is as long as needed, and trailing empty matches are retained.
+        // If l > 0, the result contains the first l matches, plus one string containing the remaining input.
+        // Examples without a trailing separator (and hence without a trailing empty match):
+        assertArraysEqual(new String[] { "a", "b", "c" }, "a,b,c".split(",", 0));
+        assertArraysEqual(new String[] { "a,b,c" }, "a,b,c".split(",", 1));
+        assertArraysEqual(new String[] { "a", "b,c" }, "a,b,c".split(",", 2));
+        assertArraysEqual(new String[] { "a", "b", "c" }, "a,b,c".split(",", 3));
+        assertArraysEqual(new String[] { "a", "b", "c" }, "a,b,c".split(",", Integer.MAX_VALUE));
+        // Examples with a trailing separator (and hence possibly with a trailing empty match):
+        assertArraysEqual(new String[] { "a", "b", "c" }, "a,b,c,".split(",", 0));
+        assertArraysEqual(new String[] { "a,b,c," }, "a,b,c,".split(",", 1));
+        assertArraysEqual(new String[] { "a", "b,c," }, "a,b,c,".split(",", 2));
+        assertArraysEqual(new String[] { "a", "b", "c," }, "a,b,c,".split(",", 3));
+        assertArraysEqual(new String[] { "a", "b", "c", "" }, "a,b,c,".split(",", Integer.MAX_VALUE));
+        assertArraysEqual(new String[] { "a", "b", "c", "" }, "a,b,c,".split(",", -1));
+    }
+    
+    private void assertArraysEqual(String[] expected, String[] actual) {
+        assertEquals(expected.length, actual.length);
+        for (int i = 0; i < expected.length; i++) {
+            assertEquals(Integer.toString(i), expected[i], actual[i]);
+        }
+    }
+    
     @TestTargetNew(
         level = TestLevel.PARTIAL_COMPLETE,
         notes = "Verifies the functionality of split(java.lang.CharSequence). Test uses not empty pattern.",
diff --git a/libcore/run-core-tests b/libcore/run-core-tests
index 62b3c51..70ab320 100755
--- a/libcore/run-core-tests
+++ b/libcore/run-core-tests
@@ -26,5 +26,5 @@
 chmod 777 $tmp
   
 exec dalvikvm -Duser.language=en -Duser.region=US -Djava.io.tmpdir=$tmp \
-     -Xbootclasspath:$BOOTCLASSPATH:/system/framework/core-tests.jar \
+     -classpath /system/framework/core-tests.jar \
      -Xmx64M com.google.coretests.Main "$@"
diff --git a/libcore/security/src/main/files/cacerts.bks b/libcore/security/src/main/files/cacerts.bks
index bbcc080..36f4919 100644
--- a/libcore/security/src/main/files/cacerts.bks
+++ b/libcore/security/src/main/files/cacerts.bks
Binary files differ
diff --git a/libcore/security/src/main/files/cacerts/3e7271e8.0 b/libcore/security/src/main/files/cacerts/3e7271e8.0
new file mode 100644
index 0000000..62b5b22
--- /dev/null
+++ b/libcore/security/src/main/files/cacerts/3e7271e8.0
@@ -0,0 +1,85 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 946059622 (0x3863b966)
+        Signature Algorithm: sha1WithRSAEncryption
+        Issuer: O=Entrust.net, OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Certification Authority (2048)
+        Validity
+            Not Before: Dec 24 17:50:51 1999 GMT
+            Not After : Dec 24 18:20:51 2019 GMT
+        Subject: O=Entrust.net, OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Certification Authority (2048)
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (2048 bit)
+                Modulus (2048 bit):
+                    00:ad:4d:4b:a9:12:86:b2:ea:a3:20:07:15:16:64:
+                    2a:2b:4b:d1:bf:0b:4a:4d:8e:ed:80:76:a5:67:b7:
+                    78:40:c0:73:42:c8:68:c0:db:53:2b:dd:5e:b8:76:
+                    98:35:93:8b:1a:9d:7c:13:3a:0e:1f:5b:b7:1e:cf:
+                    e5:24:14:1e:b1:81:a9:8d:7d:b8:cc:6b:4b:03:f1:
+                    02:0c:dc:ab:a5:40:24:00:7f:74:94:a1:9d:08:29:
+                    b3:88:0b:f5:87:77:9d:55:cd:e4:c3:7e:d7:6a:64:
+                    ab:85:14:86:95:5b:97:32:50:6f:3d:c8:ba:66:0c:
+                    e3:fc:bd:b8:49:c1:76:89:49:19:fd:c0:a8:bd:89:
+                    a3:67:2f:c6:9f:bc:71:19:60:b8:2d:e9:2c:c9:90:
+                    76:66:7b:94:e2:af:78:d6:65:53:5d:3c:d6:9c:b2:
+                    cf:29:03:f9:2f:a4:50:b2:d4:48:ce:05:32:55:8a:
+                    fd:b2:64:4c:0e:e4:98:07:75:db:7f:df:b9:08:55:
+                    60:85:30:29:f9:7b:48:a4:69:86:e3:35:3f:1e:86:
+                    5d:7a:7a:15:bd:ef:00:8e:15:22:54:17:00:90:26:
+                    93:bc:0e:49:68:91:bf:f8:47:d3:9d:95:42:c1:0e:
+                    4d:df:6f:26:cf:c3:18:21:62:66:43:70:d6:d5:c0:
+                    07:e1
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            Netscape Cert Type: 
+                SSL CA, S/MIME CA, Object Signing CA
+            X509v3 Authority Key Identifier: 
+                keyid:55:E4:81:D1:11:80:BE:D8:89:B9:08:A3:31:F9:A1:24:09:16:B9:70
+
+            X509v3 Subject Key Identifier: 
+                55:E4:81:D1:11:80:BE:D8:89:B9:08:A3:31:F9:A1:24:09:16:B9:70
+            1.2.840.113533.7.65.0: 
+                0...V5.0:4.0....
+    Signature Algorithm: sha1WithRSAEncryption
+        59:47:ac:21:84:8a:17:c9:9c:89:53:1e:ba:80:85:1a:c6:3c:
+        4e:3e:b1:9c:b6:7c:c6:92:5d:18:64:02:e3:d3:06:08:11:61:
+        7c:63:e3:2b:9d:31:03:70:76:d2:a3:28:a0:f4:bb:9a:63:73:
+        ed:6d:e5:2a:db:ed:14:a9:2b:c6:36:11:d0:2b:eb:07:8b:a5:
+        da:9e:5c:19:9d:56:12:f5:54:29:c8:05:ed:b2:12:2a:8d:f4:
+        03:1b:ff:e7:92:10:87:b0:3a:b5:c3:9d:05:37:12:a3:c7:f4:
+        15:b9:d5:a4:39:16:9b:53:3a:23:91:f1:a8:82:a2:6a:88:68:
+        c1:79:02:22:bc:aa:a6:d6:ae:df:b0:14:5f:b8:87:d0:dd:7c:
+        7f:7b:ff:af:1c:cf:e6:db:07:ad:5e:db:85:9d:d0:2b:0d:33:
+        db:04:d1:e6:49:40:13:2b:76:fb:3e:e9:9c:89:0f:15:ce:18:
+        b0:85:78:21:4f:6b:4f:0e:fa:36:67:cd:07:f2:ff:08:d0:e2:
+        de:d9:bf:2a:af:b8:87:86:21:3c:04:ca:b7:94:68:7f:cf:3c:
+        e9:98:d7:38:ff:ec:c0:d9:50:f0:2e:4b:58:ae:46:6f:d0:2e:
+        c3:60:da:72:55:72:bd:4c:45:9e:61:ba:bf:84:81:92:03:d1:
+        d2:69:7c:c5
+-----BEGIN CERTIFICATE-----
+MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML
+RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp
+bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5
+IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0xOTEy
+MjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3
+LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp
+YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG
+A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq
+K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe
+sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX
+MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT
+XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/
+HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH
+4QIDAQABo3QwcjARBglghkgBhvhCAQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGA
+vtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdERgL7YibkIozH5oSQJFrlwMB0G
+CSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEA
+WUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo
+oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQ
+h7A6tcOdBTcSo8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18
+f3v/rxzP5tsHrV7bhZ3QKw0z2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfN
+B/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjXOP/swNlQ8C5LWK5Gb9Auw2DaclVy
+vUxFnmG6v4SBkgPR0ml8xQ==
+-----END CERTIFICATE-----
diff --git a/libcore/security/src/main/files/cacerts/ab86d4de.0 b/libcore/security/src/main/files/cacerts/ab86d4de.0
new file mode 100644
index 0000000..c6f241f
--- /dev/null
+++ b/libcore/security/src/main/files/cacerts/ab86d4de.0
@@ -0,0 +1,104 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 946062766 (0x3863c5ae)
+        Signature Algorithm: sha1WithRSAEncryption
+        Issuer: O=Entrust.net, OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Certification Authority (2048)
+        Validity
+            Not Before: Aug 25 18:14:26 2008 GMT
+            Not After : Aug 25 18:44:26 2018 GMT
+        Subject: C=US, O=Entrust, Inc., OU=AND ADDITIONAL TERMS GOVERNING USE AND RELIANCE, OU=CPS CONTAINS IMPORTANT LIMITATIONS OF WARRANTIES AND LIABILITY, OU=www.entrust.net/CPS is incorporated by reference, OU=(c) 2008 Entrust, Inc., CN=Entrust Certification Authority - L1B
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (2048 bit)
+                Modulus (2048 bit):
+                    00:dc:21:f5:68:f9:7a:ce:87:f2:78:df:d8:3b:4d:
+                    06:7d:c6:24:e4:a9:cd:9d:01:56:e4:f6:71:17:aa:
+                    7f:75:22:18:e4:74:6d:1b:3e:56:d5:b1:a6:1e:dd:
+                    59:26:53:ca:06:e6:ba:0b:6f:37:bb:a8:c6:9c:15:
+                    3b:06:1b:87:0c:c2:1a:4d:d3:81:ae:db:50:65:a5:
+                    3a:64:4f:30:34:9a:2b:a9:1f:fd:2b:d1:38:71:19:
+                    68:f2:8e:eb:7b:c9:40:3c:48:c4:19:b1:b7:10:25:
+                    ef:44:a7:e6:77:9b:7d:22:9a:de:d8:5e:d9:c3:ce:
+                    c9:71:22:bb:ae:ef:05:d6:f2:17:e7:56:78:e1:53:
+                    05:4a:26:73:b8:c7:49:67:93:23:0f:56:b2:8f:dd:
+                    c9:59:05:e5:63:15:b4:87:7e:40:46:e9:b5:00:7b:
+                    03:b4:0d:e4:96:67:2c:de:1b:59:0b:1a:1f:b8:63:
+                    44:ae:c1:d7:44:87:c4:91:59:9c:00:43:6d:c6:df:
+                    0a:b0:b1:04:cd:fe:be:30:5e:3a:25:72:dd:a2:3e:
+                    ed:46:3a:c7:a4:5c:5c:e4:25:f2:13:07:e8:ae:da:
+                    9b:19:9b:a2:d9:60:9d:ce:90:47:6a:61:7b:40:e8:
+                    14:c2:fe:2f:84:5a:66:17:c0:97:d3:49:38:de:63:
+                    02:9f
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            Authority Information Access: 
+                OCSP - URI:http://ocsp.entrust.net
+
+            X509v3 CRL Distribution Points: 
+                URI:http://crl.entrust.net/2048ca.crl
+
+            X509v3 Certificate Policies: 
+                Policy: X509v3 Any Policy
+                  CPS: http://www.entrust.net/CPS
+
+            X509v3 Subject Key Identifier: 
+                F5:F2:96:88:7D:0D:F3:2A:F9:4E:E7:34:A0:BD:46:7E:13:D6:16:C8
+            X509v3 Authority Key Identifier: 
+                keyid:55:E4:81:D1:11:80:BE:D8:89:B9:08:A3:31:F9:A1:24:09:16:B9:70
+
+            1.2.840.113533.7.65.0: 
+                0
+..V7.1....
+    Signature Algorithm: sha1WithRSAEncryption
+        0b:25:3c:58:fa:8e:dc:a2:42:3b:76:71:6e:6c:d4:4f:2b:b9:
+        53:5c:b2:58:b9:b1:dc:6f:1a:e4:e3:c4:50:f2:41:82:ba:f4:
+        7d:c7:c1:f9:fa:8c:53:bf:b9:62:b7:49:e3:1d:0a:fc:1f:d6:
+        c4:76:6a:93:cb:77:1e:2c:7f:d0:3f:16:63:4c:72:4c:67:60:
+        0f:f8:80:d6:a7:9a:ca:a2:33:91:0f:44:b2:66:3d:8e:68:0c:
+        40:85:12:37:91:b9:82:77:34:59:2d:5c:df:82:6e:2c:b6:7a:
+        d2:04:90:67:68:4b:70:fc:2d:b8:ff:90:64:6f:7e:91:f7:d1:
+        47:33:f3:5b:b8:58:2e:21:d8:75:60:1b:13:cc:f8:b2:a8:fa:
+        6a:a9:2a:5a:4f:45:85:40:b4:dd:34:05:b7:70:ca:01:ef:e1:
+        81:e7:11:50:db:3e:e2:d7:10:2e:6a:15:7f:b7:d4:a3:62:b2:
+        89:69:61:57:c6:7f:8e:9e:d4:24:7a:f3:a1:43:5f:a0:7a:89:
+        dc:59:cd:7d:d7:75:a7:bc:53:d5:47:35:c6:31:30:20:9f:9b:
+        ba:b5:83:e6:89:55:01:4d:91:3b:d6:89:35:87:3c:83:6b:7a:
+        29:82:d4:4b:d4:e6:16:74:b0:01:10:ab:69:06:14:37:7b:f7:
+        66:30:3a:c5
+-----BEGIN CERTIFICATE-----
+MIIFkTCCBHmgAwIBAgIEOGPFrjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML
+RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp
+bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5
+IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw0wODA4MjUxODE0MjZaFw0xODA4
+MjUxODQ0MjZaMIIBNDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIElu
+Yy4xODA2BgNVBAsTL0FORCBBRERJVElPTkFMIFRFUk1TIEdPVkVSTklORyBVU0Ug
+QU5EIFJFTElBTkNFMUcwRQYDVQQLEz5DUFMgQ09OVEFJTlMgSU1QT1JUQU5UIExJ
+TUlUQVRJT05TIE9GIFdBUlJBTlRJRVMgQU5EIExJQUJJTElUWTE5MDcGA1UECxMw
+d3d3LmVudHJ1c3QubmV0L0NQUyBpcyBpbmNvcnBvcmF0ZWQgYnkgcmVmZXJlbmNl
+MR8wHQYDVQQLExYoYykgMjAwOCBFbnRydXN0LCBJbmMuMS4wLAYDVQQDEyVFbnRy
+dXN0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gTDFCMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEA3CH1aPl6zofyeN/YO00GfcYk5KnNnQFW5PZxF6p/
+dSIY5HRtGz5W1bGmHt1ZJlPKBua6C283u6jGnBU7BhuHDMIaTdOBrttQZaU6ZE8w
+NJorqR/9K9E4cRlo8o7re8lAPEjEGbG3ECXvRKfmd5t9Ipre2F7Zw87JcSK7ru8F
+1vIX51Z44VMFSiZzuMdJZ5MjD1ayj93JWQXlYxW0h35ARum1AHsDtA3klmcs3htZ
+CxofuGNErsHXRIfEkVmcAENtxt8KsLEEzf6+MF46JXLdoj7tRjrHpFxc5CXyEwfo
+rtqbGZui2WCdzpBHamF7QOgUwv4vhFpmF8CX00k43mMCnwIDAQABo4IBJjCCASIw
+DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wMwYIKwYBBQUHAQEEJzAl
+MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5lbnRydXN0Lm5ldDAyBgNVHR8EKzAp
+MCegJaAjhiFodHRwOi8vY3JsLmVudHJ1c3QubmV0LzIwNDhjYS5jcmwwOwYDVR0g
+BDQwMjAwBgRVHSAAMCgwJgYIKwYBBQUHAgEWGmh0dHA6Ly93d3cuZW50cnVzdC5u
+ZXQvQ1BTMB0GA1UdDgQWBBT18paIfQ3zKvlO5zSgvUZ+E9YWyDAfBgNVHSMEGDAW
+gBRV5IHREYC+2Im5CKMx+aEkCRa5cDAZBgkqhkiG9n0HQQAEDDAKGwRWNy4xAwIA
+gTANBgkqhkiG9w0BAQUFAAOCAQEACyU8WPqO3KJCO3ZxbmzUTyu5U1yyWLmx3G8a
+5OPEUPJBgrr0fcfB+fqMU7+5YrdJ4x0K/B/WxHZqk8t3Hix/0D8WY0xyTGdgD/iA
+1qeayqIzkQ9EsmY9jmgMQIUSN5G5gnc0WS1c34JuLLZ60gSQZ2hLcPwtuP+QZG9+
+kffRRzPzW7hYLiHYdWAbE8z4sqj6aqkqWk9FhUC03TQFt3DKAe/hgecRUNs+4tcQ
+LmoVf7fUo2KyiWlhV8Z/jp7UJHrzoUNfoHqJ3FnNfdd1p7xT1Uc1xjEwIJ+burWD
+5olVAU2RO9aJNYc8g2t6KYLUS9TmFnSwARCraQYUN3v3ZjA6xQ==
+-----END CERTIFICATE-----
diff --git a/libcore/security/src/main/files/cacerts/b0f3e76e.0 b/libcore/security/src/main/files/cacerts/b0f3e76e.0
index 05ce1ec..386b70a 100644
--- a/libcore/security/src/main/files/cacerts/b0f3e76e.0
+++ b/libcore/security/src/main/files/cacerts/b0f3e76e.0
@@ -2,12 +2,12 @@
     Data:
         Version: 3 (0x2)
         Serial Number:
-            02:00:00:00:00:00:d6:78:b7:94:05
-        Signature Algorithm: md5WithRSAEncryption
+            04:00:00:00:00:01:15:4b:5a:c3:94
+        Signature Algorithm: sha1WithRSAEncryption
         Issuer: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA
         Validity
             Not Before: Sep  1 12:00:00 1998 GMT
-            Not After : Jan 28 12:00:00 2014 GMT
+            Not After : Jan 28 12:00:00 2028 GMT
         Subject: C=BE, O=GlobalSign nv-sa, OU=Root CA, CN=GlobalSign Root CA
         Subject Public Key Info:
             Public Key Algorithm: rsaEncryption
@@ -35,32 +35,31 @@
         X509v3 extensions:
             X509v3 Key Usage: critical
                 Certificate Sign, CRL Sign
-            X509v3 Subject Key Identifier: 
-                60:7B:66:1A:45:0D:97:CA:89:50:2F:7D:04:CD:34:A8:FF:FC:FD:4B
             X509v3 Basic Constraints: critical
                 CA:TRUE
-    Signature Algorithm: md5WithRSAEncryption
-        ae:aa:9f:fc:b7:d2:cb:1f:5f:39:29:28:18:9e:34:c9:6c:4f:
-        6f:1a:f0:64:a2:70:4a:4f:13:86:9b:60:28:9e:e8:81:49:98:
-        7d:0a:bb:e5:b0:9d:3d:36:db:8f:05:51:ff:09:31:2a:1f:dd:
-        89:77:9e:0f:2e:6c:95:04:ed:86:cb:b4:00:3f:84:02:4d:80:
-        6a:2a:2d:78:0b:ae:6f:2b:a2:83:44:83:1f:cd:50:82:4c:24:
-        af:bd:f7:a5:b4:c8:5a:0f:f4:e7:47:5e:49:8e:37:96:fe:9a:
-        88:05:3a:d9:c0:db:29:87:e6:19:96:47:a7:3a:a6:8c:8b:3c:
-        77:fe:46:63:a7:53:da:21:d1:ac:7e:49:a2:4b:e6:c3:67:59:
-        2f:b3:8a:0e:bb:2c:bd:a9:aa:42:7c:35:c1:d8:7f:d5:a7:31:
-        3a:4e:63:43:39:af:08:b0:61:34:8c:d3:98:a9:43:34:f6:0f:
-        87:29:3b:9d:c2:56:58:98:77:c3:f7:1b:ac:f6:9d:f8:3e:aa:
-        a7:54:45:f0:f5:f9:d5:31:65:fe:6b:58:9c:71:b3:1e:d7:52:
-        ea:32:17:fc:40:60:1d:c9:79:24:b2:f6:6c:fd:a8:66:0e:82:
-        dd:98:cb:da:c2:44:4f:2e:a0:7b:f2:f7:6b:2c:76:11:84:46:
-        8a:78:a3:e3
-SHA1 Fingerprint=2F:17:3F:7D:E9:96:67:AF:A5:7A:F8:0A:A2:D1:B1:2F:AC:83:03:38
+            X509v3 Subject Key Identifier: 
+                60:7B:66:1A:45:0D:97:CA:89:50:2F:7D:04:CD:34:A8:FF:FC:FD:4B
+    Signature Algorithm: sha1WithRSAEncryption
+        d6:73:e7:7c:4f:76:d0:8d:bf:ec:ba:a2:be:34:c5:28:32:b5:
+        7c:fc:6c:9c:2c:2b:bd:09:9e:53:bf:6b:5e:aa:11:48:b6:e5:
+        08:a3:b3:ca:3d:61:4d:d3:46:09:b3:3e:c3:a0:e3:63:55:1b:
+        f2:ba:ef:ad:39:e1:43:b9:38:a3:e6:2f:8a:26:3b:ef:a0:50:
+        56:f9:c6:0a:fd:38:cd:c4:0b:70:51:94:97:98:04:df:c3:5f:
+        94:d5:15:c9:14:41:9c:c4:5d:75:64:15:0d:ff:55:30:ec:86:
+        8f:ff:0d:ef:2c:b9:63:46:f6:aa:fc:df:bc:69:fd:2e:12:48:
+        64:9a:e0:95:f0:a6:ef:29:8f:01:b1:15:b5:0c:1d:a5:fe:69:
+        2c:69:24:78:1e:b3:a7:1c:71:62:ee:ca:c8:97:ac:17:5d:8a:
+        c2:f8:47:86:6e:2a:c4:56:31:95:d0:67:89:85:2b:f9:6c:a6:
+        5d:46:9d:0c:aa:82:e4:99:51:dd:70:b7:db:56:3d:61:e4:6a:
+        e1:5c:d6:f6:fe:3d:de:41:cc:07:ae:63:52:bf:53:53:f4:2b:
+        e9:c7:fd:b6:f7:82:5f:85:d2:41:18:db:81:b3:04:1c:c5:1f:
+        a4:80:6f:15:20:c9:de:0c:88:0a:1d:d6:66:55:e2:fc:48:c9:
+        29:26:69:e0
 -----BEGIN CERTIFICATE-----
-MIIDdTCCAl2gAwIBAgILAgAAAAAA1ni3lAUwDQYJKoZIhvcNAQEEBQAwVzELMAkG
+MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
 A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
 b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
-MDBaFw0xNDAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
+MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
 YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
 aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
 jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
@@ -68,12 +67,12 @@
 1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
 snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
 U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
-9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIABjAdBgNVHQ4EFgQU
-YHtmGkUNl8qJUC99BM00qP/8/UswDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0B
-AQQFAAOCAQEArqqf/LfSyx9fOSkoGJ40yWxPbxrwZKJwSk8ThptgKJ7ogUmYfQq7
-5bCdPTbbjwVR/wkxKh/diXeeDy5slQTthsu0AD+EAk2AaioteAuubyuig0SDH81Q
-gkwkr733pbTIWg/050deSY43lv6aiAU62cDbKYfmGZZHpzqmjIs8d/5GY6dT2iHR
-rH5Jokvmw2dZL7OKDrssvamqQnw1wdh/1acxOk5jQzmvCLBhNIzTmKlDNPYPhyk7
-ncJWWJh3w/cbrPad+D6qp1RF8PX51TFl/mtYnHGzHtdS6jIX/EBgHcl5JLL2bP2o
-Zg6C3ZjL2sJETy6ge/L3ayx2EYRGinij4w==
+9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
+BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
+AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
+yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
+38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
+AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
+DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
+HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
 -----END CERTIFICATE-----
diff --git a/libcore/security/src/main/files/cacerts/bf64f35b.0 b/libcore/security/src/main/files/cacerts/bf64f35b.0
new file mode 100644
index 0000000..389623c
--- /dev/null
+++ b/libcore/security/src/main/files/cacerts/bf64f35b.0
@@ -0,0 +1,92 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 1116155212 (0x42872d4c)
+        Signature Algorithm: sha1WithRSAEncryption
+        Issuer: C=US, O=Entrust.net, OU=www.entrust.net/CPS incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Secure Server Certification Authority
+        Validity
+            Not Before: Jan  5 19:20:39 2007 GMT
+            Not After : Jan  5 19:50:39 2017 GMT
+        Subject: C=US, O=Entrust, Inc., OU=www.entrust.net/CPS is incorporated by reference, OU=(c) 2006 Entrust, Inc., CN=Entrust Root Certification Authority
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+            RSA Public Key: (2048 bit)
+                Modulus (2048 bit):
+                    00:b6:95:b6:43:42:fa:c6:6d:2a:6f:48:df:94:4c:
+                    39:57:05:ee:c3:79:11:41:68:36:ed:ec:fe:9a:01:
+                    8f:a1:38:28:fc:f7:10:46:66:2e:4d:1e:1a:b1:1a:
+                    4e:c6:d1:c0:95:88:b0:c9:ff:31:8b:33:03:db:b7:
+                    83:7b:3e:20:84:5e:ed:b2:56:28:a7:f8:e0:b9:40:
+                    71:37:c5:cb:47:0e:97:2a:68:c0:22:95:62:15:db:
+                    47:d9:f5:d0:2b:ff:82:4b:c9:ad:3e:de:4c:db:90:
+                    80:50:3f:09:8a:84:00:ec:30:0a:3d:18:cd:fb:fd:
+                    2a:59:9a:23:95:17:2c:45:9e:1f:6e:43:79:6d:0c:
+                    5c:98:fe:48:a7:c5:23:47:5c:5e:fd:6e:e7:1e:b4:
+                    f6:68:45:d1:86:83:5b:a2:8a:8d:b1:e3:29:80:fe:
+                    25:71:88:ad:be:bc:8f:ac:52:96:4b:aa:51:8d:e4:
+                    13:31:19:e8:4e:4d:9f:db:ac:b3:6a:d5:bc:39:54:
+                    71:ca:7a:7a:7f:90:dd:7d:1d:80:d9:81:bb:59:26:
+                    c2:11:fe:e6:93:e2:f7:80:e4:65:fb:34:37:0e:29:
+                    80:70:4d:af:38:86:2e:9e:7f:57:af:9e:17:ae:eb:
+                    1c:cb:28:21:5f:b6:1c:d8:e7:a2:04:22:f9:d3:da:
+                    d8:cb
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            Authority Information Access: 
+                OCSP - URI:http://ocsp.entrust.net
+
+            X509v3 CRL Distribution Points: 
+                URI:http://crl.entrust.net/server1.crl
+
+            X509v3 Certificate Policies: 
+                Policy: X509v3 Any Policy
+                  CPS: http://www.entrust.net/CPS
+
+            X509v3 Subject Key Identifier: 
+                68:90:E4:67:A4:A6:53:80:C7:86:66:A4:F1:F7:4B:43:FB:84:BD:6D
+            X509v3 Authority Key Identifier: 
+                keyid:F0:17:62:13:55:3D:B3:FF:0A:00:6B:FB:50:84:97:F3:ED:62:D0:1A
+
+            1.2.840.113533.7.65.0: 
+                0
+..V7.1....
+    Signature Algorithm: sha1WithRSAEncryption
+        0c:b0:84:7c:2d:13:fe:9a:3d:bf:18:05:95:3d:20:48:a3:16:
+        81:87:15:50:15:a4:88:8d:9f:60:d4:3a:6f:eb:2d:6e:3a:86:
+        a4:a9:d2:c1:9d:89:7a:08:1c:a4:2d:b3:47:8e:0f:64:4a:6f:
+        66:03:83:3f:4f:34:94:36:aa:29:6d:8b:8d:02:22:2b:8c:cd:
+        77:a5:70:95:86:91:d1:b6:bf:52:be:33:6a:6b:99:f9:6f:e1:
+        12:be:04:cb:33:bf:f5:12:1a:4e:44:ba:5b:16:4d:30:b9:f3:
+        b4:74:ce:6e:f2:68:56:58:dd:d8:a1:fd:54:05:f4:23:91:85:
+        c9:f9
+-----BEGIN CERTIFICATE-----
+MIIEmzCCBASgAwIBAgIEQoctTDANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC
+VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u
+ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc
+KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u
+ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNzAx
+MDUxOTIwMzlaFw0xNzAxMDUxOTUwMzlaMIGwMQswCQYDVQQGEwJVUzEWMBQGA1UE
+ChMNRW50cnVzdCwgSW5jLjE5MDcGA1UECxMwd3d3LmVudHJ1c3QubmV0L0NQUyBp
+cyBpbmNvcnBvcmF0ZWQgYnkgcmVmZXJlbmNlMR8wHQYDVQQLExYoYykgMjAwNiBF
+bnRydXN0LCBJbmMuMS0wKwYDVQQDEyRFbnRydXN0IFJvb3QgQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC2lbZD
+QvrGbSpvSN+UTDlXBe7DeRFBaDbt7P6aAY+hOCj89xBGZi5NHhqxGk7G0cCViLDJ
+/zGLMwPbt4N7PiCEXu2yViin+OC5QHE3xctHDpcqaMAilWIV20fZ9dAr/4JLya0+
+3kzbkIBQPwmKhADsMAo9GM37/SpZmiOVFyxFnh9uQ3ltDFyY/kinxSNHXF79buce
+tPZoRdGGg1uiio2x4ymA/iVxiK2+vI+sUpZLqlGN5BMxGehOTZ/brLNq1bw5VHHK
+enp/kN19HYDZgbtZJsIR/uaT4veA5GX7NDcOKYBwTa84hi6ef1evnheu6xzLKCFf
+thzY56IEIvnT2tjLAgMBAAGjggEnMIIBIzAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0T
+AQH/BAUwAwEB/zAzBggrBgEFBQcBAQQnMCUwIwYIKwYBBQUHMAGGF2h0dHA6Ly9v
+Y3NwLmVudHJ1c3QubmV0MDMGA1UdHwQsMCowKKAmoCSGImh0dHA6Ly9jcmwuZW50
+cnVzdC5uZXQvc2VydmVyMS5jcmwwOwYDVR0gBDQwMjAwBgRVHSAAMCgwJgYIKwYB
+BQUHAgEWGmh0dHA6Ly93d3cuZW50cnVzdC5uZXQvQ1BTMB0GA1UdDgQWBBRokORn
+pKZTgMeGZqTx90tD+4S9bTAfBgNVHSMEGDAWgBTwF2ITVT2z/woAa/tQhJfz7WLQ
+GjAZBgkqhkiG9n0HQQAEDDAKGwRWNy4xAwIAgTANBgkqhkiG9w0BAQUFAAOBgQAM
+sIR8LRP+mj2/GAWVPSBIoxaBhxVQFaSIjZ9g1Dpv6y1uOoakqdLBnYl6CBykLbNH
+jg9kSm9mA4M/TzSUNqopbYuNAiIrjM13pXCVhpHRtr9SvjNqa5n5b+ESvgTLM7/1
+EhpORLpbFk0wufO0dM5u8mhWWN3Yof1UBfQjkYXJ+Q==
+-----END CERTIFICATE-----
diff --git a/libcore/security/src/main/files/certimport.sh b/libcore/security/src/main/files/certimport.sh
index 7c0fab0..c021a10 100755
--- a/libcore/security/src/main/files/certimport.sh
+++ b/libcore/security/src/main/files/certimport.sh
@@ -1,4 +1,5 @@
 #!/bin/bash
+# java version >= 1.6 is required for this script.
 # This script was tested to work with bouncycastle 1.32.
 
 set -x
@@ -6,6 +7,14 @@
 
 CERTSTORE=cacerts.bks
 
+# Check java version.
+JAVA_VERSION=`java -version 2>&1 | head -1`
+JAVA_VERSION_MINOR=`expr match "$JAVA_VERSION" "java version \"[1-9]\.\([0-9]\).*\""`
+if [ $JAVA_VERSION_MINOR -lt 6 ]; then
+  echo "java version 1.6 or greater required for keytool usage"
+  exit 255
+fi
+
 if [ -a $CERTSTORE ]; then
     rm $CERTSTORE || exit 1
 fi
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 c8f9494..34337eb 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
@@ -327,11 +327,15 @@
                 if (attrFormat == X500Principal.CANONICAL) {
                     // only PrintableString and UTF8String in string format
                     // all others are output in hex format
+                    // BEGIN android-changed
+                    // no hex for teletex; see bug 2102191
                     int tag = value.getTag();
                     if (!ASN1StringType.UTF8STRING.checkTag(tag)
-                            && !ASN1StringType.PRINTABLESTRING.checkTag(tag)) {
+                            && !ASN1StringType.PRINTABLESTRING.checkTag(tag)
+                            && !ASN1StringType.TELETEXSTRING.checkTag(tag)) {
                         hexFormat = true;
                     }
+                    // END android-changed
                 }
 
             } else {
diff --git a/libcore/security/src/main/java/org/bouncycastle/jce/provider/IndexedPKIXParameters.java b/libcore/security/src/main/java/org/bouncycastle/jce/provider/IndexedPKIXParameters.java
index e8e834a..03679e2 100644
--- a/libcore/security/src/main/java/org/bouncycastle/jce/provider/IndexedPKIXParameters.java
+++ b/libcore/security/src/main/java/org/bouncycastle/jce/provider/IndexedPKIXParameters.java
@@ -109,7 +109,7 @@
             if (anchor != null) {
                 return anchor;
             }
-        } catch (Exception e) { 
+        } catch (Exception e) {
             Logger.getLogger(IndexedPKIXParameters.class.getName()).log(
                     Level.WARNING, "Error encoding cert.", e);
         }
@@ -125,6 +125,21 @@
     }
 
     /**
+     * Returns true if the given certificate is found in the trusted key
+     * store.
+     */
+    public boolean isDirectlyTrusted(X509Certificate cert) {
+        try {
+            Bytes encoded = new Bytes(cert.getEncoded());
+            return encodings.containsKey(encoded);
+        } catch (Exception e) {
+            Logger.getLogger(IndexedPKIXParameters.class.getName()).log(
+                    Level.WARNING, "Error encoding cert.", e);
+            return false;
+        }
+    }
+
+    /**
      * Wraps a byte[] and adds equals() and hashCode() support.
      */
     static class Bytes {
diff --git a/libcore/security/src/test/java/org/bouncycastle/jce/provider/AllTests.java b/libcore/security/src/test/java/org/bouncycastle/jce/provider/AllTests.java
new file mode 100644
index 0000000..e9fbdb0
--- /dev/null
+++ b/libcore/security/src/test/java/org/bouncycastle/jce/provider/AllTests.java
@@ -0,0 +1,34 @@
+/*
+ * 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 org.bouncycastle.jce.provider;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(AllTests.suite());
+    }
+
+    public static Test suite() {
+        TestSuite suite = tests.TestSuiteFactory.createTestSuite(
+                "All tests for " + AllTests.class.getPackage());
+        suite.addTestSuite(PKIXCertPathValidatorSpiTest.class);
+        return suite;
+    }
+}
diff --git a/libcore/security/src/test/java/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpiTest.java b/libcore/security/src/test/java/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpiTest.java
new file mode 100644
index 0000000..734e11d
--- /dev/null
+++ b/libcore/security/src/test/java/org/bouncycastle/jce/provider/PKIXCertPathValidatorSpiTest.java
@@ -0,0 +1,65 @@
+// Copyright 2009 Google Inc. All Rights Reserved.
+
+package org.bouncycastle.jce.provider;
+
+import junit.framework.TestCase;
+import org.apache.harmony.security.provider.cert.X509CertImpl;
+import org.apache.harmony.security.provider.cert.X509CertPathImpl;
+import org.bouncycastle.asn1.x509.X509CertificateStructure;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.ASN1InputStream;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.HashSet;
+import java.security.cert.CertificateException;
+import java.security.cert.TrustAnchor;
+import java.security.cert.CertPathValidatorException;
+import java.security.KeyStoreException;
+import java.security.InvalidAlgorithmParameterException;
+
+/**
+ * Verify the behavior of PKIXCertPathValidatorSpi.
+ */
+public class PKIXCertPathValidatorSpiTest extends TestCase {
+
+    /**
+     * A chain of 3 ASN1-encoded certificates for https://service.sprint.com.
+     * The certificate subjects are "service.sprint.com", "Entrust Certification
+     * Authority - L1B", and "Entrust.net Certification Authority (2048)". The
+     * last certificate uses UTF8 encoding for its X509 name.
+     */
+    private final byte[][] serviceSprintComCertChain = new byte[][] {
+            new byte[] { 48, -126, 6, 89, 48, -126, 5, 65, -96, 3, 2, 1, 2, 2, 4, 72, 13, 115, -81, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 5, 5, 0, 48, -126, 1, 52, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 22, 48, 20, 6, 3, 85, 4, 10, 19, 13, 69, 110, 116, 114, 117, 115, 116, 44, 32, 73, 110, 99, 46, 49, 56, 48, 54, 6, 3, 85, 4, 11, 19, 47, 65, 78, 68, 32, 65, 68, 68, 73, 84, 73, 79, 78, 65, 76, 32, 84, 69, 82, 77, 83, 32, 71, 79, 86, 69, 82, 78, 73, 78, 71, 32, 85, 83, 69, 32, 65, 78, 68, 32, 82, 69, 76, 73, 65, 78, 67, 69, 49, 71, 48, 69, 6, 3, 85, 4, 11, 19, 62, 67, 80, 83, 32, 67, 79, 78, 84, 65, 73, 78, 83, 32, 73, 77, 80, 79, 82, 84, 65, 78, 84, 32, 76, 73, 77, 73, 84, 65, 84, 73, 79, 78, 83, 32, 79, 70, 32, 87, 65, 82, 82, 65, 78, 84, 73, 69, 83, 32, 65, 78, 68, 32, 76, 73, 65, 66, 73, 76, 73, 84, 89, 49, 57, 48, 55, 6, 3, 85, 4, 11, 19, 48, 119, 119, 119, 46, 101, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 47, 67, 80, 83, 32, 105, 115, 32, 105, 110, 99, 111, 114, 112, 111, 114, 97, 116, 101, 100, 32, 98, 121, 32, 114, 101, 102, 101, 114, 101, 110, 99, 101, 49, 31, 48, 29, 6, 3, 85, 4, 11, 19, 22, 40, 99, 41, 32, 50, 48, 48, 56, 32, 69, 110, 116, 114, 117, 115, 116, 44, 32, 73, 110, 99, 46, 49, 46, 48, 44, 6, 3, 85, 4, 3, 19, 37, 69, 110, 116, 114, 117, 115, 116, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 32, 45, 32, 76, 49, 66, 48, 30, 23, 13, 48, 57, 48, 52, 50, 57, 49, 53, 50, 54, 53, 57, 90, 23, 13, 49, 49, 48, 53, 48, 53, 49, 53, 53, 54, 53, 55, 90, 48, 120, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 15, 48, 13, 6, 3, 85, 4, 8, 19, 6, 75, 65, 78, 83, 65, 83, 49, 22, 48, 20, 6, 3, 85, 4, 7, 19, 13, 79, 118, 101, 114, 108, 97, 110, 100, 32, 80, 97, 114, 107, 49, 15, 48, 13, 6, 3, 85, 4, 10, 19, 6, 83, 112, 114, 105, 110, 116, 49, 18, 48, 16, 6, 3, 85, 4, 11, 19, 9, 100, 97, 115, 110, 109, 112, 48, 52, 98, 49, 27, 48, 25, 6, 3, 85, 4, 3, 19, 18, 115, 101, 114, 118, 105, 99, 101, 46, 115, 112, 114, 105, 110, 116, 46, 99, 111, 109, 48, -127, -97, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 1, 5, 0, 3, -127, -115, 0, 48, -127, -119, 2, -127, -127, 0, -80, 99, 109, 108, 94, -41, -78, 88, 56, -97, 33, -23, 65, -74, -118, 0, 1, 119, 126, 122, -59, -83, -25, -16, -75, -87, 100, 46, 37, -98, 65, -104, 54, -87, 56, -81, 96, -38, -4, -78, 11, 101, -29, 70, -13, -110, -76, -125, -106, -35, 41, 83, 71, 56, 6, 67, -8, 82, -58, -81, -113, 90, 91, 79, 74, -38, 34, 28, 39, -37, -12, 54, 87, 61, 48, 33, -16, 10, 112, -40, -37, -15, 59, -72, 112, 96, 85, 109, 123, -122, 58, 18, 95, 56, -81, 49, 43, -39, 99, 69, -28, -81, -106, -64, 8, -62, 40, -92, 95, -109, -122, 94, 53, -13, -33, 88, -104, 3, -77, -30, -27, 23, 92, -69, 12, -23, -9, 125, 2, 3, 1, 0, 1, -93, -126, 2, -81, 48, -126, 2, -85, 48, 11, 6, 3, 85, 29, 15, 4, 4, 3, 2, 5, -96, 48, 43, 6, 3, 85, 29, 16, 4, 36, 48, 34, -128, 15, 50, 48, 48, 57, 48, 52, 50, 57, 49, 53, 50, 54, 53, 57, 90, -127, 15, 50, 48, 49, 49, 48, 53, 48, 53, 49, 53, 53, 54, 53, 55, 90, 48, 19, 6, 3, 85, 29, 37, 4, 12, 48, 10, 6, 8, 43, 6, 1, 5, 5, 7, 3, 1, 48, 51, 6, 3, 85, 29, 31, 4, 44, 48, 42, 48, 40, -96, 38, -96, 36, -122, 34, 104, 116, 116, 112, 58, 47, 47, 99, 114, 108, 46, 101, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 47, 108, 101, 118, 101, 108, 49, 98, 46, 99, 114, 108, 48, 100, 6, 8, 43, 6, 1, 5, 5, 7, 1, 1, 4, 88, 48, 86, 48, 35, 6, 8, 43, 6, 1, 5, 5, 7, 48, 1, -122, 23, 104, 116, 116, 112, 58, 47, 47, 111, 99, 115, 112, 46, 101, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 48, 47, 6, 8, 43, 6, 1, 5, 5, 7, 48, 2, -122, 35, 104, 116, 116, 112, 58, 47, 47, 97, 105, 97, 46, 101, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 47, 50, 48, 52, 56, 45, 108, 49, 98, 46, 99, 101, 114, 48, -126, 1, 87, 6, 3, 85, 29, 32, 4, -126, 1, 78, 48, -126, 1, 74, 48, -126, 1, 70, 6, 9, 42, -122, 72, -122, -10, 125, 7, 75, 2, 48, -126, 1, 55, 48, 38, 6, 8, 43, 6, 1, 5, 5, 7, 2, 1, 22, 26, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 101, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 47, 99, 112, 115, 48, -126, 1, 11, 6, 8, 43, 6, 1, 5, 5, 7, 2, 2, 48, -127, -2, 26, -127, -5, 84, 104, 101, 32, 69, 110, 116, 114, 117, 115, 116, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 80, 114, 97, 99, 116, 105, 99, 101, 32, 83, 116, 97, 116, 101, 109, 101, 110, 116, 32, 40, 67, 80, 83, 41, 32, 97, 118, 97, 105, 108, 97, 98, 108, 101, 32, 97, 116, 32, 119, 119, 119, 46, 101, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 47, 99, 112, 115, 32, 32, 105, 115, 32, 104, 101, 114, 101, 98, 121, 32, 105, 110, 99, 111, 114, 112, 111, 114, 97, 116, 101, 100, 32, 105, 110, 116, 111, 32, 121, 111, 117, 114, 32, 117, 115, 101, 32, 111, 114, 32, 114, 101, 108, 105, 97, 110, 99, 101, 32, 111, 110, 32, 116, 104, 105, 115, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 46, 32, 32, 84, 104, 105, 115, 32, 67, 80, 83, 32, 99, 111, 110, 116, 97, 105, 110, 115, 32, 108, 105, 109, 105, 116, 97, 116, 105, 111, 110, 115, 32, 111, 110, 32, 119, 97, 114, 114, 97, 110, 116, 105, 101, 115, 32, 97, 110, 100, 32, 108, 105, 97, 98, 105, 108, 105, 116, 105, 101, 115, 46, 32, 67, 111, 112, 121, 114, 105, 103, 104, 116, 32, 40, 99, 41, 32, 50, 48, 48, 56, 32, 69, 110, 116, 114, 117, 115, 116, 32, 76, 105, 109, 105, 116, 101, 100, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, -128, 20, -11, -14, -106, -120, 125, 13, -13, 42, -7, 78, -25, 52, -96, -67, 70, 126, 19, -42, 22, -56, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 68, 101, 26, -23, -69, -107, 32, 89, 18, 28, -123, 32, 74, -116, -33, -48, 70, -52, 68, 77, 48, 9, 6, 3, 85, 29, 19, 4, 2, 48, 0, 48, 25, 6, 9, 42, -122, 72, -122, -10, 125, 7, 65, 0, 4, 12, 48, 10, 27, 4, 86, 55, 46, 49, 3, 2, 3, 40, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 5, 5, 0, 3, -126, 1, 1, 0, 18, 56, 92, -74, -100, -56, 95, 121, 27, -84, -88, -104, -27, -98, -12, 58, 48, -26, 40, -7, 25, -68, -124, -104, -54, -121, 84, 52, 3, 22, -106, 88, 44, -39, 126, 17, 96, 4, -41, -84, -101, 74, -92, -113, -12, -99, 77, 108, -30, 38, 19, 78, 48, 32, -126, 95, -10, -114, 58, 98, -49, -108, -109, -87, 5, -80, -43, 121, 21, -99, 43, -73, 26, 51, 31, 87, -38, -119, 78, -113, -59, -100, -118, -84, -46, -48, 93, 99, 2, 40, -39, 76, -48, -122, -60, -25, -73, 103, 126, 83, -86, -26, 66, 122, -65, -89, -102, 115, 105, -124, -85, -18, -66, 85, 30, -29, -96, 104, 65, -66, 40, 69, -91, 101, -19, 39, -86, -21, -18, 39, 51, -1, 36, -52, 53, -65, 53, 12, -62, -97, -45, -26, 113, -20, 102, 56, 102, 104, 37, 17, 57, -96, -83, -71, 106, 63, -64, -122, 61, 59, 8, -123, 108, 22, 62, -58, -105, 88, 38, 96, -6, -29, -114, 105, 110, -102, -72, 109, -33, 56, 61, 52, 70, -75, -92, 97, -9, -6, -64, 53, -76, 81, -100, 90, -50, 19, -87, 30, -24, -53, 109, -75, 45, -38, 14, 119, -31, 44, -30, -93, -76, 14, 97, -53, -107, 60, 30, -102, 68, 12, 26, 76, -114, 73, -13, -127, 21, 94, -42, 94, 30, -50, -3, 116, 41, -3, -89, 23, -27, -49, -3, -95, 119, -104, -45, 112, 35, 66, 59, 84, 116, 19, -102, -68, -104, 1 },
+            new byte[] { 48, -126, 5, -111, 48, -126, 4, 121, -96, 3, 2, 1, 2, 2, 4, 56, 99, -59, -82, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 5, 5, 0, 48, -127, -76, 49, 20, 48, 18, 6, 3, 85, 4, 10, 19, 11, 69, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 49, 64, 48, 62, 6, 3, 85, 4, 11, 20, 55, 119, 119, 119, 46, 101, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 47, 67, 80, 83, 95, 50, 48, 52, 56, 32, 105, 110, 99, 111, 114, 112, 46, 32, 98, 121, 32, 114, 101, 102, 46, 32, 40, 108, 105, 109, 105, 116, 115, 32, 108, 105, 97, 98, 46, 41, 49, 37, 48, 35, 6, 3, 85, 4, 11, 19, 28, 40, 99, 41, 32, 49, 57, 57, 57, 32, 69, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 32, 76, 105, 109, 105, 116, 101, 100, 49, 51, 48, 49, 6, 3, 85, 4, 3, 19, 42, 69, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 32, 40, 50, 48, 52, 56, 41, 48, 30, 23, 13, 48, 56, 48, 56, 50, 53, 49, 56, 49, 52, 50, 54, 90, 23, 13, 49, 56, 48, 56, 50, 53, 49, 56, 52, 52, 50, 54, 90, 48, -126, 1, 52, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 85, 83, 49, 22, 48, 20, 6, 3, 85, 4, 10, 19, 13, 69, 110, 116, 114, 117, 115, 116, 44, 32, 73, 110, 99, 46, 49, 56, 48, 54, 6, 3, 85, 4, 11, 19, 47, 65, 78, 68, 32, 65, 68, 68, 73, 84, 73, 79, 78, 65, 76, 32, 84, 69, 82, 77, 83, 32, 71, 79, 86, 69, 82, 78, 73, 78, 71, 32, 85, 83, 69, 32, 65, 78, 68, 32, 82, 69, 76, 73, 65, 78, 67, 69, 49, 71, 48, 69, 6, 3, 85, 4, 11, 19, 62, 67, 80, 83, 32, 67, 79, 78, 84, 65, 73, 78, 83, 32, 73, 77, 80, 79, 82, 84, 65, 78, 84, 32, 76, 73, 77, 73, 84, 65, 84, 73, 79, 78, 83, 32, 79, 70, 32, 87, 65, 82, 82, 65, 78, 84, 73, 69, 83, 32, 65, 78, 68, 32, 76, 73, 65, 66, 73, 76, 73, 84, 89, 49, 57, 48, 55, 6, 3, 85, 4, 11, 19, 48, 119, 119, 119, 46, 101, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 47, 67, 80, 83, 32, 105, 115, 32, 105, 110, 99, 111, 114, 112, 111, 114, 97, 116, 101, 100, 32, 98, 121, 32, 114, 101, 102, 101, 114, 101, 110, 99, 101, 49, 31, 48, 29, 6, 3, 85, 4, 11, 19, 22, 40, 99, 41, 32, 50, 48, 48, 56, 32, 69, 110, 116, 114, 117, 115, 116, 44, 32, 73, 110, 99, 46, 49, 46, 48, 44, 6, 3, 85, 4, 3, 19, 37, 69, 110, 116, 114, 117, 115, 116, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 32, 45, 32, 76, 49, 66, 48, -126, 1, 34, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 1, 5, 0, 3, -126, 1, 15, 0, 48, -126, 1, 10, 2, -126, 1, 1, 0, -36, 33, -11, 104, -7, 122, -50, -121, -14, 120, -33, -40, 59, 77, 6, 125, -58, 36, -28, -87, -51, -99, 1, 86, -28, -10, 113, 23, -86, 127, 117, 34, 24, -28, 116, 109, 27, 62, 86, -43, -79, -90, 30, -35, 89, 38, 83, -54, 6, -26, -70, 11, 111, 55, -69, -88, -58, -100, 21, 59, 6, 27, -121, 12, -62, 26, 77, -45, -127, -82, -37, 80, 101, -91, 58, 100, 79, 48, 52, -102, 43, -87, 31, -3, 43, -47, 56, 113, 25, 104, -14, -114, -21, 123, -55, 64, 60, 72, -60, 25, -79, -73, 16, 37, -17, 68, -89, -26, 119, -101, 125, 34, -102, -34, -40, 94, -39, -61, -50, -55, 113, 34, -69, -82, -17, 5, -42, -14, 23, -25, 86, 120, -31, 83, 5, 74, 38, 115, -72, -57, 73, 103, -109, 35, 15, 86, -78, -113, -35, -55, 89, 5, -27, 99, 21, -76, -121, 126, 64, 70, -23, -75, 0, 123, 3, -76, 13, -28, -106, 103, 44, -34, 27, 89, 11, 26, 31, -72, 99, 68, -82, -63, -41, 68, -121, -60, -111, 89, -100, 0, 67, 109, -58, -33, 10, -80, -79, 4, -51, -2, -66, 48, 94, 58, 37, 114, -35, -94, 62, -19, 70, 58, -57, -92, 92, 92, -28, 37, -14, 19, 7, -24, -82, -38, -101, 25, -101, -94, -39, 96, -99, -50, -112, 71, 106, 97, 123, 64, -24, 20, -62, -2, 47, -124, 90, 102, 23, -64, -105, -45, 73, 56, -34, 99, 2, -97, 2, 3, 1, 0, 1, -93, -126, 1, 38, 48, -126, 1, 34, 48, 14, 6, 3, 85, 29, 15, 1, 1, -1, 4, 4, 3, 2, 1, 6, 48, 15, 6, 3, 85, 29, 19, 1, 1, -1, 4, 5, 48, 3, 1, 1, -1, 48, 51, 6, 8, 43, 6, 1, 5, 5, 7, 1, 1, 4, 39, 48, 37, 48, 35, 6, 8, 43, 6, 1, 5, 5, 7, 48, 1, -122, 23, 104, 116, 116, 112, 58, 47, 47, 111, 99, 115, 112, 46, 101, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 48, 50, 6, 3, 85, 29, 31, 4, 43, 48, 41, 48, 39, -96, 37, -96, 35, -122, 33, 104, 116, 116, 112, 58, 47, 47, 99, 114, 108, 46, 101, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 47, 50, 48, 52, 56, 99, 97, 46, 99, 114, 108, 48, 59, 6, 3, 85, 29, 32, 4, 52, 48, 50, 48, 48, 6, 4, 85, 29, 32, 0, 48, 40, 48, 38, 6, 8, 43, 6, 1, 5, 5, 7, 2, 1, 22, 26, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 101, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 47, 67, 80, 83, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, -11, -14, -106, -120, 125, 13, -13, 42, -7, 78, -25, 52, -96, -67, 70, 126, 19, -42, 22, -56, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, -128, 20, 85, -28, -127, -47, 17, -128, -66, -40, -119, -71, 8, -93, 49, -7, -95, 36, 9, 22, -71, 112, 48, 25, 6, 9, 42, -122, 72, -122, -10, 125, 7, 65, 0, 4, 12, 48, 10, 27, 4, 86, 55, 46, 49, 3, 2, 0, -127, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 5, 5, 0, 3, -126, 1, 1, 0, 11, 37, 60, 88, -6, -114, -36, -94, 66, 59, 118, 113, 110, 108, -44, 79, 43, -71, 83, 92, -78, 88, -71, -79, -36, 111, 26, -28, -29, -60, 80, -14, 65, -126, -70, -12, 125, -57, -63, -7, -6, -116, 83, -65, -71, 98, -73, 73, -29, 29, 10, -4, 31, -42, -60, 118, 106, -109, -53, 119, 30, 44, 127, -48, 63, 22, 99, 76, 114, 76, 103, 96, 15, -8, -128, -42, -89, -102, -54, -94, 51, -111, 15, 68, -78, 102, 61, -114, 104, 12, 64, -123, 18, 55, -111, -71, -126, 119, 52, 89, 45, 92, -33, -126, 110, 44, -74, 122, -46, 4, -112, 103, 104, 75, 112, -4, 45, -72, -1, -112, 100, 111, 126, -111, -9, -47, 71, 51, -13, 91, -72, 88, 46, 33, -40, 117, 96, 27, 19, -52, -8, -78, -88, -6, 106, -87, 42, 90, 79, 69, -123, 64, -76, -35, 52, 5, -73, 112, -54, 1, -17, -31, -127, -25, 17, 80, -37, 62, -30, -41, 16, 46, 106, 21, 127, -73, -44, -93, 98, -78, -119, 105, 97, 87, -58, 127, -114, -98, -44, 36, 122, -13, -95, 67, 95, -96, 122, -119, -36, 89, -51, 125, -41, 117, -89, -68, 83, -43, 71, 53, -58, 49, 48, 32, -97, -101, -70, -75, -125, -26, -119, 85, 1, 77, -111, 59, -42, -119, 53, -121, 60, -125, 107, 122, 41, -126, -44, 75, -44, -26, 22, 116, -80, 1, 16, -85, 105, 6, 20, 55, 123, -9, 102, 48, 58, -59 },
+            new byte[] { 48, -126, 4, 92, 48, -126, 3, 68, -96, 3, 2, 1, 2, 2, 4, 56, 99, -71, 102, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 5, 5, 0, 48, -127, -76, 49, 20, 48, 18, 6, 3, 85, 4, 10, 19, 11, 69, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 49, 64, 48, 62, 6, 3, 85, 4, 11, 20, 55, 119, 119, 119, 46, 101, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 47, 67, 80, 83, 95, 50, 48, 52, 56, 32, 105, 110, 99, 111, 114, 112, 46, 32, 98, 121, 32, 114, 101, 102, 46, 32, 40, 108, 105, 109, 105, 116, 115, 32, 108, 105, 97, 98, 46, 41, 49, 37, 48, 35, 6, 3, 85, 4, 11, 19, 28, 40, 99, 41, 32, 49, 57, 57, 57, 32, 69, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 32, 76, 105, 109, 105, 116, 101, 100, 49, 51, 48, 49, 6, 3, 85, 4, 3, 19, 42, 69, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 32, 40, 50, 48, 52, 56, 41, 48, 30, 23, 13, 57, 57, 49, 50, 50, 52, 49, 55, 53, 48, 53, 49, 90, 23, 13, 49, 57, 49, 50, 50, 52, 49, 56, 50, 48, 53, 49, 90, 48, -127, -76, 49, 20, 48, 18, 6, 3, 85, 4, 10, 19, 11, 69, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 49, 64, 48, 62, 6, 3, 85, 4, 11, 20, 55, 119, 119, 119, 46, 101, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 47, 67, 80, 83, 95, 50, 48, 52, 56, 32, 105, 110, 99, 111, 114, 112, 46, 32, 98, 121, 32, 114, 101, 102, 46, 32, 40, 108, 105, 109, 105, 116, 115, 32, 108, 105, 97, 98, 46, 41, 49, 37, 48, 35, 6, 3, 85, 4, 11, 19, 28, 40, 99, 41, 32, 49, 57, 57, 57, 32, 69, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 32, 76, 105, 109, 105, 116, 101, 100, 49, 51, 48, 49, 6, 3, 85, 4, 3, 19, 42, 69, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 32, 40, 50, 48, 52, 56, 41, 48, -126, 1, 34, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 1, 5, 0, 3, -126, 1, 15, 0, 48, -126, 1, 10, 2, -126, 1, 1, 0, -83, 77, 75, -87, 18, -122, -78, -22, -93, 32, 7, 21, 22, 100, 42, 43, 75, -47, -65, 11, 74, 77, -114, -19, -128, 118, -91, 103, -73, 120, 64, -64, 115, 66, -56, 104, -64, -37, 83, 43, -35, 94, -72, 118, -104, 53, -109, -117, 26, -99, 124, 19, 58, 14, 31, 91, -73, 30, -49, -27, 36, 20, 30, -79, -127, -87, -115, 125, -72, -52, 107, 75, 3, -15, 2, 12, -36, -85, -91, 64, 36, 0, 127, 116, -108, -95, -99, 8, 41, -77, -120, 11, -11, -121, 119, -99, 85, -51, -28, -61, 126, -41, 106, 100, -85, -123, 20, -122, -107, 91, -105, 50, 80, 111, 61, -56, -70, 102, 12, -29, -4, -67, -72, 73, -63, 118, -119, 73, 25, -3, -64, -88, -67, -119, -93, 103, 47, -58, -97, -68, 113, 25, 96, -72, 45, -23, 44, -55, -112, 118, 102, 123, -108, -30, -81, 120, -42, 101, 83, 93, 60, -42, -100, -78, -49, 41, 3, -7, 47, -92, 80, -78, -44, 72, -50, 5, 50, 85, -118, -3, -78, 100, 76, 14, -28, -104, 7, 117, -37, 127, -33, -71, 8, 85, 96, -123, 48, 41, -7, 123, 72, -92, 105, -122, -29, 53, 63, 30, -122, 93, 122, 122, 21, -67, -17, 0, -114, 21, 34, 84, 23, 0, -112, 38, -109, -68, 14, 73, 104, -111, -65, -8, 71, -45, -99, -107, 66, -63, 14, 77, -33, 111, 38, -49, -61, 24, 33, 98, 102, 67, 112, -42, -43, -64, 7, -31, 2, 3, 1, 0, 1, -93, 116, 48, 114, 48, 17, 6, 9, 96, -122, 72, 1, -122, -8, 66, 1, 1, 4, 4, 3, 2, 0, 7, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, -128, 20, 85, -28, -127, -47, 17, -128, -66, -40, -119, -71, 8, -93, 49, -7, -95, 36, 9, 22, -71, 112, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 85, -28, -127, -47, 17, -128, -66, -40, -119, -71, 8, -93, 49, -7, -95, 36, 9, 22, -71, 112, 48, 29, 6, 9, 42, -122, 72, -122, -10, 125, 7, 65, 0, 4, 16, 48, 14, 27, 8, 86, 53, 46, 48, 58, 52, 46, 48, 3, 2, 4, -112, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 5, 5, 0, 3, -126, 1, 1, 0, 89, 71, -84, 33, -124, -118, 23, -55, -100, -119, 83, 30, -70, -128, -123, 26, -58, 60, 78, 62, -79, -100, -74, 124, -58, -110, 93, 24, 100, 2, -29, -45, 6, 8, 17, 97, 124, 99, -29, 43, -99, 49, 3, 112, 118, -46, -93, 40, -96, -12, -69, -102, 99, 115, -19, 109, -27, 42, -37, -19, 20, -87, 43, -58, 54, 17, -48, 43, -21, 7, -117, -91, -38, -98, 92, 25, -99, 86, 18, -11, 84, 41, -56, 5, -19, -78, 18, 42, -115, -12, 3, 27, -1, -25, -110, 16, -121, -80, 58, -75, -61, -99, 5, 55, 18, -93, -57, -12, 21, -71, -43, -92, 57, 22, -101, 83, 58, 35, -111, -15, -88, -126, -94, 106, -120, 104, -63, 121, 2, 34, -68, -86, -90, -42, -82, -33, -80, 20, 95, -72, -121, -48, -35, 124, 127, 123, -1, -81, 28, -49, -26, -37, 7, -83, 94, -37, -123, -99, -48, 43, 13, 51, -37, 4, -47, -26, 73, 64, 19, 43, 118, -5, 62, -23, -100, -119, 15, 21, -50, 24, -80, -123, 120, 33, 79, 107, 79, 14, -6, 54, 103, -51, 7, -14, -1, 8, -48, -30, -34, -39, -65, 42, -81, -72, -121, -122, 33, 60, 4, -54, -73, -108, 104, 127, -49, 60, -23, -104, -41, 56, -1, -20, -64, -39, 80, -16, 46, 75, 88, -82, 70, 111, -48, 46, -61, 96, -38, 114, 85, 114, -67, 76, 69, -98, 97, -70, -65, -124, -127, -110, 3, -47, -46, 105, 124, -59 },
+    };
+
+    /**
+     * ASN1-encoded trusted certificate #946059622 for Entrust.net. This
+     * certificate uses the TELETEX encoding for its X509 name.
+     */
+    private final byte[] trustedCert = new byte[] { 48, -126, 4, 92, 48, -126, 3, 68, -96, 3, 2, 1, 2, 2, 4, 56, 99, -71, 102, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 5, 5, 0, 48, -127, -76, 49, 20, 48, 18, 6, 3, 85, 4, 10, 19, 11, 69, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 49, 64, 48, 62, 6, 3, 85, 4, 11, 20, 55, 119, 119, 119, 46, 101, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 47, 67, 80, 83, 95, 50, 48, 52, 56, 32, 105, 110, 99, 111, 114, 112, 46, 32, 98, 121, 32, 114, 101, 102, 46, 32, 40, 108, 105, 109, 105, 116, 115, 32, 108, 105, 97, 98, 46, 41, 49, 37, 48, 35, 6, 3, 85, 4, 11, 19, 28, 40, 99, 41, 32, 49, 57, 57, 57, 32, 69, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 32, 76, 105, 109, 105, 116, 101, 100, 49, 51, 48, 49, 6, 3, 85, 4, 3, 19, 42, 69, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 32, 40, 50, 48, 52, 56, 41, 48, 30, 23, 13, 57, 57, 49, 50, 50, 52, 49, 55, 53, 48, 53, 49, 90, 23, 13, 49, 57, 49, 50, 50, 52, 49, 56, 50, 48, 53, 49, 90, 48, -127, -76, 49, 20, 48, 18, 6, 3, 85, 4, 10, 19, 11, 69, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 49, 64, 48, 62, 6, 3, 85, 4, 11, 20, 55, 119, 119, 119, 46, 101, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 47, 67, 80, 83, 95, 50, 48, 52, 56, 32, 105, 110, 99, 111, 114, 112, 46, 32, 98, 121, 32, 114, 101, 102, 46, 32, 40, 108, 105, 109, 105, 116, 115, 32, 108, 105, 97, 98, 46, 41, 49, 37, 48, 35, 6, 3, 85, 4, 11, 19, 28, 40, 99, 41, 32, 49, 57, 57, 57, 32, 69, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 32, 76, 105, 109, 105, 116, 101, 100, 49, 51, 48, 49, 6, 3, 85, 4, 3, 19, 42, 69, 110, 116, 114, 117, 115, 116, 46, 110, 101, 116, 32, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 32, 65, 117, 116, 104, 111, 114, 105, 116, 121, 32, 40, 50, 48, 52, 56, 41, 48, -126, 1, 34, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 1, 5, 0, 3, -126, 1, 15, 0, 48, -126, 1, 10, 2, -126, 1, 1, 0, -83, 77, 75, -87, 18, -122, -78, -22, -93, 32, 7, 21, 22, 100, 42, 43, 75, -47, -65, 11, 74, 77, -114, -19, -128, 118, -91, 103, -73, 120, 64, -64, 115, 66, -56, 104, -64, -37, 83, 43, -35, 94, -72, 118, -104, 53, -109, -117, 26, -99, 124, 19, 58, 14, 31, 91, -73, 30, -49, -27, 36, 20, 30, -79, -127, -87, -115, 125, -72, -52, 107, 75, 3, -15, 2, 12, -36, -85, -91, 64, 36, 0, 127, 116, -108, -95, -99, 8, 41, -77, -120, 11, -11, -121, 119, -99, 85, -51, -28, -61, 126, -41, 106, 100, -85, -123, 20, -122, -107, 91, -105, 50, 80, 111, 61, -56, -70, 102, 12, -29, -4, -67, -72, 73, -63, 118, -119, 73, 25, -3, -64, -88, -67, -119, -93, 103, 47, -58, -97, -68, 113, 25, 96, -72, 45, -23, 44, -55, -112, 118, 102, 123, -108, -30, -81, 120, -42, 101, 83, 93, 60, -42, -100, -78, -49, 41, 3, -7, 47, -92, 80, -78, -44, 72, -50, 5, 50, 85, -118, -3, -78, 100, 76, 14, -28, -104, 7, 117, -37, 127, -33, -71, 8, 85, 96, -123, 48, 41, -7, 123, 72, -92, 105, -122, -29, 53, 63, 30, -122, 93, 122, 122, 21, -67, -17, 0, -114, 21, 34, 84, 23, 0, -112, 38, -109, -68, 14, 73, 104, -111, -65, -8, 71, -45, -99, -107, 66, -63, 14, 77, -33, 111, 38, -49, -61, 24, 33, 98, 102, 67, 112, -42, -43, -64, 7, -31, 2, 3, 1, 0, 1, -93, 116, 48, 114, 48, 17, 6, 9, 96, -122, 72, 1, -122, -8, 66, 1, 1, 4, 4, 3, 2, 0, 7, 48, 31, 6, 3, 85, 29, 35, 4, 24, 48, 22, -128, 20, 85, -28, -127, -47, 17, -128, -66, -40, -119, -71, 8, -93, 49, -7, -95, 36, 9, 22, -71, 112, 48, 29, 6, 3, 85, 29, 14, 4, 22, 4, 20, 85, -28, -127, -47, 17, -128, -66, -40, -119, -71, 8, -93, 49, -7, -95, 36, 9, 22, -71, 112, 48, 29, 6, 9, 42, -122, 72, -122, -10, 125, 7, 65, 0, 4, 16, 48, 14, 27, 8, 86, 53, 46, 48, 58, 52, 46, 48, 3, 2, 4, -112, 48, 13, 6, 9, 42, -122, 72, -122, -9, 13, 1, 1, 5, 5, 0, 3, -126, 1, 1, 0, 89, 71, -84, 33, -124, -118, 23, -55, -100, -119, 83, 30, -70, -128, -123, 26, -58, 60, 78, 62, -79, -100, -74, 124, -58, -110, 93, 24, 100, 2, -29, -45, 6, 8, 17, 97, 124, 99, -29, 43, -99, 49, 3, 112, 118, -46, -93, 40, -96, -12, -69, -102, 99, 115, -19, 109, -27, 42, -37, -19, 20, -87, 43, -58, 54, 17, -48, 43, -21, 7, -117, -91, -38, -98, 92, 25, -99, 86, 18, -11, 84, 41, -56, 5, -19, -78, 18, 42, -115, -12, 3, 27, -1, -25, -110, 16, -121, -80, 58, -75, -61, -99, 5, 55, 18, -93, -57, -12, 21, -71, -43, -92, 57, 22, -101, 83, 58, 35, -111, -15, -88, -126, -94, 106, -120, 104, -63, 121, 2, 34, -68, -86, -90, -42, -82, -33, -80, 20, 95, -72, -121, -48, -35, 124, 127, 123, -1, -81, 28, -49, -26, -37, 7, -83, 94, -37, -123, -99, -48, 43, 13, 51, -37, 4, -47, -26, 73, 64, 19, 43, 118, -5, 62, -23, -100, -119, 15, 21, -50, 24, -80, -123, 120, 33, 79, 107, 79, 14, -6, 54, 103, -51, 7, -14, -1, 8, -48, -30, -34, -39, -65, 42, -81, -72, -121, -122, 33, 60, 4, -54, -73, -108, 104, 127, -49, 60, -23, -104, -41, 56, -1, -20, -64, -39, 80, -16, 46, 75, 88, -82, 70, 111, -48, 46, -61, 96, -38, 114, 85, 114, -67, 76, 69, -98, 97, -70, -65, -124, -127, -110, 3, -47, -46, 105, 124, -59 };
+
+    public void testTrustAndRemoteCertificatesWithDifferentEncodings()
+            throws IOException, CertificateException, KeyStoreException,
+            InvalidAlgorithmParameterException, CertPathValidatorException {
+
+        X509CertPathImpl certPath = new X509CertPathImpl(Arrays.asList(
+                new X509CertImpl(serviceSprintComCertChain[0]),
+                new X509CertImpl(serviceSprintComCertChain[1]),
+                new X509CertImpl(serviceSprintComCertChain[2])));
+
+        Set<TrustAnchor> trustAnchors = new HashSet<TrustAnchor>();
+        trustAnchors.add(new TrustAnchor(new X509CertificateObject(
+                new X509CertificateStructure(
+                        (ASN1Sequence) new ASN1InputStream(trustedCert).readObject())), null));
+
+        IndexedPKIXParameters indexedPKIXParameters = new IndexedPKIXParameters(trustAnchors);
+        indexedPKIXParameters.setRevocationEnabled(false);
+
+        new PKIXCertPathValidatorSpi().engineValidate(certPath, indexedPKIXParameters);
+        // completing normally indicates that the certificate was valid
+    }
+}
diff --git a/libcore/security/src/test/java/tests/security/AllTests.java b/libcore/security/src/test/java/tests/security/AllTests.java
index 2a69b59..a88cc0e 100644
--- a/libcore/security/src/test/java/tests/security/AllTests.java
+++ b/libcore/security/src/test/java/tests/security/AllTests.java
@@ -32,6 +32,7 @@
         TestSuite suite = tests.TestSuiteFactory.createTestSuite("All security test suites");
         // $JUnit-BEGIN$
         suite.addTest(org.apache.harmony.security.tests.java.security.AllTests.suite());
+        suite.addTest(org.bouncycastle.jce.provider.AllTests.suite());
         suite.addTest(tests.api.java.security.AllTests.suite());
         suite.addTest(tests.java.security.AllTests.suite());
     
diff --git a/libcore/sql/src/main/java/java/sql/Array.java b/libcore/sql/src/main/java/java/sql/Array.java
index 6113c46..fc9debe 100644
--- a/libcore/sql/src/main/java/java/sql/Array.java
+++ b/libcore/sql/src/main/java/java/sql/Array.java
@@ -21,8 +21,6 @@
 
 /**
  * A Java representation of the SQL {@code ARRAY} type.
- *  
- * @since Android 1.0
  */
 public interface Array {
 
@@ -33,7 +31,6 @@
      * @return A Java array containing the elements of this Array
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public Object getArray() throws SQLException;
 
@@ -50,7 +47,6 @@
      * @return A Java array containing the desired set of elements from this Array
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public Object getArray(long index, int count) throws SQLException;
 
@@ -70,7 +66,6 @@
      * @return A Java array containing the desired set of elements from this Array
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public Object getArray(long index, int count, Map<String, Class<?>> map)
             throws SQLException;
@@ -84,7 +79,6 @@
      * @return A Java array containing the elements of this array
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public Object getArray(Map<String, Class<?>> map) throws SQLException;
 
@@ -95,7 +89,6 @@
      * @return An integer constant from the {@code java.sql.Types} class
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public int getBaseType() throws SQLException;
 
@@ -106,7 +99,6 @@
      * @return The database specific name or a fully-qualified SQL type name.
      * @throws SQLException
      *              if there is a database error.
-     * @since Android 1.0
      */
     public String getBaseTypeName() throws SQLException;
 
@@ -117,7 +109,6 @@
      * @return the elements of the array as a {@code ResultSet}.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public ResultSet getResultSet() throws SQLException;
 
@@ -134,7 +125,6 @@
      * @return the elements of the array as a {@code ResultSet}.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public ResultSet getResultSet(long index, int count) throws SQLException;
 
@@ -155,7 +145,6 @@
      *         database error has occurred.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public ResultSet getResultSet(long index, int count,
             Map<String, Class<?>> map) throws SQLException;
@@ -170,7 +159,6 @@
      * @return the array as a {@code ResultSet}.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public ResultSet getResultSet(Map<String, Class<?>> map)
             throws SQLException;
diff --git a/libcore/sql/src/main/java/java/sql/BatchUpdateException.java b/libcore/sql/src/main/java/java/sql/BatchUpdateException.java
index 36a7ef9..0a616db 100644
--- a/libcore/sql/src/main/java/java/sql/BatchUpdateException.java
+++ b/libcore/sql/src/main/java/java/sql/BatchUpdateException.java
@@ -26,7 +26,7 @@
  * problem that occurred, compared with a standard {@code SQLException}. It
  * supplies update counts for successful commands which were executed before the
  * exception was encountered.
- * </p>
+ * <p>
  * The element order in the array of update counts matches the order that the
  * commands were added to the batch operation.
  * <p>
@@ -37,9 +37,6 @@
  * for every command in the batch, not only those that executed successfully. In
  * this case, the array element for any command which encountered a problem is
  * set to {@code Statement.EXECUTE_FAILED}.
- * </p>
- * 
- * @since Android 1.0
  */
 public class BatchUpdateException extends SQLException implements Serializable {
 
@@ -51,8 +48,6 @@
      * Creates a default {@code BatchUpdateException} with the parameters
      * <i>reason</i>, <i>SQLState</i>, and <i>update counts</i> set to {@code
      * null} and the <i>vendor code</i> set to 0.
-     * 
-     * @since Android 1.0
      */
     public BatchUpdateException() {
         super();
@@ -67,7 +62,6 @@
      *            the array of {@code updateCounts} giving the number of
      *            successful updates (or another status code) for each command
      *            in the batch that was attempted.
-     * @since Android 1.0
      */
     public BatchUpdateException(int[] updateCounts) {
         super();
@@ -86,7 +80,6 @@
      *            the array of {@code updateCounts} giving the number of
      *            successful updates (or another status code) for each command
      *            in the batch that was attempted.
-     * @since Android 1.0
      */
     public BatchUpdateException(String reason, int[] updateCounts) {
         super(reason);
@@ -107,7 +100,6 @@
      *            the array of {@code updateCounts} giving the number of
      *            successful updates (or another status code) for each command
      *            in the batch that was attempted.
-     * @since Android 1.0
      */
     public BatchUpdateException(String reason, String SQLState,
             int[] updateCounts) {
@@ -130,7 +122,6 @@
      *            the array of {@code updateCounts} giving the number of
      *            successful updates (or another status code) for each command
      *            in the batch that was attempted.
-     * @since Android 1.0
      */
     public BatchUpdateException(String reason, String SQLState, int vendorCode,
             int[] updateCounts) {
@@ -162,7 +153,6 @@
      *         <li>{@code Statement.EXECUTE_FAILED} indicating that the command
      *         was unsuccessful.</li>
      *         </ol>
-     * @since Android 1.0
      */
     public int[] getUpdateCounts() {
         return updateCounts;
diff --git a/libcore/sql/src/main/java/java/sql/Blob.java b/libcore/sql/src/main/java/java/sql/Blob.java
index e6d9b19..0074b98 100644
--- a/libcore/sql/src/main/java/java/sql/Blob.java
+++ b/libcore/sql/src/main/java/java/sql/Blob.java
@@ -25,12 +25,10 @@
  * <p>
  * An SQL {@code BLOB} type stores a large array of binary data (bytes) as the
  * value in a column of a database.
- * </p>
+ * <p>
  * The {@code java.sql.Blob} interface provides methods for setting and
  * retrieving data in the {@code Blob}, for querying {@code Blob} data length,
  * and for searching for data within the {@code Blob}.
- *  
- * @since Android 1.0
  */
 public interface Blob {
 
@@ -41,7 +39,6 @@
      *         data.
      * @throws SQLException
      *             if an error occurs accessing the {@code Blob}.
-     * @since Android 1.0
      */
     public InputStream getBinaryStream() throws SQLException;
 
@@ -57,7 +54,6 @@
      *         at {@code pos} and is up to {@code length} bytes long.
      * @throws SQLException
      *             if an error occurs accessing the {@code Blob}.
-     * @since Android 1.0
      */
     public byte[] getBytes(long pos, int length) throws SQLException;
 
@@ -68,7 +64,6 @@
      *         bytes.
      * @throws SQLException
      *             if an error occurs accessing the {@code Blob}.
-     * @since Android 1.0
      */
     public long length() throws SQLException;
 
@@ -87,7 +82,6 @@
      *         {@code Blob}.
      * @throws SQLException
      *             if an error occurs accessing the {@code Blob}.
-     * @since Android 1.0
      */
     public long position(Blob pattern, long start) throws SQLException;
 
@@ -106,7 +100,6 @@
      *         {@code Blob}.
      * @throws SQLException
      *             if an error occurs accessing the {@code Blob}.
-     * @since Android 1.0
      */
     public long position(byte[] pattern, long start) throws SQLException;
 
@@ -121,7 +114,6 @@
      *         the {@code Blob} starting at the specified position.
      * @throws SQLException
      *             if an error occurs accessing the {@code Blob}.
-     * @since Android 1.0
      */
     public OutputStream setBinaryStream(long pos) throws SQLException;
 
@@ -139,7 +131,6 @@
      *         Blob}.
      * @throws SQLException
      *             if an error occurs accessing the {@code Blob}.
-     * @since Android 1.0
      */
     public int setBytes(long pos, byte[] theBytes) throws SQLException;
 
@@ -162,7 +153,6 @@
      *         Blob}.
      * @throws SQLException
      *             if an error occurs accessing the {@code Blob}.
-     * @since Android 1.0
      */
     public int setBytes(long pos, byte[] theBytes, int offset, int len)
             throws SQLException;
@@ -176,7 +166,6 @@
      *            is to be truncated.
      * @throws SQLException
      *             if an error occurs accessing the {@code Blob}.
-     * @since Android 1.0
      */
     public void truncate(long len) throws SQLException;
 }
diff --git a/libcore/sql/src/main/java/java/sql/CallableStatement.java b/libcore/sql/src/main/java/java/sql/CallableStatement.java
index 7a90041..be5463b 100644
--- a/libcore/sql/src/main/java/java/sql/CallableStatement.java
+++ b/libcore/sql/src/main/java/java/sql/CallableStatement.java
@@ -36,7 +36,6 @@
  * name or by a numerical index starting at 1.
  * <p>
  * The correct syntax is:
- * </p>
  * <dd>
  * <dl>
  * { ?= call &lt;procedurename&gt; [( [parameter1,parameter2,...] )] }
@@ -44,7 +43,8 @@
  * <dl>
  * { call &lt;procedurename&gt; [( [parameter1,parameter2,...] )] }
  * </dl>
- * </code></dd> </p> {@code IN} parameters are set before calling the procedure,
+ * </code></dd>
+ * {@code IN} parameters are set before calling the procedure,
  * using the setter methods which are inherited from {@code PreparedStatement}.
  * For {@code OUT} parameters, their type must be registered before executing
  * the stored procedure. The values are retrieved using the getter methods
@@ -53,9 +53,6 @@
  * {@code CallableStatement}s can return one or more {@code ResultSets}. In the
  * event that multiple {@code ResultSets} are returned, they are accessed using
  * the methods inherited from the {@code Statement} interface.
- * </p>
- *  
- * @since Android 1.0
  */
 public interface CallableStatement extends PreparedStatement {
 
@@ -69,7 +66,6 @@
      * @return a {@code java.sql.Array} containing the parameter value.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public Array getArray(int parameterIndex) throws SQLException;
 
@@ -82,7 +78,6 @@
      * @return a {@code java.sql.Array} containing the parameter's value.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public Array getArray(String parameterName) throws SQLException;
 
@@ -98,7 +93,6 @@
      *         the parameter in question is an SQL {@code NULL}.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public BigDecimal getBigDecimal(int parameterIndex) throws SQLException;
 
@@ -119,7 +113,6 @@
      *             if a database error occurs.
      * @deprecated Use {@link #getBigDecimal(int)} or
      *             {@link #getBigDecimal(String)}
-     * @since Android 1.0
      */
     @Deprecated
     public BigDecimal getBigDecimal(int parameterIndex, int scale)
@@ -136,7 +129,6 @@
      *         the parameter in question is an SQL {@code NULL}.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public BigDecimal getBigDecimal(String parameterName) throws SQLException;
 
@@ -152,7 +144,6 @@
      *         the parameter in question is an SQL {@code NULL}.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public Blob getBlob(int parameterIndex) throws SQLException;
 
@@ -167,7 +158,6 @@
      *         the parameter in question is an SQL {@code NULL}.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public Blob getBlob(String parameterName) throws SQLException;
 
@@ -181,7 +171,6 @@
      *            is returned if the value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public boolean getBoolean(int parameterIndex) throws SQLException;
 
@@ -195,7 +184,6 @@
      *         {@code false} is returned if the SQL value is {@code NULL}.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public boolean getBoolean(String parameterName) throws SQLException;
 
@@ -210,7 +198,6 @@
      *            {@code 0} is returned if the value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public byte getByte(int parameterIndex) throws SQLException;
 
@@ -224,7 +211,6 @@
      *         {@code 0} is returned if the SQL value is {@code NULL}.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public byte getByte(String parameterName) throws SQLException;
 
@@ -239,7 +225,6 @@
      *         is returned if the value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public byte[] getBytes(int parameterIndex) throws SQLException;
 
@@ -253,7 +238,6 @@
      *         is returned if the value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public byte[] getBytes(String parameterName) throws SQLException;
 
@@ -270,7 +254,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see Clob
-     * @since Android 1.0
      */
     public Clob getClob(int parameterIndex) throws SQLException;
 
@@ -285,7 +268,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see Clob
-     * @since Android 1.0
      */
     public Clob getClob(String parameterName) throws SQLException;
 
@@ -301,7 +283,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see Date
-     * @since Android 1.0
      */
     public Date getDate(int parameterIndex) throws SQLException;
 
@@ -312,8 +293,7 @@
      * The JDBC driver uses the calendar to create the Date using a particular
      * timezone and locale. The default behavior of the driver is to use the Java
      * virtual machine default settings.
-     * </p>
-     * 
+     *
      * @param parameterIndex
      *            the parameter number index, where the first parameter has
      *            index 1.
@@ -324,7 +304,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see Date
-     * @since Android 1.0
      */
     public Date getDate(int parameterIndex, Calendar cal) throws SQLException;
 
@@ -339,7 +318,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see Date
-     * @since Android 1.0
      */
     public Date getDate(String parameterName) throws SQLException;
 
@@ -350,8 +328,7 @@
      * The JDBC driver uses the calendar to create the date using a particular
      * timezone and locale. The default behavior of the driver is to use the Java
      * virtual machine default settings.
-     * </p>
-     * 
+     *
      * @param parameterName
      *            the name of the desired parameter.
      * @param cal
@@ -361,7 +338,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see Date
-     * @since Android 1.0
      */
     public Date getDate(String parameterName, Calendar cal) throws SQLException;
 
@@ -376,7 +352,6 @@
      *         is returned if the value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public double getDouble(int parameterIndex) throws SQLException;
 
@@ -390,7 +365,6 @@
      *         is returned if the value is SQL {@code NULL}.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public double getDouble(String parameterName) throws SQLException;
 
@@ -405,7 +379,6 @@
      *         is returned if the value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public float getFloat(int parameterIndex) throws SQLException;
 
@@ -419,7 +392,6 @@
      *         is returned if the value is SQL {@code NULL}.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public float getFloat(String parameterName) throws SQLException;
 
@@ -434,7 +406,6 @@
      *         is returned if the value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public int getInt(int parameterIndex) throws SQLException;
 
@@ -448,7 +419,6 @@
      *         is returned if the value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public int getInt(String parameterName) throws SQLException;
 
@@ -463,7 +433,6 @@
      *         is returned if the value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public long getLong(int parameterIndex) throws SQLException;
 
@@ -477,7 +446,6 @@
      *         is returned if the value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public long getLong(String parameterName) throws SQLException;
 
@@ -488,15 +456,13 @@
      * with a {@code registerOutParameter} call. If a parameter was registered
      * as a {@code java.sql.Types.OTHER} then it may hold abstract types that
      * are particular to the connected database.
-     * </p>
-     * 
+     *
      * @param parameterIndex
      *            the parameter number index, where the first parameter has
      *            index 1.
      * @return an Object holding the value of the parameter.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public Object getObject(int parameterIndex) throws SQLException;
 
@@ -513,7 +479,6 @@
      * @return an Object holding the value of the parameter.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public Object getObject(int parameterIndex, Map<String, Class<?>> map)
             throws SQLException;
@@ -526,15 +491,13 @@
      * If a parameter was registered as a {@code java.sql.Types.OTHER} 
      * then it may hold abstract types that are particular to the 
      * connected database.
-     * </p>
-     * 
+     *
      * @param parameterName
      *            the parameter name.
      * @return the Java {@code Object} representation of the value of the
      *         parameter.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public Object getObject(String parameterName) throws SQLException;
 
@@ -550,7 +513,6 @@
      * @return an {@code Object} holding the value of the parameter.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public Object getObject(String parameterName, Map<String, Class<?>> map)
             throws SQLException;
@@ -566,7 +528,6 @@
      *         is returned if the value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public Ref getRef(int parameterIndex) throws SQLException;
 
@@ -582,7 +543,6 @@
      * @throws SQLException
      *             if there is a problem accessing the database.
      * @see Ref
-     * @since Android 1.0
      */
     public Ref getRef(String parameterName) throws SQLException;
 
@@ -597,7 +557,6 @@
      *         if the parameter's value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public short getShort(int parameterIndex) throws SQLException;
 
@@ -611,7 +570,6 @@
      *         if the parameter's value is SQL {@code NULL}.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public short getShort(String parameterName) throws SQLException;
 
@@ -623,8 +581,7 @@
      * The {@code String} corresponding to a {@code CHAR} of fixed length 
      * will be of identical length to the value in the database inclusive 
      * of padding characters.
-     * </p>
-     * 
+     *
      * @param parameterIndex
      *            the parameter number index, where the first parameter has
      *            index 1.
@@ -632,7 +589,6 @@
      *         is returned if the value is SQL {@code NULL}.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public String getString(int parameterIndex) throws SQLException;
 
@@ -644,15 +600,13 @@
      * The string corresponding to a {@code CHAR} of fixed length will be of
      * identical length to the value in the database inclusive of padding
      * characters.
-     * </p>
-     * 
+     *
      * @param parameterName
      *            the desired parameter's name.
      * @return the parameter's value as a {@code String}. {@code null} 
      *         is returned if the value is SQL {@code NULL}.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public String getString(String parameterName) throws SQLException;
 
@@ -668,7 +622,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see Time
-     * @since Android 1.0
      */
     public Time getTime(int parameterIndex) throws SQLException;
 
@@ -689,7 +642,6 @@
      *             if a database error occurs.
      * @see Time
      * @see java.util.Calendar
-     * @since Android 1.0
      */
     public Time getTime(int parameterIndex, Calendar cal) throws SQLException;
 
@@ -704,7 +656,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see Time
-     * @since Android 1.0
      */
     public Time getTime(String parameterName) throws SQLException;
 
@@ -724,7 +675,6 @@
      *             if a database error occurs.
      * @see Time
      * @see java.util.Calendar
-     * @since Android 1.0
      */
     public Time getTime(String parameterName, Calendar cal) throws SQLException;
 
@@ -741,7 +691,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see Timestamp
-     * @since Android 1.0
      */
     public Timestamp getTimestamp(int parameterIndex) throws SQLException;
 
@@ -761,7 +710,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see Timestamp
-     * @since Android 1.0
      */
     public Timestamp getTimestamp(int parameterIndex, Calendar cal)
             throws SQLException;
@@ -778,7 +726,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see Timestamp
-     * @since Android 1.0
      */
     public Timestamp getTimestamp(String parameterName) throws SQLException;
 
@@ -797,7 +744,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see Timestamp
-     * @since Android 1.0
      */
     public Timestamp getTimestamp(String parameterName, Calendar cal)
             throws SQLException;
@@ -814,7 +760,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see java.net.URL
-     * @since Android 1.0
      */
     public URL getURL(int parameterIndex) throws SQLException;
 
@@ -830,7 +775,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see java.net.URL
-     * @since Android 1.0
      */
     public URL getURL(String parameterName) throws SQLException;
 
@@ -845,8 +789,7 @@
      * If a database specific type is expected for a parameter, the Type {@code
      * java.sql.Types.OTHER} should be used. Note that there is another variant
      * of this method for User Defined Types or a {@code REF} type.
-     * </p>
-     * 
+     *
      * @param parameterIndex
      *            the parameter number index, where the first parameter has
      *            index 1
@@ -857,7 +800,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see Types
-     * @since Android 1.0
      */
     public void registerOutParameter(int parameterIndex, int sqlType)
             throws SQLException;
@@ -873,8 +815,7 @@
      * The type supplied in the {@code sqlType} parameter fixes the  
      * type that will be returned by the getter methods of 
      * {@code CallableStatement}. 
-     * </p>
-     * 
+     *
      * @param parameterIndex
      *            the parameter number index, where the first parameter has
      *            index 1
@@ -886,7 +827,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see Types
-     * @since Android 1.0
      */
     public void registerOutParameter(int parameterIndex, int sqlType, int scale)
             throws SQLException;
@@ -908,7 +848,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see Ref
-     * @since Android 1.0
      */
     public void registerOutParameter(int paramIndex, int sqlType,
             String typeName) throws SQLException;
@@ -923,8 +862,7 @@
      * If a database-specific type is expected for a parameter, the Type {@code
      * java.sql.Types.OTHER} should be used. Note that there is another variant
      * of this method for User Defined Types or a {@code REF} type.
-     * </p>
-     * 
+     *
      * @param parameterName
      *            the parameter name.
      * @param sqlType
@@ -934,7 +872,6 @@
      *            parameter.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void registerOutParameter(String parameterName, int sqlType)
             throws SQLException;
@@ -950,8 +887,7 @@
      * The type supplied in the {@code sqlType} parameter fixes the  
      * type that will be returned by the getter methods of 
      * {@code CallableStatement}. 
-     * </p>
-     * 
+     *
      * @param parameterName
      *            the parameter name.
      * @param sqlType
@@ -961,7 +897,6 @@
      *            than or equal to 0.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void registerOutParameter(String parameterName, int sqlType,
             int scale) throws SQLException;
@@ -982,7 +917,6 @@
      *            of the referenced type.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void registerOutParameter(String parameterName, int sqlType,
             String typeName) throws SQLException;
@@ -991,12 +925,11 @@
      * Sets the value of a specified parameter to the content of a supplied
      * {@code InputStream}, which has a specified number of bytes.
      * <p>
-     * This is a good method for setting an SQL {@code LONVARCHAR} parameter
+     * This is a good method for setting an SQL {@code LONGVARCHAR} parameter
      * where the length of the data is large. Data is read from the {@code
      * InputStream} until end-of-file is reached or the specified number of
      * bytes is copied.
-     * </p>
-     * 
+     *
      * @param parameterName
      *            the parameter name
      * @param theInputStream
@@ -1007,7 +940,6 @@
      *            parameter.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void setAsciiStream(String parameterName,
             InputStream theInputStream, int length) throws SQLException;
@@ -1022,7 +954,6 @@
      *            the {@code java.math.BigInteger} value to set.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void setBigDecimal(String parameterName, BigDecimal theBigDecimal)
             throws SQLException;
@@ -1033,8 +964,7 @@
      * <p>
      * Use this method when a large amount of data needs to be set into a
      * {@code LONGVARBINARY} parameter.
-     * </p>
-     * 
+     *
      * @param parameterName
      *            the name of the parameter.
      * @param theInputStream
@@ -1045,7 +975,6 @@
      *            parameter.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void setBinaryStream(String parameterName,
             InputStream theInputStream, int length) throws SQLException;
@@ -1060,7 +989,6 @@
      *            the new value with which to update the parameter.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void setBoolean(String parameterName, boolean theBoolean)
             throws SQLException;
@@ -1074,7 +1002,6 @@
      *            the new value with which to update the parameter.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void setByte(String parameterName, byte theByte) throws SQLException;
 
@@ -1089,7 +1016,6 @@
      *            the new value with which to update the parameter.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void setBytes(String parameterName, byte[] theBytes)
             throws SQLException;
@@ -1106,7 +1032,6 @@
      *            a count of the characters contained in {@code reader}.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void setCharacterStream(String parameterName, Reader reader,
             int length) throws SQLException;
@@ -1121,7 +1046,6 @@
      *            the new value with which to update the parameter.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void setDate(String parameterName, Date theDate) throws SQLException;
 
@@ -1144,7 +1068,6 @@
      *             if a database error occurs.
      * @see java.util.Calendar
      * @see Date
-     * @since Android 1.0
      */
     public void setDate(String parameterName, Date theDate, Calendar cal)
             throws SQLException;
@@ -1159,7 +1082,6 @@
      *            the new value with which to update the parameter.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void setDouble(String parameterName, double theDouble)
             throws SQLException;
@@ -1174,7 +1096,6 @@
      *            the new value with which to update the parameter.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void setFloat(String parameterName, float theFloat)
             throws SQLException;
@@ -1188,7 +1109,6 @@
      *            the new value with which to update the parameter.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void setInt(String parameterName, int theInt) throws SQLException;
 
@@ -1201,7 +1121,6 @@
      *            the new value with which to update the parameter.
      * @throws SQLException
      *             if a database error occurs.
-     *             @since Android 1.0
      */
     public void setLong(String parameterName, long theLong) throws SQLException;
 
@@ -1216,7 +1135,6 @@
      *            a JDBC type expressed as a constant from {@link Types}.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void setNull(String parameterName, int sqlType) throws SQLException;
 
@@ -1229,8 +1147,7 @@
      * type code and type name (which is just the parameter name if the type is
      * user defined, referred to as a {@code UDT}, or the name of the referenced
      * type in case of a {@code REF} type).
-     * </p>
-     * 
+     *
      * @param parameterName
      *            the parameter name.
      * @param sqlType
@@ -1243,7 +1160,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see Types
-     * @since Android 1.0
      */
     public void setNull(String parameterName, int sqlType, String typeName)
             throws SQLException;
@@ -1263,8 +1179,7 @@
      * <li>{@link Array}</li>
      * <li>{@link Clob}</li>
      * <li>{@link Blob}</li> </ul>
-     * </p>
-     * 
+     *
      * @param parameterName
      *            the parameter name
      * @param theObject
@@ -1272,7 +1187,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see SQLData
-     * @since Android 1.0
      */
     public void setObject(String parameterName, Object theObject)
             throws SQLException;
@@ -1295,8 +1209,7 @@
      * </ul>
      * then the driver is in charge of mapping the value to the appropriate 
      * SQL type and deliver it to the database.
-     * </p>
-     * 
+     *
      * @param parameterName
      *            the parameter name.
      * @param theObject
@@ -1306,7 +1219,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see SQLData
-     * @since Android 1.0
      */
     public void setObject(String parameterName, Object theObject,
             int targetSqlType) throws SQLException;
@@ -1328,8 +1240,7 @@
      * </ul>
      * then the driver is charge of mapping the value to the appropriate 
      * SQL type.
-     * </p>
-     * 
+     *
      * @param parameterName
      *            the parameter name.
      * @param theObject
@@ -1342,7 +1253,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see SQLData
-     * @since Android 1.0
      */
     public void setObject(String parameterName, Object theObject,
             int targetSqlType, int scale) throws SQLException;
@@ -1357,7 +1267,6 @@
      *            a short value to update the parameter.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void setShort(String parameterName, short theShort)
             throws SQLException;
@@ -1371,7 +1280,6 @@
      *            a {@code String} value to update the parameter.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void setString(String parameterName, String theString)
             throws SQLException;
@@ -1387,7 +1295,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see Time
-     * @since Android 1.0
      */
     public void setTime(String parameterName, Time theTime) throws SQLException;
 
@@ -1409,7 +1316,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see Time
-     * @since Android 1.0
      */
     public void setTime(String parameterName, Time theTime, Calendar cal)
             throws SQLException;
@@ -1425,7 +1331,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see Timestamp
-     * @since Android 1.0
      */
     public void setTimestamp(String parameterName, Timestamp theTimestamp)
             throws SQLException;
@@ -1437,8 +1342,7 @@
      * The driver uses the supplied calendar to create the SQL {@code TIMESTAMP}
      * value, which allows it to use a custom timezone - otherwise the driver
      * uses the default timezone of the Java virtual machine.
-     * </p>
-     * 
+     *
      * @param parameterName
      *            the parameter name.
      * @param theTimestamp
@@ -1449,7 +1353,6 @@
      *             if a database error occurs.
      * @see Timestamp
      * @see java.util.Calendar
-     * @since Android 1.0
      */
     public void setTimestamp(String parameterName, Timestamp theTimestamp,
             Calendar cal) throws SQLException;
@@ -1465,7 +1368,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see java.net.URL
-     * @since Android 1.0
      */
     public void setURL(String parameterName, URL theURL) throws SQLException;
 
@@ -1477,7 +1379,6 @@
      *         otherwise.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public boolean wasNull() throws SQLException;
 }
diff --git a/libcore/sql/src/main/java/java/sql/Clob.java b/libcore/sql/src/main/java/java/sql/Clob.java
index 339d4e5..73fe7fb 100644
--- a/libcore/sql/src/main/java/java/sql/Clob.java
+++ b/libcore/sql/src/main/java/java/sql/Clob.java
@@ -31,8 +31,6 @@
  * The {@code java.sql.Clob} interface provides methods for setting and
  * retrieving data in the {@code Clob}, for querying {@code Clob} data length,
  * for searching for data within the {@code Clob}.
- *  
- * @since Android 1.0
  */
 public interface Clob {
 
@@ -43,7 +41,6 @@
      *            {@code Clob} data.
      * @throws SQLException
      *             if an error occurs accessing the {@code Clob}.
-     * @since Android 1.0
      */
     public InputStream getAsciiStream() throws SQLException;
 
@@ -54,7 +51,6 @@
      *         Clob} data.
      * @throws SQLException
      *             if an error occurs accessing the {@code Clob}.
-     * @since Android 1.0
      */
     public Reader getCharacterStream() throws SQLException;
 
@@ -68,7 +64,6 @@
      * @return A string containing the requested data.
      * @throws SQLException
      *             if an error occurs accessing the {@code Clob}.
-     * @since Android 1.0
      */
     public String getSubString(long pos, int length) throws SQLException;
 
@@ -78,7 +73,6 @@
      * @return a long value with the number of character in this {@code Clob}.
      * @throws SQLException
      *             if an error occurs accessing the {@code Clob}.
-     * @since Android 1.0
      */
     public long length() throws SQLException;
 
@@ -94,7 +88,6 @@
      *         Clob} occurs within this {@code Clob}.
      * @throws SQLException
      *             if an error occurs accessing the {@code Clob}.
-     * @since Android 1.0
      */
     public long position(Clob searchstr, long start) throws SQLException;
 
@@ -111,7 +104,6 @@
      *         occurs within this {@code Clob}.
      * @throws SQLException
      *             if an error occurs accessing the {@code Clob}.
-     * @since Android 1.0
      */
     public long position(String searchstr, long start) throws SQLException;
 
@@ -125,7 +117,6 @@
      *         this {@code Clob}.
      * @throws SQLException
      *             if an error occurs accessing the {@code Clob}.
-     * @since Android 1.0
      */
     public OutputStream setAsciiStream(long pos) throws SQLException;
 
@@ -139,7 +130,6 @@
      *         {@code Clob}.
      * @throws SQLException
      *             if an error occurs accessing the {@code Clob}.
-     * @since Android 1.0
      */
     public Writer setCharacterStream(long pos) throws SQLException;
 
@@ -154,7 +144,6 @@
      * @return the number of characters written.
      * @throws SQLException
      *             if an error occurs accessing the {@code Clob}.
-     * @since Android 1.0
      */
     public int setString(long pos, String str) throws SQLException;
 
@@ -173,7 +162,6 @@
      * @return the number of characters written.
      * @throws SQLException
      *             if an error occurs accessing the {@code Clob}.
-     * @since Android 1.0
      */
     public int setString(long pos, String str, int offset, int len)
             throws SQLException;
@@ -186,7 +174,6 @@
      *            truncate this {@code Clob}.
      * @throws SQLException
      *             if an error occurs accessing the {@code Clob}.
-     * @since Android 1.0
      */
     public void truncate(long len) throws SQLException;
 }
diff --git a/libcore/sql/src/main/java/java/sql/Connection.java b/libcore/sql/src/main/java/java/sql/Connection.java
index 523071c..0704cca 100644
--- a/libcore/sql/src/main/java/java/sql/Connection.java
+++ b/libcore/sql/src/main/java/java/sql/Connection.java
@@ -23,8 +23,10 @@
  * A connection represents a link from a Java application to a database. All SQL
  * statements and results are returned within the context of a connection.
  * Database statements that are executed within this context form a
- * database session which forms one or more closed transactions. Especially In distributed applications, multiple concurrent connections may exist accessing the same values of the database.
- * which may lead to the following phenomena (referred to as <i>transaction isolation levels</i>):
+ * database session which forms one or more closed transactions. Especially in
+ * distributed applications, multiple concurrent connections may exist accessing
+ * the same values of the database. which may lead to the following phenomena
+ * (referred to as <i>transaction isolation levels</i>):
  * <ul>
  * <li><i>dirty reads</i>:<br>
  * reading values from table rows that are not committed.</br></li>
@@ -36,15 +38,11 @@
  * because other transactions have inserted additional rows that satisfy an
  * SQL {@code WHERE} clause</br></li>
  * </ul>
- *  
- * @since Android 1.0
  */
 public interface Connection {
 
     /**
      * A constant indicating that transactions are not supported.
-     * 
-     * @since Android 1.0
      */
     public static final int TRANSACTION_NONE = 0;
 
@@ -52,8 +50,6 @@
      * No <i>dirty reads</i> are permitted, therefore transactions may not read
      * a row containing uncommitted values - but does not prevent an application
      * from <i>non-repeatable reads</i> and <i>phantom reads</i>.
-     * 
-     * @since Android 1.0
      */
     public static final int TRANSACTION_READ_COMMITTED = 2;
 
@@ -65,16 +61,12 @@
      * <li><i>non-repeatable reads</i></li>
      * <li><i>phantom reads</i></li>
      * </ul>
-     * 
-     * @since Android 1.0
      */
     public static final int TRANSACTION_READ_UNCOMMITTED = 1;
 
     /**
      * A constant indicating that <i>dirty reads</i> and <i>non-repeatable
      * reads</i> are <b>prevented</b> but <i>phantom reads</i> can occur.
-     * 
-     * @since Android 1.0
      */
     public static final int TRANSACTION_REPEATABLE_READ = 4;
 
@@ -86,8 +78,6 @@
      * <li><i>non-repeatable reads</i></li>
      * <li><i>phantom reads</i></li>
      * </ul>
-     * 
-     * @since Android 1.0
      */
     public static final int TRANSACTION_SERIALIZABLE = 8;
 
@@ -112,8 +102,7 @@
      * connection before garbage collection takes place, it is not advisable to
      * leave the {@code close} operation to take place in this way. Mainly
      * because undesired side-effects may appear.
-     * </p>
-     * 
+     *
      * @throws SQLException
      *             if there is a problem accessing the database.
      */
@@ -217,7 +206,6 @@
      *         false}.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public boolean getAutoCommit() throws SQLException;
 
@@ -242,7 +230,6 @@
      *         </ul>
      * @throws SQLException
      *             if there is a problem accessing the a database.
-     * @since Android 1.0
      */
     public int getHoldability() throws SQLException;
 
@@ -255,7 +242,6 @@
      *         description.
      * @throws SQLException
      *             if there is a problem accessing the a database.
-     * @since Android 1.0
      */
     public DatabaseMetaData getMetaData() throws SQLException;
 
@@ -270,7 +256,6 @@
      * @see #TRANSACTION_READ_UNCOMMITTED
      * @see #TRANSACTION_REPEATABLE_READ
      * @see #TRANSACTION_SERIALIZABLE
-     * @since Android 1.0
      */
     public int getTransactionIsolation() throws SQLException;
 
@@ -281,7 +266,6 @@
      * @return the Type Map as a {@code java.util.Map}.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public Map<String, Class<?>> getTypeMap() throws SQLException;
 
@@ -294,14 +278,12 @@
      * By invoking the {@link SQLWarning#getNextWarning()} method of the
      * returned {@code SQLWarning} object it is possible to obtain all of
      * this connection's warning objects.
-     * </p>
-     * 
+     *
      * @return the first warning as an SQLWarning object (may be {@code null}).
      * @throws SQLException
      *             if there is a problem accessing the database or if the call
      *             has been made on a connection which has been previously
      *             closed.
-     * @since Android 1.0
      */
     public SQLWarning getWarnings() throws SQLException;
 
@@ -315,7 +297,6 @@
      * @return {@code true} if closed, otherwise {@code false}.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public boolean isClosed() throws SQLException;
 
@@ -326,7 +307,6 @@
      * @return {@code true} if in read-only state, otherwise {@code false}.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public boolean isReadOnly() throws SQLException;
 
@@ -356,7 +336,6 @@
      *         {@link ResultSet#CONCUR_READ_ONLY}.
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public CallableStatement prepareCall(String sql) throws SQLException;
 
@@ -387,7 +366,6 @@
      *         resultSetType} and {@code resultSetConcurrency} values.
      * @throws SQLException
      *             if a problem occurs accessing the database
-     * @since Android 1.0
      */
     public CallableStatement prepareCall(String sql, int resultSetType,
             int resultSetConcurrency) throws SQLException;
@@ -426,7 +404,6 @@
      *         resultSetHoldability} values.
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public CallableStatement prepareCall(String sql, int resultSetType,
             int resultSetConcurrency, int resultSetHoldability)
@@ -441,7 +418,7 @@
      * the driver does not support precompiled statements, the statement will
      * not reach the database server until it is executed. This distinction
      * determines the moment when {@code SQLException}s get raised.
-     * </p>
+     * <p>
      * By default, {@code ResultSet}s from the returned object will be
      * {@link ResultSet#TYPE_FORWARD_ONLY} type with a
      * {@link ResultSet#CONCUR_READ_ONLY} mode of concurrency.
@@ -452,7 +429,6 @@
      *         statement.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public PreparedStatement prepareStatement(String sql) throws SQLException;
 
@@ -467,7 +443,7 @@
      * precompiled in a {@code PreparedStatement}. The {@code PreparedStatement}
      * can then be then be used to execute the statement multiple times in an
      * efficient way.
-     * </p>
+     * <p>
      * Subject to JDBC driver support, this operation will attempt to send the
      * precompiled version of the statement to the database. If
      * the driver does not support precompiled statements, the statement will
@@ -477,8 +453,7 @@
      * By default, {@code ResultSet}s from the returned object will be
      * {@link ResultSet#TYPE_FORWARD_ONLY} type with a
      * {@link ResultSet#CONCUR_READ_ONLY} mode of concurrency.
-     * </p>
-     * 
+     *
      * @param sql
      *            the SQL statement.
      * @param autoGeneratedKeys
@@ -491,7 +466,6 @@
      *         SQL statement.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
             throws SQLException;
@@ -509,13 +483,11 @@
      * the driver does not support precompiled statements, the statement will
      * not reach the database server until it is executed. This distinction
      * determines the moment when {@code SQLException}s get raised.
-     * </p>
      * <p>
      * By default, {@code ResultSet}s from the returned object will be
      * {@link ResultSet#TYPE_FORWARD_ONLY} type with a
      * {@link ResultSet#CONCUR_READ_ONLY} concurrency mode.
-     * </p>
-     * 
+     *
      * @param sql
      *            the SQL statement.
      * @param columnIndexes
@@ -524,7 +496,6 @@
      * @return the PreparedStatement containing the supplied SQL statement.
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public PreparedStatement prepareStatement(String sql, int[] columnIndexes)
             throws SQLException;
@@ -556,7 +527,6 @@
      *         resultSetType} and {@code resultSetConcurrency} values.
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public PreparedStatement prepareStatement(String sql, int resultSetType,
             int resultSetConcurrency) throws SQLException;
@@ -594,7 +564,6 @@
      *         resultSetHoldability} values.
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public PreparedStatement prepareStatement(String sql, int resultSetType,
             int resultSetConcurrency, int resultSetHoldability)
@@ -614,13 +583,11 @@
      * statement will not reach the database server until it is executed. This
      * will have a bearing on precisely <i>when</i> {@code SQLException}
      * instances get raised.
-     * </p>
      * <p>
      * By default, ResultSets from the returned object will be
      * {@link ResultSet#TYPE_FORWARD_ONLY} type with a
      * {@link ResultSet#CONCUR_READ_ONLY} concurrency mode.
-     * </p>
-     * 
+     *
      * @param sql
      *            the SQL statement.
      * @param columnNames
@@ -629,7 +596,6 @@
      * @return the PreparedStatement containing the supplied SQL statement.
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public PreparedStatement prepareStatement(String sql, String[] columnNames)
             throws SQLException;
@@ -645,7 +611,6 @@
      *             if there is a problem with accessing the database or if
      *             {@code savepoint} is considered not valid in this
      *             transaction.
-     * @since Android 1.0
      */
     public void releaseSavepoint(Savepoint savepoint) throws SQLException;
 
@@ -657,7 +622,6 @@
      * @throws SQLException
      *             if there is a problem with the database or if the method is
      *             called while in auto-commit mode of operation.
-     * @since Android 1.0
      */
     public void rollback() throws SQLException;
 
@@ -669,7 +633,6 @@
      *            the Savepoint to roll back to
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public void rollback(Savepoint savepoint) throws SQLException;
 
@@ -682,26 +645,23 @@
      * statements get grouped into transactions that need to be completed by
      * explicit calls to either the {@link #commit()} or {@link #rollback()}
      * methods.
-     * </p>
+     * <p>
      * Auto-commit is the default mode for new connection instances.
      * <p>
      * When in this mode, commits will automatically occur upon successful SQL
      * statement completion or upon successful completion of an execute.
      * Statements are not considered successfully completed until all associated
      * {@code ResultSet}s and output parameters have been obtained or closed.
-     * </p>
      * <p>
      * Calling this operation during an uncommitted transaction will result in
      * it being committed.
-     * </p>
-     * 
+     *
      * @param autoCommit
      *            {@code boolean} indication of whether to put the target
      *            connection into auto-commit mode ({@code true}) or not (
      *            {@code false}).
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public void setAutoCommit(boolean autoCommit) throws SQLException;
 
@@ -714,7 +674,6 @@
      *            the catalog name to use.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public void setCatalog(String catalog) throws SQLException;
 
@@ -738,14 +697,12 @@
      * <p>
      * This serves as a hint to the driver, which can enable database
      * optimizations.
-     * </p>
-     * 
+     *
      * @param readOnly
      *            {@code true} to set the Connection to read only mode. {@code
      *            false} disables read-only mode.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public void setReadOnly(boolean readOnly) throws SQLException;
 
@@ -755,7 +712,6 @@
      * @return a {@code Savepoint} object for this savepoint.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public Savepoint setSavepoint() throws SQLException;
 
@@ -767,7 +723,6 @@
      * @return a {@code Savepoint} object for this savepoint.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public Savepoint setSavepoint(String name) throws SQLException;
 
@@ -776,8 +731,7 @@
      * <p>
      * If this method is called during a transaction, the results are
      * implementation defined.
-     * </p>
-     * 
+     *
      * @param level
      *            the new transaction isolation level to use from the following
      *            list of possible values:
@@ -790,7 +744,6 @@
      * @throws SQLException
      *             if there is a problem with the database or if the value of
      *             {@code level} is not one of the expected constant values.
-     * @since Android 1.0
      */
     public void setTransactionIsolation(int level) throws SQLException;
 
@@ -803,7 +756,6 @@
      * @throws SQLException
      *             if there is a problem accessing the database or if {@code
      *             map} is not an instance of {@link Map}.
-     * @since Android 1.0
      */
     public void setTypeMap(Map<String, Class<?>> map) throws SQLException;
 }
diff --git a/libcore/sql/src/main/java/java/sql/DataTruncation.java b/libcore/sql/src/main/java/java/sql/DataTruncation.java
index a472cc5..20da727 100644
--- a/libcore/sql/src/main/java/java/sql/DataTruncation.java
+++ b/libcore/sql/src/main/java/java/sql/DataTruncation.java
@@ -24,8 +24,6 @@
  * value either when reading (resulting in warning), or when writing data
  * (resulting in an error). The {@code SQLState} error code for truncated data
  * is {@code 01004}.
- *  
- * @since Android 1.0
  */
 public class DataTruncation extends SQLWarning implements Serializable {
 
@@ -66,7 +64,6 @@
      *            the original size of the truncated data.
      * @param transferSize
      *            the size of the data after truncation.
-     * @since Android 1.0
      */
     public DataTruncation(int index, boolean parameter, boolean read,
             int dataSize, int transferSize) {
@@ -83,7 +80,6 @@
      * 
      * @return the number of bytes that should have been read or written. The
      *         value is set to {@code -1} if the size is unknown.
-     * @since Android 1.0
      */
     public int getDataSize() {
         return dataSize;
@@ -93,7 +89,6 @@
      * Gets the index of the column or of the parameter that was truncated.
      * 
      * @return the index number of the column or of the parameter.
-     * @since Android 1.0
      */
     public int getIndex() {
         return index;
@@ -104,7 +99,6 @@
      * 
      * @return {@code true} if the value truncated was a parameter value,
      *         {@code false} if it was a column value.
-     * @since Android 1.0
      */
     public boolean getParameter() {
         return parameter;
@@ -116,7 +110,6 @@
      * 
      * @return {@code true} if the value was truncated on a read operation,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean getRead() {
         return read;
@@ -127,7 +120,6 @@
      * 
      * @return the number of bytes actually read/written. The value may be set
      *         to {@code -1} if the size is unknown.
-     * @since Android 1.0
      */
     public int getTransferSize() {
         return transferSize;
diff --git a/libcore/sql/src/main/java/java/sql/DatabaseMetaData.java b/libcore/sql/src/main/java/java/sql/DatabaseMetaData.java
index 82219c5..aca03c0 100644
--- a/libcore/sql/src/main/java/java/sql/DatabaseMetaData.java
+++ b/libcore/sql/src/main/java/java/sql/DatabaseMetaData.java
@@ -24,7 +24,6 @@
  * This interface is implemented by JDBC driver vendors in order to provide
  * information about the underlying database capabilities in association with
  * the JDBC driver.
- * </p>
  * <p>
  * Some of the methods in this interface take string parameters which are
  * patterns. Within these string patterns, {@code '%'} and {@code '_'}
@@ -33,144 +32,105 @@
  * "match any character". Only metadata entries that match the pattern are
  * returned. If such a search pattern string is set to {@code null}, that
  * argument's criteria are dropped from the search.
- * </p>
- *  
- * @since Android 1.0
  */
 public interface DatabaseMetaData {
 
     /**
      * States that it may not be permitted to store {@code NULL} values.
-     * 
-     * @since Android 1.0
      */
     public static final short attributeNoNulls = 0;
 
     /**
      * States that {@code NULL} values are definitely permitted.
-     *
-     * @since Android 1.0
      */
     public static final short attributeNullable = 1;
 
     /**
      * States that whether {@code NULL} values are permitted is unknown.
-     * 
-     * @since Android 1.0
      */
     public static final short attributeNullableUnknown = 2;
 
     /**
      * States the best row identifier is <em>NOT</em> a pseudo column.
-     * 
-     * @since Android 1.0
      */
     public static final int bestRowNotPseudo = 1;
 
     /**
      * States that the best row identifier is a pseudo column.
-     * 
-     * @since Android 1.0
      */
     public static final int bestRowPseudo = 2;
 
     /**
      * States that the remainder of the current session is used as the scope for
      * the best row identifier.
-     * 
-     * @since Android 1.0
      */
     public static final int bestRowSession = 2;
 
     /**
      * States that best row identifier scope lasts only while the row is being
      * used.
-     * 
-     * @since Android 1.0
      */
     public static final int bestRowTemporary = 0;
 
     /**
      * States that the remainder of the current transaction is used as the scope
      * for the best row identifier.
-     * 
-     * @since Android 1.0
      */
     public static final int bestRowTransaction = 1;
 
     /**
      * States that the best row identifier may or may not be a pseudo column.
-     * 
-     * @since Android 1.0
      */
     public static final int bestRowUnknown = 0;
 
     /**
      * States that the column must not allow {@code NULL} values.
-     * 
-     * @since Android 1.0
      */
     public static final int columnNoNulls = 0;
 
     /**
      * States that the column definitely allows {@code NULL} values.
-     * 
-     * @since Android 1.0
      */
     public static final int columnNullable = 1;
 
     /**
      * States that it is unknown whether the columns may be nulled.
-     * 
-     * @since Android 1.0
      */
     public static final int columnNullableUnknown = 2;
 
     /**
      * For the column {@code UPDATE_RULE}, states that when the primary key is
      * updated, the foreign key (imported key) is changed accordingly.
-     * 
-     * @since Android 1.0
      */
     public static final int importedKeyCascade = 0;
 
     /**
      * States that the evaluation of foreign key constraints is deferred (delayed
      * until commit).
-     * 
-     * @since Android 1.0
      */
     public static final int importedKeyInitiallyDeferred = 5;
 
     /**
      * States that the evaluation of foreign key constraint is {@code IMMEDIATE}
      * .
-     * 
-     * @since Android 1.0
      */
     public static final int importedKeyInitiallyImmediate = 6;
 
     /**
      * For the columns {@code UPDATE_RULE} and {@code DELETE_RULE}, states that
      * if the primary key has been imported, it cannot be updated or deleted.
-     * 
-     * @since Android 1.0
      */
     public static final int importedKeyNoAction = 3;
 
     /**
      * States that the evaluation of foreign key constraint must not be {@code
      * DEFERRED}.
-     * 
-     * @since Android 1.0
      */
     public static final int importedKeyNotDeferrable = 7;
 
     /**
      * States that a primary key must not be updated when imported as a foreign
      * key by some other table. Used for the column {@code UPDATE_RULE}.
-     * 
-     * @since Android 1.0
      */
     public static final int importedKeyRestrict = 1;
 
@@ -178,8 +138,6 @@
      * States that when the primary key is modified (updated or deleted) the
      * foreign (imported) key is changed to its default value. Applies to the
      * {@code UPDATE_RULE} and {@code DELETE_RULE} columns.
-     * 
-     * @since Android 1.0
      */
     public static final int importedKeySetDefault = 4;
 
@@ -187,190 +145,138 @@
      * States that when the primary key is modified (updated or deleted) the
      * foreign (imported) key is changed to {@code NULL}. Applies to the {@code
      * UPDATE_RULE} and {@code DELETE_RULE} columns.
-     * 
-     * @since Android 1.0
      */
     public static final int importedKeySetNull = 2;
 
     /**
      * States that the column stores {@code IN} type parameters.
-     * 
-     * @since Android 1.0
      */
     public static final int procedureColumnIn = 1;
 
     /**
      * States that this column stores {@code INOUT} type parameters.
-     * 
-     * @since Android 1.0
      */
     public static final int procedureColumnInOut = 2;
 
     /**
      * States that this column stores {@code OUT} type parameters.
-     * 
-     * @since Android 1.0
      */
     public static final int procedureColumnOut = 4;
 
     /**
      * States that the column stores results.
-     * 
-     * @since Android 1.0
      */
     public static final int procedureColumnResult = 3;
 
     /**
      * States that the column stores return values.
-     * 
-     * @since Android 1.0
      */
     public static final int procedureColumnReturn = 5;
 
     /**
      * States that type of the column is unknown.
-     * 
-     * @since Android 1.0
      */
     public static final int procedureColumnUnknown = 0;
 
     /**
      * States that {@code NULL} values are not permitted.
-     * 
-     * @since Android 1.0
      */
     public static final int procedureNoNulls = 0;
 
     /**
      * States that the procedure does not return a result.
-     * 
-     * @since Android 1.0
      */
     public static final int procedureNoResult = 1;
 
     /**
      * States that {@code NULL} values are permitted.
-     * 
-     * @since Android 1.0
      */
     public static final int procedureNullable = 1;
 
     /**
      * States that it is unknown whether {@code NULL} values are permitted.
-     * 
-     * @since Android 1.0
      */
     public static final int procedureNullableUnknown = 2;
 
     /**
      * States that it is unknown whether or not the procedure returns a result.
-     * 
-     * @since Android 1.0
      */
     public static final int procedureResultUnknown = 0;
 
     /**
      * States that the procedure returns a result.
-     * 
-     * @since Android 1.0
      */
     public static final int procedureReturnsResult = 2;
 
     /**
      * States that the value is an SQL99 {@code SQLSTATE} value.
-     * 
-     * @since Android 1.0
      */
     public static final int sqlStateSQL99 = 2;
 
     /**
      * States that the value is an SQL {@code CLI SQLSTATE} value as defined by
      * the X/Open standard.
-     * 
-     * @since Android 1.0
      */
     public static final int sqlStateXOpen = 1;
 
     /**
      * States that this table index is a clustered index.
-     * 
-     * @since Android 1.0
      */
     public static final short tableIndexClustered = 1;
 
     /**
      * States that this table index is a hashed index.
-     * 
-     * @since Android 1.0
      */
     public static final short tableIndexHashed = 2;
 
     /**
      * States this table's index is neither a clustered index, not a hashed
      * index, and not a table statistics index; i.e. it is something else.
-     * 
-     * @since Android 1.0
      */
     public static final short tableIndexOther = 3;
 
     /**
      * States this column has the table's statistics, and that it is returned in
      * conjunction with the table's index description.
-     * 
-     * @since Android 1.0
      */
     public static final short tableIndexStatistic = 0;
 
     /**
      * States that a {@code NULL} value is <em>NOT</em> permitted for
      * this data type.
-     * 
-     * @since Android 1.0
      */
     public static final int typeNoNulls = 0;
 
     /**
      * States that a {@code NULL} value is permitted for this data type.
-     * 
-     * @since Android 1.0
      */
     public static final int typeNullable = 1;
 
     /**
      * States that it is unknown if a {@code NULL} value is permitted for
      * this data type.
-     * 
-     * @since Android 1.0
      */
     public static final int typeNullableUnknown = 2;
 
     /**
      * States that this column shall not be used for {@code WHERE} statements
      * with a {@code LIKE} clause.
-     * 
-     * @since Android 1.0
      */
     public static final int typePredBasic = 2;
 
     /**
      * States that this column can only be used in a {@code WHERE...LIKE}
      * statement.
-     * 
-     * @since Android 1.0
      */
     public static final int typePredChar = 1;
 
     /**
      * States that this column does not support searches.
-     * 
-     * @since Android 1.0
      */
     public static final int typePredNone = 0;
 
     /**
      * States that the column is searchable.
-     * 
-     * @since Android 1.0
      */
     public static final int typeSearchable = 3;
 
@@ -397,7 +303,6 @@
      *         {@code false} otherwise.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public boolean allProceduresAreCallable() throws SQLException;
 
@@ -409,7 +314,6 @@
      *         otherwise.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public boolean allTablesAreSelectable() throws SQLException;
 
@@ -421,7 +325,6 @@
      *         otherwise.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public boolean dataDefinitionCausesTransactionCommit() throws SQLException;
 
@@ -433,7 +336,6 @@
      *         {@code false} otherwise.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public boolean dataDefinitionIgnoredInTransactions() throws SQLException;
 
@@ -450,7 +352,6 @@
      *         false} otherwise.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public boolean deletesAreDetected(int type) throws SQLException;
 
@@ -462,7 +363,6 @@
      *         and {@code LONGVARCHAR}, otherwise {@code false}.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public boolean doesMaxRowSizeIncludeBlobs() throws SQLException;
 
@@ -530,8 +430,7 @@
      * generated REF type or for a Distinct type. ({@code NULL} if {@code
      * DATA_TYPE} is not DISTINCT or a user generated REF)</li>
      * </ol>
-     * </p>
-     * 
+     *
      * @param catalog
      *            a catalog name. {@code null} is used to imply no narrowing of
      *            the search by catalog name. Otherwise, the name must match a
@@ -551,7 +450,6 @@
      * @return a {@code ResultSet}, where each row is an attribute description.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public ResultSet getAttributes(String catalog, String schemaPattern,
             String typeNamePattern, String attributeNamePattern)
@@ -592,8 +490,7 @@
      * </ul>
      * </li>
      * </ol>
-     * </p>
-     * 
+     *
      * @param catalog
      *            a catalog name. {@code null} is used to imply no narrowing of
      *            the search by catalog name. Otherwise, the name must match a
@@ -616,7 +513,6 @@
      *         and the complete set of rows is the optimal set for this table.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public ResultSet getBestRowIdentifier(String catalog, String schema,
             String table, int scope, boolean nullable) throws SQLException;
@@ -630,7 +526,6 @@
      *         single column named {@code TABLE_CAT}.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public ResultSet getCatalogs() throws SQLException;
 
@@ -641,7 +536,6 @@
      * @return a String containing the separator.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public String getCatalogSeparator() throws SQLException;
 
@@ -651,7 +545,6 @@
      * @return a String with the vendor's term for "catalog".
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public String getCatalogTerm() throws SQLException;
 
@@ -674,8 +567,7 @@
      * receiver can grant access to others, {@code "NO"} if the receiver cannot
      * grant access to others, {@code null} if unknown.</li>
      * </ol>
-     * </p>
-     * 
+     *
      * @param catalog
      *            a catalog name. {@code null} is used to imply no narrowing of
      *            the search by catalog name. Otherwise, the name must match a
@@ -696,7 +588,6 @@
      *         each privilege description.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public ResultSet getColumnPrivileges(String catalog, String schema,
             String table, String columnNamePattern) throws SQLException;
@@ -754,8 +645,7 @@
      * generated REF type or for a Distinct type. ({@code NULL} if {@code
      * DATA_TYPE} is not DISTINCT or a user generated REF)</li>
      * </ol>
-     * </p>
-     * 
+     *
      * @param catalog
      *            a catalog name. {@code null} is used to imply no narrowing of
      *            the search by catalog name. Otherwise, the name must match a
@@ -776,7 +666,6 @@
      *         defined above.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public ResultSet getColumns(String catalog, String schemaPattern,
             String tableNamePattern, String columnNamePattern)
@@ -788,7 +677,6 @@
      * @return the connection to the database.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public Connection getConnection() throws SQLException;
 
@@ -857,8 +745,7 @@
      * </ul>
      * </li>
      * </ol>
-     * </p>
-     * 
+     *
      * @param primaryCatalog
      *            a catalog name for the primary key table. {@code null} is used to imply no narrowing of
      *            the search by catalog name. Otherwise, the name must match a
@@ -889,7 +776,6 @@
      *         foreign keys laid out according to the format defined above.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public ResultSet getCrossReference(String primaryCatalog,
             String primarySchema, String primaryTable, String foreignCatalog,
@@ -901,7 +787,6 @@
      * @return the major version number of the database software.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public int getDatabaseMajorVersion() throws SQLException;
 
@@ -911,7 +796,6 @@
      * @return the minor version number of the database software.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public int getDatabaseMinorVersion() throws SQLException;
 
@@ -921,7 +805,6 @@
      * @return a {@code String} with the name of the database software.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public String getDatabaseProductName() throws SQLException;
 
@@ -932,7 +815,6 @@
      *         software.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public String getDatabaseProductVersion() throws SQLException;
 
@@ -949,7 +831,6 @@
      *         </ul>
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public int getDefaultTransactionIsolation() throws SQLException;
 
@@ -957,7 +838,6 @@
      * Returns the JDBC driver's major version number.
      * 
      * @return the driver's major version number.
-     * @since Android 1.0
      */
     public int getDriverMajorVersion();
 
@@ -965,7 +845,6 @@
      * Returns the JDBC driver's minor version number.
      * 
      * @return the driver's minor version number.
-     * @since Android 1.0
      */
     public int getDriverMinorVersion();
 
@@ -975,7 +854,6 @@
      * @return a {@code String} containing the name of the JDBC driver
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public String getDriverName() throws SQLException;
 
@@ -986,7 +864,6 @@
      *         JDBC driver.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public String getDriverVersion() throws SQLException;
 
@@ -1056,8 +933,7 @@
      * </ul>
      * </li>
      * </ol>
-     * </p>
-     * 
+     *
      * @param catalog
      *            a catalog name. {@code null} is used to imply no narrowing of
      *            the search by catalog name. Otherwise, the name must match a
@@ -1075,7 +951,6 @@
      *         columns, as defined above
      * @throws SQLException
      *             a database error occurred
-     * @since Android 1.0
      */
     public ResultSet getExportedKeys(String catalog, String schema, String table)
             throws SQLException;
@@ -1088,7 +963,6 @@
      * @return a String containing all the additional permitted characters.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public String getExtraNameCharacters() throws SQLException;
 
@@ -1099,7 +973,6 @@
      * @return the String used to quote SQL identifiers.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public String getIdentifierQuoteString() throws SQLException;
 
@@ -1169,8 +1042,7 @@
      * </ul>
      * </li>
      * </ol>
-     * </p>
-     * 
+     *
      * @param catalog
      *            a catalog name. {@code null} is used to imply no narrowing of
      *            the search by catalog name. Otherwise, the name must match a
@@ -1188,7 +1060,6 @@
      *         rows in the format defined above.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public ResultSet getImportedKeys(String catalog, String schema, String table)
             throws SQLException;
@@ -1235,8 +1106,7 @@
      * <li>{@code FILTER_CONDITION} - String - Filter condition. (possibly null)
      * </li>
      * </ol>
-     * </p>
-     * 
+     *
      * @param catalog
      *            a catalog name. {@code null} is used to imply no narrowing of
      *            the search by catalog name. Otherwise, the name must match a
@@ -1262,7 +1132,6 @@
      *         for the table, in the format defined above.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public ResultSet getIndexInfo(String catalog, String schema, String table,
             boolean unique, boolean approximate) throws SQLException;
@@ -1273,7 +1142,6 @@
      * @return the major JDBC version number.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public int getJDBCMajorVersion() throws SQLException;
 
@@ -1283,7 +1151,6 @@
      * @return the Minor JDBC Version Number.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public int getJDBCMinorVersion() throws SQLException;
 
@@ -1295,7 +1162,6 @@
      *         literal. If the number is unlimited then the result is zero.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public int getMaxBinaryLiteralLength() throws SQLException;
 
@@ -1306,7 +1172,6 @@
      *         is unknown, or the value is unlimited, then the result is zero.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public int getMaxCatalogNameLength() throws SQLException;
 
@@ -1318,7 +1183,6 @@
      *         zero.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public int getMaxCharLiteralLength() throws SQLException;
 
@@ -1329,7 +1193,6 @@
      *         is unknown, or the value is unlimited, then the result is zero.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public int getMaxColumnNameLength() throws SQLException;
 
@@ -1342,7 +1205,6 @@
      *         is zero.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public int getMaxColumnsInGroupBy() throws SQLException;
 
@@ -1353,7 +1215,6 @@
      *         unknown, or the value is unlimited, then the result is zero.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public int getMaxColumnsInIndex() throws SQLException;
 
@@ -1366,7 +1227,6 @@
      *         is zero.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public int getMaxColumnsInOrderBy() throws SQLException;
 
@@ -1379,7 +1239,6 @@
      *         zero.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public int getMaxColumnsInSelect() throws SQLException;
 
@@ -1390,7 +1249,6 @@
      *         unknown, or the value is unlimited, then the result is zero.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public int getMaxColumnsInTable() throws SQLException;
 
@@ -1401,7 +1259,6 @@
      *         the value is unlimited, then the result is zero.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public int getMaxConnections() throws SQLException;
 
@@ -1412,7 +1269,6 @@
      *         is unknown, or the value is unlimited, then the result is zero.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public int getMaxCursorNameLength() throws SQLException;
 
@@ -1424,7 +1280,6 @@
      *         unknown, or the value is unlimited, then the result is zero.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public int getMaxIndexLength() throws SQLException;
 
@@ -1437,7 +1292,6 @@
      *         zero.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public int getMaxProcedureNameLength() throws SQLException;
 
@@ -1449,7 +1303,6 @@
      *         unknown, or the value is unlimited, then the result is zero.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public int getMaxRowSize() throws SQLException;
 
@@ -1461,7 +1314,6 @@
      *         is unknown, or the value is unlimited, then the result is zero.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public int getMaxSchemaNameLength() throws SQLException;
 
@@ -1474,7 +1326,6 @@
      *         zero.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public int getMaxStatementLength() throws SQLException;
 
@@ -1486,7 +1337,6 @@
      *         unknown, or the value is unlimited, then the result is zero.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public int getMaxStatements() throws SQLException;
 
@@ -1497,7 +1347,6 @@
      *         unknown, or the value is unlimited, then the result is zero.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public int getMaxTableNameLength() throws SQLException;
 
@@ -1510,7 +1359,6 @@
      *         then the result is zero.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public int getMaxTablesInSelect() throws SQLException;
 
@@ -1521,7 +1369,6 @@
      *         unknown, or the value is unlimited, then the result is zero.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public int getMaxUserNameLength() throws SQLException;
 
@@ -1534,7 +1381,6 @@
      *         separated list.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public String getNumericFunctions() throws SQLException;
 
@@ -1553,8 +1399,7 @@
      * primary key</li>
      * <li>{@code PK_NAME} - String - the primary key name (possibly null)</li>
      * </ol>
-     * </p>
-     * 
+     *
      * @param catalog
      *            a catalog name. {@code null} is used to imply no narrowing of
      *            the search by catalog name. Otherwise, the name must match a
@@ -1572,7 +1417,6 @@
      *         defined above.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public ResultSet getPrimaryKeys(String catalog, String schema, String table)
             throws SQLException;
@@ -1630,8 +1474,7 @@
      * <li>{@code REMARKS} - String - an explanatory comment about the data item
      * </li>
      * </ol>
-     * </p>
-     * 
+     *
      * @param catalog
      *            a catalog name. {@code null} is used to imply no narrowing of
      *            the search by catalog name. Otherwise, the name must match a
@@ -1652,7 +1495,6 @@
      *         in the format defined above.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public ResultSet getProcedureColumns(String catalog, String schemaPattern,
             String procedureNamePattern, String columnNamePattern)
@@ -1702,7 +1544,6 @@
      *         procedure in the format defined above.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public ResultSet getProcedures(String catalog, String schemaPattern,
             String procedureNamePattern) throws SQLException;
@@ -1713,7 +1554,6 @@
      * @return a String with the vendor's preferred name for "procedure".
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public String getProcedureTerm() throws SQLException;
 
@@ -1724,7 +1564,6 @@
      *         ResultSet.CLOSE_CURSORS_AT_COMMIT}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public int getResultSetHoldability() throws SQLException;
 
@@ -1741,7 +1580,6 @@
      *         defined above.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public ResultSet getSchemas() throws SQLException;
 
@@ -1751,7 +1589,6 @@
      * @return a String which is the vendor's preferred term for schema.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public String getSchemaTerm() throws SQLException;
 
@@ -1765,7 +1602,6 @@
      * @return a String used to escape the wildcard characters.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public String getSearchStringEscape() throws SQLException;
 
@@ -1777,7 +1613,6 @@
      *         format.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public String getSQLKeywords() throws SQLException;
 
@@ -1791,7 +1626,6 @@
      *         DatabaseMetaData.sqlStateXOpen}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public int getSQLStateType() throws SQLException;
 
@@ -1804,7 +1638,6 @@
      *         separated format.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public String getStringFunctions() throws SQLException;
 
@@ -1824,8 +1657,7 @@
      * <li>{@code TABLE_NAME} - String - The table name</li>
      * <li>SUPER{@code TABLE_NAME} - String - The super table name</li>
      * </ol>
-     * </p>
-     * 
+     *
      * @param catalog
      *            a catalog name. {@code null} is used to imply no narrowing of
      *            the search by catalog name. Otherwise, the name must match a
@@ -1846,7 +1678,6 @@
      *         returned if the database does not support table hierarchies.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public ResultSet getSuperTables(String catalog, String schemaPattern,
             String tableNamePattern) throws SQLException;
@@ -1871,8 +1702,7 @@
      * (possibly {@code null})</li>
      * <li>SUPER{@code TYPE_NAME} - String - direct supertype's name</li>
      * </ol>
-     * </p>
-     * 
+     *
      * @param catalog
      *            the catalog name. "" means get the UDTs without a catalog.
      *            {@code null} means don't use the catalog name to restrict the
@@ -1889,7 +1719,6 @@
      *         returned for a database that does not support type hierarchies.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public ResultSet getSuperTypes(String catalog, String schemaPattern,
             String typeNamePattern) throws SQLException;
@@ -1903,7 +1732,6 @@
      *         separated format.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public String getSystemFunctions() throws SQLException;
 
@@ -1930,8 +1758,7 @@
      * access to others, {@code "NO"} implies guarantee cannot grant access to
      * others, {@code null} means this status is unknown</li>
      * </ol>
-     * </p>
-     * 
+     *
      * @param catalog
      *            a catalog name. {@code null} is used to imply no narrowing of
      *            the search by catalog name. Otherwise, the name must match a
@@ -1949,7 +1776,6 @@
      *         in the format defined above.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public ResultSet getTablePrivileges(String catalog, String schemaPattern,
             String tableNamePattern) throws SQLException;
@@ -1982,8 +1808,7 @@
      * "USER" | "DERIVED" - specifies how values in the {@code
      * SELF_REFERENCING_COL_NAME} are created (possibly {@code null})</li>
      * </ol>
-     * </p>
-     * 
+     *
      * @param catalog
      *            a catalog name. {@code null} is used to imply no narrowing of
      *            the search by catalog name. Otherwise, the name must match a
@@ -2004,7 +1829,6 @@
      *         above.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public ResultSet getTables(String catalog, String schemaPattern,
             String tableNamePattern, String[] types) throws SQLException;
@@ -2020,13 +1844,11 @@
      * {@code "TABLE"}, {@code "VIEW"}, "{@code SYSTEM TABLE"}, {@code "ALIAS"},
      * {@code "SYNONYM"}, {@code "GLOBAL TEMPORARY"}</li>
      * </ol>
-     * </p>
-     * 
+     *
      * @return a {@code ResultSet} with one row per table type in the format
      *         defined above.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public ResultSet getTableTypes() throws SQLException;
 
@@ -2037,7 +1859,6 @@
      *         functions.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public String getTimeDateFunctions() throws SQLException;
 
@@ -2096,7 +1917,6 @@
      * @return a {@code ResultSet} which is structured as described above.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public ResultSet getTypeInfo() throws SQLException;
 
@@ -2122,11 +1942,9 @@
      * This is defined in {@code java.sql.Types}, and will be {@code null} if
      * the {@code DATA_TYPE} does not match these criteria.</li>
      * </ol>
-     * </p>
      * <p>
      * If the driver does not support UDTs, the {@code ResultSet} is empty.
-     * </p>
-     * 
+     *
      * @param catalog
      *            a catalog name. {@code null} is used to imply no narrowing of
      *            the search by catalog name. Otherwise, the name must match a
@@ -2146,7 +1964,6 @@
      * @return a {@code ResultSet} in the format described above.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public ResultSet getUDTs(String catalog, String schemaPattern,
             String typeNamePattern, int[] types) throws SQLException;
@@ -2157,7 +1974,6 @@
      * @return the URL for the database. {@code null} if it cannot be generated.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public String getURL() throws SQLException;
 
@@ -2167,7 +1983,6 @@
      * @return the user name.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public String getUserName() throws SQLException;
 
@@ -2197,8 +2012,7 @@
      * </ul>
      * </li>
      * </ol>
-     * </p>
-     * 
+     *
      * @param catalog
      *            a catalog name. {@code null} is used to imply no narrowing of
      *            the search using catalog name. Otherwise, the name must match
@@ -2216,7 +2030,6 @@
      *         column, in the format defined above.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public ResultSet getVersionColumns(String catalog, String schema,
             String table) throws SQLException;
@@ -2235,7 +2048,6 @@
      * @throws SQLException
      *             a database error occurred.
      * @see ResultSet#rowInserted()
-     * @since Android 1.0
      */
     public boolean insertsAreDetected(int type) throws SQLException;
 
@@ -2247,7 +2059,6 @@
      *         qualified table name, {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean isCatalogAtStart() throws SQLException;
 
@@ -2258,7 +2069,6 @@
      *         otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean isReadOnly() throws SQLException;
 
@@ -2270,7 +2080,6 @@
      *         {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean locatorsUpdateCopy() throws SQLException;
 
@@ -2282,7 +2091,6 @@
      *         produce a {@code NULL} result, {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean nullPlusNonNullIsNull() throws SQLException;
 
@@ -2296,7 +2104,6 @@
      *         {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean nullsAreSortedAtEnd() throws SQLException;
 
@@ -2309,7 +2116,6 @@
      *         {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean nullsAreSortedAtStart() throws SQLException;
 
@@ -2321,7 +2127,6 @@
      *         false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean nullsAreSortedHigh() throws SQLException;
 
@@ -2333,7 +2138,6 @@
      *         otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean nullsAreSortedLow() throws SQLException;
 
@@ -2350,7 +2154,6 @@
      *         otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean othersDeletesAreVisible(int type) throws SQLException;
 
@@ -2367,7 +2170,6 @@
      *         false}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean othersInsertsAreVisible(int type) throws SQLException;
 
@@ -2384,7 +2186,6 @@
      *         false}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean othersUpdatesAreVisible(int type) throws SQLException;
 
@@ -2401,7 +2202,6 @@
      *         ResultSet} itself, otherwise {@code false}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean ownDeletesAreVisible(int type) throws SQLException;
 
@@ -2418,7 +2218,6 @@
      *         ResultSet} itself, otherwise {@code false}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean ownInsertsAreVisible(int type) throws SQLException;
 
@@ -2435,7 +2234,6 @@
      *         ResultSet} itself, otherwise {@code false}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean ownUpdatesAreVisible(int type) throws SQLException;
 
@@ -2448,7 +2246,6 @@
      *         case, {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean storesLowerCaseIdentifiers() throws SQLException;
 
@@ -2460,7 +2257,6 @@
      *         {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean storesLowerCaseQuotedIdentifiers() throws SQLException;
 
@@ -2472,7 +2268,6 @@
      *         {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean storesMixedCaseIdentifiers() throws SQLException;
 
@@ -2485,7 +2280,6 @@
      *         {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean storesMixedCaseQuotedIdentifiers() throws SQLException;
 
@@ -2497,7 +2291,6 @@
      *         case, {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean storesUpperCaseIdentifiers() throws SQLException;
 
@@ -2509,7 +2302,6 @@
      *         {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean storesUpperCaseQuotedIdentifiers() throws SQLException;
 
@@ -2521,7 +2313,6 @@
      *         supported, {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsAlterTableWithAddColumn() throws SQLException;
 
@@ -2533,7 +2324,6 @@
      *         supported, {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsAlterTableWithDropColumn() throws SQLException;
 
@@ -2544,7 +2334,6 @@
      *         {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsANSI92EntryLevelSQL() throws SQLException;
 
@@ -2555,7 +2344,6 @@
      *         false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsANSI92FullSQL() throws SQLException;
 
@@ -2566,7 +2354,6 @@
      *         {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsANSI92IntermediateSQL() throws SQLException;
 
@@ -2577,7 +2364,6 @@
      *         otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsBatchUpdates() throws SQLException;
 
@@ -2589,7 +2375,6 @@
      *         statements, {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsCatalogsInDataManipulation() throws SQLException;
 
@@ -2600,7 +2385,6 @@
      *         statements, {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsCatalogsInIndexDefinitions() throws SQLException;
 
@@ -2612,7 +2396,6 @@
      *         statements, {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException;
 
@@ -2623,7 +2406,6 @@
      *         statements.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsCatalogsInProcedureCalls() throws SQLException;
 
@@ -2634,7 +2416,6 @@
      *         statements, {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsCatalogsInTableDefinitions() throws SQLException;
 
@@ -2643,8 +2424,7 @@
      * <p>
      * If aliasing is supported, then the SQL AS clause is used to provide names
      * for computed columns and provide alias names for columns.
-     * </p>
-     * 
+     *
      * @return {@code true} if column aliasing is supported, {@code false}
      *         otherwise.
      * @throws SQLException
@@ -2660,7 +2440,6 @@
      *         {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsConvert() throws SQLException;
 
@@ -2676,7 +2455,6 @@
      *         these types, {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsConvert(int fromType, int toType)
             throws SQLException;
@@ -2688,7 +2466,6 @@
      *         otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsCoreSQLGrammar() throws SQLException;
 
@@ -2699,7 +2476,6 @@
      *         and {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsCorrelatedSubqueries() throws SQLException;
 
@@ -2711,7 +2487,6 @@
      *         false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsDataDefinitionAndDataManipulationTransactions()
             throws SQLException;
@@ -2724,7 +2499,6 @@
      *         {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsDataManipulationTransactionsOnly()
             throws SQLException;
@@ -2737,7 +2511,6 @@
      *         names, {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsDifferentTableCorrelationNames() throws SQLException;
 
@@ -2748,7 +2521,6 @@
      *         supported.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsExpressionsInOrderBy() throws SQLException;
 
@@ -2759,7 +2531,6 @@
      *         false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsExtendedSQLGrammar() throws SQLException;
 
@@ -2770,7 +2541,6 @@
      *         false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsFullOuterJoins() throws SQLException;
 
@@ -2782,7 +2552,6 @@
      *         false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsGetGeneratedKeys() throws SQLException;
 
@@ -2793,7 +2562,6 @@
      *         false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsGroupBy() throws SQLException;
 
@@ -2807,7 +2575,6 @@
      *         this way, {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsGroupByBeyondSelect() throws SQLException;
 
@@ -2819,7 +2586,6 @@
      *         in the {@code SELECT} statement, {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsGroupByUnrelated() throws SQLException;
 
@@ -2831,7 +2597,6 @@
      *         {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsIntegrityEnhancementFacility() throws SQLException;
 
@@ -2842,7 +2607,6 @@
      *         otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsLikeEscapeClause() throws SQLException;
 
@@ -2855,7 +2619,6 @@
      *         {@code supportsFullOuterJoins} returns {@code true}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsLimitedOuterJoins() throws SQLException;
 
@@ -2866,7 +2629,6 @@
      *         false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsMinimumSQLGrammar() throws SQLException;
 
@@ -2878,7 +2640,6 @@
      *         case, {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsMixedCaseIdentifiers() throws SQLException;
 
@@ -2890,7 +2651,6 @@
      *         {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException;
 
@@ -2903,7 +2663,6 @@
      *         otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsMultipleOpenResults() throws SQLException;
 
@@ -2915,7 +2674,6 @@
      *         {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsMultipleResultSets() throws SQLException;
 
@@ -2927,7 +2685,6 @@
      *         false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsMultipleTransactions() throws SQLException;
 
@@ -2938,7 +2695,6 @@
      *         statements, {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsNamedParameters() throws SQLException;
 
@@ -2949,7 +2705,6 @@
      *         false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsNonNullableColumns() throws SQLException;
 
@@ -2972,7 +2727,6 @@
      *         operations, {@code false} if they might get closed.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsOpenCursorsAcrossRollback() throws SQLException;
 
@@ -2984,7 +2738,6 @@
      *         they might not.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsOpenStatementsAcrossCommit() throws SQLException;
 
@@ -2996,7 +2749,6 @@
      *         they might not.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsOpenStatementsAcrossRollback() throws SQLException;
 
@@ -3008,7 +2760,6 @@
      *         not in the {@code SELECT}, {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsOrderByUnrelated() throws SQLException;
 
@@ -3019,7 +2770,6 @@
      *         false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsOuterJoins() throws SQLException;
 
@@ -3030,7 +2780,6 @@
      *         statements.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsPositionedDelete() throws SQLException;
 
@@ -3041,7 +2790,6 @@
      *         statements, {@code false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsPositionedUpdate() throws SQLException;
 
@@ -3065,7 +2813,6 @@
      *         pairing is supported otherwise {@code false}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsResultSetConcurrency(int type, int concurrency)
             throws SQLException;
@@ -3082,7 +2829,6 @@
      *         if it isn't then {@code false}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsResultSetHoldability(int holdability)
             throws SQLException;
@@ -3099,7 +2845,6 @@
      *         false} otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsResultSetType(int type) throws SQLException;
 
@@ -3110,7 +2855,6 @@
      *         otherwise.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsSavepoints() throws SQLException;
 
@@ -3122,7 +2866,6 @@
      *         otherwise {@code false}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsSchemasInDataManipulation() throws SQLException;
 
@@ -3134,7 +2877,6 @@
      *         otherwise {@code false}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsSchemasInIndexDefinitions() throws SQLException;
 
@@ -3146,7 +2888,6 @@
      *         definition, otherwise {@code false}
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException;
 
@@ -3157,7 +2898,6 @@
      *         otherwise {@code false}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsSchemasInProcedureCalls() throws SQLException;
 
@@ -3168,7 +2908,6 @@
      *         otherwise {@code false}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsSchemasInTableDefinitions() throws SQLException;
 
@@ -3179,7 +2918,6 @@
      *         supported, otherwise {@code false}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsSelectForUpdate() throws SQLException;
 
@@ -3190,7 +2928,6 @@
      *         otherwise {@code false}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsStatementPooling() throws SQLException;
 
@@ -3202,7 +2939,6 @@
      *         escape syntax are supported, otherwise {@code false}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsStoredProcedures() throws SQLException;
 
@@ -3213,7 +2949,6 @@
      *         expressions.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsSubqueriesInComparisons() throws SQLException;
 
@@ -3224,7 +2959,6 @@
      *         expressions, otherwise {@code false}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsSubqueriesInExists() throws SQLException;
 
@@ -3235,7 +2969,6 @@
      *         otherwise {@code false}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsSubqueriesInIns() throws SQLException;
 
@@ -3245,7 +2978,6 @@
      * @return {@code true} if subqueries are supported, otherwise {@code false}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsSubqueriesInQuantifieds() throws SQLException;
 
@@ -3256,7 +2988,6 @@
      *         {@code false}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsTableCorrelationNames() throws SQLException;
 
@@ -3273,7 +3004,6 @@
      *         otherwise {@code false}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsTransactionIsolationLevel(int level)
             throws SQLException;
@@ -3284,13 +3014,11 @@
      * If transactions are not supported, then the {@code commit} method does
      * nothing and the transaction isolation level is always {@code
      * TRANSACTION_NONE}.
-     * </p>
-     * 
+     *
      * @return {@code true} if transactions are supported, otherwise {@code
      *         false}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsTransactions() throws SQLException;
 
@@ -3301,7 +3029,6 @@
      *         {@code false}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsUnion() throws SQLException;
 
@@ -3312,7 +3039,6 @@
      *         otherwise {@code false}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean supportsUnionAll() throws SQLException;
 
@@ -3328,7 +3054,6 @@
      *         false}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean updatesAreDetected(int type) throws SQLException;
 
@@ -3339,7 +3064,6 @@
      *         otherwise {@code false}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean usesLocalFilePerTable() throws SQLException;
 
@@ -3350,7 +3074,6 @@
      *         otherwise {@code false}.
      * @throws SQLException
      *             a database error occurred.
-     * @since Android 1.0
      */
     public boolean usesLocalFiles() throws SQLException;
 }
diff --git a/libcore/sql/src/main/java/java/sql/Date.java b/libcore/sql/src/main/java/java/sql/Date.java
index e506a43..90b5246 100644
--- a/libcore/sql/src/main/java/java/sql/Date.java
+++ b/libcore/sql/src/main/java/java/sql/Date.java
@@ -17,25 +17,20 @@
 
 package java.sql;
 
-import java.text.SimpleDateFormat;
-
 /**
  * A class which can consume and produce dates in SQL {@code Date} format.
  * <p>
  * Dates are represented in SQL as {@code yyyy-mm-dd}. Note that this date
  * format only deals with year, month and day values. There are no values for
  * hours, minutes, seconds.
- * </p>
- * This is unlike the familiar {@code java.util.Date} object, which also includes 
+ * <p>
+ * This is unlike the familiar {@code java.util.Date} object, which also includes
  * values for hours, minutes, seconds, and milliseconds.
  * <p>
  * Time points are handled as millisecond values - milliseconds since the Epoch,
  * January 1st 1970, 00:00:00.000 GMT. Time values passed to the {@code
  * java.sql.Date} class are "normalized" to the time 00:00:00.000 GMT on the
  * date implied by the time value.
- * </p>
- *  
- * @since Android 1.0
  */
 public class Date extends java.util.Date {
 
@@ -44,8 +39,8 @@
     /**
      * Constructs a {@code Date} object corresponding to the supplied year,
      * month and day.
-     * 
-     * @deprecated Please use the constructor {@link #Date(long)}.
+     *
+     * @deprecated Use the constructor {@link #Date(long)}.
      * @param theYear
      *            the year, specified as the year minus 1900. Must be in the
      *            range {@code [0,8099]}.
@@ -54,9 +49,7 @@
      *            the range {@code [0,11]}.
      * @param theDay
      *            the day in the month. Must be in the range {@code [1,31]}.
-     * @since Android 1.0
      */
-    @SuppressWarnings("deprecation")
     @Deprecated
     public Date(int theYear, int theMonth, int theDay) {
         super(theYear, theMonth, theDay);
@@ -72,7 +65,6 @@
      *            milliseconds) stored in the {@code Date} object is adjusted to
      *            correspond to 00:00:00 GMT on the day determined by the supplied
      *            time value.
-     * @since Android 1.0
      */
     public Date(long theDate) {
         super(normalizeTime(theDate));
@@ -84,9 +76,7 @@
      * @return does not return anything.
      * @throws IllegalArgumentException
      *             if this method is called.
-     * @since Android 1.0
      */
-    @SuppressWarnings("deprecation")
     @Deprecated
     @Override
     public int getHours() {
@@ -99,9 +89,7 @@
      * @return does not return anything.
      * @throws IllegalArgumentException
      *             if this method is called.
-     * @since Android 1.0
      */
-    @SuppressWarnings("deprecation")
     @Deprecated
     @Override
     public int getMinutes() {
@@ -114,9 +102,7 @@
      * @return does not return anything.
      * @throws IllegalArgumentException
      *             if this method is called.
-     * @since Android 1.0
      */
-    @SuppressWarnings("deprecation")
     @Deprecated
     @Override
     public int getSeconds() {
@@ -130,9 +116,7 @@
      *            the number of hours to set.
      * @throws IllegalArgumentException
      *             if this method is called.
-     * @since Android 1.0
      */
-    @SuppressWarnings("deprecation")
     @Deprecated
     @Override
     public void setHours(int theHours) {
@@ -146,9 +130,7 @@
      *            the number of minutes to set.
      * @throws IllegalArgumentException
      *             if this method is called.
-     * @since Android 1.0
      */
-    @SuppressWarnings("deprecation")
     @Deprecated
     @Override
     public void setMinutes(int theMinutes) {
@@ -162,9 +144,7 @@
      *            the number of seconds to set.
      * @throws IllegalArgumentException
      *             if this method is called.
-     * @since Android 1.0
      */
-    @SuppressWarnings("deprecation")
     @Deprecated
     @Override
     public void setSeconds(int theSeconds) {
@@ -177,7 +157,6 @@
      * 
      * @param theTime
      *            the time in milliseconds since the Epoch.
-     * @since Android 1.0
      */
     @Override
     public void setTime(long theTime) {
@@ -193,12 +172,31 @@
      * 
      * @return a string representation of the date in SQL format - {@code
      *         "yyyy-mm-dd"}.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
-        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); //$NON-NLS-1$
-        return dateFormat.format(this);
+        StringBuilder sb = new StringBuilder(10);
+
+        format((getYear() + 1900), 4, sb);
+        sb.append('-');
+        format((getMonth() + 1), 2, sb);
+        sb.append('-');
+        format(getDate(), 2, sb);
+
+        return sb.toString();
+    }
+
+    private static final String PADDING = "0000";  //$NON-NLS-1$
+
+    /* 
+    * Private method to format the time 
+    */ 
+    private void format(int date, int digits, StringBuilder sb) { 
+        String str = String.valueOf(date);
+        if (digits - str.length() > 0) {
+            sb.append(PADDING.substring(0, digits - str.length()));
+        }
+        sb.append(str); 
     }
 
     /**
@@ -212,7 +210,6 @@
      * @throws IllegalArgumentException
      *             if the format of the supplied string does not match the SQL
      *             format.
-     * @since Android 1.0
      */
     public static Date valueOf(String dateString) {
         if (dateString == null) {
diff --git a/libcore/sql/src/main/java/java/sql/Driver.java b/libcore/sql/src/main/java/java/sql/Driver.java
index c0499cb..207aec5 100644
--- a/libcore/sql/src/main/java/java/sql/Driver.java
+++ b/libcore/sql/src/main/java/java/sql/Driver.java
@@ -27,15 +27,12 @@
  * {@code xxxx:yyyy}" is referred to as the <i>subprotocol</i> and is normally
  * the same for all of a particular driver. " {@code SpecificData}" is a string
  * which identifies the particular data source that the driver should use.
- * </p>
  * <p>
  * A driver needs to be registered with a {@link DriverManager}. It is
  * registered and instantiated by calling {@code Class.forName("DriverURL")}
  * with the URL string as argument.
- * </p>
+ *
  * @see DriverManager
- *  
- * @since Android 1.0
  */
 public interface Driver {
 
@@ -51,7 +48,6 @@
      *         the subprotocol specified by the driver.
      * @throws SQLException
      *          if a database error occurs.
-     * @since Android 1.0
      */
     public boolean acceptsURL(String url) throws SQLException;
 
@@ -70,7 +66,6 @@
      * @return the connection to the database.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public Connection connect(String url, Properties info) throws SQLException;
 
@@ -78,7 +73,6 @@
      * Gets the driver's major version number.
      * 
      * @return the major version number of the driver - typically starts at 1.
-     * @since Android 1.0
      */
     public int getMajorVersion();
 
@@ -86,7 +80,6 @@
      * Gets the driver's minor version number.
      * 
      * @return the minor version number of the driver - typically starts at 0.
-     * @since Android 1.0
      */
     public int getMinorVersion();
 
@@ -97,8 +90,7 @@
      * the client of the driver must supply in order to establish a connection
      * to a database. Note that the returned array of properties may change
      * depending on the supplied list of property values.
-     * </p>
-     * 
+     *
      * @param url
      *            the URL of the database. An application may call this method
      *            iteratively as the property list is built up - for example,
@@ -113,7 +105,6 @@
      *         connect to the database.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public DriverPropertyInfo[] getPropertyInfo(String url, Properties info)
             throws SQLException;
@@ -125,11 +116,9 @@
      * <p>
      * A driver may not be fully compliant if the underlying database has
      * limited functionality.
-     * </p>
-     * 
+     *
      * @return {@code true} if the driver is fully JDBC compliant, {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public boolean jdbcCompliant();
 
diff --git a/libcore/sql/src/main/java/java/sql/DriverManager.java b/libcore/sql/src/main/java/java/sql/DriverManager.java
index afcf2f5..1c41a46 100644
--- a/libcore/sql/src/main/java/java/sql/DriverManager.java
+++ b/libcore/sql/src/main/java/java/sql/DriverManager.java
@@ -17,14 +17,16 @@
 
 package java.sql;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Properties;
 import java.util.Enumeration;
 import java.util.Iterator;
-import java.util.Set;
 import java.io.PrintStream;
 import java.io.PrintWriter;
-import java.util.HashSet;
 import java.util.Vector;
+import java.security.AccessController;
+import org.apache.harmony.luni.util.PriviAction;
 import org.apache.harmony.sql.internal.nls.Messages;
 // BEGIN android-changed
 import dalvik.system.VMStack;
@@ -36,9 +38,6 @@
  * The {@code DriverManager} class loads JDBC drivers during its initialization,
  * from the list of drivers referenced by the system property {@code
  * "jdbc.drivers"}.
- * </p>
- *  
- * @since Android 1.0
  */
 public class DriverManager {
 
@@ -57,10 +56,11 @@
      * Set to hold Registered Drivers - initial capacity 10 drivers (will expand
      * automatically if necessary.
      */
-    private static final Set<Driver> theDriverSet = new HashSet<Driver>(10);
+    private static final List<Driver> theDrivers = new ArrayList<Driver>(10);
 
     // Permission for setting log
-    private static final SQLPermission logPermission = new SQLPermission("setLog"); //$NON-NLS-1$
+    private static final SQLPermission logPermission = new SQLPermission(
+            "setLog"); //$NON-NLS-1$
 
     /*
      * Load drivers on initialization
@@ -74,7 +74,9 @@
      * it is defined.
      */
     private static void loadInitialDrivers() {
-        String theDriverList = System.getProperty("jdbc.drivers", null); //$NON-NLS-1$
+        String theDriverList = AccessController
+                .doPrivileged(new PriviAction<String>("jdbc.drivers", null)); //$NON-NLS-1$
+
         if (theDriverList == null) {
             return;
         }
@@ -112,14 +114,12 @@
      * <p>
      * If the removal succeeds, the {@code DriverManager} will not use this
      * driver in the future when asked to get a {@code Connection}.
-     * </p>
-     * 
+     *
      * @param driver
      *            the JDBC driver to remove.
      * @throws SQLException
      *             if there is a problem interfering with accessing the
      *             database.
-     * @since Android 1.0
      */
     public static void deregisterDriver(Driver driver) throws SQLException {
         if (driver == null) {
@@ -130,11 +130,12 @@
         // END android-changed
 
         if (!DriverManager.isClassFromClassLoader(driver, callerClassLoader)) {
-            // sql.1=DriverManager: calling class not authorized to deregister JDBC driver
+            // sql.1=DriverManager: calling class not authorized to deregister
+            // JDBC driver
             throw new SecurityException(Messages.getString("sql.1")); //$NON-NLS-1$
         } // end if
-        synchronized (theDriverSet) {
-            theDriverSet.remove(driver);
+        synchronized (theDrivers) {
+            theDrivers.remove(driver);
         }
     }
 
@@ -148,7 +149,6 @@
      * @throws SQLException
      *             if there is an error while attempting to connect to the
      *             database identified by the URL.
-     * @since Android 1.0
      */
     public static Connection getConnection(String url) throws SQLException {
         return getConnection(url, new Properties());
@@ -171,7 +171,6 @@
      * @throws SQLException
      *             if there is an error while attempting to connect to the
      *             database identified by the URL.
-     * @since Android 1.0
      */
     public static Connection getConnection(String url, Properties info)
             throws SQLException {
@@ -182,13 +181,13 @@
             // sql.5=The url cannot be null
             throw new SQLException(Messages.getString("sql.5"), sqlState); //$NON-NLS-1$
         }
-        synchronized (theDriverSet) {
+        synchronized (theDrivers) {
             /*
              * Loop over the drivers in the DriverSet checking to see if one can
              * open a connection to the supplied URL - return the first
              * connection which is returned
              */
-            for (Driver theDriver : theDriverSet) {
+            for (Driver theDriver : theDrivers) {
                 Connection theConnection = theDriver.connect(url, info);
                 if (theConnection != null) {
                     return theConnection;
@@ -214,15 +213,14 @@
      * @throws SQLException
      *             if there is an error while attempting to connect to the
      *             database identified by the URL.
-     * @since Android 1.0
      */
     public static Connection getConnection(String url, String user,
             String password) throws SQLException {
         Properties theProperties = new Properties();
-        if(null != user){
+        if (null != user) {
             theProperties.setProperty("user", user); //$NON-NLS-1$
         }
-        if(null != password){
+        if (null != password) {
             theProperties.setProperty("password", password); //$NON-NLS-1$
         }
         return getConnection(url, theProperties);
@@ -243,13 +241,13 @@
         ClassLoader callerClassLoader = VMStack.getCallingClassLoader();
         // END android-changed
 
-        synchronized (theDriverSet) {
+        synchronized (theDrivers) {
             /*
              * Loop over the drivers in the DriverSet checking to see if one
              * does understand the supplied URL - return the first driver which
              * does understand the URL
              */
-            Iterator<Driver> theIterator = theDriverSet.iterator();
+            Iterator<Driver> theIterator = theDrivers.iterator();
             while (theIterator.hasNext()) {
                 Driver theDriver = theIterator.next();
                 if (theDriver.acceptsURL(url)
@@ -261,8 +259,8 @@
         }
         // If no drivers understand the URL, throw an SQLException
         // sql.6=No suitable driver
-        //SQLState: 08 - connection exception
-        //001 - SQL-client unable to establish SQL-connection
+        // SQLState: 08 - connection exception
+        // 001 - SQL-client unable to establish SQL-connection
         throw new SQLException(Messages.getString("sql.6"), "08001"); //$NON-NLS-1$ //$NON-NLS-2$
     }
 
@@ -272,7 +270,6 @@
      * 
      * @return An {@code Enumeration} containing all the currently loaded JDBC
      *         {@code Drivers}.
-     * @since Android 1.0
      */
     public static Enumeration<Driver> getDrivers() {
         // BEGIN android-changed
@@ -282,13 +279,13 @@
          * Synchronize to avoid clashes with additions and removals of drivers
          * in the DriverSet
          */
-        synchronized (theDriverSet) {
+        synchronized (theDrivers) {
             /*
              * Create the Enumeration by building a Vector from the elements of
              * the DriverSet
              */
             Vector<Driver> theVector = new Vector<Driver>();
-            Iterator<Driver> theIterator = theDriverSet.iterator();
+            Iterator<Driver> theIterator = theDrivers.iterator();
             while (theIterator.hasNext()) {
                 Driver theDriver = theIterator.next();
                 if (DriverManager.isClassFromClassLoader(theDriver,
@@ -304,7 +301,6 @@
      * Returns the login timeout when connecting to a database in seconds.
      * 
      * @return the login timeout in seconds.
-     * @since Android 1.0
      */
     public static int getLoginTimeout() {
         return loginTimeout;
@@ -313,10 +309,9 @@
     /**
      * Gets the log {@code PrintStream} used by the {@code DriverManager} and
      * all the JDBC Drivers.
-     * 
+     *
      * @deprecated use {@link #getLogWriter()} instead.
      * @return the {@code PrintStream} used for logging activities.
-     * @since Android 1.0
      */
     @Deprecated
     public static PrintStream getLogStream() {
@@ -328,7 +323,6 @@
      * 
      * @return A {@code PrintWriter} object used as the log writer. {@code null}
      *         if no log writer is set.
-     * @since Android 1.0
      */
     public static PrintWriter getLogWriter() {
         return thePrintWriter;
@@ -340,7 +334,6 @@
      * 
      * @param message
      *            the message to print to the JDBC log stream.
-     * @since Android 1.0
      */
     public static void println(String message) {
         if (thePrintWriter != null) {
@@ -362,8 +355,7 @@
      * <p>
      * A newly loaded JDBC driver class should register itself with the
      * {@code DriverManager} by calling this method.
-     * </p>
-     * 
+     *
      * @param driver
      *            the {@code Driver} to register with the {@code DriverManager}.
      * @throws SQLException
@@ -373,8 +365,8 @@
         if (driver == null) {
             throw new NullPointerException();
         }
-        synchronized (theDriverSet) {
-            theDriverSet.add(driver);
+        synchronized (theDrivers) {
+            theDrivers.add(driver);
         }
     }
 
@@ -383,7 +375,6 @@
      * 
      * @param seconds
      *            seconds until timeout. 0 indicates wait forever.
-     * @since Android 1.0
      */
     public static void setLoginTimeout(int seconds) {
         loginTimeout = seconds;
@@ -393,11 +384,10 @@
     /**
      * Sets the print stream to use for logging data from the {@code
      * DriverManager} and the JDBC drivers.
-     * 
+     *
      * @deprecated Use {@link #setLogWriter} instead.
      * @param out
      *            the {@code PrintStream} to use for logging.
-     * @since Android 1.0
      */
     @Deprecated
     public static void setLogStream(PrintStream out) {
@@ -411,7 +401,6 @@
      * 
      * @param out
      *            the {@code PrintWriter} to be used.
-     * @since Android 1.0
      */
     public static void setLogWriter(PrintWriter out) {
         checkLogSecurity();
@@ -442,13 +431,13 @@
      */
     private static boolean isClassFromClassLoader(Object theObject,
             ClassLoader theClassLoader) {
-    
+
         if ((theObject == null) || (theClassLoader == null)) {
             return false;
         }
-    
+
         Class<?> objectClass = theObject.getClass();
-    
+
         try {
             Class<?> checkClass = Class.forName(objectClass.getName(), true,
                     theClassLoader);
diff --git a/libcore/sql/src/main/java/java/sql/DriverPropertyInfo.java b/libcore/sql/src/main/java/java/sql/DriverPropertyInfo.java
index 3875abb..aa18585 100644
--- a/libcore/sql/src/main/java/java/sql/DriverPropertyInfo.java
+++ b/libcore/sql/src/main/java/java/sql/DriverPropertyInfo.java
@@ -22,38 +22,28 @@
  * This class is returned by the
  * {@link Driver#getPropertyInfo(String, java.util.Properties)} method and
  * allows for the advanced connection handling.
- * 
- * @since Android 1.0
  */
 public class DriverPropertyInfo {
 
     /**
      * If the value member can be chosen from a set of possible values, they are
      * contained here. Otherwise choices is {@code null}.
-     * 
-     * @since Android 1.0
      */
     public String[] choices;
 
     /**
      * A description of the property. May be {@code null}.
-     * 
-     * @since Android 1.0
      */
     public String description;
 
     /**
      * The name of the property.
-     * 
-     * @since Android 1.0
      */
     public String name;
 
     /**
-     * {@code True} when the value member must be provided during {@code
-     * Driver.connect}. {@code False} otherwise.
-     * 
-     * @since Android 1.0
+     * {@code true} when the value member must be provided during {@code
+     * Driver.connect}. {@code false} otherwise.
      */
     public boolean required;
 
@@ -61,8 +51,6 @@
      * The current value associated with this property. It is depending on the
      * data gathered by the {@code getPropertyInfo} method, the general Java
      * environment and the driver's default values.
-     * 
-     * @since Android 1.0
      */
     public String value;
 
@@ -74,7 +62,6 @@
      *            The property name.
      * @param value
      *            The property value.
-     * @since Android 1.0
      */
     public DriverPropertyInfo(String name, String value) {
         this.name = name;
diff --git a/libcore/sql/src/main/java/java/sql/ParameterMetaData.java b/libcore/sql/src/main/java/java/sql/ParameterMetaData.java
index 94901ae..1e241c6 100644
--- a/libcore/sql/src/main/java/java/sql/ParameterMetaData.java
+++ b/libcore/sql/src/main/java/java/sql/ParameterMetaData.java
@@ -20,58 +20,42 @@
 /**
  * An interface used to get information about the types and properties of
  * parameters in a {@code PreparedStatement}.
- *  
- * @since Android 1.0
  */
 public interface ParameterMetaData {
 
     /**
      * Indicates that the parameter mode is {@code IN}.
-     * 
-     * @since Android 1.0
      */
     public static final int parameterModeIn = 1;
 
     /**
      * Indicates that the parameter mode is {@code INOUT}.
-     * 
-     * @since Android 1.0
      */
     public static final int parameterModeInOut = 2;
 
     /**
      * Indicates that the parameter mode is {@code OUT}.
-     * 
-     * @since Android 1.0
      */
     public static final int parameterModeOut = 4;
 
     /**
      * Indicates that the parameter mode is not known.
-     * 
-     * @since Android 1.0
      */
     public static final int parameterModeUnknown = 0;
 
     /**
      * Indicates that a parameter is not permitted to be {@code NULL}.
-     * 
-     * @since Android 1.0
      */
     public static final int parameterNoNulls = 0;
 
     /**
      * Indicates that a parameter is permitted to be {@code NULL}.
-     * 
-     * @since Android 1.0
      */
     public static final int parameterNullable = 1;
 
     /**
      * Indicates that whether a parameter is allowed to be {@code null} or not
      * is not known.
-     * 
-     * @since Android 1.0
      */
     public static final int parameterNullableUnknown = 2;
 
@@ -87,7 +71,6 @@
      *         between SQL types and Java objects.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public String getParameterClassName(int paramIndex) throws SQLException;
 
@@ -98,7 +81,6 @@
      * @return the number of parameters.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public int getParameterCount() throws SQLException;
 
@@ -117,7 +99,6 @@
      * @return the parameter's mode.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public int getParameterMode(int paramIndex) throws SQLException;
 
@@ -131,7 +112,6 @@
      *         java.sql.Types}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public int getParameterType(int paramIndex) throws SQLException;
 
@@ -146,7 +126,6 @@
      *         Defined Type</i> (UDT).
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public String getParameterTypeName(int paramIndex) throws SQLException;
 
@@ -160,7 +139,6 @@
      *         {@code 0} if the parameter is not a numeric type.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public int getPrecision(int paramIndex) throws SQLException;
 
@@ -175,7 +153,6 @@
      *         the parameter. {@code 0} if the parameter is not a numeric type.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public int getScale(int paramIndex) throws SQLException;
 
@@ -194,7 +171,6 @@
      * @return the int code indicating the nullability of the parameter.
      * @throws SQLException
      *             if a database error is encountered.
-     * @since Android 1.0
      */
     public int isNullable(int paramIndex) throws SQLException;
 
@@ -208,7 +184,6 @@
      *         {@code false} otherwise.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public boolean isSigned(int paramIndex) throws SQLException;
 }
diff --git a/libcore/sql/src/main/java/java/sql/PreparedStatement.java b/libcore/sql/src/main/java/java/sql/PreparedStatement.java
index ab81871..1cd9668 100644
--- a/libcore/sql/src/main/java/java/sql/PreparedStatement.java
+++ b/libcore/sql/src/main/java/java/sql/PreparedStatement.java
@@ -28,14 +28,10 @@
  * <p>
  * An SQL Statement is put into a {@code PreparedStatement} and is precompiled
  * so that it can be executed efficiently multiple times.
- * </p>
  * <p>
  * Setter methods are supplied in the {@code PreparedStatement} interface for
  * the setting of {@code IN} parameters for the statement. The setter method
  * used for each {@code IN} parameter must match the parameter's type.
- * </p>
- *  
- * @since Android 1.0
  */
 public interface PreparedStatement extends Statement {
 
@@ -44,7 +40,6 @@
      * 
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void addBatch() throws SQLException;
 
@@ -55,11 +50,9 @@
      * {@code Statement}. Setting a parameter value replaces the previous value. This
      * method clears the values for all parameters, releasing all resources used
      * by those parameters.
-     * </p>
-     * 
+     *
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void clearParameters() throws SQLException;
 
@@ -72,14 +65,12 @@
      * {@code getResultSet} or {@code getUpdateCount} are used to retrieve 
      * the first result, and the second and subsequent results are 
      * retrieved with {@code getMoreResults}.
-     * </p>
-     * 
+     *
      * @return {@code true} if the result of the execution is a {@code
      *         ResultSet}, {@code false} if there is no result or if the result
      *         is an update count.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public boolean execute() throws SQLException;
 
@@ -91,7 +82,6 @@
      * @throws SQLException
      *             if a database error happens or if the SQL statement does not
      *             produce a {@code ResultSet}.
-     * @since Android 1.0
      */
     public ResultSet executeQuery() throws SQLException;
 
@@ -105,7 +95,6 @@
      * @throws SQLException
      *             if a database error happens or if the SQL statement returns a
      *             {@code ResultSet}.
-     * @since Android 1.0
      */
     public int executeUpdate() throws SQLException;
 
@@ -117,14 +106,12 @@
      * executing the {@code PreparedStatement}, because the {@code
      * PreparedStatement} is precompiled. As a result the metadata can be
      * queried ahead of time without actually executing the statement.
-     * </p>
-     * 
+     *
      * @return a {@code ResultSetMetaData} object with the information about the
      *         columns of the {@code ResultSet}, if the driver can return a
      *         {@code ResultSetMetaData}. {@code null} otherwise.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public ResultSetMetaData getMetaData() throws SQLException;
 
@@ -136,7 +123,6 @@
      *         PreparedStatement}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public ParameterMetaData getParameterMetaData() throws SQLException;
 
@@ -152,7 +138,6 @@
      * @throws SQLException
      *             if a database error happens.
      * @see Array
-     * @since Android 1.0
      */
     public void setArray(int parameterIndex, Array theArray)
             throws SQLException;
@@ -161,12 +146,11 @@
      * Sets the value of a specified parameter to the content of a supplied
      * {@code InputStream}, which has a specified number of bytes.
      * <p>
-     * This is a good method for setting an SQL {@code LONVARCHAR} parameter
+     * This is a good method for setting an SQL {@code LONGVARCHAR} parameter
      * where the length of the data is large. Data is read from the {@code
      * InputStream} until end-of-file is reached or the specified number of
      * bytes is copied.
-     * </p>
-     * 
+     *
      * @param parameterIndex
      *            the parameter number index, where the first parameter has
      *            index 1.
@@ -178,7 +162,6 @@
      *            parameter.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void setAsciiStream(int parameterIndex, InputStream theInputStream,
             int length) throws SQLException;
@@ -196,7 +179,6 @@
      * @throws SQLException
      *             if a database error happens.
      * @see java.math.BigDecimal
-     * @since Android 1.0
      */
     public void setBigDecimal(int parameterIndex, BigDecimal theBigDecimal)
             throws SQLException;
@@ -207,8 +189,7 @@
      * <p>
      * Use this method when a large amount of data needs to be set into a
      * {@code LONGVARBINARY} parameter.
-     * </p>
-     * 
+     *
      * @param parameterIndex
      *            the parameter number index, where the first parameter has
      *            index 1.
@@ -220,7 +201,6 @@
      *            parameter.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void setBinaryStream(int parameterIndex, InputStream theInputStream,
             int length) throws SQLException;
@@ -236,7 +216,6 @@
      *            parameterIndex} is set.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      * @see Blob
      */
     public void setBlob(int parameterIndex, Blob theBlob) throws SQLException;
@@ -253,7 +232,6 @@
      *            parameterIndex} is set.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void setBoolean(int parameterIndex, boolean theBoolean)
             throws SQLException;
@@ -269,7 +247,6 @@
      *            parameterIndex} is set.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void setByte(int parameterIndex, byte theByte) throws SQLException;
 
@@ -286,7 +263,6 @@
      *            parameterIndex} is set.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void setBytes(int parameterIndex, byte[] theBytes)
             throws SQLException;
@@ -298,8 +274,7 @@
      * Data is read from the {@code
      * Reader} until end-of-file is reached or the specified number of
      * characters are copied.
-     * </p>
-     * 
+     *
      * @param parameterIndex
      *            the parameter number index, where the first parameter has
      *            index 1
@@ -309,7 +284,6 @@
      *            the number of characters to be read.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void setCharacterStream(int parameterIndex, Reader reader, int length)
             throws SQLException;
@@ -325,7 +299,6 @@
      *            parameter at {@code parameterIndex} is set.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void setClob(int parameterIndex, Clob theClob) throws SQLException;
 
@@ -341,7 +314,6 @@
      *            parameterIndex} is set.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void setDate(int parameterIndex, Date theDate) throws SQLException;
 
@@ -366,7 +338,6 @@
      *             if a database error happens.
      * @see Date
      * @see java.util.Calendar
-     * @since Android 1.0
      */
     public void setDate(int parameterIndex, Date theDate, Calendar cal)
             throws SQLException;
@@ -383,7 +354,6 @@
      *            parameterIndex} is set.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void setDouble(int parameterIndex, double theDouble)
             throws SQLException;
@@ -399,7 +369,6 @@
      *            the {@code float} value to update the parameter.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void setFloat(int parameterIndex, float theFloat)
             throws SQLException;
@@ -415,7 +384,6 @@
      *            parameterIndex} is set.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void setInt(int parameterIndex, int theInt) throws SQLException;
 
@@ -430,7 +398,6 @@
      *            parameterIndex} is set.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void setLong(int parameterIndex, long theLong) throws SQLException;
 
@@ -447,7 +414,6 @@
      *            java.sql.Types}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void setNull(int parameterIndex, int sqlType) throws SQLException;
 
@@ -461,8 +427,7 @@
      * SQL type name when supplying a {@code NULL} UDT or REF. For a UDT, the
      * type name is the type name of the parameter itself, but for a REF
      * parameter the type name is the type name of the referenced type.
-     * </p>
-     * 
+     *
      * @param paramIndex
      *            the parameter number index, where the first parameter has
      *            index 1.
@@ -475,7 +440,6 @@
      * @throws SQLException
      *             if a database error happens.
      * @see Types
-     * @since Android 1.0
      */
     public void setNull(int paramIndex, int sqlType, String typeName)
             throws SQLException;
@@ -493,8 +457,7 @@
      * object's class implements {@code Ref}, {@code Blob}, {@code Clob},
      * {@code Struct}, or {@code Array}, the driver passes it to the database as
      * a value of the corresponding SQL type.
-     * </p>
-     * 
+     *
      * @param parameterIndex
      *            the parameter number index, where the first parameter has
      *            index 1.
@@ -503,7 +466,6 @@
      *            {@code parameterIndex} is set.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void setObject(int parameterIndex, Object theObject)
             throws SQLException;
@@ -518,8 +480,7 @@
      * object's class implements {@code Ref}, {@code Blob}, {@code Clob},
      * {@code Struct}, or {@code Array}, the driver will pass it to the database
      * in the form of the relevant SQL type.
-     * </p>
-     * 
+     *
      * @param parameterIndex
      *            the parameter index, where the first parameter has index 1.
      * @param theObject
@@ -530,7 +491,6 @@
      *            java.sql.Types}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void setObject(int parameterIndex, Object theObject,
             int targetSqlType) throws SQLException;
@@ -545,8 +505,7 @@
      * object's class implements {@code Ref}, {@code Blob}, {@code Clob},
      * {@code Struct}, or {@code Array}, the driver will pass it to the database
      * in the form of the relevant SQL type.
-     * </p>
-     * 
+     *
      * @param parameterIndex
      *            the parameter index, where the first parameter has index 1.
      * @param theObject
@@ -561,7 +520,6 @@
      *            java.sql.Types.NUMERIC} - ignored for all other types.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void setObject(int parameterIndex, Object theObject,
             int targetSqlType, int scale) throws SQLException;
@@ -579,7 +537,6 @@
      * @throws SQLException
      *             if a database error happens.
      * @see Ref
-     * @since Android 1.0
      */
     public void setRef(int parameterIndex, Ref theRef) throws SQLException;
 
@@ -595,7 +552,6 @@
      *            parameterIndex} is set.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void setShort(int parameterIndex, short theShort)
             throws SQLException;
@@ -611,7 +567,6 @@
      *            set.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void setString(int parameterIndex, String theString)
             throws SQLException;
@@ -628,7 +583,6 @@
      *            {@code parameterIndex} is set.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void setTime(int parameterIndex, Time theTime) throws SQLException;
 
@@ -639,8 +593,7 @@
      * The driver uses the supplied {@code Calendar} to create the SQL {@code
      * TIME} value, which allows it to use a custom timezone - otherwise the
      * driver uses the default timezone of the Java virtual machine.
-     * </p>
-     * 
+     *
      * @param parameterIndex
      *            the parameter number index, where the first parameter has 
      *            index 1.
@@ -654,7 +607,6 @@
      *             if a database error happens.
      * @see Time
      * @see java.util.Calendar
-     * @since Android 1.0
      */
     public void setTime(int parameterIndex, Time theTime, Calendar cal)
             throws SQLException;
@@ -671,7 +623,6 @@
      *            parameterIndex} is set.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void setTimestamp(int parameterIndex, Timestamp theTimestamp)
             throws SQLException;
@@ -683,8 +634,7 @@
      * The driver uses the supplied {@code Calendar} to create the SQL {@code
      * TIMESTAMP} value, which allows it to use a custom timezone - otherwise
      * the driver uses the default timezone of the Java virtual machine.
-     * </p>
-     * 
+     *
      * @param parameterIndex
      *            the parameter number index, where the first parameter has
      *            index 1.
@@ -698,7 +648,6 @@
      *             if a database error happens.
      * @see Timestamp
      * @see java.util.Calendar
-     * @since Android 1.0
      */
     public void setTimestamp(int parameterIndex, Timestamp theTimestamp,
             Calendar cal) throws SQLException;
@@ -736,7 +685,6 @@
      * @throws SQLException
      *             if a database error happens.
      * @see URL
-     * @since Android 1.0
      */
     public void setURL(int parameterIndex, URL theURL) throws SQLException;
 }
diff --git a/libcore/sql/src/main/java/java/sql/Ref.java b/libcore/sql/src/main/java/java/sql/Ref.java
index 2ceac8b..cbc5454 100644
--- a/libcore/sql/src/main/java/java/sql/Ref.java
+++ b/libcore/sql/src/main/java/java/sql/Ref.java
@@ -29,11 +29,9 @@
  * the database supports the {@code Ref} type, it is not typically 
  * necessary to get the underlying object before using it in a method call -
  * the {@code Ref} object can be used in place of the data structure.
- * </p>
+ * <p>
  * A {@code Ref} object is stored into the database using the
  * {@link PreparedStatement#setRef(int, Ref)} method.
- *  
- * @since Android 1.0
  */
 public interface Ref {
 
@@ -44,7 +42,6 @@
      * @return the fully qualified name of the SQL structured type.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public String getBaseTypeName() throws SQLException;
 
@@ -55,7 +52,6 @@
      *         structured type.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public Object getObject() throws SQLException;
 
@@ -69,7 +65,6 @@
      *         structured type.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public Object getObject(Map<String, Class<?>> map) throws SQLException;
 
@@ -82,7 +77,6 @@
      *            that this {@code Ref} references.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public void setObject(Object value) throws SQLException;
 }
diff --git a/libcore/sql/src/main/java/java/sql/ResultSet.java b/libcore/sql/src/main/java/java/sql/ResultSet.java
index f33f9de..8ecbe6c 100644
--- a/libcore/sql/src/main/java/java/sql/ResultSet.java
+++ b/libcore/sql/src/main/java/java/sql/ResultSet.java
@@ -34,7 +34,6 @@
  * use the {@code next} method. The {@code next} method returns {@code true} as
  * long as there are more rows in the {@code ResultSet}, otherwise it returns
  * {@code false}.
- * </p>
  * <p>
  * The default type of {@code ResultSet} can not be updated and its cursor can
  * only advance forward through the rows of data. This means that it is only
@@ -42,7 +41,6 @@
  * are implemented: an <i>updatable</i> type and also types where the cursor can
  * be <i>scrolled</i> forward and backward through the rows of data. How such a
  * {@code ResultSet} is created is demonstrated in the following example:
- * </p>
  * <ul>
  * <dd>
  *         {@code Connection con;}</dd>
@@ -63,13 +61,11 @@
  * is better to use column indexes. Ideally the columns should be read
  * left-to-right and read once only, since not all databases are optimized to
  * handle other techniques of reading the data.
- * </p>
  * <p>
  * When reading data via the appropriate getter methods, the JDBC driver maps
  * the SQL data retrieved from the database to the Java type implied by the
  * method invoked by the application. The JDBC specification has a table for the
  * mappings from SQL types to Java types.
- * </p>
  * <p>
  * There are also methods for writing data into the {@code ResultSet}, such as
  * {@code updateInt} and {@code updateString}. The update methods can be used
@@ -80,94 +76,70 @@
  * method. For insertion of new rows, the cursor is first moved to a special row
  * called the <i>Insert Row</i>, data is added using the update methods,
  * followed by calling the {@code ResultSet.insertRow} method.
- * </p>
  * <p>
  * A {@code ResultSet} is closed if the statement which generated it closes, the
  * statement is executed again, or the same statement's next {@code ResultSet} 
  * is retrieved (if the statement returned of multiple results).
- * </p>
- * 
- * @since Android 1.0
  */
 public interface ResultSet {
 
     /**
      * A constant used to indicate that a {@code ResultSet} object must be
      * closed when the method {@code Connection.commit} is invoked.
-     * 
-     * @since Android 1.0
      */
     public static final int CLOSE_CURSORS_AT_COMMIT = 2;
 
     /**
      * A constant used to indicate that a {@code ResultSet} object must not be
      * closed when the method {@code Connection.commit} is invoked.
-     * 
-     * @since Android 1.0
      */
     public static final int HOLD_CURSORS_OVER_COMMIT = 1;
 
     /**
      * A constant used to indicate the concurrency mode for a {@code ResultSet}
      * object that cannot be updated.
-     * 
-     * @since Android 1.0
      */
     public static final int CONCUR_READ_ONLY = 1007;
 
     /**
      * A constant used to indicate the concurrency mode for a {@code ResultSet}
      * object that can be updated.
-     * 
-     * @since Android 1.0
      */
     public static final int CONCUR_UPDATABLE = 1008;
 
     /**
      * A constant used to indicate processing of the rows of a {@code ResultSet}
      * in the forward direction, first to last.
-     * 
-     * @since Android 1.0
      */
     public static final int FETCH_FORWARD = 1000;
 
     /**
      * A constant used to indicate processing of the rows of a {@code ResultSet}
      * in the reverse direction, last to first.
-     * 
-     * @since Android 1.0
      */
     public static final int FETCH_REVERSE = 1001;
 
     /**
      * A constant used to indicate that the order of processing of the rows of a
      * {@code ResultSet} is unknown.
-     * 
-     * @since Android 1.0
      */
     public static final int FETCH_UNKNOWN = 1002;
 
     /**
      * A constant used to indicate a {@code ResultSet} object whose cursor can
      * only move forward.
-     * 
-     * @since Android 1.0
      */
     public static final int TYPE_FORWARD_ONLY = 1003;
 
     /**
      * A constant used to indicate a {@code ResultSet} object which is
      * scrollable but is insensitive to changes made by others.
-     * 
-     * @since Android 1.0
      */
     public static final int TYPE_SCROLL_INSENSITIVE = 1004;
 
     /**
      * A constant used to indicate a {@code ResultSet} object which is
      * scrollable and sensitive to changes made by others.
-     * 
-     * @since Android 1.0
      */
     public static final int TYPE_SCROLL_SENSITIVE = 1005;
 
@@ -181,7 +153,6 @@
      *         ResultSet}, {@code false} otherwise.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public boolean absolute(int row) throws SQLException;
 
@@ -190,7 +161,6 @@
      * 
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void afterLast() throws SQLException;
 
@@ -200,7 +170,6 @@
      * 
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void beforeFirst() throws SQLException;
 
@@ -209,7 +178,6 @@
      * 
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void cancelRowUpdates() throws SQLException;
 
@@ -218,7 +186,6 @@
      * 
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void clearWarnings() throws SQLException;
 
@@ -232,7 +199,6 @@
      * 
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void close() throws SQLException;
 
@@ -242,7 +208,6 @@
      * 
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void deleteRow() throws SQLException;
 
@@ -256,7 +221,6 @@
      *         name.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public int findColumn(String columnName) throws SQLException;
 
@@ -267,7 +231,6 @@
      *         false} if the {@code ResultSet} contains no rows.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public boolean first() throws SQLException;
 
@@ -280,7 +243,6 @@
      * @return a {@code java.sql.Array} with the data from the column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public Array getArray(int columnIndex) throws SQLException;
 
@@ -293,7 +255,6 @@
      * @return a {@code java.sql.Array} with the data from the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public Array getArray(String colName) throws SQLException;
 
@@ -306,7 +267,6 @@
      * @return an {@code InputStream} with the data from the column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public InputStream getAsciiStream(int columnIndex) throws SQLException;
 
@@ -319,7 +279,6 @@
      * @return an {@code InputStream} with the data from the column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public InputStream getAsciiStream(String columnName) throws SQLException;
 
@@ -332,7 +291,6 @@
      * @return a {@code BigDecimal} with the value of the column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public BigDecimal getBigDecimal(int columnIndex) throws SQLException;
 
@@ -349,7 +307,6 @@
      * @return a {@code BigDecimal} with the value of the column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     @Deprecated
     public BigDecimal getBigDecimal(int columnIndex, int scale)
@@ -364,7 +321,6 @@
      * @return a BigDecimal with value of the column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public BigDecimal getBigDecimal(String columnName) throws SQLException;
 
@@ -381,7 +337,6 @@
      * @return a BigDecimal with value of the column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     @Deprecated
     public BigDecimal getBigDecimal(String columnName, int scale)
@@ -395,15 +350,13 @@
      * data in the {@code InputStream} should be read before getting data from
      * any other column. A further call to a getter method will implicitly close
      * the {@code InputStream}.
-     * </p>
-     * 
+     *
      * @param columnIndex
      *            the index of the column to read.
      * @return an {@code InputStream} with the data from the column. If the
      *         column value is SQL {@code NULL}, {@code null} is returned.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public InputStream getBinaryStream(int columnIndex) throws SQLException;
 
@@ -414,15 +367,13 @@
      * data in the {@code InputStream} should be read before getting data from
      * any other column. A further call to a getter method will implicitly close
      * the {@code InputStream}.
-     * </p>
-     * 
+     *
      * @param columnName
      *            the name of the column to read.
      * @return an {@code InputStream} with the data from the column if the
      *         column value is SQL {@code NULL}, {@code null} is returned.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public InputStream getBinaryStream(String columnName) throws SQLException;
 
@@ -435,7 +386,6 @@
      * @return a {@code java.sql.Blob} with the value of the column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public Blob getBlob(int columnIndex) throws SQLException;
 
@@ -448,7 +398,6 @@
      * @return a {@code java.sql.Blob} with the value of the column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public Blob getBlob(String columnName) throws SQLException;
 
@@ -462,7 +411,6 @@
      *         {@code NULL}, {@code false} is returned.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public boolean getBoolean(int columnIndex) throws SQLException;
 
@@ -476,7 +424,6 @@
      *         {@code NULL}, {@code false} is returned.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public boolean getBoolean(String columnName) throws SQLException;
 
@@ -489,7 +436,6 @@
      *         is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public byte getByte(int columnIndex) throws SQLException;
 
@@ -502,7 +448,6 @@
      *         is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public byte getByte(String columnName) throws SQLException;
 
@@ -515,7 +460,6 @@
      *         the column contains SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public byte[] getBytes(int columnIndex) throws SQLException;
 
@@ -528,7 +472,6 @@
      *         the column contains SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public byte[] getBytes(String columnName) throws SQLException;
 
@@ -543,7 +486,6 @@
      * @throws SQLException
      *             if a database error happens.
      * @see java.io.Reader
-     * @since Android 1.0
      */
     public Reader getCharacterStream(int columnIndex) throws SQLException;
 
@@ -557,7 +499,6 @@
      *         the column value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public Reader getCharacterStream(String columnName) throws SQLException;
 
@@ -571,7 +512,6 @@
      *         {@code null} if the value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public Clob getClob(int columnIndex) throws SQLException;
 
@@ -585,7 +525,6 @@
      *         {@code null} if the value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public Clob getClob(String colName) throws SQLException;
 
@@ -596,7 +535,6 @@
      *         , {@code ResultSet.CONCUR_UPDATABLE}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public int getConcurrency() throws SQLException;
 
@@ -606,7 +544,6 @@
      * @return the SQL cursor name.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public String getCursorName() throws SQLException;
 
@@ -620,7 +557,6 @@
      *         if the column is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public Date getDate(int columnIndex) throws SQLException;
 
@@ -636,7 +572,6 @@
      *         if the column is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public Date getDate(int columnIndex, Calendar cal) throws SQLException;
 
@@ -650,7 +585,6 @@
      *         if the column is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public Date getDate(String columnName) throws SQLException;
 
@@ -666,7 +600,6 @@
      *         if the column is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public Date getDate(String columnName, Calendar cal) throws SQLException;
 
@@ -680,7 +613,6 @@
      *         column is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public double getDouble(int columnIndex) throws SQLException;
 
@@ -694,7 +626,6 @@
      *         column is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public double getDouble(String columnName) throws SQLException;
 
@@ -709,7 +640,6 @@
      *         </ul>
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public int getFetchDirection() throws SQLException;
 
@@ -719,7 +649,6 @@
      * @return the fetch size as an int
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public int getFetchSize() throws SQLException;
 
@@ -733,7 +662,6 @@
      *         column is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public float getFloat(int columnIndex) throws SQLException;
 
@@ -747,7 +675,6 @@
      *         column is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public float getFloat(String columnName) throws SQLException;
 
@@ -761,7 +688,6 @@
      *         column is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public int getInt(int columnIndex) throws SQLException;
 
@@ -775,7 +701,6 @@
      *         column is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public int getInt(String columnName) throws SQLException;
 
@@ -789,7 +714,6 @@
      *         column is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public long getLong(int columnIndex) throws SQLException;
 
@@ -803,7 +727,6 @@
      *         column is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public long getLong(String columnName) throws SQLException;
 
@@ -815,7 +738,6 @@
      *         {@code ResultSet}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public ResultSetMetaData getMetaData() throws SQLException;
 
@@ -827,15 +749,13 @@
      * For SQL User Defined Types, if a column value is Structured or Distinct,
      * this method behaves the same as a call to: {@code
      * getObject(columnIndex,this.getStatement().getConnection().getTypeMap())}
-     * </p>
-     * 
+     *
      * @param columnIndex
      *            the index of the column to read.
      * @return an {@code Object} containing the value of the column. {@code
      *         null} if the column value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public Object getObject(int columnIndex) throws SQLException;
 
@@ -846,8 +766,7 @@
      * The type of the Java object will be determined by the supplied Map to
      * perform the mapping of SQL {@code Struct} or Distinct types into Java
      * objects.
-     * </p>
-     * 
+     *
      * @param columnIndex
      *            the index of the column to read.
      * @param map
@@ -857,7 +776,6 @@
      *         null} if the column value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public Object getObject(int columnIndex, Map<String, Class<?>> map)
             throws SQLException;
@@ -870,15 +788,13 @@
      * For SQL User Defined Types, if a column value is structured or distinct,
      * this method behaves the same as a call to: {@code
      * getObject(columnIndex,this.getStatement().getConnection().getTypeMap())}
-     * </p>
-     * 
+     *
      * @param columnName
      *            the name of the column to read.
      * @return an {@code Object} containing the value of the column. {@code
      *         null} if the column value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public Object getObject(String columnName) throws SQLException;
 
@@ -888,8 +804,7 @@
      * <p>
      * The type of the Java object will be determined by the supplied Map to
      * perform the mapping of SQL Struct or Distinct types into Java objects.
-     * </p>
-     * 
+     *
      * @param columnName
      *            the name of the column to read.
      * @param map
@@ -899,7 +814,6 @@
      *         null} if the column value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public Object getObject(String columnName, Map<String, Class<?>> map)
             throws SQLException;
@@ -913,7 +827,6 @@
      * @return a Ref representing the value of the SQL REF in the column
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public Ref getRef(int columnIndex) throws SQLException;
 
@@ -926,7 +839,6 @@
      * @return a Ref representing the value of the SQL {@code REF} in the column
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public Ref getRef(String colName) throws SQLException;
 
@@ -938,7 +850,6 @@
      *         there is no current row.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public int getRow() throws SQLException;
 
@@ -951,7 +862,6 @@
      *         the value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public short getShort(int columnIndex) throws SQLException;
 
@@ -964,7 +874,6 @@
      *         the value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public short getShort(String columnName) throws SQLException;
 
@@ -978,7 +887,6 @@
      *         null} if the {@code ResultSet} was not created by a Statement.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public Statement getStatement() throws SQLException;
 
@@ -991,7 +899,6 @@
      *         the column is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public String getString(int columnIndex) throws SQLException;
 
@@ -1004,7 +911,6 @@
      *         the column is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public String getString(String columnName) throws SQLException;
 
@@ -1018,7 +924,6 @@
      *         value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public Time getTime(int columnIndex) throws SQLException;
 
@@ -1035,7 +940,6 @@
      *         value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public Time getTime(int columnIndex, Calendar cal) throws SQLException;
 
@@ -1049,7 +953,6 @@
      *         NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public Time getTime(String columnName) throws SQLException;
 
@@ -1066,7 +969,6 @@
      *         value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public Time getTime(String columnName, Calendar cal) throws SQLException;
 
@@ -1080,7 +982,6 @@
      *         column value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public Timestamp getTimestamp(int columnIndex) throws SQLException;
 
@@ -1097,7 +998,6 @@
      *         column value is SQL NULL.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public Timestamp getTimestamp(int columnIndex, Calendar cal)
             throws SQLException;
@@ -1112,7 +1012,6 @@
      *         column value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public Timestamp getTimestamp(String columnName) throws SQLException;
 
@@ -1129,7 +1028,6 @@
      *         column value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public Timestamp getTimestamp(String columnName, Calendar cal)
             throws SQLException;
@@ -1145,7 +1043,6 @@
      *         </ul>
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public int getType() throws SQLException;
 
@@ -1160,7 +1057,6 @@
      *         null} if the column value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     @Deprecated
     public InputStream getUnicodeStream(int columnIndex) throws SQLException;
@@ -1176,7 +1072,6 @@
      *         null} if the column value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     @Deprecated
     public InputStream getUnicodeStream(String columnName) throws SQLException;
@@ -1190,7 +1085,6 @@
      * @return a URL. {@code null} if the column value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public URL getURL(int columnIndex) throws SQLException;
 
@@ -1203,7 +1097,6 @@
      * @return the column vaule as a URL. {@code null} if the column value is SQL {@code NULL}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public URL getURL(String columnName) throws SQLException;
 
@@ -1217,15 +1110,13 @@
      * generated by {@code ResultSet} method calls - warnings generated by
      * Statement methods are held by the Statement.
      * <p>
-     * </p>
      * An {@code SQLException} is generated if this method is called on a closed
-     * {@code ResultSet}. </p>
+     * {@code ResultSet}.
      * 
      * @return an SQLWarning which is the first warning for this {@code
      *         ResultSet}. {@code null} if there are no warnings.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public SQLWarning getWarnings() throws SQLException;
 
@@ -1239,7 +1130,6 @@
      *             cursor not being on the Insert Row or if any columns in the
      *             row do not have a value where the column is declared as
      *             not-nullable.
-     * @since Android 1.0
      */
     public void insertRow() throws SQLException;
 
@@ -1251,7 +1141,6 @@
      *         in the {@code ResultSet}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public boolean isAfterLast() throws SQLException;
 
@@ -1263,7 +1152,6 @@
      *         in the {@code ResultSet}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public boolean isBeforeFirst() throws SQLException;
 
@@ -1275,7 +1163,6 @@
      *         in the {@code ResultSet}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public boolean isFirst() throws SQLException;
 
@@ -1287,7 +1174,6 @@
      *         in the {@code ResultSet}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public boolean isLast() throws SQLException;
 
@@ -1298,7 +1184,6 @@
      *         false} if the {@code ResultSet} contains no rows.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public boolean last() throws SQLException;
 
@@ -1309,7 +1194,6 @@
      * 
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void moveToCurrentRow() throws SQLException;
 
@@ -1321,7 +1205,6 @@
      * 
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void moveToInsertRow() throws SQLException;
 
@@ -1330,14 +1213,12 @@
      * <p>
      * Any input streams associated with the current row are closed and any
      * warnings are cleared.
-     * </p>
-     * 
+     *
      * @return {@code true} if the updated cursor position is pointing to a
      *         valid row, {@code false} otherwise (i.e. when the cursor is after
      *         the last row in the {@code ResultSet}).
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public boolean next() throws SQLException;
 
@@ -1349,7 +1230,6 @@
      *         false} if the cursor is now before the first row.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public boolean previous() throws SQLException;
 
@@ -1360,12 +1240,10 @@
      * If any columns in the current row have been updated but the {@code
      * updateRow} has not been called, then the updates are lost when this
      * method is called.
-     * </p>
-     * 
+     *
      * @throws SQLException
      *             if a database error happens., including if the current row is
      *             the Insert row.
-     * @since Android 1.0
      */
     public void refreshRow() throws SQLException;
 
@@ -1381,7 +1259,6 @@
      *         false} otherwise
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public boolean relative(int rows) throws SQLException;
 
@@ -1393,7 +1270,6 @@
      *         detected, {@code false} otherwise.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public boolean rowDeleted() throws SQLException;
 
@@ -1406,7 +1282,6 @@
      *         detected, {@code false} otherwise.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public boolean rowInserted() throws SQLException;
 
@@ -1418,7 +1293,6 @@
      *         can be detected, {@code false} otherwise.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public boolean rowUpdated() throws SQLException;
 
@@ -1432,7 +1306,6 @@
      *            ResultSet.FETCH_REVERSE}, or {@code ResultSet.FETCH_UNKNOWN}
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public void setFetchDirection(int direction) throws SQLException;
 
@@ -1449,7 +1322,6 @@
      *            ResultSet}.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void setFetchSize(int rows) throws SQLException;
 
@@ -1463,7 +1335,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateArray(int columnIndex, Array x) throws SQLException;
 
@@ -1477,7 +1348,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateArray(String columnName, Array x) throws SQLException;
 
@@ -1492,7 +1362,6 @@
      *            the length of the data to write from the stream
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateAsciiStream(int columnIndex, InputStream x, int length)
             throws SQLException;
@@ -1508,7 +1377,6 @@
      *            the length of the data to write from the stream
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateAsciiStream(String columnName, InputStream x, int length)
             throws SQLException;
@@ -1523,7 +1391,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateBigDecimal(int columnIndex, BigDecimal x)
             throws SQLException;
@@ -1538,7 +1405,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateBigDecimal(String columnName, BigDecimal x)
             throws SQLException;
@@ -1554,7 +1420,6 @@
      *            the number of bytes to be read from the the stream.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateBinaryStream(int columnIndex, InputStream x, int length)
             throws SQLException;
@@ -1570,7 +1435,6 @@
      *            he number of bytes to be read from the the stream.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateBinaryStream(String columnName, InputStream x, int length)
             throws SQLException;
@@ -1585,7 +1449,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateBlob(int columnIndex, Blob x) throws SQLException;
 
@@ -1599,7 +1462,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateBlob(String columnName, Blob x) throws SQLException;
 
@@ -1613,7 +1475,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateBoolean(int columnIndex, boolean x) throws SQLException;
 
@@ -1626,7 +1487,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateBoolean(String columnName, boolean x) throws SQLException;
 
@@ -1639,7 +1499,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateByte(int columnIndex, byte x) throws SQLException;
 
@@ -1652,7 +1511,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateByte(String columnName, byte x) throws SQLException;
 
@@ -1666,7 +1524,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateBytes(int columnIndex, byte[] x) throws SQLException;
 
@@ -1679,7 +1536,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateBytes(String columnName, byte[] x) throws SQLException;
 
@@ -1695,7 +1551,6 @@
      *            the length of data to write from the stream
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateCharacterStream(int columnIndex, Reader x, int length)
             throws SQLException;
@@ -1712,7 +1567,6 @@
      *            the length of data to write from the Reader
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateCharacterStream(String columnName, Reader reader,
             int length) throws SQLException;
@@ -1727,7 +1581,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateClob(int columnIndex, Clob x) throws SQLException;
 
@@ -1741,7 +1594,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateClob(String columnName, Clob x) throws SQLException;
 
@@ -1755,7 +1607,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateDate(int columnIndex, Date x) throws SQLException;
 
@@ -1769,7 +1620,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateDate(String columnName, Date x) throws SQLException;
 
@@ -1782,7 +1632,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     *             @since Android 1.0
      */
     public void updateDouble(int columnIndex, double x) throws SQLException;
 
@@ -1795,7 +1644,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateDouble(String columnName, double x) throws SQLException;
 
@@ -1808,7 +1656,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateFloat(int columnIndex, float x) throws SQLException;
 
@@ -1821,7 +1668,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateFloat(String columnName, float x) throws SQLException;
 
@@ -1834,7 +1680,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateInt(int columnIndex, int x) throws SQLException;
 
@@ -1847,7 +1692,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateInt(String columnName, int x) throws SQLException;
 
@@ -1860,7 +1704,6 @@
      *            the new value for the specified column..
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateLong(int columnIndex, long x) throws SQLException;
 
@@ -1873,7 +1716,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateLong(String columnName, long x) throws SQLException;
 
@@ -1884,7 +1726,6 @@
      *            the index of the column to update.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateNull(int columnIndex) throws SQLException;
 
@@ -1895,7 +1736,6 @@
      *            the name of the column to update.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateNull(String columnName) throws SQLException;
 
@@ -1909,7 +1749,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateObject(int columnIndex, Object x) throws SQLException;
 
@@ -1927,7 +1766,6 @@
      *            after the decimal point.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateObject(int columnIndex, Object x, int scale)
             throws SQLException;
@@ -1941,7 +1779,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateObject(String columnName, Object x) throws SQLException;
 
@@ -1958,7 +1795,6 @@
      *            after the decimal point.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateObject(String columnName, Object x, int scale)
             throws SQLException;
@@ -1973,7 +1809,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateRef(int columnIndex, Ref x) throws SQLException;
 
@@ -1987,7 +1822,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateRef(String columnName, Ref x) throws SQLException;
 
@@ -1997,7 +1831,6 @@
      * 
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateRow() throws SQLException;
 
@@ -2010,7 +1843,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateShort(int columnIndex, short x) throws SQLException;
 
@@ -2023,7 +1855,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateShort(String columnName, short x) throws SQLException;
 
@@ -2036,7 +1867,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateString(int columnIndex, String x) throws SQLException;
 
@@ -2049,7 +1879,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateString(String columnName, String x) throws SQLException;
 
@@ -2062,7 +1891,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateTime(int columnIndex, Time x) throws SQLException;
 
@@ -2075,7 +1903,6 @@
      *            the new value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateTime(String columnName, Time x) throws SQLException;
 
@@ -2089,7 +1916,6 @@
      *            the new timestamp value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateTimestamp(int columnIndex, Timestamp x)
             throws SQLException;
@@ -2103,7 +1929,6 @@
      *            the new timestamp value for the specified column.
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public void updateTimestamp(String columnName, Timestamp x)
             throws SQLException;
@@ -2116,7 +1941,6 @@
      *         NULL}, {@code false} otherwise
      * @throws SQLException
      *             if a database error happens.
-     * @since Android 1.0
      */
     public boolean wasNull() throws SQLException;
 }
diff --git a/libcore/sql/src/main/java/java/sql/ResultSetMetaData.java b/libcore/sql/src/main/java/java/sql/ResultSetMetaData.java
index 95c515d..097093f 100644
--- a/libcore/sql/src/main/java/java/sql/ResultSetMetaData.java
+++ b/libcore/sql/src/main/java/java/sql/ResultSetMetaData.java
@@ -19,29 +19,21 @@
 
 /**
  * Provides information about the columns returned in a {@code ResultSet}.
- * 
- * @since Android 1.0
  */
 public interface ResultSetMetaData {
 
     /**
      * Indicates that a column cannot contain {@code NULL} values.
-     * 
-     * @since Android 1.0
      */
     public static final int columnNoNulls = 0;
 
     /**
      * Indicates that a column can contain {@code NULL} values.
-     * 
-     * @since Android 1.0
      */
     public static final int columnNullable = 1;
 
     /**
      * Indicates that it is unknown whether a column can contain {@code NULL}s or not.
-     * 
-     * @since Android 1.0
      */
     public static final int columnNullableUnknown = 2;
 
@@ -53,7 +45,6 @@
      * @return the catalog title.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public String getCatalogName(int column) throws SQLException;
 
@@ -67,7 +58,6 @@
      * @throws SQLException
      *             if there is a database error.
      * @see ResultSet#getObject
-     * @since Android 1.0
      */
     public String getColumnClassName(int column) throws SQLException;
 
@@ -77,7 +67,6 @@
      * @return the column count.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public int getColumnCount() throws SQLException;
 
@@ -90,7 +79,6 @@
      * @return the column's max width.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public int getColumnDisplaySize(int column) throws SQLException;
 
@@ -103,7 +91,6 @@
      * @return the column's title.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public String getColumnLabel(int column) throws SQLException;
 
@@ -115,7 +102,6 @@
      * @return the column title.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public String getColumnName(int column) throws SQLException;
 
@@ -128,7 +114,6 @@
      * @throws SQLException
      *             if there is a database error.
      * @see Types
-     * @since Android 1.0
      */
     public int getColumnType(int column) throws SQLException;
 
@@ -140,7 +125,6 @@
      * @return the type name.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public String getColumnTypeName(int column) throws SQLException;
 
@@ -152,7 +136,6 @@
      * @return the precision.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public int getPrecision(int column) throws SQLException;
 
@@ -165,7 +148,6 @@
      * @return number of decimal places.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public int getScale(int column) throws SQLException;
 
@@ -177,7 +159,6 @@
      * @return the name of the columns schema.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public String getSchemaName(int column) throws SQLException;
 
@@ -189,7 +170,6 @@
      * @return the table title.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public String getTableName(int column) throws SQLException;
 
@@ -203,7 +183,6 @@
      *         otherwise.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public boolean isAutoIncrement(int column) throws SQLException;
 
@@ -216,7 +195,6 @@
      * @return {@code true} if case matters, {@code false} otherwise.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public boolean isCaseSensitive(int column) throws SQLException;
 
@@ -228,7 +206,6 @@
      * @return {@code true} if it is a monetary value, {@code false} otherwise.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public boolean isCurrency(int column) throws SQLException;
 
@@ -241,7 +218,6 @@
      * @return {@code true} if the write is guaranteed, {@code false} otherwise.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public boolean isDefinitelyWritable(int column) throws SQLException;
 
@@ -253,7 +229,6 @@
      * @return {@code true} if it is nullable, {@code false} otherwise.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public int isNullable(int column) throws SQLException;
 
@@ -266,7 +241,6 @@
      * @return {@code true} if the column is read-only, {@code false} otherwise.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public boolean isReadOnly(int column) throws SQLException;
 
@@ -279,7 +253,6 @@
      *         otherwise.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public boolean isSearchable(int column) throws SQLException;
 
@@ -292,7 +265,6 @@
      * @return {@code true} if they are signed, {@code false} otherwise.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public boolean isSigned(int column) throws SQLException;
 
@@ -305,7 +277,6 @@
      * @return {@code true} if it is possible to write, {@code false} otherwise.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public boolean isWritable(int column) throws SQLException;
 }
diff --git a/libcore/sql/src/main/java/java/sql/SQLData.java b/libcore/sql/src/main/java/java/sql/SQLData.java
index cae9d15..f7dba05 100644
--- a/libcore/sql/src/main/java/java/sql/SQLData.java
+++ b/libcore/sql/src/main/java/java/sql/SQLData.java
@@ -31,7 +31,7 @@
  * and can store changes back into the database using the
  * {@link PreparedStatement#setObject} method which performs the reverse mapping
  * into the SQL {@code UDT}.
- * </p>
+ * <p>
  * Normally the implementation of a custom mapping is generated by
  * a tool requiring the name of the SQL {@code UDT}, the name
  * of the class which it is going to be mapped to, and the field names to which
@@ -44,9 +44,6 @@
  * Ordinarily an application would not call {@code SQLData} methods directly.
  * Similarly {@code SQLInput} and {@code SQLOutput} methods are not usually
  * called directly.
- * </p>
- * 
- * @since Android 1.0
  */
 public interface SQLData {
 
@@ -59,7 +56,6 @@
      *         {@code readSQL} when the object was created.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public String getSQLTypeName() throws SQLException;
 
@@ -78,12 +74,10 @@
      * distinct, then read its only data entry. For structured types, read every
      * entry.</li>
      * </ul>
-     * </p>
      * <p>
      * The supplied input stream is typically initialized by the calling JDBC
      * driver with the type map before {@code readSQL} is called.
-     * </p>
-     * 
+     *
      * @param stream
      *            the {@code SQLInput} stream from which the type map data is
      *            read for the custom mapping.
@@ -92,7 +86,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see SQLInput
-     * @since Android 1.0
      */
     public void readSQL(SQLInput stream, String typeName) throws SQLException;
 
@@ -109,7 +102,6 @@
      * Write a single data element for a distinct type. For a structured type,
      * write a value for each attribute of the the SQL type.</li>
      * </ul>
-     * </p>
      * 
      * @param stream
      *            the {@code SQLOutput} stream to use to write out the data for
@@ -117,7 +109,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see SQLOutput
-     * @since Android 1.0
      */
     public void writeSQL(SQLOutput stream) throws SQLException;
 }
diff --git a/libcore/sql/src/main/java/java/sql/SQLException.java b/libcore/sql/src/main/java/java/sql/SQLException.java
index 2cea139..5022eb0 100644
--- a/libcore/sql/src/main/java/java/sql/SQLException.java
+++ b/libcore/sql/src/main/java/java/sql/SQLException.java
@@ -38,11 +38,8 @@
  * <li>A chain to a next {@code Exception}, if relevant, which can give access
  * to additional error information.</li>
  * </ul>
- * </p>
  * 
  * @see DatabaseMetaData
- * 
- * @since Android 1.0
  */
 public class SQLException extends Exception implements Serializable {
 
@@ -84,7 +81,6 @@
      *            the string to use as the reason string.
      * @param theSQLState
      *            the string to use as the {@code SQLState} string.
-     * @since Android 1.0
      */
     public SQLException(String theReason, String theSQLState) {
         this(theReason, theSQLState, 0);
@@ -102,7 +98,6 @@
      *            the string to use as the {@code SQLState} string.
      * @param theErrorCode
      *            the integer value for the error code.
-     * @since Android 1.0
      */
     public SQLException(String theReason, String theSQLState, int theErrorCode) {
         super(theReason);
@@ -115,7 +110,6 @@
      * 
      * @return The integer error code for this {@code SQLException}. The meaning
      *         of the code is specific to the vendor of the database.
-     * @since Android 1.0
      */
     public int getErrorCode() {
         return vendorCode;
@@ -156,7 +150,6 @@
      * @param ex
      *            the new {@code SQLException} to be added to the end of the
      *            chain.
-     * @since Android 1.0
      */
     public void setNextException(SQLException ex) {    
         if (next != null) {
diff --git a/libcore/sql/src/main/java/java/sql/SQLInput.java b/libcore/sql/src/main/java/java/sql/SQLInput.java
index b72c839..cd77a91 100644
--- a/libcore/sql/src/main/java/java/sql/SQLInput.java
+++ b/libcore/sql/src/main/java/java/sql/SQLInput.java
@@ -32,7 +32,7 @@
  * application programmers do not normally use the {@code SQLInput} methods
  * directly. Reader methods such as {@code readLong} and {@code readBytes}
  * provide means to read values from an {@code SQLInput} stream.
- * </p><p>
+ * <p>
  * When the {@code getObject} method is called with an object which implements
  * the {@code SQLData} interface, the JDBC driver determines the SQL type of the
  * UDT being mapped by calling the {@code SQLData.getSQLType} method. The driver
@@ -40,11 +40,8 @@
  * the attributes of the UDT. The {@code SQLInput} stream is passed to the
  * {@code SQLData.readSQL} method which then calls the {@code SQLInput} reader
  * methods to read the attributes.
- * </p>
- * 
+ *
  * @see SQLData
- * 
- * @since Android 1.0
  */
 public interface SQLInput {
 
@@ -55,7 +52,6 @@
      * 
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public String readString() throws SQLException;
 
@@ -67,7 +63,6 @@
      *         value is SQL {@code NULL}.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public boolean readBoolean() throws SQLException;
 
@@ -78,7 +73,6 @@
      *         {@code NULL}.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public byte readByte() throws SQLException;
 
@@ -89,7 +83,6 @@
      *         {@code NULL}.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public short readShort() throws SQLException;
 
@@ -100,7 +93,6 @@
      *         {@code NULL}.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public int readInt() throws SQLException;
 
@@ -111,7 +103,6 @@
      *         {@code NULL}.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public long readLong() throws SQLException;
 
@@ -122,7 +113,6 @@
      *         {@code NULL}.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public float readFloat() throws SQLException;
 
@@ -133,7 +123,6 @@
      *         {@code NULL}.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public double readDouble() throws SQLException;
 
@@ -146,7 +135,6 @@
      * @throws SQLException
      *             if there is a database error.
      * @see java.math.BigDecimal
-     * @since Android 1.0
      */
     public BigDecimal readBigDecimal() throws SQLException;
 
@@ -157,7 +145,6 @@
      *         SQL {@code NULL}.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public byte[] readBytes() throws SQLException;
 
@@ -170,7 +157,6 @@
      * @throws SQLException
      *             if there is a database error.
      * @see Date
-     * @since Android 1.0
      */
     public Date readDate() throws SQLException;
 
@@ -183,7 +169,6 @@
      * @throws SQLException
      *             if there is a database error.
      * @see Time
-     * @since Android 1.0
      */
     public Time readTime() throws SQLException;
 
@@ -196,7 +181,6 @@
      * @throws SQLException
      *             if there is a database error.
      * @see Timestamp
-     * @since Android 1.0
      */
     public Timestamp readTimestamp() throws SQLException;
 
@@ -209,7 +193,6 @@
      * @throws SQLException
      *             if there is a database error.
      * @see java.io.Reader
-     * @since Android 1.0
      */
     public Reader readCharacterStream() throws SQLException;
 
@@ -222,7 +205,6 @@
      * @throws SQLException
      *             if there is a database error.
      * @see java.io.InputStream
-     * @since Android 1.0
      */
     public InputStream readAsciiStream() throws SQLException;
 
@@ -235,7 +217,6 @@
      * @throws SQLException
      *             if there is a database error.
      * @see java.io.InputStream
-     * @since Android 1.0
      */
     public InputStream readBinaryStream() throws SQLException;
 
@@ -247,20 +228,17 @@
      * for this JDBC driver, including any customized mappings, if present. A
      * type map is given to the {@code SQLInput} by the JDBC driver before the
      * {@code SQLInput} is given to the application.
-     * </p>
      * <p>
      * If the attribute is an SQL structured or distinct type, its SQL type is
      * determined. If the stream's type map contains an element for that SQL
      * type, the driver creates an object for the relevant type and invokes the
      * method {@code SQLData.readSQL} on it, which reads supplementary data from
      * the stream using whichever protocol is defined for that method.
-     * </p>
      * 
      * @return the next attribute as an Object. {@code null} if the value is SQL
      *         {@code NULL}.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public Object readObject() throws SQLException;
 
@@ -273,7 +251,6 @@
      * @throws SQLException
      *             if there is a database error.
      * @see Ref
-     * @since Android 1.0
      */
     public Ref readRef() throws SQLException;
 
@@ -285,7 +262,6 @@
      *         the value is SQL {@code NULL}.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public Blob readBlob() throws SQLException;
 
@@ -298,7 +274,6 @@
      * @throws SQLException
      *             if there is a database error.
      * @see Clob
-     * @since Android 1.0
      */
     public Clob readClob() throws SQLException;
 
@@ -311,7 +286,6 @@
      * @throws SQLException
      *             if there is a database error.
      * @see Array
-     * @since Android 1.0
      */
     public Array readArray() throws SQLException;
 
@@ -322,7 +296,6 @@
      *         false} otherwise.
      * @throws SQLException
      *             if there is a database error.
-     * @since Android 1.0
      */
     public boolean wasNull() throws SQLException;
 
@@ -335,7 +308,6 @@
      * @throws SQLException
      *             if there is a database error.
      * @see java.net.URL
-     * @since Android 1.0
      */
     public URL readURL() throws SQLException;
 }
diff --git a/libcore/sql/src/main/java/java/sql/SQLOutput.java b/libcore/sql/src/main/java/java/sql/SQLOutput.java
index 9fded5e..6710d4f 100644
--- a/libcore/sql/src/main/java/java/sql/SQLOutput.java
+++ b/libcore/sql/src/main/java/java/sql/SQLOutput.java
@@ -35,11 +35,8 @@
  * the {@code SQLData.writeSQL} method, which in turn uses the appropriate
  * {@code SQLOutput} writer methods to write the data from the {@code SQLData}
  * object into the stream according to the defined mapping.
- * </p>
- * 
+ *
  * @see SQLData
- * 
- * @since Android 1.0
  */
 public interface SQLOutput {
 
@@ -50,7 +47,6 @@
      *            the {@code String} to write.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void writeString(String theString) throws SQLException;
 
@@ -61,7 +57,6 @@
      *            the {@code boolean} value to write.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void writeBoolean(boolean theFlag) throws SQLException;
 
@@ -72,7 +67,6 @@
      *            the {@code byte} value to write.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void writeByte(byte theByte) throws SQLException;
 
@@ -83,7 +77,6 @@
      *            the {@code short} value to write.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void writeShort(short theShort) throws SQLException;
 
@@ -94,7 +87,6 @@
      *            the {@code int} value to write.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void writeInt(int theInt) throws SQLException;
 
@@ -105,7 +97,6 @@
      *            the {@code long} value to write.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void writeLong(long theLong) throws SQLException;
 
@@ -116,7 +107,6 @@
      *            the {@code float} value to write.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void writeFloat(float theFloat) throws SQLException;
 
@@ -127,7 +117,6 @@
      *            the {@code double} value to write.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void writeDouble(double theDouble) throws SQLException;
 
@@ -138,7 +127,6 @@
      *            the {@code BigDecimal} value to write.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void writeBigDecimal(BigDecimal theBigDecimal) throws SQLException;
 
@@ -149,7 +137,6 @@
      *            the array of bytes to write.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void writeBytes(byte[] theBytes) throws SQLException;
 
@@ -161,7 +148,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see Date
-     * @since Android 1.0
      */
     public void writeDate(Date theDate) throws SQLException;
 
@@ -173,7 +159,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see Time
-     * @since Android 1.0
      */
     public void writeTime(Time theTime) throws SQLException;
 
@@ -185,7 +170,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see Timestamp
-     * @since Android 1.0
      */
     public void writeTimestamp(Timestamp theTimestamp) throws SQLException;
 
@@ -197,7 +181,6 @@
      *            java.io.Reader} object.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void writeCharacterStream(Reader theStream) throws SQLException;
 
@@ -209,7 +192,6 @@
      *            java.io.InputStream} object
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void writeAsciiStream(InputStream theStream) throws SQLException;
 
@@ -221,7 +203,6 @@
      *            object
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public void writeBinaryStream(InputStream theStream) throws SQLException;
 
@@ -229,21 +210,18 @@
      * Write an {@code SQLData} object into the output stream.
      * <p>
      * If the {@code SQLData} object is null, writes {@code NULL} to the stream.
-     * </p>
      * <p>
      * Otherwise, calls the {@code SQLData.writeSQL} method of the object, which
      * writes the object's attributes to the stream by calling the appropriate
      * SQLOutput writer methods for each attribute, in order. The order of the
      * attributes is the order they are listed in the SQL definition of the User
      * Defined Type.
-     * </p>
      * 
      * @param theObject
      *            the {@code SQLData} object to write.
      * @throws SQLException
      *             if a database error occurs.
      * @see SQLData
-     * @since Android 1.0
      */
     public void writeObject(SQLData theObject) throws SQLException;
 
@@ -255,7 +233,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see Ref
-     * @since Android 1.0
      */
     public void writeRef(Ref theRef) throws SQLException;
 
@@ -267,7 +244,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see Blob
-     * @since Android 1.0
      */
     public void writeBlob(Blob theBlob) throws SQLException;
 
@@ -279,7 +255,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see Clob
-     * @since Android 1.0
      */
     public void writeClob(Clob theClob) throws SQLException;
 
@@ -291,7 +266,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see Struct
-     * @since Android 1.0
      */
     public void writeStruct(Struct theStruct) throws SQLException;
 
@@ -303,7 +277,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see Array
-     * @since Android 1.0
      */
     public void writeArray(Array theArray) throws SQLException;
 
@@ -315,7 +288,6 @@
      * @throws SQLException
      *             if a database error occurs.
      * @see java.net.URL
-     * @since Android 1.0
      */
     public void writeURL(URL theURL) throws SQLException;
 }
diff --git a/libcore/sql/src/main/java/java/sql/SQLPermission.java b/libcore/sql/src/main/java/java/sql/SQLPermission.java
index a9f82d1..85dff72 100644
--- a/libcore/sql/src/main/java/java/sql/SQLPermission.java
+++ b/libcore/sql/src/main/java/java/sql/SQLPermission.java
@@ -31,11 +31,8 @@
  * the {@code DriverManager.setLogStream} method. This is a potentially
  * dangerous operation since the logging stream can contain sensitive
  * information such as usernames and passwords.
- * </p>
  * 
  * @see DriverManager
- * 
- * @since Android 1.0
  */
 public final class SQLPermission extends BasicPermission implements Guard,
         Serializable {
diff --git a/libcore/sql/src/main/java/java/sql/SQLWarning.java b/libcore/sql/src/main/java/java/sql/SQLWarning.java
index de94da5..3ef67f5 100644
--- a/libcore/sql/src/main/java/java/sql/SQLWarning.java
+++ b/libcore/sql/src/main/java/java/sql/SQLWarning.java
@@ -23,8 +23,6 @@
 
 /**
  * An exception class that holds information about Database access warnings.
- * 
- * @since Android 1.0
  */
 public class SQLWarning extends SQLException implements Serializable {
 
@@ -34,8 +32,6 @@
      * Creates an {@code SQLWarning} object. The reason string is set to {@code
      * null}, the {@code SQLState} string is set to {@code null} and the error
      * code is set to 0.
-     * 
-     * @since Android 1.0
      */
     public SQLWarning() {
         super();
@@ -48,7 +44,6 @@
      * 
      * @param theReason
      *            the reason why this warning is issued.
-     * @since Android 1.0
      */
     public SQLWarning(String theReason) {
         super(theReason);
@@ -80,7 +75,6 @@
      *            the X/Open standard specifc error code.
      * @param theErrorCode
      *            a vendor specific error code.
-     * @since Android 1.0
      */
     public SQLWarning(String theReason, String theSQLState, int theErrorCode) {
         super(theReason, theSQLState, theErrorCode);
@@ -92,7 +86,6 @@
      * @return the {@code SQLWarning} chained to this {@code SQLWarning}.
      *         {@code null} if no {@code SQLWarning} is chained to this {@code
      *         SQLWarning}.
-     * @since Android 1.0
      */
     public SQLWarning getNextWarning() {
         SQLException next = super.getNextException();
@@ -110,7 +103,6 @@
      * 
      * @param w
      *            the {@code SQLWarning} linked to this {@code SQLWarning}.
-     * @since Android 1.0
      */
     public void setNextWarning(SQLWarning w) {
         super.setNextException(w);
diff --git a/libcore/sql/src/main/java/java/sql/Savepoint.java b/libcore/sql/src/main/java/java/sql/Savepoint.java
index 42b4a17..0c65515 100644
--- a/libcore/sql/src/main/java/java/sql/Savepoint.java
+++ b/libcore/sql/src/main/java/java/sql/Savepoint.java
@@ -22,8 +22,6 @@
  * by a rollback via the {@link Connection#rollback} command. Rolling back to a
  * particular savepoint means that all changes that occurred after that
  * savepoint are undone.
- * 
- * @since Android 1.0
  */
 public interface Savepoint {
 
@@ -33,7 +31,6 @@
      * @return the ID for this savepoint.
      * @throws SQLException
      *             if an error occurrs accessing the database.
-     * @since Android 1.0
      */
     public int getSavepointId() throws SQLException;
 
@@ -43,7 +40,6 @@
      * @return the name of this savepoint.
      * @throws SQLException
      *             if an error occurrs accessing the database.
-     * @since Android 1.0
      */
     public String getSavepointName() throws SQLException;
 }
diff --git a/libcore/sql/src/main/java/java/sql/Statement.java b/libcore/sql/src/main/java/java/sql/Statement.java
index 4985a9e..6f2a1ed 100644
--- a/libcore/sql/src/main/java/java/sql/Statement.java
+++ b/libcore/sql/src/main/java/java/sql/Statement.java
@@ -27,70 +27,52 @@
  * <p>
  * To have multiple {@code ResultSet} objects opened concurrently, multiple
  * {@code Statement} objects must be created and then executed.
- * </p>
  * <p>
  * To obtain such an executable statement one needs to invoke {@code
  * Connection#createStatement}.
- * </p>
- * 
+ *
  * @see ResultSet
  * @see Connection#createStatement
- * 
- * @since Android 1.0
  */
 public interface Statement {
 
     /**
      * Passing this constant to {@link #getMoreResults} implies that all {@code
      * ResultSet} objects previously kept open should be closed.
-     * 
-     * @since Android 1.0
      */
     public static final int CLOSE_ALL_RESULTS = 3;
 
     /**
      * Passing this constant to {@link #getMoreResults} implies that the current
      * {@code ResultSet} object should be closed.
-     * 
-     * @since Android 1.0
      */
     public static final int CLOSE_CURRENT_RESULT = 1;
 
     /**
      * Indicates that an error was encountered during execution of a batch
      * statement.
-     * 
-     * @since Android 1.0
      */
     public static final int EXECUTE_FAILED = -3;
 
     /**
      * Passing this constant to <i>getMoreResults</i> implies that the current
      * {@code ResultSet} object should not be closed.
-     * 
-     * @since Android 1.0
      */
     public static final int KEEP_CURRENT_RESULT = 2;
 
     /**
      * Indicates that generated keys should not be accessible for retrieval.
-     * 
-     * @since Android 1.0
      */
     public static final int NO_GENERATED_KEYS = 2;
 
     /**
      * Indicates that generated keys should be accessible for retrieval.
-     * 
-     * @since Android 1.0
      */
     public static final int RETURN_GENERATED_KEYS = 1;
 
     /**
      * Indicates that a batch statement was executed with a successful result,
      * but a count of the number of rows it affected is unavailable.
-     * 
-     * @since Android 1.0
      */
     public static final int SUCCESS_NO_INFO = -2;
 
@@ -100,15 +82,13 @@
      * <p>
      * The list of commands is executed by invoking the {@code executeBatch}
      * method.
-     * </p>
-     * 
+     *
      * @param sql
      *            the SQL command as a String. Typically an {@code INSERT} or
      *            {@code UPDATE} statement.
      * @throws SQLException
      *             if an error occurs accessing the database or the database
      *             does not support batch updates.
-     * @since Android 1.0
      */
     public void addBatch(String sql) throws SQLException;
 
@@ -120,7 +100,6 @@
      * 
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void cancel() throws SQLException;
 
@@ -130,7 +109,6 @@
      * @throws SQLException
      *             if an error occurs accessing the database or the database
      *             does not support batch updates.
-     * @since Android 1.0
      */
     public void clearBatch() throws SQLException;
 
@@ -139,7 +117,6 @@
      * 
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void clearWarnings() throws SQLException;
 
@@ -148,13 +125,11 @@
      * <p>
      * Using this method to release these resources as soon as possible is
      * strongly recommended.
-     * </p>
      * <p>
      * One should not rely on the resources being automatically released when
      * finalized during garbage collection. Doing so can result in unpredictable
      * behavior for the application.
-     * </p>
-     * 
+     *
      * @throws SQLException
      *             if an error occurs accessing the database.
      */
@@ -166,8 +141,7 @@
      * <p>
      * Use the {@code getResultSet} or {@code getUpdateCount} methods to get the
      * first result and {@code getMoreResults} to get any subsequent results.
-     * </p>
-     * 
+     *
      * @param sql
      *            the SQL statement to execute
      * @return {@code true} if the first result is a {@code ResultSet}, {@code
@@ -175,7 +149,6 @@
      *         result.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public boolean execute(String sql) throws SQLException;
 
@@ -187,8 +160,7 @@
      * <p>
      * Use the {@code getResultSet} or {@code getUpdateCount} methods to get the
      * first result and {@code getMoreResults} to get any subsequent results.
-     * </p>
-     * 
+     *
      * @param sql
      *            the SQL statement to execute.
      * @param autoGeneratedKeys
@@ -201,7 +173,6 @@
      *         or if there is no result.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public boolean execute(String sql, int autoGeneratedKeys)
             throws SQLException;
@@ -214,8 +185,7 @@
      * <p>
      * Use the {@code getResultSet} or {@code getUpdateCount} methods to get the
      * first result and {@code getMoreResults} to get any subsequent results.
-     * </p>
-     * 
+     *
      * @param sql
      *            the SQL statement to execute.
      * @param columnIndexes
@@ -227,7 +197,6 @@
      *         result.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public boolean execute(String sql, int[] columnIndexes) throws SQLException;
 
@@ -239,8 +208,7 @@
      * <p>
      * Use the {@code getResultSet} or {@code getUpdateCount} methods to get the
      * first result and {@code getMoreResults} to get any subsequent results.
-     * </p>
-     * 
+     *
      * @param sql
      *            the SQL statement to execute.
      * @param columnNames
@@ -252,7 +220,6 @@
      *         result
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public boolean execute(String sql, String[] columnNames)
             throws SQLException;
@@ -300,7 +267,6 @@
      * @throws SQLException
      *             if an error occurs accessing the database or if the statement
      *             produces anything other than a single {@code ResultSet}.
-     * @since Android 1.0
      */
     public ResultSet executeQuery(String sql) throws SQLException;
 
@@ -317,7 +283,6 @@
      * @throws SQLException
      *             if an error occurs accessing the database or if the statement
      *             produces a {@code ResultSet}.
-     * @since Android 1.0
      */
     public int executeUpdate(String sql) throws SQLException;
 
@@ -339,7 +304,6 @@
      * @throws SQLException
      *             if an error occurs accessing the database or if the statement
      *             produces a {@code ResultSet}.
-     * @since Android 1.0
      */
     public int executeUpdate(String sql, int autoGeneratedKeys)
             throws SQLException;
@@ -360,7 +324,6 @@
      * @throws SQLException
      *             if an error occurs accessing the database or if the statement
      *             produces a {@code ResultSet}.
-     * @since Android 1.0
      */
     public int executeUpdate(String sql, int[] columnIndexes)
             throws SQLException;
@@ -381,7 +344,6 @@
      * @throws SQLException
      *             if an error occurs accessing the database or if the statement
      *             produces a {@code ResultSet}.
-     * @since Android 1.0
      */
     public int executeUpdate(String sql, String[] columnNames)
             throws SQLException;
@@ -393,7 +355,6 @@
      *         transmitted to the database.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public Connection getConnection() throws SQLException;
 
@@ -408,7 +369,6 @@
      *         </ul>
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public int getFetchDirection() throws SQLException;
 
@@ -420,7 +380,6 @@
      *         statement.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public int getFetchSize() throws SQLException;
 
@@ -431,7 +390,6 @@
      *         no keys are generated by this statement.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public ResultSet getGeneratedKeys() throws SQLException;
 
@@ -447,7 +405,6 @@
      *         limit.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public int getMaxFieldSize() throws SQLException;
 
@@ -460,7 +417,6 @@
      *         limit.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public int getMaxRows() throws SQLException;
 
@@ -476,7 +432,6 @@
      *         return -1.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public boolean getMoreResults() throws SQLException;
 
@@ -499,7 +454,6 @@
      *         will return -1.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public boolean getMoreResults(int current) throws SQLException;
 
@@ -512,7 +466,6 @@
      *         there is no current timeout.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public int getQueryTimeout() throws SQLException;
 
@@ -523,7 +476,6 @@
      *         result is an update count or if there are no more results.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public ResultSet getResultSet() throws SQLException;
 
@@ -535,7 +487,6 @@
      *         ResultSet.CONCUR_UPDATABLE}.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public int getResultSetConcurrency() throws SQLException;
 
@@ -547,7 +498,6 @@
      *         ResultSet.CLOSE_CURSORS_AT_COMMIT}
      * @throws SQLException
      *             if there is an error while accessing the database.
-     * @since Android 1.0
      */
     public int getResultSetHoldability() throws SQLException;
 
@@ -563,7 +513,6 @@
      *         which is scrollable but is sensitive to changes made by others.
      * @throws SQLException
      *             if there is an error accessing the database.
-     * @since Android 1.0
      */
     public int getResultSetType() throws SQLException;
 
@@ -575,7 +524,6 @@
      *         result is a {@code ResultSet} or if there are no more results.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public int getUpdateCount() throws SQLException;
 
@@ -588,12 +536,10 @@
      * Warnings associated with reads from the {@code ResultSet} returned from
      * executing the statement will be attached to the {@code ResultSet}, not the
      * statement object.
-     * </p>
-     * 
+     *
      * @return an SQLWarning, null if there are no warnings
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public SQLWarning getWarnings() throws SQLException;
 
@@ -602,19 +548,16 @@
      * execute methods.
      * <p>
      * Cursor names must be unique within one Connection.
-     * </p>
      * <p>
      * With the cursor name set, it can then be used in SQL positioned
      * update or delete statements to determine the current row in a {@code
      * ResultSet} generated from this statement. The positioned update or delete
      * must be done with a different statement than this one.
-     * </p>
-     * 
+     *
      * @param name
      *            the Cursor name as a string,
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setCursorName(String name) throws SQLException;
 
@@ -625,14 +568,12 @@
      * on an SQL statement before sending it for execution. This does not apply
      * to {@link PreparedStatement}s since they are processed when created,
      * before this method can be called.
-     * </p>
-     * 
+     *
      * @param enable
      *            {@code true} to set escape processing mode <i>on</i>, {@code
      *            false} to turn it <i>off</i>.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setEscapeProcessing(boolean enable) throws SQLException;
 
@@ -666,7 +607,6 @@
      * @throws SQLException
      *             if an error occurs accessing the database, or if the rows
      *             parameter is out of range.
-     * @since Android 1.0
      */
     public void setFetchSize(int rows) throws SQLException;
 
@@ -682,7 +622,6 @@
      * @throws SQLException
      *             if an error occurs accessing the database or the {@code max}
      *             value is &lt; {@code 0}.
-     * @since Android 1.0
      */
     public void setMaxFieldSize(int max) throws SQLException;
 
@@ -696,7 +635,6 @@
      * @throws SQLException
      *             if an error occurs accessing the database or if max < {@code
      *             0}.
-     * @since Android 1.0
      */
     public void setMaxRows(int max) throws SQLException;
 
@@ -710,7 +648,6 @@
      * @throws SQLException
      *             if an error occurs accessing the database or if seconds <
      *             {@code 0}.
-     * @since Android 1.0
      */
     public void setQueryTimeout(int seconds) throws SQLException;
 }
diff --git a/libcore/sql/src/main/java/java/sql/Struct.java b/libcore/sql/src/main/java/java/sql/Struct.java
index 1167cdf..4d94d49 100644
--- a/libcore/sql/src/main/java/java/sql/Struct.java
+++ b/libcore/sql/src/main/java/java/sql/Struct.java
@@ -23,8 +23,6 @@
  * An interface which provides facilities for manipulating an SQL structured type 
  * as a Java object. The {@code Struct} object has a value for each attribute of the SQL structured
  * type.
- * 
- * @since Android 1.0
  */
 public interface Struct {
 
@@ -35,7 +33,6 @@
      * @return the fully qualified name of SQL structured type.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public String getSQLTypeName() throws SQLException;
 
@@ -49,7 +46,6 @@
      * @return an {@code Object} array containing the ordered attributes.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public Object[] getAttributes() throws SQLException;
 
@@ -66,7 +62,6 @@
      * @return an Object array containing the ordered attributes,.
      * @throws SQLException
      *             if a database error occurs.
-     * @since Android 1.0
      */
     public Object[] getAttributes(Map<String, Class<?>> theMap)
             throws SQLException;
diff --git a/libcore/sql/src/main/java/java/sql/Time.java b/libcore/sql/src/main/java/java/sql/Time.java
index 7fb28e1..d522ef8 100644
--- a/libcore/sql/src/main/java/java/sql/Time.java
+++ b/libcore/sql/src/main/java/java/sql/Time.java
@@ -17,14 +17,11 @@
 
 package java.sql;
 
-import java.text.SimpleDateFormat;
 import java.util.Date;
 
 /**
  * Java representation of an SQL {@code TIME} value. Provides utilities to 
  * format and parse the time's representation as a String in JDBC escape format.
- * 
- * @since Android 1.0
  */
 public class Time extends Date {
 
@@ -33,24 +30,22 @@
     /**
      * Constructs a {@code Time} object using the supplied values for <i>Hour</i>,
      * <i>Minute</i> and <i>Second</i>. The <i>Year</i>, <i>Month</i> and
-     * <i>Day</i> elements of the {@code Time} object are set to the date 
+     * <i>Day</i> elements of the {@code Time} object are set to the date
      * of the Epoch (January 1, 1970).
      * <p>
      * Any attempt to access the <i>Year</i>, <i>Month</i> or <i>Day</i>
      * elements of a {@code Time} object will result in an {@code
      * IllegalArgumentException}.
-     * </p><p>
+     * <p>
      * The result is undefined if any argument is out of bounds.
-     * </p>
-     * 
-     * @deprecated Please use the constructor {@link #Time(long)}.
+     *
+     * @deprecated Use the constructor {@link #Time(long)}.
      * @param theHour
      *            a value in the range {@code [0,23]}.
      * @param theMinute
      *            a value in the range {@code [0,59]}.
      * @param theSecond
      *            a value in the range {@code [0,59]}.
-     * @since Android 1.0
      */
     @SuppressWarnings("deprecation")
     @Deprecated
@@ -65,7 +60,6 @@
      * @param theTime
      *            a {@code Time} specified in milliseconds since the
      *            <i>Epoch</i> (January 1st 1970, 00:00:00.000).
-     * @since Android 1.0
      */
     public Time(long theTime) {
         super(theTime);
@@ -77,7 +71,6 @@
      * @return does not return anything.
      * @throws IllegalArgumentException
      *             if this method is called.
-     * @since Android 1.0
      */
     @SuppressWarnings("deprecation")
     @Deprecated
@@ -92,7 +85,6 @@
      * @return does not return anything.
      * @throws IllegalArgumentException
      *             if this method is called.
-     * @since Android 1.0
      */
     @SuppressWarnings("deprecation")
     @Deprecated
@@ -107,7 +99,6 @@
      * @return does not return anything.
      * @throws IllegalArgumentException
      *             if this method is called.
-     * @since Android 1.0
      */
     @SuppressWarnings("deprecation")
     @Deprecated
@@ -122,7 +113,6 @@
      * @return does not return anything.
      * @throws IllegalArgumentException
      *             if this method is called.
-     * @since Android 1.0
      */
     @SuppressWarnings("deprecation")
     @Deprecated
@@ -136,7 +126,6 @@
      *             {@code Time} object does not have a {@code Date} component.
      * @throws IllegalArgumentException
      *             if this method is called.
-     * @since Android 1.0
      */
     @SuppressWarnings("deprecation")
     @Deprecated
@@ -150,7 +139,6 @@
      *             {@code Time} object does not have a <i>Month</i> component.
      * @throws IllegalArgumentException
      *             if this method is called.
-     * @since Android 1.0
      */
     @SuppressWarnings("deprecation")
     @Deprecated
@@ -180,7 +168,6 @@
      *            A time value expressed as milliseconds since the <i>Epoch</i>.
      *            Negative values are milliseconds before the Epoch. The Epoch
      *            is January 1 1970, 00:00:00.000.
-     * @since Android 1.0
      */
     @Override
     public void setTime(long time) {
@@ -193,12 +180,31 @@
      * 
      * @return A String representing the {@code Time} value in JDBC escape
      *         format: {@code HH:mm:ss}
-     * @since Android 1.0
      */
     @Override
     public String toString() {
-        SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); //$NON-NLS-1$
-        return dateFormat.format(this);
+        StringBuilder sb = new StringBuilder(8);
+
+        format(getHours(), 2, sb);
+        sb.append(':');
+        format(getMinutes(), 2, sb);
+        sb.append(':');
+        format(getSeconds(), 2, sb);
+
+        return sb.toString();
+    }
+
+    private static final String PADDING = "00";  //$NON-NLS-1$
+
+    /* 
+    * Private method to format the time 
+    */ 
+    private void format(int date, int digits, StringBuilder sb) { 
+        String str = String.valueOf(date);
+        if (digits - str.length() > 0) {
+            sb.append(PADDING.substring(0, digits - str.length()));
+        }
+        sb.append(str); 
     }
 
     /**
@@ -206,8 +212,7 @@
      * JDBC escape format: {@code hh:mm:ss}.
      * <p>
      * An exception occurs if the input string does not comply with this format.
-     * </p>
-     * 
+     *
      * @param timeString
      *            A String representing the time value in JDBC escape format:
      *            {@code hh:mm:ss}.
@@ -215,7 +220,6 @@
      *         time.
      * @throws IllegalArgumentException
      *             if the supplied time string is not in JDBC escape format.
-     * @since Android 1.0
      */
     public static Time valueOf(String timeString) {
         if (timeString == null) {
@@ -223,18 +227,21 @@
         }
         int firstIndex = timeString.indexOf(':');
         int secondIndex = timeString.indexOf(':', firstIndex + 1);
-        // secondIndex == -1 means none or only one separator '-' has been found.
+        // secondIndex == -1 means none or only one separator '-' has been
+        // found.
         // The string is separated into three parts by two separator characters,
         // if the first or the third part is null string, we should throw
         // IllegalArgumentException to follow RI
-        if (secondIndex == -1|| firstIndex == 0 || secondIndex + 1 == timeString.length()) {
+        if (secondIndex == -1 || firstIndex == 0
+                || secondIndex + 1 == timeString.length()) {
             throw new IllegalArgumentException();
         }
         // parse each part of the string
         int hour = Integer.parseInt(timeString.substring(0, firstIndex));
-        int minute = Integer.parseInt(timeString.substring(firstIndex + 1, secondIndex));
-        int second = Integer.parseInt(timeString.substring(secondIndex + 1, timeString
-                .length()));
+        int minute = Integer.parseInt(timeString.substring(firstIndex + 1,
+                secondIndex));
+        int second = Integer.parseInt(timeString.substring(secondIndex + 1,
+                timeString.length()));
         return new Time(hour, minute, second);
     }
 }
diff --git a/libcore/sql/src/main/java/java/sql/Timestamp.java b/libcore/sql/src/main/java/java/sql/Timestamp.java
index b526fb3..f16d93a 100644
--- a/libcore/sql/src/main/java/java/sql/Timestamp.java
+++ b/libcore/sql/src/main/java/java/sql/Timestamp.java
@@ -17,10 +17,10 @@
 
 package java.sql;
 
-import java.text.DecimalFormat;
 import java.text.ParsePosition;
 import java.text.SimpleDateFormat;
 import java.util.Date;
+import java.util.regex.Pattern;
 
 import org.apache.harmony.sql.internal.nls.Messages;
 
@@ -32,18 +32,16 @@
  * The {@code Timestamp} class consists of a regular date/time value, where only
  * the integral seconds value is stored, plus a nanoseconds value where the
  * fractional seconds are stored.
- * </p><p>
+ * <p>
  * The addition of the nanosecond value field to the {@code Timestamp} object
  * makes it significantly different from the {@code java.util.Date} object which
  * it extends. Users should be aware that {@code Timestamp} objects are not
  * interchangable with {@code java.util.Date} objects when used outside the
  * confines of the {@code java.sql} package.
- * </p>
- * 
+ *
  * @see Date
  * @see Time
  * @see java.util.Date
- * @since Android 1.0
  */
 public class Timestamp extends Date {
 
@@ -52,12 +50,15 @@
     // The nanoseconds time value of the Timestamp
     private int nanos;
 
+    // The regex pattern of yyyy-mm-dd hh:mm:ss
+    private static final String TIME_FORMAT_REGEX = "[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}.*"; //$NON-NLS-1$
+
     /**
      * Returns a {@code Timestamp} corresponding to the time specified by the
      * supplied values for <i>Year</i>, <i>Month</i>, <i>Date</i>, <i>Hour</i>,
      * <i>Minutes</i>, <i>Seconds</i> and <i>Nanoseconds</i>.
-     * 
-     * @deprecated Please use the constructor {@link #Timestamp(long)}.
+     *
+     * @deprecated Use the constructor {@link #Timestamp(long)}.
      * @param theYear
      *            specified as the year minus 1900.
      * @param theMonth
@@ -75,7 +76,6 @@
      *            as an integer in the range [0,999'999'999]
      * @throws IllegalArgumentException
      *             if any of the parameters is out of range.
-     * @since Android 1.0
      */
     @SuppressWarnings("deprecation")
     @Deprecated
@@ -96,7 +96,6 @@
      * @param theTime
      *            a time value in the format of milliseconds since the Epoch
      *            (January 1 1970 00:00:00.000 GMT).
-     * @since Android 1.0
      */
     public Timestamp(long theTime) {
         super(theTime);
@@ -104,7 +103,7 @@
          * Now set the time for this Timestamp object - which deals with the
          * nanosecond value as well as the base time
          */
-        this.setTime(theTime);
+        setTimeImpl(theTime);
     }
 
     /**
@@ -115,7 +114,6 @@
      *            the timestamp to compare with this timestamp object.
      * @return {@code true} if this {@code Timestamp} object is later than the
      *         supplied timestamp, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean after(Timestamp theTimestamp) {
         long thisTime = this.getTime();
@@ -148,7 +146,6 @@
      *            the timestamp to compare with this {@code Timestamp} object.
      * @return {@code true} if this {@code Timestamp} object is earlier than the
      *         supplied timestamp, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean before(Timestamp theTimestamp) {
         long thisTime = this.getTime();
@@ -195,7 +192,6 @@
      *         </dd>
      * @throws ClassCastException
      *             if the supplied object is not a {@code Timestamp} object.
-     * @since Android 1.0
      */
     @Override
     public int compareTo(Date theObject) throws ClassCastException {
@@ -218,7 +214,6 @@
      *         <li> {@code > 0}, if this {@code Timestamp} object is after the
      *         supplied {@code Timestamp}</li>
      *         </ul>
-     * @since Android 1.0
      */
     public int compareTo(Timestamp theTimestamp) {
         int result = super.compareTo(theTimestamp);
@@ -245,7 +240,6 @@
      *         supplied {@code Timestamp} object<br>{@code false} if the object
      *         is not a {@code Timestamp} object or if the object is a {@code
      *         Timestamp} but represents a different instant in time.
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object theObject) {
@@ -263,7 +257,6 @@
      *            passed as an {@code Object}.
      * @return {@code true} if this {@code Timestamp} object is equal to the
      *         supplied {@code Timestamp} object, {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean equals(Timestamp theTimestamp) {
         if (theTimestamp == null) {
@@ -278,7 +271,6 @@
      * 
      * @return The timestamp's nanosecond value, an integer between 0 and
      *         999,999,999.
-     * @since Android 1.0
      */
     public int getNanos() {
         return nanos;
@@ -288,10 +280,9 @@
      * Returns the time represented by this {@code Timestamp} object, as a long
      * value containing the number of milliseconds since the Epoch (January 1
      * 1970, 00:00:00.000 GMT).
-     * 
+     *
      * @return the number of milliseconds that have passed since January 1 1970,
      *         00:00:00.000 GMT.
-     * @since Android 1.0
      */
     @Override
     public long getTime() {
@@ -302,13 +293,12 @@
 
     /**
      * Sets the nanosecond value for this {@code Timestamp}.
-     * 
+     *
      * @param n
      *            number of nanoseconds.
      * @throws IllegalArgumentException
      *             if number of nanoseconds smaller than 0 or greater than
      *             999,999,999.
-     * @since Android 1.0
      */
     public void setNanos(int n) throws IllegalArgumentException {
         if ((n < 0) || (n > 999999999)) {
@@ -322,14 +312,17 @@
      * Sets the time represented by this {@code Timestamp} object to the
      * supplied time, defined as the number of milliseconds since the Epoch
      * (January 1 1970, 00:00:00.000 GMT).
-     * 
+     *
      * @param theTime
      *            number of milliseconds since the Epoch (January 1 1970,
      *            00:00:00.000 GMT).
-     * @since Android 1.0
      */
     @Override
     public void setTime(long theTime) {
+        setTimeImpl(theTime);
+    }
+    
+    private void setTimeImpl(long theTime) {
         /*
          * Deal with the nanoseconds value. The supplied time is in milliseconds -
          * so we must extract the milliseconds value and multiply by 1000000 to
@@ -356,67 +349,47 @@
      * 
      * @return A string representing the instant defined by the {@code
      *         Timestamp}, in JDBC Timestamp escape format.
-     * @since Android 1.0
      */
     @SuppressWarnings("deprecation")
     @Override
     public String toString() {
-        /*
-         * Use a DecimalFormat to lay out the nanosecond value as a simple
-         * string of 9 integers, with leading Zeros
-         */
-        DecimalFormat decimalFormat = new DecimalFormat("0"); //$NON-NLS-1$
-        decimalFormat.setMinimumIntegerDigits(9);
-        decimalFormat.setMaximumIntegerDigits(9);
-        String theNanos = decimalFormat.format(nanos);
-        theNanos = stripTrailingZeros(theNanos);
-        
-        String year = format((getYear() + 1900), 4);
-        String month = format((getMonth() + 1), 2);
-        String date = format(getDate(), 2);
-        String hours = format(getHours(), 2);
-        String minutes = format(getMinutes(), 2);
-        String seconds = format(getSeconds(), 2);
+        StringBuilder sb = new StringBuilder(29);
 
-        return year + '-' + month + '-' + date + ' ' + hours + ':' + minutes
-                + ':' + seconds + '.' + theNanos;
-    }
-
-    /*
-     * Private method to format the time
-     */
-    private String format(int date, int digits) {
-        StringBuilder dateStringBuffer = new StringBuilder(String.valueOf(date));
-        while (dateStringBuffer.length() < digits) {
-            dateStringBuffer = dateStringBuffer.insert(0,'0');
-        }
-        return dateStringBuffer.toString();
-    }
-    
-    /*
-     * Private method to strip trailing '0' characters from a string. @param
-     * inputString the starting string @return a string with the trailing zeros
-     * stripped - will leave a single 0 at the beginning of the string
-     */
-    private String stripTrailingZeros(String inputString) {
-        String finalString;
-
-        int i;
-        for (i = inputString.length(); i > 0; i--) {
-            if (inputString.charAt(i - 1) != '0') {
-                break;
-            }
-            /*
-             * If the string has a 0 as its first character, return a string
-             * with a single '0'
-             */
-            if (i == 1) {
-                return "0"; //$NON-NLS-1$
+        format((getYear() + 1900), 4, sb);
+        sb.append('-');
+        format((getMonth() + 1), 2, sb);
+        sb.append('-');
+        format(getDate(), 2, sb);
+        sb.append(' ');
+        format(getHours(), 2, sb);
+        sb.append(':');
+        format(getMinutes(), 2, sb);
+        sb.append(':');
+        format(getSeconds(), 2, sb);
+        sb.append('.');
+        if (nanos == 0) {
+            sb.append('0');
+        } else {
+            format(nanos, 9, sb);
+            while (sb.charAt(sb.length() - 1) == '0') {
+                sb.setLength(sb.length() - 1);
             }
         }
 
-        finalString = inputString.substring(0, i);
-        return finalString;
+        return sb.toString();
+    }
+
+    private static final String PADDING = "000000000";  //$NON-NLS-1$
+
+    /* 
+    * Private method to format the time 
+    */ 
+    private void format(int date, int digits, StringBuilder sb) { 
+        String str = String.valueOf(date);
+        if (digits - str.length() > 0) {
+            sb.append(PADDING.substring(0, digits - str.length()));
+        }
+        sb.append(str); 
     }
 
     /**
@@ -431,7 +404,6 @@
      *         supplied {@code String}.
      * @throws IllegalArgumentException
      *             if the provided string is {@code null}.
-     * @since Android 1.0
      */
     public static Timestamp valueOf(String s) throws IllegalArgumentException {
         if (s == null) {
@@ -439,6 +411,12 @@
             throw new IllegalArgumentException(Messages.getString("sql.3")); //$NON-NLS-1$
         }
 
+        // omit trailing whitespaces
+        s = s.trim();
+        if (!Pattern.matches(TIME_FORMAT_REGEX, s)) {
+            throw new IllegalArgumentException(Messages.getString("sql.2")); //$NON-NLS-1$
+        }
+
         SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //$NON-NLS-1$
         ParsePosition pp = new ParsePosition(0);
 
@@ -495,7 +473,8 @@
             // Require the next character to be a "."
             if (s.charAt(position) != '.') {
                 // sql.4=Bad input string format: expected '.' not {0}
-                throw new NumberFormatException(Messages.getString("sql.4", s.charAt(position))); //$NON-NLS-1$
+                throw new NumberFormatException(Messages.getString(
+                        "sql.4", s.charAt(position))); //$NON-NLS-1$
             }
             // Get the length of the number string - need to account for the '.'
             int nanoLength = s.length() - position - 1;
diff --git a/libcore/sql/src/main/java/java/sql/Types.java b/libcore/sql/src/main/java/java/sql/Types.java
index 8ce0421..fed8671 100644
--- a/libcore/sql/src/main/java/java/sql/Types.java
+++ b/libcore/sql/src/main/java/java/sql/Types.java
@@ -21,8 +21,6 @@
  * A class which defines constants used to identify generic SQL types, also
  * called JDBC types. The type constant values are equivalent to those defined
  * by X/OPEN.
- * 
- * @since Android 1.0
  */
 public class Types {
 
@@ -35,141 +33,101 @@
 
     /**
      * The type code that identifies the SQL type {@code ARRAY}.
-     * 
-     * @since Android 1.0
      */
     public static final int ARRAY = 2003;
 
     /**
      * The type code that identifies the SQL type {@code BIGINT}.
-     * 
-     * @since Android 1.0
      */
     public static final int BIGINT = -5;
 
     /**
      * The type code that identifies the SQL type {@code BINARY}.
-     * 
-     * @since Android 1.0
      */
     public static final int BINARY = -2;
 
     /**
      * The type code that identifies the SQL type {@code BIT}.
-     * 
-     * @since Android 1.0
      */
     public static final int BIT = -7;
 
     /**
      * The type code that identifies the SQL type {@code BLOB}.
-     * 
-     * @since Android 1.0
      */
     public static final int BLOB = 2004;
 
     /**
      * The type code that identifies the SQL type {@code BOOLEAN}.
-     * 
-     * @since Android 1.0
      */
     public static final int BOOLEAN = 16;
 
     /**
      * The type code that identifies the SQL type {@code CHAR}.
-     * 
-     * @since Android 1.0
      */
     public static final int CHAR = 1;
 
     /**
      * The type code that identifies the SQL type {@code CLOB}.
-     * 
-     * @since Android 1.0
      */
     public static final int CLOB = 2005;
 
     /**
      * The type code that identifies the SQL type {@code DATALINK}.
-     * 
-     * @since Android 1.0
      */
     public static final int DATALINK = 70;
 
     /**
      * The type code that identifies the SQL type {@code DATE}.
-     * 
-     * @since Android 1.0
      */
     public static final int DATE = 91;
 
     /**
      * The type code that identifies the SQL type {@code DECIMAL}.
-     * 
-     * @since Android 1.0
      */
     public static final int DECIMAL = 3;
 
     /**
      * The type code that identifies the SQL type {@code DISTINCT}.
-     * 
-     * @since Android 1.0
      */
     public static final int DISTINCT = 2001;
 
     /**
      * The type code that identifies the SQL type {@code DOUBLE}.
-     * 
-     * @since Android 1.0
      */
     public static final int DOUBLE = 8;
 
     /**
      * The type code that identifies the SQL type {@code FLOAT}.
-     * 
-     * @since Android 1.0
      */
     public static final int FLOAT = 6;
 
     /**
      * The type code that identifies the SQL type {@code INTEGER}.
-     * 
-     * @since Android 1.0
      */
     public static final int INTEGER = 4;
 
     /**
      * The type code that identifies the SQL type {@code JAVA_OBJECT}.
-     * 
-     * @since Android 1.0
      */
     public static final int JAVA_OBJECT = 2000;
 
     /**
      * The type code that identifies the SQL type {@code LONGVARBINARY}.
-     * 
-     * @since Android 1.0
      */
     public static final int LONGVARBINARY = -4;
 
     /**
      * The type code that identifies the SQL type {@code LONGVARCHAR}.
-     * 
-     * @since Android 1.0
      */
     public static final int LONGVARCHAR = -1;
 
     /**
      * The type code that identifies the SQL type {@code NULL}.
-     * 
-     * @since Android 1.0
      */
     public static final int NULL = 0;
 
     /**
      * The type code that identifies the SQL type {@code NUMERIC}.
-     * 
-     * @since Android 1.0
      */
     public static final int NUMERIC = 2;
 
@@ -177,71 +135,51 @@
      * The type code that identifies that the SQL type is database specific and
      * is mapped to a Java object, accessed via the methods
      * {@code getObject} and {@code setObject}.
-     * 
-     * @since Android 1.0
      */
     public static final int OTHER = 1111;
 
     /**
      * The type code that identifies the SQL type {@code REAL}.
-     * 
-     * @since Android 1.0
      */
     public static final int REAL = 7;
 
     /**
      * The type code that identifies the SQL type {@code REF}.
-     * 
-     * @since Android 1.0
      */
     public static final int REF = 2006;
 
     /**
      * The type code that identifies the SQL type {@code SMALLINT}.
-     * 
-     * @since Android 1.0
      */
     public static final int SMALLINT = 5;
 
     /**
      * The type code that identifies the SQL type {@code STRUCT}.
-     * 
-     * @since Android 1.0
      */
     public static final int STRUCT = 2002;
 
     /**
      * The type code that identifies the SQL type {@code TIME}.
-     * 
-     * @since Android 1.0
      */
     public static final int TIME = 92;
 
     /**
      * The type code that identifies the SQL type {@code TIMESTAMP}.
-     * 
-     * @since Android 1.0
      */
     public static final int TIMESTAMP = 93;
 
     /**
      * The type code that identifies the SQL type {@code TINYINT}.
-     * 
-     * @since Android 1.0
      */
     public static final int TINYINT = -6;
 
     /**
      * The type code that identifies the SQL type {@code VARBINARY}.
-     * 
-     * @since Android 1.0
      */
     public static final int VARBINARY = -3;
 
     /**
      * The type code that identifies the SQL type {@code VARCHAR}.
-     * 
-     * @since Android 1.0
      */
     public static final int VARCHAR = 12;
 }
diff --git a/libcore/sql/src/main/java/javax/sql/ConnectionEvent.java b/libcore/sql/src/main/java/javax/sql/ConnectionEvent.java
index e07e7c1..cce8a78 100644
--- a/libcore/sql/src/main/java/javax/sql/ConnectionEvent.java
+++ b/libcore/sql/src/main/java/javax/sql/ConnectionEvent.java
@@ -25,23 +25,20 @@
  * Sent when specific events happen on a {@link PooledConnection} object. These
  * events are a facility to report when an application closes the pooled
  * connection or when an error occurs in the pooled connection.
- * 
- * @since Android 1.0
  */
 public class ConnectionEvent extends EventObject implements Serializable {
 
     private static final long serialVersionUID = -4843217645290030002L;
 
-    private SQLException theSQLException;
+    private SQLException ex;
 
     /**
      * Creates a connection event initialized with the supplied {@code
      * PooledConnection} reporting that the application has closed the
      * connection.
-     * 
+     *
      * @param theConnection
      *            the connection for which this event is created.
-     * @since Android 1.0
      */
     public ConnectionEvent(PooledConnection theConnection) {
         super(theConnection);
@@ -51,29 +48,27 @@
      * Creates a {@code ConnectionEvent} initialized with the supplied {@code
      * PooledConnection} and with the supplied {@code SQLException} indicating
      * that an error has occurred within the {@code PooledConnection}.
-     * 
+     *
      * @param theConnection
      *            the connection for which this event is created.
      * @param theException
      *            information about the state of error that has occurred on the
      *            application side.
-     * @since Android 1.0
      */
     public ConnectionEvent(PooledConnection theConnection,
             SQLException theException) {
         super(theConnection);
-        theSQLException = theException;
+        ex = theException;
     }
 
     /**
      * Gets the {@code SQLException} which holds information about the error
      * which occurred in the {@code PooledConnection}.
-     * 
+     *
      * @return a {@code SQLException} containing information about the error.
      *         May be {@code null} if no error has occurred.
-     * @since Android 1.0
      */
     public SQLException getSQLException() {
-        return theSQLException;
+        return ex;
     }
 }
diff --git a/libcore/sql/src/main/java/javax/sql/ConnectionEventListener.java b/libcore/sql/src/main/java/javax/sql/ConnectionEventListener.java
index 1333814..eec0d5b 100644
--- a/libcore/sql/src/main/java/javax/sql/ConnectionEventListener.java
+++ b/libcore/sql/src/main/java/javax/sql/ConnectionEventListener.java
@@ -27,13 +27,9 @@
  * to a {@code ConnectionEventListener} either when the application closes a
  * connection it has been using or when a significant error occurs while the
  * connection is being used.
- * </p>
  * <p>
  * The connection pool manager can return closed connections to the pool for
  * later reuse. Connections experiencing an error should be discarded.
- * </p>
- * 
- * @since Android 1.0
  */
 public interface ConnectionEventListener extends EventListener {
 
@@ -44,7 +40,6 @@
      * @param theEvent
      *            a {@code ConnectionEvent} containing details about the source
      *            of the event.
-     * @since Android 1.0
      */
     public void connectionClosed(ConnectionEvent theEvent);
 
@@ -57,7 +52,6 @@
      * @param theEvent
      *            a {@code ConnectionEvent} containing details about the source
      *            of the event and the {@code SQLException} that has occurred.
-     * @since Android 1.0
      */
     public void connectionErrorOccurred(ConnectionEvent theEvent);
 }
diff --git a/libcore/sql/src/main/java/javax/sql/ConnectionPoolDataSource.java b/libcore/sql/src/main/java/javax/sql/ConnectionPoolDataSource.java
index d73128b..379fde0 100644
--- a/libcore/sql/src/main/java/javax/sql/ConnectionPoolDataSource.java
+++ b/libcore/sql/src/main/java/javax/sql/ConnectionPoolDataSource.java
@@ -27,9 +27,6 @@
  * A class which implements the {@code ConnectionPoolDataSource} interface is
  * typically registered with a JNDI naming service directory and is retrieved
  * from there by name.
- * </p>
- * 
- * @since Android 1.0
  */
 public interface ConnectionPoolDataSource {
 
@@ -44,7 +41,6 @@
      * @return the login timeout value in seconds.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public int getLoginTimeout() throws SQLException;
 
@@ -58,14 +54,12 @@
      * created is {@code null}. Note that the log writer for an {@code
      * ConnectionPoolDataSource} is not the same as the log writer used by a
      * {@code DriverManager}.
-     * </p>
-     * 
+     *
      * @return a {@code PrintWriter} which is the log writer for this {@code
      *         ConnectionPoolDataSource}. Can be {@code null}, in which case log
      *         writing is disabled for this {@code ConnectionPoolDataSource}.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public PrintWriter getLogWriter() throws SQLException;
 
@@ -77,7 +71,6 @@
      *         database.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public PooledConnection getPooledConnection() throws SQLException;
 
@@ -94,7 +87,6 @@
      *         to the database.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public PooledConnection getPooledConnection(String theUser,
             String thePassword) throws SQLException;
@@ -111,7 +103,6 @@
      *            the new login timeout value in seconds.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public void setLoginTimeout(int theTimeout) throws SQLException;
 
@@ -125,13 +116,11 @@
      * is {@code null}. Note that the log writer for a {@code
      * ConnectionPoolDataSource} is not the same as the log writer used by a
      * {@code DriverManager}.
-     * </p>
      * 
      * @param theWriter
      *            is the log writer for this {@code ConnectionPoolDataSource}.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public void setLogWriter(PrintWriter theWriter) throws SQLException;
 }
diff --git a/libcore/sql/src/main/java/javax/sql/DataSource.java b/libcore/sql/src/main/java/javax/sql/DataSource.java
index 98be761..7f73947 100644
--- a/libcore/sql/src/main/java/javax/sql/DataSource.java
+++ b/libcore/sql/src/main/java/javax/sql/DataSource.java
@@ -29,12 +29,10 @@
  * A class which implements the {@code DataSource} interface is typically
  * registered with a JNDI naming service directory and is retrieved from there
  * by name.
- * </p>
  * <p>
  * The {@code DataSource} interface is typically implemented by the writer of a
  * JDBC driver. There are three variants of the {@code DataSource} interface,
  * which produce connections with different characteristics:
- * </p>
  * <ol>
  * <li><i>Standard {@code DataSource}</i>: produces standard {@code Connection}
  * objects with no special features.</li>
@@ -51,9 +49,6 @@
  * Note that a JDBC driver which is accessed via the {@code DataSource}
  * interface is loaded via a JNDI lookup process. A driver loaded in this way
  * does not register itself with the {@code DriverManager}.
- * </p>
- * 
- * @since Android 1.0
  */
 public interface DataSource {
 
@@ -65,7 +60,6 @@
      *         database.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public Connection getConnection() throws SQLException;
 
@@ -82,7 +76,6 @@
      *         database.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public Connection getConnection(String theUsername, String thePassword)
             throws SQLException;
@@ -97,7 +90,6 @@
      * @return the login timeout value in seconds.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public int getLoginTimeout() throws SQLException;
 
@@ -110,14 +102,12 @@
      * log writer when an {@code DataSource} is created is {@code null}. Note
      * that the log writer for a {@code DataSource} is not the same as the log
      * writer used by a {@code DriverManager}.
-     * </p>
-     * 
+     *
      * @return a {@code PrintWriter} which is the log writer for this {@code
      *         DataSource}. Can be {@code null}, in which case log writing is
      *         disabled for this {@code DataSource}.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public PrintWriter getLogWriter() throws SQLException;
 
@@ -132,7 +122,6 @@
      *            the new login timeout value in seconds.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public void setLoginTimeout(int theTimeout) throws SQLException;
 
@@ -145,14 +134,12 @@
      * log writer when a {@code DataSource} is created is {@code null}. Note
      * that the log writer for a {@code DataSource} is not the same as the log
      * writer used by a {@code DriverManager}.
-     * </p>
      * 
      * @param theWriter
      *            a {@code PrintWriter} to use as the log writer for this
      *            {@code DataSource}.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public void setLogWriter(PrintWriter theWriter) throws SQLException;
 }
diff --git a/libcore/sql/src/main/java/javax/sql/PooledConnection.java b/libcore/sql/src/main/java/javax/sql/PooledConnection.java
index b4c5616..b268e0c 100644
--- a/libcore/sql/src/main/java/javax/sql/PooledConnection.java
+++ b/libcore/sql/src/main/java/javax/sql/PooledConnection.java
@@ -30,13 +30,11 @@
  * process both to establish a connection to a database and to destroy the
  * connection. Reusing connections through a pool is a way of improving system
  * performance and reducing overhead.
- * </p>
  * <p>
  * It is not intended that an application uses the {@code PooledConnection}
  * interface directly. The {@code PooledConnection} interface is intended for
  * use by a component called a connection pool manager, typically part of the
  * infrastructure that supports use of the database by applications.
- * </p>
  * <p>
  * Applications obtain connections to the database by calling the
  * {@link DataSource#getConnection} method. Behind the scenes, the connection
@@ -44,7 +42,6 @@
  * pool and passes back a connection object that wraps or references the {@code
  * PooledConnection} object. A new {@code PooledConnection} object will only be
  * created if the pool is empty.
- * </p>
  * <p>
  * When the application is finished using a {@code PooledConnection}, the
  * application calls the {@link Connection#close} method. The connection pool
@@ -54,7 +51,6 @@
  * the underlying {@code PooledConnection} object from the connection and
  * returns it to the pool for reuse - the {@code PooledConnection} is thus
  * recycled rather than being destroyed.
- * </p>
  * <p>
  * The connection to the database represented by the {@code PooledConnection} is
  * kept open until the {@code PooledConnection} object itself is deactivated by
@@ -62,9 +58,6 @@
  * This is typically done if there are too many inactive connections in the
  * pool, if the {@code PooledConnection} encounters a problem that makes it
  * unusable or if the whole system is being shut down.
- * </p>
- * 
- * @since Android 1.0
  */
 public interface PooledConnection {
 
@@ -77,7 +70,6 @@
      * @param theListener
      *            an object which implements the {@code ConnectionEventListener}
      *            interface.
-     * @since Android 1.0
      */
     public void addConnectionEventListener(ConnectionEventListener theListener);
 
@@ -89,7 +81,6 @@
      * 
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public void close() throws SQLException;
 
@@ -102,7 +93,6 @@
      * @return a {@code Connection} object.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public Connection getConnection() throws SQLException;
 
@@ -116,7 +106,6 @@
      *            interface. This object should have previously been registered
      *            with the {@code PooledConnection} using the {@code
      *            addConnectionEventListener} method.
-     * @since Android 1.0
      */
     public void removeConnectionEventListener(
             ConnectionEventListener theListener);
diff --git a/libcore/sql/src/main/java/javax/sql/RowSet.java b/libcore/sql/src/main/java/javax/sql/RowSet.java
index 4edc3d3..77321a2 100644
--- a/libcore/sql/src/main/java/javax/sql/RowSet.java
+++ b/libcore/sql/src/main/java/javax/sql/RowSet.java
@@ -43,14 +43,12 @@
  * distinct data values which constitute the row set. The {@code RowSet} class
  * supports JavaBean events so that other components in an application can be
  * informed when changes happen such as changes in data values.
- * </p>
  * <p>
  * {@code RowSet} is a facility implemented on top of the remainder of the JDBC
  * API. It may be <i>connected</i>, maintaining a connection to the database
  * throughout its lifecycle. The changes made on a <i>disconnected</i> {@code
  * RowSet} on the other hand can be persisted only establishing a new connection
  * with the database each time.
- * </p>
  * <p>
  * Disconnected {@code RowSets} make use of {@code RowSetReaders} to populate
  * the {@code RowSet} with data, possibly from a non-relational database source.
@@ -58,11 +56,9 @@
  * data store. There is considerable freedom in the way that {@code
  * RowSetReaders} and {@code RowSetWriters} may be implemented to retrieve and
  * store data.
- * </p>
- * 
+ *
  * @see RowSetReader
  * @see RowSetWriter
- * @since Android 1.0
  */
 public interface RowSet extends ResultSet {
 
@@ -74,7 +70,6 @@
      * @param theListener
      *            an object which implements the {@code rowSetListener}
      *            interface.
-     * @since Android 1.0
      */
     public void addRowSetListener(RowSetListener theListener);
 
@@ -85,11 +80,9 @@
      * a parameter is set or its value is actively reset. {@code
      * clearParameters} provides a facility to clear the values for all
      * parameters with one method call.
-     * </p>
-     * 
+     *
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public void clearParameters() throws SQLException;
 
@@ -104,20 +97,17 @@
      * transaction isolation, type map; plus some or all of the properties:
      * command, read only, maximum field size, maximum rows, escape processing,
      * and query timeout.
-     * </p>
      * <p>
      * The {@code RowSet} may use a {@code RowSetReader} to access the database
      * it will then invoke the {@link RowSetReader#readData} method on the
      * reader to fetch the data. When the new data is fetched all the listeners
      * are notified to take appropriate measures.
-     * </p>
-     * 
+     *
      * @throws SQLException
      *             if a problem occurs accessing the database or if the
      *             properties needed to access the database have not been set.
      * @see RowSetMetaData
      * @see RowSetReader
-     * @since Android 1.0
      */
     public void execute() throws SQLException;
 
@@ -127,7 +117,6 @@
      * @return a string containing the {@code RowSet}'s command property. A
      *         command is a SQL statement which is executed to fetch required
      *         data into the {@code RowSet}.
-     * @since Android 1.0
      */
     public String getCommand();
 
@@ -138,7 +127,6 @@
      * can then be used to create a connection to the database.
      * 
      * @return the name of the database.
-     * @since Android 1.0
      */
     public String getDataSourceName();
 
@@ -152,7 +140,6 @@
      *         false} otherwise.
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public boolean getEscapeProcessing() throws SQLException;
 
@@ -166,7 +153,6 @@
      * @return the current maximum size in bytes. 0 implies no size limit.
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public int getMaxFieldSize() throws SQLException;
 
@@ -177,7 +163,6 @@
      * @return the previous maximum number of rows. 0 implies no row limit.
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public int getMaxRows() throws SQLException;
 
@@ -187,7 +172,6 @@
      * Therefore it should be set prior to invoking the {@link #execute} method.
      * 
      * @return the value of the password property.
-     * @since Android 1.0
      */
     public String getPassword();
 
@@ -199,7 +183,6 @@
      * @return the timeout value in seconds.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public int getQueryTimeout() throws SQLException;
 
@@ -217,7 +200,6 @@
      *         <li>{@code Connection.TRANSACTION_SERIALIZABLE}</li>
      *         </ul>
      * @see java.sql.Connection
-     * @since Android 1.0
      */
     public int getTransactionIsolation();
 
@@ -228,7 +210,6 @@
      * @return the custom mappings of SQL types to Java classes.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public Map<String, Class<?>> getTypeMap() throws SQLException;
 
@@ -241,7 +222,6 @@
      * @return a String holding the value of the URL property.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public String getUrl() throws SQLException;
 
@@ -252,7 +232,6 @@
      * 
      * @return a {@code String} holding the value of the {@code username}
      *         property.
-     * @since Android 1.0
      */
     public String getUsername();
 
@@ -261,7 +240,6 @@
      * 
      * @return {@code true} if this {@code RowSet} is read-only, {@code false}
      *         if it is updatable.
-     * @since Android 1.0
      */
     public boolean isReadOnly();
 
@@ -272,7 +250,6 @@
      * @param theListener
      *            the {@link RowSetListener} to remove from the set of listeners
      *            for this {@code RowSet}.
-     * @since Android 1.0
      */
     public void removeRowSetListener(RowSetListener theListener);
 
@@ -287,7 +264,6 @@
      *            the {@code Array} data value to which the parameter is set.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setArray(int parameterIndex, Array theArray)
             throws SQLException;
@@ -306,7 +282,6 @@
      *            the length of the data in bytes.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setAsciiStream(int parameterIndex, InputStream theInputStream,
             int length) throws SQLException;
@@ -323,7 +298,6 @@
      *            the big decimal value to which the parameter is set.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setBigDecimal(int parameterIndex, BigDecimal theBigDecimal)
             throws SQLException;
@@ -342,7 +316,6 @@
      *            the length of the data in bytes.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setBinaryStream(int parameterIndex, InputStream theInputStream,
             int length) throws SQLException;
@@ -358,7 +331,6 @@
      *            the {@code Blob} value to which the parameter is set.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setBlob(int parameterIndex, Blob theBlob) throws SQLException;
 
@@ -373,7 +345,6 @@
      *            the {@code boolean} value to which the parameter is set.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setBoolean(int parameterIndex, boolean theBoolean)
             throws SQLException;
@@ -389,7 +360,6 @@
      *            the {@code byte} value to which the parameter is set.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setByte(int parameterIndex, byte theByte) throws SQLException;
 
@@ -404,7 +374,6 @@
      *            the {@code Array} of {@code bytes} to which the parameter is set.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setBytes(int parameterIndex, byte[] theByteArray)
             throws SQLException;
@@ -424,7 +393,6 @@
      *            the length of the data in the {@code Reader} in characters.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setCharacterStream(int parameterIndex, Reader theReader,
             int length) throws SQLException;
@@ -440,7 +408,6 @@
      *            the {@code Clob} value to which the parameter is set.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setClob(int parameterIndex, Clob theClob) throws SQLException;
 
@@ -453,7 +420,6 @@
      *            the SQL query. Can be {@code null}.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setCommand(String cmd) throws SQLException;
 
@@ -470,7 +436,6 @@
      * @throws SQLException
      *             if an error occurs accessing the database.
      * @see java.sql.ResultSet
-     * @since Android 1.0
      */
     public void setConcurrency(int concurrency) throws SQLException;
 
@@ -480,13 +445,11 @@
      * The database name can be used to find a {@link DataSource} which has been
      * registered with a naming service - the {@link DataSource} can then be
      * used to create a connection to the database.
-     * </p>
-     * 
+     *
      * @param name
      *            the database name.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setDataSourceName(String name) throws SQLException;
 
@@ -501,7 +464,6 @@
      *            the date value to which the parameter is set.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setDate(int parameterIndex, Date theDate) throws SQLException;
 
@@ -521,7 +483,6 @@
      *            {@code DATE} value.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setDate(int parameterIndex, Date theDate, Calendar theCalendar)
             throws SQLException;
@@ -537,7 +498,6 @@
      *            the {@code double} value to which the parameter is set.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setDouble(int parameterIndex, double theDouble)
             throws SQLException;
@@ -553,7 +513,6 @@
      *            turn it off.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setEscapeProcessing(boolean enable) throws SQLException;
 
@@ -568,7 +527,6 @@
      *            the {@code float} value to which the parameter is set.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setFloat(int parameterIndex, float theFloat)
             throws SQLException;
@@ -584,7 +542,6 @@
      *            the {@code integer} value to which the parameter is set.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setInt(int parameterIndex, int theInteger) throws SQLException;
 
@@ -599,7 +556,6 @@
      *            the {@code long} value value to which the parameter is set.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setLong(int parameterIndex, long theLong) throws SQLException;
 
@@ -615,7 +571,6 @@
      *            implies no size limit.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setMaxFieldSize(int max) throws SQLException;
 
@@ -628,7 +583,6 @@
      *            RowSet}. 0 means no limit.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setMaxRows(int max) throws SQLException;
 
@@ -644,7 +598,6 @@
      *            java.sql.Types}.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setNull(int parameterIndex, int sqlType) throws SQLException;
 
@@ -665,7 +618,6 @@
      *            type. Ignored if the sqlType is not a UDT or REF type.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setNull(int parameterIndex, int sqlType, String typeName)
             throws SQLException;
@@ -677,8 +629,7 @@
      * The JDBC specification provides a standard mapping for Java objects to
      * SQL data types. Database specific types can be mapped by JDBC driver
      * specific Java types.
-     * </p>
-     * 
+     *
      * @param parameterIndex
      *            the index of the parameter to set; the first parameter's index
      *            is 1.
@@ -687,7 +638,6 @@
      *            parameter is set.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setObject(int parameterIndex, Object theObject)
             throws SQLException;
@@ -706,7 +656,6 @@
      *            java.sql.Types}.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setObject(int parameterIndex, Object theObject,
             int targetSqlType) throws SQLException;
@@ -729,7 +678,6 @@
      *            types. Ignored for all other types.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setObject(int parameterIndex, Object theObject,
             int targetSqlType, int scale) throws SQLException;
@@ -743,7 +691,6 @@
      *            a {@code String} holding the password.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setPassword(String password) throws SQLException;
 
@@ -755,7 +702,6 @@
      *            the number of seconds for the timeout.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setQueryTimeout(int seconds) throws SQLException;
 
@@ -767,7 +713,6 @@
      *            {@code false} to allow updates.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setReadOnly(boolean readOnly) throws SQLException;
 
@@ -784,7 +729,6 @@
      * @throws SQLException
      *             if an error occurs accessing the database.
      * @see java.sql.Ref
-     * @since Android 1.0
      */
     public void setRef(int parameterIndex, Ref theRef) throws SQLException;
 
@@ -799,7 +743,6 @@
      *            the value to which the parameter is set.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setShort(int parameterIndex, short theShort)
             throws SQLException;
@@ -817,7 +760,6 @@
      *            the value to which the parameter is set.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setString(int parameterIndex, String theString)
             throws SQLException;
@@ -836,7 +778,6 @@
      *             if an error occurs accessing the database.
      * @see java.util.Calendar
      * @see java.sql.Time
-     * @since Android 1.0
      */
     public void setTime(int parameterIndex, Time theTime) throws SQLException;
 
@@ -856,7 +797,6 @@
      *             if an error occurs accessing the database.
      * @see java.util.Calendar
      * @see java.sql.Time
-     * @since Android 1.0
      */
     public void setTime(int parameterIndex, Time theTime, Calendar theCalendar)
             throws SQLException;
@@ -875,7 +815,6 @@
      *             if an error occurs accessing the database.
      * @see java.util.Calendar
      * @see java.sql.Timestamp
-     * @since Android 1.0
      */
     public void setTimestamp(int parameterIndex, Timestamp theTimestamp)
             throws SQLException;
@@ -896,7 +835,6 @@
      *             if an error occurs accessing the database.
      * @see java.util.Calendar
      * @see java.sql.Timestamp
-     * @since Android 1.0
      */
     public void setTimestamp(int parameterIndex, Timestamp theTimestamp,
             Calendar theCalendar) throws SQLException;
@@ -909,8 +847,7 @@
      * <p>
      * Keep in mind that setting a transaction isolation level has no effect
      * unless your driver and DBMS support it.
-     * </p>
-     * 
+     *
      * @param level
      *            the transaction isolation level. One of:
      *            <ul>
@@ -922,7 +859,6 @@
      * @throws SQLException
      *             if an error occurs accessing the database.
      * @see java.sql.Connection
-     * @since Android 1.0
      */
     public void setTransactionIsolation(int level) throws SQLException;
 
@@ -939,7 +875,6 @@
      *            </ul>
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setType(int type) throws SQLException;
 
@@ -953,7 +888,6 @@
      *            mapped.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setTypeMap(Map<String, Class<?>> theTypeMap)
             throws SQLException;
@@ -967,7 +901,6 @@
      *            the URL for the database. Can be {@code null}.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setUrl(String theURL) throws SQLException;
 
@@ -979,7 +912,6 @@
      *            the new user name for this row set.
      * @throws SQLException
      *             if an error occurs accessing the database.
-     * @since Android 1.0
      */
     public void setUsername(String theUsername) throws SQLException;
 }
diff --git a/libcore/sql/src/main/java/javax/sql/RowSetEvent.java b/libcore/sql/src/main/java/javax/sql/RowSetEvent.java
index 9d4c98c..d18e9ce 100644
--- a/libcore/sql/src/main/java/javax/sql/RowSetEvent.java
+++ b/libcore/sql/src/main/java/javax/sql/RowSetEvent.java
@@ -33,9 +33,6 @@
  * The event contains a reference to the {@code RowSet} object which generated
  * the message so that the listeners can extract whatever information they need
  * from that reference.
- * </p>
- * 
- * @since Android 1.0
  */
 public class RowSetEvent extends EventObject implements Serializable {
 
@@ -50,7 +47,6 @@
      * 
      * @param theSource
      *            the {@code RowSet} which generated the event.
-     * @since Android 1.0
      */
     public RowSetEvent(RowSet theSource) {
         super(theSource);
diff --git a/libcore/sql/src/main/java/javax/sql/RowSetInternal.java b/libcore/sql/src/main/java/javax/sql/RowSetInternal.java
index baa261d..78de4b0 100644
--- a/libcore/sql/src/main/java/javax/sql/RowSetInternal.java
+++ b/libcore/sql/src/main/java/javax/sql/RowSetInternal.java
@@ -22,9 +22,9 @@
 import java.sql.ResultSet;
 
 /**
- * An interface provided by a {@code RowSet} object to let either a {@code RowSetReader} or a
- * {@code RowSetWriter} access its internal state, thereby providing facilities to read and update the state of
- * the {@code RowSet}.
+ * An interface provided by a {@code RowSet} object to let either a {@code
+ * RowSetReader} or a {@code RowSetWriter} access its internal state, thereby
+ * providing facilities to read and update the state of the {@code RowSet}.
  */
 public interface RowSetInternal {
 
@@ -34,7 +34,6 @@
      * @return the connection or {@code null}.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public Connection getConnection() throws SQLException;
 
@@ -44,13 +43,11 @@
      * <p>
      * The {@code ResultSet}'s cursor is positioned before the first row of
      * data.
-     * </p>
      * 
      * @return the {@code ResultSet} that contained the original data value of
      *         the {@code RowSet}.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public ResultSet getOriginal() throws SQLException;
 
@@ -63,7 +60,6 @@
      *             if there is a problem accessing the database, or if the
      *             cursor is not on a valid row (before the first row, after the
      *             last one or pointing to the insert row).
-     * @since Android 1.0
      */
     public ResultSet getOriginalRow() throws SQLException;
 
@@ -74,7 +70,6 @@
      * @return the values of parameters that have been set.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public Object[] getParams() throws SQLException;
 
@@ -87,7 +82,6 @@
      *            holds the metadata about the {@code RowSet}'s columns.
      * @throws SQLException
      *             if there is a problem accessing the database.
-     * @since Android 1.0
      */
     public void setMetaData(RowSetMetaData theMetaData) throws SQLException;
 }
diff --git a/libcore/sql/src/main/java/javax/sql/RowSetListener.java b/libcore/sql/src/main/java/javax/sql/RowSetListener.java
index 06a7253..ede0197 100644
--- a/libcore/sql/src/main/java/javax/sql/RowSetListener.java
+++ b/libcore/sql/src/main/java/javax/sql/RowSetListener.java
@@ -25,8 +25,6 @@
  * implement the {@code RowSetListener} interface and then register itself with
  * the {@code RowSet} of interest using the
  * {@link RowSet#addRowSetListener(RowSetListener)} method.
- * 
- * @since Android 1.0
  */
 public interface RowSetListener extends EventListener {
 
@@ -39,7 +37,6 @@
      *            {@code RowSet} involved. This information can be used to
      *            retrieve information about the change, such as the updated
      *            data values.
-     * @since Android 1.0
      */
     public void cursorMoved(RowSetEvent theEvent);
 
@@ -52,7 +49,6 @@
      *            {@code RowSet} involved. This information can be used to
      *            retrieve information about the change, such as the new cursor
      *            position.
-     * @since Android 1.0
      */
     public void rowChanged(RowSetEvent theEvent);
 
@@ -66,7 +62,6 @@
      *            {@code RowSet} involved. This information can be used to
      *            retrieve information about the change, such as the updated
      *            rows of data.
-     * @since Android 1.0
      */
     public void rowSetChanged(RowSetEvent theEvent);
 }
diff --git a/libcore/sql/src/main/java/javax/sql/RowSetMetaData.java b/libcore/sql/src/main/java/javax/sql/RowSetMetaData.java
index 3051876..ad07199 100644
--- a/libcore/sql/src/main/java/javax/sql/RowSetMetaData.java
+++ b/libcore/sql/src/main/java/javax/sql/RowSetMetaData.java
@@ -26,14 +26,11 @@
  * <p>
  * {@code RowSetMetaData} extends {@link java.sql.ResultSetMetaData}, adding new
  * operations for carrying out value sets.
- * </p>
  * <p>
  * Application code would not normally call this interface directly. It would be
  * called internally when {@code RowSet.execute} is called.
- * </p>
- * 
+ *
  * @see RowSetInternal#setMetaData(RowSetMetaData)
- * @since Android 1.0
  */
 public interface RowSetMetaData extends ResultSetMetaData {
 
@@ -50,7 +47,6 @@
      *            turn it off (default).
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public void setAutoIncrement(int columnIndex, boolean autoIncrement)
             throws SQLException;
@@ -67,7 +63,6 @@
      *            to make it case insensitive (default).
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public void setCaseSensitive(int columnIndex, boolean caseSensitive)
             throws SQLException;
@@ -82,7 +77,6 @@
      *            the new catalog's name.
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public void setCatalogName(int columnIndex, String catalogName)
             throws SQLException;
@@ -94,7 +88,6 @@
      *            the number of columns contained in the {@code RowSet}.
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public void setColumnCount(int columnCount) throws SQLException;
 
@@ -109,7 +102,6 @@
      *            the normal maximum column width in characters.
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public void setColumnDisplaySize(int columnIndex, int displaySize)
             throws SQLException;
@@ -125,7 +117,6 @@
      *            the alias name for the column.
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public void setColumnLabel(int columnIndex, String theLabel)
             throws SQLException;
@@ -140,7 +131,6 @@
      *            the column's label.
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public void setColumnName(int columnIndex, String theColumnName)
             throws SQLException;
@@ -155,7 +145,6 @@
      *            the SQL Type, as defined by {@code java.sql.Types}.
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public void setColumnType(int columnIndex, int theSQLType)
             throws SQLException;
@@ -171,7 +160,6 @@
      *            the SQL type name for the column.
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public void setColumnTypeName(int columnIndex, String theTypeName)
             throws SQLException;
@@ -189,7 +177,6 @@
      *            value (default).
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public void setCurrency(int columnIndex, boolean isCurrency)
             throws SQLException;
@@ -210,10 +197,8 @@
      *            <p>
      *            The default value is {@code
      *            ResultSetMetaData.columnNullableUnknown}.
-     *            </p>
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public void setNullable(int columnIndex, int nullability)
             throws SQLException;
@@ -229,7 +214,6 @@
      *            the number of decimal digits.
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public void setPrecision(int columnIndex, int thePrecision)
             throws SQLException;
@@ -245,7 +229,6 @@
      *            the number of digits after the decimal point.
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public void setScale(int columnIndex, int theScale) throws SQLException;
 
@@ -259,7 +242,6 @@
      *            a {@code String} containing the schema name.
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public void setSchemaName(int columnIndex, String theSchemaName)
             throws SQLException;
@@ -276,7 +258,6 @@
      *            clause search, {@code false} otherwise.
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public void setSearchable(int columnIndex, boolean isSearchable)
             throws SQLException;
@@ -292,7 +273,6 @@
      *            false} otherwise.
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public void setSigned(int columnIndex, boolean isSigned)
             throws SQLException;
@@ -307,7 +287,6 @@
      *            the table name for the column.
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public void setTableName(int columnIndex, String theTableName)
             throws SQLException;
diff --git a/libcore/sql/src/main/java/javax/sql/RowSetReader.java b/libcore/sql/src/main/java/javax/sql/RowSetReader.java
index d4a902f..0ff5c90 100644
--- a/libcore/sql/src/main/java/javax/sql/RowSetReader.java
+++ b/libcore/sql/src/main/java/javax/sql/RowSetReader.java
@@ -27,7 +27,6 @@
  * RowSet} for this to work.
  * 
  * @see RowSet
- * @since Android 1.0
  */
 public interface RowSetReader {
 
@@ -44,7 +43,6 @@
      * events are sent to listeners - any listeners are informed by the calling
      * {@code RowSet}'s {@code execute} method once the reader returns from the
      * {@code readData} method.
-     * </p>
      * 
      * @param theCaller
      *            must be the calling {@code RowSet} object, which must have
@@ -53,7 +51,6 @@
      *             if a problem occurs accessing the database or if the reader
      *             calls the {@link RowSet#execute()} method.
      * @see RowSetInternal
-     * @since Android 1.0
      */
     public void readData(RowSetInternal theCaller) throws SQLException;
 }
diff --git a/libcore/sql/src/main/java/javax/sql/RowSetWriter.java b/libcore/sql/src/main/java/javax/sql/RowSetWriter.java
index 34473b2..8e56d50 100644
--- a/libcore/sql/src/main/java/javax/sql/RowSetWriter.java
+++ b/libcore/sql/src/main/java/javax/sql/RowSetWriter.java
@@ -28,16 +28,13 @@
  * The writer must establish a connection to the {@code RowSet}'s database
  * before writing the data. The {@code RowSet} calling this interface must
  * implement the {@code RowSetInternal} interface.
- * </p>
  * <p>
  * The writer may encounter a situation where the updated data needs to be
  * written back to the database, but has already been updated there in the mean
  * time. How a conflict of this kind is handled is determined by the
  * implementation of this writer.
- * </p>
- * 
+ *
  * @see RowSetInternal
- * @since Android 1.0
  */
 public interface RowSetWriter {
 
@@ -56,7 +53,6 @@
      *         otherwise (which typically implies some form of conflict).
      * @throws SQLException
      *             if a problem occurs accessing the database.
-     * @since Android 1.0
      */
     public boolean writeData(RowSetInternal theRowSet) throws SQLException;
 }
diff --git a/libcore/sql/src/main/java/org/apache/harmony/sql/internal/nls/Messages.java b/libcore/sql/src/main/java/org/apache/harmony/sql/internal/nls/Messages.java
index b3dbd32..234bdc9 100644
--- a/libcore/sql/src/main/java/org/apache/harmony/sql/internal/nls/Messages.java
+++ b/libcore/sql/src/main/java/org/apache/harmony/sql/internal/nls/Messages.java
@@ -27,7 +27,6 @@
 
 package org.apache.harmony.sql.internal.nls;
 
-
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.Locale;
diff --git a/libcore/sql/src/main/java/org/apache/harmony/sql/internal/nls/messages.properties b/libcore/sql/src/main/java/org/apache/harmony/sql/internal/nls/messages.properties
index 3e6ff1d..6927cf2 100644
--- a/libcore/sql/src/main/java/org/apache/harmony/sql/internal/nls/messages.properties
+++ b/libcore/sql/src/main/java/org/apache/harmony/sql/internal/nls/messages.properties
@@ -40,3 +40,22 @@
 sql.23=Buffer is not sufficient to hold the value
 sql.24=Invalid length for truncate
 sql.25=Unsupported operation. SerialClob is not instantiated with a fully implemented Clob object.
+sql.26=Invalid column count. Cannot be less or equal to zero
+sql.27=Invalid column index :{0}
+sql.28=Invalid SQL type for column
+sql.29=Invalid nullable constant set. Must be either columnNoNulls, columnNullable or columnNullableUnknown
+sql.30=Invalid column display size. Cannot be less than zero
+sql.31=Invalid precision value. Cannot be less than zero
+sql.32=Invalid scale size. Cannot be less than zero
+sql.33=Cannot instantiate a SQLOutputImpl instance with null parameters
+sql.34=Cannot instantiate a SQLInputImpl instance with null parameters
+sql.35=SQLInputImpl exception: Invalid read position
+sql.36=No more attributes
+sql.37=Operation not supported
+sql.38=Object is invalid
+sql.39=Cannot instantiate a SerialArray object with a null Array object
+sql.40=ClassNotFoundException: {0}
+sql.41=Invalid JNDI context supplied
+sql.42=Illegal Argument
+sql.43=The object is not serializable
+sql.44=No logger has been set
diff --git a/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DateTest.java b/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DateTest.java
index 3b833c4..39f5074 100644
--- a/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DateTest.java
+++ b/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DateTest.java
@@ -293,17 +293,27 @@
         args = {}
     )
     public void testToString() {
-        // This test is set up for GMT time zone, so need to set the time zone
-        // to GMT first
-        TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
-
-        for (int i = 0; i < TIME_ARRAY.length; i++) {
-            Date theDate = new Date(TIME_ARRAY[i]);
-            assertEquals(SQL_DATEARRAY[i], theDate.toString());
+		// Loop through the timezones testing the String conversion for each
+		for (int i = 0; i < TIMEZONES.length; i++) {
+			testToString(TIMEZONES[i], TIME_ARRAY, SQL_TZ_DATEARRAYS[i]);
         } // end for
 
     } // end method testToString()
 
+    private void testToString(String timeZone, long[] theDates, String[] theDateStrings) {
+        // Set the timezone
+        TimeZone.setDefault(TimeZone.getTimeZone(timeZone));
+
+        for (int i = 0; i < theDates.length; i++) {
+            // Create the Date object
+            Date theDate = new Date(theDates[i]);
+            // Convert to a date string ... and compare
+            String JDBCString = theDate.toString();
+            assertEquals(theDateStrings[i], JDBCString);
+        } // end for
+
+    } // end testToString( String, long[], String[] )
+
     /*
      * Test of the void setTime(int) method This does depend on the Time Zone
      * settings and sets up the time zone to one of a group of specific time
@@ -372,7 +382,7 @@
                 theDate = Date.valueOf(element);
                 fail("Should throw IllegalArgumentException.");
             } catch (IllegalArgumentException e) {
-                //expected
+                // expected
             } // end try
         } // end for
 
@@ -388,70 +398,77 @@
         args = {java.lang.String.class}
     )
     public void test_valueOf_IllegalArgumentException() {
-        try{
+        try {
             Date.valueOf("1996-10-07-01");
             fail("should throw NumberFormatException");
         } catch (NumberFormatException e) {
-            //expected
+            // expected
         }
         
-        try{
+        try {
             Date.valueOf("-10-07-01");
             fail("should throw IllegalArgumentException");
         } catch (IllegalArgumentException e) {
-            //expected
+            // expected
         }
         
-        try{
+        try {
             Date.valueOf("--01");
             fail("should throw IllegalArgumentException");
         } catch (IllegalArgumentException e) {
-            //expected
+            // expected
         }
         
-        try{
+        try {
             Date.valueOf("1991--");
             fail("should throw IllegalArgumentException");
         } catch (IllegalArgumentException e) {
-            //expected
+            // expected
         }
         
-        try{
+        try {
             Date.valueOf("-01-");
             fail("should throw IllegalArgumentException");
         } catch (IllegalArgumentException e) {
-            //expected
+            // expected
         }
         
-        try{
+        try {
             Date.valueOf("-10-w2-01");
             fail("should throw IllegalArgumentException");
         } catch (IllegalArgumentException e) {
-            //expected
+            // expected
         }
         
-        try{
+        try {
             Date.valueOf("07-w2-");
             fail("should throw IllegalArgumentException");
         } catch (IllegalArgumentException e) {
-            //expected
+            // expected
         }
         
-        try{
+        try {
             Date.valueOf("1997-w2-w2");
             fail("should throw NumberFormatException");
         } catch (NumberFormatException e) {
-            //expected
+            // expected
         }
         
-        try{
+        try {
             Date.valueOf("1996--01");
             fail("should throw NumberFormatException");
         } catch (NumberFormatException e) {
-            //expected
+            // expected
         }
     }
 
+    // Reset defualt timezone
+    static TimeZone defaultTimeZone = TimeZone.getDefault();
+
+    protected void tearDown(){
+    	TimeZone.setDefault(defaultTimeZone);
+    }
+
 } // end class DateTest
 
 
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 7e08db9..5552f4f 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
@@ -24,6 +24,7 @@
 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;
@@ -31,10 +32,12 @@
 import java.sql.Connection;
 import java.sql.Driver;
 import java.sql.DriverManager;
+import java.sql.DriverPropertyInfo;
 import java.sql.SQLException;
 import java.sql.SQLPermission;
 import java.util.Enumeration;
 import java.util.Properties;
+import tests.support.Support_Exec;
 
 import junit.framework.TestCase;
 @TestTargetClass(DriverManager.class)
@@ -684,6 +687,77 @@
 
     } // end class TestSecurityManager
 
+    /**
+     * @tests {@link java.sql.DriverManager#registerDriver(Driver)}
+     *
+     * Registers a driver for multiple times and deregisters it only once.
+     *
+     * Regression for HARMONY-4205
+     */
+    public void test_registerDriver_MultiTimes() throws SQLException {
+        int register_count = 10;
+        int deregister_count = 1;
+
+        Driver dummy = new DummyDriver();
+        DriverManager.registerDriver(new BadDummyDriver());
+        for (int i = 0; i < register_count; i++) {
+            DriverManager.registerDriver(dummy);
+        }
+        DriverManager.registerDriver(new BadDummyDriver());
+        for (int i = 0; i < deregister_count; i++) {
+            DriverManager.deregisterDriver(dummy);
+        }
+        Driver d = DriverManager.getDriver("jdbc:dummy_protocol:dummy_subname");
+        assertNotNull(d);
+    }
+
+    /**
+     * Regression for HARMONY-4303
+     */
+    @KnownFailure(value="bug 2002061")
+    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);
+    }
+
+    private static class BadDummyDriver extends DummyDriver {
+        public boolean acceptsURL(String url) {
+            return false;
+        }
+    }
+
+    private static class DummyDriver implements Driver {
+
+        String goodurl = "jdbc:dummy_protocol:dummy_subname";
+
+        public boolean acceptsURL(String url) {
+            return url.equals(goodurl);
+        }
+
+        public Connection connect(String url, Properties info) {
+            return null;
+        }
+
+        public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) {
+            return null;
+        }
+
+        public int getMajorVersion() {
+            return 0;
+        }
+
+        public int getMinorVersion() {
+            return 0;
+        }
+
+        public boolean jdbcCompliant() {
+            return true;
+        }
+
+    }
+
 } // end class DriverManagerTest
 
 
diff --git a/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Connection1.java b/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Connection1.java
index 8b1fd60..d782444 100644
--- a/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Connection1.java
+++ b/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Connection1.java
@@ -46,8 +46,9 @@
         return null;
     }
 
-    public Statement createStatement(int resultSetType, int resultSetConcurrency,
-            int resultSetHoldability) throws SQLException {
+    public Statement createStatement(int resultSetType,
+            int resultSetConcurrency, int resultSetHoldability)
+            throws SQLException {
         return null;
     }
 
@@ -97,12 +98,13 @@
     }
 
     public CallableStatement prepareCall(String sql, int resultSetType,
-            int resultSetConcurrency, int resultSetHoldability) throws SQLException {
+            int resultSetConcurrency, int resultSetHoldability)
+            throws SQLException {
         return null;
     }
 
-    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency)
-            throws SQLException {
+    public CallableStatement prepareCall(String sql, int resultSetType,
+            int resultSetConcurrency) throws SQLException {
         return null;
     }
 
@@ -111,7 +113,8 @@
     }
 
     public PreparedStatement prepareStatement(String sql, int resultSetType,
-            int resultSetConcurrency, int resultSetHoldability) throws SQLException {
+            int resultSetConcurrency, int resultSetHoldability)
+            throws SQLException {
         return null;
     }
 
diff --git a/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver1.java b/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver1.java
index ae09f94..8638d2b 100644
--- a/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver1.java
+++ b/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver1.java
@@ -104,7 +104,8 @@
 
     public DriverPropertyInfo[] getPropertyInfo(String url, Properties info)
             throws SQLException {
-        DriverPropertyInfo[] theInfos = { new DriverPropertyInfo(userProperty, "*"),
+        DriverPropertyInfo[] theInfos = {
+                new DriverPropertyInfo(userProperty, "*"),
                 new DriverPropertyInfo(passwordProperty, "*"), };
         return theInfos;
     }
diff --git a/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver3.java b/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver3.java
index f02bdc3..f78bb31 100644
--- a/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver3.java
+++ b/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver3.java
@@ -17,7 +17,6 @@
 
 package org.apache.harmony.sql.tests.java.sql;
 
-
 /**
  * TODO Type description
  * 
diff --git a/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver4.java b/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver4.java
index 655436d..3e7000c 100644
--- a/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver4.java
+++ b/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver4.java
@@ -92,10 +92,13 @@
                         String user = (String) info.get(userProperty);
                         String password = (String) info.get(passwordProperty);
                         if (user == null || password == null) {
-                            throw new SQLException("Userid and/or password not supplied");
+                            throw new SQLException(
+                                    "Userid and/or password not supplied");
                         }
-                        if (!user.equals(validuser) || !password.equals(validpassword)) {
-                            throw new SQLException("Userid and/or password not valid");
+                        if (!user.equals(validuser)
+                                || !password.equals(validpassword)) {
+                            throw new SQLException(
+                                    "Userid and/or password not valid");
                         } // end if
                     } // end if
                     // It all checks out - so return a connection
@@ -117,7 +120,8 @@
 
     public DriverPropertyInfo[] getPropertyInfo(String url, Properties info)
             throws SQLException {
-        DriverPropertyInfo[] theInfos = { new DriverPropertyInfo(userProperty, "*"),
+        DriverPropertyInfo[] theInfos = {
+                new DriverPropertyInfo(userProperty, "*"),
                 new DriverPropertyInfo(passwordProperty, "*"), };
         return theInfos;
     }
diff --git a/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestMainForDriver.java b/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestMainForDriver.java
new file mode 100644
index 0000000..0fe7f67
--- /dev/null
+++ b/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestMainForDriver.java
@@ -0,0 +1,36 @@
+/*
+ * 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.sql.tests.java.sql;
+
+/*
+ * Load DriverManager class and initialize the class with SecurityManager
+ * Regression for HARMONY-4303
+ */
+public class TestMainForDriver {
+    public static void main(String[] args) throws Throwable {
+        // Install SecurityManager
+        System.setSecurityManager(new SecurityManager());
+        // Load java.sql.DriverManager and it will invoke its <clinit> method
+        try {
+            Class.forName("java.sql.DriverManager");
+        } catch (ExceptionInInitializerError e) {
+            // ExceptionInInitializerError is caused by AccessControlException
+            throw e.getException();
+        }
+    }
+}
diff --git a/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TimestampTest.java b/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TimestampTest.java
index bc1a9d5..c1c09a0 100644
--- a/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TimestampTest.java
+++ b/libcore/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TimestampTest.java
@@ -37,6 +37,22 @@
 
 public class TimestampTest extends TestCase {
 
+    static class MockTimestamp extends Timestamp{
+        private String holiday;
+
+        public MockTimestamp(long theTime) {
+            super(theTime);
+            holiday = "Christmas";
+        }
+
+        // Constructor should not call this public API,
+        // since it may be overrided to use variables uninitialized.
+        public void setTime(long theTime){
+            super.setTime(theTime);
+            holiday.hashCode();
+        }
+    }
+
     static long TIME_TEST1 = 38720231; // 10:45:20.231 GMT
 
     static long TIME_TEST2 = 80279000; // 22:17:59.000 GMT
@@ -126,6 +142,9 @@
 
         // The Timestamp should have been created
         assertNotNull(theTimestamp);
+
+        Timestamp mockTimestamp = new MockTimestamp(TIME_TEST1);
+        assertNotNull(mockTimestamp);
     } // end method testTimestamplong
 
     /*
@@ -277,6 +296,7 @@
     )
     @SuppressWarnings("deprecation")
     public void testGetDate() {
+    	TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
         for (int i = 0; i < TIME_ARRAY.length; i++) {
             Timestamp theTimestamp = new Timestamp(TIME_ARRAY[i]);
             assertEquals(DATE_ARRAY[i], theTimestamp.getDate());
@@ -295,6 +315,7 @@
     )
     @SuppressWarnings("deprecation")
     public void testGetHours() {
+    	TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
         for (int i = 0; i < TIME_ARRAY.length; i++) {
             Timestamp theTimestamp = new Timestamp(TIME_ARRAY[i]);
             assertEquals(HOURS_ARRAY[i], theTimestamp.getHours());
@@ -350,6 +371,7 @@
         args = {java.lang.String.class}
     )
     public void testValueOfString() {
+    	TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
         for (int i = 0; i < TIME_ARRAY.length; i++) {
             Timestamp theTimestamp = new Timestamp(TIME_ARRAY[i]);
             Timestamp theTimestamp2 = Timestamp.valueOf(STRING_GMT_ARRAY[i]);
@@ -370,7 +392,7 @@
                 Timestamp.valueOf(element);
                 fail("Should throw IllegalArgumentException.");
             } catch (IllegalArgumentException e) {
-                //expected
+                // expected
             } // end try
 
         } // end for
@@ -387,6 +409,7 @@
         args = {java.lang.String.class}
     )
     public void testValueOfString1() {
+    	TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
 
         Timestamp theReturn;
 
@@ -439,8 +462,37 @@
             }
         }
 
+        // Regression test for HARMONY-5506
+        String date = "1970-01-01 22:17:59.0                 ";
+        Timestamp t = Timestamp.valueOf(date);
+        assertEquals(80279000,t.getTime());
+
     } // end method testValueOfString
 
+    public void testValueOf_IAE() {
+        try {
+            java.sql.Timestamp.valueOf("2008-12-22 15:00:01.");
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+
+        try {
+            // bug of RI 5, passed on RI 6
+            java.sql.Timestamp.valueOf("178548938-12-22 15:00:01.000000001");
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+
+        try {
+            java.sql.Timestamp.valueOf("2008-12-22 15:00:01.0000000011");
+            fail("should throw IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // Expected
+        }
+    }
+
     /*
      * Method test for toString
      */
@@ -451,14 +503,36 @@
         args = {}
     )
     public void testToString() {
+        TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+
         for (int i = 0; i < TIME_ARRAY.length; i++) {
             Timestamp theTimestamp = new Timestamp(TIME_ARRAY[i]);
             assertEquals("Wrong conversion for test " + i, STRING_GMT_ARRAY[i],
                     theTimestamp.toString());
         } // end for
 
+		Timestamp t1 = new Timestamp(Long.MIN_VALUE);
+		assertEquals("292278994-08-17 07:12:55.192", t1.toString()); //$NON-NLS-1$
+
+		Timestamp t2 = new Timestamp(Long.MIN_VALUE + 1);
+		assertEquals("292278994-08-17 07:12:55.193", t2.toString()); //$NON-NLS-1$
+
+		Timestamp t3 = new Timestamp(Long.MIN_VALUE + 807);
+		assertEquals("292278994-08-17 07:12:55.999", t3.toString()); //$NON-NLS-1$
+
+		Timestamp t4 = new Timestamp(Long.MIN_VALUE + 808);
+		assertEquals("292269055-12-02 16:47:05.0", t4.toString()); //$NON-NLS-1$
     } // end method testtoString
 
+    private void testToString(String timeZone, long[] theTimeStamps, String[] theTimeStampStrings) {
+    	TimeZone.setDefault(TimeZone.getTimeZone(timeZone));
+        for (int i = 0; i < TIME_ARRAY.length; i++) {
+            Timestamp theTimestamp = new Timestamp(theTimeStamps[i]);
+            assertEquals(theTimeStampStrings[i], theTimestamp.toString());
+        } // end for
+
+    }
+
     /*
      * Method test for getNanos
      */
@@ -487,6 +561,8 @@
         args = {int.class}
     )
     public void testSetNanosint() {
+    	TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+
         int[] NANOS_INVALID = { -137891990, 1635665198, -1 };
         for (int i = 0; i < TIME_ARRAY.length; i++) {
             Timestamp theTimestamp = new Timestamp(TIME_ARRAY[i]);
@@ -787,5 +863,11 @@
         Timestamp t4 = new Timestamp(Long.MIN_VALUE + 808);
         assertEquals("292269055-12-02 16:47:05.0", t4.toString()); //$NON-NLS-1$
     }
- 
+
+    // Reset defualt timezone
+    TimeZone defaultTimeZone = TimeZone.getDefault();
+
+    protected void tearDown() {
+        TimeZone.setDefault(defaultTimeZone);
+    }
 } // end class TimestampTest
diff --git a/libcore/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/ConnectionEventTest.java b/libcore/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/ConnectionEventTest.java
index 376b173..12d4364 100644
--- a/libcore/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/ConnectionEventTest.java
+++ b/libcore/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/ConnectionEventTest.java
@@ -25,10 +25,14 @@
 import junit.framework.TestCase;
 
 import java.sql.SQLException;
+import java.io.Serializable;
 
 import javax.sql.ConnectionEvent;
 import javax.sql.PooledConnection;
 
+import org.apache.harmony.testframework.serialization.SerializationTest;
+import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert;
+
 @TestTargetClass(ConnectionEvent.class)
 public class ConnectionEventTest extends TestCase {
 
@@ -112,5 +116,63 @@
         assertNotSame(ce3.getSQLException(), ce2.getSQLException());
 
     }
-}   
 
+    @TestTargetNew(
+            level = TestLevel.SUFFICIENT,
+            notes = "",
+            method = "!SerializationSelf",
+            args = {}
+    )
+    public void testSerializationSelf() throws Exception {
+        Impl_PooledConnection ipc = new Impl_PooledConnection();
+        SQLException e = new SQLException();
+        ConnectionEvent ce = new ConnectionEvent(ipc, e);
+        SerializationTest.verifySelf(ce, CONNECTIONEVENT_COMPARATOR);
+    }
+
+    @TestTargetNew(
+            level = TestLevel.SUFFICIENT,
+            notes = "",
+            method = "!Serialization",
+            args = {}
+    )
+    public void testSerializationCompatibility() throws Exception {
+        Impl_PooledConnection ipc = new Impl_PooledConnection();
+        SQLException nextSQLException = new SQLException("nextReason",
+                "nextSQLState", 33);
+
+        int vendorCode = 10;
+        SQLException sqlException = new SQLException("reason", "SQLState",
+                vendorCode);
+
+        sqlException.setNextException(nextSQLException);
+
+        ConnectionEvent ce = new ConnectionEvent(ipc, sqlException);
+
+        SerializationTest.verifyGolden(this, ce, CONNECTIONEVENT_COMPARATOR);
+    }
+
+    private static final SerializableAssert CONNECTIONEVENT_COMPARATOR = new SerializableAssert() {
+
+        public void assertDeserialized(Serializable initial,
+                Serializable deserialized) {
+            ConnectionEvent ceInitial = (ConnectionEvent) initial;
+            ConnectionEvent ceDeser = (ConnectionEvent) deserialized;
+
+            SQLException initThr = ceInitial.getSQLException();
+            SQLException dserThr = ceDeser.getSQLException();
+
+            // verify SQLState
+            assertEquals(initThr.getSQLState(), dserThr.getSQLState());
+
+            // verify vendorCode
+            assertEquals(initThr.getErrorCode(), dserThr.getErrorCode());
+
+            // verify next
+            if (initThr.getNextException() == null) {
+                assertNull(dserThr.getNextException());
+            }
+        }
+
+    };
+}
diff --git a/libcore/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/Impl_PooledConnection.java b/libcore/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/Impl_PooledConnection.java
index d135ced..0eca2d2 100644
--- a/libcore/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/Impl_PooledConnection.java
+++ b/libcore/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/Impl_PooledConnection.java
@@ -33,6 +33,7 @@
         return null;
     }
 
-    public void removeConnectionEventListener(ConnectionEventListener theListener) {
+    public void removeConnectionEventListener(
+            ConnectionEventListener theListener) {
     }
 }
diff --git a/libcore/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/Impl_RowSet.java b/libcore/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/Impl_RowSet.java
index ace6b9a..946c40d 100644
--- a/libcore/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/Impl_RowSet.java
+++ b/libcore/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/Impl_RowSet.java
@@ -99,34 +99,38 @@
     public void removeRowSetListener(RowSetListener theListener) {
     }
 
-    public void setArray(int parameterIndex, Array theArray) throws SQLException {
-    }
-
-    public void setAsciiStream(int parameterIndex, InputStream theInputStream, int length)
+    public void setArray(int parameterIndex, Array theArray)
             throws SQLException {
     }
 
-    public void setBigDecimal(int parameterIndex, BigDecimal theBigDecimal) throws SQLException {
+    public void setAsciiStream(int parameterIndex, InputStream theInputStream,
+            int length) throws SQLException {
     }
 
-    public void setBinaryStream(int parameterIndex, InputStream theInputStream, int length)
+    public void setBigDecimal(int parameterIndex, BigDecimal theBigDecimal)
             throws SQLException {
     }
 
+    public void setBinaryStream(int parameterIndex, InputStream theInputStream,
+            int length) throws SQLException {
+    }
+
     public void setBlob(int parameterIndex, Blob theBlob) throws SQLException {
     }
 
-    public void setBoolean(int parameterIndex, boolean theBoolean) throws SQLException {
+    public void setBoolean(int parameterIndex, boolean theBoolean)
+            throws SQLException {
     }
 
     public void setByte(int parameterIndex, byte theByte) throws SQLException {
     }
 
-    public void setBytes(int parameterIndex, byte[] theByteArray) throws SQLException {
+    public void setBytes(int parameterIndex, byte[] theByteArray)
+            throws SQLException {
     }
 
-    public void setCharacterStream(int parameterIndex, Reader theReader, int length)
-            throws SQLException {
+    public void setCharacterStream(int parameterIndex, Reader theReader,
+            int length) throws SQLException {
     }
 
     public void setClob(int parameterIndex, Clob theClob) throws SQLException {
@@ -148,13 +152,15 @@
     public void setDate(int parameterIndex, Date theDate) throws SQLException {
     }
 
-    public void setDouble(int parameterIndex, double theDouble) throws SQLException {
+    public void setDouble(int parameterIndex, double theDouble)
+            throws SQLException {
     }
 
     public void setEscapeProcessing(boolean enable) throws SQLException {
     }
 
-    public void setFloat(int parameterIndex, float theFloat) throws SQLException {
+    public void setFloat(int parameterIndex, float theFloat)
+            throws SQLException {
     }
 
     public void setInt(int parameterIndex, int theInteger) throws SQLException {
@@ -169,21 +175,23 @@
     public void setMaxRows(int max) throws SQLException {
     }
 
-    public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException {
+    public void setNull(int parameterIndex, int sqlType, String typeName)
+            throws SQLException {
     }
 
     public void setNull(int parameterIndex, int sqlType) throws SQLException {
     }
 
-    public void setObject(int parameterIndex, Object theObject, int targetSqlType, int scale)
-            throws SQLException {
+    public void setObject(int parameterIndex, Object theObject,
+            int targetSqlType, int scale) throws SQLException {
     }
 
-    public void setObject(int parameterIndex, Object theObject, int targetSqlType)
-            throws SQLException {
+    public void setObject(int parameterIndex, Object theObject,
+            int targetSqlType) throws SQLException {
     }
 
-    public void setObject(int parameterIndex, Object theObject) throws SQLException {
+    public void setObject(int parameterIndex, Object theObject)
+            throws SQLException {
     }
 
     public void setPassword(String password) throws SQLException {
@@ -198,10 +206,12 @@
     public void setRef(int parameterIndex, Ref theRef) throws SQLException {
     }
 
-    public void setShort(int parameterIndex, short theShort) throws SQLException {
+    public void setShort(int parameterIndex, short theShort)
+            throws SQLException {
     }
 
-    public void setString(int parameterIndex, String theString) throws SQLException {
+    public void setString(int parameterIndex, String theString)
+            throws SQLException {
     }
 
     public void setTime(int parameterIndex, Time theTime, Calendar theCalendar)
@@ -211,11 +221,12 @@
     public void setTime(int parameterIndex, Time theTime) throws SQLException {
     }
 
-    public void setTimestamp(int parameterIndex, Timestamp theTimestamp, Calendar theCalendar)
-            throws SQLException {
+    public void setTimestamp(int parameterIndex, Timestamp theTimestamp,
+            Calendar theCalendar) throws SQLException {
     }
 
-    public void setTimestamp(int parameterIndex, Timestamp theTimestamp) throws SQLException {
+    public void setTimestamp(int parameterIndex, Timestamp theTimestamp)
+            throws SQLException {
     }
 
     public void setTransactionIsolation(int level) throws SQLException {
@@ -224,7 +235,8 @@
     public void setType(int type) throws SQLException {
     }
 
-    public void setTypeMap(Map<String, Class<?>> theTypeMap) throws SQLException {
+    public void setTypeMap(Map<String, Class<?>> theTypeMap)
+            throws SQLException {
     }
 
     public void setUrl(String theURL) throws SQLException {
@@ -279,7 +291,8 @@
         return null;
     }
 
-    public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
+    public BigDecimal getBigDecimal(int columnIndex, int scale)
+            throws SQLException {
         return null;
     }
 
@@ -287,7 +300,8 @@
         return null;
     }
 
-    public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException {
+    public BigDecimal getBigDecimal(String columnName, int scale)
+            throws SQLException {
         return null;
     }
 
@@ -419,7 +433,8 @@
         return null;
     }
 
-    public Object getObject(int columnIndex, Map<String, Class<?>> map) throws SQLException {
+    public Object getObject(int columnIndex, Map<String, Class<?>> map)
+            throws SQLException {
         return null;
     }
 
@@ -427,7 +442,8 @@
         return null;
     }
 
-    public Object getObject(String columnName, Map<String, Class<?>> map) throws SQLException {
+    public Object getObject(String columnName, Map<String, Class<?>> map)
+            throws SQLException {
         return null;
     }
 
@@ -483,7 +499,8 @@
         return null;
     }
 
-    public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException {
+    public Timestamp getTimestamp(int columnIndex, Calendar cal)
+            throws SQLException {
         return null;
     }
 
@@ -491,7 +508,8 @@
         return null;
     }
 
-    public Timestamp getTimestamp(String columnName, Calendar cal) throws SQLException {
+    public Timestamp getTimestamp(String columnName, Calendar cal)
+            throws SQLException {
         return null;
     }
 
@@ -599,10 +617,12 @@
             throws SQLException {
     }
 
-    public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException {
+    public void updateBigDecimal(int columnIndex, BigDecimal x)
+            throws SQLException {
     }
 
-    public void updateBigDecimal(String columnName, BigDecimal x) throws SQLException {
+    public void updateBigDecimal(String columnName, BigDecimal x)
+            throws SQLException {
     }
 
     public void updateBinaryStream(int columnIndex, InputStream x, int length)
@@ -641,8 +661,8 @@
             throws SQLException {
     }
 
-    public void updateCharacterStream(String columnName, Reader reader, int length)
-            throws SQLException {
+    public void updateCharacterStream(String columnName, Reader reader,
+            int length) throws SQLException {
     }
 
     public void updateClob(int columnIndex, Clob x) throws SQLException {
@@ -687,13 +707,15 @@
     public void updateNull(String columnName) throws SQLException {
     }
 
-    public void updateObject(int columnIndex, Object x, int scale) throws SQLException {
+    public void updateObject(int columnIndex, Object x, int scale)
+            throws SQLException {
     }
 
     public void updateObject(int columnIndex, Object x) throws SQLException {
     }
 
-    public void updateObject(String columnName, Object x, int scale) throws SQLException {
+    public void updateObject(String columnName, Object x, int scale)
+            throws SQLException {
     }
 
     public void updateObject(String columnName, Object x) throws SQLException {
@@ -726,10 +748,12 @@
     public void updateTime(String columnName, Time x) throws SQLException {
     }
 
-    public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException {
+    public void updateTimestamp(int columnIndex, Timestamp x)
+            throws SQLException {
     }
 
-    public void updateTimestamp(String columnName, Timestamp x) throws SQLException {
+    public void updateTimestamp(String columnName, Timestamp x)
+            throws SQLException {
     }
 
     public boolean wasNull() throws SQLException {
diff --git a/libcore/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/RowSetEventTest.java b/libcore/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/RowSetEventTest.java
index bf30fbc..9f048f7 100644
--- a/libcore/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/RowSetEventTest.java
+++ b/libcore/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/RowSetEventTest.java
@@ -45,7 +45,7 @@
             fail("illegal argument exception expected");
         } catch (IllegalArgumentException e) {
         }
-        
+
         Impl_RowSet irs = new Impl_RowSet();
         RowSetEvent rse = new RowSetEvent(irs);
         assertSame(irs, rse.getSource());
diff --git a/libcore/suncompat/src/main/java/sun/misc/Unsafe.java b/libcore/suncompat/src/main/java/sun/misc/Unsafe.java
index e880af2..6ae572f 100644
--- a/libcore/suncompat/src/main/java/sun/misc/Unsafe.java
+++ b/libcore/suncompat/src/main/java/sun/misc/Unsafe.java
@@ -52,9 +52,7 @@
          * Only code on the bootclasspath is allowed to get at the
          * Unsafe instance.
          */
-        ClassLoader calling = VMStack.getCallingClassLoader2();
-        ClassLoader current = Unsafe.class.getClassLoader();
-
+        ClassLoader calling = VMStack.getCallingClassLoader();
         if ((calling != null) && (calling != Unsafe.class.getClassLoader())) {
             throw new SecurityException("Unsafe access denied");
         }
diff --git a/libcore/suncompat/src/test/java/sun/misc/AllTests.java b/libcore/suncompat/src/test/java/sun/misc/AllTests.java
new file mode 100644
index 0000000..8ea3bcf
--- /dev/null
+++ b/libcore/suncompat/src/test/java/sun/misc/AllTests.java
@@ -0,0 +1,39 @@
+/*
+ * 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 sun.misc;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(AllTests.suite());
+    }
+
+    public static Test suite() {
+        TestSuite suite = tests.TestSuiteFactory.createTestSuite("Test for sun.misc");
+
+        // $JUnit-BEGIN$
+
+        suite.addTestSuite(UnsafeTest.class);
+
+        // $JUnit-END$
+
+        return suite;
+    }
+}
diff --git a/libcore/suncompat/src/test/java/sun/misc/UnsafeTest.java b/libcore/suncompat/src/test/java/sun/misc/UnsafeTest.java
new file mode 100644
index 0000000..338055b
--- /dev/null
+++ b/libcore/suncompat/src/test/java/sun/misc/UnsafeTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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 sun.misc;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import junit.framework.TestCase;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executors;
+
+@TestTargetClass(Unsafe.class)
+public class UnsafeTest extends TestCase {
+
+    @TestTargetNew(
+            level = TestLevel.PARTIAL,
+            notes = "",
+            method = "getUnsafe",
+            args = {}
+    )
+    public void test_getUnsafeForbidden() {
+        try {
+            Unsafe.getUnsafe();
+            fail();
+        } catch (SecurityException expected) {
+        }
+    }
+
+    /**
+     * Regression for 2053217. We used to look one level higher than necessary
+     * on the stack.
+     */
+    @TestTargetNew(
+            level = TestLevel.PARTIAL,
+            notes = "",
+            method = "getUnsafe",
+            args = {}
+    )
+    public void test_getUnsafeForbiddenWithSystemCaller() throws Exception {
+        Callable<Object> callable = Executors.callable(new Runnable() {
+            public void run() {
+                Unsafe.getUnsafe();
+            }
+        });
+
+        try {
+            callable.call();
+            fail();
+        } catch (SecurityException expected) {
+        }
+    }
+}
diff --git a/libcore/suncompat/src/test/java/tests/suncompat/AllTests.java b/libcore/suncompat/src/test/java/tests/suncompat/AllTests.java
new file mode 100644
index 0000000..0884517
--- /dev/null
+++ b/libcore/suncompat/src/test/java/tests/suncompat/AllTests.java
@@ -0,0 +1,38 @@
+/* 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 tests.suncompat;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Test suite that includes all tests for the suncompat project.
+ */
+public class AllTests {
+
+    public static void main(String[] args) {
+        junit.textui.TestRunner.run(AllTests.suite());
+    }
+
+    public static Test suite() {
+        TestSuite suite = tests.TestSuiteFactory.createTestSuite("All suncompat test suites");
+        // $JUnit-BEGIN$
+        suite.addTest(sun.misc.AllTests.suite());
+        // $JUnit-END$
+        return suite;
+    }
+}
diff --git a/libcore/support/src/test/java/tests/resources/EmptyEntries_signed.jar b/libcore/support/src/test/java/tests/resources/EmptyEntries_signed.jar
new file mode 100644
index 0000000..237d244
--- /dev/null
+++ b/libcore/support/src/test/java/tests/resources/EmptyEntries_signed.jar
Binary files differ
diff --git a/libcore/support/src/test/java/tests/support/Support_Configuration.java b/libcore/support/src/test/java/tests/support/Support_Configuration.java
index 9294ae9..19af32e 100644
--- a/libcore/support/src/test/java/tests/support/Support_Configuration.java
+++ b/libcore/support/src/test/java/tests/support/Support_Configuration.java
@@ -75,8 +75,6 @@
 
     public static byte[] InetTestCaddr = { 9, 26, -56, -111 };
 
-    public static int InetTestHashcode = 2130706433;
-
     public static final String HomeAddress6 = "jcltest6.apache.org";
 
     public static String IPv6GlobalAddressJcl4 = "FE80:0000:0000:0000:020D:60FF:FE0F:A776%4"; // this
@@ -92,13 +90,6 @@
     // this allows us to check the timeouts for connect
     public static String ResolvedNotExistingHost = "9.26.194.72";
 
-    /**
-     * You can compute the hash code with the following code: try { String name =
-     * "whatever.xxx.com";
-     * System.out.println(InetAddress.getByName(name).hashCode()); } catch
-     * (UnknownHostException e) {}
-     */
-
     // BEGIN android-changed
     /**
      * An address that resolves to more than one IP address so that the
@@ -292,11 +283,6 @@
             InetTestIP2 = value;
         }
 
-        value = props.get("InetTestHashcode");
-        if (value != null) {
-            InetTestHashcode = Integer.parseInt(value);
-        }
-
         value = props.get("SpecialInetTestAddress");
         if (value != null) {
             SpecialInetTestAddress = value;
diff --git a/libcore/support/src/test/java/tests/support/Support_TestWebServer.java b/libcore/support/src/test/java/tests/support/Support_TestWebServer.java
index 8ee7248..609e993 100644
--- a/libcore/support/src/test/java/tests/support/Support_TestWebServer.java
+++ b/libcore/support/src/test/java/tests/support/Support_TestWebServer.java
@@ -19,9 +19,9 @@
 import java.io.*;
 import java.lang.Thread;
 import java.net.*;
-import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.logging.Logger;
 
 /**
@@ -42,6 +42,10 @@
     /* Where worker threads stand idle */
     Vector threads = new Vector();
 
+    /** maps the recently requested URLs to the full request snapshot */
+    private final Map<String, Request> pathToRequest
+            = new ConcurrentHashMap<String, Request>();
+
     /* List of all active worker threads */
     Vector activeThreads = new Vector();
 
@@ -206,7 +210,7 @@
      * a redirect code with the Location response header set to the value
      * specified.
      * @param redirect The location to be redirected to
-     * @param redirectCode The code to send when redirecting
+     * @param code The code to send when redirecting
      */
     public void setRedirect(String redirect, int code) {
         redirectHost = redirect;
@@ -215,6 +219,14 @@
     }
 
     /**
+     * Returns a map from recently-requested paths (like "/index.html") to a
+     * snapshot of the request data.
+     */
+    public Map<String, Request> pathToRequest() {
+        return pathToRequest;
+    }
+
+    /**
      * Cause the thread accepting connections on the server socket to close
      */
     public void close() {
@@ -328,6 +340,28 @@
     static final byte[] EOL = {(byte)'\r', (byte)'\n' };
 
     /**
+     * An immutable snapshot of an HTTP request.
+     */
+    public static class Request {
+        private final String path;
+        private final Map<String, String> headers;
+        // TODO: include posted content?
+
+        public Request(String path, Map<String, String> headers) {
+            this.path = path;
+            this.headers = new LinkedHashMap<String, String>(headers);
+        }
+
+        public String getPath() {
+            return path;
+        }
+
+        public Map<String, String> getHeaders() {
+            return headers;
+        }
+    }
+
+    /**
      * The worker thread handles all interactions with a current open
      * connection. If pipelining is turned on, this will allow this
      * thread to continuously operate on numerous requests before the
@@ -347,6 +381,9 @@
         /* Reference to current requests test file/data */
         private String testID;
 
+        /* The requested path, such as "/test1" */
+        private String path;
+
         /* Reference to test number from testID */
         private int testNum;
 
@@ -359,7 +396,7 @@
         boolean running = false;
 
         /* Request headers are stored here */
-        private Hashtable<String, String> headers = new Hashtable<String, String>();
+        private Map<String, String> headers = new LinkedHashMap<String, String>();
 
         /* Create a new worker thread */
         Worker() {
@@ -559,10 +596,8 @@
                     i++;
                 }
 
-                testID = new String(buf, 0, index, i-index);
-                if (testID.startsWith("/")) {
-                    testID = testID.substring(1);
-                }
+                path = new String(buf, 0, index, i-index);
+                testID = path.substring(1);
 
                 return nread;
             }
@@ -601,7 +636,7 @@
             while (buf[i] == ' ') {
                 i++;
             }
-            String headerValue = new String(buf, i, nread-1);
+            String headerValue = new String(buf, i, nread-i);
 
             headers.put(headerName, headerValue);
             return nread;
@@ -666,6 +701,8 @@
                     // If status line found, read any headers
                     nread = readHeaders(is);
 
+                    pathToRequest().put(path, new Request(path, headers));
+
                     // Then read content (if any)
                     // TODO handle chunked encoding from the client
                     if (headers.get(requestHeaders[REQ_CONTENT_LENGTH]) != null) {
diff --git a/libcore/support/src/test/java/tests/util/PrefsTester.java b/libcore/support/src/test/java/tests/util/PrefsTester.java
new file mode 100644
index 0000000..047b357
--- /dev/null
+++ b/libcore/support/src/test/java/tests/util/PrefsTester.java
@@ -0,0 +1,73 @@
+/* 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 tests.util;
+
+import java.util.prefs.BackingStoreException;
+import java.util.prefs.Preferences;
+import java.util.Arrays;
+
+/**
+ * Prepares the shared preferences store for a test by wiping preference data
+ * before and after the test. Sample usage:
+ * <pre>
+ * public void MyPreferencesTest extends TestCase {
+ *     private final PrefsTester prefsTester = new PrefsTester();
+ *
+ *     public void setUp() throws BackingStoreException {
+ *         super.setUp();
+ *         prefsTester.setUp();
+ *     }
+ *
+ *     public void tearDown() throws BackingStoreException {
+ *         prefsTester.tearDown();
+ *         super.tearDown();
+ *     }
+ *
+ *     ...
+ * }</pre>
+ *
+ * <p>Once the preferences classes have been initialized, the path where their
+ * data is stored is fixed. For that reason, every test that reads or writes
+ * preferences must first prepare preferences for testing by using this class.
+ */
+public final class PrefsTester {
+
+    static {
+        String tmp = System.getProperty("java.io.tmpdir");
+        System.setProperty("user.home", tmp);
+        System.setProperty("java.home", tmp);
+    }
+
+    public void setUp() throws BackingStoreException {
+        clear();
+    }
+
+    public void tearDown() throws BackingStoreException {
+        clear();
+    }
+
+    private void clear() throws BackingStoreException {
+        for (Preferences root : Arrays .asList(
+                Preferences.systemRoot(), Preferences.userRoot())) {
+            for (String child : root.childrenNames()) {
+                root.node(child).removeNode();
+            }
+            root.clear();
+            root.flush();
+        }
+    }
+}
diff --git a/libcore/text/src/main/java/java/text/Annotation.java b/libcore/text/src/main/java/java/text/Annotation.java
index a45ccaa..4023449 100644
--- a/libcore/text/src/main/java/java/text/Annotation.java
+++ b/libcore/text/src/main/java/java/text/Annotation.java
@@ -30,13 +30,9 @@
  * By wrapping text attribute values into an {@code Annotation}, these aspects
  * will be taken into account when handling annotation text and the
  * corresponding main text.
- * </p>
  * <p>
  * Note: There is no semantic connection between this annotation class and the
  * {@code java.lang.annotation} package.
- * </p>
- * 
- * @since Android 1.0
  */
 public class Annotation {
 
@@ -44,10 +40,9 @@
 
     /**
      * Constructs a new {@code Annotation}.
-     * 
+     *
      * @param attribute the attribute attached to this annotation. This may be
      *        {@code null}.
-     * @since Android 1.0
      */
     public Annotation(Object attribute) {
         value = attribute;
@@ -55,9 +50,8 @@
 
     /**
      * Returns the value of this annotation. The value may be {@code null}.
-     * 
+     *
      * @return the value of this annotation or {@code null}.
-     * @since Android 1.0
      */
     public Object getValue() {
         return value;
@@ -65,9 +59,8 @@
 
     /**
      * Returns this annotation in string representation.
-     * 
+     *
      * @return the string representation of this annotation.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
diff --git a/libcore/text/src/main/java/java/text/AttributedCharacterIterator.java b/libcore/text/src/main/java/java/text/AttributedCharacterIterator.java
index 07bbdec..4f260ec 100644
--- a/libcore/text/src/main/java/java/text/AttributedCharacterIterator.java
+++ b/libcore/text/src/main/java/java/text/AttributedCharacterIterator.java
@@ -31,15 +31,11 @@
  * {@code AttributedCharacterIterator} also allows the user to find runs and
  * their limits. Runs are defined as ranges of characters that all have the same
  * attributes with the same values.
- * 
- * @since Android 1.0
  */
 public interface AttributedCharacterIterator extends CharacterIterator {
 
     /**
      * Defines keys for text attributes.
-     * 
-     * @since Android 1.0
      */
     public static class Attribute implements Serializable {
 
@@ -48,11 +44,9 @@
         /**
          * This attribute marks segments from an input method. Most input
          * methods create these segments for words.
-         * 
+         *
          * The value objects are of the type {@code Annotation} which contain
          * {@code null}.
-         * 
-         * @since Android 1.0
          */
         public static final Attribute INPUT_METHOD_SEGMENT = new Attribute(
                 "input_method_segment"); //$NON-NLS-1$
@@ -60,8 +54,6 @@
         /**
          * The attribute describing the language of a character. The value
          * objects are of type {@code Locale} or a subtype of it.
-         * 
-         * @since Android 1.0
          */
         public static final Attribute LANGUAGE = new Attribute("language"); //$NON-NLS-1$
 
@@ -70,8 +62,6 @@
          * Japanese), this attribute allows to define which reading should be
          * used. The value objects are of type {@code Annotation} which
          * contain a {@code String}.
-         * 
-         * @since Android 1.0
          */
         public static final Attribute READING = new Attribute("reading"); //$NON-NLS-1$
 
@@ -79,10 +69,9 @@
 
         /**
          * The constructor for an {@code Attribute} with the name passed.
-         * 
+         *
          * @param name
          *            the name of the new {@code Attribute}.
-         * @since Android 1.0
          */
         protected Attribute(String name) {
             this.name = name;
@@ -92,23 +81,21 @@
          * Compares this attribute with the specified object. Checks if both
          * objects are the same instance. It is defined final so all subclasses
          * have the same behavior for this method.
-         * 
+         *
          * @param object
          *            the object to compare against.
          * @return {@code true} if the object passed is equal to this instance;
          *         {@code false} otherwise.
-         * @since Android 1.0
          */
         @Override
         public final boolean equals(Object object) {
-            return super.equals(object);
+            return this == object;
         }
 
         /**
          * Returns the name of this attribute.
-         * 
+         *
          * @return the name of this attribute.
-         * @since Android 1.0
          */
         protected String getName() {
             return name;
@@ -118,9 +105,8 @@
          * Calculates the hash code for objects of type {@code Attribute}. It
          * is defined final so all sub types calculate their hash code
          * identically.
-         * 
+         *
          * @return the hash code for this instance of {@code Attribute}.
-         * @since Android 1.0
          */
         @Override
         public final int hashCode() {
@@ -129,27 +115,30 @@
 
         /**
          * Resolves a deserialized instance to the correct constant attribute.
-         * 
+         *
          * @return the {@code Attribute} this instance represents.
          * @throws InvalidObjectException
          *             if this instance is not of type {@code Attribute.class}
          *             or if it is not a known {@code Attribute}.
-         * @since Android 1.0
          */
         protected Object readResolve() throws InvalidObjectException {
             if (this.getClass() != Attribute.class) {
                 // text.0C=cannot resolve subclasses
                 throw new InvalidObjectException(Messages.getString("text.0C")); //$NON-NLS-1$
             }
-            if (this.name.equals(INPUT_METHOD_SEGMENT.name)) {
+            // BEGIN android-changed
+            // call getName() only once
+            String name = this.getName();
+            if (name.equals(INPUT_METHOD_SEGMENT.getName())) {
                 return INPUT_METHOD_SEGMENT;
             }
-            if (this.name.equals(LANGUAGE.name)) {
+            if (name.equals(LANGUAGE.getName())) {
                 return LANGUAGE;
             }
-            if (this.name.equals(READING.name)) {
+            if (name.equals(READING.getName())) {
                 return READING;
             }
+            // END android-changed
             // text.02=Unknown attribute
             throw new InvalidObjectException(Messages.getString("text.02")); //$NON-NLS-1$
         }
@@ -157,9 +146,8 @@
         /**
          * Returns the name of the class followed by a "(", the name of the
          * attribute, and a ")".
-         * 
+         *
          * @return the string representing this instance.
-         * @since Android 1.0
          */
         @Override
         public String toString() {
@@ -171,20 +159,18 @@
      * Returns a set of attributes present in the {@code
      * AttributedCharacterIterator}. An empty set is returned if no attributes
      * were defined.
-     * 
+     *
      * @return a set of attribute keys; may be empty.
-     * @since Android 1.0
      */
     public Set<Attribute> getAllAttributeKeys();
 
     /**
      * Returns the value stored in the attribute for the current character. If
      * the attribute was not defined then {@code null} is returned.
-     * 
+     *
      * @param attribute the attribute for which the value should be returned.
      * @return the value of the requested attribute for the current character or
      *         {@code null} if it was not defined.
-     * @since Android 1.0
      */
     public Object getAttribute(Attribute attribute);
 
@@ -192,72 +178,65 @@
      * Returns a map of all attributes of the current character. If no
      * attributes were defined for the current character then an empty map is
      * returned.
-     * 
+     *
      * @return a map of all attributes for the current character or an empty
      *         map.
-     * @since Android 1.0
      */
     public Map<Attribute, Object> getAttributes();
 
     /**
      * Returns the index of the last character in the run having the same
      * attributes as the current character.
-     * 
+     *
      * @return the index of the last character of the current run.
-     * @since Android 1.0
      */
     public int getRunLimit();
 
     /**
      * Returns the index of the last character in the run that has the same
      * attribute value for the given attribute as the current character.
-     * 
+     *
      * @param attribute
      *            the attribute which the run is based on.
      * @return the index of the last character of the current run.
-     * @since Android 1.0
      */
     public int getRunLimit(Attribute attribute);
 
     /**
      * Returns the index of the last character in the run that has the same
      * attribute values for the attributes in the set as the current character.
-     * 
+     *
      * @param attributes
      *            the set of attributes which the run is based on.
      * @return the index of the last character of the current run.
-     * @since Android 1.0
      */
     public int getRunLimit(Set<? extends Attribute> attributes);
 
     /**
      * Returns the index of the first character in the run that has the same
      * attributes as the current character.
-     * 
+     *
      * @return the index of the last character of the current run.
-     * @since Android 1.0
      */
     public int getRunStart();
 
     /**
      * Returns the index of the first character in the run that has the same
      * attribute value for the given attribute as the current character.
-     * 
+     *
      * @param attribute
      *            the attribute which the run is based on.
      * @return the index of the last character of the current run.
-     * @since Android 1.0
      */
     public int getRunStart(Attribute attribute);
 
     /**
      * Returns the index of the first character in the run that has the same
      * attribute values for the attributes in the set as the current character.
-     * 
+     *
      * @param attributes
      *            the set of attributes which the run is based on.
      * @return the index of the last character of the current run.
-     * @since Android 1.0
      */
     public int getRunStart(Set<? extends Attribute> attributes);
 }
diff --git a/libcore/text/src/main/java/java/text/AttributedString.java b/libcore/text/src/main/java/java/text/AttributedString.java
index 540e671..77bbf78 100644
--- a/libcore/text/src/main/java/java/text/AttributedString.java
+++ b/libcore/text/src/main/java/java/text/AttributedString.java
@@ -33,8 +33,6 @@
 /**
  * Holds a string with attributes describing the characters of
  * this string.
- * 
- * @since Android 1.0
  */
 public class AttributedString {
 
@@ -180,8 +178,8 @@
 
         /**
          * Returns a set of attributes present in the {@code AttributedString}.
-         * An empty set returned indicates that no attributes where defined
-         * 
+         * An empty set returned indicates that no attributes where defined.
+         *
          * @return a set of attribute keys that may be empty.
          */
         public Set<AttributedIterator.Attribute> getAllAttributeKeys() {
@@ -384,18 +382,17 @@
     /**
      * Constructs an {@code AttributedString} from an {@code
      * AttributedCharacterIterator}, which represents attributed text.
-     * 
+     *
      * @param iterator
      *            the {@code AttributedCharacterIterator} that contains the text
      *            for this attributed string.
-     * @since Android 1.0
      */
     public AttributedString(AttributedCharacterIterator iterator) {
         if (iterator.getBeginIndex() > iterator.getEndIndex()) {
             // text.0A=Invalid substring range
             throw new IllegalArgumentException(Messages.getString("text.0A")); //$NON-NLS-1$
         }
-        StringBuffer buffer = new StringBuffer();
+        StringBuilder buffer = new StringBuilder();
         for (int i = iterator.getBeginIndex(); i < iterator.getEndIndex(); i++) {
             buffer.append(iterator.current());
             iterator.next();
@@ -436,7 +433,7 @@
             return;
         }
 
-        StringBuffer buffer = new StringBuffer();
+        StringBuilder buffer = new StringBuilder();
         iterator.setIndex(start);
         while (iterator.getIndex() < end) {
             buffer.append(iterator.current());
@@ -470,7 +467,7 @@
      * in the specified {@code AttributedCharacterIterator}, starting at {@code
      * start} and ending at {@code end}. All attributes will be copied to this
      * attributed string.
-     * 
+     *
      * @param iterator
      *            the {@code AttributedCharacterIterator} that contains the text
      *            for this attributed string.
@@ -479,10 +476,9 @@
      * @param end
      *            the end index of the range of the copied text.
      * @throws IllegalArgumentException
-     *             if {@code start} is less than first index of 
+     *             if {@code start} is less than first index of
      *             {@code iterator}, {@code end} is greater than the last
      *             index + 1 in {@code iterator} or if {@code start > end}.
-     * @since Android 1.0
      */
     public AttributedString(AttributedCharacterIterator iterator, int start,
             int end) {
@@ -495,7 +491,7 @@
      * start}, ending at {@code end} and it will copy the attributes defined in
      * the specified set. If the set is {@code null} then all attributes are
      * copied.
-     * 
+     *
      * @param iterator
      *            the {@code AttributedCharacterIterator} that contains the text
      *            for this attributed string.
@@ -507,10 +503,9 @@
      *            the set of attributes that will be copied, or all if it is
      *            {@code null}.
      * @throws IllegalArgumentException
-     *             if {@code start} is less than first index of 
-     *             {@code iterator}, {@code end} is greater than the last index + 
+     *             if {@code start} is less than first index of
+     *             {@code iterator}, {@code end} is greater than the last index +
      *             1 in {@code iterator} or if {@code start > end}.
-     * @since Android 1.0
      */
     public AttributedString(AttributedCharacterIterator iterator, int start,
             int end, AttributedCharacterIterator.Attribute[] attributes) {
@@ -527,10 +522,9 @@
 
     /**
      * Creates an {@code AttributedString} from the given text.
-     * 
+     *
      * @param value
      *            the text to take as base for this attributed string.
-     * @since Android 1.0
      */
     public AttributedString(String value) {
         if (value == null) {
@@ -543,7 +537,7 @@
     /**
      * Creates an {@code AttributedString} from the given text and the
      * attributes. The whole text has the given attributes applied.
-     * 
+     *
      * @param value
      *            the text to take as base for this attributed string.
      * @param attributes
@@ -553,7 +547,6 @@
      *             attributes} is greater than 0.
      * @throws NullPointerException
      *             if {@code value} is {@code null}.
-     * @since Android 1.0
      */
     public AttributedString(String value,
             Map<? extends AttributedCharacterIterator.Attribute, ?> attributes) {
@@ -579,7 +572,7 @@
 
     /**
      * Applies a given attribute to this string.
-     * 
+     *
      * @param attribute
      *            the attribute that will be applied to this string.
      * @param value
@@ -589,7 +582,6 @@
      *             if the length of this attributed string is 0.
      * @throws NullPointerException
      *             if {@code attribute} is {@code null}.
-     * @since Android 1.0
      */
     public void addAttribute(AttributedCharacterIterator.Attribute attribute,
             Object value) {
@@ -612,7 +604,7 @@
 
     /**
      * Applies a given attribute to the given range of this string.
-     * 
+     *
      * @param attribute
      *            the attribute that will be applied to this string.
      * @param value
@@ -627,7 +619,6 @@
      *             of this string, or if {@code start >= end}.
      * @throws NullPointerException
      *             if {@code attribute} is {@code null}.
-     * @since Android 1.0
      */
     public void addAttribute(AttributedCharacterIterator.Attribute attribute,
             Object value, int start, int end) {
@@ -650,9 +641,6 @@
             return;
         }
         ListIterator<Range> it = ranges.listIterator();
-        // BEGIN android-changed
-        // copied from a newer version of harmony
-        // value can't be null
         while (it.hasNext()) {
             Range range = it.next();
             if (end <= range.start) {
@@ -710,13 +698,12 @@
                 return;
             }
         }
-        // END android-changed
         it.add(new Range(start, end, value));
     }
 
     /**
      * Applies a given set of attributes to the given range of the string.
-     * 
+     *
      * @param attributes
      *            the set of attributes that will be applied to this string.
      * @param start
@@ -726,7 +713,6 @@
      * @throws IllegalArgumentException
      *             if {@code start < 0}, {@code end} is greater than the length
      *             of this string, or if {@code start >= end}.
-     * @since Android 1.0
      */
     public void addAttributes(
             Map<? extends AttributedCharacterIterator.Attribute, ?> attributes,
@@ -743,9 +729,8 @@
     /**
      * Returns an {@code AttributedCharacterIterator} that gives access to the
      * complete content of this attributed string.
-     * 
+     *
      * @return the newly created {@code AttributedCharacterIterator}.
-     * @since Android 1.0
      */
     public AttributedCharacterIterator getIterator() {
         return new AttributedIterator(this);
@@ -756,12 +741,11 @@
      * complete content of this attributed string. Only attributes contained in
      * {@code attributes} are available from this iterator if they are defined
      * for this text.
-     * 
+     *
      * @param attributes
      *            the array containing attributes that will be in the new
      *            iterator if they are defined for this text.
      * @return the newly created {@code AttributedCharacterIterator}.
-     * @since Android 1.0
      */
     public AttributedCharacterIterator getIterator(
             AttributedCharacterIterator.Attribute[] attributes) {
@@ -773,7 +757,7 @@
      * contents of this attributed string starting at index {@code start} up to
      * index {@code end}. Only attributes contained in {@code attributes} are
      * available from this iterator if they are defined for this text.
-     * 
+     *
      * @param attributes
      *            the array containing attributes that will be in the new
      *            iterator if they are defined for this text.
@@ -782,7 +766,6 @@
      * @param end
      *            the end index of the iterator on the underlying text.
      * @return the newly created {@code AttributedCharacterIterator}.
-     * @since Android 1.0
      */
     public AttributedCharacterIterator getIterator(
             AttributedCharacterIterator.Attribute[] attributes, int start,
diff --git a/libcore/text/src/main/java/java/text/Bidi.java b/libcore/text/src/main/java/java/text/Bidi.java
index 228dab3..7939dea 100644
--- a/libcore/text/src/main/java/java/text/Bidi.java
+++ b/libcore/text/src/main/java/java/text/Bidi.java
@@ -15,8 +15,13 @@
  * limitations under the License.
  */
 
+// BEGIN android-note
+// changed from icu.text.Bidi to BidiWrapper
+// END android-note
+
 package java.text;
 
+// BEGIN android-added
 import java.awt.font.NumericShaper;
 import java.awt.font.TextAttribute;
 import java.util.Arrays;
@@ -24,6 +29,7 @@
 
 import org.apache.harmony.text.BidiRun;
 import org.apache.harmony.text.BidiWrapper;
+// END android-added
 import org.apache.harmony.text.internal.nls.Messages;
 
 /**
@@ -40,40 +46,51 @@
  * obtained from the run index. The level of any particular run indicates the
  * direction of the text as well as the nesting level. Left-to-right runs have
  * even levels while right-to-left runs have odd levels.
- * 
- * @since Android 1.0
  */
 public final class Bidi {
     /**
      * Constant that indicates the default base level. If there is no strong
      * character, then set the paragraph level to 0 (left-to-right).
-     * 
-     * @since Android 1.0
      */
     public static final int DIRECTION_DEFAULT_LEFT_TO_RIGHT = -2;
 
     /**
      * Constant that indicates the default base level. If there is no strong
      * character, then set the paragraph level to 1 (right-to-left).
-     * 
-     * @since Android 1.0
      */
     public static final int DIRECTION_DEFAULT_RIGHT_TO_LEFT = -1;
 
     /**
      * Constant that specifies the default base level as 0 (left-to-right).
-     * 
-     * @since Android 1.0
      */
     public static final int DIRECTION_LEFT_TO_RIGHT = 0;
 
     /**
      * Constant that specifies the default base level as 1 (right-to-left).
-     * 
-     * @since Android 1.0
      */
     public static final int DIRECTION_RIGHT_TO_LEFT = 1;
 
+    // BEGIN android-removed
+    // /*
+    //  * Converts the constant from the value specified in the Java spec, to the
+    //  * value required by the ICU implementation.
+    //  */
+    // private final static int convertDirectionConstant(int javaConst) {
+    //     switch (javaConst) {
+    //     case DIRECTION_DEFAULT_LEFT_TO_RIGHT : return com.ibm.icu.text.Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT;
+    //     case DIRECTION_DEFAULT_RIGHT_TO_LEFT : return com.ibm.icu.text.Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT;
+    //     case DIRECTION_LEFT_TO_RIGHT         : return com.ibm.icu.text.Bidi.DIRECTION_LEFT_TO_RIGHT;
+    //     case DIRECTION_RIGHT_TO_LEFT         : return com.ibm.icu.text.Bidi.DIRECTION_RIGHT_TO_LEFT;
+    //     default                              : return com.ibm.icu.text.Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT;
+    //     }
+    // }
+    //
+    // /* 
+    //  * Use an embedded ICU4J Bidi object to do all the work
+    //  */
+    // private com.ibm.icu.text.Bidi icuBidi;
+    // END android-removed
+
     /**
      * Creates a {@code Bidi} object from the {@code
      * AttributedCharacterIterator} of a paragraph text. The RUN_DIRECTION
@@ -89,16 +106,15 @@
      * attribute specifies the instance of NumericShaper used to convert
      * European digits to other decimal digits before performing the bidi
      * algorithm.
-     * 
+     *
      * @param paragraph
      *            the String containing the paragraph text to perform the
      *            algorithm.
      * @throws IllegalArgumentException
      *             if {@code paragraph} is {@code null}.
-     * @see TextAttribute#BIDI_EMBEDDING
-     * @see TextAttribute#NUMERIC_SHAPING
-     * @see TextAttribute#RUN_DIRECTION
-     * @since Android 1.0
+     * @see java.awt.font.TextAttribute#BIDI_EMBEDDING
+     * @see java.awt.font.TextAttribute#NUMERIC_SHAPING
+     * @see java.awt.font.TextAttribute#RUN_DIRECTION
      */
     public Bidi(AttributedCharacterIterator paragraph) {
         if (paragraph == null) {
@@ -106,6 +122,7 @@
             throw new IllegalArgumentException(Messages.getString("text.14")); //$NON-NLS-1$
         }
 
+        // BEGIN android-added
         int begin = paragraph.getBeginIndex();
         int end = paragraph.getEndIndex();
         int length = end - begin;
@@ -164,6 +181,7 @@
         long pBidi = createUBiDi(text, 0, embeddings, 0, length, flags);
         readBidiInfo(pBidi);
         BidiWrapper.ubidi_close(pBidi);
+        // END android-added
     }
 
     /**
@@ -191,17 +209,27 @@
      *            DIRECTION_DEFAULT_LEFT_TO_RIGHT.
      * @throws IllegalArgumentException
      *             if {@code textStart}, {@code embStart}, or {@code
-     *             paragraphLength} is negative; if 
-     *             {@code text.length < textStart + paragraphLength} or 
+     *             paragraphLength} is negative; if
+     *             {@code text.length < textStart + paragraphLength} or
      *             {@code embeddings.length < embStart + paragraphLength}.
      * @see #DIRECTION_LEFT_TO_RIGHT
      * @see #DIRECTION_RIGHT_TO_LEFT
      * @see #DIRECTION_DEFAULT_RIGHT_TO_LEFT
      * @see #DIRECTION_DEFAULT_LEFT_TO_RIGHT
-     * @since Android 1.0
      */
     public Bidi(char[] text, int textStart, byte[] embeddings, int embStart,
             int paragraphLength, int flags) {
+
+        if (text == null || text.length - textStart < paragraphLength) {
+            throw new IllegalArgumentException();
+        }
+
+        if (embeddings != null) {
+            if (embeddings.length - embStart < paragraphLength) {
+                throw new IllegalArgumentException();
+            }
+        }
+
         if (textStart < 0) {
             // text.0D=Negative textStart value {0}
             throw new IllegalArgumentException(Messages.getString(
@@ -217,10 +245,13 @@
             throw new IllegalArgumentException(Messages.getString(
                     "text.11", paragraphLength)); //$NON-NLS-1$
         }
+        
+        // BEGIN android-changed
         long pBidi = createUBiDi(text, textStart, embeddings, embStart,
                 paragraphLength, flags);
         readBidiInfo(pBidi);
         BidiWrapper.ubidi_close(pBidi);
+        // END android-changed
     }
 
     /**
@@ -238,13 +269,13 @@
      * @see #DIRECTION_RIGHT_TO_LEFT
      * @see #DIRECTION_DEFAULT_RIGHT_TO_LEFT
      * @see #DIRECTION_DEFAULT_LEFT_TO_RIGHT
-     * @since Android 1.0
      */
     public Bidi(String paragraph, int flags) {
         this((paragraph == null ? null : paragraph.toCharArray()), 0, null, 0,
                 (paragraph == null ? 0 : paragraph.length()), flags);
     }
 
+    // BEGIN android-added
     // create the native UBiDi struct, need to be closed with ubidi_close().
     private static long createUBiDi(char[] text, int textStart,
             byte[] embeddings, int embStart, int paragraphLength, int flags) {
@@ -291,7 +322,7 @@
         return bidi;
     }
 
-    // private constructor, used by createLineBidi()
+    /* private constructor used by createLineBidi() */
     private Bidi(long pBidi) {
         readBidiInfo(pBidi);
     }
@@ -335,15 +366,17 @@
     private int direction;
 
     private boolean unidirectional;
+    // END android-added
 
     /**
      * Returns whether the base level is from left to right.
      * 
      * @return true if the base level is from left to right.
-     * @since Android 1.0
      */
     public boolean baseIsLeftToRight() {
+        // BEGIN android-changed
         return baseLevel % 2 == 0 ? true : false;
+        // END android-changed
     }
 
     /**
@@ -360,15 +393,19 @@
      *             if {@code lineStart < 0}, {@code lineLimit < 0}, {@code
      *             lineStart > lineLimit} or if {@code lineStart} is greater
      *             than the length of this object's paragraph text.
-     * @since Android 1.0
      */
     public Bidi createLineBidi(int lineStart, int lineLimit) {
+        // BEGIN android-removed
+        // int length = icuBidi.getLength();
+        // END android-removed
         if (lineStart < 0 || lineLimit < 0 || lineLimit > length
                 || lineStart > lineLimit) {
             // text.12=Invalid ranges (start={0}, limit={1}, length={2})
             throw new IllegalArgumentException(Messages.getString(
                     "text.12", new Object[] { lineStart, lineLimit, length })); //$NON-NLS-1$
         }
+        
+        // BEGIN android-changed
         char[] text = new char[this.length];
         Arrays.fill(text, 'a');
         byte[] embeddings = new byte[this.length];
@@ -386,26 +423,29 @@
         BidiWrapper.ubidi_close(line);
         BidiWrapper.ubidi_close(parent);
         return result;
+        // END android-changed
     }
 
     /**
      * Returns the base level.
      * 
      * @return the base level.
-     * @since Android 1.0
      */
     public int getBaseLevel() {
+        // BEGIN android-changed
         return baseLevel;
+        // END android-changed
     }
 
     /**
      * Returns the length of the text in the {@code Bidi} object.
      * 
      * @return the length.
-     * @since Android 1.0
      */
     public int getLength() {
+        // BEGIN android-changed
         return length;
+        // END android-changed
     }
 
     /**
@@ -414,24 +454,26 @@
      * @param offset
      *            the offset of the character.
      * @return the level.
-     * @since Android 1.0
      */
     public int getLevelAt(int offset) {
+        // BEGIN android-changed
         try {
             return offsetLevel[offset] & ~BidiWrapper.UBIDI_LEVEL_OVERRIDE;
         } catch (RuntimeException e) {
             return baseLevel;
         }
+        // END android-changed
     }
 
     /**
      * Returns the number of runs in the bidirectional text.
      * 
      * @return the number of runs, at least 1.
-     * @since Android 1.0
      */
     public int getRunCount() {
+        // BEGIN android-changed
         return unidirectional ? 1 : runs.length;
+        // END android-changed
     }
 
     /**
@@ -440,10 +482,11 @@
      * @param run
      *            the index of the run.
      * @return the level of the run.
-     * @since Android 1.0
      */
     public int getRunLevel(int run) {
+        // BEGIN android-changed
         return unidirectional ? baseLevel : runs[run].getLevel();
+        // END android-changed
     }
 
     /**
@@ -452,10 +495,11 @@
      * @param run
      *            the index of the run.
      * @return the limit offset of the run.
-     * @since Android 1.0
      */
     public int getRunLimit(int run) {
+        // BEGIN android-changed
         return unidirectional ? length : runs[run].getLimit();
+        // END android-changed
     }
 
     /**
@@ -464,10 +508,11 @@
      * @param run
      *            the index of the run.
      * @return the start offset of the run.
-     * @since Android 1.0
      */
     public int getRunStart(int run) {
+        // BEGIN android-changed
         return unidirectional ? 0 : runs[run].getStart();
+        // END android-changed
     }
 
     /**
@@ -476,10 +521,11 @@
      * 
      * @return {@code true} if the text is from left to right; {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public boolean isLeftToRight() {
+        // BEGIN android-changed
         return direction == BidiWrapper.UBiDiDirection_UBIDI_LTR;
+        // END android-changed
     }
 
     /**
@@ -487,10 +533,11 @@
      * 
      * @return {@code true} if the text direction is mixed; {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public boolean isMixed() {
+        // BEGIN android-changed
         return direction == BidiWrapper.UBiDiDirection_UBIDI_MIXED;
+        // END android-changed
     }
 
     /**
@@ -499,10 +546,11 @@
      * 
      * @return {@code true} if the text is from right to left; {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public boolean isRightToLeft() {
+        // BEGIN android-changed
         return direction == BidiWrapper.UBiDiDirection_UBIDI_RTL;
+        // END android-changed
     }
 
     /**
@@ -526,7 +574,6 @@
      *             if {@code count}, {@code levelStart} or {@code objectStart}
      *             is negative; if {@code count > levels.length - levelStart} or
      *             if {@code count > objects.length - objectStart}.
-     * @since Android 1.0
      */
     public static void reorderVisually(byte[] levels, int levelStart,
             Object[] objects, int objectStart, int count) {
@@ -539,6 +586,8 @@
                     new Object[] { levels.length, levelStart, objects.length,
                             objectStart, count }));
         }
+        
+        // BEGIN android-changed
         byte[] realLevels = new byte[count];
         System.arraycopy(levels, levelStart, realLevels, 0, count);
 
@@ -550,6 +599,7 @@
         }
 
         System.arraycopy(result.toArray(), 0, objects, objectStart, count);
+        // END android-changed
     }
 
     /**
@@ -568,15 +618,17 @@
      *             if {@code start} or {@code limit} is negative; {@code start >
      *             limit} or {@code limit} is greater than the length of this
      *             object's paragraph text.
-     * @since Android 1.0
      */
     public static boolean requiresBidi(char[] text, int start, int limit) {
-        int length = text.length;
-        if (limit < 0 || start < 0 || start > limit || limit > length) {
+        //int length = text.length;
+        if (limit < 0 || start < 0 || start > limit || limit > text.length) {
             throw new IllegalArgumentException();
         }
+        
+        // BEGIN android-changed
         Bidi bidi = new Bidi(text, start, null, 0, limit - start, 0);
         return !bidi.isLeftToRight();
+        // END android-changed
     }
 
     /**
@@ -584,12 +636,13 @@
      * debugging.
      * 
      * @return a string containing the internal message.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
+        // BEGIN android-changed
         return super.toString()
                 + "[direction: " + direction + " baselevel: " + baseLevel //$NON-NLS-1$ //$NON-NLS-2$
                 + " length: " + length + " runs: " + (unidirectional ? "null" : runs.toString()) + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+        // END android-changed
     }
 }
diff --git a/libcore/text/src/main/java/java/text/BreakIterator.java b/libcore/text/src/main/java/java/text/BreakIterator.java
index 76b848e..7d19179 100644
--- a/libcore/text/src/main/java/java/text/BreakIterator.java
+++ b/libcore/text/src/main/java/java/text/BreakIterator.java
@@ -14,17 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-/**
-*******************************************************************************
-* Copyright (C) 1996-2007, International Business Machines Corporation and    *
-* others. All Rights Reserved.                                                *
-*******************************************************************************
-*/
 
 // BEGIN android-note
-// The class javadoc and some of the method descriptions are copied from ICU4J
-// source files. Changes have been made to the copied descriptions.
-// The icu license header was added to this file. 
 // The icu implementation used was changed from icu4j to icu4jni.
 // END android-note
 
@@ -93,7 +84,6 @@
  * {@link CharacterIterator}, which makes it possible to use {@code
  * BreakIterator} to analyze text in any text-storage vehicle that provides a
  * {@code CharacterIterator} interface.
- * </p>
  * <p>
  * <em>Note:</em> Some types of {@code BreakIterator} can take a long time to
  * create, and instances of {@code BreakIterator} are not currently cached by
@@ -104,12 +94,10 @@
  * wrapping) and use it to do the whole job of wrapping the text.
  * <p>
  * <em>Examples</em>:
- * </p>
  * <p>
  * Creating and using text boundaries:
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * public static void main(String args[]) {
  *     if (args.length == 1) {
@@ -127,13 +115,12 @@
  *     }
  * }
  * </pre>
- * 
+ *
  * </blockquote>
  * <p>
  * Print each element in order:
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * public static void printEachForward(BreakIterator boundary, String source) {
  *     int start = boundary.first();
@@ -142,13 +129,12 @@
  *     }
  * }
  * </pre>
- * 
+ *
  * </blockquote>
  * <p>
  * Print each element in reverse order:
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * public static void printEachBackward(BreakIterator boundary, String source) {
  *     int end = boundary.last();
@@ -158,13 +144,12 @@
  *     }
  * }
  * </pre>
- * 
+ *
  * </blockquote>
  * <p>
  * Print the first element:
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * public static void printFirst(BreakIterator boundary, String source) {
  *     int start = boundary.first();
@@ -172,13 +157,12 @@
  *     System.out.println(source.substring(start, end));
  * }
  * </pre>
- * 
+ *
  * </blockquote>
  * <p>
  * Print the last element:
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * public static void printLast(BreakIterator boundary, String source) {
  *     int end = boundary.last();
@@ -186,13 +170,12 @@
  *     System.out.println(source.substring(start, end));
  * }
  * </pre>
- * 
+ *
  * </blockquote>
  * <p>
  * Print the element at a specified position:
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * public static void printAt(BreakIterator boundary, int pos, String source) {
  *     int end = boundary.following(pos);
@@ -200,13 +183,12 @@
  *     System.out.println(source.substring(start, end));
  * }
  * </pre>
- * 
+ *
  * </blockquote>
  * <p>
  * Find the next word:
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * public static int nextWordStartAfter(int pos, String text) {
  *     BreakIterator wb = BreakIterator.getWordInstance();
@@ -224,7 +206,7 @@
  *     return BreakIterator.DONE;
  * }
  * </pre>
- * 
+ *
  * </blockquote>
  * <p>
  * The iterator returned by {@code BreakIterator.getWordInstance()} is unique in
@@ -239,23 +221,14 @@
  * CJK ideograph, a Hangul syllable, a Kana character, etc.), then the text
  * between this boundary and the next is a word; otherwise, it's the material
  * between words.)
- * </p>
- * 
+ *
  * @see CharacterIterator
- * @since Android 1.0
  */
 public abstract class BreakIterator implements Cloneable {
 
-    /*
-     * -----------------------------------------------------------------------
-     * constants
-     * -----------------------------------------------------------------------
-     */
     /**
      * This constant is returned by iterate methods like {@code previous()} or
      * {@code next()} if they have returned all valid boundaries.
-     * 
-     * @since Android 1.0
      */
     public static final int DONE = -1;
 
@@ -265,23 +238,11 @@
 
     private static final int SHORT_LENGTH = 2;
 
-    /*
-     * -----------------------------------------------------------------------
-     * variables
-     * -----------------------------------------------------------------------
-     */
     // the wrapped ICU implementation
     com.ibm.icu4jni.text.BreakIterator wrapped;
 
-    /*
-     * -----------------------------------------------------------------------
-     * constructors
-     * -----------------------------------------------------------------------
-     */
     /**
      * Default constructor, just for invocation by a subclass.
-     * 
-     * @since Android 1.0
      */
     protected BreakIterator() {
         super();
@@ -294,16 +255,10 @@
         wrapped = iterator;
     }
 
-    /*
-     * -----------------------------------------------------------------------
-     * methods
-     * -----------------------------------------------------------------------
-     */
     /**
      * Returns all supported locales in an array.
      * 
      * @return all supported locales.
-     * @since Android 1.0
      */
     public static Locale[] getAvailableLocales() {
         return com.ibm.icu4jni.text.BreakIterator.getAvailableLocales();
@@ -314,7 +269,6 @@
      * characters using the default locale.
      * 
      * @return a new instance of {@code BreakIterator} using the default locale.
-     * @since Android 1.0
      */
     public static BreakIterator getCharacterInstance() {
         return new RuleBasedBreakIterator(com.ibm.icu4jni.text.BreakIterator
@@ -328,7 +282,6 @@
      * @param where
      *            the given locale.
      * @return a new instance of {@code BreakIterator} using the given locale.
-     * @since Android 1.0
      */
     public static BreakIterator getCharacterInstance(Locale where) {
         if (where == null) {
@@ -344,7 +297,6 @@
      * line breaks using the default locale.
      * 
      * @return a new instance of {@code BreakIterator} using the default locale.
-     * @since Android 1.0
      */
     public static BreakIterator getLineInstance() {
         return new RuleBasedBreakIterator(com.ibm.icu4jni.text.BreakIterator
@@ -359,7 +311,6 @@
      *            the given locale.
      * @return a new instance of {@code BreakIterator} using the given locale.
      * @throws NullPointerException if {@code where} is {@code null}.
-     * @since Android 1.0
      */
     public static BreakIterator getLineInstance(Locale where) {
         if (where == null) {
@@ -375,7 +326,6 @@
      * sentence-breaks using the default locale.
      * 
      * @return a new instance of {@code BreakIterator} using the default locale.
-     * @since Android 1.0
      */
     public static BreakIterator getSentenceInstance() {
         return new RuleBasedBreakIterator(com.ibm.icu4jni.text.BreakIterator
@@ -390,7 +340,6 @@
      *            the given locale.
      * @return a new instance of {@code BreakIterator} using the given locale.
      * @throws NullPointerException if {@code where} is {@code null}.
-     * @since Android 1.0
      */
     public static BreakIterator getSentenceInstance(Locale where) {
         if (where == null) {
@@ -406,7 +355,6 @@
      * word-breaks using the default locale.
      * 
      * @return a new instance of {@code BreakIterator} using the default locale.
-     * @since Android 1.0
      */
     public static BreakIterator getWordInstance() {
         return new RuleBasedBreakIterator(com.ibm.icu4jni.text.BreakIterator
@@ -421,7 +369,6 @@
      *            the given locale.
      * @return a new instance of {@code BreakIterator} using the given locale.
      * @throws NullPointerException if {@code where} is {@code null}.
-     * @since Android 1.0
      */
     public static BreakIterator getWordInstance(Locale where) {
         if (where == null) {
@@ -442,7 +389,6 @@
      *            the given offset to check.
      * @return {@code true} if the given offset is a boundary position; {@code
      *         false} otherwise.
-     * @since Android 1.0
      */
     public boolean isBoundary(int offset) {
         return wrapped.isBoundary(offset);
@@ -452,11 +398,12 @@
      * Returns the position of last boundary preceding the given offset, and
      * sets the current position to the returned value, or {@code DONE} if the
      * given offset specifies the starting position.
-     * 
+     *
      * @param offset
      *            the given start position to be searched for.
      * @return the position of the last boundary preceding the given offset.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *            if the offset is invalid.
      */
     public int preceding(int offset) {
         return wrapped.preceding(offset);
@@ -469,22 +416,15 @@
      * 
      * @param newText
      *            the new text string to be analyzed.
-     * @since Android 1.0
      */
     public void setText(String newText) {
         wrapped.setText(newText);
     }
 
-    /*
-     * -----------------------------------------------------------------------
-     * abstract methods
-     * -----------------------------------------------------------------------
-     */
     /**
      * Returns this iterator's current position.
      * 
      * @return this iterator's current position.
-     * @since Android 1.0
      */
     public abstract int current();
 
@@ -493,7 +433,6 @@
      * that position.
      * 
      * @return the position of the first boundary.
-     * @since Android 1.0
      */
     public abstract int first();
 
@@ -501,11 +440,12 @@
      * Sets the position of the first boundary to the one following the given
      * offset and returns this position. Returns {@code DONE} if there is no
      * boundary after the given offset.
-     * 
+     *
      * @param offset
      *            the given position to be searched for.
      * @return the position of the first boundary following the given offset.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *            if the offset is invalid.
      */
     public abstract int following(int offset);
 
@@ -518,7 +458,6 @@
      * 
      * @return a {@code CharacterIterator} which represents the text being
      *         analyzed.
-     * @since Android 1.0
      */
     public abstract CharacterIterator getText();
 
@@ -527,7 +466,6 @@
      * that position.
      * 
      * @return the position of last boundary.
-     * @since Android 1.0
      */
     public abstract int last();
 
@@ -537,7 +475,6 @@
      * boundary was found after the current position.
      * 
      * @return the position of last boundary.
-     * @since Android 1.0
      */
     public abstract int next();
 
@@ -549,7 +486,6 @@
      * @param n
      *            the given position.
      * @return the position of last boundary.
-     * @since Android 1.0
      */
     public abstract int next(int n);
 
@@ -559,7 +495,6 @@
      * no boundary was found before the current position.
      * 
      * @return the position of last boundary.
-     * @since Android 1.0
      */
     public abstract int previous();
 
@@ -571,21 +506,14 @@
      * @param newText
      *            the {@code CharacterIterator} referring to the text to be
      *            analyzed.
-     * @since Android 1.0
      */
     public abstract void setText(CharacterIterator newText);
 
-    /*
-     * -----------------------------------------------------------------------
-     * methods override Object
-     * -----------------------------------------------------------------------
-     */
     /**
      * Creates a copy of this iterator, all status information including the
      * current position are kept the same.
      * 
      * @return a copy of this iterator.
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -612,7 +540,6 @@
      * @throws ArrayIndexOutOfBoundsException
      *             if {@code offset < 0} or {@code offset + LONG_LENGTH} is
      *             greater than the length of {@code buf}.
-     * @since Android 1.0
      */
     protected static long getLong(byte[] buf, int offset) {
         if (null == buf) {
@@ -642,7 +569,6 @@
      * @throws ArrayIndexOutOfBoundsException
      *             if {@code offset < 0} or {@code offset + INT_LENGTH} is
      *             greater than the length of {@code buf}.
-     * @since Android 1.0
      */
     protected static int getInt(byte[] buf, int offset) {
         if (null == buf) {
@@ -672,7 +598,6 @@
      * @throws ArrayIndexOutOfBoundsException
      *             if {@code offset < 0} or {@code offset + SHORT_LENGTH} is
      *             greater than the length of {@code buf}.
-     * @since Android 1.0
      */
     protected static short getShort(byte[] buf, int offset) {
         if (null == buf) {
diff --git a/libcore/text/src/main/java/java/text/CharacterIterator.java b/libcore/text/src/main/java/java/text/CharacterIterator.java
index dfcd21d..81c1fa4 100644
--- a/libcore/text/src/main/java/java/text/CharacterIterator.java
+++ b/libcore/text/src/main/java/java/text/CharacterIterator.java
@@ -21,16 +21,12 @@
  * An interface for the bidirectional iteration over a group of characters. The
  * iteration starts at the begin index in the group of characters and continues
  * to one index before the end index.
- * 
- * @since Android 1.0
  */
 public interface CharacterIterator extends Cloneable {
 
     /**
      * A constant which indicates that there is no character at the current
      * index.
-     * 
-     * @since Android 1.0
      */
     public static final char DONE = '\uffff';
 
@@ -40,7 +36,6 @@
      * @return a shallow copy of this character iterator.
      * 
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     public Object clone();
 
@@ -49,7 +44,6 @@
      * 
      * @return the current character, or {@code DONE} if the current index is
      *         past the beginning or end of the sequence.
-     * @since Android 1.0
      */
     public char current();
 
@@ -58,7 +52,6 @@
      * the new position.
      * 
      * @return the character at the begin index.
-     * @since Android 1.0
      */
     public char first();
 
@@ -66,7 +59,6 @@
      * Returns the begin index.
      * 
      * @return the index of the first character of the iteration.
-     * @since Android 1.0
      */
     public int getBeginIndex();
 
@@ -74,7 +66,6 @@
      * Returns the end index.
      * 
      * @return the index one past the last character of the iteration.
-     * @since Android 1.0
      */
     public int getEndIndex();
 
@@ -82,7 +73,6 @@
      * Returns the current index.
      * 
      * @return the current index.
-     * @since Android 1.0
      */
     public int getIndex();
 
@@ -91,7 +81,6 @@
      * at the new position.
      * 
      * @return the character before the end index.
-     * @since Android 1.0
      */
     public char last();
 
@@ -100,7 +89,6 @@
      * 
      * @return the character at the next index, or {@code DONE} if the next
      *         index would be past the end.
-     * @since Android 1.0
      */
     public char next();
 
@@ -109,7 +97,6 @@
      * 
      * @return the character at the previous index, or {@code DONE} if the
      *         previous index would be past the beginning.
-     * @since Android 1.0
      */
     public char previous();
 
@@ -121,10 +108,9 @@
      *            the new index that this character iterator is set to.
      * @return the character at the new index, or {@code DONE} if the index is
      *         past the end.
-     * @exception IllegalArgumentException
-     *                if {@code location} is less than the begin index or
-     *                greater than the end index.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *         if {@code location} is less than the begin index or greater than
+     *         the end index.
      */
     public char setIndex(int location);
 }
diff --git a/libcore/text/src/main/java/java/text/ChoiceFormat.java b/libcore/text/src/main/java/java/text/ChoiceFormat.java
index 41daced..1a61781 100644
--- a/libcore/text/src/main/java/java/text/ChoiceFormat.java
+++ b/libcore/text/src/main/java/java/text/ChoiceFormat.java
@@ -14,18 +14,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-/**
-*******************************************************************************
-* Copyright (C) 1996-2007, International Business Machines Corporation and    *
-* others. All Rights Reserved.                                                *
-*******************************************************************************
-*/
-
-// BEGIN android-note
-// The class javadoc description is copied from ICU UserGuide.
-// Changes have been made to the copied descriptions.
-// The icu license header was added to this file. 
-// END android-note
 
 package java.text;
 
@@ -46,44 +34,38 @@
  * or last index is used depending on whether the number is too low or too high.
  * The length of the format array must be the same as the length of the limits
  * array.
- * </p>
  * <h5>Examples:</h5>
  * <blockquote>
- * 
+ *
  * <pre>
  * double[] limits = {1, 2, 3, 4, 5, 6, 7};
  * String[] fmts = {"Sun", "Mon", "Tue", "Wed", "Thur", "Fri", "Sat"};
- * 
+ *
  * double[] limits2 = {0, 1, ChoiceFormat.nextDouble(1)};
  * String[] fmts2 = {"no files", "one file", "many files"};
  * </pre>
  * </blockquote>
- * <p> 
+ * <p>
  * ChoiceFormat.nextDouble(double) allows to get the double following the one
  * passed to the method. This is used to create half open intervals.
- * </p>
  * <p>
  * {@code ChoiceFormat} objects also may be converted to and from patterns.
  * The conversion can be done programmatically, as in the example above, or
  * by using a pattern like the following:
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * "1#Sun|2#Mon|3#Tue|4#Wed|5#Thur|6#Fri|7#Sat"
  * "0#are no files|1#is one file|1&lt;are many files"
  * </pre>
- * 
+ *
  * </blockquote>
  * <p>
  * where:
- * </p>
  * <ul>
  * <li><number>"#"</number> specifies an inclusive limit value;</li>
  * <li><number>"<"</number> specifies an exclusive limit value.</li>
  * </ul>
- * 
- * @since Android 1.0
  */
 public class ChoiceFormat extends NumberFormat {
 
@@ -102,8 +84,7 @@
      * <p>
      * The length of the {@code limits} and {@code formats} arrays must be the
      * same.
-     * </p>
-     * 
+     *
      * @param limits
      *            an array of doubles in ascending order. The lowest and highest
      *            possible values are negative and positive infinity.
@@ -111,7 +92,6 @@
      *            the strings associated with the ranges defined through {@code
      *            limits}. The lower bound of the associated range is at the
      *            same index as the string.
-     * @since Android 1.0
      */
     public ChoiceFormat(double[] limits, String[] formats) {
         setChoices(limits, formats);
@@ -123,10 +103,8 @@
      * 
      * @param template
      *            the pattern of strings and ranges.
-     * 
-     * @exception IllegalArgumentException
-     *                if an error occurs while parsing the pattern.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *            if an error occurs while parsing the pattern.
      */
     public ChoiceFormat(String template) {
         applyPattern(template);
@@ -138,10 +116,8 @@
      * 
      * @param template
      *            the pattern of strings and ranges.
-     * 
-     * @exception IllegalArgumentException
-     *                if an error occurs while parsing the pattern.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *            if an error occurs while parsing the pattern.
      */
     public void applyPattern(String template) {
         double[] limits = new double[5];
@@ -212,7 +188,6 @@
      * @return a shallow copy of this {@code ChoiceFormat}.
      * 
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -232,7 +207,6 @@
      * @return {@code true} if the specified object is equal to this instance;
      *         {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -258,7 +232,6 @@
      * @param field
      *            a {@code FieldPosition} which is ignored.
      * @return the string buffer.
-     * @since Android 1.0
      */
     @Override
     public StringBuffer format(double value, StringBuffer buffer,
@@ -283,7 +256,6 @@
      * @param field
      *            a {@code FieldPosition} which is ignored.
      * @return the string buffer.
-     * @since Android 1.0
      */
     @Override
     public StringBuffer format(long value, StringBuffer buffer,
@@ -296,7 +268,6 @@
      * ChoiceFormat}.
      * 
      * @return an array of format strings.
-     * @since Android 1.0
      */
     public Object[] getFormats() {
         return choiceFormats;
@@ -307,7 +278,6 @@
      * 
      * @return the array of doubles which make up the limits of this {@code
      *         ChoiceFormat}.
-     * @since Android 1.0
      */
     public double[] getLimits() {
         return choiceLimits;
@@ -320,7 +290,6 @@
      * @return the receiver's hash.
      * 
      * @see #equals
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -339,7 +308,6 @@
      * @param value
      *            a double value.
      * @return the next larger double value.
-     * @since Android 1.0
      */
     public static final double nextDouble(double value) {
         if (value == Double.POSITIVE_INFINITY) {
@@ -365,7 +333,6 @@
      *            {@code true} to get the next larger value, {@code false} to
      *            get the previous smaller value.
      * @return the next larger or smaller double value.
-     * @since Android 1.0
      */
     public static double nextDouble(double value, boolean increment) {
         return increment ? nextDouble(value) : previousDouble(value);
@@ -378,26 +345,30 @@
      * corresponding range in the limits array is returned. If the string is
      * successfully parsed then the index of the {@code ParsePosition} passed to
      * this method is updated to the index following the parsed text.
-     * 
-     * @param string
-     *            the source string to parse.
-     * @param position
-     *            input/output parameter, specifies the start index in {@code string}
-     *            from where to start parsing. See the <em>Returns</em> section for
-     *            a description of the output values.
-     * @return if one of the format strings of this {@code ChoiceFormat} instance
-     * is found in {@code string} starting at the index specified by {@code position.getIndex()} then
+     * <p>
+     * If one of the format strings of this {@code ChoiceFormat} instance is
+     * found in {@code string} starting at {@code position.getIndex()} then
      * <ul>
-     * <li>the index in {@code position} is set to the index following the parsed text;
-     * <li>the {@link java.lang.Double Double} corresponding to the format string is returned.</li>
+     * <li>the index in {@code position} is set to the index following the
+     * parsed text;
+     * <li>the {@link java.lang.Double Double} corresponding to the format
+     * string is returned.</li>
      * </ul>
      * <p>
      * If none of the format strings is found in {@code string} then
-     * <ul> 
-     * <li>the error index in {@code position} is set to the current index in {@code position};</li>
+     * <ul>
+     * <li>the error index in {@code position} is set to the current index in
+     * {@code position};</li>
      * <li> {@link java.lang.Double#NaN Double.NaN} is returned.
      * </ul>
-     * @since Android 1.0
+     * @param string
+     *            the source string to parse.
+     * @param position
+     *            input/output parameter, specifies the start index in {@code
+     *            string} from where to start parsing. See the <em>Returns</em>
+     *            section for a description of the output values.
+     * @return a Double resulting from the parse, or Double.NaN if there is an
+     *         error
      */
     @Override
     public Number parse(String string, ParsePosition position) {
@@ -419,7 +390,6 @@
      * @param value
      *            a double value.
      * @return the next smaller double value.
-     * @since Android 1.0
      */
     public static final double previousDouble(double value) {
         if (value == Double.NEGATIVE_INFINITY) {
@@ -439,13 +409,12 @@
      * Sets the double values and associated strings of this ChoiceFormat. When
      * calling {@link #format(double, StringBuffer, FieldPosition) format} with
      * a double value {@code d}, then the element {@code i} in {@code formats}
-     * is selected where {@code i} fulfills 
+     * is selected where {@code i} fulfills
      * {@code limits[i] <= d < limits[i+1]}.
      * <p>
      * The length of the {@code limits} and {@code formats} arrays must be the
      * same.
-     * </p>
-     * 
+     *
      * @param limits
      *            an array of doubles in ascending order. The lowest and highest
      *            possible values are negative and positive infinity.
@@ -453,7 +422,6 @@
      *            the strings associated with the ranges defined through {@code
      *            limits}. The lower bound of the associated range is at the
      *            same index as the string.
-     * @since Android 1.0
      */
     public void setChoices(double[] limits, String[] formats) {
         if (limits.length != formats.length) {
@@ -476,10 +444,9 @@
      * ranges and their associated strings.
      * 
      * @return the pattern.
-     * @since Android 1.0
      */
     public String toPattern() {
-        StringBuffer buffer = new StringBuffer();
+        StringBuilder buffer = new StringBuilder();
         for (int i = 0; i < choiceLimits.length; i++) {
             if (i != 0) {
                 buffer.append('|');
diff --git a/libcore/text/src/main/java/java/text/CollationElementIterator.java b/libcore/text/src/main/java/java/text/CollationElementIterator.java
index 66c0079..fb562d8 100644
--- a/libcore/text/src/main/java/java/text/CollationElementIterator.java
+++ b/libcore/text/src/main/java/java/text/CollationElementIterator.java
@@ -28,31 +28,23 @@
  * source string.
  * <p>
  * For illustration, consider the following in Spanish:
- * </p>
  * <p>
  * "ca": the first collation element is collation_element('c') and second
  * collation element is collation_element('a').
- * </p>
  * <p>
  * Since "ch" in Spanish sorts as one entity, the example below returns one
  * collation element for the two characters 'c' and 'h':
- * </p>
  * <p>
  * "cha": the first collation element is collation_element('ch') and the second
  * one is collation_element('a').
- * </p>
  * <p>
  * In German, since the character '&#92;u0086' is a composed character of 'a'
  * and 'e', the iterator returns two collation elements for the single character
  * '&#92;u0086':
- * </p>
  * <p>
  * "&#92;u0086b": the first collation element is collation_element('a'), the
  * second one is collation_element('e'), and the third collation element is
  * collation_element('b').
- * </p>
- * 
- * @since Android 1.0
  */
 public final class CollationElementIterator {
 
@@ -61,8 +53,6 @@
      * {@code next()} and {@code previous()} when the end or the
      * beginning of the source string has been reached, and there are no more
      * valid collation elements to return.
-     * 
-     * @since Android 1.0
      */
     public static final int NULLORDER = -1;
 
@@ -83,7 +73,6 @@
      *            method.
      * @return the maximum length of any expansion sequence ending with the
      *         specified collation element.
-     * @since Android 1.0
      */
     public int getMaxExpansion(int order) {
         return this.icuIterator.getMaxExpansion(order);
@@ -111,7 +100,6 @@
      * @return The position of the collation element in the source string that
      *         will be returned by the next invocation of the {@link #next()}
      *         method.
-     * @since Android 1.0
      */
     public int getOffset() {
         return this.icuIterator.getOffset();
@@ -122,7 +110,6 @@
      * 
      * @return the next collation element or {@code NULLORDER} if the end
      *         of the iteration has been reached.
-     * @since Android 1.0
      */
     public int next() {
         return this.icuIterator.next();
@@ -133,7 +120,6 @@
      * 
      * @return the previous collation element, or {@code NULLORDER} when
      *         the start of the iteration has been reached.
-     * @since Android 1.0
      */
     public int previous() {
         return this.icuIterator.previous();
@@ -146,7 +132,6 @@
      * @param order
      *            the element of the collation.
      * @return the element's 16 bit primary order.
-     * @since Android 1.0
      */
     public static final int primaryOrder(int order) {
         return com.ibm.icu4jni.text.CollationElementIterator.primaryOrder(order);
@@ -160,9 +145,6 @@
      * If the {@code RuleBasedCollator} used by this iterator has had its
      * attributes changed, calling {@code reset()} reinitializes the iterator to
      * use the new attributes.
-     * </p>
-     * 
-     * @since Android 1.0
      */
     public void reset() {
         this.icuIterator.reset();
@@ -175,7 +157,6 @@
      * @param order
      *            the element of the collator.
      * @return the 8 bit secondary order of the element.
-     * @since Android 1.0
      */
     public static final short secondaryOrder(int order) {
         return (short) com.ibm.icu4jni.text.CollationElementIterator
@@ -193,19 +174,16 @@
      * adjusted to the start of that sequence. As a result of this, any
      * subsequent call made to {@code getOffset()} may not return the same value
      * set by this method.
-     * </p>
      * <p>
      * If the decomposition mode is on, and offset is in the middle of a
      * decomposable range of source text, the iterator may not return a correct
      * result for the next forwards or backwards iteration. The user must ensure
      * that the offset is not in the middle of a decomposable range.
-     * </p>
      * 
      * @param newOffset
      *            the character offset into the original source string to set.
      *            Note that this is not an offset into the corresponding
      *            sequence of collation elements.
-     * @since Android 1.0
      */
     public void setOffset(int newOffset) {
         this.icuIterator.setOffset(newOffset);
@@ -217,7 +195,6 @@
      * 
      * @param source
      *            the new source string iterator for iteration.
-     * @since Android 1.0
      */
     public void setText(CharacterIterator source) {
         this.icuIterator.setText(source);
@@ -229,7 +206,6 @@
      * 
      * @param source
      *            the new source string for iteration.
-     * @since Android 1.0
      */
     public void setText(String source) {
         this.icuIterator.setText(source);
@@ -242,7 +218,6 @@
      * @param order
      *            the element of the collation.
      * @return the 8 bit tertiary order of the element.
-     * @since Android 1.0
      */
     public static final short tertiaryOrder(int order) {
         return (short) com.ibm.icu4jni.text.CollationElementIterator
diff --git a/libcore/text/src/main/java/java/text/CollationKey.java b/libcore/text/src/main/java/java/text/CollationKey.java
index f43bfd1..a994fe2 100644
--- a/libcore/text/src/main/java/java/text/CollationKey.java
+++ b/libcore/text/src/main/java/java/text/CollationKey.java
@@ -14,17 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-/**
-*******************************************************************************
-* Copyright (C) 1996-2006, International Business Machines Corporation and    *
-* others. All Rights Reserved.                                                *
-*******************************************************************************
-*/
 
 // BEGIN android-note
-// The class javadoc and some of the method descriptions are copied from ICU4J
-// source files. Changes have been made to the copied descriptions.
-// The icu license header was added to this file. 
 // The icu implementation used was changed from icu4j to icu4jni.
 // END android-note
 
@@ -38,13 +29,11 @@
  * string under two different {@code Collator} instances might differ. Hence
  * comparing collation keys generated from different {@code Collator} instances
  * can give incorrect results.
- * </p>
  * <p>
  * Both the method {@code CollationKey.compareTo(CollationKey)} and the method
  * {@code Collator.compare(String, String)} compares two strings and returns
  * their relative order. The performance characteristics of these two approaches
  * can differ.
- * </p>
  * <p>
  * During the construction of a {@code CollationKey}, the entire source string
  * is examined and processed into a series of bits terminated by a null, that
@@ -54,19 +43,16 @@
  * the {@code CollationKey}, but once the key is created, binary comparisons
  * are fast. This approach is recommended when the same strings are to be
  * compared over and over again.
- * </p>
  * <p>
  * On the other hand, implementations of
  * {@code Collator.compare(String, String)} can examine and process the strings
  * only until the first characters differ in order. This approach is
  * recommended if the strings are to be compared only once.
- * </p>
  * <p>
  * The following example shows how collation keys can be used to sort a
  * list of strings:
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * // Create an array of CollationKeys for the Strings to be sorted.
  * Collator myCollator = Collator.getInstance();
@@ -89,12 +75,11 @@
  * System.out.println(keys[1].getSourceString());
  * System.out.println(keys[2].getSourceString());
  * </pre>
- * 
+ *
  * </blockquote>
- * 
+ *
  * @see Collator
  * @see RuleBasedCollator
- * @since Android 1.0
  */
 public final class CollationKey implements Comparable<CollationKey> {
 
@@ -116,7 +101,6 @@
      * @return a negative value if this {@code CollationKey} is less than the
      *         specified {@code CollationKey}, 0 if they are equal and a
      *         positive value if this {@code CollationKey} is greater.
-     * @since Android 1.0
      */
     public int compareTo(CollationKey value) {
         return icuKey.compareTo(value.icuKey);
@@ -133,7 +117,6 @@
      * @return {@code true} if {@code object} is equal to this collation key;
      *         {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -148,7 +131,6 @@
      * Returns the string from which this collation key was created.
      * 
      * @return the source string of this collation key.
-     * @since Android 1.0
      */
     public String getSourceString() {
         return this.source;
@@ -161,7 +143,6 @@
      * @return the receiver's hash.
      * 
      * @see #equals
-     * @since Android 1.0
      */
     @Override
     public int hashCode() {
@@ -172,7 +153,6 @@
      * Returns the collation key as a byte array.
      * 
      * @return an array of bytes.
-     * @since Android 1.0
      */
     public byte[] toByteArray() {
         return icuKey.toByteArray();
diff --git a/libcore/text/src/main/java/java/text/Collator.java b/libcore/text/src/main/java/java/text/Collator.java
index a34b412..aaa3e12 100644
--- a/libcore/text/src/main/java/java/text/Collator.java
+++ b/libcore/text/src/main/java/java/text/Collator.java
@@ -14,17 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-/**
-*******************************************************************************
-* Copyright (C) 1996-2007, International Business Machines Corporation and    *
-* others. All Rights Reserved.                                                *
-*******************************************************************************
-*/
 
 // BEGIN android-note
-// The class javadoc and some of the method descriptions are copied from ICU4J
-// source files. Changes have been made to the copied descriptions.
-// The icu license header was added to this file.
 // The icu implementation used was changed from icu4j to icu4jni.
 // END android-note
 
@@ -47,7 +38,6 @@
  * href="http://www.unicode.org/unicode/reports/tr10/"> Unicode Collation
  * Algorithm (UCA)</a>, there are 4 different levels of strength used in
  * comparisons:
- * </p>
  * <ul>
  * <li>PRIMARY strength: Typically, this is used to denote differences between
  * base characters (for example, "a" &lt; "b"). It is the strongest difference.
@@ -83,12 +73,10 @@
  * NFD. If canonical decomposition is turned off, it is the user's
  * responsibility to ensure that all text is already in the appropriate form
  * before performing a comparison or before getting a {@link CollationKey}.
- * </p>
  * <p>
  * <em>Examples:</em>
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * // Get the Collator for US English and set its strength to PRIMARY
  * Collator usCollator = Collator.getInstance(Locale.US);
@@ -97,14 +85,13 @@
  *     System.out.println(&quot;Strings are equivalent&quot;);
  * }
  * </pre>
- * 
+ *
  * </blockquote>
  * <p>
  * The following example shows how to compare two strings using the collator for
  * the default locale.
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * // Compare two strings in the default locale
  * Collator myCollator = Collator.getInstance();
@@ -121,12 +108,11 @@
  *     System.out.println(&quot;Error: \u00e0\u0325 should be not equal to a\u0325\u0300 without decomposition&quot;);
  * }
  * </pre>
- * 
+ *
  * </blockquote>
- * 
+ *
  * @see RuleBasedCollator
  * @see CollationKey
- * @since Android 1.0
  */
 public abstract class Collator implements Comparator<Object>, Cloneable {
 
@@ -138,51 +124,37 @@
 
     /**
      * Constant used to specify the decomposition rule.
-     * 
-     * @since Android 1.0
      */
     public static final int NO_DECOMPOSITION = 0;
 
     /**
      * Constant used to specify the decomposition rule.
-     * 
-     * @since Android 1.0
      */
     public static final int CANONICAL_DECOMPOSITION = 1;
 
     /**
      * Constant used to specify the decomposition rule. This value for
      * decomposition is not supported.
-     * 
-     * @since Android 1.0
      */
     public static final int FULL_DECOMPOSITION = 2;
 
     /**
      * Constant used to specify the collation strength.
-     * 
-     * @since Android 1.0
      */
     public static final int PRIMARY = 0;
 
     /**
      * Constant used to specify the collation strength.
-     * 
-     * @since Android 1.0
      */
     public static final int SECONDARY = 1;
 
     /**
      * Constant used to specify the collation strength.
-     * 
-     * @since Android 1.0
      */
     public static final int TERTIARY = 2;
 
     /**
      * Constant used to specify the collation strength.
-     * 
-     * @since Android 1.0
      */
     public static final int IDENTICAL = 3;
 
@@ -214,8 +186,6 @@
 
     /**
      * Constructs a new {@code Collator} instance.
-     * 
-     * @since Android 1.0
      */
     protected Collator() {
         super();
@@ -230,7 +200,6 @@
      * 
      * @return a shallow copy of this collator.
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -254,10 +223,8 @@
      * @return a negative value if {@code object1} is less than {@code object2},
      *         0 if they are equal, and a positive value if {@code object1} is
      *         greater than {@code object2}.
-     * @exception ClassCastException
-     *                if {@code object1} or {@code object2} is not a
-     *                {@code String}.
-     * @since Android 1.0
+     * @throws ClassCastException
+     *         if {@code object1} or {@code object2} is not a {@code String}.
      */
     public int compare(Object object1, Object object2) {
         return compare((String) object1, (String) object2);
@@ -273,7 +240,6 @@
      * @return a negative value if {@code string1} is less than {@code string2},
      *         0 if they are equal and a positive value if {@code string1} is
      *         greater than {@code string2}.
-     * @since Android 1.0
      */
     public abstract int compare(String string1, String string2);
 
@@ -287,7 +253,6 @@
      *         it has the same strength and decomposition values as this
      *         collator; {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -309,7 +274,6 @@
      *            the second string to compare.
      * @return {@code true} if {@code string1} and {@code string2} are equal
      *         using the collation rules, false otherwise.
-     * @since Android 1.0
      */
     public boolean equals(String string1, String string2) {
         return compare(string1, string2) == 0;
@@ -320,7 +284,6 @@
      * {@code Collator}.
      * 
      * @return an array of {@code Locale}.
-     * @since Android 1.0
      */
     public static Locale[] getAvailableLocales() {
         return com.ibm.icu4jni.text.Collator.getAvailableLocales();
@@ -333,7 +296,6 @@
      * @param string
      *            the source string that is converted into a collation key.
      * @return the collation key for {@code string}.
-     * @since Android 1.0
      */
     public abstract CollationKey getCollationKey(String string);
 
@@ -343,7 +305,6 @@
      * @return the decomposition rule, either {@code NO_DECOMPOSITION} or
      *         {@code CANONICAL_DECOMPOSITION}. {@code FULL_DECOMPOSITION} is
      *         not supported.
-     * @since Android 1.0
      */
     public int getDecomposition() {
         return decompositionMode_ICU_Java(this.icuColl.getDecomposition());
@@ -354,7 +315,6 @@
      * {@code Locale}.
      * 
      * @return the collator for the default locale.
-     * @since Android 1.0
      */
     public static Collator getInstance() {
         return getInstance(Locale.getDefault());
@@ -367,7 +327,6 @@
      * @param locale
      *            the locale.
      * @return the collator for {@code locale}.
-     * @since Android 1.0
      */
     public static Collator getInstance(Locale locale) {
         String key = locale.toString();
@@ -386,7 +345,6 @@
      * 
      * @return the strength value, either PRIMARY, SECONDARY, TERTIARY or
      *         IDENTICAL.
-     * @since Android 1.0
      */
     public int getStrength() {
         return strength_ICU_Java(this.icuColl.getStrength());
@@ -399,7 +357,6 @@
      * 
      * @see #equals(Object)
      * @see #equals(String, String)
-     * @since Android 1.0
      */
     @Override
     public abstract int hashCode();
@@ -411,10 +368,9 @@
      *            the decomposition rule, either {@code NO_DECOMPOSITION} or
      *            {@code CANONICAL_DECOMPOSITION}. {@code FULL_DECOMPOSITION}
      *            is not supported.
-     * @exception IllegalArgumentException
-     *                if the provided decomposition rule is not valid. This 
-     *                includes {@code FULL_DECOMPOSITION}.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *            if the provided decomposition rule is not valid. This includes
+     *            {@code FULL_DECOMPOSITION}.
      */
     public void setDecomposition(int value) {
         this.icuColl.setDecomposition(decompositionMode_Java_ICU(value));
@@ -426,10 +382,8 @@
      * @param value
      *            the strength value, either PRIMARY, SECONDARY, TERTIARY, or
      *            IDENTICAL.
-     * 
-     * @exception IllegalArgumentException
-     *                if the provided strength value is not valid.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *            if the provided strength value is not valid.
      */
     public void setStrength(int value) {
         this.icuColl.setStrength(strength_Java_ICU(value));
diff --git a/libcore/text/src/main/java/java/text/DateFormat.java b/libcore/text/src/main/java/java/text/DateFormat.java
index 38759ae..f39965a 100644
--- a/libcore/text/src/main/java/java/text/DateFormat.java
+++ b/libcore/text/src/main/java/java/text/DateFormat.java
@@ -14,17 +14,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-/**
-*******************************************************************************
-* Copyright (C) 1996-2007, International Business Machines Corporation and    *
-* others. All Rights Reserved.                                                *
-*******************************************************************************
-*/
 
 // BEGIN android-note
-// The class javadoc and some of the method descriptions are copied from ICU4J
-// source files. Changes have been made to the copied descriptions.
-// The icu license header was added to this file. 
+// changed from ICU to resource bundles
 // END android-note
 
 package java.text;
@@ -34,7 +26,9 @@
 import java.util.Date;
 import java.util.Hashtable;
 import java.util.Locale;
+// BEGIN android-added
 import java.util.ResourceBundle;
+// BEGIN android-added
 import java.util.TimeZone;
 
 import org.apache.harmony.text.internal.nls.Messages;
@@ -52,58 +46,52 @@
  * styles. The formatting styles include FULL, LONG, MEDIUM, and SHORT. More
  * details and examples for using these styles are provided in the method
  * descriptions.
- * </p>
  * <p>
  * {@code DateFormat} helps you to format and parse dates for any locale. Your
  * code can be completely independent of the locale conventions for months, days
  * of the week, or even the calendar format: lunar vs. solar.
- * </p>
  * <p>
  * To format a date for the current Locale, use one of the static factory
  * methods:
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * myString = DateFormat.getDateInstance().format(myDate);
  * </pre>
- * 
+ *
  * </blockquote>
  * <p>
  * If you are formatting multiple dates, it is more efficient to get the format
  * and use it multiple times so that the system doesn't have to fetch the
  * information about the local language and country conventions multiple times.
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * DateFormat df = DateFormat.getDateInstance();
  * for (int i = 0; i &lt; a.length; ++i) {
  *     output.println(df.format(myDate[i]) + &quot;; &quot;);
  * }
  * </pre>
- * 
+ *
  * </blockquote>
  * <p>
  * To format a number for a different locale, specify it in the call to
  * {@code getDateInstance}:
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, Locale.FRANCE);
  * </pre>
- * 
+ *
  * </blockquote>
  * <p>
  * {@code DateFormat} can also be used to parse strings:
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * myDate = df.parse(myString);
  * </pre>
- * 
+ *
  * </blockquote>
  * <p>
  * Use {@code getDateInstance} to get the normal date format for a country.
@@ -112,7 +100,6 @@
  * date and time format. You can pass in different options to these factory
  * methods to control the length of the result; from SHORT to MEDIUM to LONG to
  * FULL. The exact result depends on the locale, but generally:
- * </p>
  * <ul>
  * <li>SHORT is completely numeric, such as 12.13.52 or 3:30pm
  * <li>MEDIUM is longer, such as Jan 12, 1952
@@ -126,7 +113,6 @@
  * from the factory methods to a {@code SimpleDateFormat}. This will work for
  * the majority of countries; just remember to put it in a try block in case you
  * encounter an unusual one.
- * </p>
  * <p>
  * There are versions of the parse and format methods which use
  * {@code ParsePosition} and {@code FieldPosition} to allow you to
@@ -139,13 +125,11 @@
  * Date formats are not synchronized. It is recommended to create separate
  * format instances for each thread. If multiple threads access a format
  * concurrently, it must be synchronized externally.
- * </p>
- * 
+ *
  * @see NumberFormat
  * @see SimpleDateFormat
  * @see Calendar
  * @see TimeZone
- * @since Android 1.0
  */
 public abstract class DateFormat extends Format {
 
@@ -154,83 +138,61 @@
     /**
      * The calendar that this {@code DateFormat} uses to format a number
      * representing a date.
-     * 
-     * @since Android 1.0
      */
     protected Calendar calendar;
 
     /**
      * The number format used to format a number.
-     * 
-     * @since Android 1.0
      */
     protected NumberFormat numberFormat;
 
     /**
      * The format style constant defining the default format style. The default
      * is MEDIUM.
-     * 
-     * @since Android 1.0
      */
     public final static int DEFAULT = 2;
 
     /**
      * The format style constant defining the full style.
-     * 
-     * @since Android 1.0
      */
     public final static int FULL = 0;
 
     /**
      * The format style constant defining the long style.
-     * 
-     * @since Android 1.0
      */
     public final static int LONG = 1;
 
     /**
      * The format style constant defining the medium style.
-     * 
-     * @since Android 1.0
      */
     public final static int MEDIUM = 2;
 
     /**
      * The format style constant defining the short style.
-     * 
-     * @since Android 1.0
      */
     public final static int SHORT = 3;
 
     /**
      * The {@code FieldPosition} selector for 'G' field alignment, corresponds
      * to the {@link Calendar#ERA} field.
-     * 
-     * @since Android 1.0
      */
     public final static int ERA_FIELD = 0;
 
     /**
      * The {@code FieldPosition} selector for 'y' field alignment, corresponds
      * to the {@link Calendar#YEAR} field.
-     * 
-     * @since Android 1.0
      */
     public final static int YEAR_FIELD = 1;
 
     /**
      * The {@code FieldPosition} selector for 'M' field alignment, corresponds
      * to the {@link Calendar#MONTH} field.
-     * 
-     * @since Android 1.0
      */
     public final static int MONTH_FIELD = 2;
 
     /**
      * The {@code FieldPosition} selector for 'd' field alignment, corresponds
      * to the {@link Calendar#DATE} field.
-     * 
-     * @since Android 1.0
      */
     public final static int DATE_FIELD = 3;
 
@@ -239,8 +201,6 @@
      * to the {@link Calendar#HOUR_OF_DAY} field. {@code HOUR_OF_DAY1_FIELD} is
      * used for the one-based 24-hour clock. For example, 23:59 + 01:00 results
      * in 24:59.
-     * 
-     * @since Android 1.0
      */
     public final static int HOUR_OF_DAY1_FIELD = 4;
 
@@ -249,80 +209,60 @@
      * to the {@link Calendar#HOUR_OF_DAY} field. {@code HOUR_OF_DAY0_FIELD} is
      * used for the zero-based 24-hour clock. For example, 23:59 + 01:00 results
      * in 00:59.
-     * 
-     * @since Android 1.0
      */
     public final static int HOUR_OF_DAY0_FIELD = 5;
 
     /**
      * FieldPosition selector for 'm' field alignment, corresponds to the
      * {@link Calendar#MINUTE} field.
-     * 
-     * @since Android 1.0
      */
     public final static int MINUTE_FIELD = 6;
 
     /**
      * FieldPosition selector for 's' field alignment, corresponds to the
      * {@link Calendar#SECOND} field.
-     * 
-     * @since Android 1.0
      */
     public final static int SECOND_FIELD = 7;
 
     /**
      * FieldPosition selector for 'S' field alignment, corresponds to the
      * {@link Calendar#MILLISECOND} field.
-     * 
-     * @since Android 1.0
      */
     public final static int MILLISECOND_FIELD = 8;
 
     /**
      * FieldPosition selector for 'E' field alignment, corresponds to the
      * {@link Calendar#DAY_OF_WEEK} field.
-     * 
-     * @since Android 1.0
      */
     public final static int DAY_OF_WEEK_FIELD = 9;
 
     /**
      * FieldPosition selector for 'D' field alignment, corresponds to the
      * {@link Calendar#DAY_OF_YEAR} field.
-     * 
-     * @since Android 1.0
      */
     public final static int DAY_OF_YEAR_FIELD = 10;
 
     /**
      * FieldPosition selector for 'F' field alignment, corresponds to the
      * {@link Calendar#DAY_OF_WEEK_IN_MONTH} field.
-     * 
-     * @since Android 1.0
      */
     public final static int DAY_OF_WEEK_IN_MONTH_FIELD = 11;
 
     /**
      * FieldPosition selector for 'w' field alignment, corresponds to the
      * {@link Calendar#WEEK_OF_YEAR} field.
-     * 
-     * @since Android 1.0
      */
     public final static int WEEK_OF_YEAR_FIELD = 12;
 
     /**
      * FieldPosition selector for 'W' field alignment, corresponds to the
      * {@link Calendar#WEEK_OF_MONTH} field.
-     * 
-     * @since Android 1.0
      */
     public final static int WEEK_OF_MONTH_FIELD = 13;
 
     /**
      * FieldPosition selector for 'a' field alignment, corresponds to the
      * {@link Calendar#AM_PM} field.
-     * 
-     * @since Android 1.0
      */
     public final static int AM_PM_FIELD = 14;
 
@@ -331,8 +271,6 @@
      * {@link Calendar#HOUR} field. {@code HOUR1_FIELD} is used for the
      * one-based 12-hour clock. For example, 11:30 PM + 1 hour results in 12:30
      * AM.
-     * 
-     * @since Android 1.0
      */
     public final static int HOUR1_FIELD = 15;
 
@@ -340,8 +278,6 @@
      * The {@code FieldPosition} selector for 'z' field alignment, corresponds
      * to the {@link Calendar#ZONE_OFFSET} and {@link Calendar#DST_OFFSET}
      * fields.
-     * 
-     * @since Android 1.0
      */
     public final static int HOUR0_FIELD = 16;
 
@@ -349,15 +285,11 @@
      * The {@code FieldPosition} selector for 'z' field alignment, corresponds
      * to the {@link Calendar#ZONE_OFFSET} and {@link Calendar#DST_OFFSET}
      * fields.
-     * 
-     * @since Android 1.0
      */
     public final static int TIMEZONE_FIELD = 17;
 
     /**
      * Constructs a new instance of {@code DateFormat}.
-     * 
-     * @since Android 1.0
      */
     protected DateFormat() {
     }
@@ -368,7 +300,6 @@
      * @return a shallow copy of this {@code DateFormat}.
      * 
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -388,7 +319,6 @@
      *         it has the same properties as this date format; {@code false}
      *         otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -417,8 +347,7 @@
      * a format field, then its {@code beginIndex} and {@code endIndex} members
      * will be updated with the position of the first occurrence of this field
      * in the formatted text.
-     * </p>
-     * 
+     *
      * @param object
      *            the source object to format, must be a {@code Date} or a
      *            {@code Number}. If {@code object} is a number then a date is
@@ -429,10 +358,9 @@
      *            on input: an optional alignment field; on output: the offsets
      *            of the alignment field in the formatted text.
      * @return the string buffer.
-     * @exception IllegalArgumentException
-     *                if {@code object} is neither a {@code Date} nor a
-     *                {@code Number} instance.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *            if {@code object} is neither a {@code Date} nor a
+     *            {@code Number} instance.
      */
     @Override
     public final StringBuffer format(Object object, StringBuffer buffer,
@@ -453,7 +381,6 @@
      * @param date
      *            the date to format.
      * @return the formatted string.
-     * @since Android 1.0
      */
     public final String format(Date date) {
         return format(date, new StringBuffer(), new FieldPosition(0))
@@ -468,8 +395,7 @@
      * a format field, then its {@code beginIndex} and {@code endIndex} members
      * will be updated with the position of the first occurrence of this field
      * in the formatted text.
-     * </p>
-     * 
+     *
      * @param date
      *            the date to format.
      * @param buffer
@@ -478,7 +404,6 @@
      *            on input: an optional alignment field; on output: the offsets
      *            of the alignment field in the formatted text.
      * @return the string buffer.
-     * @since Android 1.0
      */
     public abstract StringBuffer format(Date date, StringBuffer buffer,
             FieldPosition field);
@@ -487,7 +412,6 @@
      * Gets the list of installed locales which support {@code DateFormat}.
      * 
      * @return an array of locales.
-     * @since Android 1.0
      */
     public static Locale[] getAvailableLocales() {
         return Locale.getAvailableLocales();
@@ -497,7 +421,6 @@
      * Returns the calendar used by this {@code DateFormat}.
      * 
      * @return the calendar used by this date format.
-     * @since Android 1.0
      */
     public Calendar getCalendar() {
         return calendar;
@@ -508,7 +431,6 @@
      * the DEFAULT style for the default locale.
      * 
      * @return the {@code DateFormat} instance for the default style and locale.
-     * @since Android 1.0
      */
     public final static DateFormat getDateInstance() {
         return getDateInstance(DEFAULT);
@@ -525,7 +447,6 @@
      * @throws IllegalArgumentException
      *             if {@code style} is not one of SHORT, MEDIUM, LONG, FULL, or
      *             DEFAULT.
-     * @since Android 1.0
      */
     public final static DateFormat getDateInstance(int style) {
         checkDateStyle(style);
@@ -545,13 +466,14 @@
      *             DEFAULT.
      * @return the {@code DateFormat} instance for {@code style} and
      *         {@code locale}.
-     * @since Android 1.0
      */
     public final static DateFormat getDateInstance(int style, Locale locale) {
         checkDateStyle(style);
+        // BEGIN android-changed
         ResourceBundle bundle = getBundle(locale);
         String pattern = bundle.getString("Date_" + getStyleName(style)); //$NON-NLS-1$
         return new SimpleDateFormat(pattern, locale);
+        // END android-changed
     }
 
     /**
@@ -559,7 +481,6 @@
      * and time values in the DEFAULT style for the default locale.
      * 
      * @return the {@code DateFormat} instance for the default style and locale.
-     * @since Android 1.0
      */
     public final static DateFormat getDateTimeInstance() {
         return getDateTimeInstance(DEFAULT, DEFAULT);
@@ -578,7 +499,6 @@
      * @throws IllegalArgumentException
      *             if {@code dateStyle} or {@code timeStyle} is not one of
      *             SHORT, MEDIUM, LONG, FULL, or DEFAULT.
-     * @since Android 1.0
      */
     public final static DateFormat getDateTimeInstance(int dateStyle,
             int timeStyle) {
@@ -602,16 +522,17 @@
      * @throws IllegalArgumentException
      *             if {@code dateStyle} or {@code timeStyle} is not one of
      *             SHORT, MEDIUM, LONG, FULL, or DEFAULT.
-     * @since Android 1.0
      */
     public final static DateFormat getDateTimeInstance(int dateStyle,
             int timeStyle, Locale locale) {
         checkTimeStyle(timeStyle);
         checkDateStyle(dateStyle);
+        // BEGIN android-changed
         ResourceBundle bundle = getBundle(locale);
         String pattern = bundle.getString("Date_" + getStyleName(dateStyle)) //$NON-NLS-1$
                 + " " + bundle.getString("Time_" + getStyleName(timeStyle)); //$NON-NLS-1$ //$NON-NLS-2$
         return new SimpleDateFormat(pattern, locale);
+        // END android-changed
     }
 
     /**
@@ -620,7 +541,6 @@
      * 
      * @return the {@code DateFormat} instance for the SHORT style and default
      *         locale.
-     * @since Android 1.0
      */
     public final static DateFormat getInstance() {
         return getDateTimeInstance(SHORT, SHORT);
@@ -630,7 +550,6 @@
      * Returns the {@code NumberFormat} used by this {@code DateFormat}.
      * 
      * @return the {@code NumberFormat} used by this date format.
-     * @since Android 1.0
      */
     public NumberFormat getNumberFormat() {
         return numberFormat;
@@ -662,7 +581,6 @@
      * values in the DEFAULT style for the default locale.
      * 
      * @return the {@code DateFormat} instance for the default style and locale.
-     * @since Android 1.0
      */
     public final static DateFormat getTimeInstance() {
         return getTimeInstance(DEFAULT);
@@ -679,7 +597,6 @@
      * @throws IllegalArgumentException
      *             if {@code style} is not one of SHORT, MEDIUM, LONG, FULL, or
      *             DEFAULT.
-     * @since Android 1.0
      */
     public final static DateFormat getTimeInstance(int style) {
         checkTimeStyle(style);
@@ -699,20 +616,20 @@
      *             DEFAULT.
      * @return the {@code DateFormat} instance for {@code style} and
      *         {@code locale}.
-     * @since Android 1.0
      */
     public final static DateFormat getTimeInstance(int style, Locale locale) {
         checkTimeStyle(style);
+        // BEGIN android-changed
         ResourceBundle bundle = getBundle(locale);
         String pattern = bundle.getString("Time_" + getStyleName(style)); //$NON-NLS-1$
         return new SimpleDateFormat(pattern, locale);
+        // END android-changed
     }
 
     /**
      * Returns the time zone of this date format's calendar.
      * 
      * @return the time zone of the calendar used by this date format.
-     * @since Android 1.0
      */
     public TimeZone getTimeZone() {
         return calendar.getTimeZone();
@@ -731,7 +648,6 @@
      * Indicates whether the calendar used by this date format is lenient.
      * 
      * @return {@code true} if the calendar is lenient; {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isLenient() {
         return calendar.isLenient();
@@ -744,9 +660,8 @@
      * @param string
      *            the string to parse.
      * @return the {@code Date} resulting from the parsing.
-     * @exception ParseException
-     *                if an error occurs during parsing.
-     * @since Android 1.0
+     * @throws ParseException
+     *         if an error occurs during parsing.
      */
     public Date parse(String string) throws ParseException {
         ParsePosition position = new ParsePosition(0);
@@ -770,8 +685,7 @@
      * this object's format method but can still be parsed as a date, then the
      * parse succeeds. Clients may insist on strict adherence to the format by
      * calling {@code setLenient(false)}.
-     * </p>
-     * 
+     *
      * @param string
      *            the string to parse.
      * @param position
@@ -782,7 +696,6 @@
      *            the index where the error occurred.
      * @return the date resulting from the parse, or {@code null} if there is an
      *         error.
-     * @since Android 1.0
      */
     public abstract Date parse(String string, ParsePosition position);
 
@@ -797,8 +710,7 @@
      * this object's format method but can still be parsed as a date, then the
      * parse succeeds. Clients may insist on strict adherence to the format by
      * calling {@code setLenient(false)}.
-     * </p>
-     * 
+     *
      * @param string
      *            the string to parse.
      * @param position
@@ -809,7 +721,6 @@
      *            is set to the index where the error occurred.
      * @return the date resulting from the parsing, or {@code null} if there is
      *         an error.
-     * @since Android 1.0
      */
     @Override
     public Object parseObject(String string, ParsePosition position) {
@@ -821,7 +732,6 @@
      * 
      * @param cal
      *            the new calendar.
-     * @since Android 1.0
      */
     public void setCalendar(Calendar cal) {
         calendar = cal;
@@ -836,7 +746,6 @@
      * @param value
      *            {@code true} to set the calendar to be lenient, {@code false}
      *            otherwise.
-     * @since Android 1.0
      */
     public void setLenient(boolean value) {
         calendar.setLenient(value);
@@ -847,7 +756,6 @@
      * 
      * @param format
      *            the new number format.
-     * @since Android 1.0
      */
     public void setNumberFormat(NumberFormat format) {
         numberFormat = format;
@@ -858,7 +766,6 @@
      * 
      * @param timezone
      *            the new time zone.
-     * @since Android 1.0
      */
     public void setTimeZone(TimeZone timezone) {
         calendar.setTimeZone(timezone);
@@ -871,8 +778,6 @@
      * <p>
      * There is no public constructor in this class, the only instances are the
      * constants defined here.
-     * </p>
-     * @since Android 1.0
      */
     public static class Field extends Format.Field {
 
@@ -882,135 +787,99 @@
 
         /**
          * Marks the era part of a date.
-         * 
-         * @since Android 1.0
          */
         public final static Field ERA = new Field("era", Calendar.ERA); //$NON-NLS-1$
 
         /**
          * Marks the year part of a date.
-         * 
-         * @since Android 1.0
          */
         public final static Field YEAR = new Field("year", Calendar.YEAR); //$NON-NLS-1$
 
         /**
          * Marks the month part of a date.
-         * 
-         * @since Android 1.0
          */
         public final static Field MONTH = new Field("month", Calendar.MONTH); //$NON-NLS-1$
 
         /**
          * Marks the hour of the day part of a date (0-11).
-         * 
-         * @since Android 1.0
          */
         public final static Field HOUR_OF_DAY0 = new Field("hour of day", //$NON-NLS-1$
                 Calendar.HOUR_OF_DAY);
 
         /**
          * Marks the hour of the day part of a date (1-12).
-         * 
-         * @since Android 1.0
          */
         public final static Field HOUR_OF_DAY1 = new Field("hour of day 1", -1); //$NON-NLS-1$
 
         /**
          * Marks the minute part of a time.
-         * 
-         * @since Android 1.0
          */
         public final static Field MINUTE = new Field("minute", Calendar.MINUTE); //$NON-NLS-1$
 
         /**
          * Marks the second part of a time.
-         * 
-         * @since Android 1.0
          */
         public final static Field SECOND = new Field("second", Calendar.SECOND); //$NON-NLS-1$
 
         /**
          * Marks the millisecond part of a time.
-         * 
-         * @since Android 1.0
          */
         public final static Field MILLISECOND = new Field("millisecond", //$NON-NLS-1$
                 Calendar.MILLISECOND);
 
         /**
          * Marks the day of the week part of a date.
-         * 
-         * @since Android 1.0
          */
         public final static Field DAY_OF_WEEK = new Field("day of week", //$NON-NLS-1$
                 Calendar.DAY_OF_WEEK);
 
         /**
          * Marks the day of the month part of a date.
-         * 
-         * @since Android 1.0
          */
         public final static Field DAY_OF_MONTH = new Field("day of month", //$NON-NLS-1$
                 Calendar.DAY_OF_MONTH);
 
         /**
          * Marks the day of the year part of a date.
-         * 
-         * @since Android 1.0
          */
         public final static Field DAY_OF_YEAR = new Field("day of year", //$NON-NLS-1$
                 Calendar.DAY_OF_YEAR);
 
         /**
          * Marks the day of the week in the month part of a date.
-         * 
-         * @since Android 1.0
          */
         public final static Field DAY_OF_WEEK_IN_MONTH = new Field(
                 "day of week in month", Calendar.DAY_OF_WEEK_IN_MONTH); //$NON-NLS-1$
 
         /**
          * Marks the week of the year part of a date.
-         * 
-         * @since Android 1.0
          */
         public final static Field WEEK_OF_YEAR = new Field("week of year", //$NON-NLS-1$
                 Calendar.WEEK_OF_YEAR);
 
         /**
          * Marks the week of the month part of a date.
-         * 
-         * @since Android 1.0
          */
         public final static Field WEEK_OF_MONTH = new Field("week of month", //$NON-NLS-1$
                 Calendar.WEEK_OF_MONTH);
 
         /**
          * Marks the time indicator part of a date.
-         * 
-         * @since Android 1.0
          */
         public final static Field AM_PM = new Field("am pm", Calendar.AM_PM); //$NON-NLS-1$
 
         /**
          * Marks the hour part of a date (0-11).
-         * 
-         * @since Android 1.0
          */
         public final static Field HOUR0 = new Field("hour", Calendar.HOUR); //$NON-NLS-1$
 
         /**
          * Marks the hour part of a date (1-12).
-         * 
-         * @since Android 1.0
          */
         public final static Field HOUR1 = new Field("hour 1", -1); //$NON-NLS-1$
 
         /**
          * Marks the time zone part of a date.
-         * 
-         * @since Android 1.0
          */
         public final static Field TIME_ZONE = new Field("time zone", -1); //$NON-NLS-1$
 
@@ -1022,12 +891,11 @@
         /**
          * Constructs a new instance of {@code DateFormat.Field} with the given
          * fieldName and calendar field.
-         * 
+         *
          * @param fieldName
          *            the field name.
          * @param calendarField
          *            the calendar field type of the field.
-         * @since Android 1.0
          */
         protected Field(String fieldName, int calendarField) {
             super(fieldName);
@@ -1042,7 +910,6 @@
          * Returns the Calendar field that this field represents.
          * 
          * @return the calendar field.
-         * @since Android 1.0
          */
         public int getCalendarField() {
             return calendarField;
@@ -1059,7 +926,6 @@
          * @throws IllegalArgumentException
          *             if {@code calendarField} is negative or greater than the
          *             field count of {@code Calendar}.
-         * @since Android 1.0
          */
         public static Field ofCalendarField(int calendarField) {
             if (calendarField < 0 || calendarField >= Calendar.FIELD_COUNT) {
@@ -1072,18 +938,23 @@
         /**
          * Resolves instances that are deserialized to the constant
          * {@code DateFormat.Field} values.
-         * 
+         *
          * @return the resolved field object.
          * @throws InvalidObjectException
          *             if an error occurs while resolving the field object.
-         * @since Android 1.0
          */
         @Override
         protected Object readResolve() throws InvalidObjectException {
+        	if (this.getClass() != Field.class) {
+                // text.0C=cannot resolve subclasses
+                throw new InvalidObjectException(Messages.getString("text.0C")); //$NON-NLS-1$
+            }
+        	
             if (calendarField != -1) {
                 try {
                     Field result = ofCalendarField(calendarField);
-                    if (result != null && this.equals(result)) {
+                    
+                    if (result != null && this.getName().equals(result.getName())) {
                         return result;
                     }
                 } catch (IllegalArgumentException e) {
diff --git a/libcore/text/src/main/java/java/text/DateFormatSymbols.java b/libcore/text/src/main/java/java/text/DateFormatSymbols.java
index 22c74e9..ad25bd8 100644
--- a/libcore/text/src/main/java/java/text/DateFormatSymbols.java
+++ b/libcore/text/src/main/java/java/text/DateFormatSymbols.java
@@ -14,29 +14,21 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-/**
-*******************************************************************************
-* Copyright (C) 1996-2007, International Business Machines Corporation and    *
-* others. All Rights Reserved.                                                *
-*******************************************************************************
-*/
 
 // BEGIN android-note
-// The class javadoc and some of the method descriptions are copied from ICU4J
-// source files. Changes have been made to the copied descriptions.
-// The icu license header was added to this file. 
+// The icu implementation used was changed from icu4j to icu4jni.
 // END android-note
 
 package java.text;
 
-import java.io.Serializable;
-// BEGIN android-added
 import java.io.IOException;
 import java.io.ObjectOutputStream;
-// END android-added
+import java.io.Serializable;
 import java.util.Arrays;
 import java.util.Locale;
+// BEGIN android-added
 import java.util.ResourceBundle;
+// END android-added
 
 // BEGIN android-added
 import com.ibm.icu4jni.util.Resources;
@@ -55,17 +47,15 @@
  * the formatter is created, you may modify its format pattern using the
  * {@code setPattern} method. For more information about creating formatters
  * using {@code DateFormat}'s factory methods, see {@link DateFormat}.
- * </p>
  * <p>
  * If you decide to create a date/time formatter with a specific format pattern
  * for a specific locale, you can do so with:
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * new SimpleDateFormat(aPattern, new DateFormatSymbols(aLocale)).
  * </pre>
- * 
+ *
  * </blockquote>
  * <p>
  * {@code DateFormatSymbols} objects can be cloned. When you obtain a
@@ -73,15 +63,12 @@
  * formatting data. For instance, you can replace the localized date/time format
  * pattern characters with the ones that you feel easy to remember or you can
  * change the representative cities to your favorite ones.
- * </p>
  * <p>
  * New {@code DateFormatSymbols} subclasses may be added to support
  * {@code SimpleDateFormat} for date/time formatting for additional locales.
- * </p>
- * 
+ *
  * @see DateFormat
  * @see SimpleDateFormat
- * @since Android 1.0
  */
 public class DateFormatSymbols implements Serializable, Cloneable {
 
@@ -93,6 +80,10 @@
 
     String[][] zoneStrings;
 
+    // BEGIN android-removed
+    // transient private com.ibm.icu4jni.text.DateFormatSymbols icuSymbols;
+    // END android-removed
+
 // BEGIN android-added
     /**
      * Locale, necessary to lazily load time zone strings. We force the time
@@ -110,15 +101,13 @@
         if (zoneStrings == null) {
             zoneStrings = Resources.getDisplayTimeZones(locale.toString());
         }
-        return zoneStrings;       
+        return zoneStrings;
     }
 // END android-added
 
     /**
      * Constructs a new {@code DateFormatSymbols} instance containing the
      * symbols for the default locale.
-     * 
-     * @since Android 1.0
      */
     public DateFormatSymbols() {
         this(Locale.getDefault());
@@ -130,9 +119,9 @@
      * 
      * @param locale
      *            the locale.
-     * @since Android 1.0
      */
     public DateFormatSymbols(Locale locale) {
+        // BEGIN android-changed
         ResourceBundle bundle = Format.getBundle(locale);
         localPatternChars = bundle.getString("LocalPatternChars"); //$NON-NLS-1$
         ampms = bundle.getStringArray("ampm"); //$NON-NLS-1$
@@ -141,12 +130,33 @@
         shortMonths = bundle.getStringArray("shortMonths"); //$NON-NLS-1$
         shortWeekdays = bundle.getStringArray("shortWeekdays"); //$NON-NLS-1$
         weekdays = bundle.getStringArray("weekdays"); //$NON-NLS-1$
-        // BEGIN android-changed
-        // zoneStrings = (String[][]) bundle.getObject("timezones"); //$NON-NLS-1$
         this.locale = locale;
         // END android-changed
     }
 
+
+    private void writeObject(ObjectOutputStream oos) throws IOException {
+        // BEGIN android-changed
+        internalZoneStrings();
+        // END android-changed
+        oos.defaultWriteObject();
+    }
+
+    // BEGIN android-removed
+    // DateFormatSymbols(Locale locale,
+    //         com.ibm.icu4jni.text.DateFormatSymbols icuSymbols) {
+    //
+    //     this.icuSymbols = icuSymbols;
+    //     localPatternChars = icuSymbols.getLocalPatternChars();
+    //     ampms = icuSymbols.getAmPmStrings();
+    //     eras = icuSymbols.getEras();
+    //     months = icuSymbols.getMonths();
+    //     shortMonths = icuSymbols.getShortMonths();
+    //     shortWeekdays = icuSymbols.getShortWeekdays();
+    //     weekdays = icuSymbols.getWeekdays();
+    // }
+    // END android-removed
+
     @Override
     public Object clone() {
         // BEGIN android-changed
@@ -168,7 +178,6 @@
      *         {@code DateFormatSymbols} and has the same symbols as this
      *         object, {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -178,7 +187,18 @@
         if (!(object instanceof DateFormatSymbols)) {
             return false;
         }
+
+        // BEGIN android-removed
+        // if (zoneStrings == null) {
+        //     zoneStrings = icuSymbols.getZoneStrings();
+        // }
+        // END android-removed
         DateFormatSymbols obj = (DateFormatSymbols) object;
+        // BEGIN android-removed
+        // if (obj.zoneStrings == null) {
+        //     obj.zoneStrings = obj.icuSymbols.getZoneStrings();
+        // }
+        // END android-removed
         if (!localPatternChars.equals(obj.localPatternChars)) {
             return false;
         }
@@ -233,7 +253,6 @@
      * {@code Calendar.PM} as indices for the array.
      * 
      * @return an array of strings.
-     * @since Android 1.0
      */
     public String[] getAmPmStrings() {
         return ampms.clone();
@@ -245,7 +264,6 @@
      * {@code GregorianCalendar.AD} as indices for the array.
      * 
      * @return an array of strings.
-     * @since Android 1.0
      */
     public String[] getEras() {
         return eras.clone();
@@ -256,7 +274,6 @@
      * specify date and time fields.
      * 
      * @return a string containing the pattern characters.
-     * @since Android 1.0
      */
     public String getLocalPatternChars() {
         return localPatternChars;
@@ -268,7 +285,6 @@
      * indices for the array.
      * 
      * @return an array of strings.
-     * @since Android 1.0
      */
     public String[] getMonths() {
         return months.clone();
@@ -280,7 +296,6 @@
      * {@code Calendar.JANUARY} etc. as indices for the array.
      * 
      * @return an array of strings.
-     * @since Android 1.0
      */
     public String[] getShortMonths() {
         return shortMonths.clone();
@@ -292,7 +307,6 @@
      * {@code Calendar.SUNDAY} etc. as indices for the array.
      * 
      * @return an array of strings.
-     * @since Android 1.0
      */
     public String[] getShortWeekdays() {
         return shortWeekdays.clone();
@@ -304,7 +318,6 @@
      * {@code Calendar.SUNDAY} etc. as indices for the array.
      * 
      * @return an array of strings.
-     * @since Android 1.0
      */
     public String[] getWeekdays() {
         return weekdays.clone();
@@ -318,12 +331,11 @@
      * and abbreviated names for daylight time.
      * 
      * @return a two-dimensional array of strings.
-     * @since Android 1.0
      */
     public String[][] getZoneStrings() {
-        // BEGIN android-added
+        // BEGIN android-changed
         String[][] zoneStrings = internalZoneStrings();
-        // END android-added
+        // END android-changed
         String[][] clone = new String[zoneStrings.length][];
         for (int i = zoneStrings.length; --i >= 0;) {
             clone[i] = zoneStrings[i].clone();
@@ -333,6 +345,9 @@
 
     @Override
     public int hashCode() {
+        // BEGIN android-changed
+        String[][] zoneStrings = internalZoneStrings();
+        // END android-changed
         int hashCode;
         hashCode = localPatternChars.hashCode();
         for (String element : ampms) {
@@ -353,12 +368,11 @@
         for (String element : weekdays) {
             hashCode += element.hashCode();
         }
-        // BEGIN android-added
-        String[][] zoneStrings = internalZoneStrings();
-        // END android-added
         for (String[] element : zoneStrings) {
             for (int j = 0; j < element.length; j++) {
-                hashCode += element[j].hashCode();
+                if (element[j] != null) {
+                    hashCode += element[j].hashCode();
+                }
             }
         }
         return hashCode;
@@ -371,7 +385,6 @@
      * 
      * @param data
      *            the array of strings for AM and PM.
-     * @since Android 1.0
      */
     public void setAmPmStrings(String[] data) {
         ampms = data.clone();
@@ -384,7 +397,6 @@
      * 
      * @param data
      *            the array of strings for BC and AD.
-     * @since Android 1.0
      */
     public void setEras(String[] data) {
         eras = data.clone();
@@ -396,7 +408,8 @@
      * 
      * @param data
      *            the string containing the pattern characters.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *            if {@code data} is null
      */
     public void setLocalPatternChars(String data) {
         if (data == null) {
@@ -412,7 +425,6 @@
      * 
      * @param data
      *            the array of strings.
-     * @since Android 1.0
      */
     public void setMonths(String[] data) {
         months = data.clone();
@@ -425,7 +437,6 @@
      * 
      * @param data
      *            the array of strings.
-     * @since Android 1.0
      */
     public void setShortMonths(String[] data) {
         shortMonths = data.clone();
@@ -438,7 +449,6 @@
      * 
      * @param data
      *            the array of strings.
-     * @since Android 1.0
      */
     public void setShortWeekdays(String[] data) {
         shortWeekdays = data.clone();
@@ -451,7 +461,6 @@
      * 
      * @param data
      *            the array of strings.
-     * @since Android 1.0
      */
     public void setWeekdays(String[] data) {
         weekdays = data.clone();
@@ -466,20 +475,8 @@
      * 
      * @param data
      *            the two-dimensional array of strings.
-     * @since Android 1.0
      */
     public void setZoneStrings(String[][] data) {
         zoneStrings = data.clone();
     }
-
-    // BEGIN android-added
-    private void writeObject(ObjectOutputStream out)
-                  throws IOException {
-        // Ensure internal zone strings are initialized to ensure backward
-        // compatibility.
-        internalZoneStrings();
-
-        out.defaultWriteObject();
-    }
-    // END android-added
 }
diff --git a/libcore/text/src/main/java/java/text/DecimalFormat.java b/libcore/text/src/main/java/java/text/DecimalFormat.java
index 393a2e5..7a0f529 100644
--- a/libcore/text/src/main/java/java/text/DecimalFormat.java
+++ b/libcore/text/src/main/java/java/text/DecimalFormat.java
@@ -14,24 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-/**
-*******************************************************************************
-* Copyright (C) 1996-2007, International Business Machines Corporation and    *
-* others. All Rights Reserved.                                                *
-*******************************************************************************
-*/
 
 // BEGIN android-note
-// The class javadoc and some of the method descriptions are copied from ICU4J
-// source files. Changes have been made to the copied descriptions.
-// The icu license header was added to this file.
 // The icu implementation used was changed from icu4j to icu4jni.
 // END android-note
 
 package java.text;
 
 import java.io.IOException;
-import java.io.InvalidObjectException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.ObjectStreamField;
@@ -42,8 +32,6 @@
 import java.util.Currency;
 import java.util.Locale;
 
-import org.apache.harmony.text.internal.nls.Messages;
-
 /**
  * A concrete subclass of {@link NumberFormat} that formats decimal numbers. It
  * has a variety of features designed to make it possible to parse and format
@@ -56,7 +44,6 @@
  * <strong>This is an enhanced version of {@code DecimalFormat} that is based on
  * the standard version in the RI. New or changed functionality is labeled
  * <strong><font color="red">NEW</font></strong>.</strong>
- * </p>
  * <p>
  * To obtain a {@link NumberFormat} for a specific locale (including the default
  * locale), call one of {@code NumberFormat}'s factory methods such as
@@ -65,18 +52,18 @@
  * {@link NumberFormat} factory methods may return subclasses other than
  * {@code DecimalFormat}. If you need to customize the format object, do
  * something like this: <blockquote>
- * 
+ *
  * <pre>
  * NumberFormat f = NumberFormat.getInstance(loc);
  * if (f instanceof DecimalFormat) {
  *     ((DecimalFormat)f).setDecimalSeparatorAlwaysShown(true);
  * }
  * </pre>
- * 
+ *
  * </blockquote>
  * <h5>Example:</h5>
  * <blockquote>
- * 
+ *
  * <pre>
  * // Print out a number using the localized number, currency,
  * // and percent format for each locale
@@ -115,7 +102,7 @@
  *     }
  * }
  * </pre>
- * 
+ *
  * </blockquote>
  * <h4>Patterns</h4>
  * <p>
@@ -126,7 +113,6 @@
  * digits. The symbols are stored in a {@link DecimalFormatSymbols} object. When
  * using the {@link NumberFormat} factory methods, the pattern and symbols are
  * read from ICU's locale data.
- * </p>
  * <h4>Special Pattern Characters</h4>
  * <p>
  * Many characters in a pattern are taken literally; they are matched during
@@ -139,19 +125,16 @@
  * character changes. Some special characters affect the behavior of the
  * formatter by their presence; for example, if the percent character is seen,
  * then the value is multiplied by 100 before being displayed.
- * </p>
  * <p>
  * To insert a special character in a pattern as a literal, that is, without any
  * special meaning, the character must be quoted. There are some exceptions to
  * this which are noted below.
- * </p>
  * <p>
  * The characters listed here are used in non-localized patterns. Localized
  * patterns use the corresponding characters taken from this formatter's
  * {@link DecimalFormatSymbols} object instead, and these characters lose their
  * special status. Two exceptions are the currency sign and quote, which are not
  * localized.
- * </p>
  * <blockquote> <table border="0" cellspacing="3" cellpadding="0" summary="Chart
  * showing symbol, location, localized, and meaning.">
  * <tr bgcolor="#ccccff">
@@ -297,7 +280,7 @@
  * {@code DecimalFormat} to throw an {@link IllegalArgumentException} with a
  * message that describes the problem.
  * <h4>Pattern BNF</h4>
- * 
+ *
  * <pre>
  * pattern    := subpattern (';' subpattern)?
  * subpattern := prefix? number exponent? suffix?
@@ -310,7 +293,7 @@
  * exponent   := 'E' '+'? '0'* '0'
  * padSpec    := '*' padChar
  * padChar    := '\\u0000'..'\\uFFFD' - quote
- *  
+ *
  * Notation:
  *   X*       0 or more instances of X
  *   X?       0 or 1 instances of X
@@ -318,7 +301,7 @@
  *   C..D     any character from C up to D, inclusive
  *   S-T      characters in S, except those in T
  * </pre>
- * 
+ *
  * The first subpattern is for positive numbers. The second (optional)
  * subpattern is for negative numbers.
  * <p>
@@ -446,7 +429,6 @@
  * specified directly, and the formatter settings for these counts are ignored.
  * Instead, the formatter uses as many integer and fraction digits as required
  * to display the specified number of significant digits.
- * </p>
  * <h5>Examples:</h5>
  * <blockquote> <table border=0 cellspacing=3 cellpadding=0>
  * <tr bgcolor="#ccccff">
@@ -554,10 +536,9 @@
  * <p>
  * {@code DecimalFormat} objects are not synchronized. Multiple threads should
  * not access one formatter concurrently.
- * 
+ *
  * @see Format
  * @see NumberFormat
- * @since Android 1.0
  */
 public class DecimalFormat extends NumberFormat {
 
@@ -578,11 +559,20 @@
     /**
      * Constructs a new {@code DecimalFormat} for formatting and parsing numbers
      * for the default locale.
-     * 
-     * @since Android 1.0
      */
     public DecimalFormat() {
-        this(getPattern(Locale.getDefault(), "Number")); //$NON-NLS-1$
+        Locale locale = Locale.getDefault();
+        icuSymbols = new com.ibm.icu4jni.text.DecimalFormatSymbols(locale);
+        symbols = new DecimalFormatSymbols(locale);
+        // BEGIN android-changed
+        dform = new com.ibm.icu4jni.text.DecimalFormat(
+                getPattern(Locale.getDefault(), "Number"), icuSymbols);
+        // END android-changed
+
+        super.setMaximumFractionDigits(dform.getMaximumFractionDigits());
+        super.setMaximumIntegerDigits(dform.getMaximumIntegerDigits());
+        super.setMinimumFractionDigits(dform.getMinimumFractionDigits());
+        super.setMinimumIntegerDigits(dform.getMinimumIntegerDigits());
     }
 
     /**
@@ -591,12 +581,19 @@
      * 
      * @param pattern
      *            the non-localized pattern.
-     * @exception IllegalArgumentException
-     *                if the pattern cannot be parsed.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *            if the pattern cannot be parsed.
      */
     public DecimalFormat(String pattern) {
-        this(pattern, new DecimalFormatSymbols());
+        Locale locale = Locale.getDefault();
+        icuSymbols = new com.ibm.icu4jni.text.DecimalFormatSymbols(locale);
+        symbols = new DecimalFormatSymbols(locale);
+        dform = new com.ibm.icu4jni.text.DecimalFormat(pattern, icuSymbols);
+
+        super.setMaximumFractionDigits(dform.getMaximumFractionDigits());
+        super.setMaximumIntegerDigits(dform.getMaximumIntegerDigits());
+        super.setMinimumFractionDigits(dform.getMinimumFractionDigits());
+        super.setMinimumIntegerDigits(dform.getMinimumIntegerDigits());
     }
 
     /**
@@ -607,13 +604,12 @@
      *            the non-localized pattern.
      * @param value
      *            the DecimalFormatSymbols.
-     * @exception IllegalArgumentException
-     *                if the pattern cannot be parsed.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *            if the pattern cannot be parsed.
      */
     public DecimalFormat(String pattern, DecimalFormatSymbols value) {
         symbols = (DecimalFormatSymbols) value.clone();
-        Locale locale = (Locale) this.getInternalField("locale", symbols); //$NON-NLS-1$
+        Locale locale = symbols.getLocale();
         icuSymbols = new com.ibm.icu4jni.text.DecimalFormatSymbols(locale);
         copySymbols(icuSymbols, symbols);
 
@@ -625,15 +621,27 @@
         super.setMinimumIntegerDigits(dform.getMinimumIntegerDigits());
     }
 
+    // BEGIN android-removed
+    // DecimalFormat(String pattern, DecimalFormatSymbols value, com.ibm.icu4jni.text.DecimalFormat icuFormat) {
+    //     symbols = value;
+    //     icuSymbols = value.getIcuSymbols();
+    //     dform = icuFormat;
+    //
+    //     super.setMaximumFractionDigits(dform.getMaximumFractionDigits());
+    //     super.setMaximumIntegerDigits(dform.getMaximumIntegerDigits());
+    //     super.setMinimumFractionDigits(dform.getMinimumFractionDigits());
+    //     super.setMinimumIntegerDigits(dform.getMinimumIntegerDigits());
+    // }
+    // END android-removed
+
     /**
      * Changes the pattern of this decimal format to the specified pattern which
      * uses localized pattern characters.
      * 
      * @param pattern
      *            the localized pattern.
-     * @exception IllegalArgumentException
-     *                if the pattern cannot be parsed.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *            if the pattern cannot be parsed.
      */
     public void applyLocalizedPattern(String pattern) {
         dform.applyLocalizedPattern(pattern);
@@ -645,9 +653,8 @@
      * 
      * @param pattern
      *            the non-localized pattern.
-     * @exception IllegalArgumentException
-     *                if the pattern cannot be parsed.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *            if the pattern cannot be parsed.
      */
     public void applyPattern(String pattern) {
 
@@ -660,7 +667,6 @@
      * 
      * @return a shallow copy of this decimal format.
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -680,7 +686,6 @@
      * @return {@code true} if the specified object is equal to this decimal
      *         format; {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -708,7 +713,6 @@
      *             if {@code object} cannot be formatted by this format.
      * @throws NullPointerException
      *             if {@code object} is {@code null}.
-     * @since Android 1.0
      */
     @Override
     public AttributedCharacterIterator formatToCharacterIterator(Object object) {
@@ -726,8 +730,7 @@
      * specifying a format field, then its {@code beginIndex} and
      * {@code endIndex} members will be updated with the position of the first
      * occurrence of this field in the formatted text.
-     * </p>
-     * 
+     *
      * @param value
      *            the double to format.
      * @param buffer
@@ -737,7 +740,6 @@
      *            on input: an optional alignment field; on output: the offsets
      *            of the alignment field in the formatted text.
      * @return the string buffer.
-     * @since Android 1.0
      */
     @Override
     public StringBuffer format(double value, StringBuffer buffer,
@@ -753,8 +755,7 @@
      * specifying a format field, then its {@code beginIndex} and
      * {@code endIndex} members will be updated with the position of the first
      * occurrence of this field in the formatted text.
-     * </p>
-     * 
+     *
      * @param value
      *            the long to format.
      * @param buffer
@@ -764,7 +765,6 @@
      *            on input: an optional alignment field; on output: the offsets
      *            of the alignment field in the formatted text.
      * @return the string buffer.
-     * @since Android 1.0
      */
     @Override
     public StringBuffer format(long value, StringBuffer buffer,
@@ -780,8 +780,7 @@
      * specifying a format field, then its {@code beginIndex} and
      * {@code endIndex} members will be updated with the position of the first
      * occurrence of this field in the formatted text.
-     * </p>
-     * 
+     *
      * @param number
      *            the object to format.
      * @param toAppendTo
@@ -794,7 +793,6 @@
      *             if {@code number} is not an instance of {@code Number}.
      * @throws NullPointerException
      *             if {@code toAppendTo} or {@code pos} is {@code null}.
-     * @since Android 1.0
      */
     @Override
     public final StringBuffer format(Object number, StringBuffer toAppendTo,
@@ -816,7 +814,6 @@
      * 
      * @return a copy of the {@code DecimalFormatSymbols} used by this decimal
      *         format.
-     * @since Android 1.0
      */
     public DecimalFormatSymbols getDecimalFormatSymbols() {
         return (DecimalFormatSymbols) symbols.clone();
@@ -827,7 +824,6 @@
      * 
      * @return the currency used by this decimal format.
      * @see DecimalFormatSymbols#getCurrency()
-     * @since Android 1.0
      */
     @Override
     public Currency getCurrency() {
@@ -841,9 +837,8 @@
      * Returns the number of digits grouped together by the grouping separator.
      * This only allows to get the primary grouping size. There is no API to get
      * the secondary grouping size.
-     * 
+     *
      * @return the number of digits grouped together.
-     * @since Android 1.0
      */
     public int getGroupingSize() {
         return dform.getGroupingSize();
@@ -854,7 +849,6 @@
      * or after parsing.
      * 
      * @return the multiplier.
-     * @since Android 1.0
      */
     public int getMultiplier() {
         return dform.getMultiplier();
@@ -864,7 +858,6 @@
      * Returns the prefix which is formatted or parsed before a negative number.
      * 
      * @return the negative prefix.
-     * @since Android 1.0
      */
     public String getNegativePrefix() {
         return dform.getNegativePrefix();
@@ -874,7 +867,6 @@
      * Returns the suffix which is formatted or parsed after a negative number.
      * 
      * @return the negative suffix.
-     * @since Android 1.0
      */
     public String getNegativeSuffix() {
         return dform.getNegativeSuffix();
@@ -884,7 +876,6 @@
      * Returns the prefix which is formatted or parsed before a positive number.
      * 
      * @return the positive prefix.
-     * @since Android 1.0
      */
     public String getPositivePrefix() {
         return dform.getPositivePrefix();
@@ -894,7 +885,6 @@
      * Returns the suffix which is formatted or parsed after a positive number.
      * 
      * @return the positive suffix.
-     * @since Android 1.0
      */
     public String getPositiveSuffix() {
         return dform.getPositiveSuffix();
@@ -911,7 +901,6 @@
      * 
      * @return {@code true} if the decimal separator should always be formatted;
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public boolean isDecimalSeparatorAlwaysShown() {
         return dform.isDecimalSeparatorAlwaysShown();
@@ -924,7 +913,6 @@
      * @return {@code true} if parse always returns {@code BigDecimals},
      *         {@code false} if the type of the result is {@code Long} or
      *         {@code Double}.
-     * @since Android 1.0
      */
     public boolean isParseBigDecimal() {
         return this.parseBigDecimal;
@@ -937,14 +925,18 @@
      * {@code java.lang.Integer}. Special cases are NaN, positive and negative
      * infinity, which are still returned as {@code java.lang.Double}.
      * 
+     *
      * @param value
      *            {@code true} that the resulting numbers of parse operations
      *            will be of type {@code java.lang.Integer} except for the
      *            special cases described above.
-     * @since Android 1.0
      */
     @Override
     public void setParseIntegerOnly(boolean value) {
+        // In this implementation, com.ibm.icu.text.DecimalFormat is wrapped to
+        // fulfill most of the format and parse feature. And this method is
+        // delegated to the wrapped instance of com.ibm.icu.text.DecimalFormat.
+
         dform.setParseIntegerOnly(value);
     }
 
@@ -954,7 +946,6 @@
      * 
      * @return {@code true} if this {@code DecimalFormat}'s parse method only
      *         returns {@code java.lang.Integer}; {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isParseIntegerOnly() {
@@ -985,7 +976,6 @@
      *         long, otherwise the result is a {@code Double}. If
      *         {@code isParseBigDecimal} is {@code true} then it returns the
      *         result as a {@code BigDecimal}.
-     * @since Android 1.0
      */
     @Override
     public Number parse(String string, ParsePosition position) {
@@ -1048,7 +1038,6 @@
      * 
      * @param value
      *            the {@code DecimalFormatSymbols} to set.
-     * @since Android 1.0
      */
     public void setDecimalFormatSymbols(DecimalFormatSymbols value) {
         if (value != null) {
@@ -1066,7 +1055,6 @@
      * @param currency
      *            the currency this {@code DecimalFormat} should use.
      * @see DecimalFormatSymbols#setCurrency(Currency)
-     * @since Android 1.0
      */
     @Override
     public void setCurrency(Currency currency) {
@@ -1084,7 +1072,6 @@
      * @param value
      *            {@code true} if the decimal separator should always be
      *            formatted; {@code false} otherwise.
-     * @since Android 1.0
      */
     public void setDecimalSeparatorAlwaysShown(boolean value) {
         dform.setDecimalSeparatorAlwaysShown(value);
@@ -1094,10 +1081,9 @@
      * Sets the number of digits grouped together by the grouping separator.
      * This only allows to set the primary grouping size; the secondary grouping
      * size can only be set with a pattern.
-     * 
+     *
      * @param value
      *            the number of digits grouped together.
-     * @since Android 1.0
      */
     public void setGroupingSize(int value) {
         dform.setGroupingSize(value);
@@ -1109,7 +1095,6 @@
      * 
      * @param value
      *            {@code true} if grouping is used; {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public void setGroupingUsed(boolean value) {
@@ -1120,7 +1105,6 @@
      * Indicates whether grouping will be used in this format.
      * 
      * @return {@code true} if grouping is used; {@code false} otherwise.
-     * @since Android 1.0
      */
     @Override
     public boolean isGroupingUsed() {
@@ -1137,7 +1121,6 @@
      * 
      * @param value
      *            the maximum number of fraction digits.
-     * @since Android 1.0
      */
     @Override
     public void setMaximumFractionDigits(int value) {
@@ -1155,7 +1138,6 @@
      * 
      * @param value
      *            the maximum number of integer digits.
-     * @since Android 1.0
      */
     @Override
     public void setMaximumIntegerDigits(int value) {
@@ -1171,7 +1153,6 @@
      * 
      * @param value
      *            the minimum number of fraction digits.
-     * @since Android 1.0
      */
     @Override
     public void setMinimumFractionDigits(int value) {
@@ -1187,7 +1168,6 @@
      * 
      * @param value
      *            the minimum number of integer digits.
-     * @since Android 1.0
      */
     @Override
     public void setMinimumIntegerDigits(int value) {
@@ -1201,7 +1181,6 @@
      * 
      * @param value
      *            the multiplier.
-     * @since Android 1.0
      */
     public void setMultiplier(int value) {
         dform.setMultiplier(value);
@@ -1212,7 +1191,6 @@
      * 
      * @param value
      *            the negative prefix.
-     * @since Android 1.0
      */
     public void setNegativePrefix(String value) {
         dform.setNegativePrefix(value);
@@ -1223,7 +1201,6 @@
      * 
      * @param value
      *            the negative suffix.
-     * @since Android 1.0
      */
     public void setNegativeSuffix(String value) {
         dform.setNegativeSuffix(value);
@@ -1234,7 +1211,6 @@
      * 
      * @param value
      *            the positive prefix.
-     * @since Android 1.0
      */
     public void setPositivePrefix(String value) {
         dform.setPositivePrefix(value);
@@ -1245,7 +1221,6 @@
      * 
      * @param value
      *            the positive suffix.
-     * @since Android 1.0
      */
     public void setPositiveSuffix(String value) {
         dform.setPositiveSuffix(value);
@@ -1258,7 +1233,6 @@
      * @param newValue
      *            {@code true} if all the returned objects should be of type
      *            {@code BigDecimal}; {@code false} otherwise.
-     * @since Android 1.0
      */
     public void setParseBigDecimal(boolean newValue) {
         this.parseBigDecimal = newValue;
@@ -1269,7 +1243,6 @@
      * characters.
      * 
      * @return the localized pattern.
-     * @since Android 1.0
      */
     public String toLocalizedPattern() {
         return dform.toLocalizedPattern();
@@ -1280,7 +1253,6 @@
      * characters.
      * 
      * @return the non-localized pattern.
-     * @since Android 1.0
      */
     public String toPattern() {
         return dform.toPattern();
@@ -1322,47 +1294,47 @@
      *             if some I/O error occurs
      * @throws ClassNotFoundException
      */
+    @SuppressWarnings("nls")
     private void writeObject(ObjectOutputStream stream) throws IOException,
             ClassNotFoundException {
         ObjectOutputStream.PutField fields = stream.putFields();
-        fields.put("positivePrefix", dform.getPositivePrefix()); //$NON-NLS-1$
-        fields.put("positiveSuffix", dform.getPositiveSuffix()); //$NON-NLS-1$
-        fields.put("negativePrefix", dform.getNegativePrefix()); //$NON-NLS-1$
-        fields.put("negativeSuffix", dform.getNegativeSuffix()); //$NON-NLS-1$
-        String posPrefixPattern = (String) this.getInternalField(
-                "posPrefixPattern", dform); //$NON-NLS-1$
-        fields.put("posPrefixPattern", posPrefixPattern); //$NON-NLS-1$
-        String posSuffixPattern = (String) this.getInternalField(
-                "posSuffixPattern", dform); //$NON-NLS-1$
-        fields.put("posSuffixPattern", posSuffixPattern); //$NON-NLS-1$
-        String negPrefixPattern = (String) this.getInternalField(
-                "negPrefixPattern", dform); //$NON-NLS-1$
-        fields.put("negPrefixPattern", negPrefixPattern); //$NON-NLS-1$
-        String negSuffixPattern = (String) this.getInternalField(
-                "negSuffixPattern", dform); //$NON-NLS-1$
-        fields.put("negSuffixPattern", negSuffixPattern); //$NON-NLS-1$
-        fields.put("multiplier", dform.getMultiplier()); //$NON-NLS-1$
-        fields.put("groupingSize", (byte) dform.getGroupingSize()); //$NON-NLS-1$
+        fields.put("positivePrefix", dform.getPositivePrefix());
+        fields.put("positiveSuffix", dform.getPositiveSuffix());
+        fields.put("negativePrefix", dform.getNegativePrefix());
+        fields.put("negativeSuffix", dform.getNegativeSuffix());
+        String posPrefixPattern = (String) Format.getInternalField(
+                "posPrefixPattern", dform);
+        fields.put("posPrefixPattern", posPrefixPattern);
+        String posSuffixPattern = (String) Format.getInternalField(
+                "posSuffixPattern", dform);
+        fields.put("posSuffixPattern", posSuffixPattern);
+        String negPrefixPattern = (String) Format.getInternalField(
+                "negPrefixPattern", dform);
+        fields.put("negPrefixPattern", negPrefixPattern);
+        String negSuffixPattern = (String) Format.getInternalField(
+                "negSuffixPattern", dform);
+        fields.put("negSuffixPattern", negSuffixPattern);
+        fields.put("multiplier", dform.getMultiplier());
+        fields.put("groupingSize", (byte) dform.getGroupingSize());
         // BEGIN android-added
-        fields.put("groupingUsed", dform.isGroupingUsed()); //$NON-NLS-1$
+        fields.put("groupingUsed", dform.isGroupingUsed());
         // END android-added
-        fields.put("decimalSeparatorAlwaysShown", dform //$NON-NLS-1$
+        fields.put("decimalSeparatorAlwaysShown", dform
                 .isDecimalSeparatorAlwaysShown());
-        fields.put("parseBigDecimal", parseBigDecimal); //$NON-NLS-1$
-        fields.put("symbols", symbols); //$NON-NLS-1$
-        boolean useExponentialNotation = ((Boolean) this.getInternalField(
-                "useExponentialNotation", dform)).booleanValue(); //$NON-NLS-1$
-        fields.put("useExponentialNotation", useExponentialNotation); //$NON-NLS-1$
-        byte minExponentDigits = ((Byte) this.getInternalField(
-                "minExponentDigits", dform)).byteValue(); //$NON-NLS-1$
-        fields.put("minExponentDigits", minExponentDigits); //$NON-NLS-1$
-        fields.put("maximumIntegerDigits", dform.getMaximumIntegerDigits()); //$NON-NLS-1$
-        fields.put("minimumIntegerDigits", dform.getMinimumIntegerDigits()); //$NON-NLS-1$
-        fields.put("maximumFractionDigits", dform.getMaximumFractionDigits()); //$NON-NLS-1$
-        fields.put("minimumFractionDigits", dform.getMinimumFractionDigits()); //$NON-NLS-1$
-        fields.put("serialVersionOnStream", CURRENT_SERIAL_VERTION); //$NON-NLS-1$
+        fields.put("parseBigDecimal", parseBigDecimal);
+        fields.put("symbols", symbols);
+        boolean useExponentialNotation = ((Boolean) Format.getInternalField(
+                "useExponentialNotation", dform)).booleanValue();
+        fields.put("useExponentialNotation", useExponentialNotation);
+        byte minExponentDigits = ((Byte) Format.getInternalField(
+                "minExponentDigits", dform)).byteValue();
+        fields.put("minExponentDigits", minExponentDigits);
+        fields.put("maximumIntegerDigits", dform.getMaximumIntegerDigits());
+        fields.put("minimumIntegerDigits", dform.getMinimumIntegerDigits());
+        fields.put("maximumFractionDigits", dform.getMaximumFractionDigits());
+        fields.put("minimumFractionDigits", dform.getMinimumFractionDigits());
+        fields.put("serialVersionOnStream", CURRENT_SERIAL_VERTION);
         stream.writeFields();
-
     }
 
     /**
@@ -1376,41 +1348,42 @@
      * @throws ClassNotFoundException
      *             if some class of serialized objects or fields cannot be found
      */
+    @SuppressWarnings("nls")
     private void readObject(ObjectInputStream stream) throws IOException,
             ClassNotFoundException {
 
         ObjectInputStream.GetField fields = stream.readFields();
-        String positivePrefix = (String) fields.get("positivePrefix", ""); //$NON-NLS-1$ //$NON-NLS-2$
-        String positiveSuffix = (String) fields.get("positiveSuffix", ""); //$NON-NLS-1$ //$NON-NLS-2$
-        String negativePrefix = (String) fields.get("negativePrefix", "-"); //$NON-NLS-1$ //$NON-NLS-2$
-        String negativeSuffix = (String) fields.get("negativeSuffix", ""); //$NON-NLS-1$ //$NON-NLS-2$
+        String positivePrefix = (String) fields.get("positivePrefix", "");
+        String positiveSuffix = (String) fields.get("positiveSuffix", "");
+        String negativePrefix = (String) fields.get("negativePrefix", "-");
+        String negativeSuffix = (String) fields.get("negativeSuffix", "");
 
-        String posPrefixPattern = (String) fields.get("posPrefixPattern", ""); //$NON-NLS-1$ //$NON-NLS-2$
-        String posSuffixPattern = (String) fields.get("posSuffixPattern", ""); //$NON-NLS-1$ //$NON-NLS-2$
-        String negPrefixPattern = (String) fields.get("negPrefixPattern", "-"); //$NON-NLS-1$ //$NON-NLS-2$
-        String negSuffixPattern = (String) fields.get("negSuffixPattern", ""); //$NON-NLS-1$ //$NON-NLS-2$
+        String posPrefixPattern = (String) fields.get("posPrefixPattern", "");
+        String posSuffixPattern = (String) fields.get("posSuffixPattern", "");
+        String negPrefixPattern = (String) fields.get("negPrefixPattern", "-");
+        String negSuffixPattern = (String) fields.get("negSuffixPattern", "");
 
-        int multiplier = fields.get("multiplier", 1); //$NON-NLS-1$
-        byte groupingSize = fields.get("groupingSize", (byte) 3); //$NON-NLS-1$
+        int multiplier = fields.get("multiplier", 1);
+        byte groupingSize = fields.get("groupingSize", (byte) 3);
         // BEGIN android-added
-        boolean groupingUsed = fields.get("groupingUsed", true); //$NON-NLS-1$
+        boolean groupingUsed = fields.get("groupingUsed", true);
         // END android-added
         boolean decimalSeparatorAlwaysShown = fields.get(
-                "decimalSeparatorAlwaysShown", false); //$NON-NLS-1$
-        boolean parseBigDecimal = fields.get("parseBigDecimal", false); //$NON-NLS-1$
-        symbols = (DecimalFormatSymbols) fields.get("symbols", null); //$NON-NLS-1$
+                "decimalSeparatorAlwaysShown", false);
+        boolean parseBigDecimal = fields.get("parseBigDecimal", false);
+        symbols = (DecimalFormatSymbols) fields.get("symbols", null);
 
-        boolean useExponentialNotation = fields.get("useExponentialNotation", //$NON-NLS-1$
+        boolean useExponentialNotation = fields.get("useExponentialNotation",
                 false);
-        byte minExponentDigits = fields.get("minExponentDigits", (byte) 0); //$NON-NLS-1$
+        byte minExponentDigits = fields.get("minExponentDigits", (byte) 0);
 
-        int maximumIntegerDigits = fields.get("maximumIntegerDigits", 309); //$NON-NLS-1$
-        int minimumIntegerDigits = fields.get("minimumIntegerDigits", 309); //$NON-NLS-1$
-        int maximumFractionDigits = fields.get("maximumFractionDigits", 340); //$NON-NLS-1$
-        int minimumFractionDigits = fields.get("minimumFractionDigits", 340); //$NON-NLS-1$
-        this.serialVersionOnStream = fields.get("serialVersionOnStream", 0); //$NON-NLS-1$
+        int maximumIntegerDigits = fields.get("maximumIntegerDigits", 309);
+        int minimumIntegerDigits = fields.get("minimumIntegerDigits", 309);
+        int maximumFractionDigits = fields.get("maximumFractionDigits", 340);
+        int minimumFractionDigits = fields.get("minimumFractionDigits", 340);
+        this.serialVersionOnStream = fields.get("serialVersionOnStream", 0);
 
-        Locale locale = (Locale) getInternalField("locale", symbols); //$NON-NLS-1$
+        Locale locale = (Locale) Format.getInternalField("locale", symbols);
         // BEGIN android-removed
         // dform = new com.ibm.icu4jni.text.DecimalFormat("", //$NON-NLS-1$
         //         new com.ibm.icu4jni.text.DecimalFormatSymbols(locale));
@@ -1421,18 +1394,18 @@
         dform = new com.ibm.icu4jni.text.DecimalFormat("", //$NON-NLS-1$
                 icuSymbols);
         // END android-added
-        setInternalField("useExponentialNotation", dform, new Boolean( //$NON-NLS-1$
-                useExponentialNotation));
-        setInternalField("minExponentDigits", dform, //$NON-NLS-1$
+        setInternalField("useExponentialNotation", dform, Boolean
+                .valueOf(useExponentialNotation));
+        setInternalField("minExponentDigits", dform,
                 new Byte(minExponentDigits));
         dform.setPositivePrefix(positivePrefix);
         dform.setPositiveSuffix(positiveSuffix);
         dform.setNegativePrefix(negativePrefix);
         dform.setNegativeSuffix(negativeSuffix);
-        setInternalField("posPrefixPattern", dform, posPrefixPattern); //$NON-NLS-1$
-        setInternalField("posSuffixPattern", dform, posSuffixPattern); //$NON-NLS-1$
-        setInternalField("negPrefixPattern", dform, negPrefixPattern); //$NON-NLS-1$
-        setInternalField("negSuffixPattern", dform, negSuffixPattern); //$NON-NLS-1$
+        setInternalField("posPrefixPattern", dform, posPrefixPattern);
+        setInternalField("posSuffixPattern", dform, posSuffixPattern);
+        setInternalField("negPrefixPattern", dform, negPrefixPattern);
+        setInternalField("negSuffixPattern", dform, negSuffixPattern);
         dform.setMultiplier(multiplier);
         dform.setGroupingSize(groupingSize);
         // BEGIN android-added
@@ -1445,21 +1418,14 @@
         dform.setMaximumFractionDigits(maximumFractionDigits);
         this.setParseBigDecimal(parseBigDecimal);
 
-        if (super.getMaximumIntegerDigits() > Integer.MAX_VALUE
-                || super.getMinimumIntegerDigits() > Integer.MAX_VALUE
-                || super.getMaximumFractionDigits() > Integer.MAX_VALUE
-                || super.getMinimumIntegerDigits() > Integer.MAX_VALUE) {
-            // text.09=The deserialized date is invalid
-            throw new InvalidObjectException(Messages.getString("text.09")); //$NON-NLS-1$
-        }
         if (serialVersionOnStream < 3) {
-            setMaximumIntegerDigits(super.getMinimumIntegerDigits());
+            setMaximumIntegerDigits(super.getMaximumIntegerDigits());
             setMinimumIntegerDigits(super.getMinimumIntegerDigits());
             setMaximumFractionDigits(super.getMaximumFractionDigits());
             setMinimumFractionDigits(super.getMinimumFractionDigits());
         }
         if (serialVersionOnStream < 1) {
-            this.setInternalField("useExponentialNotation", dform, //$NON-NLS-1$
+            this.setInternalField("useExponentialNotation", dform,
                     Boolean.FALSE);
         }
         serialVersionOnStream = 3;
@@ -1473,10 +1439,16 @@
      */
     private void copySymbols(final com.ibm.icu4jni.text.DecimalFormatSymbols icu,
             final DecimalFormatSymbols dfs) {
+        Currency currency = dfs.getCurrency();
         // BEGIN android-changed
-        icu.setCurrency(Currency.getInstance(dfs.getCurrency()
-                .getCurrencyCode()));
+        if (currency == null) {
+            icu.setCurrency(Currency.getInstance("XXX")); //$NON-NLS-1$
+        } else {
+            icu.setCurrency(Currency.getInstance(dfs.getCurrency()
+                    .getCurrencyCode()));
+        }
         // END android-changed
+       
         icu.setCurrencySymbol(dfs.getCurrencySymbol());
         icu.setDecimalSeparator(dfs.getDecimalSeparator());
         icu.setDigit(dfs.getDigit());
@@ -1518,31 +1490,4 @@
                     }
                 });
     }
-
-    /*
-     * Gets private field value by reflection.
-     * 
-     * @param fieldName the field name to be set @param target the object which
-     * field to be gotten
-     */
-    private Object getInternalField(final String fieldName, final Object target) {
-        Object value = AccessController
-                .doPrivileged(new PrivilegedAction<Object>() {
-                    public Object run() {
-                        Object result = null;
-                        java.lang.reflect.Field field = null;
-                        try {
-                            field = target.getClass().getDeclaredField(
-                                    fieldName);
-                            field.setAccessible(true);
-                            result = field.get(target);
-                        } catch (Exception e1) {
-                            return null;
-                        }
-                        return result;
-                    }
-                });
-        return value;
-    }
-
 }
diff --git a/libcore/text/src/main/java/java/text/DecimalFormatSymbols.java b/libcore/text/src/main/java/java/text/DecimalFormatSymbols.java
index 3415ee8..a71a4c6 100644
--- a/libcore/text/src/main/java/java/text/DecimalFormatSymbols.java
+++ b/libcore/text/src/main/java/java/text/DecimalFormatSymbols.java
@@ -14,17 +14,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-/**
-*******************************************************************************
-* Copyright (C) 1996-2007, International Business Machines Corporation and    *
-* others. All Rights Reserved.                                                *
-*******************************************************************************
-*/
 
 // BEGIN android-note
-// The class javadoc and some of the method descriptions are copied from ICU4J
-// source files. Changes have been made to the copied descriptions.
-// The icu license header was added to this file. 
+// changed from ICU to resource bundles
 // END android-note
 
 package java.text;
@@ -37,7 +29,9 @@
 import java.util.Arrays;
 import java.util.Currency;
 import java.util.Locale;
+// BEGIN android-added
 import java.util.ResourceBundle;
+// END android-added
 
 /**
  * Encapsulates the set of symbols (such as the decimal separator, the grouping
@@ -46,10 +40,9 @@
  * {@code DecimalFormatSymbols} from its locale data. If you need to change any
  * of these symbols, you can get the {@code DecimalFormatSymbols} object from
  * your {@code DecimalFormat} and modify it.
- * 
+ *
  * @see java.util.Locale
  * @see DecimalFormat
- * @since Android 1.0
  */
 public final class DecimalFormatSymbols implements Cloneable, Serializable {
 
@@ -73,8 +66,6 @@
      * the default locale. Best practice is to create a {@code DecimalFormat}
      * and then to get the {@code DecimalFormatSymbols} from that object by
      * calling {@link DecimalFormat#getDecimalFormatSymbols()}.
-     * 
-     * @since Android 1.0
      */
     public DecimalFormatSymbols() {
         this(Locale.getDefault());
@@ -88,9 +79,9 @@
      * 
      * @param locale
      *            the locale.
-     * @since Android 1.0
      */
     public DecimalFormatSymbols(Locale locale) {
+        // BEGIN android-changed
         ResourceBundle bundle = Format.getBundle(locale);
         patternChars = bundle.getString("DecimalPatternChars").toCharArray(); //$NON-NLS-1$
         infinity = bundle.getString("Infinity"); //$NON-NLS-1$
@@ -105,8 +96,10 @@
             currencySymbol = bundle.getString("CurrencySymbol"); //$NON-NLS-1$
             intlCurrencySymbol = bundle.getString("IntCurrencySymbol"); //$NON-NLS-1$
         }
+        // END android-changed
     }
 
+ 
     /**
      * Returns a new {@code DecimalFormatSymbols} with the same symbols as this
      * {@code DecimalFormatSymbols}.
@@ -114,7 +107,6 @@
      * @return a shallow copy of this {@code DecimalFormatSymbols}.
      * 
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -137,7 +129,6 @@
      * @return {@code true} if the specified object is equal to this
      *         {@code DecimalFormatSymbols}; {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -161,13 +152,12 @@
      * been previously called with a value that is not a valid ISO 4217 currency
      * code.
      * <p>
-     * 
+     *
      * @return the currency that was set in the constructor or by calling
      *         {@code setCurrency()} or {@code setInternationalCurrencySymbol()},
      *         or {@code null} if an invalid currency was set.
      * @see #setCurrency(Currency)
      * @see #setInternationalCurrencySymbol(String)
-     * @since Android 1.0
      */
     public Currency getCurrency() {
         return currency;
@@ -177,7 +167,6 @@
      * Returns the international currency symbol.
      * 
      * @return the international currency symbol as string.
-     * @since Android 1.0
      */
     public String getInternationalCurrencySymbol() {
         return intlCurrencySymbol;
@@ -187,7 +176,6 @@
      * Returns the currency symbol.
      * 
      * @return the currency symbol as string.
-     * @since Android 1.0
      */
     public String getCurrencySymbol() {
         return currencySymbol;
@@ -197,7 +185,6 @@
      * Returns the character which represents the decimal point in a number.
      * 
      * @return the decimal separator character.
-     * @since Android 1.0
      */
     public char getDecimalSeparator() {
         return patternChars[DecimalSeparator];
@@ -208,7 +195,6 @@
      * pattern.
      * 
      * @return the digit pattern character.
-     * @since Android 1.0
      */
     public char getDigit() {
         return patternChars[Digit];
@@ -218,7 +204,6 @@
      * Returns the character used as the thousands separator in a number.
      * 
      * @return the thousands separator character.
-     * @since Android 1.0
      */
     public char getGroupingSeparator() {
         return patternChars[GroupingSeparator];
@@ -228,7 +213,6 @@
      * Returns the string which represents infinity.
      * 
      * @return the infinity symbol as a string.
-     * @since Android 1.0
      */
     public String getInfinity() {
         return infinity;
@@ -238,7 +222,6 @@
      * Returns the minus sign character.
      * 
      * @return the minus sign as a character.
-     * @since Android 1.0
      */
     public char getMinusSign() {
         return patternChars[MinusSign];
@@ -249,7 +232,6 @@
      * value.
      * 
      * @return the monetary decimal point as a character.
-     * @since Android 1.0
      */
     public char getMonetaryDecimalSeparator() {
         return patternChars[MonetaryDecimalSeparator];
@@ -259,7 +241,6 @@
      * Returns the string which represents NaN.
      * 
      * @return the symbol NaN as a string.
-     * @since Android 1.0
      */
     public String getNaN() {
         return NaN;
@@ -270,7 +251,6 @@
      * in a format pattern.
      * 
      * @return the pattern separator character.
-     * @since Android 1.0
      */
     public char getPatternSeparator() {
         return patternChars[PatternSeparator];
@@ -280,7 +260,6 @@
      * Returns the percent character.
      * 
      * @return the percent character.
-     * @since Android 1.0
      */
     public char getPercent() {
         return patternChars[Percent];
@@ -290,7 +269,6 @@
      * Returns the per mill sign character.
      * 
      * @return the per mill sign character.
-     * @since Android 1.0
      */
     public char getPerMill() {
         return patternChars[PerMill];
@@ -300,7 +278,6 @@
      * Returns the character which represents zero.
      * 
      * @return the zero character.
-     * @since Android 1.0
      */
     public char getZeroDigit() {
         return patternChars[ZeroDigit];
@@ -331,7 +308,6 @@
      *            the new currency.
      * @throws NullPointerException
      *             if {@code currency} is {@code null}.
-     * @since Android 1.0
      */
     public void setCurrency(Currency currency) {
         if (currency == null) {
@@ -355,7 +331,6 @@
      * 
      * @param value
      *            the currency code.
-     * @since Android 1.0
      */
     public void setInternationalCurrencySymbol(String value) {
         if (value == null) {
@@ -382,7 +357,6 @@
      * 
      * @param value
      *            the currency symbol.
-     * @since Android 1.0
      */
     public void setCurrencySymbol(String value) {
         currencySymbol = value;
@@ -393,7 +367,6 @@
      * 
      * @param value
      *            the decimal separator character.
-     * @since Android 1.0
      */
     public void setDecimalSeparator(char value) {
         patternChars[DecimalSeparator] = value;
@@ -404,7 +377,6 @@
      * 
      * @param value
      *            the digit character.
-     * @since Android 1.0
      */
     public void setDigit(char value) {
         patternChars[Digit] = value;
@@ -415,7 +387,6 @@
      * 
      * @param value
      *            the grouping separator character.
-     * @since Android 1.0
      */
     public void setGroupingSeparator(char value) {
         patternChars[GroupingSeparator] = value;
@@ -426,7 +397,6 @@
      * 
      * @param value
      *            the string representing infinity.
-     * @since Android 1.0
      */
     public void setInfinity(String value) {
         infinity = value;
@@ -437,7 +407,6 @@
      * 
      * @param value
      *            the minus sign character.
-     * @since Android 1.0
      */
     public void setMinusSign(char value) {
         patternChars[MinusSign] = value;
@@ -449,7 +418,6 @@
      * 
      * @param value
      *            the monetary decimal separator character.
-     * @since Android 1.0
      */
     public void setMonetaryDecimalSeparator(char value) {
         patternChars[MonetaryDecimalSeparator] = value;
@@ -460,7 +428,6 @@
      * 
      * @param value
      *            the string representing NaN.
-     * @since Android 1.0
      */
     public void setNaN(String value) {
         NaN = value;
@@ -472,7 +439,6 @@
      * 
      * @param value
      *            the pattern separator character.
-     * @since Android 1.0
      */
     public void setPatternSeparator(char value) {
         patternChars[PatternSeparator] = value;
@@ -483,7 +449,6 @@
      * 
      * @param value
      *            the percent character.
-     * @since Android 1.0
      */
     public void setPercent(char value) {
         patternChars[Percent] = value;
@@ -494,7 +459,6 @@
      * 
      * @param value
      *            the per mill character.
-     * @since Android 1.0
      */
     public void setPerMill(char value) {
         patternChars[PerMill] = value;
@@ -505,7 +469,6 @@
      * 
      * @param value
      *            the zero digit character.
-     * @since Android 1.0
      */
     public void setZeroDigit(char value) {
         patternChars[ZeroDigit] = value;
@@ -588,4 +551,14 @@
             currency = null;
         }
     }
+    
+    Locale getLocale(){
+        return locale;
+    }
+
+    // BEGIN android-removed
+    // com.ibm.icu4jni.text.DecimalFormatSymbols getIcuSymbols() {
+    //     return icuSymbols;
+    // }
+    // END android-removed
 }
diff --git a/libcore/text/src/main/java/java/text/FieldPosition.java b/libcore/text/src/main/java/java/text/FieldPosition.java
index 4cf985d..d2da297 100644
--- a/libcore/text/src/main/java/java/text/FieldPosition.java
+++ b/libcore/text/src/main/java/java/text/FieldPosition.java
@@ -25,13 +25,9 @@
  * A {@code FieldPosition} can be created by using the integer constants in the
  * various format classes (for example {@code NumberFormat.INTEGER_FIELD}) or
  * one of the fields of type {@code Format.Field}.
- * </p>
  * <p>
  * If more than one field information is needed, the method
  * {@link NumberFormat#formatToCharacterIterator(Object)} should be used.
- * </p>
- * 
- * @since Android 1.0
  */
 public class FieldPosition {
 
@@ -44,7 +40,6 @@
      * 
      * @param field
      *            the field to identify.
-     * @since Android 1.0
      */
     public FieldPosition(int field) {
         myField = field;
@@ -56,7 +51,6 @@
      * 
      * @param attribute
      *            the field attribute to identify.
-     * @since Android 1.0
      */
     public FieldPosition(Format.Field attribute) {
         myAttribute = attribute;
@@ -71,7 +65,6 @@
      *            the field attribute to identify.
      * @param field
      *            the field to identify.
-     * @since Android 1.0
      */
     public FieldPosition(Format.Field attribute, int field) {
         myAttribute = attribute;
@@ -92,7 +85,6 @@
      * @return {@code true} if the specified object is equal to this field
      *         position; {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -108,7 +100,6 @@
      * Returns the index of the beginning of the field.
      * 
      * @return the first index of the field.
-     * @since Android 1.0
      */
     public int getBeginIndex() {
         return beginIndex;
@@ -118,7 +109,6 @@
      * Returns the index one past the end of the field.
      * 
      * @return one past the index of the last character in the field.
-     * @since Android 1.0
      */
     public int getEndIndex() {
         return endIndex;
@@ -128,7 +118,6 @@
      * Returns the field which is being identified.
      * 
      * @return the field constant.
-     * @since Android 1.0
      */
     public int getField() {
         return myField;
@@ -138,7 +127,6 @@
      * Returns the attribute which is being identified.
      * 
      * @return the field.
-     * @since Android 1.0
      */
     public Format.Field getFieldAttribute() {
         return myAttribute;
@@ -155,7 +143,6 @@
      * 
      * @param index
      *            the index of the first character in the field.
-     * @since Android 1.0
      */
     public void setBeginIndex(int index) {
         beginIndex = index;
@@ -166,7 +153,6 @@
      * 
      * @param index
      *            one past the index of the last character in the field.
-     * @since Android 1.0
      */
     public void setEndIndex(int index) {
         endIndex = index;
@@ -176,7 +162,6 @@
      * Returns the string representation of this field position.
      * 
      * @return the string representation of this field position.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
diff --git a/libcore/text/src/main/java/java/text/Format.java b/libcore/text/src/main/java/java/text/Format.java
index 5e31cd4..6ee1ba2 100644
--- a/libcore/text/src/main/java/java/text/Format.java
+++ b/libcore/text/src/main/java/java/text/Format.java
@@ -14,26 +14,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-/**
-*******************************************************************************
-* Copyright (C) 1996-2007, International Business Machines Corporation and    *
-* others. All Rights Reserved.                                                *
-*******************************************************************************
-*/
-
-// BEGIN android-note
-// The class javadoc and some of the method descriptions are copied from ICU4J
-// source files. Changes have been made to the copied descriptions.
-// The icu license header was added to this file. 
-// END android-note
 
 package java.text;
 
 import java.io.Serializable;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+// BEGIN android-added
 import java.util.Locale;
 import java.util.ResourceBundle;
+// END android-added
 
 import org.apache.harmony.text.internal.nls.Messages;
 
@@ -49,7 +39,6 @@
  * A date and time formatter like {@code SimpleDateFormat} may represent a
  * specific date, encoded numerically, as a string such as "Wednesday, February
  * 26, 1997 AD".
- * </p>
  * <p>
  * Many of the concrete subclasses of {@code Format} employ the notion of a
  * pattern. A pattern is a string representation of the rules which govern the
@@ -60,7 +49,6 @@
  * of a pattern is defined by each subclass. Even though many subclasses use
  * patterns, the notion of a pattern is not inherent to {@code Format} classes
  * in general, and is not part of the explicit base class protocol.
- * </p>
  * <p>
  * Two complex formatting classes are worth mentioning: {@code MessageFormat}
  * and {@code ChoiceFormat}. {@code ChoiceFormat} is a subclass of
@@ -73,9 +61,6 @@
  * 27, 1997." given the arguments 0, "MyDisk", and the date value of 2/27/97.
  * See the {@link ChoiceFormat} and {@link MessageFormat} descriptions for
  * further information.
- * </p>
- * 
- * @since Android 1.0
  */
 public abstract class Format implements Serializable, Cloneable {
 
@@ -83,8 +68,6 @@
 
     /**
      * Constructs a new {@code Format} instance.
-     * 
-     * @since Android 1.0
      */
     public Format() {
     }
@@ -95,7 +78,6 @@
      * @return a shallow copy of this format.
      * 
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -106,6 +88,7 @@
         }
     }
 
+    // BEGIN android-added
     static ResourceBundle getBundle(final Locale locale) {
         return AccessController
                 .doPrivileged(new PrivilegedAction<ResourceBundle>() {
@@ -116,6 +99,7 @@
                     }
                 });
     }
+    // END android-added
 
     String convertPattern(String template, String fromChars, String toChars,
             boolean check) {
@@ -156,9 +140,8 @@
      * @param object
      *            the object to format.
      * @return the formatted string.
-     * @exception IllegalArgumentException
-     *                if the object cannot be formatted by this format.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *         if the object cannot be formatted by this format.
      */
     public final String format(Object object) {
         return format(object, new StringBuffer(), new FieldPosition(0))
@@ -173,8 +156,7 @@
      * member contains an enum value specifying a field on input, then its
      * {@code beginIndex} and {@code endIndex} members will be updated with the
      * text offset of the first occurrence of this field in the formatted text.
-     * </p>
-     * 
+     *
      * @param object
      *            the object to format.
      * @param buffer
@@ -183,9 +165,8 @@
      *            on input: an optional alignment field; on output: the offsets
      *            of the alignment field in the formatted text.
      * @return the string buffer.
-     * @exception IllegalArgumentException
-     *                if the object cannot be formatted by this format.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *            if the object cannot be formatted by this format.
      */
     public abstract StringBuffer format(Object object, StringBuffer buffer,
             FieldPosition field);
@@ -197,15 +178,13 @@
      * <p>
      * Subclasses should return an {@code AttributedCharacterIterator} with the
      * appropriate attributes.
-     * </p>
-     * 
+     *
      * @param object
      *            the object to format.
      * @return an {@code AttributedCharacterIterator} with the formatted object
      *         and attributes.
-     * @exception IllegalArgumentException
-     *                if the object cannot be formatted by this format.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *            if the object cannot be formatted by this format.
      */
     public AttributedCharacterIterator formatToCharacterIterator(Object object) {
         return new AttributedString(format(object)).getIterator();
@@ -217,9 +196,8 @@
      * @param string
      *            the string to parse.
      * @return the object resulting from the parse.
-     * @exception ParseException
-     *                if an error occurs during parsing.
-     * @since Android 1.0
+     * @throws ParseException
+     *            if an error occurs during parsing.
      */
     public Object parseObject(String string) throws ParseException {
         ParsePosition position = new ParsePosition(0);
@@ -247,10 +225,35 @@
      *            set to the index where the error occurred.
      * @return the object resulting from the parse or {@code null} if there is
      *         an error.
-     * @since Android 1.0
      */
     public abstract Object parseObject(String string, ParsePosition position);
 
+    /*
+     * Gets private field value by reflection.
+     * 
+     * @param fieldName the field name to be set @param target the object which
+     * field to be gotten
+     */
+    static Object getInternalField(final String fieldName, final Object target) {
+        Object value = AccessController
+                .doPrivileged(new PrivilegedAction<Object>() {
+                    public Object run() {
+                        Object result = null;
+                        java.lang.reflect.Field field = null;
+                        try {
+                            field = target.getClass().getDeclaredField(
+                                    fieldName);
+                            field.setAccessible(true);
+                            result = field.get(target);
+                        } catch (Exception e1) {
+                            return null;
+                        }
+                        return result;
+                    }
+                });
+        return value;
+    }
+
     static boolean upTo(String string, ParsePosition position,
             StringBuffer buffer, char stop) {
         int index = position.getIndex(), length = string.length();
@@ -307,8 +310,6 @@
      * {@code AttributedCharacterIterator} that the
      * {@code formatToCharacterIterator()} method returns in {@code Format}
      * subclasses.
-     * 
-     * @since Android 1.0
      */
     public static class Field extends AttributedCharacterIterator.Attribute {
 
@@ -316,10 +317,9 @@
 
         /**
          * Constructs a new instance of {@code Field} with the given field name.
-         * 
+         *
          * @param fieldName
          *            the field name.
-         * @since Android 1.0
          */
         protected Field(String fieldName) {
             super(fieldName);
diff --git a/libcore/text/src/main/java/java/text/MessageFormat.java b/libcore/text/src/main/java/java/text/MessageFormat.java
index 6405b6c..4ab1ade 100644
--- a/libcore/text/src/main/java/java/text/MessageFormat.java
+++ b/libcore/text/src/main/java/java/text/MessageFormat.java
@@ -14,18 +14,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-/**
-*******************************************************************************
-* Copyright (C) 1996-2007, International Business Machines Corporation and    *
-* others. All Rights Reserved.                                                *
-*******************************************************************************
-*/
-
-// BEGIN android-note
-// The class javadoc and some of the method descriptions are copied from ICU4J
-// source files. Changes have been made to the copied descriptions.
-// The icu license header was added to this file. 
-// END android-note
 
 package java.text;
 
@@ -44,12 +32,11 @@
 
 /**
  * Produces concatenated
- * messages in language-neutral way. Use this class to construct messages 
+ * messages in language-neutral way. Use this class to construct messages
  * displayed for end users.
  * <p>
  * {@code MessageFormat} takes a set of objects, formats them and then
  * inserts the formatted strings into the pattern at the appropriate places.
- * </p>
  * <p>
  * <strong>Note:</strong> {@code MessageFormat} differs from the other
  * {@code Format} classes in that you create a {@code MessageFormat}
@@ -58,12 +45,12 @@
  * {@code MessageFormat} itself doesn't implement locale specific
  * behavior. Any locale specific behavior is defined by the pattern that you
  * provide as well as the subformats used for inserted arguments.
- * 
+ *
  * <h4><a name="patterns">Patterns and their interpretation</a></h4>
- * 
+ *
  * {@code MessageFormat} uses patterns of the following form:
  * <blockquote>
- * 
+ *
  * <pre>
  * <i>MessageFormatPattern:</i>
  *         <i>String</i>
@@ -97,9 +84,9 @@
  *         ' <i>QuotedPattern</i> '
  *         <i>UnquotedPattern</i>
  * </pre>
- * 
+ *
  * </blockquote>
- * 
+ *
  * <p>
  * Within a <i>String</i>, {@code "''"} represents a single quote. A
  * <i>QuotedString</i> can contain arbitrary characters except single quotes;
@@ -118,7 +105,6 @@
  * {@code "ab {0} de"} and {@code "ab '}' de"} are valid subformat
  * patterns, but {@code "ab {0'}' de"} and {@code "ab } de"} are
  * not.
- * </p>
  * <dl>
  * <dt><b>Warning:</b></dt>
  * <dd>The rules for using quotes within message format patterns unfortunately
@@ -233,11 +219,11 @@
  * <td>{@code new ChoiceFormat(subformatPattern)}</td>
  * </tr>
  * </table>
- * 
+ *
  * <h4>Usage Information</h4>
  * <p>
  * Here are some examples of usage: <blockquote>
- * 
+ *
  * <pre>
  * Object[] arguments = {
  *         new Integer(7), new Date(System.currentTimeMillis()),
@@ -250,15 +236,14 @@
  * </em>
  * At 12:30 PM on Jul 3, 2053, there was a disturbance in the Force on planet 7.
  * </pre>
- * 
- * </blockquote> 
+ *
+ * </blockquote>
  * <p>
  * Typically, the message format will come from resources, and the
  * arguments will be dynamically set at runtime.
- * </p>
  * <p>
  * Example 2: <blockquote>
- * 
+ *
  * <pre>
  * Object[] testArgs = {new Long(3), "MyDisk"};
  * MessageFormat form = new MessageFormat("The disk \"{1}\" contains {0} file(s).");
@@ -270,15 +255,14 @@
  * The disk "MyDisk" contains 1 file(s).
  * The disk "MyDisk" contains 1,273 file(s).
  * </pre>
- * 
+ *
  * </blockquote>
- * 
+ *
  * <p>
  * For more sophisticated patterns, you can use a {@code ChoiceFormat} to
- * get output such as: 
- * </p>
+ * get output such as:
  * <blockquote>
- * 
+ *
  * <pre>
  * MessageFormat form = new MessageFormat("The disk \"{1}\" contains {0}.");
  * double[] filelimits = {0,1,2};
@@ -294,15 +278,15 @@
  * The disk "MyDisk" contains one file.
  * The disk "MyDisk" contains 1,273 files.
  * </pre>
- * 
+ *
  * </blockquote> You can either do this programmatically, as in the above
  * example, or by using a pattern (see {@link ChoiceFormat} for more
  * information) as in: <blockquote>
- * 
+ *
  * <pre>
  * form.applyPattern("There {0,choice,0#are no files|1#is one file|1&lt;are {0,number,integer} files}.");
  * </pre>
- * 
+ *
  * </blockquote>
  * <p>
  * <strong>Note:</strong> As we see above, the string produced by a
@@ -312,11 +296,9 @@
  * {@code ChoiceFormat} programmatically (instead of using the string
  * patterns), then be careful not to produce a format that recurses on itself,
  * which will cause an infinite loop.
- * </p>
  * <p>
  * When a single argument is parsed more than once in the string, the last match
  * will be the final result of the parsing. For example:
- * </p>
  * <blockquote>
  * <pre>
  * MessageFormat mf = new MessageFormat("{0,number,#.##}, {0,number,#.#}");
@@ -329,10 +311,9 @@
  * </pre>
  * </blockquote>
  * <p>
- * Likewise, parsing with a {@code MessageFormat} object using patterns 
- * containing multiple occurrences of the same argument would return the last 
+ * Likewise, parsing with a {@code MessageFormat} object using patterns
+ * containing multiple occurrences of the same argument would return the last
  * match. For example:
- * </p>
  * <blockquote>
  * <pre>
  * MessageFormat mf = new MessageFormat("{0}, {0}, {0}");
@@ -346,14 +327,12 @@
  * Message formats are not synchronized. It is recommended to create separate
  * format instances for each thread. If multiple threads access a format
  * concurrently, it must be synchronized externally.
- * </p>
- * 
+ *
  * @see java.util.Locale
  * @see Format
  * @see NumberFormat
  * @see DecimalFormat
  * @see ChoiceFormat
- * @since Android 1.0
  */
 public class MessageFormat extends Format {
 
@@ -379,9 +358,8 @@
      *            the pattern.
      * @param locale
      *            the locale.
-     * @exception IllegalArgumentException
-     *                if the pattern cannot be parsed.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *            if the pattern cannot be parsed.
      */
     public MessageFormat(String template, Locale locale) {
         this.locale = locale;
@@ -394,9 +372,8 @@
      * 
      * @param template
      *            the pattern.
-     * @exception IllegalArgumentException
-     *                if the pattern cannot be parsed.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *            if the pattern cannot be parsed.
      */
     public MessageFormat(String template) {
         applyPattern(template);
@@ -407,9 +384,8 @@
      * 
      * @param template
      *            the new pattern.
-     * @exception IllegalArgumentException
-     *                if the pattern cannot be parsed.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *            if the pattern cannot be parsed.
      */
     public void applyPattern(String template) {
         int length = template.length();
@@ -422,15 +398,31 @@
         Vector<Format> localFormats = new Vector<Format>();
         while (position.getIndex() < length) {
             if (Format.upTo(template, position, buffer, '{')) {
-                byte arg;
+                int arg = 0;
                 int offset = position.getIndex();
-                if (offset >= length
-                        || (arg = (byte) Character.digit(template
-                                .charAt(offset++), 10)) == -1) {
+                if (offset >= length) {
                     // text.19=Invalid argument number
                     throw new IllegalArgumentException(Messages
                             .getString("text.19")); //$NON-NLS-1$
                 }
+                // Get argument number
+                char ch;
+                while ((ch = template.charAt(offset++)) != '}' && ch != ',') {
+                    if (ch < '0' && ch > '9') {
+                        // text.19=Invalid argument number
+                        throw new IllegalArgumentException(Messages
+                            .getString("text.19")); //$NON-NLS-1$
+                    }
+                    
+                    arg = arg * 10 + (ch - '0');
+                    
+                    if (arg < 0 || offset >= length) {
+                        // text.19=Invalid argument number
+                        throw new IllegalArgumentException(Messages
+                            .getString("text.19")); //$NON-NLS-1$
+                    }
+                }
+                offset--;
                 position.setIndex(offset);
                 localFormats.addElement(parseVariable(template, position));
                 if (argCount >= args.length) {
@@ -465,7 +457,6 @@
      * 
      * @return a shallow copy of this {@code MessageFormat}.
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -490,7 +481,6 @@
      * @return {@code true} if the specified object is equal to this
      *         {@code MessageFormat}; {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -526,10 +516,9 @@
      *            the object to format.
      * @return an {@code AttributedCharacterIterator} with the formatted message and
      *         attributes.
-     * @exception IllegalArgumentException
-     *                if the arguments in the object array cannot be formatted
-     *                by this message format.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *            if the arguments in the object array cannot be formatted
+     *            by this message format.
      */
     @Override
     public AttributedCharacterIterator formatToCharacterIterator(Object object) {
@@ -564,8 +553,7 @@
      * {@code MessageFormat.Field.ARGUMENT}, then the begin and end index of
      * this field position is set to the location of the first occurrence of a
      * message format argument. Otherwise, the {@code FieldPosition} is ignored.
-     * </p>
-     * 
+     *
      * @param objects
      *            the array of objects to format.
      * @param buffer
@@ -574,7 +562,6 @@
      *            on input: an optional alignment field; on output: the offsets
      *            of the alignment field in the formatted text.
      * @return the string buffer.
-     * @since Android 1.0
      */
     public final StringBuffer format(Object[] objects, StringBuffer buffer,
             FieldPosition field) {
@@ -723,18 +710,16 @@
      * {@code MessageFormat.Field.ARGUMENT}, then the begin and end index of
      * this field position is set to the location of the first occurrence of a
      * message format argument. Otherwise, the {@code FieldPosition} is ignored.
-     * </p>
      * <p>
      * Calling this method is equivalent to calling
-     * </p>
      * <blockquote>
      * 
      * <pre>
      * format((Object[])object, buffer, field)
      * </pre>
-     * 
+     *
      * </blockquote>
-     * 
+     *
      * @param object
      *            the object to format, must be an array of {@code Object}.
      * @param buffer
@@ -745,7 +730,6 @@
      * @return the string buffer.
      * @throws ClassCastException
      *             if {@code object} is not an array of {@code Object}.
-     * @since Android 1.0
      */
     @Override
     public final StringBuffer format(Object object, StringBuffer buffer,
@@ -761,22 +745,26 @@
      * @param objects
      *            the array of objects to format.
      * @return the formatted result.
-     * @exception IllegalArgumentException
-     *                if the pattern cannot be parsed.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *            if the pattern cannot be parsed.
      */
     public static String format(String template, Object... objects) {
-        // BEGIN android-note
-        // changed parameter type from array to varargs.
-        // END android-note
+        if (objects != null) {
+            for (int i = 0; i < objects.length; i++) {
+                if (objects[i] == null) {
+                    objects[i] = "null";
+                }
+            }
+        }
+        // BEGIN android-changed
         return new MessageFormat(template).format(objects);
+        // END android-changed
     }
 
     /**
      * Returns the {@code Format} instances used by this message format.
      * 
      * @return an array of {@code Format} instances.
-     * @since Android 1.0
      */
     public Format[] getFormats() {
         return formats.clone();
@@ -788,7 +776,6 @@
      * of the last one.
      * 
      * @return an array of formats, ordered by argument index.
-     * @since Android 1.0
      */
     public Format[] getFormatsByArgumentIndex() {
         Format[] answer = new Format[maxArgumentIndex + 1];
@@ -806,7 +793,6 @@
      *            the index of the format to set.
      * @param format
      *            the format that will be set at index {@code argIndex}.
-     * @since Android 1.0
      */
     public void setFormatByArgumentIndex(int argIndex, Format format) {
         for (int i = 0; i < maxOffset + 1; i++) {
@@ -822,7 +808,6 @@
      * 
      * @param formats
      *            the formats in an array.
-     * @since Android 1.0
      */
     public void setFormatsByArgumentIndex(Format[] formats) {
         for (int j = 0; j < formats.length; j++) {
@@ -838,7 +823,6 @@
      * Returns the locale used when creating formats.
      * 
      * @return the locale used to create formats.
-     * @since Android 1.0
      */
     public Locale getLocale() {
         return locale;
@@ -869,9 +853,8 @@
      * @param string
      *            the string to parse.
      * @return the array of {@code Object} arguments resulting from the parse.
-     * @exception ParseException
-     *                if an error occurs during parsing.
-     * @since Android 1.0
+     * @throws ParseException
+     *            if an error occurs during parsing.
      */
     public Object[] parse(String string) throws ParseException {
         ParsePosition position = new ParsePosition(0);
@@ -900,7 +883,6 @@
      *            set to the index where the error occurred.
      * @return the array of objects resulting from the parse, or {@code null} if
      *         there is an error.
-     * @since Android 1.0
      */
     public Object[] parse(String string, ParsePosition position) {
         if (string == null) {
@@ -972,7 +954,6 @@
      *            set to the index where the error occurred.
      * @return the array of objects resulting from the parse, or {@code null} if
      *         there is an error.
-     * @since Android 1.0
      */
     @Override
     public Object parseObject(String string, ParsePosition position) {
@@ -1096,7 +1077,6 @@
      *            the index of the format to change.
      * @param format
      *            the {@code Format} that replaces the old format.
-     * @since Android 1.0
      */
     public void setFormat(int offset, Format format) {
         formats[offset] = format;
@@ -1107,7 +1087,6 @@
      * 
      * @param formats
      *            an array of {@code Format}.
-     * @since Android 1.0
      */
     public void setFormats(Format[] formats) {
         int min = this.formats.length;
@@ -1126,7 +1105,6 @@
      * 
      * @param locale
      *            the new locale.
-     * @since Android 1.0
      */
     public void setLocale(Locale locale) {
         this.locale = locale;
@@ -1216,7 +1194,6 @@
      * Returns the pattern of this message format.
      * 
      * @return the pattern.
-     * @since Android 1.0
      */
     public String toPattern() {
         StringBuffer buffer = new StringBuffer();
@@ -1302,7 +1279,7 @@
         int offset = 0;
         int offsetsLength = maxOffset + 1;
         int[] offsets = new int[offsetsLength];
-        StringBuffer pattern = new StringBuffer();
+        StringBuilder pattern = new StringBuilder();
         for (int i = 0; i <= maxOffset; i++) {
             offset += strings[i].length();
             offsets[i] = offset;
@@ -1351,32 +1328,22 @@
      * <p>
      * There is no public constructor in this class, the only instances are the
      * constants defined here.
-     * </p>
-     * 
-     * @since Android 1.0
      */
     public static class Field extends Format.Field {
 
         private static final long serialVersionUID = 7899943957617360810L;
 
-        // BEGIN android-removed
-        // public static final Field ARGUMENT = new Field("message argument field"); //$NON-NLS-1$
-        // END android-removed
-
         /**
          * This constant stands for the message argument.
-         * 
-         * @since Android 1.0
          */
         public static final Field ARGUMENT = new Field("message argument field"); //$NON-NLS-1$
 
         /**
          * Constructs a new instance of {@code MessageFormat.Field} with the
          * given field name.
-         * 
+         *
          * @param fieldName
          *            the field name.
-         * @since Android 1.0
          */
         protected Field(String fieldName) {
             super(fieldName);
@@ -1385,7 +1352,7 @@
         /**
          * Resolves instances that are deserialized to the constant
          * {@code MessageFormat.Field} values.
-         * 
+         *
          * @return the resolved field object.
          * @throws InvalidObjectException
          *             if an error occurs while resolving the field object.
diff --git a/libcore/text/src/main/java/java/text/NumberFormat.java b/libcore/text/src/main/java/java/text/NumberFormat.java
index 7510240..5b8d883 100644
--- a/libcore/text/src/main/java/java/text/NumberFormat.java
+++ b/libcore/text/src/main/java/java/text/NumberFormat.java
@@ -14,17 +14,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-/**
-*******************************************************************************
-* Copyright (C) 1996-2007, International Business Machines Corporation and    *
-* others. All Rights Reserved.                                                *
-*******************************************************************************
-*/
 
 // BEGIN android-note
-// The class javadoc and some of the method descriptions are copied from ICU4J
-// source files. Changes have been made to the copied descriptions.
-// The icu license header was added to this file. 
+// changed from ICU to resource bundles
 // END android-note
 
 package java.text;
@@ -36,7 +28,9 @@
 import java.io.ObjectStreamField;
 import java.util.Currency;
 import java.util.Locale;
+// BEGIN android-added
 import java.util.ResourceBundle;
+// END android-added
 
 import org.apache.harmony.text.internal.nls.Messages;
 
@@ -50,53 +44,48 @@
  * Your code can be completely independent of the locale conventions for decimal
  * points, thousands-separators, or even the particular decimal digits used, or
  * whether the number format is even decimal.
- * </p>
  * <p>
  * To format a number for the current locale, use one of the factory class
  * methods:
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * myString = NumberFormat.getInstance().format(myNumber);
  * </pre>
- * 
+ *
  * </blockquote>
  * <p>
  * If you are formatting multiple numbers, it is more efficient to get the
  * format and use it multiple times so that the system doesn't have to fetch the
  * information about the local language and country conventions multiple times.
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * NumberFormat nf = NumberFormat.getInstance();
  * for (int i = 0; i &lt; a.length; ++i) {
  *     output.println(nf.format(myNumber[i]) + &quot;; &quot;);
  * }
  * </pre>
- * 
+ *
  * </blockquote>
  * <p>
  * To format a number for a different locale, specify it in the call to
  * {@code getInstance}.
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH);
  * </pre>
- * 
+ *
  * </blockquote>
  * <p>
  * You can also use a {@code NumberFormat} to parse numbers:
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * myNumber = nf.parse(myString);
  * </pre>
- * 
+ *
  * </blockquote>
  * <p>
  * Use {@code getInstance} or {@code getNumberInstance} to get the normal number
@@ -104,7 +93,6 @@
  * {@code getCurrencyInstance} to get the currency number format and use
  * {@code getPercentInstance} to get a format for displaying percentages. With
  * this format, a fraction like 0.53 is displayed as 53%.
- * </p>
  * <p>
  * You can also control the display of numbers with methods such as
  * {@code setMinimumFractionDigits}. If you want even more control over the
@@ -113,7 +101,6 @@
  * {@code DecimalFormat}. This will work for the vast majority of locales; just
  * remember to put it in a {@code try} block in case you encounter an unusual
  * one.
- * </p>
  * <p>
  * {@code NumberFormat} is designed such that some controls work for formatting
  * and others work for parsing. For example, {@code setParseIntegerOnly} only
@@ -121,7 +108,6 @@
  * leaves the parse position just after '6'); if set to {@code false},
  * "3456.78" is parsed as 3456.78 (and leaves the parse position just after
  * '8'). This is independent of formatting.
- * </p>
  * <p>
  * You can also use forms of the {@code parse} and {@code format} methods with
  * {@code ParsePosition} and {@code FieldPosition} to allow you to:
@@ -155,11 +141,9 @@
  * and the {@code NumberFormat} API is essentially an abstraction of
  * {@code DecimalFormat's} API. Refer to {@code DecimalFormat} for more
  * information about this API.
- * </p>
- * 
+ *
  * @see DecimalFormat
  * @see java.text.ChoiceFormat
- * @since Android 1.0
  */
 public abstract class NumberFormat extends Format {
 
@@ -167,15 +151,11 @@
 
     /**
      * Field constant identifying the integer part of a number.
-     * 
-     * @since Android 1.0
      */
     public static final int INTEGER_FIELD = 0;
 
     /**
      * Field constant identifying the fractional part of a number.
-     * 
-     * @since Android 1.0
      */
     public static final int FRACTION_FIELD = 1;
 
@@ -186,8 +166,6 @@
 
     /**
      * Constructs a new instance of {@code NumberFormat}.
-     * 
-     * @since Android 1.0
      */
     public NumberFormat() {
     }
@@ -198,7 +176,6 @@
      * 
      * @return a shallow copy of this {@code NumberFormat}.
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -215,7 +192,6 @@
      * @return {@code true} if the specified object is equal to this number
      *         format; {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -240,7 +216,6 @@
      * @param value
      *            the double to format.
      * @return the formatted string.
-     * @since Android 1.0
      */
     public final String format(double value) {
         return format(value, new StringBuffer(), new FieldPosition(0))
@@ -255,8 +230,7 @@
      * specifying a format field, then its {@code beginIndex} and
      * {@code endIndex} members will be updated with the position of the first
      * occurrence of this field in the formatted text.
-     * </p>
-     * 
+     *
      * @param value
      *            the double to format.
      * @param buffer
@@ -266,7 +240,6 @@
      *            on input: an optional alignment field; on output: the offsets
      *            of the alignment field in the formatted text.
      * @return the string buffer.
-     * @since Android 1.0
      */
     public abstract StringBuffer format(double value, StringBuffer buffer,
             FieldPosition field);
@@ -277,7 +250,6 @@
      * @param value
      *            the long to format.
      * @return the formatted string.
-     * @since Android 1.0
      */
     public final String format(long value) {
         return format(value, new StringBuffer(), new FieldPosition(0))
@@ -292,8 +264,7 @@
      * specifying a format field, then its {@code beginIndex} and
      * {@code endIndex} members will be updated with the position of the first
      * occurrence of this field in the formatted text.
-     * </p>
-     * 
+     *
      * @param value
      *            the long to format.
      * @param buffer
@@ -303,7 +274,6 @@
      *            on input: an optional alignment field; on output: the offsets
      *            of the alignment field in the formatted text.
      * @return the string buffer.
-     * @since Android 1.0
      */
     public abstract StringBuffer format(long value, StringBuffer buffer,
             FieldPosition field);
@@ -316,8 +286,7 @@
      * a format field, then its {@code beginIndex} and {@code endIndex} members
      * will be updated with the position of the first occurrence of this field
      * in the formatted text.
-     * </p>
-     * 
+     *
      * @param object
      *            the object to format, must be a {@code Number}.
      * @param buffer
@@ -328,7 +297,6 @@
      * @return the string buffer.
      * @throws IllegalArgumentException
      *             if {@code object} is not an instance of {@code Number}.
-     * @since Android 1.0
      */
     @Override
     public StringBuffer format(Object object, StringBuffer buffer,
@@ -348,7 +316,6 @@
      * Gets the list of installed locales which support {@code NumberFormat}.
      * 
      * @return an array of locales.
-     * @since Android 1.0
      */
     public static Locale[] getAvailableLocales() {
         return Locale.getAvailableLocales();
@@ -365,7 +332,6 @@
      * @return the currency that was set in getInstance() or in setCurrency(),
      *         or {@code null}.
      * @throws UnsupportedOperationException
-     * @since Android 1.0
      */
     public Currency getCurrency() {
         throw new UnsupportedOperationException();
@@ -376,7 +342,6 @@
      * for the default locale.
      * 
      * @return a {@code NumberFormat} for handling currency values.
-     * @since Android 1.0
      */
     public final static NumberFormat getCurrencyInstance() {
         return getCurrencyInstance(Locale.getDefault());
@@ -389,10 +354,11 @@
      * @param locale
      *            the locale to use.
      * @return a {@code NumberFormat} for handling currency values.
-     * @since Android 1.0
      */
     public static NumberFormat getCurrencyInstance(Locale locale) {
+        // BEGIN android-changed
         return getInstance(locale, "Currency"); //$NON-NLS-1$
+        // END android-changed
     }
 
     /**
@@ -400,7 +366,6 @@
      * default locale.
      * 
      * @return a {@code NumberFormat} for handling integers.
-     * @since Android 1.0
      */
     public final static NumberFormat getIntegerInstance() {
         return getIntegerInstance(Locale.getDefault());
@@ -413,12 +378,13 @@
      * @param locale
      *            the locale to use.
      * @return a {@code NumberFormat} for handling integers.
-     * @since Android 1.0
      */
     public static NumberFormat getIntegerInstance(Locale locale) {
+        // BEGIN android-changed
         NumberFormat format = getInstance(locale, "Integer"); //$NON-NLS-1$
         format.setParseIntegerOnly(true);
         return format;
+        // END android-changed
     }
 
     /**
@@ -426,7 +392,6 @@
      * default locale.
      * 
      * @return a {@code NumberFormat} for handling {@code Number} objects.
-     * @since Android 1.0
      */
     public final static NumberFormat getInstance() {
         return getNumberInstance();
@@ -439,16 +404,17 @@
      * @param locale
      *            the locale to use.
      * @return a {@code NumberFormat} for handling {@code Number} objects.
-     * @since Android 1.0
      */
     public static NumberFormat getInstance(Locale locale) {
         return getNumberInstance(locale);
     }
 
+    // BEGIN android-added
     static NumberFormat getInstance(Locale locale, String type) {
         return new DecimalFormat(getPattern(locale, type),
                 new DecimalFormatSymbols(locale));
     }
+    // END android-added
 
     /**
      * Returns the maximum number of fraction digits that are printed when
@@ -456,7 +422,6 @@
      * the least significant digits are truncated.
      * 
      * @return the maximum number of fraction digits.
-     * @since Android 1.0
      */
     public int getMaximumFractionDigits() {
         return maximumFractionDigits;
@@ -468,7 +433,6 @@
      * most significant digits are truncated.
      * 
      * @return the maximum number of integer digits.
-     * @since Android 1.0
      */
     public int getMaximumIntegerDigits() {
         return maximumIntegerDigits;
@@ -479,7 +443,6 @@
      * formatting.
      * 
      * @return the minimum number of fraction digits.
-     * @since Android 1.0
      */
     public int getMinimumFractionDigits() {
         return minimumFractionDigits;
@@ -490,7 +453,6 @@
      * formatting.
      * 
      * @return the minimum number of integer digits.
-     * @since Android 1.0
      */
     public int getMinimumIntegerDigits() {
         return minimumIntegerDigits;
@@ -501,7 +463,6 @@
      * default locale.
      * 
      * @return a {@code NumberFormat} for handling {@code Number} objects.
-     * @since Android 1.0
      */
     public final static NumberFormat getNumberInstance() {
         return getNumberInstance(Locale.getDefault());
@@ -514,23 +475,25 @@
      * @param locale
      *            the locale to use.
      * @return a {@code NumberFormat} for handling {@code Number} objects.
-     * @since Android 1.0
      */
     public static NumberFormat getNumberInstance(Locale locale) {
+        // BEGIN android-changed
         return getInstance(locale, "Number"); //$NON-NLS-1$
+        // END android-changed
     }
 
+    // BEGIN android-added
     static String getPattern(Locale locale, String type) {
         ResourceBundle bundle = getBundle(locale);
         return bundle.getString(type);
     }
+    // END android-added
 
     /**
      * Returns a {@code NumberFormat} for formatting and parsing percentage
      * values for the default locale.
      * 
      * @return a {@code NumberFormat} for handling percentage values.
-     * @since Android 1.0
      */
     public final static NumberFormat getPercentInstance() {
         return getPercentInstance(Locale.getDefault());
@@ -543,10 +506,11 @@
      * @param locale
      *            the locale to use.
      * @return a {@code NumberFormat} for handling percentage values.
-     * @since Android 1.0
      */
     public static NumberFormat getPercentInstance(Locale locale) {
+        // BEGIN android-changed
         return getInstance(locale, "Percent"); //$NON-NLS-1$
+        // END android-changed
     }
 
     @Override
@@ -562,7 +526,6 @@
      * 
      * @return {@code true} if a grouping separator is used; {@code false}
      *         otherwise.
-     * @since Android 1.0
      */
     public boolean isGroupingUsed() {
         return groupingUsed;
@@ -574,7 +537,6 @@
      * 
      * @return {@code true} if this number format only parses integers,
      *         {@code false} if if parsese integers as well as fractions.
-     * @since Android 1.0
      */
     public boolean isParseIntegerOnly() {
         return parseIntegerOnly;
@@ -587,9 +549,8 @@
      * @param string
      *            the string to parse.
      * @return the {@code Number} resulting from the parsing.
-     * @exception ParseException
-     *                if an error occurs during parsing.
-     * @since Android 1.0
+     * @throws ParseException
+     *            if an error occurs during parsing.
      */
     public Number parse(String string) throws ParseException {
         ParsePosition pos = new ParsePosition(0);
@@ -617,7 +578,6 @@
      *            set to the index where the error occurred.
      * @return the {@code Number} resulting from the parse or {@code null} if
      *         there is an error.
-     * @since Android 1.0
      */
     public abstract Number parse(String string, ParsePosition position);
 
@@ -642,12 +602,10 @@
      * This implementation throws {@code UnsupportedOperationException},
      * concrete subclasses should override this method if they support currency
      * formatting.
-     * </p>
-     * 
+     *
      * @param currency
      *            the new currency.
      * @throws UnsupportedOperationException
-     * @since Android 1.0
      */
     public void setCurrency(Currency currency) {
         throw new UnsupportedOperationException();
@@ -660,7 +618,6 @@
      * @param value
      *            {@code true} if a grouping separator is used; {@code false}
      *            otherwise.
-     * @since Android 1.0
      */
     public void setGroupingUsed(boolean value) {
         groupingUsed = value;
@@ -673,7 +630,6 @@
      * 
      * @param value
      *            the maximum number of fraction digits.
-     * @since Android 1.0
      */
     public void setMaximumFractionDigits(int value) {
         maximumFractionDigits = value < 0 ? 0 : value;
@@ -689,7 +645,6 @@
      * 
      * @param value
      *            the new maximum number of integer numerals for display.
-     * @since Android 1.0
      */
     public void setMaximumIntegerDigits(int value) {
         maximumIntegerDigits = value < 0 ? 0 : value;
@@ -704,7 +659,6 @@
      * 
      * @param value
      *            the minimum number of fraction digits.
-     * @since Android 1.0
      */
     public void setMinimumFractionDigits(int value) {
         minimumFractionDigits = value < 0 ? 0 : value;
@@ -719,7 +673,6 @@
      * 
      * @param value
      *            the minimum number of integer digits.
-     * @since Android 1.0
      */
     public void setMinimumIntegerDigits(int value) {
         minimumIntegerDigits = value < 0 ? 0 : value;
@@ -737,7 +690,6 @@
      * @param value
      *            {@code true} to only parse integers, {@code false} to parse
      *            integers as well as fractions.
-     * @since Android 1.0
      */
     public void setParseIntegerOnly(boolean value) {
         parseIntegerOnly = value;
@@ -824,8 +776,6 @@
      * There is no public constructor in this class, the only instances are the
      * constants defined here.
      * <p>
-     * 
-     * @since Android 1.0
      */
     public static class Field extends Format.Field {
 
@@ -833,90 +783,67 @@
 
         /**
          * This constant stands for the number sign.
-         * 
-         * @since Android 1.0
          */
         public static final Field SIGN = new Field("sign"); //$NON-NLS-1$
 
         /**
          * This constant stands for the integer part of the number.
-         * 
-         * @since Android 1.0
          */
         public static final Field INTEGER = new Field("integer"); //$NON-NLS-1$
 
         /**
          * This constant stands for the fraction part of the number.
-         * 
-         * @since Android 1.0
          */
         public static final Field FRACTION = new Field("fraction"); //$NON-NLS-1$
 
         /**
          * This constant stands for the exponent part of the number.
-         * 
-         * @since Android 1.0
          */
         public static final Field EXPONENT = new Field("exponent"); //$NON-NLS-1$
 
         /**
          * This constant stands for the exponent sign symbol.
-         * 
-         * @since Android 1.0
          */
         public static final Field EXPONENT_SIGN = new Field("exponent sign"); //$NON-NLS-1$
 
         /**
          * This constant stands for the exponent symbol.
-         * 
-         * @since Android 1.0
          */
         public static final Field EXPONENT_SYMBOL = new Field("exponent symbol"); //$NON-NLS-1$
 
         /**
          * This constant stands for the decimal separator.
-         * 
-         * @since Android 1.0
          */
         public static final Field DECIMAL_SEPARATOR = new Field(
                 "decimal separator"); //$NON-NLS-1$
 
         /**
          * This constant stands for the grouping separator.
-         * 
-         * @since Android 1.0
          */
         public static final Field GROUPING_SEPARATOR = new Field(
                 "grouping separator"); //$NON-NLS-1$
 
         /**
          * This constant stands for the percent symbol.
-         * 
-         * @since Android 1.0
          */
         public static final Field PERCENT = new Field("percent"); //$NON-NLS-1$
 
         /**
          * This constant stands for the permille symbol.
-         * 
-         * @since Android 1.0
          */
         public static final Field PERMILLE = new Field("per mille"); //$NON-NLS-1$
 
         /**
          * This constant stands for the currency symbol.
-         * 
-         * @since Android 1.0
          */
         public static final Field CURRENCY = new Field("currency"); //$NON-NLS-1$
 
         /**
          * Constructs a new instance of {@code NumberFormat.Field} with the
          * given field name.
-         * 
+         *
          * @param fieldName
          *            the field name.
-         * @since Android 1.0
          */
         protected Field(String fieldName) {
             super(fieldName);
@@ -925,7 +852,7 @@
         /**
          * Resolves instances that are deserialized to the constant
          * {@code NumberFormat.Field} values.
-         * 
+         *
          * @return the resolved field object.
          * @throws InvalidObjectException
          *             if an error occurs while resolving the field object.
diff --git a/libcore/text/src/main/java/java/text/ParseException.java b/libcore/text/src/main/java/java/text/ParseException.java
index 5218462..b5a9c62 100644
--- a/libcore/text/src/main/java/java/text/ParseException.java
+++ b/libcore/text/src/main/java/java/text/ParseException.java
@@ -19,8 +19,6 @@
 
 /**
  * Thrown when the string being parsed is not in the correct form.
- * 
- * @since Android 1.0
  */
 public class ParseException extends Exception {
 
@@ -36,7 +34,6 @@
      *            the detail message for this exception.
      * @param location
      *            the index at which the parse exception occurred.
-     * @since Android 1.0
      */
     public ParseException(String detailMessage, int location) {
         super(detailMessage);
@@ -47,7 +44,6 @@
      * Returns the index at which this parse exception occurred.
      * 
      * @return the location of this exception in the parsed string.
-     * @since Android 1.0
      */
     public int getErrorOffset() {
         return errorOffset;
diff --git a/libcore/text/src/main/java/java/text/ParsePosition.java b/libcore/text/src/main/java/java/text/ParsePosition.java
index c3d1001..c643df9 100644
--- a/libcore/text/src/main/java/java/text/ParsePosition.java
+++ b/libcore/text/src/main/java/java/text/ParsePosition.java
@@ -21,8 +21,6 @@
  * Tracks the current position in a parsed string. In case of an error the error
  * index can be set to the position where the error occurred without having to
  * change the parse position.
- * 
- * @since Android 1.0
  */
 public class ParsePosition {
 
@@ -33,7 +31,6 @@
      * 
      * @param index
      *            the index to begin parsing.
-     * @since Android 1.0
      */
     public ParsePosition(int index) {
         currentPosition = index;
@@ -50,7 +47,6 @@
      * @return {@code true} if the specified object is equal to this
      *         {@code ParsePosition}; {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -66,7 +62,6 @@
      * Returns the index at which the parse could not continue.
      * 
      * @return the index of the parse error or -1 if there is no error.
-     * @since Android 1.0
      */
     public int getErrorIndex() {
         return errorIndex;
@@ -76,7 +71,6 @@
      * Returns the current parse position.
      * 
      * @return the current position.
-     * @since Android 1.0
      */
     public int getIndex() {
         return currentPosition;
@@ -92,7 +86,6 @@
      * 
      * @param index
      *            the index of the parse error.
-     * @since Android 1.0
      */
     public void setErrorIndex(int index) {
         errorIndex = index;
@@ -103,7 +96,6 @@
      * 
      * @param index
      *            the current parse position.
-     * @since Android 1.0
      */
     public void setIndex(int index) {
         currentPosition = index;
@@ -113,7 +105,6 @@
      * Returns the string representation of this parse position.
      * 
      * @return the string representation of this parse position.
-     * @since Android 1.0
      */
     @Override
     public String toString() {
diff --git a/libcore/text/src/main/java/java/text/RuleBasedCollator.java b/libcore/text/src/main/java/java/text/RuleBasedCollator.java
index 41a51e2..1a3bab7 100644
--- a/libcore/text/src/main/java/java/text/RuleBasedCollator.java
+++ b/libcore/text/src/main/java/java/text/RuleBasedCollator.java
@@ -15,17 +15,7 @@
  * limitations under the License.
  */
 
-/**
-*******************************************************************************
-* Copyright (C) 1996-2007, International Business Machines Corporation and    *
-* others. All Rights Reserved.                                                *
-*******************************************************************************
-*/
-
 // BEGIN android-note
-// The class javadoc and some of the method descriptions are copied from ICU4J
-// source files. Changes have been made to the copied descriptions.
-// The icu license header was added to this file. 
 // The icu implementation used was changed from icu4j to icu4jni.
 // END android-note
 
@@ -38,7 +28,6 @@
  * <p>
  * {@code RuleBasedCollator} has the following restrictions for efficiency
  * (other subclasses may be used for more complex languages):
- * </p>
  * <ol>
  * <li> If a French secondary ordering is specified it applies to the whole
  * collator object.</li>
@@ -51,19 +40,17 @@
  * <p>
  * The collation table is composed of a list of collation rules, where each rule
  * is of three forms:
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * <modifier>
  * <relation> <text-argument>
  * <reset> <text-argument>
  * </pre>
- * 
+ *
  * </blockquote>
  * <p>
  * The rule elements are defined as follows:
- * </p>
  * <ul type="disc">
  * <li><strong>Text-Argument</strong>: A text-argument is any sequence of
  * characters, excluding special characters (that is, common whitespace
@@ -76,7 +63,6 @@
  * specify that all accents (secondary differences) are backwards.
  * <p>
  * '@' : Indicates that accents are sorted backwards, as in French.
- * </p>
  * </li>
  * <li><strong>Relation</strong>: The relations are the following:
  * <ul type=square>
@@ -92,33 +78,30 @@
  * <p>
  * '&' : Indicates that the next rule follows the position to where the reset
  * text-argument would be sorted.
- * </p>
  * </li>
  * </ul>
  * <p>
  * This sounds more complicated than it is in practice. For example, the
  * following are equivalent ways of expressing the same thing:
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * a < b < c
  * a < b & b < c
  * a < c & a < b
  * </pre>
- * 
+ *
  * </blockquote>
  * <p>
  * Notice that the order is important, as the subsequent item goes immediately
  * after the text-argument. The following are not equivalent:
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * a < b & a < c
  * a < c & a < b
  * </pre>
- * 
+ *
  * </blockquote>
  * <p>
  * Either the text-argument must already be present in the sequence, or some
@@ -132,7 +115,6 @@
  * German a-umlaut is treated as if it expands to two characters (expressed as
  * {@code "a,A < b,B  ... & ae;\u00e3 & AE;\u00c3"}, where \u00e3 and \u00c3
  * are the escape sequences for a-umlaut).
- * </p>
  * <h4>Ignorable Characters</h4>
  * <p>
  * For ignorable characters, the first rule must start with a relation (the
@@ -141,7 +123,6 @@
  * {@code "<"}, then all text-arguments up to the first {@code "<"} are
  * ignorable. For example, {@code ", - < a < b"} makes {@code "-"} an ignorable
  * character.
- * </p>
  * <h4>Normalization and Accents</h4>
  * <p>
  * {@code RuleBasedCollator} automatically processes its rule table to include
@@ -150,7 +131,6 @@
  * combining accent characters, the pre-composed accented characters matching
  * all canonical combinations of characters from the rule string will be entered
  * in the table.
- * </p>
  * <p>
  * This allows you to use a RuleBasedCollator to compare accented strings even
  * when the collator is set to NO_DECOMPOSITION. However, if the strings to be
@@ -158,11 +138,9 @@
  * should set the collator to CANONICAL_DECOMPOSITION to enable sorting of
  * combining sequences. For more information, see <a
  * href="http://www.aw.com/devpress">The Unicode Standard, Version 3.0</a>.
- * </p>
  * <h4>Errors</h4>
  * <p>
  * The following rules are not valid:
- * </p>
  * <ul type="disc">
  * <li>A text-argument contains unquoted punctuation symbols, for example
  * {@code "a < b-c < d"}.</li>
@@ -175,7 +153,6 @@
  * <p>
  * If you produce one of these errors, {@code RuleBasedCollator} throws a
  * {@code ParseException}.
- * </p>
  * <h4>Examples</h4>
  * <p>
  * Normally, to create a rule-based collator object, you will use
@@ -183,117 +160,109 @@
  * rule-based collator object with specialized rules tailored to your needs, you
  * construct the {@code RuleBasedCollator} with the rules contained in a
  * {@code String} object. For example:
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * String Simple = "< a < b < c < d";
- * 
+ *
  * RuleBasedCollator mySimple = new RuleBasedCollator(Simple);
  * </pre>
- * 
+ *
  * </blockquote>
  * <p>
  * Or:
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * String Norwegian = "< a,A< b,B< c,C< d,D< e,E< f,F< g,G< h,H< i,I"
- *         + "< j,J< k,K< l,L< m,M< n,N< o,O< p,P< q,Q< r,R" 
+ *         + "< j,J< k,K< l,L< m,M< n,N< o,O< p,P< q,Q< r,R"
  *         + "< s,S< t,T< u,U< v,V< w,W< x,X< y,Y< z,Z"
- *         + "< \u00E5=a\u030A,\u00C5=A\u030A" 
+ *         + "< \u00E5=a\u030A,\u00C5=A\u030A"
  *         + ";aa,AA< \u00E6,\u00C6< \u00F8,\u00D8";
- * 
+ *
  * RuleBasedCollator myNorwegian = new RuleBasedCollator(Norwegian);
  * </pre>
- * 
+ *
  * </blockquote>
  * <p>
  * Combining {@code Collator}s is as simple as concatenating strings. Here is
  * an example that combines two {@code Collator}s from two different locales:
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * // Create an en_US Collator object
  * RuleBasedCollator en_USCollator = (RuleBasedCollator)Collator
  *         .getInstance(new Locale("en", "US", ""));
- * 
+ *
  * // Create a da_DK Collator object
  * RuleBasedCollator da_DKCollator = (RuleBasedCollator)Collator
  *         .getInstance(new Locale("da", "DK", ""));
- * 
+ *
  * // Combine the two collators
  * // First, get the collation rules from en_USCollator
  * String en_USRules = en_USCollator.getRules();
- * 
+ *
  * // Second, get the collation rules from da_DKCollator
  * String da_DKRules = da_DKCollator.getRules();
- * 
+ *
  * RuleBasedCollator newCollator = new RuleBasedCollator(en_USRules + da_DKRules);
  * // newCollator has the combined rules
  * </pre>
- * 
+ *
  * </blockquote>
  * <p>
  * The next example shows to make changes on an existing table to create a new
  * {@code Collator} object. For example, add {@code "& C < ch, cH, Ch, CH"} to
  * the {@code en_USCollator} object to create your own:
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * // Create a new Collator object with additional rules
  * String addRules = "& C < ch, cH, Ch, CH";
- * 
+ *
  * RuleBasedCollator myCollator = new RuleBasedCollator(en_USCollator + addRules);
  * // myCollator contains the new rules
  * </pre>
- * 
+ *
  * </blockquote>
  * <p>
  * The following example demonstrates how to change the order of non-spacing
  * accents:
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * // old rule
  * String oldRules = "= \u00a8 ; \u00af ; \u00bf" + "< a , A ; ae, AE ; \u00e6 , \u00c6"
  *         + "< b , B < c, C < e, E & C < d, D";
- * 
+ *
  * // change the order of accent characters
  * String addOn = "& \u00bf ; \u00af ; \u00a8;";
- * 
+ *
  * RuleBasedCollator myCollator = new RuleBasedCollator(oldRules + addOn);
  * </pre>
- * 
+ *
  * </blockquote>
  * <p>
  * The last example shows how to put new primary ordering in before the default
  * setting. For example, in the Japanese {@code Collator}, you can either sort
  * English characters before or after Japanese characters:
- * </p>
  * <blockquote>
- * 
+ *
  * <pre>
  * // get en_US Collator rules
  * RuleBasedCollator en_USCollator = (RuleBasedCollator)
  *     Collator.getInstance(Locale.US);
- * 
+ *
  * // add a few Japanese character to sort before English characters
  * // suppose the last character before the first base letter 'a' in
  * // the English collation rule is \u30A2
  * String jaString = "& \u30A2 , \u30FC < \u30C8";
- * 
- * RuleBasedCollator myJapaneseCollator = 
+ *
+ * RuleBasedCollator myJapaneseCollator =
  *     new RuleBasedCollator(en_USCollator.getRules() + jaString);
  * </pre>
- * 
+ *
  * </blockquote>
- * 
- * @since Android 1.0
  */
 public class RuleBasedCollator extends Collator {
 
@@ -320,7 +289,6 @@
      * @throws ParseException
      *             if {@code rules} contains rules with invalid collation rule
      *             syntax.
-     * @since Android 1.0
      */
     public RuleBasedCollator(String rules) throws ParseException {
         if (rules == null) {
@@ -359,7 +327,6 @@
      * @param source
      *            the source character iterator.
      * @return a {@code CollationElementIterator} for {@code source}.
-     * @since Android 1.0
      */
     public CollationElementIterator getCollationElementIterator(
             CharacterIterator source) {
@@ -377,7 +344,6 @@
      * @param source
      *            the source string.
      * @return the {@code CollationElementIterator} for {@code source}.
-     * @since Android 1.0
      */
     public CollationElementIterator getCollationElementIterator(String source) {
         if (source == null) {
@@ -390,7 +356,7 @@
 
     /**
      * Returns the collation rules of this collator. These {@code rules} can be
-     * fed into the {@link #RuleBasedCollator(String)} constructor.
+     * fed into the {@code RuleBasedCollator(String)} constructor.
      * <p>
      * Note that the {@code rules} are actually interpreted as a delta to the
      * standard Unicode Collation Algorithm (UCA). Hence, an empty {@code rules}
@@ -399,7 +365,6 @@
      * specifications and may result in different behavior.
      *
      * @return the collation rules.
-     * @since Android 1.0
      */
     public String getRules() {
         return ((com.ibm.icu4jni.text.RuleBasedCollator) this.icuColl).getRules();
@@ -411,7 +376,6 @@
      * 
      * @return a shallow copy of this collator.
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -431,7 +395,6 @@
      * {@code CollationKey.compareTo(CollationKey)} for the comparisons. If each
      * string is compared to only once, using
      * {@code RuleBasedCollator.compare(String, String)} has better performance.
-     * </p>
      * 
      * @param source
      *            the source text.
@@ -440,7 +403,6 @@
      * @return an integer which may be a negative value, zero, or else a
      *         positive value depending on whether {@code source} is less than,
      *         equivalent to, or greater than {@code target}.
-     * @since Android 1.0
      */
     @Override
     public int compare(String source, String target) {
@@ -457,7 +419,6 @@
      * @param source
      *            the specified source text.
      * @return the {@code CollationKey} for the given source text.
-     * @since Android 1.0
      */
     @Override
     public CollationKey getCollationKey(String source) {
@@ -486,7 +447,6 @@
      * @return {@code true} if the specified object is equal to this
      *         {@code RuleBasedCollator}; {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object obj) {
diff --git a/libcore/text/src/main/java/java/text/SimpleDateFormat.java b/libcore/text/src/main/java/java/text/SimpleDateFormat.java
index c78f29e..52c5e1b 100644
--- a/libcore/text/src/main/java/java/text/SimpleDateFormat.java
+++ b/libcore/text/src/main/java/java/text/SimpleDateFormat.java
@@ -15,17 +15,8 @@
  * limitations under the License.
  */
 
-/**
-*******************************************************************************
-* Copyright (C) 1996-2007, International Business Machines Corporation and    *
-* others. All Rights Reserved.                                                *
-*******************************************************************************
-*/
-
 // BEGIN android-note
-// The class javadoc and some of the method descriptions are copied from ICU4J
-// source files. Changes have been made to the copied descriptions.
-// The icu license header was added to this file. 
+// changed from ICU to resource bundles and Java parsing/formatting
 // END android-note
 
 package java.text;
@@ -38,9 +29,11 @@
 import java.util.Date;
 import java.util.GregorianCalendar;
 import java.util.Locale;
+// BEGIN android-added
 import java.util.ResourceBundle;
 import java.util.SimpleTimeZone;
 import java.util.TimeZone;
+// END android-added
 import java.util.Vector;
 
 import org.apache.harmony.text.internal.nls.Messages;
@@ -58,13 +51,11 @@
  * default format pattern. You may modify the format pattern using the {@code
  * applyPattern} methods as desired. For more information on using these
  * methods, see {@link DateFormat}.
- * </p>
  * <h4>Time Format Syntax</h4>
  * <p>
  * To specify the time format, use a <em>time pattern</em> string. In this
  * pattern, all ASCII letters are reserved as pattern letters, which are defined
  * as follows:
- * </p>
  * <table border=0 cellspacing=3 cellpadding=0>
  * <tr bgcolor="#ccccff">
  * <th>Symbol</th>
@@ -217,7 +208,6 @@
  * <strong>(Text)</strong>: 4 or more pattern letters &rarr; use the full form,
  * less than 4 pattern letters &rarr; use a short or abbreviated form if one
  * exists.
- * </p>
  * <p>
  * <strong>(Number)</strong>: the minimum number of digits. Shorter numbers are
  * zero-padded to this amount. Year is handled specially; that is, if the count
@@ -225,18 +215,15 @@
  * "1997", "yy" produces "97".) Unlike other fields, fractional seconds are
  * padded on the right with zero.
  * <p>
- * </p>
  * <strong>(Text & Number)</strong>: 3 or over, use text, otherwise use number.
  * <p>
  * Any characters in the pattern that are not in the ranges of ['a'..'z'] and
  * ['A'..'Z'] will be treated as quoted text. For instance, characters like ':',
  * '.', ' ', '#' and '@' will appear in the resulting time text even they are
  * not embraced within single quotes.
- * </p>
  * <p>
  * A pattern containing any invalid pattern letter will result in an exception
  * thrown during formatting or parsing.
- * </p>
  * <h4>Examples Using the US Locale</h4> <blockquote>
  * 
  * <pre>
@@ -275,7 +262,6 @@
  * am/pm marker 'a' is left out from the format pattern while the
  * "hour in am/pm" pattern symbol is used. This information loss can happen when
  * formatting the time in PM.
- * </p>
  * <p>
  * When parsing a date string using the abbreviated year pattern ("yy"), {@code
  * SimpleDateFormat} must interpret the abbreviated year relative to some
@@ -291,12 +277,10 @@
  * example, "-1"), is interpreted literally. So "01/02/3" or "01/02/003" are
  * parsed, using the same pattern, as Jan 2, 3 AD. Likewise, "01/02/-3" is
  * parsed as Jan 2, 4 BC.
- * </p>
  * <p>
  * If the year pattern does not have exactly two 'y' characters, the year is
  * interpreted literally, regardless of the number of digits. So using the
  * pattern "MM/dd/yyyy", "01/11/12" parses to Jan 11, 12 A.D.
- * </p>
  * <p>
  * When numeric fields are adjacent directly, with no intervening delimiter
  * characters, they constitute a run of adjacent numeric fields. Such runs are
@@ -308,11 +292,9 @@
  * parsed again. This is repeated until either the parse succeeds or the
  * leftmost field is one character in length. If the parse still fails at that
  * point, the parse of the run fails.
- * </p>
  * <p>
  * For time zones that have no names, use the strings "GMT+hours:minutes" or
  * "GMT-hours:minutes".
- * </p>
  * <p>
  * The calendar defines the first day of the week, the first week of the year,
  * whether hours are zero based or not (0 vs. 12 or 24) and the time zone. There
@@ -324,17 +306,19 @@
  * 
  * @see Calendar
  * @see GregorianCalendar
- * @see TimeZone
+ * @see java.util.TimeZone
  * @see DateFormat
  * @see DateFormatSymbols
  * @see DecimalFormat
- * @since Android 1.0
  */
 public class SimpleDateFormat extends DateFormat {
 
     private static final long serialVersionUID = 4774881970558875024L;
 
+    // BEGIN android-changed
+    // private static final String patternChars = "GyMdkHmsSEDFwWahKzYeugAZvcLQqV"; //$NON-NLS-1$
     private static final String patternChars = "GyMdkHmsSEDFwWahKzZ"; //$NON-NLS-1$
+    // END android-changed
 
     private String pattern;
 
@@ -344,15 +328,21 @@
 
     private Date defaultCenturyStart;
 
+    // BEGIN android-removed
+    // private transient String tzId;
+    //
+    // private transient com.ibm.icu.text.SimpleDateFormat icuFormat;
+    // END android-removed
+
     /**
      * Constructs a new {@code SimpleDateFormat} for formatting and parsing
      * dates and times in the {@code SHORT} style for the default locale.
-     * 
-     * @since Android 1.0
      */
     public SimpleDateFormat() {
         this(Locale.getDefault());
+        // BEGIN android-changed
         pattern = defaultPattern();
+        // END android-changed
         formatData = new DateFormatSymbols(Locale.getDefault());
     }
 
@@ -363,35 +353,133 @@
      * 
      * @param pattern
      *            the pattern.
-     * @exception IllegalArgumentException
-     *                if {@code pattern} is not considered to be usable by this
-     *                formatter.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *            if the pattern is {@code null}.
+     * @throws IllegalArgumentException
+     *            if {@code pattern} is not considered to be usable by this
+     *            formatter.
      */
     public SimpleDateFormat(String pattern) {
         this(pattern, Locale.getDefault());
     }
+    
+    /**
+     * Validates the format character.
+     *
+     * @param format
+     *            the format character
+     *
+     * @throws IllegalArgumentException
+     *             when the format character is invalid
+     */
+    private void validateFormat(char format) {
+        int index = patternChars.indexOf(format);
+        if (index == -1) {
+            // text.03=Unknown pattern character - '{0}'
+            throw new IllegalArgumentException(Messages.getString(
+                    "text.03", format)); //$NON-NLS-1$
+        }
+    }
 
     /**
+     * Validates the pattern.
+     *
+     * @param template
+     *            the pattern to validate.
+     *
+     * @throws NullPointerException
+     *             if the pattern is null
+     * @throws IllegalArgumentException
+     *             if the pattern is invalid
+     */
+    private void validatePattern(String template) {
+        boolean quote = false;
+        int next, last = -1, count = 0;
+
+        final int patternLength = template.length();
+        for (int i = 0; i < patternLength; i++) {
+            next = (template.charAt(i));
+            if (next == '\'') {
+                if (count > 0) {
+                    validateFormat((char) last);
+                    count = 0;
+                }
+                if (last == next) {
+                    last = -1;
+                } else {
+                    last = next;
+                }
+                quote = !quote;
+                continue;
+            }
+            if (!quote
+                    && (last == next || (next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z'))) {
+                if (last == next) {
+                    count++;
+                } else {
+                    if (count > 0) {
+                        validateFormat((char) last);
+                    }
+                    last = next;
+                    count = 1;
+                }
+            } else {
+                if (count > 0) {
+                    validateFormat((char) last);
+                    count = 0;
+                }
+                last = -1;
+            }
+        }
+        if (count > 0) {
+            validateFormat((char) last);
+        }
+
+        if (quote) {
+            // text.04=Unterminated quote {0}
+            throw new IllegalArgumentException(Messages.getString("text.04")); //$NON-NLS-1$
+        }
+
+    }
+    
+    /**
      * Constructs a new {@code SimpleDateFormat} using the specified
      * non-localized pattern and {@code DateFormatSymbols} and the {@code
      * Calendar} for the default locale.
-     * 
+     *
      * @param template
      *            the pattern.
      * @param value
      *            the DateFormatSymbols.
-     * @exception IllegalArgumentException
-     *                if the pattern is invalid.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *            if the pattern is {@code null}.
+     * @throws IllegalArgumentException
+     *            if the pattern is invalid.
      */
     public SimpleDateFormat(String template, DateFormatSymbols value) {
         this(Locale.getDefault());
         validatePattern(template);
+        // BEGIN android-removed
+        // icuFormat = new com.ibm.icu.text.SimpleDateFormat(template, Locale.getDefault());
+        // icuFormat.setTimeZone(com.ibm.icu.util.TimeZone.getTimeZone(tzId));
+        // END android-removed
         pattern = template;
         formatData = (DateFormatSymbols) value.clone();
     }
 
+    // BEGIN android-removed
+    // private void copySymbols(DateFormatSymbols value, com.ibm.icu.text.DateFormatSymbols icuSymbols) {
+    //     icuSymbols.setAmPmStrings(value.getAmPmStrings());
+    //     icuSymbols.setEras(value.getEras());
+    //     icuSymbols.setLocalPatternChars(value.getLocalPatternChars());
+    //     icuSymbols.setMonths(value.getMonths());
+    //     icuSymbols.setShortMonths(value.getShortMonths());
+    //     icuSymbols.setShortWeekdays(value.getShortWeekdays());
+    //     icuSymbols.setWeekdays(value.getWeekdays());
+    //     icuSymbols.setZoneStrings(value.getZoneStrings());
+    // }
+    // END android-removed
+
     /**
      * Constructs a new {@code SimpleDateFormat} using the specified
      * non-localized pattern and the {@code DateFormatSymbols} and {@code
@@ -401,27 +489,299 @@
      *            the pattern.
      * @param locale
      *            the locale.
-     * @exception IllegalArgumentException
-     *                if the pattern is invalid.
-     * @since Android 1.0
+     * @throws NullPointerException
+     *            if the pattern is {@code null}.
+     * @throws IllegalArgumentException
+     *            if the pattern is invalid.
      */
     public SimpleDateFormat(String template, Locale locale) {
         this(locale);
         validatePattern(template);
+        // BEGIN android-removed
+        // icuFormat = new com.ibm.icu.text.SimpleDateFormat(template, locale);
+        // icuFormat.setTimeZone(com.ibm.icu.util.TimeZone.getTimeZone(tzId));
+        // END android-removed
         pattern = template;
+        // BEGIN android-changed
         formatData = new DateFormatSymbols(locale);
+        // END android-changed
     }
 
+    // BEGIN android-removed
+    // SimpleDateFormat(Locale locale, com.ibm.icu.text.SimpleDateFormat icuFormat){
+    //     this(locale);
+    //     this.icuFormat = icuFormat;
+    //     this.icuFormat.setTimeZone(com.ibm.icu.util.TimeZone.getTimeZone(tzId));
+    //     pattern = (String)Format.getInternalField("pattern", icuFormat); //$NON-NLS-1$
+    //     formatData = new DateFormatSymbols(locale);
+    // }
+    // END android-removed
+    
     private SimpleDateFormat(Locale locale) {
         numberFormat = NumberFormat.getInstance(locale);
         numberFormat.setParseIntegerOnly(true);
         numberFormat.setGroupingUsed(false);
         calendar = new GregorianCalendar(locale);
         calendar.add(Calendar.YEAR, -80);
+        // BEGIN android-removed
+        // tzId = calendar.getTimeZone().getID();
+        // END android-removed
         creationYear = calendar.get(Calendar.YEAR);
         defaultCenturyStart = calendar.getTime();
     }
 
+    /**
+     * Changes the pattern of this simple date format to the specified pattern
+     * which uses localized pattern characters.
+     * 
+     * @param template
+     *            the localized pattern.
+     */
+    public void applyLocalizedPattern(String template) {
+        // BEGIN android-changed
+        pattern = convertPattern(template, formatData.getLocalPatternChars(),
+                patternChars, true);
+        // END android-changed
+    }
+
+    /**
+     * Changes the pattern of this simple date format to the specified pattern
+     * which uses non-localized pattern characters.
+     * 
+     * @param template
+     *            the non-localized pattern.
+     * @throws NullPointerException
+     *                if the pattern is {@code null}.
+     * @throws IllegalArgumentException
+     *                if the pattern is invalid.
+     */
+    public void applyPattern(String template) {
+        validatePattern(template);
+        // BEGIN android-removed
+        // /*
+        //  * ICU spec explicitly mentions that "ICU interprets a single 'y'
+        //  * differently than Java." We need to do a trick here to follow Java
+        //  * spec.
+        //  */
+        // String templateForICU = patternForICU(template);
+        // icuFormat.applyPattern(templateForICU);
+        // END android-removed
+        pattern = template;
+    }
+
+    /**
+     * Converts the Java-spec pattern into an equivalent pattern used by ICU.
+     * 
+     * @param p
+     *            the Java-spec style pattern.
+     * @return the ICU-style pattern.
+     */
+    @SuppressWarnings("nls")
+    private String patternForICU(String p) {
+        String[] subPatterns = p.split("'");
+        boolean quote = false;
+        boolean first = true;
+        StringBuilder result = new StringBuilder();
+        for (String subPattern : subPatterns) {
+            if (!quote) {
+                // replace 'y' with 'yy' for ICU to follow Java spec
+                result.append((first ? "" : "'")
+                        + subPattern.replaceAll("(?<!y)y(?!y)", "yy"));
+                first = false;
+            } else {
+                result.append("'" + subPattern);
+            }
+            quote = !quote;
+        }
+        if (p.endsWith("'")) {
+            result.append("'");
+        }
+        return result.toString();
+    }
+
+    /**
+     * Returns a new {@code SimpleDateFormat} with the same pattern and
+     * properties as this simple date format.
+     * 
+     * @return a shallow copy of this simple date format.
+     * @see java.lang.Cloneable
+     */
+    @Override
+    public Object clone() {
+        SimpleDateFormat clone = (SimpleDateFormat) super.clone();
+        clone.formatData = (DateFormatSymbols) formatData.clone();
+        clone.defaultCenturyStart = new Date(defaultCenturyStart.getTime());
+        // BEGIN android-removed
+        // clone.tzId = tzId;
+        // END android-removed
+        return clone;
+    }
+
+    // BEGIN android-added
+    private static String defaultPattern() {
+        ResourceBundle bundle = getBundle(Locale.getDefault());
+        String styleName = getStyleName(SHORT);
+        return bundle.getString("Date_" + styleName) + " " //$NON-NLS-1$ //$NON-NLS-2$
+                + bundle.getString("Time_" + styleName); //$NON-NLS-1$
+    }
+    // END android-added
+
+    /**
+     * Compares the specified object with this simple date format and indicates
+     * if they are equal. In order to be equal, {@code object} must be an
+     * instance of {@code SimpleDateFormat} and have the same {@code DateFormat}
+     * properties, pattern, {@code DateFormatSymbols} and creation year.
+     * 
+     * @param object
+     *            the object to compare with this object.
+     * @return {@code true} if the specified object is equal to this simple date
+     *         format; {@code false} otherwise.
+     * @see #hashCode
+     */
+    @Override
+    public boolean equals(Object object) {
+        if (this == object) {
+            return true;
+        }
+        if (!(object instanceof SimpleDateFormat)) {
+            return false;
+        }
+        SimpleDateFormat simple = (SimpleDateFormat) object;
+        return super.equals(object) && pattern.equals(simple.pattern)
+                && formatData.equals(simple.formatData);
+    }
+
+    /**
+     * Formats the specified object using the rules of this simple date format
+     * and returns an {@code AttributedCharacterIterator} with the formatted
+     * date and attributes.
+     * 
+     * @param object
+     *            the object to format.
+     * @return an {@code AttributedCharacterIterator} with the formatted date
+     *         and attributes.
+     * @throws NullPointerException
+     *            if the object is {@code null}.
+     * @throws IllegalArgumentException
+     *            if the object cannot be formatted by this simple date
+     *            format.
+     */
+    @Override
+    public AttributedCharacterIterator formatToCharacterIterator(Object object) {
+        if (object == null) {
+            throw new NullPointerException();
+        }
+        if (object instanceof Date) {
+            return formatToCharacterIteratorImpl((Date) object);
+        }
+        if (object instanceof Number) {
+            return formatToCharacterIteratorImpl(new Date(((Number) object)
+                    .longValue()));
+        }
+        throw new IllegalArgumentException();
+        
+    }
+    
+    private AttributedCharacterIterator formatToCharacterIteratorImpl(Date date) {
+        StringBuffer buffer = new StringBuffer();
+        Vector<FieldPosition> fields = new Vector<FieldPosition>();
+
+        // format the date, and find fields
+        formatImpl(date, buffer, null, fields);
+
+        // create and AttributedString with the formatted buffer
+        AttributedString as = new AttributedString(buffer.toString());
+
+        // add DateFormat field attributes to the AttributedString
+        for (int i = 0; i < fields.size(); i++) {
+            FieldPosition pos = fields.elementAt(i);
+            Format.Field attribute = pos.getFieldAttribute();
+            as.addAttribute(attribute, attribute, pos.getBeginIndex(), pos
+                    .getEndIndex());
+        }
+
+        // return the CharacterIterator from AttributedString
+        return as.getIterator();
+    }
+
+    /**
+     * Formats the date.
+     * <p>
+     * If the FieldPosition {@code field} is not null, and the field
+     * specified by this FieldPosition is formatted, set the begin and end index
+     * of the formatted field in the FieldPosition.
+     * <p>
+     * If the Vector {@code fields} is not null, find fields of this
+     * date, set FieldPositions with these fields, and add them to the fields
+     * vector.
+     * 
+     * @param date
+     *            Date to Format
+     * @param buffer
+     *            StringBuffer to store the resulting formatted String
+     * @param field
+     *            FieldPosition to set begin and end index of the field
+     *            specified, if it is part of the format for this date
+     * @param fields
+     *            Vector used to store the FieldPositions for each field in this
+     *            date
+     * @return the formatted Date
+     * @throws IllegalArgumentException
+     *            if the object cannot be formatted by this Format.
+     */
+    private StringBuffer formatImpl(Date date, StringBuffer buffer,
+            FieldPosition field, Vector<FieldPosition> fields) {
+
+        boolean quote = false;
+        int next, last = -1, count = 0;
+        calendar.setTime(date);
+        if (field != null) {
+            field.clear();
+        }
+
+        final int patternLength = pattern.length();
+        for (int i = 0; i < patternLength; i++) {
+            next = (pattern.charAt(i));
+            if (next == '\'') {
+                if (count > 0) {
+                    append(buffer, field, fields, (char) last, count);
+                    count = 0;
+                }
+                if (last == next) {
+                    buffer.append('\'');
+                    last = -1;
+                } else {
+                    last = next;
+                }
+                quote = !quote;
+                continue;
+            }
+            if (!quote
+                    && (last == next || (next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z'))) {
+                if (last == next) {
+                    count++;
+                } else {
+                    if (count > 0) {
+                        append(buffer, field, fields, (char) last, count);
+                    }
+                    last = next;
+                    count = 1;
+                }
+            } else {
+                if (count > 0) {
+                    append(buffer, field, fields, (char) last, count);
+                    count = 0;
+                }
+                last = -1;
+                buffer.append((char) next);
+            }
+        }
+        if (count > 0) {
+            append(buffer, field, fields, (char) last, count);
+        }
+        return buffer;
+    }
+    
     private void append(StringBuffer buffer, FieldPosition position,
             Vector<FieldPosition> fields, char format, int count) {
         int field = -1;
@@ -434,7 +794,6 @@
 
         int beginPosition = buffer.length();
         Field dateFormatField = null;
-
         switch (index) {
             case ERA_FIELD:
                 dateFormatField = Field.ERA;
@@ -528,10 +887,12 @@
                 dateFormatField = Field.TIME_ZONE;
                 appendTimeZone(buffer, count, true);
                 break;
+            // BEGIN android-changed
             case (TIMEZONE_FIELD + 1): // Z
                 dateFormatField = Field.TIME_ZONE;
                 appendTimeZone(buffer, count, false);
                 break;
+            // END android-changed
         }
         if (field != -1) {
             appendNumber(buffer, count, calendar.get(field));
@@ -552,7 +913,7 @@
             }
         }
     }
-
+    
     private void appendTimeZone(StringBuffer buffer, int count,
             boolean generalTimezone) {
         // cannot call TimeZone.getDisplayName() because it would not use
@@ -612,139 +973,13 @@
         numberFormat.setMinimumIntegerDigits(minimumIntegerDigits);
     }
 
-    /**
-     * Changes the pattern of this simple date format to the specified pattern
-     * which uses localized pattern characters.
-     * 
-     * @param template
-     *            the localized pattern.
-     * @since Android 1.0
-     */
-    public void applyLocalizedPattern(String template) {
-        pattern = convertPattern(template, formatData.getLocalPatternChars(),
-                patternChars, true);
-    }
-
-    /**
-     * Changes the pattern of this simple date format to the specified pattern
-     * which uses non-localized pattern characters.
-     * 
-     * @param template
-     *            the non-localized pattern.
-     * @exception IllegalArgumentException
-     *                if the pattern is invalid.
-     * @since Android 1.0
-     */
-    public void applyPattern(String template) {
-        validatePattern(template);
-        pattern = template;
-    }
-
-    /**
-     * Returns a new {@code SimpleDateFormat} with the same pattern and
-     * properties as this simple date format.
-     * 
-     * @return a shallow copy of this simple date format.
-     * @see java.lang.Cloneable
-     * @since Android 1.0
-     */
-    @Override
-    public Object clone() {
-        SimpleDateFormat clone = (SimpleDateFormat) super.clone();
-        clone.formatData = (DateFormatSymbols) formatData.clone();
-        clone.defaultCenturyStart = new Date(defaultCenturyStart.getTime());
-        return clone;
-    }
-
-    private static String defaultPattern() {
-        ResourceBundle bundle = getBundle(Locale.getDefault());
-        String styleName = getStyleName(SHORT);
-        return bundle.getString("Date_" + styleName) + " " //$NON-NLS-1$ //$NON-NLS-2$
-                + bundle.getString("Time_" + styleName); //$NON-NLS-1$
-    }
-
-    /**
-     * Compares the specified object with this simple date format and indicates
-     * if they are equal. In order to be equal, {@code object} must be an
-     * instance of {@code SimpleDateFormat} and have the same {@code DateFormat}
-     * properties, pattern, {@code DateFormatSymbols} and creation year.
-     * 
-     * @param object
-     *            the object to compare with this object.
-     * @return {@code true} if the specified object is equal to this simple date
-     *         format; {@code false} otherwise.
-     * @see #hashCode
-     * @since Android 1.0
-     */
-    @Override
-    public boolean equals(Object object) {
-        if (this == object) {
-            return true;
-        }
-        if (!(object instanceof SimpleDateFormat)) {
-            return false;
-        }
-        SimpleDateFormat simple = (SimpleDateFormat) object;
-        return super.equals(object) && pattern.equals(simple.pattern)
-                && formatData.equals(simple.formatData);
-    }
-
+    // BEGIN android-added
     private Date error(ParsePosition position, int offset, TimeZone zone) {
         position.setErrorIndex(offset);
         calendar.setTimeZone(zone);
         return null;
     }
-
-    /**
-     * Formats the specified object using the rules of this simple date format
-     * and returns an {@code AttributedCharacterIterator} with the formatted
-     * date and attributes.
-     * 
-     * @param object
-     *            the object to format.
-     * @return an {@code AttributedCharacterIterator} with the formatted date
-     *         and attributes.
-     * @exception IllegalArgumentException
-     *                when the object cannot be formatted by this simple date
-     *                format.
-     * @since Android 1.0
-     */
-    @Override
-    public AttributedCharacterIterator formatToCharacterIterator(Object object) {
-        if (object == null) {
-            throw new NullPointerException();
-        }
-        if (object instanceof Date) {
-            return formatToCharacterIteratorImpl((Date) object);
-        }
-        if (object instanceof Number) {
-            return formatToCharacterIteratorImpl(new Date(((Number) object)
-                    .longValue()));
-        }
-        throw new IllegalArgumentException();
-    }
-
-    private AttributedCharacterIterator formatToCharacterIteratorImpl(Date date) {
-        StringBuffer buffer = new StringBuffer();
-        Vector<FieldPosition> fields = new Vector<FieldPosition>();
-
-        // format the date, and find fields
-        formatImpl(date, buffer, null, fields);
-
-        // create and AttributedString with the formatted buffer
-        AttributedString as = new AttributedString(buffer.toString());
-
-        // add DateFormat field attributes to the AttributedString
-        for (int i = 0; i < fields.size(); i++) {
-            FieldPosition pos = fields.elementAt(i);
-            Format.Field attribute = pos.getFieldAttribute();
-            as.addAttribute(attribute, attribute, pos.getBeginIndex(), pos
-                    .getEndIndex());
-        }
-
-        // return the CharacterIterator from AttributedString
-        return as.getIterator();
-    }
+    // END android-added
 
     /**
      * Formats the specified date as a string using the pattern of this date
@@ -754,191 +989,39 @@
      * a format field, then its {@code beginIndex} and {@code endIndex} members
      * will be updated with the position of the first occurrence of this field
      * in the formatted text.
-     * </p>
-     * 
+     *
      * @param date
      *            the date to format.
      * @param buffer
      *            the target string buffer to append the formatted date/time to.
-     * @param field
+     * @param fieldPos
      *            on input: an optional alignment field; on output: the offsets
      *            of the alignment field in the formatted text.
      * @return the string buffer.
      * @throws IllegalArgumentException
      *             if there are invalid characters in the pattern.
-     * @since Android 1.0
      */
     @Override
     public StringBuffer format(Date date, StringBuffer buffer,
-            FieldPosition field) {
-        return formatImpl(date, buffer, field, null);
+            FieldPosition fieldPos) {
+        // BEGIN android-changed
+        // Harmony delegates to ICU's SimpleDateFormat, we implement it directly
+        return formatImpl(date, buffer, fieldPos, null);
+        // END android-changed
     }
 
-    /**
-     * Validates the format character.
-     * 
-     * @param format
-     *            the format character
-     * 
-     * @throws IllegalArgumentException
-     *             when the format character is invalid
-     */
-    private void validateFormat(char format) {
-        int index = patternChars.indexOf(format);
-        if (index == -1) {
-            // text.03=Unknown pattern character - '{0}'
-            throw new IllegalArgumentException(Messages.getString(
-                    "text.03", format)); //$NON-NLS-1$
-        }
-    }
+    // BEGIN android-removed
+    // private com.ibm.icu.text.DateFormat.Field toICUField(
+    //         DateFormat.Field attribute) {
+    //     ...
+    // }
+    // END android-removed
 
     /**
-     * Validates the pattern.
-     * 
-     * @param template
-     *            the pattern to validate.
-     * 
-     * @throws NullPointerException
-     *             if the pattern is null
-     * @throws IllegalArgumentException
-     *             if the pattern is invalid
-     */
-    private void validatePattern(String template) {
-        boolean quote = false;
-        int next, last = -1, count = 0;
-
-        final int patternLength = template.length();
-        for (int i = 0; i < patternLength; i++) {
-            next = (template.charAt(i));
-            if (next == '\'') {
-                if (count > 0) {
-                    validateFormat((char) last);
-                    count = 0;
-                }
-                if (last == next) {
-                    last = -1;
-                } else {
-                    last = next;
-                }
-                quote = !quote;
-                continue;
-            }
-            if (!quote
-                    && (last == next || (next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z'))) {
-                if (last == next) {
-                    count++;
-                } else {
-                    if (count > 0) {
-                        validateFormat((char) last);
-                    }
-                    last = next;
-                    count = 1;
-                }
-            } else {
-                if (count > 0) {
-                    validateFormat((char) last);
-                    count = 0;
-                }
-                last = -1;
-            }
-        }
-        if (count > 0) {
-            validateFormat((char) last);
-        }
-
-        if (quote) {
-            // text.04=Unterminated quote {0}
-            throw new IllegalArgumentException(Messages.getString("text.04")); //$NON-NLS-1$
-        }
-
-    }
-
-    /**
-     * Formats the date.
-     * <p>
-     * If the FieldPosition {@code field} is not null, and the field
-     * specified by this FieldPosition is formatted, set the begin and end index
-     * of the formatted field in the FieldPosition.
-     * <p>
-     * If the Vector {@code fields} is not null, find fields of this
-     * date, set FieldPositions with these fields, and add them to the fields
-     * vector.
-     * 
-     * @param date
-     *            Date to Format
-     * @param buffer
-     *            StringBuffer to store the resulting formatted String
-     * @param field
-     *            FieldPosition to set begin and end index of the field
-     *            specified, if it is part of the format for this date
-     * @param fields
-     *            Vector used to store the FieldPositions for each field in this
-     *            date
-     * 
-     * @return the formatted Date
-     * 
-     * @exception IllegalArgumentException
-     *                when the object cannot be formatted by this Format
-     */
-    private StringBuffer formatImpl(Date date, StringBuffer buffer,
-            FieldPosition field, Vector<FieldPosition> fields) {
-
-        boolean quote = false;
-        int next, last = -1, count = 0;
-        calendar.setTime(date);
-        if (field != null) {
-            field.clear();
-        }
-
-        final int patternLength = pattern.length();
-        for (int i = 0; i < patternLength; i++) {
-            next = (pattern.charAt(i));
-            if (next == '\'') {
-                if (count > 0) {
-                    append(buffer, field, fields, (char) last, count);
-                    count = 0;
-                }
-                if (last == next) {
-                    buffer.append('\'');
-                    last = -1;
-                } else {
-                    last = next;
-                }
-                quote = !quote;
-                continue;
-            }
-            if (!quote
-                    && (last == next || (next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z'))) {
-                if (last == next) {
-                    count++;
-                } else {
-                    if (count > 0) {
-                        append(buffer, field, fields, (char) last, count);
-                    }
-                    last = next;
-                    count = 1;
-                }
-            } else {
-                if (count > 0) {
-                    append(buffer, field, fields, (char) last, count);
-                    count = 0;
-                }
-                last = -1;
-                buffer.append((char) next);
-            }
-        }
-        if (count > 0) {
-            append(buffer, field, fields, (char) last, count);
-        }
-        return buffer;
-    }
-
-    /**
-     * Returns the date which is the start of the one hundred year period for
+     * Answers the Date which is the start of the one hundred year period for
      * two digits year values.
      * 
-     * @return a date.
-     * @since Android 1.0
+     * @return a Date
      */
     public Date get2DigitYearStart() {
         return defaultCenturyStart;
@@ -946,9 +1029,8 @@
 
     /**
      * Returns the {@code DateFormatSymbols} used by this simple date format.
-     * 
+     *
      * @return the {@code DateFormatSymbols} object.
-     * @since Android 1.0
      */
     public DateFormatSymbols getDateFormatSymbols() {
         // Return a clone so the arrays in the ResourceBundle are not modified
@@ -961,6 +1043,7 @@
                 + creationYear;
     }
 
+    // BEGIN android-added
     private int parse(String string, int offset, char format, int count) {
         int index = patternChars.indexOf(format);
         if (index == -1) {
@@ -1085,6 +1168,7 @@
         }
         return offset;
     }
+    // END android-added
 
     /**
      * Parses a date from the specified string starting at the index specified
@@ -1092,7 +1176,7 @@
      * of the {@code ParsePosition} is updated to the index following the parsed
      * text. On error, the index is unchanged and the error index of {@code
      * ParsePosition} is set to the index where the error occurred.
-     * 
+     *
      * @param string
      *            the string to parse using the pattern of this simple date
      *            format.
@@ -1106,10 +1190,11 @@
      *         error.
      * @throws IllegalArgumentException
      *             if there are invalid characters in the pattern.
-     * @since Android 1.0
      */
     @Override
     public Date parse(String string, ParsePosition position) {
+        // BEGIN android-changed
+        // Harmony delegates to ICU's SimpleDateFormat, we implement it directly
         boolean quote = false;
         int next, last = -1, count = 0, offset = position.getIndex();
         int length = string.length();
@@ -1178,8 +1263,10 @@
         position.setIndex(offset);
         calendar.setTimeZone(zone);
         return date;
+        // END android-changed
     }
 
+    // BEGIN android-added
     private Number parseNumber(int max, String string, ParsePosition position) {
         int digit, length = string.length(), result = 0;
         int index = position.getIndex();
@@ -1299,6 +1386,7 @@
         }
         return -offset - 1;
     }
+    // END android-added
 
     /**
      * Sets the date which is the start of the one hundred year period for two
@@ -1306,9 +1394,11 @@
      * 
      * @param date
      *            the new date.
-     * @since Android 1.0
      */
     public void set2DigitYearStart(Date date) {
+        // BEGIN android-removed
+        // icuFormat.set2DigitYearStart(date);
+        // END android-removed
         defaultCenturyStart = date;
         Calendar cal = new GregorianCalendar();
         cal.setTime(date);
@@ -1320,9 +1410,13 @@
      * 
      * @param value
      *            the new {@code DateFormatSymbols} object.
-     * @since Android 1.0
      */
     public void setDateFormatSymbols(DateFormatSymbols value) {
+        // BEGIN android-removed
+        // com.ibm.icu.text.DateFormatSymbols icuSymbols = new com.ibm.icu.text.DateFormatSymbols();
+        // copySymbols(value, icuSymbols);
+        // icuFormat.setDateFormatSymbols(icuSymbols);
+        // END android-removed
         formatData = (DateFormatSymbols) value.clone();
     }
 
@@ -1331,11 +1425,12 @@
      * characters.
      * 
      * @return the localized pattern.
-     * @since Android 1.0
      */
     public String toLocalizedPattern() {
+        // BEGIN android-changed
         return convertPattern(pattern, patternChars, formatData
                 .getLocalPatternChars(), false);
+        // END android-changed
     }
 
     /**
@@ -1343,7 +1438,6 @@
      * pattern characters.
      * 
      * @return the non-localized pattern.
-     * @since Android 1.0
      */
     public String toPattern() {
         return pattern;
diff --git a/libcore/text/src/main/java/java/text/StringCharacterIterator.java b/libcore/text/src/main/java/java/text/StringCharacterIterator.java
index 5d02ceb..8ef0341 100644
--- a/libcore/text/src/main/java/java/text/StringCharacterIterator.java
+++ b/libcore/text/src/main/java/java/text/StringCharacterIterator.java
@@ -19,8 +19,6 @@
 
 /**
  * An implementation of {@link CharacterIterator} for strings.
- * 
- * @since Android 1.0
  */
 public final class StringCharacterIterator implements CharacterIterator {
 
@@ -35,7 +33,6 @@
      * 
      * @param value
      *            the source string to iterate over.
-     * @since Android 1.0
      */
     public StringCharacterIterator(String value) {
         string = value;
@@ -53,10 +50,9 @@
      *            the source string to iterate over.
      * @param location
      *            the current index.
-     * @exception IllegalArgumentException
-     *                if {@code location} is negative or greater than the length
-     *                of the source string.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *            if {@code location} is negative or greater than the length
+     *            of the source string.
      */
     public StringCharacterIterator(String value, int location) {
         string = value;
@@ -80,11 +76,10 @@
      *            the index one past the last character to iterate.
      * @param location
      *            the current index.
-     * @exception IllegalArgumentException
-     *                if {@code start < 0}, {@code start > end},
-     *                {@code location < start}, {@code location > end} or if
-     *                {@code end} is greater than the length of {@code value}.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *            if {@code start < 0}, {@code start > end}, {@code location <
+     *            start}, {@code location > end} or if {@code end} is greater
+     *            than the length of {@code value}.
      */
     public StringCharacterIterator(String value, int start, int end,
             int location) {
@@ -104,7 +99,6 @@
      * 
      * @return a shallow copy of this iterator.
      * @see java.lang.Cloneable
-     * @since Android 1.0
      */
     @Override
     public Object clone() {
@@ -120,7 +114,6 @@
      * 
      * @return the current character, or {@code DONE} if the current index is
      *         past the end.
-     * @since Android 1.0
      */
     public char current() {
         if (offset == end) {
@@ -140,7 +133,6 @@
      * @return {@code true} if the specified object is equal to this
      *         {@code StringCharacterIterator}; {@code false} otherwise.
      * @see #hashCode
-     * @since Android 1.0
      */
     @Override
     public boolean equals(Object object) {
@@ -158,7 +150,6 @@
      * 
      * @return the character at the begin index or {@code DONE} if the begin
      *         index is equal to the end index.
-     * @since Android 1.0
      */
     public char first() {
         if (start == end) {
@@ -172,7 +163,6 @@
      * Returns the begin index in the source string.
      * 
      * @return the index of the first character of the iteration.
-     * @since Android 1.0
      */
     public int getBeginIndex() {
         return start;
@@ -182,7 +172,6 @@
      * Returns the end index in the source string.
      * 
      * @return the index one past the last character of the iteration.
-     * @since Android 1.0
      */
     public int getEndIndex() {
         return end;
@@ -192,7 +181,6 @@
      * Returns the current index in the source string.
      * 
      * @return the current index.
-     * @since Android 1.0
      */
     public int getIndex() {
         return offset;
@@ -209,9 +197,8 @@
      * 
      * @return the character before the end index or {@code DONE} if the begin
      *         index is equal to the end index.
-     * @since Android 1.0
      */
-   public char last() {
+    public char last() {
         if (start == end) {
             return DONE;
         }
@@ -219,14 +206,13 @@
         return string.charAt(offset);
     }
 
-   /**
-    * Increments the current index and returns the character at the new index.
-    * 
-    * @return the character at the next index, or {@code DONE} if the next
-    *         index would be past the end.
-    * @since Android 1.0
-    */
-   public char next() {
+    /**
+     * Increments the current index and returns the character at the new index.
+     *
+     * @return the character at the next index, or {@code DONE} if the next
+     *         index would be past the end.
+     */
+    public char next() {
         if (offset >= (end - 1)) {
             offset = end;
             return DONE;
@@ -234,13 +220,12 @@
         return string.charAt(++offset);
     }
 
-   /**
-    * Decrements the current index and returns the character at the new index.
-    * 
-    * @return the character at the previous index, or {@code DONE} if the
-    *         previous index would be past the beginning.
-    * @since Android 1.0
-    */
+    /**
+     * Decrements the current index and returns the character at the new index.
+     * 
+     * @return the character at the previous index, or {@code DONE} if the
+     *         previous index would be past the beginning.
+     */
     public char previous() {
         if (offset == start) {
             return DONE;
@@ -255,10 +240,9 @@
      *            the index the current position is set to.
      * @return the character at the new index, or {@code DONE} if
      *         {@code location} is set to the end index.
-     * @exception IllegalArgumentException
-     *                if {@code location} is smaller than the begin index or
-     *                greater than the end index.
-     * @since Android 1.0
+     * @throws IllegalArgumentException
+     *            if {@code location} is smaller than the begin index or greater
+     *            than the end index.
      */
     public char setIndex(int location) {
         if (location < start || location > end) {
@@ -277,7 +261,6 @@
      * 
      * @param value
      *            the new source string.
-     * @since Android 1.0
      */
     public void setText(String value) {
         string = value;
diff --git a/libcore/text/src/main/java/org/apache/harmony/text/BidiWrapper.java b/libcore/text/src/main/java/org/apache/harmony/text/BidiWrapper.java
index 240fcdf..f9dc8da 100644
--- a/libcore/text/src/main/java/org/apache/harmony/text/BidiWrapper.java
+++ b/libcore/text/src/main/java/org/apache/harmony/text/BidiWrapper.java
@@ -18,7 +18,8 @@
 package org.apache.harmony.text;
 
 /**
- * TODO: type description
+ * Dalvik Bidi wrapper. Derived from an old version of Harmony; today they call
+ * straight through to ICU4J.
  */
 
 public final class BidiWrapper {
diff --git a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/BidiTest.java b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/BidiTest.java
index e3ea9dc..deef841 100644
--- a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/BidiTest.java
+++ b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/BidiTest.java
@@ -1757,8 +1757,13 @@
             // Expected
         }
 
-// Outsourced to _AndroidFailure:
-//        bidi.createLineBidi(2, 2);
+        // BEGIN android-removed
+        // Outsourced to _AndroidFailure:
+        // try {
+        //     bidi.createLineBidi(2, 2);
+        // } catch (IllegalArgumentException expected) {
+        // }
+        // END android-removed
 
         try {
             bidi.createLineBidi(2, 4);
@@ -1974,19 +1979,23 @@
 
     @TestTargetNew(
         level = TestLevel.PARTIAL_COMPLETE,
-        notes = "Doesn't verify any int value between 0 and getRunCount().",
+        notes = "",
         method = "getRunLimit",
         args = {int.class}
     )
+    @KnownFailure("Doesn't verify any int value between 0 and getRunCount().")
     public void testGetRunLimit() {
         bd = new Bidi("text", Bidi.DIRECTION_LEFT_TO_RIGHT);
         try {
             assertTrue(4 == bd.getRunLimit(-1));
-        } catch (Exception e) {
-            fail("Unexpected exception: " + e);
+        } catch (IllegalArgumentException e) {
+            // Expected for illegal run limit
+            return;
         }
+
+        fail("Expected IllegalArgumentException to be thrown for invalid run limit");
     }
-    
+
     @TestTargetNew(
         level = TestLevel.COMPLETE,
         notes = "",
@@ -2052,13 +2061,17 @@
         method = "Bidi",
         args = {java.text.AttributedCharacterIterator.class}
     )
+    @KnownFailure("Doesn't verify any int value between 0 and getRunCount().")
     public void testBidiConstructor_Iterator() {
         AttributedString paragraph = new AttributedString("text");
         bd = new Bidi(paragraph.getIterator());
         try {
             assertTrue(4 == bd.getRunLimit(1));
-        } catch (Exception e) {
-            fail("Unexpected exception: " + e);
+        } catch (IllegalArgumentException e) {
+            // Expected for illegal run limit
+            return;
         }
+
+        fail("Expected IllegalArgumentException to be thrown for invalid run limit");
     }
 }
diff --git a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DataFormatFieldTest.java b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DataFormatFieldTest.java
index ff05e64..ff6dd8e 100644
--- a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DataFormatFieldTest.java
+++ b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DataFormatFieldTest.java
@@ -207,7 +207,6 @@
         method = "readResolve",
         args = {}
     )
-    @KnownFailure("readResolve does not work properly")
     public void test_readResolve() {
         // test for method java.lang.Object readResolve()
 
diff --git a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DateFormatSymbolsTest.java b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DateFormatSymbolsTest.java
index 4151dc8..a0d9615 100644
--- a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DateFormatSymbolsTest.java
+++ b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DateFormatSymbolsTest.java
@@ -16,11 +16,14 @@
  */
 package org.apache.harmony.text.tests.java.text;
 
-import dalvik.annotation.TestTargets;
 import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
 import java.text.DateFormatSymbols;
 import java.util.Arrays;
 import java.util.Locale;
@@ -42,11 +45,7 @@
     public void test_Constructor() {
         // Test for method java.text.DateFormatSymbols()
         // Used in tests
-        try {
-            new DateFormatSymbols();
-        } catch (Exception e) {
-            fail("Constructor failed.");
-        }
+        new DateFormatSymbols();
     }
 
     /**
@@ -60,11 +59,7 @@
     )
     public void test_ConstructorLjava_util_Locale() {
         // Test for method java.text.DateFormatSymbols(java.util.Locale)
-        try {
-            new DateFormatSymbols(new Locale("en", "us"));
-        } catch (Exception e) {
-            fail("Constructor failed.");
-        }
+        new DateFormatSymbols(new Locale("en", "us"));
     }
 
     /**
@@ -156,8 +151,10 @@
         String retVal = dfs.getLocalPatternChars();
 
         String val = "GyMdkHmsSEDFwWahKzZ";
+        // Harmony uses a different set of pattern chars
+        // String val = "GyMdkHmsSEDFwWahKzYeugAZvcLQqV";
 
-        assertTrue("Returned incorrect pattern string", retVal.equals(val));
+        assertEquals("Returned incorrect pattern string", val, retVal);
     }
 
     /**
@@ -175,9 +172,9 @@
         String[] retVal = dfs.getMonths();
         String[] val = { "January", "February", "March", "April", "May",
                 "June", "July", "August", "September", "October", "November",
-                "December", "" };
-        if (retVal.length != val.length)
-            fail("Returned wrong array: " + retVal.length);
+                "December", ""};
+        // Note: Harmony doesn't include "" at the end of the array
+        assertEquals("Returned wrong array: ", val.length, retVal.length);
         for (int i = 0; i < val.length; i++)
             assertTrue("Array values do not match", retVal[i].equals(val[i]));
     }
@@ -196,9 +193,9 @@
         // java.text.DateFormatSymbols.getShortMonths()
         String[] retVal = dfs.getShortMonths();
         String[] val = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
-                "Aug", "Sep", "Oct", "Nov", "Dec", "" };
-        if (retVal.length != val.length)
-            fail("Returned wrong array");
+                "Aug", "Sep", "Oct", "Nov", "Dec", ""};
+        // Note: Harmony doesn't include "" at the end of the array
+        assertEquals("Returned wrong array: ", val.length, retVal.length);
         for (int i = 0; i < val.length; i++)
             assertTrue("Array values do not match", retVal[i].equals(val[i]));
     }
@@ -482,4 +479,32 @@
      */
     protected void tearDown() {
     }
+
+    @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            notes = "Checks serialization mechanism.",
+            method = "!SerializationSelf",
+            args = {}
+    )
+    public void test_serialization() throws Exception {
+        DateFormatSymbols symbols = new DateFormatSymbols(Locale.FRANCE);
+        String[][] zoneStrings = symbols.getZoneStrings();
+        assertNotNull(zoneStrings);
+
+        // serialize
+        ByteArrayOutputStream byteOStream = new ByteArrayOutputStream();
+        ObjectOutputStream objectOStream = new ObjectOutputStream(byteOStream);
+        objectOStream.writeObject(symbols);
+
+        // and deserialize
+        ObjectInputStream objectIStream = new ObjectInputStream(
+                new ByteArrayInputStream(byteOStream.toByteArray()));
+        DateFormatSymbols symbolsD = (DateFormatSymbols) objectIStream
+                .readObject();
+
+        // The associated currency will not persist
+        String[][] zoneStringsD = symbolsD.getZoneStrings();
+        assertNotNull(zoneStringsD);
+        assertEquals(symbols, symbolsD);
+    }
 }
diff --git a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DateFormatTest.java b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DateFormatTest.java
index e70aaf2..e7609a8 100644
--- a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DateFormatTest.java
+++ b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DateFormatTest.java
@@ -1079,4 +1079,43 @@
             fail("Unexpected exception " + e.toString());
         }
     }
+
+    /**
+     * @tests java.text.DateFormat#parse(String)
+     */
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "",
+            method = "parse",
+            args = {java.lang.String.class}
+    )
+    public void test_parse_LString() {
+        DateFormat format = DateFormat.getInstance();
+        try {
+            format.parse("not a Date");
+            fail("should throw ParseException first");
+        } catch (ParseException e) {
+            assertNotNull(e.getMessage());
+        }
+    }
+
+    /**
+     * @tests java.text.DateFormat#setLenient(boolean)
+     */
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "",
+            method = "setLenient",
+            args = {boolean.class}
+    )
+    public void test_setLenient() {
+        Date d = null;
+        DateFormat output = new SimpleDateFormat("MM/dd/yy");
+        output.setLenient(false);
+        try {
+            d = output.parse("01/01/-1");
+            fail("Should throw ParseException here.");
+        } catch (ParseException e) {}
+    }
+
 }
diff --git a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatSymbolsTest.java b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatSymbolsTest.java
index ce2e6d5..47107cd 100644
--- a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatSymbolsTest.java
+++ b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/DecimalFormatSymbolsTest.java
@@ -149,8 +149,8 @@
     @KnownFailure("some locales were removed last minute in cupcake")
     public void test_getCurrency() {
         Currency currency = Currency.getInstance("USD");
-        assertTrue("Returned incorrect currency",
-                dfsUS.getCurrency() == currency);
+        assertEquals("Returned incorrect currency",
+                dfsUS.getCurrency(), currency);
 
         // use cs_CZ instead
         //Currency currK = Currency.getInstance("KRW");
@@ -446,8 +446,8 @@
         dfs.setCurrency(currency);
 
         assertTrue("Returned incorrect currency", currency == dfs.getCurrency());
-        assertTrue("Returned incorrect currency symbol", currency.getSymbol(
-                locale).equals(dfs.getCurrencySymbol()));
+        assertEquals("Returned incorrect currency symbol", currency.getSymbol(
+                locale), dfs.getCurrencySymbol());
         assertTrue("Returned incorrect international currency symbol", currency
                 .getCurrencyCode().equals(dfs.getInternationalCurrencySymbol()));
     }
@@ -551,8 +551,8 @@
 
         assertTrue("Test1: Returned incorrect currency", currency == dfs
                 .getCurrency());
-        assertTrue("Test1: Returned incorrect currency symbol", currency
-                .getSymbol(locale).equals(dfs.getCurrencySymbol()));
+        assertEquals("Test1: Returned incorrect currency symbol", currency
+                .getSymbol(locale), dfs.getCurrencySymbol());
         assertTrue("Test1: Returned incorrect international currency symbol",
                 currency.getCurrencyCode().equals(
                         dfs.getInternationalCurrencySymbol()));
@@ -754,8 +754,43 @@
                     i.close();
                 }
             } catch (Exception e) {
-                // ignore
             }
         }
+        assertDecimalFormatSymbolsRIFrance(dfs);
+    }
+    
+    static void assertDecimalFormatSymbolsRIFrance(DecimalFormatSymbols dfs) {
+        // Values based on Java 1.5 RI DecimalFormatSymbols for Locale.FRANCE
+        /*
+         * currency = [EUR]
+         * currencySymbol = [€][U+20ac]
+         * decimalSeparator = [,][U+002c]
+         * digit = [#][U+0023]
+         * groupingSeparator = [ ][U+00a0]
+         * infinity = [∞][U+221e]
+         * internationalCurrencySymbol = [EUR]
+         * minusSign = [-][U+002d]
+         * monetaryDecimalSeparator = [,][U+002c]
+         * naN = [�][U+fffd]
+         * patternSeparator = [;][U+003b]
+         * perMill = [‰][U+2030]
+         * percent = [%][U+0025]
+         * zeroDigit = [0][U+0030]
+         */
+        assertEquals("EUR", dfs.getCurrency().getCurrencyCode());
+        assertEquals("\u20AC", dfs.getCurrencySymbol());
+        assertEquals(',', dfs.getDecimalSeparator());
+        assertEquals('#', dfs.getDigit());
+        assertEquals('\u00a0', dfs.getGroupingSeparator());
+        assertEquals("\u221e", dfs.getInfinity());
+        assertEquals("EUR", dfs.getInternationalCurrencySymbol());
+        assertEquals('-', dfs.getMinusSign());
+        assertEquals(',', dfs.getMonetaryDecimalSeparator());
+        // RI's default NaN is U+FFFD, Harmony's is based on ICU
+        assertEquals("\uFFFD", dfs.getNaN());
+        assertEquals('\u003b', dfs.getPatternSeparator());
+        assertEquals('\u2030', dfs.getPerMill());
+        assertEquals('%', dfs.getPercent());
+        assertEquals('0', dfs.getZeroDigit());
     }
 }
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 a802ad8..aa36abc 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
@@ -31,6 +31,7 @@
 import tests.support.Support_DecimalFormat;
 
 import java.io.ObjectInputStream;
+import java.io.IOException;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.text.AttributedCharacterIterator;
@@ -40,6 +41,7 @@
 import java.text.NumberFormat;
 import java.text.ParseException;
 import java.text.ParsePosition;
+import java.util.BitSet;
 import java.util.Currency;
 import java.util.Locale;
 
@@ -1495,7 +1497,7 @@
                 .t_format_with_FieldPosition();
 
         int failCount = 0;
-        Support_BitSet failures = new Support_BitSet();
+        BitSet failures = new BitSet();
 
         final DecimalFormatSymbols dfs = new DecimalFormatSymbols(Locale.US);
 
@@ -1729,7 +1731,7 @@
     @KnownFailure("Something seems wrong with Android implementation, here!")
     public void test_formatJLjava_lang_StringBufferLjava_text_FieldPosition() {
         int failCount = 0;
-        Support_BitSet failures = new Support_BitSet();
+        BitSet failures = new BitSet();
 
         final DecimalFormatSymbols dfs = new DecimalFormatSymbols(Locale.US);
 
@@ -2437,7 +2439,7 @@
         args = {}
     )
     @KnownFailure("a regression. This didn't fail before")
-    public void test_serializationHarmonyRICompatible() {
+    public void test_serializationHarmonyRICompatible() throws Exception {
         NumberFormat nf = NumberFormat.getInstance(Locale.FRANCE);
 
         DecimalFormat df = null;
@@ -2455,8 +2457,6 @@
             oinput = new ObjectInputStream(this.getClass().getResource(
                     "/serialization/java/text/DecimalFormat.ser").openStream());
             deserializedDF = (DecimalFormat) oinput.readObject();
-        } catch (Exception e) {
-            fail("Error occurs during deserialization");
         } finally {
             try {
                 if (null != oinput) {
@@ -2473,8 +2473,7 @@
         assertEquals(df.getPositiveSuffix(), deserializedDF.getPositiveSuffix());
         assertEquals(df.getCurrency(), deserializedDF.getCurrency());
 
-        assertEquals(df.getDecimalFormatSymbols(), deserializedDF
-                .getDecimalFormatSymbols());
+        DecimalFormatSymbolsTest.assertDecimalFormatSymbolsRIFrance(deserializedDF.getDecimalFormatSymbols());
 
         assertEquals(df.getGroupingSize(), df.getGroupingSize());
         assertEquals(df.getMaximumFractionDigits(), deserializedDF
@@ -2545,11 +2544,7 @@
     )
     public void testSetDecimalFormatSymbolsAsNull() {
         // Regression for HARMONY-1070
-        try {
-            DecimalFormat format = (DecimalFormat) DecimalFormat.getInstance();
-            format.setDecimalFormatSymbols(null);
-        } catch (Exception e) {
-            fail("Unexpected exception caught: " + e);
-        }
+        DecimalFormat format = (DecimalFormat) DecimalFormat.getInstance();
+        format.setDecimalFormatSymbols(null);
     }
 }
diff --git a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/MessageFormatTest.java b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/MessageFormatTest.java
index 0265a51..57a1206 100644
--- a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/MessageFormatTest.java
+++ b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/MessageFormatTest.java
@@ -145,22 +145,15 @@
         assertEquals("Simple string", "Test message", new MessageFormat(
                 "Test message").format(new Object[0]));
 
-        try {
-            result = new MessageFormat("Don't").format(new Object[0]);
-            assertTrue("Should not throw IllegalArgumentException: " + result,
+        result = new MessageFormat("Don't").format(new Object[0]);
+        assertTrue("Should not throw IllegalArgumentException: " + result,
                     "Dont".equals(result));
-        } catch (Exception e) {
-            fail("Unexpected exception: " + e);
-        }
 
         try {
             new MessageFormat("Invalid {1,foobar} format descriptor!");
             fail("Expected test_ConstructorLjava_lang_String to throw IAE.");
         } catch (IllegalArgumentException ex) {
             // expected
-        } catch (Throwable ex) {
-            fail("Expected test_ConstructorLjava_lang_String to throw IAE, not a "
-                    + ex.getClass().getName());
         }
 
         try {
@@ -168,9 +161,6 @@
                     "Invalid {1,date,invalid-spec} format descriptor!");
         } catch (IllegalArgumentException ex) {
             // expected
-        } catch (Throwable ex) {
-            fail("Expected test_ConstructorLjava_lang_String to throw IAE, not a "
-                    + ex.getClass().getName());
         }
 
         checkSerialization(new MessageFormat(""));
@@ -1177,10 +1167,10 @@
      *        java.text.MessageFormat#parse(java.lang.String).
      */
     @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "parse",
-        args = {java.lang.String.class}
+            level = TestLevel.COMPLETE,
+            notes = "",
+            method = "parse",
+            args = {java.lang.String.class}
     )
     public void test_parseLjava_lang_String() throws ParseException {
         String pattern = "A {3, number, currency} B {2, time} C {0, number, percent} D {4}  E {1,choice,0#off|1#on} F {0, date}";
@@ -1242,10 +1232,10 @@
      *        argument ParsePosition as null.
      */
     @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "parseObject",
-        args = {java.lang.String.class, java.text.ParsePosition.class}
+            level = TestLevel.COMPLETE,
+            notes = "",
+            method = "parseObject",
+            args = {java.lang.String.class, java.text.ParsePosition.class}
     )
     public void test_parseObjectLjava_lang_StringLjavajava_text_ParsePosition() {
         MessageFormat mf = new MessageFormat("{0,number,#.##}, {0,number,#.#}");
@@ -1288,10 +1278,10 @@
         }
     }
     @TestTargetNew(
-        level = TestLevel.PARTIAL,
-        notes = "Regression test. Doesn't verifies exception.",
-        method = "format",
-        args = {java.lang.Object.class}
+            level = TestLevel.PARTIAL,
+            notes = "Regression test. Doesn't verifies exception.",
+            method = "format",
+            args = {java.lang.Object.class}
     )
     public void test_format_Object() {
         // Regression for HARMONY-1875
@@ -1304,4 +1294,35 @@
         assertEquals(etalon, obj.format(new Object[] { new Date() }));
     }
 
+    /**
+     * @tests java.text.MessageFormat#parse(java.lang.String)
+     */
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "",
+            method = "parse",
+            args = {java.lang.String.class}
+    )
+    public void test_parse() throws ParseException {
+        // Regression for HARMONY-63
+        MessageFormat mf = new MessageFormat("{0,number,#,####}", Locale.US);
+        Object[] res = mf.parse("1,00,00");
+        assertEquals("Assert 0: incorrect size of parsed data ", 1, res.length);
+        assertEquals("Assert 1: parsed value incorrectly", new Long(10000), (Long)res[0]);
+    }
+
+    @TestTargetNew(
+            level = TestLevel.PARTIAL_COMPLETE,
+            notes = "",
+            method = "format",
+            args = {java.lang.String.class, java.lang.Object[].class}
+    )
+    public void testHARMONY5323() {
+        Object []messageArgs = new Object[11];
+        for (int i = 0; i < messageArgs.length; i++)
+            messageArgs[i] = "dumb"+i;
+
+        String res = MessageFormat.format("bgcolor=\"{10}\"", messageArgs);
+        assertEquals(res, "bgcolor=\"dumb10\"");
+    }
 }
diff --git a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/NumberFormatTest.java b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/NumberFormatTest.java
index 93e58db..0480704 100644
--- a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/NumberFormatTest.java
+++ b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/NumberFormatTest.java
@@ -206,7 +206,7 @@
                 "#,##0;#,##0-", format.toPattern());
         assertEquals(
                 "Test8: NumberFormat.getIntegerInstance(new Locale(\"ar\", \"AE\")).format(-35.76) returned wrong value",
-                "36-", format.format(-35.76));
+                "\u0666-", format.format(-6));
         assertEquals(
                 "Test9: NumberFormat.getIntegerInstance(new Locale(\"ar\", \"AE\")).parse(\"-36-\") returned wrong number",
                 new Long(-36), format.parse("36-"));
diff --git a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/ParsePositionTest.java b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/ParsePositionTest.java
index 9c1fb21..89cb7e4 100644
--- a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/ParsePositionTest.java
+++ b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/ParsePositionTest.java
@@ -39,15 +39,10 @@
     )
     public void test_ConstructorI() {
         // Test for method java.text.ParsePosition(int)
-        try {
-            ParsePosition pp1 = new ParsePosition(Integer.MIN_VALUE);
-            assertTrue("Initialization failed.",
-                    pp1.getIndex() == Integer.MIN_VALUE);
-            assertEquals("Initialization failed.", -1, pp1.getErrorIndex());
-        } catch (Exception e) {
-            fail("Constructor failed.");
-        }
-
+        ParsePosition pp1 = new ParsePosition(Integer.MIN_VALUE);
+        assertTrue("Initialization failed.",
+                pp1.getIndex() == Integer.MIN_VALUE);
+        assertEquals("Initialization failed.", -1, pp1.getErrorIndex());
     }
 
     /**
diff --git a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/Support_DecimalFormat.java b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/Support_DecimalFormat.java
new file mode 100644
index 0000000..2fe1107
--- /dev/null
+++ b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/Support_DecimalFormat.java
@@ -0,0 +1,287 @@
+/* 
+ * 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.text.tests.java.text;
+
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.util.Locale;
+import java.util.Vector;
+
+
+public class Support_DecimalFormat extends Support_Format {
+
+	public Support_DecimalFormat(String p1) {
+		super(p1);
+	}
+
+	@Override
+    public void runTest() {
+		t_formatToCharacterIterator();
+		t_format_with_FieldPosition();
+	}
+
+	public static void main(String[] args) {
+		new Support_DecimalFormat("").runTest();
+	}
+
+	public void t_format_with_FieldPosition() {
+		DecimalFormat format = (DecimalFormat) NumberFormat
+				.getCurrencyInstance(Locale.US);
+		Number number = new Double(10000000.76);
+		String text = "$10,000,000.76";
+
+		t_FormatWithField(0, format, number, text, NumberFormat.Field.CURRENCY,
+				0, 1);
+		t_FormatWithField(1, format, number, text, NumberFormat.Field.INTEGER,
+				1, 11);
+		t_FormatWithField(2, format, number, text,
+				NumberFormat.Field.GROUPING_SEPARATOR, 3, 4);
+		t_FormatWithField(3, format, number, text,
+				NumberFormat.Field.DECIMAL_SEPARATOR, 11, 12);
+		t_FormatWithField(4, format, number, text, NumberFormat.Field.FRACTION,
+				12, 14);
+
+		// test fields that are not included in the formatted text
+		t_FormatWithField(5, format, number, text, NumberFormat.Field.SIGN, 0,
+				0);
+		t_FormatWithField(6, format, number, text, NumberFormat.Field.EXPONENT,
+				0, 0);
+		t_FormatWithField(7, format, number, text,
+				NumberFormat.Field.EXPONENT_SIGN, 0, 0);
+		t_FormatWithField(8, format, number, text,
+				NumberFormat.Field.EXPONENT_SYMBOL, 0, 0);
+		t_FormatWithField(9, format, number, text, NumberFormat.Field.PERCENT,
+				0, 0);
+		t_FormatWithField(10, format, number, text,
+				NumberFormat.Field.PERMILLE, 0, 0);
+
+		// test Exponential
+		format = new DecimalFormat("000000000.0#E0");
+		text = "100000007.6E-1";
+		t_FormatWithField(11, format, number, text, NumberFormat.Field.INTEGER,
+				0, 9);
+		t_FormatWithField(12, format, number, text,
+				NumberFormat.Field.DECIMAL_SEPARATOR, 9, 10);
+		t_FormatWithField(13, format, number, text,
+				NumberFormat.Field.FRACTION, 10, 11);
+		t_FormatWithField(14, format, number, text,
+				NumberFormat.Field.EXPONENT_SYMBOL, 11, 12);
+		t_FormatWithField(15, format, number, text,
+				NumberFormat.Field.EXPONENT_SIGN, 12, 13);
+		t_FormatWithField(16, format, number, text,
+				NumberFormat.Field.EXPONENT, 13, 14);
+
+		// test fields that are not included in the formatted text
+		t_FormatWithField(17, format, number, text,
+				NumberFormat.Field.GROUPING_SEPARATOR, 0, 0);
+		t_FormatWithField(18, format, number, text, NumberFormat.Field.SIGN, 0,
+				0);
+		t_FormatWithField(19, format, number, text,
+				NumberFormat.Field.CURRENCY, 0, 0);
+		t_FormatWithField(20, format, number, text, NumberFormat.Field.PERCENT,
+				0, 0);
+		t_FormatWithField(21, format, number, text,
+				NumberFormat.Field.PERMILLE, 0, 0);
+
+		// test currency instance with TR Locale
+		number = new Double(350.76);
+		format = (DecimalFormat) NumberFormat.getCurrencyInstance(new Locale(
+				"tr", "TR"));
+		text = "351 TL";
+		t_FormatWithField(22, format, number, text, NumberFormat.Field.INTEGER,
+				0, 3);
+		t_FormatWithField(23, format, number, text,
+				NumberFormat.Field.CURRENCY, 4, 6);
+
+		// test fields that are not included in the formatted text
+		t_FormatWithField(25, format, number, text,
+				NumberFormat.Field.GROUPING_SEPARATOR, 0, 0);
+		t_FormatWithField(26, format, number, text,
+				NumberFormat.Field.DECIMAL_SEPARATOR, 0, 0);
+		t_FormatWithField(27, format, number, text, NumberFormat.Field.SIGN, 0,
+				0);
+		t_FormatWithField(28, format, number, text,
+				NumberFormat.Field.EXPONENT, 0, 0);
+		t_FormatWithField(29, format, number, text,
+				NumberFormat.Field.EXPONENT_SIGN, 0, 0);
+		t_FormatWithField(30, format, number, text,
+				NumberFormat.Field.EXPONENT_SYMBOL, 0, 0);
+		t_FormatWithField(31, format, number, text, NumberFormat.Field.PERCENT,
+				0, 0);
+		t_FormatWithField(32, format, number, text,
+				NumberFormat.Field.PERMILLE, 0, 0);
+
+	}
+
+	public void t_formatToCharacterIterator() {
+
+		Number number = new Double(350.76);
+		Number negativeNumber = new Double(-350.76);
+
+		Locale us = Locale.US;
+		Locale tr = new Locale("tr", "TR");
+
+		// test number instance
+		t_Format(1, number, NumberFormat.getNumberInstance(us),
+				getNumberVectorUS());
+
+		// test integer instance
+		// testFormat(2, number, NumberFormat.getIntegerInstance(us),
+		// getPercentVectorUS());
+
+		// test percent instance
+		t_Format(3, number, NumberFormat.getPercentInstance(us),
+				getPercentVectorUS());
+
+		// test permille pattern
+		DecimalFormat format = new DecimalFormat("###0.##\u2030");
+		t_Format(4, number, format, getPermilleVector());
+
+		// test exponential pattern with positive exponent
+		format = new DecimalFormat("00.0#E0");
+		t_Format(5, number, format, getPositiveExponentVector());
+
+		// test exponential pattern with negative exponent
+		format = new DecimalFormat("0000.0#E0");
+		t_Format(6, number, format, getNegativeExponentVector());
+
+		// test currency instance with US Locale
+		t_Format(7, number, NumberFormat.getCurrencyInstance(us),
+				getPositiveCurrencyVectorUS());
+
+		// test negative currency instance with US Locale
+		t_Format(8, negativeNumber, NumberFormat.getCurrencyInstance(us),
+				getNegativeCurrencyVectorUS());
+
+		// test currency instance with TR Locale
+		t_Format(9, number, NumberFormat.getCurrencyInstance(tr),
+				getPositiveCurrencyVectorTR());
+
+		// test negative currency instance with TR Locale
+		t_Format(10, negativeNumber, NumberFormat.getCurrencyInstance(tr),
+				getNegativeCurrencyVectorTR());
+
+		// test multiple grouping seperators
+		number = new Long(100300400);
+		t_Format(11, number, NumberFormat.getNumberInstance(us),
+				getNumberVector2US());
+
+		// test 0
+		number = new Long(0);
+		t_Format(12, number, NumberFormat.getNumberInstance(us),
+				getZeroVector());
+	}
+
+	private static Vector<FieldContainer> getNumberVectorUS() {
+		Vector<FieldContainer> v = new Vector<FieldContainer>();
+		v.add(new FieldContainer(0, 3, NumberFormat.Field.INTEGER));
+		v.add(new FieldContainer(3, 4, NumberFormat.Field.DECIMAL_SEPARATOR));
+		v.add(new FieldContainer(4, 6, NumberFormat.Field.FRACTION));
+		return v;
+	}
+
+	private static Vector<FieldContainer> getPositiveCurrencyVectorTR() {
+		Vector<FieldContainer> v = new Vector<FieldContainer>();
+		v.add(new FieldContainer(0, 3, NumberFormat.Field.INTEGER));
+		v.add(new FieldContainer(4, 6, NumberFormat.Field.CURRENCY));
+		return v;
+	}
+
+	private static Vector<FieldContainer> getNegativeCurrencyVectorTR() {
+		Vector<FieldContainer> v = new Vector<FieldContainer>();
+		v.add(new FieldContainer(0, 1, NumberFormat.Field.SIGN));
+		v.add(new FieldContainer(1, 4, NumberFormat.Field.INTEGER));
+		v.add(new FieldContainer(5, 7, NumberFormat.Field.CURRENCY));
+		return v;
+	}
+
+	private static Vector<FieldContainer> getPositiveCurrencyVectorUS() {
+		Vector<FieldContainer> v = new Vector<FieldContainer>();
+		v.add(new FieldContainer(0, 1, NumberFormat.Field.CURRENCY));
+		v.add(new FieldContainer(1, 4, NumberFormat.Field.INTEGER));
+		v.add(new FieldContainer(4, 5, NumberFormat.Field.DECIMAL_SEPARATOR));
+		v.add(new FieldContainer(5, 7, NumberFormat.Field.FRACTION));
+		return v;
+	}
+
+	private static Vector<FieldContainer> getNegativeCurrencyVectorUS() {
+		Vector<FieldContainer> v = new Vector<FieldContainer>();
+		v.add(new FieldContainer(1, 2, NumberFormat.Field.CURRENCY));
+		v.add(new FieldContainer(2, 5, NumberFormat.Field.INTEGER));
+		v.add(new FieldContainer(5, 6, NumberFormat.Field.DECIMAL_SEPARATOR));
+		v.add(new FieldContainer(6, 8, NumberFormat.Field.FRACTION));
+		return v;
+	}
+
+	private static Vector<FieldContainer> getPercentVectorUS() {
+		Vector<FieldContainer> v = new Vector<FieldContainer>();
+		v.add(new FieldContainer(0, 2, NumberFormat.Field.INTEGER));
+		v.add(new FieldContainer(2, 3, NumberFormat.Field.INTEGER));
+		v.add(new FieldContainer(2, 3, NumberFormat.Field.GROUPING_SEPARATOR));
+		v.add(new FieldContainer(3, 6, NumberFormat.Field.INTEGER));
+		v.add(new FieldContainer(6, 7, NumberFormat.Field.PERCENT));
+		return v;
+	}
+
+	private static Vector<FieldContainer> getPermilleVector() {
+		Vector<FieldContainer> v = new Vector<FieldContainer>();
+		v.add(new FieldContainer(0, 6, NumberFormat.Field.INTEGER));
+		v.add(new FieldContainer(6, 7, NumberFormat.Field.PERMILLE));
+		return v;
+	}
+
+	private static Vector<FieldContainer> getNegativeExponentVector() {
+		Vector<FieldContainer> v = new Vector<FieldContainer>();
+		v.add(new FieldContainer(0, 4, NumberFormat.Field.INTEGER));
+		v.add(new FieldContainer(4, 5, NumberFormat.Field.DECIMAL_SEPARATOR));
+		v.add(new FieldContainer(5, 6, NumberFormat.Field.FRACTION));
+		v.add(new FieldContainer(6, 7, NumberFormat.Field.EXPONENT_SYMBOL));
+		v.add(new FieldContainer(7, 8, NumberFormat.Field.EXPONENT_SIGN));
+		v.add(new FieldContainer(8, 9, NumberFormat.Field.EXPONENT));
+		return v;
+	}
+
+	private static Vector<FieldContainer> getPositiveExponentVector() {
+		Vector<FieldContainer> v = new Vector<FieldContainer>();
+		v.add(new FieldContainer(0, 2, NumberFormat.Field.INTEGER));
+		v.add(new FieldContainer(2, 3, NumberFormat.Field.DECIMAL_SEPARATOR));
+		v.add(new FieldContainer(3, 5, NumberFormat.Field.FRACTION));
+		v.add(new FieldContainer(5, 6, NumberFormat.Field.EXPONENT_SYMBOL));
+		v.add(new FieldContainer(6, 7, NumberFormat.Field.EXPONENT));
+		return v;
+	}
+
+	private static Vector<FieldContainer> getNumberVector2US() {
+		Vector<FieldContainer> v = new Vector<FieldContainer>();
+		v.add(new FieldContainer(0, 3, NumberFormat.Field.INTEGER));
+		v.add(new FieldContainer(3, 4, NumberFormat.Field.GROUPING_SEPARATOR));
+		v.add(new FieldContainer(3, 4, NumberFormat.Field.INTEGER));
+		v.add(new FieldContainer(4, 7, NumberFormat.Field.INTEGER));
+		v.add(new FieldContainer(7, 8, NumberFormat.Field.GROUPING_SEPARATOR));
+		v.add(new FieldContainer(7, 8, NumberFormat.Field.INTEGER));
+		v.add(new FieldContainer(8, 11, NumberFormat.Field.INTEGER));
+		return v;
+	}
+
+	private static Vector<FieldContainer> getZeroVector() {
+		Vector<FieldContainer> v = new Vector<FieldContainer>();
+		v.add(new FieldContainer(0, 1, NumberFormat.Field.INTEGER));
+		return v;
+	}
+
+}
diff --git a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/Support_Format.java b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/Support_Format.java
new file mode 100644
index 0000000..ffcdf1c
--- /dev/null
+++ b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/Support_Format.java
@@ -0,0 +1,143 @@
+/* 
+ * 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.text.tests.java.text;
+
+import java.text.AttributedCharacterIterator;
+import java.text.FieldPosition;
+import java.text.Format;
+import java.text.AttributedCharacterIterator.Attribute;
+import java.util.Iterator;
+import java.util.Vector;
+import junit.framework.TestCase;
+
+public class Support_Format extends TestCase {
+
+	protected String text;
+
+	public Support_Format(String p1) {
+		super(p1);
+	}
+
+	protected void t_FormatWithField(int count, Format format, Object object,
+			String text, Format.Field field, int begin, int end) {
+		StringBuffer buffer = new StringBuffer();
+		FieldPosition pos = new FieldPosition(field);
+		format.format(object, buffer, pos);
+
+		// System.out.println(buffer);
+		// System.out.println(pos);
+
+		if (text == null) {
+            assertEquals("Test " + count + ": incorrect formatted text",
+					this.text, buffer.toString());
+        } else {
+            assertEquals("Test " + count + ": incorrect formatted text", text,
+					buffer.toString());
+        }
+
+		assertEquals("Test " + count + ": incorrect begin index for field "
+				+ field, begin, pos.getBeginIndex());
+		assertEquals("Test " + count + ": incorrect end index for field"
+				+ field, end, pos.getEndIndex());
+	}
+
+	protected void t_Format(int count, Object object, Format format,
+			Vector<FieldContainer> expectedResults) {
+		// System.out.println(format.format(object));
+		Vector<FieldContainer> results = findFields(format.formatToCharacterIterator(object));
+		assertTrue("Test " + count
+				+ ": Format returned incorrect CharacterIterator for "
+				+ format.format(object), compare(results, expectedResults));
+	}
+
+	/**
+	 * compares two vectors regardless of the order of their elements
+	 */
+	protected static boolean compare(Vector<FieldContainer> vector1, Vector<FieldContainer> vector2) {
+		return vector1.size() == vector2.size() && vector1.containsAll(vector2);
+	}
+
+	/**
+	 * finds attributes with regards to char index in this
+	 * AttributedCharacterIterator, and puts them in a vector
+	 * 
+	 * @param iterator
+	 * @return a vector, each entry in this vector are of type FieldContainer ,
+	 *         which stores start and end indexes and an attribute this range
+	 *         has
+	 */
+	protected static Vector<FieldContainer> findFields(AttributedCharacterIterator iterator) {
+		Vector<FieldContainer> result = new Vector<FieldContainer>();
+		while (iterator.getIndex() != iterator.getEndIndex()) {
+			int start = iterator.getRunStart();
+			int end = iterator.getRunLimit();
+
+			Iterator<Attribute> it = iterator.getAttributes().keySet().iterator();
+			while (it.hasNext()) {
+				AttributedCharacterIterator.Attribute attribute = it.next();
+				Object value = iterator.getAttribute(attribute);
+				result.add(new FieldContainer(start, end, attribute, value));
+				// System.out.println(start + " " + end + ": " + attribute + ",
+				// " + value );
+				// System.out.println("v.add(new FieldContainer(" + start +"," +
+				// end +"," + attribute+ "," + value+ "));");
+			}
+			iterator.setIndex(end);
+		}
+		return result;
+	}
+
+	protected static class FieldContainer {
+		int start, end;
+
+		AttributedCharacterIterator.Attribute attribute;
+
+		Object value;
+
+		// called from support_decimalformat and support_simpledateformat tests
+		public FieldContainer(int start, int end,
+				AttributedCharacterIterator.Attribute attribute) {
+			this(start, end, attribute, attribute);
+		}
+
+		// called from support_messageformat tests
+		public FieldContainer(int start, int end, Attribute attribute, int value) {
+			this(start, end, attribute, new Integer(value));
+		}
+
+		// called from support_messageformat tests
+		public FieldContainer(int start, int end, Attribute attribute,
+				Object value) {
+			this.start = start;
+			this.end = end;
+			this.attribute = attribute;
+			this.value = value;
+		}
+
+		@Override
+        public boolean equals(Object obj) {
+			if (!(obj instanceof FieldContainer)) {
+                return false;
+            }
+
+			FieldContainer fc = (FieldContainer) obj;
+			return (start == fc.start && end == fc.end
+					&& attribute == fc.attribute && value.equals(fc.value));
+		}
+	}
+}
diff --git a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/Support_MessageFormat.java b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/Support_MessageFormat.java
new file mode 100644
index 0000000..454caeb
--- /dev/null
+++ b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/Support_MessageFormat.java
@@ -0,0 +1,120 @@
+/* 
+ * 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.text.tests.java.text;
+
+import java.text.DateFormat;
+import java.text.MessageFormat;
+import java.text.NumberFormat;
+import java.text.MessageFormat.Field;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+import java.util.Vector;
+
+
+public class Support_MessageFormat extends Support_Format {
+
+	public Support_MessageFormat(String p1) {
+		super(p1);
+	}
+
+	@Override
+    public void runTest() {
+		t_formatToCharacterIterator();
+		t_format_with_FieldPosition();
+	}
+
+	public static void main(String[] args) {
+		new Support_MessageFormat("").runTest();
+	}
+
+	public void t_format_with_FieldPosition() {
+
+		String pattern = "On {4,date} at {3,time}, he ate {2,number, integer} hamburger{2,choice,1#|1<s} and drank {1, number} litres of coke. That was {0,choice,1#just enough|1<more than enough} food!";
+		MessageFormat format = new MessageFormat(pattern, Locale.US);
+
+		Date date = new GregorianCalendar(2005, 1, 28, 14, 20, 16).getTime();
+		Integer hamburgers = new Integer(8);
+		Object[] objects = new Object[] { hamburgers, new Double(3.5),
+				hamburgers, date, date };
+
+		super.text = "On Feb 28, 2005 at 2:20:16 PM, he ate 8 hamburgers and drank 3.5 litres of coke. That was more than enough food!";
+
+		// test with MessageFormat.Field.ARGUMENT
+		t_FormatWithField(1, format, objects, null, Field.ARGUMENT, 3, 15);
+
+		// test other format fields that are included in the formatted text
+		t_FormatWithField(2, format, objects, null, DateFormat.Field.AM_PM, 0,
+				0);
+		t_FormatWithField(3, format, objects, null,
+				NumberFormat.Field.FRACTION, 0, 0);
+
+		// test fields that are not included in the formatted text
+		t_FormatWithField(4, format, objects, null, DateFormat.Field.ERA, 0, 0);
+		t_FormatWithField(5, format, objects, null,
+				NumberFormat.Field.EXPONENT_SIGN, 0, 0);
+	}
+
+	public void t_formatToCharacterIterator() {
+
+		String pattern = "On {4,date} at {3,time}, he ate {2,number, integer} hamburger{2,choice,1#|1<s} and drank {1, number} litres of coke. That was {0,choice,1#just enough|1<more than enough} food!";
+		MessageFormat format = new MessageFormat(pattern, Locale.US);
+
+		Date date = new GregorianCalendar(2005, 1, 28, 14, 20, 16).getTime();
+		Integer hamburgers = new Integer(8);
+		Object[] objects = new Object[] { hamburgers, new Double(3.5),
+				hamburgers, date, date };
+
+		t_Format(1, objects, format, getMessageVector1());
+	}
+
+	private Vector<FieldContainer> getMessageVector1() {
+		Vector<FieldContainer> v = new Vector<FieldContainer>();
+		v.add(new FieldContainer(3, 6, Field.ARGUMENT, 4));
+		v.add(new FieldContainer(3, 6, DateFormat.Field.MONTH));
+		v.add(new FieldContainer(6, 7, Field.ARGUMENT, 4));
+		v.add(new FieldContainer(7, 9, Field.ARGUMENT, 4));
+		v.add(new FieldContainer(7, 9, DateFormat.Field.DAY_OF_MONTH));
+		v.add(new FieldContainer(9, 11, Field.ARGUMENT, 4));
+		v.add(new FieldContainer(11, 15, Field.ARGUMENT, 4));
+		v.add(new FieldContainer(11, 15, DateFormat.Field.YEAR));
+		v.add(new FieldContainer(19, 20, Field.ARGUMENT, 3));
+		v.add(new FieldContainer(19, 20, DateFormat.Field.HOUR1));
+		v.add(new FieldContainer(20, 21, Field.ARGUMENT, 3));
+		v.add(new FieldContainer(21, 23, Field.ARGUMENT, 3));
+		v.add(new FieldContainer(21, 23, DateFormat.Field.MINUTE));
+		v.add(new FieldContainer(23, 24, Field.ARGUMENT, 3));
+		v.add(new FieldContainer(24, 26, Field.ARGUMENT, 3));
+		v.add(new FieldContainer(24, 26, DateFormat.Field.SECOND));
+		v.add(new FieldContainer(26, 27, Field.ARGUMENT, 3));
+		v.add(new FieldContainer(27, 29, Field.ARGUMENT, 3));
+		v.add(new FieldContainer(27, 29, DateFormat.Field.AM_PM));
+		v.add(new FieldContainer(38, 39, Field.ARGUMENT, 2));
+		v.add(new FieldContainer(38, 39, NumberFormat.Field.INTEGER));
+		v.add(new FieldContainer(49, 50, Field.ARGUMENT, 2));
+		v.add(new FieldContainer(61, 62, Field.ARGUMENT, 1));
+		v.add(new FieldContainer(61, 62, NumberFormat.Field.INTEGER));
+		v.add(new FieldContainer(62, 63, Field.ARGUMENT, 1));
+		v.add(new FieldContainer(62, 63, NumberFormat.Field.DECIMAL_SEPARATOR));
+		v.add(new FieldContainer(63, 64, Field.ARGUMENT, 1));
+		v.add(new FieldContainer(63, 64, NumberFormat.Field.FRACTION));
+		v.add(new FieldContainer(90, 106, Field.ARGUMENT, 0));
+		return v;
+	}
+
+}
diff --git a/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/Support_SimpleDateFormat.java b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/Support_SimpleDateFormat.java
new file mode 100644
index 0000000..24a436b
--- /dev/null
+++ b/libcore/text/src/test/java/org/apache/harmony/text/tests/java/text/Support_SimpleDateFormat.java
@@ -0,0 +1,266 @@
+/* 
+ * 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.text.tests.java.text;
+
+import java.text.DateFormat;
+import java.text.NumberFormat;
+import java.text.SimpleDateFormat;
+import java.text.DateFormat.Field;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+import java.util.TimeZone;
+import java.util.Vector;
+
+import org.apache.harmony.text.tests.java.text.Support_Format.FieldContainer;
+
+
+public class Support_SimpleDateFormat extends Support_Format {
+
+	public Support_SimpleDateFormat(String p1) {
+		super(p1);
+	}
+
+	@Override
+    public void runTest() {
+		t_formatToCharacterIterator();
+		t_format_with_FieldPosition();
+	}
+
+	public static void main(String[] args) {
+		new Support_SimpleDateFormat("").runTest();
+	}
+
+	public void t_format_with_FieldPosition() {
+		TimeZone tz = TimeZone.getTimeZone("EST");
+		Calendar cal = new GregorianCalendar(tz);
+		cal.set(1999, Calendar.SEPTEMBER, 13, 17, 19, 01);
+		cal.set(Calendar.MILLISECOND, 0);
+		Date date = cal.getTime();
+		SimpleDateFormat format = (SimpleDateFormat) DateFormat
+                .getDateInstance(DateFormat.DEFAULT, Locale.US);
+		format.setTimeZone(tz);
+
+		// test with all pattern chars, and multiple occurances
+		format
+				.applyPattern("G GGGG y yy yyyy M MM MMM MMMM d dd ddd k kk kkk H HH HHH h hh hhh m mmm s ss sss S SS SSS EE EEEE D DD DDD F FF w www W WWW a  aaa  K KKK z zzzz Z ZZZZ");
+
+		StringBuffer textbuffer = new StringBuffer(
+				"AD Anno Domini 99 99 1999 9 09 Sep September 13 13 013 17 17 017 17 17 017 5 05");
+		textbuffer
+				.append(" 005 19 019 1 01 001 0 00 000 Mon Monday 256 256 256 2 02 38 038 3 003 PM");
+		textbuffer.append("  PM  5 005 GMT-05:00 GMT-05:00 -0500 GMT-05:00");
+
+		// to avoid passing the huge Stringbuffer each time.
+		super.text = textbuffer.toString();
+
+		// test if field positions are set correctly for these fields occuring
+		// multiple times.
+		t_FormatWithField(0, format, date, null, Field.ERA, 0, 2);
+		t_FormatWithField(1, format, date, null, Field.YEAR, 15, 17);
+		t_FormatWithField(2, format, date, null, Field.MONTH, 26, 27);
+		t_FormatWithField(3, format, date, null, Field.DAY_OF_MONTH, 45, 47);
+		t_FormatWithField(4, format, date, null, Field.HOUR_OF_DAY1, 55, 57);
+		t_FormatWithField(5, format, date, null, Field.HOUR_OF_DAY0, 65, 67);
+		t_FormatWithField(6, format, date, null, Field.HOUR1, 75, 76);
+		t_FormatWithField(7, format, date, null, Field.MINUTE, 84, 86);
+		t_FormatWithField(8, format, date, null, Field.SECOND, 91, 92);
+		t_FormatWithField(9, format, date, null, Field.MILLISECOND, 100, 101);
+		t_FormatWithField(10, format, date, null, Field.DAY_OF_WEEK, 109, 112);
+		t_FormatWithField(11, format, date, null, Field.DAY_OF_YEAR, 120, 123);
+		t_FormatWithField(12, format, date, null, Field.DAY_OF_WEEK_IN_MONTH,
+				132, 133);
+		t_FormatWithField(13, format, date, null, Field.WEEK_OF_YEAR, 137, 139);
+		t_FormatWithField(14, format, date, null, Field.WEEK_OF_MONTH, 144, 145);
+		t_FormatWithField(15, format, date, null, Field.AM_PM, 150, 152);
+		t_FormatWithField(16, format, date, null, Field.HOUR0, 158, 159);
+		t_FormatWithField(17, format, date, null, Field.TIME_ZONE, 164, 173);
+
+		// test fields that are not included in the formatted text
+		t_FormatWithField(18, format, date, null,
+				NumberFormat.Field.EXPONENT_SIGN, 0, 0);
+
+		// test with simple example
+		format.applyPattern("h:m z");
+
+		super.text = "5:19 GMT-05:00";
+		t_FormatWithField(21, format, date, null, Field.HOUR1, 0, 1);
+		t_FormatWithField(22, format, date, null, Field.MINUTE, 2, 4);
+		t_FormatWithField(23, format, date, null, Field.TIME_ZONE, 5, 14);
+
+		// test fields that are not included in the formatted text
+
+		t_FormatWithField(24, format, date, null, Field.ERA, 0, 0);
+		t_FormatWithField(25, format, date, null, Field.YEAR, 0, 0);
+		t_FormatWithField(26, format, date, null, Field.MONTH, 0, 0);
+		t_FormatWithField(27, format, date, null, Field.DAY_OF_MONTH, 0, 0);
+		t_FormatWithField(28, format, date, null, Field.HOUR_OF_DAY1, 0, 0);
+		t_FormatWithField(29, format, date, null, Field.HOUR_OF_DAY0, 0, 0);
+		t_FormatWithField(30, format, date, null, Field.SECOND, 0, 0);
+		t_FormatWithField(31, format, date, null, Field.MILLISECOND, 0, 0);
+		t_FormatWithField(32, format, date, null, Field.DAY_OF_WEEK, 0, 0);
+		t_FormatWithField(33, format, date, null, Field.DAY_OF_YEAR, 0, 0);
+		t_FormatWithField(34, format, date, null, Field.DAY_OF_WEEK_IN_MONTH,
+				0, 0);
+		t_FormatWithField(35, format, date, null, Field.WEEK_OF_YEAR, 0, 0);
+		t_FormatWithField(36, format, date, null, Field.WEEK_OF_MONTH, 0, 0);
+		t_FormatWithField(37, format, date, null, Field.AM_PM, 0, 0);
+		t_FormatWithField(38, format, date, null, Field.HOUR0, 0, 0);
+
+		t_FormatWithField(39, format, date, null, NumberFormat.Field.EXPONENT,
+				0, 0);
+
+		// test with simple example with pattern char Z
+		format.applyPattern("h:m Z z");
+		super.text = "5:19 -0500 GMT-05:00";
+		t_FormatWithField(40, format, date, null, Field.HOUR1, 0, 1);
+		t_FormatWithField(41, format, date, null, Field.MINUTE, 2, 4);
+		t_FormatWithField(42, format, date, null, Field.TIME_ZONE, 5, 10);
+	}
+
+	public void t_formatToCharacterIterator() {
+		TimeZone tz = TimeZone.getTimeZone("EST");
+		Calendar cal = new GregorianCalendar(tz);
+		cal.set(1999, Calendar.SEPTEMBER, 13, 17, 19, 01);
+		cal.set(Calendar.MILLISECOND, 0);
+		Date date = cal.getTime();
+		SimpleDateFormat format = (SimpleDateFormat) DateFormat
+                .getDateInstance(DateFormat.DEFAULT, Locale.US);
+		format.setTimeZone(tz);
+
+		format.applyPattern("yyyyMMddHHmmss");
+		t_Format(1, date, format, getDateVector1());
+
+		format.applyPattern("w W dd MMMM yyyy EEEE");
+		t_Format(2, date, format, getDateVector2());
+
+		format.applyPattern("h:m z");
+		t_Format(3, date, format, getDateVector3());
+
+		format.applyPattern("h:m Z");
+		t_Format(5, date, format, getDateVector5());
+
+		// with all pattern chars, and multiple occurances
+		format
+				.applyPattern("G GGGG y yy yyyy M MM MMM MMMM d dd ddd k kk kkk H HH HHH h hh hhh m mmm s ss sss S SS SSS EE EEEE D DD DDD F FF w www W WWW a  aaa  K KKK z zzzz Z ZZZZ");
+		t_Format(4, date, format, getDateVector4());
+	}
+
+	private Vector<FieldContainer> getDateVector1() {
+		// "19990913171901"
+		Vector<FieldContainer> v = new Vector<FieldContainer>();
+		v.add(new FieldContainer(0, 4, Field.YEAR));
+		v.add(new FieldContainer(4, 6, Field.MONTH));
+		v.add(new FieldContainer(6, 8, Field.DAY_OF_MONTH));
+		v.add(new FieldContainer(8, 10, Field.HOUR_OF_DAY0));
+		v.add(new FieldContainer(10, 12, Field.MINUTE));
+		v.add(new FieldContainer(12, 14, Field.SECOND));
+		return v;
+	}
+
+	private Vector<FieldContainer> getDateVector2() {
+		// "12 3 5 March 2002 Monday"
+		Vector<FieldContainer> v = new Vector<FieldContainer>();
+		v.add(new FieldContainer(0, 2, Field.WEEK_OF_YEAR));
+		v.add(new FieldContainer(3, 4, Field.WEEK_OF_MONTH));
+		v.add(new FieldContainer(5, 7, Field.DAY_OF_MONTH));
+		v.add(new FieldContainer(8, 17, Field.MONTH));
+		v.add(new FieldContainer(18, 22, Field.YEAR));
+		v.add(new FieldContainer(23, 29, Field.DAY_OF_WEEK));
+		return v;
+	}
+
+	private Vector<FieldContainer> getDateVector3() {
+		// "5:19 EDT"
+		Vector<FieldContainer> v = new Vector<FieldContainer>();
+		v.add(new FieldContainer(0, 1, Field.HOUR1));
+		v.add(new FieldContainer(2, 4, Field.MINUTE));
+		v.add(new FieldContainer(5, 14, Field.TIME_ZONE));
+		return v;
+	}
+
+	private Vector<FieldContainer> getDateVector5() {
+		// "5:19 -0400"
+		Vector<FieldContainer> v = new Vector<FieldContainer>();
+		v.add(new FieldContainer(0, 1, Field.HOUR1));
+		v.add(new FieldContainer(2, 4, Field.MINUTE));
+		v.add(new FieldContainer(5, 10, Field.TIME_ZONE));
+		return v;
+	}
+
+	private Vector<FieldContainer> getDateVector4() {
+		Vector<FieldContainer> v = new Vector<FieldContainer>();
+
+		// "AD AD 99 99 1999 9 09 Sep September 13 13 013 17 17 017 17 17 017 5
+		// 05
+		// 005 19 019 1 01 001 0 00 000 Mon Monday 256 256 256 2 02 38 038 3 003
+		// PM
+		// PM 5 005 EDT Eastern Daylight Time -0400 -0400"
+		v.add(new FieldContainer(0, 2, Field.ERA));
+		v.add(new FieldContainer(3, 5, Field.ERA));
+		v.add(new FieldContainer(6, 8, Field.YEAR));
+		v.add(new FieldContainer(9, 11, Field.YEAR));
+		v.add(new FieldContainer(12, 16, Field.YEAR));
+		v.add(new FieldContainer(17, 18, Field.MONTH));
+		v.add(new FieldContainer(19, 21, Field.MONTH));
+		v.add(new FieldContainer(22, 25, Field.MONTH));
+		v.add(new FieldContainer(26, 35, Field.MONTH));
+		v.add(new FieldContainer(36, 38, Field.DAY_OF_MONTH));
+		v.add(new FieldContainer(39, 41, Field.DAY_OF_MONTH));
+		v.add(new FieldContainer(42, 45, Field.DAY_OF_MONTH));
+		v.add(new FieldContainer(46, 48, Field.HOUR_OF_DAY1));
+		v.add(new FieldContainer(49, 51, Field.HOUR_OF_DAY1));
+		v.add(new FieldContainer(52, 55, Field.HOUR_OF_DAY1));
+		v.add(new FieldContainer(56, 58, Field.HOUR_OF_DAY0));
+		v.add(new FieldContainer(59, 61, Field.HOUR_OF_DAY0));
+		v.add(new FieldContainer(62, 65, Field.HOUR_OF_DAY0));
+		v.add(new FieldContainer(66, 67, Field.HOUR1));
+		v.add(new FieldContainer(68, 70, Field.HOUR1));
+		v.add(new FieldContainer(71, 74, Field.HOUR1));
+		v.add(new FieldContainer(75, 77, Field.MINUTE));
+		v.add(new FieldContainer(78, 81, Field.MINUTE));
+		v.add(new FieldContainer(82, 83, Field.SECOND));
+		v.add(new FieldContainer(84, 86, Field.SECOND));
+		v.add(new FieldContainer(87, 90, Field.SECOND));
+		v.add(new FieldContainer(91, 92, Field.MILLISECOND));
+		v.add(new FieldContainer(93, 95, Field.MILLISECOND));
+		v.add(new FieldContainer(96, 99, Field.MILLISECOND));
+		v.add(new FieldContainer(100, 103, Field.DAY_OF_WEEK));
+		v.add(new FieldContainer(104, 110, Field.DAY_OF_WEEK));
+		v.add(new FieldContainer(111, 114, Field.DAY_OF_YEAR));
+		v.add(new FieldContainer(115, 118, Field.DAY_OF_YEAR));
+		v.add(new FieldContainer(119, 122, Field.DAY_OF_YEAR));
+		v.add(new FieldContainer(123, 124, Field.DAY_OF_WEEK_IN_MONTH));
+		v.add(new FieldContainer(125, 127, Field.DAY_OF_WEEK_IN_MONTH));
+		v.add(new FieldContainer(128, 130, Field.WEEK_OF_YEAR));
+		v.add(new FieldContainer(131, 134, Field.WEEK_OF_YEAR));
+		v.add(new FieldContainer(135, 136, Field.WEEK_OF_MONTH));
+		v.add(new FieldContainer(137, 140, Field.WEEK_OF_MONTH));
+		v.add(new FieldContainer(141, 143, Field.AM_PM));
+		v.add(new FieldContainer(145, 147, Field.AM_PM));
+		v.add(new FieldContainer(149, 150, Field.HOUR0));
+		v.add(new FieldContainer(151, 154, Field.HOUR0));
+		v.add(new FieldContainer(155, 164, Field.TIME_ZONE));
+		v.add(new FieldContainer(165, 174, Field.TIME_ZONE));
+		v.add(new FieldContainer(175, 180, Field.TIME_ZONE));
+		v.add(new FieldContainer(181, 186, Field.TIME_ZONE));
+		return v;
+	}
+
+}
diff --git a/libcore/tools/integrate/Android.mk b/libcore/tools/integrate/Android.mk
new file mode 100644
index 0000000..629a5fd
--- /dev/null
+++ b/libcore/tools/integrate/Android.mk
@@ -0,0 +1,19 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+	Command.java  \
+	Filesystem.java \
+	Git.java \
+	Module.java \
+	Modules.java \
+	MappedDirectory.java \
+	PullHarmonyCode.java \
+	Svn.java
+
+LOCAL_MODULE:= integrate
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
+include $(call all-subdir-makefiles)
diff --git a/libcore/tools/integrate/Command.java b/libcore/tools/integrate/Command.java
new file mode 100644
index 0000000..5e7796f
--- /dev/null
+++ b/libcore/tools/integrate/Command.java
@@ -0,0 +1,104 @@
+/*
+ * 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.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * An out of process executable.
+ */
+class Command {
+
+    private final List<String> args;
+    private final boolean permitNonZeroExitStatus;
+
+    Command(String... args) {
+        this(Arrays.asList(args));
+    }
+
+    Command(List<String> args) {
+        this.args = new ArrayList<String>(args);
+        this.permitNonZeroExitStatus = false;
+    }
+
+    private Command(Builder builder) {
+        this.args = new ArrayList<String>(builder.args);
+        this.permitNonZeroExitStatus = builder.permitNonZeroExitStatus;
+    }
+
+    static class Builder {
+        private final List<String> args = new ArrayList<String>();
+        private boolean permitNonZeroExitStatus = false;
+
+        public Builder args(String... args) {
+            return args(Arrays.asList(args));
+        }
+
+        public Builder args(Collection<String> args) {
+            this.args.addAll(args);
+            return this;
+        }
+
+        public Builder permitNonZeroExitStatus() {
+            permitNonZeroExitStatus = true;
+            return this;
+        }
+
+        public Command build() {
+            return new Command(this);
+        }
+
+        public List<String> execute() {
+            return build().execute();
+        }
+    }
+
+    public List<String> execute() {
+        try {
+            Process process = new ProcessBuilder()
+                    .command(args)
+                    .redirectErrorStream(true)
+                    .start();
+
+            BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
+            List<String> outputLines = new ArrayList<String>();
+            String outputLine;
+            while ((outputLine = in.readLine()) != null) {
+                outputLines.add(outputLine);
+            }
+
+            if (process.waitFor() != 0 && !permitNonZeroExitStatus) {
+                StringBuilder message = new StringBuilder();
+                for (String line : outputLines) {
+                    message.append("\n").append(line);
+                }
+                throw new RuntimeException("Process failed: " + args + message);
+            }
+
+            return outputLines;
+        } catch (IOException e) {
+            throw new RuntimeException("Process failed: " + args, e);
+        } catch (InterruptedException e) {
+            throw new RuntimeException("Process failed: " + args, e);
+        }
+    }
+
+}
diff --git a/libcore/tools/integrate/Filesystem.java b/libcore/tools/integrate/Filesystem.java
new file mode 100644
index 0000000..a9c1789
--- /dev/null
+++ b/libcore/tools/integrate/Filesystem.java
@@ -0,0 +1,63 @@
+/*
+ * 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.util.Collection;
+import java.util.List;
+
+/**
+ * Factory for filesystem commands.
+ */
+class Filesystem {
+
+    public void move(String source, String target) {
+        new Command("mv", source, target).execute();
+    }
+
+    /**
+     * Moves 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 moveContents(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();
+        }
+        return files.size();
+    }
+
+    private String parent(String file) {
+        return file.substring(0, file.lastIndexOf('/'));
+    }
+
+    public void mkdir(String dir) {
+        new Command("mkdir", "-p", dir).execute();
+    }
+
+    public List<String> find(String where, String name) {
+        return new Command("find", where, "-name", name).execute();
+    }
+
+    public void rm(Collection<String> files) {
+        new Command.Builder().args("rm", "-r").args(files).execute();
+    }
+
+    public void rm(String file) {
+        new Command("rm", "-r", file).execute();
+    }
+}
diff --git a/libcore/tools/integrate/Git.java b/libcore/tools/integrate/Git.java
new file mode 100644
index 0000000..da7dcfa
--- /dev/null
+++ b/libcore/tools/integrate/Git.java
@@ -0,0 +1,90 @@
+/*
+ * 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.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Factory for git commands.
+ */
+class Git {
+
+    private static final Pattern STATUS_DELETED
+            = Pattern.compile("#\\tdeleted:    (.*)");
+
+    public void branch(String newBranch) {
+        branch(newBranch, "HEAD");
+    }
+
+    /**
+     * @param base another branch, or a revision identifier like {@code HEAD}.
+     */
+    public void branch(String newBranch, String base) {
+        // -b is used by git to branch from another checkout
+        new Command("git", "checkout", "-b", newBranch, base).execute();
+    }
+
+    public void commit(String message) {
+        new Command("git", "commit", "-m", message).execute();
+    }
+
+    public void add(String path) {
+        new Command("git", "add", path).execute();
+    }
+
+    public void remove(Collection<String> paths) {
+        new Command.Builder().args("git", "rm").args(paths).execute();
+    }
+
+    public List<String> merge(String otherBranch) {
+        return new Command.Builder()
+                .args("git", "merge", "-s", "recursive", otherBranch)
+                .permitNonZeroExitStatus()
+                .execute();
+    }
+
+    /**
+     * Returns the files that have been deleted from the filesystem, but that
+     * don't exist in the active git change.
+     */
+    public List<String> listDeleted() {
+        List<String> statusLines = new Command.Builder()
+                .args("git", "status")
+                .permitNonZeroExitStatus()
+                .execute();
+
+        List<String> deletedFiles = new ArrayList<String>();
+        Matcher matcher = STATUS_DELETED.matcher("");
+        for (String line : statusLines) {
+            matcher.reset(line);
+            if (matcher.matches()) {
+                deletedFiles.add(matcher.group(1));
+            }
+        }
+        return deletedFiles;
+    }
+
+    public void rm(List<String> files) {
+        new Command.Builder()
+                .args("git", "rm").args(files)
+                .permitNonZeroExitStatus()
+                .build()
+                .execute();
+    }
+}
diff --git a/libcore/tools/integrate/MappedDirectory.java b/libcore/tools/integrate/MappedDirectory.java
new file mode 100644
index 0000000..8e28d29
--- /dev/null
+++ b/libcore/tools/integrate/MappedDirectory.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+/**
+ * A logical directory that has a different location in Harmony and Dalvik.
+ */
+class MappedDirectory {
+
+    private final String svnPath;
+    private final String gitPath;
+
+    public MappedDirectory(String svnPath, String gitPath) {
+        this.svnPath = svnPath;
+        this.gitPath = gitPath;
+    }
+
+    public String svnPath() {
+        return svnPath;
+    }
+
+    public String gitPath() {
+        return gitPath;
+    }
+
+    @Override public String toString() {
+        return "svn:" + svnPath + " -> git:" + gitPath;
+    }
+}
diff --git a/libcore/tools/integrate/Module.java b/libcore/tools/integrate/Module.java
new file mode 100644
index 0000000..5cb7035
--- /dev/null
+++ b/libcore/tools/integrate/Module.java
@@ -0,0 +1,67 @@
+/*
+ * 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.util.LinkedHashSet;
+import java.util.Set;
+
+/**
+ * A logical unit of code shared between Apache Harmony and Dalvik.
+ */
+class Module {
+
+    private final String svnBaseUrl;
+    private final String path;
+    private final Set<MappedDirectory> mappedDirectories;
+
+    public String getSvnBaseUrl() {
+        return svnBaseUrl;
+    }
+
+    public String path() {
+        return path;
+    }
+
+    public Set<MappedDirectory> getMappedDirectories() {
+        return mappedDirectories;
+    }
+
+    private Module(Builder builder) {
+        this.svnBaseUrl = builder.svnBaseUrl;
+        this.path = builder.path;
+        this.mappedDirectories = new LinkedHashSet<MappedDirectory>(builder.mappedDirectories);
+    }
+
+    public static class Builder {
+        private final String svnBaseUrl;
+        private final String path;
+        private final Set<MappedDirectory> mappedDirectories
+                = new LinkedHashSet<MappedDirectory>();
+
+        public Builder(String svnBaseUrl, String path) {
+            this.svnBaseUrl = svnBaseUrl;
+            this.path = path;
+        }
+
+        public Builder mapDirectory(String svnPath, String gitPath) {
+            mappedDirectories.add(new MappedDirectory(svnPath, gitPath));
+            return this;
+        }
+
+        public Module build() {
+            return new Module(this);
+        }
+    }
+}
diff --git a/libcore/tools/integrate/Modules.java b/libcore/tools/integrate/Modules.java
new file mode 100644
index 0000000..2475852
--- /dev/null
+++ b/libcore/tools/integrate/Modules.java
@@ -0,0 +1,62 @@
+/*
+ * 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
new file mode 100644
index 0000000..6710801
--- /dev/null
+++ b/libcore/tools/integrate/PullHarmonyCode.java
@@ -0,0 +1,109 @@
+/*
+ * 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.util.List;
+import java.util.UUID;
+
+/**
+ * Download two versions of Apache Harmony from their SVN version, and use it
+ * to perform a three-way merge with Dalvik.
+ */
+public class PullHarmonyCode {
+
+    private final int currentVersion;
+    private final int targetVersion;
+
+    public PullHarmonyCode(int currentVersion, int targetVersion) {
+        this.currentVersion = currentVersion;
+        this.targetVersion = targetVersion;
+    }
+
+    public void pull(Module module) {
+        String path = module.path();
+        String svnOldBranch = path + "_" + currentVersion;
+        String svnNewBranch = path + "_" + targetVersion;
+        String dalvikBranch = path + "_dalvik";
+
+        Git git = new Git();
+        Filesystem filesystem = new Filesystem();
+        Svn svn = new Svn();
+
+        // Assume we're starting with the current Dalvik code. Tuck this away
+        // somewhere while we rewrite history.
+        String temp = "/tmp/" + UUID.randomUUID();
+        filesystem.mkdir(temp);
+
+        // To prepare a three-way-merge, we need a common starting point: the
+        // time at which Dalvik and Harmony were most the same. We'll use the
+        // previous Harmony SVN code as this starting point. We grab the old
+        // code from their repository, and commit it as a git branch.
+        System.out.print("Creating branch " + svnOldBranch + "...");
+        git.branch(svnOldBranch);
+        filesystem.move(path, temp + "/" + path);
+        svn.checkOut(currentVersion, module.getSvnBaseUrl() + "/" + path);
+        filesystem.rm(filesystem.find(path, ".svn"));
+        for (MappedDirectory mappedDirectory : module.getMappedDirectories()) {
+            filesystem.moveContents(mappedDirectory.svnPath(), mappedDirectory.gitPath());
+        }
+        git.rm(git.listDeleted());
+        git.add(path);
+        git.commit(svnOldBranch);
+        System.out.println("done");
+
+        // Create a branch that's derived from the starting point. It will
+        // contain all of the changes Harmony has made from then until now.
+        System.out.print("Creating branch " + svnNewBranch + "...");
+        git.branch(svnNewBranch, svnOldBranch);
+        filesystem.rm(path);
+        svn.checkOut(targetVersion, module.getSvnBaseUrl() + "/" + path);
+        filesystem.rm(filesystem.find(path, ".svn"));
+        for (MappedDirectory mappedDirectory : module.getMappedDirectories()) {
+            filesystem.moveContents(mappedDirectory.svnPath(), mappedDirectory.gitPath());
+        }
+        git.rm(git.listDeleted());
+        git.add(path);
+        git.commit(svnNewBranch);
+        System.out.println("done");
+
+        // Create another branch that's derived from the starting point. It will
+        // contain all of the changes Dalvik has made from then until now.
+        System.out.print("Creating branch " + dalvikBranch + "...");
+        git.branch(dalvikBranch, svnOldBranch);
+        filesystem.rm(path);
+        filesystem.move(temp + "/" + path, path);
+        git.rm(git.listDeleted());
+        git.add(path);
+        git.commit(dalvikBranch);
+        System.out.println("done");
+
+        // Merge the two sets of changes together: Harmony's and Dalvik's. By
+        // initializing a common starting point, git can make better decisions
+        // when the two new versions differ. For example, if today's Dalvik has
+        // a method that today's Harmony does not, it may be because Dalvik
+        // added it, or because Harmony deleted it!
+        System.out.println("Merging " + svnNewBranch + " into " + dalvikBranch + ":");
+        List<String> mergeResults = git.merge(svnNewBranch);
+        for (String mergeResult : mergeResults) {
+            System.out.print("  ");
+            System.out.println(mergeResult);
+        }
+    }
+
+    public static void main(String[] args) {
+//        new PullHarmonyCode(527399, 802921).pull(Modules.CRYPTO);
+        new PullHarmonyCode(772995, 802921).pull(Modules.ARCHIVE);
+    }
+}
diff --git a/libcore/tools/integrate/Svn.java b/libcore/tools/integrate/Svn.java
new file mode 100644
index 0000000..dc9be35
--- /dev/null
+++ b/libcore/tools/integrate/Svn.java
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+
+/**
+ * Factory for Subversion commands.
+ */
+class Svn {
+
+    public void checkOut(int version, String url) {
+        new Command("svn", "co", "-r", "" + version, url).execute();
+    }
+}
diff --git a/libcore/x-net/src/main/java/javax/net/DefaultServerSocketFactory.java b/libcore/x-net/src/main/java/javax/net/DefaultServerSocketFactory.java
index 0b309df..9e31be4 100644
--- a/libcore/x-net/src/main/java/javax/net/DefaultServerSocketFactory.java
+++ b/libcore/x-net/src/main/java/javax/net/DefaultServerSocketFactory.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
 package javax.net;
 
 import java.io.IOException;
@@ -27,24 +22,27 @@
 import java.net.ServerSocket;
 
 /**
- * Default implementation of javax.net.ServerSocketFactory.
- * 
- * @since Android 1.0
- * 
+ * Default implementation of {@link javax.net.ServerSocketFactory}
  */
-class DefaultServerSocketFactory extends ServerSocketFactory {
+final class DefaultServerSocketFactory extends ServerSocketFactory {
 
+    DefaultServerSocketFactory() {
+        super();
+    }
+
+    @Override
     public ServerSocket createServerSocket(int port) throws IOException {
         return new ServerSocket(port);
     }
 
-    public ServerSocket createServerSocket(int port, int backlog)
-            throws IOException {
+    @Override
+    public ServerSocket createServerSocket(int port, int backlog) throws IOException {
         return new ServerSocket(port, backlog);
     }
 
-    public ServerSocket createServerSocket(int port, int backlog,
-            InetAddress iAddress) throws IOException {
+    @Override
+    public ServerSocket createServerSocket(int port, int backlog, InetAddress iAddress)
+            throws IOException {
         return new ServerSocket(port, backlog, iAddress);
     }
 
diff --git a/libcore/x-net/src/main/java/javax/net/DefaultSocketFactory.java b/libcore/x-net/src/main/java/javax/net/DefaultSocketFactory.java
index 8aa82d9..010c720 100644
--- a/libcore/x-net/src/main/java/javax/net/DefaultSocketFactory.java
+++ b/libcore/x-net/src/main/java/javax/net/DefaultSocketFactory.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
 package javax.net;
 
 import java.io.IOException;
@@ -28,32 +23,38 @@
 import java.net.UnknownHostException;
 
 /**
- * Default implementation of javax.net.SocketFactory
- * 
- * @since Android 1.0
+ * Default implementation of {@link javax.net.SocketFactory}
  */
-class DefaultSocketFactory extends SocketFactory {
+final class DefaultSocketFactory extends SocketFactory {
 
+    DefaultSocketFactory() {
+        super();
+    }
+
+    @Override
     public Socket createSocket() throws IOException {
         return new Socket();
     }
 
-    public Socket createSocket(String host, int port) throws IOException,
-            UnknownHostException {
+    @Override
+    public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
         return new Socket(host, port);
     }
 
-    public Socket createSocket(String host, int port, InetAddress localHost,
-            int localPort) throws IOException, UnknownHostException {
+    @Override
+    public Socket createSocket(String host, int port, InetAddress localHost, int localPort)
+            throws IOException, UnknownHostException {
         return new Socket(host, port, localHost, localPort);
     }
 
+    @Override
     public Socket createSocket(InetAddress host, int port) throws IOException {
         return new Socket(host, port);
     }
 
-    public Socket createSocket(InetAddress address, int port,
-            InetAddress localAddress, int localPort) throws IOException {
+    @Override
+    public Socket createSocket(InetAddress address, int port, InetAddress localAddress,
+            int localPort) throws IOException {
         return new Socket(address, port, localAddress, localPort);
     }
 }
diff --git a/libcore/x-net/src/main/java/javax/net/ServerSocketFactory.java b/libcore/x-net/src/main/java/javax/net/ServerSocketFactory.java
index 28a79f6..f2d2c0d 100644
--- a/libcore/x-net/src/main/java/javax/net/ServerSocketFactory.java
+++ b/libcore/x-net/src/main/java/javax/net/ServerSocketFactory.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
 package javax.net;
 
 import java.io.IOException;
@@ -30,66 +25,59 @@
 /**
  * This abstract class defines methods to create server sockets. It can be
  * subclassed to create specific server socket types.
- * 
- * @since Android 1.0
  */
 public abstract class ServerSocketFactory {
-    static ServerSocketFactory defaultFactory;
-    
-    /**
-     * Creates a new {@code ServerSocketFactory} instance.
-     * 
-     * @since Android 1.0
-     */
-    protected ServerSocketFactory() {
-    }
+    private static ServerSocketFactory defaultFactory;
 
     /**
      * Gets the default server socket factory of the system which can be used to
      * create new server sockets without creating a subclass of this factory.
-     * 
+     *
      * @return the system default server socket factory.
-     * @since Android 1.0
      */
     public static synchronized ServerSocketFactory getDefault() {
         if (defaultFactory == null) {
-                defaultFactory = new DefaultServerSocketFactory();
+            defaultFactory = new DefaultServerSocketFactory();
         }
         return defaultFactory;
     }
 
     /**
+     * Creates a new {@code ServerSocketFactory} instance.
+     */
+    protected ServerSocketFactory() {
+        super();
+    }
+
+    /**
      * Creates a new server socket which is not bound to any local address. This
      * method has to be overridden by a subclass otherwise a {@code
      * SocketException} is thrown.
-     * 
+     *
      * @return the created unbound server socket.
      * @throws IOException
      *             if an error occurs while creating a new server socket.
-     * @since Android 1.0
      */
     public ServerSocket createServerSocket() throws IOException {
-        // follow RI's behavior 
+        // follow RI's behavior
         throw new SocketException("Unbound server sockets not implemented");
     }
 
     /**
      * Creates a new server socket which is bound to the given port.
-     * 
+     *
      * @param port
      *            the port on which the created socket has to listen.
      * @return the created bound server socket.
      * @throws IOException
      *             if an error occurs while creating a new server socket.
-     * @since Android 1.0
      */
-    public abstract ServerSocket createServerSocket(int port)
-            throws IOException;
+    public abstract ServerSocket createServerSocket(int port) throws IOException;
 
     /**
      * Creates a new server socket which is bound to the given port and
      * configures its maximum of queued connections.
-     * 
+     *
      * @param port
      *            the port on which the created socket has to listen.
      * @param backlog
@@ -97,15 +85,13 @@
      * @return the created bound server socket.
      * @throws IOException
      *             if an error occurs while creating a new server socket.
-     * @since Android 1.0
      */
-    public abstract ServerSocket createServerSocket(int port, int backlog)
-            throws IOException;
+    public abstract ServerSocket createServerSocket(int port, int backlog) throws IOException;
 
     /**
      * Creates a new server socket which is bound to the given address on the
      * specified port and configures its maximum of queued connections.
-     * 
+     *
      * @param port
      *            the port on which the created socket has to listen.
      * @param backlog
@@ -116,9 +102,8 @@
      * @return the created bound server socket.
      * @throws IOException
      *             if an error occurs while creating a new server socket.
-     * @since Android 1.0
      */
-    public abstract ServerSocket createServerSocket(int port, int backlog,
-            InetAddress iAddress) throws IOException;
+    public abstract ServerSocket createServerSocket(int port, int backlog, InetAddress iAddress)
+            throws IOException;
 
-}
\ No newline at end of file
+}
diff --git a/libcore/x-net/src/main/java/javax/net/SocketFactory.java b/libcore/x-net/src/main/java/javax/net/SocketFactory.java
index 6e5017e..eb0cfcb 100644
--- a/libcore/x-net/src/main/java/javax/net/SocketFactory.java
+++ b/libcore/x-net/src/main/java/javax/net/SocketFactory.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Boris V. Kuznetsov
-* @version $Revision$
-*/
-
 package javax.net;
 
 import java.io.IOException;
@@ -31,27 +26,16 @@
 /**
  * This abstract class defines methods to create sockets. It can be subclassed
  * to create specific socket types with additional socket-level functionality.
- * 
- * @since Android 1.0
  */
 public abstract class SocketFactory {
 
-    static SocketFactory defaultFactory;
-    
-    /**
-     * Creates a new {@code SocketFactory} instance.
-     * 
-     * @since Android 1.0
-     */
-    protected SocketFactory() {
-    }
+    private static SocketFactory defaultFactory;
 
     /**
      * Gets the default socket factory of the system which can be used to create
      * new sockets without creating a subclass of this factory.
-     * 
+     *
      * @return the system default socket factory.
-     * @since Android 1.0
      */
     public static synchronized SocketFactory getDefault() {
         if (defaultFactory == null) {
@@ -61,17 +45,23 @@
     }
 
     /**
+     * Creates a new {@code SocketFactory} instance.
+     */
+    protected SocketFactory() {
+        super();
+    }
+
+    /**
      * Creates a new socket which is not connected to any remote host. This
      * method has to be overridden by a subclass otherwise a {@code
      * SocketException} is thrown.
-     * 
+     *
      * @return the created unconnected socket.
      * @throws IOException
      *             if an error occurs while creating a new socket.
-     * @since Android 1.0
      */
     public Socket createSocket() throws IOException {
-        // follow RI's behavior 
+        // follow RI's behavior
         throw new SocketException("Unconnected sockets not implemented");
     }
 
@@ -79,7 +69,7 @@
      * Creates a new socket which is connected to the remote host specified by
      * the parameters {@code host} and {@code port}. The socket is bound to any
      * available local address and port.
-     * 
+     *
      * @param host
      *            the remote host address the socket has to be connected to.
      * @param port
@@ -91,17 +81,16 @@
      * @throws UnknownHostException
      *             if the specified host is unknown or the IP address could not
      *             be resolved.
-     * @since Android 1.0
      */
-    public abstract Socket createSocket(String host, int port)
-            throws IOException, UnknownHostException;
+    public abstract Socket createSocket(String host, int port) throws IOException,
+            UnknownHostException;
 
     /**
      * Creates a new socket which is connected to the remote host specified by
      * the parameters {@code host} and {@code port}. The socket is bound to the
      * local network interface specified by the InetAddress {@code localHost} on
      * port {@code localPort}.
-     * 
+     *
      * @param host
      *            the remote host address the socket has to be connected to.
      * @param port
@@ -118,17 +107,15 @@
      * @throws UnknownHostException
      *             if the specified host is unknown or the IP address could not
      *             be resolved.
-     * @since Android 1.0
      */
-    public abstract Socket createSocket(String host, int port,
-            InetAddress localHost, int localPort) throws IOException,
-            UnknownHostException;
+    public abstract Socket createSocket(String host, int port, InetAddress localHost, int localPort)
+            throws IOException, UnknownHostException;
 
     /**
      * Creates a new socket which is connected to the remote host specified by
      * the InetAddress {@code host}. The socket is bound to any available local
      * address and port.
-     * 
+     *
      * @param host
      *            the host address the socket has to be connected to.
      * @param port
@@ -137,17 +124,16 @@
      * @return the created connected socket.
      * @throws IOException
      *             if an error occurs while creating a new socket.
-     * @since Android 1.0
      */
-    public abstract Socket createSocket(InetAddress host, int port)
-            throws IOException;
+    public abstract Socket createSocket(InetAddress host, int port) throws IOException;
+
 
     /**
      * Creates a new socket which is connected to the remote host specified by
      * the InetAddress {@code address}. The socket is bound to the local network
      * interface specified by the InetAddress {@code localHost} on port {@code
      * localPort}.
-     * 
+     *
      * @param address
      *            the remote host address the socket has to be connected to.
      * @param port
@@ -161,8 +147,7 @@
      * @return the created connected socket.
      * @throws IOException
      *             if an error occurs while creating a new socket.
-     * @since Android 1.0
      */
-    public abstract Socket createSocket(InetAddress address, int port,
-            InetAddress localAddress, int localPort) throws IOException;
+    public abstract Socket createSocket(InetAddress address, int port, InetAddress localAddress,
+            int localPort) throws IOException;
 }
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/CertPathTrustManagerParameters.java b/libcore/x-net/src/main/java/javax/net/ssl/CertPathTrustManagerParameters.java
index 5903663..dcf7a4d 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/CertPathTrustManagerParameters.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/CertPathTrustManagerParameters.java
@@ -22,11 +22,12 @@
 /**
  * Certification path parameters to provide to certification path
  * based {@link TrustManager}.
- * @since Android 1.0
+ *
+ * @since 1.5
  */
 public class CertPathTrustManagerParameters implements ManagerFactoryParameters {
 
-    private CertPathParameters param;
+    private final CertPathParameters param;
 
     /**
      * Creates a new {@code CertPathTrustManagerParameters} with the specified
@@ -34,7 +35,6 @@
      * 
      * @param parameters
      *            the certification path parameters.
-     * @since Android 1.0
      */
     public CertPathTrustManagerParameters(CertPathParameters parameters) {
         param = (CertPathParameters) parameters.clone();
@@ -44,10 +44,9 @@
      * Returns a copy of the certification path parameters.
      * 
      * @return a copy of the certification path parameters.
-     * @since Android 1.0
      */
     public CertPathParameters getParameters() {
         return (CertPathParameters) param.clone();
     }
 
-}
\ No newline at end of file
+}
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/ContextImpl.java b/libcore/x-net/src/main/java/javax/net/ssl/ContextImpl.java
deleted file mode 100644
index 096cbba..0000000
--- a/libcore/x-net/src/main/java/javax/net/ssl/ContextImpl.java
+++ /dev/null
@@ -1,33 +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 javax.net.ssl;
-
-import java.security.Provider;
-
-/**
- * Support class for this package.
- * 
- * @since Android 1.0
- */
-
-class ContextImpl extends SSLContext {
-    public ContextImpl(SSLContextSpi contextSpi, Provider provider,
-            String protocol) {
-        super(contextSpi, provider, protocol);
-    }
-}
\ No newline at end of file
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/DefaultSSLContext.java b/libcore/x-net/src/main/java/javax/net/ssl/DefaultSSLContext.java
index d2ab2f4..a12d385 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/DefaultSSLContext.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/DefaultSSLContext.java
@@ -19,28 +19,24 @@
 
 import java.io.FileInputStream;
 import java.security.AccessController;
+import java.security.KeyStore;
+import java.security.PrivilegedAction;
 import java.security.Provider;
 import java.security.Security;
-import java.security.KeyStore;
-import java.util.Iterator;
 
 import org.apache.harmony.security.fortress.Engine;
 import org.apache.harmony.security.fortress.Services;
 
-
 /**
  * Support class for this package.
- * 
- * @since Android 1.0
  */
-
-class DefaultSSLContext {
+final class DefaultSSLContext {
     private static SSLContext defaultSSLContext;
 
-    public static SSLContext getContext() {
+     static synchronized SSLContext getContext() {
         if (defaultSSLContext == null) {
             defaultSSLContext = AccessController
-                    .doPrivileged(new java.security.PrivilegedAction<SSLContext>() {
+                    .doPrivileged(new PrivilegedAction<SSLContext>() {
                         public SSLContext run() {
                             return findDefault();
                         }
@@ -51,40 +47,37 @@
 
     private static SSLContext findDefault() {
         // FIXME EXPORT CONTROL
-        Provider.Service service;
-        for (Iterator it1 = Services.getProvidersList().iterator(); it1
-                .hasNext();) {
-            service = Engine.door.getService((Provider) it1.next(),
-                    "SSLContext");
+        for (Provider provider : Services.getProvidersList()) {
+            final Provider.Service service = Engine.door.getService(provider, "SSLContext");
             if (service != null) {
                 try {
-                    SSLContext con = new ContextImpl(
-                            (SSLContextSpi) service.newInstance(null),
-                            service.getProvider(), 
-                            service.getAlgorithm());
+                    SSLContext con = new SSLContext((SSLContextSpi) service.newInstance(null),
+                            service.getProvider(), service.getAlgorithm());
 
- //TODO javax.net.ssl.keyStoreProvider, javax.net.ssl.trustStoreProvider system property
+                    /* 
+                     * TODO 
+                     * javax.net.ssl.keyStoreProvider, 
+                     * javax.net.ssl.trustStoreProvider system property
+                     */
+                    
                     // find KeyStore, KeyManagers
                     KeyManager[] keyManagers = null;
-                    KeyStore ks = KeyStore.getInstance(KeyStore
-                            .getDefaultType());
-                    String keystore = System
-                            .getProperty("javax.net.ssl.keyStore");
-                    String keystorepwd = System
-                            .getProperty("javax.net.ssl.keyStorePassword");
+                    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
+                    String keystore = System.getProperty("javax.net.ssl.keyStore");
+                    String keystorepwd = System.getProperty("javax.net.ssl.keyStorePassword");
                     char[] pwd = null;
                     if (keystorepwd != null) {
                         pwd = keystorepwd.toCharArray();
                     }
                     if (keystore != null) {
-                        FileInputStream fis = new java.io.FileInputStream(
-                                keystore);
-                        ks.load(fis, pwd);
-                        fis.close();
-
+                        FileInputStream fis = new FileInputStream(keystore);
+                        try {
+                            ks.load(fis, pwd);
+                        } finally {
+                            fis.close();
+                        }
                         KeyManagerFactory kmf;
-                        String kmfAlg = Security
-                                .getProperty("ssl.KeyManagerFactory.algorithm");
+                        String kmfAlg = Security.getProperty("ssl.KeyManagerFactory.algorithm");
                         if (kmfAlg == null) {
                             kmfAlg = "SunX509";
                         }
@@ -96,21 +89,21 @@
                     // find TrustStore, TrustManagers
                     TrustManager[] trustManagers = null;
                     keystore = System.getProperty("javax.net.ssl.trustStore");
-                    keystorepwd = System
-                            .getProperty("javax.net.ssl.trustStorePassword");
+                    keystorepwd = System.getProperty("javax.net.ssl.trustStorePassword");
                     pwd = null;
                     if (keystorepwd != null) {
                         pwd = keystorepwd.toCharArray();
                     }
-                    //TODO Defaults: jssecacerts; cacerts
+                    // TODO Defaults: jssecacerts; cacerts
                     if (keystore != null) {
-                        FileInputStream fis = new java.io.FileInputStream(
-                                keystore);
-                        ks.load(fis, pwd);
-                        fis.close();
+                        FileInputStream fis = new FileInputStream(keystore);
+                        try {
+                            ks.load(fis, pwd);
+                        } finally {
+                            fis.close();
+                        }
                         TrustManagerFactory tmf;
-                        String tmfAlg = Security
-                                .getProperty("ssl.TrustManagerFactory.algorithm");
+                        String tmfAlg = Security.getProperty("ssl.TrustManagerFactory.algorithm");
                         if (tmfAlg == null) {
                             tmfAlg = "PKIX";
                         }
@@ -122,7 +115,6 @@
                     con.init(keyManagers, trustManagers, null);
                     return con;
                 } catch (Exception e) {
-                    // e.printStackTrace();
                     // ignore and try another
                 }
             }
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/DefaultSSLServerSocketFactory.java b/libcore/x-net/src/main/java/javax/net/ssl/DefaultSSLServerSocketFactory.java
index c41f61a..6620841 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/DefaultSSLServerSocketFactory.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/DefaultSSLServerSocketFactory.java
@@ -29,33 +29,36 @@
  */
 class DefaultSSLServerSocketFactory extends SSLServerSocketFactory {
 
-    private String errMessage;
-    
+    private final String errMessage;
+
+    DefaultSSLServerSocketFactory(String mes) {
+        errMessage = mes;
+    }
+
+    @Override
     public String[] getDefaultCipherSuites() {
         return new String[0];
     }
 
+    @Override
     public String[] getSupportedCipherSuites() {
         return new String[0];
     }
 
+    @Override
     public ServerSocket createServerSocket(int port) throws IOException {
         throw new SocketException(errMessage);
     }
 
+    @Override
+    public ServerSocket createServerSocket(int port, int backlog) throws IOException {
+        throw new SocketException(errMessage);
+    }
 
-    public ServerSocket createServerSocket(int port, int backlog)
+    @Override
+    public ServerSocket createServerSocket(int port, int backlog, InetAddress iAddress)
             throws IOException {
         throw new SocketException(errMessage);
     }
 
-    public ServerSocket createServerSocket(int port, int backlog,
-            InetAddress iAddress) throws IOException {
-        throw new SocketException(errMessage);
-    }
-    
-    DefaultSSLServerSocketFactory(String mes) {
-        errMessage = mes;
-    }
-
 }
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/DefaultSSLSocketFactory.java b/libcore/x-net/src/main/java/javax/net/ssl/DefaultSSLSocketFactory.java
index fc4e340..4035a0e 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/DefaultSSLSocketFactory.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/DefaultSSLSocketFactory.java
@@ -26,61 +26,51 @@
 /**
  * Default inoperative implementation of javax.net.ssl.SSLSocketFactory
  * 
- * @since Android 1.0
  */
 class DefaultSSLSocketFactory extends SSLSocketFactory {
-    
-    private String errMessage;
-    
+
+    private final String errMessage;
+
+    DefaultSSLSocketFactory(String mes) {
+        errMessage = mes;
+    }
+
+    @Override
     public String[] getDefaultCipherSuites() {
         return new String[0];
     }
 
+    @Override
     public String[] getSupportedCipherSuites() {
         return new String[0];
     }
 
-    /**
-     * @see javax.net.ssl.SSLSocketFactory#createSocket(java.net.Socket, java.lang.String, int, boolean)
-     */
-    public Socket createSocket(Socket s, String host, int port,
-            boolean autoClose) throws IOException {
+    @Override
+    public Socket createSocket(Socket s, String host, int port, boolean autoClose)
+            throws IOException {
         throw new SocketException(errMessage);
     }
 
-    /**
-     * @see javax.net.SocketFactory#createSocket(java.lang.String, int)
-     */
-    public Socket createSocket(String host, int port) throws IOException,
-            UnknownHostException {
+    @Override
+    public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
         throw new SocketException(errMessage);
     }
 
-    /**
-     * @see javax.net.SocketFactory#createSocket(java.lang.String, int, java.net.InetAddress, int)
-     */
-    public Socket createSocket(String host, int port, InetAddress localHost,
-            int localPort) throws IOException, UnknownHostException {
+    @Override
+    public Socket createSocket(String host, int port, InetAddress localHost, int localPort)
+            throws IOException, UnknownHostException {
         throw new SocketException(errMessage);
     }
 
-    /**
-     * @see javax.net.SocketFactory#createSocket(java.net.InetAddress, int)
-     */
+    @Override
     public Socket createSocket(InetAddress host, int port) throws IOException {
         throw new SocketException(errMessage);
     }
 
-    /**
-     * @see javax.net.SocketFactory#createSocket(java.net.InetAddress, int, java.net.InetAddress, int)
-     */
-    public Socket createSocket(InetAddress address, int port,
-            InetAddress localAddress, int localPort) throws IOException {
+    @Override
+    public Socket createSocket(InetAddress address, int port, InetAddress localAddress,
+            int localPort) throws IOException {
         throw new SocketException(errMessage);
     }
-    
-    DefaultSSLSocketFactory(String mes) {
-        errMessage = mes;
-    }
 
 }
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/HandshakeCompletedEvent.java b/libcore/x-net/src/main/java/javax/net/ssl/HandshakeCompletedEvent.java
index 5ec5666..4618280 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/HandshakeCompletedEvent.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/HandshakeCompletedEvent.java
@@ -26,11 +26,8 @@
 /**
  * The event object encapsulating the information about a completed SSL
  * handshake on a SSL connection.
- * 
- * @since Android 1.0
  */
-public class HandshakeCompletedEvent extends EventObject implements
-        Serializable {
+public class HandshakeCompletedEvent extends EventObject implements Serializable {
 
     /**
      * The 5.0 spec. doesn't declare this serialVersionUID field In order to be
@@ -43,12 +40,11 @@
     /**
      * Creates a new {@code HandshakeCompletedEvent} with the specified SSL
      * socket and SSL session.
-     * 
+     *
      * @param sock
      *            the SSL socket.
      * @param s
      *            the SSL session.
-     * @since Android 1.0
      */
     public HandshakeCompletedEvent(SSLSocket sock, SSLSession s) {
         super(sock);
@@ -57,9 +53,8 @@
 
     /**
      * Returns the SSL session associated with this event.
-     * 
+     *
      * @return the SSL session associated with this event.
-     * @since Android 1.0
      */
     public SSLSession getSession() {
         return session;
@@ -67,9 +62,8 @@
 
     /**
      * Returns the name of the cipher suite negotiated during this handshake.
-     * 
+     *
      * @return the name of the cipher suite negotiated during this handshake.
-     * @since Android 1.0
      */
     public String getCipherSuite() {
         return session.getCipherSuite();
@@ -78,11 +72,10 @@
     /**
      * Returns the list of local certificates used during the handshake. These
      * certificates were sent to the peer.
-     * 
+     *
      * @return Returns the list of certificates used during the handshake with
      *         the local identity certificate followed by CAs, or {@code null}
      *         if no certificates were used during the handshake.
-     * @since Android 1.0
      */
     public Certificate[] getLocalCertificates() {
         return session.getLocalCertificates();
@@ -91,15 +84,13 @@
     /**
      * Return the list of certificates identifying the peer during the
      * handshake.
-     * 
+     *
      * @return the list of certificates identifying the peer with the peer's
      *         identity certificate followed by CAs.
      * @throws SSLPeerUnverifiedException
      *             if the identity of the peer has not been verified.
-     * @since Android 1.0
      */
-    public Certificate[] getPeerCertificates()
-            throws SSLPeerUnverifiedException {
+    public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
         return session.getPeerCertificates();
     }
 
@@ -109,48 +100,42 @@
      * certificates.
      * <p>
      * <b>Replaced by:</b> {@link #getPeerCertificates()}
-     * </p>
-     * 
+     *
      * @return the list of certificates identifying the peer
      * @throws SSLPeerUnverifiedException
      *             if the identity of the peer has not been verified.
-     * @since Android 1.0
      */
-    public X509Certificate[] getPeerCertificateChain()
-            throws SSLPeerUnverifiedException {
+    public X509Certificate[] getPeerCertificateChain() throws SSLPeerUnverifiedException {
         return session.getPeerCertificateChain();
     }
 
     /**
      * Returns the {@code Principal} identifying the peer.
-     * 
+     *
      * @return the {@code Principal} identifying the peer.
      * @throws SSLPeerUnverifiedException
      *             if the identity of the peer has not been verified.
-     * @since Android 1.0
      */
     public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
         return session.getPeerPrincipal();
     }
-    
+
     /**
      * Returns the {@code Principal} used to identify during the handshake.
-     * 
+     *
      * @return the {@code Principal} used to identify during the handshake.
-     * @since Android 1.0
      */
     public Principal getLocalPrincipal() {
         return session.getLocalPrincipal();
     }
-    
+
     /**
      * Returns the SSL socket that produced this event.
-     * 
+     *
      * @return the SSL socket that produced this event.
-     * @since Android 1.0
      */
     public SSLSocket getSocket() {
-        return (SSLSocket)this.source;
+        return (SSLSocket) this.source;
     }
 
-}
\ No newline at end of file
+}
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/HandshakeCompletedListener.java b/libcore/x-net/src/main/java/javax/net/ssl/HandshakeCompletedListener.java
index 9ffcbc1..5032c63 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/HandshakeCompletedListener.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/HandshakeCompletedListener.java
@@ -22,17 +22,13 @@
 /**
  * The listener to be implemented to receive event notifications on completion
  * of SSL handshake on an SSL connection.
- * 
- * @since Android 1.0
  */
 public interface HandshakeCompletedListener extends EventListener {
-
     /**
      * The callback method that is invoked when a SSL handshake is completed.
-     * 
+     *
      * @param event
      *            the information on the completed SSL handshake event.
-     * @since Android 1.0
      */
-    public void handshakeCompleted(HandshakeCompletedEvent event);
-}
\ No newline at end of file
+    void handshakeCompleted(HandshakeCompletedEvent event);
+}
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/HostnameVerifier.java b/libcore/x-net/src/main/java/javax/net/ssl/HostnameVerifier.java
index fe767ef..805762e 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/HostnameVerifier.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/HostnameVerifier.java
@@ -23,23 +23,18 @@
  * This is an extended verification option that implementers can provide. It is to be used
  * during a handshake if the URL's hostname does not match the peer's
  * identification hostname.
- * </p>
- * 
- * @since Android 1.0
  */
 public interface HostnameVerifier {
-
     /**
      * Verifies that the specified hostname is allowed within the specified SSL
      * session.
-     * 
+     *
      * @param hostname
      *            the hostname.
      * @param session
      *            the SSL session of the connection.
      * @return {@code true} if the specified hostname is allowed, otherwise
      *         {@code false}.
-     * @since Android 1.0
      */
-    public boolean verify(String hostname, SSLSession session);
-}
\ No newline at end of file
+    boolean verify(String hostname, SSLSession session);
+}
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/HttpsURLConnection.java b/libcore/x-net/src/main/java/javax/net/ssl/HttpsURLConnection.java
index 0a95fb1..8c49690 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/HttpsURLConnection.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/HttpsURLConnection.java
@@ -26,8 +26,6 @@
 /**
  * This abstract subclass of {@code HttpURLConnection} defines methods for
  * managing HTTPS connections according to the description given by RFC 2818.
- * 
- * @since Android 1.0
  */
 public abstract class HttpsURLConnection extends HttpURLConnection {
 
@@ -37,114 +35,12 @@
             .getDefault();
 
     /**
-     * The host name verifier used by this connection. It is initialized from
-     * the default hostname verifier
-     * {@link #setDefaultHostnameVerifier(HostnameVerifier)} or
-     * {@link #getDefaultHostnameVerifier()}.
-     * 
-     * @since Android 1.0
-     */
-    protected HostnameVerifier hostnameVerifier;
-
-    private static SSLSocketFactory socketFactory;
-
-    /**
-     * Creates a new {@code HttpsURLConnection} with the specified {@code URL}.
-     * 
-     * @param url
-     *            the {@code URL} to connect to.
-     * @since Android 1.0
-     */
-    protected HttpsURLConnection(URL url) {
-        super(url);
-        hostnameVerifier = defaultHostnameVerifier;
-        socketFactory = defaultSSLSocketFactory;
-    }
-
-    /**
-     * Returns the name of the cipher suite negotiated during the SSL handshake.
-     * 
-     * @return the name of the cipher suite negotiated during the SSL handshake.
-     * @throws IllegalStateException
-     *             if no connection has been established yet.
-     * @since Android 1.0
-     */
-    public abstract String getCipherSuite();
-
-    /**
-     * Returns the list of local certificates used during the handshake. These
-     * certificates were sent to the peer.
-     * 
-     * @return Returns the list of certificates used during the handshake with
-     *         the local identity certificate followed by CAs, or {@code null}
-     *         if no certificates were used during the handshake.
-     * @throws IllegalStateException
-     *             if no connection has been established yet.
-     * @since Android 1.0
-     */    
-    public abstract Certificate[] getLocalCertificates();
-
-    /**
-     * Return the list of certificates identifying the peer during the
-     * handshake.
-     * 
-     * @return the list of certificates identifying the peer with the peer's
-     *         identity certificate followed by CAs.
-     * @throws SSLPeerUnverifiedException
-     *             if the identity of the peer has not been verified..
-     * @throws IllegalStateException
-     *             if no connection has been established yet.
-     * @since Android 1.0
-     */    
-    public abstract Certificate[] getServerCertificates()
-            throws SSLPeerUnverifiedException;
-
-    /**
-     * Returns the {@code Principal} identifying the peer.
-     * 
-     * @return the {@code Principal} identifying the peer.
-     * @throws SSLPeerUnverifiedException
-     *             if the identity of the peer has not been verified.
-     * @throws IllegalStateException
-     *             if no connection has been established yet.
-     * @since Android 1.0
-     */
-    public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
-        Certificate[] certs = getServerCertificates();
-        if (certs == null || certs.length == 0 || 
-                (!(certs[0] instanceof X509Certificate))) {
-            throw new SSLPeerUnverifiedException(
-                    "No server's end-entity certificate");
-        }
-        return ((X509Certificate) certs[0]).getSubjectX500Principal();
-    }
-
-    /**
-     * Returns the {@code Principal} used to identify the local host during the handshake.
-     * 
-     * @return the {@code Principal} used to identify the local host during the handshake, or
-     *         {@code null} if none was used.
-     * @throws IllegalStateException
-     *             if no connection has been established yet.
-     * @since Android 1.0
-     */    
-    public Principal getLocalPrincipal() {
-        Certificate[] certs = getLocalCertificates();
-        if (certs == null || certs.length == 0
-                || (!(certs[0] instanceof X509Certificate))) {
-            return null;
-        }
-        return ((X509Certificate) certs[0]).getSubjectX500Principal();
-    }
-
-    /**
      * Sets the default hostname verifier to be used by new instances.
-     * 
+     *
      * @param v
      *            the new default hostname verifier
      * @throws IllegalArgumentException
      *             if the specified verifier is {@code null}.
-     * @since Android 1.0
      */
     public static void setDefaultHostnameVerifier(HostnameVerifier v) {
         if (v == null) {
@@ -155,48 +51,20 @@
 
     /**
      * Returns the default hostname verifier.
-     * 
+     *
      * @return the default hostname verifier.
-     * @since Android 1.0
      */
     public static HostnameVerifier getDefaultHostnameVerifier() {
         return defaultHostnameVerifier;
     }
 
     /**
-     * Sets the hostname verifier for this instance.
-     * 
-     * @param v
-     *            the hostname verifier for this instance.
-     * @throws IllegalArgumentException
-     *             if the specified verifier is {@code null}.
-     * @since Android 1.0
-     */
-    public void setHostnameVerifier(HostnameVerifier v) {
-        if (v == null) {
-            throw new IllegalArgumentException("HostnameVerifier is null");
-        }
-        hostnameVerifier = v;
-    }
-
-    /**
-     * Returns the hostname verifier used by this instance.
-     * 
-     * @return the hostname verifier used by this instance.
-     * @since Android 1.0
-     */
-    public HostnameVerifier getHostnameVerifier() {
-        return hostnameVerifier;
-    }
-
-    /**
      * Sets the default SSL socket factory to be used by new instances.
-     * 
+     *
      * @param sf
      *            the new default SSL socket factory.
      * @throws IllegalArgumentException
      *             if the specified socket factory is {@code null}.
-     * @since Android 1.0
      */
     public static void setDefaultSSLSocketFactory(SSLSocketFactory sf) {
         if (sf == null) {
@@ -207,38 +75,148 @@
 
     /**
      * Returns the default SSL socket factory for new instances.
-     * 
+     *
      * @return the default SSL socket factory for new instances.
-     * @since Android 1.0
      */
     public static SSLSocketFactory getDefaultSSLSocketFactory() {
         return defaultSSLSocketFactory;
     }
 
     /**
+     * The host name verifier used by this connection. It is initialized from
+     * the default hostname verifier
+     * {@link #setDefaultHostnameVerifier(HostnameVerifier)} or
+     * {@link #getDefaultHostnameVerifier()}.
+     */
+    protected HostnameVerifier hostnameVerifier;
+
+    private SSLSocketFactory sslSocketFactory;
+
+    /**
+     * Creates a new {@code HttpsURLConnection} with the specified {@code URL}.
+     *
+     * @param url
+     *            the {@code URL} to connect to.
+     */
+    protected HttpsURLConnection(URL url) {
+        super(url);
+        hostnameVerifier = defaultHostnameVerifier;
+        sslSocketFactory = defaultSSLSocketFactory;
+    }
+
+    /**
+     * Returns the name of the cipher suite negotiated during the SSL handshake.
+     *
+     * @return the name of the cipher suite negotiated during the SSL handshake.
+     * @throws IllegalStateException
+     *             if no connection has been established yet.
+     */
+    public abstract String getCipherSuite();
+
+    /**
+     * Returns the list of local certificates used during the handshake. These
+     * certificates were sent to the peer.
+     *
+     * @return Returns the list of certificates used during the handshake with
+     *         the local identity certificate followed by CAs, or {@code null}
+     *         if no certificates were used during the handshake.
+     * @throws IllegalStateException
+     *             if no connection has been established yet.
+     */
+    public abstract Certificate[] getLocalCertificates();
+
+    /**
+     * Return the list of certificates identifying the peer during the
+     * handshake.
+     *
+     * @return the list of certificates identifying the peer with the peer's
+     *         identity certificate followed by CAs.
+     * @throws SSLPeerUnverifiedException
+     *             if the identity of the peer has not been verified..
+     * @throws IllegalStateException
+     *             if no connection has been established yet.
+     */
+    public abstract Certificate[] getServerCertificates() throws SSLPeerUnverifiedException;
+
+    /**
+     * Returns the {@code Principal} identifying the peer.
+     *
+     * @return the {@code Principal} identifying the peer.
+     * @throws SSLPeerUnverifiedException
+     *             if the identity of the peer has not been verified.
+     * @throws IllegalStateException
+     *             if no connection has been established yet.
+     */
+    public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
+        Certificate[] certs = getServerCertificates();
+        if (certs == null || certs.length == 0 || (!(certs[0] instanceof X509Certificate))) {
+            throw new SSLPeerUnverifiedException("No server's end-entity certificate");
+        }
+        return ((X509Certificate) certs[0]).getSubjectX500Principal();
+    }
+
+    /**
+     * Returns the {@code Principal} used to identify the local host during the handshake.
+     *
+     * @return the {@code Principal} used to identify the local host during the handshake, or
+     *         {@code null} if none was used.
+     * @throws IllegalStateException
+     *             if no connection has been established yet.
+     */
+    public Principal getLocalPrincipal() {
+        Certificate[] certs = getLocalCertificates();
+        if (certs == null || certs.length == 0 || (!(certs[0] instanceof X509Certificate))) {
+            return null;
+        }
+        return ((X509Certificate) certs[0]).getSubjectX500Principal();
+    }
+
+    /**
+     * Sets the hostname verifier for this instance.
+     *
+     * @param v
+     *            the hostname verifier for this instance.
+     * @throws IllegalArgumentException
+     *             if the specified verifier is {@code null}.
+     */
+    public void setHostnameVerifier(HostnameVerifier v) {
+        if (v == null) {
+            throw new IllegalArgumentException("HostnameVerifier is null");
+        }
+        hostnameVerifier = v;
+    }
+
+    /**
+     * Returns the hostname verifier used by this instance.
+     *
+     * @return the hostname verifier used by this instance.
+     */
+    public HostnameVerifier getHostnameVerifier() {
+        return hostnameVerifier;
+    }
+
+    /**
      * Sets the SSL socket factory for this instance.
-     * 
+     *
      * @param sf
      *            the SSL socket factory to be used by this instance.
      * @throws IllegalArgumentException
      *             if the specified socket factory is {@code null}.
-     * @since Android 1.0
      */
     public void setSSLSocketFactory(SSLSocketFactory sf) {
         if (sf == null) {
             throw new IllegalArgumentException("SSLSocketFactory is null");
         }
-        socketFactory = sf;
+        sslSocketFactory = sf;
     }
 
     /**
      * Returns the SSL socket factory used by this instance.
-     * 
+     *
      * @return the SSL socket factory used by this instance.
-     * @since Android 1.0
      */
     public SSLSocketFactory getSSLSocketFactory() {
-        return socketFactory;
+        return sslSocketFactory;
     }
 
 }
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/KeyManager.java b/libcore/x-net/src/main/java/javax/net/ssl/KeyManager.java
index 08939f7..30c8032 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/KeyManager.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/KeyManager.java
@@ -18,12 +18,10 @@
 package javax.net.ssl;
 
 /**
- * This is the interface to implement in order to mark a class as a JSSE key managers
- * so that key managers can be easily grouped. 
- * The key managers are responsible for handling the keys used to
- * authenticate the local side to its peer,
- * 
- * @since Android 1.0
+ * This is the interface to implement in order to mark a class as a JSSE key
+ * managers so that key managers can be easily grouped. The key managers are
+ * responsible for handling the keys used to authenticate the local side to its
+ * peer,
  */
 public interface KeyManager {
-}
\ No newline at end of file
+}
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/KeyManagerFactory.java b/libcore/x-net/src/main/java/javax/net/ssl/KeyManagerFactory.java
index a47d736..99a37a8 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/KeyManagerFactory.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/KeyManagerFactory.java
@@ -17,23 +17,21 @@
 
 package javax.net.ssl;
 
-import org.apache.harmony.security.fortress.Engine;
-
 import java.security.AccessController;
 import java.security.InvalidAlgorithmParameterException;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
 import java.security.NoSuchProviderException;
+import java.security.PrivilegedAction;
 import java.security.Provider;
 import java.security.Security;
 import java.security.UnrecoverableKeyException;
 
+import org.apache.harmony.security.fortress.Engine;
 
 /**
  * The public API for {@code KeyManagerFactory} implementations.
- * 
- * @since Android 1.0
  */
 public class KeyManagerFactory {
     // Store KeyManagerFactory service name
@@ -45,47 +43,26 @@
     // Store default property name
     private static final String PROPERTY_NAME = "ssl.KeyManagerFactory.algorithm";
 
-    // Store used provider
-    private final Provider provider;
-
-    // Store used KeyManagerFactorySpi implementation
-    private final KeyManagerFactorySpi spiImpl;
-
-    // Store used algorithm
-    private final String algorithm;
-
     /**
-     * Creates a new {@code KeyManagerFactory}.
-     * 
-     * @param factorySpi
-     *            the implementation delegate.
-     * @param provider
-     *            the provider.
-     * @param algorithm
-     *            the key management algorithm name.
-     * @since Android 1.0
+     * Returns the default key manager factory algorithm name.
+     * <p>
+     * The default algorithm name is specified by the security property:
+     * {@code 'ssl.KeyManagerFactory.algorithm'}.
+     *
+     * @return the default algorithm name.
      */
-    protected KeyManagerFactory(KeyManagerFactorySpi factorySpi,
-            Provider provider, String algorithm) {
-        this.provider = provider;
-        this.algorithm = algorithm;
-        this.spiImpl = factorySpi;
-    }
-
-    /**
-     * Returns the name of the key management algorithm.
-     * 
-     * @return the name of the key management algorithm.
-     * @since Android 1.0
-     */
-    public final String getAlgorithm() {
-        return algorithm;
+    public static final String getDefaultAlgorithm() {
+        return AccessController.doPrivileged(new PrivilegedAction<String>() {
+            public String run() {
+                return Security.getProperty(PROPERTY_NAME);
+            }
+        });
     }
 
     /**
      * Creates a new {@code KeyManagerFactory} instance for the specified key
      * management algorithm.
-     * 
+     *
      * @param algorithm
      *            the name of the requested key management algorithm.
      * @return a key manager factory for the requested algorithm.
@@ -94,24 +71,23 @@
      * @throws NullPointerException
      *             if {@code algorithm} is {@code null} (instead of
      *             NoSuchAlgorithmException as in 1.4 release)
-     * @since Android 1.0
      */
     public static final KeyManagerFactory getInstance(String algorithm)
             throws NoSuchAlgorithmException {
         if (algorithm == null) {
-            throw new NullPointerException("algorith is null");
+            throw new NullPointerException("algorithm is null");
         }
         synchronized (engine) {
             engine.getInstance(algorithm, null);
-            return new KeyManagerFactory((KeyManagerFactorySpi) engine.spi,
-                    engine.provider, algorithm);
+            return new KeyManagerFactory((KeyManagerFactorySpi) engine.spi, engine.provider,
+                    algorithm);
         }
     }
 
     /**
      * Creates a new {@code KeyManagerFactory} instance for the specified key
      * management algorithm from the specified provider.
-     * 
+     *
      * @param algorithm
      *            the name of the requested key management algorithm name.
      * @param provider
@@ -126,11 +102,9 @@
      * @throws NullPointerException
      *             if {@code algorithm} is {@code null} (instead of
      *             NoSuchAlgorithmException as in 1.4 release)
-     * @since Android 1.0
      */
-    public static final KeyManagerFactory getInstance(String algorithm,
-            String provider) throws NoSuchAlgorithmException,
-            NoSuchProviderException {
+    public static final KeyManagerFactory getInstance(String algorithm, String provider)
+            throws NoSuchAlgorithmException, NoSuchProviderException {
         if ((provider == null) || (provider.length() == 0)) {
             throw new IllegalArgumentException("Provider is null or empty");
         }
@@ -144,7 +118,7 @@
     /**
      * Creates a new {@code KeyManagerFactory} instance for the specified key
      * management algorithm from the specified provider.
-     * 
+     *
      * @param algorithm
      *            the name of the requested key management algorithm name.
      * @param provider
@@ -156,28 +130,60 @@
      * @throws NullPointerException
      *             if {@code algorithm} is {@code null} (instead of
      *             NoSuchAlgorithmException as in 1.4 release)
-     * @since Android 1.0
      */
-    public static final KeyManagerFactory getInstance(String algorithm,
-            Provider provider) throws NoSuchAlgorithmException {
+    public static final KeyManagerFactory getInstance(String algorithm, Provider provider)
+            throws NoSuchAlgorithmException {
         if (provider == null) {
             throw new IllegalArgumentException("Provider is null");
         }
         if (algorithm == null) {
-            throw new NullPointerException("algorith is null");
+            throw new NullPointerException("algorithm is null");
         }
         synchronized (engine) {
             engine.getInstance(algorithm, provider, null);
-            return new KeyManagerFactory((KeyManagerFactorySpi) engine.spi,
-                    provider, algorithm);
+            return new KeyManagerFactory((KeyManagerFactorySpi) engine.spi, provider, algorithm);
         }
     }
 
+    // Store used provider
+    private final Provider provider;
+
+    // Store used KeyManagerFactorySpi implementation
+    private final KeyManagerFactorySpi spiImpl;
+
+    // Store used algorithm
+    private final String algorithm;
+
+    /**
+     * Creates a new {@code KeyManagerFactory}.
+     *
+     * @param factorySpi
+     *            the implementation delegate.
+     * @param provider
+     *            the provider.
+     * @param algorithm
+     *            the key management algorithm name.
+     */
+    protected KeyManagerFactory(KeyManagerFactorySpi factorySpi, Provider provider, String algorithm) {
+        super();
+        this.provider = provider;
+        this.algorithm = algorithm;
+        this.spiImpl = factorySpi;
+    }
+
+    /**
+     * Returns the name of the key management algorithm.
+     *
+     * @return the name of the key management algorithm.
+     */
+    public final String getAlgorithm() {
+        return algorithm;
+    }
+
     /**
      * Returns the provider for this {@code KeyManagerFactory} instance.
-     * 
+     *
      * @return the provider for this {@code KeyManagerFactory} instance.
-     * @since Android 1.0
      */
     public final Provider getProvider() {
         return provider;
@@ -185,7 +191,7 @@
 
     /**
      * Initializes this instance with the specified key store and password.
-     * 
+     *
      * @param ks
      *            the key store or {@code null} to use the default key store.
      * @param password
@@ -197,55 +203,31 @@
      *             if a required algorithm is not available.
      * @throws UnrecoverableKeyException
      *             if a key cannot be recovered.
-     * @since Android 1.0
      */
-    public final void init(KeyStore ks, char[] password)
-            throws KeyStoreException, NoSuchAlgorithmException,
-            UnrecoverableKeyException {
+    public final void init(KeyStore ks, char[] password) throws KeyStoreException,
+            NoSuchAlgorithmException, UnrecoverableKeyException {
         spiImpl.engineInit(ks, password);
     }
 
     /**
      * Initializes this instance with the specified factory parameters.
-     * 
+     *
      * @param spec
      *            the factory parameters.
      * @throws InvalidAlgorithmParameterException
      *             if an error occurs.
-     * @since Android 1.0
      */
-    public final void init(ManagerFactoryParameters spec)
-            throws InvalidAlgorithmParameterException {
+    public final void init(ManagerFactoryParameters spec) throws InvalidAlgorithmParameterException {
         spiImpl.engineInit(spec);
     }
 
     /**
      * Returns a list of key managers, one instance for each type of key in the
      * key store.
-     * 
+     *
      * @return a list of key managers.
-     * @since Android 1.0
      */
     public final KeyManager[] getKeyManagers() {
         return spiImpl.engineGetKeyManagers();
     }
-
-    /**
-     * Returns the default key manager factory algorithm name.
-     * <p>
-     * The default algorithm name is specified by the security property:
-     *  {@code 'ssl.KeyManagerFactory.algorithm'}.
-     * </p>
-     * 
-     * @return the default algorithm name.
-     * @since Android 1.0
-     */
-    public static final String getDefaultAlgorithm() {
-        return AccessController
-                .doPrivileged(new java.security.PrivilegedAction<String>() {
-                    public String run() {
-                        return Security.getProperty(PROPERTY_NAME);
-                    }
-                });
-    }
-}
\ No newline at end of file
+}
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/KeyManagerFactorySpi.java b/libcore/x-net/src/main/java/javax/net/ssl/KeyManagerFactorySpi.java
index 7cdccf8..39925f9 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/KeyManagerFactorySpi.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/KeyManagerFactorySpi.java
@@ -26,23 +26,19 @@
 /**
  * The <i>Service Provider Interface</i> (SPI) for the
  * {@code KeyManagerFactory} class.
- * 
- * @since Android 1.0
  */
-
 public abstract class KeyManagerFactorySpi {
-
+    
     /**
      * Creates a new {@code KeyManagerFactorySpi} instance.
-     * 
-     * @since Android 1.0
      */
     public KeyManagerFactorySpi() {
+        super();
     }
 
     /**
      * Initializes this instance with the specified key store and password.
-     * 
+     *
      * @param ks
      *            the key store or {@code null} to use the default key store.
      * @param password
@@ -53,20 +49,17 @@
      *             if a required algorithm is not available.
      * @throws UnrecoverableKeyException
      *             if a key cannot be recovered.
-     * @since Android 1.0
      */
-    protected abstract void engineInit(KeyStore ks, char[] password)
-            throws KeyStoreException, NoSuchAlgorithmException,
-            UnrecoverableKeyException;
+    protected abstract void engineInit(KeyStore ks, char[] password) throws KeyStoreException,
+            NoSuchAlgorithmException, UnrecoverableKeyException;
 
     /**
      * Initializes this instance with the specified factory parameters.
-     * 
+     *
      * @param spec
      *            the factory parameters.
      * @throws InvalidAlgorithmParameterException
      *             if an error occurs.
-     * @since Android 1.0
      */
     protected abstract void engineInit(ManagerFactoryParameters spec)
             throws InvalidAlgorithmParameterException;
@@ -74,9 +67,8 @@
     /**
      * Returns a list of key managers, one instance for each type of key in the
      * key store.
-     * 
+     *
      * @return a list of key managers.
-     * @since Android 1.0
      */
     protected abstract KeyManager[] engineGetKeyManagers();
-}
\ No newline at end of file
+}
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/KeyStoreBuilderParameters.java b/libcore/x-net/src/main/java/javax/net/ssl/KeyStoreBuilderParameters.java
index b000fd5..d30cc8a 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/KeyStoreBuilderParameters.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/KeyStoreBuilderParameters.java
@@ -25,12 +25,13 @@
 /**
  * The parameters for {@code KeyManager}s. The parameters are a list of
  * {@code KeyStore.Builder}s.
- * 
- * @since Android 1.0
+ *
+ * @since 1.5
+ * @see KeyStore.Builder
  */
 public class KeyStoreBuilderParameters implements ManagerFactoryParameters {
 
-    private List ksbuilders;
+    private final List<KeyStore.Builder> ksbuilders;
 
     /**
      * Creates a new {@code KeyStoreBuilderParameters} with the specified key
@@ -38,13 +39,10 @@
      * 
      * @param builder
      *            the key store builder.
-     * @since Android 1.0
      */
     public KeyStoreBuilderParameters(KeyStore.Builder builder) {
-        ksbuilders = new ArrayList();
-        if (builder != null) {
-            ksbuilders.add(builder);
-        }
+        super();
+        ksbuilders = Collections.singletonList(builder);
     }
 
     /**
@@ -55,16 +53,17 @@
      *            the list of key store builders
      * @throws IllegalArgumentException
      *             if the specified list is empty.
-     * @since Android 1.0
      */
+    @SuppressWarnings("unchecked")
     public KeyStoreBuilderParameters(List parameters) {
+        super();
         if (parameters == null) {
             throw new NullPointerException("Builders list is null");
         }
         if (parameters.isEmpty()) {
             throw new IllegalArgumentException("Builders list is empty");
         }
-        ksbuilders = new ArrayList(parameters);
+        ksbuilders = Collections.unmodifiableList(new ArrayList<KeyStore.Builder>(parameters));
     }
 
     /**
@@ -72,9 +71,9 @@
      * with this parameters instance.
      * 
      * @return the unmodifiable list of {@code KeyStore.Builder}s.
-     * @since Android 1.0
      */
+    @SuppressWarnings("unchecked")
     public List getParameters() {
-        return Collections.unmodifiableList(ksbuilders);
+        return ksbuilders;
     }
 }
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/ManagerFactoryParameters.java b/libcore/x-net/src/main/java/javax/net/ssl/ManagerFactoryParameters.java
index 8909e62..b90deeb 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/ManagerFactoryParameters.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/ManagerFactoryParameters.java
@@ -20,8 +20,8 @@
 /**
  * The marker interface for key manager factory parameters. Its purpose is to
  * group key manager factory parameters objects.
- * 
- * @since Android 1.0
+ *
+ * @since 1.4
  */
 public interface ManagerFactoryParameters {
-}
\ No newline at end of file
+}
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/SSLContext.java b/libcore/x-net/src/main/java/javax/net/ssl/SSLContext.java
index 10d3a60..8a0a157 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/SSLContext.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/SSLContext.java
@@ -30,10 +30,7 @@
 /**
  * The public API for secure socket protocol implementations. It acts as factory
  * for {@code SSLSocketFactory}'s and {@code SSLEngine}s.
- * 
- * @since Android 1.0
  */
-
 public class SSLContext {
     // StoreSSLContext service name
     private static final String SERVICE = "SSLContext";
@@ -41,36 +38,9 @@
     // Used to access common engine functionality
     private static Engine engine = new Engine(SERVICE);
 
-    // Storeused provider
-    private final Provider provider;
-
-    // Storeused SSLContextSpi implementation
-    private final SSLContextSpi spiImpl;
-
-    // Storeused protocol
-    private final String protocol;
-
-    /**
-     * Creates a new {@code SSLContext}.
-     * 
-     * @param contextSpi
-     *            the implementation delegate.
-     * @param provider
-     *            the provider.
-     * @param protocol
-     *            the protocol name.
-     * @since Android 1.0
-     */
-    protected SSLContext(SSLContextSpi contextSpi, Provider provider,
-            String protocol) {
-        this.provider = provider;
-        this.protocol = protocol;
-        this.spiImpl = contextSpi;
-    }
-
     /**
      * Creates a new {@code SSLContext} instance for the specified protocol.
-     * 
+     *
      * @param protocol
      *            the requested protocol to create a context for.
      * @return the created {@code SSLContext} instance.
@@ -79,24 +49,21 @@
      * @throws NullPointerException
      *             if {@code protocol} is {@code null} (instead of
      *             NoSuchAlgorithmException as in 1.4 release)
-     * @since Android 1.0
      */
-    public static SSLContext getInstance(String protocol)
-            throws NoSuchAlgorithmException {
+    public static SSLContext getInstance(String protocol) throws NoSuchAlgorithmException {
         if (protocol == null) {
             throw new NullPointerException("protocol is null");
         }
         synchronized (engine) {
             engine.getInstance(protocol, null);
-            return new SSLContext((SSLContextSpi) engine.spi, engine.provider,
-                    protocol);
+            return new SSLContext((SSLContextSpi) engine.spi, engine.provider, protocol);
         }
     }
 
     /**
      * Creates a new {@code SSLContext} instance for the specified protocol from
      * the specified provider.
-     * 
+     *
      * @param protocol
      *            the requested protocol to create a context for.
      * @param provider
@@ -110,7 +77,6 @@
      * @throws NullPointerException
      *             if {@code protocol} is {@code null} (instead of
      *             NoSuchAlgorithmException as in 1.4 release)
-     * @since Android 1.0
      */
     public static SSLContext getInstance(String protocol, String provider)
             throws NoSuchAlgorithmException, NoSuchProviderException {
@@ -130,7 +96,7 @@
     /**
      * Creates a new {@code SSLContext} instance for the specified protocol from
      * the specified provider.
-     * 
+     *
      * @param protocol
      *            the requested protocol to create a context for
      * @param provider
@@ -142,7 +108,6 @@
      * @throws NullPointerException
      *             if {@code protocol} is {@code null} (instead of
      *             NoSuchAlgorithmException as in 1.4 release)
-     * @since Android 1.0
      */
     public static SSLContext getInstance(String protocol, Provider provider)
             throws NoSuchAlgorithmException {
@@ -158,11 +123,32 @@
         }
     }
 
+    private final Provider provider;
+
+    private final SSLContextSpi spiImpl;
+
+    private final String protocol;
+
+    /**
+     * Creates a new {@code SSLContext}.
+     *
+     * @param contextSpi
+     *            the implementation delegate.
+     * @param provider
+     *            the provider.
+     * @param protocol
+     *            the protocol name.
+     */
+    protected SSLContext(SSLContextSpi contextSpi, Provider provider, String protocol) {
+        this.provider = provider;
+        this.protocol = protocol;
+        this.spiImpl = contextSpi;
+    }
+
     /**
      * Returns the name of the secure socket protocol of this instance.
-     * 
+     *
      * @return the name of the secure socket protocol of this instance.
-     * @since Android 1.0
      */
     public final String getProtocol() {
         return protocol;
@@ -170,9 +156,8 @@
 
     /**
      * Returns the provider of this {@code SSLContext} instance.
-     * 
+     *
      * @return the provider of this {@code SSLContext} instance.
-     * @since Android 1.0
      */
     public final Provider getProvider() {
         return provider;
@@ -182,7 +167,7 @@
      * Initializes this {@code SSLContext} instance. All of the arguments are
      * optional, and the security providers will be searched for the required
      * implementations of the needed algorithms.
-     * 
+     *
      * @param km
      *            the key sources or {@code null}.
      * @param tm
@@ -191,7 +176,6 @@
      *            the randomness source or {@code null.}
      * @throws KeyManagementException
      *             if initializing this instance fails.
-     * @since Android 1.0 
      */
     public final void init(KeyManager[] km, TrustManager[] tm, SecureRandom sr)
             throws KeyManagementException {
@@ -200,9 +184,8 @@
 
     /**
      * Returns a socket factory for this instance.
-     * 
+     *
      * @return a socket factory for this instance.
-     * @since Android 1.0
      */
     public final SSLSocketFactory getSocketFactory() {
         return spiImpl.engineGetSocketFactory();
@@ -210,9 +193,8 @@
 
     /**
      * Returns a server socket factory for this instance.
-     * 
+     *
      * @return a server socket factory for this instance.
-     * @since Android 1.0
      */
     public final SSLServerSocketFactory getServerSocketFactory() {
         return spiImpl.engineGetServerSocketFactory();
@@ -220,11 +202,10 @@
 
     /**
      * Creates an {@code SSLEngine} instance from this context.
-     * 
+     *
      * @return an {@code SSLEngine} instance from this context.
      * @throws UnsupportedOperationException
      *             if the provider does not support the operation.
-     * @since Android 1.0
      */
     public final SSLEngine createSSLEngine() {
         return spiImpl.engineCreateSSLEngine();
@@ -233,7 +214,7 @@
     /**
      * Creates an {@code SSLEngine} instance from this context with the
      * specified hostname and port.
-     * 
+     *
      * @param peerHost
      *            the name of the host
      * @param peerPort
@@ -241,7 +222,6 @@
      * @return an {@code SSLEngine} instance from this context.
      * @throws UnsupportedOperationException
      *             if the provider does not support the operation.
-     * @since Android 1.0
      */
     public final SSLEngine createSSLEngine(String peerHost, int peerPort) {
         return spiImpl.engineCreateSSLEngine(peerHost, peerPort);
@@ -250,11 +230,10 @@
     /**
      * Returns the SSL session context that encapsulates the set of SSL sessions
      * that can be used for handshake of server-side SSL sockets.
-     * 
+     *
      * @return the SSL server session context for this context or {@code null}
      *         if the underlying provider does not provide an implementation of
      *         the {@code SSLSessionContext} interface.
-     * @since Android 1.0
      */
     public final SSLSessionContext getServerSessionContext() {
         return spiImpl.engineGetServerSessionContext();
@@ -263,13 +242,12 @@
     /**
      * Returns the SSL session context that encapsulates the set of SSL sessions
      * that can be used for handshake of client-side SSL sockets.
-     * 
+     *
      * @return the SSL client session context for this context or {@code null}
      *         if the underlying provider does not provide an implementation of
      *         the {@code SSLSessionContext} interface.
-     * @since Android 1.0
      */
     public final SSLSessionContext getClientSessionContext() {
         return spiImpl.engineGetClientSessionContext();
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/SSLContextSpi.java b/libcore/x-net/src/main/java/javax/net/ssl/SSLContextSpi.java
index 6b2a60e..44d2c59 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/SSLContextSpi.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/SSLContextSpi.java
@@ -20,28 +20,23 @@
 import java.security.KeyManagementException;
 import java.security.SecureRandom;
 
-
 /**
  * The <i>Service Provider Interface</i> (SPI) for the {@code SSLContext} class.
- * 
- * @since Android 1.0
  */
-
 public abstract class SSLContextSpi {
 
     /**
      * Creates a new {@code SSLContextSpi} instance.
-     * 
-     * @since Android 1.0
      */
     public SSLContextSpi() {
+        super();
     }
 
     /**
      * Initializes this {@code SSLContext} instance. All of the arguments are
      * optional, and the security providers will be searched for the required
      * implementations of the needed algorithms.
-     * 
+     *
      * @param km
      *            the key sources or {@code null}.
      * @param tm
@@ -50,31 +45,28 @@
      *            the randomness source or {@code null.}
      * @throws KeyManagementException
      *             if initializing this instance fails.
-     * @since Android 1.0 
-     */ 
-    protected abstract void engineInit(KeyManager[] km, TrustManager[] tm,
-            SecureRandom sr) throws KeyManagementException;
+     */
+    protected abstract void engineInit(KeyManager[] km, TrustManager[] tm, SecureRandom sr)
+            throws KeyManagementException;
 
     /**
      * Returns a socket factory for this instance.
-     * 
+     *
      * @return a socket factory for this instance.
-     * @since Android 1.0
      */
     protected abstract SSLSocketFactory engineGetSocketFactory();
 
     /**
      * Returns a server socket factory for this instance.
-     * 
+     *
      * @return a server socket factory for this instance.
-     * @since Android 1.0
      */
     protected abstract SSLServerSocketFactory engineGetServerSocketFactory();
 
     /**
      * Creates an {@code SSLEngine} instance from this context with the
      * specified hostname and port.
-     * 
+     *
      * @param host
      *            the name of the host
      * @param port
@@ -82,40 +74,36 @@
      * @return an {@code SSLEngine} instance from this context.
      * @throws UnsupportedOperationException
      *             if the provider does not support the operation.
-     * @since Android 1.0
      */
     protected abstract SSLEngine engineCreateSSLEngine(String host, int port);
 
     /**
      * Creates an {@code SSLEngine} instance from this context.
-     * 
+     *
      * @return an {@code SSLEngine} instance from this context.
      * @throws UnsupportedOperationException
      *             if the provider does not support the operation.
-     * @since Android 1.0
      */
     protected abstract SSLEngine engineCreateSSLEngine();
 
     /**
      * Returns the SSL session context that encapsulates the set of SSL sessions
      * that can be used for the server side of the SSL handshake.
-     * 
+     *
      * @return the SSL server session context for this context or {@code null}
      *         if the underlying provider does not provide an implementation of
      *         the {@code SSLSessionContext} interface.
-     * @since Android 1.0
      */
     protected abstract SSLSessionContext engineGetServerSessionContext();
 
     /**
      * Returns the SSL session context that encapsulates the set of SSL sessions
      * that can be used for the client side of the SSL handshake.
-     * 
+     *
      * @return the SSL client session context for this context or {@code null}
      *         if the underlying provider does not provide an implementation of
      *         the {@code SSLSessionContext} interface.
-     * @since Android 1.0
      */
     protected abstract SSLSessionContext engineGetClientSessionContext();
 
-}
\ No newline at end of file
+}
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/SSLEngine.java b/libcore/x-net/src/main/java/javax/net/ssl/SSLEngine.java
index be5d266..46e11a4 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/SSLEngine.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/SSLEngine.java
@@ -15,48 +15,62 @@
  *  limitations under the License.
  */
 
- package javax.net.ssl;
+package javax.net.ssl;
 
 import java.nio.ByteBuffer;
-import java.nio.ReadOnlyBufferException;
 
 /**
  * The abstract implementation of secure communications using SSL, TLS, or other
- * protocols. It includes the setup, handshake, and encrypt/decrypt functionality
- * needed to create a secure connection.
- * 
- * @since Android 1.0
+ * protocols. It includes the setup, handshake, and encrypt/decrypt
+ * functionality needed to create a secure connection.
+ *
+ * @since 1.5
  */
 public abstract class SSLEngine {
-    // Store host value
-    private final String host;
-
-    // Store port value
-    private final int port;
+    private final String peerHost;
+    private final int peerPort;
 
     /**
      * Creates a new {@code SSLEngine} instance.
-     * 
-     * @since Android 1.0
      */
     protected SSLEngine() {
-        host = null;
-        port = -1;
+        super();
+        peerHost = null;
+        peerPort = -1;
     }
 
     /**
      * Creates a new {@code SSLEngine} instance with the specified host and
      * port.
-     * 
+     *
      * @param host
      *            the name of the host.
      * @param port
      *            the port of the host.
-     * @since Android 1.0
      */
     protected SSLEngine(String host, int port) {
-        this.host = host;
-        this.port = port;
+        super();
+        this.peerHost = host;
+        this.peerPort = port;
+    }
+
+    /**
+     * Returns the name of the peer host.
+     *
+     * @return the name of the peer host, or {@code null} if none is available.
+     */
+    public String getPeerHost() {
+        return peerHost;
+    }
+
+    /**
+     * Returns the port number of the peer host.
+     *
+     * @return the port number of the peer host, or {@code -1} is none is
+     *         available.
+     */
+    public int getPeerPort() {
+        return peerPort;
     }
 
     /**
@@ -65,33 +79,28 @@
      * Calling this method is not needed for the initial handshake: it will be
      * called by {@code wrap} or {@code unwrap} if the initial handshake has not
      * been started yet.
-     * </p>
-     * 
+     *
      * @throws SSLException
      *             if starting the handshake fails.
      * @throws IllegalStateException
      *             if the engine does not have all the needed settings (e.g.
      *             client/server mode not set).
-     * @since Android 1.0
      */
     public abstract void beginHandshake() throws SSLException;
 
     /**
      * Notifies this engine instance that no more inbound network data will be
      * sent to this engine.
-     * 
+     *
      * @throws SSLException
      *             if this engine did not receive a needed protocol specific
      *             close notification message from the peer.
-     * @since Android 1.0
      */
     public abstract void closeInbound() throws SSLException;
 
     /**
      * Notifies this engine instance that no more outbound application data will
      * be sent to this engine.
-     * 
-     * @since Android 1.0
      */
     public abstract void closeOutbound();
 
@@ -102,84 +111,56 @@
      * that a delegated task result is needed. In this case the
      * {@link Runnable#run() run} method of the returned {@code Runnable}
      * delegated task must be called.
-     * 
+     *
      * @return a delegate task, or {@code null} if none are available.
-     * @since Android 1.0
      */
     public abstract Runnable getDelegatedTask();
 
     /**
      * Returns the SSL cipher suite names that are enabled in this engine
      * instance.
-     * 
+     *
      * @return the SSL cipher suite names that are enabled in this engine
      *         instance.
-     * @since Android 1.0
      */
     public abstract String[] getEnabledCipherSuites();
 
     /**
      * Returns the protocol version names that are enabled in this engine
      * instance.
-     * 
+     *
      * @return the protocol version names that are enabled in this engine
      *         instance.
-     * @since Android 1.0
      */
     public abstract String[] getEnabledProtocols();
 
     /**
      * Returns whether new SSL sessions may be established by this engine.
-     * 
+     *
      * @return {@code true} if new session may be established, {@code false} if
      *         existing sessions must be reused.
-     * @since Android 1.0
      */
     public abstract boolean getEnableSessionCreation();
 
     /**
      * Returns the status of the handshake of this engine instance.
-     * 
+     *
      * @return the status of the handshake of this engine instance.
-     * @since Android 1.0
      */
     public abstract SSLEngineResult.HandshakeStatus getHandshakeStatus();
 
     /**
      * Returns whether this engine instance will require client authentication.
-     * 
+     *
      * @return {@code true} if this engine will require client authentication,
      *         {@code false} if no client authentication is needed.
-     * @since Android 1.0
      */
     public abstract boolean getNeedClientAuth();
 
     /**
-     * Returns the name of the peer host.
-     * 
-     * @return the name of the peer host, or {@code null} if none is available.
-     * @since Android 1.0
-     */
-    public String getPeerHost() {
-        return host;
-    }
-
-    /**
-     * Returns the port number of the peer host.
-     * 
-     * @return the port number of the peer host, or {@code -1} is none is
-     *         available.
-     * @since Android 1.0
-     */
-    public int getPeerPort() {
-        return port;
-    }
-
-    /**
      * Returns the SSL session for this engine instance.
-     * 
+     *
      * @return the SSL session for this engine instance.
-     * @since Android 1.0
      */
     public abstract SSLSession getSession();
 
@@ -187,55 +168,49 @@
      * Returns the SSL cipher suite names that are supported by this engine.
      * These cipher suites can be enabled using
      * {@link #setEnabledCipherSuites(String[])}.
-     * 
+     *
      * @return the SSL cipher suite names that are supported by this engine.
-     * @since Android 1.0
      */
     public abstract String[] getSupportedCipherSuites();
 
     /**
      * Returns the protocol names that are supported by this engine. These
      * protocols can be enables using {@link #setEnabledProtocols(String[])}.
-     * 
+     *
      * @return the protocol names that are supported by this engine.
-     * @since Android 1.0
      */
     public abstract String[] getSupportedProtocols();
 
     /**
      * Returns whether this engine is set to act in client mode when
      * handshaking.
-     * 
+     *
      * @return {@code true} if the engine is set to do handshaking in client
      *         mode.
-     * @since Android 1.0
      */
     public abstract boolean getUseClientMode();
 
     /**
      * Returns whether this engine will request client authentication.
-     * 
+     *
      * @return {@code true} if client authentication will be requested,
      *         {@code false} otherwise.
-     * @since Android 1.0
      */
     public abstract boolean getWantClientAuth();
 
     /**
      * Returns whether no more inbound data will be accepted by this engine.
-     * 
+     *
      * @return {@code true} if no more inbound data will be accepted by this
      *         engine, {@code false} otherwise.
-     * @since Android 1.0
      */
     public abstract boolean isInboundDone();
 
     /**
      * Returns whether no more outbound data will be produced by this engine.
-     * 
+     *
      * @return {@code true} if no more outbound data will be producted by this
      *         engine, {@code otherwise} false.
-     * @since Android 1.0
      */
     public abstract boolean isOutboundDone();
 
@@ -243,13 +218,12 @@
      * Sets the SSL cipher suite names that should be enabled in this engine
      * instance. Only cipher suites listed by {@code getSupportedCipherSuites()}
      * are allowed.
-     * 
+     *
      * @param suites
      *            the SSL cipher suite names to be enabled.
      * @throws IllegalArgumentException
      *             if one of the specified cipher suites is not supported, or if
      *             {@code suites} is {@code null}.
-     * @since Android 1.0
      */
     public abstract void setEnabledCipherSuites(String[] suites);
 
@@ -257,23 +231,21 @@
      * Sets the protocol version names that should be enabled in this engine
      * instance. Only protocols listed by {@code getSupportedProtocols()} are
      * allowed.
-     * 
+     *
      * @param protocols
      *            the protocol version names to be enabled.
      * @throws IllegalArgumentException
      *             if one of the protocol version names is not supported, or if
      *             {@code protocols} is {@code null}.
-     * @since Android 1.0
      */
     public abstract void setEnabledProtocols(String[] protocols);
 
     /**
      * Sets whether new SSL sessions may be established by this engine instance.
-     * 
+     *
      * @param flag
      *            {@code true} if new SSL sessions may be established,
      *            {@code false} if existing SSL sessions must be reused.
-     * @since Android 1.0
      */
     public abstract void setEnableSessionCreation(boolean flag);
 
@@ -286,25 +258,23 @@
      * <li>no authentication needed</li>
      * </ul>
      * This method overrides the setting of {@link #setWantClientAuth(boolean)}.
-     * 
+     *
      * @param need
      *            {@code true} if client authentication is required,
      *            {@code false} if no authentication is needed.
-     * @since Android 1.0
      */
     public abstract void setNeedClientAuth(boolean need);
 
     /**
      * Sets whether this engine should act in client (or server) mode when
      * handshaking.
-     * 
+     *
      * @param mode
      *            {@code true} if this engine should act in client mode,
      *            {@code false} if not.
      * @throws IllegalArgumentException
      *             if this method is called after starting the initial
      *             handshake.
-     * @since Android 1.0
      */
     public abstract void setUseClientMode(boolean mode);
 
@@ -317,11 +287,10 @@
      * <li>no authentication needed</li>
      * </ul>
      * This method overrides the setting of {@link #setNeedClientAuth(boolean)}.
-     * 
+     *
      * @param want
      *            {@code true} if client authentication should be requested,
      *            {@code false} if no authentication is needed.
-     * @since Android 1.0
      */
     public abstract void setWantClientAuth(boolean want);
 
@@ -329,7 +298,7 @@
      * Decodes the incoming network data buffer into application data buffers.
      * If a handshake has not been started yet, it will automatically be
      * started.
-     * 
+     *
      * @param src
      *            the buffer with incoming network data
      * @param dsts
@@ -339,14 +308,14 @@
      *            the offset in the array of destination buffers to which data
      *            is to be transferred.
      * @param length
-     *            the maximum number of destination buffers to be used. 
+     *            the maximum number of destination buffers to be used.
      * @return the result object of this operation.
      * @throws SSLException
      *             if a problem occurred while processing the data.
      * @throws IndexOutOfBoundsException
      *             if {@code length} is greater than
      *             {@code dsts.length - offset}.
-     * @throws ReadOnlyBufferException
+     * @throws java.nio.ReadOnlyBufferException
      *             if one of the destination buffers is read-only.
      * @throws IllegalArgumentException
      *             if {@code src}, {@code dsts}, or one of the entries in
@@ -354,16 +323,15 @@
      * @throws IllegalStateException
      *             if the engine does not have all the needed settings (e.g.
      *             client/server mode not set).
-     * @since Android 1.0
      */
-    public abstract SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts,
-            int offset, int length) throws SSLException;
+    public abstract SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts, int offset, int length)
+            throws SSLException;
 
     /**
      * Encodes the outgoing application data buffers into the network data
      * buffer. If a handshake has not been started yet, it will automatically be
      * started.
-     * 
+     *
      * @param srcs
      *            the array of source buffers of outgoing application data.
      * @param offset
@@ -379,7 +347,7 @@
      * @throws IndexOutOfBoundsException
      *             if {@code length} is greater than
      *             {@code srcs.length - offset}.
-     * @throws ReadOnlyBufferException
+     * @throws java.nio.ReadOnlyBufferException
      *             if the destination buffer is readonly.
      * @throws IllegalArgumentException
      *             if {@code srcs}, {@code dst}, or one the entries in
@@ -387,10 +355,9 @@
      * @throws IllegalStateException
      *             if the engine does not have all the needed settings (e.g.
      *             client/server mode not set).
-     * @since Android 1.0
      */
-    public abstract SSLEngineResult wrap(ByteBuffer[] srcs, int offset,
-            int length, ByteBuffer dst) throws SSLException;
+    public abstract SSLEngineResult wrap(ByteBuffer[] srcs, int offset, int length, ByteBuffer dst)
+            throws SSLException;
 
     /**
      * Decodes the incoming network data buffer into the application data
@@ -404,26 +371,15 @@
      * @return the result object of this operation.
      * @throws SSLException
      *             if a problem occurred while processing the data.
-     * @throws ReadOnlyBufferException
+     * @throws java.nio.ReadOnlyBufferException
      *             if one of the destination buffers is read-only.
      * @throws IllegalArgumentException
      *             if {@code src} or {@code dst} is {@code null}.
      * @throws IllegalStateException
      *             if the engine does not have all the needed settings (e.g.
      *             client/server mode not set).
-     * @since Android 1.0
      */
-    public SSLEngineResult unwrap(ByteBuffer src, ByteBuffer dst)
-            throws SSLException {
-//        if (src == null) {
-//            throw new IllegalArgumentException("Byte buffer src is null");
-//        }
-//        if (dst == null) {
-//            throw new IllegalArgumentException("Byte buffer dst is null");
-//        }
-//        if (dst.isReadOnly()) {
-//            throw new ReadOnlyBufferException();
-//        }
+    public SSLEngineResult unwrap(ByteBuffer src, ByteBuffer dst) throws SSLException {
         return unwrap(src, new ByteBuffer[] { dst }, 0, 1);
     }
 
@@ -431,7 +387,7 @@
      * Decodes the incoming network data buffer into the application data
      * buffers. If a handshake has not been started yet, it will automatically
      * be started.
-     * 
+     *
      * @param src
      *            the buffer with incoming network data
      * @param dsts
@@ -440,32 +396,18 @@
      * @return the result object of this operation.
      * @throws SSLException
      *             if a problem occurred while processing the data.
-     * @throws ReadOnlyBufferException
+     * @throws java.nio.ReadOnlyBufferException
      *             if one of the destination buffers is read-only.
      * @throws IllegalArgumentException
      *             if {@code src} or {@code dsts} is {@code null}.
      * @throws IllegalStateException
      *             if the engine does not have all the needed settings (e.g.
      *             client/server mode not set).
-     * @since Android 1.0
      */
-    public SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts)
-            throws SSLException {
-//        if (src == null) {
-//            throw new IllegalArgumentException("Byte buffer src is null");
-//        }
+    public SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts) throws SSLException {
         if (dsts == null) {
             throw new IllegalArgumentException("Byte buffer array dsts is null");
         }
-//        for (int i = 0; i < dsts.length; i++) {
-//            if (dsts[i] == null) {
-//                throw new IllegalArgumentException("Byte buffer dsts[" + i
-//                        + "]  is null");
-//            }
-//            if (dsts[i].isReadOnly()) {
-//                throw new ReadOnlyBufferException();
-//            }
-//        }
         return unwrap(src, dsts, 0, dsts.length);
     }
 
@@ -481,32 +423,18 @@
      * @return the result object of this operation.
      * @throws SSLException
      *             if a problem occurred while processing the data.
-     * @throws ReadOnlyBufferException
+     * @throws java.nio.ReadOnlyBufferException
      *             if the destination buffer is readonly.
      * @throws IllegalArgumentException
      *             if {@code srcs} or {@code dst} is {@code null}.
      * @throws IllegalStateException
      *             if the engine does not have all the needed settings (e.g.
      *             client/server mode not set).
-     * @since Android 1.0
      */
-    public SSLEngineResult wrap(ByteBuffer[] srcs, ByteBuffer dst)
-            throws SSLException {
+    public SSLEngineResult wrap(ByteBuffer[] srcs, ByteBuffer dst) throws SSLException {
         if (srcs == null) {
             throw new IllegalArgumentException("Byte buffer array srcs is null");
         }
-//        for (int i = 0; i < srcs.length; i++) {
-//            if (srcs[i] == null) {
-//                throw new IllegalArgumentException("Byte buffer srcs[" + i
-//                        + "]  is null");
-//            }
-//        }
-//        if (dst == null) {
-//            throw new IllegalArgumentException("Byte buffer array dst is null");
-//        }
-//        if (dst.isReadOnly()) {
-//            throw new ReadOnlyBufferException();
-//        }
         return wrap(srcs, 0, srcs.length, dst);
     }
 
@@ -522,26 +450,15 @@
      * @return the result object of this operation.
      * @throws SSLException
      *             if a problem occurred while processing the data.
-     * @throws ReadOnlyBufferException
+     * @throws java.nio.ReadOnlyBufferException
      *             if the destination buffer is readonly.
      * @throws IllegalArgumentException
      *             if {@code src} or {@code dst} is {@code null}.
      * @throws IllegalStateException
      *             if the engine does not have all the needed settings (e.g.
      *             client/server mode not set).
-     * @since Android 1.0
      */
-    public SSLEngineResult wrap(ByteBuffer src, ByteBuffer dst)
-            throws SSLException {
-//        if (src == null) {
-//            throw new IllegalArgumentException("Byte buffer src is null");
-//        }
-//        if (dst == null) {
-//            throw new IllegalArgumentException("Byte buffer dst is null");
-//        }
-//        if (dst.isReadOnly()) {
-//            throw new ReadOnlyBufferException();
-//        }
+    public SSLEngineResult wrap(ByteBuffer src, ByteBuffer dst) throws SSLException {
         return wrap(new ByteBuffer[] { src }, 0, 1, dst);
     }
 }
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/SSLEngineResult.java b/libcore/x-net/src/main/java/javax/net/ssl/SSLEngineResult.java
index dc55836..8a98831 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/SSLEngineResult.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/SSLEngineResult.java
@@ -20,11 +20,64 @@
 /**
  * The result object describing the state of the {@code SSLEngine} produced
  * by the {@code wrap()} and {@code unwrap()} operations.
- * 
- * @since Android 1.0
  */
 public class SSLEngineResult {
-    
+
+    /**
+     * The {@code enum} describing the state of the current handshake.
+     */
+    public enum HandshakeStatus {
+        /**
+         * No handshake in progress.
+         */
+        NOT_HANDSHAKING,
+        /**
+         * The handshake is finished.
+         */
+        FINISHED,
+        /**
+         * The results of one (or more) delegated tasks are needed to continue
+         * the handshake.
+         */
+        NEED_TASK,
+        /**
+         * The engine must send data to the remote side to continue the
+         * handshake.
+         */
+        NEED_WRAP,
+        /**
+         * The engine needs to receive data from the remote side to continue the
+         * handshake.
+         */
+        NEED_UNWRAP
+    }
+
+    /**
+     * The {@code enum} describing the result of the {@code SSLEngine}
+     * operation.
+     */
+    public static enum Status {
+        /**
+         * The size of the destination buffer is too small to hold the result of
+         * the current operation.
+         */
+        BUFFER_OVERFLOW,
+        /**
+         * There were not enough bytes available in the source buffer to
+         * complete the current operation.
+         */
+        BUFFER_UNDERFLOW,
+        /**
+         * The operation closed this side of the communication or was already
+         * closed.
+         */
+        CLOSED,
+        /**
+         * The operation completed successfully.
+         */
+        OK
+    }
+
     // Store Status object
     private final SSLEngineResult.Status status;
 
@@ -40,7 +93,7 @@
     /**
      * Creates a new {@code SSLEngineResult} instance with the specified state
      * values.
-     * 
+     *
      * @param status
      *            the return value of the {@code SSLEngine} operation.
      * @param handshakeStatus
@@ -53,11 +106,9 @@
      *             if {@code status} or {@code handshakeStatus} is {@code null},
      *             or if {@code bytesConsumed} or {@code bytesProduces} are
      *             negative.
-     * @since Android 1.0
      */
     public SSLEngineResult(SSLEngineResult.Status status,
-            SSLEngineResult.HandshakeStatus handshakeStatus, int bytesConsumed,
-            int bytesProduced) {
+            SSLEngineResult.HandshakeStatus handshakeStatus, int bytesConsumed, int bytesProduced) {
         if (status == null) {
             throw new IllegalArgumentException("status is null");
         }
@@ -78,9 +129,8 @@
 
     /**
      * Returns the return value of the {@code SSLEngine} operation.
-     * 
+     *
      * @return the return value of the {@code SSLEngine} operation.
-     * @since Android 1.0
      */
     public final Status getStatus() {
         return status;
@@ -88,9 +138,8 @@
 
     /**
      * Returns the status of the current handshake.
-     * 
+     *
      * @return the status of the current handshake.
-     * @since Android 1.0
      */
     public final HandshakeStatus getHandshakeStatus() {
         return handshakeStatus;
@@ -98,9 +147,8 @@
 
     /**
      * Returns the number of bytes retrieved from the source buffer(s).
-     * 
+     *
      * @return the number of bytes retrieved from the source buffer(s).
-     * @since Android 1.0
      */
     public final int bytesConsumed() {
         return bytesConsumed;
@@ -108,106 +156,17 @@
 
     /**
      * Returns the number of bytes transferred to the destination buffer(s).
-     * 
+     *
      * @return the number of bytes transferred to the destination buffer(s).
-     * @since Android 1.0
      */
     public final int bytesProduced() {
         return bytesProduced;
     }
 
-    /**
-     * Returns a string representation of this instance.
-     * 
-     * @return a string representation of this instance.
-     * @since Android 1.0
-     */
+    @Override
     public String toString() {
-        StringBuffer sb = new StringBuffer("SSLEngineReport: Status = ");
-        sb.append(status.toString());
-        sb.append("  HandshakeStatus = ");
-        sb.append(handshakeStatus.toString());
-        sb.append("\n                 bytesConsumed = ");
-        sb.append(Integer.toString(bytesConsumed));
-        sb.append(" bytesProduced = ");
-        sb.append(Integer.toString(bytesProduced));
-        return sb.toString();
+        return "SSLEngineReport: Status = " + status + "  HandshakeStatus = " + handshakeStatus
+                + "\n                 bytesConsumed = " + bytesConsumed + " bytesProduced = "
+                + bytesProduced;
     }
-
-    /**
-     * The {@code enum} describing the state of the current handshake.
-     * 
-     * @since Android 1.0
-     */
-    public enum HandshakeStatus {
-        /**
-         * No handshake in progress.
-         * 
-         * @since Android 1.0
-         */
-        NOT_HANDSHAKING,
-        /**
-         * The handshake is finished.
-         * 
-         * @since Android 1.0
-         */
-        FINISHED,
-        /**
-         * The results of one (or more) delegated tasks are needed to continue
-         * the handshake.
-         * 
-         * @since Android 1.0
-         */
-        NEED_TASK,
-        /**
-         * The engine must send data to the remote side to continue the
-         * handshake.
-         * 
-         * @since Android 1.0
-         */
-        NEED_WRAP,
-        /**
-         * The engine needs to receive data from the remote side to continue the
-         * handshake.
-         * 
-         * @since Android 1.0
-         */
-        NEED_UNWRAP
-    }
-
-    /**
-     * The {@code enum} describing the result of the {@code SSLEngine}
-     * operation.
-     * 
-     * @since Android 1.0
-     */
-    public static enum Status {
-        /**
-         * The size of the destination buffer is too small to hold the result of
-         * the current operation.
-         * 
-         * @since Android 1.0
-         */
-        BUFFER_OVERFLOW,
-        /**
-         * There were not enough bytes available in the source buffer to
-         * complete the current operation.
-         * 
-         * @since Android 1.0
-         */
-        BUFFER_UNDERFLOW,
-        /**
-         * The operation closed this side of the communication or was already
-         * closed.
-         * 
-         * @since Android 1.0
-         */
-        CLOSED,
-        /**
-         * The operation completed successfully.
-         * 
-         * @since Android 1.0
-         */
-        OK
-    }
-}
\ No newline at end of file
+}
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/SSLException.java b/libcore/x-net/src/main/java/javax/net/ssl/SSLException.java
index 43ba493..5d716f7 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/SSLException.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/SSLException.java
@@ -21,19 +21,15 @@
 
 /**
  * The base class for all SSL related exceptions.
- * 
- * @since Android 1.0
  */
 public class SSLException extends IOException {
-
     private static final long serialVersionUID = 4511006460650708967L;
 
     /**
      * Creates a new {@code SSLException} with the specified reason.
-     * 
+     *
      * @param reason
      *            the reason for the exception.
-     * @since Android 1.0
      */
     public SSLException(String reason) {
         super(reason);
@@ -41,12 +37,11 @@
 
     /**
      * Creates a new {@code SSLException} with the specified message and cause.
-     * 
+     *
      * @param message
      *            the detail message for the exception.
      * @param cause
      *            the cause.
-     * @since Android 1.0
      */
     public SSLException(String message, Throwable cause) {
         super(message);
@@ -55,10 +50,9 @@
 
     /**
      * Creates a new {@code SSLException} with the specified cause.
-     * 
+     *
      * @param cause
      *            the cause
-     * @since Android 1.0
      */
     public SSLException(Throwable cause) {
         super(cause == null ? null : cause.toString());
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/SSLHandshakeException.java b/libcore/x-net/src/main/java/javax/net/ssl/SSLHandshakeException.java
index 81e44dc..1c17ae7 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/SSLHandshakeException.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/SSLHandshakeException.java
@@ -20,19 +20,16 @@
 /**
  * The exception that is thrown when a handshake could not be completed
  * successfully.
- * 
- * @since Android 1.0
  */
 public class SSLHandshakeException extends SSLException {
-    
+
     private static final long serialVersionUID = -5045881315018326890L;
 
     /**
      * Creates a new {@code SSLHandshakeException} with the specified message.
-     * 
+     *
      * @param reason
      *            the detail message for the exception.
-     * @since Android 1.0
      */
     public SSLHandshakeException(String reason) {
         super(reason);
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/SSLKeyException.java b/libcore/x-net/src/main/java/javax/net/ssl/SSLKeyException.java
index cc4bc84..6d81676 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/SSLKeyException.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/SSLKeyException.java
@@ -18,22 +18,19 @@
 package javax.net.ssl;
 
 /**
- * The exception that is thrown when an invalid SSL key is encountered.  
- * 
- * @since Android 1.0
+ * The exception that is thrown when an invalid SSL key is encountered.
  */
 public class SSLKeyException extends SSLException {
 
     private static final long serialVersionUID = -8071664081941937874L;
-    
+
     /**
      * Creates a new {@code SSLKeyException} with the specified message.
-     * 
+     *
      * @param reason
      *            the detail message for the exception.
-     * @since Android 1.0
      */
     public SSLKeyException(String reason) {
         super(reason);
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/SSLPeerUnverifiedException.java b/libcore/x-net/src/main/java/javax/net/ssl/SSLPeerUnverifiedException.java
index 6e5734a..bb5bd64 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/SSLPeerUnverifiedException.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/SSLPeerUnverifiedException.java
@@ -20,22 +20,19 @@
 /**
  * The exception that is thrown when the identity of a peer has not beed
  * verified.
- * 
- * @since Android 1.0
  */
 public class SSLPeerUnverifiedException extends SSLException {
-    
+
     private static final long serialVersionUID = -8919512675000600547L;
 
     /**
      * Creates a new {@code SSLPeerUnverifiedException} with the specified
      * message.
-     * 
+     *
      * @param reason
      *            the detail message for the exception.
-     * @since Android 1.0
      */
     public SSLPeerUnverifiedException(String reason) {
         super(reason);
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/SSLPermission.java b/libcore/x-net/src/main/java/javax/net/ssl/SSLPermission.java
index afc1abb..5b5c76f 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/SSLPermission.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/SSLPermission.java
@@ -23,26 +23,22 @@
  * The class representing a network permission.
  * <p>
  * The following permissions are defined, allowing the specified action:
- * </p>
  * <dl>
  * <dt> {@code "setHostnameVerifier"} </dt>
- * <dd> setting a callback object for additional verification of a hostname mismatch.</dd> 
+ * <dd> setting a callback object for additional verification of a hostname mismatch.</dd>
  * <dt> {@code "getSSLSessionContext"} </dt>
  * <dd> getting the {@code SSLSessionContext} of an {@code SSLSession}.</dd>
- * </dl> 
- * 
- * @since Android 1.0
+ * </dl>
  */
 public final class SSLPermission extends BasicPermission {
-    
+
     private static final long serialVersionUID = -3456898025505876775L;
-    
+
     /**
      * Creates a new {@code SSLPermission} with the specified name.
-     * 
+     *
      * @param name
      *            the permission name.
-     * @since Android 1.0
      */
     public SSLPermission(String name) {
         super(name);
@@ -50,14 +46,13 @@
 
     /**
      * Creates a new {@code SSLPermission} with the specified name.
-     * 
+     *
      * @param name
      *            the permission name.
      * @param actions
      *            is ignored and should be {@code null}.
-     * @since Android 1.0
      */
     public SSLPermission(String name, String actions) {
         super(name, actions);
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/SSLProtocolException.java b/libcore/x-net/src/main/java/javax/net/ssl/SSLProtocolException.java
index ef49ced..50ed74d 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/SSLProtocolException.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/SSLProtocolException.java
@@ -20,21 +20,18 @@
 /**
  * The exception that is thrown when an error in the operation of the SSL
  * protocol is encountered.
- * 
- * @since Android 1.0
  */
 public class SSLProtocolException extends SSLException {
-    
+
     private static final long serialVersionUID = 5445067063799134928L;
 
     /**
      * Creates a new {@code SSLProtocolException} with the specified message.
-     * 
+     *
      * @param reason
      *            the detail message for the exception.
-     * @since Android 1.0
      */
     public SSLProtocolException(String reason) {
         super(reason);
     }
-}
\ No newline at end of file
+}
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/SSLServerSocket.java b/libcore/x-net/src/main/java/javax/net/ssl/SSLServerSocket.java
index dc41556..8bd8918 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/SSLServerSocket.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/SSLServerSocket.java
@@ -24,20 +24,16 @@
 /**
  * The extension of {@code ServerSocket} which provides secure server sockets
  * based on protocols like SSL, TLS, or others.
- * 
- * @since Android 1.0
  */
 public abstract class SSLServerSocket extends ServerSocket {
-    
+
     /**
      * Only to be used by subclasses.
      * <p>
      * Creates a TCP server socket with the default authentication context.
-     * </p>
-     * 
+     *
      * @throws IOException
      *             if creating the socket fails.
-     * @since Android 1.0
      */
     protected SSLServerSocket() throws IOException {
         super();
@@ -49,12 +45,10 @@
      * Creates a TCP server socket on the specified port with the default
      * authentication context. The connection's default backlog size is 50
      * connections.
-     * </p>
      * @param port
      *            the port to listen on.
      * @throws IOException
      *             if creating the socket fails.
-     * @since Android 1.0
      */
     protected SSLServerSocket(int port) throws IOException {
         super(port);
@@ -65,14 +59,13 @@
      * <p>
      * Creates a TCP server socket on the specified port using the specified
      * backlog and the default authentication context.
-     * 
+     *
      * @param port
      *            the port to listen on.
      * @param backlog
      *            the number of pending connections to queue.
      * @throws IOException
      *             if creating the socket fails.
-     * @since Android 1.0
      */
     protected SSLServerSocket(int port, int backlog) throws IOException {
         super(port, backlog);
@@ -84,8 +77,7 @@
      * Creates a TCP server socket on the specified port, using the specified
      * backlog, listening on the specified interface, and using the default
      * authentication context.
-     * </p>
-     * 
+     *
      * @param port
      *            the port the listen on.
      * @param backlog
@@ -94,20 +86,17 @@
      *            the address of the interface to accept connections on.
      * @throws IOException
      *             if creating the socket fails.
-     * @since Android 1.0
      */
-    protected SSLServerSocket(int port, int backlog, InetAddress address)
-            throws IOException {
+    protected SSLServerSocket(int port, int backlog, InetAddress address) throws IOException {
         super(port, backlog, address);
     }
-    
+
     /**
      * Returns the names of the enabled cipher suites to be used for new
      * connections.
-     * 
+     *
      * @return the names of the enabled cipher suites to be used for new
      *         connections.
-     * @since Android 1.0
      */
     public abstract String[] getEnabledCipherSuites();
 
@@ -115,50 +104,45 @@
      * Sets the names of the cipher suites to be enabled for new connections.
      * Only cipher suites returned by {@link #getSupportedCipherSuites()} are
      * allowed.
-     * 
+     *
      * @param suites
      *            the names of the to be enabled cipher suites.
      * @throws IllegalArgumentException
      *             if one of the cipher suite names is not supported.
-     * @since Android 1.0
      */
     public abstract void setEnabledCipherSuites(String[] suites);
 
     /**
      * Returns the names of the supported cipher suites.
-     * 
+     *
      * @return the names of the supported cipher suites.
-     * @since Android 1.0
      */
     public abstract String[] getSupportedCipherSuites();
 
     /**
      * Returns the names of the supported protocols.
-     * 
+     *
      * @return the names of the supported protocols.
-     * @since Android 1.0
      */
     public abstract String[] getSupportedProtocols();
 
     /**
      * Returns the names of the enabled protocols to be used for new
      * connections.
-     * 
+     *
      * @return the names of the enabled protocols to be used for new
      *         connections.
-     * @since Android 1.0
      */
     public abstract String[] getEnabledProtocols();
 
     /**
      * Sets the names of the protocols to be enabled for new connections. Only
      * protocols returned by {@link #getSupportedProtocols()} are allowed.
-     * 
+     *
      * @param protocols
      *            the names of the to be enabled protocols.
      * @throws IllegalArgumentException
      *             if one of the protocols is not supported.
-     * @since Android 1.0
      */
     public abstract void setEnabledProtocols(String[] protocols);
 
@@ -171,21 +155,19 @@
      * <li>no authentication needed</li>
      * </ul>
      * This method overrides the setting of {@link #setWantClientAuth(boolean)}.
-     * 
+     *
      * @param need
      *            {@code true} if client authentication is required,
      *            {@code false} if no authentication is needed.
-     * @since Android 1.0
      */
     public abstract void setNeedClientAuth(boolean need);
 
     /**
      * Returns whether server-mode connections will be configured to require
      * client authentication.
-     * 
+     *
      * @return {@code true} if client authentication is required, {@code false}
      *         if no client authentication is needed.
-     * @since Android 1.0
      */
     public abstract boolean getNeedClientAuth();
 
@@ -198,59 +180,53 @@
      * <li>no authentication needed</li>
      * </ul>
      * This method overrides the setting of {@link #setNeedClientAuth(boolean)}.
-     * 
+     *
      * @param want
      *            {@code true} if client authentication should be requested,
      *            {@code false} if no authentication is needed.
-     * @since Android 1.0
      */
     public abstract void setWantClientAuth(boolean want);
 
     /**
      * Returns whether server-mode connections will be configured to request
      * client authentication.
-     * 
+     *
      * @return {@code true} is client authentication will be requested,
      *         {@code false} if no client authentication is needed.
-     * @since Android 1.0
      */
     public abstract boolean getWantClientAuth();
 
     /**
      * Sets whether new connections should act in client mode when handshaking.
-     * 
+     *
      * @param mode
      *            {@code true} if new connections should act in client mode,
      *            {@code false} if not.
-     * @since Android 1.0
      */
     public abstract void setUseClientMode(boolean mode);
 
     /**
      * Returns whether new connection will act in client mode when handshaking.
-     * 
+     *
      * @return {@code true} if new connections will act in client mode when
      *         handshaking, {@code false} if not.
-     * @since Android 1.0
      */
     public abstract boolean getUseClientMode();
 
     /**
      * Sets whether new SSL sessions may be established for new connections.
-     * 
+     *
      * @param flag
      *            {@code true} if new SSL sessions may be established,
      *            {@code false} if existing SSL sessions must be reused.
-     * @since Android 1.0
      */
     public abstract void setEnableSessionCreation(boolean flag);
- 
+
     /**
      * Returns whether new SSL sessions may be established for new connections.
-     * 
+     *
      * @return {@code true} if new SSL sessions may be established,
      *         {@code false} if existing SSL sessions must be reused.
-     * @since Android 1.0
      */
     public abstract boolean getEnableSessionCreation();
 }
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/SSLServerSocketFactory.java b/libcore/x-net/src/main/java/javax/net/ssl/SSLServerSocketFactory.java
index 14f467c..ccb2c5d 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/SSLServerSocketFactory.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/SSLServerSocketFactory.java
@@ -18,59 +18,46 @@
 package javax.net.ssl;
 
 import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.security.Security;
 
 import javax.net.ServerSocketFactory;
 
 /**
  * The factory for SSL server sockets.
- * 
- * @since Android 1.0
  */
 public abstract class SSLServerSocketFactory extends ServerSocketFactory {
-// TODO EXPORT CONTROL
-    
+    // TODO EXPORT CONTROL
+
     // The default SSL socket factory
     private static ServerSocketFactory defaultServerSocketFactory;
 
     private static String defaultName;
-    
-    /**
-     * Creates a new {@code SSLServerSocketFactory} instance.
-     * 
-     * @since Android 1.0
-     */
-    protected SSLServerSocketFactory() {
-        super();
-    }
 
     /**
      * Returns the default {@code SSLServerSocketFactory} instance. The default
      * implementation is defined by the security property
      * "ssl.ServerSocketFactory.provider".
-     * 
+     *
      * @return the default {@code SSLServerSocketFactory} instance.
-     * @since Android 1.0
      */
-    public static ServerSocketFactory getDefault() {
+    public static synchronized ServerSocketFactory getDefault() {
         if (defaultServerSocketFactory != null) {
             return defaultServerSocketFactory;
         }
         if (defaultName == null) {
-            AccessController.doPrivileged(new java.security.PrivilegedAction(){
-                public Object run() {
+            AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                public Void run() {
                     defaultName = Security.getProperty("ssl.ServerSocketFactory.provider");
-                    if (defaultName != null) {    
+                    if (defaultName != null) {
                         ClassLoader cl = Thread.currentThread().getContextClassLoader();
                         if (cl == null) {
                             cl = ClassLoader.getSystemClassLoader();
                         }
                         try {
-                            defaultServerSocketFactory = (ServerSocketFactory) Class
-                                    .forName(defaultName, true, cl)
-                                    .newInstance();
+                            final Class<?> ssfc = Class.forName(defaultName, true, cl);
+                            defaultServerSocketFactory = (ServerSocketFactory) ssfc.newInstance();
                         } catch (Exception e) {
-                            return e;
                         }
                     }
                     return null;
@@ -81,31 +68,36 @@
             // Try to find in providers
             SSLContext context = DefaultSSLContext.getContext();
             if (context != null) {
-                defaultServerSocketFactory = context.getServerSocketFactory();    
+                defaultServerSocketFactory = context.getServerSocketFactory();
             }
         }
         if (defaultServerSocketFactory == null) {
             // Use internal dummy implementation
-            defaultServerSocketFactory = new DefaultSSLServerSocketFactory("No ServerSocketFactory installed");
-        }    
+            defaultServerSocketFactory = new DefaultSSLServerSocketFactory(
+                    "No ServerSocketFactory installed");
+        }
         return defaultServerSocketFactory;
     }
-    
+
+    /**
+     * Creates a new {@code SSLServerSocketFactory} instance.
+     */
+    protected SSLServerSocketFactory() {
+        super();
+    }
+
     /**
      * Returns the names of the cipher suites that are enabled by default.
-     * 
+     *
      * @return the names of the cipher suites that are enabled by default
-     * @since Android 1.0
      */
     public abstract String[] getDefaultCipherSuites();
-    
+
     /**
      * Returns the list of supported cipher suites that could be enabled for an
      * SSL connection created by this factory.
-     * 
+     *
      * @return the list of supported cipher suites
-     * @since Android 1.0
      */
     public abstract String[] getSupportedCipherSuites();
-
 }
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/SSLSession.java b/libcore/x-net/src/main/java/javax/net/ssl/SSLSession.java
index 553d74f..14a312a 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/SSLSession.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/SSLSession.java
@@ -15,7 +15,6 @@
  *  limitations under the License.
  */
 
-
 package javax.net.ssl;
 
 import java.security.Principal;
@@ -24,78 +23,68 @@
 
 /**
  * The interface representing an SSL session.
- * 
- * @since Android 1.0
  */
 public interface SSLSession {
 
     /**
      * Returns the maximum size that an application buffer can be for this
      * session.
-     * 
+     *
      * @return the maximum application buffer size.
-     * @since Android 1.0
      */
     public int getApplicationBufferSize();
 
     /**
      * Returns the name of the cipher suite used in this session.
-     * 
+     *
      * @return the name of the cipher suite used in this session.
-     * @since Android 1.0
      */
     public String getCipherSuite();
 
     /**
      * Returns the time this session was created, in milliseconds since midnight
      * January 1st 1970 UTC.
-     * 
+     *
      * @return the time the session was created.
-     * @since Android 1.0
      */
     public long getCreationTime();
 
     /**
      * Returns this sessions identifier.
-     * 
+     *
      * @return this sessions identifier.
-     * @since Android 1.0
      */
     public byte[] getId();
 
     /**
      * Returns the time this session was last accessed, in milliseconds since
      * midnight January 1st 1970 UTC.
-     * 
+     *
      * @return the time this session was last accessed.
-     * @since Android 1.0
      */
     public long getLastAccessedTime();
 
     /**
      * Returns the list of certificates that were used to identify the local
      * side to the peer during the handshake.
-     * 
+     *
      * @return the list of certificates, ordered from local certificate to
      *         CA's certificates.
-     * @since Android 1.0
      */
     public Certificate[] getLocalCertificates();
 
     /**
      * Returns the principal used to identify the local side to the peer during
      * the handshake.
-     * 
+     *
      * @return the principal used to identify the local side.
-     * @since Android 1.0
      */
     public Principal getLocalPrincipal();
 
     /**
      * Returns the maximum size that a network buffer can be for this session.
-     * 
+     *
      * @return the maximum network buffer size.
-     * @since Android 1.0
      */
     public int getPacketBufferSize();
 
@@ -105,67 +94,58 @@
      * <p>
      * Note: this method exists for compatility reasons, use
      * {@link #getPeerCertificates()} instead.
-     * </p>
-     * 
+     *
      * @return the list of certificates, ordered from the identity certificate to
      *         the CA's certificates
      * @throws SSLPeerUnverifiedException
      *             if the identity of the peer is not verified.
-     * @since Android 1.0
      */
-    public X509Certificate[] getPeerCertificateChain()
-            throws SSLPeerUnverifiedException;
+    public X509Certificate[] getPeerCertificateChain() throws SSLPeerUnverifiedException;
 
     /**
      * Returns the list of certificates the peer used to identify itself during
      * the handshake.
-     * 
+     *
      * @return the list of certificates, ordered from the identity certificate to
      *         the CA's certificates.
      * @throws SSLPeerUnverifiedException
      *             if the identity of the peer is not verified.
-     * @since Android 1.0
      */
-    public Certificate[] getPeerCertificates()
-            throws SSLPeerUnverifiedException;
+    public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException;
 
     /**
      * Returns the host name of the peer of this session. The host name is not
      * authenticated.
-     * 
+     *
      * @return the host name of the peer of this session, or {@code null} if no
      *         host name is available.
-     * @since Android 1.0
      */
     public String getPeerHost();
 
     /**
      * Returns the port number of the peer of this session. The port number is
      * not authenticated.
-     * 
+     *
      * @return the port number of the peer, of {@code -1} is no port number is
      *         available.
-     * @since Android 1.0
      */
     public int getPeerPort();
 
     /**
      * Returns the principal identifying the peer during the handshake.
-     * 
+     *
      * @return the principal identifying the peer.
      * @throws SSLPeerUnverifiedException
      *             if the identity of the peer has not been verified.
-     * @since Android 1.0
      */
     public Principal getPeerPrincipal() throws SSLPeerUnverifiedException;
 
     /**
      * Returns the protocol name that is used for all connections in this
      * session.
-     * 
+     *
      * @return the protocol name that is used for all connections in this
      *         session.
-     * @since Android 1.0
      */
     public String getProtocol();
 
@@ -174,17 +154,16 @@
      * security manager is installed, the
      * {@code SSLPermission("getSSLSessionContext"} is checked with the security
      * manager.
-     * 
+     *
      * @return the context of this session or {@code null} if no context is
      *         available.
-     * @since Android 1.0
      */
     public SSLSessionContext getSessionContext();
 
     /**
      * Returns the object bound to the specified name in this session's
      * application layer data.
-     * 
+     *
      * @param name
      *            the name of the bound value.
      * @return the value bound to the specified name, or {@code null} if the
@@ -192,7 +171,6 @@
      *         access control context.
      * @throws IllegalArgumentException
      *             if {@code name} is {@code null}.
-     * @since Android 1.0
      */
     public Object getValue(String name);
 
@@ -202,11 +180,9 @@
      * <p>
      * Depending on the current access control context, the list of object names
      * may be different.
-     * </p>
-     * 
+     *
      * @return the list of the object names bound to this session's application
      *         layer data.
-     * @since Android 1.0
      */
     public String[] getValueNames();
 
@@ -215,17 +191,13 @@
      * <p>
      * No new connections can be created, but any existing connection remains
      * valid until it is closed.
-     * </p>
-     * 
-     * @since Android 1.0
      */
     public void invalidate();
 
     /**
      * Returns whether this session is valid.
-     * 
+     *
      * @return {@code true} if this session is valid, otherwise {@code false}.
-     * @since Android 1.0
      */
     public boolean isValid();
 
@@ -235,15 +207,13 @@
      * <p>
      * For bindings (new or existing) implementing the
      * {@code SSLSessionBindingListener} interface the object will be notified.
-     * </p>
-     * 
+     *
      * @param name
      *            the name to bind the object to.
      * @param value
      *            the object to bind.
      * @throws IllegalArgumentException
      *             if either {@code name} or {@code value} is {@code null}.
-     * @since Android 1.0
      */
     public void putValue(String name, Object value);
 
@@ -251,12 +221,11 @@
      * Removes the binding for the specified name in this session's application
      * layer data. If the existing binding implements the
      * {@code SSLSessionBindingListener} interface the object will be notified.
-     * 
+     *
      * @param name
      *            the binding to remove.
      * @throws IllegalArgumentException
      *             if {@code name} is {@code null}.
-     * @since Android 1.0
      */
     public void removeValue(String name);
-}
\ No newline at end of file
+}
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/SSLSessionBindingEvent.java b/libcore/x-net/src/main/java/javax/net/ssl/SSLSessionBindingEvent.java
index dbda787..19ae835 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/SSLSessionBindingEvent.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/SSLSessionBindingEvent.java
@@ -22,54 +22,54 @@
 
 /**
  * The event sent to an {@code SSLSessionBindingListener} when the listener
- * object is bound ({@link SSLSession#putValue(String, Object)}) or unbound 
+ * object is bound ({@link SSLSession#putValue(String, Object)}) or unbound
  * ({@link SSLSession#removeValue(String)}) to an {@code SSLSession}.
- * 
- * @since Android 1.0
  */
 public class SSLSessionBindingEvent extends EventObject implements Serializable {
 
+    /**
+     * The 5.0 spec. doesn't declare this serialVersionUID field In order to be compatible it is
+     * explicitly declared here
+     */
     private static final long serialVersionUID = 3989172637106345L;
 
-    private String name;
+    /**
+     * @serial include
+     */
+    private final String name;
 
     /**
      * Creates a new {@code SSLSessionBindingEvent} for the specified session
      * indicating a binding event for the specified name.
-     * 
+     *
      * @param session
      *            the session for which the event occurs.
      * @param name
      *            the name of the object being (un)bound.
-     * @since Android 1.0
      */
     public SSLSessionBindingEvent(SSLSession session, String name) {
         super(session);
         this.name = name;
     }
-    
+
     /**
      * Returns the name of the binding being added or removed.
-     * 
+     *
      * @return the name of the binding.
-     * @since Android 1.0
      */
     public String getName() {
         return name;
     }
-    
+
     /**
      * Returns the session to which the binding is added or from which it is
      * removed.
-     * 
+     *
      * @return the session to which the binding is added or from which it is
      *         removed.
-     * @since Android 1.0
      */
     public SSLSession getSession() {
-        return (SSLSession)this.source;
+        return (SSLSession) this.source;
     }
-    
 
-
-}
\ No newline at end of file
+}
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/SSLSessionBindingListener.java b/libcore/x-net/src/main/java/javax/net/ssl/SSLSessionBindingListener.java
index 7781c53..43ad745 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/SSLSessionBindingListener.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/SSLSessionBindingListener.java
@@ -21,28 +21,24 @@
 
 /**
  * The interface to be implemented by any object that requires notification when
- * data objects are bound to (or unbound from) an {@code SSLSession}. 
- * 
- * @since Android 1.0
+ * data objects are bound to (or unbound from) an {@code SSLSession}.
  */
 public interface SSLSessionBindingListener extends EventListener {
 
     /**
      * Notifies this listener when a value is bound to an {@code SSLSession}.
-     * 
+     *
      * @param event
      *            the event data.
-     * @since Android 1.0
      */
     public void valueBound(SSLSessionBindingEvent event);
 
     /**
      * Notifies this listener when a value is unbound from an {@code SSLSession}.
-     * 
+     *
      * @param event
      *            the event data.
-     * @since Android 1.0
      */
     public void valueUnbound(SSLSessionBindingEvent event);
 
-}
\ No newline at end of file
+}
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/SSLSessionContext.java b/libcore/x-net/src/main/java/javax/net/ssl/SSLSessionContext.java
index 9d831f3..154376e 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/SSLSessionContext.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/SSLSessionContext.java
@@ -20,72 +20,63 @@
 import java.util.Enumeration;
 
 /**
- * A collection of {@code SSLSession}s. 
- * 
- * @since Android 1.0
+ * A collection of {@code SSLSession}s.
  */
 public interface SSLSessionContext {
-
     /**
      * Returns an iterable of all session identifiers in this session context.
-     * 
+     *
      * @return an iterable of all session identifiers in this session context.
-     * @since Android 1.0
      */
+    @SuppressWarnings("unchecked")
     public Enumeration getIds();
 
     /**
      * Returns the session for the specified session identifier.
-     * 
+     *
      * @param sessionId
      *            the session identifier of the session to look up.
      * @return the session for the specified session identifier, or {@code null}
      *         if the specified session identifier does not refer to a session
      *         in this context.
-     * @since Android 1.0
      */
     public SSLSession getSession(byte[] sessionId);
 
     /**
      * Returns the size of the session cache for this session context.
-     * 
+     *
      * @return the size of the session cache for this session context, or
      *         {@code zero} if unlimited.
-     * @since Android 1.0
      */
     public int getSessionCacheSize();
 
     /**
      * Returns the timeout for sessions in this session context. Sessions
      * exceeding the timeout are invalidated.
-     * 
+     *
      * @return the timeout in seconds, or {@code zero} if unlimited.
-     * @since Android 1.0
      */
     public int getSessionTimeout();
 
     /**
      * Sets the size of the session cache for this session context.
-     * 
+     *
      * @param size
      *            the size of the session cache, or {@code zero} for unlimited
      *            cache size.
      * @throws IllegalArgumentException
      *             if {@code size} is negative.
-     * @since Android 1.0
      */
     public void setSessionCacheSize(int size) throws IllegalArgumentException;
 
     /**
      * Sets the timeout for sessions in this context. Sessions exceeding the
      * timeout are invalidated.
-     * 
+     *
      * @param seconds
      *            the timeout in seconds, or {@code zero} if unlimited.
      * @throws IllegalArgumentException
      *             if {@code seconds} is negative.
-     * @since Android 1.0
      */
     public void setSessionTimeout(int seconds) throws IllegalArgumentException;
-
-}
\ No newline at end of file
+}
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/SSLSocket.java b/libcore/x-net/src/main/java/javax/net/ssl/SSLSocket.java
index 7320416..4a70843 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/SSLSocket.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/SSLSocket.java
@@ -24,19 +24,14 @@
 
 /**
  * The extension of {@code Socket} providing secure protocols like SSL (Secure
- * Socket Layer") or TLS (Transport Layer Security).  
- * 
- * @since Android 1.0
+ * Socket Layer") or TLS (Transport Layer Security).
  */
 public abstract class SSLSocket extends Socket {
-    
+
     /**
      * Only to be used by subclasses.
      * <p>
      * Creates a TCP socket.
-     * </p>
-     * 
-     * @since Android 1.0
      */
     protected SSLSocket() {
         super();
@@ -47,8 +42,7 @@
      * <p>
      * Creates a TCP socket connection to the specified host at the specified
      * port.
-     * </p>
-     * 
+     *
      * @param host
      *            the host name to connect to.
      * @param port
@@ -57,10 +51,8 @@
      *             if creating the socket fails.
      * @throws UnknownHostException
      *             if the specified host is not known.
-     * @since Android 1.0
      */
-    protected SSLSocket(String host, int port) throws IOException,
-            UnknownHostException {
+    protected SSLSocket(String host, int port) throws IOException, UnknownHostException {
         super(host, port);
     }
 
@@ -69,15 +61,13 @@
      * <p>
      * Creates a TCP socket connection to the specified address at the specified
      * port.
-     * </p>
-     * 
+     *
      * @param address
      *            the address to connect to.
      * @param port
      *            the port number to connect to.
      * @throws IOException
      *             if creating the socket fails.
-     * @since Android 1.0
      */
     protected SSLSocket(InetAddress address, int port) throws IOException {
         super(address, port);
@@ -88,8 +78,7 @@
      * <p>
      * Creates a TCP socket connection to the specified host at the specified
      * port with the client side bound to the specified address and port.
-     * </p>
-     * 
+     *
      * @param host
      *            the host name to connect to.
      * @param port
@@ -102,10 +91,9 @@
      *             if creating the socket fails.
      * @throws UnknownHostException
      *             if the specified host is not known.
-     * @since Android 1.0
      */
-    protected SSLSocket(String host, int port, InetAddress clientAddress,
-            int clientPort) throws IOException, UnknownHostException {
+    protected SSLSocket(String host, int port, InetAddress clientAddress, int clientPort)
+            throws IOException, UnknownHostException {
         super(host, port, clientAddress, clientPort);
     }
 
@@ -114,8 +102,7 @@
      * <p>
      * Creates a TCP socket connection to the specified address at the specified
      * port with the client side bound to the specified address and port.
-     * </p>
-     * 
+     *
      * @param address
      *            the address to connect to.
      * @param port
@@ -126,132 +113,119 @@
      *            the client port number to bind to.
      * @throws IOException
      *             if creating the socket fails.
-     * @since Android 1.0
      */
-    protected SSLSocket(InetAddress address, int port,
-            InetAddress clientAddress, int clientPort) throws IOException {
+    protected SSLSocket(InetAddress address, int port, InetAddress clientAddress, int clientPort)
+            throws IOException {
         super(address, port, clientAddress, clientPort);
     }
-    
+
     /**
      * Returns the names of the supported cipher suites.
-     * 
+     *
      * @return the names of the supported cipher suites.
-     * @since Android 1.0
      */
     public abstract String[] getSupportedCipherSuites();
-    
+
     /**
      * Returns the names of the enabled cipher suites.
-     * 
+     *
      * @return the names of the enabled cipher suites.
-     * @since Android 1.0
      */
     public abstract String[] getEnabledCipherSuites();
-    
+
     /**
      * Sets the names of the cipher suites to be enabled.
      * Only cipher suites returned by {@link #getSupportedCipherSuites()} are
      * allowed.
-     * 
+     *
      * @param suites
      *            the names of the to be enabled cipher suites.
      * @throws IllegalArgumentException
      *             if one of the cipher suite names is not supported.
-     * @since Android 1.0
      */
     public abstract void setEnabledCipherSuites(String[] suites);
-    
+
     /**
      * Returns the names of the supported protocols.
-     * 
+     *
      * @return the names of the supported protocols.
-     * @since Android 1.0
      */
     public abstract String[] getSupportedProtocols();
-    
+
     /**
      * Returns the names of the enabled protocols.
-     * 
+     *
      * @return the names of the enabled protocols.
-     * @since Android 1.0
      */
     public abstract String[] getEnabledProtocols();
-    
+
     /**
      * Sets the names of the protocols to be enabled. Only
      * protocols returned by {@link #getSupportedProtocols()} are allowed.
-     * 
+     *
      * @param protocols
      *            the names of the to be enabled protocols.
      * @throws IllegalArgumentException
      *             if one of the protocols is not supported.
-     * @since Android 1.0
      */
     public abstract void setEnabledProtocols(String[] protocols);
-    
+
     /**
      * Returns the {@code SSLSession} for this connection. If necessary, a
      * handshake will be initiated, in which case this method will block until the handshake
      * has been established. If the handshake fails, an invalid session object
      * will be returned.
-     * 
+     *
      * @return the session object.
-     * @since Android 1.0
      */
     public abstract SSLSession getSession();
-    
+
     /**
      * Registers the specified listener to receive notification on completion of a
      * handshake on this connection.
-     * 
+     *
      * @param listener
      *            the listener to register.
      * @throws IllegalArgumentException
      *             if {@code listener} is {@code null}.
-     * @since Android 1.0
      */
     public abstract void addHandshakeCompletedListener(HandshakeCompletedListener listener);
-    
+
     /**
      * Removes the specified handshake completion listener.
-     * 
+     *
      * @param listener
      *            the listener to remove.
      * @throws IllegalArgumentException
      *             if the specified listener is not registered or {@code null}.
-     * @since Android 1.0
      */
     public abstract void removeHandshakeCompletedListener(HandshakeCompletedListener listener);
-    
+
     /**
      * Starts a new SSL handshake on this connection.
-     * 
+     *
      * @throws IOException
      *             if an error occurs.
-     * @since Android 1.0
      */
     public abstract void startHandshake() throws IOException;
-    
+
     /**
      * Sets whether this connection should act in client mode when handshaking.
-     * 
+     *
      * @param mode
      *            {@code true} if this connection should act in client mode,
      *            {@code false} if not.
-     * @since Android 1.0
      */
     public abstract void setUseClientMode(boolean mode);
-    
+
     /**
      * Returns whether this connection will act in client mode when handshaking.
-     * 
+     *
      * @return {@code true} if this connections will act in client mode when
      *         handshaking, {@code false} if not.
-     * @since Android 1.0
      */
     public abstract boolean getUseClientMode();
-    
+
     /**
      * Sets whether this connection should require client authentication. This
      * is only useful for sockets in server mode. The client authentication is
@@ -262,24 +236,22 @@
      * <li>no authentication needed</li>
      * </ul>
      * This method overrides the setting of {@link #setWantClientAuth(boolean)}.
-     * 
+     *
      * @param need
      *            {@code true} if client authentication is required,
      *            {@code false} if no authentication is needed.
-     * @since Android 1.0
      */
     public abstract void setNeedClientAuth(boolean need);
-    
+
     /**
      * Returns whether this connection requires client authentication.
      * This is only useful for sockets in server mode.
-     * 
+     *
      * @return {@code true} if client authentication is required, {@code false}
      *         if no client authentication is needed.
-     * @since Android 1.0
      */
     public abstract boolean getNeedClientAuth();
-    
+
     /**
      * Sets whether this connections should request client authentication. This
      * is only useful for sockets in server mode. The client authentication is
@@ -290,42 +262,38 @@
      * <li>no authentication needed</li>
      * </ul>
      * This method overrides the setting of {@link #setNeedClientAuth(boolean)}.
-     * 
+     *
      * @param want
      *            {@code true} if client authentication should be requested,
      *            {@code false} if not authentication is needed.
-     * @since Android 1.0
      */
     public abstract void setWantClientAuth(boolean want);
-    
+
     /**
      * Returns whether this connections will request client authentication.
-     * 
+     *
      * @return {@code true} is client authentication will be requested,
      *         {@code false} if no client authentication is needed.
-     * @since Android 1.0
      */
     public abstract boolean getWantClientAuth();
-    
+
     /**
      * Sets whether new SSL sessions may be created by this socket or if
      * existing sessions must be reused.
-     * 
+     *
      * @param flag
      *            {@code true} if new sessions may be created, otherwise
      *            {@code false}.
-     * @since Android 1.0
      */
     public abstract void setEnableSessionCreation(boolean flag);
-    
+
     /**
      * Returns whether new SSL sessions may be created by this socket or if
      * existing sessions must be reused.
-     * 
+     *
      * @return {@code true} if new sessions may be created, otherwise
      *         {@code false}.
-     * @since Android 1.0
      */
     public abstract boolean getEnableSessionCreation();
-    
-}
\ No newline at end of file
+
+}
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/SSLSocketFactory.java b/libcore/x-net/src/main/java/javax/net/ssl/SSLSocketFactory.java
index 2b7c03e..d9db099 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/SSLSocketFactory.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/SSLSocketFactory.java
@@ -20,10 +20,9 @@
 import java.io.IOException;
 import java.net.Socket;
 import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.security.Security;
 // BEGIN android-added
-import java.lang.reflect.Method;
-import java.net.UnknownHostException;
 import java.util.logging.Logger;
 // END android-added
 
@@ -31,10 +30,9 @@
 
 /**
  * The abstract factory implementation to create {@code SSLSocket}s.
- * 
- * @since Android 1.0
  */
 public abstract class SSLSocketFactory extends SocketFactory {
+    // FIXME EXPORT CONTROL
 
     // The default SSL socket factory
     private static SocketFactory defaultSocketFactory;
@@ -42,66 +40,53 @@
     private static String defaultName;
 
     /**
-     * Creates a new {@code SSLSocketFactory}.
-     * 
-     * @since Android 1.0
-     */
-    public SSLSocketFactory() {
-        super();
-    }
-
-    /**
      * Returns the default {@code SSLSocketFactory} instance. The default is
      * defined by the security property {@code 'ssl.SocketFactory.provider'}.
-     * 
+     *
      * @return the default ssl socket factory instance.
-     * @since Android 1.0
      */
-    public static SocketFactory getDefault() {
-        synchronized (SSLSocketFactory.class) {
-            if (defaultSocketFactory != null) {
-                // BEGIN android-added
-                log("SSLSocketFactory", "Using factory " + defaultSocketFactory);
-                // END android-added
-                return defaultSocketFactory;
-            }
-            if (defaultName == null) {
-                AccessController.doPrivileged(new java.security.PrivilegedAction(){
-                    public Object run() {
-                        defaultName = Security.getProperty("ssl.SocketFactory.provider");
-                        if (defaultName != null) {
-                            ClassLoader cl = Thread.currentThread().getContextClassLoader();
-                            if (cl == null) {
-                                cl = ClassLoader.getSystemClassLoader();
-                            }
-                            try {
-                                defaultSocketFactory = (SocketFactory) Class.forName(
-                                        defaultName, true, cl).newInstance();
-                             } catch (Exception e) {
-                                return e;
-                            }
-                        }
-                        return null;
-                    }
-                });
-            }
-
-            if (defaultSocketFactory == null) {
-                // Try to find in providers
-                SSLContext context = DefaultSSLContext.getContext();
-                if (context != null) {
-                    defaultSocketFactory = context.getSocketFactory();
-                }
-            }
-            if (defaultSocketFactory == null) {
-                // Use internal implementation
-                defaultSocketFactory = new DefaultSSLSocketFactory("No SSLSocketFactory installed");
-            }
+    public static synchronized SocketFactory getDefault() {
+        if (defaultSocketFactory != null) {
             // BEGIN android-added
             log("SSLSocketFactory", "Using factory " + defaultSocketFactory);
             // END android-added
             return defaultSocketFactory;
         }
+        if (defaultName == null) {
+            AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                public Void run() {
+                    defaultName = Security.getProperty("ssl.SocketFactory.provider");
+                    if (defaultName != null) {
+                        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+                        if (cl == null) {
+                            cl = ClassLoader.getSystemClassLoader();
+                        }
+                        try {
+                            final Class<?> sfc = Class.forName(defaultName, true, cl);
+                            defaultSocketFactory = (SocketFactory) sfc.newInstance();
+                        } catch (Exception e) {
+                        }
+                    }
+                    return null;
+                }
+            });
+        }
+
+        if (defaultSocketFactory == null) {
+            // Try to find in providers
+            SSLContext context = DefaultSSLContext.getContext();
+            if (context != null) {
+                defaultSocketFactory = context.getSocketFactory();
+            }
+        }
+        if (defaultSocketFactory == null) {
+            // Use internal implementation
+            defaultSocketFactory = new DefaultSSLSocketFactory("No SSLSocketFactory installed");
+        }
+            // BEGIN android-added
+            log("SSLSocketFactory", "Using factory " + defaultSocketFactory);
+            // END android-added
+        return defaultSocketFactory;
     }
 
     // BEGIN android-added
@@ -112,26 +97,31 @@
     // END android-added
 
     /**
+     * Creates a new {@code SSLSocketFactory}.
+     */
+    public SSLSocketFactory() {
+        super();
+    }
+
+    /**
      * Returns the names of the cipher suites that are enabled by default.
-     * 
+     *
      * @return the names of the cipher suites that are enabled by default.
-     * @since Android 1.0
      */
     public abstract String[] getDefaultCipherSuites();
 
     /**
      * Returns the names of the cipher suites that are supported and could be
      * enabled for an SSL connection.
-     * 
+     *
      * @return the names of the cipher suites that are supported.
-     * @since Android 1.0
      */
     public abstract String[] getSupportedCipherSuites();
 
     /**
      * Creates an {@code SSLSocket} over the specified socket that is connected
      * to the specified host at the specified port.
-     * 
+     *
      * @param s
      *            the socket.
      * @param host
@@ -145,11 +135,9 @@
      * @return the creates ssl socket.
      * @throws IOException
      *             if creating the socket fails.
-     * @throws UnknownHostException
+     * @throws java.net.UnknownHostException
      *             if the host is unknown.
-     * @since Android 1.0
      */
-    public abstract Socket createSocket(Socket s, String host, int port,
-            boolean autoClose) throws IOException;
-
+    public abstract Socket createSocket(Socket s, String host, int port, boolean autoClose)
+            throws IOException;
 }
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/TrustManager.java b/libcore/x-net/src/main/java/javax/net/ssl/TrustManager.java
index 5d8afcd..9bdb16b 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/TrustManager.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/TrustManager.java
@@ -20,11 +20,9 @@
 /**
  * The marker interface for JSSE trust managers. The purpose is to group trust
  * managers. The responsibility a trust manager is to handle the trust data used to
- * make trust decisions for deciding whether credentials of a peer should be 
+ * make trust decisions for deciding whether credentials of a peer should be
  * accepted,
  * @see TrustManagerFactory
- * 
- * @since Android 1.0
  */
 public interface TrustManager {
-}
\ No newline at end of file
+}
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/TrustManagerFactory.java b/libcore/x-net/src/main/java/javax/net/ssl/TrustManagerFactory.java
index 480eb26..6d9e4c9 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/TrustManagerFactory.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/TrustManagerFactory.java
@@ -23,18 +23,15 @@
 import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
 import java.security.NoSuchProviderException;
+import java.security.PrivilegedAction;
 import java.security.Provider;
 import java.security.Security;
 
 import org.apache.harmony.security.fortress.Engine;
 
-
-
 /**
  * The factory for {@code TrustManager}s based on {@code KeyStore} or provider
  * specific implementation.
- * 
- * @since Android 1.0
  */
 public class TrustManagerFactory {
     // Store TrustManager service name
@@ -46,49 +43,25 @@
     // Store default property name
     private static final String PROPERTYNAME = "ssl.TrustManagerFactory.algorithm";
 
-    // Store used provider
-    private final Provider provider;
-
-    // Storeused TrustManagerFactorySpi implementation
-    private final TrustManagerFactorySpi spiImpl;
-
-    // Store used algorithm
-    private final String algorithm;
-
     /**
-     * Creates a new {@code TrustManagerFactory} instance.
-     * 
-     * @param factorySpi
-     *            the implementation delegate.
-     * @param provider
-     *            the provider
-     * @param algorithm
-     *            the algorithm name.
-     * @since Android 1.0
+     * Returns the default algorithm name for the {@code TrustManagerFactory}. The
+     * default algorithm name is specified by the security property
+     * {@code 'ssl.TrustManagerFactory.algorithm'}.
+     *
+     * @return the default algorithm name.
      */
-    protected TrustManagerFactory(TrustManagerFactorySpi factorySpi,
-            Provider provider, String algorithm) {
-        this.provider = provider;
-        this.algorithm = algorithm;
-        this.spiImpl = factorySpi;
-    }
-
-    /**
-     * Returns the name of this {@code TrustManagerFactory} algorithm
-     * implementation.
-     * 
-     * @return the name of this {@code TrustManagerFactory} algorithm
-     *         implementation.
-     * @since Android 1.0
-     */
-    public final String getAlgorithm() {
-        return algorithm;
+    public static final String getDefaultAlgorithm() {
+        return AccessController.doPrivileged(new PrivilegedAction<String>() {
+            public String run() {
+                return Security.getProperty(PROPERTYNAME);
+            }
+        });
     }
 
     /**
      * Creates a new {@code TrustManagerFactory} instance for the specified
      * trust management algorithm.
-     * 
+     *
      * @param algorithm
      *            the name of the requested trust management algorithm.
      * @return a trust manager factory for the requested algorithm.
@@ -97,7 +70,6 @@
      * @throws NullPointerException
      *             if {@code algorithm} is {@code null} (instead of
      *             NoSuchAlgorithmException as in 1.4 release)
-     * @since Android 1.0
      */
     public static final TrustManagerFactory getInstance(String algorithm)
             throws NoSuchAlgorithmException {
@@ -106,15 +78,15 @@
         }
         synchronized (engine) {
             engine.getInstance(algorithm, null);
-            return new TrustManagerFactory((TrustManagerFactorySpi) engine.spi,
-                    engine.provider, algorithm);
+            return new TrustManagerFactory((TrustManagerFactorySpi) engine.spi, engine.provider,
+                    algorithm);
         }
     }
 
     /**
      * Creates a new {@code TrustManagerFactory} instance for the specified
      * trust management algorithm from the specified provider.
-     * 
+     *
      * @param algorithm
      *            the name of the requested trust management algorithm name.
      * @param provider
@@ -129,11 +101,9 @@
      * @throws NullPointerException
      *             if {@code algorithm} is {@code null} (instead of
      *             NoSuchAlgorithmException as in 1.4 release)
-     * @since Android 1.0
      */
-    public static final TrustManagerFactory getInstance(String algorithm,
-            String provider) throws NoSuchAlgorithmException,
-            NoSuchProviderException {
+    public static final TrustManagerFactory getInstance(String algorithm, String provider)
+            throws NoSuchAlgorithmException, NoSuchProviderException {
         if ((provider == null) || (provider.length() == 0)) {
             throw new IllegalArgumentException("Provider is null oe empty");
         }
@@ -147,7 +117,7 @@
     /**
      * Creates a new {@code TrustManagerFactory} instance for the specified
      * trust management algorithm from the specified provider.
-     * 
+     *
      * @param algorithm
      *            the name of the requested key management algorithm name.
      * @param provider
@@ -159,10 +129,9 @@
      * @throws NullPointerException
      *             if {@code algorithm} is {@code null} (instead of
      *             NoSuchAlgorithmException as in 1.4 release)
-     * @since Android 1.0
      */
-    public static final TrustManagerFactory getInstance(String algorithm,
-            Provider provider) throws NoSuchAlgorithmException {
+    public static final TrustManagerFactory getInstance(String algorithm, Provider provider)
+            throws NoSuchAlgorithmException {
         if (provider == null) {
             throw new IllegalArgumentException("Provider is null");
         }
@@ -171,16 +140,51 @@
         }
         synchronized (engine) {
             engine.getInstance(algorithm, provider, null);
-            return new TrustManagerFactory((TrustManagerFactorySpi) engine.spi,
-                    provider, algorithm);
+            return new TrustManagerFactory((TrustManagerFactorySpi) engine.spi, provider, algorithm);
         }
     }
 
+    // Store used provider
+    private final Provider provider;
+
+    // Store used TrustManagerFactorySpi implementation
+    private final TrustManagerFactorySpi spiImpl;
+
+    // Store used algorithm
+    private final String algorithm;
+
+    /**
+     * Creates a new {@code TrustManagerFactory} instance.
+     *
+     * @param factorySpi
+     *            the implementation delegate.
+     * @param provider
+     *            the provider
+     * @param algorithm
+     *            the algorithm name.
+     */
+    protected TrustManagerFactory(TrustManagerFactorySpi factorySpi, Provider provider,
+            String algorithm) {
+        this.provider = provider;
+        this.algorithm = algorithm;
+        this.spiImpl = factorySpi;
+    }
+
+    /**
+     * Returns the name of this {@code TrustManagerFactory} algorithm
+     * implementation.
+     *
+     * @return the name of this {@code TrustManagerFactory} algorithm
+     *         implementation.
+     */
+    public final String getAlgorithm() {
+        return algorithm;
+    }
+
     /**
      * Returns the provider for this {@code TrustManagerFactory} instance.
-     * 
+     *
      * @return the provider for this {@code TrustManagerFactory} instance.
-     * @since Android 1.0
      */
     public final Provider getProvider() {
         return provider;
@@ -189,12 +193,11 @@
     /**
      * Initializes this factory instance with the specified keystore as source
      * of certificate authorities and trust material.
-     * 
+     *
      * @param ks
      *            the keystore or {@code null}.
      * @throws KeyStoreException
      *             if the initialization fails.
-     * @since Android 1.0
      */
     public final void init(KeyStore ks) throws KeyStoreException {
         spiImpl.engineInit(ks);
@@ -203,43 +206,24 @@
     /**
      * Initializes this factory instance with the specified provider-specific
      * parameters for a source of trust material.
-     * 
+     *
      * @param spec
      *            the provider-specific parameters.
      * @throws InvalidAlgorithmParameterException
      *             if the initialization fails.
-     * @since Android 1.0
      */
-    public final void init(ManagerFactoryParameters spec)
-            throws InvalidAlgorithmParameterException {
+    public final void init(ManagerFactoryParameters spec) throws InvalidAlgorithmParameterException {
         spiImpl.engineInit(spec);
     }
 
     /**
      * Returns the list of {@code TrustManager}s with one entry for each type
      * of trust material.
-     * 
+     *
      * @return the list of {@code TrustManager}s
-     * @since Android 1.0
      */
     public final TrustManager[] getTrustManagers() {
         return spiImpl.engineGetTrustManagers();
     }
 
-    /**
-     * Returns the default algorithm name for the {@code TrustManagerFactory}. The
-     * default algorithm name is specified by the security property
-     * {@code 'ssl.TrustManagerFactory.algorithm'}.
-     * 
-     * @return the default algorithm name.
-     * @since Android 1.0
-     */
-    public static final String getDefaultAlgorithm() {
-        return AccessController
-                .doPrivileged(new java.security.PrivilegedAction<String>() {
-                    public String run() {
-                        return Security.getProperty(PROPERTYNAME);
-                    }
-                });
-    }
-}
\ No newline at end of file
+}
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/TrustManagerFactorySpi.java b/libcore/x-net/src/main/java/javax/net/ssl/TrustManagerFactorySpi.java
index 08e213e..1b04c5b 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/TrustManagerFactorySpi.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/TrustManagerFactorySpi.java
@@ -24,40 +24,35 @@
 /**
  * The <i>Service Provider Interface</i> (SPI) for the
  * {@code TrustManagerFactory} class.
- * 
- * @since Android 1.0
  */
 public abstract class TrustManagerFactorySpi {
 
     /**
      * Creates a new {@code TrustManagerFactorySpi} instance.
-     * 
-     * @since Android 1.0
      */
     public TrustManagerFactorySpi() {
+        super();
     }
 
     /**
      * Initializes this factory instance with the specified keystore as source
      * of certificate authorities and trust material.
-     * 
+     *
      * @param ks
      *            the keystore or {@code null}.
      * @throws KeyStoreException
      *             if the initialization fails.
-     * @since Android 1.0
      */
     protected abstract void engineInit(KeyStore ks) throws KeyStoreException;
 
     /**
      * Initializes this factory instance with the specified provider-specific
      * parameters for a source of trust material.
-     * 
+     *
      * @param spec
      *            the provider-specific parameters.
      * @throws InvalidAlgorithmParameterException
      *             if the initialization fails.
-     * @since Android 1.0
      */
     protected abstract void engineInit(ManagerFactoryParameters spec)
             throws InvalidAlgorithmParameterException;
@@ -65,9 +60,8 @@
     /**
      * Returns the list of {@code TrustManager}s with one entry for each type
      * of trust material.
-     * 
+     *
      * @return the list of {@code TrustManager}s
-     * @since Android 1.0
      */
     protected abstract TrustManager[] engineGetTrustManagers();
-}
\ No newline at end of file
+}
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/X509ExtendedKeyManager.java b/libcore/x-net/src/main/java/javax/net/ssl/X509ExtendedKeyManager.java
index bd5570d..3298d8e 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/X509ExtendedKeyManager.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/X509ExtendedKeyManager.java
@@ -21,27 +21,22 @@
 
 /**
  * The abstract extension for the {@code X509KeyManager} interface.
- * 
- * @since Android 1.0
  */
 public abstract class X509ExtendedKeyManager implements X509KeyManager {
-   
+
     /**
      * To be used by subclasses only.
      * <p>
      * Creates a new {@code X509ExtendedKeyManager} instance.
-     * </p>
-     * 
-     * @since Android 1.0
      */
     protected X509ExtendedKeyManager() {
         super();
     }
 
     /**
-     * Chooses a alias for the client side of an SSL connection to authenticate
+     * Chooses an alias for the client side of an SSL connection to authenticate
      * it with the specified public key type and certificate issuers.
-     * 
+     *
      * @param keyType
      *            the list of public key algorithm names.
      * @param issuers
@@ -52,7 +47,6 @@
      *            no engine is predefined.
      * @return the alias name of a matching key or {@code null} if there are no
      *         matches.
-     * @since Android 1.0
      */
     public String chooseEngineClientAlias(String[] keyType,
             Principal[] issuers, SSLEngine engine) {
@@ -60,9 +54,9 @@
     }
 
     /**
-     * Chooses a alias for the server side of an SSL connection to authenticate
+     * Chooses an alias for the server side of an SSL connection to authenticate
      * it with the specified public key type and certificate issuers.
-     * 
+     *
      * @param keyType
      *            the list of public key algorithm names.
      * @param issuers
@@ -73,11 +67,10 @@
      *            no engine is predefined.
      * @return the alias name of a matching key or {@code null} if there are no
      *         matches.
-     * @since Android 1.0
      */
     public String chooseEngineServerAlias(String keyType, Principal[] issuers,
             SSLEngine engine) {
         return null;
     }
 
-}
\ No newline at end of file
+}
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/X509KeyManager.java b/libcore/x-net/src/main/java/javax/net/ssl/X509KeyManager.java
index f65ae4e..aebc427 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/X509KeyManager.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/X509KeyManager.java
@@ -24,15 +24,13 @@
 
 /**
  * A Key Manager for X509 certificate-based key pairs.
- * 
- * @since Android 1.0
  */
 public interface X509KeyManager extends KeyManager {
 
     /**
      * Chooses an alias for the client side of an SSL connection to authenticate
      * it with the specified public key type and certificate issuers.
-     * 
+     *
      * @param keyType
      *            the list of public key algorithm names.
      * @param issuers
@@ -43,7 +41,6 @@
      *            the alias selected does not depend on a specific socket.
      * @return the alias name of a matching key or {@code null} if there are no
      *         matches.
-     * @since Android 1.0
      */
     public String chooseClientAlias(String[] keyType, Principal[] issuers,
             Socket socket);
@@ -51,7 +48,7 @@
     /**
      * Chooses an alias for the server side of an SSL connection to authenticate
      * it with the specified public key type and certificate issuers.
-     * 
+     *
      * @param keyType
      *            the list of public key algorithm type names.
      * @param issuers
@@ -62,26 +59,24 @@
      *            the alias selected does not depend on a specific socket.
      * @return the alias name of a matching key or {@code null} if there are no
      *         matches.
-     * @since Android 1.0
      */
     public String chooseServerAlias(String keyType, Principal[] issuers,
             Socket socket);
 
     /**
      * Returns the certificate chain for the specified alias.
-     * 
+     *
      * @param alias
      *            the alias to get the certificate chain for.
      * @return the certificate chain for the specified alias, or {@code null} if
      *         the alias cannot be found.
-     * @since Android 1.0
      */
     public X509Certificate[] getCertificateChain(String alias);
 
     /**
      * Returns the client aliases for the specified public key type and list of
      * certificate issuers.
-     * 
+     *
      * @param keyType
      *            the public key algorithm type name.
      * @param issuers
@@ -89,14 +84,13 @@
      *            will do.
      * @return the client aliases for the specified public key type, or
      *         {@code null} if there are no matching aliases.
-     * @since Android 1.0
      */
     public String[] getClientAliases(String keyType, Principal[] issuers);
 
     /**
      * Returns the server aliases for the specified public key type and list of
      * certificate issuers.
-     * 
+     *
      * @param keyType
      *            the public key algorithm type name.
      * @param issuers
@@ -104,18 +98,16 @@
      *            will do.
      * @return the client aliases for the specified public key type, or
      *         {@code null} if there are no matching aliases.
-     * @since Android 1.0
      */
     public String[] getServerAliases(String keyType, Principal[] issuers);
 
     /**
      * Returns the private key for the specified alias.
-     * 
+     *
      * @param alias
      *            the alias to get the private key for.
      * @return the private key for the specified alias, or {@code null} if the
      *         alias cannot be found.
-     * @since Android 1.0
      */
     public PrivateKey getPrivateKey(String alias);
-}
\ No newline at end of file
+}
diff --git a/libcore/x-net/src/main/java/javax/net/ssl/X509TrustManager.java b/libcore/x-net/src/main/java/javax/net/ssl/X509TrustManager.java
index 135c0e7..7d7827e 100644
--- a/libcore/x-net/src/main/java/javax/net/ssl/X509TrustManager.java
+++ b/libcore/x-net/src/main/java/javax/net/ssl/X509TrustManager.java
@@ -22,9 +22,7 @@
 
 /**
  * The trust manager for X509 certificates to be used to perform authentication
- * for secure sockets. 
- * 
- * @since Android 1.0
+ * for secure sockets.
  */
 public interface X509TrustManager extends TrustManager {
 
@@ -32,7 +30,7 @@
      * Checks whether the specified certificate chain (partial or complete) can
      * be validated and is trusted for client authentication for the specified
      * authentication type.
-     * 
+     *
      * @param chain
      *            the certificate chain to validate.
      * @param authType
@@ -43,7 +41,6 @@
      *             if the specified certificate chain is empty or {@code null},
      *             or if the specified authentication type is {@code null} or an
      *             empty string.
-     * @since Android 1.0
      */
     public void checkClientTrusted(X509Certificate[] chain, String authType)
             throws CertificateException;
@@ -53,7 +50,7 @@
      * Checks whether the specified certificate chain (partial or complete) can
      * be validated and is trusted for server authentication for the specified
      * key exchange algorithm.
-     * 
+     *
      * @param chain
      *            the certificate chain to validate.
      * @param authType
@@ -64,7 +61,6 @@
      *             if the specified certificate chain is empty or {@code null},
      *             or if the specified authentication type is {@code null} or an
      *             empty string.
-     * @since Android 1.0
      */
     public void checkServerTrusted(X509Certificate[] chain, String authType)
             throws CertificateException;
@@ -72,10 +68,9 @@
     /**
      * Returns the list of certificate issuer authorities which are trusted for
      * authentication of peers.
-     * 
+     *
      * @return the list of certificate issuer authorities which are trusted for
      *         authentication of peers.
-     * @since Android 1.0
      */
     public X509Certificate[] getAcceptedIssuers();
-}
\ No newline at end of file
+}
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/AlertException.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/AlertException.java
index edf7638..f607364 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/AlertException.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/AlertException.java
@@ -15,21 +15,17 @@
  *  limitations under the License.
  */
 
-/**
- * @author Alexander Y. Kleymenov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import javax.net.ssl.SSLException;
 
 /**
- * This exception is used to signalize the fatal alert
- * occured during the work of protocol.
+ * This exception is used to signal that a fatal alert has occurred while working through the
+ * protocol.
  */
 public class AlertException extends RuntimeException {
 
+    private static final long serialVersionUID = -4448327177165687581L;
     // SSLException to be thrown to application side
     private final SSLException reason;
     // alert description code
@@ -37,11 +33,11 @@
 
     /**
      * Constructs the instance.
-     * @param   description:    The alert description code.
-     * @see org.apache.harmony.xnet.provider.jsse.AlertProtocol
-     * @param   reason:  The SSLException to be thrown to application
-     * side after alert processing (sending the record with alert,
-     * shoutdown work, etc).
+     * 
+     * @param description The alert description code from {@link AlertProtocol}
+     * @param reason The SSLException to be thrown to application side after alert processing
+     *            (sending the record with alert, shutdown work, etc).
+     * @see AlertProtocol
      */
     protected AlertException(byte description, SSLException reason) {
         super(reason);
@@ -50,8 +46,8 @@
     }
 
     /**
-     * Returns the reason of alert. This reason should be rethrown
-     * after alert protcessin.
+     * Returns the reason of alert. This reason should be rethrown after alert processing.
+     * 
      * @return the reason of alert.
      */
     protected SSLException getReason() {
@@ -60,9 +56,9 @@
 
     /**
      * Returns alert's description code.
-     * @return byte value describing the occured alert.
-     * @see org.apache.harmony.xnet.provider.jsse.AlertProtocol for more information about possible
-     * reason codes.
+     * 
+     * @return alert description code from {@link AlertProtocol}
+     * @see AlertProtocol for more information about possible reason codes.
      */
     protected byte getDescriptionCode() {
         return description;
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/AlertProtocol.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/AlertProtocol.java
index 8f10875..a12d00a 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/AlertProtocol.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/AlertProtocol.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Alexander Y. Kleymenov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import org.apache.harmony.xnet.provider.jsse.SSLRecordProtocol;
@@ -136,8 +131,6 @@
      * Defines the description code of the no_renegotiation alert
      */
     protected static final byte NO_RENEGOTIATION = 100;
-
-
     // holds level and description codes
     private final byte[] alert = new byte[2];
     // record protocol to be used to wrap the alerts
@@ -271,7 +264,7 @@
     /**
      * Returns the record with reported alert message.
      * The returned array of bytes is ready to be sent to another peer.
-     * Note, that this method does not automatically set the state of allert
+     * Note, that this method does not automatically set the state of alert
      * protocol in "no alert" state, so after wrapping the method setProcessed
      * should be called.
      */
@@ -281,7 +274,7 @@
     }
 
     /**
-     * Shutdownes the protocol. It will be impossiblke to use the instance
+     * Shutdown the protocol. It will be impossible to use the instance
      * after the calling of this method.
      */
     protected void shutdown() {
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/Appendable.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/Appendable.java
index 1485bae..070f42a 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/Appendable.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/Appendable.java
@@ -15,24 +15,19 @@
  *  limitations under the License.
  */
 
-/**
- * @author Alexander Y. Kleymenov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 /**
- * This interface represents the ability of the input stream related
- * classes to provide additianal data to be read.
+ * This interface represents the ability of the input stream related classes to provide additional
+ * data to be read.
  */
 public interface Appendable {
 
     /**
      * Provides the additional data to be read.
-     * @param   src:  the source data to be appended.
+     * 
+     * @param src the source data to be appended.
      */
     public void append(byte[] src);
 
 }
-
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateMessage.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateMessage.java
index 6aac128..8065860 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateMessage.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateMessage.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Boris Kuznetsov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import org.apache.harmony.xnet.provider.jsse.Message;
@@ -28,6 +23,7 @@
 import org.apache.harmony.xnet.provider.jsse.AlertProtocol;
 
 import java.io.IOException;
+import java.security.cert.Certificate;
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
@@ -35,7 +31,6 @@
 import java.util.Vector;
 
 /**
- * 
  * Represents server/client certificate message
  * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS
  * 1.0 spec., 7.4.2. Server certificate; 7.4.6. Client certificate</a>
@@ -80,7 +75,7 @@
             fatalAlert(AlertProtocol.INTERNAL_ERROR, "INTERNAL ERROR", e);
             return;
         }
-        Vector certs_vector = new Vector();
+        Vector<Certificate> certs_vector = new Vector<Certificate>();
         int size = 0;
         int enc_size = 0;
         while (l > 0) {
@@ -141,6 +136,7 @@
      * 
      * @param out
      */
+    @Override
     public void send(HandshakeIODataStream out) {
 
         int total_length = 0;
@@ -172,6 +168,7 @@
      * 
      * @return
      */
+    @Override
     public int getType() {
         return Handshake.CERTIFICATE;
     }
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateRequest.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateRequest.java
index 8bedccd..7b27787 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateRequest.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateRequest.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Boris Kuznetsov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import org.apache.harmony.xnet.provider.jsse.Message;
@@ -110,7 +105,7 @@
         certificate_authorities = new X500Principal[size];
         int totalPrincipalsLength = 0;
         int principalLength = 0;
-        Vector principals = new Vector();
+        Vector<X500Principal> principals = new Vector<X500Principal>();
         while (totalPrincipalsLength < size) {            
             principalLength = in.readUint16(); // encoded X500Principal size
             principals.add(new X500Principal(in));
@@ -119,7 +114,7 @@
         }
         certificate_authorities = new X500Principal[principals.size()];
         for (int i = 0; i < certificate_authorities.length; i++) {
-            certificate_authorities[i] = (X500Principal) principals.elementAt(i);
+            certificate_authorities[i] = principals.elementAt(i);
         }
         this.length = 3 + certificate_types.length + totalPrincipalsLength;
         if (this.length != length) {
@@ -134,6 +129,7 @@
      * 
      * @param out
      */
+    @Override
     public void send(HandshakeIODataStream out) {
 
         out.writeUint8(certificate_types.length);
@@ -156,6 +152,7 @@
      * 
      * @return
      */
+    @Override
     public int getType() {
         return Handshake.CERTIFICATE_REQUEST;
     }
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateVerify.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateVerify.java
index 183b8aa..9b18ecb 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateVerify.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateVerify.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Boris Kuznetsov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import org.apache.harmony.xnet.provider.jsse.Message;
@@ -30,7 +25,6 @@
 import java.io.IOException;
 
 /**
- * 
  * Represents certificate verify message
  * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS 1.0 spec., 7.4.8.
  * Certificate verify</a>
@@ -83,6 +77,7 @@
      * 
      * @param out
      */
+    @Override
     public void send(HandshakeIODataStream out) {
         if (signedHash.length != 0) {
             out.writeUint16(signedHash.length);
@@ -95,6 +90,7 @@
      * 
      * @return
      */
+    @Override
     public int getType() {
         return Handshake.CERTIFICATE_VERIFY;
     }
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/CipherSuite.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/CipherSuite.java
index 8352386..f084195 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/CipherSuite.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/CipherSuite.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Boris Kuznetsov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import java.security.GeneralSecurityException;
@@ -277,29 +272,29 @@
             };
 
     // hash for quick access to cipher suite by name 
-    private static Hashtable cuitesByName;
+    private static Hashtable<String, CipherSuite> cuitesByName;
 
     /**
-     * array of supported sipher suites.
+     * array of supported cipher suites.
      * Set of supported suites is defined at the moment provider's start 
      */
-//  TODO Dinamical supported suites: new providers may be dynamically 
-//  added/removed and the set of supportes suites may be changed
+//  TODO Dynamically supported suites: new providers may be dynamically 
+//  added/removed and the set of supported suites may be changed
     static CipherSuite[] supportedCipherSuites;
 
     /**
-     * array of supported sipher suites names
+     * array of supported cipher suites names
      */
     static String[] supportedCipherSuiteNames;
 
     /**
-     * default sipher suites
+     * default cipher suites
      */
     static CipherSuite[] defaultCipherSuites;
     
     static {
         int count = 0;
-        cuitesByName = new Hashtable();
+        cuitesByName = new Hashtable<String, CipherSuite>();
         for (int i = 0; i < cuitesByCode.length; i++) {
             cuitesByName.put(cuitesByCode[i].getName(), cuitesByCode[i]);
             if (cuitesByCode[i].supported) {
@@ -353,7 +348,7 @@
      * @return
      */
     public static CipherSuite getByName(String name) {
-        return (CipherSuite) cuitesByName.get(name);
+        return cuitesByName.get(name);
     }
 
     /**
@@ -364,8 +359,8 @@
      * @return
      */
     public static CipherSuite getByCode(byte b1, byte b2) {
-        if (b1 != 0 || b2 > cuitesByCode.length) {
-            // Unknoun
+        if (b1 != 0 || (b2 & 0xFF) > cuitesByCode.length) {
+            // Unknown
             return new CipherSuite("UNKNOUN_" + b1 + "_" + b2, false, 0, "",
                     "", new byte[] { b1, b2 });
         }
@@ -383,7 +378,7 @@
      */
     public static CipherSuite getByCode(byte b1, byte b2, byte b3) {
         if (b1 == 0 && b2 == 0) {
-            if (b3 <= cuitesByCode.length) {
+            if ((b3 & 0xFF) <= cuitesByCode.length) {
                 return cuitesByCode[b3];
             }
         }
@@ -523,7 +518,7 @@
      * @return
      */
     public static String[] getSupportedCipherSuiteNames() {
-        return (String[]) supportedCipherSuiteNames.clone();
+        return supportedCipherSuiteNames.clone();
     }
 
     /**
@@ -545,6 +540,7 @@
     /**
      * Returns cipher suite description
      */
+    @Override
     public String toString() {
         return name + ": " + cipherSuiteCode[0] + " " + cipherSuiteCode[1];
     }
@@ -552,6 +548,7 @@
     /**
      * Compares this cipher suite to the specified object.
      */
+    @Override
     public boolean equals(Object obj) {
         if (obj instanceof CipherSuite
                 && this.cipherSuiteCode[0] == ((CipherSuite) obj).cipherSuiteCode[0]
@@ -610,3 +607,4 @@
     }
 
 }
+
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHandshakeImpl.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHandshakeImpl.java
index 55a06f5..b488a0e 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHandshakeImpl.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHandshakeImpl.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Boris Kuznetsov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import java.io.IOException;
@@ -52,7 +47,7 @@
  * Handshake protocol operates on top of the Record Protocol.
  * It is responsible for session negotiating.
  * 
- * The implementation proceses inbound server handshake messages,
+ * The implementation processes inbound server handshake messages,
  * creates and sends respond messages. Outbound messages are supplied 
  * to Record Protocol. Detected errors are reported to the Alert protocol.
  * 
@@ -75,6 +70,7 @@
      * Starts handshake
      *
      */  
+    @Override
     public void start() {
         if (session == null) { // initial handshake
             session = findSessionToResume();
@@ -139,9 +135,10 @@
     }
 
     /**
-     * Proceses inbound handshake messages
+     * Processes inbound handshake messages
      * @param bytes
      */
+    @Override
     public void unwrap(byte[] bytes) {
         if (this.delegatedTaskErr != null) {
             Exception e = this.delegatedTaskErr;
@@ -248,7 +245,7 @@
                     session.protocol = servProt;
                     recordProtocol.setVersion(session.protocol.version);
                     session.cipherSuite = serverHello.cipher_suite;
-                    session.id = (byte[]) serverHello.session_id.clone();
+                    session.id = serverHello.session_id.clone();
                     session.serverRandom = serverHello.random;
                     break;
                 case 11: // CERTIFICATE
@@ -285,15 +282,12 @@
                     }
                     serverHelloDone = new ServerHelloDone(io_stream, length);
                     if (this.nonBlocking) {
-                        delegatedTasks.add(new DelegatedTask(
-                                new PrivilegedExceptionAction(){ 
-                            public Object run() throws Exception {
+                        delegatedTasks.add(new DelegatedTask(new PrivilegedExceptionAction<Void>() {
+                            public Void run() throws Exception {
                                 processServerHelloDone();
                                 return null;
-                                } 
-                            },
-                            this,
-                            AccessController.getContext()));
+                            }
+                        }, this, AccessController.getContext()));
                         return;
                     }
                     processServerHelloDone();
@@ -338,6 +332,7 @@
      * @ see TLS 1.0 spec., E.1. Version 2 client hello
      * @param bytes
      */
+    @Override
     public void unwrapSSLv2(byte[] bytes) {
         unexpectedMessage();
     }
@@ -345,6 +340,7 @@
     /**
      * Creates and sends Finished message
      */
+    @Override
     protected void makeFinished() {
         byte[] verify_data;
         if (serverHello.server_version[1] == 1) {
@@ -591,8 +587,9 @@
     }
 
     /**
-     * Proceses ChangeCipherSpec message
+     * Processes ChangeCipherSpec message
      */
+    @Override
     public void receiveChangeCipherSpec() {
         if (isResuming) {
             if (serverHello == null) {
@@ -628,3 +625,4 @@
     }
 
 }
+
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHello.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHello.java
index aa811fb..5764105 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHello.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHello.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Boris Kuznetsov
-* @version $Revision$
-*/
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import java.io.IOException;
@@ -27,7 +22,6 @@
 import java.util.Arrays;
 
 /**
- * 
  * Represents Client Hello message
  * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS 1.0 spec., 7.4.1.2.
  * Client hello</a>
@@ -176,6 +170,7 @@
      * Sends message
      * @param out
      */
+    @Override
     public void send(HandshakeIODataStream out) {
         out.write(client_version);
         out.write(random);
@@ -204,6 +199,7 @@
      * Returns message type 
      * @return
      */
+    @Override
     public int getType() {
         return Handshake.CLIENT_HELLO;
     }
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientKeyExchange.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientKeyExchange.java
index a208456..af751c2 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientKeyExchange.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientKeyExchange.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Boris Kuznetsov
-* @version $Revision$
-*/
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import org.apache.harmony.xnet.provider.jsse.Message;
@@ -30,7 +25,6 @@
 import java.math.BigInteger;
 
 /**
- * 
  * Represents client key exchange message
  * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS 1.0 spec., 7.4.7.
  * Client key exchange message</a>
@@ -129,6 +123,7 @@
      * Sends message
      * @param out
      */
+    @Override
     public void send(HandshakeIODataStream out) {
         if (exchange_keys.length != 0) {    
             if (!isRSA || isTLS) {// DH or TLSv1 RSA
@@ -142,6 +137,7 @@
      * Returns message type 
      * @return
      */
+    @Override
     public int getType() {
         return Handshake.CLIENT_KEY_EXCHANGE;
     }
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionState.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionState.java
index 63bad5d..49a7af9 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionState.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionState.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Alexander Y. Kleymenov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import org.apache.harmony.xnet.provider.jsse.Logger;
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionStateSSLv3.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionStateSSLv3.java
index 078bf58..07bd340 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionStateSSLv3.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionStateSSLv3.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Alexander Y. Kleymenov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import java.security.GeneralSecurityException;
@@ -31,7 +26,7 @@
 import javax.net.ssl.SSLProtocolException;
 
 /**
- * This class incapsulates the operating environment of the SSL v3
+ * This class encapsulates the operating environment of the SSL v3
  * (http://wp.netscape.com/eng/ssl3) Record Protocol and provides 
  * relating encryption/decryption functionality. 
  * The work functionality is based on the security
@@ -218,8 +213,9 @@
     /**
      * Creates the GenericStreamCipher or GenericBlockCipher
      * data structure for specified data of specified type.
-     * @throws org.apache.harmony.xnet.provider.jsse.AlertException if alert was occured.
+     * @throws AlertException if alert was occurred.
      */
+    @Override
     protected byte[] encrypt(byte type, byte[] fragment, int offset, int len) {
         try {
             int content_mac_length = len + hash_size;
@@ -282,6 +278,7 @@
      * the specified type from the provided data.
      * @throws AlertException if alert was occured.
      */
+    @Override
     protected byte[] decrypt(byte type, byte[] fragment,
             int offset, int len) {
         // plain data of the Generic[Stream|Block]Cipher structure
@@ -344,9 +341,10 @@
     }
 
     /**
-     * Shutdownes the protocol. It will be impossiblke to use the instance
+     * Shutdown the protocol. It will be impossible to use the instance
      * after the calling of this method.
      */
+    @Override
     protected void shutdown() {
         Arrays.fill(mac_write_secret, (byte) 0);
         Arrays.fill(mac_read_secret, (byte) 0);
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionStateTLS.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionStateTLS.java
index 1b21b17..949e655 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionStateTLS.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionStateTLS.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Alexander Y. Kleymenov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import org.apache.harmony.xnet.provider.jsse.AlertException;
@@ -36,7 +31,7 @@
 import javax.net.ssl.SSLProtocolException;
 
 /**
- * This class incapsulates the operating environment of the TLS v1
+ * This class encapsulates the operating environment of the TLS v1
  * (http://www.ietf.org/rfc/rfc2246.txt) Record Protocol and provides 
  * relating encryption/decryption functionality. 
  * The work functionality is based on the security
@@ -44,7 +39,7 @@
  */
 public class ConnectionStateTLS extends ConnectionState {
 
-    // Precomputed prf label values:
+    // Pre-calculated prf label values:
     // "key expansion".getBytes()
     private static byte[] KEY_EXPANSION_LABEL = {
         (byte) 0x6B, (byte) 0x65, (byte) 0x79, (byte) 0x20, (byte) 0x65, 
@@ -235,8 +230,9 @@
     /**
      * Creates the GenericStreamCipher or GenericBlockCipher
      * data structure for specified data of specified type.
-     * @throws org.apache.harmony.xnet.provider.jsse.AlertException if alert was occured.
+     * @throws AlertException if alert was occurred.
      */
+    @Override
     protected byte[] encrypt(byte type, byte[] fragment, int offset, int len) {
         try {
             int content_mac_length = len + hash_size;
@@ -298,8 +294,9 @@
      * Retrieves the fragment of the Plaintext structure of
      * the specified type from the provided data representing
      * the Generic[Stream|Block]Cipher structure.
-     * @throws org.apache.harmony.xnet.provider.jsse.AlertException if alert was occured.
+     * @throws AlertException if alert was occurred.
      */
+    @Override
     protected byte[] decrypt(byte type, byte[] fragment,
             int offset, int len) {
         // plain data of the Generic[Stream|Block]Cipher structure
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ContentType.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ContentType.java
index dedfe64..69704f5 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ContentType.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ContentType.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Alexander Y. Kleymenov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 /**
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/DHParameters.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/DHParameters.java
index 1a441a5..441fc5f 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/DHParameters.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/DHParameters.java
@@ -14,11 +14,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-
-/**
- * @author Boris Kuznetsov
- * @version $Revision$
- */
 package org.apache.harmony.xnet.provider.jsse;
 
 /**
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/DataStream.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/DataStream.java
index b52b838..ffc8612 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/DataStream.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/DataStream.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Alexander Y. Kleymenov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 /**
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/DelegatedTask.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/DelegatedTask.java
index ea6ba78..3b2e103 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/DelegatedTask.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/DelegatedTask.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Boris Kuznetsov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import org.apache.harmony.xnet.provider.jsse.HandshakeProtocol;
@@ -35,7 +30,7 @@
 public class DelegatedTask implements Runnable {
 
     private final HandshakeProtocol handshaker;
-    private final PrivilegedExceptionAction action;
+    private final PrivilegedExceptionAction<Void> action;
     private final AccessControlContext  context;
     
     /**
@@ -44,7 +39,7 @@
      * @param handshaker
      * @param context
      */
-    public DelegatedTask(PrivilegedExceptionAction action, HandshakeProtocol handshaker, AccessControlContext  context) {
+    public DelegatedTask(PrivilegedExceptionAction<Void> action, HandshakeProtocol handshaker, AccessControlContext  context) {
         this.action = action;
         this.handshaker = handshaker;
         this.context = context;
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/DigitalSignature.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/DigitalSignature.java
index a8794df..a0f18b4 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/DigitalSignature.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/DigitalSignature.java
@@ -14,26 +14,26 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-
-/**
- * @author Boris Kuznetsov
- * @version $Revision$
- */
 package org.apache.harmony.xnet.provider.jsse;
 
-import org.apache.harmony.xnet.provider.jsse.AlertException;
-
+import java.security.DigestException;
+import java.security.InvalidKeyException;
 import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
 import java.security.Signature;
+import java.security.SignatureException;
 import java.security.cert.Certificate;
 import java.util.Arrays;
 
+import javax.crypto.BadPaddingException;
 import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
 import javax.net.ssl.SSLException;
 
 /**
- * This class represents Signature type, as descrybed in TLS v 1.0 Protocol
+ * This class represents Signature type, as described in TLS v 1.0 Protocol
  * specification, 7.4.3. It allow to init, update and sign hash. Hash algorithm
  * depends on SignatureAlgorithm.
  * 
@@ -56,10 +56,10 @@
  */
 public class DigitalSignature {
 
-    private MessageDigest md5 = null;
-    private MessageDigest sha = null;
-    private Signature signature = null;
-    private Cipher cipher = null;
+    private final MessageDigest md5;
+    private final MessageDigest sha;
+    private final Signature signature;
+    private final Cipher cipher;
     
     private byte[] md5_hash;
     private byte[] sha_hash;
@@ -69,33 +69,35 @@
      * @param keyExchange
      */
     public DigitalSignature(int keyExchange) {
-        try { 
+        try {
+            sha = MessageDigest.getInstance("SHA-1");
+            
             if (keyExchange == CipherSuite.KeyExchange_RSA_EXPORT ||
                     keyExchange == CipherSuite.KeyExchange_RSA ||
                     keyExchange == CipherSuite.KeyExchange_DHE_RSA ||
                     keyExchange == CipherSuite.KeyExchange_DHE_RSA_EXPORT) {
                 // SignatureAlgorithm is rsa
                 md5 = MessageDigest.getInstance("MD5");
-                sha = MessageDigest.getInstance("SHA-1");
                 cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
+                signature = null;
             } else if (keyExchange == CipherSuite.KeyExchange_DHE_DSS ||
                     keyExchange == CipherSuite.KeyExchange_DHE_DSS_EXPORT ) {
                 // SignatureAlgorithm is dsa
-                sha = MessageDigest.getInstance("SHA-1");
                 signature = Signature.getInstance("NONEwithDSA");
-// The Signature should be empty in case of anonimous signature algorithm:
-//            } else if (keyExchange == CipherSuite.KeyExchange_DH_anon ||
-//                    keyExchange == CipherSuite.KeyExchange_DH_anon_EXPORT) {            
-//
+                cipher = null;
+                md5 = null;
+            } else {
+                cipher = null;
+                signature = null;
+                md5 = null;
             }
-        } catch (Exception e) {
-            throw new AlertException(
-                    AlertProtocol.INTERNAL_ERROR,
-                    new SSLException(
-                            "INTERNAL ERROR: Unexpected exception on digital signature",
-                            e));
-        }    
-            
+        } catch (NoSuchAlgorithmException e) {
+            // this should never happen
+            throw new AssertionError(e);
+        } catch (NoSuchPaddingException e) {
+            // this should never happen
+            throw new AssertionError(e);
+        }
     }
     
     /**
@@ -109,8 +111,9 @@
             } else if (cipher != null) {
                 cipher.init(Cipher.ENCRYPT_MODE, key);
             }
-        } catch (Exception e){
-            e.printStackTrace();
+        } catch (InvalidKeyException e){
+            throw new AlertException(AlertProtocol.BAD_CERTIFICATE,
+                    new SSLException("init - invalid private key", e));
         }
     }
     
@@ -125,8 +128,9 @@
             } else if (cipher != null) {
                 cipher.init(Cipher.DECRYPT_MODE, cert);
             }
-        } catch (Exception e){
-            e.printStackTrace();
+        } catch (InvalidKeyException e){
+            throw new AlertException(AlertProtocol.BAD_CERTIFICATE,
+                    new SSLException("init - invalid certificate", e));
         }
     }
     
@@ -135,16 +139,12 @@
      * @param data
      */
     public void update(byte[] data) {
-        try {
-            if (sha != null) {
-                sha.update(data);
-            }
-            if (md5 != null) {
-                md5.update(data);
-            }
-        } catch (Exception e){
-            e.printStackTrace();
-        }        
+        if (sha != null) {
+            sha.update(data);
+        }
+        if (md5 != null) {
+            md5.update(data);
+        }
     }
     
     /**
@@ -197,10 +197,15 @@
                 return cipher.doFinal();
             } 
             return new byte[0];
-        } catch (Exception e){
-            e.printStackTrace();
+        } catch (DigestException e){
             return new byte[0];
-        }    
+        } catch (SignatureException e){
+            return new byte[0];
+        } catch (BadPaddingException e){
+            return new byte[0];
+        } catch (IllegalBlockSizeException e){
+            return new byte[0];
+        }
     }
 
     /**
@@ -209,34 +214,40 @@
      * @return true if verified
      */
     public boolean verifySignature(byte[] data) {
-        try {
-            if (signature != null) {
+        if (signature != null) {
+            try {
                 return signature.verify(data);
-            } else if (cipher != null) {
-                byte[] decrypt = cipher.doFinal(data);
-                byte[] md5_sha;
-                if (md5_hash != null && sha_hash != null) {
-                    md5_sha = new byte[md5_hash.length + sha_hash.length];
-                    System.arraycopy(md5_hash, 0, md5_sha, 0, md5_hash.length);
-                    System.arraycopy(sha_hash, 0, md5_sha, md5_hash.length, sha_hash.length);
-                } else if (md5_hash != null) {
-                    md5_sha = md5_hash;
-                } else {
-                    md5_sha = sha_hash;
-                }
-                if (Arrays.equals(decrypt, md5_sha)) {
-                    return true;
-                } else {
-                    return false;
-                }
-            } else if (data == null || data.length == 0) {
-                return true;
-            } else {
+            } catch (SignatureException e) {
                 return false;
             }
-        } catch (Exception e){
-                e.printStackTrace();
+        }
+        
+        if (cipher != null) {
+            final byte[] decrypt;
+            try {
+                decrypt = cipher.doFinal(data);
+            } catch (IllegalBlockSizeException e) {
                 return false;
+            } catch (BadPaddingException e) {
+                return false;
+            }
+            
+            final byte[] md5_sha;
+            if (md5_hash != null && sha_hash != null) {
+                md5_sha = new byte[md5_hash.length + sha_hash.length];
+                System.arraycopy(md5_hash, 0, md5_sha, 0, md5_hash.length);
+                System.arraycopy(sha_hash, 0, md5_sha, md5_hash.length, sha_hash.length);
+            } else if (md5_hash != null) {
+                md5_sha = md5_hash;
+            } else {
+                md5_sha = sha_hash;
+            }
+            
+            return Arrays.equals(decrypt, md5_sha);
+        } else if (data == null || data.length == 0) {
+            return true;
+        } else {
+            return false;
         }
     }
 
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/EndOfBufferException.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/EndOfBufferException.java
index b2bcafe..1dcdd20 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/EndOfBufferException.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/EndOfBufferException.java
@@ -15,25 +15,18 @@
  *  limitations under the License.
  */
 
-/**
- * @author Alexander Y. Kleymenov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import java.io.IOException;
 
 /**
- * This class represents the exception signalizing that
- * data could not be read from the stream because
- * underlying input stream reached its end.
+ * This exception indicates that data could not be read from the stream because the underlying input
+ * stream reached its end.
  */
 public class EndOfBufferException extends IOException {
 
-    /**
-     * Constructor
-     */
+    private static final long serialVersionUID = 1838636631255369519L;
+
     public EndOfBufferException() {
         super();
     }
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/EndOfSourceException.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/EndOfSourceException.java
index fbc1eaf..631679a 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/EndOfSourceException.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/EndOfSourceException.java
@@ -15,28 +15,20 @@
  *  limitations under the License.
  */
 
-/**
- * @author Alexander Y. Kleymenov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import java.io.IOException;
 
 /**
- * This class represents the exception signalizing that
- * data could not be read from the buffered stream because
- * underlying data buffer was exhausted.
+ * This exception indicates that data could not be read from the buffered stream because underlying
+ * data buffer was exhausted.
  */
 public class EndOfSourceException extends IOException {
 
-    /**
-     * Constructor
-     */
+    private static final long serialVersionUID = -4673611435974054413L;
+
     public EndOfSourceException() {
         super();
     }
 
 }
-
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/Finished.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/Finished.java
index d0f1fe1..6b555c6 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/Finished.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/Finished.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Boris Kuznetsov
-* @version $Revision$
-*/
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import org.apache.harmony.xnet.provider.jsse.Message;
@@ -63,6 +58,7 @@
         }
     }
 
+    @Override
     public void send(HandshakeIODataStream out) {
         out.write(data);
     }
@@ -71,6 +67,7 @@
      * Returns message type 
      * @return
      */
+    @Override
     public int getType() {
         return Handshake.FINISHED;
     }
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/Handshake.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/Handshake.java
index 4668b8c..64e73dd 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/Handshake.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/Handshake.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Boris Kuznetsov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 /**
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeIODataStream.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeIODataStream.java
index b5c4553..74cc27d 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeIODataStream.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeIODataStream.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Alexander Y. Kleymenov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import org.apache.harmony.xnet.provider.jsse.AlertException;
@@ -101,14 +96,17 @@
     // position of the last byte to read + 1
     private int read_pos_end;
 
+    @Override
     public int available() {
         return read_pos_end - read_pos;
     }
 
+    @Override
     public boolean markSupported() {
         return true;
     }
 
+    @Override
     public void mark(int limit) {
         marked_pos = read_pos;
     }
@@ -117,6 +115,7 @@
         marked_pos = read_pos;
     }
 
+    @Override
     public void reset() {
         read_pos = marked_pos;
     }
@@ -138,6 +137,7 @@
      * @param   byte:   byte
      * @return
      */
+    @Override
     public int read() throws IOException {
         if (read_pos == read_pos_end) {
             //return -1;
@@ -151,6 +151,7 @@
      * @param   new:    long
      * @return
      */
+    @Override
     public byte[] read(int length) throws IOException {
         if (length > available()) {
             throw new EndOfBufferException();
@@ -161,6 +162,7 @@
         return res;
     }
 
+    @Override
     public int read(byte[] dest, int offset, int length) throws IOException {
         if (length > available()) {
             throw new EndOfBufferException();
@@ -174,7 +176,7 @@
 
     /**
      * Appends the income data to be read by handshake protocol.
-     * The attempts to overflow the buffer by meens of this methos
+     * The attempts to overflow the buffer by means of this methods
      * seem to be futile because of:
      * 1. The SSL protocol specifies the maximum size of the record
      * and record protocol does not pass huge messages. 
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeProtocol.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeProtocol.java
index 606e5c7..6579398 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeProtocol.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeProtocol.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Boris Kuznetsov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import java.math.BigInteger;
@@ -89,7 +84,7 @@
     /**
      * Delegated tasks for this handshake implementation
      */
-    protected Vector delegatedTasks = new Vector();
+    protected Vector<DelegatedTask> delegatedTasks = new Vector<DelegatedTask>();
     
     /**
      * Indicates non-blocking handshake
@@ -169,13 +164,13 @@
         if (owner instanceof SSLEngineImpl) {
             engineOwner = (SSLEngineImpl) owner;
             nonBlocking = true;
-            this.parameters = (SSLParameters) engineOwner.sslParameters;
+            this.parameters = engineOwner.sslParameters;
         }
         // BEGIN android-removed
         // else if (owner instanceof SSLSocketImpl) {
         //     socketOwner = (SSLSocketImpl) owner;
         //     nonBlocking = false;
-        //     this.parameters = (SSLParameters) socketOwner.sslParameters;
+        //     this.parameters = socketOwner.sslParameters;
         // }
         // END android-removed
     }
@@ -482,11 +477,8 @@
     public Runnable getTask() {
         if (delegatedTasks.isEmpty()) {
             return null;
-        } else {
-            Runnable task = (Runnable)delegatedTasks.firstElement();
-            delegatedTasks.remove(0);
-            return task;
         }
+        return delegatedTasks.remove(0);
     }
     
     /**
@@ -523,7 +515,7 @@
             mod = ((RSAKey) pk).getModulus();
         } else {
             KeyFactory kf = KeyFactory.getInstance("RSA");
-            mod = ((RSAPublicKeySpec) kf.getKeySpec(pk, RSAPublicKeySpec.class))
+            mod = kf.getKeySpec(pk, RSAPublicKeySpec.class)
                     .getModulus();
         }
         return mod.bitLength();
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/HelloRequest.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/HelloRequest.java
index 2ce4061..40d4a71 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/HelloRequest.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/HelloRequest.java
@@ -15,10 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Boris Kuznetsov
-* @version $Revision$
-*/
 package org.apache.harmony.xnet.provider.jsse;
 
 import org.apache.harmony.xnet.provider.jsse.Message;
@@ -60,9 +56,11 @@
      * Sends message
      * @param out
      */
+    @Override
     public void send(HandshakeIODataStream out) {
     }
 
+    @Override
     public int length() {
         return 0;
     } 
@@ -71,6 +69,7 @@
      * Returns message type 
      * @return
      */
+    @Override
     public int getType() {
         return Handshake.HELLO_REQUEST;
     }
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/JSSEProvider.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/JSSEProvider.java
index e65f832..33b0a45 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/JSSEProvider.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/JSSEProvider.java
@@ -15,14 +15,10 @@
  *  limitations under the License.
  */
 
-/**
- * @author Alexander Y. Kleymenov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.security.Provider;
 
 /**
@@ -67,7 +63,7 @@
  *     TLS_DH_anon_WITH_DES_CBC_SHA
  *     TLS_DH_anon_WITH_3DES_EDE_CBC_SHA
  * 
- * The real set of availible cipher suites depends on set of availible 
+ * The real set of available cipher suites depends on set of available 
  * crypto algorithms. These algorithms must be provided by some crypto
  * provider.
  * 
@@ -108,17 +104,16 @@
  */
 public final class JSSEProvider extends Provider {
 
+    private static final long serialVersionUID = 3075686092260669675L;
+
     public JSSEProvider() {
         super("HarmonyJSSE", 1.0, "Harmony JSSE Provider");
-        AccessController.doPrivileged(new java.security.PrivilegedAction<Void>() {
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
             public Void run() {
-                put("SSLContext.TLS",
-                        "org.apache.harmony.xnet.provider.jsse.SSLContextImpl");
+                put("SSLContext.TLS", SSLContextImpl.class.getName());
                 put("Alg.Alias.SSLContext.TLSv1", "TLS");
-                put("KeyManagerFactory.X509",
-                        "org.apache.harmony.xnet.provider.jsse.KeyManagerFactoryImpl");
-                put("TrustManagerFactory.X509",
-                        "org.apache.harmony.xnet.provider.jsse.TrustManagerFactoryImpl");
+                put("KeyManagerFactory.X509", KeyManagerFactoryImpl.class.getName());
+                put("TrustManagerFactory.X509", TrustManagerFactoryImpl.class.getName());
                 // BEGIN android-added
                 put("MessageDigest.SHA-1", "org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK$SHA1");
                 put("Alg.Alias.MessageDigest.SHA1", "SHA-1");
@@ -138,4 +133,3 @@
         });
     }
 }
-
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/KeyManagerFactoryImpl.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/KeyManagerFactoryImpl.java
index 1daf80c..3b55299 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/KeyManagerFactoryImpl.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/KeyManagerFactoryImpl.java
@@ -14,11 +14,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-
-/**
- * @author Boris Kuznetsov
- * @version $Revision$
- */
 package org.apache.harmony.xnet.provider.jsse;
 
 import java.io.File;
@@ -53,13 +48,14 @@
      * @see javax.net.ssl.KeyManagerFactorySpi#engineInit(KeyStore ks, char[]
      *      password)
      */
+    @Override
     public void engineInit(KeyStore ks, char[] password)
             throws KeyStoreException, NoSuchAlgorithmException,
             UnrecoverableKeyException {
         if (ks != null) {
             keyStore = ks;
             if (password != null) {
-                pwd = (char[]) password.clone();
+                pwd = password.clone();
             } else {
                 pwd = new char[0];
             }
@@ -115,6 +111,7 @@
      * @see javax.net.ssl.KeyManagerFactorySpi#engineInit(ManagerFactoryParameters
      *      spec)
      */
+    @Override
     public void engineInit(ManagerFactoryParameters spec)
             throws InvalidAlgorithmParameterException {
         throw new InvalidAlgorithmParameterException(
@@ -125,6 +122,7 @@
     /**
      * @see javax.net.ssl.KeyManagerFactorySpi#engineGetKeyManagers()
      */
+    @Override
     public KeyManager[] engineGetKeyManagers() {
         if (keyStore == null) {
             throw new IllegalStateException("KeyManagerFactory is not initialized");
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/KeyManagerImpl.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/KeyManagerImpl.java
index b7451d5..f63170f 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/KeyManagerImpl.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/KeyManagerImpl.java
@@ -14,11 +14,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-
-/**
- * @author Boris Kuznetsov
- * @version $Revision$
- */
 package org.apache.harmony.xnet.provider.jsse;
 
 import java.net.Socket;
@@ -28,6 +23,7 @@
 import java.security.Principal;
 import java.security.PrivateKey;
 import java.security.UnrecoverableEntryException;
+import java.security.KeyStore.PrivateKeyEntry;
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
 import java.util.Enumeration;
@@ -40,11 +36,11 @@
 
 /**
  * KeyManager implementation.
- * This implementation uses hashed key store information.
- * It works faster than retrieving all of the data from the key store.
- * Any key store changes, that happen after key manager was created, have no effect.
- * The implementation does not use peer information (host, port)
- * that may be obtained from socket or engine.
+ * 
+ * This implementation uses hashed key store information. It works faster than retrieving all of the
+ * data from the key store. Any key store changes, that happen after key manager was created, have
+ * no effect. The implementation does not use peer information (host, port) that may be obtained
+ * from socket or engine.
  * 
  * @see javax.net.ssl.KeyManager
  * 
@@ -52,7 +48,7 @@
 public class KeyManagerImpl extends X509ExtendedKeyManager {
 
     // hashed key store information
-    private final Hashtable hash = new Hashtable();
+    private final Hashtable<String, PrivateKeyEntry> hash;
 
     /**
      * Creates Key manager
@@ -61,21 +57,20 @@
      * @param pwd
      */
     public KeyManagerImpl(KeyStore keyStore, char[] pwd) {
-        String alias;
-        KeyStore.PrivateKeyEntry entry;
-        Enumeration aliases;
+        super();
+        this.hash = new Hashtable<String, PrivateKeyEntry>();
+        final Enumeration<String> aliases;
         try {
             aliases = keyStore.aliases();
         } catch (KeyStoreException e) {
             return;
         }
         for (; aliases.hasMoreElements();) {
-            alias = (String) aliases.nextElement();          
+            final String alias = aliases.nextElement();
             try {
-                if (keyStore.entryInstanceOf(alias,
-                        KeyStore.PrivateKeyEntry.class)) {
-                    entry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias,
-                            new KeyStore.PasswordProtection(pwd));
+                if (keyStore.entryInstanceOf(alias, KeyStore.PrivateKeyEntry.class)) {
+                    final KeyStore.PrivateKeyEntry entry = (KeyStore.PrivateKeyEntry) keyStore
+                            .getEntry(alias, new KeyStore.PasswordProtection(pwd));
                     hash.put(alias, entry);
                 }
             } catch (KeyStoreException e) {
@@ -86,41 +81,18 @@
                 continue;
             }
         }
-
     }
 
-    /**
-     * @see javax.net.ssl.X509ExtendedKeyManager#chooseClientAlias(String[]
-     *      keyType, Principal[] issuers, Socket socket)
-     */
-    public String chooseClientAlias(String[] keyType, Principal[] issuers,
-            Socket socket) {
-        String[] al = chooseAlias(keyType, issuers);
-        if (al != null) {
-            return al[0];
-        } else {
-            return null;
-        }
+    public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) {
+        final String[] al = chooseAlias(keyType, issuers);
+        return (al == null ? null : al[0]);
     }
 
-    /**
-     * @see javax.net.ssl.X509ExtendedKeyManager#chooseServerAlias(String
-     *      keyType, Principal[] issuers, Socket socket)
-     */
-    public String chooseServerAlias(String keyType, Principal[] issuers,
-            Socket socket) {
-        String[] al = chooseAlias(new String[] { keyType }, issuers);
-        if (al != null) {
-            return al[0];
-        } else {
-            return null;
-        }
+    public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
+        final String[] al = chooseAlias(new String[] { keyType }, issuers);
+        return (al == null ? null : al[0]);
     }
 
-    /**
-     * @see javax.net.ssl.X509ExtendedKeyManager#getCertificateChain(String
-     *      alias)
-     */
     public X509Certificate[] getCertificateChain(String alias) {
         // BEGIN android-changed
         if (alias == null) {
@@ -128,8 +100,7 @@
         }
         // END android-changed
         if (hash.containsKey(alias)) {
-            Certificate[] certs = ((KeyStore.PrivateKeyEntry) hash.get(alias))
-                    .getCertificateChain();
+            Certificate[] certs = hash.get(alias).getCertificateChain();
             if (certs[0] instanceof X509Certificate) {
                 X509Certificate[] xcerts = new X509Certificate[certs.length];
                 for (int i = 0; i < certs.length; i++) {
@@ -142,25 +113,14 @@
 
     }
 
-    /**
-     * @see javax.net.ssl.X509ExtendedKeyManager#getClientAliases(String
-     *      keyType, Principal[] issuers)
-     */
     public String[] getClientAliases(String keyType, Principal[] issuers) {
         return chooseAlias(new String[] { keyType }, issuers);
     }
 
-    /**
-     * @see javax.net.ssl.X509ExtendedKeyManager#getServerAliases(String
-     *      keyType, Principal[] issuers)
-     */
     public String[] getServerAliases(String keyType, Principal[] issuers) {
         return chooseAlias(new String[] { keyType }, issuers);
     }
 
-    /**
-     * @see javax.net.ssl.X509ExtendedKeyManager#getPrivateKey(String alias)
-     */
     public PrivateKey getPrivateKey(String alias) {
         // BEGIN android-changed
         if (alias == null) {
@@ -168,53 +128,33 @@
         }
         // END android-changed
         if (hash.containsKey(alias)) {
-            return ((KeyStore.PrivateKeyEntry) hash.get(alias)).getPrivateKey();
+            return hash.get(alias).getPrivateKey();
         }
         return null;
     }
 
-    /**
-     * @see javax.net.ssl.X509ExtendedKeyManager#chooseEngineClientAlias(String[]
-     *      keyType, Principal[] issuers, SSLEngine engine)
-     */
-    public String chooseEngineClientAlias(String[] keyType,
-            Principal[] issuers, SSLEngine engine) {
-        String[] al = chooseAlias(keyType, issuers);
-        if (al != null) {
-            return al[0];
-        } else {
-            return null;
-        }
+    @Override
+    public String chooseEngineClientAlias(String[] keyType, Principal[] issuers, SSLEngine engine) {
+        final String[] al = chooseAlias(keyType, issuers);
+        return (al == null ? null : al[0]);
     }
 
-    /**
-     * @see javax.net.ssl.X509ExtendedKeyManager#chooseEngineServerAlias(String
-     *      keyType, Principal[] issuers, SSLEngine engine)
-     */
-    public String chooseEngineServerAlias(String keyType, Principal[] issuers,
-            SSLEngine engine) {
-        String[] al = chooseAlias(new String[] { keyType }, issuers);
-        if (al != null) {
-            return al[0];
-        } else {
-            return null;
-        }
+    @Override
+    public String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine engine) {
+        final String[] al = chooseAlias(new String[] { keyType }, issuers);
+        return (al == null ? null : al[0]);
     }
 
     private String[] chooseAlias(String[] keyType, Principal[] issuers) {
-        String alias;
-        KeyStore.PrivateKeyEntry entry;
-        
         if (keyType == null || keyType.length == 0) {
             return null;
         }
-        Vector found = new Vector();
-        int count = 0;
-        for (Enumeration aliases = hash.keys(); aliases.hasMoreElements();) {
-            alias = (String) aliases.nextElement();
-            entry = (KeyStore.PrivateKeyEntry) hash.get(alias);
-            Certificate[] certs = entry.getCertificateChain();
-            String alg = certs[0].getPublicKey().getAlgorithm();
+        Vector<String> found = new Vector<String>();
+        for (Enumeration<String> aliases = hash.keys(); aliases.hasMoreElements();) {
+            final String alias = aliases.nextElement();
+            final KeyStore.PrivateKeyEntry entry = hash.get(alias);
+            final Certificate[] certs = entry.getCertificateChain();
+            final String alg = certs[0].getPublicKey().getAlgorithm();
             for (int i = 0; i < keyType.length; i++) {
                 if (alg.equals(keyType[i])) {
                     if (issuers != null && issuers.length != 0) {
@@ -226,7 +166,6 @@
                                 for (int iii = 0; iii < issuers.length; iii++) {
                                     if (issuer.equals(issuers[iii])) {
                                         found.add(alias);
-                                        count++;
                                         break loop;
                                     }
                                 }
@@ -235,18 +174,13 @@
                         }
                     } else {
                         found.add(alias);
-                        count++;
                     }
                 }
             }
         }
-        if (count > 0) {
-            String[] result = new String[count];
-            found.toArray(result);
-            return result;
-        } else {
-            return null;
+        if (!found.isEmpty()) {
+            return found.toArray(new String[found.size()]);
         }
+        return null;
     }
-
 }
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/Logger.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/Logger.java
index 5b7ba2c..c06aa7e 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/Logger.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/Logger.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Alexander Y. Kleymenov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import java.io.PrintStream;
@@ -41,6 +36,7 @@
             prefix = name + "["+Thread.currentThread().getName()+"] ";
         }
 
+        @Override
         public void print(String msg) {
             for (int i=0; i<indent; i++) {
                 super.print("  ");
@@ -56,6 +52,7 @@
             indent --;
         }
 
+        @Override
         public void println(String msg) {
             print(prefix);
             super.println(msg);
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/Message.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/Message.java
index cf99d6e..f1b2515 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/Message.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/Message.java
@@ -15,10 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Boris Kuznetsov
-* @version $Revision$
-*/
 package org.apache.harmony.xnet.provider.jsse;
 
 import org.apache.harmony.xnet.provider.jsse.AlertException;
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImplWrapper.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImplWrapper.java
index e3451aa..959f2a0 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImplWrapper.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImplWrapper.java
@@ -1,17 +1,18 @@
 /*
- * Copyright (C) 2008 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 org.apache.harmony.xnet.provider.jsse;
@@ -38,132 +39,164 @@
         this.socket = socket;
     }
 
+    @Override
     public void connect(SocketAddress sockaddr, int timeout)
         throws IOException {
         throw new IOException("Underlying socket is already connected.");
     }
 
+    @Override
     public void connect(SocketAddress sockaddr) throws IOException {
         throw new IOException("Underlying socket is already connected.");
     }
 
+    @Override
     public void bind(SocketAddress sockaddr) throws IOException {
         throw new IOException("Underlying socket is already connected.");
     }
 
+    @Override
     public SocketAddress getRemoteSocketAddress() {
         return socket.getRemoteSocketAddress();
     }
 
+    @Override
     public SocketAddress getLocalSocketAddress() {
         return socket.getLocalSocketAddress();
     }
 
+    @Override
     public InetAddress getLocalAddress() {
         return socket.getLocalAddress();
     }
 
+    @Override
     public InetAddress getInetAddress() {
         return socket.getInetAddress();
     }
 
+    @Override
     public String toString() {
         return "SSL socket over " + socket.toString();
     }
 
+    @Override
     public void setSoLinger(boolean on, int linger) throws SocketException {
         socket.setSoLinger(on, linger);
     }
 
+    @Override
     public void setTcpNoDelay(boolean on) throws SocketException {
         socket.setTcpNoDelay(on);
     }
 
+    @Override
     public void setReuseAddress(boolean on) throws SocketException {
         socket.setReuseAddress(on);
     }
 
+    @Override
     public void setKeepAlive(boolean on) throws SocketException {
         socket.setKeepAlive(on);
     }
 
+    @Override
     public void setTrafficClass(int tos) throws SocketException {
         socket.setTrafficClass(tos);
     }
 
+    @Override
     public void setSoTimeout(int to) throws SocketException {
         socket.setSoTimeout(to);
         super.setSoTimeout(to);
     }
 
+    @Override
     public void setSendBufferSize(int size) throws SocketException {
         socket.setSendBufferSize(size);
     }
 
+    @Override
     public void setReceiveBufferSize(int size) throws SocketException {
         socket.setReceiveBufferSize(size);
     }
 
+    @Override
     public boolean getTcpNoDelay() throws SocketException {
         return socket.getTcpNoDelay();
     }
 
+    @Override
     public boolean getReuseAddress() throws SocketException {
         return socket.getReuseAddress();
     }
 
+    @Override
     public boolean getOOBInline() throws SocketException {
         return socket.getOOBInline();
     }
 
+    @Override
     public boolean getKeepAlive() throws SocketException {
         return socket.getKeepAlive();
     }
 
+    @Override
     public int getTrafficClass() throws SocketException {
         return socket.getTrafficClass();
     }
 
+    @Override
     public int getSoTimeout() throws SocketException {
         return socket.getSoTimeout();
     }
 
+    @Override
     public int getSoLinger() throws SocketException {
         return socket.getSoLinger();
     }
 
+    @Override
     public int getSendBufferSize() throws SocketException {
         return socket.getSendBufferSize();
     }
 
+    @Override
     public int getReceiveBufferSize() throws SocketException {
         return socket.getReceiveBufferSize();
     }
 
+    @Override
     public boolean isConnected() {
         return socket.isConnected();
     }
 
+    @Override
     public boolean isClosed() {
         return socket.isClosed();
     }
 
+    @Override
     public boolean isBound() {
         return socket.isBound();
     }
 
+    @Override
     public boolean isOutputShutdown() {
         return socket.isOutputShutdown();
     }
 
+    @Override
     public boolean isInputShutdown() {
         return socket.isInputShutdown();
     }
 
+    @Override
     public int getPort() {
         return socket.getPort();
     }
 
+    @Override
     public int getLocalPort() {
         return socket.getLocalPort();
     }
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/PRF.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/PRF.java
index 3ed9b2a..c2f91a3 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/PRF.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/PRF.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Alexander Y. Kleymenov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import org.apache.harmony.xnet.provider.jsse.AlertException;
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ProtocolVersion.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ProtocolVersion.java
index 1343c3b..def27f9 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ProtocolVersion.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ProtocolVersion.java
@@ -14,11 +14,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-
-/**
- * @author Boris Kuznetsov
- * @version $Revision$
- */
 package org.apache.harmony.xnet.provider.jsse;
 
 import java.util.Hashtable;
@@ -28,41 +23,13 @@
  * Represents Protocol Version
  */
 public class ProtocolVersion {
-
     /**
-     * Protocol name
-     */
-    public final String name;
-
-    /**
-     * Protocol version as byte array
-     */
-    public final byte[] version;
-
-    /**
-     * Protocols supported by this provider implementaton
+     * Protocols supported by this provider implementation
      */
     public static final String[] supportedProtocols = new String[] { "TLSv1",
             "SSLv3" };
 
-    private static Hashtable protocolsByName = new Hashtable(4);
-
-    private ProtocolVersion(String name, byte[] version) {
-        this.name = name;
-        this.version = version;
-    }
-
-    /**
-     * Compares this ProtocolVersion to the specified object.
-     */
-    public boolean equals(Object o) {
-        if (o instanceof ProtocolVersion
-                && this.version[0] == ((ProtocolVersion) o).version[0]
-                && this.version[1] == ((ProtocolVersion) o).version[1]) {
-            return true;
-        }
-        return false;
-    }
+    private static Hashtable<String, ProtocolVersion> protocolsByName = new Hashtable<String, ProtocolVersion>(4);
 
     /**
      * 
@@ -112,7 +79,7 @@
      * @return
      */
     public static ProtocolVersion getByName(String name) {
-        return (ProtocolVersion) protocolsByName.get(name);
+        return protocolsByName.get(name);
     }
 
     /**
@@ -161,4 +128,31 @@
         protocolsByName.put("TLS", TLSv1);
     }
 
+    /**
+     * Protocol name
+     */
+    public final String name;
+
+    /**
+     * Protocol version as byte array
+     */
+    public final byte[] version;
+
+    private ProtocolVersion(String name, byte[] version) {
+        this.name = name;
+        this.version = version;
+    }
+
+    /**
+     * Compares this ProtocolVersion to the specified object.
+     */
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof ProtocolVersion
+                && this.version[0] == ((ProtocolVersion) o).version[0]
+                && this.version[1] == ((ProtocolVersion) o).version[1]) {
+            return true;
+        }
+        return false;
+    }
 }
\ No newline at end of file
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLBufferedInput.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLBufferedInput.java
index 44009b9..a150470 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLBufferedInput.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLBufferedInput.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Alexander Y. Kleymenov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import org.apache.harmony.xnet.provider.jsse.SSLInputStream;
@@ -57,6 +52,7 @@
     /**
      * Returns the number of bytes available for reading.
      */
+    @Override
     public int available() throws IOException {
         // in assumption that the buffer has been set
         return in.remaining();
@@ -73,6 +69,7 @@
      * Reads the following byte value. If there are no bytes in the source 
      * buffer, method throws java.nio.BufferUnderflowException.
      */
+    @Override
     public int read() throws IOException {
         // TODO: implement optimized read(int) 
         // and read(byte[], int, int) methods
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLContextImpl.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLContextImpl.java
index 2e4de04..c39e3ff 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLContextImpl.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLContextImpl.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Alexander Y. Kleymenov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import org.apache.harmony.xnet.provider.jsse.SSLEngineImpl;
@@ -61,6 +56,7 @@
         super();
     }
 
+    @Override
     public void engineInit(KeyManager[] kms, TrustManager[] tms,
             SecureRandom sr) throws KeyManagementException {
         engineInit(kms, tms, sr, null, null);
@@ -96,6 +92,7 @@
         return new OpenSSLSocketFactoryImpl(sslParameters);
     }
 
+    @Override
     public SSLServerSocketFactory engineGetServerSocketFactory() {
         if (sslParameters == null) {
             throw new IllegalStateException("SSLContext is not initiallized.");
@@ -103,6 +100,7 @@
         return new OpenSSLServerSocketFactoryImpl(sslParameters);
     }
 
+    @Override
     public SSLEngine engineCreateSSLEngine(String host, int port) {
         if (sslParameters == null) {
             throw new IllegalStateException("SSLContext is not initiallized.");
@@ -111,6 +109,7 @@
                 (SSLParameters) sslParameters.clone());
     }
 
+    @Override
     public SSLEngine engineCreateSSLEngine() {
         if (sslParameters == null) {
             throw new IllegalStateException("SSLContext is not initiallized.");
@@ -118,10 +117,12 @@
         return new SSLEngineImpl((SSLParameters) sslParameters.clone());
     }
 
+    @Override
     public ServerSessionContext engineGetServerSessionContext() {
         return serverSessionContext;
     }
 
+    @Override
     public ClientSessionContext engineGetClientSessionContext() {
         return clientSessionContext;
     }
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineAppData.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineAppData.java
index 698723b..9a2cb5e 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineAppData.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineAppData.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Alexander Y. Kleymenov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import org.apache.harmony.xnet.provider.jsse.AlertException;
@@ -77,11 +72,10 @@
                 pos = len;
                 // data was written, exit
                 break;
-            } else {
-                // write chunk of data
-                dsts[i].put(buffer, pos, rem);
-                pos += rem;
             }
+            // write chunk of data
+            dsts[i].put(buffer, pos, rem);
+            pos += rem;
         }
         if (pos != len) {
             // The data did not feet into the buffers,
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineDataStream.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineDataStream.java
index bc13577..e209dd1 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineDataStream.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineDataStream.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Alexander Y. Kleymenov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import java.nio.ByteBuffer;
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineImpl.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineImpl.java
index 383e146..c28a311 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineImpl.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineImpl.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Alexander Y. Kleymenov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import org.apache.harmony.xnet.provider.jsse.AlertException;
@@ -114,6 +109,7 @@
      * @see javax.net.ssl.SSLEngine#beginHandshake() method documentation
      * for more information
      */
+    @Override
     public void beginHandshake() throws SSLException {
         if (engine_was_closed) {
             throw new SSLException("Engine has already been closed.");
@@ -143,6 +139,7 @@
      * @see javax.net.ssl.SSLEngine#closeInbound() method documentation
      * for more information
      */
+    @Override
     public void closeInbound() throws SSLException {
         if (logger != null) {
             logger.println("closeInbound() "+isInboundDone);
@@ -173,6 +170,7 @@
      * @see javax.net.ssl.SSLEngine#closeOutbound() method documentation
      * for more information
      */
+    @Override
     public void closeOutbound() {
         if (logger != null) {
             logger.println("closeOutbound() "+isOutboundDone);
@@ -199,6 +197,7 @@
      * @see javax.net.ssl.SSLEngine#getDelegatedTask() method documentation
      * for more information
      */
+    @Override
     public Runnable getDelegatedTask() {
         return handshakeProtocol.getTask();
     }
@@ -209,6 +208,7 @@
      * @see javax.net.ssl.SSLEngine#getSupportedCipherSuites() method
      * documentation for more information
      */
+    @Override
     public String[] getSupportedCipherSuites() {
         return CipherSuite.getSupportedCipherSuiteNames();
     }
@@ -220,6 +220,7 @@
      * @see javax.net.ssl.SSLEngine#getEnabledCipherSuites() method
      * documentation for more information
      */
+    @Override
     public String[] getEnabledCipherSuites() {
         return sslParameters.getEnabledCipherSuites();
     }
@@ -229,6 +230,7 @@
      * @see javax.net.ssl.SSLEngine#setEnabledCipherSuites(String[]) method
      * documentation for more information
      */
+    @Override
     public void setEnabledCipherSuites(String[] suites) {
         sslParameters.setEnabledCipherSuites(suites);
     }
@@ -238,8 +240,9 @@
      * @see javax.net.ssl.SSLEngine#getSupportedProtocols() method
      * documentation for more information
      */
+    @Override
     public String[] getSupportedProtocols() {
-        return (String[]) ProtocolVersion.supportedProtocols.clone();
+        return ProtocolVersion.supportedProtocols.clone();
     }
 
     /**
@@ -247,6 +250,7 @@
      * @see javax.net.ssl.SSLEngine#getEnabledProtocols() method
      * documentation for more information
      */
+    @Override
     public String[] getEnabledProtocols() {
         return sslParameters.getEnabledProtocols();
     }
@@ -256,6 +260,7 @@
      * @see javax.net.ssl.SSLEngine#setEnabledProtocols(String[]) method
      * documentation for more information
      */
+    @Override
     public void setEnabledProtocols(String[] protocols) {
         sslParameters.setEnabledProtocols(protocols);
     }
@@ -265,6 +270,7 @@
      * @see javax.net.ssl.SSLEngine#setUseClientMode(boolean) method
      * documentation for more information
      */
+    @Override
     public void setUseClientMode(boolean mode) {
         if (handshake_started) {
             throw new IllegalArgumentException(
@@ -279,6 +285,7 @@
      * @see javax.net.ssl.SSLEngine#getUseClientMode() method
      * documentation for more information
      */
+    @Override
     public boolean getUseClientMode() {
         return sslParameters.getUseClientMode();
     }
@@ -288,6 +295,7 @@
      * @see javax.net.ssl.SSLEngine#setNeedClientAuth(boolean) method
      * documentation for more information
      */
+    @Override
     public void setNeedClientAuth(boolean need) {
         sslParameters.setNeedClientAuth(need);
     }
@@ -297,6 +305,7 @@
      * @see javax.net.ssl.SSLEngine#getNeedClientAuth() method
      * documentation for more information
      */
+    @Override
     public boolean getNeedClientAuth() {
         return sslParameters.getNeedClientAuth();
     }
@@ -306,6 +315,7 @@
      * @see javax.net.ssl.SSLEngine#setWantClientAuth(boolean) method
      * documentation for more information
      */
+    @Override
     public void setWantClientAuth(boolean want) {
         sslParameters.setWantClientAuth(want);
     }
@@ -315,6 +325,7 @@
      * @see javax.net.ssl.SSLEngine#getWantClientAuth() method
      * documentation for more information
      */
+    @Override
     public boolean getWantClientAuth() {
         return sslParameters.getWantClientAuth();
     }
@@ -324,6 +335,7 @@
      * @see javax.net.ssl.SSLEngine#setEnableSessionCreation(boolean) method
      * documentation for more information
      */
+    @Override
     public void setEnableSessionCreation(boolean flag) {
         sslParameters.setEnableSessionCreation(flag);
     }
@@ -333,6 +345,7 @@
      * @see javax.net.ssl.SSLEngine#getEnableSessionCreation() method
      * documentation for more information
      */
+    @Override
     public boolean getEnableSessionCreation() {
         return sslParameters.getEnableSessionCreation();
     }
@@ -344,6 +357,7 @@
      * @see javax.net.ssl.SSLEngine#getHandshakeStatus() method
      * documentation for more information
      */
+    @Override
     public SSLEngineResult.HandshakeStatus getHandshakeStatus() {
         if (!handshake_started || engine_was_shutteddown) {
             // initial handshake has not been started yet
@@ -365,12 +379,12 @@
      * @see javax.net.ssl.SSLEngine#getSession() method
      * documentation for more information
      */
+    @Override
     public SSLSession getSession() {
         if (session != null) {
             return session;
-        } else {
-            return SSLSessionImpl.NULL_SESSION;
         }
+        return SSLSessionImpl.NULL_SESSION;
     }
 
     /**
@@ -378,6 +392,7 @@
      * @see javax.net.ssl.SSLEngine#isInboundDone() method
      * documentation for more information
      */
+    @Override
     public boolean isInboundDone() {
         return isInboundDone || engine_was_closed;
     }
@@ -387,6 +402,7 @@
      * @see javax.net.ssl.SSLEngine#isOutboundDone() method
      * documentation for more information
      */
+    @Override
     public boolean isOutboundDone() {
         return isOutboundDone;
     }
@@ -402,6 +418,7 @@
      * @see javax.net.ssl.SSLEngine#unwrap(ByteBuffer,ByteBuffer[],int,int)
      * method documentation for more information
      */
+    @Override
     public SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts,
                                 int offset, int length) throws SSLException {
         if (engine_was_shutteddown) {
@@ -566,6 +583,7 @@
      * @see javax.net.ssl.SSLEngine#wrap(ByteBuffer[],int,int,ByteBuffer) method
      * documentation for more information
      */
+    @Override
     public SSLEngineResult wrap(ByteBuffer[] srcs, int offset,
                             int len, ByteBuffer dst) throws SSLException {
         if (engine_was_shutteddown) {
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 bd9b6cf..6c23a91 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
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Alexander Y. Kleymenov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import java.io.IOException;
@@ -37,6 +32,7 @@
     /**
      * @see java.io.InputStream#available()
      */
+    @Override
     public abstract int available() throws IOException;
 
     /**
@@ -49,11 +45,13 @@
      * @see org.apache.harmony.xnet.provider.jsse.SSLBufferedInput#read()
      * @see org.apache.harmony.xnet.provider.jsse.HandshakeIODataStream#read()
      */
+    @Override
     public abstract int read() throws IOException;
 
     /**
      * @see java.io.InputStream#skip(long)
      */
+    @Override
     public long skip(long n) throws IOException {
         long skept = n;
         while (n > 0) {
@@ -119,6 +117,7 @@
     /**
      * @see java.io.InputStream#read(byte[],int,int)
      */
+    @Override
     public int read(byte[] b, int off, int len) throws IOException {
         int read_b;
         int i = 0;
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLParameters.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLParameters.java
index d91388a..89916de 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLParameters.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLParameters.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Alexander Y. Kleymenov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import java.security.KeyManagementException;
@@ -317,7 +312,7 @@
                 enabledCipherSuiteNames[i] = enabledCipherSuites[i].getName();
             }
         }
-        return (String[]) enabledCipherSuiteNames.clone();
+        return enabledCipherSuiteNames.clone();
     }
 
     /**
@@ -345,7 +340,7 @@
      * @return the set of enabled protocols
      */
     protected String[] getEnabledProtocols() {
-        return (String[]) enabledProtocols.clone();
+        return enabledProtocols.clone();
     }
 
     /**
@@ -436,6 +431,7 @@
      * Returns the clone of this object.
      * @return the clone.
      */
+    @Override
     protected Object clone() {
 // BEGIN android-changed
         try {
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLRecordProtocol.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLRecordProtocol.java
index 4428820..423a817 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLRecordProtocol.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLRecordProtocol.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Alexander Y. Kleymenov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import org.apache.harmony.xnet.provider.jsse.AlertException;
@@ -33,7 +28,7 @@
  * This class performs functionality dedicated to SSL record layer.
  * It unpacks and routes income data to the appropriate
  * client protocol (handshake, alert, application data protocols)
- * and paketizes outcome data into SSL/TLS records.
+ * and packages outcome data into SSL/TLS records.
  * Initially created object has null connection state and does not
  * perform any cryptography computations over the income/outcome data.
  * After handshake protocol agreed upon security parameters they are placed
@@ -179,14 +174,13 @@
         }
         if (activeReadState == null) {
             return record_size;
-        } else {
-            return activeReadState.getContentSize(record_size);
         }
+        return activeReadState.getContentSize(record_size);
     }
 
     /**
      * Depending on the Connection State (Session) encrypts and compress
-     * the provided data, and packs it into TLSCiphertext structute.
+     * the provided data, and packs it into TLSCiphertext structure.
      * @param   content_type: int
      * @param   fragment: byte[]
      * @return  ssl packet created over the current connection state
@@ -198,7 +192,7 @@
 
     /**
      * Depending on the Connection State (Session) encrypts and compress
-     * the provided data, and packs it into TLSCiphertext structute.
+     * the provided data, and packs it into TLSCiphertext structure.
      * @param   content_type: int
      * @param   fragment: byte[]
      * @return  ssl packet created over the current connection state
@@ -374,7 +368,7 @@
                             type));
             }
         } else {
-            in.skip((long) 2); // just skip the version number
+            in.skip(2); // just skip the version number
         }
         int length = in.readUint16();
         if (logger != null) {
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSessionImpl.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSessionImpl.java
index 4510c96..5d46568 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSessionImpl.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSessionImpl.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Boris Kuznetsov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import java.security.AccessControlContext;
@@ -29,7 +24,8 @@
 import java.security.cert.Certificate;
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.X509Certificate;
-import java.util.Iterator;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Vector;
 
 import javax.net.ssl.SSLPeerUnverifiedException;
@@ -39,25 +35,67 @@
 import javax.net.ssl.SSLSessionBindingListener;
 import javax.net.ssl.SSLSessionContext;
 
-import org.apache.harmony.luni.util.TwoKeyHashMap;
-
 /**
  * 
  * SSLSession implementation
- *
+ * 
  * @see javax.net.ssl.SSLSession
  */
-public class SSLSessionImpl implements SSLSession {
+public class SSLSessionImpl implements SSLSession, Cloneable  {
 
     /**
-     * Session object reporting an invalid cipher suite of 
-     * "SSL_NULL_WITH_NULL_NULL"
+     * Session object reporting an invalid cipher suite of "SSL_NULL_WITH_NULL_NULL"
      */
     public static final SSLSessionImpl NULL_SESSION = new SSLSessionImpl(null);
 
+    /**
+     * Container class for the 'value' map's keys.
+     */
+    private static final class ValueKey {
+        final String name;
+        final AccessControlContext acc;
+
+        ValueKey(String name) {
+            super();
+            this.name = name;
+            this.acc = AccessController.getContext();
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + ((acc == null) ? 0 : acc.hashCode());
+            result = prime * result + ((name == null) ? 0 : name.hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj)
+                return true;
+            if (obj == null)
+                return false;
+            if (!(obj instanceof ValueKey))
+                return false;
+            ValueKey other = (ValueKey) obj;
+            if (acc == null) {
+                if (other.acc != null)
+                    return false;
+            } else if (!acc.equals(other.acc))
+                return false;
+            if (name == null) {
+                if (other.name != null)
+                    return false;
+            } else if (!name.equals(other.name))
+                return false;
+            return true;
+        }
+    }
+
     private long creationTime;
     private boolean isValid = true;
-    private TwoKeyHashMap values = new TwoKeyHashMap();
+    private Map<ValueKey, Object> values = new HashMap<ValueKey, Object>();
 
     /**
      * ID of the session
@@ -65,7 +103,7 @@
     byte[] id;
 
     /**
-     * Last time the session was accessed 
+     * Last time the session was accessed
      */
     long lastAccessedTime;
 
@@ -87,7 +125,7 @@
 // END android-changed
 
     /**
-     * certificates were sent to the peer 
+     * certificates were sent to the peer
      */
     X509Certificate[] localCertificates;
 
@@ -97,21 +135,20 @@
     X509Certificate[] peerCertificates;
 
     /**
-     * Peer host name 
+     * Peer host name
      */
-    String peerHost;
+    private String peerHost;
 
     /**
      * Peer port number
      */
-    int peerPort = -1;
+    private int peerPort = -1;
 
     /**
      * Master secret
      */
     byte[] master_secret;
 
-
     /**
      * clientRandom
      */
@@ -125,10 +162,11 @@
     /**
      * True if this entity is considered the server
      */
-    boolean isServer = false;
+    final boolean isServer;
 
     /**
      * Creates SSLSession implementation
+     * 
      * @param cipher_suite
      * @param sr
      */
@@ -143,11 +181,11 @@
             this.cipherSuite = cipher_suite;
             id = new byte[32];
             sr.nextBytes(id);
-            long time = new java.util.Date().getTime() / 1000;
+            long time = creationTime / 1000;
             id[28] = (byte) ((time & 0xFF000000) >>> 24);
-            id[29] = (byte) ((time & 0xFF0000) >>> 16);
-            id[30] = (byte) ((time & 0xFF00) >>> 8);
-            id[31] = (byte) (time & 0xFF);
+            id[29] = (byte) ((time & 0x00FF0000) >>> 16);
+            id[30] = (byte) ((time & 0x0000FF00) >>> 8);
+            id[31] = (byte) ((time & 0x000000FF));
             isServer = true;
         }
 
@@ -155,78 +193,48 @@
 
     /**
      * Creates SSLSession implementation
+     * 
      * @param sr
      */
     public SSLSessionImpl(SecureRandom sr) {
         this(null, sr);
     }
 
-    private SSLSessionImpl() {
-    }
-
-    /**
-     * @see javax.net.ssl.SSLSession#getApplicationBufferSize()
-     */
     public int getApplicationBufferSize() {
         return SSLRecordProtocol.MAX_DATA_LENGTH;
     }
 
-    /**
-     * @see javax.net.ssl.SSLSession#getCipherSuite()
-     */
     public String getCipherSuite() {
         return cipherSuite.getName();
     }
 
-    /**
-     * @see javax.net.ssl.SSLSession#getCreationTime()
-     */
     public long getCreationTime() {
         return creationTime;
     }
 
-    /**
-     * @see javax.net.ssl.SSLSession#getId()
-     */
     public byte[] getId() {
         return id;
     }
 
-    /**
-     * @see javax.net.ssl.SSLSession#getLastAccessedTime()
-     */
     public long getLastAccessedTime() {
         return lastAccessedTime;
     }
 
-    /**
-     * @see javax.net.ssl.SSLSession#getLocalCertificates()
-     */
     public Certificate[] getLocalCertificates() {
         return localCertificates;
     }
 
-    /**
-     * @see javax.net.ssl.SSLSession#getLocalPrincipal()
-     */
     public Principal getLocalPrincipal() {
         if (localCertificates != null && localCertificates.length > 0) {
             return localCertificates[0].getSubjectX500Principal();
-        } else {
-            return null;
         }
+        return null;
     }
 
-    /**
-     * @see javax.net.ssl.SSLSession#getPacketBufferSize()
-     */
     public int getPacketBufferSize() {
         return SSLRecordProtocol.MAX_SSL_PACKET_SIZE;
     }
 
-    /**
-     * @see javax.net.ssl.SSLSession#getPeerCertificateChain()
-     */
     public javax.security.cert.X509Certificate[] getPeerCertificateChain()
             throws SSLPeerUnverifiedException {
         if (peerCertificates == null) {
@@ -235,8 +243,8 @@
         javax.security.cert.X509Certificate[] certs = new javax.security.cert.X509Certificate[peerCertificates.length];
         for (int i = 0; i < certs.length; i++) {
             try {
-                certs[i] = javax.security.cert.X509Certificate
-                        .getInstance(peerCertificates[i].getEncoded());
+                certs[i] = javax.security.cert.X509Certificate.getInstance(peerCertificates[i]
+                        .getEncoded());
             } catch (javax.security.cert.CertificateException e) {
             } catch (CertificateEncodingException e) {
             }
@@ -244,34 +252,21 @@
         return certs;
     }
 
-    /**
-     * @see javax.net.ssl.SSLSession#getPeerCertificates()
-     */
-    public Certificate[] getPeerCertificates()
-            throws SSLPeerUnverifiedException {
+    public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
         if (peerCertificates == null) {
             throw new SSLPeerUnverifiedException("No peer certificate");
         }
         return peerCertificates;
     }
 
-    /**
-     * @see javax.net.ssl.SSLSession#getPeerHost()
-     */
     public String getPeerHost() {
         return peerHost;
     }
 
-    /**
-     * @see javax.net.ssl.SSLSession#getPeerPort()
-     */
     public int getPeerPort() {
         return peerPort;
     }
 
-    /**
-     * @see javax.net.ssl.SSLSession#getPeerPrincipal()
-     */
     public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
         if (peerCertificates == null) {
             throw new SSLPeerUnverifiedException("No peer certificate");
@@ -279,16 +274,10 @@
         return peerCertificates[0].getSubjectX500Principal();
     }
 
-    /**
-     * @see javax.net.ssl.SSLSession#getProtocol()
-     */
     public String getProtocol() {
         return protocol.name;
     }
 
-    /**
-     * @see javax.net.ssl.SSLSession#getSessionContext()
-     */
     public SSLSessionContext getSessionContext() {
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
@@ -297,109 +286,71 @@
         return context;
     }
 
-    /**
-     * @see javax.net.ssl.SSLSession#getValue(String name)
-     */
     public Object getValue(String name) {
         if (name == null) {
             throw new IllegalArgumentException("Parameter is null");
         }
-        return values.get(name, AccessController.getContext());
+        return values.get(new ValueKey(name));
     }
 
-    /**
-     * @see javax.net.ssl.SSLSession#getValueNames()
-     */
     public String[] getValueNames() {
-        Vector v = new Vector();
-        AccessControlContext current = AccessController.getContext();
-        AccessControlContext cont;
-        for (Iterator it = values.entrySet().iterator(); it.hasNext();) {
-            TwoKeyHashMap.Entry entry = (TwoKeyHashMap.Entry) it.next();
-            cont = (AccessControlContext) entry.getKey2();
-            if ((current == null && cont == null)
-                    || (current != null && current.equals(cont))) {
-                v.add(entry.getKey1());
+        final Vector<String> v = new Vector<String>();
+        final AccessControlContext currAcc = AccessController.getContext();
+        for (ValueKey key : values.keySet()) {
+            if ((currAcc == null && key.acc == null)
+                    || (currAcc != null && currAcc.equals(key.acc))) {
+                v.add(key.name);
             }
         }
-        return (String[]) v.toArray(new String[0]);
+        return v.toArray(new String[v.size()]);
     }
 
-    /**
-     * @see javax.net.ssl.SSLSession#invalidate()
-     */
     public void invalidate() {
         isValid = false;
     }
 
-    /**
-     * @see javax.net.ssl.SSLSession#isValid()
-     */
     public boolean isValid() {
-        if (isValid
-                && context != null
-                && context.getSessionTimeout() != 0
-                && lastAccessedTime + context.getSessionTimeout() > System
-                        .currentTimeMillis()) {
+        if (isValid && context != null && context.getSessionTimeout() != 0
+                && lastAccessedTime + context.getSessionTimeout() > System.currentTimeMillis()) {
             isValid = false;
         }
         return isValid;
     }
 
-    /**
-     * @see javax.net.ssl.SSLSession#putValue(String name, Object value)
-     */
     public void putValue(String name, Object value) {
         if (name == null || value == null) {
             throw new IllegalArgumentException("Parameter is null");
         }
-        Object old = values.put(name, AccessController.getContext(), value);
+        Object old = values.put(new ValueKey(name), value);
         if (value instanceof SSLSessionBindingListener) {
-            ((SSLSessionBindingListener) value)
-                    .valueBound(new SSLSessionBindingEvent(this, name));
+            ((SSLSessionBindingListener) value).valueBound(new SSLSessionBindingEvent(this, name));
         }
         if (old != null && old instanceof SSLSessionBindingListener) {
-            ((SSLSessionBindingListener) old)
-                    .valueUnbound(new SSLSessionBindingEvent(this, name));
+            ((SSLSessionBindingListener) old).valueUnbound(new SSLSessionBindingEvent(this, name));
         }
 
     }
 
-    /**
-     * @see javax.net.ssl.SSLSession#removeValue(String name)
-     */
     public void removeValue(String name) {
         if (name == null) {
             throw new IllegalArgumentException("Parameter is null");
         }
-        values.remove(name, AccessController.getContext());
+        values.remove(new ValueKey(name));
 
     }
 
+    @Override
     public Object clone() {
-        SSLSessionImpl ses = new SSLSessionImpl();
-        ses.id = this.id;
-        ses.creationTime = this.creationTime;
-        ses.lastAccessedTime = this.lastAccessedTime;
-        ses.isValid = this.isValid;
-        ses.cipherSuite = this.cipherSuite;
-        ses.localCertificates = this.localCertificates;
-        ses.peerCertificates = this.peerCertificates;
-        ses.master_secret = this.master_secret;
-        ses.clientRandom = this.clientRandom;
-        ses.serverRandom = this.serverRandom;
-        ses.peerHost = this.peerHost;
-        ses.peerPort = this.peerPort;
-        ses.isServer = this.isServer;
-        ses.context = this.context;
-        ses.protocol = this.protocol;
-        ses.values = this.values;
-        return ses;
+        try {
+            return super.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new AssertionError(e);
+        }
     }
 
-
     /**
      * Sets the address of the peer
+     * 
      * @param peerHost
      * @param peerPort
      */
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLStreamedInput.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLStreamedInput.java
index efabef8..c040653 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLStreamedInput.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLStreamedInput.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Alexander Y. Kleymenov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import java.io.IOException;
@@ -37,6 +32,7 @@
         this.in = in;
     }
 
+    @Override
     public int available() throws IOException {
         return in.available();
     }
@@ -49,6 +45,7 @@
      * @throws org.apache.harmony.xnet.provider.jsse.EndOfSourceException if the end of the underlying
      * stream has been reached.
      */
+    @Override
     public int read() throws IOException {
         int res = in.read();
         if (res < 0) {
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLv3Constants.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLv3Constants.java
index 1a03f7f..07aaca8 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLv3Constants.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLv3Constants.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Boris Kuznetsov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 /**
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHandshakeImpl.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHandshakeImpl.java
index f6eef23..3bb096b 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHandshakeImpl.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHandshakeImpl.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Boris Kuznetsov
-* @version $Revision$
-*/
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import org.apache.harmony.xnet.provider.jsse.SSLv3Constants;
@@ -56,7 +51,7 @@
  * Handshake protocol operates on top of the Record Protocol.
  * It responsible for negotiating a session.
  * 
- * The implementation proceses inbound client handshake messages,
+ * The implementation processes inbound client handshake messages,
  * creates and sends respond messages. Outbound messages are supplied 
  * to Record Protocol. Detected errors are reported to the Alert protocol.
  * 
@@ -82,6 +77,7 @@
     /**
      * Start session negotiation
      */
+    @Override
     public void start() {
         if (session == null) { // initial handshake
             status = NEED_UNWRAP;
@@ -101,6 +97,7 @@
      * Proceses inbound handshake messages
      * @param bytes
      */
+    @Override
     public void unwrap(byte[] bytes) {
 
         io_stream.append(bytes);
@@ -128,15 +125,12 @@
                     needSendHelloRequest = false;
                     clientHello = new ClientHello(io_stream, length);
                     if (nonBlocking) {
-                        delegatedTasks.add(new DelegatedTask(
-                                new PrivilegedExceptionAction(){
-                            public Object run() throws Exception {
+                        delegatedTasks.add(new DelegatedTask(new PrivilegedExceptionAction<Void>() {
+                            public Void run() throws Exception {
                                 processClientHello();
                                 return null;
-                                }
-                            },
-                            this,
-                            AccessController.getContext()));
+                            }
+                        }, this, AccessController.getContext()));
                         return;
                     }
                     processClientHello();
@@ -152,7 +146,7 @@
                     if (clientCert.certs.length == 0) {
                         if (parameters.getNeedClientAuth()) {
                             fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
-                                    "HANDSHAKE FAILURE: no client certificate recived");
+                                    "HANDSHAKE FAILURE: no client certificate received");
                         }
                     } else {
                         String authType = clientCert.certs[0].getPublicKey()
@@ -324,32 +318,27 @@
      * @ see TLS 1.0 spec., E.1. Version 2 client hello
      * @param bytes
      */
+    @Override
     public void unwrapSSLv2(byte[] bytes) {
+        io_stream.append(bytes);
+        io_stream.mark();
         try {
-            io_stream.append(bytes);
-            io_stream.mark();
-            try {
-                clientHello = new ClientHello(io_stream);
-            } catch (IOException e) {
-                io_stream.reset();
-                return;
-            }
-            if (nonBlocking) {
-                delegatedTasks.add(new DelegatedTask(
-                        new PrivilegedExceptionAction(){ 
-                    public Object run() throws Exception {
-                        processClientHello();
-                        return null;
-                        }
-                    },
-                    this,
-                    AccessController.getContext()));
-                return;
-            }
-            processClientHello();
-        } catch (Exception e) {
-            fatalAlert(AlertProtocol.INTERNAL_ERROR, "INTERNAL ERROR", e);
+            clientHello = new ClientHello(io_stream);
+        } catch (IOException e) {
+            io_stream.reset();
+            return;
         }
+        if (nonBlocking) {
+            delegatedTasks.add(new DelegatedTask(
+                    new PrivilegedExceptionAction<Void>() {
+                        public Void run() throws Exception {
+                            processClientHello();
+                            return null;
+                        }
+                    }, this, AccessController.getContext()));
+            return;
+        }
+        processClientHello();
     }
 
     /**
@@ -407,10 +396,9 @@
                         status = NOT_HANDSHAKING;
                         clearMessages();
                         return;
-                    } else {
-                        fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
-                                "SSL Session may not be created");
                     }
+                    // throw AlertException
+                    fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, "SSL Session may not be created");
                 }
                 session = null;
             } else {
@@ -569,7 +557,7 @@
                     } catch (NoSuchAlgorithmException e) {
                             kf = KeyFactory.getInstance("DiffieHellman");
                     }
-                    dhkeySpec = (DHPublicKeySpec) kf.getKeySpec(dhkey,
+                    dhkeySpec = kf.getKeySpec(dhkey,
                             DHPublicKeySpec.class);
                 }
                 if (!cipher_suite.isAnonymous()) { // calculate signed_params
@@ -654,6 +642,7 @@
     /**
      * Creates and sends finished message
      */
+    @Override
     protected void makeFinished() {
         byte[] verify_data;
         boolean isTLS = (serverHello.server_version[1] == 1); // TLS 1.0 protocol
@@ -702,8 +691,9 @@
     }
 
     /**
-     * Proceses inbound ChangeCipherSpec message
+     * Processes inbound ChangeCipherSpec message
      */
+    @Override
     public void receiveChangeCipherSpec() {    
         if (isResuming) {
             if (serverFinished == null) {
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHello.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHello.java
index 0365288..1cd9624 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHello.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHello.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Boris Kuznetsov
-* @version $Revision$
-*/
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import org.apache.harmony.xnet.provider.jsse.Message;
@@ -112,6 +107,7 @@
      * Sends message
      * @param out
      */
+    @Override
     public void send(HandshakeIODataStream out) {
         out.write(server_version);
         out.write(random);
@@ -134,6 +130,7 @@
      * Returns message type 
      * @return
      */
+    @Override
     public int getType() {
         return Handshake.SERVER_HELLO;
     }
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHelloDone.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHelloDone.java
index e794ed9..73b6a81 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHelloDone.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHelloDone.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Boris Kuznetsov
-* @version $Revision$
-*/
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import org.apache.harmony.xnet.provider.jsse.Message;
@@ -59,6 +54,7 @@
      * Sends message
      * @param out
      */
+    @Override
     public void send(HandshakeIODataStream out) {
     }
     
@@ -66,6 +62,7 @@
      * Returns message length
      * @return
      */
+    @Override
     public int length() {
         return 0;
     }
@@ -74,6 +71,7 @@
      * Returns message type 
      * @return
      */
+    @Override
     public int getType() {
         return Handshake.SERVER_HELLO_DONE;
     }
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerKeyExchange.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerKeyExchange.java
index 1d93ece..446b7b4 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerKeyExchange.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerKeyExchange.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
-* @author Boris Kuznetsov
-* @version $Revision$
-*/
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import org.apache.harmony.xnet.provider.jsse.Message;
@@ -150,6 +145,7 @@
      * Sends message
      * @param out
      */
+    @Override
     public void send(HandshakeIODataStream out) {
         out.writeUint16(bytes1.length);
         out.write(bytes1);
@@ -189,6 +185,7 @@
      * Returns message type 
      * @return
      */
+    @Override
     public int getType() {
         return Handshake.SERVER_KEY_EXCHANGE;
     }
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerFactoryImpl.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerFactoryImpl.java
index b96d1ab..c473864 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerFactoryImpl.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerFactoryImpl.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Boris Kuznetsov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import java.io.File;
@@ -50,6 +45,7 @@
     /**
      * @see javax.net.ssl.TrustManagerFactorySpi#engineInit(KeyStore)
      */
+    @Override
     public void engineInit(KeyStore ks) throws KeyStoreException {
         if (ks != null) {
             keyStore = ks;
@@ -117,6 +113,7 @@
     /**
      * @see javax.net.ssl#engineInit(ManagerFactoryParameters)
      */
+    @Override
     public void engineInit(ManagerFactoryParameters spec)
             throws InvalidAlgorithmParameterException {
         throw new InvalidAlgorithmParameterException(
@@ -126,6 +123,7 @@
     /**
      * @see javax.net.ssl#engineGetTrustManagers()
      */
+    @Override
     public TrustManager[] engineGetTrustManagers() {
         if (keyStore == null) {
             throw new IllegalStateException(
diff --git a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImpl.java b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImpl.java
index 15756bd..543dfb2 100644
--- a/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImpl.java
+++ b/libcore/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImpl.java
@@ -15,11 +15,6 @@
  *  limitations under the License.
  */
 
-/**
- * @author Boris Kuznetsov
- * @version $Revision$
- */
-
 package org.apache.harmony.xnet.provider.jsse;
 
 import org.bouncycastle.jce.provider.IndexedPKIXParameters;
@@ -49,11 +44,11 @@
 // END android-added
 
 /**
- * 
+ *
  * TrustManager implementation. The implementation is based on CertPathValidator
  * PKIX and CertificateFactory X509 implementations. This implementations should
  * be provided by some certification provider.
- * 
+ *
  * @see javax.net.ssl.X509TrustManager
  */
 public class TrustManagerImpl implements X509TrustManager {
@@ -68,20 +63,18 @@
 
     /**
      * Creates trust manager implementation
-     * 
+     *
      * @param ks
      */
     public TrustManagerImpl(KeyStore ks) {
         try {
             validator = CertPathValidator.getInstance("PKIX");
             factory = CertificateFactory.getInstance("X509");
-            String alias;
-            X509Certificate cert;
             byte[] nameConstrains = null;
-            Set trusted = new HashSet();
-            for (Enumeration en = ks.aliases(); en.hasMoreElements();) {
-                alias = (String) en.nextElement();
-                cert = (X509Certificate) ks.getCertificate(alias);
+            Set<TrustAnchor> trusted = new HashSet<TrustAnchor>();
+            for (Enumeration<String> en = ks.aliases(); en.hasMoreElements();) {
+                final String alias = en.nextElement();
+                final X509Certificate cert = (X509Certificate) ks.getCertificate(alias);
                 if (cert != null) {
                     trusted.add(new TrustAnchor(cert, nameConstrains));
                 }
@@ -151,70 +144,77 @@
             throws CertificateException {
         if (chain == null || chain.length == 0 || authType == null
                 || authType.length() == 0) {
-            throw new IllegalArgumentException("null or zero-length parameter");
+            throw new IllegalArgumentException(
+                    "null or zero-length parameter");
         }
         if (err != null) {
             throw new CertificateException(err);
         }
-        // BEGIN android-added
-        // Cater for degenerate special case where we can't
-        // establish an actual certificate chain the usual way,
-        // but have the peer certificate in our trust store.
-        if (isDirectlyTrustedCert(chain)) {
-            return;
-        }
-        // END android-added
+// BEGIN android-changed
+        CertificateException ce = null;
         try {
-            // BEGIN android-changed
-            CertPath certPath = factory.generateCertPath(Arrays.asList(chain));
+            CertPath certPath = factory.generateCertPath(
+                    Arrays.asList(chain));
             if (!Arrays.equals(chain[0].getEncoded(),
-                    ((X509Certificate)certPath.getCertificates().get(0))
-                    .getEncoded())) {
-                // sanity check failed (shouldn't ever happen, but we are using pretty remote code)
+                    certPath.getCertificates().get(0).getEncoded())) {
+                // Sanity check failed (shouldn't ever happen, but we are
+                // using pretty remote code)
                 throw new CertificateException("Certificate chain error");
             }
             validator.validate(certPath, params);
-            // END android-changed
         } catch (InvalidAlgorithmParameterException e) {
-            throw new CertificateException(e);
+            ce = new CertificateException(e);
         } catch (CertPathValidatorException e) {
-            throw new CertificateException(e);
+            ce = new CertificateException(e);
+        }
+        if (ce != null) {
+            // Caters to degenerate special case where we can't
+            // establish an actual certificate chain the usual way
+            // but have the peer certificate in our trust store.
+            if (!isDirectlyTrustedCert(chain)) {
+                throw ce;
+            }
         }
     }
 
-    // BEGIN android-added
     /**
      * Checks whether the given chain is just a certificate
      * that we have in our trust store.
-     * 
+     *
      * @param chain The certificate chain.
-     * 
-     * @return True if the certificate is in our trust store, false otherwise. 
+     *
+     * @return True if the certificate is in our trust store, false otherwise.
      */
     private boolean isDirectlyTrustedCert(X509Certificate[] chain) {
         byte[] questionable;
 
         if (chain.length == 1) {
-          try {
-            questionable = chain[0].getEncoded();
-            Set<TrustAnchor> anchors = params.getTrustAnchors();
+            if (params instanceof IndexedPKIXParameters) {
+                IndexedPKIXParameters index = (IndexedPKIXParameters) params;
+                return index.isDirectlyTrusted(chain[0]);
+            } else {
+                try {
+                    questionable = chain[0].getEncoded();
+                    Set<TrustAnchor> anchors = params.getTrustAnchors();
 
-            for (TrustAnchor trustAnchor : anchors) {
-              byte[] trusted = trustAnchor.getTrustedCert().getEncoded();
-
-              if (Arrays.equals(questionable, trusted)) {
-                return true;
-              }
+                    for (TrustAnchor trustAnchor : anchors) {
+                        byte[] trusted = trustAnchor.getTrustedCert()
+                                .getEncoded();
+                        if (Arrays.equals(questionable, trusted)) {
+                            return true;
+                        }
+                    }
+                } catch (CertificateEncodingException e) {
+                    // Ignore.
+                }
             }
-          } catch (CertificateEncodingException e) {
-            // Ignore.
-          }
+
         }
 
         return false;
     }
-    // END android-added
-    
+// END android-changed
+
     /**
      * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
      */
@@ -222,11 +222,11 @@
         if (params == null) {
             return new X509Certificate[0];
         }
-        Set anchors = params.getTrustAnchors();
+        Set<TrustAnchor> anchors = params.getTrustAnchors();
         X509Certificate[] certs = new X509Certificate[anchors.size()];
         int i = 0;
-        for (Iterator it = anchors.iterator(); it.hasNext();) {
-            certs[i++] = ((TrustAnchor) it.next()).getTrustedCert();
+        for (Iterator<TrustAnchor> it = anchors.iterator(); it.hasNext();) {
+            certs[i++] = it.next().getTrustedCert();
         }
         return certs;
     }
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 250cf83..87f2af3 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
@@ -36,8 +36,6 @@
 #include <openssl/rand.h>
 #include <openssl/ssl.h>
 
-#include <utils/LogSocket.h>
-
 #include "org_apache_harmony_xnet_provider_jsse_common.h"
 
 /**
@@ -423,7 +421,7 @@
 static int sslCreateAppData(SSL* ssl) {
     APP_DATA* data = (APP_DATA*) malloc(sizeof(APP_DATA));
 
-    memset(data, sizeof(APP_DATA), 0);
+    memset(data, 0, sizeof(APP_DATA));
 
     data->aliveAndKicking = 1;
     data->waitingThreads = 0;
@@ -670,8 +668,11 @@
         
         // LOGD("Doing SSL_Read()");
         int result = SSL_read(ssl, buf, len);
-        int error = SSL_get_error(ssl, result);
-        freeSslErrorState();
+        int error = SSL_ERROR_NONE;
+        if (result <= 0) {
+            error = SSL_get_error(ssl, result);
+            freeSslErrorState();
+        }
         // LOGD("Returned from SSL_Read() with result %d, error code %d", result, error);
 
         // If we have been successful in moving data around, check whether it
@@ -693,7 +694,6 @@
         switch (error) {
              // Sucessfully read at least one byte.
             case SSL_ERROR_NONE: {
-                add_recv_stats(fd, result);
                 return result;
             }
 
@@ -786,8 +786,11 @@
         
         // LOGD("Doing SSL_write() with %d bytes to go", len);
         int result = SSL_write(ssl, buf, len);
-        int error = SSL_get_error(ssl, result);
-        freeSslErrorState();
+        int error = SSL_ERROR_NONE;
+        if (result <= 0) {
+            error = SSL_get_error(ssl, result);
+            freeSslErrorState();
+        }
         // LOGD("Returned from SSL_write() with result %d, error code %d", result, error);
 
         // If we have been successful in moving data around, check whether it
@@ -861,7 +864,6 @@
             }
         }
     }
-    add_send_stats(fd, count);
     // LOGD("Successfully wrote %d bytes", count);
     
     return count;
diff --git a/libcore/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderTest.java b/libcore/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderTest.java
index c515d20..292c2f1 100644
--- a/libcore/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderTest.java
+++ b/libcore/xml/src/test/java/tests/api/javax/xml/parsers/DocumentBuilderTest.java
@@ -278,7 +278,6 @@
         method = "parse",
         args = {java.io.File.class}
     )
-    @KnownFailure("d.getChildNodes returns an unexpected/strange #Text node")
     public void test_parseLjava_io_File() throws IOException {
         File f = resourceToTmpFile("/simple.xml");
 
diff --git a/libdex/DexFile.c b/libdex/DexFile.c
index 2639d7b..99b38c9 100644
--- a/libdex/DexFile.c
+++ b/libdex/DexFile.c
@@ -13,12 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 /*
  * Access the contents of a .dex file.
  */
 
 #include "DexFile.h"
 #include "DexProto.h"
+#include "DexCatch.h"
 #include "Leb128.h"
 #include "sha1.h"
 #include "ZipArchive.h"
@@ -643,6 +645,10 @@
             }
             indexMapType = *pAux;
             break;
+        case kDexChunkRegisterMaps:
+            LOGV("+++ found register maps, size=%u\n", size);
+            pDexFile->pRegisterMapPool = data;
+            break;
         default:
             LOGI("Unknown chunk 0x%08x (%c%c%c%c), size=%d in aux data area\n",
                 *pAux,
@@ -883,6 +889,43 @@
 
 
 /*
+ * Compute the size, in bytes, of a DexCode.
+ */
+size_t dexGetDexCodeSize(const DexCode* pCode)
+{
+    /*
+     * The catch handler data is the last entry.  It has a variable number
+     * of variable-size pieces, so we need to create an iterator.
+     */
+    u4 handlersSize;
+    u4 offset;
+    u4 ui;
+
+    if (pCode->triesSize != 0) {
+        handlersSize = dexGetHandlersSize(pCode);
+        offset = dexGetFirstHandlerOffset(pCode);
+    } else {
+        handlersSize = 0;
+        offset = 0;
+    }
+
+    for (ui = 0; ui < handlersSize; ui++) {
+        DexCatchIterator iterator;
+        dexCatchIteratorInit(&iterator, pCode, offset);
+        offset = dexCatchIteratorGetEndOffset(&iterator, pCode);
+    }
+
+    const u1* handlerData = dexGetCatchHandlerData(pCode);
+
+    //LOGD("+++ pCode=%p handlerData=%p last offset=%d\n",
+    //    pCode, handlerData, offset);
+
+    /* return the size of the catch handler + everything before it */
+    return (handlerData - (u1*) pCode) + offset;
+}
+
+
+/*
  * ===========================================================================
  *      Debug info
  * ===========================================================================
@@ -1181,3 +1224,4 @@
         free(methodDescriptor);
     }
 }
+
diff --git a/libdex/DexFile.h b/libdex/DexFile.h
index d1ea5eb..4b5fe7c 100644
--- a/libdex/DexFile.h
+++ b/libdex/DexFile.h
@@ -163,6 +163,7 @@
 /* auxillary data section chunk codes */
 enum {
     kDexChunkClassLookup            = 0x434c4b50,   /* CLKP */
+    kDexChunkRegisterMaps           = 0x524d4150,   /* RMAP */
 
     kDexChunkReducingIndexMap       = 0x5249584d,   /* RIXM */
     kDexChunkExpandingIndexMap      = 0x4549584d,   /* EIXM */
@@ -514,11 +515,13 @@
     const DexClassDef*  pClassDefs;
     const DexLink*      pLinkData;
 
-    /* mapped in "auxillary" section */
+    /*
+     * These are mapped out of the "auxillary" section, and may not be
+     * included in the file.
+     */
     const DexClassLookup* pClassLookup;
-
-    /* mapped in "auxillary" section */
     DexIndexMap         indexMap;
+    const void*         pRegisterMapPool;       // RegisterMapClassPool
 
     /* points to start of DEX file data */
     const u1*           baseAddr;
@@ -672,6 +675,15 @@
     return &pDexFile->pClassDefs[idx];
 }
 
+/* given a ClassDef pointer, recover its index */
+DEX_INLINE u4 dexGetIndexForClassDef(const DexFile* pDexFile,
+    const DexClassDef* pClassDef)
+{
+    assert(pClassDef >= pDexFile->pClassDefs &&
+           pClassDef < pDexFile->pClassDefs + pDexFile->pHeader->classDefsSize);
+    return pClassDef - pDexFile->pClassDefs;
+}
+
 /* get the interface list for a DexClass */
 DEX_INLINE const DexTypeList* dexGetInterfacesList(const DexFile* pDexFile,
     const DexClassDef* pClassDef)
@@ -723,6 +735,9 @@
     return dexStringById(pDexFile, pClassDef->sourceFileIdx);
 }
 
+/* get the size, in bytes, of a DexCode */
+size_t dexGetDexCodeSize(const DexCode* pCode);
+
 /* Get the list of "tries" for the given DexCode. */
 DEX_INLINE const DexTry* dexGetTries(const DexCode* pCode) {
     const u2* insnsEnd = &pCode->insns[pCode->insnsSize];
@@ -741,6 +756,7 @@
     return (const u1*) &pTries[pCode->triesSize];
 }
 
+/* get a pointer to the start of the debugging data */
 DEX_INLINE const u1* dexGetDebugInfoStream(const DexFile* pDexFile,
     const DexCode* pCode)
 {
diff --git a/libdex/DexSwapVerify.c b/libdex/DexSwapVerify.c
index 5ecda9f..bc6f51f 100644
--- a/libdex/DexSwapVerify.c
+++ b/libdex/DexSwapVerify.c
@@ -362,12 +362,15 @@
 static bool swapMap(CheckState* state, DexMapList* pMap)
 {
     DexMapItem* item = pMap->list;
-    u4 count = pMap->size;
+    u4 count;
     u4 dataItemCount = 0; // Total count of items in the data section.
     u4 dataItemsLeft = state->pHeader->dataSize; // See use below.
     u4 usedBits = 0;      // Bit set: one bit per section
     bool first = true;
     u4 lastOffset = 0;
+
+    SWAP_FIELD4(pMap->size);
+    count = pMap->size;
     
     CHECK_LIST_SIZE(item, count, sizeof(DexMapItem));
 
@@ -392,21 +395,21 @@
         }
 
         if (isDataSectionType(item->type)) {
-            u4 count = item->size;
+            u4 icount = item->size;
 
             /*
              * This sanity check on the data section items ensures that
              * there are no more items than the number of bytes in
              * the data section.
              */
-            if (count > dataItemsLeft) {
+            if (icount > dataItemsLeft) {
                 LOGE("Unrealistically many items in the data section: "
-                        "at least %d\n", dataItemCount + count);
+                        "at least %d\n", dataItemCount + icount);
                 return false;
             }
 
-            dataItemsLeft -= count;
-            dataItemCount += count;
+            dataItemsLeft -= icount;
+            dataItemCount += icount;
         }
 
         u4 bit = mapTypeToBitMask(item->type);
@@ -2077,6 +2080,7 @@
     while (size--) {
         data = verifyEncodedValue(state, data, crossVerify);
         if (data == NULL) {
+            LOGE("Bogus encoded_array value\n");
             return NULL;
         }
     }
diff --git a/libdex/InstrUtils.c b/libdex/InstrUtils.c
index b0718f3..93e1f00 100644
--- a/libdex/InstrUtils.c
+++ b/libdex/InstrUtils.c
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 /*
  * Dalvik instruction utility functions.
  */
@@ -37,6 +38,10 @@
  */
 InstructionWidth* dexCreateInstrWidthTable(void)
 {
+#ifdef __ARM_ARCH_7A__
+    /* hack to work around mysterious problem on emulator */
+    LOGD("creating instr width table\n");
+#endif
     InstructionWidth* instrWidth;
     int i;
 
@@ -49,7 +54,7 @@
         int width = 0;
 
         switch (opc) {
-        case OP_NOP:    /* switch-statement data is a special case of NOP */
+        case OP_NOP:    /* note data for e.g. switch-* encoded "inside" a NOP */
         case OP_MOVE:
         case OP_MOVE_WIDE:
         case OP_MOVE_OBJECT:
@@ -289,6 +294,7 @@
         case OP_IPUT_QUICK:
         case OP_IPUT_WIDE_QUICK:
         case OP_IPUT_OBJECT_QUICK:
+        case OP_THROW_VERIFICATION_ERROR:
             width = -2;
             break;
         case OP_INVOKE_VIRTUAL_QUICK:
@@ -320,7 +326,6 @@
         case OP_UNUSED_EA:
         case OP_UNUSED_EB:
         case OP_UNUSED_EC:
-        case OP_UNUSED_ED:
         case OP_UNUSED_EF:
         case OP_UNUSED_F1:
         case OP_UNUSED_FC:
@@ -538,16 +543,6 @@
         case OP_SPUT_SHORT:
         case OP_SPUT_WIDE:
         case OP_SPUT_OBJECT:
-        case OP_INVOKE_VIRTUAL:
-        case OP_INVOKE_VIRTUAL_RANGE:
-        case OP_INVOKE_SUPER:
-        case OP_INVOKE_SUPER_RANGE:
-        case OP_INVOKE_DIRECT:
-        case OP_INVOKE_DIRECT_RANGE:
-        case OP_INVOKE_STATIC:
-        case OP_INVOKE_STATIC_RANGE:
-        case OP_INVOKE_INTERFACE:
-        case OP_INVOKE_INTERFACE_RANGE:
         case OP_DIV_INT:
         case OP_REM_INT:
         case OP_DIV_LONG:
@@ -563,6 +558,19 @@
             flags = kInstrCanContinue | kInstrCanThrow;
             break;
 
+        case OP_INVOKE_VIRTUAL:
+        case OP_INVOKE_VIRTUAL_RANGE:
+        case OP_INVOKE_SUPER:
+        case OP_INVOKE_SUPER_RANGE:
+        case OP_INVOKE_DIRECT:
+        case OP_INVOKE_DIRECT_RANGE:
+        case OP_INVOKE_STATIC:
+        case OP_INVOKE_STATIC_RANGE:
+        case OP_INVOKE_INTERFACE:
+        case OP_INVOKE_INTERFACE_RANGE:
+            flags = kInstrCanContinue | kInstrCanThrow | kInstrInvoke;
+            break;
+
         case OP_RETURN_VOID:
         case OP_RETURN:
         case OP_RETURN_WIDE:
@@ -578,7 +586,7 @@
         case OP_GOTO:
         case OP_GOTO_16:
         case OP_GOTO_32:
-            flags = kInstrCanBranch;
+            flags = kInstrCanBranch | kInstrUnconditional;
             break;
 
         /* conditional branches */
@@ -603,7 +611,10 @@
             flags = kInstrCanSwitch | kInstrCanContinue;
             break;
 
-        /* optimizer-generated instructions */
+        /* verifier/optimizer-generated instructions */
+        case OP_THROW_VERIFICATION_ERROR:
+            flags = kInstrCanThrow;
+            break;
         case OP_EXECUTE_INLINE:
             flags = kInstrCanContinue;
             break;
@@ -613,12 +624,15 @@
         case OP_IPUT_QUICK:
         case OP_IPUT_WIDE_QUICK:
         case OP_IPUT_OBJECT_QUICK:
+            flags = kInstrCanContinue | kInstrCanThrow;
+            break;
+
         case OP_INVOKE_VIRTUAL_QUICK:
         case OP_INVOKE_VIRTUAL_QUICK_RANGE:
         case OP_INVOKE_SUPER_QUICK:
         case OP_INVOKE_SUPER_QUICK_RANGE:
         case OP_INVOKE_DIRECT_EMPTY:
-            flags = kInstrCanContinue | kInstrCanThrow;
+            flags = kInstrCanContinue | kInstrCanThrow | kInstrInvoke;
             break;
 
         /* these should never appear */
@@ -641,7 +655,6 @@
         case OP_UNUSED_EA:
         case OP_UNUSED_EB:
         case OP_UNUSED_EC:
-        case OP_UNUSED_ED:
         case OP_UNUSED_EF:
         case OP_UNUSED_F1:
         case OP_UNUSED_FC:
@@ -950,6 +963,9 @@
         /*
          * Optimized instructions.
          */
+        case OP_THROW_VERIFICATION_ERROR:
+            fmt = kFmt20bc;
+            break;
         case OP_IGET_QUICK:
         case OP_IGET_WIDE_QUICK:
         case OP_IGET_OBJECT_QUICK:
@@ -993,7 +1009,6 @@
         case OP_UNUSED_EA:
         case OP_UNUSED_EB:
         case OP_UNUSED_EC:
-        case OP_UNUSED_ED:
         case OP_UNUSED_EF:
         case OP_UNUSED_F1:
         case OP_UNUSED_FC:
@@ -1038,38 +1053,39 @@
     pDec->opCode = (OpCode) INST_INST(inst);
 
     switch (dexGetInstrFormat(fmts, pDec->opCode)) {
-    case kFmt10x:        // op
+    case kFmt10x:       // op
         /* nothing to do; copy the AA bits out for the verifier */
         pDec->vA = INST_AA(inst);
         break;
-    case kFmt12x:        // op vA, vB
+    case kFmt12x:       // op vA, vB
         pDec->vA = INST_A(inst);
         pDec->vB = INST_B(inst);
         break;
-    case kFmt11n:        // op vA, #+B
+    case kFmt11n:       // op vA, #+B
         pDec->vA = INST_A(inst); 
         pDec->vB = (s4) (INST_B(inst) << 28) >> 28; // sign extend 4-bit value
         break;
-    case kFmt11x:        // op vAA
+    case kFmt11x:       // op vAA
         pDec->vA = INST_AA(inst);
         break;
-    case kFmt10t:        // op +AA
+    case kFmt10t:       // op +AA
         pDec->vA = (s1) INST_AA(inst);              // sign-extend 8-bit value
         break;
-    case kFmt20t:        // op +AAAA
+    case kFmt20t:       // op +AAAA
         pDec->vA = (s2) FETCH(1);                   // sign-extend 16-bit value
         break;
-    case kFmt21c:        // op vAA, thing@BBBB
-    case kFmt22x:        // op vAA, vBBBB
+    case kFmt20bc:      // op AA, thing@BBBB
+    case kFmt21c:       // op vAA, thing@BBBB
+    case kFmt22x:       // op vAA, vBBBB
         pDec->vA = INST_AA(inst);
         pDec->vB = FETCH(1);
         break;
-    case kFmt21s:        // op vAA, #+BBBB
-    case kFmt21t:        // op vAA, +BBBB
+    case kFmt21s:       // op vAA, #+BBBB
+    case kFmt21t:       // op vAA, +BBBB
         pDec->vA = INST_AA(inst);
         pDec->vB = (s2) FETCH(1);                   // sign-extend 16-bit value
         break;
-    case kFmt21h:        // op vAA, #+BBBB0000[00000000]
+    case kFmt21h:       // op vAA, #+BBBB0000[00000000]
         pDec->vA = INST_AA(inst);
         /*
          * The value should be treated as right-zero-extended, but we don't
@@ -1078,24 +1094,24 @@
          */
         pDec->vB = FETCH(1);
         break;
-    case kFmt23x:        // op vAA, vBB, vCC
+    case kFmt23x:       // op vAA, vBB, vCC
         pDec->vA = INST_AA(inst);
         pDec->vB = FETCH(1) & 0xff;
         pDec->vC = FETCH(1) >> 8;
         break;
-    case kFmt22b:        // op vAA, vBB, #+CC
+    case kFmt22b:       // op vAA, vBB, #+CC
         pDec->vA = INST_AA(inst);
         pDec->vB = FETCH(1) & 0xff;
         pDec->vC = (s1) (FETCH(1) >> 8);            // sign-extend 8-bit value
         break;
-    case kFmt22s:        // op vA, vB, #+CCCC
-    case kFmt22t:        // op vA, vB, +CCCC
+    case kFmt22s:       // op vA, vB, #+CCCC
+    case kFmt22t:       // op vA, vB, +CCCC
         pDec->vA = INST_A(inst);
         pDec->vB = INST_B(inst);
         pDec->vC = (s2) FETCH(1);                   // sign-extend 16-bit value
         break;
-    case kFmt22c:        // op vA, vB, thing@CCCC
-    case kFmt22cs:       // [opt] op vA, vB, field offset CCCC
+    case kFmt22c:       // op vA, vB, thing@CCCC
+    case kFmt22cs:      // [opt] op vA, vB, field offset CCCC
         pDec->vA = INST_A(inst);
         pDec->vB = INST_B(inst);
         pDec->vC = FETCH(1);
@@ -1103,21 +1119,21 @@
     case kFmt30t:        // op +AAAAAAAA
         pDec->vA = FETCH(1) | ((u4) FETCH(2) << 16); // signed 32-bit value
         break;
-    case kFmt31t:        // op vAA, +BBBBBBBB
-    case kFmt31c:        // op vAA, thing@BBBBBBBB
+    case kFmt31t:       // op vAA, +BBBBBBBB
+    case kFmt31c:       // op vAA, thing@BBBBBBBB
         pDec->vA = INST_AA(inst);
         pDec->vB = FETCH(1) | ((u4) FETCH(2) << 16); // 32-bit value
         break;
-    case kFmt32x:        // op vAAAA, vBBBB
+    case kFmt32x:       // op vAAAA, vBBBB
         pDec->vA = FETCH(1);
         pDec->vB = FETCH(2);
         break;
-    case kFmt31i:        // op vAA, #+BBBBBBBB
+    case kFmt31i:       // op vAA, #+BBBBBBBB
         pDec->vA = INST_AA(inst);
         pDec->vB = FETCH(1) | ((u4) FETCH(2) << 16);
         break;
-    case kFmt35c:        // op vB, {vD..vG,vA}, thing@CCCC
-    case kFmt35ms:       // [opt] invoke-virtual+super
+    case kFmt35c:       // op vB, {vD..vG,vA}, thing@CCCC
+    case kFmt35ms:      // [opt] invoke-virtual+super
         {
             /*
              * The lettering changes that came about when we went from 4 args
@@ -1158,7 +1174,7 @@
                 pDec->vC = pDec->arg[0];
         }
         break;
-    case kFmt3inline:    // [opt] inline invoke
+    case kFmt3inline:   // [opt] inline invoke
         {
             u2 regList;
             int i;
diff --git a/libdex/InstrUtils.h b/libdex/InstrUtils.h
index 9d8e5c3..9728cd4 100644
--- a/libdex/InstrUtils.h
+++ b/libdex/InstrUtils.h
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 /*
  * Dalvik instruction utility functions.
  */
@@ -42,6 +43,7 @@
     kFmt11n,        // op vA, #+B
     kFmt11x,        // op vAA
     kFmt10t,        // op +AA
+    kFmt20bc,       // op AA, thing@BBBB
     kFmt20t,        // op +AAAA
     kFmt22x,        // op vAA, vBBBB
     kFmt21t,        // op vAA, +BBBB
@@ -97,6 +99,8 @@
     kInstrCanSwitch     = 1 << 2,   // switch statement
     kInstrCanThrow      = 1 << 3,   // could cause an exception to be thrown
     kInstrCanReturn     = 1 << 4,   // returns, no additional statements
+    kInstrInvoke        = 1 << 5,   // a flavor of invoke
+    kInstrUnconditional = 1 << 6,   // unconditional branch
 };
 
 
diff --git a/libdex/Leb128.h b/libdex/Leb128.h
index 215ae30..41799fe 100644
--- a/libdex/Leb128.h
+++ b/libdex/Leb128.h
@@ -124,4 +124,41 @@
  */
 int readAndVerifySignedLeb128(const u1** pStream, const u1* limit, bool* okay);
 
+
+/*
+ * Writes a 32-bit value in unsigned ULEB128 format.
+ *
+ * Returns the updated pointer.
+ */
+DEX_INLINE u1* writeUnsignedLeb128(u1* ptr, u4 data)
+{
+    while (true) {
+        u1 out = data & 0x7f;
+        if (out != data) {
+            *ptr++ = out | 0x80;
+            data >>= 7;
+        } else {
+            *ptr++ = out;
+            break;
+        }
+    }
+
+    return ptr;
+}
+
+/*
+ * Returns the number of bytes needed to encode "val" in ULEB128 form.
+ */
+DEX_INLINE int unsignedLeb128Size(u4 data)
+{
+    int count = 0;
+
+    do {
+        data >>= 7;
+        count++;
+    } while (data != 0);
+
+    return count;
+}
+
 #endif
diff --git a/libdex/OpCode.h b/libdex/OpCode.h
index d389472..1272231 100644
--- a/libdex/OpCode.h
+++ b/libdex/OpCode.h
@@ -331,9 +331,9 @@
     OP_UNUSED_EA                    = 0xea,
     OP_UNUSED_EB                    = 0xeb,
     OP_UNUSED_EC                    = 0xec,
-    OP_UNUSED_ED                    = 0xed,
 
     /* optimizer output -- these are never generated by "dx" */
+    OP_THROW_VERIFICATION_ERROR     = 0xed,
     OP_EXECUTE_INLINE               = 0xee,
     OP_UNUSED_EF                    = 0xef, /* OP_EXECUTE_INLINE_RANGE? */
 
@@ -628,7 +628,7 @@
         H(OP_UNUSED_EA),                                                    \
         H(OP_UNUSED_EB),                                                    \
         H(OP_UNUSED_EC),                                                    \
-        H(OP_UNUSED_ED),                                                    \
+        H(OP_THROW_VERIFICATION_ERROR),                                     \
         H(OP_EXECUTE_INLINE),                                               \
         H(OP_UNUSED_EF),                                                    \
         /* f0..ff */                                                        \
diff --git a/libdex/SysUtil.c b/libdex/SysUtil.c
index 530ac2e..bf1be88 100644
--- a/libdex/SysUtil.c
+++ b/libdex/SysUtil.c
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 /*
  * System utilities.
  */
@@ -64,6 +65,25 @@
 #endif
 }
 
+/*
+ * Create a private anonymous storage area.
+ */
+int sysCreatePrivateMap(size_t length, MemMapping* pMap)
+{
+    void* memPtr;
+
+    memPtr = sysCreateAnonShmem(length);
+    if (memPtr == NULL)
+        return -1;
+
+    pMap->addr = pMap->baseAddr = memPtr;
+    pMap->length = pMap->baseLength = length;
+    return 0;
+}
+
+/*
+ * Determine the current offset and remaining length of the open file.
+ */
 static int getFileStartAndLength(int fd, off_t *start_, size_t *length_)
 {
     off_t start, end;
diff --git a/libdex/SysUtil.h b/libdex/SysUtil.h
index 8d85efa..8b80503 100644
--- a/libdex/SysUtil.h
+++ b/libdex/SysUtil.h
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 /*
  * System utilities.
  */
@@ -63,6 +64,13 @@
     MemMapping* pMap);
 
 /*
+ * Create a private anonymous mapping, useful for large allocations.
+ *
+ * On success, "pMap" is filled in, and zero is returned.
+ */
+int sysCreatePrivateMap(size_t length, MemMapping* pMap);
+
+/*
  * Release the pages associated with a shared memory segment.
  *
  * This does not free "pMap"; it just releases the memory.
diff --git a/libdex/ZipArchive.c b/libdex/ZipArchive.c
index a75a85b..3f88e7d 100644
--- a/libdex/ZipArchive.c
+++ b/libdex/ZipArchive.c
@@ -285,6 +285,8 @@
 
     LOGV("Opening archive '%s' %p\n", fileName, pArchive);
 
+    memset(pArchive, 0, sizeof(ZipArchive));
+
     fd = open(fileName, O_RDONLY, 0);
     if (fd < 0) {
         err = errno ? errno : -1;
diff --git a/libnativehelper/Android.mk b/libnativehelper/Android.mk
index 5f553c5..aa4be86 100644
--- a/libnativehelper/Android.mk
+++ b/libnativehelper/Android.mk
@@ -1,20 +1,36 @@
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
+# 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.
 
-LOCAL_SRC_FILES := \
+
+LOCAL_PATH := $(call my-dir)
+
+#
+# Common definitions for host and device.
+#
+
+src_files := \
 	JNIHelp.c \
 	Register.c
 
-LOCAL_C_INCLUDES += \
+c_includes := \
 	$(JNI_H_INCLUDE)
 
 # Any shared/static libs required by libjavacore
 # need to be mentioned here as well.
 # TODO: fix this requirement
 
-LOCAL_SHARED_LIBRARIES := \
-	liblog \
-	libcutils \
+shared_libraries := \
 	libexpat \
 	libssl \
 	libutils \
@@ -25,10 +41,51 @@
 	libicui18n \
 	libsqlite
 
-LOCAL_STATIC_LIBRARIES := \
+static_libraries := \
 	libjavacore \
 	libfdlibm
 
+
+
+#
+# Build for the target (device).
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(src_files)
+LOCAL_C_INCLUDES := $(c_includes)
+LOCAL_SHARED_LIBRARIES := $(shared_libraries)
+LOCAL_STATIC_LIBRARIES := $(static_libraries)
+
+# liblog and libcutils are shared for target.
+LOCAL_SHARED_LIBRARIES += \
+	liblog libcutils
+
 LOCAL_MODULE := libnativehelper
 
 include $(BUILD_SHARED_LIBRARY)
+
+
+#
+# Build for the host.
+#
+
+ifeq ($(WITH_HOST_DALVIK),true)
+
+    include $(CLEAR_VARS)
+
+    LOCAL_SRC_FILES := $(src_files)
+    LOCAL_C_INCLUDES := $(c_includes)
+    LOCAL_SHARED_LIBRARIES := $(shared_libraries)
+    LOCAL_STATIC_LIBRARIES := $(static_libraries)
+
+    # liblog and libcutils are static for host.
+    LOCAL_STATIC_LIBRARIES += \
+        liblog libcutils
+
+    LOCAL_MODULE := libnativehelper-host
+
+    include $(BUILD_HOST_SHARED_LIBRARY)
+
+endif
diff --git a/libnativehelper/include/nativehelper/JNIHelp.h b/libnativehelper/include/nativehelper/JNIHelp.h
index eec7af8..3982797 100644
--- a/libnativehelper/include/nativehelper/JNIHelp.h
+++ b/libnativehelper/include/nativehelper/JNIHelp.h
@@ -42,6 +42,8 @@
 
 /*
  * Throw an exception with the specified class and an optional message.
+ * The "className" argument will be passed directly to FindClass, which
+ * takes strings with slashes (e.g. "java/lang/Object").
  *
  * Returns 0 on success, nonzero if something failed (e.g. the exception
  * class couldn't be found).
diff --git a/tests/003-omnibus-opcodes/expected.txt b/tests/003-omnibus-opcodes/expected.txt
index 81a8879..4895dc3 100644
--- a/tests/003-omnibus-opcodes/expected.txt
+++ b/tests/003-omnibus-opcodes/expected.txt
@@ -23,6 +23,7 @@
 IntMath.divideByZero
 IntMath.bigDivideOverflow
 IntMath.checkConsts
+IntMath.jlmTests
 FloatMath.convTest
 FloatMath.floatOperTest
 FloatMath.doubleOperTest
@@ -39,6 +40,7 @@
  2: 123.45600128173828
 -2.005440939E9, -8.6133032459203287E18, 123.4560012817382
 FloatMath.checkConsts
+FloatMath.jlmTests
 IntMath.testIntCompare
 IntMath.testLongCompare
 IntMath.testFloatCompare
@@ -64,8 +66,9 @@
 Throw.twoA
 Throw.twoN
 Throw.rethrow
-Caught: java.lang.VerifyError: UnresTest1
-Caught (retry): java.lang.VerifyError: UnresTest1
-Caught: java.lang.VerifyError: UnresTest2
+UnresTest1...
+UnresTest1...
+UnresTest2...
+UnresTest2 done
 InternedString.run
 Done!
diff --git a/tests/003-omnibus-opcodes/src/FloatMath.java b/tests/003-omnibus-opcodes/src/FloatMath.java
index 0c1fe1b..cf4869c 100644
--- a/tests/003-omnibus-opcodes/src/FloatMath.java
+++ b/tests/003-omnibus-opcodes/src/FloatMath.java
@@ -262,6 +262,50 @@
         assert(d > 9.9 && d < 10.1);
     }
 
+    /*
+     * Determine if two floating point numbers are approximately equal.
+     *
+     * (Assumes that floating point is generally working, so we can't use
+     * this for the first set of tests.)
+     */
+    static boolean approxEqual(float a, float b, float maxDelta) {
+        if (a > b)
+            return (a - b) < maxDelta;
+        else
+            return (b - a) < maxDelta;
+    }
+    static boolean approxEqual(double a, double b, double maxDelta) {
+        if (a > b)
+            return (a - b) < maxDelta;
+        else
+            return (b - a) < maxDelta;
+    }
+
+    /*
+     * Test some java.lang.Math functions.
+     *
+     * The method arguments are positive values.
+     */
+    static void jlmTests(float ff, double dd) {
+        System.out.println("FloatMath.jlmTests");
+
+        assert(approxEqual(Math.abs(ff), ff, 0.001f));
+        assert(approxEqual(Math.abs(-ff), ff, 0.001f));
+        assert(approxEqual(Math.min(ff, -5.0f), -5.0f, 0.001f));
+        assert(approxEqual(Math.max(ff, -5.0f), ff, 0.001f));
+
+        assert(approxEqual(Math.abs(dd), dd, 0.001));
+        assert(approxEqual(Math.abs(-dd), dd, 0.001));
+        assert(approxEqual(Math.min(dd, -5.0), -5.0, 0.001));
+        assert(approxEqual(Math.max(dd, -5.0), dd, 0.001));
+
+        double sq = Math.sqrt(dd);
+        assert(approxEqual(sq*sq, dd, 0.001));
+
+        assert(approxEqual(0.5403023058681398, Math.cos(1.0), 0.00000001));
+        assert(approxEqual(0.8414709848078965, Math.sin(1.0), 0.00000001));
+    }
+
     public static void run() {
         convTest();
 
@@ -287,6 +331,8 @@
         unopTest(123.456f);
 
         checkConsts();
+
+        jlmTests(3.14159f, 123456.78987654321);
     }
 }
 
diff --git a/tests/003-omnibus-opcodes/src/IntMath.java b/tests/003-omnibus-opcodes/src/IntMath.java
index 126bec6..d5ac744 100644
--- a/tests/003-omnibus-opcodes/src/IntMath.java
+++ b/tests/003-omnibus-opcodes/src/IntMath.java
@@ -432,6 +432,25 @@
         assert(huge == 0x9922334455667788L);    // const-wide
     }
 
+    /*
+     * Test some java.lang.Math functions.
+     *
+     * The method arguments are positive values.
+     */
+    static void jlmTests(int ii, long ll) {
+        System.out.println("IntMath.jlmTests");
+
+        assert(Math.abs(ii) == ii);
+        assert(Math.abs(-ii) == ii);
+        assert(Math.min(ii, -5) == -5);
+        assert(Math.max(ii, -5) == ii);
+
+        assert(Math.abs(ll) == ll);
+        assert(Math.abs(-ll) == ll);
+        assert(Math.min(ll, -5L) == -5L);
+        assert(Math.max(ll, -5L) == ll);
+    }
+
     public static void run() {
         shiftTest1();
         shiftTest2();
@@ -467,6 +486,8 @@
         checkConsts((byte) 1, (short) -256, -88888, 0x9922334455667788L);
 
         unopCheck(unopTest(38));
+
+        jlmTests(12345, 0x1122334455667788L);
     }
 }
 
diff --git a/tests/003-omnibus-opcodes/src/UnresTest2.java b/tests/003-omnibus-opcodes/src/UnresTest2.java
index 43a92ac..b458bfe 100644
--- a/tests/003-omnibus-opcodes/src/UnresTest2.java
+++ b/tests/003-omnibus-opcodes/src/UnresTest2.java
@@ -44,6 +44,7 @@
         }
 
         checkCasts(stuff);
+        System.out.println("UnresTest2 done");
     }
 }
 
diff --git a/tests/030-bad-finalizer/info.txt b/tests/030-bad-finalizer/info.txt
index 08127da..0f76ad6 100644
--- a/tests/030-bad-finalizer/info.txt
+++ b/tests/030-bad-finalizer/info.txt
@@ -1,6 +1,3 @@
-This is a miscellaneous test that was imported into the new-at-the-time
-runtime test framework. The test is intended to exercise basic features,
-and as such cannot be build on top of junit, since failure of such basic
-features might disrupt junit.
-
-TODO: Real description goes here.
+The finalizer for this class never finishes.  Dalvik is expected to detect
+this situation and abort the VM (so you will likely see a "deadd00d"
+crash in the log output).
diff --git a/tests/042-new-instance/src/Main.java b/tests/042-new-instance/src/Main.java
index 49894fe..037aa2a 100644
--- a/tests/042-new-instance/src/Main.java
+++ b/tests/042-new-instance/src/Main.java
@@ -1,4 +1,20 @@
-// Copyright 2007 The Android Open Source Project
+/*
+ * Copyright (C) 2007 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.reflect.Constructor;
 
 import java.lang.reflect.Constructor;
 
@@ -29,7 +45,7 @@
         try {
             Class c = Class.forName("otherpackage.PackageAccess");
             Object obj = c.newInstance();
-            System.out.println("ERROR: PackageAccess succeeded unexpectedly");
+            System.err.println("ERROR: PackageAccess succeeded unexpectedly");
         } catch (IllegalAccessException iae) {
             System.out.println("Got expected PackageAccess complaint");
         } catch (Exception ex) {
diff --git a/tests/044-proxy/expected.txt b/tests/044-proxy/expected.txt
index 255cf99..69a94f2 100644
--- a/tests/044-proxy/expected.txt
+++ b/tests/044-proxy/expected.txt
@@ -45,10 +45,10 @@
  (no args)
 Got expected ie
 
-Proxy methods: [public native boolean .$Proxy0.equals(java.lang.Object), public native int .$Proxy0.hashCode(), public native java.lang.String .$Proxy0.toString(), public native int .$Proxy0.rectangle(int,int), public native int .$Proxy0.square(int,int), public native int .$Proxy0.trapezoid(int,double,int), public native java.lang.String .$Proxy0.blob(), public native void .$Proxy0.circle(int), public native void .$Proxy0.upCheck(), public native void .$Proxy0.upChuck(), public native double .$Proxy0.blue(int), public native R0aa .$Proxy0.checkMe(), public native int .$Proxy0.green(double), public native int .$Proxy0.mauve(java.lang.String), public native int .$Proxy0.red(float)]
+Proxy methods: [public native boolean $Proxy0.equals(java.lang.Object), public native int $Proxy0.hashCode(), public native java.lang.String $Proxy0.toString(), public native int $Proxy0.rectangle(int,int), public native int $Proxy0.square(int,int), public native int $Proxy0.trapezoid(int,double,int), public native java.lang.String $Proxy0.blob(), public native void $Proxy0.circle(int), public native void $Proxy0.upCheck(), public native void $Proxy0.upChuck(), public native double $Proxy0.blue(int), public native R0aa $Proxy0.checkMe(), public native int $Proxy0.green(double), public native int $Proxy0.mauve(java.lang.String), public native int $Proxy0.red(float)]
 Decl annos: []
 Param annos (1) : [[]]
-Proxy fields: [private static [[Ljava.lang.Throwable; .$Proxy0.throws]
+Proxy fields: [private static [[Ljava.lang.Throwable; $Proxy0.throws]
 Dupe threw expected exception
 Clash threw expected exception
 Clash2 threw expected exception
diff --git a/tests/065-mismatched-implements/expected.txt b/tests/065-mismatched-implements/expected.txt
index 36ebe5e..09c0596 100644
--- a/tests/065-mismatched-implements/expected.txt
+++ b/tests/065-mismatched-implements/expected.txt
@@ -1,3 +1 @@
-Dalvik VM unable to find static main(String[]) in 'Main'
-java.lang.VerifyError: Main
-	at dalvik.system.NativeStart.main(Native Method)
+Got expected ICCE
diff --git a/tests/065-mismatched-implements/info.txt b/tests/065-mismatched-implements/info.txt
index 58d9b69..74c3ff3 100644
--- a/tests/065-mismatched-implements/info.txt
+++ b/tests/065-mismatched-implements/info.txt
@@ -1,19 +1,2 @@
 This tests what happens when class A implements interface B, but somebody
 turns B into an abstract class without rebuilding A.
-
-If you run this with --no-verify you get reasonable results:
-
-java.lang.NoClassDefFoundError: Base
-	at Main.main(Main.java:8)
-	at dalvik.system.NativeStart.main(Native Method)
-Caused by: java.lang.IncompatibleClassChangeError: Base
-	at dalvik.system.DexFile.defineClass(Native Method)
-	at dalvik.system.DexFile.loadClass(DexFile.java:91)
-	at dalvik.system.PathClassLoader.findClass(PathClassLoader.java:175)
-	at java.lang.ClassLoader.loadClass(ClassLoader.java:453)
-	at java.lang.ClassLoader.loadClass(ClassLoader.java:421)
-	... 2 more
-
-With the verifier enabled, you get a relatively content-free VerifyError
-with the detail only appearing in the log file.
-
diff --git a/tests/065-mismatched-implements/src/Indirect.java b/tests/065-mismatched-implements/src/Indirect.java
new file mode 100644
index 0000000..dd87a65
--- /dev/null
+++ b/tests/065-mismatched-implements/src/Indirect.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Error indirection class.
+ *
+ * Some VMs will load this class and fail on the "new" call, others will
+ * refuse to load this class at all.
+ */
+public class Indirect {
+    public static void main() {
+        Base base = new Base();
+    }
+}
+
diff --git a/tests/065-mismatched-implements/src/Main.java b/tests/065-mismatched-implements/src/Main.java
index 4a25232..6993b17 100644
--- a/tests/065-mismatched-implements/src/Main.java
+++ b/tests/065-mismatched-implements/src/Main.java
@@ -1,11 +1,30 @@
-// Copyright 2008 The Android Open Source Project
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 /*
  * Test field access through reflection.
  */
 public class Main {
     public static void main(String[] args) {
-        Base base = new Base();
+        try {
+            Indirect.main();
+            System.err.println("Succeeded unexpectedly");
+        } catch (IncompatibleClassChangeError icce) {
+            System.out.println("Got expected ICCE");
+        }
     }
 }
 
diff --git a/tests/066-mismatched-super/expected.txt b/tests/066-mismatched-super/expected.txt
index 36ebe5e..09c0596 100644
--- a/tests/066-mismatched-super/expected.txt
+++ b/tests/066-mismatched-super/expected.txt
@@ -1,3 +1 @@
-Dalvik VM unable to find static main(String[]) in 'Main'
-java.lang.VerifyError: Main
-	at dalvik.system.NativeStart.main(Native Method)
+Got expected ICCE
diff --git a/tests/066-mismatched-super/info.txt b/tests/066-mismatched-super/info.txt
index 2158899..7865ffc 100644
--- a/tests/066-mismatched-super/info.txt
+++ b/tests/066-mismatched-super/info.txt
@@ -1,19 +1,2 @@
 This tests what happens when class A extends abstract class B, but somebody
 turns B into an interface without rebuilding A.
-
-If you run this with --no-verify you get reasonable results:
-
-java.lang.NoClassDefFoundError: Base
-	at Main.main(Main.java:8)
-	at dalvik.system.NativeStart.main(Native Method)
-Caused by: java.lang.IncompatibleClassChangeError: superclass is an interface
-	at dalvik.system.DexFile.defineClass(Native Method)
-	at dalvik.system.DexFile.loadClass(DexFile.java:91)
-	at dalvik.system.PathClassLoader.findClass(PathClassLoader.java:175)
-	at java.lang.ClassLoader.loadClass(ClassLoader.java:453)
-	at java.lang.ClassLoader.loadClass(ClassLoader.java:421)
-	... 2 more
-
-With the verifier enabled, you get a relatively content-free VerifyError
-with the detail only appearing in the log file.
-
diff --git a/tests/066-mismatched-super/src/Indirect.java b/tests/066-mismatched-super/src/Indirect.java
new file mode 100644
index 0000000..dd87a65
--- /dev/null
+++ b/tests/066-mismatched-super/src/Indirect.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Error indirection class.
+ *
+ * Some VMs will load this class and fail on the "new" call, others will
+ * refuse to load this class at all.
+ */
+public class Indirect {
+    public static void main() {
+        Base base = new Base();
+    }
+}
+
diff --git a/tests/066-mismatched-super/src/Main.java b/tests/066-mismatched-super/src/Main.java
index 4a25232..6993b17 100644
--- a/tests/066-mismatched-super/src/Main.java
+++ b/tests/066-mismatched-super/src/Main.java
@@ -1,11 +1,30 @@
-// Copyright 2008 The Android Open Source Project
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 /*
  * Test field access through reflection.
  */
 public class Main {
     public static void main(String[] args) {
-        Base base = new Base();
+        try {
+            Indirect.main();
+            System.err.println("Succeeded unexpectedly");
+        } catch (IncompatibleClassChangeError icce) {
+            System.out.println("Got expected ICCE");
+        }
     }
 }
 
diff --git a/tests/068-classloader/expected.txt b/tests/068-classloader/expected.txt
index 0ca8862..bf131ee 100644
--- a/tests/068-classloader/expected.txt
+++ b/tests/068-classloader/expected.txt
@@ -4,6 +4,9 @@
 Got expected CNFE/IAE #2
 Got expected CNFE/IAE #3
 Got expected LinkageError on DE
+Got DEO result DoubledExtendOkay 1
+Got LinkageError on GD
+Got LinkageError on TA
 Ctor: doubled implement, type 1
 DoubledImplement one
 Got LinkageError on DI (early)
diff --git a/tests/068-classloader/src-ex/AbstractGet.java b/tests/068-classloader/src-ex/AbstractGet.java
new file mode 100644
index 0000000..b62aa8f
--- /dev/null
+++ b/tests/068-classloader/src-ex/AbstractGet.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+/**
+ * Verify that we don't reject this with a LinkageError.
+ */
+public class AbstractGet extends AbstractBase {
+    public DoubledExtendOkay getExtended() {
+        return new DoubledExtendOkay();
+    }
+}
+
+/**
+ * Abstract class, does not declare getAbstract.  This cause the VM to
+ * generate a "miranda" method.
+ */
+abstract class AbstractBase extends BaseOkay {
+    public abstract DoubledExtendOkay getExtended();
+}
+
diff --git a/tests/068-classloader/src-ex/DoubledExtendOkay.java b/tests/068-classloader/src-ex/DoubledExtendOkay.java
new file mode 100644
index 0000000..766fa8e
--- /dev/null
+++ b/tests/068-classloader/src-ex/DoubledExtendOkay.java
@@ -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.
+ */
+
+/**
+ * "Okay" doubled sub-class, form #2.
+ */
+public class DoubledExtendOkay extends BaseOkay {
+    public DoubledExtendOkay() {
+        //System.out.println("Ctor: doubled extend okay, type 2");
+    }
+
+    /*
+    @Override
+    public DoubledExtendOkay getExtended() {
+        //System.out.println("getExtended 2");
+        return new DoubledExtendOkay();
+    }
+    */
+
+    public String getStr() {
+        return "DoubledExtendOkay 2";
+    }
+}
+
diff --git a/tests/068-classloader/src-ex/GetDoubled.java b/tests/068-classloader/src-ex/GetDoubled.java
new file mode 100644
index 0000000..5e20441
--- /dev/null
+++ b/tests/068-classloader/src-ex/GetDoubled.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * The interface we implement was declared in a different class loader,
+ * which means the DoubledExtend we return is not the one it was declared
+ * to return.
+ */
+public class GetDoubled implements IGetDoubled {
+    public DoubledExtendOkay getDoubled() {
+        return new DoubledExtendOkay();
+    }
+}
+
diff --git a/tests/068-classloader/src/BaseOkay.java b/tests/068-classloader/src/BaseOkay.java
new file mode 100644
index 0000000..c5c3f7a
--- /dev/null
+++ b/tests/068-classloader/src/BaseOkay.java
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+/**
+ * Common base class.
+ */
+public class BaseOkay implements IDoubledExtendOkay {
+    public BaseOkay() {}
+
+    public DoubledExtendOkay getExtended() {
+        return new DoubledExtendOkay();
+    }
+
+    public static String doStuff(DoubledExtendOkay dt) {
+        return dt.getStr();
+    }
+}
+
+/**
+ * Interface that declares the not-overridden method.  This exists to ensure
+ * that the existence of an interface doesn't trip the check.
+ */
+interface IDoubledExtendOkay {
+    public DoubledExtendOkay getExtended();
+}
+
diff --git a/tests/068-classloader/src/DoubledExtendOkay.java b/tests/068-classloader/src/DoubledExtendOkay.java
new file mode 100644
index 0000000..e8ff404
--- /dev/null
+++ b/tests/068-classloader/src/DoubledExtendOkay.java
@@ -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.
+ */
+
+/**
+ * "Okay" doubled sub-class, form #1.
+ */
+public class DoubledExtendOkay extends BaseOkay {
+    public DoubledExtendOkay() {
+        //System.out.println("Ctor: doubled extend okay, type 1");
+    }
+
+    /*
+    @Override
+    public DoubledExtendOkay getExtended() {
+        System.out.println("getExtended 1");
+        return new DoubledExtendOkay();
+    }
+    */
+
+    public String getStr() {
+        return "DoubledExtendOkay 1";
+    }
+}
+
diff --git a/tests/068-classloader/src/FancyLoader.java b/tests/068-classloader/src/FancyLoader.java
index 491fd5c..1daf155 100644
--- a/tests/068-classloader/src/FancyLoader.java
+++ b/tests/068-classloader/src/FancyLoader.java
@@ -1,4 +1,18 @@
-// Copyright 2008 The Android Open Source Project
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -29,6 +43,8 @@
     /* on Dalvik, this is a DexFile; otherwise, it's null */
     private Class mDexClass;
 
+    private Object mDexFile;
+
     /**
      * Construct FancyLoader, grabbing a reference to the DexFile class
      * if we're running under Dalvik.
@@ -64,26 +80,29 @@
     private Class<?> findClassDalvik(String name)
         throws ClassNotFoundException {
 
-        Constructor ctor;
-        Object dexFile;
+        if (mDexFile == null) {
+            synchronized (FancyLoader.class) {
+                Constructor ctor;
+                /*
+                 * Construct a DexFile object through reflection.
+                 */
+                try {
+                    ctor = mDexClass.getConstructor(new Class[] {String.class});
+                } catch (NoSuchMethodException nsme) {
+                    throw new ClassNotFoundException("getConstructor failed",
+                        nsme);
+                }
 
-        /*
-         * Construct a DexFile object through reflection.
-         */
-        try {
-            ctor = mDexClass.getConstructor(new Class[] { String.class });
-        } catch (NoSuchMethodException nsme) {
-            throw new ClassNotFoundException("getConstructor failed", nsme);
-        }
-
-        try {
-            dexFile = ctor.newInstance(DEX_FILE);
-        } catch (InstantiationException ie) {
-            throw new ClassNotFoundException("newInstance failed", ie);
-        } catch (IllegalAccessException iae) {
-            throw new ClassNotFoundException("newInstance failed", iae);
-        } catch (InvocationTargetException ite) {
-            throw new ClassNotFoundException("newInstance failed", ite);
+                try {
+                    mDexFile = ctor.newInstance(DEX_FILE);
+                } catch (InstantiationException ie) {
+                    throw new ClassNotFoundException("newInstance failed", ie);
+                } catch (IllegalAccessException iae) {
+                    throw new ClassNotFoundException("newInstance failed", iae);
+                } catch (InvocationTargetException ite) {
+                    throw new ClassNotFoundException("newInstance failed", ite);
+                }
+            }
         }
 
         /*
@@ -99,7 +118,7 @@
         }
 
         try {
-            meth.invoke(dexFile, name, this);
+            meth.invoke(mDexFile, name, this);
         } catch (IllegalAccessException iae) {
             throw new ClassNotFoundException("loadClass failed", iae);
         } catch (InvocationTargetException ite) {
diff --git a/tests/068-classloader/src/IGetDoubled.java b/tests/068-classloader/src/IGetDoubled.java
new file mode 100644
index 0000000..0a4ac91
--- /dev/null
+++ b/tests/068-classloader/src/IGetDoubled.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+/**
+ * Interface, loaded from one loader, used from another.
+ */
+public interface IGetDoubled {
+    public DoubledExtendOkay getDoubled();
+}
+
diff --git a/tests/068-classloader/src/Main.java b/tests/068-classloader/src/Main.java
index f8698be..0788b52 100644
--- a/tests/068-classloader/src/Main.java
+++ b/tests/068-classloader/src/Main.java
@@ -25,6 +25,8 @@
         FancyLoader loader;
 
         loader = new FancyLoader(ClassLoader.getSystemClassLoader());
+        //System.out.println("SYSTEM: " + ClassLoader.getSystemClassLoader());
+        //System.out.println("ALTERN: " + loader);
 
         /*
          * This statement has no effect on this program, but it can
@@ -51,6 +53,9 @@
         testAccess3(loader);
 
         testExtend(loader);
+        testExtendOkay(loader);
+        testInterface(loader);
+        testAbstract(loader);
         testImplement(loader);
         testIfaceImplement(loader);
     }
@@ -175,6 +180,146 @@
     }
 
     /**
+     * Test a doubled class that extends the base class, but is okay since
+     * it doesn't override the base class method.
+     */
+    static void testExtendOkay(ClassLoader loader) {
+        Class doubledExtendOkayClass;
+        Object obj;
+
+        /* get the "alternate" version of DoubledExtendOkay */
+        try {
+            doubledExtendOkayClass = loader.loadClass("DoubledExtendOkay");
+        } catch (ClassNotFoundException cnfe) {
+            System.err.println("loadClass failed: " + cnfe);
+            return;
+        }
+
+        /* instantiate */
+        try {
+            obj = doubledExtendOkayClass.newInstance();
+        } catch (InstantiationException ie) {
+            System.err.println("newInstance failed: " + ie);
+            return;
+        } catch (IllegalAccessException iae) {
+            System.err.println("newInstance failed: " + iae);
+            return;
+        } catch (LinkageError le) {
+            System.err.println("Got unexpected LinkageError on DEO");
+            le.printStackTrace();
+            return;
+        }
+
+        /* use the base class reference to get a CL-specific instance */
+        BaseOkay baseRef = (BaseOkay) obj;
+        DoubledExtendOkay de = baseRef.getExtended();
+
+        /* try to call through it */
+        try {
+            String result;
+
+            result = BaseOkay.doStuff(de);
+            System.out.println("Got DEO result " + result);
+        } catch (LinkageError le) {
+            System.err.println("Got unexpected LinkageError on DEO");
+            le.printStackTrace();
+            return;
+        }
+    }
+
+    /**
+     * Try to access a doubled class through a class that implements
+     * an interface declared in a different class.
+     */
+    static void testInterface(ClassLoader loader) {
+        Class getDoubledClass;
+        Object obj;
+
+        /* get GetDoubled from the "alternate" class loader */
+        try {
+            getDoubledClass = loader.loadClass("GetDoubled");
+        } catch (ClassNotFoundException cnfe) {
+            System.err.println("loadClass failed: " + cnfe);
+            return;
+        }
+
+        /* instantiate */
+        try {
+            obj = getDoubledClass.newInstance();
+        } catch (InstantiationException ie) {
+            System.err.println("newInstance failed: " + ie);
+            return;
+        } catch (IllegalAccessException iae) {
+            System.err.println("newInstance failed: " + iae);
+            return;
+        } catch (LinkageError le) {
+            // Dalvik bails here
+            System.out.println("Got LinkageError on GD");
+            return;
+        }
+
+        /*
+         * Cast the object to the interface, and try to use it.
+         */
+        IGetDoubled iface = (IGetDoubled) obj;
+        try {
+            /* "de" will be the wrong variety of DoubledExtendOkay */
+            DoubledExtendOkay de = iface.getDoubled();
+            // reference impl bails here
+            String str = de.getStr();
+        } catch (LinkageError le) {
+            System.out.println("Got LinkageError on GD");
+            return;
+        }
+        System.err.println("Should have failed by now on GetDoubled");
+    }
+
+    /**
+     * Throw an abstract class into the middle and see what happens.
+     */
+    static void testAbstract(ClassLoader loader) {
+        Class abstractGetClass;
+        Object obj;
+
+        /* get AbstractGet from the "alternate" loader */
+        try {
+            abstractGetClass = loader.loadClass("AbstractGet");
+        } catch (ClassNotFoundException cnfe) {
+            System.err.println("loadClass ta failed: " + cnfe);
+            return;
+        }
+
+        /* instantiate */
+        try {
+            obj = abstractGetClass.newInstance();
+        } catch (InstantiationException ie) {
+            System.err.println("newInstance failed: " + ie);
+            return;
+        } catch (IllegalAccessException iae) {
+            System.err.println("newInstance failed: " + iae);
+            return;
+        } catch (LinkageError le) {
+            System.out.println("Got LinkageError on TA");
+            return;
+        }
+
+        /* use the base class reference to get a CL-specific instance */
+        BaseOkay baseRef = (BaseOkay) obj;
+        DoubledExtendOkay de = baseRef.getExtended();
+
+        /* try to call through it */
+        try {
+            String result;
+
+            result = BaseOkay.doStuff(de);
+        } catch (LinkageError le) {
+            System.out.println("Got LinkageError on TA");
+            return;
+        }
+        System.err.println("Should have failed by now in testAbstract");
+    }
+
+    /**
      * Test a doubled class that implements a common interface.
      */
     static void testImplement(ClassLoader loader) {
diff --git a/tests/071-dexfile/info.txt b/tests/071-dexfile/info.txt
index 5eb0489..54d9ed0 100644
--- a/tests/071-dexfile/info.txt
+++ b/tests/071-dexfile/info.txt
@@ -1,2 +1,4 @@
 Exercise some Dalvik-specific DEX file features.  This is not expected to
 work on other VMs.
+
+NOTE: the test requires that /sdcard exists and is writable.
diff --git a/tests/071-dexfile/src/Main.java b/tests/071-dexfile/src/Main.java
index 0e6cce7..42c841d 100644
--- a/tests/071-dexfile/src/Main.java
+++ b/tests/071-dexfile/src/Main.java
@@ -15,6 +15,7 @@
  */
 
 import java.io.File;
+import java.io.IOException;
 import java.lang.reflect.Constructor;
 
 /**
@@ -28,10 +29,49 @@
     private static final String LIB_DIR = "/nowhere/nothing/";
 
     /**
+     * Prep the environment then run the test.
+     */
+    public static void main(String[] args) {
+        Process p;
+        try {
+            /*
+             * Create a sub-process to see if the ProcessManager wait
+             * interferes with the dexopt invocation wait.
+             *
+             * /dev/random never hits EOF, so we're sure that we'll still
+             * be waiting for the process to complete.  On the device it
+             * stops pretty quickly (which means the child won't be
+             * spinning).
+             */
+            ProcessBuilder pb = new ProcessBuilder("cat", "/dev/random");
+            p = pb.start();
+        } catch (IOException ioe) {
+            System.err.println("cmd failed: " + ioe.getMessage());
+            p = null;
+        }
+
+        try {
+            testDexClassLoader();
+        } finally {
+            // shouldn't be necessary, but it's good to be tidy
+            if (p != null)
+                p.destroy();
+
+            // let the ProcessManager's daemon thread finish before we shut down
+            // (avoids the occasional segmentation fault)
+            try {
+                Thread.sleep(500);
+            } catch (Exception ex) {}
+        }
+
+        System.out.println("done");
+    }
+
+    /**
      * Create a class loader, explicitly specifying the source DEX and
      * the location for the optimized DEX.
      */
-    public static void main(String[] args) {
+    private static void testDexClassLoader() {
         ClassLoader dexClassLoader = getDexClassLoader();
 
         Class anotherClass;
@@ -50,10 +90,8 @@
             throw new RuntimeException("new another", ie);
         }
 
-        /* not expected to work; just exercises the call */
+        // not expected to work; just exercises the call
         dexClassLoader.getResource("nonexistent");
-
-        System.out.println("done");
     }
 
     /*
@@ -94,6 +132,7 @@
             throw new RuntimeException("DCL ctor", nsme);
         }
 
+        // create an instance, using the path we found
         Object dclObj;
         try {
             dclObj = ctor.newInstance(CLASS_PATH, odexDir, LIB_DIR, myLoader);
diff --git a/tests/072-precise-gc/expected.txt b/tests/072-precise-gc/expected.txt
new file mode 100644
index 0000000..18ec087
--- /dev/null
+++ b/tests/072-precise-gc/expected.txt
@@ -0,0 +1,2 @@
+Valid refs: 0
+String0String1String2String3String4String5String6String7String8String9
diff --git a/tests/072-precise-gc/info.txt b/tests/072-precise-gc/info.txt
new file mode 100644
index 0000000..b0b2cea
--- /dev/null
+++ b/tests/072-precise-gc/info.txt
@@ -0,0 +1 @@
+Try to detect whether precise GC is working.
diff --git a/tests/072-precise-gc/src/Main.java b/tests/072-precise-gc/src/Main.java
new file mode 100644
index 0000000..9b2315d
--- /dev/null
+++ b/tests/072-precise-gc/src/Main.java
@@ -0,0 +1,114 @@
+/*
+ * 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.WeakReference;
+
+public class Main {
+    public static void main(String[] args) {
+        staleStackTest();
+    }
+
+    public static void staleStackTest() {
+        WeakReference wrefs[] = new WeakReference[10];
+
+        populate(wrefs);
+
+        check(wrefs);
+    }
+
+    static void populate(WeakReference[] wrefs) {
+        /*
+         * Get a bunch of non-constant String objects into registers.  These
+         * should be the first locals declared.
+         */
+        String str0 = generateString("String", 0);
+        String str1 = generateString("String", 1);
+        String str2 = generateString("String", 2);
+        String str3 = generateString("String", 3);
+        String str4 = generateString("String", 4);
+        String str5 = generateString("String", 5);
+        String str6 = generateString("String", 6);
+        String str7 = generateString("String", 7);
+        String str8 = generateString("String", 8);
+        String str9 = generateString("String", 9);
+
+        /* stuff them into the weak references array */
+        wrefs[0] = new WeakReference(str0);
+        wrefs[1] = new WeakReference(str1);
+        wrefs[2] = new WeakReference(str2);
+        wrefs[3] = new WeakReference(str3);
+        wrefs[4] = new WeakReference(str4);
+        wrefs[5] = new WeakReference(str5);
+        wrefs[6] = new WeakReference(str6);
+        wrefs[7] = new WeakReference(str7);
+        wrefs[8] = new WeakReference(str8);
+        wrefs[9] = new WeakReference(str9);
+    }
+
+    static String generateString(String base, int num) {
+        return base + num;
+    }
+
+    static void check(WeakReference[] wrefs) {
+        /*
+         * Declare locals so that our stack overlaps the same region
+         * that populate() did.
+         */
+        String str0;
+        String str1;
+        String str2;
+        String str3;
+        String str4;
+        String str5;
+        String str6;
+        String str7;
+        String str8;
+        String str9;
+        int numValid = 0;
+
+        /*
+         * This *should* blow out all the weakly-reference objects.  If
+         * we still have stale copies of references on the stack, a
+         * conservative GC will try to hold on to those objects and the
+         * count will be nonzero.
+         *
+         * Getting a zero result here isn't conclusive, but it's a strong
+         * indicator that precise GC is having an impact.
+         */
+        System.gc();
+
+        for (int i = 0; i < wrefs.length; i++) {
+            if (wrefs[i].get() != null)
+                numValid++;
+        }
+
+        System.out.println("Valid refs: " + numValid);
+
+        /* use the locals in case the compiler gets smart */
+        str0 = generateString("String", 0);
+        str1 = generateString("String", 1);
+        str2 = generateString("String", 2);
+        str3 = generateString("String", 3);
+        str4 = generateString("String", 4);
+        str5 = generateString("String", 5);
+        str6 = generateString("String", 6);
+        str7 = generateString("String", 7);
+        str8 = generateString("String", 8);
+        str9 = generateString("String", 9);
+        System.out.println(str0+str1+str2+str3+str4+str5+str6+str7+str8+str9);
+    }
+}
+
diff --git a/tests/073-mismatched-field/expected.txt b/tests/073-mismatched-field/expected.txt
new file mode 100644
index 0000000..90fbab8
--- /dev/null
+++ b/tests/073-mismatched-field/expected.txt
@@ -0,0 +1 @@
+Got expected failure
diff --git a/tests/073-mismatched-field/info.txt b/tests/073-mismatched-field/info.txt
new file mode 100644
index 0000000..4a15263
--- /dev/null
+++ b/tests/073-mismatched-field/info.txt
@@ -0,0 +1,3 @@
+Test behavior when an instance field is overlapped (through separate
+compilation) by a static field.  The VM is expected to detect the conflict
+and throw an IncompatibleClassChangeError when the field is accessed.
diff --git a/tests/073-mismatched-field/src/IMain.java b/tests/073-mismatched-field/src/IMain.java
new file mode 100644
index 0000000..301dd21
--- /dev/null
+++ b/tests/073-mismatched-field/src/IMain.java
@@ -0,0 +1,20 @@
+/*
+ * 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 interface IMain {
+    //static int f = 123;
+}
+
diff --git a/tests/073-mismatched-field/src/Main.java b/tests/073-mismatched-field/src/Main.java
new file mode 100644
index 0000000..fb9f32a
--- /dev/null
+++ b/tests/073-mismatched-field/src/Main.java
@@ -0,0 +1,32 @@
+/*
+ * 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 extends SuperMain implements IMain {
+    public static void main(String[] args) {
+        Main main = new Main();
+        main.doit();
+    }
+
+    void doit() {
+        try {
+            System.out.println("value=" + this.f);
+            System.err.println("Succeeded unexpectedly");
+        } catch (IncompatibleClassChangeError icce) {
+            System.out.println("Got expected failure");
+        }
+    }
+}
+
diff --git a/tests/073-mismatched-field/src/SuperMain.java b/tests/073-mismatched-field/src/SuperMain.java
new file mode 100644
index 0000000..7447739
--- /dev/null
+++ b/tests/073-mismatched-field/src/SuperMain.java
@@ -0,0 +1,20 @@
+/*
+ * 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 SuperMain {
+    public int f = 456;
+}
+
diff --git a/tests/073-mismatched-field/src2/IMain.java b/tests/073-mismatched-field/src2/IMain.java
new file mode 100644
index 0000000..585c738
--- /dev/null
+++ b/tests/073-mismatched-field/src2/IMain.java
@@ -0,0 +1,20 @@
+/*
+ * 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 interface IMain {
+    static int f = 123;
+}
+
diff --git a/tests/074-gc-thrash/expected.txt b/tests/074-gc-thrash/expected.txt
new file mode 100644
index 0000000..2669165
--- /dev/null
+++ b/tests/074-gc-thrash/expected.txt
@@ -0,0 +1,2 @@
+Running (10 seconds) ...
+Done.
diff --git a/tests/074-gc-thrash/info.txt b/tests/074-gc-thrash/info.txt
new file mode 100644
index 0000000..c195adb
--- /dev/null
+++ b/tests/074-gc-thrash/info.txt
@@ -0,0 +1,2 @@
+This thrashes the memory allocator and garbage collector for a brief period.
+
diff --git a/tests/074-gc-thrash/src/Main.java b/tests/074-gc-thrash/src/Main.java
new file mode 100644
index 0000000..f79e5ce
--- /dev/null
+++ b/tests/074-gc-thrash/src/Main.java
@@ -0,0 +1,338 @@
+/*
+ * 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.io.File;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
+
+public class Main {
+    public static volatile boolean quit = false;
+    public static final boolean DEBUG = false;
+
+    private static final boolean WRITE_HPROF_DATA = false;
+    private static final int TEST_TIME = 10;
+    private static final String OUTPUT_FILE = "gc-thrash.hprof";
+
+    public static void main(String[] args) {
+        // dump heap before
+
+        System.out.println("Running (" + TEST_TIME + " seconds) ...");
+        runTests();
+
+        Method dumpHprofDataMethod = null;
+        String dumpFile = null;
+
+        if (WRITE_HPROF_DATA) {
+            dumpHprofDataMethod = getDumpHprofDataMethod();
+            if (dumpHprofDataMethod != null) {
+                dumpFile = getDumpFileName();
+                System.out.println("Sending output to " + dumpFile);
+            }
+        }
+
+        System.gc();
+        System.runFinalization();
+        System.gc();
+
+        if (WRITE_HPROF_DATA && dumpHprofDataMethod != null) {
+            try {
+                dumpHprofDataMethod.invoke(null, dumpFile);
+            } catch (IllegalAccessException iae) {
+                System.err.println(iae);
+            } catch (InvocationTargetException ite) {
+                System.err.println(ite);
+            }
+        }
+
+        System.out.println("Done.");
+    }
+
+    /**
+     * Finds VMDebug.dumpHprofData() through reflection.  In the reference
+     * implementation this will not be available.
+     *
+     * @return the reflection object, or null if the method can't be found
+     */
+    private static Method getDumpHprofDataMethod() {
+        ClassLoader myLoader = Main.class.getClassLoader();
+        Class vmdClass;
+        try {
+            vmdClass = myLoader.loadClass("dalvik.system.VMDebug");
+        } catch (ClassNotFoundException cnfe) {
+            return null;
+        }
+
+        Method meth;
+        try {
+            meth = vmdClass.getMethod("dumpHprofData",
+                    new Class[] { String.class });
+        } catch (NoSuchMethodException nsme) {
+            System.err.println("Found VMDebug but not dumpHprofData method");
+            return null;
+        }
+
+        return meth;
+    }
+
+    private static String getDumpFileName() {
+        File tmpDir = new File("/tmp");
+        if (tmpDir.exists() && tmpDir.isDirectory()) {
+            return "/tmp/" + OUTPUT_FILE;
+        }
+
+        File sdcard = new File("/sdcard");
+        if (sdcard.exists() && sdcard.isDirectory()) {
+            return "/sdcard/" + OUTPUT_FILE;
+        }
+
+        return null;
+    }
+
+
+    /**
+     * Run the various tests for a set period.
+     */
+    public static void runTests() {
+        Robin robin = new Robin();
+        Deep deep = new Deep();
+        Large large = new Large();
+
+        /* start all threads */
+        robin.start();
+        deep.start();
+        large.start();
+
+        /* let everybody run for 10 seconds */
+        sleep(TEST_TIME * 1000);
+
+        quit = true;
+
+        try {
+            /* wait for all threads to stop */
+            robin.join();
+            deep.join();
+            large.join();
+        } catch (InterruptedException ie) {
+            System.err.println("join was interrupted");
+        }
+    }
+
+    /**
+     * Sleeps for the "ms" milliseconds.
+     */
+    public static void sleep(int ms) {
+        try {
+            Thread.sleep(ms);
+        } catch (InterruptedException ie) {
+            System.err.println("sleep was interrupted");
+        }
+    }
+
+    /**
+     * Sleeps briefly, allowing other threads some CPU time to get started.
+     */
+    public static void startupDelay() {
+        sleep(500);
+    }
+}
+
+
+/**
+ * Allocates useless objects and holds on to several of them.
+ *
+ * Uses a single large array of references, replaced repeatedly in round-robin
+ * order.
+ */
+class Robin extends Thread {
+    private static final int ARRAY_SIZE = 40960;
+    int sleepCount = 0;
+
+    public void run() {
+        Main.startupDelay();
+
+        String strings[] = new String[ARRAY_SIZE];
+        int idx = 0;
+
+        while (!Main.quit) {
+            strings[idx] = makeString(idx);
+
+            if (idx % (ARRAY_SIZE / 4) == 0) {
+                Main.sleep(400);
+                sleepCount++;
+            }
+
+            idx = (idx + 1) % ARRAY_SIZE;
+        }
+
+        if (Main.DEBUG)
+            System.out.println("Robin: sleepCount=" + sleepCount);
+    }
+
+    private String makeString(int val) {
+        return new String("Robin" + val);
+    }
+}
+
+
+/**
+ * Allocates useless objects in recursive calls.
+ */
+class Deep extends Thread {
+    private static final int MAX_DEPTH = 61;
+
+    private static String strong[] = new String[MAX_DEPTH];
+    private static WeakReference weak[] = new WeakReference[MAX_DEPTH];
+
+    public void run() {
+        int iter = 0;
+        boolean once = false;
+
+        Main.startupDelay();
+
+        while (!Main.quit) {
+            dive(0, iter);
+            once = true;
+            iter += MAX_DEPTH;
+        }
+
+        if (!once) {
+            System.err.println("not even once?");
+            return;
+        }
+
+        /*
+         * Check the results of the last trip through.  Everything in
+         * "weak" should be matched in "strong", and the two should be
+         * equivalent (object-wise, not just string-equality-wise).
+         */
+        for (int i = 0; i < MAX_DEPTH; i++) {
+            if (strong[i] != weak[i].get()) {
+                System.err.println("Deep: " + i + " strong=" + strong[i] +
+                    ", weak=" + weak[i].get());
+            }
+        }
+
+        /*
+         * Wipe "strong", do a GC, see if "weak" got collected.
+         */
+        for (int i = 0; i < MAX_DEPTH; i++)
+            strong[i] = null;
+
+        System.gc();
+
+        for (int i = 0; i < MAX_DEPTH; i++) {
+            if (weak[i].get() != null) {
+                System.err.println("Deep: weak still has " + i);
+            }
+        }
+
+        if (Main.DEBUG)
+            System.out.println("Deep: iters=" + iter / MAX_DEPTH);
+    }
+
+    /**
+     * Recursively dive down, setting one or more local variables.
+     *
+     * We pad the stack out with locals, attempting to create a mix of
+     * valid and invalid references on the stack.
+     */
+    private String dive(int depth, int iteration) {
+        String str0;
+        String str1;
+        String str2;
+        String str3;
+        String str4;
+        String str5;
+        String str6;
+        String str7;
+        String funStr;
+
+        funStr = "";
+
+        switch (iteration % 8) {
+            case 0:
+                funStr = str0 = makeString(iteration);
+                break;
+            case 1:
+                funStr = str1 = makeString(iteration);
+                break;
+            case 2:
+                funStr = str2 = makeString(iteration);
+                break;
+            case 3:
+                funStr = str3 = makeString(iteration);
+                break;
+            case 4:
+                funStr = str4 = makeString(iteration);
+                break;
+            case 5:
+                funStr = str5 = makeString(iteration);
+                break;
+            case 6:
+                funStr = str6 = makeString(iteration);
+                break;
+            case 7:
+                funStr = str7 = makeString(iteration);
+                break;
+        }
+
+        strong[depth] = funStr;
+        weak[depth] = new WeakReference(funStr);
+
+        if (depth+1 < MAX_DEPTH)
+            dive(depth+1, iteration+1);
+        else
+            Main.sleep(100);
+
+        return funStr;
+    }
+
+    private String makeString(int val) {
+        return new String("Deep" + val);
+    }
+}
+
+
+/**
+ * Allocates large useless objects.
+ */
+class Large extends Thread {
+    public void run() {
+        byte[] chunk;
+        int count = 0;
+        int sleepCount = 0;
+
+        Main.startupDelay();
+
+        while (!Main.quit) {
+            chunk = new byte[100000];
+            pretendToUse(chunk);
+
+            count++;
+            if ((count % 500) == 0) {
+                Main.sleep(400);
+                sleepCount++;
+            }
+        }
+
+        if (Main.DEBUG)
+            System.out.println("Large: sleepCount=" + sleepCount);
+    }
+
+    public void pretendToUse(byte[] chunk) {}
+}
+
diff --git a/tests/075-verification-error/expected.txt b/tests/075-verification-error/expected.txt
new file mode 100644
index 0000000..6e4f584
--- /dev/null
+++ b/tests/075-verification-error/expected.txt
@@ -0,0 +1,12 @@
+Got expected InstantationError
+Got expected NoSuchFieldError
+Got expected NoSuchFieldError
+Got expected NoSuchMethodError
+Got expected NoSuchMethodError
+Got expected IllegalAccessError (ifield)
+Got expected IllegalAccessError (sfield)
+Got expected IllegalAccessError (method)
+Got expected IllegalAccessError (smethod)
+Got expected IllegalAccessError (meth-class)
+Got expected IllegalAccessError (field-class)
+Got expected IllegalAccessError (meth-meth)
diff --git a/tests/075-verification-error/info.txt b/tests/075-verification-error/info.txt
new file mode 100644
index 0000000..be688ff
--- /dev/null
+++ b/tests/075-verification-error/info.txt
@@ -0,0 +1 @@
+Exercise deferred verification error reporting.
diff --git a/tests/075-verification-error/src/Main.java b/tests/075-verification-error/src/Main.java
new file mode 100644
index 0000000..f357242
--- /dev/null
+++ b/tests/075-verification-error/src/Main.java
@@ -0,0 +1,149 @@
+/*
+ * 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 other.Mutant;
+import other.InaccessibleClass;
+import other.InaccessibleMethod;
+
+/**
+ * Test some problematic situations that the verifier detects.
+ */
+public class Main {
+    public static final boolean VERBOSE = false;
+
+    public static void main(String[] args) {
+        testClassNewInstance();
+        testMissingStuff();
+        testBadAccess();
+    }
+
+    /**
+     * Try to create a new instance of an abstract class.
+     */
+    static void testClassNewInstance() {
+        try {
+            MaybeAbstract ma = new MaybeAbstract();
+            System.err.println("ERROR: MaybeAbstract succeeded unexpectedly");
+        } catch (InstantiationError ie) {
+            System.out.println("Got expected InstantationError");
+            if (VERBOSE) System.out.println("--- " + ie);
+        } catch (Exception ex) {
+            System.err.println("Got unexpected MaybeAbstract failure");
+        }
+    }
+
+    /**
+     * Test stuff that disappears.
+     */
+    static void testMissingStuff() {
+        Mutant mutant = new Mutant();
+
+        try {
+            int x = mutant.disappearingField;
+        } catch (NoSuchFieldError nsfe) {
+            System.out.println("Got expected NoSuchFieldError");
+            if (VERBOSE) System.out.println("--- " + nsfe);
+        }
+
+        try {
+            int y = Mutant.disappearingStaticField;
+        } catch (NoSuchFieldError nsfe) {
+            System.out.println("Got expected NoSuchFieldError");
+            if (VERBOSE) System.out.println("--- " + nsfe);
+        }
+
+        try {
+            mutant.disappearingMethod();
+        } catch (NoSuchMethodError nsme) {
+            System.out.println("Got expected NoSuchMethodError");
+            if (VERBOSE) System.out.println("--- " + nsme);
+        }
+
+        try {
+            Mutant.disappearingStaticMethod();
+        } catch (NoSuchMethodError nsme) {
+            System.out.println("Got expected NoSuchMethodError");
+            if (VERBOSE) System.out.println("--- " + nsme);
+        }
+    }
+
+    /**
+     * Test stuff that becomes inaccessible.
+     */
+    static void testBadAccess() {
+        Mutant mutant = new Mutant();
+
+        try {
+            int x = mutant.inaccessibleField;
+            System.err.println("ERROR: bad access succeeded\n");
+        } catch (IllegalAccessError iae) {
+            System.out.println("Got expected IllegalAccessError (ifield)");
+            if (VERBOSE) System.out.println("--- " + iae);
+        }
+
+        try {
+            int y = Mutant.inaccessibleStaticField;
+            System.err.println("ERROR: bad access succeeded\n");
+        } catch (IllegalAccessError iae) {
+            System.out.println("Got expected IllegalAccessError (sfield)");
+            if (VERBOSE) System.out.println("--- " + iae);
+        }
+
+        try {
+            mutant.inaccessibleMethod();
+            System.err.println("ERROR: bad access succeeded\n");
+        } catch (IllegalAccessError iae) {
+            System.out.println("Got expected IllegalAccessError (method)");
+            if (VERBOSE) System.out.println("--- " + iae);
+        }
+
+        try {
+            Mutant.inaccessibleStaticMethod();
+            System.err.println("ERROR: bad access succeeded\n");
+        } catch (IllegalAccessError iae) {
+            System.out.println("Got expected IllegalAccessError (smethod)");
+            if (VERBOSE) System.out.println("--- " + iae);
+        }
+
+        try {
+            /* accessible static method in an inaccessible class */
+            InaccessibleClass.test();
+            System.err.println("ERROR: bad meth-class access succeeded\n");
+        } catch (IllegalAccessError iae) {
+            System.out.println("Got expected IllegalAccessError (meth-class)");
+            if (VERBOSE) System.out.println("--- " + iae);
+        }
+
+        try {
+            /* accessible static field in an inaccessible class */
+            int blah = InaccessibleClass.blah;
+            System.err.println("ERROR: bad field-class access succeeded\n");
+        } catch (IllegalAccessError iae) {
+            System.out.println("Got expected IllegalAccessError (field-class)");
+            if (VERBOSE) System.out.println("--- " + iae);
+        }
+
+        try {
+            /* inaccessible static method in an accessible class */
+            InaccessibleMethod.test();
+            System.err.println("ERROR: bad access succeeded\n");
+        } catch (IllegalAccessError iae) {
+            System.out.println("Got expected IllegalAccessError (meth-meth)");
+            if (VERBOSE) System.out.println("--- " + iae);
+        }
+    }
+}
+
diff --git a/tests/075-verification-error/src/MaybeAbstract.java b/tests/075-verification-error/src/MaybeAbstract.java
new file mode 100644
index 0000000..43c002b
--- /dev/null
+++ b/tests/075-verification-error/src/MaybeAbstract.java
@@ -0,0 +1,21 @@
+/*
+ * 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 /*abstract*/ class MaybeAbstract {
+    public MaybeAbstract() {}
+    int foo() { return 0; }
+}
+
diff --git a/tests/075-verification-error/src/other/InaccessibleClass.java b/tests/075-verification-error/src/other/InaccessibleClass.java
new file mode 100644
index 0000000..254eaa3
--- /dev/null
+++ b/tests/075-verification-error/src/other/InaccessibleClass.java
@@ -0,0 +1,24 @@
+/*
+ * 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 other;
+
+public class InaccessibleClass {
+    public static void test() {}
+
+    public static int blah = 5;
+}
+
diff --git a/tests/075-verification-error/src/other/InaccessibleMethod.java b/tests/075-verification-error/src/other/InaccessibleMethod.java
new file mode 100644
index 0000000..49a0b29
--- /dev/null
+++ b/tests/075-verification-error/src/other/InaccessibleMethod.java
@@ -0,0 +1,22 @@
+/*
+ * 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 other;
+
+public class InaccessibleMethod {
+    public static void test() {}
+}
+
diff --git a/tests/075-verification-error/src/other/Mutant.java b/tests/075-verification-error/src/other/Mutant.java
new file mode 100644
index 0000000..6c869c0
--- /dev/null
+++ b/tests/075-verification-error/src/other/Mutant.java
@@ -0,0 +1,44 @@
+/*
+ * 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 other;
+
+/**
+ * Parts of this class will disappear or change form.
+ */
+public class Mutant {
+    public int disappearingField = 3;
+    public static int disappearingStaticField = 4;
+
+    public void disappearingMethod() {
+        System.out.println("bye");
+    }
+    public static void disappearingStaticMethod() {
+        System.out.println("kthxbai");
+    }
+
+    public int inaccessibleField = 5;
+    public static int inaccessibleStaticField = 6;
+
+    public void inaccessibleMethod() {
+        System.out.println("no");
+    }
+
+    public static void inaccessibleStaticMethod() {
+        System.out.println("nay");
+    }
+}
+
diff --git a/tests/075-verification-error/src2/MaybeAbstract.java b/tests/075-verification-error/src2/MaybeAbstract.java
new file mode 100644
index 0000000..bfbfd45
--- /dev/null
+++ b/tests/075-verification-error/src2/MaybeAbstract.java
@@ -0,0 +1,21 @@
+/*
+ * 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 abstract class MaybeAbstract {
+    public MaybeAbstract() {}
+    int foo() { return 0; }
+}
+
diff --git a/tests/075-verification-error/src2/other/InaccessibleClass.java b/tests/075-verification-error/src2/other/InaccessibleClass.java
new file mode 100644
index 0000000..a3cfbff
--- /dev/null
+++ b/tests/075-verification-error/src2/other/InaccessibleClass.java
@@ -0,0 +1,24 @@
+/*
+ * 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 other;
+
+/*package*/ class InaccessibleClass {
+    public static void test() {}
+
+    public static int blah = 5;
+}
+
diff --git a/tests/075-verification-error/src2/other/InaccessibleMethod.java b/tests/075-verification-error/src2/other/InaccessibleMethod.java
new file mode 100644
index 0000000..6e2738e
--- /dev/null
+++ b/tests/075-verification-error/src2/other/InaccessibleMethod.java
@@ -0,0 +1,22 @@
+/*
+ * 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 other;
+
+public class InaccessibleMethod {
+    /*package*/ static void test() {}
+}
+
diff --git a/tests/075-verification-error/src2/other/Mutant.java b/tests/075-verification-error/src2/other/Mutant.java
new file mode 100644
index 0000000..220fda0
--- /dev/null
+++ b/tests/075-verification-error/src2/other/Mutant.java
@@ -0,0 +1,45 @@
+/*
+ * 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 other;
+
+/**
+ * Parts of this class will disappear or change form.
+ */
+public class Mutant {
+    //public int disappearingField = 3;
+    //public static int disappearingStaticField = 4;
+
+    //public static void disappearingMethod() {
+    //    System.out.println("bye");
+    //}
+    //public static void disappearingStaticMethod() {
+    //    System.out.println("kthxbai");
+    //}
+
+    protected int inaccessibleField = 5;
+    protected static int inaccessibleStaticField = 6;
+
+    protected void inaccessibleMethod() {
+        System.out.println("no");
+    }
+
+    protected static void inaccessibleStaticMethod() {
+        System.out.println("nay");
+    }
+}
+
+
diff --git a/tests/076-boolean-put/expected.txt b/tests/076-boolean-put/expected.txt
new file mode 100644
index 0000000..a965a70
--- /dev/null
+++ b/tests/076-boolean-put/expected.txt
@@ -0,0 +1 @@
+Done
diff --git a/tests/076-boolean-put/info.txt b/tests/076-boolean-put/info.txt
new file mode 100644
index 0000000..5b3ef4d
--- /dev/null
+++ b/tests/076-boolean-put/info.txt
@@ -0,0 +1,3 @@
+This checks a case where javac generates code that stores a byte into a
+boolean field.  The code as generated should not pass the verifier, so the
+verifier had to be "loosened" to allow this case.
diff --git a/tests/076-boolean-put/src/Main.java b/tests/076-boolean-put/src/Main.java
new file mode 100644
index 0000000..b325422
--- /dev/null
+++ b/tests/076-boolean-put/src/Main.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+/**
+ * Test access to private boolean fields.
+ *
+ * Accessing private boolean fields from an inner class causes the compiler
+ * to generate an accessor method that performs the boolean operation.
+ * Unfortunately the generated method takes an integer as an argument,
+ * not a boolean, which makes the verifier upset when the result of the
+ * operation is written back to a boolean field.
+ */
+public class Main {
+    private boolean mInstance;
+    private static boolean mStatic;
+
+    public static void main(String[] args) {
+        Main foo = new Main();
+        foo.test();
+
+        System.out.println("Done");
+    }
+
+    void test() {
+        Innard innard = new Innard();
+        innard.doStuff();
+    }
+
+    class Innard {
+        void doStuff() {
+            mInstance |= true;
+            mStatic |= true;
+        }
+    }
+}
diff --git a/tests/077-method-override/expected.txt b/tests/077-method-override/expected.txt
new file mode 100644
index 0000000..2e9bda3
--- /dev/null
+++ b/tests/077-method-override/expected.txt
@@ -0,0 +1,15 @@
+declaredInBase: Base
+notDeclaredInBase: Derived
+wasOverridden: Derived
+overrideWithPublic: Derived
+overrideProtectedWithPublic: Derived
+overridePublicWithProtected: Derived
+overridePublicWithPrivate: Base
+overridePrivateWithPublic: Base
+overridePrivateWithPublic: Derived
+overrideVirtualWithStatic: Base
+overrideVirtualWithStatic: Derived
+overrideStaticWithVirtual: Base
+overrideStaticWithVirtual: Derived
+Got expected exception - ovws
+Got expected exception - oswv
diff --git a/tests/077-method-override/info.txt b/tests/077-method-override/info.txt
new file mode 100644
index 0000000..914b4f2
--- /dev/null
+++ b/tests/077-method-override/info.txt
@@ -0,0 +1,2 @@
+Test various forms of method overrides, including some not allowed by the
+compiler but possible with separate compilation.
diff --git a/tests/077-method-override/src/Base.java b/tests/077-method-override/src/Base.java
new file mode 100644
index 0000000..eed6f22
--- /dev/null
+++ b/tests/077-method-override/src/Base.java
@@ -0,0 +1,84 @@
+/*
+ * 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 Base {
+    public void declaredInBase() {
+        System.out.println("declaredInBase: Base");
+    }
+
+    public void overridden() {
+        System.out.println("overridden: Base");
+    }
+
+    /* src2: removed */
+    public void wasOverridden() {
+        System.out.println("wasOverridden: Base");
+    }
+
+    public void callOverrideWithPublic() {
+        overrideWithPublic();
+    }
+    public void overrideWithPublic() {
+        System.out.println("overrideWithPublic: Base");
+    }
+
+    public void callOverridePublicWithProtected() {
+        overridePublicWithProtected();
+    }
+    /* src2: public */
+    protected void overridePublicWithProtected() {
+        System.out.println("overridePublicWithProtected: Base");
+    }
+
+    public void callOverrideProtectedWithPublic() {
+        overrideProtectedWithPublic();
+    }
+    protected void overrideProtectedWithPublic() {
+        System.out.println("overrideProtectedWithPublic: Base");
+    }
+
+    public void callOverridePublicWithPrivate() {
+        overridePublicWithPrivate();
+    }
+    /* src2: public */
+    private void overridePublicWithPrivate() {
+        System.out.println("overridePublicWithPrivate: Base");
+    }
+
+    public void callOverridePrivateWithPublic() {
+        overridePrivateWithPublic();
+    }
+    private void overridePrivateWithPublic() {
+        System.out.println("overridePrivateWithPublic: Base");
+    }
+
+    public void callOverrideVirtualWithStatic() {
+        overrideVirtualWithStatic();
+    }
+    /* src2: non-static */
+    public static void overrideVirtualWithStatic() {
+        System.out.println("overrideVirtualWithStatic: Base");
+    }
+
+    public void callOverrideStaticWithVirtual() {
+        overrideStaticWithVirtual();
+    }
+    /* src2: static */
+    public void overrideStaticWithVirtual() {
+        System.out.println("overrideStaticWithVirtual: Base");
+    }
+}
+
diff --git a/tests/077-method-override/src/Derived.java b/tests/077-method-override/src/Derived.java
new file mode 100644
index 0000000..09ffdf6
--- /dev/null
+++ b/tests/077-method-override/src/Derived.java
@@ -0,0 +1,60 @@
+/*
+ * 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 Derived extends Base {
+    public static void notDeclaredInBase() {
+        System.out.println("notDeclaredInBase: Derived");
+    }
+
+    public void overridden() {
+        System.out.println("overridden: Derived");
+    }
+
+    public void wasOverridden() {
+        System.out.println("wasOverridden: Derived");
+    }
+
+    public void overrideWithPublic() {
+        System.out.println("overrideWithPublic: Derived");
+    }
+
+    protected void overridePublicWithProtected() {
+        System.out.println("overridePublicWithProtected: Derived");
+    }
+
+    public void overrideProtectedWithPublic() {
+        System.out.println("overrideProtectedWithPublic: Derived");
+    }
+
+    private void overridePublicWithPrivate() {
+        System.out.println("overridePublicWithPrivate: Derived");
+    }
+
+    public void overridePrivateWithPublic() {
+        System.out.println("overridePrivateWithPublic: Derived");
+    }
+
+    /* not really an "override"; just has same method signature */
+    public static void overrideVirtualWithStatic() {
+        System.out.println("overrideVirtualWithStatic: Derived");
+    }
+
+    /* not really an "override"; just has same method signature */
+    public void overrideStaticWithVirtual() {
+        System.out.println("overrideStaticWithVirtual: Derived");
+    }
+}
+
diff --git a/tests/077-method-override/src/Main.java b/tests/077-method-override/src/Main.java
new file mode 100644
index 0000000..fa401cd
--- /dev/null
+++ b/tests/077-method-override/src/Main.java
@@ -0,0 +1,54 @@
+/*
+ * 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 {
+    public static void main(String args[]) {
+        Derived derived = new Derived();
+
+        derived.declaredInBase();
+        derived.notDeclaredInBase();
+        derived.wasOverridden();
+
+        derived.callOverrideWithPublic();
+        derived.callOverrideProtectedWithPublic();
+        derived.callOverridePublicWithProtected();
+        derived.callOverridePublicWithPrivate();
+        derived.callOverridePrivateWithPublic();
+        derived.overridePrivateWithPublic();
+        derived.callOverrideVirtualWithStatic();
+        derived.overrideVirtualWithStatic();
+        derived.callOverrideStaticWithVirtual();
+        derived.overrideStaticWithVirtual();
+
+        try {
+            ((Base)derived).overrideVirtualWithStatic();
+        } catch (NoSuchMethodError nsme) {
+            /* NSME is subclass of ICCE, so check it explicitly */
+            System.err.println("Got NSME - ovws");
+        } catch (IncompatibleClassChangeError icce) {
+            System.out.println("Got expected exception - ovws");
+        }
+
+        try {
+            ((Base)derived).overrideStaticWithVirtual();
+        } catch (NoSuchMethodError nsme) {
+            System.err.println("Got NSME - ovws");
+        } catch (IncompatibleClassChangeError icce) {
+            System.out.println("Got expected exception - oswv");
+        }
+    }
+}
+
diff --git a/tests/077-method-override/src2/Base.java b/tests/077-method-override/src2/Base.java
new file mode 100644
index 0000000..8be42bc
--- /dev/null
+++ b/tests/077-method-override/src2/Base.java
@@ -0,0 +1,83 @@
+/*
+ * 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 Base {
+    public void declaredInBase() {
+        System.out.println("declaredInBase: Base");
+    }
+
+    public void overridden() {
+        System.out.println("overridden: Base");
+    }
+
+    /* src2: removed */
+    //public void wasOverridden() {
+    //    System.out.println("wasOverridden: Base");
+    //}
+
+    public void callOverrideWithPublic() {
+        overrideWithPublic();
+    }
+    public void overrideWithPublic() {
+        System.out.println("overrideWithPublic: Base");
+    }
+
+    public void callOverridePublicWithProtected() {
+        overridePublicWithProtected();
+    }
+    /* src2: public */
+    public void overridePublicWithProtected() {
+        System.out.println("overridePublicWithProtected: Base");
+    }
+
+    public void callOverrideProtectedWithPublic() {
+        overrideProtectedWithPublic();
+    }
+    protected void overrideProtectedWithPublic() {
+        System.out.println("overrideProtectedWithPublic: Base");
+    }
+
+    public void callOverridePublicWithPrivate() {
+        overridePublicWithPrivate();
+    }
+    /* src2: public */
+    public void overridePublicWithPrivate() {
+        System.out.println("overridePublicWithPrivate: Base");
+    }
+
+    public void callOverridePrivateWithPublic() {
+        overridePrivateWithPublic();
+    }
+    private void overridePrivateWithPublic() {
+        System.out.println("overridePrivateWithPublic: Base");
+    }
+
+    public void callOverrideVirtualWithStatic() {
+        overrideVirtualWithStatic();
+    }
+    /* src2: non-static */
+    public void overrideVirtualWithStatic() {
+        System.out.println("overrideVirtualWithStatic: Base");
+    }
+
+    public void callOverrideStaticWithVirtual() {
+        overrideStaticWithVirtual();
+    }
+    public static void overrideStaticWithVirtual() {
+        System.out.println("overrideStaticWithVirtual: Base");
+    }
+}
+
diff --git a/tests/078-polymorphic-virtual/expected.txt b/tests/078-polymorphic-virtual/expected.txt
new file mode 100644
index 0000000..0d29728
--- /dev/null
+++ b/tests/078-polymorphic-virtual/expected.txt
@@ -0,0 +1,3 @@
+10000000
+20000000
+30000000
diff --git a/tests/078-polymorphic-virtual/info.txt b/tests/078-polymorphic-virtual/info.txt
new file mode 100644
index 0000000..7c8a561
--- /dev/null
+++ b/tests/078-polymorphic-virtual/info.txt
@@ -0,0 +1,2 @@
+Stress test predicted chaining for overloaded virtual callsite with 3 resolved
+calless invoked 10,000,000 times each in three threads.
diff --git a/tests/078-polymorphic-virtual/src/Base.java b/tests/078-polymorphic-virtual/src/Base.java
new file mode 100644
index 0000000..ec3aadd
--- /dev/null
+++ b/tests/078-polymorphic-virtual/src/Base.java
@@ -0,0 +1,32 @@
+/*
+ * 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 Base extends Thread {
+    int value;
+
+    public void run() {
+        for (int i = 0; i < 10000000; i++) {
+            incrimentValue();
+        }
+    }
+
+    public void incrimentValue() {
+    }
+
+    public int getValue() {
+        return value;
+    }
+}
diff --git a/tests/078-polymorphic-virtual/src/Derived1.java b/tests/078-polymorphic-virtual/src/Derived1.java
new file mode 100644
index 0000000..57bd3b0
--- /dev/null
+++ b/tests/078-polymorphic-virtual/src/Derived1.java
@@ -0,0 +1,21 @@
+/*
+ * 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 Derived1 extends Base {
+    public void incrimentValue() {
+        value += 1;
+    }
+}
diff --git a/tests/078-polymorphic-virtual/src/Derived2.java b/tests/078-polymorphic-virtual/src/Derived2.java
new file mode 100644
index 0000000..1d7de57
--- /dev/null
+++ b/tests/078-polymorphic-virtual/src/Derived2.java
@@ -0,0 +1,21 @@
+/*
+ * 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 Derived2 extends Base {
+    public void incrimentValue() {
+        value += 2;
+    }
+}
diff --git a/tests/078-polymorphic-virtual/src/Derived3.java b/tests/078-polymorphic-virtual/src/Derived3.java
new file mode 100644
index 0000000..c2594d2
--- /dev/null
+++ b/tests/078-polymorphic-virtual/src/Derived3.java
@@ -0,0 +1,21 @@
+/*
+ * 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 Derived3 extends Base {
+    public void incrimentValue() {
+        value += 3;
+    }
+}
diff --git a/tests/078-polymorphic-virtual/src/Main.java b/tests/078-polymorphic-virtual/src/Main.java
new file mode 100644
index 0000000..0514e53
--- /dev/null
+++ b/tests/078-polymorphic-virtual/src/Main.java
@@ -0,0 +1,40 @@
+/*
+ * 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 {
+    public static void main(String args[]) {
+        Derived1 derived1 = new Derived1();
+        Derived2 derived2 = new Derived2();
+        Derived3 derived3 = new Derived3();
+
+        derived1.start();
+        derived2.start();
+        derived3.start();
+
+        try {
+            derived1.join();
+            derived2.join();
+            derived3.join();
+        } catch (Exception e) {
+            System.out.println(e);
+            return;
+        }
+
+        System.out.println(derived1.getValue());
+        System.out.println(derived2.getValue());
+        System.out.println(derived3.getValue());
+    }
+}
diff --git a/tests/etc/local-run-test-jar b/tests/etc/local-run-test-jar
index 0c802ba..6155e3f 100755
--- a/tests/etc/local-run-test-jar
+++ b/tests/etc/local-run-test-jar
@@ -6,6 +6,7 @@
 # Options:
 #   --quiet       -- don't chatter
 #   --fast        -- use the fast interpreter (the default)
+#   --jit         -- use the jit
 #   --portable    -- use the portable interpreter
 #   --debug       -- wait for debugger to attach
 #   --valgrind    -- use valgrind
@@ -26,11 +27,16 @@
 VALGRIND="n"
 DEV_MODE="n"
 QUIET="n"
+PRECISE="y"
 
 while true; do
     if [ "x$1" = "x--quiet" ]; then
         QUIET="y"
         shift
+    elif [ "x$1" = "x--jit" ]; then
+        INTERP="jit"
+        msg "Using jit"
+        shift
     elif [ "x$1" = "x--fast" ]; then
         INTERP="fast"
         msg "Using fast interpreter"
@@ -57,6 +63,9 @@
     elif [ "x$1" = "x--no-optimize" ]; then
         OPTIMIZE="n"
         shift
+    elif [ "x$1" = "x--no-precise" ]; then
+        PRECISE="n"
+        shift
     elif [ "x$1" = "x--" ]; then
         shift
         break
@@ -96,11 +105,17 @@
 if [ "$VALGRIND" = "y" ]; then
     msg "Running with valgrind"
     valgrind_cmd="valgrind"
-    #valgrind_cmd="$valgrind_cmd --leak-check=full"
+    #valgrind_cmd="valgrind --leak-check=full"
 else
     valgrind_cmd=""
 fi
 
+if [ "$PRECISE" = "y" ]; then
+    GC_OPTS="-Xgc:precise -Xgenregmap"
+else
+    GC_OPTS="-Xgc:noprecise"
+fi
+
 msg "------------------------------"
 
 BASE="$OUT" # from build environment
@@ -109,9 +124,9 @@
 
 export ANDROID_PRINTF_LOG=brief
 if [ "$DEV_MODE" = "y" ]; then
-	export ANDROID_LOG_TAGS='*:d'
+    export ANDROID_LOG_TAGS='*:d'
 else
-	export ANDROID_LOG_TAGS='*:s'
+    export ANDROID_LOG_TAGS='*:s'
 fi
 export ANDROID_DATA="$DATA_DIR"
 export ANDROID_ROOT="${BASE}/system"
@@ -134,5 +149,5 @@
 fi
 
 $valgrind_cmd $gdb $exe $gdbargs "-Xbootclasspath:${bpath}" \
-    $DEX_VERIFY $DEX_OPTIMIZE $DEX_DEBUG "-Xint:${INTERP}" -ea \
+    $DEX_VERIFY $DEX_OPTIMIZE $DEX_DEBUG $GC_OPTS "-Xint:${INTERP}" -ea \
     -cp test.jar Main "$@"
diff --git a/tests/etc/push-and-run-test-jar b/tests/etc/push-and-run-test-jar
index c9bcfb2..df66a8e 100755
--- a/tests/etc/push-and-run-test-jar
+++ b/tests/etc/push-and-run-test-jar
@@ -6,12 +6,14 @@
 # Options:
 #   --quiet       -- don't chatter
 #   --fast        -- use the fast interpreter (the default)
+#   --jit         -- use the jit
 #   --portable    -- use the portable interpreter
 #   --debug       -- wait for debugger to attach
 #   --zygote      -- use the zygote (if so, all other options are ignored)
 #   --dev         -- development mode
 #   --no-verify   -- turn off verification (on by default)
 #   --no-optimize -- turn off optimization (on by default)
+#   --no-precise  -- turn off precise GC (on by default)
 
 msg() {
     if [ "$QUIET" = "n" ]; then
@@ -25,6 +27,7 @@
 OPTIMIZE="y"
 ZYGOTE="n"
 QUIET="n"
+PRECISE="y"
 
 while true; do
     if [ "x$1" = "x--quiet" ]; then
@@ -34,6 +37,10 @@
         INTERP="fast"
         msg "Using fast interpreter"
         shift
+    elif [ "x$1" = "x--jit" ]; then
+        INTERP="jit"
+        msg "Using jit"
+        shift
     elif [ "x$1" = "x--portable" ]; then
         INTERP="portable"
         msg "Using portable interpreter"
@@ -54,6 +61,9 @@
     elif [ "x$1" = "x--no-optimize" ]; then
         OPTIMIZE="n"
         shift
+    elif [ "x$1" = "x--no-precise" ]; then
+        PRECISE="n"
+        shift
     elif [ "x$1" = "x--" ]; then
         shift
         break
@@ -106,9 +116,15 @@
     DEX_DEBUG="-agentlib:jdwp=transport=dt_android_adb,server=y,suspend=y"
 fi
 
+if [ "$PRECISE" = "y" ]; then
+    GC_OPTS="-Xgc:precise -Xgenregmap"
+else
+    GC_OPTS="-Xgc:noprecise"
+fi
+
 if [ "$ZYGOTE" = "y" ]; then
     adb shell cd /data \; dvz -classpath test.jar Main "$@"
 else
     adb shell cd /data \; dalvikvm $DEX_VERIFY $DEX_OPTIMIZE $DEX_DEBUG \
-        -cp test.jar "-Xint:${INTERP}" -ea Main "$@"
+        $GC_OPTS -cp test.jar "-Xint:${INTERP}" -ea Main "$@"
 fi
diff --git a/tests/run-test b/tests/run-test
index b503905..c5e2090 100755
--- a/tests/run-test
+++ b/tests/run-test
@@ -57,6 +57,9 @@
     elif [ "x$1" = "x--reference" ]; then
         RUN="${progdir}/etc/reference-run-test-classes"
         shift
+    elif [ "x$1" = "x--jit" ]; then
+        run_args="${run_args} --jit"
+        shift
     elif [ "x$1" = "x--fast" ]; then
         run_args="${run_args} --fast"
         shift
@@ -79,6 +82,9 @@
     elif [ "x$1" = "x--no-optimize" ]; then
         run_args="${run_args} --no-optimize"
         shift
+    elif [ "x$1" = "x--no-precise" ]; then
+        run_args="${run_args} --no-precise"
+        shift
     elif [ "x$1" = "x--valgrind" ]; then
         run_args="${run_args} --valgrind"
         shift
@@ -141,11 +147,13 @@
 	    "current directory."
         echo "  Runtime Options:"
         echo "    --fast         Use the fast interpreter (the default)."
+        echo "    --jit          Use the jit."
         echo "    --portable     Use the portable interpreter."
         echo "    --debug        Wait for a debugger to attach."
         #echo "    --gdb          Run under gdb; incompatible with some tests."
         echo "    --no-verify    Turn off verification (on by default)."
         echo "    --no-optimize  Turn off optimization (on by default)."
+        echo "    --no-precise   Turn off precise GC (on by default)."
         echo "    --zygote       Spawn the process from the Zygote." \
 	    "If used, then the"
 	echo "                   other runtime options are ignored."
diff --git a/tools/dexcheck b/tools/dexcheck
new file mode 100755
index 0000000..76662e8
--- /dev/null
+++ b/tools/dexcheck
@@ -0,0 +1,32 @@
+#!/bin/bash
+#
+# 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".
+
+# Get the list of files.  Use "sed" to drop the trailing carriage return.
+files=`adb shell "cd /data/dalvik-cache; echo *" | sed -e s/.$//`
+if [ "$files" = "*" ]; then
+    echo 'ERROR: commands must run as root on device (try "adb root" first?)'
+    exit 1
+fi
+
+failure=0
+
+# Check each file in turn.  This is much faster with "dexdump -c", but that
+# was added post-cupcake.
+#
+# The dexdump found in older builds does not stop on checksum failures and
+# will likely crash.
+for file in $files; do
+    echo $file
+    errout=`adb shell "dexdump /data/dalvik-cache/$file > dev/null"`
+    errcount=`echo $errout | wc -w` > /dev/null
+    if [ $errcount != "0" ]; then
+        echo "  Failure in $file: $errout"
+        failure=1
+    fi
+done
+
+exit $failure
+
diff --git a/tools/dexdeps/Android.mk b/tools/dexdeps/Android.mk
new file mode 100644
index 0000000..9c2cec7
--- /dev/null
+++ b/tools/dexdeps/Android.mk
@@ -0,0 +1,44 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+# We use copy-file-to-new-target so that the installed
+# script files' timestamps are at least as new as the
+# .jar files they wrap.
+
+# the dexdeps script
+# ============================================================
+include $(CLEAR_VARS)
+LOCAL_IS_HOST_MODULE := true
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE := dexdeps
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(HOST_OUT_JAVA_LIBRARIES)/dexdeps$(COMMON_JAVA_PACKAGE_SUFFIX)
+$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/etc/dexdeps | $(ACP)
+	@echo "Copy: $(PRIVATE_MODULE) ($@)"
+	$(copy-file-to-new-target)
+	$(hide) chmod 755 $@
+
+INTERNAL_DALVIK_MODULES += $(LOCAL_INSTALLED_MODULE)
+
+# the other stuff
+# ============================================================
+subdirs := $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \
+		src \
+	))
+
+include $(subdirs)
diff --git a/tools/dexdeps/README.txt b/tools/dexdeps/README.txt
new file mode 100644
index 0000000..14d65b0
--- /dev/null
+++ b/tools/dexdeps/README.txt
@@ -0,0 +1,28 @@
+dexdeps -- DEX external dependency dump
+
+
+This tool dumps a list of fields and methods that a DEX file uses but does
+not define.  When combined with a list of public APIs, it can be used to
+determine whether an APK is accessing fields and calling methods that it
+shouldn't be.  It may also be useful in determining whether an application
+requires a certain minimum API level to execute.
+
+Basic usage:
+
+  dexdeps [options] <file.{dex,apk,jar}>
+
+For zip archives (including .jar and .apk), dexdeps will look for a
+"classes.dex" entry.
+
+Supported options are:
+
+  --format={brief,xml}
+
+    Specifies the output format.
+
+    "brief" produces one line of output for each field and method.  Field
+    and argument types are shown as descriptor strings.
+
+    "xml" produces a larger output file, readable with an XML browser.  Types
+    are shown in a more human-readable form (e.g. "[I" becomes "int[]").
+
diff --git a/tools/dexdeps/etc/dexdeps b/tools/dexdeps/etc/dexdeps
new file mode 100644
index 0000000..dc628bd
--- /dev/null
+++ b/tools/dexdeps/etc/dexdeps
@@ -0,0 +1,69 @@
+#!/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.
+
+# Set up prog to be the path of this script, including following symlinks,
+# and set up progdir to be the fully-qualified pathname of its directory.
+prog="$0"
+while [ -h "${prog}" ]; do
+    newProg=`/bin/ls -ld "${prog}"`
+    newProg=`expr "${newProg}" : ".* -> \(.*\)$"`
+    if expr "x${newProg}" : 'x/' >/dev/null; then
+        prog="${newProg}"
+    else
+        progdir=`dirname "${prog}"`
+        prog="${progdir}/${newProg}"
+    fi
+done
+oldwd=`pwd`
+progdir=`dirname "${prog}"`
+cd "${progdir}"
+progdir=`pwd`
+prog="${progdir}"/`basename "${prog}"`
+cd "${oldwd}"
+
+jarfile=dexdeps.jar
+libdir="$progdir"
+if [ ! -r "$libdir/$jarfile" ]
+then
+    libdir=`dirname "$progdir"`/tools/lib
+fi
+if [ ! -r "$libdir/$jarfile" ]
+then
+    libdir=`dirname "$progdir"`/framework
+fi
+if [ ! -r "$libdir/$jarfile" ]
+then
+    echo `basename "$prog"`": can't find $jarfile"
+    exit 1
+fi
+
+javaOpts=""
+
+# Alternatively, this will extract any parameter "-Jxxx" from the command line
+# and pass them to Java (instead of to dexdeps).
+while expr "x$1" : 'x-J' >/dev/null; do
+    opt=`expr "$1" : '-J\(.*\)'`
+    javaOpts="${javaOpts} -${opt}"
+    shift
+done
+
+if [ "$OSTYPE" = "cygwin" ] ; then
+    jarpath=`cygpath -w  "$libdir/$jarfile"`
+else
+    jarpath="$libdir/$jarfile"
+fi
+
+exec java $javaOpts -jar "$jarpath" "$@"
diff --git a/tools/dexdeps/etc/manifest.txt b/tools/dexdeps/etc/manifest.txt
new file mode 100644
index 0000000..7606744
--- /dev/null
+++ b/tools/dexdeps/etc/manifest.txt
@@ -0,0 +1 @@
+Main-Class: com.android.dexdeps.Main
diff --git a/tools/dexdeps/src/Android.mk b/tools/dexdeps/src/Android.mk
new file mode 100644
index 0000000..756a0b3
--- /dev/null
+++ b/tools/dexdeps/src/Android.mk
@@ -0,0 +1,32 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+
+# dexdeps java library
+# ============================================================
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_JAR_MANIFEST := ../etc/manifest.txt
+
+LOCAL_MODULE:= dexdeps
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
+INTERNAL_DALVIK_MODULES += $(LOCAL_INSTALLED_MODULE)
+
+include $(BUILD_DROIDDOC)
+
diff --git a/tools/dexdeps/src/com/android/dexdeps/DexData.java b/tools/dexdeps/src/com/android/dexdeps/DexData.java
new file mode 100644
index 0000000..fa79d60
--- /dev/null
+++ b/tools/dexdeps/src/com/android/dexdeps/DexData.java
@@ -0,0 +1,585 @@
+/*
+ * 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.android.dexdeps;
+
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.Arrays;
+
+/**
+ * Data extracted from a DEX file.
+ */
+public class DexData {
+    private RandomAccessFile mDexFile;
+    private HeaderItem mHeaderItem;
+    private String[] mStrings;              // strings from string_data_*
+    private TypeIdItem[] mTypeIds;
+    private ProtoIdItem[] mProtoIds;
+    private FieldIdItem[] mFieldIds;
+    private MethodIdItem[] mMethodIds;
+    private ClassDefItem[] mClassDefs;
+
+    private byte tmpBuf[] = new byte[4];
+    private boolean isBigEndian = false;
+
+    /**
+     * Constructs a new DexData for this file.
+     */
+    public DexData(RandomAccessFile raf) {
+        mDexFile = raf;
+    }
+
+    /**
+     * Loads the contents of the DEX file into our data structures.
+     *
+     * @throws IOException if we encounter a problem while reading
+     * @throws DexDataException if the DEX contents look bad
+     */
+    public void load() throws IOException {
+        parseHeaderItem();
+
+        loadStrings();
+        loadTypeIds();
+        loadProtoIds();
+        loadFieldIds();
+        loadMethodIds();
+        loadClassDefs();
+
+        markInternalClasses();
+    }
+
+
+    /**
+     * Parses the interesting bits out of the header.
+     */
+    void parseHeaderItem() throws IOException {
+        mHeaderItem = new HeaderItem();
+
+        seek(0);
+
+        byte[] magic = new byte[8];
+        readBytes(magic);
+        if (!Arrays.equals(magic, HeaderItem.DEX_FILE_MAGIC)) {
+            System.err.println("Magic number is wrong -- are you sure " +
+                "this is a DEX file?");
+            throw new DexDataException();
+        }
+
+        /*
+         * Read the endian tag, so we properly swap things as we read
+         * them from here on.
+         */
+        seek(8+4+20+4+4);
+        mHeaderItem.endianTag = readInt();
+        if (mHeaderItem.endianTag == HeaderItem.ENDIAN_CONSTANT) {
+            /* do nothing */
+        } else if (mHeaderItem.endianTag == HeaderItem.REVERSE_ENDIAN_CONSTANT){
+            /* file is big-endian (!), reverse future reads */
+            isBigEndian = true;
+        } else {
+            System.err.println("Endian constant has unexpected value " +
+                Integer.toHexString(mHeaderItem.endianTag));
+            throw new DexDataException();
+        }
+
+        seek(8+4+20);  // magic, checksum, signature
+        mHeaderItem.fileSize = readInt();
+        mHeaderItem.headerSize = readInt();
+        /*mHeaderItem.endianTag =*/ readInt();
+        /*mHeaderItem.linkSize =*/ readInt();
+        /*mHeaderItem.linkOff =*/ readInt();
+        /*mHeaderItem.mapOff =*/ readInt();
+        mHeaderItem.stringIdsSize = readInt();
+        mHeaderItem.stringIdsOff = readInt();
+        mHeaderItem.typeIdsSize = readInt();
+        mHeaderItem.typeIdsOff = readInt();
+        mHeaderItem.protoIdsSize = readInt();
+        mHeaderItem.protoIdsOff = readInt();
+        mHeaderItem.fieldIdsSize = readInt();
+        mHeaderItem.fieldIdsOff = readInt();
+        mHeaderItem.methodIdsSize = readInt();
+        mHeaderItem.methodIdsOff = readInt();
+        mHeaderItem.classDefsSize = readInt();
+        mHeaderItem.classDefsOff = readInt();
+        /*mHeaderItem.dataSize =*/ readInt();
+        /*mHeaderItem.dataOff =*/ readInt();
+    }
+
+    /**
+     * Loads the string table out of the DEX.
+     *
+     * First we read all of the string_id_items, then we read all of the
+     * string_data_item.  Doing it this way should allow us to avoid
+     * seeking around in the file.
+     */
+    void loadStrings() throws IOException {
+        int count = mHeaderItem.stringIdsSize;
+        int stringOffsets[] = new int[count];
+
+        //System.out.println("reading " + count + " strings");
+
+        seek(mHeaderItem.stringIdsOff);
+        for (int i = 0; i < count; i++) {
+            stringOffsets[i] = readInt();
+        }
+
+        mStrings = new String[count];
+
+        seek(stringOffsets[0]);
+        for (int i = 0; i < count; i++) {
+            seek(stringOffsets[i]);         // should be a no-op
+            mStrings[i] = readString();
+            //System.out.println("STR: " + i + ": " + mStrings[i]);
+        }
+    }
+
+    /**
+     * Loads the type ID list.
+     */
+    void loadTypeIds() throws IOException {
+        int count = mHeaderItem.typeIdsSize;
+        mTypeIds = new TypeIdItem[count];
+
+        //System.out.println("reading " + count + " typeIds");
+        seek(mHeaderItem.typeIdsOff);
+        for (int i = 0; i < count; i++) {
+            mTypeIds[i] = new TypeIdItem();
+            mTypeIds[i].descriptorIdx = readInt();
+
+            //System.out.println(i + ": " + mTypeIds[i].descriptorIdx +
+            //    " " + mStrings[mTypeIds[i].descriptorIdx]);
+        }
+    }
+
+    /**
+     * Loads the proto ID list.
+     */
+    void loadProtoIds() throws IOException {
+        int count = mHeaderItem.protoIdsSize;
+        mProtoIds = new ProtoIdItem[count];
+
+        //System.out.println("reading " + count + " protoIds");
+        seek(mHeaderItem.protoIdsOff);
+
+        /*
+         * Read the proto ID items.
+         */
+        for (int i = 0; i < count; i++) {
+            mProtoIds[i] = new ProtoIdItem();
+            mProtoIds[i].shortyIdx = readInt();
+            mProtoIds[i].returnTypeIdx = readInt();
+            mProtoIds[i].parametersOff = readInt();
+
+            //System.out.println(i + ": " + mProtoIds[i].shortyIdx +
+            //    " " + mStrings[mProtoIds[i].shortyIdx]);
+        }
+
+        /*
+         * Go back through and read the type lists.
+         */
+        for (int i = 0; i < count; i++) {
+            ProtoIdItem protoId = mProtoIds[i];
+
+            int offset = protoId.parametersOff;
+
+            if (offset == 0) {
+                protoId.types = new int[0];
+                continue;
+            } else {
+                seek(offset);
+                int size = readInt();       // #of entries in list
+                protoId.types = new int[size];
+
+                for (int j = 0; j < size; j++) {
+                    protoId.types[j] = readShort() & 0xffff;
+                }
+            }
+        }
+    }
+
+    /**
+     * Loads the field ID list.
+     */
+    void loadFieldIds() throws IOException {
+        int count = mHeaderItem.fieldIdsSize;
+        mFieldIds = new FieldIdItem[count];
+
+        //System.out.println("reading " + count + " fieldIds");
+        seek(mHeaderItem.fieldIdsOff);
+        for (int i = 0; i < count; i++) {
+            mFieldIds[i] = new FieldIdItem();
+            mFieldIds[i].classIdx = readShort() & 0xffff;
+            mFieldIds[i].typeIdx = readShort() & 0xffff;
+            mFieldIds[i].nameIdx = readInt();
+
+            //System.out.println(i + ": " + mFieldIds[i].nameIdx +
+            //    " " + mStrings[mFieldIds[i].nameIdx]);
+        }
+    }
+
+    /**
+     * Loads the method ID list.
+     */
+    void loadMethodIds() throws IOException {
+        int count = mHeaderItem.methodIdsSize;
+        mMethodIds = new MethodIdItem[count];
+
+        //System.out.println("reading " + count + " methodIds");
+        seek(mHeaderItem.methodIdsOff);
+        for (int i = 0; i < count; i++) {
+            mMethodIds[i] = new MethodIdItem();
+            mMethodIds[i].classIdx = readShort() & 0xffff;
+            mMethodIds[i].protoIdx = readShort() & 0xffff;
+            mMethodIds[i].nameIdx = readInt();
+
+            //System.out.println(i + ": " + mMethodIds[i].nameIdx +
+            //    " " + mStrings[mMethodIds[i].nameIdx]);
+        }
+    }
+
+    /**
+     * Loads the class defs list.
+     */
+    void loadClassDefs() throws IOException {
+        int count = mHeaderItem.classDefsSize;
+        mClassDefs = new ClassDefItem[count];
+
+        //System.out.println("reading " + count + " classDefs");
+        seek(mHeaderItem.classDefsOff);
+        for (int i = 0; i < count; i++) {
+            mClassDefs[i] = new ClassDefItem();
+            mClassDefs[i].classIdx = readInt();
+
+            /* access_flags = */ readInt();
+            /* superclass_idx = */ readInt();
+            /* interfaces_off = */ readInt();
+            /* source_file_idx = */ readInt();
+            /* annotations_off = */ readInt();
+            /* class_data_off = */ readInt();
+            /* static_values_off = */ readInt();
+
+            //System.out.println(i + ": " + mClassDefs[i].classIdx + " " +
+            //    mStrings[mTypeIds[mClassDefs[i].classIdx].descriptorIdx]);
+        }
+    }
+
+    /**
+     * Sets the "internal" flag on type IDs which are defined in the
+     * DEX file or within the VM (e.g. primitive classes and arrays).
+     */
+    void markInternalClasses() {
+        for (int i = mClassDefs.length -1; i >= 0; i--) {
+            mTypeIds[mClassDefs[i].classIdx].internal = true;
+        }
+
+        for (int i = 0; i < mTypeIds.length; i++) {
+            String className = mStrings[mTypeIds[i].descriptorIdx];
+
+            if (className.length() == 1) {
+                // primitive class
+                mTypeIds[i].internal = true;
+            } else if (className.charAt(0) == '[') {
+                mTypeIds[i].internal = true;
+            }
+
+            //System.out.println(i + " " +
+            //    (mTypeIds[i].internal ? "INTERNAL" : "external") + " - " +
+            //    mStrings[mTypeIds[i].descriptorIdx]);
+        }
+    }
+
+
+    /*
+     * =======================================================================
+     *      Queries
+     * =======================================================================
+     */
+
+    /**
+     * Returns the class name, given an index into the type_ids table.
+     */
+    private String classNameFromTypeIndex(int idx) {
+        return mStrings[mTypeIds[idx].descriptorIdx];
+    }
+
+    /**
+     * Returns an array of method argument type strings, given an index
+     * into the proto_ids table.
+     */
+    private String[] argArrayFromProtoIndex(int idx) {
+        ProtoIdItem protoId = mProtoIds[idx];
+        String[] result = new String[protoId.types.length];
+
+        for (int i = 0; i < protoId.types.length; i++) {
+            result[i] = mStrings[mTypeIds[protoId.types[i]].descriptorIdx];
+        }
+
+        return result;
+    }
+
+    /**
+     * Returns a string representing the method's return type, given an
+     * index into the proto_ids table.
+     */
+    private String returnTypeFromProtoIndex(int idx) {
+        ProtoIdItem protoId = mProtoIds[idx];
+        return mStrings[mTypeIds[protoId.returnTypeIdx].descriptorIdx];
+    }
+
+    /**
+     * Returns an array with all of the field references that don't
+     * correspond to classes in the DEX file.
+     */
+    public FieldRef[] getExternalFieldReferences() {
+        // get a count
+        int count = 0;
+        for (int i = 0; i < mFieldIds.length; i++) {
+            if (!mTypeIds[mFieldIds[i].classIdx].internal)
+                count++;
+        }
+
+        //System.out.println("count is " + count + " of " + mFieldIds.length);
+
+        FieldRef[] fieldRefs = new FieldRef[count];
+        count = 0;
+        for (int i = 0; i < mFieldIds.length; i++) {
+            if (!mTypeIds[mFieldIds[i].classIdx].internal) {
+                FieldIdItem fieldId = mFieldIds[i];
+                fieldRefs[count++] =
+                    new FieldRef(classNameFromTypeIndex(fieldId.classIdx),
+                                 classNameFromTypeIndex(fieldId.typeIdx),
+                                 mStrings[fieldId.nameIdx]);
+            }
+        }
+
+        assert count == fieldRefs.length;
+
+        return fieldRefs;
+    }
+
+    /**
+     * Returns an array with all of the method references that don't
+     * correspond to classes in the DEX file.
+     */
+    public MethodRef[] getExternalMethodReferences() {
+        // get a count
+        int count = 0;
+        for (int i = 0; i < mMethodIds.length; i++) {
+            if (!mTypeIds[mMethodIds[i].classIdx].internal)
+                count++;
+        }
+
+        //System.out.println("count is " + count + " of " + mMethodIds.length);
+
+        MethodRef[] methodRefs = new MethodRef[count];
+        count = 0;
+        for (int i = 0; i < mMethodIds.length; i++) {
+            if (!mTypeIds[mMethodIds[i].classIdx].internal) {
+                MethodIdItem methodId = mMethodIds[i];
+                methodRefs[count++] =
+                    new MethodRef(classNameFromTypeIndex(methodId.classIdx),
+                                 argArrayFromProtoIndex(methodId.protoIdx),
+                                 returnTypeFromProtoIndex(methodId.protoIdx),
+                                 mStrings[methodId.nameIdx]);
+            }
+        }
+
+        assert count == methodRefs.length;
+
+        return methodRefs;
+    }
+
+
+    /*
+     * =======================================================================
+     *      Basic I/O functions
+     * =======================================================================
+     */
+
+    /**
+     * Seeks the DEX file to the specified absolute position.
+     */
+    void seek(int position) throws IOException {
+        mDexFile.seek(position);
+    }
+
+    /**
+     * Fills the buffer by reading bytes from the DEX file.
+     */
+    void readBytes(byte[] buffer) throws IOException {
+        mDexFile.readFully(buffer);
+    }
+
+    /**
+     * Reads a single signed byte value.
+     */
+    byte readByte() throws IOException {
+        mDexFile.readFully(tmpBuf, 0, 1);
+        return tmpBuf[0];
+    }
+
+    /**
+     * Reads a signed 16-bit integer, byte-swapping if necessary.
+     */
+    short readShort() throws IOException {
+        mDexFile.readFully(tmpBuf, 0, 2);
+        if (isBigEndian) {
+            return (short) ((tmpBuf[1] & 0xff) | ((tmpBuf[0] & 0xff) << 8));
+        } else {
+            return (short) ((tmpBuf[0] & 0xff) | ((tmpBuf[1] & 0xff) << 8));
+        }
+    }
+
+    /**
+     * Reads a signed 32-bit integer, byte-swapping if necessary.
+     */
+    int readInt() throws IOException {
+        mDexFile.readFully(tmpBuf, 0, 4);
+
+        if (isBigEndian) {
+            return (tmpBuf[3] & 0xff) | ((tmpBuf[2] & 0xff) << 8) |
+                   ((tmpBuf[1] & 0xff) << 16) | ((tmpBuf[0] & 0xff) << 24);
+        } else {
+            return (tmpBuf[0] & 0xff) | ((tmpBuf[1] & 0xff) << 8) |
+                   ((tmpBuf[2] & 0xff) << 16) | ((tmpBuf[3] & 0xff) << 24);
+        }
+    }
+
+    /**
+     * Reads a variable-length unsigned LEB128 value.  Does not attempt to
+     * verify that the value is valid.
+     *
+     * @throws EOFException if we run off the end of the file
+     */
+    int readUnsignedLeb128() throws IOException {
+        int result = 0;
+        byte val;
+
+        do {
+            val = readByte();
+            result = (result << 7) | (val & 0x7f);
+        } while (val < 0);
+
+        return result;
+    }
+
+    /**
+     * Reads a UTF-8 string.
+     *
+     * We don't know how long the UTF-8 string is, so we have to read one
+     * byte at a time.  We could make an educated guess based on the
+     * utf16_size and seek back if we get it wrong, but seeking backward
+     * may cause the underlying implementation to reload I/O buffers.
+     */
+    String readString() throws IOException {
+        int utf16len = readUnsignedLeb128();
+        byte inBuf[] = new byte[utf16len * 3];      // worst case
+        int idx;
+
+        for (idx = 0; idx < inBuf.length; idx++) {
+            byte val = readByte();
+            if (val == 0)
+                break;
+            inBuf[idx] = val;
+        }
+
+        return new String(inBuf, 0, idx, "UTF-8");
+    }
+
+
+    /*
+     * =======================================================================
+     *      Internal "structure" declarations
+     * =======================================================================
+     */
+
+    /**
+     * Holds the contents of a header_item.
+     */
+    static class HeaderItem {
+        public int fileSize;
+        public int headerSize;
+        public int endianTag;
+        public int stringIdsSize, stringIdsOff;
+        public int typeIdsSize, typeIdsOff;
+        public int protoIdsSize, protoIdsOff;
+        public int fieldIdsSize, fieldIdsOff;
+        public int methodIdsSize, methodIdsOff;
+        public int classDefsSize, classDefsOff;
+
+        /* expected magic values */
+        public static final byte[] DEX_FILE_MAGIC = {
+            0x64, 0x65, 0x78, 0x0a, 0x30, 0x33, 0x35, 0x00 };
+        public static final int ENDIAN_CONSTANT = 0x12345678;
+        public static final int REVERSE_ENDIAN_CONSTANT = 0x78563412;
+    }
+
+    /**
+     * Holds the contents of a type_id_item.
+     *
+     * This is chiefly a list of indices into the string table.  We need
+     * some additional bits of data, such as whether or not the type ID
+     * represents a class defined in this DEX, so we use an object for
+     * each instead of a simple integer.  (Could use a parallel array, but
+     * since this is a desktop app it's not essential.)
+     */
+    static class TypeIdItem {
+        public int descriptorIdx;       // index into string_ids
+
+        public boolean internal;        // defined within this DEX file?
+    }
+
+    /**
+     * Holds the contents of a proto_id_item.
+     */
+    static class ProtoIdItem {
+        public int shortyIdx;           // index into string_ids
+        public int returnTypeIdx;       // index into type_ids
+        public int parametersOff;       // file offset to a type_list
+
+        public int types[];             // contents of type list
+    }
+
+    /**
+     * Holds the contents of a field_id_item.
+     */
+    static class FieldIdItem {
+        public int classIdx;            // index into type_ids (defining class)
+        public int typeIdx;             // index into type_ids (field type)
+        public int nameIdx;             // index into string_ids
+    }
+
+    /**
+     * Holds the contents of a method_id_item.
+     */
+    static class MethodIdItem {
+        public int classIdx;            // index into type_ids
+        public int protoIdx;            // index into proto_ids
+        public int nameIdx;             // index into string_ids
+    }
+
+    /**
+     * Holds the contents of a class_def_item.
+     *
+     * We don't really need a class for this, but there's some stuff in
+     * the class_def_item that we might want later.
+     */
+    static class ClassDefItem {
+        public int classIdx;            // index into type_ids
+    }
+}
+
diff --git a/tools/dexdeps/src/com/android/dexdeps/DexDataException.java b/tools/dexdeps/src/com/android/dexdeps/DexDataException.java
new file mode 100644
index 0000000..e51853f
--- /dev/null
+++ b/tools/dexdeps/src/com/android/dexdeps/DexDataException.java
@@ -0,0 +1,24 @@
+/*
+ * 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.android.dexdeps;
+
+/**
+ * Bad data found inside a DEX file.
+ */
+public class DexDataException extends RuntimeException {
+}
+
diff --git a/tools/dexdeps/src/com/android/dexdeps/FieldRef.java b/tools/dexdeps/src/com/android/dexdeps/FieldRef.java
new file mode 100644
index 0000000..2726a7a
--- /dev/null
+++ b/tools/dexdeps/src/com/android/dexdeps/FieldRef.java
@@ -0,0 +1,52 @@
+/*
+ * 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.android.dexdeps;
+
+public class FieldRef {
+    private String mDeclClass, mFieldType, mFieldName;
+
+    /**
+     * Initializes a new field reference.
+     */
+    public FieldRef(String declClass, String fieldType, String fieldName) {
+        mDeclClass = declClass;
+        mFieldType = fieldType;
+        mFieldName = fieldName;
+    }
+
+    /**
+     * Gets the name of the field's declaring class.
+     */
+    public String getDeclClassName() {
+        return mDeclClass;
+    }
+
+    /**
+     * Gets the type name.  Examples: "Ljava/lang/String;", "[I".
+     */
+    public String getTypeName() {
+        return mFieldType;
+    }
+
+    /**
+     * Gets the field name.
+     */
+    public String getName() {
+        return mFieldName;
+    }
+}
+
diff --git a/tools/dexdeps/src/com/android/dexdeps/Main.java b/tools/dexdeps/src/com/android/dexdeps/Main.java
new file mode 100644
index 0000000..7eba3aa
--- /dev/null
+++ b/tools/dexdeps/src/com/android/dexdeps/Main.java
@@ -0,0 +1,201 @@
+/*
+ * 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.android.dexdeps;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipException;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipInputStream;
+
+public class Main {
+    private static final String CLASSES_DEX = "classes.dex";
+
+    private String mInputFileName;
+    private String mOutputFormat = "brief";
+
+    /**
+     * Entry point.
+     */
+    public static void main(String[] args) {
+        Main main = new Main();
+        main.run(args);
+    }
+
+    /**
+     * Start things up.
+     */
+    void run(String[] args) {
+        try {
+            parseArgs(args);
+            RandomAccessFile raf = openInputFile();
+            DexData dexData = new DexData(raf);
+            dexData.load();
+
+            Output.generate(dexData, mOutputFormat);
+        } catch (UsageException ue) {
+            usage();
+            System.exit(2);
+        } catch (IOException ioe) {
+            if (ioe.getMessage() != null)
+                System.err.println("Failed: " + ioe);
+            System.exit(1);
+        } catch (DexDataException dde) {
+            /* a message was already reported, just bail quietly */
+            System.exit(1);
+        }
+    }
+
+    /**
+     * Opens the input file, which could be a .dex or a .jar/.apk with a
+     * classes.dex inside.  If the latter, we extract the contents to a
+     * temporary file.
+     */
+    RandomAccessFile openInputFile() throws IOException {
+        RandomAccessFile raf;
+
+        raf = openInputFileAsZip();
+        if (raf == null) {
+            File inputFile = new File(mInputFileName);
+            raf = new RandomAccessFile(inputFile, "r");
+        }
+
+        return raf;
+    }
+
+    /**
+     * Tries to open the input file as a Zip archive (jar/apk) with a
+     * "classes.dex" inside.
+     *
+     * @return a RandomAccessFile for classes.dex, or null if the input file
+     *         is not a zip archive
+     * @throws IOException if the file isn't found, or it's a zip and
+     *         classes.dex isn't found inside
+     */
+    RandomAccessFile openInputFileAsZip() throws IOException {
+        ZipFile zipFile;
+
+        /*
+         * Try it as a zip file.
+         */
+        try {
+            zipFile = new ZipFile(mInputFileName);
+        } catch (FileNotFoundException fnfe) {
+            /* not found, no point in retrying as non-zip */
+            System.err.println("Unable to open '" + mInputFileName + "': " +
+                fnfe.getMessage());
+            throw fnfe;
+        } catch (ZipException ze) {
+            /* not a zip */
+            return null;
+        }
+
+        /*
+         * We know it's a zip; see if there's anything useful inside.  A
+         * failure here results in some type of IOException (of which
+         * ZipException is a subclass).
+         */
+        ZipEntry entry = zipFile.getEntry(CLASSES_DEX);
+        if (entry == null) {
+            System.err.println("Unable to find '" + CLASSES_DEX +
+                "' in '" + mInputFileName + "'");
+            zipFile.close();
+            throw new ZipException();
+        }
+
+        InputStream zis = zipFile.getInputStream(entry);
+
+        /*
+         * Create a temp file to hold the DEX data, open it, and delete it
+         * to ensure it doesn't hang around if we fail.
+         */
+        File tempFile = File.createTempFile("dexdeps", ".dex");
+        //System.out.println("+++ using temp " + tempFile);
+        RandomAccessFile raf = new RandomAccessFile(tempFile, "rw");
+        tempFile.delete();
+
+        /*
+         * Copy all data from input stream to output file.
+         */
+        byte copyBuf[] = new byte[32768];
+        int actual;
+
+        while (true) {
+            actual = zis.read(copyBuf);
+            if (actual == -1)
+                break;
+
+            raf.write(copyBuf, 0, actual);
+        }
+
+        zis.close();
+        raf.seek(0);
+
+        return raf;
+    }
+
+
+    /**
+     * Parses command-line arguments.
+     *
+     * @throws UsageException if arguments are missing or poorly formed
+     */
+    void parseArgs(String[] args) {
+        int idx;
+
+        for (idx = 0; idx < args.length; idx++) {
+            String arg = args[idx];
+
+            if (arg.equals("--") || !arg.startsWith("--")) {
+                break;
+            } else if (arg.startsWith("--format=")) {
+                mOutputFormat = arg.substring(arg.indexOf('=') + 1);
+                if (!mOutputFormat.equals("brief") &&
+                    !mOutputFormat.equals("xml"))
+                {
+                    System.err.println("Unknown format '" + mOutputFormat +"'");
+                    throw new UsageException();
+                }
+                //System.out.println("+++ using format " + mOutputFormat);
+            } else {
+                System.err.println("Unknown option '" + arg + "'");
+                throw new UsageException();
+            }
+        }
+
+        // expecting one argument left
+        if (idx != args.length - 1) {
+            throw new UsageException();
+        }
+
+        mInputFileName = args[idx];
+    }
+
+    /**
+     * Prints command-line usage info.
+     */
+    void usage() {
+        System.err.println("\nUsage: dexdeps [options] <file.{dex,apk,jar}>");
+        System.err.println("Options:");
+        System.err.println("  --format={brief,xml}");
+    }
+}
+
diff --git a/tools/dexdeps/src/com/android/dexdeps/MethodRef.java b/tools/dexdeps/src/com/android/dexdeps/MethodRef.java
new file mode 100644
index 0000000..96522eb
--- /dev/null
+++ b/tools/dexdeps/src/com/android/dexdeps/MethodRef.java
@@ -0,0 +1,88 @@
+/*
+ * 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.android.dexdeps;
+
+public class MethodRef {
+    private String mDeclClass, mReturnType, mMethodName;
+    private String[] mArgTypes;
+
+    /**
+     * Initializes a new field reference.
+     */
+    public MethodRef(String declClass, String[] argTypes, String returnType,
+            String methodName) {
+        mDeclClass = declClass;
+        mArgTypes = argTypes;
+        mReturnType = returnType;
+        mMethodName = methodName;
+    }
+
+    /**
+     * Gets the name of the method's declaring class.
+     */
+    public String getDeclClassName() {
+        return mDeclClass;
+    }
+
+    /**
+     * Gets the method's descriptor.
+     */
+    public String getDescriptor() {
+        return descriptorFromProtoArray(mArgTypes, mReturnType);
+    }
+
+    /**
+     * Gets the method's name.
+     */
+    public String getName() {
+        return mMethodName;
+    }
+
+    /**
+     * Gets an array of method argument types.
+     */
+    public String[] getArgumentTypeNames() {
+        return mArgTypes;
+    }
+
+    /**
+     * Gets the method's return type.  Examples: "Ljava/lang/String;", "[I".
+     */
+    public String getReturnTypeName() {
+        return mReturnType;
+    }
+
+    /**
+     * Returns the method descriptor, given the argument and return type
+     * prototype strings.
+     */
+    private static String descriptorFromProtoArray(String[] protos,
+            String returnType) {
+        StringBuilder builder = new StringBuilder();
+
+        builder.append("(");
+        for (int i = 0; i < protos.length; i++) {
+            builder.append(protos[i]);
+        }
+
+        builder.append(")");
+        builder.append(returnType);
+
+        return builder.toString();
+    }
+}
+
diff --git a/tools/dexdeps/src/com/android/dexdeps/Output.java b/tools/dexdeps/src/com/android/dexdeps/Output.java
new file mode 100644
index 0000000..0039b33
--- /dev/null
+++ b/tools/dexdeps/src/com/android/dexdeps/Output.java
@@ -0,0 +1,264 @@
+/*
+ * 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.android.dexdeps;
+
+/**
+ * Generate fancy output.
+ */
+public class Output {
+    public static void generate(DexData dexData, String format) {
+        if (format.equals("brief")) {
+            printBrief(dexData);
+        } else if (format.equals("xml")) {
+            printXml(dexData);
+        } else {
+            /* should've been trapped in arg handler */
+            throw new RuntimeException("unknown output format");
+        }
+    }
+
+    /**
+     * Prints the data in a simple human-readable format.
+     */
+    static void printBrief(DexData dexData) {
+        FieldRef[] externFieldRefs = dexData.getExternalFieldReferences();
+        MethodRef[] externMethodRefs = dexData.getExternalMethodReferences();
+
+        printFieldRefs(externFieldRefs);
+        printMethodRefs(externMethodRefs);
+    }
+
+    /**
+     * Prints the list of fields in a simple human-readable format.
+     */
+    static void printFieldRefs(FieldRef[] fields) {
+        System.out.println("Fields:");
+        for (int i = 0; i < fields.length; i++) {
+            FieldRef ref = fields[i];
+
+            System.out.println(descriptorToDot(ref.getDeclClassName()) + "." +
+                ref.getName() + " : " + ref.getTypeName());
+        }
+    }
+
+    /**
+     * Prints the list of methods in a simple human-readable format.
+     */
+    static void printMethodRefs(MethodRef[] methods) {
+        System.out.println("Methods:");
+        for (int i = 0; i < methods.length; i++) {
+            MethodRef ref = methods[i];
+
+            System.out.println(descriptorToDot(ref.getDeclClassName()) +
+                "." + ref.getName() + " : " + ref.getDescriptor());
+        }
+    }
+
+
+    /**
+     * Prints the output in XML format.
+     *
+     * We shouldn't need to XML-escape the field/method info.
+     */
+    static void printXml(DexData dexData) {
+        final String IN0 = "";
+        final String IN1 = "  ";
+        final String IN2 = "    ";
+        final String IN3 = "      ";
+        FieldRef[] externFieldRefs = dexData.getExternalFieldReferences();
+        MethodRef[] externMethodRefs = dexData.getExternalMethodReferences();
+        String prevClass = null;
+
+        System.out.println(IN0 + "<external>");
+
+        /* print fields */
+        for (int i = 0; i < externFieldRefs.length; i++) {
+            FieldRef fref = externFieldRefs[i];
+            String declClassName = fref.getDeclClassName();
+
+            if (prevClass != null && !prevClass.equals(declClassName)) {
+                System.out.println(IN1 + "</class>");
+            }
+            if (!declClassName.equals(prevClass)) {
+                String className = classNameOnly(declClassName);
+                String packageName = packageNameOnly(declClassName);
+                System.out.println(IN1 + "<class package=\"" + packageName +
+                    "\" name=\"" + className + "\">");
+                prevClass = declClassName;
+            }
+
+            System.out.println(IN2 + "<field name=\"" + fref.getName() +
+                "\" type=\"" + descriptorToDot(fref.getTypeName()) + "\"/>");
+        }
+
+        /* print methods */
+        for (int i = 0; i < externMethodRefs.length; i++) {
+            MethodRef mref = externMethodRefs[i];
+            String declClassName = mref.getDeclClassName();
+            boolean constructor;
+
+            if (prevClass != null && !prevClass.equals(declClassName)) {
+                System.out.println(IN1 + "</class>");
+            }
+            if (!declClassName.equals(prevClass)) {
+                String className = classNameOnly(declClassName);
+                String packageName = packageNameOnly(declClassName);
+                System.out.println(IN1 + "<class package=\"" + packageName +
+                    "\" name=\"" + className + "\">");
+                prevClass = declClassName;
+            }
+
+            constructor = mref.getName().equals("<init>");
+            if (constructor) {
+                /* use class name instead of method name */
+                System.out.println(IN2 + "<constructor name=\"" +
+                    classNameOnly(declClassName) + "\" return=\"" +
+                    descriptorToDot(mref.getReturnTypeName()) + "\">");
+            } else {
+                System.out.println(IN2 + "<method name=\"" + mref.getName() +
+                    "\" return=\"" + descriptorToDot(mref.getReturnTypeName()) +
+                    "\">");
+            }
+            String[] args = mref.getArgumentTypeNames();
+            for (int j = 0; j < args.length; j++) {
+                System.out.println(IN3 + "<parameter type=\"" +
+                    descriptorToDot(args[j]) + "\"/>");
+            }
+            if (constructor) {
+                System.out.println(IN2 + "</constructor>");
+            } else {
+                System.out.println(IN2 + "</method>");
+            }
+        }
+
+        if (prevClass != null)
+            System.out.println(IN1 + "</class>");
+        System.out.println(IN0 + "</external>");
+    }
+
+
+    /*
+     * =======================================================================
+     *      Utility functions
+     * =======================================================================
+     */
+
+    /**
+     * Converts a single-character primitive type into its human-readable
+     * equivalent.
+     */
+    static String primitiveTypeLabel(char typeChar) {
+        /* primitive type; substitute human-readable name in */
+        switch (typeChar) {
+            case 'B':   return "byte";
+            case 'C':   return "char";
+            case 'D':   return "double";
+            case 'F':   return "float";
+            case 'I':   return "int";
+            case 'J':   return "long";
+            case 'S':   return "short";
+            case 'V':   return "void";
+            case 'Z':   return "boolean";
+            default:
+                /* huh? */
+                System.err.println("Unexpected class char " + typeChar);
+                assert false;
+                return "UNKNOWN";
+        }
+    }
+
+    /**
+     * Converts a type descriptor to human-readable "dotted" form.  For
+     * example, "Ljava/lang/String;" becomes "java.lang.String", and
+     * "[I" becomes "int[].
+     */
+    static String descriptorToDot(String descr) {
+        int targetLen = descr.length();
+        int offset = 0;
+        int arrayDepth = 0;
+
+        /* strip leading [s; will be added to end */
+        while (targetLen > 1 && descr.charAt(offset) == '[') {
+            offset++;
+            targetLen--;
+        }
+        arrayDepth = offset;
+
+        if (targetLen == 1) {
+            descr = primitiveTypeLabel(descr.charAt(offset));
+            offset = 0;
+            targetLen = descr.length();
+        } else {
+            /* account for leading 'L' and trailing ';' */
+            if (targetLen >= 2 && descr.charAt(offset) == 'L' &&
+                descr.charAt(offset+targetLen-1) == ';')
+            {
+                targetLen -= 2;     /* two fewer chars to copy */
+                offset++;           /* skip the 'L' */
+            }
+        }
+
+        char[] buf = new char[targetLen + arrayDepth * 2];
+
+        /* copy class name over */
+        int i;
+        for (i = 0; i < targetLen; i++) {
+            char ch = descr.charAt(offset + i);
+            buf[i] = (ch == '/') ? '.' : ch;
+        }
+
+        /* add the appopriate number of brackets for arrays */
+        while (arrayDepth-- > 0) {
+            buf[i++] = '[';
+            buf[i++] = ']';
+        }
+        assert i == buf.length;
+
+        return new String(buf);
+    }
+
+    /**
+     * Extracts the class name from a type descriptor.
+     */
+    static String classNameOnly(String typeName) {
+        String dotted = descriptorToDot(typeName);
+
+        int start = dotted.lastIndexOf(".");
+        if (start < 0) {
+            return dotted;
+        } else {
+            return dotted.substring(start+1);
+        }
+    }
+
+    /**
+     * Extracts the package name from a type descriptor, and returns it in
+     * dotted form.
+     */
+    static String packageNameOnly(String typeName) {
+        String dotted = descriptorToDot(typeName);
+
+        int end = dotted.lastIndexOf(".");
+        if (end < 0) {
+            /* lives in default package */
+            return "";
+        } else {
+            return dotted.substring(0, end);
+        }
+    }
+}
+
diff --git a/tools/dexdeps/src/com/android/dexdeps/UsageException.java b/tools/dexdeps/src/com/android/dexdeps/UsageException.java
new file mode 100644
index 0000000..f9f971b
--- /dev/null
+++ b/tools/dexdeps/src/com/android/dexdeps/UsageException.java
@@ -0,0 +1,24 @@
+/*
+ * 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.android.dexdeps;
+
+/**
+ * Tells the main entry point to show the usage information and bail.
+ */
+public class UsageException extends RuntimeException {
+}
+
diff --git a/tools/dmtracedump/TraceDump.c b/tools/dmtracedump/TraceDump.c
index ae56d4d..2308148 100644
--- a/tools/dmtracedump/TraceDump.c
+++ b/tools/dmtracedump/TraceDump.c
@@ -14,6 +14,7 @@
 ** See the License for the specific language governing permissions and 
 ** limitations under the License.
 */
+
 /*
  * Process dmtrace output.
  *
@@ -127,6 +128,7 @@
 typedef struct ThreadEntry {
     int         threadId;
     const char* threadName;
+    uint64_t    elapsedTime;
 } ThreadEntry;
 
 struct MethodEntry;
@@ -178,7 +180,7 @@
  * The parsed contents of the key file.
  */
 typedef struct DataKeys {
-    char*        fileData;        /* contents of the entire file */
+    char*        fileData;      /* contents of the entire file */
     long         fileLen;
     int          numThreads;
     ThreadEntry* threads;
@@ -398,6 +400,37 @@
 
 /*
  * This comparison function is called from qsort() to sort
+ * threads into decreasing order of elapsed time.
+ */
+int compareElapsed(const void *a, const void *b) {
+    const ThreadEntry *threadA, *threadB;
+    uint64_t elapsed1, elapsed2;
+    int result = 0;
+
+    threadA = (ThreadEntry const *)a;
+    threadB = (ThreadEntry const *)b;
+    elapsed1 = threadA->elapsedTime;
+    elapsed2 = threadB->elapsedTime;
+    if (elapsed1 < elapsed2)
+        return 1;
+    if (elapsed1 > elapsed2)
+        return -1;
+
+    /* If the elapsed times of two threads are equal, then sort them
+     * by thread id.
+     */
+    int idA = threadA->threadId;
+    int idB = threadB->threadId;
+    if (idA < idB)
+        result = -1;
+    if (idA > idB)
+        result = 1;
+
+    return result;
+}
+
+/*
+ * This comparison function is called from qsort() to sort
  * TimedMethods into decreasing order of inclusive elapsed time.
  */
 int compareTimedMethod(const void *a, const void *b) {
@@ -1078,7 +1111,7 @@
 }
 
 /*
- * Look up a method by it's method ID.
+ * Look up a method by its method ID (using binary search).
  *
  * Returns NULL if no matching method was found.
  */
@@ -1096,7 +1129,7 @@
         id = pKeys->methods[mid].methodId;
         if (id == methodId)           /* match */
             return &pKeys->methods[mid];
-        else if (id < methodId)       /* too low */
+	else if (id < methodId)       /* too low */
             lo = mid + 1;
         else                          /* too high */
             hi = mid - 1;
@@ -1490,6 +1523,7 @@
     printf("<ul>\n");
     printf("  <li><a href=\"#exclusive\">Exclusive profile</a></li>\n");
     printf("  <li><a href=\"#inclusive\">Inclusive profile</a></li>\n");
+    printf("  <li><a href=\"#thread\">Thread profile</a></li>\n");
     printf("  <li><a href=\"#class\">Class/method profile</a></li>\n");
     printf("  <li><a href=\"#method\">Method/class profile</a></li>\n");
     printf("</ul>\n\n");
@@ -1500,6 +1534,7 @@
     printf("<a href=\"#contents\">[Top]</a>\n");
     printf("<a href=\"#exclusive\">[Exclusive]</a>\n");
     printf("<a href=\"#inclusive\">[Inclusive]</a>\n");
+    printf("<a href=\"#thread\">[Thread]</a>\n");
     printf("<a href=\"#class\">[Class]</a>\n");
     printf("<a href=\"#method\">[Method]</a>\n");
     printf("<br><br>\n");
@@ -1765,6 +1800,65 @@
     }
 }
 
+void printThreadProfile(ThreadEntry *pThreads, int numThreads, uint64_t sumThreadTime)
+{
+    int ii;
+    ThreadEntry thread;
+    double total, per, sum_per;
+    uint64_t sum;
+    char threadBuf[HTML_BUFSIZE];
+    char anchor_buf[80];
+    char *anchor_close = "";
+
+    total = sumThreadTime;
+    anchor_buf[0] = 0;
+    if (gOptions.outputHtml) {
+        anchor_close = "</a>";
+        printf("<a name=\"thread\"></a>\n");
+        printf("<hr>\n");
+        outputNavigationBar();
+    } else {
+        printf("\n%s\n", profileSeparator);
+    }
+
+    /* Sort the threads into decreasing order of elapsed time. */
+    qsort(pThreads, numThreads, sizeof(ThreadEntry), compareElapsed);
+
+    printf("\nElapsed times for each thread, sorted by elapsed time.\n\n");
+
+    if (gOptions.outputHtml) {
+        printf("<br><br>\n<pre>\n");
+    }
+
+    printf("    Usecs   self %%  sum %% tid   ThreadName\n");
+    sum = 0;
+
+    for (ii = 0; ii < numThreads; ++ii) {
+        int threadId;
+        char *threadName;
+        uint64_t time;
+
+        thread = pThreads[ii];
+
+        threadId = thread.threadId;
+        threadName = (char*)(thread.threadName);
+        time = thread.elapsedTime;
+
+        sum += time;
+        per = 100.0 * time / total;
+        sum_per = 100.0 * sum / total;
+
+        if (gOptions.outputHtml) {
+	    threadName = htmlEscape(threadName, threadBuf, HTML_BUFSIZE);
+        }
+	printf("%9llu  %6.2f %6.2f  %3d   %s\n", time, per, sum_per, threadId, threadName);
+    }
+
+    if (gOptions.outputHtml)
+        printf("</pre>\n");
+
+}
+
 void createClassList(TraceData* traceData, MethodEntry **pMethods, int numMethods)
 {
     int ii;
@@ -2416,16 +2510,25 @@
      */
     CallStack *pStack;
     int threadId;
+    uint64_t elapsedTime = 0;
     uint64_t sumThreadTime = 0;
     for (threadId = 0; threadId < MAX_THREADS; ++threadId) {
+
         pStack = traceData->stacks[threadId];
 
         /* If this thread never existed, then continue with next thread */
         if (pStack == NULL)
             continue;
 
-        /* Also, add up the time taken by all of the threads */
-        sumThreadTime += pStack->lastEventTime - pStack->threadStartTime;
+        /* Calculate time spent in thread, and add it to total time */
+        elapsedTime = pStack->lastEventTime - pStack->threadStartTime;
+        sumThreadTime += elapsedTime;
+
+	/* Save the per-thread elapsed time in the DataKeys struct */
+	for (ii = 0; ii < dataKeys->numThreads; ++ii) {
+	    if (dataKeys->threads[ii].threadId == threadId)
+	        dataKeys->threads[ii].elapsedTime = elapsedTime;
+	}
 
         for (ii = 0; ii < pStack->top; ++ii) {
             if (ii == 0)
@@ -2479,7 +2582,8 @@
 /*
  * Produce a function profile from the following methods
  */
-void profileTrace(TraceData* traceData, MethodEntry **pMethods, int numMethods, uint64_t sumThreadTime)
+void profileTrace(TraceData* traceData, MethodEntry **pMethods, int numMethods, uint64_t sumThreadTime,
+                  ThreadEntry *pThreads, int numThreads)
 {
     /* Print the html header, if necessary */
     if (gOptions.outputHtml) {
@@ -2490,6 +2594,8 @@
     printExclusiveProfile(pMethods, numMethods, sumThreadTime);
     printInclusiveProfile(pMethods, numMethods, sumThreadTime);
 
+    printThreadProfile(pThreads, numThreads, sumThreadTime);
+
     createClassList(traceData, pMethods, numMethods);
     printClassProfiles(traceData, sumThreadTime);
 
@@ -2844,7 +2950,7 @@
     if (gOptions.threshold < 0 || 100 <= gOptions.threshold) {
         gOptions.threshold = 20;
     }
-    
+
     if (gOptions.dump) {
         dumpTrace();
         return 0;
@@ -2870,7 +2976,8 @@
         freeDataKeys(d2);
     } else {
         MethodEntry** methods = parseMethodEntries(dataKeys);
-        profileTrace(&data1, methods, dataKeys->numMethods, sumThreadTime);
+        profileTrace(&data1, methods, dataKeys->numMethods, sumThreadTime,
+                     dataKeys->threads, dataKeys->numThreads);
         if (gOptions.graphFileName != NULL) {
             createInclusiveProfileGraphNew(dataKeys);
         }
diff --git a/tools/gclog.py b/tools/gclog.py
new file mode 100755
index 0000000..4d5b704
--- /dev/null
+++ b/tools/gclog.py
@@ -0,0 +1,235 @@
+#!/usr/bin/env python
+#
+# 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.
+
+#
+# Parse event log output, looking for GC events.  Format them for human
+# consumption.
+#
+# ALL OUTPUT VALUES ARE APPROXIMATE.  The event log data format uses a
+# 12-bit floating-point representation, which means there aren't enough
+# bits to accurately represent anything but small integers.  Larger
+# values will be rounded off.
+#
+# The data is generated by dalvik/vm/alloc/HeapDebug.c.
+#
+
+import getopt
+import sys
+import os
+import re
+import time
+
+DEBUG = False       # DEBUG is a global variable
+
+
+def unfloat12(f12):
+    """Unpack a float12 value"""
+    if f12 < 0:
+        raise DataParseError, "bad float12 value %s" % f12
+    return (f12 & 0x1ff) << ((f12 >> 9) * 4)
+
+
+def parseGlobalInfo(value):
+    """Parse event0 (global info)"""
+    value = int(value)
+
+    # Global information:
+    #
+    # [63   ] Must be zero
+    # [62-24] ASCII process identifier
+    # [23-12] GC time in ms
+    # [11- 0] Bytes freed
+    id = (value >> 24) & 0xffffffffff
+    gctime = unfloat12((value >> 12) & 0xfff)
+    bytes_freed = unfloat12(value & 0xfff)
+
+    idstr = "%c%c%c%c%c" % ( \
+            (id >> 32) & 0xff, \
+            (id >> 24) & 0xff, \
+            (id >> 16) & 0xff, \
+            (id >> 8) & 0xff, \
+            id & 0xff )
+
+    return ( idstr, gctime, bytes_freed )
+
+
+def parseAggHeapStats(value):
+    """Parse event1 (aggregated heap stats)"""
+    value = int(value)
+
+    # Aggregated heap stats:
+    #
+    # [63-62] 10
+    # [61-60] Reserved; must be zero
+    # [59-48] Objects freed
+    # [47-36] Actual size (current footprint)
+    # [35-24] Allowed size (current hard max)
+    # [23-12] Objects allocated
+    # [11- 0] Bytes allocated
+    freed = unfloat12((value >> 48) & 0xfff)
+    footprint = unfloat12((value >> 36) & 0xfff)
+    allowed = unfloat12((value >> 24) & 0xfff)
+    objs = unfloat12((value >> 12) & 0xfff)
+    bytes = unfloat12(value & 0xfff)
+
+    return ( freed, footprint, allowed, objs, bytes )
+
+
+def parseZygoteStats(value):
+    """Parse event2 (zygote heap stats)"""
+    value = int(value)
+
+    # Zygote heap stats (except for the soft limit, which belongs to the
+    # active heap):
+    #
+    # [63-62] 11
+    # [61-60] Reserved; must be zero
+    # [59-48] Soft Limit (for the active heap)
+    # [47-36] Actual size (current footprint)
+    # [35-24] Allowed size (current hard max)
+    # [23-12] Objects allocated
+    # [11- 0] Bytes allocated
+    soft_limit = unfloat12((value >> 48) & 0xfff)
+    actual = unfloat12((value >> 36) & 0xfff)
+    allowed = unfloat12((value >> 24) & 0xfff)
+    objs = unfloat12((value >> 12) & 0xfff)
+    bytes = unfloat12(value & 0xfff)
+
+    return ( soft_limit, actual, allowed, objs, bytes )
+
+
+def parseExternalStats(value):
+    """Parse event3 (external allocation stats)"""
+    value = int(value)
+
+    # Report the current external allocation stats and the native heap
+    # summary.
+    #
+    # [63-48] Reserved; must be zero (TODO: put new data in these slots)
+    # [47-36] dlmalloc_footprint
+    # [35-24] mallinfo: total allocated space
+    # [23-12] External byte limit
+    # [11- 0] External bytes allocated
+    footprint = unfloat12((value >> 36) & 0xfff)    # currently disabled
+    total = unfloat12((value >> 24) & 0xfff)        # currently disabled
+    limit = unfloat12((value >> 12) & 0xfff)
+    bytes = unfloat12(value & 0xfff)
+
+    return ( footprint, total, limit, bytes )
+
+
+def handleGcInfo(procFilter, timestamp, pid, values):
+    """Handle a single dvm_gc_info event"""
+
+    pid = int(pid)
+
+    global_info = parseGlobalInfo(values[0])
+
+    if len(procFilter) > 0:
+        if global_info[0] != procFilter:
+            return
+
+    heap_stats = parseAggHeapStats(values[1])
+    zygote = parseZygoteStats(values[2])
+    external = parseExternalStats(values[3])
+
+    print "%s %s(%d) softlim=%dKB, extlim=%dKB, extalloc=%dKB" % \
+            (timestamp, global_info[0], pid, zygote[0]/1024, external[2]/1024, external[3]/1024)
+
+    if DEBUG:
+        # print "RAW: %s %s (%s,%s,%s,%s)" % \
+        #        (timestamp, pid, values[0], values[1], values[2], values[3])
+
+        print "+ id=\"%s\" time=%d freed=%d" % (global_info[0], global_info[1], global_info[2])
+        print "+  freed=%d foot=%d allow=%d objs=%d bytes=%d" % \
+                (heap_stats[0], heap_stats[1], heap_stats[2], heap_stats[3], heap_stats[4])
+        print "+  soft=%d act=%d allow=%d objs=%d bytes=%d" % \
+                (zygote[0], zygote[1], zygote[2], zygote[3], zygote[4])
+        print "+  foot=%d total=%d limit=%d alloc=%d" % \
+                (external[0], external[1], external[2], external[3])
+
+    print "  freed %d objects / %d bytes in %dms" % \
+            (heap_stats[0], global_info[2], global_info[1])
+
+
+def filterInput(logPipe, processFilter):
+    """Loop until EOF, pulling out GC events"""
+
+    # 04-29 20:31:00.334 I/dvm_gc_info(   69): [8320808730292729543,-8916699241518090181,-4006371297196337158,8165229]
+    gc_info_re = re.compile(r"""
+        (\d+-\d+\ \d+:\d+:\d+)\.\d+     # extract the date (#1), ignoring ms
+        .*                              # filler, usually " I/"
+        dvm_gc_info                     # only interested in GC info lines
+        \(\s*(\d+)\)                    # extract the pid (#2)
+        :\ \[                           # filler
+        ([0-9-]+),([0-9-]+),([0-9-]+),([0-9-]+) # four values, may be negative
+        \].*                            # junk to end of line
+        """, re.VERBOSE)
+
+    while True:
+        line = logPipe.readline()
+        if not line:
+            print "EOF hit"
+            return
+
+        match = gc_info_re.match(line)
+        if not match:
+            #print "no match on %s" % line.strip()
+            continue
+        else:
+            handleGcInfo(processFilter, match.group(1), match.group(2), ( match.group(3), \
+                    match.group(4), match.group(5), match.group(6) ) )
+
+def PrintUsage():
+  print "usage: %s [-p procFilter] [-d]" % sys.argv[0]
+
+
+def start():
+    """Entry point"""
+
+    global DEBUG
+
+    procFilter = ""
+
+    opts, args = getopt.getopt(sys.argv[1:], "hdp:")
+
+    for opt, val in opts:
+        if opt == "-h":
+            PrintUsage()
+            sys.exit(2)
+        elif opt == "-p":
+            procFilter = val
+        elif opt == "-d":
+            DEBUG = True
+
+    print "procfilter = %s" % procFilter
+    print "DEBUG = %s" % DEBUG
+
+    # launch a logcat and read from it
+    command = 'adb logcat -v time -b events'
+    logPipe = os.popen(command)
+
+
+    try:
+        filterInput(logPipe, procFilter)
+    except KeyboardInterrupt, err:
+        print "Stopping on keyboard interrupt."
+
+    logPipe.close()
+
+
+start()
+
diff --git a/vm/Android.mk b/vm/Android.mk
index f3eed3f..5c276aa 100644
--- a/vm/Android.mk
+++ b/vm/Android.mk
@@ -12,262 +12,71 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+
 #
-# Android.mk for Dalvik VM.  If you enable or disable optional features here,
+# Android.mk for Dalvik VM.
+#
+# This makefile builds both for host and target, and so the very large
+# swath of common definitions are factored out into a separate file to
+# minimize duplication.
+#
+# Also, if you enable or disable optional features here (or Dvm.mk),
 # rebuild the VM with "make clean-libdvm && make -j4 libdvm".
 #
+
 LOCAL_PATH:= $(call my-dir)
+
+#
+# Build for the target (device).
+#
+
 include $(CLEAR_VARS)
 
+# Variables used in the included Dvm.mk.
+dvm_os := $(TARGET_OS)
+dvm_arch := $(TARGET_ARCH)
+dvm_arch_variant := $(TARGET_ARCH_VARIANT)
+dvm_simulator := $(TARGET_SIMULATOR)
 
-#
-# Compiler defines.
-#
-LOCAL_CFLAGS += -fstrict-aliasing -Wstrict-aliasing=2 -fno-align-jumps
+include $(LOCAL_PATH)/Dvm.mk
 
-#
-# Optional features.  These may impact the size or performance of the VM.
-#
-LOCAL_CFLAGS += -DWITH_PROFILER -DWITH_DEBUGGER
-
-# 0=full cache, 1/2=reduced, 3=no cache
-LOCAL_CFLAGS += -DDVM_RESOLVER_CACHE=0
-
-ifeq ($(WITH_DEADLOCK_PREDICTION),true)
-  LOCAL_CFLAGS += -DWITH_DEADLOCK_PREDICTION
-  WITH_MONITOR_TRACKING := true
-endif
-ifeq ($(WITH_MONITOR_TRACKING),true)
-  LOCAL_CFLAGS += -DWITH_MONITOR_TRACKING
-endif
-
-# Make DEBUG_DALVIK_VM default to true when building the simulator.
-ifeq ($(TARGET_SIMULATOR),true)
-  ifeq ($(strip $(DEBUG_DALVIK_VM)),)
-    DEBUG_DALVIK_VM := true
-  endif
-endif
-
-ifeq ($(strip $(DEBUG_DALVIK_VM)),true)
-  #
-  # "Debug" profile:
-  # - debugger enabled
-  # - profiling enabled
-  # - tracked-reference verification enabled
-  # - allocation limits enabled
-  # - GDB helpers enabled
-  # - LOGV
-  # - assert()  (NDEBUG is handled in the build system)
-  #
-  LOCAL_CFLAGS += -DWITH_INSTR_CHECKS -DWITH_EXTRA_OBJECT_VALIDATION
-  LOCAL_CFLAGS += -DWITH_TRACKREF_CHECKS
-  LOCAL_CFLAGS += -DWITH_ALLOC_LIMITS
-  #LOCAL_CFLAGS += -DCHECK_MUTEX
-  #LOCAL_CFLAGS += -DPROFILE_FIELD_ACCESS
-  LOCAL_CFLAGS += -DDVM_SHOW_EXCEPTION=3
-  # add some extra stuff to make it easier to examine with GDB
-  LOCAL_CFLAGS += -DEASY_GDB
-else  # !DALVIK_VM_DEBUG
-  #
-  # "Performance" profile:
-  # - all development features disabled
-  # - compiler optimizations enabled (redundant for "release" builds)
-  # - (debugging and profiling still enabled)
-  #
-  #LOCAL_CFLAGS += -DNDEBUG -DLOG_NDEBUG=1
-  # "-O2" is redundant for device (release) but useful for sim (debug)
-  #LOCAL_CFLAGS += -O2 -Winline
-  LOCAL_CFLAGS += -DDVM_SHOW_EXCEPTION=1
-  # if you want to try with assertions on the device, add:
-  #LOCAL_CFLAGS += -UNDEBUG -DDEBUG=1 -DLOG_NDEBUG=1 -DWITH_DALVIK_ASSERT
-endif  # !DALVIK_VM_DEBUG
-
-# bug hunting: checksum and verify interpreted stack when making JNI calls
-#LOCAL_CFLAGS += -DWITH_JNI_STACK_CHECK
-
-LOCAL_SRC_FILES := \
-	AllocTracker.c \
-	AtomicCache.c \
-	CheckJni.c \
-	Ddm.c \
-	Debugger.c \
-	DvmDex.c \
-	Exception.c \
-	Hash.c \
-	Init.c \
-	InlineNative.c.arm \
-	Inlines.c \
-	Intern.c \
-	Jni.c \
-	JarFile.c \
-	LinearAlloc.c \
-	Misc.c.arm \
-	Native.c \
-	PointerSet.c \
-	Profile.c \
-	Properties.c \
-	RawDexFile.c \
-	ReferenceTable.c \
-	SignalCatcher.c \
-	StdioConverter.c \
-	Sync.c \
-	Thread.c \
-	UtfString.c \
-	alloc/clz.c.arm \
-	alloc/Alloc.c \
-	alloc/HeapBitmap.c.arm \
-	alloc/HeapDebug.c \
-	alloc/HeapSource.c \
-	alloc/HeapTable.c \
-	alloc/HeapWorker.c \
-	alloc/Heap.c.arm \
-	alloc/MarkSweep.c.arm \
-	alloc/DdmHeap.c \
-	analysis/CodeVerify.c \
-	analysis/DexOptimize.c \
-	analysis/DexVerify.c \
-	analysis/ReduceConstants.c \
-	analysis/RegisterMap.c \
-	analysis/VerifySubs.c \
-	interp/Interp.c.arm \
-	interp/Stack.c \
-	jdwp/ExpandBuf.c \
-	jdwp/JdwpAdb.c \
-	jdwp/JdwpConstants.c \
-	jdwp/JdwpEvent.c \
-	jdwp/JdwpHandler.c \
-	jdwp/JdwpMain.c \
-	jdwp/JdwpSocket.c \
-	mterp/Mterp.c.arm \
-	mterp/out/InterpC-portstd.c.arm \
-	mterp/out/InterpC-portdbg.c.arm \
-	native/InternalNative.c \
-	native/dalvik_system_DexFile.c \
-	native/dalvik_system_VMDebug.c \
-	native/dalvik_system_VMRuntime.c \
-	native/dalvik_system_VMStack.c \
-	native/dalvik_system_Zygote.c \
-	native/java_lang_Class.c \
-	native/java_lang_Object.c \
-	native/java_lang_Runtime.c \
-	native/java_lang_String.c \
-	native/java_lang_System.c \
-	native/java_lang_SystemProperties.c \
-	native/java_lang_Throwable.c \
-	native/java_lang_VMClassLoader.c \
-	native/java_lang_VMThread.c \
-	native/java_lang_reflect_AccessibleObject.c \
-	native/java_lang_reflect_Array.c \
-	native/java_lang_reflect_Constructor.c \
-	native/java_lang_reflect_Field.c \
-	native/java_lang_reflect_Method.c \
-	native/java_lang_reflect_Proxy.c \
-	native/java_security_AccessController.c \
-	native/java_util_concurrent_atomic_AtomicLong.c \
-	native/org_apache_harmony_dalvik_NativeTestTarget.c \
-	native/org_apache_harmony_dalvik_ddmc_DdmServer.c \
-	native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.c \
-	native/sun_misc_Unsafe.c \
-	oo/AccessCheck.c \
-	oo/Array.c \
-	oo/Class.c \
-	oo/Object.c \
-	oo/Resolve.c \
-	oo/TypeCheck.c \
-	reflect/Annotation.c \
-	reflect/Proxy.c \
-	reflect/Reflect.c \
-	test/TestHash.c
-
-WITH_HPROF := $(strip $(WITH_HPROF))
-ifeq ($(WITH_HPROF),)
-  WITH_HPROF := true
-endif
-ifeq ($(WITH_HPROF),true)
-  LOCAL_SRC_FILES += \
-	hprof/Hprof.c \
-	hprof/HprofClass.c \
-	hprof/HprofHeap.c \
-	hprof/HprofOutput.c \
-	hprof/HprofString.c
-  LOCAL_CFLAGS += -DWITH_HPROF=1
-
-  ifeq ($(strip $(WITH_HPROF_UNREACHABLE)),true)
-    LOCAL_CFLAGS += -DWITH_HPROF_UNREACHABLE=1
-  endif
-
-  ifeq ($(strip $(WITH_HPROF_STACK)),true)
-    LOCAL_SRC_FILES += \
-	hprof/HprofStack.c \
-	hprof/HprofStackFrame.c
-    LOCAL_CFLAGS += -DWITH_HPROF_STACK=1
-  endif # WITH_HPROF_STACK
-endif   # WITH_HPROF
-
-ifeq ($(strip $(DVM_TRACK_HEAP_MARKING)),true)
-  LOCAL_CFLAGS += -DDVM_TRACK_HEAP_MARKING=1
-endif
-
-LOCAL_C_INCLUDES += \
-	$(JNI_H_INCLUDE) \
-	dalvik \
-	dalvik/vm \
-	external/zlib \
-	$(KERNEL_HEADERS)
-
-
-ifeq ($(TARGET_SIMULATOR),true)
-  LOCAL_LDLIBS += -lpthread -ldl
-  ifeq ($(HOST_OS),linux)
-    # need this for clock_gettime() in profiling
-    LOCAL_LDLIBS += -lrt
-  endif
-else
-  LOCAL_SHARED_LIBRARIES += libdl
-endif
-
-ifeq ($(TARGET_ARCH),arm)
-  LOCAL_SRC_FILES += \
-		arch/arm/CallOldABI.S \
-		arch/arm/CallEABI.S \
-		arch/arm/HintsEABI.c
-  # TODO: select sources for ARMv4 vs. ARMv5TE
-  LOCAL_SRC_FILES += \
-		mterp/out/InterpC-armv5te.c.arm \
-		mterp/out/InterpAsm-armv5te.S
-  LOCAL_SHARED_LIBRARIES += libdl
-else
-  ifeq ($(TARGET_ARCH),x86)
-    LOCAL_SRC_FILES += \
-		arch/x86/Call386ABI.S \
-		arch/x86/Hints386ABI.c
-    LOCAL_SRC_FILES += \
-		mterp/out/InterpC-x86.c \
-		mterp/out/InterpAsm-x86.S
-  else
-	# unknown architecture, try to use FFI
-    LOCAL_C_INCLUDES += external/libffi/$(TARGET_OS)-$(TARGET_ARCH)
-    LOCAL_SRC_FILES += \
-		arch/generic/Call.c \
-		arch/generic/Hints.c
-    LOCAL_SHARED_LIBRARIES += libffi
-	
-    LOCAL_SRC_FILES += \
-		mterp/out/InterpC-allstubs.c \
-		mterp/out/InterpAsm-allstubs.S
-  endif
-endif
-
+# liblog and libcutils are shared for target.
+LOCAL_SHARED_LIBRARIES += \
+	liblog libcutils
 
 LOCAL_MODULE := libdvm
 
-LOCAL_SHARED_LIBRARIES += \
-	liblog \
-	libcutils \
-	libnativehelper \
-	libz
-
-LOCAL_STATIC_LIBRARIES += \
-	libdex
-
 include $(BUILD_SHARED_LIBRARY)
+
+
+#
+# Build for the host.
+#
+
+ifeq ($(WITH_HOST_DALVIK),true)
+
+    include $(CLEAR_VARS)
+
+    # Variables used in the included Dvm.mk.
+    dvm_os := $(HOST_OS)
+    dvm_arch := $(HOST_ARCH)
+    dvm_arch_variant := $(HOST_ARCH_VARIANT)
+    dvm_simulator := false
+
+    include $(LOCAL_PATH)/Dvm.mk
+
+    # liblog and libcutils are static for host.
+    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))
+
+    LOCAL_MODULE := libdvm-host
+
+    include $(BUILD_HOST_SHARED_LIBRARY)
+
+endif
diff --git a/vm/CheckJni.c b/vm/CheckJni.c
index b17d0de..bc90527 100644
--- a/vm/CheckJni.c
+++ b/vm/CheckJni.c
@@ -35,13 +35,155 @@
 
 #include <zlib.h>
 
+static void abortMaybe(void);       // fwd
+
+
+/*
+ * ===========================================================================
+ *      JNI call bridge wrapper
+ * ===========================================================================
+ */
+
+/*
+ * Check the result of a native method call that returns an object reference.
+ *
+ * The primary goal here is to verify that native code is returning the
+ * correct type of object.  If it's declared to return a String but actually
+ * returns a byte array, things will fail in strange ways later on.
+ *
+ * This can be a fairly expensive operation, since we have to look up the
+ * return type class by name in method->clazz' class loader.  We take a
+ * shortcut here and allow the call to succeed if the descriptor strings
+ * match.  This will allow some false-positives when a class is redefined
+ * by a class loader, but that's rare enough that it doesn't seem worth
+ * testing for.
+ *
+ * At this point, pResult->l has already been converted to an object pointer.
+ */
+static void checkCallCommon(const u4* args, JValue* pResult,
+    const Method* method, Thread* self)
+{
+    assert(pResult->l != NULL);
+    Object* resultObj = (Object*) pResult->l;
+    ClassObject* objClazz = resultObj->clazz;
+
+    /*
+     * Make sure that pResult->l is an instance of the type this
+     * method was expected to return.
+     */
+    const char* declType = dexProtoGetReturnType(&method->prototype);
+    const char* objType = objClazz->descriptor;
+    if (strcmp(declType, objType) == 0) {
+        /* names match; ignore class loader issues and allow it */
+        LOGV("Check %s.%s: %s io %s (FAST-OK)\n",
+            method->clazz->descriptor, method->name, objType, declType);
+    } else {
+        /*
+         * Names didn't match.  We need to resolve declType in the context
+         * of method->clazz->classLoader, and compare the class objects
+         * for equality.
+         *
+         * Since we're returning an instance of declType, it's safe to
+         * assume that it has been loaded and initialized (or, for the case
+         * of an array, generated), so we can just look for it in the
+         * loaded-classes list.
+         */
+        ClassObject* declClazz;
+
+        declClazz = dvmLookupClass(declType, method->clazz->classLoader, false);
+        if (declClazz == NULL) {
+            LOGW("JNI WARNING: method declared to return '%s' returned '%s'\n",
+                declType, objType);
+            LOGW("             failed in %s.%s ('%s' not found)\n",
+                method->clazz->descriptor, method->name, declType);
+            abortMaybe();
+            return;
+        }
+        if (!dvmInstanceof(objClazz, declClazz)) {
+            LOGW("JNI WARNING: method declared to return '%s' returned '%s'\n",
+                declType, objType);
+            LOGW("             failed in %s.%s\n",
+                method->clazz->descriptor, method->name);
+            abortMaybe();
+            return;
+        } else {
+            LOGV("Check %s.%s: %s io %s (SLOW-OK)\n",
+                method->clazz->descriptor, method->name, objType, declType);
+        }
+    }
+}
+
+/*
+ * Determine if we need to check the return type coming out of the call.
+ *
+ * (We don't do this at the top of checkCallCommon() because this is on
+ * the critical path for native method calls.)
+ */
+static inline bool callNeedsCheck(const u4* args, JValue* pResult,
+    const Method* method, Thread* self)
+{
+    return (method->shorty[0] == 'L' && !dvmCheckException(self) &&
+            pResult->l != NULL);
+}
+
+/*
+ * Check a call into native code.
+ */
+void dvmCheckCallJNIMethod_general(const u4* args, JValue* pResult,
+    const Method* method, Thread* self)
+{
+    dvmCallJNIMethod_general(args, pResult, method, self);
+    if (callNeedsCheck(args, pResult, method, self))
+        checkCallCommon(args, pResult, method, self);
+}
+
+/*
+ * Check a synchronized call into native code.
+ */
+void dvmCheckCallJNIMethod_synchronized(const u4* args, JValue* pResult,
+    const Method* method, Thread* self)
+{
+    dvmCallJNIMethod_synchronized(args, pResult, method, self);
+    if (callNeedsCheck(args, pResult, method, self))
+        checkCallCommon(args, pResult, method, self);
+}
+
+/*
+ * Check a virtual call with no reference arguments (other than "this").
+ */
+void dvmCheckCallJNIMethod_virtualNoRef(const u4* args, JValue* pResult,
+    const Method* method, Thread* self)
+{
+    dvmCallJNIMethod_virtualNoRef(args, pResult, method, self);
+    if (callNeedsCheck(args, pResult, method, self))
+        checkCallCommon(args, pResult, method, self);
+}
+
+/*
+ * Check a static call with no reference arguments (other than "clazz").
+ */
+void dvmCheckCallJNIMethod_staticNoRef(const u4* args, JValue* pResult,
+    const Method* method, Thread* self)
+{
+    dvmCallJNIMethod_staticNoRef(args, pResult, method, self);
+    if (callNeedsCheck(args, pResult, method, self))
+        checkCallCommon(args, pResult, method, self);
+}
+
+
+/*
+ * ===========================================================================
+ *      JNI function helpers
+ * ===========================================================================
+ */
+
 #define JNI_ENTER()     dvmChangeStatus(NULL, THREAD_RUNNING)
 #define JNI_EXIT()      dvmChangeStatus(NULL, THREAD_NATIVE)
 
 #define BASE_ENV(_env)  (((JNIEnvExt*)_env)->baseFuncTable)
 #define BASE_VM(_vm)    (((JavaVMExt*)_vm)->baseFuncTable)
 
-#define kRedundantDirectBufferTest true
+#define kRedundantDirectBufferTest false
 
 /*
  * Flags passed into checkThread().
@@ -84,8 +226,8 @@
 #define CHECK_VMEXIT(_vm, _hasmeth)                                         \
     do { JNI_TRACE(false, _hasmeth); } while(false)
 
-#define CHECK_FIELD_TYPE(_obj, _fieldid, _prim, _isstatic)                  \
-    checkFieldType(_obj, _fieldid, _prim, _isstatic, __FUNCTION__)
+#define CHECK_FIELD_TYPE(_env, _obj, _fieldid, _prim, _isstatic)            \
+    checkFieldType(_env, _obj, _fieldid, _prim, _isstatic, __FUNCTION__)
 #define CHECK_INST_FIELD_ID(_env, _obj, _fieldid)                           \
     checkInstanceFieldID(_env, _obj, _fieldid, __FUNCTION__)
 #define CHECK_CLASS(_env, _clazz)                                           \
@@ -145,7 +287,7 @@
 /*
  * Abort if we are configured to bail out on JNI warnings.
  */
-static inline void abortMaybe()
+static void abortMaybe(void)
 {
     JavaVMExt* vm = (JavaVMExt*) gDvm.vmList;
     if (vm->warnError) {
@@ -186,7 +328,8 @@
      */
     if (threadEnv == NULL) {
         LOGE("JNI ERROR: non-VM thread making JNI calls\n");
-        // don't set printWarn
+        // don't set printWarn -- it'll try to call showLocation()
+        dvmAbort();
     } else if ((JNIEnvExt*) env != threadEnv) {
         if (dvmThreadSelf()->threadId != threadEnv->envThreadId) {
             LOGE("JNI: threadEnv != thread->env?\n");
@@ -202,7 +345,8 @@
         //    "invalid use of JNI env ptr");
     } else if (((JNIEnvExt*) env)->self != dvmThreadSelf()) {
         /* correct JNIEnv*; make sure the "self" pointer is correct */
-        LOGE("JNI: env->self != thread-self\n");
+        LOGE("JNI ERROR: env->self != thread-self (%p vs. %p)\n",
+            ((JNIEnvExt*) env)->self, dvmThreadSelf());
         dvmAbort();
     }
 
@@ -244,12 +388,6 @@
         printException = true;
     }
 
-    if (false) {
-        Thread* self = dvmThreadSelf();
-        LOGW("NOW: %d\n",
-            (int) dvmReferenceTableEntries(&self->internalLocalRefTable));
-    }
-
     if (printWarn)
         showLocation(dvmGetCurrentJNIMethod(), func);
     if (printException) {
@@ -266,8 +404,8 @@
  *
  * Works for both static and instance fields.
  */
-static void checkFieldType(jobject obj, jfieldID fieldID, PrimitiveType prim,
-    bool isStatic, const char* func)
+static void checkFieldType(JNIEnv* env, jobject jobj, jfieldID fieldID,
+    PrimitiveType prim, bool isStatic, const char* func)
 {
     static const char* primNameList[] = {
         "Object/Array", "boolean", "char", "float", "double",
@@ -283,10 +421,11 @@
     }
 
     if (field->signature[0] == 'L' || field->signature[0] == '[') {
+        Object* obj = dvmDecodeIndirectRef(env, jobj);
         if (obj != NULL) {
             ClassObject* fieldClass =
                 dvmFindLoadedClass(field->signature);
-            ClassObject* objClass = ((Object*)obj)->clazz;
+            ClassObject* objClass = obj->clazz;
 
             assert(fieldClass != NULL);
             assert(objClass != NULL);
@@ -318,27 +457,32 @@
 }
 
 /*
- * Verify that "obj" is a valid object, and that it's an object that JNI
+ * Verify that "jobj" is a valid object, and that it's an object that JNI
  * is allowed to know about.  We allow NULL references.
  *
  * Switches to "running" mode before performing checks.
  */
-static void checkObject(JNIEnv* env, jobject obj, const char* func)
+static void checkObject(JNIEnv* env, jobject jobj, const char* func)
 {
     UNUSED_PARAMETER(env);
     bool printWarn = false;
 
-    if (obj == NULL)
+    if (jobj == NULL)
         return;
 
     JNI_ENTER();
-    if (!dvmIsValidObject(obj)) {
-        LOGW("JNI WARNING: native code passing in bad object %p (%s)\n",
-            obj, func);
+
+    if (dvmGetJNIRefType(env, jobj) == JNIInvalidRefType) {
+        LOGW("JNI WARNING: %p is not a valid JNI reference\n", jobj);
         printWarn = true;
-    } else if (dvmGetJNIRefType(obj) == JNIInvalidRefType) {
-        LOGW("JNI WARNING: ref %p should not be visible to native code\n", obj);
-        printWarn = true;
+    } else {
+        Object* obj = dvmDecodeIndirectRef(env, jobj);
+
+        if (obj == NULL || !dvmIsValidObject(obj)) {
+            LOGW("JNI WARNING: native code passing in bad object %p %p (%s)\n",
+                jobj, obj, func);
+            printWarn = true;
+        }
     }
 
     if (printWarn) {
@@ -365,7 +509,7 @@
     JNI_ENTER();
     bool printWarn = false;
 
-    ClassObject* clazz = (ClassObject*) jclazz;
+    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
 
     if (clazz == NULL) {
         LOGW("JNI WARNING: received null jclass\n");
@@ -391,22 +535,28 @@
  *
  * Since we're dealing with objects, switch to "running" mode.
  */
-static void checkString(JNIEnv* env, jstring str, const char* func)
+static void checkString(JNIEnv* env, jstring jstr, const char* func)
 {
     JNI_ENTER();
     bool printWarn = false;
 
-    Object* obj = (Object*) str;
+    Object* obj = dvmDecodeIndirectRef(env, jstr);
 
     if (obj == NULL) {
         LOGW("JNI WARNING: received null jstring (%s)\n", func);
         printWarn = true;
     } else if (obj->clazz != gDvm.classJavaLangString) {
+        /*
+         * TODO: we probably should test dvmIsValidObject first, because
+         * this will crash if "obj" is non-null but pointing to an invalid
+         * memory region.  However, the "is valid" test is a little slow,
+         * we're doing it again over in checkObject().
+         */
         if (dvmIsValidObject(obj))
-            LOGW("JNI WARNING: jstring points to non-string object (%s)\n",
-                func);
+            LOGW("JNI WARNING: jstring %p points to non-string object (%s)\n",
+                jstr, func);
         else
-            LOGW("JNI WARNING: jstring %p is bogus (%s)\n", str, func);
+            LOGW("JNI WARNING: jstring %p is bogus (%s)\n", jstr, func);
         printWarn = true;
     }
     JNI_EXIT();
@@ -414,7 +564,7 @@
     if (printWarn)
         abortMaybe();
     else
-        checkObject(env, str, func);
+        checkObject(env, jstr, func);
 }
 
 /*
@@ -531,21 +681,22 @@
  *
  * Since we're dealing with objects, switch to "running" mode.
  */
-static void checkArray(JNIEnv* env, jarray array, const char* func)
+static void checkArray(JNIEnv* env, jarray jarr, const char* func)
 {
     JNI_ENTER();
     bool printWarn = false;
 
-    Object* obj = (Object*) array;
+    Object* obj = dvmDecodeIndirectRef(env, jarr);
 
     if (obj == NULL) {
         LOGW("JNI WARNING: received null array (%s)\n", func);
         printWarn = true;
     } else if (obj->clazz->descriptor[0] != '[') {
         if (dvmIsValidObject(obj))
-            LOGW("JNI WARNING: jarray points to non-array object\n");
+            LOGW("JNI WARNING: jarray %p points to non-array object (%s)\n",
+                jarr, obj->clazz->descriptor);
         else
-            LOGW("JNI WARNING: jarray is bogus (%p)\n", array);
+            LOGW("JNI WARNING: jarray %p is bogus\n", jarr);
         printWarn = true;
     }
 
@@ -554,7 +705,7 @@
     if (printWarn)
         abortMaybe();
     else
-        checkObject(env, array, func);
+        checkObject(env, jarr, func);
 }
 
 /*
@@ -626,16 +777,17 @@
 /*
  * Verify that this static field ID is valid for this class.
  */
-static void checkStaticFieldID(JNIEnv* env, jclass clazz, jfieldID fieldID)
+static void checkStaticFieldID(JNIEnv* env, jclass jclazz, jfieldID fieldID)
 {
-    StaticField* base = ((ClassObject*) clazz)->sfields;
-    int fieldCount = ((ClassObject*) clazz)->sfieldCount;
+    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
+    StaticField* base = clazz->sfields;
+    int fieldCount = clazz->sfieldCount;
 
     if ((StaticField*) fieldID < base ||
         (StaticField*) fieldID >= base + fieldCount)
     {
         LOGW("JNI WARNING: static fieldID %p not valid for class %s\n",
-            fieldID, ((ClassObject*) clazz)->descriptor);
+            fieldID, clazz->descriptor);
         LOGW("             base=%p count=%d\n", base, fieldCount);
         abortMaybe();
     }
@@ -644,18 +796,19 @@
 /*
  * Verify that this instance field ID is valid for this object.
  */
-static void checkInstanceFieldID(JNIEnv* env, jobject obj, jfieldID fieldID,
+static void checkInstanceFieldID(JNIEnv* env, jobject jobj, jfieldID fieldID,
     const char* func)
 {
     JNI_ENTER();
 
-    if (obj == NULL) {
+    if (jobj == NULL) {
         LOGW("JNI WARNING: invalid null object (%s)\n", func);
         abortMaybe();
         goto bail;
     }
 
-    ClassObject* clazz = ((Object*)obj)->clazz;
+    Object* obj = dvmDecodeIndirectRef(env, jobj);
+    ClassObject* clazz = obj->clazz;
 
     /*
      * Check this class and all of its superclasses for a matching field.
@@ -672,7 +825,7 @@
     }
 
     LOGW("JNI WARNING: inst fieldID %p not valid for class %s\n",
-        fieldID, ((Object*)obj)->clazz->descriptor);
+        fieldID, obj->clazz->descriptor);
     abortMaybe();
 
 bail:
@@ -845,7 +998,7 @@
     void* originalPtr = (void*) pExtra->originalPtr;
     size_t len = pExtra->originalLen;
 
-    memset(dataBuf, len, 0xdd);
+    memset(dataBuf, 0xdd, len);
     free(fullBuf);
     return originalPtr;
 }
@@ -892,13 +1045,15 @@
  * Create a guarded copy of a primitive array.  Modifications to the copied
  * data are allowed.  Returns a pointer to the copied data.
  */
-static void* createGuardedPACopy(const ArrayObject* array, jboolean* isCopy)
+static void* createGuardedPACopy(JNIEnv* env, const jarray jarr,
+    jboolean* isCopy)
 {
-    PrimitiveType primType = array->obj.clazz->elementClass->primitiveType;
-    int len = array->length * dvmPrimitiveTypeWidth(primType);
+    ArrayObject* arrObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
+    PrimitiveType primType = arrObj->obj.clazz->elementClass->primitiveType;
+    int len = arrObj->length * dvmPrimitiveTypeWidth(primType);
     void* result;
 
-    result = createGuardedCopy(array->contents, len, true);
+    result = createGuardedCopy(arrObj->contents, len, true);
 
     if (isCopy != NULL)
         *isCopy = JNI_TRUE;
@@ -910,9 +1065,11 @@
  * Perform the array "release" operation, which may or may not copy data
  * back into the VM, and may or may not release the underlying storage.
  */
-static void* releaseGuardedPACopy(ArrayObject* array, void* dataBuf, int mode)
+static void* releaseGuardedPACopy(JNIEnv* env, jarray jarr, void* dataBuf,
+    int mode)
 {
-    PrimitiveType primType = array->obj.clazz->elementClass->primitiveType;
+    ArrayObject* arrObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
+    PrimitiveType primType = arrObj->obj.clazz->elementClass->primitiveType;
     //int len = array->length * dvmPrimitiveTypeWidth(primType);
     bool release, copyBack;
     u1* result;
@@ -943,7 +1100,7 @@
 
     if (copyBack) {
         size_t len = getGuardedCopyOriginalLen(dataBuf);
-        memcpy(array->contents, dataBuf, len);
+        memcpy(arrObj->contents, dataBuf, len);
     }
 
     if (release) {
@@ -1143,11 +1300,22 @@
     return result;
 }
 
-static void Check_DeleteGlobalRef(JNIEnv* env, jobject localRef)
+static void Check_DeleteGlobalRef(JNIEnv* env, jobject globalRef)
 {
     CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
-    CHECK_OBJECT(env, localRef);
-    BASE_ENV(env)->DeleteGlobalRef(env, localRef);
+    CHECK_OBJECT(env, globalRef);
+#ifdef USE_INDIRECT_REF
+    if (globalRef != NULL &&
+        dvmGetJNIRefType(env, globalRef) != JNIGlobalRefType)
+    {
+        LOGW("JNI WARNING: DeleteGlobalRef on non-global %p (type=%d)\n",
+            globalRef, dvmGetJNIRefType(env, globalRef));
+        abortMaybe();
+    } else
+#endif
+    {
+        BASE_ENV(env)->DeleteGlobalRef(env, globalRef);
+    }
     CHECK_EXIT(env);
 }
 
@@ -1161,11 +1329,22 @@
     return result;
 }
 
-static void Check_DeleteLocalRef(JNIEnv* env, jobject globalRef)
+static void Check_DeleteLocalRef(JNIEnv* env, jobject localRef)
 {
     CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
-    CHECK_OBJECT(env, globalRef);
-    BASE_ENV(env)->DeleteLocalRef(env, globalRef);
+    CHECK_OBJECT(env, localRef);
+#ifdef USE_INDIRECT_REF
+    if (localRef != NULL &&
+        dvmGetJNIRefType(env, localRef) != JNILocalRefType)
+    {
+        LOGW("JNI WARNING: DeleteLocalRef on non-local %p (type=%d)\n",
+            localRef, dvmGetJNIRefType(env, localRef));
+        abortMaybe();
+    } else
+#endif
+    {
+        BASE_ENV(env)->DeleteLocalRef(env, localRef);
+    }
     CHECK_EXIT(env);
 }
 
@@ -1308,7 +1487,7 @@
     return result;
 }
 
-#define GET_STATIC_TYPE_FIELD(_ctype, _jname, _isref)                       \
+#define GET_STATIC_TYPE_FIELD(_ctype, _jname)                               \
     static _ctype Check_GetStatic##_jname##Field(JNIEnv* env, jclass clazz, \
         jfieldID fieldID)                                                   \
     {                                                                       \
@@ -1321,15 +1500,15 @@
         CHECK_EXIT(env);                                                    \
         return result;                                                      \
     }
-GET_STATIC_TYPE_FIELD(jobject, Object, true);
-GET_STATIC_TYPE_FIELD(jboolean, Boolean, false);
-GET_STATIC_TYPE_FIELD(jbyte, Byte, false);
-GET_STATIC_TYPE_FIELD(jchar, Char, false);
-GET_STATIC_TYPE_FIELD(jshort, Short, false);
-GET_STATIC_TYPE_FIELD(jint, Int, false);
-GET_STATIC_TYPE_FIELD(jlong, Long, false);
-GET_STATIC_TYPE_FIELD(jfloat, Float, false);
-GET_STATIC_TYPE_FIELD(jdouble, Double, false);
+GET_STATIC_TYPE_FIELD(jobject, Object);
+GET_STATIC_TYPE_FIELD(jboolean, Boolean);
+GET_STATIC_TYPE_FIELD(jbyte, Byte);
+GET_STATIC_TYPE_FIELD(jchar, Char);
+GET_STATIC_TYPE_FIELD(jshort, Short);
+GET_STATIC_TYPE_FIELD(jint, Int);
+GET_STATIC_TYPE_FIELD(jlong, Long);
+GET_STATIC_TYPE_FIELD(jfloat, Float);
+GET_STATIC_TYPE_FIELD(jdouble, Double);
 
 #define SET_STATIC_TYPE_FIELD(_ctype, _jname, _ftype)                       \
     static void Check_SetStatic##_jname##Field(JNIEnv* env, jclass clazz,   \
@@ -1338,7 +1517,8 @@
         CHECK_ENTER(env, kFlag_Default);                                    \
         CHECK_CLASS(env, clazz);                                            \
         checkStaticFieldID(env, clazz, fieldID);                            \
-        CHECK_FIELD_TYPE((jobject)(u4)value, fieldID, _ftype, true);        \
+        /* "value" arg only used when type == ref */                        \
+        CHECK_FIELD_TYPE(env, (jobject)(u4)value, fieldID, _ftype, true);   \
         BASE_ENV(env)->SetStatic##_jname##Field(env, clazz, fieldID,        \
             value);                                                         \
         CHECK_EXIT(env);                                                    \
@@ -1353,7 +1533,7 @@
 SET_STATIC_TYPE_FIELD(jfloat, Float, PRIM_FLOAT);
 SET_STATIC_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE);
 
-#define GET_TYPE_FIELD(_ctype, _jname, _isref)                              \
+#define GET_TYPE_FIELD(_ctype, _jname)                                      \
     static _ctype Check_Get##_jname##Field(JNIEnv* env, jobject obj,        \
         jfieldID fieldID)                                                   \
     {                                                                       \
@@ -1365,15 +1545,15 @@
         CHECK_EXIT(env);                                                    \
         return result;                                                      \
     }
-GET_TYPE_FIELD(jobject, Object, true);
-GET_TYPE_FIELD(jboolean, Boolean, false);
-GET_TYPE_FIELD(jbyte, Byte, false);
-GET_TYPE_FIELD(jchar, Char, false);
-GET_TYPE_FIELD(jshort, Short, false);
-GET_TYPE_FIELD(jint, Int, false);
-GET_TYPE_FIELD(jlong, Long, false);
-GET_TYPE_FIELD(jfloat, Float, false);
-GET_TYPE_FIELD(jdouble, Double, false);
+GET_TYPE_FIELD(jobject, Object);
+GET_TYPE_FIELD(jboolean, Boolean);
+GET_TYPE_FIELD(jbyte, Byte);
+GET_TYPE_FIELD(jchar, Char);
+GET_TYPE_FIELD(jshort, Short);
+GET_TYPE_FIELD(jint, Int);
+GET_TYPE_FIELD(jlong, Long);
+GET_TYPE_FIELD(jfloat, Float);
+GET_TYPE_FIELD(jdouble, Double);
 
 #define SET_TYPE_FIELD(_ctype, _jname, _ftype)                              \
     static void Check_Set##_jname##Field(JNIEnv* env, jobject obj,          \
@@ -1382,7 +1562,8 @@
         CHECK_ENTER(env, kFlag_Default);                                    \
         CHECK_OBJECT(env, obj);                                             \
         CHECK_INST_FIELD_ID(env, obj, fieldID);                             \
-        CHECK_FIELD_TYPE((jobject)(u4) value, fieldID, _ftype, false);      \
+        /* "value" arg only used when type == ref */                        \
+        CHECK_FIELD_TYPE(env, (jobject)(u4) value, fieldID, _ftype, false); \
         BASE_ENV(env)->Set##_jname##Field(env, obj, fieldID, value);        \
         CHECK_EXIT(env);                                                    \
     }
@@ -1396,8 +1577,7 @@
 SET_TYPE_FIELD(jfloat, Float, PRIM_FLOAT);
 SET_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE);
 
-#define CALL_VIRTUAL(_ctype, _jname, _retfail, _retdecl, _retasgn, _retok,  \
-        _retsig)                                                            \
+#define CALL_VIRTUAL(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig)   \
     static _ctype Check_Call##_jname##Method(JNIEnv* env, jobject obj,      \
         jmethodID methodID, ...)                                            \
     {                                                                       \
@@ -1437,19 +1617,19 @@
         CHECK_EXIT(env);                                                    \
         return _retok;                                                      \
     }
-CALL_VIRTUAL(jobject, Object, NULL, Object* result, result=, result, 'L');
-CALL_VIRTUAL(jboolean, Boolean, 0, jboolean result, result=, result, 'Z');
-CALL_VIRTUAL(jbyte, Byte, 0, jbyte result, result=, result, 'B');
-CALL_VIRTUAL(jchar, Char, 0, jchar result, result=, result, 'C');
-CALL_VIRTUAL(jshort, Short, 0, jshort result, result=, result, 'S');
-CALL_VIRTUAL(jint, Int, 0, jint result, result=, result, 'I');
-CALL_VIRTUAL(jlong, Long, 0, jlong result, result=, result, 'J');
-CALL_VIRTUAL(jfloat, Float, 0.0f, jfloat result, result=, *(float*)&result, 'F');
-CALL_VIRTUAL(jdouble, Double, 0.0, jdouble result, result=, *(double*)&result, 'D');
-CALL_VIRTUAL(void, Void, , , , , 'V');
+CALL_VIRTUAL(jobject, Object, Object* result, result=, result, 'L');
+CALL_VIRTUAL(jboolean, Boolean, jboolean result, result=, result, 'Z');
+CALL_VIRTUAL(jbyte, Byte, jbyte result, result=, result, 'B');
+CALL_VIRTUAL(jchar, Char, jchar result, result=, result, 'C');
+CALL_VIRTUAL(jshort, Short, jshort result, result=, result, 'S');
+CALL_VIRTUAL(jint, Int, jint result, result=, result, 'I');
+CALL_VIRTUAL(jlong, Long, jlong result, result=, result, 'J');
+CALL_VIRTUAL(jfloat, Float, jfloat result, result=, result, 'F');
+CALL_VIRTUAL(jdouble, Double, jdouble result, result=, result, 'D');
+CALL_VIRTUAL(void, Void, , , , 'V');
 
-#define CALL_NONVIRTUAL(_ctype, _jname, _retfail, _retdecl, _retasgn,       \
-        _retok, _retsig)                                                    \
+#define CALL_NONVIRTUAL(_ctype, _jname, _retdecl, _retasgn, _retok,         \
+        _retsig)                                                            \
     static _ctype Check_CallNonvirtual##_jname##Method(JNIEnv* env,         \
         jobject obj, jclass clazz, jmethodID methodID, ...)                 \
     {                                                                       \
@@ -1492,20 +1672,19 @@
         CHECK_EXIT(env);                                                    \
         return _retok;                                                      \
     }
-CALL_NONVIRTUAL(jobject, Object, NULL, Object* result, result=, (Object*)(u4)result, 'L');
-CALL_NONVIRTUAL(jboolean, Boolean, 0, jboolean result, result=, result, 'Z');
-CALL_NONVIRTUAL(jbyte, Byte, 0, jbyte result, result=, result, 'B');
-CALL_NONVIRTUAL(jchar, Char, 0, jchar result, result=, result, 'C');
-CALL_NONVIRTUAL(jshort, Short, 0, jshort result, result=, result, 'S');
-CALL_NONVIRTUAL(jint, Int, 0, jint result, result=, result, 'I');
-CALL_NONVIRTUAL(jlong, Long, 0, jlong result, result=, result, 'J');
-CALL_NONVIRTUAL(jfloat, Float, 0.0f, jfloat result, result=, *(float*)&result, 'F');
-CALL_NONVIRTUAL(jdouble, Double, 0.0, jdouble result, result=, *(double*)&result, 'D');
-CALL_NONVIRTUAL(void, Void, , , , , 'V');
+CALL_NONVIRTUAL(jobject, Object, Object* result, result=, result, 'L');
+CALL_NONVIRTUAL(jboolean, Boolean, jboolean result, result=, result, 'Z');
+CALL_NONVIRTUAL(jbyte, Byte, jbyte result, result=, result, 'B');
+CALL_NONVIRTUAL(jchar, Char, jchar result, result=, result, 'C');
+CALL_NONVIRTUAL(jshort, Short, jshort result, result=, result, 'S');
+CALL_NONVIRTUAL(jint, Int, jint result, result=, result, 'I');
+CALL_NONVIRTUAL(jlong, Long, jlong result, result=, result, 'J');
+CALL_NONVIRTUAL(jfloat, Float, jfloat result, result=, result, 'F');
+CALL_NONVIRTUAL(jdouble, Double, jdouble result, result=, result, 'D');
+CALL_NONVIRTUAL(void, Void, , , , 'V');
 
 
-#define CALL_STATIC(_ctype, _jname, _retfail, _retdecl, _retasgn, _retok,   \
-        _retsig)                                                            \
+#define CALL_STATIC(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig)    \
     static _ctype Check_CallStatic##_jname##Method(JNIEnv* env,             \
         jclass clazz, jmethodID methodID, ...)                              \
     {                                                                       \
@@ -1545,16 +1724,16 @@
         CHECK_EXIT(env);                                                    \
         return _retok;                                                      \
     }
-CALL_STATIC(jobject, Object, NULL, Object* result, result=, (Object*)(u4)result, 'L');
-CALL_STATIC(jboolean, Boolean, 0, jboolean result, result=, result, 'Z');
-CALL_STATIC(jbyte, Byte, 0, jbyte result, result=, result, 'B');
-CALL_STATIC(jchar, Char, 0, jchar result, result=, result, 'C');
-CALL_STATIC(jshort, Short, 0, jshort result, result=, result, 'S');
-CALL_STATIC(jint, Int, 0, jint result, result=, result, 'I');
-CALL_STATIC(jlong, Long, 0, jlong result, result=, result, 'J');
-CALL_STATIC(jfloat, Float, 0.0f, jfloat result, result=, *(float*)&result, 'F');
-CALL_STATIC(jdouble, Double, 0.0, jdouble result, result=, *(double*)&result, 'D');
-CALL_STATIC(void, Void, , , , , 'V');
+CALL_STATIC(jobject, Object, Object* result, result=, result, 'L');
+CALL_STATIC(jboolean, Boolean, jboolean result, result=, result, 'Z');
+CALL_STATIC(jbyte, Byte, jbyte result, result=, result, 'B');
+CALL_STATIC(jchar, Char, jchar result, result=, result, 'C');
+CALL_STATIC(jshort, Short, jshort result, result=, result, 'S');
+CALL_STATIC(jint, Int, jint result, result=, result, 'I');
+CALL_STATIC(jlong, Long, jlong result, result=, result, 'J');
+CALL_STATIC(jfloat, Float, jfloat result, result=, result, 'F');
+CALL_STATIC(jdouble, Double, jdouble result, result=, result, 'D');
+CALL_STATIC(void, Void, , , , 'V');
 
 static jstring Check_NewString(JNIEnv* env, const jchar* unicodeChars,
     jsize len)
@@ -1584,6 +1763,7 @@
     const jchar* result;
     result = BASE_ENV(env)->GetStringChars(env, string, isCopy);
     if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
+        // TODO: fix for indirect
         int len = dvmStringLen(string) * 2;
         result = (const jchar*) createGuardedCopy(result, len, false);
         if (isCopy != NULL)
@@ -1639,6 +1819,7 @@
     const char* result;
     result = BASE_ENV(env)->GetStringUTFChars(env, string, isCopy);
     if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
+        // TODO: fix for indirect
         int len = dvmStringUtf8ByteLen(string) + 1;
         result = (const char*) createGuardedCopy(result, len, false);
         if (isCopy != NULL)
@@ -1741,8 +1922,7 @@
         result = BASE_ENV(env)->Get##_jname##ArrayElements(env,             \
             array, isCopy);                                                 \
         if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {           \
-            result = (_ctype*)                                              \
-                createGuardedPACopy((ArrayObject*) array, isCopy);          \
+            result = (_ctype*) createGuardedPACopy(env, array, isCopy);     \
         }                                                                   \
         CHECK_EXIT(env);                                                    \
         return result;                                                      \
@@ -1757,8 +1937,7 @@
         CHECK_NON_NULL(env, elems);                                         \
         CHECK_RELEASE_MODE(env, mode);                                      \
         if (((JNIEnvExt*)env)->forceDataCopy) {                             \
-            elems = (_ctype*) releaseGuardedPACopy((ArrayObject*) array,    \
-                elems, mode);                                               \
+            elems = (_ctype*) releaseGuardedPACopy(env, array, elems, mode);\
         }                                                                   \
         BASE_ENV(env)->Release##_jname##ArrayElements(env,                  \
             array, elems, mode);                                            \
@@ -1879,7 +2058,7 @@
     void* result;
     result = BASE_ENV(env)->GetPrimitiveArrayCritical(env, array, isCopy);
     if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
-        result = createGuardedPACopy((ArrayObject*) array, isCopy);
+        result = createGuardedPACopy(env, array, isCopy);
     }
     CHECK_EXIT(env);
     return result;
@@ -1893,7 +2072,7 @@
     CHECK_NON_NULL(env, carray);
     CHECK_RELEASE_MODE(env, mode);
     if (((JNIEnvExt*)env)->forceDataCopy) {
-        carray = releaseGuardedPACopy((ArrayObject*) array, carray, mode);
+        carray = releaseGuardedPACopy(env, array, carray, mode);
     }
     BASE_ENV(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
     CHECK_EXIT(env);
@@ -1907,6 +2086,7 @@
     const jchar* result;
     result = BASE_ENV(env)->GetStringCritical(env, string, isCopy);
     if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
+        // TODO: fix for indirect
         int len = dvmStringLen(string) * 2;
         result = (const jchar*) createGuardedCopy(result, len, false);
         if (isCopy != NULL)
@@ -2004,7 +2184,7 @@
          * interfaces.  Note this does not guarantee that it's a direct buffer.
          */
         if (JNI_FALSE == (*env)->IsInstanceOf(env, buf,
-                (jclass) gDvm.classOrgApacheHarmonyNioInternalDirectBuffer))
+                gDvm.jclassOrgApacheHarmonyNioInternalDirectBuffer))
         {
             goto bail;
         }
@@ -2027,10 +2207,12 @@
             goto bail;
         }
 
-        Method* toLong = ((Object*)platformAddr)->clazz->vtable[
-                gDvm.voffOrgApacheHarmonyLuniPlatformPlatformAddress_toLong];
+        jclass platformAddrClass = (*env)->FindClass(env,
+            "org/apache/harmony/luni/platform/PlatformAddress");
+        jmethodID toLongMethod = (*env)->GetMethodID(env, platformAddrClass,
+            "toLong", "()J");
         checkResult = (void*)(u4)(*env)->CallLongMethod(env, platformAddr,
-                (jmethodID)toLong);
+                toLongMethod);
 
     bail:
         if (platformAddr != NULL)
@@ -2425,4 +2607,3 @@
     pVm->baseFuncTable = pVm->funcTable;
     pVm->funcTable = &gCheckInvokeInterface;
 }
-
diff --git a/vm/Common.h b/vm/Common.h
index 8ca5224..d0c021d 100644
--- a/vm/Common.h
+++ b/vm/Common.h
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 /*
  * Common defines for all Dalvik code.
  */
@@ -29,8 +30,8 @@
 #if !defined(NDEBUG) && defined(WITH_DALVIK_ASSERT)
 # undef assert
 # define assert(x) \
-    ((x) ? ((void)0) : (LOGE("ASSERT FAILED (%s:%d): " #x "\n", \
-        __FILE__, __LINE__), *(int*)39=39, 0) )
+    ((x) ? ((void)0) : (LOGE("ASSERT FAILED (%s:%d): %s\n", \
+        __FILE__, __LINE__, #x), *(int*)39=39, 0) )
 #endif
 
 
@@ -96,11 +97,15 @@
 } JValue;
 
 /*
- * Some systems might have this in <stdbool.h>.
+ * The <stdbool.h> definition uses _Bool, a type known to the compiler.
  */
-#ifndef __bool_true_false_are_defined
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>   /* C99 */
+#else
+# ifndef __bool_true_false_are_defined
 typedef enum { false=0, true=!false } bool;
-#define __bool_true_false_are_defined 1
+# define __bool_true_false_are_defined 1
+# endif
 #endif
 
 #define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
diff --git a/vm/Dalvik.h b/vm/Dalvik.h
index 2c7bd7c..054b838 100644
--- a/vm/Dalvik.h
+++ b/vm/Dalvik.h
@@ -44,6 +44,7 @@
 #include "UtfString.h"
 #include "Intern.h"
 #include "ReferenceTable.h"
+#include "IndirectRefTable.h"
 #include "AtomicCache.h"
 #include "Thread.h"
 #include "Ddm.h"
@@ -67,11 +68,15 @@
 #include "LinearAlloc.h"
 #include "analysis/DexVerify.h"
 #include "analysis/DexOptimize.h"
+#include "analysis/RegisterMap.h"
 #include "Init.h"
 #include "libdex/OpCode.h"
 #include "libdex/InstrUtils.h"
 #include "AllocTracker.h"
 #include "PointerSet.h"
+#if defined(WITH_JIT)
+#include "compiler/Compiler.h"
+#endif
 #include "Globals.h"
 #include "reflect/Reflect.h"
 #include "oo/TypeCheck.h"
diff --git a/vm/DalvikVersion.h b/vm/DalvikVersion.h
index 4926fd0..efbb393 100644
--- a/vm/DalvikVersion.h
+++ b/vm/DalvikVersion.h
@@ -24,14 +24,14 @@
  * The version we show to tourists.
  */
 #define DALVIK_MAJOR_VERSION    1
-#define DALVIK_MINOR_VERSION    0
-#define DALVIK_BUG_VERSION      1
+#define DALVIK_MINOR_VERSION    1
+#define DALVIK_BUG_VERSION      0
 
 /*
  * VM build number.  This must change whenever something that affects the
  * way classes load changes, e.g. field ordering or vtable layout.  Changing
  * this guarantees that the optimized form of the DEX file is regenerated.
  */
-#define DALVIK_VM_BUILD         14
+#define DALVIK_VM_BUILD         17
 
 #endif /*_DALVIK_VERSION*/
diff --git a/vm/Debugger.c b/vm/Debugger.c
index 3affa97..4ddf25c 100644
--- a/vm/Debugger.c
+++ b/vm/Debugger.c
@@ -2814,7 +2814,7 @@
         free(desc);
     }
 
-    dvmCallMethodA(self, meth, pReq->obj, &pReq->resultValue,
+    dvmCallMethodA(self, meth, pReq->obj, false, &pReq->resultValue,
         (jvalue*)pReq->argArray);
     pReq->exceptObj = objectToObjectId(dvmGetException(self));
     pReq->resultTag = resultTagFromSignature(meth);
diff --git a/vm/Dvm.mk b/vm/Dvm.mk
new file mode 100644
index 0000000..96f6dac
--- /dev/null
+++ b/vm/Dvm.mk
@@ -0,0 +1,331 @@
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Common definitions for host or target builds of libdvm.
+#
+# If you enable or disable optional features here,
+# rebuild the VM with "make clean-libdvm && make -j4 libdvm".
+#
+
+
+#
+# Compiler defines.
+#
+LOCAL_CFLAGS += -fstrict-aliasing -Wstrict-aliasing=2 -fno-align-jumps
+#LOCAL_CFLAGS += -DUSE_INDIRECT_REF
+
+#
+# Optional features.  These may impact the size or performance of the VM.
+#
+LOCAL_CFLAGS += -DWITH_PROFILER -DWITH_DEBUGGER
+
+# 0=full cache, 1/2=reduced, 3=no cache
+LOCAL_CFLAGS += -DDVM_RESOLVER_CACHE=0
+
+ifeq ($(WITH_DEADLOCK_PREDICTION),true)
+  LOCAL_CFLAGS += -DWITH_DEADLOCK_PREDICTION
+  WITH_MONITOR_TRACKING := true
+endif
+ifeq ($(WITH_MONITOR_TRACKING),true)
+  LOCAL_CFLAGS += -DWITH_MONITOR_TRACKING
+endif
+
+# Make a debugging version when building the simulator (if not told
+# otherwise) and when explicitly asked.
+dvm_make_debug_vm := false
+ifeq ($(strip $(DEBUG_DALVIK_VM)),)
+  ifeq ($(dvm_simulator),true)
+    dvm_make_debug_vm := true
+  endif
+else
+  dvm_make_debug_vm := $(DEBUG_DALVIK_VM)
+endif
+
+ifeq ($(dvm_make_debug_vm),true)
+  #
+  # "Debug" profile:
+  # - debugger enabled
+  # - profiling enabled
+  # - tracked-reference verification enabled
+  # - allocation limits enabled
+  # - GDB helpers enabled
+  # - LOGV
+  # - assert()
+  #
+  LOCAL_CFLAGS += -DWITH_INSTR_CHECKS
+  LOCAL_CFLAGS += -DWITH_EXTRA_OBJECT_VALIDATION
+  LOCAL_CFLAGS += -DWITH_TRACKREF_CHECKS
+  LOCAL_CFLAGS += -DWITH_ALLOC_LIMITS
+  LOCAL_CFLAGS += -DWITH_EXTRA_GC_CHECKS=1
+  #LOCAL_CFLAGS += -DCHECK_MUTEX
+  #LOCAL_CFLAGS += -DPROFILE_FIELD_ACCESS
+  LOCAL_CFLAGS += -DDVM_SHOW_EXCEPTION=3
+  # add some extra stuff to make it easier to examine with GDB
+  LOCAL_CFLAGS += -DEASY_GDB
+  # overall config may be for a "release" build, so reconfigure these
+  LOCAL_CFLAGS += -UNDEBUG -DDEBUG=1 -DLOG_NDEBUG=1 -DWITH_DALVIK_ASSERT
+else  # !dvm_make_debug_vm
+  #
+  # "Performance" profile:
+  # - all development features disabled
+  # - compiler optimizations enabled (redundant for "release" builds)
+  # - (debugging and profiling still enabled)
+  #
+  #LOCAL_CFLAGS += -DNDEBUG -DLOG_NDEBUG=1
+  # "-O2" is redundant for device (release) but useful for sim (debug)
+  #LOCAL_CFLAGS += -O2 -Winline
+  #LOCAL_CFLAGS += -DWITH_EXTRA_OBJECT_VALIDATION
+  LOCAL_CFLAGS += -DDVM_SHOW_EXCEPTION=1
+  # if you want to try with assertions on the device, add:
+  #LOCAL_CFLAGS += -UNDEBUG -DDEBUG=1 -DLOG_NDEBUG=1 -DWITH_DALVIK_ASSERT
+endif  # !dvm_make_debug_vm
+
+# bug hunting: checksum and verify interpreted stack when making JNI calls
+#LOCAL_CFLAGS += -DWITH_JNI_STACK_CHECK
+
+LOCAL_SRC_FILES := \
+	AllocTracker.c \
+	AtomicCache.c \
+	CheckJni.c \
+	Ddm.c \
+	Debugger.c \
+	DvmDex.c \
+	Exception.c \
+	Hash.c \
+	IndirectRefTable.c.arm \
+	Init.c \
+	InlineNative.c.arm \
+	Inlines.c \
+	Intern.c \
+	Jni.c \
+	JarFile.c \
+	LinearAlloc.c \
+	Misc.c.arm \
+	Native.c \
+	PointerSet.c \
+	Profile.c \
+	Properties.c \
+	RawDexFile.c \
+	ReferenceTable.c \
+	SignalCatcher.c \
+	StdioConverter.c \
+	Sync.c \
+	Thread.c \
+	UtfString.c \
+	alloc/clz.c.arm \
+	alloc/Alloc.c \
+	alloc/HeapBitmap.c.arm \
+	alloc/HeapDebug.c \
+	alloc/HeapSource.c \
+	alloc/HeapTable.c \
+	alloc/HeapWorker.c \
+	alloc/Heap.c.arm \
+	alloc/MarkSweep.c.arm \
+	alloc/DdmHeap.c \
+	analysis/CodeVerify.c \
+	analysis/DexOptimize.c \
+	analysis/DexVerify.c \
+	analysis/ReduceConstants.c \
+	analysis/RegisterMap.c \
+	analysis/VerifySubs.c \
+	interp/Interp.c.arm \
+	interp/Stack.c \
+	jdwp/ExpandBuf.c \
+	jdwp/JdwpAdb.c \
+	jdwp/JdwpConstants.c \
+	jdwp/JdwpEvent.c \
+	jdwp/JdwpHandler.c \
+	jdwp/JdwpMain.c \
+	jdwp/JdwpSocket.c \
+	mterp/Mterp.c.arm \
+	mterp/out/InterpC-portstd.c.arm \
+	mterp/out/InterpC-portdbg.c.arm \
+	native/InternalNative.c \
+	native/dalvik_system_DexFile.c \
+	native/dalvik_system_SamplingProfiler.c \
+	native/dalvik_system_VMDebug.c \
+	native/dalvik_system_VMRuntime.c \
+	native/dalvik_system_VMStack.c \
+	native/dalvik_system_Zygote.c \
+	native/java_lang_Class.c \
+	native/java_lang_Object.c \
+	native/java_lang_Runtime.c \
+	native/java_lang_String.c \
+	native/java_lang_System.c \
+	native/java_lang_SystemProperties.c \
+	native/java_lang_Throwable.c \
+	native/java_lang_VMClassLoader.c \
+	native/java_lang_VMThread.c \
+	native/java_lang_reflect_AccessibleObject.c \
+	native/java_lang_reflect_Array.c \
+	native/java_lang_reflect_Constructor.c \
+	native/java_lang_reflect_Field.c \
+	native/java_lang_reflect_Method.c \
+	native/java_lang_reflect_Proxy.c \
+	native/java_security_AccessController.c \
+	native/java_util_concurrent_atomic_AtomicLong.c \
+	native/org_apache_harmony_dalvik_NativeTestTarget.c \
+	native/org_apache_harmony_dalvik_ddmc_DdmServer.c \
+	native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.c \
+	native/sun_misc_Unsafe.c \
+	native/SystemThread.c \
+	oo/AccessCheck.c \
+	oo/Array.c \
+	oo/Class.c \
+	oo/Object.c \
+	oo/Resolve.c \
+	oo/TypeCheck.c \
+	reflect/Annotation.c \
+	reflect/Proxy.c \
+	reflect/Reflect.c \
+	test/AtomicSpeed.c \
+	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
+
+ifeq ($(WITH_JIT),true)
+  LOCAL_CFLAGS += -DWITH_JIT
+  LOCAL_SRC_FILES += \
+	../dexdump/OpCodeNames.c \
+	compiler/Compiler.c \
+	compiler/Frontend.c \
+	compiler/Utility.c \
+	compiler/IntermediateRep.c \
+	interp/Jit.c
+endif
+
+WITH_HPROF := $(strip $(WITH_HPROF))
+ifeq ($(WITH_HPROF),)
+  WITH_HPROF := true
+endif
+ifeq ($(WITH_HPROF),true)
+  LOCAL_SRC_FILES += \
+	hprof/Hprof.c \
+	hprof/HprofClass.c \
+	hprof/HprofHeap.c \
+	hprof/HprofOutput.c \
+	hprof/HprofString.c
+  LOCAL_CFLAGS += -DWITH_HPROF=1
+
+  ifeq ($(strip $(WITH_HPROF_UNREACHABLE)),true)
+    LOCAL_CFLAGS += -DWITH_HPROF_UNREACHABLE=1
+  endif
+
+  ifeq ($(strip $(WITH_HPROF_STACK)),true)
+    LOCAL_SRC_FILES += \
+	hprof/HprofStack.c \
+	hprof/HprofStackFrame.c
+    LOCAL_CFLAGS += -DWITH_HPROF_STACK=1
+  endif # WITH_HPROF_STACK
+endif   # WITH_HPROF
+
+ifeq ($(strip $(DVM_TRACK_HEAP_MARKING)),true)
+  LOCAL_CFLAGS += -DDVM_TRACK_HEAP_MARKING=1
+endif
+
+LOCAL_C_INCLUDES += \
+	$(JNI_H_INCLUDE) \
+	dalvik \
+	dalvik/vm \
+	external/zlib \
+	$(KERNEL_HEADERS)
+
+
+ifeq ($(dvm_simulator),true)
+  LOCAL_LDLIBS += -lpthread -ldl
+  ifeq ($(HOST_OS),linux)
+    # need this for clock_gettime() in profiling
+    LOCAL_LDLIBS += -lrt
+  endif
+else
+  ifeq ($(dvm_os),linux)
+    LOCAL_SHARED_LIBRARIES += libdl
+  endif
+endif
+
+MTERP_ARCH_KNOWN := false
+
+ifeq ($(dvm_arch),arm)
+  #dvm_arch_variant := armv7-a
+  #LOCAL_CFLAGS += -march=armv7-a -mfloat-abi=softfp -mfpu=vfp
+  MTERP_ARCH_KNOWN := true
+  # Select architecture-specific sources (armv4t, armv5te etc.)
+  LOCAL_SRC_FILES += \
+		arch/arm/CallOldABI.S \
+		arch/arm/CallEABI.S \
+		arch/arm/HintsEABI.c \
+		mterp/out/InterpC-$(dvm_arch_variant).c.arm \
+		mterp/out/InterpAsm-$(dvm_arch_variant).S
+
+  ifeq ($(WITH_JIT),true)
+    LOCAL_SRC_FILES += \
+		compiler/codegen/arm/Codegen-$(dvm_arch_variant).c \
+		compiler/codegen/arm/Assemble.c \
+		compiler/codegen/arm/ArchUtility.c \
+		compiler/codegen/arm/LocalOptimizations.c \
+		compiler/codegen/arm/GlobalOptimizations.c \
+		compiler/template/out/CompilerTemplateAsm-$(dvm_arch_variant).S
+  endif
+endif
+
+ifeq ($(dvm_arch),x86)
+  ifeq ($(dvm_os),linux)
+    MTERP_ARCH_KNOWN := true
+    LOCAL_SRC_FILES += \
+		arch/x86/Call386ABI.S \
+		arch/x86/Hints386ABI.c \
+		mterp/out/InterpC-x86.c \
+		mterp/out/InterpAsm-x86.S
+  endif
+endif
+
+ifeq ($(dvm_arch),sh)
+  MTERP_ARCH_KNOWN := true
+  LOCAL_SRC_FILES += \
+		arch/sh/CallSH4ABI.S \
+		arch/generic/Hints.c \
+		mterp/out/InterpC-allstubs.c \
+		mterp/out/InterpAsm-allstubs.S
+endif
+
+ifeq ($(MTERP_ARCH_KNOWN),false)
+  # unknown architecture, try to use FFI
+  LOCAL_C_INCLUDES += external/libffi/$(dvm_os)-$(dvm_arch)
+  LOCAL_SHARED_LIBRARIES += libffi
+
+  LOCAL_SRC_FILES += \
+		arch/generic/Call.c \
+		arch/generic/Hints.c \
+		mterp/out/InterpC-allstubs.c
+
+  # The following symbols are usually defined in the asm file, but
+  # since we don't have an asm file in this case, we instead just
+  # peg them at 0 here, and we add an #ifdef'able define for good
+  # measure, too.
+  LOCAL_CFLAGS += -DdvmAsmInstructionStart=0 -DdvmAsmInstructionEnd=0 \
+	-DdvmAsmSisterStart=0 -DdvmAsmSisterEnd=0 -DDVM_NO_ASM_INTERP=1
+endif
+
+LOCAL_SHARED_LIBRARIES += \
+	libnativehelper \
+	libz
+
+LOCAL_STATIC_LIBRARIES += \
+	libdex
diff --git a/vm/DvmDex.c b/vm/DvmDex.c
index b5f8d02..6740632 100644
--- a/vm/DvmDex.c
+++ b/vm/DvmDex.c
@@ -171,8 +171,10 @@
     int parseFlags = kDexParseDefault;
     int result = -1;
 
+    /* -- file is incomplete, new checksum has not yet been calculated
     if (gDvm.verifyDexChecksum)
         parseFlags |= kDexParseVerifyChecksum;
+    */
 
     pDexFile = dexFileParse(addr, len, parseFlags);
     if (pDexFile == NULL) {
diff --git a/vm/Exception.c b/vm/Exception.c
index 4881640..3a56cc3 100644
--- a/vm/Exception.c
+++ b/vm/Exception.c
@@ -102,6 +102,9 @@
 
 /*
  * Cache pointers to some of the exception classes we use locally.
+ *
+ * Note this is NOT called during dexopt optimization.  Some of the fields
+ * are initialized by the verifier (dvmVerifyCodeFlow).
  */
 bool dvmExceptionStartup(void)
 {
@@ -377,6 +380,14 @@
         }
     }
 
+    if (cause != NULL) {
+        if (!dvmInstanceof(cause->clazz, gDvm.classJavaLangThrowable)) {
+            LOGE("Tried to init exception with cause '%s'\n",
+                cause->clazz->descriptor);
+            dvmAbort();
+        }
+    }
+
     /*
      * The Throwable class has four public constructors:
      *  (1) Throwable()
@@ -625,6 +636,28 @@
 }
 
 /*
+ * Get the "cause" field from an exception.
+ *
+ * The Throwable class initializes the "cause" field to "this" to
+ * differentiate between being initialized to null and never being
+ * initialized.  We check for that here and convert it to NULL.
+ */
+Object* dvmGetExceptionCause(const Object* exception)
+{
+    if (!dvmInstanceof(exception->clazz, gDvm.classJavaLangThrowable)) {
+        LOGE("Tried to get cause from object of type '%s'\n",
+            exception->clazz->descriptor);
+        dvmAbort();
+    }
+    Object* cause =
+        dvmGetFieldObject(exception, gDvm.offJavaLangThrowable_cause);
+    if (cause == exception)
+        return NULL;
+    else
+        return cause;
+}
+
+/*
  * Print the stack trace of the current exception on stderr.  This is called
  * from the JNI ExceptionDescribe call.
  *
@@ -1208,9 +1241,8 @@
 
     for (;;) {
         logStackTraceOf(exception);
-        cause = (Object*) dvmGetFieldObject(exception,
-                    gDvm.offJavaLangThrowable_cause);
-        if ((cause == NULL) || (cause == exception)) {
+        cause = dvmGetExceptionCause(exception);
+        if (cause == NULL) {
             break;
         }
         LOGI("Caused by:\n");
diff --git a/vm/Exception.h b/vm/Exception.h
index 9887929..4044345 100644
--- a/vm/Exception.h
+++ b/vm/Exception.h
@@ -123,6 +123,13 @@
 void dvmWrapException(const char* newExcepStr);
 
 /*
+ * Get the "cause" field from an exception.
+ *
+ * Returns NULL if the field is null or uninitialized.
+ */
+Object* dvmGetExceptionCause(const Object* exception);
+
+/*
  * Print the exception stack trace on stderr.  Calls the exception's
  * print function.
  */
diff --git a/vm/Globals.h b/vm/Globals.h
index acaebaa..9b12d84 100644
--- a/vm/Globals.h
+++ b/vm/Globals.h
@@ -54,6 +54,9 @@
     kExecutionModeUnknown = 0,
     kExecutionModeInterpPortable,
     kExecutionModeInterpFast,
+#if defined(WITH_JIT)
+    kExecutionModeJit,
+#endif
 } ExecutionMode;
 
 /*
@@ -99,6 +102,7 @@
 
     DexOptimizerMode    dexOptMode;
     DexClassVerifyMode  classVerifyMode;
+    bool        preciseGc;
     bool        generateRegisterMaps;
 
     int         assertionCtrlCount;
@@ -190,6 +194,7 @@
     ClassObject* classOrgApacheHarmonyLangAnnotationAnnotationMember;
     ClassObject* classOrgApacheHarmonyLangAnnotationAnnotationMemberArray;
     ClassObject* classOrgApacheHarmonyNioInternalDirectBuffer;
+    jclass      jclassOrgApacheHarmonyNioInternalDirectBuffer;
 
     /* synthetic classes for arrays of primitives */
     ClassObject* classArrayBoolean;
@@ -338,6 +343,8 @@
      *  (3) a thread has hit a breakpoint or exception that the debugger
      *      has marked as a "suspend all" event;
      *  (4) the SignalCatcher caught a signal that requires suspension.
+     *  (5) (if implemented) the JIT needs to perform a heavyweight
+     *      rearrangement of the translation cache or JitTable.
      *
      * Because we use "safe point" self-suspension, it is never safe to
      * do a blocking "lock" call on this mutex -- if it has been acquired,
@@ -365,6 +372,12 @@
     pthread_cond_t  threadSuspendCountCond;
 
     /*
+     * Sum of all threads' suspendCount fields.  The JIT needs to know if any
+     * thread is suspended.  Guarded by threadSuspendCountLock.
+     */
+    int  sumThreadSuspendCount;
+
+    /*
      * MUTEX ORDERING: when locking multiple mutexes, always grab them in
      * this order to avoid deadlock:
      *
@@ -397,12 +410,22 @@
     /*
      * JNI global reference table.
      */
+#ifdef USE_INDIRECT_REF
+    IndirectRefTable jniGlobalRefTable;
+#else
     ReferenceTable  jniGlobalRefTable;
+#endif
     pthread_mutex_t jniGlobalRefLock;
     int         jniGlobalRefHiMark;
     int         jniGlobalRefLoMark;
 
     /*
+     * JNI pinned object table (used for primitive arrays).
+     */
+    ReferenceTable  jniPinRefTable;
+    pthread_mutex_t jniPinRefLock;
+
+    /*
      * Native shared library table.
      */
     HashTable*  nativeLibs;
@@ -417,12 +440,11 @@
     GcHeap*     gcHeap;
 
     /*
-     * Pre-allocated object for out-of-memory errors.
+     * Pre-allocated throwables.
      */
     Object*     outOfMemoryObj;
-
-    /* pre-allocated general failure exception */
     Object*     internalErrorObj;
+    Object*     noClassDefFoundErrorObj;
 
     /* Monitor list, so we can free them */
     /*volatile*/ Monitor* monitorList;
@@ -487,9 +509,12 @@
 
     /*
      * JDWP debugger support.
+     *
+     * Note "debuggerActive" is accessed from mterp, so its storage size and
+     * meaning must not be changed without updating the assembly sources.
      */
     bool        debuggerConnected;      /* debugger or DDMS is connected */
-    bool        debuggerActive;         /* debugger is making requests */
+    u1          debuggerActive;         /* debugger is making requests */
     JdwpState*  jdwpState;
 
     /*
@@ -608,12 +633,127 @@
      */
     pid_t systemServerPid;
 
+    int kernelGroupScheduling;
+
 //#define COUNT_PRECISE_METHODS
 #ifdef COUNT_PRECISE_METHODS
     PointerSet* preciseMethods;
 #endif
+
+    /* some RegisterMap statistics, useful during development */
+    void*       registerMapStats;
 };
 
 extern struct DvmGlobals gDvm;
 
+#if defined(WITH_JIT)
+
+/*
+ * JIT-specific global state
+ */
+struct DvmJitGlobals {
+    /*
+     * Guards writes to Dalvik PC (dPC), translated code address (codeAddr) and
+     * chain fields within the JIT hash table.  Note carefully the access
+     * mechanism.
+     * Only writes are guarded, and the guarded fields must be updated in a
+     * specific order using atomic operations.  Further, once a field is
+     * written it cannot be changed without halting all threads.
+     *
+     * The write order is:
+     *    1) codeAddr
+     *    2) dPC
+     *    3) chain [if necessary]
+     *
+     * This mutex also guards both read and write of curJitTableEntries.
+     */
+    pthread_mutex_t tableLock;
+
+    /* The JIT hash table.  Note that for access speed, copies of this pointer
+     * are stored in each thread. */
+    struct JitEntry *pJitEntryTable;
+
+    /* Array of profile threshold counters */
+    unsigned char *pProfTable;
+    unsigned char *pProfTableCopy;
+
+    /* Size of JIT hash table in entries.  Must be a power of 2 */
+    unsigned int jitTableSize;
+
+    /* Mask used in hash function for JitTable.  Should be jitTableSize-1 */
+    unsigned int jitTableMask;
+
+    /* How many entries in the JitEntryTable are in use */
+    unsigned int jitTableEntriesUsed;
+
+    /* Trigger for trace selection */
+    unsigned short threshold;
+
+    /* JIT Compiler Control */
+    bool               haltCompilerThread;
+    bool               blockingMode;
+    pthread_t          compilerHandle;
+    pthread_mutex_t    compilerLock;
+    pthread_cond_t     compilerQueueActivity;
+    pthread_cond_t     compilerQueueEmpty;
+    int                compilerQueueLength;
+    int                compilerHighWater;
+    int                compilerWorkEnqueueIndex;
+    int                compilerWorkDequeueIndex;
+    CompilerWorkOrder  compilerWorkQueue[COMPILER_WORK_QUEUE_SIZE];
+
+    /* JIT internal stats */
+    int                compilerMaxQueued;
+    int                addrLookupsFound;
+    int                addrLookupsNotFound;
+    int                noChainExit;
+    int                normalExit;
+    int                puntExit;
+    int                translationChains;
+    int                invokeChain;
+    int                invokePredictedChain;
+    int                invokeNative;
+    int                returnOp;
+
+    /* Compiled code cache */
+    void* codeCache;
+
+    /* Bytes used by the code templates */
+    unsigned int templateSize;
+
+    /* Bytes already used in the code cache */
+    unsigned int codeCacheByteUsed;
+
+    /* Number of installed compilations in the cache */
+    unsigned int numCompilations;
+
+    /* Flag to indicate that the code cache is full */
+    bool codeCacheFull;
+
+    /* true/false: compile/reject opcodes specified in the -Xjitop list */
+    bool includeSelectedOp;
+
+    /* true/false: compile/reject methods specified in the -Xjitmethod list */
+    bool includeSelectedMethod;
+
+    /* Disable JIT for selected opcodes - one bit for each opcode */
+    char opList[32];
+
+    /* Disable JIT for selected methods */
+    HashTable *methodTable;
+
+    /* Flag to dump all compiled code */
+    bool printMe;
+
+    /* Flag to count trace execution */
+    bool profile;
+
+    /* Table to track the overall and trace statistics of hot methods */
+    HashTable*  methodStatsTable;
+};
+
+extern struct DvmJitGlobals gDvmJit;
+
+#endif
+
 #endif /*_DALVIK_GLOBALS*/
diff --git a/vm/IndirectRefTable.c b/vm/IndirectRefTable.c
new file mode 100644
index 0000000..f7c7647
--- /dev/null
+++ b/vm/IndirectRefTable.c
@@ -0,0 +1,459 @@
+/*
+ * 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.
+ */
+
+/*
+ * Indirect reference table management.
+ */
+#include "Dalvik.h"
+
+/*
+ * Initialize an IndirectRefTable structure.
+ */
+bool dvmInitIndirectRefTable(IndirectRefTable* pRef, int initialCount,
+    int maxCount, IndirectRefKind kind)
+{
+    assert(initialCount > 0);
+    assert(initialCount <= maxCount);
+    assert(kind == kIndirectKindLocal || kind == kIndirectKindGlobal);
+
+    pRef->table = (Object**) malloc(initialCount * sizeof(Object*));
+    if (pRef->table == NULL)
+        return false;
+#ifndef NDEBUG
+    memset(pRef->table, 0xd1, initialCount * sizeof(Object*));
+#endif
+    pRef->segmentState.all = IRT_FIRST_SEGMENT;
+    pRef->allocEntries = initialCount;
+    pRef->maxEntries = maxCount;
+    pRef->kind = kind;
+
+    return true;
+}
+
+/*
+ * Clears out the contents of a IndirectRefTable, freeing allocated storage.
+ */
+void dvmClearIndirectRefTable(IndirectRefTable* pRef)
+{
+    free(pRef->table);
+    pRef->table = NULL;
+    pRef->allocEntries = pRef->maxEntries = -1;
+}
+
+/*
+ * Remove one or more segments from the top.  The table entry identified
+ * by "cookie" becomes the new top-most entry.
+ *
+ * Returns false if "cookie" is invalid or the table has only one segment.
+ */
+bool dvmPopIndirectRefTableSegmentCheck(IndirectRefTable* pRef, u4 cookie)
+{
+    IRTSegmentState sst;
+
+    /*
+     * The new value for "top" must be <= the current value.  Otherwise
+     * this would represent an expansion of the table.
+     */
+    sst.all = cookie;
+    if (sst.parts.topIndex > pRef->segmentState.parts.topIndex) {
+        LOGE("Attempt to expand table with segment pop (%d to %d)\n",
+            pRef->segmentState.parts.topIndex, sst.parts.topIndex);
+        return false;
+    }
+    if (sst.parts.numHoles >= sst.parts.topIndex) {
+        LOGE("Absurd numHoles in cookie (%d bi=%d)\n",
+            sst.parts.numHoles, sst.parts.topIndex);
+        return false;
+    }
+
+    LOGV("--- after pop, top=%d holes=%d\n",
+        sst.parts.topIndex, sst.parts.numHoles);
+
+    return true;
+}
+
+/*
+ * Make sure that the entry at "idx" is correctly paired with "iref".
+ */
+static bool checkEntry(IndirectRefTable* pRef, IndirectRef iref, int idx)
+{
+    Object* obj = pRef->table[idx];
+    IndirectRef checkRef = dvmObjectToIndirectRef(obj, idx, pRef->kind);
+    if (checkRef != iref) {
+        LOGW("iref mismatch: %p vs %p\n", iref, checkRef);
+        return false;
+    }
+    return true;
+}
+
+/*
+ * Add "obj" to "pRef".
+ */
+IndirectRef dvmAddToIndirectRefTable(IndirectRefTable* pRef, u4 cookie,
+    Object* obj)
+{
+    IRTSegmentState prevState;
+    prevState.all = cookie;
+    int topIndex = pRef->segmentState.parts.topIndex;
+    int bottomIndex = prevState.parts.topIndex;
+
+    assert(obj != NULL);
+    assert(dvmIsValidObject(obj));
+    assert(pRef->table != NULL);
+    assert(pRef->allocEntries <= pRef->maxEntries);
+    assert(pRef->segmentState.parts.numHoles >= prevState.parts.numHoles);
+
+    if (topIndex == pRef->allocEntries) {
+        /* reached end of allocated space; did we hit buffer max? */
+        if (topIndex == pRef->maxEntries) {
+            LOGW("IndirectRefTable overflow (max=%d)\n", pRef->maxEntries);
+            return NULL;
+        }
+
+        Object** newTable;
+        int newSize;
+
+        newSize = pRef->allocEntries * 2;
+        if (newSize > pRef->maxEntries)
+            newSize = pRef->maxEntries;
+        assert(newSize > pRef->allocEntries);
+
+        newTable = (Object**) realloc(pRef->table, newSize * sizeof(Object*));
+        if (newTable == NULL) {
+            LOGE("Unable to expand iref table (from %d to %d, max=%d)\n",
+                pRef->allocEntries, newSize, pRef->maxEntries);
+            return false;
+        }
+        LOGI("Growing ireftab %p from %d to %d (max=%d)\n",
+            pRef, pRef->allocEntries, newSize, pRef->maxEntries);
+
+        /* update entries; adjust "nextEntry" in case memory moved */
+        pRef->table = newTable;
+        pRef->allocEntries = newSize;
+    }
+
+    IndirectRef result;
+
+    /*
+     * We know there's enough room in the table.  Now we just need to find
+     * the right spot.  If there's a hole, find it and fill it; otherwise,
+     * add to the end of the list.
+     */
+    int numHoles = pRef->segmentState.parts.numHoles - prevState.parts.numHoles;
+    if (numHoles > 0) {
+        assert(topIndex > 1);
+        /* find the first hole; likely to be near the end of the list */
+        Object** pScan = &pRef->table[topIndex - 1];
+        assert(*pScan != NULL);
+        while (*--pScan != NULL) {
+            assert(pScan >= pRef->table + bottomIndex);
+        }
+        result = dvmObjectToIndirectRef(obj, pScan - pRef->table, pRef->kind);
+        *pScan = obj;
+        pRef->segmentState.parts.numHoles--;
+    } else {
+        /* add to the end */
+        result = dvmObjectToIndirectRef(obj, topIndex, pRef->kind);
+        pRef->table[topIndex++] = obj;
+        pRef->segmentState.parts.topIndex = topIndex;
+    }
+
+    assert(result != NULL);
+    return result;
+}
+
+/*
+ * Verify that the indirect table lookup is valid.
+ *
+ * Returns "false" if something looks bad.
+ */
+bool dvmGetFromIndirectRefTableCheck(IndirectRefTable* pRef, IndirectRef iref)
+{
+    if (dvmGetIndirectRefType(iref) == kIndirectKindInvalid) {
+        LOGW("Invalid indirect reference 0x%08x\n", (u4) iref);
+        return false;
+    }
+
+    int topIndex = pRef->segmentState.parts.topIndex;
+    int idx = dvmIndirectRefToIndex(iref);
+
+    if (iref == NULL) {
+        LOGI("--- lookup on NULL iref\n");
+        return false;
+    }
+    if (idx >= topIndex) {
+        /* bad -- stale reference? */
+        LOGI("Attempt to access invalid index %d (top=%d)\n",
+            idx, topIndex);
+        return false;
+    }
+
+    Object* obj = pRef->table[idx];
+    if (obj == NULL) {
+        LOGI("Attempt to read from hole, iref=%p\n", iref);
+        return false;
+    }
+    if (!checkEntry(pRef, iref, idx))
+        return false;
+
+    return true;
+}
+
+/*
+ * Remove "obj" from "pRef".  We extract the table offset bits from "iref"
+ * and zap the corresponding entry, leaving a hole if it's not at the top.
+ *
+ * If the entry is not between the current top index and the bottom index
+ * specified by the cookie, we don't remove anything.  This is the behavior
+ * required by JNI's DeleteLocalRef function.
+ *
+ * Returns "false" if nothing was removed.
+ */
+bool dvmRemoveFromIndirectRefTable(IndirectRefTable* pRef, u4 cookie,
+    IndirectRef iref)
+{
+    IRTSegmentState prevState;
+    prevState.all = cookie;
+    int topIndex = pRef->segmentState.parts.topIndex;
+    int bottomIndex = prevState.parts.topIndex;
+
+    assert(pRef->table != NULL);
+    assert(pRef->allocEntries <= pRef->maxEntries);
+    assert(pRef->segmentState.parts.numHoles >= prevState.parts.numHoles);
+
+    int idx = dvmIndirectRefToIndex(iref);
+    if (idx < bottomIndex) {
+        /* wrong segment */
+        LOGV("Attempt to remove index outside index area (%d vs %d-%d)\n",
+            idx, bottomIndex, topIndex);
+        return false;
+    }
+    if (idx >= topIndex) {
+        /* bad -- stale reference? */
+        LOGI("Attempt to remove invalid index %d (bottom=%d top=%d)\n",
+            idx, bottomIndex, topIndex);
+        return false;
+    }
+
+    if (idx == topIndex-1) {
+        /*
+         * Top-most entry.  Scan up and consume holes.  No need to NULL
+         * out the entry, since the test vs. topIndex will catch it.
+         */
+        if (!checkEntry(pRef, iref, idx))
+            return false;
+
+#ifndef NDEBUG
+        pRef->table[idx] = (IndirectRef) 0xd3d3d3d3;
+#endif
+
+        int numHoles =
+            pRef->segmentState.parts.numHoles - prevState.parts.numHoles;
+        if (numHoles != 0) {
+            while (--topIndex > bottomIndex && numHoles != 0) {
+                LOGV("+++ checking for hole at %d (cookie=0x%08x) val=%p\n",
+                    topIndex-1, cookie, pRef->table[topIndex-1]);
+                if (pRef->table[topIndex-1] != NULL)
+                    break;
+                LOGV("+++ ate hole at %d\n", topIndex-1);
+                numHoles--;
+            }
+            pRef->segmentState.parts.numHoles =
+                numHoles + prevState.parts.numHoles;
+            pRef->segmentState.parts.topIndex = topIndex;
+        } else {
+            pRef->segmentState.parts.topIndex = topIndex-1;
+            LOGV("+++ ate last entry %d\n", topIndex-1);
+        }
+    } else {
+        /*
+         * Not the top-most entry.  This creates a hole.  We NULL out the
+         * entry to prevent somebody from deleting it twice and screwing up
+         * the hole count.
+         */
+        if (pRef->table[idx] == NULL) {
+            LOGV("--- WEIRD: removing null entry %d\n", idx);
+            return false;
+        }
+        if (!checkEntry(pRef, iref, idx))
+            return false;
+
+        pRef->table[idx] = NULL;
+        pRef->segmentState.parts.numHoles++;
+        LOGV("+++ left hole at %d, holes=%d\n",
+            idx, pRef->segmentState.parts.numHoles);
+    }
+
+    return true;
+}
+
+/*
+ * This is a qsort() callback.  We sort Object* by class, allocation size,
+ * and then by the Object* itself.
+ */
+static int compareObject(const void* vobj1, const void* vobj2)
+{
+    Object* obj1 = *((Object**) vobj1);
+    Object* obj2 = *((Object**) vobj2);
+
+    /* ensure null references appear at the end */
+    if (obj1 == NULL) {
+        if (obj2 == NULL) {
+            return 0;
+        } else {
+            return 1;
+        }
+    } else if (obj2 == NULL) {
+        return -1;
+    }
+
+    if (obj1->clazz != obj2->clazz) {
+        return (u1*)obj1->clazz - (u1*)obj2->clazz;
+    } else {
+        int size1 = dvmObjectSizeInHeap(obj1);
+        int size2 = dvmObjectSizeInHeap(obj2);
+        if (size1 != size2) {
+            return size1 - size2;
+        } else {
+            return (u1*)obj1 - (u1*)obj2;
+        }
+    }
+}
+
+/*
+ * Log an object with some additional info.
+ *
+ * Pass in the number of additional elements that are identical to or
+ * equivalent to the original.
+ */
+static void logObject(Object* obj, int size, int identical, int equiv)
+{
+    if (obj == NULL) {
+        LOGW("  NULL reference (count=%d)\n", equiv);
+        return;
+    }
+
+    if (identical + equiv != 0) {
+        LOGW("%5d of %s %dB (%d unique)\n", identical + equiv +1,
+            obj->clazz->descriptor, size, equiv +1);
+    } else {
+        LOGW("%5d of %s %dB\n", identical + equiv +1,
+            obj->clazz->descriptor, size);
+    }
+}
+
+/*
+ * Dump the contents of a IndirectRefTable to the log.
+ */
+void dvmDumpIndirectRefTable(const IndirectRefTable* pRef, const char* descr)
+{
+    const int kLast = 10;
+    int count = dvmIndirectRefTableEntries(pRef);
+    Object** refs;
+    int i;
+
+    if (count == 0) {
+        LOGW("Reference table has no entries\n");
+        return;
+    }
+    assert(count > 0);
+
+    /*
+     * Dump the most recent N entries.  If there are holes, we will show
+     * fewer than N.
+     */
+    LOGW("Last %d entries in %s reference table:\n", kLast, descr);
+    refs = pRef->table;         // use unsorted list
+    int size;
+    int start = count - kLast;
+    if (start < 0)
+        start = 0;
+
+    for (i = start; i < count; i++) {
+        if (refs[i] == NULL)
+            continue;
+        size = dvmObjectSizeInHeap(refs[i]);
+        Object* ref = refs[i];
+        if (ref->clazz == gDvm.classJavaLangClass) {
+            ClassObject* clazz = (ClassObject*) ref;
+            LOGW("%5d: %p cls=%s '%s' (%d bytes)\n", i, ref,
+                (refs[i] == NULL) ? "-" : ref->clazz->descriptor,
+                clazz->descriptor, size);
+        } else {
+            LOGW("%5d: %p cls=%s (%d bytes)\n", i, ref,
+                (refs[i] == NULL) ? "-" : ref->clazz->descriptor, size);
+        }
+    }
+
+    /*
+     * Make a copy of the table, and sort it.
+     *
+     * The NULL "holes" wind up at the end, so we can strip them off easily.
+     */
+    Object** tableCopy = (Object**)malloc(sizeof(Object*) * count);
+    memcpy(tableCopy, pRef->table, sizeof(Object*) * count);
+    qsort(tableCopy, count, sizeof(Object*), compareObject);
+    refs = tableCopy;       // use sorted list
+
+    {
+        int q;
+        for (q = 0; q < count; q++)
+            LOGI("%d %p\n", q, refs[q]);
+    }
+
+    int holes = 0;
+    while (refs[count-1] == NULL) {
+        count--;
+        holes++;
+    }
+
+    /*
+     * Dump uniquified table summary.  While we're at it, generate a
+     * cumulative total amount of pinned memory based on the unique entries.
+     */
+    LOGW("%s reference table summary (%d entries / %d holes):\n",
+        descr, count, holes);
+    int equiv, identical, total;
+    total = equiv = identical = 0;
+    for (i = 1; i < count; i++) {
+        size = dvmObjectSizeInHeap(refs[i-1]);
+
+        if (refs[i] == refs[i-1]) {
+            /* same reference, added more than once */
+            identical++;
+        } else if (refs[i]->clazz == refs[i-1]->clazz &&
+            (int) dvmObjectSizeInHeap(refs[i]) == size)
+        {
+            /* same class / size, different object */
+            total += size;
+            equiv++;
+        } else {
+            /* different class */
+            total += size;
+            logObject(refs[i-1], size, identical, equiv);
+            equiv = identical = 0;
+        }
+    }
+
+    /* handle the last entry (everything above outputs refs[i-1]) */
+    size = (refs[count-1] == NULL) ? 0 : dvmObjectSizeInHeap(refs[count-1]);
+    total += size;
+    logObject(refs[count-1], size, identical, equiv);
+
+    LOGW("Memory held directly by native code is %d bytes\n", total);
+    free(tableCopy);
+}
+
diff --git a/vm/IndirectRefTable.h b/vm/IndirectRefTable.h
new file mode 100644
index 0000000..c03353b
--- /dev/null
+++ b/vm/IndirectRefTable.h
@@ -0,0 +1,368 @@
+/*
+ * 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_INDIRECTREFTABLE
+#define _DALVIK_INDIRECTREFTABLE
+/*
+ * Maintain a table of indirect references.  Used for local/global JNI
+ * references.
+ *
+ * The table contains object references that are part of the GC root set.
+ * When an object is added we return an IndirectRef that is not a valid
+ * pointer but can be used to find the original value in O(1) time.
+ * Conversions to and from indirect refs are performed on JNI method calls
+ * in and out of the VM, so they need to be very fast.
+ *
+ * To be efficient for JNI local variable storage, we need to provide
+ * operations that allow us to operate on segments of the table, where
+ * segments are pushed and popped as if on a stack.  For example, deletion
+ * of an entry should only succeed if it appears in the current segment,
+ * and we want to be able to strip off the current segment quickly when
+ * a method returns.  Additions to the table must be made in the current
+ * segment even if space is available in an earlier area.
+ *
+ * A new segment is created when we call into native code from interpreted
+ * code, or when we handle the JNI PushLocalFrame function.
+ *
+ * The GC must be able to scan the entire table quickly.
+ *
+ * In summary, these must be very fast:
+ *  - adding or removing a segment
+ *  - adding references to a new segment
+ *  - converting an indirect reference back to an Object
+ * These can be a little slower, but must still be pretty quick:
+ *  - adding references to a "mature" segment
+ *  - removing individual references
+ *  - scanning the entire table straight through
+ *
+ * If there's more than one segment, we don't guarantee that the table
+ * will fill completely before we fail due to lack of space.  We do ensure
+ * that the current segment will pack tightly, which should satisfy JNI
+ * requirements (e.g. EnsureLocalCapacity).
+ *
+ * To make everything fit nicely in 32-bit integers, the maximum size of
+ * the table is capped at 64K.
+ *
+ * None of the table functions are synchronized.
+ */
+
+/*
+ * Indirect reference definition.  This must be interchangeable with JNI's
+ * jobject, and it's convenient to let null be null, so we use void*.
+ *
+ * We need a 16-bit table index and a 2-bit reference type (global, local,
+ * weak global).  Real object pointers will have zeroes in the low 2 or 3
+ * bits (4- or 8-byte alignment), so it's useful to put the ref type
+ * in the low bits and reserve zero as an invalid value.
+ *
+ * The remaining 14 bits can be used to detect stale indirect references.
+ * For example, if objects don't move, we can use a hash of the original
+ * Object* to make sure the entry hasn't been re-used.  (If the Object*
+ * we find there doesn't match because of heap movement, we could do a
+ * secondary check on the preserved hash value; this implies that creating
+ * a global/local ref queries the hash value and forces it to be saved.)
+ * This is only done when CheckJNI is enabled.
+ *
+ * A more rigorous approach would be to put a serial number in the extra
+ * bits, and keep a copy of the serial number in a parallel table.  This is
+ * easier when objects can move, but requires 2x the memory and additional
+ * memory accesses on add/get.  It will catch additional problems, e.g.:
+ * create iref1 for obj, delete iref1, create iref2 for same obj, lookup
+ * iref1.  A pattern based on object bits will miss this.
+ */
+typedef void* IndirectRef;
+
+/*
+ * Indirect reference kind, used as the two low bits of IndirectRef.
+ *
+ * For convenience these match up with enum jobjectRefType from jni.h.
+ */
+typedef enum IndirectRefKind {
+    kIndirectKindInvalid    = 0,
+    kIndirectKindLocal      = 1,
+    kIndirectKindGlobal     = 2,
+    kIndirectKindWeakGlobal = 3
+} IndirectRefKind;
+
+/*
+ * Table definition.
+ *
+ * For the global reference table, the expected common operations are
+ * adding a new entry and removing a recently-added entry (usually the
+ * most-recently-added entry).  For JNI local references, the common
+ * operations are adding a new entry and removing an entire table segment.
+ *
+ * If "allocEntries" is not equal to "maxEntries", the table may expand
+ * when entries are added, which means the memory may move.  If you want
+ * to keep pointers into "table" rather than offsets, you must use a
+ * fixed-size table.
+ *
+ * If we delete entries from the middle of the list, we will be left with
+ * "holes".  We track the number of holes so that, when adding new elements,
+ * we can quickly decide to do a trivial append or go slot-hunting.
+ *
+ * When the top-most entry is removed, any holes immediately below it are
+ * also removed.  Thus, deletion of an entry may reduce "topIndex" by more
+ * than one.
+ *
+ * To get the desired behavior for JNI locals, we need to know the bottom
+ * and top of the current "segment".  The top is managed internally, and
+ * the bottom is passed in as a function argument (the VM keeps it in a
+ * slot in the interpreted stack frame).  When we call a native method or
+ * push a local frame, the current top index gets pushed on, and serves
+ * as the new bottom.  When we pop a frame off, the value from the stack
+ * becomes the new top index, and the value stored in the previous frame
+ * becomes the new bottom.
+ *
+ * To avoid having to re-scan the table after a pop, we want to push the
+ * number of holes in the table onto the stack.  Because of our 64K-entry
+ * cap, we can combine the two into a single unsigned 32-bit value.
+ * Instead of a "bottom" argument we take a "cookie", which includes the
+ * bottom index and the count of holes below the bottom.
+ *
+ * We need to minimize method call/return overhead.  If we store the
+ * "cookie" externally, on the interpreted call stack, the VM can handle
+ * pushes and pops with a single 4-byte load and store.  (We could also
+ * store it internally in a public structure, but the local JNI refs are
+ * logically tied to interpreted stack frames anyway.)
+ *
+ * Common alternative implementation: make IndirectRef a pointer to the
+ * actual reference slot.  Instead of getting a table and doing a lookup,
+ * the lookup can be done instantly.  Operations like determining the
+ * type and deleting the reference are more expensive because the table
+ * must be hunted for (i.e. you have to do a pointer comparison to see
+ * which table it's in), you can't move the table when expanding it (so
+ * realloc() is out), and tricks like serial number checking to detect
+ * stale references aren't possible (though we may be able to get similar
+ * benefits with other approaches).
+ *
+ * TODO: consider a "lastDeleteIndex" for quick hole-filling when an
+ * add immediately follows a delete; must invalidate after segment pop
+ * (which could increase the cost/complexity of method call/return).
+ * Might be worth only using it for JNI globals.
+ *
+ * TODO: may want completely different add/remove algorithms for global
+ * and local refs to improve performance.  A large circular buffer might
+ * reduce the amortized cost of adding global references.
+ *
+ * TODO: if we can guarantee that the underlying storage doesn't move,
+ * e.g. by using oversized mmap regions to handle expanding tables, we may
+ * be able to avoid having to synchronize lookups.  Might make sense to
+ * add a "synchronized lookup" call that takes the mutex as an argument,
+ * and either locks or doesn't lock based on internal details.
+ */
+typedef union IRTSegmentState {
+    u4          all;
+    struct {
+        u4      topIndex:16;            /* index of first unused entry */
+        u4      numHoles:16;            /* #of holes in entire table */
+    } parts;
+} IRTSegmentState;
+typedef struct IndirectRefTable {
+    /* semi-public - read/write by interpreter in native call handler */
+    IRTSegmentState segmentState;
+
+    /* semi-public - read-only during GC scan; pointer must not be kept */
+    Object**        table;              /* bottom of the stack */
+
+    /* private */
+    int             allocEntries;       /* #of entries we have space for */
+    int             maxEntries;         /* max #of entries allowed */
+    IndirectRefKind kind;               /* bit mask, ORed into all irefs */
+
+    // TODO: want hole-filling stats (#of holes filled, total entries scanned)
+    //       for performance evaluation.
+} IndirectRefTable;
+
+/* use as initial value for "cookie", and when table has only one segment */
+#define IRT_FIRST_SEGMENT   0
+
+/*
+ * (This is PRIVATE, but we want it inside other inlines in this header.)
+ *
+ * Indirectify the object.
+ *
+ * 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)
+{
+    assert(tableIndex < 65536);
+    u4 objChunk = (((u4) obj >> 3) ^ ((u4) obj >> 19)) & 0x3fff;
+    u4 uref = objChunk << 18 | (tableIndex << 2) | kind;
+    return (IndirectRef) uref;
+}
+
+/*
+ * (This is PRIVATE, but we want it inside other inlines in this header.)
+ *
+ * Extract the table index from an indirect reference.
+ */
+INLINE u4 dvmIndirectRefToIndex(IndirectRef iref)
+{
+    u4 uref = (u4) iref;
+    return (uref >> 2) & 0xffff;
+}
+
+/*
+ * Determine what kind of indirect reference this is.
+ */
+INLINE IndirectRefKind dvmGetIndirectRefType(IndirectRef iref)
+{
+    return (u4) iref & 0x03;
+}
+
+/*
+ * Initialize an IndirectRefTable.
+ *
+ * If "initialCount" != "maxCount", the table will expand as required.
+ *
+ * "kind" should be Local or Global.  The Global table may also hold
+ * WeakGlobal refs.
+ *
+ * Returns "false" if table allocation fails.
+ */
+bool dvmInitIndirectRefTable(IndirectRefTable* pRef, int initialCount,
+    int maxCount, IndirectRefKind kind);
+
+/*
+ * Clear out the contents, freeing allocated storage.  Does not free "pRef".
+ *
+ * You must call dvmInitReferenceTable() before you can re-use this table.
+ */
+void dvmClearIndirectRefTable(IndirectRefTable* pRef);
+
+/*
+ * Start a new segment at the top of the table.
+ *
+ * Returns an opaque 32-bit value that must be provided when the segment
+ * is to be removed.
+ *
+ * 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.
+ */
+INLINE u4 dvmPushIndirectRefTableSegment(IndirectRefTable* pRef)
+{
+    return pRef->segmentState.all;
+}
+
+/* extra debugging checks */
+bool dvmPopIndirectRefTableSegmentCheck(IndirectRefTable* pRef, u4 cookie);
+
+/*
+ * Remove one or more segments from the top.  The table entry identified
+ * by "cookie" becomes the new top-most entry.
+ *
+ * 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.
+ */
+INLINE void dvmPopIndirectRefTableSegment(IndirectRefTable* pRef, u4 cookie)
+{
+    dvmPopIndirectRefTableSegmentCheck(pRef, cookie);
+    pRef->segmentState.all = cookie;
+}
+
+/*
+ * Return the #of entries in the entire table.  This includes holes, and
+ * so may be larger than the actual number of "live" entries.
+ */
+INLINE size_t dvmIndirectRefTableEntries(const IndirectRefTable* pRef)
+{
+    return pRef->segmentState.parts.topIndex;
+}
+
+/*
+ * Returns "true" if the table is full.  The table is considered full if
+ * we would need to expand it to add another entry to the current segment.
+ */
+INLINE size_t dvmIsIndirectRefTableFull(const IndirectRefTable* pRef)
+{
+    return dvmIndirectRefTableEntries(pRef) == (size_t)pRef->allocEntries;
+}
+
+/*
+ * Add a new entry.  "obj" must be a valid non-NULL object reference
+ * (though it's okay if it's not fully-formed, e.g. the result from
+ * dvmMalloc doesn't have obj->clazz set).
+ *
+ * Returns NULL if the table is full (max entries reached, or alloc
+ * failed during expansion).
+ */
+IndirectRef dvmAddToIndirectRefTable(IndirectRefTable* pRef, u4 cookie,
+    Object* obj);
+
+/*
+ * Add a new entry at the end.  Similar to Add but does not usually attempt
+ * to fill in holes.  This is only appropriate to use right after a new
+ * segment has been pushed.
+ *
+ * (This is intended for use when calling into a native JNI method, so
+ * performance is critical.)
+ */
+INLINE IndirectRef dvmAppendToIndirectRefTable(IndirectRefTable* pRef,
+    u4 cookie, Object* obj)
+{
+    int topIndex = pRef->segmentState.parts.topIndex;
+    if (topIndex == pRef->allocEntries) {
+        /* up against alloc or max limit, call the fancy version */
+        return dvmAddToIndirectRefTable(pRef, cookie, obj);
+    } else {
+        IndirectRef result = dvmObjectToIndirectRef(obj, topIndex, pRef->kind);
+        pRef->table[topIndex++] = obj;
+        pRef->segmentState.parts.topIndex = topIndex;
+        return result;
+    }
+}
+
+/* extra debugging checks */
+bool dvmGetFromIndirectRefTableCheck(IndirectRefTable* pRef, IndirectRef iref);
+
+/*
+ * Given an IndirectRef in the table, return the Object it refers to.
+ *
+ * Returns NULL if iref is invalid.
+ */
+INLINE Object* dvmGetFromIndirectRefTable(IndirectRefTable* pRef,
+    IndirectRef iref)
+{
+    if (!dvmGetFromIndirectRefTableCheck(pRef, iref))
+        return NULL;
+
+    int idx = dvmIndirectRefToIndex(iref);
+    return pRef->table[idx];
+}
+
+/*
+ * Remove an existing entry.
+ *
+ * If the entry is not between the current top index and the bottom index
+ * specified by the cookie, we don't remove anything.  This is the behavior
+ * required by JNI's DeleteLocalRef function.
+ *
+ * Returns "false" if nothing was removed.
+ */
+bool dvmRemoveFromIndirectRefTable(IndirectRefTable* pRef, u4 cookie,
+    IndirectRef iref);
+
+/*
+ * Dump the contents of a reference table to the log file.
+ */
+void dvmDumpIndirectRefTable(const IndirectRefTable* pRef, const char* descr);
+
+#endif /*_DALVIK_INDIRECTREFTABLE*/
diff --git a/vm/Init.c b/vm/Init.c
index 176910c..c46de25 100644
--- a/vm/Init.c
+++ b/vm/Init.c
@@ -20,6 +20,7 @@
 #include "Dalvik.h"
 #include "test/Test.h"
 #include "mterp/Mterp.h"
+#include "Hash.h"
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -49,6 +50,11 @@
 /* global state */
 struct DvmGlobals gDvm;
 
+/* JIT-specific global state */
+#if defined(WITH_JIT)
+struct DvmJitGlobals gDvmJit;
+#endif
+
 /*
  * Show usage.
  *
@@ -83,8 +89,13 @@
         kMinStackSize / 1024, kMaxStackSize / 1024);
     dvmFprintf(stderr, "  -Xverify:{none,remote,all}\n");
     dvmFprintf(stderr, "  -Xrs\n");
+#if defined(WITH_JIT)
+    dvmFprintf(stderr,
+                "  -Xint  (extended to accept ':portable', ':fast' and ':jit')\n");
+#else
     dvmFprintf(stderr,
                 "  -Xint  (extended to accept ':portable' and ':fast')\n");
+#endif
     dvmFprintf(stderr, "\n");
     dvmFprintf(stderr, "These are unique to Dalvik:\n");
     dvmFprintf(stderr, "  -Xzygote\n");
@@ -95,8 +106,21 @@
     dvmFprintf(stderr, "  -Xjniopts:{warnonly,forcecopy}\n");
     dvmFprintf(stderr, "  -Xdeadlockpredict:{off,warn,err,abort}\n");
     dvmFprintf(stderr, "  -Xstacktracefile:<filename>\n");
+    dvmFprintf(stderr, "  -Xgc:[no]precise\n");
     dvmFprintf(stderr, "  -Xgenregmap\n");
     dvmFprintf(stderr, "  -Xcheckdexsum\n");
+#if defined(WITH_JIT)
+    dvmFprintf(stderr, "  -Xincludeselectedop\n");
+    dvmFprintf(stderr, "  -Xjitop:hexopvalue[-endvalue]"
+                       "[,hexopvalue[-endvalue]]*\n");
+    dvmFprintf(stderr, "  -Xincludeselectedmethod\n");
+    dvmFprintf(stderr, "  -Xthreshold:decimalvalue\n");
+    dvmFprintf(stderr, "  -Xblocking\n");
+    dvmFprintf(stderr, "  -Xjitmethod:signture[,signature]* "
+                       "(eg Ljava/lang/String\\;replace)\n");
+    dvmFprintf(stderr, "  -Xjitverbose\n");
+    dvmFprintf(stderr, "  -Xjitprofile\n");
+#endif
     dvmFprintf(stderr, "\n");
     dvmFprintf(stderr, "Configured with:"
 #ifdef WITH_DEBUGGER
@@ -132,6 +156,9 @@
 #ifdef WITH_EXTRA_OBJECT_VALIDATION
         " extra_object_validation"
 #endif
+#ifdef WITH_EXTRA_GC_CHECKS
+        " extra_gc_checks"
+#endif
 #ifdef WITH_DALVIK_ASSERT
         " dalvik_assert"
 #endif
@@ -157,6 +184,9 @@
 #elif DVM_RESOLVER_CACHE == DVM_RC_NO_CACHE
         " resolver_cache_disabled"
 #endif
+#if defined(WITH_JIT)
+        " with_jit"
+#endif
     );
 #ifdef DVM_SHOW_EXCEPTION
     dvmFprintf(stderr, " show_exception=%d", DVM_SHOW_EXCEPTION);
@@ -527,6 +557,97 @@
     free(gDvm.assertionCtrl);
 }
 
+#if defined(WITH_JIT)
+/* Parse -Xjitop to selectively turn on/off certain opcodes for JIT */
+static void processXjitop(const char *opt)
+{
+    if (opt[7] == ':') {
+        const char *startPtr = &opt[8];
+        char *endPtr = NULL;
+
+        do {
+            long startValue, endValue;
+
+            startValue = strtol(startPtr, &endPtr, 16);
+            if (startPtr != endPtr) {
+                /* Just in case value is out of range */
+                startValue &= 0xff;
+
+                if (*endPtr == '-') {
+                    endValue = strtol(endPtr+1, &endPtr, 16);
+                    endValue &= 0xff;
+                } else {
+                    endValue = startValue;
+                }
+
+                for (; startValue <= endValue; startValue++) {
+                    LOGW("Dalvik opcode %x is selected for debugging",
+                         (unsigned int) startValue);
+                    /* Mark the corresponding bit to 1 */
+                    gDvmJit.opList[startValue >> 3] |=
+                        1 << (startValue & 0x7);
+                }
+
+                if (*endPtr == 0) {
+                    break;
+                }
+
+                startPtr = endPtr + 1;
+
+                continue;
+            } else {
+                if (*endPtr != 0) {
+                    dvmFprintf(stderr,
+                        "Warning: Unrecognized opcode value substring "
+                        "%s\n", endPtr);
+                }
+                break;
+            }
+        } while (1);
+    } else {
+        int i;
+        for (i = 0; i < 32; i++) {
+            gDvmJit.opList[i] = 0xff;
+        }
+        dvmFprintf(stderr, "Warning: select all opcodes\n");
+    }
+}
+
+/* Parse -Xjitmethod to selectively turn on/off certain methods for JIT */
+static void processXjitmethod(const char *opt)
+{
+    char *buf = strdup(&opt[12]);
+    char *start, *end;
+
+    gDvmJit.methodTable = dvmHashTableCreate(8, NULL);
+
+    start = buf;
+    /* 
+     * Break comma-separated method signatures and enter them into the hash
+     * table individually.
+     */
+    do {
+        int hashValue;
+
+        end = strchr(start, ',');
+        if (end) {
+            *end = 0;
+        }
+
+        hashValue = dvmComputeUtf8Hash(start);
+
+        dvmHashTableLookup(gDvmJit.methodTable, hashValue,
+                           strdup(start),
+                           (HashCompareFunc) strcmp, true);
+        if (end) {
+            start = end + 1;
+        } else {
+            break;
+        }
+    } while (1);
+    free(buf);
+}
+#endif
 
 /*
  * Process an argument vector full of options.  Unlike standard C programs,
@@ -756,6 +877,10 @@
                     gDvm.executionMode = kExecutionModeInterpPortable;
                 else if (strcmp(argv[i] + 6, "fast") == 0)
                     gDvm.executionMode = kExecutionModeInterpFast;
+#ifdef WITH_JIT
+                else if (strcmp(argv[i] + 6, "jit") == 0)
+                    gDvm.executionMode = kExecutionModeJit;
+#endif
                 else {
                     dvmFprintf(stderr,
                         "Warning: Unrecognized interpreter mode %s\n",argv[i]);
@@ -765,6 +890,25 @@
                 /* disable JIT -- nothing to do here for now */
             }
 
+#ifdef WITH_JIT
+        } else if (strncmp(argv[i], "-Xjitop", 7) == 0) {
+            processXjitop(argv[i]);
+        } else if (strncmp(argv[i], "-Xjitmethod", 11) == 0) {
+            processXjitmethod(argv[i]);
+        } else if (strncmp(argv[i], "-Xblocking", 10) == 0) {
+          gDvmJit.blockingMode = true;
+        } else if (strncmp(argv[i], "-Xthreshold:", 12) == 0) {
+          gDvmJit.threshold = atoi(argv[i] + 12);
+        } else if (strncmp(argv[i], "-Xincludeselectedop", 19) == 0) {
+          gDvmJit.includeSelectedOp = true;
+        } else if (strncmp(argv[i], "-Xincludeselectedmethod", 23) == 0) {
+          gDvmJit.includeSelectedMethod = true;
+        } else if (strncmp(argv[i], "-Xjitverbose", 12) == 0) {
+          gDvmJit.printMe = true;
+        } else if (strncmp(argv[i], "-Xjitprofile", 12) == 0) {
+          gDvmJit.profile = true;
+#endif
+
         } else if (strncmp(argv[i], "-Xdeadlockpredict:", 18) == 0) {
 #ifdef WITH_DEADLOCK_PREDICTION
             if (strcmp(argv[i] + 18, "off") == 0)
@@ -788,6 +932,18 @@
 
         } else if (strcmp(argv[i], "-Xgenregmap") == 0) {
             gDvm.generateRegisterMaps = true;
+            LOGV("Register maps will be generated during verification\n");
+
+        } else if (strncmp(argv[i], "-Xgc:", 5) == 0) {
+            if (strcmp(argv[i] + 5, "precise") == 0)
+                gDvm.preciseGc = true;
+            else if (strcmp(argv[i] + 5, "noprecise") == 0)
+                gDvm.preciseGc = false;
+            else {
+                dvmFprintf(stderr, "Bad value for -Xgc");
+                return -1;
+            }
+            LOGD("Precise GC configured %s\n", gDvm.preciseGc ? "ON" : "OFF");
 
         } else if (strcmp(argv[i], "-Xcheckdexsum") == 0) {
             gDvm.verifyDexChecksum = true;
@@ -810,6 +966,8 @@
 
 /*
  * Set defaults for fields altered or modified by arguments.
+ *
+ * Globals are initialized to 0 (a/k/a NULL or false).
  */
 static void setCommandLineDefaults()
 {
@@ -849,7 +1007,19 @@
      * we know we're using the "desktop" build we should probably be
      * using "portable" rather than "fast".
      */
+#if defined(WITH_JIT)
+    gDvm.executionMode = kExecutionModeJit;
+    /* 
+     * TODO - check system property and insert command-line options in 
+     *        frameworks/base/core/jni/AndroidRuntime.cpp
+     */
+    gDvmJit.blockingMode = false;
+    gDvmJit.jitTableSize = 512;
+    gDvmJit.jitTableMask = gDvmJit.jitTableSize - 1;
+    gDvmJit.threshold = 200;
+#else
     gDvm.executionMode = kExecutionModeInterpFast;
+#endif
 }
 
 
@@ -886,6 +1056,9 @@
     sigemptyset(&mask);
     sigaddset(&mask, SIGQUIT);
     sigaddset(&mask, SIGUSR1);      // used to initiate heap dump
+#if defined(WITH_JIT) && defined(WITH_JIT_TUNING)
+    sigaddset(&mask, SIGUSR2);      // used to investigate JIT internals
+#endif
     //sigaddset(&mask, SIGPIPE);
     cc = sigprocmask(SIG_BLOCK, &mask, NULL);
     assert(cc == 0);
@@ -936,6 +1109,22 @@
         goto fail;
     }
 
+#if WITH_EXTRA_GC_CHECKS > 1
+    /* only "portable" interp has the extra goodies */
+    if (gDvm.executionMode != kExecutionModeInterpPortable) {
+        LOGI("Switching to 'portable' interpreter for GC checks\n");
+        gDvm.executionMode = kExecutionModeInterpPortable;
+    }
+#endif
+
+    /* Configure group scheduling capabilities */
+    if (!access("/dev/cpuctl/tasks", F_OK)) {
+        LOGV("Using kernel group scheduling");
+        gDvm.kernelGroupScheduling = 1;
+    } else {
+        LOGV("Using kernel scheduler policies");
+    }
+
     /* configure signal handling */
     if (!gDvm.reduceSignals)
         blockSignals();
@@ -957,6 +1146,8 @@
         goto fail;
     if (!dvmVerificationStartup())
         goto fail;
+    if (!dvmRegisterMapStartup())
+        goto fail;
     if (!dvmInstanceofStartup())
         goto fail;
     if (!dvmClassStartup())
@@ -1028,7 +1219,7 @@
      * Do some "late" initialization for the memory allocator.  This may
      * allocate storage and initialize classes.
      */
-    if (!dvmGcLateInit())
+    if (!dvmCreateStockExceptions())
         goto fail;
 
     /*
@@ -1058,7 +1249,10 @@
 
 
 #ifndef NDEBUG
-    dvmTestHash();
+    if (!dvmTestHash())
+        LOGE("dmvTestHash FAILED\n");
+    if (false /*noisy!*/ && !dvmTestIndirectRefTable())
+        LOGE("dvmTestIndirectRefTable FAILED\n");
 #endif
 
     assert(!dvmCheckException(dvmThreadSelf()));
@@ -1167,6 +1361,11 @@
         (int)(endHeap-startHeap), (int)(endQuit-startQuit),
         (int)(endJdwp-startJdwp), (int)(endJdwp-startHeap));
 
+#ifdef WITH_JIT
+    if (!dvmJitStartup())
+        return false;
+#endif
+
     return true;
 }
 
@@ -1290,6 +1489,8 @@
         goto fail;
     if (!dvmVerificationStartup())
         goto fail;
+    if (!dvmRegisterMapStartup())
+        goto fail;
     if (!dvmInstanceofStartup())
         goto fail;
     if (!dvmClassStartup())
@@ -1350,6 +1551,11 @@
     /* shut down stdout/stderr conversion */
     dvmStdioConverterShutdown();
 
+#ifdef WITH_JIT
+    /* tell the compiler to shut down if it was started */
+    dvmJitShutdown();
+#endif
+
     /*
      * Kill any daemon threads that still exist.  Actively-running threads
      * are likely to crash the process if they continue to execute while
@@ -1370,6 +1576,7 @@
     dvmThreadShutdown();
     dvmClassShutdown();
     dvmVerificationShutdown();
+    dvmRegisterMapShutdown();
     dvmInstanceofShutdown();
     dvmInlineNativeShutdown();
     dvmGcShutdown();
diff --git a/vm/Init.h b/vm/Init.h
index 8549338..63051a2 100644
--- a/vm/Init.h
+++ b/vm/Init.h
@@ -41,9 +41,14 @@
     DexClassVerifyMode verifyMode, int dexoptFlags);
 
 /*
- * Unconditionally abort the entire VM.  Try not to use this.
+ * Replacement for fprintf() when we want to send a message to the console.
+ * This defaults to fprintf(), but will use the JNI fprintf callback if
+ * one was provided.
  */
-int dvmFprintf(FILE* fp, const char* format, ...);
-void dvmAbort(void);
+int dvmFprintf(FILE* fp, const char* format, ...)
+#if defined(__GNUC__)
+    __attribute__ ((format(printf, 2, 3)))
+#endif
+    ;
 
 #endif /*_DALVIK_INIT*/
diff --git a/vm/InlineNative.c b/vm/InlineNative.c
index 49025a6..f829360 100644
--- a/vm/InlineNative.c
+++ b/vm/InlineNative.c
@@ -20,6 +20,8 @@
  */
 #include "Dalvik.h"
 
+#include <math.h>
+
 #ifdef HAVE__MEMCMP16
 /* hand-coded assembly implementation, available on some platforms */
 //#warning "trying memcmp16"
@@ -388,6 +390,154 @@
 
 /*
  * ===========================================================================
+ *      java.lang.Math
+ * ===========================================================================
+ */
+
+/*
+ * public static int abs(int)
+ */
+static bool javaLangMath_abs_int(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+    JValue* pResult)
+{
+    s4 val = (s4) arg0;
+    pResult->i = (val >= 0) ? val : -val;
+    return true;
+}
+
+/*
+ * public static long abs(long)
+ */
+static bool javaLangMath_abs_long(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+    JValue* pResult)
+{
+    union {
+        u4 arg[2];
+        s8 ll;
+    } convert;
+
+    convert.arg[0] = arg0;
+    convert.arg[1] = arg1;
+    s8 val = convert.ll;
+    pResult->j = (val >= 0) ? val : -val;
+    return true;
+}
+
+/*
+ * public static float abs(float)
+ */
+static bool javaLangMath_abs_float(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+    JValue* pResult)
+{
+    union {
+        u4 arg;
+        float ff;
+    } convert;
+
+    /* clear the sign bit; assumes a fairly common fp representation */
+    convert.arg = arg0 & 0x7fffffff;
+    pResult->f = convert.ff;
+    return true;
+}
+
+/*
+ * public static double abs(double)
+ */
+static bool javaLangMath_abs_double(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+    JValue* pResult)
+{
+    union {
+        u4 arg[2];
+        s8 ll;
+        double dd;
+    } convert;
+
+    /* clear the sign bit in the (endian-dependent) high word */
+    convert.arg[0] = arg0;
+    convert.arg[1] = arg1;
+    convert.ll &= 0x7fffffffffffffffULL;
+    pResult->d = convert.dd;
+    return true;
+}
+
+/*
+ * public static int min(int)
+ */
+static bool javaLangMath_min_int(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+    JValue* pResult)
+{
+    pResult->i = ((s4) arg0 < (s4) arg1) ? arg0 : arg1;
+    return true;
+}
+
+/*
+ * public static int max(int)
+ */
+static bool javaLangMath_max_int(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+    JValue* pResult)
+{
+    pResult->i = ((s4) arg0 > (s4) arg1) ? arg0 : arg1;
+    return true;
+}
+
+/*
+ * public static double sqrt(double)
+ *
+ * With ARM VFP enabled, gcc turns this into an fsqrtd instruction, followed
+ * by an fcmpd of the result against itself.  If it doesn't match (i.e.
+ * it's NaN), the libm sqrt() is invoked.
+ */
+static bool javaLangMath_sqrt(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+    JValue* pResult)
+{
+    union {
+        u4 arg[2];
+        double dd;
+    } convert;
+
+    convert.arg[0] = arg0;
+    convert.arg[1] = arg1;
+    pResult->d = sqrt(convert.dd);
+    return true;
+}
+
+/*
+ * public static double cos(double)
+ */
+static bool javaLangMath_cos(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+    JValue* pResult)
+{
+    union {
+        u4 arg[2];
+        double dd;
+    } convert;
+
+    convert.arg[0] = arg0;
+    convert.arg[1] = arg1;
+    pResult->d = cos(convert.dd);
+    return true;
+}
+
+/*
+ * public static double sin(double)
+ */
+static bool javaLangMath_sin(u4 arg0, u4 arg1, u4 arg2, u4 arg3,
+    JValue* pResult)
+{
+    union {
+        u4 arg[2];
+        double dd;
+    } convert;
+
+    convert.arg[0] = arg0;
+    convert.arg[1] = arg1;
+    pResult->d = sin(convert.dd);
+    return true;
+}
+
+
+/*
+ * ===========================================================================
  *      Infrastructure
  * ===========================================================================
  */
@@ -400,12 +550,14 @@
  * pointer field.
  *
  * IMPORTANT: you must update DALVIK_VM_BUILD in DalvikVersion.h if you make
- * changes to this table.
+ * changes to this table.  Must also be kept in sync with NativeInlineOps
+ * enum in InlineNative.h.
  */
 const InlineOperation gDvmInlineOpsTable[] = {
     { org_apache_harmony_dalvik_NativeTestTarget_emptyInlineMethod,
         "Lorg/apache/harmony/dalvik/NativeTestTarget;",
         "emptyInlineMethod", "()V" },
+
     { javaLangString_charAt,
         "Ljava/lang/String;", "charAt", "(I)C" },
     { javaLangString_compareTo,
@@ -414,6 +566,25 @@
         "Ljava/lang/String;", "equals", "(Ljava/lang/Object;)Z" },
     { javaLangString_length,
         "Ljava/lang/String;", "length", "()I" },
+
+    { javaLangMath_abs_int,
+        "Ljava/lang/Math;", "abs", "(I)I" },
+    { javaLangMath_abs_long,
+        "Ljava/lang/Math;", "abs", "(J)J" },
+    { javaLangMath_abs_float,
+        "Ljava/lang/Math;", "abs", "(F)F" },
+    { javaLangMath_abs_double,
+        "Ljava/lang/Math;", "abs", "(D)D" },
+    { javaLangMath_min_int,
+        "Ljava/lang/Math;", "min", "(II)I" },
+    { javaLangMath_max_int,
+        "Ljava/lang/Math;", "max", "(II)I" },
+    { javaLangMath_sqrt,
+        "Ljava/lang/Math;", "sqrt", "(D)D" },
+    { javaLangMath_cos,
+        "Ljava/lang/Math;", "cos", "(D)D" },
+    { javaLangMath_sin,
+        "Ljava/lang/Math;", "sin", "(D)D" },
 };
 
 
@@ -525,4 +696,3 @@
 #endif
     return (*gDvmInlineOpsTable[opIndex].func)(arg0, arg1, arg2, arg3, pResult);
 }
-
diff --git a/vm/InlineNative.h b/vm/InlineNative.h
index a6177a6..98398da 100644
--- a/vm/InlineNative.h
+++ b/vm/InlineNative.h
@@ -48,6 +48,24 @@
     const char*     methodSignature;
 } InlineOperation;
 
+/* Must be kept in sync w/ gDvmInlineOpsTable in InlineNative.c */
+typedef enum NativeInlineOps {
+    INLINE_EMPTYINLINEMETHOD = 0,
+    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,
+} NativeInlineOps;
+
 /*
  * Get the inlineops table.
  */
diff --git a/vm/Inlines.c b/vm/Inlines.c
index 57405e3..e314448 100644
--- a/vm/Inlines.c
+++ b/vm/Inlines.c
@@ -21,6 +21,7 @@
 #define _DALVIK_GEN_INLINES
 #include "Dalvik.h"
 #include "analysis/CodeVerify.h"
+#include "analysis/RegisterMap.h"
 #include "mterp/c/header.c"
 
 #undef LOG_TAG
diff --git a/vm/JarFile.c b/vm/JarFile.c
index 4a4eb62..0a58390 100644
--- a/vm/JarFile.c
+++ b/vm/JarFile.c
@@ -261,7 +261,8 @@
                     dexGetZipEntryCrc32(&archive, entry),
                     isBootstrap, &newFile, /*createIfMissing=*/true);
             if (fd < 0) {
-                LOGI("Unable to open or create cache for %s\n", fileName);
+                LOGI("Unable to open or create cache for %s (%s)\n",
+                    fileName, cachedName);
                 goto bail;
             }
             locked = true;
diff --git a/vm/Jni.c b/vm/Jni.c
index 0248e8f..10afcaa 100644
--- a/vm/Jni.c
+++ b/vm/Jni.c
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 /*
  * Dalvik implementation of JNI interfaces.
  */
@@ -47,19 +48,21 @@
 
 General notes on local/global reference tracking
 
-JNI provides explicit control over natively-held references that the VM GC
+JNI provides explicit control over natively-held references that the GC
 needs to know about.  These can be local, in which case they're released
-when the native method returns, or global, which are held until explicitly
-released.
+when the native method returns into the VM, or global, which are held
+until explicitly released.  (There are also weak-global references,
+which have the lifespan and visibility of global references, but the
+object they refer to may be collected.)
 
-The references can be created and deleted with JNI NewLocalRef /
-NewGlobalRef calls, but this is unusual except perhaps for holding on
-to a Class reference.  Most often they are created transparently by the
-JNI functions.  For example, the paired Get/Release calls guarantee that
-objects survive until explicitly released, so a simple way to implement
-this is to create a global reference on "Get" and delete it on "Release".
-The AllocObject/NewObject functions must create local references, because
-nothing else in the GC root set has a reference to the new objects.
+The references can be created with explicit JNI NewLocalRef / NewGlobalRef
+calls.  The former is very unusual, the latter is reasonably common
+(e.g. for caching references to class objects).
+
+Local references are most often created as a side-effect of JNI functions.
+For example, the AllocObject/NewObject functions must create local
+references to the objects returned, because nothing else in the GC root
+set has a reference to the new objects.
 
 The most common mode of operation is for a method to create zero or
 more local references and return.  Explicit "local delete" operations
@@ -70,38 +73,52 @@
 pathological situations, we need to reclaim the space used by deleted
 entries.
 
-The simplest implementation is an expanding append-only array that compacts
-when objects are deleted.  In typical situations, e.g. running through
-an array of objects, we will be deleting one of the most recently added
-entries, so we can minimize the number of elements moved (or avoid having
-to move any).
+If we just want to maintain a list for the GC root set, we can use an
+expanding append-only array that compacts when objects are deleted.
+In typical situations, e.g. running through an array of objects, we will
+be deleting one of the most recently added entries, so we can minimize
+the number of elements moved (or avoid having to move any).
+
+If we want to conceal the pointer values from native code, which is
+necessary to allow the GC to move JNI-referenced objects around, then we
+have to use a more complicated indirection mechanism.
 
 The spec says, "Local references are only valid in the thread in which
 they are created.  The native code must not pass local references from
-one thread to another."  It should also be noted that, while some calls
-will *create* global references as a side-effect, only the NewGlobalRef
-and NewWeakGlobalRef calls actually *return* global references.
+one thread to another."
+
+
+Pinned objects
+
+For some large chunks of data, notably primitive arrays and String data,
+JNI allows the VM to choose whether it wants to pin the array object or
+make a copy.  We currently pin the memory for better execution performance.
+
+TODO: we're using simple root set references to pin primitive array data,
+because they have the property we need (i.e. the pointer we return is
+guaranteed valid until we explicitly release it).  However, if we have a
+compacting GC and don't want to pin all memory held by all global refs,
+we need to treat these differently.
 
 
 Global reference tracking
 
 There should be a small "active" set centered around the most-recently
-added items.  We can use an append-only, compacting array like we do for
-local refs.
+added items.
 
-Because it's global, access to it has to be synchronized.
+Because it's global, access to it has to be synchronized.  Additions and
+removals require grabbing a mutex.  If the table serves as an indirection
+mechanism (i.e. it's not just a list for the benefit of the garbage
+collector), reference lookups may also require grabbing a mutex.
 
 The JNI spec does not define any sort of limit, so the list must be able
-to expand.  It may be useful to log significant increases in usage to
-help identify resource leaks.
+to expand to a reasonable size.  It may be useful to log significant
+increases in usage to help identify resource leaks.
 
-TODO: we currently use global references on strings and primitive array
-data, because they have the property we need (i.e. the pointer we return
-is guaranteed valid until we explicitly release it).  However, if we have
-a compacting GC and don't want to pin all memory held by all global refs,
-we actually want to treat these differently.  Either we need a way to
-tell the GC that specific global references are pinned, or we have to
-make a copy of the data and return that instead (something JNI supports).
+
+Weak-global reference tracking
+
+[TBD]
 
 
 Local reference tracking
@@ -174,14 +191,14 @@
 
 *** Approach #2: use a parallel stack
 
-Each Thread/JNIEnv points to a ReferenceTable struct.  The struct
-has a system-heap-allocated array of references and a pointer to the
+Each Thread/JNIEnv points to a reference table.  The struct has
+a system-heap-allocated array of references and a pointer to the
 next-available entry ("nextEntry").
 
-Each stack frame has a pointer to what it sees as the "top" element in the
-array (we can double-up the "currentPc" field).  This is set to "nextEntry"
-when the frame is pushed on.  As local references are added or removed,
-"nextEntry" is updated.
+Each stack frame has a pointer to what it sees as the "bottom" element
+in the array (we can double-up the "currentPc" field).  This is set to
+"nextEntry" when the frame is pushed on.  As local references are added
+or removed, "nextEntry" is updated.
 
 We implement Push/PopLocalFrame with actual stack frames.  Before a JNI
 frame gets popped, we set "nextEntry" to the "top" pointer of the current
@@ -219,14 +236,13 @@
 
 /* fwd */
 static const struct JNINativeInterface gNativeInterface;
-static jobject addGlobalReference(jobject obj);
-
+static jobject addGlobalReference(Object* obj);
 
 #ifdef WITH_JNI_STACK_CHECK
 # define COMPUTE_STACK_SUM(_self)   computeStackSum(_self);
 # define CHECK_STACK_SUM(_self)     checkStackSum(_self);
-static void computeStackSum(Thread* self);
-static void checkStackSum(Thread* self);
+//static void computeStackSum(Thread* self);
+//static void checkStackSum(Thread* self);
 #else
 # define COMPUTE_STACK_SUM(_self)   ((void)0)
 # define CHECK_STACK_SUM(_self)     ((void)0)
@@ -235,85 +251,6 @@
 
 /*
  * ===========================================================================
- *      JNI call bridge
- * ===========================================================================
- */
-
-/*
- * Bridge to calling a JNI function.  This ideally gets some help from
- * assembly language code in dvmPlatformInvoke, because the arguments
- * must be pushed into the native stack as if we were calling a <stdarg.h>
- * function.
- *
- * The number of values in "args" must match method->insSize.
- *
- * This is generally just set up by the resolver and then called through.
- * We don't call here explicitly.  This takes the same arguments as all
- * of the "internal native" methods.
- */
-void dvmCallJNIMethod(const u4* args, JValue* pResult, const Method* method,
-    Thread* self)
-{
-    int oldStatus;
-
-    assert(method->insns != NULL);
-
-    //int i;
-    //LOGI("JNI calling %p (%s.%s %s):\n", method->insns,
-    //    method->clazz->descriptor, method->name, method->signature);
-    //for (i = 0; i < method->insSize; i++)
-    //    LOGI("  %d: 0x%08x\n", i, args[i]);
-
-    oldStatus = dvmChangeStatus(self, THREAD_NATIVE);
-
-    COMPUTE_STACK_SUM(self);
-    // TODO: should we be converting 'this' to a local ref?
-    dvmPlatformInvoke(self->jniEnv,
-        dvmIsStaticMethod(method) ? method->clazz : NULL,
-        method->jniArgInfo, method->insSize, args, method->shorty,
-        (void*)method->insns, pResult);
-    CHECK_STACK_SUM(self);
-
-    dvmChangeStatus(self, oldStatus);
-}
-
-/*
- * Alternate call bridge for the unusual case of a synchronized native method.
- *
- * Lock the object, then call through the usual function.
- */
-void dvmCallSynchronizedJNIMethod(const u4* args, JValue* pResult,
-    const Method* method, Thread* self)
-{
-    Object* lockObj;
-
-    assert(dvmIsSynchronizedMethod(method));
-
-    if (dvmIsStaticMethod(method))
-        lockObj = (Object*) method->clazz;
-    else
-        lockObj = (Object*) args[0];
-
-    LOGVV("Calling %s.%s: locking %p (%s)\n",
-        method->clazz->descriptor, method->name,
-        lockObj, lockObj->clazz->descriptor);
-
-    dvmLockObject(self, lockObj);
-    dvmCallJNIMethod(args, pResult, method, self);
-    dvmUnlockObject(self, lockObj);
-}
-
-/*
- * Extract the return type enum from the "jniArgInfo" field.
- */
-DalvikJniReturnType dvmGetArgInfoReturnType(int jniArgInfo)
-{
-    return (jniArgInfo & DALVIK_JNI_RETURN_MASK) >> DALVIK_JNI_RETURN_SHIFT;
-}
-
-
-/*
- * ===========================================================================
  *      Utility functions
  * ===========================================================================
  */
@@ -346,26 +283,41 @@
         COMPUTE_STACK_SUM(_self)
 
 #define kGlobalRefsTableInitialSize 512
-#define kGlobalRefsTableMaxSize     51200       /* arbitrary */
+#define kGlobalRefsTableMaxSize     51200       /* arbitrary, must be < 64K */
 #define kGrefWaterInterval          100
-
 #define kTrackGrefUsage             true
 
+#define kPinTableInitialSize        16
+#define kPinTableMaxSize            1024
+#define kPinComplainThreshold       10
+
 /*
  * Allocate the global references table, and look up some classes for
  * the benefit of direct buffer access.
  */
 bool dvmJniStartup(void)
 {
+#ifdef USE_INDIRECT_REF
+    if (!dvmInitIndirectRefTable(&gDvm.jniGlobalRefTable,
+            kGlobalRefsTableInitialSize, kGlobalRefsTableMaxSize,
+            kIndirectKindGlobal))
+        return false;
+#else
     if (!dvmInitReferenceTable(&gDvm.jniGlobalRefTable,
             kGlobalRefsTableInitialSize, kGlobalRefsTableMaxSize))
         return false;
+#endif
 
     dvmInitMutex(&gDvm.jniGlobalRefLock);
-
     gDvm.jniGlobalRefLoMark = 0;
     gDvm.jniGlobalRefHiMark = kGrefWaterInterval * 2;
 
+    if (!dvmInitReferenceTable(&gDvm.jniPinRefTable,
+            kPinTableInitialSize, kPinTableMaxSize))
+        return false;
+
+    dvmInitMutex(&gDvm.jniPinRefLock);
+
     /*
      * Look up and cache pointers to some direct buffer classes, fields,
      * and methods.
@@ -390,10 +342,11 @@
         LOGE("Unable to find internal direct buffer classes\n");
         return false;
     }
-    /* needs to be a global ref so CheckJNI thinks we're allowed to see it */
-    gDvm.classOrgApacheHarmonyNioInternalDirectBuffer =
-        addGlobalReference((Object*) directBufferClass);
     gDvm.classJavaNioReadWriteDirectByteBuffer = readWriteBufferClass;
+    gDvm.classOrgApacheHarmonyNioInternalDirectBuffer = directBufferClass;
+    /* need a global reference for extended CheckJNI tests */
+    gDvm.jclassOrgApacheHarmonyNioInternalDirectBuffer =
+        addGlobalReference((Object*) directBufferClass);
 
     /*
      * We need a Method* here rather than a vtable offset, because
@@ -465,7 +418,11 @@
  */
 void dvmJniShutdown(void)
 {
+#ifdef USE_INDIRECT_REF
+    dvmClearIndirectRefTable(&gDvm.jniGlobalRefTable);
+#else
     dvmClearReferenceTable(&gDvm.jniGlobalRefTable);
+#endif
 }
 
 
@@ -571,14 +528,70 @@
 /*
  * Retrieve the ReferenceTable struct for the current thread.
  *
- * If we know the code isn't sharing JNIEnv pointers between threads, we
- * could put this into env and skip the TLS lookup.
+ * Going through "env" rather than dvmThreadSelf() is faster but will
+ * get weird if the JNI code is passing the wrong JNIEnv around.
  */
-static inline ReferenceTable* getLocalRefTable(void)
+#ifdef USE_INDIRECT_REF
+static inline IndirectRefTable* getLocalRefTable(JNIEnv* env)
+#else
+static inline ReferenceTable* getLocalRefTable(JNIEnv* env)
+#endif
 {
-    return &dvmThreadSelf()->jniLocalRefTable;
+    //return &dvmThreadSelf()->jniLocalRefTable;
+    return &((JNIEnvExt*)env)->self->jniLocalRefTable;
 }
 
+#ifdef USE_INDIRECT_REF
+/*
+ * Convert an indirect reference to an Object reference.  The indirect
+ * reference may be local, global, or weak-global.
+ *
+ * If "jobj" is NULL or an invalid indirect reference, this returns NULL.
+ */
+Object* dvmDecodeIndirectRef(JNIEnv* env, jobject jobj)
+{
+    if (jobj == NULL)
+        return NULL;
+
+    Object* result;
+
+    switch (dvmGetIndirectRefType(jobj)) {
+    case kIndirectKindLocal:
+        {
+            IndirectRefTable* pRefTable = getLocalRefTable(env);
+            result = dvmGetFromIndirectRefTable(pRefTable, jobj);
+        }
+        break;
+    case kIndirectKindGlobal:
+        {
+            // TODO: find a way to avoid the mutex activity here
+            IndirectRefTable* pRefTable = &gDvm.jniGlobalRefTable;
+            dvmLockMutex(&gDvm.jniGlobalRefLock);
+            result = dvmGetFromIndirectRefTable(pRefTable, jobj);
+            dvmUnlockMutex(&gDvm.jniGlobalRefLock);
+        }
+        break;
+    case kIndirectKindWeakGlobal:
+        {
+            LOGE("weak-global not yet supported\n");
+            result = NULL;
+            dvmAbort();
+        }
+        break;
+    case kIndirectKindInvalid:
+    default:
+        LOGW("Invalid indirect reference %p in decodeIndirectRef\n", jobj);
+        dvmAbort();
+        result = NULL;
+        break;
+    }
+
+    return result;
+}
+#else
+    /* use trivial inline in JniInternal.h for performance */
+#endif
+
 /*
  * Add a local reference for an object to the current stack frame.  When
  * the native function returns, the reference will be discarded.
@@ -591,52 +604,100 @@
  * Returns the local reference (currently just the same pointer that was
  * passed in), or NULL on failure.
  */
-static jobject addLocalReference(jobject obj)
+static jobject addLocalReference(JNIEnv* env, Object* obj)
 {
     if (obj == NULL)
         return NULL;
 
-    ReferenceTable* pRef = getLocalRefTable();
+    jobject jobj;
 
-    if (!dvmAddToReferenceTable(pRef, (Object*)obj)) {
-        dvmDumpReferenceTable(pRef, "JNI local");
+#ifdef USE_INDIRECT_REF
+    IndirectRefTable* pRefTable = getLocalRefTable(env);
+    void* curFrame = ((JNIEnvExt*)env)->self->curFrame;
+    u4 cookie = SAVEAREA_FROM_FP(curFrame)->xtra.localRefCookie;
+
+    jobj = (jobject) dvmAddToIndirectRefTable(pRefTable, cookie, obj);
+    if (jobj == NULL) {
+        dvmDumpIndirectRefTable(pRefTable, "JNI local");
         LOGE("Failed adding to JNI local ref table (has %d entries)\n",
-            (int) dvmReferenceTableEntries(pRef));
+            (int) dvmIndirectRefTableEntries(pRefTable));
         dvmDumpThread(dvmThreadSelf(), false);
         dvmAbort();     // spec says call FatalError; this is equivalent
     } else {
-        LOGVV("LREF add %p  (%s.%s)\n", obj,
+        LOGVV("LREF add %p  (%s.%s) (ent=%d)\n", obj,
             dvmGetCurrentJNIMethod()->clazz->descriptor,
-            dvmGetCurrentJNIMethod()->name);
+            dvmGetCurrentJNIMethod()->name,
+            (int) dvmReferenceTableEntries(pRefTable));
+    }
+#else
+    ReferenceTable* pRefTable = getLocalRefTable(env);
+
+    if (!dvmAddToReferenceTable(pRefTable, obj)) {
+        dvmDumpReferenceTable(pRefTable, "JNI local");
+        LOGE("Failed adding to JNI local ref table (has %d entries)\n",
+            (int) dvmReferenceTableEntries(pRefTable));
+        dvmDumpThread(dvmThreadSelf(), false);
+        dvmAbort();     // spec says call FatalError; this is equivalent
+    } else {
+        LOGVV("LREF add %p  (%s.%s) (ent=%d)\n", obj,
+            dvmGetCurrentJNIMethod()->clazz->descriptor,
+            dvmGetCurrentJNIMethod()->name,
+            (int) dvmReferenceTableEntries(pRefTable));
     }
 
-    return obj;
+    jobj = (jobject) obj;
+#endif
+
+    return jobj;
 }
 
 /*
  * Ensure that at least "capacity" references can be held in the local
  * refs table of the current thread.
  */
-static bool ensureLocalCapacity(int capacity)
+static bool ensureLocalCapacity(JNIEnv* env, int capacity)
 {
-    ReferenceTable* pRef = getLocalRefTable();
+#ifdef USE_INDIRECT_REF
+    IndirectRefTable* pRefTable = getLocalRefTable(env);
+    int numEntries = dvmIndirectRefTableEntries(pRefTable);
+    // TODO: this isn't quite right, since "numEntries" includes holes
+    return ((kJniLocalRefMax - numEntries) >= capacity);
+#else
+    ReferenceTable* pRefTable = getLocalRefTable(env);
 
-    return (kJniLocalRefMax - (pRef->nextEntry - pRef->table) >= capacity);
+    return (kJniLocalRefMax - (pRefTable->nextEntry - pRefTable->table) >= capacity);
+#endif
 }
 
 /*
  * Explicitly delete a reference from the local list.
  */
-static void deleteLocalReference(jobject obj)
+static void deleteLocalReference(JNIEnv* env, jobject jobj)
 {
-    if (obj == NULL)
+    if (jobj == NULL)
         return;
 
-    ReferenceTable* pRef = getLocalRefTable();
-    Thread* self = dvmThreadSelf();
-    Object** top = SAVEAREA_FROM_FP(self->curFrame)->xtra.localRefTop;
+#ifdef USE_INDIRECT_REF
+    IndirectRefTable* pRefTable = getLocalRefTable(env);
+    Thread* self = ((JNIEnvExt*)env)->self;
+    u4 cookie = SAVEAREA_FROM_FP(self->curFrame)->xtra.localRefCookie;
 
-    if (!dvmRemoveFromReferenceTable(pRef, top, (Object*) obj)) {
+    if (!dvmRemoveFromIndirectRefTable(pRefTable, cookie, jobj)) {
+        /*
+         * Attempting to delete a local reference that is not in the
+         * topmost local reference frame is a no-op.  DeleteLocalRef returns
+         * void and doesn't throw any exceptions, but we should probably
+         * complain about it so the user will notice that things aren't
+         * going quite the way they expect.
+         */
+        LOGW("JNI WARNING: DeleteLocalRef(%p) failed to find entry\n", jobj);
+    }
+#else
+    ReferenceTable* pRefTable = getLocalRefTable(env);
+    Thread* self = ((JNIEnvExt*)env)->self;
+    Object** bottom = SAVEAREA_FROM_FP(self->curFrame)->xtra.localRefCookie;
+
+    if (!dvmRemoveFromReferenceTable(pRefTable, bottom, (Object*) jobj)) {
         /*
          * Attempting to delete a local reference that is not in the
          * topmost local reference frame is a no-op.  DeleteLocalRef returns
@@ -645,8 +706,9 @@
          * going quite the way they expect.
          */
         LOGW("JNI WARNING: DeleteLocalRef(%p) failed to find entry (valid=%d)\n",
-            obj, dvmIsValidObject((Object*) obj));
+            jobj, dvmIsValidObject((Object*) jobj));
     }
+#endif
 }
 
 /*
@@ -655,7 +717,7 @@
  * We may add the same object more than once.  Add/remove calls are paired,
  * so it needs to appear on the list multiple times.
  */
-static jobject addGlobalReference(jobject obj)
+static jobject addGlobalReference(Object* obj)
 {
     if (obj == NULL)
         return NULL;
@@ -682,8 +744,8 @@
     }
     if (false && ((Object*)obj)->clazz == gDvm.classArrayByte) {
         ArrayObject* arrayObj = (ArrayObject*) obj;
-        if (arrayObj->length == 8192 &&
-            dvmReferenceTableEntries(&gDvm.jniGlobalRefTable) > 400)
+        if (arrayObj->length == 8192 /*&&
+            dvmReferenceTableEntries(&gDvm.jniGlobalRefTable) > 400*/)
         {
             LOGI("Adding global ref on byte array %p (len=%d)\n",
                 arrayObj, arrayObj->length);
@@ -691,14 +753,11 @@
         }
     }
 
+    jobject jobj;
+
     dvmLockMutex(&gDvm.jniGlobalRefLock);
 
     /*
-     * Expanding the table should happen rarely, so I'm not overly
-     * concerned about the performance impact of copying the old list
-     * over.  We shouldn't see one-time activity spikes, so freeing
-     * up storage shouldn't be required.
-     *
      * Throwing an exception on failure is problematic, because JNI code
      * may not be expecting an exception, and things sort of cascade.  We
      * want to have a hard limit to catch leaks during debugging, but this
@@ -707,12 +766,51 @@
      * we're either leaking global ref table entries or we're going to
      * run out of space in the GC heap.
      */
-    if (!dvmAddToReferenceTable(&gDvm.jniGlobalRefTable, (Object*)obj)) {
+#ifdef USE_INDIRECT_REF
+    jobj = dvmAddToIndirectRefTable(&gDvm.jniGlobalRefTable, IRT_FIRST_SEGMENT,
+            obj);
+    if (jobj == NULL) {
+        dvmDumpIndirectRefTable(&gDvm.jniGlobalRefTable, "JNI global");
+        LOGE("Failed adding to JNI global ref table (%d entries)\n",
+            (int) dvmIndirectRefTableEntries(&gDvm.jniGlobalRefTable));
+        dvmAbort();
+    }
+
+    LOGVV("GREF add %p  (%s.%s)\n", obj,
+        dvmGetCurrentJNIMethod()->clazz->descriptor,
+        dvmGetCurrentJNIMethod()->name);
+
+    /* GREF usage tracking; should probably be disabled for production env */
+    if (kTrackGrefUsage && gDvm.jniGrefLimit != 0) {
+        int count = dvmIndirectRefTableEntries(&gDvm.jniGlobalRefTable);
+        // TODO: adjust for "holes"
+        if (count > gDvm.jniGlobalRefHiMark) {
+            LOGD("GREF has increased to %d\n", count);
+            gDvm.jniGlobalRefHiMark += kGrefWaterInterval;
+            gDvm.jniGlobalRefLoMark += kGrefWaterInterval;
+
+            /* watch for "excessive" use; not generally appropriate */
+            if (count >= gDvm.jniGrefLimit) {
+                JavaVMExt* vm = (JavaVMExt*) gDvm.vmList;
+                if (vm->warnError) {
+                    dvmDumpIndirectRefTable(&gDvm.jniGlobalRefTable,
+                        "JNI global");
+                    LOGE("Excessive JNI global references (%d)\n", count);
+                    dvmAbort();
+                } else {
+                    LOGW("Excessive JNI global references (%d)\n", count);
+                }
+            }
+        }
+    }
+#else
+    if (!dvmAddToReferenceTable(&gDvm.jniGlobalRefTable, obj)) {
         dvmDumpReferenceTable(&gDvm.jniGlobalRefTable, "JNI global");
         LOGE("Failed adding to JNI global ref table (%d entries)\n",
             (int) dvmReferenceTableEntries(&gDvm.jniGlobalRefTable));
         dvmAbort();
     }
+    jobj = (jobject) obj;
 
     LOGVV("GREF add %p  (%s.%s)\n", obj,
         dvmGetCurrentJNIMethod()->clazz->descriptor,
@@ -739,10 +837,11 @@
             }
         }
     }
+#endif
 
 bail:
     dvmUnlockMutex(&gDvm.jniGlobalRefLock);
-    return obj;
+    return jobj;
 }
 
 /*
@@ -752,18 +851,36 @@
  * Thought: if it's not the most recent entry, just null it out.  When we
  * fill up, do a compaction pass before we expand the list.
  */
-static void deleteGlobalReference(jobject obj)
+static void deleteGlobalReference(jobject jobj)
 {
-    if (obj == NULL)
+    if (jobj == NULL)
         return;
 
     dvmLockMutex(&gDvm.jniGlobalRefLock);
 
+#ifdef USE_INDIRECT_REF
+    if (!dvmRemoveFromIndirectRefTable(&gDvm.jniGlobalRefTable,
+            IRT_FIRST_SEGMENT, jobj))
+    {
+        LOGW("JNI: DeleteGlobalRef(%p) failed to find entry\n", jobj);
+        goto bail;
+    }
+
+    if (kTrackGrefUsage && gDvm.jniGrefLimit != 0) {
+        int count = dvmIndirectRefTableEntries(&gDvm.jniGlobalRefTable);
+        // TODO: not quite right, need to subtract holes
+        if (count < gDvm.jniGlobalRefLoMark) {
+            LOGD("GREF has decreased to %d\n", count);
+            gDvm.jniGlobalRefHiMark -= kGrefWaterInterval;
+            gDvm.jniGlobalRefLoMark -= kGrefWaterInterval;
+        }
+    }
+#else
     if (!dvmRemoveFromReferenceTable(&gDvm.jniGlobalRefTable,
-            gDvm.jniGlobalRefTable.table, obj))
+            gDvm.jniGlobalRefTable.table, jobj))
     {
         LOGW("JNI: DeleteGlobalRef(%p) failed to find entry (valid=%d)\n",
-            obj, dvmIsValidObject((Object*) obj));
+            jobj, dvmIsValidObject((Object*) jobj));
         goto bail;
     }
 
@@ -775,29 +892,125 @@
             gDvm.jniGlobalRefLoMark -= kGrefWaterInterval;
         }
     }
+#endif
 
 bail:
     dvmUnlockMutex(&gDvm.jniGlobalRefLock);
 }
 
 /*
+ * Objects don't currently move, so we just need to create a reference
+ * that will ensure the array object isn't collected.
+ *
+ * We use a separate reference table, which is part of the GC root set.
+ */
+static void pinPrimitiveArray(ArrayObject* arrayObj)
+{
+    if (arrayObj == NULL)
+        return;
+
+    dvmLockMutex(&gDvm.jniPinRefLock);
+    if (!dvmAddToReferenceTable(&gDvm.jniPinRefTable, (Object*)arrayObj)) {
+        dvmDumpReferenceTable(&gDvm.jniPinRefTable, "JNI pinned array");
+        LOGE("Failed adding to JNI pinned array ref table (%d entries)\n",
+            (int) dvmReferenceTableEntries(&gDvm.jniPinRefTable));
+        dvmDumpThread(dvmThreadSelf(), false);
+        dvmAbort();
+    }
+
+    /*
+     * If we're watching global ref usage, also keep an eye on these.
+     *
+     * The total number of pinned primitive arrays should be pretty small.
+     * A single array should not be pinned more than once or twice; any
+     * more than that is a strong indicator that a Release function is
+     * not being called.
+     */
+    if (kTrackGrefUsage && gDvm.jniGrefLimit != 0) {
+        int count = 0;
+        Object** ppObj = gDvm.jniPinRefTable.table;
+        while (ppObj < gDvm.jniPinRefTable.nextEntry) {
+            if (*ppObj++ == (Object*) arrayObj)
+                count++;
+        }
+
+        if (count > kPinComplainThreshold) {
+            LOGW("JNI: pin count on array %p (%s) is now %d\n",
+                arrayObj, arrayObj->obj.clazz->descriptor, count);
+            /* keep going */
+        }
+    }
+
+    dvmUnlockMutex(&gDvm.jniPinRefLock);
+}
+
+/*
+ * Un-pin the array object.  If an object was pinned twice, it must be
+ * unpinned twice before it's free to move.
+ */
+static void unpinPrimitiveArray(ArrayObject* arrayObj)
+{
+    if (arrayObj == NULL)
+        return;
+
+    dvmLockMutex(&gDvm.jniPinRefLock);
+    if (!dvmRemoveFromReferenceTable(&gDvm.jniPinRefTable,
+            gDvm.jniPinRefTable.table, (Object*) arrayObj))
+    {
+        LOGW("JNI: unpinPrimitiveArray(%p) failed to find entry (valid=%d)\n",
+            arrayObj, dvmIsValidObject((Object*) arrayObj));
+        goto bail;
+    }
+
+bail:
+    dvmUnlockMutex(&gDvm.jniPinRefLock);
+}
+
+/*
  * GC helper function to mark all JNI global references.
+ *
+ * We're currently handling the "pin" table here too.
  */
 void dvmGcMarkJniGlobalRefs()
 {
-    Object **op;
+    Object** op;
 
     dvmLockMutex(&gDvm.jniGlobalRefLock);
 
+#ifdef USE_INDIRECT_REF
+    IndirectRefTable* pRefTable = &gDvm.jniGlobalRefTable;
+    op = pRefTable->table;
+    int numEntries = dvmIndirectRefTableEntries(pRefTable);
+    int i;
+
+    for (i = 0; i < numEntries; i++) {
+        Object* obj = *op;
+        if (obj != NULL)
+            dvmMarkObjectNonNull(obj);
+        op++;
+    }
+#else
     op = gDvm.jniGlobalRefTable.table;
     while ((uintptr_t)op < (uintptr_t)gDvm.jniGlobalRefTable.nextEntry) {
         dvmMarkObjectNonNull(*(op++));
     }
+#endif
 
     dvmUnlockMutex(&gDvm.jniGlobalRefLock);
+
+
+    dvmLockMutex(&gDvm.jniPinRefLock);
+
+    op = gDvm.jniPinRefTable.table;
+    while ((uintptr_t)op < (uintptr_t)gDvm.jniPinRefTable.nextEntry) {
+        dvmMarkObjectNonNull(*(op++));
+    }
+
+    dvmUnlockMutex(&gDvm.jniPinRefLock);
 }
 
 
+#ifndef USE_INDIRECT_REF
 /*
  * Determine if "obj" appears in the argument list for the native method.
  *
@@ -868,16 +1081,17 @@
     }
     return false;
 }
+#endif
 
 /*
  * Verify that a reference passed in from native code is one that the
  * code is allowed to have.
  *
  * It's okay for native code to pass us a reference that:
- *  - was just passed in as an argument when invoked by native code
- *  - was returned to it from JNI (and is now in the JNI local refs table)
+ *  - was passed in as an argument when invoked by native code (and hence
+ *    is in the JNI local refs table)
+ *  - was returned to it from JNI (and is now in the local refs table)
  *  - is present in the JNI global refs table
- * The first one is a little awkward.  The latter two are just table lookups.
  *
  * Used by -Xcheck:jni and GetObjectRefType.
  *
@@ -885,32 +1099,46 @@
  * something is both global and local, we can't tell them apart, and always
  * return "local".
  */
-jobjectRefType dvmGetJNIRefType(Object* obj)
+jobjectRefType dvmGetJNIRefType(JNIEnv* env, jobject jobj)
 {
-    ReferenceTable* pRef = getLocalRefTable();
+#ifdef USE_INDIRECT_REF
+    /*
+     * IndirectRefKind is currently defined as an exact match of
+     * jobjectRefType, so this is easy.  We have to decode it to determine
+     * if it's a valid reference and not merely valid-looking.
+     */
+    Object* obj = dvmDecodeIndirectRef(env, jobj);
+
+    if (obj == NULL) {
+        /* invalid ref, or jobj was NULL */
+        return JNIInvalidRefType;
+    } else {
+        return (jobjectRefType) dvmGetIndirectRefType(jobj);
+    }
+#else
+    ReferenceTable* pRefTable = getLocalRefTable(env);
     Thread* self = dvmThreadSelf();
     //Object** top;
     Object** ptr;
 
     /* check args */
-    if (findInArgList(self, obj)) {
-        //LOGI("--- REF found %p on stack\n", obj);
+    if (findInArgList(self, jobj)) {
+        //LOGI("--- REF found %p on stack\n", jobj);
         return JNILocalRefType;
     }
 
     /* check locals */
-    //top = SAVEAREA_FROM_FP(self->curFrame)->xtra.localRefTop;
-    if (dvmFindInReferenceTable(pRef, pRef->table, obj) != NULL) {
-        //LOGI("--- REF found %p in locals\n", obj);
+    if (dvmFindInReferenceTable(pRefTable, pRefTable->table, jobj) != NULL) {
+        //LOGI("--- REF found %p in locals\n", jobj);
         return JNILocalRefType;
     }
 
     /* check globals */
     dvmLockMutex(&gDvm.jniGlobalRefLock);
     if (dvmFindInReferenceTable(&gDvm.jniGlobalRefTable,
-            gDvm.jniGlobalRefTable.table, obj))
+            gDvm.jniGlobalRefTable.table, jobj))
     {
-        //LOGI("--- REF found %p in globals\n", obj);
+        //LOGI("--- REF found %p in globals\n", jobj);
         dvmUnlockMutex(&gDvm.jniGlobalRefLock);
         return JNIGlobalRefType;
     }
@@ -918,6 +1146,7 @@
 
     /* not found! */
     return JNIInvalidRefType;
+#endif
 }
 
 /*
@@ -953,14 +1182,7 @@
         /* keep going, I guess */
     }
 
-    /*
-     * Point "nativeFunc" at the JNI bridge, and overload "insns" to
-     * point at the actual function.
-     */
-    if (dvmIsSynchronizedMethod(method))
-        dvmSetNativeFunc(method, dvmCallSynchronizedJNIMethod, fnPtr);
-    else
-        dvmSetNativeFunc(method, dvmCallJNIMethod, fnPtr);
+    dvmUseJNIBridge(method, fnPtr);
 
     LOGV("JNI-registered %s.%s %s\n", clazz->descriptor, methodName,
         signature);
@@ -971,6 +1193,78 @@
 }
 
 /*
+ * Returns "true" if CheckJNI is enabled in the VM.
+ */
+static bool dvmIsCheckJNIEnabled(void)
+{
+    JavaVMExt* vm = (JavaVMExt*) gDvm.vmList;
+    return vm->useChecked;
+}
+
+/*
+ * Point "method->nativeFunc" at the JNI bridge, and overload "method->insns"
+ * to point at the actual function.
+ */
+void dvmUseJNIBridge(Method* method, void* func)
+{
+    enum {
+        kJNIGeneral = 0,
+        kJNISync = 1,
+        kJNIVirtualNoRef = 2,
+        kJNIStaticNoRef = 3,
+    } kind;
+    static const DalvikBridgeFunc stdFunc[] = {
+        dvmCallJNIMethod_general,
+        dvmCallJNIMethod_synchronized,
+        dvmCallJNIMethod_virtualNoRef,
+        dvmCallJNIMethod_staticNoRef
+    };
+    static const DalvikBridgeFunc checkFunc[] = {
+        dvmCheckCallJNIMethod_general,
+        dvmCheckCallJNIMethod_synchronized,
+        dvmCheckCallJNIMethod_virtualNoRef,
+        dvmCheckCallJNIMethod_staticNoRef
+    };
+
+    bool hasRefArg = false;
+
+    if (dvmIsSynchronizedMethod(method)) {
+        /* use version with synchronization; calls into general handler */
+        kind = kJNISync;
+    } else {
+        /*
+         * Do a quick scan through the "shorty" signature to see if the method
+         * takes any reference arguments.
+         */
+        const char* cp = method->shorty;
+        while (*++cp != '\0') {     /* pre-incr to skip return type */
+            if (*cp == 'L') {
+                /* 'L' used for both object and array references */
+                hasRefArg = true;
+                break;
+            }
+        }
+
+        if (hasRefArg) {
+            /* use general handler to slurp up reference args */
+            kind = kJNIGeneral;
+        } else {
+            /* virtual methods have a ref in args[0] (not in signature) */
+            if (dvmIsStaticMethod(method))
+                kind = kJNIStaticNoRef;
+            else
+                kind = kJNIVirtualNoRef;
+        }
+    }
+
+    if (dvmIsCheckJNIEnabled()) {
+        dvmSetNativeFunc(method, checkFunc[kind], func);
+    } else {
+        dvmSetNativeFunc(method, stdFunc[kind], func);
+    }
+}
+
+/*
  * Get the method currently being executed by examining the interp stack.
  */
 const Method* dvmGetCurrentJNIMethod(void)
@@ -1020,14 +1314,15 @@
     }
 }
 
+
 /*
  * Track a JNI MonitorExit in the current thread.
  */
 static void trackMonitorExit(Thread* self, Object* obj)
 {
-    ReferenceTable* refTable = &self->jniMonitorRefTable;
+    ReferenceTable* pRefTable = &self->jniMonitorRefTable;
 
-    if (!dvmRemoveFromReferenceTable(refTable, refTable->table, obj)) {
+    if (!dvmRemoveFromReferenceTable(pRefTable, pRefTable->table, obj)) {
         LOGE("JNI monitor %p not found in tracking list\n", obj);
         /* keep going? */
     } else {
@@ -1040,13 +1335,13 @@
  */
 void dvmReleaseJniMonitors(Thread* self)
 {
-    ReferenceTable* refTable = &self->jniMonitorRefTable;
-    Object** top = refTable->table;
+    ReferenceTable* pRefTable = &self->jniMonitorRefTable;
+    Object** top = pRefTable->table;
 
     if (top == NULL)
         return;
 
-    Object** ptr = refTable->nextEntry;
+    Object** ptr = pRefTable->nextEntry;
     while (--ptr >= top) {
         if (!dvmUnlockObject(self, *ptr)) {
             LOGW("Unable to unlock monitor %p at thread detach\n", *ptr);
@@ -1056,7 +1351,7 @@
     }
 
     /* zap it */
-    refTable->nextEntry = refTable->table;
+    pRefTable->nextEntry = pRefTable->table;
 }
 
 #ifdef WITH_JNI_STACK_CHECK
@@ -1116,6 +1411,250 @@
 
 /*
  * ===========================================================================
+ *      JNI call bridge
+ * ===========================================================================
+ */
+
+/*
+ * The functions here form a bridge between interpreted code and JNI native
+ * functions.  The basic task is to convert an array of primitives and
+ * references into C-style function arguments.  This is architecture-specific
+ * and usually requires help from assembly code.
+ *
+ * The bridge takes four arguments: the array of parameters, a place to
+ * store the function result (if any), the method to call, and a pointer
+ * to the current thread.
+ *
+ * These functions aren't called directly from elsewhere in the VM.
+ * A pointer in the Method struct points to one of these, and when a native
+ * method is invoked the interpreter jumps to it.
+ *
+ * (The "internal native" methods are invoked the same way, but instead
+ * of calling through a bridge, the target method is called directly.)
+ *
+ * The "args" array should not be modified, but we do so anyway for
+ * performance reasons.  We know that it points to the "outs" area on
+ * the current method's interpreted stack.  This area is ignored by the
+ * precise GC, because there is no register map for a native method (for
+ * an interpreted method the args would be listed in the argument set).
+ * We know all of the values exist elsewhere on the interpreted stack,
+ * because the method call setup copies them right before making the call,
+ * so we don't have to worry about concealing stuff from the GC.
+ *
+ * If we don't want to modify "args", we either have to create a local
+ * copy and modify it before calling dvmPlatformInvoke, or we have to do
+ * the local reference replacement within dvmPlatformInvoke.  The latter
+ * has some performance advantages, though if we can inline the local
+ * reference adds we may win when there's a lot of reference args (unless
+ * we want to code up some local ref table manipulation in assembly.
+ */
+
+/*
+ * If necessary, convert the value in pResult from a local/global reference
+ * to an object pointer.
+ */
+static inline void convertReferenceResult(JNIEnv* env, JValue* pResult,
+    const Method* method, Thread* self)
+{
+#ifdef USE_INDIRECT_REF
+    if (method->shorty[0] == 'L' && !dvmCheckException(self) &&
+            pResult->l != NULL)
+    {
+        pResult->l = dvmDecodeIndirectRef(env, pResult->l);
+    }
+#endif
+}
+
+/*
+ * General form, handles all cases.
+ */
+void dvmCallJNIMethod_general(const u4* args, JValue* pResult,
+    const Method* method, Thread* self)
+{
+    int oldStatus;
+    u4* modArgs = (u4*) args;
+    jclass staticMethodClass;
+    JNIEnv* env = self->jniEnv;
+
+    assert(method->insns != NULL);
+
+    //LOGI("JNI calling %p (%s.%s:%s):\n", method->insns,
+    //    method->clazz->descriptor, method->name, method->shorty);
+
+#ifdef USE_INDIRECT_REF
+    /*
+     * Walk the argument list, creating local references for appropriate
+     * arguments.
+     */
+    int idx = 0;
+    if (dvmIsStaticMethod(method)) {
+        /* add the class object we pass in */
+        staticMethodClass = addLocalReference(env, (Object*) method->clazz);
+        if (staticMethodClass == NULL) {
+            assert(dvmCheckException(self));
+            return;
+        }
+    } else {
+        /* add "this" */
+        staticMethodClass = NULL;
+        jobject thisObj = addLocalReference(env, (Object*) modArgs[0]);
+        if (thisObj == NULL) {
+            assert(dvmCheckException(self));
+            return;
+        }
+        modArgs[idx] = (u4) thisObj;
+        idx = 1;
+    }
+
+    const char* shorty = &method->shorty[1];        /* skip return type */
+    while (*shorty != '\0') {
+        switch (*shorty++) {
+        case 'L':
+            //LOGI("  local %d: 0x%08x\n", idx, modArgs[idx]);
+            if (modArgs[idx] != 0) {
+                //if (!dvmIsValidObject((Object*) modArgs[idx]))
+                //    dvmAbort();
+                jobject argObj = addLocalReference(env, (Object*) modArgs[idx]);
+                if (argObj == NULL) {
+                    assert(dvmCheckException(self));
+                    return;
+                }
+                modArgs[idx] = (u4) argObj;
+            }
+            break;
+        case 'D':
+        case 'J':
+            idx++;
+            break;
+        default:
+            /* Z B C S I -- do nothing */
+            break;
+        }
+
+        idx++;
+    }
+#else
+    staticMethodClass = dvmIsStaticMethod(method) ?
+        (jclass) method->clazz : NULL;
+#endif
+
+    oldStatus = dvmChangeStatus(self, THREAD_NATIVE);
+
+    COMPUTE_STACK_SUM(self);
+    dvmPlatformInvoke(env, staticMethodClass,
+        method->jniArgInfo, method->insSize, modArgs, method->shorty,
+        (void*)method->insns, pResult);
+    CHECK_STACK_SUM(self);
+
+    dvmChangeStatus(self, oldStatus);
+
+    convertReferenceResult(env, pResult, method, self);
+}
+
+/*
+ * Handler for the unusual case of a synchronized native method.
+ *
+ * Lock the object, then call through the general function.
+ */
+void dvmCallJNIMethod_synchronized(const u4* args, JValue* pResult,
+    const Method* method, Thread* self)
+{
+    Object* lockObj;
+
+    assert(dvmIsSynchronizedMethod(method));
+
+    if (dvmIsStaticMethod(method))
+        lockObj = (Object*) method->clazz;
+    else
+        lockObj = (Object*) args[0];
+
+    LOGVV("Calling %s.%s: locking %p (%s)\n",
+        method->clazz->descriptor, method->name,
+        lockObj, lockObj->clazz->descriptor);
+
+    dvmLockObject(self, lockObj);
+    dvmCallJNIMethod_general(args, pResult, method, self);
+    dvmUnlockObject(self, lockObj);
+}
+
+/*
+ * Virtual method call, no reference arguments.
+ *
+ * We need to local-ref the "this" argument, found in args[0].
+ */
+void dvmCallJNIMethod_virtualNoRef(const u4* args, JValue* pResult,
+    const Method* method, Thread* self)
+{
+    u4* modArgs = (u4*) args;
+    int oldStatus;
+
+#ifdef USE_INDIRECT_REF
+    jobject thisObj = addLocalReference(self->jniEnv, (Object*) args[0]);
+    if (thisObj == NULL) {
+        assert(dvmCheckException(self));
+        return;
+    }
+    modArgs[0] = (u4) thisObj;
+#endif
+
+    oldStatus = dvmChangeStatus(self, THREAD_NATIVE);
+
+    COMPUTE_STACK_SUM(self);
+    dvmPlatformInvoke(self->jniEnv, NULL,
+        method->jniArgInfo, method->insSize, modArgs, method->shorty,
+        (void*)method->insns, pResult);
+    CHECK_STACK_SUM(self);
+
+    dvmChangeStatus(self, oldStatus);
+
+    convertReferenceResult(self->jniEnv, pResult, method, self);
+}
+
+/*
+ * Static method call, no reference arguments.
+ *
+ * We need to local-ref the class reference.
+ */
+void dvmCallJNIMethod_staticNoRef(const u4* args, JValue* pResult,
+    const Method* method, Thread* self)
+{
+    jclass staticMethodClass;
+    int oldStatus;
+
+#ifdef USE_INDIRECT_REF
+    staticMethodClass = addLocalReference(self->jniEnv, (Object*)method->clazz);
+    if (staticMethodClass == NULL) {
+        assert(dvmCheckException(self));
+        return;
+    }
+#else
+    staticMethodClass = (jobject) method->clazz;
+#endif
+
+    oldStatus = dvmChangeStatus(self, THREAD_NATIVE);
+
+    COMPUTE_STACK_SUM(self);
+    dvmPlatformInvoke(self->jniEnv, staticMethodClass,
+        method->jniArgInfo, method->insSize, args, method->shorty,
+        (void*)method->insns, pResult);
+    CHECK_STACK_SUM(self);
+
+    dvmChangeStatus(self, oldStatus);
+
+    convertReferenceResult(self->jniEnv, pResult, method, self);
+}
+
+/*
+ * Extract the return type enum from the "jniArgInfo" field.
+ */
+DalvikJniReturnType dvmGetArgInfoReturnType(int jniArgInfo)
+{
+    return (jniArgInfo & DALVIK_JNI_RETURN_MASK) >> DALVIK_JNI_RETURN_SHIFT;
+}
+
+
+/*
+ * ===========================================================================
  *      JNI implementation
  * ===========================================================================
  */
@@ -1149,7 +1688,7 @@
     UNUSED_PARAMETER(bufLen);
 
     JNI_ENTER();
-    LOGW("Rejecting JNI DefineClass request\n");
+    LOGW("JNI DefineClass is not supported\n");
     JNI_EXIT();
     return NULL;
 }
@@ -1174,6 +1713,7 @@
 
     const Method* thisMethod;
     ClassObject* clazz;
+    jclass jclazz = NULL;
     Object* loader;
     char* descriptor = NULL;
 
@@ -1202,25 +1742,28 @@
     }
 
     clazz = dvmFindClassNoInit(descriptor, loader);
-    clazz = addLocalReference(clazz);
+    jclazz = addLocalReference(env, (Object*) clazz);
 
 bail:
     free(descriptor);
-    
+
     JNI_EXIT();
-    return (jclass)clazz;
+    return jclazz;
 }
 
 /*
  * Return the superclass of a class.
  */
-static jclass GetSuperclass(JNIEnv* env, jclass clazz)
+static jclass GetSuperclass(JNIEnv* env, jclass jclazz)
 {
     JNI_ENTER();
-    jclass super = (jclass) ((ClassObject*) clazz)->super;
-    super = addLocalReference(super);
+    jclass jsuper = NULL;
+
+    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
+    if (clazz != NULL)
+        jsuper = addLocalReference(env, (Object*)clazz->super);
     JNI_EXIT();
-    return super;
+    return jsuper;
 }
 
 /*
@@ -1228,12 +1771,14 @@
  *
  * Like IsInstanceOf, but with a pair of class objects instead of obj+class.
  */
-static jboolean IsAssignableFrom(JNIEnv* env, jclass clazz1, jclass clazz2)
+static jboolean IsAssignableFrom(JNIEnv* env, jclass jclazz1, jclass jclazz2)
 {
     JNI_ENTER();
 
-    jboolean result;
-    result = dvmInstanceof((ClassObject*) clazz1, (ClassObject*) clazz2);
+    ClassObject* clazz1 = (ClassObject*) dvmDecodeIndirectRef(env, jclazz1);
+    ClassObject* clazz2 = (ClassObject*) dvmDecodeIndirectRef(env, jclazz2);
+
+    jboolean result = dvmInstanceof(clazz1, clazz2);
 
     JNI_EXIT();
     return result;
@@ -1242,11 +1787,12 @@
 /*
  * Given a java.lang.reflect.Method or .Constructor, return a methodID.
  */
-static jmethodID FromReflectedMethod(JNIEnv* env, jobject method)
+static jmethodID FromReflectedMethod(JNIEnv* env, jobject jmethod)
 {
     JNI_ENTER();
     jmethodID methodID;
-    methodID = (jmethodID) dvmGetMethodFromReflectObj((Object*)method);
+    Object* method = dvmDecodeIndirectRef(env, jmethod);
+    methodID = (jmethodID) dvmGetMethodFromReflectObj(method);
     JNI_EXIT();
     return methodID;
 }
@@ -1254,10 +1800,12 @@
 /*
  * Given a java.lang.reflect.Field, return a fieldID.
  */
-static jfieldID FromReflectedField(JNIEnv* env, jobject field)
+static jfieldID FromReflectedField(JNIEnv* env, jobject jfield)
 {
     JNI_ENTER();
-    jfieldID fieldID = (jfieldID) dvmGetFieldFromReflectObj((Object*)field);
+    jfieldID fieldID;
+    Object* field = dvmDecodeIndirectRef(env, jfield);
+    fieldID = (jfieldID) dvmGetFieldFromReflectObj(field);
     JNI_EXIT();
     return fieldID;
 }
@@ -1269,17 +1817,16 @@
  *
  * Throws OutOfMemory and returns NULL on failure.
  */
-static jobject ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID methodID,
+static jobject ToReflectedMethod(JNIEnv* env, jclass jcls, jmethodID methodID,
     jboolean isStatic)
 {
     JNI_ENTER();
-    jobject obj;
-    obj = (jobject) dvmCreateReflectObjForMethod((ClassObject*) cls,
-            (Method*) methodID);
+    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jcls);
+    Object* obj = dvmCreateReflectObjForMethod(clazz, (Method*) methodID);
     dvmReleaseTrackedAlloc(obj, NULL);
-    obj = addLocalReference(obj);
+    jobject jobj = addLocalReference(env, obj);
     JNI_EXIT();
-    return obj;
+    return jobj;
 }
 
 /*
@@ -1289,50 +1836,50 @@
  *
  * Throws OutOfMemory and returns NULL on failure.
  */
-static jobject ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID,
+static jobject ToReflectedField(JNIEnv* env, jclass jcls, jfieldID fieldID,
     jboolean isStatic)
 {
     JNI_ENTER();
-    jobject obj;
-    obj = (jobject) dvmCreateReflectObjForField((ClassObject*) cls,
-            (Field*) fieldID);
+    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jcls);
+    Object* obj = dvmCreateReflectObjForField(jcls, (Field*) fieldID);
     dvmReleaseTrackedAlloc(obj, NULL);
-    obj = addLocalReference(obj);
+    jobject jobj = addLocalReference(env, obj);
     JNI_EXIT();
-    return obj;
+    return jobj;
 }
 
-
 /*
  * Take this exception and throw it.
  */
-static jint Throw(JNIEnv* env, jthrowable obj)
+static jint Throw(JNIEnv* env, jthrowable jobj)
 {
     JNI_ENTER();
 
     jint retval;
 
-    if (obj != NULL) {
+    if (jobj != NULL) {
+        Object* obj = dvmDecodeIndirectRef(env, jobj);
         dvmSetException(_self, obj);
         retval = JNI_OK;
-    } else
+    } else {
         retval = JNI_ERR;
+    }
 
     JNI_EXIT();
     return retval;
 }
 
 /*
- * Constructs an exeption object from the specified class with the message
+ * Constructs an exception object from the specified class with the message
  * specified by "message", and throws it.
  */
-static jint ThrowNew(JNIEnv* env, jclass clazz, const char* message)
+static jint ThrowNew(JNIEnv* env, jclass jclazz, const char* message)
 {
     JNI_ENTER();
 
-    ClassObject* classObj = (ClassObject*) clazz;
-
-    dvmThrowExceptionByClass(classObj, message);
+    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
+    dvmThrowExceptionByClass(clazz, message);
+    // TODO: should return failure if this didn't work (e.g. OOM)
 
     JNI_EXIT();
     return JNI_OK;
@@ -1351,10 +1898,10 @@
     JNI_ENTER();
 
     Object* exception;
-    Object* localException;
+    jobject localException;
 
-    exception = (Object*) dvmGetException(_self);
-    localException = addLocalReference(exception);
+    exception = dvmGetException(_self);
+    localException = addLocalReference(env, exception);
     if (localException == NULL && exception != NULL) {
         /*
          * We were unable to add a new local reference, and threw a new
@@ -1419,7 +1966,7 @@
 {
     JNI_ENTER();
     int result = JNI_OK;
-    if (!ensureLocalCapacity(capacity) ||
+    if (!ensureLocalCapacity(env, capacity) ||
         !dvmPushLocalFrame(_self /*dvmThreadSelf()*/, dvmGetCurrentJNIMethod()))
     {
         /* yes, OutOfMemoryError, not StackOverflowError */
@@ -1436,16 +1983,17 @@
  * Pop the local frame off.  If "result" is not null, add it as a
  * local reference on the now-current frame.
  */
-static jobject PopLocalFrame(JNIEnv* env, jobject result)
+static jobject PopLocalFrame(JNIEnv* env, jobject jresult)
 {
     JNI_ENTER();
+    Object* result = dvmDecodeIndirectRef(env, jresult);
     if (!dvmPopLocalFrame(_self /*dvmThreadSelf()*/)) {
         LOGW("JNI WARNING: too many PopLocalFrame calls\n");
         dvmClearException(_self);
         dvmThrowException("Ljava/lang/RuntimeException;",
             "too many PopLocalFrame calls");
     }
-    result = addLocalReference(result);
+    jresult = addLocalReference(env, result);
     JNI_EXIT();
     return result;
 }
@@ -1453,9 +2001,10 @@
 /*
  * Add a reference to the global list.
  */
-static jobject NewGlobalRef(JNIEnv* env, jobject obj)
+static jobject NewGlobalRef(JNIEnv* env, jobject jobj)
 {
     JNI_ENTER();
+    Object* obj = dvmDecodeIndirectRef(env, jobj);
     jobject retval = addGlobalReference(obj);
     JNI_EXIT();
     return retval;
@@ -1464,10 +2013,10 @@
 /*
  * Delete a reference from the global list.
  */
-static void DeleteGlobalRef(JNIEnv* env, jobject globalRef)
+static void DeleteGlobalRef(JNIEnv* env, jobject jglobalRef)
 {
     JNI_ENTER();
-    deleteGlobalReference(globalRef);
+    deleteGlobalReference(jglobalRef);
     JNI_EXIT();
 }
 
@@ -1475,12 +2024,11 @@
 /*
  * Add a reference to the local list.
  */
-static jobject NewLocalRef(JNIEnv* env, jobject ref)
+static jobject NewLocalRef(JNIEnv* env, jobject jref)
 {
     JNI_ENTER();
-
-    jobject retval = addLocalReference(ref);
-
+    Object* obj = dvmDecodeIndirectRef(env, jref);
+    jobject retval = addLocalReference(env, obj);
     JNI_EXIT();
     return retval;
 }
@@ -1488,10 +2036,10 @@
 /*
  * Delete a reference from the local list.
  */
-static void DeleteLocalRef(JNIEnv* env, jobject localRef)
+static void DeleteLocalRef(JNIEnv* env, jobject jlocalRef)
 {
     JNI_ENTER();
-    deleteLocalReference(localRef);
+    deleteLocalReference(env, jlocalRef);
     JNI_EXIT();
 }
 
@@ -1499,10 +2047,10 @@
  * Ensure that the local references table can hold at least this many
  * references.
  */
-static jint EnsureLocalCapacity(JNIEnv *env, jint capacity)
+static jint EnsureLocalCapacity(JNIEnv* env, jint capacity)
 {
     JNI_ENTER();
-    bool okay = ensureLocalCapacity(capacity);
+    bool okay = ensureLocalCapacity(env, capacity);
     if (!okay) {
         dvmThrowException("Ljava/lang/OutOfMemoryError;",
             "can't ensure local reference capacity");
@@ -1518,10 +2066,12 @@
 /*
  * Determine whether two Object references refer to the same underlying object.
  */
-static jboolean IsSameObject(JNIEnv* env, jobject ref1, jobject ref2)
+static jboolean IsSameObject(JNIEnv* env, jobject jref1, jobject jref2)
 {
     JNI_ENTER();
-    jboolean result = (ref1 == ref2);
+    Object* obj1 = dvmDecodeIndirectRef(env, jref1);
+    Object* obj2 = dvmDecodeIndirectRef(env, jref2);
+    jboolean result = (obj1 == obj2);
     JNI_EXIT();
     return result;
 }
@@ -1533,83 +2083,82 @@
 {
     JNI_ENTER();
 
-    ClassObject* clazz = (ClassObject*) jclazz;
-    jobject newObj;
+    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
+    jobject result;
 
     if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz)) {
         assert(dvmCheckException(_self));
-        newObj = NULL;
+        result = NULL;
     } else {
-        newObj = (jobject) dvmAllocObject(clazz, ALLOC_DONT_TRACK);
-        newObj = addLocalReference(newObj);
+        Object* newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
+        result = addLocalReference(env, newObj);
     }
 
     JNI_EXIT();
-    return newObj;
+    return result;
 }
 
 /*
- * Construct a new object.
+ * Allocate a new object and invoke the supplied constructor.
  */
 static jobject NewObject(JNIEnv* env, jclass jclazz, jmethodID methodID, ...)
 {
     JNI_ENTER();
-
-    ClassObject* clazz = (ClassObject*) jclazz;
-    jobject newObj;
+    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
+    jobject result;
 
     if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz)) {
         assert(dvmCheckException(_self));
-        newObj = NULL;
+        result = NULL;
     } else {
-        newObj = (jobject) dvmAllocObject(clazz, ALLOC_DONT_TRACK);
-        newObj = addLocalReference(newObj);
+        Object* newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
+        result = addLocalReference(env, newObj);
         if (newObj != NULL) {
             JValue unused;
             va_list args;
             va_start(args, methodID);
-            dvmCallMethodV(_self, (Method*) methodID, (Object*)newObj, &unused,
+            dvmCallMethodV(_self, (Method*) methodID, newObj, true, &unused,
                 args);
             va_end(args);
         }
     }
 
     JNI_EXIT();
-    return newObj;
+    return result;
 }
-static jobject NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID,
+static jobject NewObjectV(JNIEnv* env, jclass jclazz, jmethodID methodID,
     va_list args)
 {
     JNI_ENTER();
+    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
+    jobject result;
 
-    jobject newObj;
-    newObj = (jobject) dvmAllocObject((ClassObject*) clazz, ALLOC_DONT_TRACK);
-    newObj = addLocalReference(newObj);
+    Object* newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
+    result = addLocalReference(env, newObj);
     if (newObj != NULL) {
         JValue unused;
-        dvmCallMethodV(_self, (Method*) methodID, (Object*)newObj, &unused,
-            args);
+        dvmCallMethodV(_self, (Method*) methodID, newObj, true, &unused, args);
     }
 
     JNI_EXIT();
-    return newObj;
+    return result;
 }
-static jobject NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID,
+static jobject NewObjectA(JNIEnv* env, jclass jclazz, jmethodID methodID,
     jvalue* args)
 {
     JNI_ENTER();
+    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
+    jobject result;
 
-    jobject newObj;
-    newObj = (jobject) dvmAllocObject((ClassObject*) clazz, ALLOC_DONT_TRACK);
-    newObj = addLocalReference(newObj);
+    Object* newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
+    result = addLocalReference(env, newObj);
     if (newObj != NULL) {
         JValue unused;
-        dvmCallMethodA(_self, (Method*) methodID, (Object*)newObj, &unused,
-            args);
+        dvmCallMethodA(_self, (Method*) methodID, newObj, true, &unused, args);
     }
 
     JNI_EXIT();
-    return newObj;
+    return result;
 }
 
 /*
@@ -1617,33 +2166,37 @@
  *
  * JNI spec says: obj must not be NULL.
  */
-static jclass GetObjectClass(JNIEnv* env, jobject obj)
+static jclass GetObjectClass(JNIEnv* env, jobject jobj)
 {
     JNI_ENTER();
 
-    assert(obj != NULL);
+    assert(jobj != NULL);
 
-    jclass clazz;
-    clazz = (jclass) ((Object*)obj)->clazz;
-    clazz = addLocalReference(clazz);
+    Object* obj = dvmDecodeIndirectRef(env, jobj);
+    jclass jclazz = addLocalReference(env, (Object*) obj->clazz);
 
     JNI_EXIT();
-    return clazz;
+    return jclazz;
 }
 
 /*
  * Determine whether "obj" is an instance of "clazz".
  */
-static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass clazz)
+static jboolean IsInstanceOf(JNIEnv* env, jobject jobj, jclass jclazz)
 {
     JNI_ENTER();
 
+    assert(jclazz != NULL);
+
     jboolean result;
 
-    if (obj == NULL)
+    if (jobj == NULL) {
         result = true;
-    else
-        result = dvmInstanceof(((Object*)obj)->clazz, (ClassObject*) clazz);
+    } else {
+        Object* obj = dvmDecodeIndirectRef(env, jobj);
+        ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
+        result = dvmInstanceof(obj->clazz, clazz);
+    }
 
     JNI_EXIT();
     return result;
@@ -1663,7 +2216,7 @@
 {
     JNI_ENTER();
 
-    ClassObject* clazz = (ClassObject*) jclazz;
+    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
     jmethodID id = NULL;
 
     if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz)) {
@@ -1686,8 +2239,8 @@
             meth = NULL;
         }
         if (meth == NULL) {
-            LOGI("Method not found: '%s' '%s' in %s\n",
-                name, sig, clazz->descriptor);
+            LOGD("GetMethodID: method not found: %s.%s:%s\n",
+                clazz->descriptor, name, sig);
             dvmThrowException("Ljava/lang/NoSuchMethodError;", name);
         }
 
@@ -1714,7 +2267,7 @@
 {
     JNI_ENTER();
 
-    ClassObject* clazz = (ClassObject*) jclazz;
+    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
     jfieldID id;
 
     if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz)) {
@@ -1722,8 +2275,11 @@
         id = NULL;
     } else {
         id = (jfieldID) dvmFindInstanceFieldHier(clazz, name, sig);
-        if (id == NULL)
+        if (id == NULL) {
+            LOGD("GetFieldID: unable to find field %s.%s:%s\n",
+                clazz->descriptor, name, sig);
             dvmThrowException("Ljava/lang/NoSuchFieldError;", name);
+        }
     }
     JNI_EXIT();
     return id;
@@ -1737,7 +2293,7 @@
 {
     JNI_ENTER();
 
-    ClassObject* clazz = (ClassObject*) jclazz;
+    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
     jmethodID id;
 
     if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz)) {
@@ -1777,7 +2333,7 @@
 {
     JNI_ENTER();
 
-    ClassObject* clazz = (ClassObject*) jclazz;
+    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
     jfieldID id;
 
     if (!dvmIsClassInitialized(clazz) && !dvmInitClass(clazz)) {
@@ -1798,15 +2354,19 @@
  * If we get an object reference, add it to the local refs list.
  */
 #define GET_STATIC_TYPE_FIELD(_ctype, _jname, _isref)                       \
-    static _ctype GetStatic##_jname##Field(JNIEnv* env, jclass clazz,       \
+    static _ctype GetStatic##_jname##Field(JNIEnv* env, jclass jclazz,      \
         jfieldID fieldID)                                                   \
     {                                                                       \
-        UNUSED_PARAMETER(clazz);                                            \
+        UNUSED_PARAMETER(jclazz);                                           \
         JNI_ENTER();                                                        \
         StaticField* sfield = (StaticField*) fieldID;                       \
-        _ctype value = dvmGetStaticField##_jname(sfield);                   \
-        if (_isref)     /* only when _ctype==jobject */                     \
-            value = (_ctype)(u4)addLocalReference((jobject)(u4)value);      \
+        _ctype value;                                                       \
+        if (_isref) {   /* only when _ctype==jobject */                     \
+            Object* obj = dvmGetStaticFieldObject(sfield);                  \
+            value = (_ctype)(u4)addLocalReference(env, obj);                \
+        } else {                                                            \
+            value = dvmGetStaticField##_jname(sfield);                      \
+        }                                                                   \
         JNI_EXIT();                                                         \
         return value;                                                       \
     }
@@ -1823,25 +2383,30 @@
 /*
  * Set a static field.
  */
-#define SET_STATIC_TYPE_FIELD(_ctype, _jname, _jvfld)                       \
-    static void SetStatic##_jname##Field(JNIEnv* env, jclass clazz,         \
+#define SET_STATIC_TYPE_FIELD(_ctype, _jname, _isref)                       \
+    static void SetStatic##_jname##Field(JNIEnv* env, jclass jclazz,        \
         jfieldID fieldID, _ctype value)                                     \
     {                                                                       \
-        UNUSED_PARAMETER(clazz);                                            \
+        UNUSED_PARAMETER(jclazz);                                           \
         JNI_ENTER();                                                        \
         StaticField* sfield = (StaticField*) fieldID;                       \
-        dvmSetStaticField##_jname(sfield, value);                           \
+        if (_isref) {   /* only when _ctype==jobject */                     \
+            Object* valObj = dvmDecodeIndirectRef(env, (jobject)(u4)value); \
+            dvmSetStaticFieldObject(sfield, valObj);                        \
+        } else {                                                            \
+            dvmSetStaticField##_jname(sfield, value);                       \
+        }                                                                   \
         JNI_EXIT();                                                         \
     }
-SET_STATIC_TYPE_FIELD(jobject, Object, l);
-SET_STATIC_TYPE_FIELD(jboolean, Boolean, z);
-SET_STATIC_TYPE_FIELD(jbyte, Byte, b);
-SET_STATIC_TYPE_FIELD(jchar, Char, c);
-SET_STATIC_TYPE_FIELD(jshort, Short, s);
-SET_STATIC_TYPE_FIELD(jint, Int, i);
-SET_STATIC_TYPE_FIELD(jlong, Long, j);
-SET_STATIC_TYPE_FIELD(jfloat, Float, f);
-SET_STATIC_TYPE_FIELD(jdouble, Double, d);
+SET_STATIC_TYPE_FIELD(jobject, Object, true);
+SET_STATIC_TYPE_FIELD(jboolean, Boolean, false);
+SET_STATIC_TYPE_FIELD(jbyte, Byte, false);
+SET_STATIC_TYPE_FIELD(jchar, Char, false);
+SET_STATIC_TYPE_FIELD(jshort, Short, false);
+SET_STATIC_TYPE_FIELD(jint, Int, false);
+SET_STATIC_TYPE_FIELD(jlong, Long, false);
+SET_STATIC_TYPE_FIELD(jfloat, Float, false);
+SET_STATIC_TYPE_FIELD(jdouble, Double, false);
 
 /*
  * Get an instance field.
@@ -1849,14 +2414,19 @@
  * If we get an object reference, add it to the local refs list.
  */
 #define GET_TYPE_FIELD(_ctype, _jname, _isref)                              \
-    static _ctype Get##_jname##Field(JNIEnv* env, jobject obj,              \
+    static _ctype Get##_jname##Field(JNIEnv* env, jobject jobj,             \
         jfieldID fieldID)                                                   \
     {                                                                       \
         JNI_ENTER();                                                        \
+        Object* obj = dvmDecodeIndirectRef(env, jobj);                      \
         InstField* field = (InstField*) fieldID;                            \
-        _ctype value = dvmGetField##_jname((Object*) obj,field->byteOffset);\
-        if (_isref)     /* only when _ctype==jobject */                     \
-            value = (_ctype)(u4)addLocalReference((jobject)(u4)value);      \
+        _ctype value;                                                       \
+        if (_isref) {   /* only when _ctype==jobject */                     \
+            Object* valObj = dvmGetFieldObject(obj, field->byteOffset);     \
+            value = (_ctype)(u4)addLocalReference(env, valObj);             \
+        } else {                                                            \
+            value = dvmGetField##_jname(obj, field->byteOffset);            \
+        }                                                                   \
         JNI_EXIT();                                                         \
         return value;                                                       \
     }
@@ -1873,24 +2443,30 @@
 /*
  * Set an instance field.
  */
-#define SET_TYPE_FIELD(_ctype, _jname)                                      \
-    static void Set##_jname##Field(JNIEnv* env, jobject obj,                \
+#define SET_TYPE_FIELD(_ctype, _jname, _isref)                              \
+    static void Set##_jname##Field(JNIEnv* env, jobject jobj,               \
         jfieldID fieldID, _ctype value)                                     \
     {                                                                       \
         JNI_ENTER();                                                        \
+        Object* obj = dvmDecodeIndirectRef(env, jobj);                      \
         InstField* field = (InstField*) fieldID;                            \
-        dvmSetField##_jname((Object*) obj, field->byteOffset, value);       \
+        if (_isref) {   /* only when _ctype==jobject */                     \
+            Object* valObj = dvmDecodeIndirectRef(env, (jobject)(u4)value); \
+            dvmSetFieldObject(obj, field->byteOffset, valObj);              \
+        } else {                                                            \
+            dvmSetField##_jname(obj, field->byteOffset, value);             \
+        }                                                                   \
         JNI_EXIT();                                                         \
     }
-SET_TYPE_FIELD(jobject, Object);
-SET_TYPE_FIELD(jboolean, Boolean);
-SET_TYPE_FIELD(jbyte, Byte);
-SET_TYPE_FIELD(jchar, Char);
-SET_TYPE_FIELD(jshort, Short);
-SET_TYPE_FIELD(jint, Int);
-SET_TYPE_FIELD(jlong, Long);
-SET_TYPE_FIELD(jfloat, Float);
-SET_TYPE_FIELD(jdouble, Double);
+SET_TYPE_FIELD(jobject, Object, true);
+SET_TYPE_FIELD(jboolean, Boolean, false);
+SET_TYPE_FIELD(jbyte, Byte, false);
+SET_TYPE_FIELD(jchar, Char, false);
+SET_TYPE_FIELD(jshort, Short, false);
+SET_TYPE_FIELD(jint, Int, false);
+SET_TYPE_FIELD(jlong, Long, false);
+SET_TYPE_FIELD(jfloat, Float, false);
+SET_TYPE_FIELD(jdouble, Double, false);
 
 /*
  * Make a virtual method call.
@@ -1899,60 +2475,60 @@
  * returning an Object, we have to add it to the local references table.
  */
 #define CALL_VIRTUAL(_ctype, _jname, _retfail, _retok, _isref)              \
-    static _ctype Call##_jname##Method(JNIEnv* env, jobject obj,            \
+    static _ctype Call##_jname##Method(JNIEnv* env, jobject jobj,           \
         jmethodID methodID, ...)                                            \
     {                                                                       \
         JNI_ENTER();                                                        \
-        Object* dobj = (Object*) obj;                                       \
+        Object* obj = dvmDecodeIndirectRef(env, jobj);                      \
         const Method* meth;                                                 \
         va_list args;                                                       \
         JValue result;                                                      \
-        meth = dvmGetVirtualizedMethod(dobj->clazz, (Method*)methodID);     \
+        meth = dvmGetVirtualizedMethod(obj->clazz, (Method*)methodID);      \
         if (meth == NULL) {                                                 \
             JNI_EXIT();                                                     \
             return _retfail;                                                \
         }                                                                   \
         va_start(args, methodID);                                           \
-        dvmCallMethodV(_self, meth, dobj, &result, args);                   \
+        dvmCallMethodV(_self, meth, obj, true, &result, args);              \
         va_end(args);                                                       \
-        if (_isref)                                                         \
-            result.l = addLocalReference(result.l);                         \
+        if (_isref && !dvmCheckException(_self))                            \
+            result.l = addLocalReference(env, result.l);                    \
         JNI_EXIT();                                                         \
         return _retok;                                                      \
     }                                                                       \
-    static _ctype Call##_jname##MethodV(JNIEnv* env, jobject obj,           \
+    static _ctype Call##_jname##MethodV(JNIEnv* env, jobject jobj,          \
         jmethodID methodID, va_list args)                                   \
     {                                                                       \
         JNI_ENTER();                                                        \
-        Object* dobj = (Object*) obj;                                       \
+        Object* obj = dvmDecodeIndirectRef(env, jobj);                      \
         const Method* meth;                                                 \
         JValue result;                                                      \
-        meth = dvmGetVirtualizedMethod(dobj->clazz, (Method*)methodID);     \
+        meth = dvmGetVirtualizedMethod(obj->clazz, (Method*)methodID);      \
         if (meth == NULL) {                                                 \
             JNI_EXIT();                                                     \
             return _retfail;                                                \
         }                                                                   \
-        dvmCallMethodV(_self, meth, dobj, &result, args);                   \
-        if (_isref)                                                         \
-            result.l = addLocalReference(result.l);                         \
+        dvmCallMethodV(_self, meth, obj, true, &result, args);              \
+        if (_isref && !dvmCheckException(_self))                            \
+            result.l = addLocalReference(env, result.l);                    \
         JNI_EXIT();                                                         \
         return _retok;                                                      \
     }                                                                       \
-    static _ctype Call##_jname##MethodA(JNIEnv* env, jobject obj,           \
+    static _ctype Call##_jname##MethodA(JNIEnv* env, jobject jobj,          \
         jmethodID methodID, jvalue* args)                                   \
     {                                                                       \
         JNI_ENTER();                                                        \
-        Object* dobj = (Object*) obj;                                       \
+        Object* obj = dvmDecodeIndirectRef(env, jobj);                      \
         const Method* meth;                                                 \
         JValue result;                                                      \
-        meth = dvmGetVirtualizedMethod(dobj->clazz, (Method*)methodID);     \
+        meth = dvmGetVirtualizedMethod(obj->clazz, (Method*)methodID);      \
         if (meth == NULL) {                                                 \
             JNI_EXIT();                                                     \
             return _retfail;                                                \
         }                                                                   \
-        dvmCallMethodA(_self, meth, dobj, &result, args);                   \
-        if (_isref)                                                         \
-            result.l = addLocalReference(result.l);                         \
+        dvmCallMethodA(_self, meth, obj, true, &result, args);              \
+        if (_isref && !dvmCheckException(_self))                            \
+            result.l = addLocalReference(env, result.l);                    \
         JNI_EXIT();                                                         \
         return _retok;                                                      \
     }
@@ -1975,63 +2551,66 @@
  * Three versions (..., va_list, jvalue[]) for each return type.
  */
 #define CALL_NONVIRTUAL(_ctype, _jname, _retfail, _retok, _isref)           \
-    static _ctype CallNonvirtual##_jname##Method(JNIEnv* env, jobject obj,  \
-        jclass clazz, jmethodID methodID, ...)                              \
+    static _ctype CallNonvirtual##_jname##Method(JNIEnv* env, jobject jobj, \
+        jclass jclazz, jmethodID methodID, ...)                             \
     {                                                                       \
         JNI_ENTER();                                                        \
-        Object* dobj = (Object*) obj;                                       \
+        Object* obj = dvmDecodeIndirectRef(env, jobj);                      \
+        ClassObject* clazz =                                                \
+            (ClassObject*) dvmDecodeIndirectRef(env, jclazz);               \
         const Method* meth;                                                 \
         va_list args;                                                       \
         JValue result;                                                      \
-        meth = dvmGetVirtualizedMethod((ClassObject*)clazz,                 \
-                (Method*)methodID);                                         \
+        meth = dvmGetVirtualizedMethod(clazz, (Method*)methodID);           \
         if (meth == NULL) {                                                 \
             JNI_EXIT();                                                     \
             return _retfail;                                                \
         }                                                                   \
         va_start(args, methodID);                                           \
-        dvmCallMethodV(_self, meth, dobj, &result, args);                   \
-        if (_isref)                                                         \
-            result.l = addLocalReference(result.l);                         \
+        dvmCallMethodV(_self, meth, obj, true, &result, args);              \
+        if (_isref && !dvmCheckException(_self))                            \
+            result.l = addLocalReference(env, result.l);                    \
         va_end(args);                                                       \
         JNI_EXIT();                                                         \
         return _retok;                                                      \
     }                                                                       \
-    static _ctype CallNonvirtual##_jname##MethodV(JNIEnv* env, jobject obj, \
-        jclass clazz, jmethodID methodID, va_list args)                     \
+    static _ctype CallNonvirtual##_jname##MethodV(JNIEnv* env, jobject jobj,\
+        jclass jclazz, jmethodID methodID, va_list args)                    \
     {                                                                       \
         JNI_ENTER();                                                        \
-        Object* dobj = (Object*) obj;                                       \
+        Object* obj = dvmDecodeIndirectRef(env, jobj);                      \
+        ClassObject* clazz =                                                \
+            (ClassObject*) dvmDecodeIndirectRef(env, jclazz);               \
         const Method* meth;                                                 \
         JValue result;                                                      \
-        meth = dvmGetVirtualizedMethod((ClassObject*)clazz,                 \
-                (Method*)methodID);                                         \
+        meth = dvmGetVirtualizedMethod(clazz, (Method*)methodID);           \
         if (meth == NULL) {                                                 \
             JNI_EXIT();                                                     \
             return _retfail;                                                \
         }                                                                   \
-        dvmCallMethodV(_self, meth, dobj, &result, args);                   \
-        if (_isref)                                                         \
-            result.l = addLocalReference(result.l);                         \
+        dvmCallMethodV(_self, meth, obj, true, &result, args);              \
+        if (_isref && !dvmCheckException(_self))                            \
+            result.l = addLocalReference(env, result.l);                    \
         JNI_EXIT();                                                         \
         return _retok;                                                      \
     }                                                                       \
-    static _ctype CallNonvirtual##_jname##MethodA(JNIEnv* env, jobject obj, \
-        jclass clazz, jmethodID methodID, jvalue* args)                     \
+    static _ctype CallNonvirtual##_jname##MethodA(JNIEnv* env, jobject jobj,\
+        jclass jclazz, jmethodID methodID, jvalue* args)                    \
     {                                                                       \
         JNI_ENTER();                                                        \
-        Object* dobj = (Object*) obj;                                       \
+        Object* obj = dvmDecodeIndirectRef(env, jobj);                      \
+        ClassObject* clazz =                                                \
+            (ClassObject*) dvmDecodeIndirectRef(env, jclazz);               \
         const Method* meth;                                                 \
         JValue result;                                                      \
-        meth = dvmGetVirtualizedMethod((ClassObject*)clazz,                 \
-                (Method*)methodID);                                         \
+        meth = dvmGetVirtualizedMethod(clazz, (Method*)methodID);           \
         if (meth == NULL) {                                                 \
             JNI_EXIT();                                                     \
             return _retfail;                                                \
         }                                                                   \
-        dvmCallMethodA(_self, meth, dobj, &result, args);                   \
-        if (_isref)                                                         \
-            result.l = addLocalReference(result.l);                         \
+        dvmCallMethodA(_self, meth, obj, true, &result, args);              \
+        if (_isref && !dvmCheckException(_self))                            \
+            result.l = addLocalReference(env, result.l);                    \
         JNI_EXIT();                                                         \
         return _retok;                                                      \
     }
@@ -2051,42 +2630,42 @@
  * Call a static method.
  */
 #define CALL_STATIC(_ctype, _jname, _retfail, _retok, _isref)               \
-    static _ctype CallStatic##_jname##Method(JNIEnv* env, jclass clazz,     \
+    static _ctype CallStatic##_jname##Method(JNIEnv* env, jclass jclazz,    \
         jmethodID methodID, ...)                                            \
     {                                                                       \
+        UNUSED_PARAMETER(jclazz);                                           \
         JNI_ENTER();                                                        \
         JValue result;                                                      \
         va_list args;                                                       \
-        assert((ClassObject*) clazz == ((Method*)methodID)->clazz);         \
         va_start(args, methodID);                                           \
-        dvmCallMethodV(_self, (Method*) methodID, NULL, &result, args);     \
+        dvmCallMethodV(_self, (Method*)methodID, NULL, true, &result, args);\
         va_end(args);                                                       \
-        if (_isref)                                                         \
-            result.l = addLocalReference(result.l);                         \
+        if (_isref && !dvmCheckException(_self))                            \
+            result.l = addLocalReference(env, result.l);                    \
         JNI_EXIT();                                                         \
         return _retok;                                                      \
     }                                                                       \
-    static _ctype CallStatic##_jname##MethodV(JNIEnv* env, jclass clazz,    \
+    static _ctype CallStatic##_jname##MethodV(JNIEnv* env, jclass jclazz,   \
         jmethodID methodID, va_list args)                                   \
     {                                                                       \
+        UNUSED_PARAMETER(jclazz);                                           \
         JNI_ENTER();                                                        \
         JValue result;                                                      \
-        assert((ClassObject*) clazz == ((Method*)methodID)->clazz);         \
-        dvmCallMethodV(_self, (Method*) methodID, NULL, &result, args);     \
-        if (_isref)                                                         \
-            result.l = addLocalReference(result.l);                         \
+        dvmCallMethodV(_self, (Method*)methodID, NULL, true, &result, args);\
+        if (_isref && !dvmCheckException(_self))                            \
+            result.l = addLocalReference(env, result.l);                    \
         JNI_EXIT();                                                         \
         return _retok;                                                      \
     }                                                                       \
-    static _ctype CallStatic##_jname##MethodA(JNIEnv* env, jclass clazz,    \
+    static _ctype CallStatic##_jname##MethodA(JNIEnv* env, jclass jclazz,   \
         jmethodID methodID, jvalue* args)                                   \
     {                                                                       \
+        UNUSED_PARAMETER(jclazz);                                           \
         JNI_ENTER();                                                        \
         JValue result;                                                      \
-        assert((ClassObject*) clazz == ((Method*)methodID)->clazz);         \
-        dvmCallMethodA(_self, (Method*) methodID, NULL, &result, args);     \
-        if (_isref)                                                         \
-            result.l = addLocalReference(result.l);                         \
+        dvmCallMethodA(_self, (Method*)methodID, NULL, true, &result, args);\
+        if (_isref && !dvmCheckException(_self))                            \
+            result.l = addLocalReference(env, result.l);                    \
         JNI_EXIT();                                                         \
         return _retok;                                                      \
     }
@@ -2110,53 +2689,51 @@
 static jstring NewString(JNIEnv* env, const jchar* unicodeChars, jsize len)
 {
     JNI_ENTER();
+    jobject retval;
 
-    StringObject* jstr;
-    jstr = dvmCreateStringFromUnicode(unicodeChars, len);
-    if (jstr != NULL) {
+    StringObject* jstr = dvmCreateStringFromUnicode(unicodeChars, len);
+    if (jstr == NULL) {
+        retval = NULL;
+    } else {
         dvmReleaseTrackedAlloc((Object*) jstr, NULL);
-        jstr = addLocalReference((jstring) jstr);
+        retval = addLocalReference(env, (Object*) jstr);
     }
 
     JNI_EXIT();
-    return jstr;
+    return retval;
 }
 
 /*
  * Return the length of a String in Unicode character units.
  */
-static jsize GetStringLength(JNIEnv* env, jstring string)
+static jsize GetStringLength(JNIEnv* env, jstring jstr)
 {
     JNI_ENTER();
 
-    jsize len = dvmStringLen((StringObject*) string);
+    StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(env, jstr);
+    jsize len = dvmStringLen(strObj);
 
     JNI_EXIT();
     return len;
 }
 
+
 /*
- * Get a pointer to the string's character data.
+ * Get a string's character data.
  *
  * The result is guaranteed to be valid until ReleaseStringChars is
- * called, which means we can't just hold a reference to it in the local
- * refs table.  We have to add it to the global refs.
- *
- * Technically, we don't need to hold a reference to the String, but rather
- * to the Char[] object within the String.
- *
- * We could also just allocate some storage and copy the data into it,
- * but it's a choice between our synchronized global reference table and
- * libc's synchronized heap allocator.
+ * called, which means we have to pin it or return a copy.
  */
-static const jchar* GetStringChars(JNIEnv* env, jstring string,
-    jboolean* isCopy)
+static const jchar* GetStringChars(JNIEnv* env, jstring jstr, jboolean* isCopy)
 {
     JNI_ENTER();
 
-    const u2* data = dvmStringChars((StringObject*) string);
-    addGlobalReference(string);
+    StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(env, jstr);
+    ArrayObject* strChars = dvmStringCharArray(strObj);
 
+    pinPrimitiveArray(strChars);
+
+    const u2* data = dvmStringChars(strObj);
     if (isCopy != NULL)
         *isCopy = JNI_FALSE;
 
@@ -2167,10 +2744,12 @@
 /*
  * Release our grip on some characters from a string.
  */
-static void ReleaseStringChars(JNIEnv* env, jstring string, const jchar* chars)
+static void ReleaseStringChars(JNIEnv* env, jstring jstr, const jchar* chars)
 {
     JNI_ENTER();
-    deleteGlobalReference(string);
+    StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(env, jstr);
+    ArrayObject* strChars = dvmStringCharArray(strObj);
+    unpinPrimitiveArray(strChars);
     JNI_EXIT();
 }
 
@@ -2184,30 +2763,30 @@
 {
     JNI_ENTER();
 
-    StringObject* newStr;
-    
+    jstring result;
+
     if (bytes == NULL) {
-        newStr = NULL;
+        result = NULL;
     } else {
-        newStr = dvmCreateStringFromCstr(bytes, ALLOC_DEFAULT);
-        if (newStr != NULL) {
-            dvmReleaseTrackedAlloc((Object*)newStr, NULL);
-            newStr = addLocalReference((jstring) newStr);
-        }
+        /* note newStr could come back NULL on OOM */
+        StringObject* newStr = dvmCreateStringFromCstr(bytes, ALLOC_DEFAULT);
+        result = addLocalReference(env, (Object*) newStr);
+        dvmReleaseTrackedAlloc((Object*)newStr, NULL);
     }
 
     JNI_EXIT();
-    return (jstring)newStr;
+    return result;
 }
 
 /*
  * Return the length in bytes of the modified UTF-8 form of the string.
  */
-static jsize GetStringUTFLength(JNIEnv* env, jstring string)
+static jsize GetStringUTFLength(JNIEnv* env, jstring jstr)
 {
     JNI_ENTER();
 
-    jsize len = dvmStringUtf8ByteLen((StringObject*) string);
+    StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(env, jstr);
+    jsize len = dvmStringUtf8ByteLen(strObj);
 
     JNI_EXIT();
     return len;
@@ -2227,20 +2806,21 @@
  * which should catch this sort of thing during development.)  Certain other
  * VMs will crash with a segmentation fault.
  */
-static const char* GetStringUTFChars(JNIEnv* env, jstring string,
+static const char* GetStringUTFChars(JNIEnv* env, jstring jstr,
     jboolean* isCopy)
 {
     JNI_ENTER();
     char* newStr;
 
-    if (string == NULL) {
+    if (jstr == NULL) {
         /* this shouldn't happen; throw NPE? */
         newStr = NULL;
     } else {
         if (isCopy != NULL)
             *isCopy = JNI_TRUE;
 
-        newStr = dvmCreateCstrFromString((StringObject*) string);
+        StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(env, jstr);
+        newStr = dvmCreateCstrFromString(strObj);
         if (newStr == NULL) {
             /* assume memory failure */
             dvmThrowException("Ljava/lang/OutOfMemoryError;",
@@ -2255,7 +2835,7 @@
 /*
  * Release a string created by GetStringUTFChars().
  */
-static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char* utf)
+static void ReleaseStringUTFChars(JNIEnv* env, jstring jstr, const char* utf)
 {
     JNI_ENTER();
     free((char*)utf);
@@ -2265,11 +2845,12 @@
 /*
  * Return the capacity of the array.
  */
-static jsize GetArrayLength(JNIEnv* env, jarray array)
+static jsize GetArrayLength(JNIEnv* env, jarray jarr)
 {
     JNI_ENTER();
 
-    jsize length = ((ArrayObject*) array)->length;
+    ArrayObject* arrObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
+    jsize length = arrObj->length;
 
     JNI_EXIT();
     return length;
@@ -2279,12 +2860,13 @@
  * Construct a new array that holds objects from class "elementClass".
  */
 static jobjectArray NewObjectArray(JNIEnv* env, jsize length,
-    jclass elementClass, jobject initialElement)
+    jclass jelementClass, jobject jinitialElement)
 {
     JNI_ENTER();
 
-    ClassObject* elemClassObj = (ClassObject*) elementClass;
-    ArrayObject* newObj = NULL;
+    jobjectArray newArray = NULL;
+    ClassObject* elemClassObj =
+        (ClassObject*) dvmDecodeIndirectRef(env, jelementClass);
 
     if (elemClassObj == NULL) {
         dvmThrowException("Ljava/lang/NullPointerException;",
@@ -2292,28 +2874,30 @@
         goto bail;
     }
 
-    newObj = dvmAllocObjectArray(elemClassObj, length, ALLOC_DEFAULT);
+    ArrayObject* newObj =
+        dvmAllocObjectArray(elemClassObj, length, ALLOC_DEFAULT);
     if (newObj == NULL) {
         assert(dvmCheckException(_self));
         goto bail;
     }
+    newArray = addLocalReference(env, (Object*) newObj);
     dvmReleaseTrackedAlloc((Object*) newObj, NULL);
 
     /*
      * Initialize the array.  Trashes "length".
      */
-    if (initialElement != NULL) {
+    if (jinitialElement != NULL) {
+        Object* initialElement = dvmDecodeIndirectRef(env, jinitialElement);
         Object** arrayData = (Object**) newObj->contents;
 
         while (length--)
-            *arrayData++ = (Object*) initialElement;
+            *arrayData++ = initialElement;
     }
 
-    newObj = addLocalReference((jobjectArray) newObj);
 
 bail:
     JNI_EXIT();
-    return (jobjectArray) newObj;
+    return newArray;
 }
 
 /*
@@ -2321,15 +2905,15 @@
  *
  * Add the object to the local references table in case the array goes away.
  */
-static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray array,
+static jobject GetObjectArrayElement(JNIEnv* env, jobjectArray jarr,
     jsize index)
 {
     JNI_ENTER();
 
-    ArrayObject* arrayObj = (ArrayObject*) array;
-    Object* value = NULL;
+    ArrayObject* arrayObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
+    jobject retval = NULL;
 
-    assert(array != NULL);
+    assert(arrayObj != NULL);
 
     /* check the array bounds */
     if (index < 0 || index >= (int) arrayObj->length) {
@@ -2338,25 +2922,25 @@
         goto bail;
     }
 
-    value = ((Object**) arrayObj->contents)[index];
-    value = addLocalReference(value);
+    Object* value = ((Object**) arrayObj->contents)[index];
+    retval = addLocalReference(env, value);
 
 bail:
     JNI_EXIT();
-    return (jobject) value;
+    return retval;
 }
 
 /*
  * Set one element of an Object array.
  */
-static void SetObjectArrayElement(JNIEnv* env, jobjectArray array,
-    jsize index, jobject value)
+static void SetObjectArrayElement(JNIEnv* env, jobjectArray jarr,
+    jsize index, jobject jobj)
 {
     JNI_ENTER();
 
-    ArrayObject* arrayObj = (ArrayObject*) array;
+    ArrayObject* arrayObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
 
-    assert(array != NULL);
+    assert(arrayObj != NULL);
 
     /* check the array bounds */
     if (index < 0 || index >= (int) arrayObj->length) {
@@ -2367,7 +2951,8 @@
 
     //LOGV("JNI: set element %d in array %p to %p\n", index, array, value);
 
-    ((Object**) arrayObj->contents)[index] = (Object*) value;
+    Object* obj = dvmDecodeIndirectRef(env, jobj);
+    ((Object**) arrayObj->contents)[index] = obj;
 
 bail:
     JNI_EXIT();
@@ -2383,12 +2968,13 @@
         ArrayObject* arrayObj;                                              \
         arrayObj = dvmAllocPrimitiveArray(_typechar, length,                \
             ALLOC_DEFAULT);                                                 \
+        jarray jarr = NULL;                                                 \
         if (arrayObj != NULL) {                                             \
+            jarr = addLocalReference(env, (Object*) arrayObj);              \
             dvmReleaseTrackedAlloc((Object*) arrayObj, NULL);               \
-            arrayObj = addLocalReference(arrayObj);                         \
         }                                                                   \
         JNI_EXIT();                                                         \
-        return (_artype)arrayObj;                                           \
+        return (_artype)jarr;                                               \
     }
 NEW_PRIMITIVE_ARRAY(jbooleanArray, Boolean, 'Z');
 NEW_PRIMITIVE_ARRAY(jbyteArray, Byte, 'B');
@@ -2403,22 +2989,20 @@
  * Get a pointer to a C array of primitive elements from an array object
  * of the matching type.
  *
- * We guarantee availability until Release is called, so we have to add
- * the array object to the global refs table.
- *
- * In a compacting GC, we either need to return a copy of the elements
- * or "pin" the memory.  Otherwise we run the risk of native code using
- * the buffer as the destination of a blocking read() call that wakes up
+ * In a compacting GC, we either need to return a copy of the elements or
+ * "pin" the memory.  Otherwise we run the risk of native code using the
+ * buffer as the destination of e.g. a blocking read() call that wakes up
  * during a GC.
  */
 #define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname)                        \
     static _ctype* Get##_jname##ArrayElements(JNIEnv* env,                  \
-        _ctype##Array array, jboolean* isCopy)                              \
+        _ctype##Array jarr, jboolean* isCopy)                               \
     {                                                                       \
         JNI_ENTER();                                                        \
         _ctype* data;                                                       \
-        ArrayObject* arrayObj = (ArrayObject*)array;                        \
-        addGlobalReference(arrayObj);                                       \
+        ArrayObject* arrayObj =                                             \
+            (ArrayObject*) dvmDecodeIndirectRef(env, jarr);                 \
+        pinPrimitiveArray(arrayObj);                                        \
         data = (_ctype*) arrayObj->contents;                                \
         if (isCopy != NULL)                                                 \
             *isCopy = JNI_FALSE;                                            \
@@ -2429,21 +3013,21 @@
 /*
  * Release the storage locked down by the "get" function.
  *
- * The API says, ""'mode' has no effect if 'elems' is not a copy of the
+ * The spec says, "'mode' has no effect if 'elems' is not a copy of the
  * elements in 'array'."  They apparently did not anticipate the need to
- * create a global reference to avoid GC race conditions.  We actually
- * want to delete the global reference in all circumstances that would
- * result in a copied array being freed.  This means anything but a
- * JNI_COMMIT release.
+ * un-pin memory.
  */
 #define RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname)                    \
     static void Release##_jname##ArrayElements(JNIEnv* env,                 \
-        _ctype##Array array, _ctype* elems, jint mode)                      \
+        _ctype##Array jarr, _ctype* elems, jint mode)                       \
     {                                                                       \
         UNUSED_PARAMETER(elems);                                            \
         JNI_ENTER();                                                        \
-        if (mode != JNI_COMMIT)                                             \
-            deleteGlobalReference(array);                                   \
+        if (mode != JNI_COMMIT) {                                           \
+            ArrayObject* arrayObj =                                         \
+                (ArrayObject*) dvmDecodeIndirectRef(env, jarr);             \
+            unpinPrimitiveArray(arrayObj);                                  \
+        }                                                                   \
         JNI_EXIT();                                                         \
     }
 
@@ -2452,10 +3036,11 @@
  */
 #define GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname)                          \
     static void Get##_jname##ArrayRegion(JNIEnv* env,                       \
-        _ctype##Array array, jsize start, jsize len, _ctype* buf)           \
+        _ctype##Array jarr, jsize start, jsize len, _ctype* buf)            \
     {                                                                       \
         JNI_ENTER();                                                        \
-        ArrayObject* arrayObj = (ArrayObject*)array;                        \
+        ArrayObject* arrayObj =                                             \
+            (ArrayObject*) dvmDecodeIndirectRef(env, jarr);                 \
         _ctype* data = (_ctype*) arrayObj->contents;                        \
         if (start < 0 || len < 0 || start + len > (int) arrayObj->length) { \
             dvmThrowException("Ljava/lang/ArrayIndexOutOfBoundsException;", \
@@ -2471,10 +3056,11 @@
  */
 #define SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname)                          \
     static void Set##_jname##ArrayRegion(JNIEnv* env,                       \
-        _ctype##Array array, jsize start, jsize len, const _ctype* buf)     \
+        _ctype##Array jarr, jsize start, jsize len, const _ctype* buf)      \
     {                                                                       \
         JNI_ENTER();                                                        \
-        ArrayObject* arrayObj = (ArrayObject*)array;                        \
+        ArrayObject* arrayObj =                                             \
+            (ArrayObject*) dvmDecodeIndirectRef(env, jarr);                 \
         _ctype* data = (_ctype*) arrayObj->contents;                        \
         if (start < 0 || len < 0 || start + len > (int) arrayObj->length) { \
             dvmThrowException("Ljava/lang/ArrayIndexOutOfBoundsException;", \
@@ -2510,22 +3096,23 @@
 /*
  * Register one or more native functions in one class.
  */
-static jint RegisterNatives(JNIEnv* env, jclass clazz,
+static jint RegisterNatives(JNIEnv* env, jclass jclazz,
     const JNINativeMethod* methods, jint nMethods)
 {
     JNI_ENTER();
 
+    ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
     jint retval;
     int i;
 
     if (gDvm.verboseJni) {
         LOGI("[Registering JNI native methods for class %s]\n",
-            ((ClassObject*) clazz)->descriptor);
+            clazz->descriptor);
     }
 
     for (i = 0; i < nMethods; i++) {
-        if (!dvmRegisterJNIMethod((ClassObject*) clazz,
-                methods[i].name, methods[i].signature, methods[i].fnPtr))
+        if (!dvmRegisterJNIMethod(clazz, methods[i].name,
+                methods[i].signature, methods[i].fnPtr))
         {
             retval = JNI_ERR;
             goto bail;
@@ -2541,7 +3128,7 @@
 /*
  * Un-register a native function.
  */
-static jint UnregisterNatives(JNIEnv* env, jclass clazz)
+static jint UnregisterNatives(JNIEnv* env, jclass jclazz)
 {
     JNI_ENTER();
     /*
@@ -2560,11 +3147,12 @@
  * We have to track all monitor enters and exits, so that we can undo any
  * outstanding synchronization before the thread exits.
  */
-static jint MonitorEnter(JNIEnv* env, jobject obj)
+static jint MonitorEnter(JNIEnv* env, jobject jobj)
 {
     JNI_ENTER();
-    dvmLockObject(_self, (Object*) obj);
-    trackMonitorEnter(_self, (Object*) obj);
+    Object* obj = dvmDecodeIndirectRef(env, jobj);
+    dvmLockObject(_self, obj);
+    trackMonitorEnter(_self, obj);
     JNI_EXIT();
     return JNI_OK;
 }
@@ -2573,17 +3161,18 @@
  * Unlock the monitor.
  *
  * Throws an IllegalMonitorStateException if the current thread
- * doesn't own the monitor. (dvmUnlockObject() takes care of the throw.)
+ * doesn't own the monitor.  (dvmUnlockObject() takes care of the throw.)
  *
  * According to the 1.6 spec, it's legal to call here with an exception
  * pending.  If this fails, we'll stomp the original exception.
  */
-static jint MonitorExit(JNIEnv* env, jobject obj)
+static jint MonitorExit(JNIEnv* env, jobject jobj)
 {
     JNI_ENTER();
-    bool success = dvmUnlockObject(_self, (Object*) obj);
+    Object* obj = dvmDecodeIndirectRef(env, jobj);
+    bool success = dvmUnlockObject(_self, obj);
     if (success)
-        trackMonitorExit(_self, (Object*) obj);
+        trackMonitorExit(_self, obj);
     JNI_EXIT();
     return success ? JNI_OK : JNI_ERR;
 }
@@ -2606,11 +3195,11 @@
 /*
  * Copies "len" Unicode characters, from offset "start".
  */
-static void GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len,
+static void GetStringRegion(JNIEnv* env, jstring jstr, jsize start, jsize len,
     jchar* buf)
 {
     JNI_ENTER();
-    StringObject* strObj = (StringObject*) str;
+    StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(env, jstr);
     if (start + len > dvmStringLen(strObj))
         dvmThrowException("Ljava/lang/StringIndexOutOfBoundsException;", NULL);
     else
@@ -2622,11 +3211,11 @@
  * Translates "len" Unicode characters, from offset "start", into
  * modified UTF-8 encoding.
  */
-static void GetStringUTFRegion(JNIEnv* env, jstring str, jsize start,
+static void GetStringUTFRegion(JNIEnv* env, jstring jstr, jsize start,
     jsize len, char* buf)
 {
     JNI_ENTER();
-    StringObject* strObj = (StringObject*) str;
+    StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(env, jstr);
     if (start + len > dvmStringLen(strObj))
         dvmThrowException("Ljava/lang/StringIndexOutOfBoundsException;", NULL);
     else
@@ -2640,15 +3229,15 @@
  * The caller is expected to call "release" before doing any JNI calls
  * or blocking I/O operations.
  *
- * In a compacting GC, we need to pin the memory or block GC.
+ * We need to pin the memory or block GC.
  */
-static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray array,
+static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray jarr,
     jboolean* isCopy)
 {
     JNI_ENTER();
     void* data;
-    ArrayObject* arrayObj = (ArrayObject*)array;
-    addGlobalReference(arrayObj);
+    ArrayObject* arrayObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
+    pinPrimitiveArray(arrayObj);
     data = arrayObj->contents;
     if (isCopy != NULL)
         *isCopy = JNI_FALSE;
@@ -2659,25 +3248,30 @@
 /*
  * Release an array obtained with GetPrimitiveArrayCritical.
  */
-static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array,
+static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray jarr,
     void* carray, jint mode)
 {
     JNI_ENTER();
-    if (mode != JNI_COMMIT)
-        deleteGlobalReference(array);
+    if (mode != JNI_COMMIT) {
+        ArrayObject* arrayObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
+        unpinPrimitiveArray(arrayObj);
+    }
     JNI_EXIT();
 }
 
 /*
  * Like GetStringChars, but with restricted use.
  */
-static const jchar* GetStringCritical(JNIEnv* env, jstring string,
+static const jchar* GetStringCritical(JNIEnv* env, jstring jstr,
     jboolean* isCopy)
 {
     JNI_ENTER();
-    const u2* data = dvmStringChars((StringObject*) string);
-    addGlobalReference(string);
+    StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(env, jstr);
+    ArrayObject* strChars = dvmStringCharArray(strObj);
 
+    pinPrimitiveArray(strChars);
+
+    const u2* data = dvmStringChars(strObj);
     if (isCopy != NULL)
         *isCopy = JNI_FALSE;
 
@@ -2688,11 +3282,13 @@
 /*
  * Like ReleaseStringChars, but with restricted use.
  */
-static void ReleaseStringCritical(JNIEnv* env, jstring string,
+static void ReleaseStringCritical(JNIEnv* env, jstring jstr,
     const jchar* carray)
 {
     JNI_ENTER();
-    deleteGlobalReference(string);
+    StringObject* strObj = (StringObject*) dvmDecodeIndirectRef(env, jstr);
+    ArrayObject* strChars = dvmStringCharArray(strObj);
+    unpinPrimitiveArray(strChars);
     JNI_EXIT();
 }
 
@@ -2743,15 +3339,10 @@
  * the same time, so while the return value is accurate it may not tell
  * the whole story.
  */
-static jobjectRefType GetObjectRefType(JNIEnv* env, jobject obj)
+static jobjectRefType GetObjectRefType(JNIEnv* env, jobject jobj)
 {
     JNI_ENTER();
-    jobjectRefType type;
-    
-    if (obj == NULL)
-        type = JNIInvalidRefType;
-    else
-        type = dvmGetJNIRefType(obj);
+    jobjectRefType type = dvmGetJNIRefType(env, jobj);
     JNI_EXIT();
     return type;
 }
@@ -2790,15 +3381,16 @@
     Object* newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
     if (newObj != NULL) {
         /* call the (PlatformAddress, int, int) constructor */
-        newObj = addLocalReference(newObj);
+        result = addLocalReference(env, newObj);
         dvmCallMethod(self, gDvm.methJavaNioReadWriteDirectByteBuffer_init,
             newObj, &callResult, platformAddress, (jint) capacity, (jint) 0);
-        if (dvmGetException(self) != NULL)
+        if (dvmGetException(self) != NULL) {
+            deleteLocalReference(env, result);
+            result = NULL;
             goto bail;
+        }
     }
 
-    result = (jobject) newObj;
-
 bail:
     if (platformAddress != NULL)
         dvmReleaseTrackedAlloc(platformAddress, self);
@@ -2811,11 +3403,11 @@
  *
  * If this is not a "direct" buffer, we return NULL.
  */
-static void* GetDirectBufferAddress(JNIEnv* env, jobject buf)
+static void* GetDirectBufferAddress(JNIEnv* env, jobject jbuf)
 {
     JNI_ENTER();
 
-    Object* bufObj = (Object*) buf;
+    Object* bufObj = dvmDecodeIndirectRef(env, jbuf);
     Thread* self = _self /*dvmThreadSelf()*/;
     void* result;
 
@@ -2852,7 +3444,7 @@
     JValue callResult;
     const Method* meth = dvmGetVirtualizedMethod(bufObj->clazz,
         gDvm.methOrgApacheHarmonyNioInternalDirectBuffer_getEffectiveAddress);
-    dvmCallMethodA(self, meth, bufObj, &callResult, NULL);
+    dvmCallMethodA(self, meth, bufObj, false, &callResult, NULL);
     if (dvmGetException(self) != NULL) {
         dvmClearException(self);
         callResult.l = NULL;
@@ -2886,7 +3478,7 @@
  * this check, since it's expensive to determine, and just return the
  * capacity regardless.)
  */
-static jlong GetDirectBufferCapacity(JNIEnv* env, jobject buf)
+static jlong GetDirectBufferCapacity(JNIEnv* env, jobject jbuf)
 {
     JNI_ENTER();
 
@@ -2896,7 +3488,8 @@
      * (The "check" version should verify that this is actually a Buffer,
      * but we're not required to do so here.)
      */
-    jlong result = dvmGetFieldInt((Object*)buf, gDvm.offJavaNioBuffer_capacity);
+    Object* buf = dvmDecodeIndirectRef(env, jbuf);
+    jlong result = dvmGetFieldInt(buf, gDvm.offJavaNioBuffer_capacity);
 
     JNI_EXIT();
     return result;
@@ -3438,12 +4031,16 @@
 /*
  * Enable "checked JNI" after the VM has partially started.  This must
  * only be called in "zygote" mode, when we have one thread running.
+ *
+ * This doesn't attempt to rewrite the JNI call bridge associated with
+ * native methods, so we won't get those checks for any methods that have
+ * already been resolved.
  */
 void dvmLateEnableCheckedJni(void)
 {
     JNIEnvExt* extEnv;
     JavaVMExt* extVm;
-    
+
     extEnv = dvmGetJNIEnvForThread();
     if (extEnv == NULL) {
         LOGE("dvmLateEnableCheckedJni: thread has no JNIEnv\n");
diff --git a/vm/JniInternal.h b/vm/JniInternal.h
index 79d16ec..37920ca 100644
--- a/vm/JniInternal.h
+++ b/vm/JniInternal.h
@@ -74,13 +74,18 @@
  * Native function return type; used by dvmPlatformInvoke().
  *
  * This is part of Method.jniArgInfo, and must fit in 3 bits.
+ * Note: Assembly code in arch/<arch>/Call<arch>.S relies on
+ * the enum values defined here.
  */
 typedef enum DalvikJniReturnType {
     DALVIK_JNI_RETURN_VOID = 0,     /* must be zero */
-    DALVIK_JNI_RETURN_FLOAT,
-    DALVIK_JNI_RETURN_DOUBLE,
-    DALVIK_JNI_RETURN_S8,
-    DALVIK_JNI_RETURN_S4
+    DALVIK_JNI_RETURN_FLOAT = 1,
+    DALVIK_JNI_RETURN_DOUBLE = 2,
+    DALVIK_JNI_RETURN_S8 = 3,
+    DALVIK_JNI_RETURN_S4 = 4,
+    DALVIK_JNI_RETURN_S2 = 5,
+    DALVIK_JNI_RETURN_U2 = 6,
+    DALVIK_JNI_RETURN_S1 = 7
 } DalvikJniReturnType;
 
 #define DALVIK_JNI_NO_ARG_INFO  0x80000000
@@ -93,15 +98,17 @@
 /*
  * Pop the JNI local stack when we return from a native method.  "saveArea"
  * points to the StackSaveArea for the method we're leaving.
+ *
+ * (This may be implemented directly in assembly in mterp, so changes here
+ * may only affect the portable interpreter.)
  */
 INLINE void dvmPopJniLocals(Thread* self, StackSaveArea* saveArea)
 {
-    if (saveArea->xtra.localRefTop != self->jniLocalRefTable.nextEntry) {
-        LOGVV("LREF: popped %d entries (%d remain)\n",
-            (int)(self->jniLocalRefTable.nextEntry-saveArea->xtra.localRefTop),
-            (int)(saveArea->xtra.localRefTop - self->jniLocalRefTable.table));
-    }
-    self->jniLocalRefTable.nextEntry = saveArea->xtra.localRefTop;
+#ifdef USE_INDIRECT_REF
+    self->jniLocalRefTable.segmentState.all = saveArea->xtra.localRefCookie;
+#else
+    self->jniLocalRefTable.nextEntry = saveArea->xtra.localRefCookie;
+#endif
 }
 
 /*
@@ -114,12 +121,32 @@
 }
 
 /*
- * JNI call bridges.  Not usually called directly.
+ * JNI call bridges.  Not called directly.
+ *
+ * The "Check" versions are used when CheckJNI is enabled.
  */
-void dvmCallJNIMethod(const u4* args, JValue* pResult, const Method* method,
-    Thread* self);
-void dvmCallSynchronizedJNIMethod(const u4* args, JValue* pResult,
+void dvmCallJNIMethod_general(const u4* args, JValue* pResult,
     const Method* method, Thread* self);
+void dvmCallJNIMethod_synchronized(const u4* args, JValue* pResult,
+    const Method* method, Thread* self);
+void dvmCallJNIMethod_virtualNoRef(const u4* args, JValue* pResult,
+    const Method* method, Thread* self);
+void dvmCallJNIMethod_staticNoRef(const u4* args, JValue* pResult,
+    const Method* method, Thread* self);
+void dvmCheckCallJNIMethod_general(const u4* args, JValue* pResult,
+    const Method* method, Thread* self);
+void dvmCheckCallJNIMethod_synchronized(const u4* args, JValue* pResult,
+    const Method* method, Thread* self);
+void dvmCheckCallJNIMethod_virtualNoRef(const u4* args, JValue* pResult,
+    const Method* method, Thread* self);
+void dvmCheckCallJNIMethod_staticNoRef(const u4* args, JValue* pResult,
+    const Method* method, Thread* self);
+
+/*
+ * Configure "method" to use the JNI bridge to call "func".
+ */
+void dvmUseJNIBridge(Method* method, void* func);
+
 
 /*
  * Enable the "checked" versions.
@@ -129,10 +156,22 @@
 void dvmLateEnableCheckedJni(void);
 
 /*
+ * Decode a local, global, or weak-global reference.
+ */
+#ifdef USE_INDIRECT_REF
+Object* dvmDecodeIndirectRef(JNIEnv* env, jobject jobj);
+#else
+/* use an inline to ensure this is a no-op */
+INLINE Object* dvmDecodeIndirectRef(JNIEnv* env, jobject jobj) {
+    return (Object*) jobj;
+}
+#endif
+
+/*
  * Verify that a reference passed in from native code is valid.  Returns
  * an indication of local/global/invalid.
  */
-jobjectRefType dvmGetJNIRefType(Object* obj);
+jobjectRefType dvmGetJNIRefType(JNIEnv* env, jobject jobj);
 
 /*
  * Get the last method called on the interp stack.  This is the method
diff --git a/vm/LinearAlloc.c b/vm/LinearAlloc.c
index 77802ee..8a18af3 100644
--- a/vm/LinearAlloc.c
+++ b/vm/LinearAlloc.c
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 /*
  * Linear memory allocation, tied to class loaders.
  */
@@ -68,7 +69,7 @@
 #define BLOCK_ALIGN         8
 
 /* default length of memory segment (worst case is probably "dexopt") */
-#define DEFAULT_MAX_LENGTH  (4*1024*1024)
+#define DEFAULT_MAX_LENGTH  (5*1024*1024)
 
 /* leave enough space for a length word */
 #define HEADER_EXTRA        4
@@ -137,7 +138,7 @@
 
     fd = ashmem_create_region("dalvik-LinearAlloc", DEFAULT_MAX_LENGTH);
     if (fd < 0) {
-        LOGE("ashmem LinearAlloc failed %s", strerror(errno)); 
+        LOGE("ashmem LinearAlloc failed %s", strerror(errno));
         free(pHdr);
         return NULL;
     }
@@ -148,13 +149,13 @@
         LOGE("LinearAlloc mmap(%d) failed: %s\n", pHdr->mapLength,
             strerror(errno));
         free(pHdr);
-	close(fd);
+        close(fd);
         return NULL;
     }
 
     close(fd);
 #else /*USE_ASHMEM*/
-    // MAP_ANON is listed as "deprecated" on Linux, 
+    // MAP_ANON is listed as "deprecated" on Linux,
     // but MAP_ANONYMOUS is not defined under Mac OS X.
     pHdr->mapAddr = mmap(NULL, pHdr->mapLength, PROT_READ | PROT_WRITE,
         MAP_PRIVATE | MAP_ANON, -1, 0);
@@ -313,7 +314,8 @@
          * works if the users of these functions actually free everything
          * they allocate.
          */
-        LOGE("LinearAlloc exceeded capacity, last=%d\n", (int) size);
+        LOGE("LinearAlloc exceeded capacity (%d), last=%d\n",
+            pHdr->mapLength, (int) size);
         dvmAbort();
     }
 
@@ -686,3 +688,21 @@
     dvmUnlockMutex(&pHdr->lock);
 }
 
+/*
+ * Determine if [start, start+length) is contained in the in-use area of
+ * a single LinearAlloc.  The full set of linear allocators is scanned.
+ *
+ * [ Since we currently only have one region, this is pretty simple.  In
+ * the future we'll need to traverse a table of class loaders. ]
+ */
+bool dvmLinearAllocContains(const void* start, size_t length)
+{
+    LinearAllocHdr* pHdr = getHeader(NULL);
+
+    if (pHdr == NULL)
+        return false;
+
+    return (char*) start >= pHdr->mapAddr &&
+           ((char*)start + length) <= (pHdr->mapAddr + pHdr->curOffset);
+}
+
diff --git a/vm/LinearAlloc.h b/vm/LinearAlloc.h
index 9c1d096..a390ee3 100644
--- a/vm/LinearAlloc.h
+++ b/vm/LinearAlloc.h
@@ -112,4 +112,10 @@
  */
 void dvmLinearAllocDump(Object* classLoader);
 
+/*
+ * Determine if [start, start+length) is contained in the in-use area of
+ * a single LinearAlloc.  The full set of linear allocators is scanned.
+ */
+bool dvmLinearAllocContains(const void* start, size_t length);
+
 #endif /*_DALVIK_LINEARALLOC*/
diff --git a/vm/Misc.c b/vm/Misc.c
index ef9c4af..f8f7256 100644
--- a/vm/Misc.c
+++ b/vm/Misc.c
@@ -280,6 +280,7 @@
         pBits->storage = realloc(pBits->storage, newSize * sizeof(u4));
         memset(&pBits->storage[pBits->storageSize], 0x00,
             (newSize - pBits->storageSize) * sizeof(u4));
+        pBits->storageSize = newSize;
     }
 
     pBits->storage[num >> 5] |= 1 << (num & 0x1f);
@@ -297,6 +298,15 @@
 }
 
 /*
+ * Mark all bits bit as "clear".
+ */
+void dvmClearAllBits(BitVector* pBits)
+{
+    int count = pBits->storageSize;
+    memset(pBits->storage, 0, count * sizeof(u4));
+}
+
+/*
  * Determine whether or not the specified bit is set.
  */
 bool dvmIsBitSet(const BitVector* pBits, int num)
@@ -334,7 +344,6 @@
     return count;
 }
 
-
 /*
  * Return a newly-allocated string in which all occurrences of '.' have
  * been changed to '/'.  If we find a '/' in the original string, NULL
diff --git a/vm/Misc.h b/vm/Misc.h
index 5f3af7b..14635a3 100644
--- a/vm/Misc.h
+++ b/vm/Misc.h
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 /*
  * Miscellaneous utility functions.
  */
@@ -51,28 +52,6 @@
     conv.in = val;
     return conv.out;
 }
-#if 0
-INLINE float dvmU8ToFloat(u8 val) {
-    union { u8 in; float out; } conv;
-    conv.in = val;
-    return conv.out;
-}
-INLINE u8 dvmFloatToU8(float val) {
-    union { float in; u8 out; } conv;
-    conv.in = val;
-    return conv.out;
-}
-INLINE double dvmU8ToDouble(u8 val) {
-    union { u8 in; double out; } conv;
-    conv.in = val;
-    return conv.out;
-}
-INLINE u8 dvmDoubleToU8(double val) {
-    union { double in; u8 out; } conv;
-    conv.in = val;
-    return conv.out;
-}
-#endif
 
 /*
  * Print a hex dump to the log file.
@@ -143,7 +122,11 @@
  * Print a debug message.
  */
 void dvmPrintDebugMessage(const DebugOutputTarget* target, const char* format,
-    ...);
+    ...)
+#if defined(__GNUC__)
+    __attribute__ ((format(printf, 2, 3)))
+#endif
+    ;
 
 
 /*
@@ -175,6 +158,7 @@
 int dvmAllocBit(BitVector* pBits);
 bool dvmSetBit(BitVector* pBits, int num);
 void dvmClearBit(BitVector* pBits, int num);
+void dvmClearAllBits(BitVector* pBits);
 bool dvmIsBitSet(const BitVector* pBits, int num);
 
 /* count the number of bits that have been set */
@@ -277,6 +261,17 @@
  */
 bool dvmSetCloseOnExec(int fd);
 
+/*
+ * Unconditionally abort the entire VM.  Try not to use this.
+ *
+ * NOTE: if this is marked ((noreturn)), gcc will merge multiple dvmAbort()
+ * calls in a single function together.  This is good, in that it reduces
+ * code size slightly, but also bad, because the native stack trace we
+ * get from the abort may point at the wrong call site.  Best to leave
+ * it undecorated.
+ */
+void dvmAbort(void);
+
 #if (!HAVE_STRLCPY)
 /* Implementation of strlcpy() for platforms that don't already have it. */
 size_t strlcpy(char *dst, const char *src, size_t size);
diff --git a/vm/Native.c b/vm/Native.c
index 618fb99..31832c2 100644
--- a/vm/Native.c
+++ b/vm/Native.c
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 /*
  * Native method resolution.
  *
@@ -61,6 +62,10 @@
  * Initializes method's class if necessary.
  *
  * An exception is thrown on resolution failure.
+ *
+ * (This should not be taking "const Method*", because it modifies the
+ * structure, but the declaration needs to match the DalvikBridgeFunc
+ * type definition.)
  */
 void dvmResolveNativeMethod(const u4* args, JValue* pResult,
     const Method* method, Thread* self)
@@ -107,11 +112,9 @@
     /* now scan any DLLs we have loaded for JNI signatures */
     func = lookupSharedLibMethod(method);
     if (func != NULL) {
-        if (dvmIsSynchronizedMethod(method))
-            dvmSetNativeFunc(method, dvmCallSynchronizedJNIMethod, func);
-        else
-            dvmSetNativeFunc(method, dvmCallJNIMethod, func);
-        dvmCallJNIMethod(args, pResult, method, self);
+        /* found it, point it at the JNI bridge and then call it */
+        dvmUseJNIBridge((Method*) method, func);
+        (*method->nativeFunc)(args, pResult, method, self);
         return;
     }
 
@@ -467,16 +470,18 @@
      * doesn't have to search through LD_LIBRARY_PATH.  (It may do so to
      * resolve this library's dependencies though.)
      *
-     * Failures here are expected when java.library.path has several entries.
+     * Failures here are expected when java.library.path has several entries
+     * and we have to hunt for the lib.
      *
      * The current android-arm dynamic linker implementation tends to
      * return "Cannot find library" from dlerror() regardless of the actual
-     * problem.  A more useful diagnostic may be sent to stdout/stderr,
-     * but often that's not visible.  Some things to try:
+     * problem.  A more useful diagnostic may be sent to stdout/stderr if
+     * linker diagnostics are enabled, but that's not usually visible in
+     * Android apps.  Some things to try:
      *   - make sure the library exists on the device
      *   - verify that the right path is being opened (the debug log message
      *     above can help with that)
-     *   - check to see if the library is valid
+     *   - check to see if the library is valid (e.g. not zero bytes long)
      *   - check config/prelink-linux-arm.map to ensure that the library
      *     is listed and is not being overrun by the previous entry (if
      *     loading suddenly stops working on a prelinked library, this is
@@ -646,7 +651,7 @@
     for (i = 0; i < charLen; i++) {
         u2 ch = utf16[i];
 
-        if (ch > 127) {
+        if (ch == '$' || ch > 127) {
             mangleLen += 6;
         } else {
             switch (ch) {
@@ -671,7 +676,7 @@
     for (i = 0, cp = mangle; i < charLen; i++) {
         u2 ch = utf16[i];
 
-        if (ch > 127) {
+        if (ch == '$' || ch > 127) {
             sprintf(cp, "_0%04x", ch);
             cp += 6;
         } else {
diff --git a/vm/Profile.c b/vm/Profile.c
index 8e19b34..7f39f1a 100644
--- a/vm/Profile.c
+++ b/vm/Profile.c
@@ -64,6 +64,8 @@
 #define TRACE_MAGIC         0x574f4c53
 #define TRACE_HEADER_LEN    32
 
+#define FILL_PATTERN        0xeeeeeeee
+
 
 /*
  * Get the wall-clock date/time, in usec.
@@ -364,7 +366,7 @@
         dvmThrowException("Ljava/lang/RuntimeException;", "file open failed");
         goto fail;
     }
-    memset(state->buf, 0xee, bufferSize);
+    memset(state->buf, (char)FILL_PATTERN, bufferSize);
 
     state->bufferSize = bufferSize;
     state->overflow = false;
@@ -418,10 +420,10 @@
  * Run through the data buffer and pull out the methods that were visited.
  * Set a mark so that we know which ones to output.
  */
-static void markTouchedMethods(void)
+static void markTouchedMethods(int endOffset)
 {
     u1* ptr = gDvm.methodTrace.buf + TRACE_HEADER_LEN;
-    u1* end = gDvm.methodTrace.buf + gDvm.methodTrace.curOffset;
+    u1* end = gDvm.methodTrace.buf + endOffset;
     unsigned int methodVal;
     Method* method;
 
@@ -508,13 +510,56 @@
     state->traceEnabled = false;
     MEM_BARRIER();
     sched_yield();
+    usleep(250 * 1000);
 
     if ((state->flags & TRACE_ALLOC_COUNTS) != 0)
         dvmStopAllocCounting();
 
+    /*
+     * It's possible under some circumstances for a thread to have advanced
+     * the data pointer but not written the method value.  It's possible
+     * (though less likely) for the data pointer to be advanced, or partial
+     * data written, while we're doing work here.
+     *
+     * To avoid seeing partially-written data, we grab state->curOffset here,
+     * and use our local copy from here on.  We then scan through what's
+     * already written.  If we see the fill pattern in what should be the
+     * method pointer, we cut things off early.  (If we don't, we'll fail
+     * when we dereference the pointer.)
+     *
+     * There's a theoretical possibility of interrupting another thread
+     * after it has partially written the method pointer, in which case
+     * we'll likely crash when we dereference it.  The possibility of
+     * this actually happening should be at or near zero.  Fixing it
+     * completely could be done by writing the thread number last and
+     * using a sentinel value to indicate a partially-written record,
+     * but that requires memory barriers.
+     */
+    int finalCurOffset = state->curOffset;
+
+    if (finalCurOffset > TRACE_HEADER_LEN) {
+        u4 fillVal = METHOD_ID(FILL_PATTERN);
+        u1* scanPtr = state->buf + TRACE_HEADER_LEN;
+
+        while (scanPtr < state->buf + finalCurOffset) {
+            u4 methodVal = scanPtr[1] | (scanPtr[2] << 8) | (scanPtr[3] << 16)
+                        | (scanPtr[4] << 24);
+            if (METHOD_ID(methodVal) == fillVal) {
+                u1* scanBase = state->buf + TRACE_HEADER_LEN;
+                LOGW("Found unfilled record at %d (of %d)\n",
+                    (scanPtr - scanBase) / TRACE_REC_SIZE,
+                    (finalCurOffset - TRACE_HEADER_LEN) / TRACE_REC_SIZE);
+                finalCurOffset = scanPtr - state->buf;
+                break;
+            }
+
+            scanPtr += TRACE_REC_SIZE;
+        }
+    }
+
     LOGI("TRACE STOPPED%s: writing %d records\n",
         state->overflow ? " (NOTE: overflowed buffer)" : "",
-        (state->curOffset - TRACE_HEADER_LEN) / TRACE_REC_SIZE);
+        (finalCurOffset - TRACE_HEADER_LEN) / TRACE_REC_SIZE);
     if (gDvm.debuggerActive) {
         LOGW("WARNING: a debugger is active; method-tracing results "
              "will be skewed\n");
@@ -525,7 +570,7 @@
      */
     u4 clockNsec = getClockOverhead();
 
-    markTouchedMethods();
+    markTouchedMethods(finalCurOffset);
 
     fprintf(state->traceFile, "%cversion\n", TOKEN_CHAR);
     fprintf(state->traceFile, "%d\n", TRACE_VERSION);
@@ -538,7 +583,7 @@
 #endif
     fprintf(state->traceFile, "elapsed-time-usec=%llu\n", elapsed);
     fprintf(state->traceFile, "num-method-calls=%d\n",
-        (state->curOffset - TRACE_HEADER_LEN) / TRACE_REC_SIZE);
+        (finalCurOffset - TRACE_HEADER_LEN) / TRACE_REC_SIZE);
     fprintf(state->traceFile, "clock-call-overhead-nsec=%d\n", clockNsec);
     fprintf(state->traceFile, "vm=dalvik\n");
     if ((state->flags & TRACE_ALLOC_COUNTS) != 0) {
@@ -555,8 +600,8 @@
     dumpMethodList(state->traceFile);
     fprintf(state->traceFile, "%cend\n", TOKEN_CHAR);
 
-    if (fwrite(state->buf, state->curOffset, 1, state->traceFile) != 1) {
-        LOGE("trace fwrite(%d) failed, errno=%d\n", state->curOffset, errno);
+    if (fwrite(state->buf, finalCurOffset, 1, state->traceFile) != 1) {
+        LOGE("trace fwrite(%d) failed, errno=%d\n", finalCurOffset, errno);
         dvmThrowException("Ljava/lang/RuntimeException;", "data write failed");
         goto bail;
     }
@@ -674,7 +719,7 @@
          * Fortunately, the trace tools can get by without the address, but
          * it would be nice to fix this.
          */
-         addr = method->nativeFunc;
+         addr = (u4) method->nativeFunc;
     } else {
         /*
          * The dexlist output shows the &DexCode.insns offset value, which
diff --git a/vm/Properties.c b/vm/Properties.c
index a9fe5e1..91288c2 100644
--- a/vm/Properties.c
+++ b/vm/Properties.c
@@ -165,6 +165,8 @@
     setProperty(propObj, put, "java.io.tmpdir", "/tmp");
     setProperty(propObj, put, "java.library.path", getenv("LD_LIBRARY_PATH"));
 
+    setProperty(propObj, put, "java.net.preferIPv6Addresses", "true");
+
     setProperty(propObj, put, "java.vendor", projectName);
     setProperty(propObj, put, "java.vendor.url", projectUrl);
     setProperty(propObj, put, "java.version", "0");
@@ -185,12 +187,7 @@
     setProperty(propObj, put, "java.specification.vendor", projectName);
     setProperty(propObj, put, "java.specification.version", "0.9");
 
-    #define OS_ARCH generic /* TODO: Use an "arch" header. */
-    #define OS_ARCH_QUOTE(x) #x
-    setProperty(propObj, put, "os.arch", OS_ARCH_QUOTE(OS_ARCH));
-    #undef OS_ARCH
-    #undef OS_ARCH_QUOTE
-
+    setProperty(propObj, put, "os.arch", info.machine);
     setProperty(propObj, put, "os.name", info.sysname);
     setProperty(propObj, put, "os.version", info.release);
     setProperty(propObj, put, "user.home", getenv("HOME"));
@@ -285,4 +282,3 @@
     dvmReleaseTrackedAlloc((Object*)keyObj, NULL);
     return result;
 }
-
diff --git a/vm/ReferenceTable.c b/vm/ReferenceTable.c
index c748222..a8010a2 100644
--- a/vm/ReferenceTable.c
+++ b/vm/ReferenceTable.c
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 /*
  * Reference table management.
  */
@@ -58,11 +59,15 @@
     assert(dvmIsValidObject(obj));
     assert(obj != NULL);
     assert(pRef->table != NULL);
+    assert(pRef->allocEntries <= pRef->maxEntries);
 
-    if (pRef->nextEntry == pRef->table + pRef->maxEntries) {
-        LOGW("ReferenceTable overflow (max=%d)\n", pRef->maxEntries);
-        return false;
-    } else if (pRef->nextEntry == pRef->table + pRef->allocEntries) {
+    if (pRef->nextEntry == pRef->table + pRef->allocEntries) {
+        /* reached end of allocated space; did we hit buffer max? */
+        if (pRef->nextEntry == pRef->table + pRef->maxEntries) {
+            LOGW("ReferenceTable overflow (max=%d)\n", pRef->maxEntries);
+            return false;
+        }
+
         Object** newTable;
         int newSize;
 
@@ -92,13 +97,13 @@
 /*
  * Returns NULL if not found.
  */
-Object** dvmFindInReferenceTable(const ReferenceTable* pRef, Object** top,
+Object** dvmFindInReferenceTable(const ReferenceTable* pRef, Object** bottom,
     Object* obj)
 {
     Object** ptr;
 
     ptr = pRef->nextEntry;
-    while (--ptr >= top) {
+    while (--ptr >= bottom) {
         if (*ptr == obj)
             return ptr;
     }
@@ -108,12 +113,12 @@
 /*
  * Remove "obj" from "pRef".  We start at the end of the list (where the
  * most-recently-added element is), and stop searching for a match after
- * examining the element at "top".
+ * examining the element at "bottom".
  *
  * Most of the time "obj" is at or near the end of the list.  If not, we
  * compact it down.
  */
-bool dvmRemoveFromReferenceTable(ReferenceTable* pRef, Object** top,
+bool dvmRemoveFromReferenceTable(ReferenceTable* pRef, Object** bottom,
     Object* obj)
 {
     Object** ptr;
@@ -121,10 +126,10 @@
     assert(pRef->table != NULL);
 
     /*
-     * Scan from the most-recently-added entry up to the top entry for
+     * Scan from the most-recently-added entry up to the bottom entry for
      * this frame.
      */
-    ptr = dvmFindInReferenceTable(pRef, top, obj);
+    ptr = dvmFindInReferenceTable(pRef, bottom, obj);
     if (ptr == NULL)
         return false;
 
diff --git a/vm/ReferenceTable.h b/vm/ReferenceTable.h
index f8f2461..d6e2d70 100644
--- a/vm/ReferenceTable.h
+++ b/vm/ReferenceTable.h
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 /*
  * Maintain a table of references.  Used for internal local references,
  * JNI locals, JNI globals, and GC heap references.
@@ -36,8 +37,8 @@
  * table/nextEntry is allowed.)
  */
 typedef struct ReferenceTable {
-    Object**        table;              /* top of the list */
-    Object**        nextEntry;          /* bottom of the list */
+    Object**        nextEntry;          /* top of the list */
+    Object**        table;              /* bottom of the list */
 
     int             allocEntries;       /* #of entries we have space for */
     int             maxEntries;         /* max #of entries allowed */
@@ -88,23 +89,24 @@
 bool dvmAddToReferenceTable(ReferenceTable* pRef, Object* obj);
 
 /*
- * Determine if "obj" is present in "pRef".  Stops searching when we hit "top".
- * To include the entire table, pass in "pRef->table" as the top.
+ * Determine if "obj" is present in "pRef".  Stops searching when we hit
+ * "bottom".  To include the entire table, pass in "pRef->table" as the
+ * bottom.
  *
  * Returns NULL if "obj" was not found.
  */
-Object** dvmFindInReferenceTable(const ReferenceTable* pRef, Object** top,
+Object** dvmFindInReferenceTable(const ReferenceTable* pRef, Object** bottom,
     Object* obj);
 
 /*
  * Remove an existing entry.
  *
- * We stop searching for a match after examining the element at "top".  This
- * is useful when entries are associated with a stack frame.
+ * We stop searching for a match after examining the element at "bottom".
+ * This is useful when entries are associated with a stack frame.
  *
  * Returns "false" if the entry was not found.
  */
-bool dvmRemoveFromReferenceTable(ReferenceTable* pRef, Object** top,
+bool dvmRemoveFromReferenceTable(ReferenceTable* pRef, Object** bottom,
     Object* obj);
 
 /*
diff --git a/vm/SignalCatcher.c b/vm/SignalCatcher.c
index 550f777..e187aeb 100644
--- a/vm/SignalCatcher.c
+++ b/vm/SignalCatcher.c
@@ -192,6 +192,9 @@
     sigemptyset(&mask);
     sigaddset(&mask, SIGQUIT);
     sigaddset(&mask, SIGUSR1);
+#if defined(WITH_JIT) && defined(WITH_JIT_TUNING)
+    sigaddset(&mask, SIGUSR2);
+#endif
 
     while (true) {
         int rcvd;
@@ -237,9 +240,13 @@
 
             logThreadStacks();
 
+#if defined(WITH_JIT) && defined(WITH_JIT_TUNING)
+            dvmCompilerDumpStats();
+#endif
+
             if (false) {
                 dvmLockMutex(&gDvm.jniGlobalRefLock);
-                dvmDumpReferenceTable(&gDvm.jniGlobalRefTable, "JNI global");
+                //dvmDumpReferenceTable(&gDvm.jniGlobalRefTable, "JNI global");
                 dvmUnlockMutex(&gDvm.jniGlobalRefLock);
             }
 
@@ -253,6 +260,13 @@
             LOGI("SIGUSR1 forcing GC (no HPROF)\n");
             dvmCollectGarbage(false);
 #endif
+#if defined(WITH_JIT) && defined(WITH_JIT_TUNING)
+        } else if (rcvd == SIGUSR2) {
+            gDvmJit.printMe ^= true;
+            dvmCompilerDumpStats();
+            /* Stress-test unchain all */
+            dvmJitUnchainAll();
+#endif
         } else {
             LOGE("unexpected signal %d\n", rcvd);
         }
@@ -260,4 +274,3 @@
 
     return NULL;
 }
-
diff --git a/vm/Thread.c b/vm/Thread.c
index ee195eb..be3e952 100644
--- a/vm/Thread.c
+++ b/vm/Thread.c
@@ -13,10 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 /*
  * Thread support.
  */
 #include "Dalvik.h"
+#include "native/SystemThread.h"
 
 #include "utils/threads.h"      // need Android thread priorities
 
@@ -26,6 +28,9 @@
 #include <sys/resource.h>
 #include <sys/mman.h>
 #include <errno.h>
+#include <fcntl.h>
+
+#include <cutils/sched_policy.h>
 
 #if defined(HAVE_PRCTL)
 #include <sys/prctl.h>
@@ -233,6 +238,16 @@
 static void waitForThreadSuspend(Thread* self, Thread* thread);
 static int getThreadPriorityFromSystem(void);
 
+/*
+ * The JIT needs to know if any thread is suspended.  We do this by
+ * maintaining a global sum of all threads' suspend counts.  All suspendCount
+ * updates should go through this after aquiring threadSuspendCountLock.
+ */
+static inline void dvmAddToThreadSuspendCount(int *pSuspendCount, int delta)
+{
+    *pSuspendCount += delta;
+    gDvm.sumThreadSuspendCount += delta;
+}
 
 /*
  * Initialize thread list and main thread's environment.  We need to set
@@ -398,8 +413,12 @@
 void dvmThreadShutdown(void)
 {
     if (gDvm.threadList != NULL) {
-        assert(gDvm.threadList->next == NULL);
-        assert(gDvm.threadList->prev == NULL);
+        /*
+         * If we walk through the thread list and try to free the
+         * lingering thread structures (which should only be for daemon
+         * threads), the daemon threads may crash if they execute before
+         * the process dies.  Let them leak.
+         */
         freeThread(gDvm.threadList);
         gDvm.threadList = NULL;
     }
@@ -448,6 +467,11 @@
  * We don't have to check to see if we should be suspended once we have
  * the lock.  Nobody can suspend all threads without holding the thread list
  * lock while they do it, so by definition there isn't a GC in progress.
+ *
+ * TODO: consider checking for suspend after acquiring the lock, and
+ * backing off if set.  As stated above, it can't happen during normal
+ * execution, but it *can* happen during shutdown when daemon threads
+ * are being suspended.
  */
 void dvmLockThreadList(Thread* self)
 {
@@ -460,7 +484,7 @@
         oldStatus = self->status;
         self->status = THREAD_VMWAIT;
     } else {
-        /* happens for JNI AttachCurrentThread [not anymore?] */
+        /* happens during VM shutdown */
         //LOGW("NULL self in dvmLockThreadList\n");
         oldStatus = -1;         // shut up gcc
     }
@@ -510,7 +534,7 @@
     u8 startWhen = 0;       // init req'd to placate gcc
     int sleepIter = 0;
     int cc;
-    
+
     do {
         cc = pthread_mutex_trylock(&gDvm._threadSuspendLock);
         if (cc != 0) {
@@ -519,8 +543,8 @@
                  * Could be that a resume-all is in progress, and something
                  * grabbed the CPU when the wakeup was broadcast.  The thread
                  * performing the resume hasn't had a chance to release the
-                 * thread suspend lock.  (Should no longer be an issue --
-                 * we now release before broadcast.)
+                 * thread suspend lock.  (We release before the broadcast,
+                 * so this should be a narrow window.)
                  *
                  * Could be we hit the window as a suspend was started,
                  * and the lock has been grabbed but the suspend counts
@@ -580,19 +604,24 @@
  *
  * It's possible for this function to get called after a failed
  * initialization, so be careful with assumptions about the environment.
+ *
+ * This will be called from whatever thread calls DestroyJavaVM, usually
+ * but not necessarily the main thread.  It's likely, but not guaranteed,
+ * that the current thread has already been cleaned up.
  */
 void dvmSlayDaemons(void)
 {
-    Thread* self = dvmThreadSelf();
+    Thread* self = dvmThreadSelf();     // may be null
     Thread* target;
-    Thread* nextTarget;
-
-    if (self == NULL)
-        return;
+    int threadId = 0;
+    bool doWait = false;
 
     //dvmEnterCritical(self);
     dvmLockThreadList(self);
 
+    if (self != NULL)
+        threadId = self->threadId;
+
     target = gDvm.threadList;
     while (target != NULL) {
         if (target == self) {
@@ -603,27 +632,95 @@
         if (!dvmGetFieldBoolean(target->threadObj,
                 gDvm.offJavaLangThread_daemon))
         {
+            /* should never happen; suspend it with the rest */
             LOGW("threadid=%d: non-daemon id=%d still running at shutdown?!\n",
-                self->threadId, target->threadId);
-            target = target->next;
-            continue;
+                threadId, target->threadId);
         }
 
-        LOGI("threadid=%d: killing leftover daemon threadid=%d [TODO]\n",
-            self->threadId, target->threadId);
-        // TODO: suspend and/or kill the thread
-        // (at the very least, we can "rescind their JNI privileges")
+        char* threadName = dvmGetThreadName(target);
+        LOGD("threadid=%d: suspending daemon id=%d name='%s'\n",
+            threadId, target->threadId, threadName);
+        free(threadName);
 
-        /* remove from list */
-        nextTarget = target->next;
+        /* mark as suspended */
+        lockThreadSuspendCount();
+        dvmAddToThreadSuspendCount(&target->suspendCount, 1);
+        unlockThreadSuspendCount();
+        doWait = true;
+
+        target = target->next;
+    }
+
+    //dvmDumpAllThreads(false);
+
+    /*
+     * Unlock the thread list, relocking it later if necessary.  It's
+     * possible a thread is in VMWAIT after calling dvmLockThreadList,
+     * and that function *doesn't* check for pending suspend after
+     * acquiring the lock.  We want to let them finish their business
+     * and see the pending suspend before we continue here.
+     *
+     * There's no guarantee of mutex fairness, so this might not work.
+     * (The alternative is to have dvmLockThreadList check for suspend
+     * after acquiring the lock and back off, something we should consider.)
+     */
+    dvmUnlockThreadList();
+
+    if (doWait) {
+        usleep(200 * 1000);
+
+        dvmLockThreadList(self);
+
+        /*
+         * Sleep for a bit until the threads have suspended.  We're trying
+         * to exit, so don't wait for too long.
+         */
+        int i;
+        for (i = 0; i < 10; i++) {
+            bool allSuspended = true;
+
+            target = gDvm.threadList;
+            while (target != NULL) {
+                if (target == self) {
+                    target = target->next;
+                    continue;
+                }
+
+                if (target->status == THREAD_RUNNING && !target->isSuspended) {
+                    LOGD("threadid=%d not ready yet\n", target->threadId);
+                    allSuspended = false;
+                    break;
+                }
+
+                target = target->next;
+            }
+
+            if (allSuspended) {
+                LOGD("threadid=%d: all daemons have suspended\n", threadId);
+                break;
+            } else {
+                LOGD("threadid=%d: waiting for daemons to suspend\n", threadId);
+            }
+
+            usleep(200 * 1000);
+        }
+        dvmUnlockThreadList();
+    }
+
+#if 0   /* bad things happen if they come out of JNI or "spuriously" wake up */
+    /*
+     * Abandon the threads and recover their resources.
+     */
+    target = gDvm.threadList;
+    while (target != NULL) {
+        Thread* nextTarget = target->next;
         unlinkThread(target);
-
         freeThread(target);
         target = nextTarget;
     }
+#endif
 
-    dvmUnlockThreadList();
-    //dvmExitCritical(self);
+    //dvmDumpAllThreads(true);
 }
 
 
@@ -886,15 +983,22 @@
     /*
      * Initialize our reference tracking tables.
      *
-     * The JNI local ref table *must* be fixed-size because we keep pointers
-     * into the table in our stack frames.
-     *
      * Most threads won't use jniMonitorRefTable, so we clear out the
      * structure but don't call the init function (which allocs storage).
      */
+#ifdef USE_INDIRECT_REF
+    if (!dvmInitIndirectRefTable(&thread->jniLocalRefTable,
+            kJniLocalRefMin, kJniLocalRefMax, kIndirectKindLocal))
+        return false;
+#else
+    /*
+     * The JNI local ref table *must* be fixed-size because we keep pointers
+     * into the table in our stack frames.
+     */
     if (!dvmInitReferenceTable(&thread->jniLocalRefTable,
             kJniLocalRefMax, kJniLocalRefMax))
         return false;
+#endif
     if (!dvmInitReferenceTable(&thread->internalLocalRefTable,
             kInternalRefDefault, kInternalRefMax))
         return false;
@@ -948,7 +1052,11 @@
 #endif
     }
 
+#ifdef USE_INDIRECT_REF
+    dvmClearIndirectRefTable(&thread->jniLocalRefTable);
+#else
     dvmClearReferenceTable(&thread->jniLocalRefTable);
+#endif
     dvmClearReferenceTable(&thread->internalLocalRefTable);
     if (&thread->jniMonitorRefTable.table != NULL)
         dvmClearReferenceTable(&thread->jniMonitorRefTable);
@@ -995,6 +1103,12 @@
  * This is mainly of use to ensure that we don't leak resources if, for
  * example, a thread attaches itself to us with AttachCurrentThread and
  * then exits without notifying the VM.
+ *
+ * We could do the detach here instead of aborting, but this will lead to
+ * portability problems.  Other implementations do not do this check and
+ * will simply be unaware that the thread has exited, leading to resource
+ * leaks (and, if this is a non-daemon thread, an infinite hang when the
+ * VM tries to shut down).
  */
 static void threadExitCheck(void* arg)
 {
@@ -1004,7 +1118,6 @@
     assert(thread != NULL);
 
     if (thread->status != THREAD_ZOMBIE) {
-        /* TODO: instead of failing, we could call dvmDetachCurrentThread() */
         LOGE("Native thread exited without telling us\n");
         dvmAbort();
     }
@@ -1185,10 +1298,18 @@
     assert(threadObj != NULL);
 
     if(gDvm.zygote) {
-        dvmThrowException("Ljava/lang/IllegalStateException;",
-            "No new threads in -Xzygote mode");
+        // Allow the sampling profiler thread. We shut it down before forking.
+        StringObject* nameStr = (StringObject*) dvmGetFieldObject(threadObj,
+                    gDvm.offJavaLangThread_name);
+        char* threadName = dvmCreateCstrFromString(nameStr);
+        bool profilerThread = strcmp(threadName, "SamplingProfiler") == 0;
+        free(threadName);
+        if (!profilerThread) {
+            dvmThrowException("Ljava/lang/IllegalStateException;",
+                "No new threads in -Xzygote mode");
 
-        goto fail;
+            goto fail;
+        }
     }
 
     self = dvmThreadSelf();
@@ -1470,7 +1591,7 @@
      * setPriority(), and then starts the thread.  We could manage this with
      * a "needs priority update" flag to avoid the redundant call.
      */
-    int priority = dvmGetFieldBoolean(self->threadObj,
+    int priority = dvmGetFieldInt(self->threadObj,
                         gDvm.offJavaLangThread_priority);
     dvmChangeThreadPriority(self, priority);
 
@@ -1562,6 +1683,12 @@
     }
 
 bail:
+#if defined(WITH_JIT)
+    /* Remove this thread's suspendCount from global suspendCount sum */
+    lockThreadSuspendCount();
+    dvmAddToThreadSuspendCount(&self->suspendCount, -self->suspendCount);
+    unlockThreadSuspendCount();
+#endif
     dvmReleaseTrackedAlloc(exception, self);
 }
 
@@ -2116,6 +2243,9 @@
     dvmUnlockThreadList();
 
     setThreadSelf(NULL);
+
+    dvmDetachSystemThread(self);
+
     freeThread(self);
 }
 
@@ -2138,7 +2268,7 @@
     //assert(thread->handle != dvmJdwpGetDebugThread(gDvm.jdwpState));
 
     lockThreadSuspendCount();
-    thread->suspendCount++;
+    dvmAddToThreadSuspendCount(&thread->suspendCount, 1);
     thread->dbgSuspendCount++;
 
     LOG_THREAD("threadid=%d: suspend++, now=%d\n",
@@ -2167,7 +2297,7 @@
 
     lockThreadSuspendCount();
     if (thread->suspendCount > 0) {
-        thread->suspendCount--;
+        dvmAddToThreadSuspendCount(&thread->suspendCount, -1);
         thread->dbgSuspendCount--;
     } else {
         LOG_THREAD("threadid=%d:  suspendCount already zero\n",
@@ -2205,7 +2335,7 @@
      * though.
      */
     lockThreadSuspendCount();
-    self->suspendCount++;
+    dvmAddToThreadSuspendCount(&self->suspendCount, 1);
     self->dbgSuspendCount++;
 
     /*
@@ -2300,7 +2430,7 @@
         char proc[100];
         sprintf(proc, "/proc/%d/exe", getpid());
         int len;
-        
+
         len = readlink(proc, exePath, sizeof(exePath)-1);
         exePath[len] = '\0';
     }
@@ -2343,29 +2473,83 @@
  *
  * TODO: track basic stats about time required to suspend VM.
  */
+#define FIRST_SLEEP (250*1000)    /* 0.25s */
+#define MORE_SLEEP  (750*1000)    /* 0.75s */
 static void waitForThreadSuspend(Thread* self, Thread* thread)
 {
     const int kMaxRetries = 10;
-    const int kSpinSleepTime = 750*1000;        /* 0.75s */
+    int spinSleepTime = FIRST_SLEEP;
     bool complained = false;
+    bool needPriorityReset = false;
+    int savedThreadPrio = -500;
 
     int sleepIter = 0;
     int retryCount = 0;
     u8 startWhen = 0;       // init req'd to placate gcc
+    u8 firstStartWhen = 0;
 
     while (thread->status == THREAD_RUNNING && !thread->isSuspended) {
-        if (sleepIter == 0)         // get current time on first iteration
+        if (sleepIter == 0) {           // get current time on first iteration
             startWhen = dvmGetRelativeTimeUsec();
+            if (firstStartWhen == 0)    // first iteration of first attempt
+                firstStartWhen = startWhen;
 
-        if (!dvmIterativeSleep(sleepIter++, kSpinSleepTime, startWhen)) {
-            LOGW("threadid=%d (h=%d): spin on suspend threadid=%d (handle=%d)\n",
-                self->threadId, (int)self->handle,
+            /*
+             * After waiting for a bit, check to see if the target thread is
+             * running at a reduced priority.  If so, bump it up temporarily
+             * to give it more CPU time.
+             *
+             * getpriority() returns the "nice" value, so larger numbers
+             * indicate lower priority.
+             *
+             * (Not currently changing the cgroup.  Wasn't necessary in some
+             * simple experiments.)
+             */
+            if (retryCount == 2) {
+                assert(thread->systemTid != 0);
+                errno = 0;
+                int threadPrio = getpriority(PRIO_PROCESS, thread->systemTid);
+                if (errno == 0 && threadPrio > 0) {
+                    const int kHigher = 0;
+                    if (setpriority(PRIO_PROCESS, thread->systemTid, kHigher) < 0)
+                    {
+                        LOGW("Couldn't raise priority on tid %d to %d\n",
+                            thread->systemTid, kHigher);
+                    } else {
+                        savedThreadPrio = threadPrio;
+                        needPriorityReset = true;
+                        LOGD("Temporarily raising priority on tid %d (%d -> %d)\n",
+                            thread->systemTid, threadPrio, kHigher);
+                    }
+                }
+            }
+        }
+
+#if defined (WITH_JIT)
+        /*
+         * If we're still waiting after the first timeout,
+         * unchain all translations.
+         */
+        if (gDvmJit.pJitEntryTable && retryCount > 0) {
+            LOGD("JIT unchain all attempt #%d",retryCount);
+            dvmJitUnchainAll();
+        }
+#endif
+
+        /*
+         * Sleep briefly.  This returns false if we've exceeded the total
+         * time limit for this round of sleeping.
+         */
+        if (!dvmIterativeSleep(sleepIter++, spinSleepTime, startWhen)) {
+            LOGW("threadid=%d: spin on suspend #%d threadid=%d (h=%d)\n",
+                self->threadId, retryCount,
                 thread->threadId, (int)thread->handle);
             dumpWedgedThread(thread);
             complained = true;
 
             // keep going; could be slow due to valgrind
             sleepIter = 0;
+            spinSleepTime = MORE_SLEEP;
 
             if (retryCount++ == kMaxRetries) {
                 LOGE("threadid=%d: stuck on threadid=%d, giving up\n",
@@ -2377,9 +2561,20 @@
     }
 
     if (complained) {
-        LOGW("threadid=%d: spin on suspend resolved\n", self->threadId);
+        LOGW("threadid=%d: spin on suspend resolved in %lld msec\n",
+            self->threadId,
+            (dvmGetRelativeTimeUsec() - firstStartWhen) / 1000);
         //dvmDumpThread(thread, false);   /* suspended, so dump is safe */
     }
+    if (needPriorityReset) {
+        if (setpriority(PRIO_PROCESS, thread->systemTid, savedThreadPrio) < 0) {
+            LOGW("NOTE: couldn't reset priority on thread %d to %d\n",
+                thread->systemTid, savedThreadPrio);
+        } else {
+            LOGV("Restored priority on %d to %d\n",
+                thread->systemTid, savedThreadPrio);
+        }
+    }
 }
 
 /*
@@ -2444,7 +2639,7 @@
             thread->handle == dvmJdwpGetDebugThread(gDvm.jdwpState))
             continue;
 
-        thread->suspendCount++;
+        dvmAddToThreadSuspendCount(&thread->suspendCount, 1);
         if (why == SUSPEND_FOR_DEBUG || why == SUSPEND_FOR_DEBUG_EVENT)
             thread->dbgSuspendCount++;
     }
@@ -2476,7 +2671,7 @@
         /* wait for the other thread to see the pending suspend */
         waitForThreadSuspend(self, thread);
 
-        LOG_THREAD("threadid=%d:   threadid=%d status=%d c=%d dc=%d isSusp=%d\n", 
+        LOG_THREAD("threadid=%d:   threadid=%d status=%d c=%d dc=%d isSusp=%d\n",
             self->threadId,
             thread->threadId, thread->status, thread->suspendCount,
             thread->dbgSuspendCount, thread->isSuspended);
@@ -2521,7 +2716,7 @@
         }
 
         if (thread->suspendCount > 0) {
-            thread->suspendCount--;
+            dvmAddToThreadSuspendCount(&thread->suspendCount, -1);
             if (why == SUSPEND_FOR_DEBUG || why == SUSPEND_FOR_DEBUG_EVENT)
                 thread->dbgSuspendCount--;
         } else {
@@ -2612,7 +2807,8 @@
         }
 
         assert(thread->suspendCount >= thread->dbgSuspendCount);
-        thread->suspendCount -= thread->dbgSuspendCount;
+        dvmAddToThreadSuspendCount(&thread->suspendCount,
+                                   -thread->dbgSuspendCount);
         thread->dbgSuspendCount = 0;
     }
     unlockThreadSuspendCount();
@@ -2827,6 +3023,23 @@
     int vmData;
 
     vmData = dvmGetFieldInt(vmThreadObj, gDvm.offJavaLangVMThread_vmData);
+
+    if (false) {
+        Thread* thread = gDvm.threadList;
+        while (thread != NULL) {
+            if ((Thread*)vmData == thread)
+                break;
+
+            thread = thread->next;
+        }
+
+        if (thread == NULL) {
+            LOGW("WARNING: vmThreadObj=%p has thread=%p, not in thread list\n",
+                vmThreadObj, (Thread*)vmData);
+            vmData = 0;
+        }
+    }
+
     return (Thread*) vmData;
 }
 
@@ -2851,41 +3064,6 @@
 };
 
 /*
- * Change the scheduler cgroup of a pid
- */
-int dvmChangeThreadSchedulerGroup(const char *cgroup)
-{
-#ifdef HAVE_ANDROID_OS
-    FILE *fp;
-    char path[255];
-    int rc;
-
-    sprintf(path, "/dev/cpuctl/%s/tasks", (cgroup ? cgroup : ""));
-
-    if (!(fp = fopen(path, "w"))) {
-#if ENABLE_CGROUP_ERR_LOGGING
-        LOGW("Unable to open %s (%s)\n", path, strerror(errno));
-#endif
-        return -errno;
-    }
-
-    rc = fprintf(fp, "0");
-    fclose(fp);
-
-    if (rc < 0) {
-#if ENABLE_CGROUP_ERR_LOGGING
-        LOGW("Unable to move pid %d to cgroup %s (%s)\n", getpid(),
-             (cgroup ? cgroup : "<default>"), strerror(errno));
-#endif
-    }
-
-    return (rc < 0) ? errno : 0;
-#else // HAVE_ANDROID_OS
-    return 0;
-#endif
-}
-
-/*
  * Change the priority of a system thread to match that of the Thread object.
  *
  * We map a priority value from 1-10 to Linux "nice" values, where lower
@@ -2902,10 +3080,10 @@
     }
     newNice = kNiceValues[newPriority-1];
 
-    if (newPriority >= ANDROID_PRIORITY_BACKGROUND) {
-        dvmChangeThreadSchedulerGroup("bg_non_interactive");
+    if (newNice >= ANDROID_PRIORITY_BACKGROUND) {
+        set_sched_policy(dvmGetSysThreadId(), SP_BACKGROUND);
     } else if (getpriority(PRIO_PROCESS, pid) >= ANDROID_PRIORITY_BACKGROUND) {
-        dvmChangeThreadSchedulerGroup(NULL);
+        set_sched_policy(dvmGetSysThreadId(), SP_FOREGROUND);
     }
 
     if (setpriority(PRIO_PROCESS, pid, newNice) != 0) {
@@ -2981,6 +3159,56 @@
 }
 
 /*
+ * Try to get the scheduler group.
+ *
+ * The data from /proc/<pid>/cgroup looks like:
+ *  2:cpu:/bg_non_interactive
+ *
+ * We return the part after the "/", which will be an empty string for
+ * the default cgroup.  If the string is longer than "bufLen", the string
+ * will be truncated.
+ */
+static bool getSchedulerGroup(Thread* thread, char* buf, size_t bufLen)
+{
+#ifdef HAVE_ANDROID_OS
+    char pathBuf[32];
+    char readBuf[256];
+    ssize_t count;
+    int fd;
+
+    snprintf(pathBuf, sizeof(pathBuf), "/proc/%d/cgroup", thread->systemTid);
+    if ((fd = open(pathBuf, O_RDONLY)) < 0) {
+        LOGV("open(%s) failed: %s\n", pathBuf, strerror(errno));
+        return false;
+    }
+
+    count = read(fd, readBuf, sizeof(readBuf));
+    if (count <= 0) {
+        LOGV("read(%s) failed (%d): %s\n",
+            pathBuf, (int) count, strerror(errno));
+        close(fd);
+        return false;
+    }
+    close(fd);
+
+    readBuf[--count] = '\0';    /* remove the '\n', now count==strlen */
+
+    char* cp = strchr(readBuf, '/');
+    if (cp == NULL) {
+        readBuf[sizeof(readBuf)-1] = '\0';
+        LOGV("no '/' in '%s' (file=%s count=%d)\n",
+            readBuf, pathBuf, (int) count);
+        return false;
+    }
+
+    memcpy(buf, cp+1, count);   /* count-1 for cp+1, count+1 for NUL */
+    return true;
+#else
+    return false;
+#endif
+}
+
+/*
  * Print information about the specified thread.
  *
  * Works best when the thread in question is "self" or has been suspended.
@@ -3000,6 +3228,7 @@
     StringObject* nameStr;
     char* threadName = NULL;
     char* groupName = NULL;
+    char schedulerGroupBuf[32];
     bool isDaemon;
     int priority;               // java.lang.Thread priority
     int policy;                 // pthread policy
@@ -3022,6 +3251,12 @@
         policy = -1;
         sp.sched_priority = -1;
     }
+    if (!getSchedulerGroup(thread, schedulerGroupBuf,sizeof(schedulerGroupBuf)))
+    {
+        strcpy(schedulerGroupBuf, "unknown");
+    } else if (schedulerGroupBuf[0] == '\0') {
+        strcpy(schedulerGroupBuf, "default");
+    }
 
     /* a null value for group is not expected, but deal with it anyway */
     groupObj = (Object*) dvmGetFieldObject(threadObj,
@@ -3049,9 +3284,9 @@
         groupName, thread->suspendCount, thread->dbgSuspendCount,
         thread->isSuspended ? 'Y' : 'N', thread->threadObj, thread);
     dvmPrintDebugMessage(target,
-        "  | sysTid=%d nice=%d sched=%d/%d handle=%d\n",
+        "  | sysTid=%d nice=%d sched=%d/%d cgrp=%s handle=%d\n",
         thread->systemTid, getpriority(PRIO_PROCESS, thread->systemTid),
-        policy, sp.sched_priority, (int)thread->handle);
+        policy, sp.sched_priority, schedulerGroupBuf, (int)thread->handle);
 
 #ifdef WITH_MONITOR_TRACKING
     if (!isRunning) {
@@ -3274,9 +3509,15 @@
  * GC helper functions
  */
 
+/*
+ * Add the contents of the registers from the interpreted call stack.
+ */
 static void gcScanInterpStackReferences(Thread *thread)
 {
     const u4 *framePtr;
+#if WITH_EXTRA_GC_CHECKS > 1
+    bool first = true;
+#endif
 
     framePtr = (const u4 *)thread->curFrame;
     while (framePtr != NULL) {
@@ -3285,27 +3526,182 @@
 
         saveArea = SAVEAREA_FROM_FP(framePtr);
         method = saveArea->method;
-        if (method != NULL) {
+        if (method != NULL && !dvmIsNativeMethod(method)) {
 #ifdef COUNT_PRECISE_METHODS
             /* the GC is running, so no lock required */
-            if (!dvmIsNativeMethod(method)) {
-                if (dvmPointerSetAddEntry(gDvm.preciseMethods, method))
-                    LOGI("Added %s.%s %p\n",
-                        method->clazz->descriptor, method->name, method);
-            }
+            if (dvmPointerSetAddEntry(gDvm.preciseMethods, method))
+                LOGI("PGC: added %s.%s %p\n",
+                    method->clazz->descriptor, method->name, method);
 #endif
-            int i;
-            for (i = method->registersSize - 1; i >= 0; i--) {
-                u4 rval = *framePtr++;
-//TODO: wrap markifobject in a macro that does pointer checks
-                if (rval != 0 && (rval & 0x3) == 0) {
-                    dvmMarkIfObject((Object *)rval);
+#if WITH_EXTRA_GC_CHECKS > 1
+            /*
+             * May also want to enable the memset() in the "invokeMethod"
+             * goto target in the portable interpreter.  That sets the stack
+             * to a pattern that makes referring to uninitialized data
+             * very obvious.
+             */
+
+            if (first) {
+                /*
+                 * First frame, isn't native, check the "alternate" saved PC
+                 * as a sanity check.
+                 *
+                 * It seems like we could check the second frame if the first
+                 * is native, since the PCs should be the same.  It turns out
+                 * this doesn't always work.  The problem is that we could
+                 * have calls in the sequence:
+                 *   interp method #2
+                 *   native method
+                 *   interp method #1
+                 *
+                 * and then GC while in the native method after returning
+                 * from interp method #2.  The currentPc on the stack is
+                 * for interp method #1, but thread->currentPc2 is still
+                 * set for the last thing interp method #2 did.
+                 *
+                 * This can also happen in normal execution:
+                 * - sget-object on not-yet-loaded class
+                 * - class init updates currentPc2
+                 * - static field init is handled by parsing annotations;
+                 *   static String init requires creation of a String object,
+                 *   which can cause a GC
+                 *
+                 * Essentially, any pattern that involves executing
+                 * interpreted code and then causes an allocation without
+                 * executing instructions in the original method will hit
+                 * this.  These are rare enough that the test still has
+                 * some value.
+                 */
+                if (saveArea->xtra.currentPc != thread->currentPc2) {
+                    LOGW("PGC: savedPC(%p) != current PC(%p), %s.%s ins=%p\n",
+                        saveArea->xtra.currentPc, thread->currentPc2,
+                        method->clazz->descriptor, method->name, method->insns);
+                    if (saveArea->xtra.currentPc != NULL)
+                        LOGE("  pc inst = 0x%04x\n", *saveArea->xtra.currentPc);
+                    if (thread->currentPc2 != NULL)
+                        LOGE("  pc2 inst = 0x%04x\n", *thread->currentPc2);
+                    dvmDumpThread(thread, false);
                 }
+            } else {
+                /*
+                 * It's unusual, but not impossible, for a non-first frame
+                 * to be at something other than a method invocation.  For
+                 * example, if we do a new-instance on a nonexistent class,
+                 * we'll have a lot of class loader activity on the stack
+                 * above the frame with the "new" operation.  Could also
+                 * happen while we initialize a Throwable when an instruction
+                 * fails.
+                 *
+                 * So there's not much we can do here to verify the PC,
+                 * except to verify that it's a GC point.
+                 */
+            }
+            assert(saveArea->xtra.currentPc != NULL);
+#endif
+
+            const RegisterMap* pMap;
+            const u1* regVector;
+            int i;
+
+            Method* nonConstMethod = (Method*) method;  // quiet gcc
+            pMap = dvmGetExpandedRegisterMap(nonConstMethod);
+            if (pMap != NULL) {
+                /* found map, get registers for this address */
+                int addr = saveArea->xtra.currentPc - method->insns;
+                regVector = dvmRegisterMapGetLine(pMap, addr);
+                if (regVector == NULL) {
+                    LOGW("PGC: map but no entry for %s.%s addr=0x%04x\n",
+                        method->clazz->descriptor, method->name, addr);
+                } else {
+                    LOGV("PGC: found map for %s.%s 0x%04x (t=%d)\n",
+                        method->clazz->descriptor, method->name, addr,
+                        thread->threadId);
+                }
+            } else {
+                /*
+                 * No map found.  If precise GC is disabled this is
+                 * expected -- we don't create pointers to the map data even
+                 * if it's present -- but if it's enabled it means we're
+                 * unexpectedly falling back on a conservative scan, so it's
+                 * worth yelling a little.
+                 */
+                if (gDvm.preciseGc) {
+                    LOGVV("PGC: no map for %s.%s\n",
+                        method->clazz->descriptor, method->name);
+                }
+                regVector = NULL;
+            }
+
+            if (regVector == NULL) {
+                /* conservative scan */
+                for (i = method->registersSize - 1; i >= 0; i--) {
+                    u4 rval = *framePtr++;
+                    if (rval != 0 && (rval & 0x3) == 0) {
+                        dvmMarkIfObject((Object *)rval);
+                    }
+                }
+            } else {
+                /*
+                 * Precise scan.  v0 is at the lowest address on the
+                 * interpreted stack, and is the first bit in the register
+                 * vector, so we can walk through the register map and
+                 * memory in the same direction.
+                 *
+                 * A '1' bit indicates a live reference.
+                 */
+                u2 bits = 1 << 1;
+                for (i = method->registersSize - 1; i >= 0; i--) {
+                    u4 rval = *framePtr++;
+
+                    bits >>= 1;
+                    if (bits == 1) {
+                        /* set bit 9 so we can tell when we're empty */
+                        bits = *regVector++ | 0x0100;
+                        LOGVV("loaded bits: 0x%02x\n", bits & 0xff);
+                    }
+
+                    if (rval != 0 && (bits & 0x01) != 0) {
+                        /*
+                         * Non-null, register marked as live reference.  This
+                         * should always be a valid object.
+                         */
+#if WITH_EXTRA_GC_CHECKS > 0
+                        if ((rval & 0x3) != 0 ||
+                            !dvmIsValidObject((Object*) rval))
+                        {
+                            /* this is very bad */
+                            LOGE("PGC: invalid ref in reg %d: 0x%08x\n",
+                                method->registersSize-1 - i, rval);
+                        } else
+#endif
+                        {
+                            dvmMarkObjectNonNull((Object *)rval);
+                        }
+                    } else {
+                        /*
+                         * Null or non-reference, do nothing at all.
+                         */
+#if WITH_EXTRA_GC_CHECKS > 1
+                        if (dvmIsValidObject((Object*) rval)) {
+                            /* this is normal, but we feel chatty */
+                            LOGD("PGC: ignoring valid ref in reg %d: 0x%08x\n",
+                                method->registersSize-1 - i, rval);
+                        }
+#endif
+                    }
+                }
+                dvmReleaseRegisterMapLine(pMap, regVector);
             }
         }
-        /* else this is a break frame; nothing to mark.
+        /* else this is a break frame and there is nothing to mark, or
+         * this is a native method and the registers are just the "ins",
+         * copied from various registers in the caller's set.
          */
 
+#if WITH_EXTRA_GC_CHECKS > 1
+        first = false;
+#endif
+
         /* Don't fall into an infinite loop if things get corrupted.
          */
         assert((uintptr_t)saveArea->prevFrame > (uintptr_t)framePtr ||
@@ -3331,6 +3727,20 @@
     }
 }
 
+static void gcScanIndirectRefTable(IndirectRefTable* pRefTable)
+{
+    Object** op = pRefTable->table;
+    int numEntries = dvmIndirectRefTableEntries(pRefTable);
+    int i;
+
+    for (i = 0; i < numEntries; i++) {
+        Object* obj = *op;
+        if (obj != NULL)
+            dvmMarkObjectNonNull(obj);
+        op++;
+    }
+}
+
 /*
  * Scan a Thread and mark any objects it references.
  */
@@ -3361,7 +3771,11 @@
 
     HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_JNI_LOCAL, thread->threadId);
 
+#ifdef USE_INDIRECT_REF
+    gcScanIndirectRefTable(&thread->jniLocalRefTable);
+#else
     gcScanReferenceTable(&thread->jniLocalRefTable);
+#endif
 
     if (thread->jniMonitorRefTable.table != NULL) {
         HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_JNI_MONITOR, thread->threadId);
@@ -3403,11 +3817,10 @@
      * through the actual ThreadGroups, but it should be
      * equivalent.
      *
-     * This assumes that the ThreadGroup class object is in 
+     * This assumes that the ThreadGroup class object is in
      * the root set, which should always be true;  it's
      * loaded by the built-in class loader, which is part
      * of the root set.
      */
     gcScanAllThreads();
 }
-
diff --git a/vm/Thread.h b/vm/Thread.h
index 9c15f9e..1bb5314 100644
--- a/vm/Thread.h
+++ b/vm/Thread.h
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 /*
  * VM thread support.
  */
@@ -22,7 +23,7 @@
 #include "jni.h"
 
 #if defined(CHECK_MUTEX) && !defined(__USE_UNIX98)
-/* Linux lacks this unless you #define __USE_UNIX98 */
+/* glibc lacks this unless you #define __USE_UNIX98 */
 int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type);
 enum { PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP };
 #endif
@@ -67,6 +68,7 @@
 void dvmSlayDaemons(void);
 
 
+#define kJniLocalRefMin         32
 #define kJniLocalRefMax         512     /* arbitrary; should be plenty */
 #define kInternalRefDefault     32      /* equally arbitrary */
 #define kInternalRefMax         4096    /* mainly a sanity check */
@@ -76,6 +78,11 @@
 #define kMaxStackSize       (256*1024 + STACK_OVERFLOW_RESERVE)
 
 /*
+ * System thread state. See native/SystemThread.h.
+ */
+typedef struct SystemThread SystemThread;
+
+/*
  * Our per-thread data.
  *
  * These are allocated on the system heap.
@@ -88,7 +95,7 @@
      * Thread's current status.  Can only be changed by the thread itself
      * (i.e. don't mess with this from other threads).
      */
-    ThreadStatus status;
+    volatile ThreadStatus status;
 
     /*
      * This is the number of times the thread has been suspended.  When the
@@ -151,7 +158,11 @@
     ReferenceTable  internalLocalRefTable;
 
     /* JNI local reference tracking */
+#ifdef USE_INDIRECT_REF
+    IndirectRefTable jniLocalRefTable;
+#else
     ReferenceTable  jniLocalRefTable;
+#endif
 
     /* JNI native monitor reference tracking (initialized on first use) */
     ReferenceTable  jniMonitorRefTable;
@@ -203,6 +214,14 @@
 #ifdef WITH_JNI_STACK_CHECK
     u4          stackCrc;
 #endif
+
+#if WITH_EXTRA_GC_CHECKS > 1
+    /* PC, saved on every instruction; redundant with StackSaveArea */
+    const u2*   currentPc2;
+#endif
+
+    /* system thread state */
+    SystemThread* systemThread;
 } Thread;
 
 /* start point for an internal thread; mimics pthread args */
@@ -250,6 +269,9 @@
     SUSPEND_FOR_DEBUG_EVENT,
     SUSPEND_FOR_STACK_DUMP,
     SUSPEND_FOR_DEX_OPT,
+#if defined(WITH_JIT)
+    SUSPEND_FOR_JIT,
+#endif
 } SuspendCause;
 void dvmSuspendThread(Thread* thread);
 void dvmSuspendSelf(bool jdwpActivity);
@@ -277,12 +299,11 @@
 bool dvmCheckSuspendPending(Thread* self);
 
 /*
- * Fast test for use in the interpreter.  If our suspend count is nonzero,
- * do a more rigorous evaluation.
+ * Fast test for use in the interpreter.  Returns "true" if our suspend
+ * count is nonzero.
  */
-INLINE void dvmCheckSuspendQuick(Thread* self) {
-    if (self->suspendCount != 0)
-        dvmCheckSuspendPending(self);
+INLINE bool dvmCheckSuspendQuick(Thread* self) {
+    return (self->suspendCount != 0);
 }
 
 /*
@@ -390,7 +411,7 @@
  * thread is part of the GC's root set.
  */
 bool dvmIsOnThreadList(const Thread* thread);
- 
+
 /*
  * Get/set the JNIEnv field.
  */
@@ -398,16 +419,10 @@
 INLINE void dvmSetThreadJNIEnv(Thread* self, JNIEnv* env) { self->jniEnv = env;}
 
 /*
- * Change the scheduler group of the current process
- */
-int dvmChangeThreadSchedulerGroup(const char *group);
-
-/*
  * Update the priority value of the underlying pthread.
  */
 void dvmChangeThreadPriority(Thread* thread, int newPriority);
 
-
 /*
  * Debug: dump information about a single thread.
  */
@@ -421,7 +436,6 @@
 void dvmDumpAllThreads(bool grabLock);
 void dvmDumpAllThreadsEx(const DebugOutputTarget* target, bool grabLock);
 
-
 #ifdef WITH_MONITOR_TRACKING
 /*
  * Track locks held by the current thread, along with the stack trace at
diff --git a/vm/UtfString.c b/vm/UtfString.c
index a5e0b35..dfb76bc 100644
--- a/vm/UtfString.c
+++ b/vm/UtfString.c
@@ -435,6 +435,15 @@
 }
 
 /*
+ * Get the char[] object from the String.
+ */
+ArrayObject* dvmStringCharArray(StringObject* jstr)
+{
+    return (ArrayObject*) dvmGetFieldObject((Object*) jstr,
+                                gDvm.offJavaLangString_value);
+}
+
+/*
  * Get the string's data.
  */
 const u2* dvmStringChars(StringObject* jstr)
diff --git a/vm/UtfString.h b/vm/UtfString.h
index 5ca2ce6..ca500a7 100644
--- a/vm/UtfString.h
+++ b/vm/UtfString.h
@@ -100,6 +100,11 @@
 int dvmStringLen(StringObject* jstr);
 
 /*
+ * Get the char[] object from the String.
+ */
+ArrayObject* dvmStringCharArray(StringObject* jstr);
+
+/*
  * Get a pointer to the Unicode data.
  */
 const u2* dvmStringChars(StringObject* jstr);
diff --git a/vm/alloc/Alloc.c b/vm/alloc/Alloc.c
index e247413..0961520 100644
--- a/vm/alloc/Alloc.c
+++ b/vm/alloc/Alloc.c
@@ -68,25 +68,27 @@
 }
 
 /*
- * Create a "stock instance" of an exception class.  These won't have
- * useful stack traces in them, but they can be thrown when everything
- * else is not working in a container class.
+ * Create a "stock instance" of an exception class.
  */
-static Object* createStockException(const char* descriptor)
+static Object* createStockException(const char* descriptor, const char* msg)
 {
+    Thread* self = dvmThreadSelf();
+    StringObject* msgStr = NULL;
     ClassObject* clazz;
     Method* init;
     Object* obj;
 
+    /* find class, initialize if necessary */
     clazz = dvmFindSystemClass(descriptor);
     if (clazz == NULL) {
         LOGE("Unable to find %s\n", descriptor);
         return NULL;
     }
 
-    init = dvmFindDirectMethodByDescriptor(clazz, "<init>", "()V");
+    init = dvmFindDirectMethodByDescriptor(clazz, "<init>",
+            "(Ljava/lang/String;)V");
     if (init == NULL) {
-        LOGE("Unable to find nullary constructor for %s\n", descriptor);
+        LOGE("Unable to find String-arg constructor for %s\n", descriptor);
         return NULL;
     }
 
@@ -94,30 +96,56 @@
     if (obj == NULL)
         return NULL;
 
-    Thread* self = dvmThreadSelf();
-    JValue unused;
-    dvmCallMethod(self, init, obj, &unused);
-    if (dvmCheckException(self))
-        return NULL;
+    if (msg == NULL) {
+        msgStr = NULL;
+    } else {
+        msgStr = dvmCreateStringFromCstr(msg, ALLOC_DEFAULT);
+        if (msgStr == NULL) {
+            LOGW("Could not allocate message string \"%s\"\n", msg);
+            dvmReleaseTrackedAlloc(obj, self);
+            return NULL;
+        }
+    }
 
+    JValue unused;
+    dvmCallMethod(self, init, obj, &unused, msgStr);
+    if (dvmCheckException(self)) {
+        dvmReleaseTrackedAlloc((Object*) msgStr, self);
+        dvmReleaseTrackedAlloc(obj, self);
+        return NULL;
+    }
+
+    dvmReleaseTrackedAlloc((Object*) msgStr, self);     // okay if msgStr NULL
     return obj;
 }
 
 /*
- * "Late" initialization.  We had to defer this until we were able to
- * interpret code.
+ * Create some "stock" exceptions.  These can be thrown when the system is
+ * too screwed up to allocate and initialize anything, or when we don't
+ * need a meaningful stack trace.
+ *
+ * We can't do this during the initial startup because we need to execute
+ * the constructors.
  */
-bool dvmGcLateInit(void)
+bool dvmCreateStockExceptions(void)
 {
     /*
      * Pre-allocate some throwables.  These need to be explicitly added
-     * to the root set by the GC.
+     * to the GC's root set (see dvmHeapMarkRootSet()).
      */
-    gDvm.outOfMemoryObj = createStockException("Ljava/lang/OutOfMemoryError;");
+    gDvm.outOfMemoryObj = createStockException("Ljava/lang/OutOfMemoryError;",
+        "[memory exhausted]");
     dvmReleaseTrackedAlloc(gDvm.outOfMemoryObj, NULL);
-    gDvm.internalErrorObj = createStockException("Ljava/lang/InternalError;");
+    gDvm.internalErrorObj = createStockException("Ljava/lang/InternalError;",
+        "[pre-allocated]");
     dvmReleaseTrackedAlloc(gDvm.internalErrorObj, NULL);
-    if (gDvm.outOfMemoryObj == NULL || gDvm.internalErrorObj == NULL) {
+    gDvm.noClassDefFoundErrorObj =
+        createStockException("Ljava/lang/NoClassDefFoundError;", NULL);
+    dvmReleaseTrackedAlloc(gDvm.noClassDefFoundErrorObj, NULL);
+
+    if (gDvm.outOfMemoryObj == NULL || gDvm.internalErrorObj == NULL ||
+        gDvm.noClassDefFoundErrorObj == NULL)
+    {
         LOGW("Unable to create stock exceptions\n");
         return false;
     }
diff --git a/vm/alloc/Alloc.h b/vm/alloc/Alloc.h
index 0489db7..facc753 100644
--- a/vm/alloc/Alloc.h
+++ b/vm/alloc/Alloc.h
@@ -25,9 +25,9 @@
  * Initialization.
  */
 bool dvmGcStartup(void);
+bool dvmCreateStockExceptions(void);
 bool dvmGcStartupAfterZygote(void);
 void dvmGcShutdown(void);
-bool dvmGcLateInit(void);
 
 /*
  * Do any last-minute preparation before we call fork() for the first time.
@@ -133,7 +133,7 @@
     }
 #ifdef WITH_EXTRA_OBJECT_VALIDATION
     if (!dvmIsValidObject(obj)) {
-        //abort();
+        dvmAbort();
         dvmThrowException("Ljava/lang/InternalError;",
             "VM detected invalid object ptr");
         return false;
@@ -142,7 +142,7 @@
 #ifndef NDEBUG
     /* check for heap corruption */
     if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) {
-        abort();
+        dvmAbort();
         dvmThrowException("Ljava/lang/InternalError;",
             "VM detected invalid object class ptr");
         return false;
diff --git a/vm/alloc/DdmHeap.c b/vm/alloc/DdmHeap.c
index 78da6cd..f21a875 100644
--- a/vm/alloc/DdmHeap.c
+++ b/vm/alloc/DdmHeap.c
@@ -224,10 +224,18 @@
      * allocation units used by the chunk.
      */
     {
+        size_t needed = (((chunklen/ALLOCATION_UNIT_SIZE + 255) / 256) * 2);
         size_t bytesLeft = ctx->bufLen - (size_t)(ctx->p - ctx->buf);
-        if (bytesLeft < (((chunklen/ALLOCATION_UNIT_SIZE + 255) / 256) * 2)) {
+        if (bytesLeft < needed) {
             flush_hpsg_chunk(ctx);
         }
+
+        bytesLeft = ctx->bufLen - (size_t)(ctx->p - ctx->buf);
+        if (bytesLeft < needed) {
+            LOGW("chunk is too big to transmit (chunklen=%zd, %zd bytes)\n",
+                chunklen, needed);
+            return;
+        }
     }
 
 //TODO: notice when there's a gap and start a new heap, or at least a new range.
@@ -345,7 +353,12 @@
     HPSG_WHAT_DISTINCT_OBJECTS = 1,
 };
 
-#define HPSx_CHUNK_SIZE (4096 - 16)
+/*
+ * Maximum chunk size.  Obtain this from the formula:
+ *
+ * (((maximum_heap_size / ALLOCATION_UNIT_SIZE) + 255) / 256) * 2
+ */
+#define HPSx_CHUNK_SIZE (16384 - 16)
 
 void dlmalloc_walk_heap(void(*)(const void*, size_t, const void*, size_t, void*),void*);
 
diff --git a/vm/alloc/Heap.c b/vm/alloc/Heap.c
index e58a8a8..17d6a5c 100644
--- a/vm/alloc/Heap.c
+++ b/vm/alloc/Heap.c
@@ -27,6 +27,8 @@
 #include "utils/threads.h"      // need Android thread priorities
 #define kInvalidPriority        10000
 
+#include <cutils/sched_policy.h>
+
 #include <sys/time.h>
 #include <sys/resource.h>
 #include <limits.h>
@@ -148,15 +150,21 @@
 
 /*
  * We've been asked to allocate something we can't, e.g. an array so
- * large that (length * elementWidth) is larger than 2^31.  We want to
- * throw an OutOfMemoryError, but doing so implies that certain other
- * actions have taken place (like clearing soft references).
+ * large that (length * elementWidth) is larger than 2^31.
  *
- * TODO: for now we just throw an InternalError.
+ * _The Java Programming Language_, 4th edition, says, "you can be sure
+ * that all SoftReferences to softly reachable objects will be cleared
+ * before an OutOfMemoryError is thrown."
+ *
+ * It's unclear whether that holds for all situations where an OOM can
+ * be thrown, or just in the context of an allocation that fails due
+ * to lack of heap space.  For simplicity we just throw the exception.
+ *
+ * (OOM due to actually running out of space is handled elsewhere.)
  */
 void dvmThrowBadAllocException(const char* msg)
 {
-    dvmThrowException("Ljava/lang/InternalError;", msg);
+    dvmThrowException("Ljava/lang/OutOfMemoryError;", msg);
 }
 
 /*
@@ -174,6 +182,7 @@
         if (self != NULL) {
             oldStatus = dvmChangeStatus(self, THREAD_VMWAIT);
         } else {
+            LOGI("ODD: waiting on heap lock, no self\n");
             oldStatus = -1; // shut up gcc
         }
 
@@ -776,7 +785,7 @@
          */
 
         if (priorityResult >= ANDROID_PRIORITY_BACKGROUND) {
-            dvmChangeThreadSchedulerGroup(NULL);
+            set_sched_policy(dvmGetSysThreadId(), SP_FOREGROUND);
         }
 
         if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL) != 0) {
@@ -867,7 +876,10 @@
 
     /* Set up the marking context.
      */
-    dvmHeapBeginMarkStep();
+    if (!dvmHeapBeginMarkStep()) {
+        LOGE_HEAP("dvmHeapBeginMarkStep failed; aborting\n");
+        dvmAbort();
+    }
 
     /* Mark the set of objects that are strongly reachable from the roots.
      */
@@ -1026,7 +1038,7 @@
         }
 
         if (oldThreadPriority >= ANDROID_PRIORITY_BACKGROUND) {
-            dvmChangeThreadSchedulerGroup("bg_non_interactive");
+            set_sched_policy(dvmGetSysThreadId(), SP_BACKGROUND);
         }
     }
     gcElapsedTime = (dvmGetRelativeTimeUsec() - gcHeap->gcStartTime) / 1000;
diff --git a/vm/alloc/HeapDebug.c b/vm/alloc/HeapDebug.c
index fc3655f..54b5cb6 100644
--- a/vm/alloc/HeapDebug.c
+++ b/vm/alloc/HeapDebug.c
@@ -15,7 +15,7 @@
  */
 
 #include <fcntl.h>
-#include <malloc.h>
+#include <stdlib.h>
 
 #include "Dalvik.h"
 #include "HeapInternal.h"
diff --git a/vm/alloc/HeapSource.c b/vm/alloc/HeapSource.c
index d97290f..830e5d7 100644
--- a/vm/alloc/HeapSource.c
+++ b/vm/alloc/HeapSource.c
@@ -787,6 +787,82 @@
 }
 
 /*
+ * Frees the first numPtrs objects in the ptrs list. The list must
+ * contain addresses all in the same mspace, and must be in increasing
+ * order. This implies that there are no duplicates, and no entries
+ * are NULL.
+ */
+void
+dvmHeapSourceFreeList(size_t numPtrs, void **ptrs)
+{
+    Heap *heap;
+
+    HS_BOILERPLATE();
+
+    if (numPtrs == 0) {
+        return;
+    }
+
+    assert(ptrs != NULL);
+    assert(*ptrs != NULL);
+    heap = ptr2heap(gHs, *ptrs);
+    if (heap != NULL) {
+        mspace *msp = heap->msp;
+        // Calling mspace_free on shared heaps disrupts sharing too
+        // much. For heap[0] -- the 'active heap' -- we call
+        // mspace_free, but on the other heaps we only do some
+        // accounting.
+        if (heap == gHs->heaps) {
+            // mspace_merge_objects takes two allocated objects, and
+            // if the second immediately follows the first, will merge
+            // them, returning a larger object occupying the same
+            // memory. This is a local operation, and doesn't require
+            // dlmalloc to manipulate any freelists. It's pretty
+            // inexpensive compared to free().
+
+            // ptrs is an array of objects all in memory order, and if
+            // client code has been allocating lots of short-lived
+            // objects, this is likely to contain runs of objects all
+            // now garbage, and thus highly amenable to this optimization.
+
+            // Unroll the 0th iteration around the loop below,
+            // countFree ptrs[0] and initializing merged.
+            assert(ptrs[0] != NULL);
+            assert(ptr2heap(gHs, ptrs[0]) == heap);
+            countFree(heap, ptrs[0], true);
+            void *merged = ptrs[0];
+
+            size_t i;
+            for (i = 1; i < numPtrs; i++) {
+                assert(merged != NULL);
+                assert(ptrs[i] != NULL);
+                assert((intptr_t)merged < (intptr_t)ptrs[i]);
+                assert(ptr2heap(gHs, ptrs[i]) == heap);
+                countFree(heap, ptrs[i], true);
+                // Try to merge. If it works, merged now includes the
+                // memory of ptrs[i]. If it doesn't, free merged, and
+                // see if ptrs[i] starts a new run of adjacent
+                // objects to merge.
+                if (mspace_merge_objects(msp, merged, ptrs[i]) == NULL) {
+                    mspace_free(msp, merged);
+                    merged = ptrs[i];
+                }
+            }
+            assert(merged != NULL);
+            mspace_free(msp, merged);
+        } else {
+            // This is not an 'active heap'. Only do the accounting.
+            size_t i;
+            for (i = 0; i < numPtrs; i++) {
+                assert(ptrs[i] != NULL);
+                assert(ptr2heap(gHs, ptrs[i]) == heap);
+                countFree(heap, ptrs[i], true);
+            }
+        }
+    }
+}
+
+/*
  * Returns true iff <ptr> was allocated from the heap source.
  */
 bool
diff --git a/vm/alloc/HeapSource.h b/vm/alloc/HeapSource.h
index 3007d4f..fdaf119 100644
--- a/vm/alloc/HeapSource.h
+++ b/vm/alloc/HeapSource.h
@@ -105,6 +105,14 @@
 void dvmHeapSourceFree(void *ptr);
 
 /*
+ * Frees the first numPtrs objects in the ptrs list. The list must
+ * contain addresses all in the same mspace, and must be in increasing
+ * order. This implies that there are no duplicates, and no entries
+ * are NULL.
+ */
+void dvmHeapSourceFreeList(size_t numPtrs, void **ptrs);
+
+/*
  * Returns true iff <ptr> was allocated from the heap source.
  */
 bool dvmHeapSourceContains(const void *ptr);
diff --git a/vm/alloc/HeapWorker.c b/vm/alloc/HeapWorker.c
index b4a2d0e..e7a4d03 100644
--- a/vm/alloc/HeapWorker.c
+++ b/vm/alloc/HeapWorker.c
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 /*
  * An async worker thread to handle certain heap operations that
  * need to be done in a separate thread to avoid synchronization
@@ -342,12 +343,20 @@
         /* Trim the heap if we were asked to. */
         trimtime = gDvm.gcHeap->heapWorkerNextTrim;
         if (trimtime.tv_sec != 0 && trimtime.tv_nsec != 0) {
-            struct timeval now;
+            struct timespec now;
 
-            gettimeofday(&now, NULL);
+#ifdef HAVE_TIMEDWAIT_MONOTONIC
+            clock_gettime(CLOCK_MONOTONIC, &now);       // relative time
+#else
+            struct timeval tvnow;
+            gettimeofday(&tvnow, NULL);                 // absolute time
+            now.tv_sec = tvnow.tv_sec;
+            now.tv_nsec = tvnow.tv_usec * 1000;
+#endif
+
             if (trimtime.tv_sec < now.tv_sec ||
                 (trimtime.tv_sec == now.tv_sec && 
-                 trimtime.tv_nsec <= now.tv_usec * 1000))
+                 trimtime.tv_nsec <= now.tv_nsec))
             {
                 size_t madvisedSizes[HEAP_SOURCE_MAX_HEAP_COUNT];
 
@@ -377,8 +386,13 @@
 
         /* sleep until signaled */
         if (timedwait) {
+#ifdef HAVE_TIMEDWAIT_MONOTONIC
+            cc = pthread_cond_timedwait_monotonic(&gDvm.heapWorkerCond,
+                    &gDvm.heapWorkerLock, &trimtime);
+#else
             cc = pthread_cond_timedwait(&gDvm.heapWorkerCond,
                     &gDvm.heapWorkerLock, &trimtime);
+#endif
             assert(cc == 0 || cc == ETIMEDOUT || cc == EINTR);
         } else {
             cc = pthread_cond_wait(&gDvm.heapWorkerCond, &gDvm.heapWorkerLock);
@@ -494,9 +508,14 @@
     } else {
         struct timeval now;
 
+#ifdef HAVE_TIMEDWAIT_MONOTONIC
+        clock_gettime(CLOCK_MONOTONIC, &timeout);
+        timeout.tv_sec += timeoutSec;
+#else
         gettimeofday(&now, NULL);
         timeout.tv_sec = now.tv_sec + timeoutSec;
         timeout.tv_nsec = now.tv_usec * 1000;
+#endif
         dvmSignalHeapWorker(false);
     }
     gcHeap->heapWorkerNextTrim = timeout;
diff --git a/vm/alloc/MarkSweep.c b/vm/alloc/MarkSweep.c
index a0601d7..09cc25f 100644
--- a/vm/alloc/MarkSweep.c
+++ b/vm/alloc/MarkSweep.c
@@ -15,6 +15,7 @@
  */
 
 #include "Dalvik.h"
+#include "alloc/clz.h"
 #include "alloc/HeapBitmap.h"
 #include "alloc/HeapInternal.h"
 #include "alloc/HeapSource.h"
@@ -22,6 +23,7 @@
 #include <limits.h>     // for ULONG_MAX
 #include <sys/mman.h>   // for madvise(), mmap()
 #include <cutils/ashmem.h>
+#include <errno.h>
 
 #define GC_DEBUG_PARANOID   2
 #define GC_DEBUG_BASIC      1
@@ -92,7 +94,7 @@
 {
     const Object **limit;
     size_t size;
-    int fd;
+    int fd, err;
 
     /* Create a stack big enough for the worst possible case,
      * where the heap is perfectly full of the smallest object.
@@ -104,14 +106,17 @@
     size = ALIGN_UP_TO_PAGE_SIZE(size);
     fd = ashmem_create_region("dalvik-heap-markstack", size);
     if (fd < 0) {
-        LOGE_GC("Could not create %d-byte ashmem mark stack\n", size);
+        LOGE_GC("Could not create %d-byte ashmem mark stack: %s\n",
+            size, strerror(errno));
         return false;
     }
     limit = (const Object **)mmap(NULL, size, PROT_READ | PROT_WRITE,
             MAP_PRIVATE, fd, 0);
+    err = errno;
     close(fd);
     if (limit == MAP_FAILED) {
-        LOGE_GC("Could not mmap %d-byte ashmem mark stack\n", size);
+        LOGE_GC("Could not mmap %d-byte ashmem mark stack: %s\n",
+            size, strerror(err));
         return false;
     }
 
@@ -374,6 +379,7 @@
     LOG_SCAN("special objects\n");
     dvmMarkObjectNonNull(gDvm.outOfMemoryObj);
     dvmMarkObjectNonNull(gDvm.internalErrorObj);
+    dvmMarkObjectNonNull(gDvm.noClassDefFoundErrorObj);
 //TODO: scan object references sitting in gDvm;  use pointer begin & end
 
     HPROF_CLEAR_GC_SCAN_STATE();
@@ -430,30 +436,39 @@
 static void scanInstanceFields(const DataObject *obj, ClassObject *clazz,
         GcMarkContext *ctx)
 {
-//TODO: Optimize this by avoiding walking the superclass chain
-    while (clazz != NULL) {
-        InstField *f;
-        int i;
-
-        /* All of the fields that contain object references
-         * are guaranteed to be at the beginning of the ifields list.
-         */
-        f = clazz->ifields;
-        for (i = 0; i < clazz->ifieldRefCount; i++) {
-            /* Mark the array or object reference.
-             * May be NULL.
-             *
-             * Note that, per the comment on struct InstField,
-             * f->byteOffset is the offset from the beginning of
-             * obj, not the offset into obj->instanceData.
-             */
-            markObject(dvmGetFieldObject((Object*)obj, f->byteOffset), ctx);
-            f++;
+    if (false && clazz->refOffsets != CLASS_WALK_SUPER) {
+        unsigned int refOffsets = clazz->refOffsets;
+        while (refOffsets != 0) {
+            const int rshift = CLZ(refOffsets);
+            refOffsets &= ~(CLASS_HIGH_BIT >> rshift);
+            markObject(dvmGetFieldObject((Object*)obj,
+                                         CLASS_OFFSET_FROM_CLZ(rshift)), ctx);
         }
+    } else {
+        while (clazz != NULL) {
+            InstField *f;
+            int i;
 
-        /* This will be NULL when we hit java.lang.Object
-         */
-        clazz = clazz->super;
+            /* All of the fields that contain object references
+             * are guaranteed to be at the beginning of the ifields list.
+             */
+            f = clazz->ifields;
+            for (i = 0; i < clazz->ifieldRefCount; i++) {
+                /* Mark the array or object reference.
+                 * May be NULL.
+                 *
+                 * Note that, per the comment on struct InstField,
+                 * f->byteOffset is the offset from the beginning of
+                 * obj, not the offset into obj->instanceData.
+                 */
+                markObject(dvmGetFieldObject((Object*)obj, f->byteOffset), ctx);
+                f++;
+            }
+
+            /* This will be NULL when we hit java.lang.Object
+             */
+            clazz = clazz->super;
+        }
     }
 }
 
@@ -520,6 +535,17 @@
     }
 #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;
@@ -540,16 +566,9 @@
          */
         return;
     }
+
 #if WITH_OBJECT_HEADERS
     gMarkParent = obj;
-    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
 
     assert(dvmIsValidObject((Object *)clazz));
@@ -1194,6 +1213,7 @@
 {
     const ClassObject *const classJavaLangClass = gDvm.classJavaLangClass;
     size_t i;
+    void **origPtrs = ptrs;
 
     for (i = 0; i < numPtrs; i++) {
         DvmHeapChunk *hc;
@@ -1256,11 +1276,10 @@
 #endif
         }
 #endif
-
-//TODO: provide a heapsource function that takes a list of pointers to free
-//      and call it outside of this loop.
-        dvmHeapSourceFree(hc);
     }
+    // TODO: dvmHeapSourceFreeList has a loop, just like the above
+    // does. Consider collapsing the two loops to save overhead.
+    dvmHeapSourceFreeList(numPtrs, origPtrs);
 
     return true;
 }
diff --git a/vm/analysis/CodeVerify.c b/vm/analysis/CodeVerify.c
index 8c5e8d2..f945f23 100644
--- a/vm/analysis/CodeVerify.c
+++ b/vm/analysis/CodeVerify.c
@@ -72,9 +72,9 @@
 static inline bool doVerboseLogging(const Method* meth) {
     return false;       /* COMMENT OUT to enable verbose debugging */
 
-    const char* cd = "Lop_lshr;";
-    const char* mn = "test";
-    const char* sg = "(II)J";
+    const char* cd = "Landroid/net/http/Request;";
+    const char* mn = "readResponse";
+    const char* sg = "(Landroid/net/http/AndroidHttpClientConnection;)V";
     return (strcmp(meth->clazz->descriptor, cd) == 0 &&
             dvmCompareNameDescriptorAndMethod(mn, sg, meth) == 0);
 }
@@ -116,12 +116,13 @@
 static void checkMergeTab(void);
 static bool isInitMethod(const Method* meth);
 static RegType getInvocationThis(const RegType* insnRegs,\
-    const int insnRegCount, const DecodedInstruction* pDecInsn, bool* pOkay);
+    const int insnRegCount, const DecodedInstruction* pDecInsn,
+    VerifyError* pFailure);
 static void verifyRegisterType(const RegType* insnRegs, const int insnRegCount,\
-    u4 vsrc, RegType checkType, bool* pOkay);
-static bool doCodeVerification(const Method* meth, InsnFlags* insnFlags,\
+    u4 vsrc, RegType checkType, VerifyError* pFailure);
+static bool doCodeVerification(Method* meth, InsnFlags* insnFlags,\
     RegisterTable* regTable, UninitInstanceMap* uninitMap);
-static bool verifyInstruction(const Method* meth, InsnFlags* insnFlags,\
+static bool verifyInstruction(Method* meth, InsnFlags* insnFlags,\
     RegisterTable* regTable, RegType* workRegs, int insnIdx,
     UninitInstanceMap* uninitMap, int* pStartGuess);
 static ClassObject* findCommonSuperclass(ClassObject* c1, ClassObject* c2);
@@ -327,7 +328,7 @@
  */
 static RegType primitiveTypeToRegType(PrimitiveType primType)
 {
-    struct {
+    static const struct {
         RegType         regType;        /* type equivalent */
         PrimitiveType   primType;       /* verification */
     } convTab[] = {
@@ -545,9 +546,11 @@
 
 /*
  * Look up a class reference given as a simple string descriptor.
+ *
+ * If we can't find it, return a generic substitute when possible.
  */
 static ClassObject* lookupClassByDescriptor(const Method* meth,
-    const char* pDescriptor, bool* pOkay)
+    const char* pDescriptor, VerifyError* pFailure)
 {
     /*
      * The javac compiler occasionally puts references to nonexistent
@@ -585,7 +588,7 @@
             if (pDescriptor[1] != 'L' && pDescriptor[1] != '[') {
                 LOG_VFY("VFY: invalid char in signature in '%s'\n",
                     pDescriptor);
-                *pOkay = false;
+                *pFailure = VERIFY_ERROR_GENERIC;
             }
 
             /*
@@ -607,17 +610,17 @@
         } else {
             /* We are looking at a primitive type. */
             LOG_VFY("VFY: invalid char in signature in '%s'\n", pDescriptor);
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
         }
 
         if (clazz == NULL) {
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
         }
     }
 
     if (dvmIsPrimitiveClass(clazz)) {
         LOG_VFY("VFY: invalid use of primitive type '%s'\n", pDescriptor);
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         clazz = NULL;
     }
 
@@ -634,7 +637,7 @@
  * NOTE: this is also expected to verify the signature.
  */
 static ClassObject* lookupSignatureClass(const Method* meth, const char** pSig,
-    bool* pOkay)
+    VerifyError* pFailure)
 {
     const char* sig = *pSig;
     const char* endp = sig;
@@ -645,7 +648,7 @@
         ;
     if (*endp != ';') {
         LOG_VFY("VFY: bad signature component '%s' (missing ';')\n", sig);
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         return NULL;
     }
 
@@ -657,7 +660,7 @@
 
     *pSig = endp - 1; /* - 1 so that *pSig points at, not past, the ';' */
 
-    return lookupClassByDescriptor(meth, typeStr, pOkay);
+    return lookupClassByDescriptor(meth, typeStr, pFailure);
 }
 
 /*
@@ -669,7 +672,7 @@
  * NOTE: this is also expected to verify the signature.
  */
 static ClassObject* lookupSignatureArrayClass(const Method* meth,
-    const char** pSig, bool* pOkay)
+    const char** pSig, VerifyError* pFailure)
 {
     const char* sig = *pSig;
     const char* endp = sig;
@@ -685,7 +688,7 @@
             ;
         if (*endp != ';') {
             LOG_VFY("VFY: bad signature component '%s' (missing ';')\n", sig);
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
             return NULL;
         }
     }
@@ -697,7 +700,7 @@
 
     *pSig = endp;
 
-    return lookupClassByDescriptor(meth, typeStr, pOkay);
+    return lookupClassByDescriptor(meth, typeStr, pFailure);
 }
 
 /*
@@ -713,7 +716,7 @@
 {
     DexParameterIterator iterator;
     int actualArgs, expectedArgs, argStart;
-    bool okay = true;
+    VerifyError failure = VERIFY_ERROR_NONE;
 
     dexParameterIteratorInit(&iterator, &meth->prototype);
     argStart = meth->registersSize - meth->insSize;
@@ -768,8 +771,8 @@
              */
             {
                 ClassObject* clazz =
-                    lookupClassByDescriptor(meth, descriptor, &okay);
-                if (!okay)
+                    lookupClassByDescriptor(meth, descriptor, &failure);
+                if (!VERIFY_OK(failure))
                     goto bad_sig;
                 regTypes[argStart + actualArgs] = regTypeFromClass(clazz);
             }
@@ -926,10 +929,10 @@
     case 'L':
     case '[':
         {
-            bool okay = true;
+            VerifyError failure = VERIFY_ERROR_NONE;
             ClassObject* clazz =
-                lookupClassByDescriptor(meth, descriptor, &okay);
-            assert(okay);
+                lookupClassByDescriptor(meth, descriptor, &failure);
+            assert(VERIFY_OK(failure));
             type = regTypeFromClass(clazz);
         }
         break;
@@ -1012,13 +1015,13 @@
  * Widening conversions on integers and references are allowed, but
  * narrowing conversions are not.
  *
- * Returns the resolved method on success, NULL (and sets "*pOkay" to "false")
- * on failure.
+ * Returns the resolved method on success, NULL on failure (with *pFailure
+ * set appropriately).
  */
 static Method* verifyInvocationArgs(const Method* meth, const RegType* insnRegs,
     const int insnRegCount, const DecodedInstruction* pDecInsn,
     UninitInstanceMap* uninitMap, MethodType methodType, bool isRange,
-    bool isSuper, bool* pOkay)
+    bool isSuper, VerifyError* pFailure)
 {
     Method* resMethod;
     char* sigOriginal = NULL;
@@ -1030,7 +1033,8 @@
     if (methodType == METHOD_INTERFACE) {
         resMethod = dvmOptResolveInterfaceMethod(meth->clazz, pDecInsn->vB);
     } else {
-        resMethod = dvmOptResolveMethod(meth->clazz, pDecInsn->vB, methodType);
+        resMethod = dvmOptResolveMethod(meth->clazz, pDecInsn->vB, methodType,
+            pFailure);
     }
     if (resMethod == NULL) {
         /* failed; print a meaningful failure message */
@@ -1051,7 +1055,7 @@
             //char* curMethodDesc =
             //    dexProtoCopyMethodDescriptor(&meth->prototype);
 
-            LOGE("Could not find method %s.%s, referenced from "
+            LOGI("Could not find method %s.%s, referenced from "
                  "method %s.%s\n",
                  dotMissingClass, methodName/*, methodDesc*/,
                  dotMethClass, meth->name/*, curMethodDesc*/);
@@ -1065,6 +1069,8 @@
             dvmMethodTypeStr(methodType), pDecInsn->vB,
             classDescriptor, methodName, methodDesc);
         free(methodDesc);
+        if (VERIFY_OK(*pFailure))       /* not set for interface resolve */
+            *pFailure = VERIFY_ERROR_NO_METHOD;
         goto fail;
     }
 
@@ -1095,6 +1101,7 @@
                     (super == NULL) ? "-" : super->descriptor,
                     resMethod->name, desc);
             free(desc);
+            *pFailure = VERIFY_ERROR_NO_METHOD;
             goto fail;
         }
     }
@@ -1135,8 +1142,8 @@
         RegType actualArgType;
 
         actualArgType = getInvocationThis(insnRegs, insnRegCount, pDecInsn,
-                            pOkay);
-        if (!*pOkay)
+                            pFailure);
+        if (!VERIFY_OK(*pFailure))
             goto fail;
 
         if (regTypeIsUninitReference(actualArgType) && resMethod->name[0] != '<')
@@ -1176,12 +1183,12 @@
         switch (*sig) {
         case 'L':
             {
-                ClassObject* clazz = lookupSignatureClass(meth, &sig, pOkay);
-                if (!*pOkay)
+                ClassObject* clazz = lookupSignatureClass(meth, &sig, pFailure);
+                if (!VERIFY_OK(*pFailure))
                     goto bad_sig;
                 verifyRegisterType(insnRegs, insnRegCount, getReg,
-                    regTypeFromClass(clazz), pOkay);
-                if (!*pOkay) {
+                    regTypeFromClass(clazz), pFailure);
+                if (!VERIFY_OK(*pFailure)) {
                     LOG_VFY("VFY: bad arg %d (into %s)\n",
                             actualArgs, clazz->descriptor);
                     goto bad_sig;
@@ -1192,12 +1199,12 @@
         case '[':
             {
                 ClassObject* clazz =
-                    lookupSignatureArrayClass(meth, &sig, pOkay);
-                if (!*pOkay)
+                    lookupSignatureArrayClass(meth, &sig, pFailure);
+                if (!VERIFY_OK(*pFailure))
                     goto bad_sig;
                 verifyRegisterType(insnRegs, insnRegCount, getReg,
-                    regTypeFromClass(clazz), pOkay);
-                if (!*pOkay) {
+                    regTypeFromClass(clazz), pFailure);
+                if (!VERIFY_OK(*pFailure)) {
                     LOG_VFY("VFY: bad arg %d (into %s)\n",
                             actualArgs, clazz->descriptor);
                     goto bad_sig;
@@ -1207,42 +1214,42 @@
             break;
         case 'Z':
             verifyRegisterType(insnRegs, insnRegCount, getReg,
-                kRegTypeBoolean, pOkay);
+                kRegTypeBoolean, pFailure);
             actualArgs++;
             break;
         case 'C':
             verifyRegisterType(insnRegs, insnRegCount, getReg,
-                kRegTypeChar, pOkay);
+                kRegTypeChar, pFailure);
             actualArgs++;
             break;
         case 'B':
             verifyRegisterType(insnRegs, insnRegCount, getReg,
-                kRegTypeByte, pOkay);
+                kRegTypeByte, pFailure);
             actualArgs++;
             break;
         case 'I':
             verifyRegisterType(insnRegs, insnRegCount, getReg,
-                kRegTypeInteger, pOkay);
+                kRegTypeInteger, pFailure);
             actualArgs++;
             break;
         case 'S':
             verifyRegisterType(insnRegs, insnRegCount, getReg,
-                kRegTypeShort, pOkay);
+                kRegTypeShort, pFailure);
             actualArgs++;
             break;
         case 'F':
             verifyRegisterType(insnRegs, insnRegCount, getReg,
-                kRegTypeFloat, pOkay);
+                kRegTypeFloat, pFailure);
             actualArgs++;
             break;
         case 'D':
             verifyRegisterType(insnRegs, insnRegCount, getReg,
-                kRegTypeDoubleLo, pOkay);
+                kRegTypeDoubleLo, pFailure);
             actualArgs += 2;
             break;
         case 'J':
             verifyRegisterType(insnRegs, insnRegCount, getReg,
-                kRegTypeLongLo, pOkay);
+                kRegTypeLongLo, pFailure);
             actualArgs += 2;
             break;
         default:
@@ -1272,13 +1279,14 @@
     if (resMethod != NULL) {
         char* desc = dexProtoCopyMethodDescriptor(&resMethod->prototype);
         LOG_VFY("VFY:  rejecting call to %s.%s %s\n",
-                resMethod->clazz->descriptor, resMethod->name, desc);
+            resMethod->clazz->descriptor, resMethod->name, desc);
         free(desc);
     }
 
 fail:
     free(sigOriginal);
-    *pOkay = false;
+    if (*pFailure == VERIFY_ERROR_NONE)
+        *pFailure = VERIFY_ERROR_GENERIC;
     return NULL;
 }
 
@@ -1324,15 +1332,15 @@
 /*
  * Get the type of register N, verifying that the register is valid.
  *
- * Sets "*pOkay" to false if the register number is out of range.
+ * Sets "*pFailure" appropriately if the register number is out of range.
  */
 static inline RegType getRegisterType(const RegType* insnRegs,
-    const int insnRegCount, u4 vsrc, bool* pOkay)
+    const int insnRegCount, u4 vsrc, VerifyError* pFailure)
 {
     RegType type;
 
     if (vsrc >= (u4) insnRegCount) {
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         return kRegTypeUnknown;
     } else {
         return insnRegs[vsrc];
@@ -1341,21 +1349,21 @@
 
 /*
  * Get the value from a register, and cast it to a ClassObject.  Sets
- * "pOkay" to false if something fails.
+ * "*pFailure" if something fails.
  *
  * This fails if the register holds an uninitialized class.
  *
  * If the register holds kRegTypeZero, this returns a NULL pointer.
  */
 static ClassObject* getClassFromRegister(const RegType* insnRegs,
-    const int insnRegCount, u4 vsrc, bool* pOkay)
+    const int insnRegCount, u4 vsrc, VerifyError* pFailure)
 {
     ClassObject* clazz = NULL;
     RegType type;
 
     /* get the element type of the array held in vsrc */
-    type = getRegisterType(insnRegs, insnRegCount, vsrc, pOkay);
-    if (!*pOkay)
+    type = getRegisterType(insnRegs, insnRegCount, vsrc, pFailure);
+    if (!VERIFY_OK(*pFailure))
         goto bail;
 
     /* if "always zero", we allow it to fail at runtime */
@@ -1365,12 +1373,12 @@
     if (!regTypeIsReference(type)) {
         LOG_VFY("VFY: tried to get class from non-ref register v%d (type=%d)\n",
             vsrc, type);
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         goto bail;
     }
     if (regTypeIsUninitReference(type)) {
         LOG_VFY("VFY: register %u holds uninitialized reference\n", vsrc);
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         goto bail;
     }
 
@@ -1391,27 +1399,28 @@
  * and then return vC.
  */
 static RegType getInvocationThis(const RegType* insnRegs,
-    const int insnRegCount, const DecodedInstruction* pDecInsn, bool* pOkay)
+    const int insnRegCount, const DecodedInstruction* pDecInsn,
+    VerifyError* pFailure)
 {
     RegType thisType = kRegTypeUnknown;
 
     if (pDecInsn->vA < 1) {
         LOG_VFY("VFY: invoke lacks 'this'\n");
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         goto bail;
     }
 
     /* get the element type of the array held in vsrc */
-    thisType = getRegisterType(insnRegs, insnRegCount, pDecInsn->vC, pOkay);
-    if (!*pOkay) {
-        LOG_VFY("VFY: failed to get this from register %u\n", pDecInsn->vC);
+    thisType = getRegisterType(insnRegs, insnRegCount, pDecInsn->vC, pFailure);
+    if (!VERIFY_OK(*pFailure)) {
+        LOG_VFY("VFY: failed to get 'this' from register %u\n", pDecInsn->vC);
         goto bail;
     }
 
     if (!regTypeIsReference(thisType)) {
         LOG_VFY("VFY: tried to get class from non-ref register v%d (type=%d)\n",
             pDecInsn->vC, thisType);
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         goto bail;
     }
 
@@ -1424,10 +1433,10 @@
  * "newType" is the "Lo" part of a 64-bit value, register N+1 will be
  * set to "newType+1".
  *
- * Sets "*pOkay" to false if the register number is out of range.
+ * Sets "*pFailure" if the register number is out of range.
  */
 static void setRegisterType(RegType* insnRegs, const int insnRegCount,
-    u4 vdst, RegType newType, bool* pOkay)
+    u4 vdst, RegType newType, VerifyError* pFailure)
 {
     //LOGD("set-reg v%u = %d\n", vdst, newType);
     switch (newType) {
@@ -1443,7 +1452,7 @@
     case kRegTypeFloat:
     case kRegTypeZero:
         if (vdst >= (u4) insnRegCount) {
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
         } else {
             insnRegs[vdst] = newType;
         }
@@ -1451,7 +1460,7 @@
     case kRegTypeLongLo:
     case kRegTypeDoubleLo:
         if (vdst+1 >= (u4) insnRegCount) {
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
         } else {
             insnRegs[vdst] = newType;
             insnRegs[vdst+1] = newType+1;
@@ -1460,14 +1469,14 @@
     case kRegTypeLongHi:
     case kRegTypeDoubleHi:
         /* should never set these explicitly */
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         break;
 
     case kRegTypeUninit:
     default:
         if (regTypeIsReference(newType)) {
             if (vdst >= (u4) insnRegCount) {
-                *pOkay = false;
+                *pFailure = VERIFY_ERROR_GENERIC;
                 break;
             }
             insnRegs[vdst] = newType;
@@ -1490,7 +1499,7 @@
     case kRegTypeConflict:      // should only be set during a merge
         LOG_VFY("Unexpected set type %d\n", newType);
         assert(false);
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         break;
     }
 }
@@ -1509,10 +1518,10 @@
  * interface, verify that the register implements checkType.
  */
 static void verifyRegisterType(const RegType* insnRegs, const int insnRegCount,
-    u4 vsrc, RegType checkType, bool* pOkay)
+    u4 vsrc, RegType checkType, VerifyError* pFailure)
 {
     if (vsrc >= (u4) insnRegCount) {
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         return;
     }
 
@@ -1531,7 +1540,7 @@
         if (!canConvertTo1nr(srcType, checkType)) {
             LOG_VFY("VFY: register1 v%u type %d, wanted %d\n",
                 vsrc, srcType, checkType);
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
         }
         break;
     case kRegTypeLongLo:
@@ -1539,15 +1548,15 @@
         if (vsrc+1 >= (u4) insnRegCount) {
             LOG_VFY("VFY: register2 v%u out of range (%d)\n",
                 vsrc, insnRegCount);
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
         } else if (insnRegs[vsrc+1] != srcType+1) {
             LOG_VFY("VFY: register2 v%u-%u values %d,%d\n",
                 vsrc, vsrc+1, insnRegs[vsrc], insnRegs[vsrc+1]);
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
         } else if (!canConvertTo2(srcType, checkType)) {
             LOG_VFY("VFY: register2 v%u type %d, wanted %d\n",
                 vsrc, srcType, checkType);
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
         }
         break;
 
@@ -1559,7 +1568,7 @@
     case kRegTypeConflict:
         /* should never be checking for these explicitly */
         assert(false);
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         return;
     case kRegTypeUninit:
     default:
@@ -1567,23 +1576,23 @@
         if (!regTypeIsReference(checkType)) {
             LOG_VFY("VFY: unexpected check type %d\n", checkType);
             assert(false);
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
             break;
         }
         if (regTypeIsUninitReference(checkType)) {
             LOG_VFY("VFY: uninitialized ref not expected as reg check\n");
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
             break;
         }
         /* make sure srcType is initialized reference or always-NULL */
         if (!regTypeIsReference(srcType)) {
             LOG_VFY("VFY: register1 v%u type %d, wanted ref\n", vsrc, srcType);
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
             break;
         }
         if (regTypeIsUninitReference(srcType)) {
             LOG_VFY("VFY: register1 v%u holds uninitialized ref\n", vsrc);
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
             break;
         }
         /* if the register isn't Zero, make sure it's an instance of check */
@@ -1605,14 +1614,14 @@
                 {
                     LOG_VFY("VFY: %s does not implement %s\n",
                             srcClass->descriptor, checkClass->descriptor);
-                    *pOkay = false;
+                    *pFailure = VERIFY_ERROR_GENERIC;
                 }
                 */
             } else {
                 if (!dvmInstanceof(srcClass, checkClass)) {
                     LOG_VFY("VFY: %s is not instance of %s\n",
                             srcClass->descriptor, checkClass->descriptor);
-                    *pOkay = false;
+                    *pFailure = VERIFY_ERROR_GENERIC;
                 }
             }
         }
@@ -1625,10 +1634,10 @@
  * "insnRegCount" to encompass the result register.
  */
 static void setResultRegisterType(RegType* insnRegs, const int insnRegCount,
-    RegType newType, bool* pOkay)
+    RegType newType, VerifyError* pFailure)
 {
     setRegisterType(insnRegs, insnRegCount + kExtraRegs,
-        RESULT_REGISTER(insnRegCount), newType, pOkay);
+        RESULT_REGISTER(insnRegCount), newType, pFailure);
 }
 
 
@@ -1639,7 +1648,7 @@
  * must be marked as initialized.
  */
 static void markRefsAsInitialized(RegType* insnRegs, int insnRegCount,
-    UninitInstanceMap* uninitMap, RegType uninitType, bool* pOkay)
+    UninitInstanceMap* uninitMap, RegType uninitType, VerifyError* pFailure)
 {
     ClassObject* clazz;
     RegType initType;
@@ -1649,7 +1658,7 @@
     if (clazz == NULL) {
         LOGE("VFY: unable to find type=0x%x (idx=%d)\n",
             uninitType, regTypeToUninitIndex(uninitType));
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         return;
     }
     initType = regTypeFromClass(clazz);
@@ -1748,9 +1757,10 @@
  *
  * For category 2 values, "type" must be the "low" half of the value.
  *
- * Sets "*pOkay" to false if not.
+ * Sets "*pFailure" if something looks wrong.
  */
-static void checkTypeCategory(RegType type, TypeCategory cat, bool* pOkay)
+static void checkTypeCategory(RegType type, TypeCategory cat,
+    VerifyError* pFailure)
 {
     switch (cat) {
     case kTypeCategory1nr:
@@ -1767,7 +1777,7 @@
         case kRegTypeInteger:
             break;
         default:
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
             break;
         }
         break;
@@ -1778,19 +1788,19 @@
         case kRegTypeDoubleLo:
             break;
         default:
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
             break;
         }
         break;
 
     case kTypeCategoryRef:
         if (type != kRegTypeZero && !regTypeIsReference(type))
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
         break;
 
     default:
         assert(false);
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         break;
     }
 }
@@ -1802,10 +1812,10 @@
  * Does not verify that "typel" is in fact the low part of a 64-bit
  * register pair.
  */
-static void checkWidePair(RegType typel, RegType typeh, bool* pOkay)
+static void checkWidePair(RegType typel, RegType typeh, VerifyError* pFailure)
 {
     if ((typeh != typel+1))
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
 }
 
 /*
@@ -1816,15 +1826,15 @@
  * "vsrc" values are checked against this.
  */
 static void copyRegister1(RegType* insnRegs, int insnRegCount, u4 vdst,
-    u4 vsrc, TypeCategory cat, bool* pOkay)
+    u4 vsrc, TypeCategory cat, VerifyError* pFailure)
 {
-    RegType type = getRegisterType(insnRegs, insnRegCount, vsrc, pOkay);
-    if (*pOkay)
-        checkTypeCategory(type, cat, pOkay);
-    if (*pOkay)
-        setRegisterType(insnRegs, insnRegCount, vdst, type, pOkay);
+    RegType type = getRegisterType(insnRegs, insnRegCount, vsrc, pFailure);
+    if (VERIFY_OK(*pFailure))
+        checkTypeCategory(type, cat, pFailure);
+    if (VERIFY_OK(*pFailure))
+        setRegisterType(insnRegs, insnRegCount, vdst, type, pFailure);
 
-    if (!*pOkay) {
+    if (!VERIFY_OK(*pFailure)) {
         LOG_VFY("VFY: copy1 v%u<-v%u type=%d cat=%d\n", vdst, vsrc, type, cat);
     }
 }
@@ -1834,18 +1844,18 @@
  * "vsrc" to "vdst".  This copies both halves of the register.
  */
 static void copyRegister2(RegType* insnRegs, int insnRegCount, u4 vdst,
-    u4 vsrc, bool* pOkay)
+    u4 vsrc, VerifyError* pFailure)
 {
-    RegType typel = getRegisterType(insnRegs, insnRegCount, vsrc, pOkay);
-    RegType typeh = getRegisterType(insnRegs, insnRegCount, vsrc+1, pOkay);
-    if (*pOkay) {
-        checkTypeCategory(typel, kTypeCategory2, pOkay);
-        checkWidePair(typel, typeh, pOkay);
+    RegType typel = getRegisterType(insnRegs, insnRegCount, vsrc, pFailure);
+    RegType typeh = getRegisterType(insnRegs, insnRegCount, vsrc+1, pFailure);
+    if (VERIFY_OK(*pFailure)) {
+        checkTypeCategory(typel, kTypeCategory2, pFailure);
+        checkWidePair(typel, typeh, pFailure);
     }
-    if (*pOkay)
-        setRegisterType(insnRegs, insnRegCount, vdst, typel, pOkay);
+    if (VERIFY_OK(*pFailure))
+        setRegisterType(insnRegs, insnRegCount, vdst, typel, pFailure);
 
-    if (!*pOkay) {
+    if (!VERIFY_OK(*pFailure)) {
         LOG_VFY("VFY: copy2 v%u<-v%u type=%d/%d\n", vdst, vsrc, typel, typeh);
     }
 }
@@ -1858,21 +1868,21 @@
  * because that would affect the test on "vdst" as well.
  */
 static void copyResultRegister1(RegType* insnRegs, const int insnRegCount,
-    u4 vdst, TypeCategory cat, bool* pOkay)
+    u4 vdst, TypeCategory cat, VerifyError* pFailure)
 {
     RegType type;
     u4 vsrc;
 
     vsrc = RESULT_REGISTER(insnRegCount);
-    type = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc, pOkay);
-    if (*pOkay)
-        checkTypeCategory(type, cat, pOkay);
-    if (*pOkay) {
-        setRegisterType(insnRegs, insnRegCount, vdst, type, pOkay);
+    type = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc, pFailure);
+    if (VERIFY_OK(*pFailure))
+        checkTypeCategory(type, cat, pFailure);
+    if (VERIFY_OK(*pFailure)) {
+        setRegisterType(insnRegs, insnRegCount, vdst, type, pFailure);
         insnRegs[vsrc] = kRegTypeUnknown;
     }
 
-    if (!*pOkay) {
+    if (!VERIFY_OK(*pFailure)) {
         LOG_VFY("VFY: copyRes1 v%u<-v%u cat=%d type=%d\n",
             vdst, vsrc, cat, type);
     }
@@ -1886,25 +1896,27 @@
  * because that would affect the test on "vdst" as well.
  */
 static void copyResultRegister2(RegType* insnRegs, const int insnRegCount,
-    u4 vdst, bool* pOkay)
+    u4 vdst, VerifyError* pFailure)
 {
     RegType typel, typeh;
     u4 vsrc;
 
     vsrc = RESULT_REGISTER(insnRegCount);
-    typel = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc, pOkay);
-    typeh = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc+1, pOkay);
-    if (*pOkay) {
-        checkTypeCategory(typel, kTypeCategory2, pOkay);
-        checkWidePair(typel, typeh, pOkay);
+    typel = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc,
+                pFailure);
+    typeh = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc+1,
+                pFailure);
+    if (VERIFY_OK(*pFailure)) {
+        checkTypeCategory(typel, kTypeCategory2, pFailure);
+        checkWidePair(typel, typeh, pFailure);
     }
-    if (*pOkay) {
-        setRegisterType(insnRegs, insnRegCount, vdst, typel, pOkay);
+    if (VERIFY_OK(*pFailure)) {
+        setRegisterType(insnRegs, insnRegCount, vdst, typel, pFailure);
         insnRegs[vsrc] = kRegTypeUnknown;
         insnRegs[vsrc+1] = kRegTypeUnknown;
     }
 
-    if (!*pOkay) {
+    if (!VERIFY_OK(*pFailure)) {
         LOG_VFY("VFY: copyRes2 v%u<-v%u type=%d/%d\n",
             vdst, vsrc, typel, typeh);
     }
@@ -1916,10 +1928,10 @@
  */
 static void checkUnop(RegType* insnRegs, const int insnRegCount,
     DecodedInstruction* pDecInsn, RegType dstType, RegType srcType,
-    bool* pOkay)
+    VerifyError* pFailure)
 {
-    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType, pOkay);
-    setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pOkay);
+    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType, pFailure);
+    setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pFailure);
 }
 
 /*
@@ -1929,6 +1941,13 @@
  *
  * Assumes we've already validated reg1/reg2.
  *
+ * TODO: consider generalizing this.  The key principle is that the
+ * result of a bitwise operation can only be as wide as the widest of
+ * the operands.  You can safely AND/OR/XOR two chars together and know
+ * you still have a char, so it's reasonable for the compiler or "dx"
+ * to skip the int-to-char instruction.  (We need to do this for boolean
+ * because there is no int-to-boolean operation.)
+ *
  * Returns true if both args are Boolean, Zero, or One.
  */
 static bool upcastBooleanOp(RegType* insnRegs, const int insnRegCount,
@@ -1958,10 +1977,10 @@
  */
 static void checkLitop(RegType* insnRegs, const int insnRegCount,
     DecodedInstruction* pDecInsn, RegType dstType, RegType srcType,
-    bool checkBooleanOp, bool* pOkay)
+    bool checkBooleanOp, VerifyError* pFailure)
 {
-    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType, pOkay);
-    if (*pOkay && checkBooleanOp) {
+    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType, pFailure);
+    if (VERIFY_OK(*pFailure) && checkBooleanOp) {
         assert(dstType == kRegTypeInteger);
         /* check vB with the call, then check the constant manually */
         if (upcastBooleanOp(insnRegs, insnRegCount, pDecInsn->vB, pDecInsn->vB)
@@ -1970,7 +1989,7 @@
             dstType = kRegTypeBoolean;
         }
     }
-    setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pOkay);
+    setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pFailure);
 }
 
 /*
@@ -1980,16 +1999,18 @@
  */
 static void checkBinop(RegType* insnRegs, const int insnRegCount,
     DecodedInstruction* pDecInsn, RegType dstType, RegType srcType1,
-    RegType srcType2, bool checkBooleanOp, bool* pOkay)
+    RegType srcType2, bool checkBooleanOp, VerifyError* pFailure)
 {
-    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType1, pOkay);
-    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vC, srcType2, pOkay);
-    if (*pOkay && checkBooleanOp) {
+    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType1,
+        pFailure);
+    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vC, srcType2,
+        pFailure);
+    if (VERIFY_OK(*pFailure) && checkBooleanOp) {
         assert(dstType == kRegTypeInteger);
         if (upcastBooleanOp(insnRegs, insnRegCount, pDecInsn->vB, pDecInsn->vC))
             dstType = kRegTypeBoolean;
     }
-    setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pOkay);
+    setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pFailure);
 }
 
 /*
@@ -1998,16 +2019,135 @@
  */
 static void checkBinop2addr(RegType* insnRegs, const int insnRegCount,
     DecodedInstruction* pDecInsn, RegType dstType, RegType srcType1,
-    RegType srcType2, bool checkBooleanOp, bool* pOkay)
+    RegType srcType2, bool checkBooleanOp, VerifyError* pFailure)
 {
-    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vA, srcType1, pOkay);
-    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType2, pOkay);
-    if (*pOkay && checkBooleanOp) {
+    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vA, srcType1,
+        pFailure);
+    verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType2,
+        pFailure);
+    if (VERIFY_OK(*pFailure) && checkBooleanOp) {
         assert(dstType == kRegTypeInteger);
         if (upcastBooleanOp(insnRegs, insnRegCount, pDecInsn->vA, pDecInsn->vB))
             dstType = kRegTypeBoolean;
     }
-    setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pOkay);
+    setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pFailure);
+}
+
+/*
+ * Treat right-shifting as a narrowing conversion when possible.
+ *
+ * For example, right-shifting an int 24 times results in a value that can
+ * be treated as a byte.
+ *
+ * Things get interesting when contemplating sign extension.  Right-
+ * shifting an integer by 16 yields a value that can be represented in a
+ * "short" but not a "char", but an unsigned right shift by 16 yields a
+ * value that belongs in a char rather than a short.  (Consider what would
+ * happen if the result of the shift were cast to a char or short and then
+ * cast back to an int.  If sign extension, or the lack thereof, causes
+ * a change in the 32-bit representation, then the conversion was lossy.)
+ *
+ * A signed right shift by 17 on an integer results in a short.  An unsigned
+ * right shfit by 17 on an integer results in a posshort, which can be
+ * assigned to a short or a char.
+ *
+ * An unsigned right shift on a short can actually expand the result into
+ * a 32-bit integer.  For example, 0xfffff123 >>> 8 becomes 0x00fffff1,
+ * which can't be represented in anything smaller than an int.
+ *
+ * javac does not generate code that takes advantage of this, but some
+ * of the code optimizers do.  It's generally a peephole optimization
+ * that replaces a particular sequence, e.g. (bipush 24, ishr, i2b) is
+ * replaced by (bipush 24, ishr).  Knowing that shifting a short 8 times
+ * to the right yields a byte is really more than we need to handle the
+ * code that's out there, but support is not much more complex than just
+ * handling integer.
+ *
+ * Right-shifting never yields a boolean value.
+ *
+ * Returns the new register type.
+ */
+static RegType adjustForRightShift(RegType* workRegs, const int insnRegCount,
+    int reg, unsigned int shiftCount, bool isUnsignedShift,
+    VerifyError* pFailure)
+{
+    RegType srcType = getRegisterType(workRegs, insnRegCount, reg, pFailure);
+    RegType newType;
+
+    /* no-op */
+    if (shiftCount == 0)
+        return srcType;
+
+    /* safe defaults */
+    if (isUnsignedShift)
+        newType = kRegTypeInteger;
+    else
+        newType = srcType;
+
+    if (shiftCount >= 32) {
+        LOG_VFY("Got unexpectedly large shift count %u\n", shiftCount);
+        /* fail? */
+        return newType;
+    }
+
+    switch (srcType) {
+    case kRegTypeInteger:               /* 32-bit signed value */
+    case kRegTypeFloat:                 /* (allowed; treat same as int) */
+        if (isUnsignedShift) {
+            if (shiftCount > 24)
+                newType = kRegTypePosByte;
+            else if (shiftCount >= 16)
+                newType = kRegTypeChar;
+        } else {
+            if (shiftCount >= 24)
+                newType = kRegTypeByte;
+            else if (shiftCount >= 16)
+                newType = kRegTypeShort;
+        }
+        break;
+    case kRegTypeShort:                 /* 16-bit signed value */
+        if (isUnsignedShift) {
+            /* default (kRegTypeInteger) is correct */
+        } else {
+            if (shiftCount >= 8)
+                newType = kRegTypeByte;
+        }
+        break;
+    case kRegTypePosShort:              /* 15-bit unsigned value */
+        if (shiftCount >= 8)
+            newType = kRegTypePosByte;
+        break;
+    case kRegTypeChar:                  /* 16-bit unsigned value */
+        if (shiftCount > 8)
+            newType = kRegTypePosByte;
+        break;
+    case kRegTypeByte:                  /* 8-bit signed value */
+        /* defaults (u=kRegTypeInteger / s=srcType) are correct */
+        break;
+    case kRegTypePosByte:               /* 7-bit unsigned value */
+        /* always use newType=srcType */
+        newType = srcType;
+        break;
+    case kRegTypeZero:                  /* 1-bit unsigned value */
+    case kRegTypeOne:
+    case kRegTypeBoolean:
+        /* unnecessary? */
+        newType = kRegTypeZero;
+        break;
+    default:
+        /* long, double, references; shouldn't be here! */
+        assert(false);
+        break;
+    }
+
+    if (newType != srcType) {
+        LOGVV("narrowing: %d(%d) --> %d to %d\n",
+            shiftCount, isUnsignedShift, srcType, newType);
+    } else {
+        LOGVV("not narrowed: %d(%d) --> %d\n",
+            shiftCount, isUnsignedShift, srcType);
+    }
+    return newType;
 }
 
 
@@ -2329,28 +2469,28 @@
  * allow it to be uninitialized if this is an "<init>" method and the field
  * is declared within the "objType" class.
  *
- * Returns an InstField on success, returns NULL and sets "*pOkay" to false
+ * Returns an InstField on success, returns NULL and sets "*pFailure"
  * on failure.
  */
 static InstField* getInstField(const Method* meth,
     const UninitInstanceMap* uninitMap, RegType objType, int fieldIdx,
-    bool* pOkay)
+    VerifyError* pFailure)
 {
     InstField* instField = NULL;
     ClassObject* objClass;
     bool mustBeLocal = false;
 
     if (!regTypeIsReference(objType)) {
-        LOG_VFY("VFY: attempt to access field of non-reference type %d\n",
+        LOG_VFY("VFY: attempt to access field in non-reference type %d\n",
             objType);
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_GENERIC;
         goto bail;
     }
 
-    instField = dvmOptResolveInstField(meth->clazz, fieldIdx);
+    instField = dvmOptResolveInstField(meth->clazz, fieldIdx, pFailure);
     if (instField == NULL) {
         LOG_VFY("VFY: unable to resolve instance field %u\n", fieldIdx);
-        *pOkay = false;
+        assert(!VERIFY_OK(*pFailure));
         goto bail;
     }
 
@@ -2367,7 +2507,7 @@
     if (regTypeIsUninitReference(objType)) {
         if (!isInitMethod(meth) || meth->clazz != objClass) {
             LOG_VFY("VFY: attempt to access field via uninitialized ref\n");
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
             goto bail;
         }
         mustBeLocal = true;
@@ -2377,7 +2517,7 @@
         LOG_VFY("VFY: invalid field access (field %s.%s, through %s ref)\n",
                 instField->field.clazz->descriptor, instField->field.name,
                 objClass->descriptor);
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_NO_FIELD;
         goto bail;
     }
 
@@ -2388,7 +2528,7 @@
         {
             LOG_VFY("VFY: invalid constructor field access (field %s in %s)\n",
                     instField->field.name, objClass->descriptor);
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
             goto bail;
         }
     }
@@ -2400,15 +2540,15 @@
 /*
  * Look up a static field.
  *
- * Returns a StaticField on success, returns NULL and sets "*pOkay" to false
+ * Returns a StaticField on success, returns NULL and sets "*pFailure"
  * on failure.
  */
 static StaticField* getStaticField(const Method* meth, int fieldIdx,
-    bool* pOkay)
+    VerifyError* pFailure)
 {
     StaticField* staticField;
 
-    staticField = dvmOptResolveStaticField(meth->clazz, fieldIdx);
+    staticField = dvmOptResolveStaticField(meth->clazz, fieldIdx, pFailure);
     if (staticField == NULL) {
         DexFile* pDexFile = meth->clazz->pDvmDex->pDexFile;
         const DexFieldId* pFieldId;
@@ -2418,8 +2558,7 @@
         LOG_VFY("VFY: unable to resolve static field %u (%s) in %s\n", fieldIdx,
             dexStringById(pDexFile, pFieldId->nameIdx),
             dexStringByTypeIdx(pDexFile, pFieldId->classIdx));
-
-        *pOkay = false;
+        assert(!VERIFY_OK(*pFailure));
         goto bail;
     }
 
@@ -2431,10 +2570,10 @@
  * If "field" is marked "final", make sure this is the either <clinit>
  * or <init> as appropriate.
  *
- * Sets "*pOkay" to false on failure.
+ * Sets "*pFailure" on failure.
  */
 static void checkFinalFieldAccess(const Method* meth, const Field* field,
-    bool* pOkay)
+    VerifyError* pFailure)
 {
     if (!dvmIsFinalField(field))
         return;
@@ -2443,21 +2582,15 @@
     if (meth->clazz != field->clazz) {
         LOG_VFY_METH(meth, "VFY: can't modify final field %s.%s\n",
             field->clazz->descriptor, field->name);
-        *pOkay = false;
+        *pFailure = VERIFY_ERROR_ACCESS_FIELD;
         return;
     }
 
     /*
-     * The EMMA code coverage tool generates a static method that
-     * modifies a private static final field.  The method is only
-     * called by <clinit>, so the code is reasonable if not quite
-     * kosher.  (Attempting to *compile* code that does something
-     * like that will earn you a quick thumbs-down from javac.)
-     *
-     * The verifier in another popular VM doesn't complain about this,
-     * so we're going to allow classes to modify their own static
-     * final fields outside of class initializers.  Further testing
-     * showed that modifications to instance fields are also allowed.
+     * The VM spec descriptions of putfield and putstatic say that
+     * IllegalAccessError is only thrown when the instructions appear
+     * outside the declaring class.  Our earlier attempts to restrict
+     * final field modification to constructors are, therefore, wrong.
      */
 #if 0
     /* make sure we're in the right kind of constructor */
@@ -2465,13 +2598,13 @@
         if (!isClassInitMethod(meth)) {
             LOG_VFY_METH(meth,
                 "VFY: can't modify final static field outside <clinit>\n");
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
         }
     } else {
         if (!isInitMethod(meth)) {
             LOG_VFY_METH(meth,
                 "VFY: can't modify final field outside <init>\n");
-            *pOkay = false;
+            *pFailure = VERIFY_ERROR_GENERIC;
         }
     }
 #endif
@@ -2480,19 +2613,19 @@
 /*
  * Make sure that the register type is suitable for use as an array index.
  *
- * Sets "*pOkay" to false if not.
+ * Sets "*pFailure" if not.
  */
 static void checkArrayIndexType(const Method* meth, RegType regType,
-    bool* pOkay)
+    VerifyError* pFailure)
 {
-    if (*pOkay) {
+    if (VERIFY_OK(*pFailure)) {
         /*
          * The 1nr types are interchangeable at this level.  We could
          * do something special if we can definitively identify it as a
          * float, but there's no real value in doing so.
          */
-        checkTypeCategory(regType, kTypeCategory1nr, pOkay);
-        if (!*pOkay) {
+        checkTypeCategory(regType, kTypeCategory1nr, pFailure);
+        if (!VERIFY_OK(*pFailure)) {
             LOG_VFY_METH(meth, "Invalid reg type for array index (%d)\n",
                 regType);
         }
@@ -2560,11 +2693,14 @@
  * Returns NULL if no matching exception handler can be found, or if the
  * exception is not a subclass of Throwable.
  */
-static ClassObject* getCaughtExceptionType(const Method* meth, int insnIdx)
+static ClassObject* getCaughtExceptionType(const Method* meth, int insnIdx,
+    VerifyError* pFailure)
 {
+    VerifyError localFailure;
     const DexCode* pCode;
     DexFile* pDexFile;
     ClassObject* commonSuper = NULL;
+    bool foundPossibleHandler = false;
     u4 handlersSize;
     u4 offset;
     u4 i;
@@ -2593,16 +2729,22 @@
 
             if (handler->address == (u4) insnIdx) {
                 ClassObject* clazz;
+                foundPossibleHandler = true;
 
                 if (handler->typeIdx == kDexNoIndex)
                     clazz = gDvm.classJavaLangThrowable;
                 else
-                    clazz = dvmOptResolveClass(meth->clazz, handler->typeIdx);
+                    clazz = dvmOptResolveClass(meth->clazz, handler->typeIdx,
+                                &localFailure);
 
                 if (clazz == NULL) {
                     LOG_VFY("VFY: unable to resolve exception class %u (%s)\n",
                         handler->typeIdx,
                         dexStringByTypeIdx(pDexFile, handler->typeIdx));
+                    /* TODO: do we want to keep going?  If we don't fail
+                     * this we run the risk of having a non-Throwable
+                     * introduced at runtime.  However, that won't pass
+                     * an instanceof test, so is essentially harmless. */
                 } else {
                     if (commonSuper == NULL)
                         commonSuper = clazz;
@@ -2616,8 +2758,12 @@
     }
 
     if (commonSuper == NULL) {
+        /* no catch blocks, or no catches with classes we can find */
         LOG_VFY_METH(meth,
             "VFY: unable to find exception handler at addr 0x%x\n", insnIdx);
+        *pFailure = VERIFY_ERROR_GENERIC;
+    } else {
+        // TODO: verify the class is an instance of Throwable?
     }
 
     return commonSuper;
@@ -2732,7 +2878,7 @@
 static void verifyFilledNewArrayRegs(const Method* meth,
     const RegType* insnRegs, const int insnRegCount,
     const DecodedInstruction* pDecInsn, ClassObject* resClass, bool isRange,
-    bool* pOkay)
+    VerifyError* pFailure)
 {
     u4 argCount = pDecInsn->vA;
     RegType expectedType;
@@ -2761,8 +2907,9 @@
         else
             getReg = pDecInsn->arg[ui];
 
-        verifyRegisterType(insnRegs, insnRegCount, getReg, expectedType, pOkay);
-        if (!*pOkay) {
+        verifyRegisterType(insnRegs, insnRegCount, getReg, expectedType,
+            pFailure);
+        if (!VERIFY_OK(*pFailure)) {
             LOG_VFY("VFY: filled-new-array arg %u(%u) not valid\n", ui, getReg);
             return;
         }
@@ -2771,6 +2918,128 @@
 
 
 /*
+ * Replace an instruction with "throw-verification-error".  This allows us to
+ * defer error reporting until the code path is first used.
+ *
+ * The throw-verification-error instruction requires two code units.  Some
+ * of the replaced instructions require three; the third code unit will
+ * receive a "nop".  The instruction's length will be left unchanged
+ * in "insnFlags".
+ *
+ * IMPORTANT: this may replace meth->insns with a pointer to a new copy of
+ * the instructions.
+ *
+ * Returns "true" on success.
+ */
+static bool replaceFailingInstruction(Method* meth, InsnFlags* insnFlags,
+    int insnIdx, VerifyError failure)
+{
+    VerifyErrorRefType refType;
+    const u2* oldInsns = meth->insns + insnIdx;
+    u2 oldInsn = *oldInsns;
+    bool result = false;
+
+    dvmMakeCodeReadWrite(meth);
+
+    //LOGD("  was 0x%04x\n", oldInsn);
+    u2* newInsns = (u2*) meth->insns + insnIdx;
+
+    /*
+     * Generate the new instruction out of the old.
+     *
+     * First, make sure this is an instruction we're expecting to stomp on.
+     */
+    switch (oldInsn & 0xff) {
+    case OP_CONST_CLASS:                // insn[1] == class ref, 2 bytes
+    case OP_CHECK_CAST:
+    case OP_INSTANCE_OF:
+    case OP_NEW_INSTANCE:
+    case OP_NEW_ARRAY:
+    case OP_FILLED_NEW_ARRAY:           // insn[1] == class ref, 3 bytes
+    case OP_FILLED_NEW_ARRAY_RANGE:
+        refType = VERIFY_ERROR_REF_CLASS;
+        break;
+
+    case OP_IGET:                       // insn[1] == field ref, 2 bytes
+    case OP_IGET_BOOLEAN:
+    case OP_IGET_BYTE:
+    case OP_IGET_CHAR:
+    case OP_IGET_SHORT:
+    case OP_IGET_WIDE:
+    case OP_IGET_OBJECT:
+    case OP_IPUT:
+    case OP_IPUT_BOOLEAN:
+    case OP_IPUT_BYTE:
+    case OP_IPUT_CHAR:
+    case OP_IPUT_SHORT:
+    case OP_IPUT_WIDE:
+    case OP_IPUT_OBJECT:
+    case OP_SGET:
+    case OP_SGET_BOOLEAN:
+    case OP_SGET_BYTE:
+    case OP_SGET_CHAR:
+    case OP_SGET_SHORT:
+    case OP_SGET_WIDE:
+    case OP_SGET_OBJECT:
+    case OP_SPUT:
+    case OP_SPUT_BOOLEAN:
+    case OP_SPUT_BYTE:
+    case OP_SPUT_CHAR:
+    case OP_SPUT_SHORT:
+    case OP_SPUT_WIDE:
+    case OP_SPUT_OBJECT:
+        refType = VERIFY_ERROR_REF_FIELD;
+        break;
+
+    case OP_INVOKE_VIRTUAL:             // insn[1] == method ref, 3 bytes
+    case OP_INVOKE_VIRTUAL_RANGE:
+    case OP_INVOKE_SUPER:
+    case OP_INVOKE_SUPER_RANGE:
+    case OP_INVOKE_DIRECT:
+    case OP_INVOKE_DIRECT_RANGE:
+    case OP_INVOKE_STATIC:
+    case OP_INVOKE_STATIC_RANGE:
+    case OP_INVOKE_INTERFACE:
+    case OP_INVOKE_INTERFACE_RANGE:
+        refType = VERIFY_ERROR_REF_METHOD;
+        break;
+
+    default:
+        /* could handle this in a generic way, but this is probably safer */
+        LOG_VFY("GLITCH: verifier asked to replace opcode 0x%02x\n",
+            oldInsn & 0xff);
+        goto bail;
+    }
+
+    /* write a NOP over the third code unit, if necessary */
+    int width = dvmInsnGetWidth(insnFlags, insnIdx);
+    switch (width) {
+    case 2:
+        /* nothing to do */
+        break;
+    case 3:
+        newInsns[2] = OP_NOP;
+        break;
+    default:
+        /* whoops */
+        LOGE("ERROR: stomped a %d-unit instruction with a verifier error\n",
+            width);
+        dvmAbort();
+    }
+
+    /* encode the opcode, with the failure code in the high byte */
+    newInsns[0] = OP_THROW_VERIFICATION_ERROR |
+        (failure << 8) | (refType << (8 + kVerifyErrorRefTypeShift));
+
+    result = true;
+
+bail:
+    dvmMakeCodeReadOnly(meth);
+    return result;
+}
+
+
+/*
  * ===========================================================================
  *      Entry point and driver loop
  * ===========================================================================
@@ -2779,7 +3048,7 @@
 /*
  * Entry point for the detailed code-flow analysis.
  */
-bool dvmVerifyCodeFlow(const Method* meth, InsnFlags* insnFlags,
+bool dvmVerifyCodeFlow(Method* meth, InsnFlags* insnFlags,
     UninitInstanceMap* uninitMap)
 {
     bool result = false;
@@ -2806,9 +3075,13 @@
     if (gDvm.classJavaLangString == NULL)
         gDvm.classJavaLangString =
             dvmFindSystemClassNoInit("Ljava/lang/String;");
-    if (gDvm.classJavaLangThrowable == NULL)
+    if (gDvm.classJavaLangThrowable == NULL) {
         gDvm.classJavaLangThrowable =
             dvmFindSystemClassNoInit("Ljava/lang/Throwable;");
+        gDvm.offJavaLangThrowable_cause =
+            dvmFindFieldOffset(gDvm.classJavaLangThrowable,
+                "cause", "Ljava/lang/Throwable;");
+    }
     if (gDvm.classJavaLangObject == NULL)
         gDvm.classJavaLangObject =
             dvmFindSystemClassNoInit("Ljava/lang/Object;");
@@ -2929,7 +3202,7 @@
  * instruction if a register contains an uninitialized instance created
  * by that same instrutcion.
  */
-static bool doCodeVerification(const Method* meth, InsnFlags* insnFlags,
+static bool doCodeVerification(Method* meth, InsnFlags* insnFlags,
     RegisterTable* regTable, UninitInstanceMap* uninitMap)
 {
     const int insnsSize = dvmGetMethodInsnsSize(meth);
@@ -3087,10 +3360,14 @@
         dvmInsnSetChanged(insnFlags, insnIdx, false);
     }
 
-    if (DEAD_CODE_SCAN) {
+    if (DEAD_CODE_SCAN && !IS_METHOD_FLAG_SET(meth, METHOD_ISWRITABLE)) {
         /*
-         * Scan for dead code.  There's nothing "evil" about dead code, but it
-         * indicates a flaw somewhere down the line, possibly in the verifier.
+         * Scan for dead code.  There's nothing "evil" about dead code
+         * (besides the wasted space), but it indicates a flaw somewhere
+         * down the line, possibly in the verifier.
+         *
+         * If we've rewritten "always throw" instructions into the stream,
+         * we are almost certainly going to have some dead code.
          */
         int deadStart = -1;
         for (insnIdx = 0; insnIdx < insnsSize;
@@ -3156,8 +3433,11 @@
  * if execution at that point needs to be (re-)evaluated.  Register changes
  * are merged into "regTypes" at the target addresses.  Does not set or
  * clear any other flags in "insnFlags".
+ *
+ * This may alter meth->insns if we need to replace an instruction with
+ * throw-verification-error.
  */
-static bool verifyInstruction(const Method* meth, InsnFlags* insnFlags,
+static bool verifyInstruction(Method* meth, InsnFlags* insnFlags,
     RegisterTable* regTable, RegType* workRegs, int insnIdx,
     UninitInstanceMap* uninitMap, int* pStartGuess)
 {
@@ -3194,14 +3474,14 @@
     RegType tmpType;
     DecodedInstruction decInsn;
     bool justSetResult = false;
-    bool okay = true;
+    VerifyError failure = VERIFY_ERROR_NONE;
 
 #ifndef NDEBUG
     memset(&decInsn, 0x81, sizeof(decInsn));
 #endif
     dexDecodeInstruction(gDvm.instrFormat, insns, &decInsn);
 
-    const int nextFlags = dexGetInstrFlags(gDvm.instrFlags, decInsn.opCode);
+    int nextFlags = dexGetInstrFlags(gDvm.instrFlags, decInsn.opCode);
 
     /*
      * Make a copy of the previous register state.  If the instruction
@@ -3229,7 +3509,7 @@
          */
         if (decInsn.vA != 0) {
             LOG_VFY("VFY: encountered data table in instruction stream\n");
-            okay = false;
+            failure = VERIFY_ERROR_GENERIC;
         }
         break;
 
@@ -3237,18 +3517,18 @@
     case OP_MOVE_FROM16:
     case OP_MOVE_16:
         copyRegister1(workRegs, insnRegCount, decInsn.vA, decInsn.vB,
-            kTypeCategory1nr, &okay);
+            kTypeCategory1nr, &failure);
         break;
     case OP_MOVE_WIDE:
     case OP_MOVE_WIDE_FROM16:
     case OP_MOVE_WIDE_16:
-        copyRegister2(workRegs, insnRegCount, decInsn.vA, decInsn.vB, &okay);
+        copyRegister2(workRegs, insnRegCount, decInsn.vA, decInsn.vB, &failure);
         break;
     case OP_MOVE_OBJECT:
     case OP_MOVE_OBJECT_FROM16:
     case OP_MOVE_OBJECT_16:
         copyRegister1(workRegs, insnRegCount, decInsn.vA, decInsn.vB,
-            kTypeCategoryRef, &okay);
+            kTypeCategoryRef, &failure);
         break;
 
     /*
@@ -3264,14 +3544,14 @@
      */
     case OP_MOVE_RESULT:
         copyResultRegister1(workRegs, insnRegCount, decInsn.vA,
-            kTypeCategory1nr, &okay);
+            kTypeCategory1nr, &failure);
         break;
     case OP_MOVE_RESULT_WIDE:
-        copyResultRegister2(workRegs, insnRegCount, decInsn.vA, &okay);
+        copyResultRegister2(workRegs, insnRegCount, decInsn.vA, &failure);
         break;
     case OP_MOVE_RESULT_OBJECT:
         copyResultRegister1(workRegs, insnRegCount, decInsn.vA,
-            kTypeCategoryRef, &okay);
+            kTypeCategoryRef, &failure);
         break;
 
     case OP_MOVE_EXCEPTION:
@@ -3284,71 +3564,75 @@
          * "resClass" will hold the closest common superclass of all
          * exceptions that can be handled here.
          */
-        resClass = getCaughtExceptionType(meth, insnIdx);
+        resClass = getCaughtExceptionType(meth, insnIdx, &failure);
         if (resClass == NULL) {
-            okay = false;
+            assert(!VERIFY_OK(failure));
         } else {
             setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                regTypeFromClass(resClass), &okay);
+                regTypeFromClass(resClass), &failure);
         }
         break;
 
     case OP_RETURN_VOID:
-        okay = checkConstructorReturn(meth, workRegs, insnRegCount);
-        if (okay && getMethodReturnType(meth) != kRegTypeUnknown) {
+        if (!checkConstructorReturn(meth, workRegs, insnRegCount)) {
+            failure = VERIFY_ERROR_GENERIC;
+        } else if (getMethodReturnType(meth) != kRegTypeUnknown) {
             LOG_VFY("VFY: return-void not expected\n");
-            okay = false;
+            failure = VERIFY_ERROR_GENERIC;
         }
         break;
     case OP_RETURN:
-        okay = checkConstructorReturn(meth, workRegs, insnRegCount);
-        if (okay) {
+        if (!checkConstructorReturn(meth, workRegs, insnRegCount)) {
+            failure = VERIFY_ERROR_GENERIC;
+        } else {
             /* check the method signature */
             RegType returnType = getMethodReturnType(meth);
-            checkTypeCategory(returnType, kTypeCategory1nr, &okay);
-            if (!okay)
+            checkTypeCategory(returnType, kTypeCategory1nr, &failure);
+            if (!VERIFY_OK(failure))
                 LOG_VFY("VFY: return-32 not expected\n");
 
             /* check the register contents */
             returnType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
-                &okay);
-            checkTypeCategory(returnType, kTypeCategory1nr, &okay);
-            if (!okay)
+                &failure);
+            checkTypeCategory(returnType, kTypeCategory1nr, &failure);
+            if (!VERIFY_OK(failure))
                 LOG_VFY("VFY: return-32 on invalid register v%d\n", decInsn.vA);
         }
         break;
     case OP_RETURN_WIDE:
-        okay = checkConstructorReturn(meth, workRegs, insnRegCount);
-        if (okay) {
+        if (!checkConstructorReturn(meth, workRegs, insnRegCount)) {
+            failure = VERIFY_ERROR_GENERIC;
+        } else {
             RegType returnType, returnTypeHi;
 
             /* check the method signature */
             returnType = getMethodReturnType(meth);
-            checkTypeCategory(returnType, kTypeCategory2, &okay);
-            if (!okay)
+            checkTypeCategory(returnType, kTypeCategory2, &failure);
+            if (!VERIFY_OK(failure))
                 LOG_VFY("VFY: return-wide not expected\n");
 
             /* check the register contents */
             returnType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
-                &okay);
+                &failure);
             returnTypeHi = getRegisterType(workRegs, insnRegCount,
-                decInsn.vA +1, &okay);
-            if (okay) {
-                checkTypeCategory(returnType, kTypeCategory2, &okay);
-                checkWidePair(returnType, returnTypeHi, &okay);
+                decInsn.vA +1, &failure);
+            if (VERIFY_OK(failure)) {
+                checkTypeCategory(returnType, kTypeCategory2, &failure);
+                checkWidePair(returnType, returnTypeHi, &failure);
             }
-            if (!okay) {
+            if (!VERIFY_OK(failure)) {
                 LOG_VFY("VFY: return-wide on invalid register pair v%d\n",
                     decInsn.vA);
             }
         }
         break;
     case OP_RETURN_OBJECT:
-        okay = checkConstructorReturn(meth, workRegs, insnRegCount);
-        if (okay) {
+        if (!checkConstructorReturn(meth, workRegs, insnRegCount)) {
+            failure = VERIFY_ERROR_GENERIC;
+        } else {
             RegType returnType = getMethodReturnType(meth);
-            checkTypeCategory(returnType, kTypeCategoryRef, &okay);
-            if (!okay) {
+            checkTypeCategory(returnType, kTypeCategoryRef, &failure);
+            if (!VERIFY_OK(failure)) {
                 LOG_VFY("VFY: return-object not expected\n");
                 break;
             }
@@ -3371,16 +3655,17 @@
 
             declClass = regTypeInitializedReferenceToClass(returnType);
             resClass = getClassFromRegister(workRegs, insnRegCount,
-                            decInsn.vA, &okay);
-            if (!okay)
+                            decInsn.vA, &failure);
+            if (!VERIFY_OK(failure))
                 break;
             if (resClass != NULL) {
                 if (!dvmIsInterfaceClass(declClass) &&
                     !dvmInstanceof(resClass, declClass))
                 {
-                    LOG_VFY("VFY: returning %s, declared %s\n",
-                            resClass->descriptor, declClass->descriptor);
-                    okay = false;
+                    LOG_VFY("VFY: returning %s (cl=%p), declared %s (cl=%p)\n",
+                            resClass->descriptor, resClass->classLoader,
+                            declClass->descriptor, declClass->classLoader);
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
             }
@@ -3392,12 +3677,12 @@
     case OP_CONST:
         /* could be boolean, int, float, or a null reference */
         setRegisterType(workRegs, insnRegCount, decInsn.vA,
-            dvmDetermineCat1Const((s4)decInsn.vB), &okay);
+            dvmDetermineCat1Const((s4)decInsn.vB), &failure);
         break;
     case OP_CONST_HIGH16:
         /* could be boolean, int, float, or a null reference */
         setRegisterType(workRegs, insnRegCount, decInsn.vA,
-            dvmDetermineCat1Const((s4) decInsn.vB << 16), &okay);
+            dvmDetermineCat1Const((s4) decInsn.vB << 16), &failure);
         break;
     case OP_CONST_WIDE_16:
     case OP_CONST_WIDE_32:
@@ -3405,36 +3690,38 @@
     case OP_CONST_WIDE_HIGH16:
         /* could be long or double; default to long and allow conversion */
         setRegisterType(workRegs, insnRegCount, decInsn.vA,
-            kRegTypeLongLo, &okay);
+            kRegTypeLongLo, &failure);
         break;
     case OP_CONST_STRING:
     case OP_CONST_STRING_JUMBO:
         assert(gDvm.classJavaLangString != NULL);
         setRegisterType(workRegs, insnRegCount, decInsn.vA,
-            regTypeFromClass(gDvm.classJavaLangString), &okay);
+            regTypeFromClass(gDvm.classJavaLangString), &failure);
         break;
     case OP_CONST_CLASS:
         assert(gDvm.classJavaLangClass != NULL);
         /* make sure we can resolve the class; access check is important */
-        resClass = dvmOptResolveClass(meth->clazz, decInsn.vB);
+        resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure);
         if (resClass == NULL) {
             const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
             dvmLogUnableToResolveClass(badClassDesc, meth);
             LOG_VFY("VFY: unable to resolve const-class %d (%s) in %s\n",
                 decInsn.vB, badClassDesc, meth->clazz->descriptor);
-            okay = false;
+            assert(failure != VERIFY_ERROR_GENERIC);
         } else {
             setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                regTypeFromClass(gDvm.classJavaLangClass), &okay);
+                regTypeFromClass(gDvm.classJavaLangClass), &failure);
         }
         break;
 
     case OP_MONITOR_ENTER:
     case OP_MONITOR_EXIT:
-        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
-        if (okay && !regTypeIsReference(tmpType)) {
-            LOG_VFY("VFY: monitor op on non-object\n");
-            okay = false;
+        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
+        if (VERIFY_OK(failure)) {
+            if (!regTypeIsReference(tmpType)) {
+                LOG_VFY("VFY: monitor op on non-object\n");
+                failure = VERIFY_ERROR_GENERIC;
+            }
         }
         break;
 
@@ -3447,86 +3734,88 @@
          * If it fails, an exception is thrown, which we deal with later
          * by ignoring the update to decInsn.vA when branching to a handler.
          */
-        resClass = dvmOptResolveClass(meth->clazz, decInsn.vB);
+        resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure);
         if (resClass == NULL) {
             const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
             dvmLogUnableToResolveClass(badClassDesc, meth);
             LOG_VFY("VFY: unable to resolve check-cast %d (%s) in %s\n",
                 decInsn.vB, badClassDesc, meth->clazz->descriptor);
-            okay = false;
+            assert(failure != VERIFY_ERROR_GENERIC);
         } else {
             RegType origType;
 
             origType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
-                        &okay);
-            if (!okay)
+                        &failure);
+            if (!VERIFY_OK(failure))
                 break;
             if (!regTypeIsReference(origType)) {
                 LOG_VFY("VFY: check-cast on non-reference in v%u\n",decInsn.vA);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
             setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                regTypeFromClass(resClass), &okay);
+                regTypeFromClass(resClass), &failure);
         }
         break;
     case OP_INSTANCE_OF:
         /* make sure we're checking a reference type */
-        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vB, &okay);
-        if (!okay)
+        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vB, &failure);
+        if (!VERIFY_OK(failure))
             break;
         if (!regTypeIsReference(tmpType)) {
             LOG_VFY("VFY: vB not a reference (%d)\n", tmpType);
-            okay = false;
+            failure = VERIFY_ERROR_GENERIC;
             break;
         }
 
         /* make sure we can resolve the class; access check is important */
-        resClass = dvmOptResolveClass(meth->clazz, decInsn.vC);
+        resClass = dvmOptResolveClass(meth->clazz, decInsn.vC, &failure);
         if (resClass == NULL) {
             const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vC);
             dvmLogUnableToResolveClass(badClassDesc, meth);
             LOG_VFY("VFY: unable to resolve instanceof %d (%s) in %s\n",
                 decInsn.vC, badClassDesc, meth->clazz->descriptor);
-            okay = false;
+            assert(failure != VERIFY_ERROR_GENERIC);
         } else {
             /* result is boolean */
             setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                kRegTypeBoolean, &okay);
+                kRegTypeBoolean, &failure);
         }
         break;
 
     case OP_ARRAY_LENGTH:
         resClass = getClassFromRegister(workRegs, insnRegCount,
-                        decInsn.vB, &okay);
-        if (!okay)
+                        decInsn.vB, &failure);
+        if (!VERIFY_OK(failure))
             break;
         if (resClass != NULL && !dvmIsArrayClass(resClass)) {
             LOG_VFY("VFY: array-length on non-array\n");
-            okay = false;
+            failure = VERIFY_ERROR_GENERIC;
             break;
         }
         setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeInteger,
-            &okay);
+            &failure);
         break;
 
     case OP_NEW_INSTANCE:
-        /*
-         * We can check for interface and abstract classes here, but we
-         * can't reject them.  We can ask the optimizer to replace the
-         * instructions with a magic "always throw InstantiationError"
-         * instruction.  (Not enough bytes to sub in a method call.)
-         */
-        resClass = dvmOptResolveClass(meth->clazz, decInsn.vB);
+        resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure);
         if (resClass == NULL) {
             const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
             dvmLogUnableToResolveClass(badClassDesc, meth);
             LOG_VFY("VFY: unable to resolve new-instance %d (%s) in %s\n",
                 decInsn.vB, badClassDesc, meth->clazz->descriptor);
-            okay = false;
+            assert(failure != VERIFY_ERROR_GENERIC);
         } else {
             RegType uninitType;
 
+            /* can't create an instance of an interface or abstract class */
+            if (dvmIsAbstractClass(resClass) || dvmIsInterfaceClass(resClass)) {
+                LOG_VFY("VFY: new-instance on interface or abstract class %s\n",
+                    resClass->descriptor);
+                failure = VERIFY_ERROR_INSTANTIATION;
+                break;
+            }
+
             /* add resolved class to uninit map if not already there */
             int uidx = dvmSetUninitInstance(uninitMap, insnIdx, resClass);
             assert(uidx >= 0);
@@ -3541,50 +3830,50 @@
 
             /* add the new uninitialized reference to the register ste */
             setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                uninitType, &okay);
+                uninitType, &failure);
         }
         break;
     case OP_NEW_ARRAY:
-        resClass = dvmOptResolveClass(meth->clazz, decInsn.vC);
+        resClass = dvmOptResolveClass(meth->clazz, decInsn.vC, &failure);
         if (resClass == NULL) {
             const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vC);
             dvmLogUnableToResolveClass(badClassDesc, meth);
             LOG_VFY("VFY: unable to resolve new-array %d (%s) in %s\n",
                 decInsn.vC, badClassDesc, meth->clazz->descriptor);
-            okay = false;
+            assert(failure != VERIFY_ERROR_GENERIC);
         } else if (!dvmIsArrayClass(resClass)) {
             LOG_VFY("VFY: new-array on non-array class\n");
-            okay = false;
+            failure = VERIFY_ERROR_GENERIC;
         } else {
             /* make sure "size" register is valid type */
             verifyRegisterType(workRegs, insnRegCount, decInsn.vB,
-                kRegTypeInteger, &okay);
+                kRegTypeInteger, &failure);
             /* set register type to array class */
             setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                regTypeFromClass(resClass), &okay);
+                regTypeFromClass(resClass), &failure);
         }
         break;
     case OP_FILLED_NEW_ARRAY:
     case OP_FILLED_NEW_ARRAY_RANGE:
-        resClass = dvmOptResolveClass(meth->clazz, decInsn.vB);
+        resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure);
         if (resClass == NULL) {
             const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
             dvmLogUnableToResolveClass(badClassDesc, meth);
             LOG_VFY("VFY: unable to resolve filled-array %d (%s) in %s\n",
                 decInsn.vB, badClassDesc, meth->clazz->descriptor);
-            okay = false;
+            assert(failure != VERIFY_ERROR_GENERIC);
         } else if (!dvmIsArrayClass(resClass)) {
             LOG_VFY("VFY: filled-new-array on non-array class\n");
-            okay = false;
+            failure = VERIFY_ERROR_GENERIC;
         } else {
             bool isRange = (decInsn.opCode == OP_FILLED_NEW_ARRAY_RANGE);
 
             /* check the arguments to the instruction */
             verifyFilledNewArrayRegs(meth, workRegs, insnRegCount, &decInsn,
-                resClass, isRange, &okay);
+                resClass, isRange, &failure);
             /* filled-array result goes into "result" register */
             setResultRegisterType(workRegs, insnRegCount,
-                regTypeFromClass(resClass), &okay);
+                regTypeFromClass(resClass), &failure);
             justSetResult = true;
         }
         break;
@@ -3592,38 +3881,38 @@
     case OP_CMPL_FLOAT:
     case OP_CMPG_FLOAT:
         verifyRegisterType(workRegs, insnRegCount, decInsn.vB, kRegTypeFloat,
-            &okay);
+            &failure);
         verifyRegisterType(workRegs, insnRegCount, decInsn.vC, kRegTypeFloat,
-            &okay);
+            &failure);
         setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeBoolean,
-            &okay);
+            &failure);
         break;
     case OP_CMPL_DOUBLE:
     case OP_CMPG_DOUBLE:
         verifyRegisterType(workRegs, insnRegCount, decInsn.vB, kRegTypeDoubleLo,
-            &okay);
+            &failure);
         verifyRegisterType(workRegs, insnRegCount, decInsn.vC, kRegTypeDoubleLo,
-            &okay);
+            &failure);
         setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeBoolean,
-            &okay);
+            &failure);
         break;
     case OP_CMP_LONG:
         verifyRegisterType(workRegs, insnRegCount, decInsn.vB, kRegTypeLongLo,
-            &okay);
+            &failure);
         verifyRegisterType(workRegs, insnRegCount, decInsn.vC, kRegTypeLongLo,
-            &okay);
+            &failure);
         setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeBoolean,
-            &okay);
+            &failure);
         break;
 
     case OP_THROW:
         resClass = getClassFromRegister(workRegs, insnRegCount,
-                        decInsn.vA, &okay);
-        if (okay && resClass != NULL) {
+                        decInsn.vA, &failure);
+        if (VERIFY_OK(failure) && resClass != NULL) {
             if (!dvmInstanceof(resClass, gDvm.classJavaLangThrowable)) {
                 LOG_VFY("VFY: thrown class %s not instanceof Throwable\n",
                         resClass->descriptor);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
             }
         }
         break;
@@ -3638,7 +3927,7 @@
     case OP_SPARSE_SWITCH:
         /* verify that vAA is an integer, or can be converted to one */
         verifyRegisterType(workRegs, insnRegCount, decInsn.vA,
-            kRegTypeInteger, &okay);
+            kRegTypeInteger, &failure);
         break;
 
     case OP_FILL_ARRAY_DATA:
@@ -3649,8 +3938,8 @@
 
             /* Similar to the verification done for APUT */
             resClass = getClassFromRegister(workRegs, insnRegCount,
-                            decInsn.vA, &okay);
-            if (!okay)
+                            decInsn.vA, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             /* resClass can be null if the reg type is Zero */
@@ -3663,7 +3952,7 @@
             {
                 LOG_VFY("VFY: invalid fill-array-data on %s\n",
                         resClass->descriptor);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
 
@@ -3678,7 +3967,7 @@
             arrayData = insns + (insns[1] | (((s4)insns[2]) << 16));
             if (arrayData[0] != kArrayDataSignature) {
                 LOG_VFY("VFY: invalid magic for array-data\n");
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
 
@@ -3712,7 +4001,7 @@
             if (arrayData[1] != elemWidth) {
                 LOG_VFY("VFY: array-data size mismatch (%d vs %d)\n",
                         arrayData[1], elemWidth);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
             }
         }
         break;
@@ -3723,9 +4012,11 @@
             RegType type1, type2;
             bool tmpResult;
 
-            type1 = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
-            type2 = getRegisterType(workRegs, insnRegCount, decInsn.vB, &okay);
-            if (!okay)
+            type1 = getRegisterType(workRegs, insnRegCount, decInsn.vA,
+                        &failure);
+            type2 = getRegisterType(workRegs, insnRegCount, decInsn.vB,
+                        &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             /* both references? */
@@ -3733,9 +4024,9 @@
                 break;
 
             /* both category-1nr? */
-            checkTypeCategory(type1, kTypeCategory1nr, &okay);
-            checkTypeCategory(type2, kTypeCategory1nr, &okay);
-            if (!okay) {
+            checkTypeCategory(type1, kTypeCategory1nr, &failure);
+            checkTypeCategory(type2, kTypeCategory1nr, &failure);
+            if (!VERIFY_OK(failure)) {
                 LOG_VFY("VFY: args to if-eq/if-ne must both be refs or cat1\n");
                 break;
             }
@@ -3745,43 +4036,43 @@
     case OP_IF_GE:
     case OP_IF_GT:
     case OP_IF_LE:
-        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
-        if (!okay)
+        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
+        if (!VERIFY_OK(failure))
             break;
-        checkTypeCategory(tmpType, kTypeCategory1nr, &okay);
-        if (!okay) {
+        checkTypeCategory(tmpType, kTypeCategory1nr, &failure);
+        if (!VERIFY_OK(failure)) {
             LOG_VFY("VFY: args to 'if' must be cat-1nr\n");
             break;
         }
-        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vB,&okay);
-        if (!okay)
+        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vB, &failure);
+        if (!VERIFY_OK(failure))
             break;
-        checkTypeCategory(tmpType, kTypeCategory1nr, &okay);
-        if (!okay) {
+        checkTypeCategory(tmpType, kTypeCategory1nr, &failure);
+        if (!VERIFY_OK(failure)) {
             LOG_VFY("VFY: args to 'if' must be cat-1nr\n");
             break;
         }
         break;
     case OP_IF_EQZ:
     case OP_IF_NEZ:
-        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
-        if (!okay)
+        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
+        if (!VERIFY_OK(failure))
             break;
         if (regTypeIsReference(tmpType))
             break;
-        checkTypeCategory(tmpType, kTypeCategory1nr, &okay);
-        if (!okay)
+        checkTypeCategory(tmpType, kTypeCategory1nr, &failure);
+        if (!VERIFY_OK(failure))
             LOG_VFY("VFY: expected cat-1 arg to if\n");
         break;
     case OP_IF_LTZ:
     case OP_IF_GEZ:
     case OP_IF_GTZ:
     case OP_IF_LEZ:
-        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
-        if (!okay)
+        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
+        if (!VERIFY_OK(failure))
             break;
-        checkTypeCategory(tmpType, kTypeCategory1nr, &okay);
-        if (!okay)
+        checkTypeCategory(tmpType, kTypeCategory1nr, &failure);
+        if (!VERIFY_OK(failure))
             LOG_VFY("VFY: expected cat-1 arg to if\n");
         break;
 
@@ -3805,14 +4096,14 @@
             RegType srcType, indexType;
 
             indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
-                            &okay);
-            checkArrayIndexType(meth, indexType, &okay);
-            if (!okay)
+                            &failure);
+            checkArrayIndexType(meth, indexType, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             resClass = getClassFromRegister(workRegs, insnRegCount,
-                            decInsn.vB, &okay);
-            if (!okay)
+                            decInsn.vB, &failure);
+            if (!VERIFY_OK(failure))
                 break;
             if (resClass != NULL) {
                 /* verify the class */
@@ -3821,7 +4112,7 @@
                 {
                     LOG_VFY("VFY: invalid aget-1nr target %s\n",
                         resClass->descriptor);
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
 
@@ -3833,13 +4124,13 @@
                     LOG_VFY("VFY: invalid aget-1nr, array type=%d with"
                             " inst type=%d (on %s)\n",
                         srcType, tmpType, resClass->descriptor);
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
 
             }
             setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                tmpType, &okay);
+                tmpType, &failure);
         }
         break;
 
@@ -3848,14 +4139,14 @@
             RegType dstType, indexType;
 
             indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
-                            &okay);
-            checkArrayIndexType(meth, indexType, &okay);
-            if (!okay)
+                            &failure);
+            checkArrayIndexType(meth, indexType, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             resClass = getClassFromRegister(workRegs, insnRegCount,
-                            decInsn.vB, &okay);
-            if (!okay)
+                            decInsn.vB, &failure);
+            if (!VERIFY_OK(failure))
                 break;
             if (resClass != NULL) {
                 /* verify the class */
@@ -3864,7 +4155,7 @@
                 {
                     LOG_VFY("VFY: invalid aget-wide target %s\n",
                         resClass->descriptor);
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
 
@@ -3880,7 +4171,7 @@
                     LOG_VFY("VFY: invalid aget-wide on %s\n",
                         resClass->descriptor);
                     dstType = kRegTypeUnknown;
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
             } else {
@@ -3893,7 +4184,7 @@
                 dstType = kRegTypeLongLo;
             }
             setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                dstType, &okay);
+                dstType, &failure);
         }
         break;
 
@@ -3902,15 +4193,15 @@
             RegType dstType, indexType;
 
             indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
-                            &okay);
-            checkArrayIndexType(meth, indexType, &okay);
-            if (!okay)
+                            &failure);
+            checkArrayIndexType(meth, indexType, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             /* get the class of the array we're pulling an object from */
             resClass = getClassFromRegister(workRegs, insnRegCount,
-                            decInsn.vB, &okay);
-            if (!okay)
+                            decInsn.vB, &failure);
+            if (!VERIFY_OK(failure))
                 break;
             if (resClass != NULL) {
                 ClassObject* elementClass;
@@ -3918,7 +4209,7 @@
                 assert(resClass != NULL);
                 if (!dvmIsArrayClass(resClass)) {
                     LOG_VFY("VFY: aget-object on non-array class\n");
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
                 assert(resClass->elementClass != NULL);
@@ -3938,7 +4229,7 @@
                 } else {
                     LOG_VFY("VFY: aget-object on non-ref array class (%s)\n",
                         resClass->descriptor);
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
 
@@ -3954,7 +4245,7 @@
                 dstType = kRegTypeZero;
             }
             setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                dstType, &okay);
+                dstType, &failure);
         }
         break;
     case OP_APUT:
@@ -3977,24 +4268,24 @@
             RegType srcType, dstType, indexType;
 
             indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
-                            &okay);
-            checkArrayIndexType(meth, indexType, &okay);
-            if (!okay)
+                            &failure);
+            checkArrayIndexType(meth, indexType, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             /* make sure the source register has the correct type */
             srcType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
-                            &okay);
+                            &failure);
             if (!canConvertTo1nr(srcType, tmpType)) {
                 LOG_VFY("VFY: invalid reg type %d on aput instr (need %d)\n",
                     srcType, tmpType);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
 
             resClass = getClassFromRegister(workRegs, insnRegCount,
-                            decInsn.vB, &okay);
-            if (!okay)
+                            decInsn.vB, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             /* resClass can be null if the reg type is Zero */
@@ -4005,7 +4296,7 @@
                 resClass->elementClass->primitiveType == PRIM_NOT)
             {
                 LOG_VFY("VFY: invalid aput-1nr on %s\n", resClass->descriptor);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
 
@@ -4017,31 +4308,31 @@
             if (!checkFieldArrayStore1nr(tmpType, dstType)) {
                 LOG_VFY("VFY: invalid aput-1nr on %s (inst=%d dst=%d)\n",
                         resClass->descriptor, tmpType, dstType);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
         }
         break;
     case OP_APUT_WIDE:
         tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
-                        &okay);
-        checkArrayIndexType(meth, tmpType, &okay);
-        if (!okay)
+                        &failure);
+        checkArrayIndexType(meth, tmpType, &failure);
+        if (!VERIFY_OK(failure))
             break;
 
-        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
-        if (okay) {
+        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
+        if (VERIFY_OK(failure)) {
             RegType typeHi =
-                getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &okay);
-            checkTypeCategory(tmpType, kTypeCategory2, &okay);
-            checkWidePair(tmpType, typeHi, &okay);
+                getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &failure);
+            checkTypeCategory(tmpType, kTypeCategory2, &failure);
+            checkWidePair(tmpType, typeHi, &failure);
         }
-        if (!okay)
+        if (!VERIFY_OK(failure))
             break;
 
         resClass = getClassFromRegister(workRegs, insnRegCount,
-                        decInsn.vB, &okay);
-        if (!okay)
+                        decInsn.vB, &failure);
+        if (!VERIFY_OK(failure))
             break;
         if (resClass != NULL) {
             /* verify the class and try to refine "dstType" */
@@ -4050,7 +4341,7 @@
             {
                 LOG_VFY("VFY: invalid aput-wide on %s\n",
                         resClass->descriptor);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
 
@@ -4062,22 +4353,22 @@
             default:
                 LOG_VFY("VFY: invalid aput-wide on %s\n",
                         resClass->descriptor);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
         }
         break;
     case OP_APUT_OBJECT:
         tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
-                        &okay);
-        checkArrayIndexType(meth, tmpType, &okay);
-        if (!okay)
+                        &failure);
+        checkArrayIndexType(meth, tmpType, &failure);
+        if (!VERIFY_OK(failure))
             break;
 
         /* get the ref we're storing; Zero is okay, Uninit is not */
         resClass = getClassFromRegister(workRegs, insnRegCount,
-                        decInsn.vA, &okay);
-        if (!okay)
+                        decInsn.vA, &failure);
+        if (!VERIFY_OK(failure))
             break;
         if (resClass != NULL) {
             ClassObject* arrayClass;
@@ -4089,14 +4380,14 @@
              * null pointer exception).
              */
             arrayClass = getClassFromRegister(workRegs, insnRegCount,
-                            decInsn.vB, &okay);
+                            decInsn.vB, &failure);
 
             if (arrayClass != NULL) {
                 /* see if the array holds a compatible type */
                 if (!dvmIsArrayClass(arrayClass)) {
                     LOG_VFY("VFY: invalid aput-object on %s\n",
                             arrayClass->descriptor);
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
 
@@ -4121,7 +4412,7 @@
                 if (elementClass->primitiveType != PRIM_NOT) {
                     LOG_VFY("VFY: invalid aput-object of %s into %s\n",
                             resClass->descriptor, arrayClass->descriptor);
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
             }
@@ -4150,12 +4441,12 @@
             RegType objType, fieldType;
 
             objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
-                        &okay);
-            if (!okay)
+                        &failure);
+            if (!VERIFY_OK(failure))
                 break;
             instField = getInstField(meth, uninitMap, objType, decInsn.vC,
-                            &okay);
-            if (!okay)
+                            &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             /* make sure the field's type is compatible with expectation */
@@ -4166,11 +4457,12 @@
                 LOG_VFY("VFY: invalid iget-1nr of %s.%s (inst=%d field=%d)\n",
                         instField->field.clazz->descriptor,
                         instField->field.name, tmpType, fieldType);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
 
-            setRegisterType(workRegs, insnRegCount, decInsn.vA, tmpType, &okay);
+            setRegisterType(workRegs, insnRegCount, decInsn.vA, tmpType,
+                &failure);
         }
         break;
     case OP_IGET_WIDE:
@@ -4181,12 +4473,12 @@
             RegType objType;
 
             objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
-                        &okay);
-            if (!okay)
+                        &failure);
+            if (!VERIFY_OK(failure))
                 break;
             instField = getInstField(meth, uninitMap, objType, decInsn.vC,
-                            &okay);
-            if (!okay)
+                            &failure);
+            if (!VERIFY_OK(failure))
                 break;
             /* check the type, which should be prim */
             switch (instField->field.signature[0]) {
@@ -4201,12 +4493,12 @@
                         instField->field.clazz->descriptor,
                         instField->field.name);
                 dstType = kRegTypeUnknown;
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
-            if (okay) {
+            if (VERIFY_OK(failure)) {
                 setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                    dstType, &okay);
+                    dstType, &failure);
             }
         }
         break;
@@ -4217,25 +4509,25 @@
             RegType objType;
 
             objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
-                        &okay);
-            if (!okay)
+                        &failure);
+            if (!VERIFY_OK(failure))
                 break;
             instField = getInstField(meth, uninitMap, objType, decInsn.vC,
-                            &okay);
-            if (!okay)
+                            &failure);
+            if (!VERIFY_OK(failure))
                 break;
             fieldClass = getFieldClass(meth, &instField->field);
             if (fieldClass == NULL) {
                 /* class not found or primitive type */
                 LOG_VFY("VFY: unable to recover field class from '%s'\n",
                     instField->field.signature);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
-            if (okay) {
+            if (VERIFY_OK(failure)) {
                 assert(!dvmIsPrimitiveClass(fieldClass));
                 setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                    regTypeFromClass(fieldClass), &okay);
+                    regTypeFromClass(fieldClass), &failure);
             }
         }
         break;
@@ -4260,26 +4552,34 @@
             ClassObject* fieldClass;
             InstField* instField;
 
-            /* make sure the source register has the correct type */
             srcType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
-                        &okay);
+                        &failure);
+
+            /*
+             * javac generates synthetic functions that write byte values
+             * into boolean fields.
+             */
+            if (tmpType == kRegTypeBoolean && srcType == kRegTypeByte)
+                srcType = kRegTypeBoolean;
+
+            /* make sure the source register has the correct type */
             if (!canConvertTo1nr(srcType, tmpType)) {
                 LOG_VFY("VFY: invalid reg type %d on iput instr (need %d)\n",
                     srcType, tmpType);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
 
             objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
-                        &okay);
-            if (!okay)
+                        &failure);
+            if (!VERIFY_OK(failure))
                 break;
             instField = getInstField(meth, uninitMap, objType, decInsn.vC,
-                            &okay);
-            if (!okay)
+                            &failure);
+            if (!VERIFY_OK(failure))
                 break;
-            checkFinalFieldAccess(meth, &instField->field, &okay);
-            if (!okay)
+            checkFinalFieldAccess(meth, &instField->field, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             /* get type of field we're storing into */
@@ -4290,34 +4590,34 @@
                 LOG_VFY("VFY: invalid iput-1nr of %s.%s (inst=%d field=%d)\n",
                         instField->field.clazz->descriptor,
                         instField->field.name, tmpType, fieldType);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
         }
         break;
     case OP_IPUT_WIDE:
-        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
-        if (okay) {
+        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
+        if (VERIFY_OK(failure)) {
             RegType typeHi =
-                getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &okay);
-            checkTypeCategory(tmpType, kTypeCategory2, &okay);
-            checkWidePair(tmpType, typeHi, &okay);
+                getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &failure);
+            checkTypeCategory(tmpType, kTypeCategory2, &failure);
+            checkWidePair(tmpType, typeHi, &failure);
         }
-        if (okay) {
+        if (VERIFY_OK(failure)) {
             ClassObject* fieldClass;
             InstField* instField;
             RegType objType;
 
             objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
-                        &okay);
-            if (!okay)
+                        &failure);
+            if (!VERIFY_OK(failure))
                 break;
             instField = getInstField(meth, uninitMap, objType, decInsn.vC,
-                            &okay);
-            if (!okay)
+                            &failure);
+            if (!VERIFY_OK(failure))
                 break;
-            checkFinalFieldAccess(meth, &instField->field, &okay);
-            if (!okay)
+            checkFinalFieldAccess(meth, &instField->field, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             /* check the type, which should be prim */
@@ -4330,7 +4630,7 @@
                 LOG_VFY("VFY: invalid iput-wide of %s.%s\n",
                         instField->field.clazz->descriptor,
                         instField->field.name);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
         }
@@ -4343,34 +4643,34 @@
             RegType objType, valueType;
 
             objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
-                        &okay);
-            if (!okay)
+                        &failure);
+            if (!VERIFY_OK(failure))
                 break;
             instField = getInstField(meth, uninitMap, objType, decInsn.vC,
-                            &okay);
-            if (!okay)
+                            &failure);
+            if (!VERIFY_OK(failure))
                 break;
-            checkFinalFieldAccess(meth, &instField->field, &okay);
-            if (!okay)
+            checkFinalFieldAccess(meth, &instField->field, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             fieldClass = getFieldClass(meth, &instField->field);
             if (fieldClass == NULL) {
                 LOG_VFY("VFY: unable to recover field class from '%s'\n",
                     instField->field.signature);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
 
             valueType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
-                        &okay);
-            if (!okay)
+                        &failure);
+            if (!VERIFY_OK(failure))
                 break;
             if (!regTypeIsReference(valueType)) {
                 LOG_VFY("VFY: storing non-ref v%d into ref field '%s' (%s)\n",
                         decInsn.vA, instField->field.name,
                         fieldClass->descriptor);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
             if (valueType != kRegTypeZero) {
@@ -4378,7 +4678,7 @@
                 if (valueClass == NULL) {
                     LOG_VFY("VFY: storing uninit ref v%d into ref field\n",
                         decInsn.vA);
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
                 /* allow if field is any interface or field is base class */
@@ -4389,7 +4689,7 @@
                             valueClass->descriptor, fieldClass->descriptor,
                             instField->field.clazz->descriptor,
                             instField->field.name);
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
             }
@@ -4416,8 +4716,8 @@
             StaticField* staticField;
             RegType fieldType;
 
-            staticField = getStaticField(meth, decInsn.vB, &okay);
-            if (!okay)
+            staticField = getStaticField(meth, decInsn.vB, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             /*
@@ -4433,11 +4733,12 @@
                 LOG_VFY("VFY: invalid sget-1nr of %s.%s (inst=%d actual=%d)\n",
                     staticField->field.clazz->descriptor,
                     staticField->field.name, tmpType, fieldType);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
 
-            setRegisterType(workRegs, insnRegCount, decInsn.vA, tmpType, &okay);
+            setRegisterType(workRegs, insnRegCount, decInsn.vA, tmpType,
+                &failure);
         }
         break;
     case OP_SGET_WIDE:
@@ -4445,8 +4746,8 @@
             StaticField* staticField;
             RegType dstType;
 
-            staticField = getStaticField(meth, decInsn.vB, &okay);
-            if (!okay)
+            staticField = getStaticField(meth, decInsn.vB, &failure);
+            if (!VERIFY_OK(failure))
                 break;
             /* check the type, which should be prim */
             switch (staticField->field.signature[0]) {
@@ -4461,12 +4762,12 @@
                         staticField->field.clazz->descriptor,
                         staticField->field.name);
                 dstType = kRegTypeUnknown;
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
-            if (okay) {
+            if (VERIFY_OK(failure)) {
                 setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                    dstType, &okay);
+                    dstType, &failure);
             }
         }
         break;
@@ -4475,23 +4776,23 @@
             StaticField* staticField;
             ClassObject* fieldClass;
 
-            staticField = getStaticField(meth, decInsn.vB, &okay);
-            if (!okay)
+            staticField = getStaticField(meth, decInsn.vB, &failure);
+            if (!VERIFY_OK(failure))
                 break;
             fieldClass = getFieldClass(meth, &staticField->field);
             if (fieldClass == NULL) {
                 LOG_VFY("VFY: unable to recover field class from '%s'\n",
                     staticField->field.signature);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
             if (dvmIsPrimitiveClass(fieldClass)) {
                 LOG_VFY("VFY: attempt to get prim field with sget-object\n");
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
             setRegisterType(workRegs, insnRegCount, decInsn.vA,
-                regTypeFromClass(fieldClass), &okay);
+                regTypeFromClass(fieldClass), &failure);
         }
         break;
     case OP_SPUT:
@@ -4514,21 +4815,29 @@
             RegType srcType, fieldType;
             StaticField* staticField;
 
-            /* make sure the source register has the correct type */
             srcType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
-                        &okay);
+                        &failure);
+
+            /*
+             * javac generates synthetic functions that write byte values
+             * into boolean fields.
+             */
+            if (tmpType == kRegTypeBoolean && srcType == kRegTypeByte)
+                srcType = kRegTypeBoolean;
+
+            /* make sure the source register has the correct type */
             if (!canConvertTo1nr(srcType, tmpType)) {
-                LOG_VFY("VFY: invalid reg type %d on iput instr (need %d)\n",
+                LOG_VFY("VFY: invalid reg type %d on sput instr (need %d)\n",
                     srcType, tmpType);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
 
-            staticField = getStaticField(meth, decInsn.vB, &okay);
-            if (!okay)
+            staticField = getStaticField(meth, decInsn.vB, &failure);
+            if (!VERIFY_OK(failure))
                 break;
-            checkFinalFieldAccess(meth, &staticField->field, &okay);
-            if (!okay)
+            checkFinalFieldAccess(meth, &staticField->field, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             /*
@@ -4543,27 +4852,27 @@
                 LOG_VFY("VFY: invalid sput-1nr of %s.%s (inst=%d actual=%d)\n",
                     staticField->field.clazz->descriptor,
                     staticField->field.name, tmpType, fieldType);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
         }
         break;
     case OP_SPUT_WIDE:
-        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &okay);
-        if (okay) {
+        tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
+        if (VERIFY_OK(failure)) {
             RegType typeHi =
-                getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &okay);
-            checkTypeCategory(tmpType, kTypeCategory2, &okay);
-            checkWidePair(tmpType, typeHi, &okay);
+                getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &failure);
+            checkTypeCategory(tmpType, kTypeCategory2, &failure);
+            checkWidePair(tmpType, typeHi, &failure);
         }
-        if (okay) {
+        if (VERIFY_OK(failure)) {
             StaticField* staticField;
 
-            staticField = getStaticField(meth, decInsn.vB, &okay);
-            if (!okay)
+            staticField = getStaticField(meth, decInsn.vB, &failure);
+            if (!VERIFY_OK(failure))
                 break;
-            checkFinalFieldAccess(meth, &staticField->field, &okay);
-            if (!okay)
+            checkFinalFieldAccess(meth, &staticField->field, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             /* check the type, which should be prim */
@@ -4576,7 +4885,7 @@
                 LOG_VFY("VFY: invalid sput-wide of %s.%s\n",
                         staticField->field.clazz->descriptor,
                         staticField->field.name);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
         }
@@ -4588,30 +4897,30 @@
             StaticField* staticField;
             RegType valueType;
 
-            staticField = getStaticField(meth, decInsn.vB, &okay);
-            if (!okay)
+            staticField = getStaticField(meth, decInsn.vB, &failure);
+            if (!VERIFY_OK(failure))
                 break;
-            checkFinalFieldAccess(meth, &staticField->field, &okay);
-            if (!okay)
+            checkFinalFieldAccess(meth, &staticField->field, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             fieldClass = getFieldClass(meth, &staticField->field);
             if (fieldClass == NULL) {
                 LOG_VFY("VFY: unable to recover field class from '%s'\n",
                     staticField->field.signature);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
 
             valueType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
-                        &okay);
-            if (!okay)
+                        &failure);
+            if (!VERIFY_OK(failure))
                 break;
             if (!regTypeIsReference(valueType)) {
                 LOG_VFY("VFY: storing non-ref v%d into ref field '%s' (%s)\n",
                         decInsn.vA, staticField->field.name,
                         fieldClass->descriptor);
-                okay = false;
+                failure = VERIFY_ERROR_GENERIC;
                 break;
             }
             if (valueType != kRegTypeZero) {
@@ -4619,7 +4928,7 @@
                 if (valueClass == NULL) {
                     LOG_VFY("VFY: storing uninit ref v%d into ref field\n",
                         decInsn.vA);
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
                 /* allow if field is any interface or field is base class */
@@ -4630,7 +4939,7 @@
                             valueClass->descriptor, fieldClass->descriptor,
                             staticField->field.clazz->descriptor,
                             staticField->field.name);
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
             }
@@ -4654,11 +4963,11 @@
 
             calledMethod = verifyInvocationArgs(meth, workRegs, insnRegCount,
                             &decInsn, uninitMap, METHOD_VIRTUAL, isRange,
-                            isSuper, &okay);
-            if (!okay)
+                            isSuper, &failure);
+            if (!VERIFY_OK(failure))
                 break;
             returnType = getMethodReturnType(calledMethod);
-            setResultRegisterType(workRegs, insnRegCount, returnType, &okay);
+            setResultRegisterType(workRegs, insnRegCount, returnType, &failure);
             justSetResult = true;
         }
         break;
@@ -4672,8 +4981,8 @@
             isRange =  (decInsn.opCode == OP_INVOKE_DIRECT_RANGE);
             calledMethod = verifyInvocationArgs(meth, workRegs, insnRegCount,
                             &decInsn, uninitMap, METHOD_DIRECT, isRange,
-                            false, &okay);
-            if (!okay)
+                            false, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             /*
@@ -4688,14 +4997,14 @@
             if (isInitMethod(calledMethod)) {
                 RegType thisType;
                 thisType = getInvocationThis(workRegs, insnRegCount,
-                            &decInsn, &okay);
-                if (!okay)
+                            &decInsn, &failure);
+                if (!VERIFY_OK(failure))
                     break;
 
                 /* no null refs allowed (?) */
                 if (thisType == kRegTypeZero) {
                     LOG_VFY("VFY: unable to initialize null ref\n");
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
 
@@ -4709,20 +5018,20 @@
                     if (thisClass != meth->clazz) {
                         LOG_VFY("VFY: invoke-direct <init> on super only "
                             "allowed for 'this' in <init>");
-                        okay = false;
+                        failure = VERIFY_ERROR_GENERIC;
                         break;
                     }
                 }  else if (calledMethod->clazz != thisClass) {
                     LOG_VFY("VFY: invoke-direct <init> must be on current "
                             "class or super\n");
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
 
                 /* arg must be an uninitialized reference */
                 if (!regTypeIsUninitReference(thisType)) {
                     LOG_VFY("VFY: can only initialize the uninitialized\n");
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
 
@@ -4734,13 +5043,13 @@
                  */
                 int uidx = regTypeToUninitIndex(thisType);
                 markRefsAsInitialized(workRegs, insnRegCount, uninitMap,
-                    thisType, &okay);
-                if (!okay)
+                    thisType, &failure);
+                if (!VERIFY_OK(failure))
                     break;
             }
             returnType = getMethodReturnType(calledMethod);
             setResultRegisterType(workRegs, insnRegCount,
-                returnType, &okay);
+                returnType, &failure);
             justSetResult = true;
         }
         break;
@@ -4754,12 +5063,12 @@
             isRange =  (decInsn.opCode == OP_INVOKE_STATIC_RANGE);
             calledMethod = verifyInvocationArgs(meth, workRegs, insnRegCount,
                             &decInsn, uninitMap, METHOD_STATIC, isRange,
-                            false, &okay);
-            if (!okay)
+                            false, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             returnType = getMethodReturnType(calledMethod);
-            setResultRegisterType(workRegs, insnRegCount, returnType, &okay);
+            setResultRegisterType(workRegs, insnRegCount, returnType, &failure);
             justSetResult = true;
         }
         break;
@@ -4773,8 +5082,8 @@
             isRange =  (decInsn.opCode == OP_INVOKE_INTERFACE_RANGE);
             absMethod = verifyInvocationArgs(meth, workRegs, insnRegCount,
                             &decInsn, uninitMap, METHOD_INTERFACE, isRange,
-                            false, &okay);
-            if (!okay)
+                            false, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
 #if 0       /* can't do this here, fails on dalvik test 052-verifier-fun */
@@ -4784,8 +5093,8 @@
              * interface classes, this might have reduced to Object.
              */
             thisType = getInvocationThis(workRegs, insnRegCount,
-                        &decInsn, &okay);
-            if (!okay)
+                        &decInsn, &failure);
+            if (!VERIFY_OK(failure))
                 break;
 
             if (thisType == kRegTypeZero) {
@@ -4796,7 +5105,7 @@
                 thisClass = regTypeInitializedReferenceToClass(thisType);
                 if (thisClass == NULL) {
                     LOG_VFY("VFY: interface call on uninitialized\n");
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
 
@@ -4812,7 +5121,7 @@
                 {
                     LOG_VFY("VFY: unable to match absMethod '%s' with %s interfaces\n",
                             absMethod->name, thisClass->descriptor);
-                    okay = false;
+                    failure = VERIFY_ERROR_GENERIC;
                     break;
                 }
             }
@@ -4824,7 +5133,7 @@
              * in the abstract method, so we're good.
              */
             returnType = getMethodReturnType(absMethod);
-            setResultRegisterType(workRegs, insnRegCount, returnType, &okay);
+            setResultRegisterType(workRegs, insnRegCount, returnType, &failure);
             justSetResult = true;
         }
         break;
@@ -4832,80 +5141,80 @@
     case OP_NEG_INT:
     case OP_NOT_INT:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeInteger, kRegTypeInteger, &okay);
+            kRegTypeInteger, kRegTypeInteger, &failure);
         break;
     case OP_NEG_LONG:
     case OP_NOT_LONG:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeLongLo, kRegTypeLongLo, &okay);
+            kRegTypeLongLo, kRegTypeLongLo, &failure);
         break;
     case OP_NEG_FLOAT:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeFloat, kRegTypeFloat, &okay);
+            kRegTypeFloat, kRegTypeFloat, &failure);
         break;
     case OP_NEG_DOUBLE:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeDoubleLo, kRegTypeDoubleLo, &okay);
+            kRegTypeDoubleLo, kRegTypeDoubleLo, &failure);
         break;
     case OP_INT_TO_LONG:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeLongLo, kRegTypeInteger, &okay);
+            kRegTypeLongLo, kRegTypeInteger, &failure);
         break;
     case OP_INT_TO_FLOAT:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeFloat, kRegTypeInteger, &okay);
+            kRegTypeFloat, kRegTypeInteger, &failure);
         break;
     case OP_INT_TO_DOUBLE:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeDoubleLo, kRegTypeInteger, &okay);
+            kRegTypeDoubleLo, kRegTypeInteger, &failure);
         break;
     case OP_LONG_TO_INT:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeInteger, kRegTypeLongLo, &okay);
+            kRegTypeInteger, kRegTypeLongLo, &failure);
         break;
     case OP_LONG_TO_FLOAT:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeFloat, kRegTypeLongLo, &okay);
+            kRegTypeFloat, kRegTypeLongLo, &failure);
         break;
     case OP_LONG_TO_DOUBLE:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeDoubleLo, kRegTypeLongLo, &okay);
+            kRegTypeDoubleLo, kRegTypeLongLo, &failure);
         break;
     case OP_FLOAT_TO_INT:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeInteger, kRegTypeFloat, &okay);
+            kRegTypeInteger, kRegTypeFloat, &failure);
         break;
     case OP_FLOAT_TO_LONG:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeLongLo, kRegTypeFloat, &okay);
+            kRegTypeLongLo, kRegTypeFloat, &failure);
         break;
     case OP_FLOAT_TO_DOUBLE:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeDoubleLo, kRegTypeFloat, &okay);
+            kRegTypeDoubleLo, kRegTypeFloat, &failure);
         break;
     case OP_DOUBLE_TO_INT:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeInteger, kRegTypeDoubleLo, &okay);
+            kRegTypeInteger, kRegTypeDoubleLo, &failure);
         break;
     case OP_DOUBLE_TO_LONG:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeLongLo, kRegTypeDoubleLo, &okay);
+            kRegTypeLongLo, kRegTypeDoubleLo, &failure);
         break;
     case OP_DOUBLE_TO_FLOAT:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeFloat, kRegTypeDoubleLo, &okay);
+            kRegTypeFloat, kRegTypeDoubleLo, &failure);
         break;
     case OP_INT_TO_BYTE:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeByte, kRegTypeInteger, &okay);
+            kRegTypeByte, kRegTypeInteger, &failure);
         break;
     case OP_INT_TO_CHAR:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeChar, kRegTypeInteger, &okay);
+            kRegTypeChar, kRegTypeInteger, &failure);
         break;
     case OP_INT_TO_SHORT:
         checkUnop(workRegs, insnRegCount, &decInsn,
-            kRegTypeShort, kRegTypeInteger, &okay);
+            kRegTypeShort, kRegTypeInteger, &failure);
         break;
 
     case OP_ADD_INT:
@@ -4917,13 +5226,13 @@
     case OP_SHR_INT:
     case OP_USHR_INT:
         checkBinop(workRegs, insnRegCount, &decInsn,
-            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &okay);
+            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &failure);
         break;
     case OP_AND_INT:
     case OP_OR_INT:
     case OP_XOR_INT:
         checkBinop(workRegs, insnRegCount, &decInsn,
-            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, true, &okay);
+            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, true, &failure);
         break;
     case OP_ADD_LONG:
     case OP_SUB_LONG:
@@ -4934,14 +5243,14 @@
     case OP_OR_LONG:
     case OP_XOR_LONG:
         checkBinop(workRegs, insnRegCount, &decInsn,
-            kRegTypeLongLo, kRegTypeLongLo, kRegTypeLongLo, false, &okay);
+            kRegTypeLongLo, kRegTypeLongLo, kRegTypeLongLo, false, &failure);
         break;
     case OP_SHL_LONG:
     case OP_SHR_LONG:
     case OP_USHR_LONG:
         /* shift distance is Int, making these different from other binops */
         checkBinop(workRegs, insnRegCount, &decInsn,
-            kRegTypeLongLo, kRegTypeLongLo, kRegTypeInteger, false, &okay);
+            kRegTypeLongLo, kRegTypeLongLo, kRegTypeInteger, false, &failure);
         break;
     case OP_ADD_FLOAT:
     case OP_SUB_FLOAT:
@@ -4949,7 +5258,7 @@
     case OP_DIV_FLOAT:
     case OP_REM_FLOAT:
         checkBinop(workRegs, insnRegCount, &decInsn,
-            kRegTypeFloat, kRegTypeFloat, kRegTypeFloat, false, &okay);
+            kRegTypeFloat, kRegTypeFloat, kRegTypeFloat, false, &failure);
         break;
     case OP_ADD_DOUBLE:
     case OP_SUB_DOUBLE:
@@ -4957,7 +5266,8 @@
     case OP_DIV_DOUBLE:
     case OP_REM_DOUBLE:
         checkBinop(workRegs, insnRegCount, &decInsn,
-            kRegTypeDoubleLo, kRegTypeDoubleLo, kRegTypeDoubleLo, false, &okay);
+            kRegTypeDoubleLo, kRegTypeDoubleLo, kRegTypeDoubleLo, false,
+            &failure);
         break;
     case OP_ADD_INT_2ADDR:
     case OP_SUB_INT_2ADDR:
@@ -4967,17 +5277,17 @@
     case OP_SHR_INT_2ADDR:
     case OP_USHR_INT_2ADDR:
         checkBinop2addr(workRegs, insnRegCount, &decInsn,
-            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &okay);
+            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &failure);
         break;
     case OP_AND_INT_2ADDR:
     case OP_OR_INT_2ADDR:
     case OP_XOR_INT_2ADDR:
         checkBinop2addr(workRegs, insnRegCount, &decInsn,
-            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, true, &okay);
+            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, true, &failure);
         break;
     case OP_DIV_INT_2ADDR:
         checkBinop2addr(workRegs, insnRegCount, &decInsn,
-            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &okay);
+            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &failure);
         break;
     case OP_ADD_LONG_2ADDR:
     case OP_SUB_LONG_2ADDR:
@@ -4988,13 +5298,13 @@
     case OP_OR_LONG_2ADDR:
     case OP_XOR_LONG_2ADDR:
         checkBinop2addr(workRegs, insnRegCount, &decInsn,
-            kRegTypeLongLo, kRegTypeLongLo, kRegTypeLongLo, false, &okay);
+            kRegTypeLongLo, kRegTypeLongLo, kRegTypeLongLo, false, &failure);
         break;
     case OP_SHL_LONG_2ADDR:
     case OP_SHR_LONG_2ADDR:
     case OP_USHR_LONG_2ADDR:
         checkBinop2addr(workRegs, insnRegCount, &decInsn,
-            kRegTypeLongLo, kRegTypeLongLo, kRegTypeInteger, false, &okay);
+            kRegTypeLongLo, kRegTypeLongLo, kRegTypeInteger, false, &failure);
         break;
     case OP_ADD_FLOAT_2ADDR:
     case OP_SUB_FLOAT_2ADDR:
@@ -5002,7 +5312,7 @@
     case OP_DIV_FLOAT_2ADDR:
     case OP_REM_FLOAT_2ADDR:
         checkBinop2addr(workRegs, insnRegCount, &decInsn,
-            kRegTypeFloat, kRegTypeFloat, kRegTypeFloat, false, &okay);
+            kRegTypeFloat, kRegTypeFloat, kRegTypeFloat, false, &failure);
         break;
     case OP_ADD_DOUBLE_2ADDR:
     case OP_SUB_DOUBLE_2ADDR:
@@ -5010,7 +5320,8 @@
     case OP_DIV_DOUBLE_2ADDR:
     case OP_REM_DOUBLE_2ADDR:
         checkBinop2addr(workRegs, insnRegCount, &decInsn,
-            kRegTypeDoubleLo, kRegTypeDoubleLo, kRegTypeDoubleLo, false, &okay);
+            kRegTypeDoubleLo, kRegTypeDoubleLo, kRegTypeDoubleLo, false,
+            &failure);
         break;
     case OP_ADD_INT_LIT16:
     case OP_RSUB_INT:
@@ -5018,13 +5329,13 @@
     case OP_DIV_INT_LIT16:
     case OP_REM_INT_LIT16:
         checkLitop(workRegs, insnRegCount, &decInsn,
-            kRegTypeInteger, kRegTypeInteger, false, &okay);
+            kRegTypeInteger, kRegTypeInteger, false, &failure);
         break;
     case OP_AND_INT_LIT16:
     case OP_OR_INT_LIT16:
     case OP_XOR_INT_LIT16:
         checkLitop(workRegs, insnRegCount, &decInsn,
-            kRegTypeInteger, kRegTypeInteger, true, &okay);
+            kRegTypeInteger, kRegTypeInteger, true, &failure);
         break;
     case OP_ADD_INT_LIT8:
     case OP_RSUB_INT_LIT8:
@@ -5032,18 +5343,35 @@
     case OP_DIV_INT_LIT8:
     case OP_REM_INT_LIT8:
     case OP_SHL_INT_LIT8:
-    case OP_SHR_INT_LIT8:
-    case OP_USHR_INT_LIT8:
         checkLitop(workRegs, insnRegCount, &decInsn,
-            kRegTypeInteger, kRegTypeInteger, false, &okay);
+            kRegTypeInteger, kRegTypeInteger, false, &failure);
+        break;
+    case OP_SHR_INT_LIT8:
+        tmpType = adjustForRightShift(workRegs, insnRegCount,
+            decInsn.vB, decInsn.vC, false, &failure);
+        checkLitop(workRegs, insnRegCount, &decInsn,
+            tmpType, kRegTypeInteger, false, &failure);
+        break;
+    case OP_USHR_INT_LIT8:
+        tmpType = adjustForRightShift(workRegs, insnRegCount,
+            decInsn.vB, decInsn.vC, true, &failure);
+        checkLitop(workRegs, insnRegCount, &decInsn,
+            tmpType, kRegTypeInteger, false, &failure);
         break;
     case OP_AND_INT_LIT8:
     case OP_OR_INT_LIT8:
     case OP_XOR_INT_LIT8:
         checkLitop(workRegs, insnRegCount, &decInsn,
-            kRegTypeInteger, kRegTypeInteger, true, &okay);
+            kRegTypeInteger, kRegTypeInteger, true, &failure);
         break;
 
+    /*
+     * This falls into the general category of "optimized" instructions,
+     * which don't generally appear during verification.  Because it's
+     * inserted in the course of verification, we can expect to see it here.
+     */
+    case OP_THROW_VERIFICATION_ERROR:
+        break;
 
     /*
      * Verifying "quickened" instructions is tricky, because we have
@@ -5089,7 +5417,7 @@
     case OP_INVOKE_VIRTUAL_QUICK_RANGE:
     case OP_INVOKE_SUPER_QUICK:
     case OP_INVOKE_SUPER_QUICK_RANGE:
-        okay = false;
+        failure = VERIFY_ERROR_GENERIC;
         break;
 
     /* these should never appear */
@@ -5112,14 +5440,13 @@
     case OP_UNUSED_EA:
     case OP_UNUSED_EB:
     case OP_UNUSED_EC:
-    case OP_UNUSED_ED:
     case OP_UNUSED_EF:
     case OP_UNUSED_F1:
     case OP_UNUSED_FC:
     case OP_UNUSED_FD:
     case OP_UNUSED_FE:
     case OP_UNUSED_FF:
-        okay = false;
+        failure = VERIFY_ERROR_GENERIC;
         break;
 
     /*
@@ -5128,10 +5455,28 @@
      */
     }
 
-    if (!okay) {
-        LOG_VFY_METH(meth, "VFY:  rejecting opcode 0x%02x at 0x%04x\n",
-            decInsn.opCode, insnIdx);
-        goto bail;
+    if (!VERIFY_OK(failure)) {
+        if (failure == VERIFY_ERROR_GENERIC || gDvm.optimizing) {
+            /* immediate failure, reject class */
+            LOG_VFY_METH(meth, "VFY:  rejecting opcode 0x%02x at 0x%04x\n",
+                decInsn.opCode, insnIdx);
+            goto bail;
+        } else {
+            /* replace opcode and continue on */
+            LOGD("VFY: replacing opcode 0x%02x at 0x%04x\n",
+                decInsn.opCode, insnIdx);
+            if (!replaceFailingInstruction(meth, insnFlags, insnIdx, failure)) {
+                LOG_VFY_METH(meth, "VFY:  rejecting opcode 0x%02x at 0x%04x\n",
+                    decInsn.opCode, insnIdx);
+                goto bail;
+            }
+            /* IMPORTANT: meth->insns may have been changed */
+            insns = meth->insns + insnIdx;
+
+            /* continue on as if we just handled a throw-verification-error */
+            failure = VERIFY_ERROR_NONE;
+            nextFlags = kInstrCanThrow;
+        }
     }
 
     /*
@@ -5206,6 +5551,7 @@
         if (!checkMoveException(meth, insnIdx+branchTarget, "branch"))
             goto bail;
 
+        /* update branch target, set "changed" if appropriate */
         updateRegisters(meth, insnFlags, regTable, insnIdx+branchTarget,
             workRegs);
     }
@@ -5297,6 +5643,7 @@
     return result;
 }
 
+
 /*
  * callback function used in dumpRegTypes to print local vars
  * valid at a given address.
diff --git a/vm/analysis/CodeVerify.h b/vm/analysis/CodeVerify.h
index 0cd4638..1b93655 100644
--- a/vm/analysis/CodeVerify.h
+++ b/vm/analysis/CodeVerify.h
@@ -198,10 +198,10 @@
     return (insnFlags[addr] & kInsnFlagGcPoint) != 0;
 }
 INLINE void dvmInsnSetGcPoint(InsnFlags* insnFlags, int addr,
-    bool isBranch)
+    bool isGcPoint)
 {
-    assert(isBranch);
-    //if (isBranch)
+    assert(isGcPoint);
+    //if (isGcPoint)
         insnFlags[addr] |= kInsnFlagGcPoint;
     //else
     //    insnFlags[addr] &= ~kInsnFlagGcPoint;
@@ -259,7 +259,7 @@
  * Verify bytecode in "meth".  "insnFlags" should be populated with
  * instruction widths and "in try" flags.
  */
-bool dvmVerifyCodeFlow(const Method* meth, InsnFlags* insnFlags,
+bool dvmVerifyCodeFlow(Method* meth, InsnFlags* insnFlags,
     UninitInstanceMap* uninitMap);
 
 #endif /*_DALVIK_CODEVERIFY*/
diff --git a/vm/analysis/DexOptimize.c b/vm/analysis/DexOptimize.c
index d086b99..b3e2d40 100644
--- a/vm/analysis/DexOptimize.c
+++ b/vm/analysis/DexOptimize.c
@@ -25,6 +25,7 @@
 #include "Dalvik.h"
 #include "libdex/InstrUtils.h"
 #include "libdex/OptInvocation.h"
+#include "analysis/RegisterMap.h"
 
 #include <zlib.h>
 
@@ -50,7 +51,7 @@
 /* fwd */
 static int writeDependencies(int fd, u4 modWhen, u4 crc);
 static bool writeAuxData(int fd, const DexClassLookup* pClassLookup,\
-    const IndexMapSet* pIndexMapSet);
+    const IndexMapSet* pIndexMapSet, const RegisterMapBuilder* pRegMapBuilder);
 static void logFailedWrite(size_t expected, ssize_t actual, const char* msg,
     int err);
 
@@ -365,6 +366,9 @@
         char* androidRoot;
         int flags;
 
+        /* change process groups, so we don't clash with ProcessManager */
+        setpgid(0, 0);
+
         /* full path to optimizer */
         androidRoot = getenv("ANDROID_ROOT");
         if (androidRoot == NULL) {
@@ -506,6 +510,7 @@
 {
     DexClassLookup* pClassLookup = NULL;
     IndexMapSet* pIndexMapSet = NULL;
+    RegisterMapBuilder* pRegMapBuilder = NULL;
     bool doVerify, doOpt;
     u4 headerFlags = 0;
 
@@ -566,6 +571,13 @@
          * Rewrite the file.  Byte reordering, structure realigning,
          * class verification, and bytecode optimization are all performed
          * here.
+         *
+         * In theory the file could change size and bits could shift around.
+         * In practice this would be annoying to deal with, so the file
+         * layout is designed so that it can always be rewritten in place.
+         *
+         * This sets "headerFlags" and creates the class lookup table as
+         * part of doing the processing.
          */
         success = rewriteDex(((u1*) mapAddr) + dexOffset, dexLength,
                     doVerify, doOpt, &headerFlags, &pClassLookup);
@@ -576,6 +588,7 @@
 
             if (dvmDexFileOpenPartial(dexAddr, dexLength, &pDvmDex) != 0) {
                 LOGE("Unable to create DexFile\n");
+                success = false;
             } else {
                 /*
                  * If configured to do so, scan the instructions, looking
@@ -586,8 +599,20 @@
                  */
                 pIndexMapSet = dvmRewriteConstants(pDvmDex);
 
-                updateChecksum(dexAddr, dexLength,
-                    (DexHeader*) pDvmDex->pHeader);
+                /*
+                 * If configured to do so, generate a full set of register
+                 * maps for all verified classes.
+                 */
+                if (gDvm.generateRegisterMaps) {
+                    pRegMapBuilder = dvmGenerateRegisterMaps(pDvmDex);
+                    if (pRegMapBuilder == NULL) {
+                        LOGE("Failed generating register maps\n");
+                        success = false;
+                    }
+                }
+
+                DexHeader* pHeader = (DexHeader*)pDvmDex->pHeader;
+                updateChecksum(dexAddr, dexLength, pHeader);
 
                 dvmDexFileFree(pDvmDex);
             }
@@ -640,8 +665,7 @@
         goto bail;
     }
 
-
-    /* compute deps length, and adjust aux start for 64-bit alignment */
+    /* compute deps length, then adjust aux start for 64-bit alignment */
     auxOffset = lseek(fd, 0, SEEK_END);
     depsLength = auxOffset - depsOffset;
 
@@ -656,7 +680,7 @@
     /*
      * Append any auxillary pre-computed data structures.
      */
-    if (!writeAuxData(fd, pClassLookup, pIndexMapSet)) {
+    if (!writeAuxData(fd, pClassLookup, pIndexMapSet, pRegMapBuilder)) {
         LOGW("Failed writing aux data\n");
         goto bail;
     }
@@ -692,8 +716,11 @@
     LOGV("Successfully wrote DEX header\n");
     result = true;
 
+    //dvmRegisterMapDumpStats();
+
 bail:
     dvmFreeIndexMapSet(pIndexMapSet);
+    dvmFreeRegisterMapBuilder(pRegMapBuilder);
     free(pClassLookup);
     return result;
 }
@@ -888,7 +915,8 @@
     }
     val = read4LE(&ptr);
     if (val != DALVIK_VM_BUILD) {
-        LOGI("DexOpt: VM build mismatch (%d vs %d)\n", val, DALVIK_VM_BUILD);
+        LOGD("DexOpt: VM build version mismatch (%d vs %d)\n",
+            val, DALVIK_VM_BUILD);
         goto bail;
     }
 
@@ -1085,19 +1113,28 @@
  * so it can be used directly when the file is mapped for reading.
  */
 static bool writeAuxData(int fd, const DexClassLookup* pClassLookup,
-    const IndexMapSet* pIndexMapSet)
+    const IndexMapSet* pIndexMapSet, const RegisterMapBuilder* pRegMapBuilder)
 {
     /* pre-computed class lookup hash table */
-    if (!writeChunk(fd, (u4) kDexChunkClassLookup, pClassLookup,
-            pClassLookup->size))
+    if (!writeChunk(fd, (u4) kDexChunkClassLookup,
+            pClassLookup, pClassLookup->size))
     {
         return false;
     }
 
     /* remapped constants (optional) */
     if (pIndexMapSet != NULL) {
-        if (!writeChunk(fd, pIndexMapSet->chunkType, pIndexMapSet->chunkData,
-                pIndexMapSet->chunkDataLen))
+        if (!writeChunk(fd, pIndexMapSet->chunkType,
+                pIndexMapSet->chunkData, pIndexMapSet->chunkDataLen))
+        {
+            return false;
+        }
+    }
+
+    /* register maps (optional) */
+    if (pRegMapBuilder != NULL) {
+        if (!writeChunk(fd, (u4) kDexChunkRegisterMaps,
+                pRegMapBuilder->data, pRegMapBuilder->size))
         {
             return false;
         }
@@ -1622,8 +1659,11 @@
  * file.
  *
  * Exceptions caused by failures are cleared before returning.
+ *
+ * On failure, returns NULL, and sets *pFailure if pFailure is not NULL.
  */
-ClassObject* dvmOptResolveClass(ClassObject* referrer, u4 classIdx)
+ClassObject* dvmOptResolveClass(ClassObject* referrer, u4 classIdx,
+    VerifyError* pFailure)
 {
     DvmDex* pDvmDex = referrer->pDvmDex;
     ClassObject* resClass;
@@ -1645,6 +1685,23 @@
             LOGV("DexOpt: class %d (%s) not found\n",
                 classIdx,
                 dexStringByTypeIdx(pDvmDex->pDexFile, classIdx));
+            if (pFailure != NULL) {
+                /* dig through the wrappers to find the original failure */
+                Object* excep = dvmGetException(dvmThreadSelf());
+                while (true) {
+                    Object* cause = dvmGetExceptionCause(excep);
+                    if (cause == NULL)
+                        break;
+                    excep = cause;
+                }
+                if (strcmp(excep->clazz->descriptor,
+                    "Ljava/lang/IncompatibleClassChangeError;") == 0)
+                {
+                    *pFailure = VERIFY_ERROR_CLASS_CHANGE;
+                } else {
+                    *pFailure = VERIFY_ERROR_NO_CLASS;
+                }
+            }
             dvmClearOptException(dvmThreadSelf());
             return NULL;
         }
@@ -1659,6 +1716,8 @@
     if (IS_CLASS_FLAG_SET(resClass, CLASS_MULTIPLE_DEFS)) {
         LOGI("DexOpt: not resolving ambiguous class '%s'\n",
             resClass->descriptor);
+        if (pFailure != NULL)
+            *pFailure = VERIFY_ERROR_NO_CLASS;
         return NULL;
     }
 
@@ -1669,6 +1728,8 @@
     if (!allowed) {
         LOGW("DexOpt: resolve class illegal access: %s -> %s\n",
             referrer->descriptor, resClass->descriptor);
+        if (pFailure != NULL)
+            *pFailure = VERIFY_ERROR_ACCESS_CLASS;
         return NULL;
     }
 
@@ -1677,8 +1738,11 @@
 
 /*
  * Alternate version of dvmResolveInstField().
+ *
+ * On failure, returns NULL, and sets *pFailure if pFailure is not NULL.
  */
-InstField* dvmOptResolveInstField(ClassObject* referrer, u4 ifieldIdx)
+InstField* dvmOptResolveInstField(ClassObject* referrer, u4 ifieldIdx,
+    VerifyError* pFailure)
 {
     DvmDex* pDvmDex = referrer->pDvmDex;
     InstField* resField;
@@ -1693,20 +1757,31 @@
         /*
          * Find the field's class.
          */
-        resClass = dvmOptResolveClass(referrer, pFieldId->classIdx);
+        resClass = dvmOptResolveClass(referrer, pFieldId->classIdx, pFailure);
         if (resClass == NULL) {
             //dvmClearOptException(dvmThreadSelf());
             assert(!dvmCheckException(dvmThreadSelf()));
+            if (pFailure != NULL) { assert(!VERIFY_OK(*pFailure)); }
             return NULL;
         }
 
-        resField = dvmFindInstanceFieldHier(resClass,
+        resField = (InstField*)dvmFindFieldHier(resClass,
             dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx),
             dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->typeIdx));
         if (resField == NULL) {
             LOGD("DexOpt: couldn't find field %s.%s\n",
                 resClass->descriptor,
                 dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx));
+            if (pFailure != NULL)
+                *pFailure = VERIFY_ERROR_NO_FIELD;
+            return NULL;
+        }
+        if (dvmIsStaticField(&resField->field)) {
+            LOGD("DexOpt: wanted instance, got static for field %s.%s\n",
+                resClass->descriptor,
+                dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx));
+            if (pFailure != NULL)
+                *pFailure = VERIFY_ERROR_CLASS_CHANGE;
             return NULL;
         }
 
@@ -1724,6 +1799,8 @@
         LOGI("DexOpt: access denied from %s to field %s.%s\n",
             referrer->descriptor, resField->field.clazz->descriptor,
             resField->field.name);
+        if (pFailure != NULL)
+            *pFailure = VERIFY_ERROR_ACCESS_FIELD;
         return NULL;
     }
 
@@ -1734,8 +1811,11 @@
  * Alternate version of dvmResolveStaticField().
  *
  * Does not force initialization of the resolved field's class.
+ *
+ * On failure, returns NULL, and sets *pFailure if pFailure is not NULL.
  */
-StaticField* dvmOptResolveStaticField(ClassObject* referrer, u4 sfieldIdx)
+StaticField* dvmOptResolveStaticField(ClassObject* referrer, u4 sfieldIdx,
+    VerifyError* pFailure)
 {
     DvmDex* pDvmDex = referrer->pDvmDex;
     StaticField* resField;
@@ -1750,18 +1830,29 @@
         /*
          * Find the field's class.
          */
-        resClass = dvmOptResolveClass(referrer, pFieldId->classIdx);
+        resClass = dvmOptResolveClass(referrer, pFieldId->classIdx, pFailure);
         if (resClass == NULL) {
             //dvmClearOptException(dvmThreadSelf());
             assert(!dvmCheckException(dvmThreadSelf()));
+            if (pFailure != NULL) { assert(!VERIFY_OK(*pFailure)); }
             return NULL;
         }
 
-        resField = dvmFindStaticFieldHier(resClass,
+        resField = (StaticField*)dvmFindFieldHier(resClass,
                     dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx),
                     dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->typeIdx));
         if (resField == NULL) {
             LOGD("DexOpt: couldn't find static field\n");
+            if (pFailure != NULL)
+                *pFailure = VERIFY_ERROR_NO_FIELD;
+            return NULL;
+        }
+        if (!dvmIsStaticField(&resField->field)) {
+            LOGD("DexOpt: wanted static, got instance for field %s.%s\n",
+                resClass->descriptor,
+                dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx));
+            if (pFailure != NULL)
+                *pFailure = VERIFY_ERROR_CLASS_CHANGE;
             return NULL;
         }
 
@@ -1784,6 +1875,8 @@
         LOGI("DexOpt: access denied from %s to field %s.%s\n",
             referrer->descriptor, resField->field.clazz->descriptor,
             resField->field.name);
+        if (pFailure != NULL)
+            *pFailure = VERIFY_ERROR_ACCESS_FIELD;
         return NULL;
     }
 
@@ -1809,7 +1902,7 @@
     InstField* field;
     int byteOffset;
 
-    field = dvmOptResolveInstField(clazz, fieldIdx);
+    field = dvmOptResolveInstField(clazz, fieldIdx, NULL);
     if (field == NULL) {
         LOGI("DexOpt: unable to optimize field ref 0x%04x at 0x%02x in %s.%s\n",
             fieldIdx, (int) (insns - method->insns), clazz->descriptor,
@@ -1833,14 +1926,18 @@
  * Alternate version of dvmResolveMethod().
  *
  * Doesn't throw exceptions, and checks access on every lookup.
+ *
+ * On failure, returns NULL, and sets *pFailure if pFailure is not NULL.
  */
 Method* dvmOptResolveMethod(ClassObject* referrer, u4 methodIdx,
-    MethodType methodType)
+    MethodType methodType, VerifyError* pFailure)
 {
     DvmDex* pDvmDex = referrer->pDvmDex;
     Method* resMethod;
 
-    assert(methodType != METHOD_INTERFACE);
+    assert(methodType == METHOD_DIRECT ||
+           methodType == METHOD_VIRTUAL ||
+           methodType == METHOD_STATIC);
 
     LOGVV("--- resolving method %u (referrer=%s)\n", methodIdx,
         referrer->descriptor);
@@ -1852,16 +1949,22 @@
 
         pMethodId = dexGetMethodId(pDvmDex->pDexFile, methodIdx);
 
-        resClass = dvmOptResolveClass(referrer, pMethodId->classIdx);
+        resClass = dvmOptResolveClass(referrer, pMethodId->classIdx, pFailure);
         if (resClass == NULL) {
-            /* can't find the class that the method is a part of */
+            /*
+             * Can't find the class that the method is a part of, or don't
+             * have permission to access the class.
+             */
             LOGV("DexOpt: can't find called method's class (?.%s)\n",
                 dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx));
+            if (pFailure != NULL) { assert(!VERIFY_OK(*pFailure)); }
             return NULL;
         }
         if (dvmIsInterfaceClass(resClass)) {
             /* method is part of an interface; this is wrong method for that */
             LOGW("DexOpt: method is in an interface\n");
+            if (pFailure != NULL)
+                *pFailure = VERIFY_ERROR_GENERIC;
             return NULL;
         }
 
@@ -1876,25 +1979,44 @@
         if (methodType == METHOD_DIRECT) {
             resMethod = dvmFindDirectMethod(resClass,
                 dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx), &proto);
-        } else if (methodType == METHOD_STATIC) {
-            resMethod = dvmFindDirectMethodHier(resClass,
-                dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx), &proto);
         } else {
-            resMethod = dvmFindVirtualMethodHier(resClass,
+            /* METHOD_STATIC or METHOD_VIRTUAL */
+            resMethod = dvmFindMethodHier(resClass,
                 dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx), &proto);
         }
 
         if (resMethod == NULL) {
             LOGV("DexOpt: couldn't find method '%s'\n",
                 dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx));
+            if (pFailure != NULL)
+                *pFailure = VERIFY_ERROR_NO_METHOD;
             return NULL;
         }
+        if (methodType == METHOD_STATIC) {
+            if (!dvmIsStaticMethod(resMethod)) {
+                LOGD("DexOpt: wanted static, got instance for method %s.%s\n",
+                    resClass->descriptor, resMethod->name);
+                if (pFailure != NULL)
+                    *pFailure = VERIFY_ERROR_CLASS_CHANGE;
+                return NULL;
+            }
+        } else if (methodType == METHOD_VIRTUAL) {
+            if (dvmIsStaticMethod(resMethod)) {
+                LOGD("DexOpt: wanted instance, got static for method %s.%s\n",
+                    resClass->descriptor, resMethod->name);
+                if (pFailure != NULL)
+                    *pFailure = VERIFY_ERROR_CLASS_CHANGE;
+                return NULL;
+            }
+        }
 
         /* see if this is a pure-abstract method */
         if (dvmIsAbstractMethod(resMethod) && !dvmIsAbstractClass(resClass)) {
             LOGW("DexOpt: pure-abstract method '%s' in %s\n",
                 dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx),
                 resClass->descriptor);
+            if (pFailure != NULL)
+                *pFailure = VERIFY_ERROR_GENERIC;
             return NULL;
         }
 
@@ -1925,6 +2047,8 @@
                 referrer->descriptor);
             free(desc);
         }
+        if (pFailure != NULL)
+            *pFailure = VERIFY_ERROR_ACCESS_METHOD;
         return NULL;
     }
 
@@ -1945,7 +2069,7 @@
     Method* baseMethod;
     u2 methodIdx = insns[1];
 
-    baseMethod = dvmOptResolveMethod(clazz, methodIdx, METHOD_VIRTUAL);
+    baseMethod = dvmOptResolveMethod(clazz, methodIdx, METHOD_VIRTUAL, NULL);
     if (baseMethod == NULL) {
         LOGD("DexOpt: unable to optimize virt call 0x%04x at 0x%02x in %s.%s\n",
             methodIdx,
@@ -1989,7 +2113,7 @@
     Method* calledMethod;
     u2 methodIdx = insns[1];
 
-    calledMethod = dvmOptResolveMethod(clazz, methodIdx, METHOD_DIRECT);
+    calledMethod = dvmOptResolveMethod(clazz, methodIdx, METHOD_DIRECT, NULL);
     if (calledMethod == NULL) {
         LOGD("DexOpt: unable to opt direct call 0x%04x at 0x%02x in %s.%s\n",
             methodIdx,
@@ -2021,6 +2145,8 @@
 /*
  * Resolve an interface method reference.
  *
+ * No method access check here -- interface methods are always public.
+ *
  * Returns NULL if the method was not found.  Does not throw an exception.
  */
 Method* dvmOptResolveInterfaceMethod(ClassObject* referrer, u4 methodIdx)
@@ -2039,7 +2165,7 @@
 
         pMethodId = dexGetMethodId(pDvmDex->pDexFile, methodIdx);
 
-        resClass = dvmOptResolveClass(referrer, pMethodId->classIdx);
+        resClass = dvmOptResolveClass(referrer, pMethodId->classIdx, NULL);
         if (resClass == NULL) {
             /* can't find the class that the method is a part of */
             dvmClearOptException(dvmThreadSelf());
@@ -2115,7 +2241,7 @@
 
     //return false;
 
-    calledMethod = dvmOptResolveMethod(clazz, methodIdx, methodType);
+    calledMethod = dvmOptResolveMethod(clazz, methodIdx, methodType, NULL);
     if (calledMethod == NULL) {
         LOGV("+++ DexOpt inline: can't find %d\n", methodIdx);
         return false;
diff --git a/vm/analysis/DexOptimize.h b/vm/analysis/DexOptimize.h
index 01aa828..afcb3cb 100644
--- a/vm/analysis/DexOptimize.h
+++ b/vm/analysis/DexOptimize.h
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 /*
  * DEX optimization declarations.
  */
@@ -36,6 +37,40 @@
 };
 
 /*
+ * An enumeration of problems that can turn up during verification.
+ */
+typedef enum VerifyError {
+    VERIFY_ERROR_NONE = 0,      /* no error; must be zero */
+    VERIFY_ERROR_GENERIC,       /* VerifyError */
+
+    VERIFY_ERROR_NO_CLASS,      /* NoClassDefFoundError */
+    VERIFY_ERROR_NO_FIELD,      /* NoSuchFieldError */
+    VERIFY_ERROR_NO_METHOD,     /* NoSuchMethodError */
+    VERIFY_ERROR_ACCESS_CLASS,  /* IllegalAccessError */
+    VERIFY_ERROR_ACCESS_FIELD,  /* IllegalAccessError */
+    VERIFY_ERROR_ACCESS_METHOD, /* IllegalAccessError */
+    VERIFY_ERROR_CLASS_CHANGE,  /* IncompatibleClassChangeError */
+    VERIFY_ERROR_INSTANTIATION, /* InstantiationError */
+} VerifyError;
+
+/*
+ * Identifies the type of reference in the instruction that generated the
+ * verify error (e.g. VERIFY_ERROR_ACCESS_CLASS could come from a method,
+ * field, or class reference).
+ *
+ * This must fit in two bits.
+ */
+typedef enum VerifyErrorRefType {
+    VERIFY_ERROR_REF_CLASS  = 0,
+    VERIFY_ERROR_REF_FIELD  = 1,
+    VERIFY_ERROR_REF_METHOD = 2,
+} VerifyErrorRefType;
+
+#define kVerifyErrorRefTypeShift 6
+
+#define VERIFY_OK(_failure) ((_failure) == VERIFY_ERROR_NONE)
+
+/*
  * Given the full path to a DEX or Jar file, and (if appropriate) the name
  * within the Jar, open the optimized version from the cache.
  *
@@ -81,11 +116,14 @@
  * Abbreviated resolution functions, for use by optimization and verification
  * code.
  */
-ClassObject* dvmOptResolveClass(ClassObject* referrer, u4 classIdx);
+ClassObject* dvmOptResolveClass(ClassObject* referrer, u4 classIdx,
+    VerifyError* pFailure);
 Method* dvmOptResolveMethod(ClassObject* referrer, u4 methodIdx,
-        MethodType methodType);
+    MethodType methodType, VerifyError* pFailure);
 Method* dvmOptResolveInterfaceMethod(ClassObject* referrer, u4 methodIdx);
-InstField* dvmOptResolveInstField(ClassObject* referrer, u4 ifieldIdx);
-StaticField* dvmOptResolveStaticField(ClassObject* referrer, u4 sfieldIdx);
+InstField* dvmOptResolveInstField(ClassObject* referrer, u4 ifieldIdx,
+    VerifyError* pFailure);
+StaticField* dvmOptResolveStaticField(ClassObject* referrer, u4 sfieldIdx,
+    VerifyError* pFailure);
 
 #endif /*_DALVIK_DEXOPTIMIZE*/
diff --git a/vm/analysis/DexVerify.c b/vm/analysis/DexVerify.c
index 354d68f..10251db 100644
--- a/vm/analysis/DexVerify.c
+++ b/vm/analysis/DexVerify.c
@@ -36,11 +36,18 @@
     gDvm.instrWidth = dexCreateInstrWidthTable();
     gDvm.instrFormat = dexCreateInstrFormatTable();
     gDvm.instrFlags = dexCreateInstrFlagsTable();
-    return (gDvm.instrWidth != NULL && gDvm.instrFormat!= NULL);
+    if (gDvm.instrWidth == NULL || gDvm.instrFormat == NULL ||
+        gDvm.instrFlags == NULL)
+    {
+        LOGE("Unable to create instruction tables\n");
+        return false;
+    }
+
+    return true;
 }
 
 /*
- * Initialize some things we need for verification.
+ * Free up some things we needed for verification.
  */
 void dvmVerificationShutdown(void)
 {
@@ -533,15 +540,36 @@
     dvmInsnSetBranchTarget(insnFlags, 0, true);
 
     for (i = 0; i < insnCount; /**/) {
-        static int gcMask = kInstrCanBranch | kInstrCanSwitch |
+        /*
+         * These types of instructions can be GC points.  To support precise
+         * GC, all such instructions must export the PC in the interpreter,
+         * or the GC won't be able to identify the current PC for the thread.
+         */
+        static const int gcMask = kInstrCanBranch | kInstrCanSwitch |
             kInstrCanThrow | kInstrCanReturn;
+
         int width = dvmInsnGetWidth(insnFlags, i);
         OpCode opcode = *insns & 0xff;
         InstructionFlags opFlags = dexGetInstrFlags(gDvm.instrFlags, opcode);
         int offset, absOffset;
 
-        if ((opFlags & gcMask) != 0)
-            dvmInsnSetGcPoint(insnFlags, i, true);
+        if ((opFlags & gcMask) != 0) {
+            /*
+             * This instruction is probably a GC point.  Branch instructions
+             * only qualify if they go backward, so we need to check the
+             * offset.
+             */
+            int offset = -1;
+            bool unused;
+            if (dvmGetBranchTarget(meth, insnFlags, i, &offset, &unused)) {
+                if (offset < 0) {
+                    dvmInsnSetGcPoint(insnFlags, i, true);
+                }
+            } else {
+                /* not a branch target */
+                dvmInsnSetGcPoint(insnFlags, i, true);
+            }
+        }
 
         switch (opcode) {
         case OP_NOP:
diff --git a/vm/analysis/RegisterMap.c b/vm/analysis/RegisterMap.c
index b02874a..0e3445a 100644
--- a/vm/analysis/RegisterMap.c
+++ b/vm/analysis/RegisterMap.c
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-// ** UNDER CONSTRUCTION **
-
 /*
  * This code generate "register maps" for Dalvik bytecode.  In a stack-based
  * VM we might call these "stack maps".  They are used to increase the
@@ -27,9 +25,1826 @@
 #include "analysis/RegisterMap.h"
 #include "libdex/DexCatch.h"
 #include "libdex/InstrUtils.h"
+#include "libdex/Leb128.h"
 
 #include <stddef.h>
 
+/* double-check the compression */
+#define REGISTER_MAP_VERIFY     false
+
+/* verbose logging */
+#define REGISTER_MAP_VERBOSE    false
+
+
+// fwd
+static void outputTypeVector(const RegType* regs, int insnRegCount, u1* data);
+static bool verifyMap(VerifierData* vdata, const RegisterMap* pMap);
+static int compareMaps(const RegisterMap* pMap1, const RegisterMap* pMap2);
+
+static void computeMapStats(RegisterMap* pMap, const Method* method);
+static RegisterMap* compressMapDifferential(const RegisterMap* pMap,\
+    const Method* meth);
+static RegisterMap* uncompressMapDifferential(const RegisterMap* pMap);
+
+
+//#define REGISTER_MAP_STATS
+#ifdef REGISTER_MAP_STATS
+/*
+ * Generate some statistics on the register maps we create and use.
+ */
+#define kMaxGcPointGap      50
+#define kUpdatePosnMinRegs  24
+#define kNumUpdatePosns     8
+#define kMaxDiffBits        20
+typedef struct MapStats {
+    /*
+     * Buckets measuring the distance between GC points.  This tells us how
+     * many bits we need to encode the advancing program counter.  We ignore
+     * some of the "long tail" entries.
+     */
+    int gcPointGap[kMaxGcPointGap];
+
+    /*
+     * Number of gaps.  Equal to (number of gcPoints - number of methods),
+     * since the computation isn't including the initial gap.
+     */
+    int gcGapCount;
+
+    /*
+     * Number of gaps.
+     */
+    int totalGcPointCount;
+
+    /*
+     * For larger methods (>= 24 registers), measure in which octant register
+     * updates occur.  This should help us understand whether register
+     * changes tend to cluster in the low regs even for large methods.
+     */
+    int updatePosn[kNumUpdatePosns];
+
+    /*
+     * For all methods, count up the number of changes to registers < 16
+     * and >= 16.
+     */
+    int updateLT16;
+    int updateGE16;
+
+    /*
+     * Histogram of the number of bits that differ between adjacent entries.
+     */
+    int numDiffBits[kMaxDiffBits];
+
+
+    /*
+     * Track the number of expanded maps, and the heap space required to
+     * hold them.
+     */
+    int numExpandedMaps;
+    int totalExpandedMapSize;
+} MapStats;
+#endif
+
+/*
+ * Prepare some things.
+ */
+bool dvmRegisterMapStartup(void)
+{
+#ifdef REGISTER_MAP_STATS
+    MapStats* pStats = calloc(1, sizeof(MapStats));
+    gDvm.registerMapStats = pStats;
+#endif
+    return true;
+}
+
+/*
+ * Clean up.
+ */
+void dvmRegisterMapShutdown(void)
+{
+#ifdef REGISTER_MAP_STATS
+    free(gDvm.registerMapStats);
+#endif
+}
+
+/*
+ * Write stats to log file.
+ */
+void dvmRegisterMapDumpStats(void)
+{
+#ifdef REGISTER_MAP_STATS
+    MapStats* pStats = (MapStats*) gDvm.registerMapStats;
+    int i, end;
+
+    for (end = kMaxGcPointGap-1; end >= 0; end--) {
+        if (pStats->gcPointGap[end] != 0)
+            break;
+    }
+
+    LOGI("Register Map gcPointGap stats (diff count=%d, total=%d):\n",
+        pStats->gcGapCount, pStats->totalGcPointCount);
+    assert(pStats->gcPointGap[0] == 0);
+    for (i = 1; i <= end; i++) {
+        LOGI(" %2d %d\n", i, pStats->gcPointGap[i]);
+    }
+
+
+    for (end = kMaxDiffBits-1; end >= 0; end--) {
+        if (pStats->numDiffBits[end] != 0)
+            break;
+    }
+
+    LOGI("Register Map bit difference stats:\n");
+    for (i = 0; i <= end; i++) {
+        LOGI(" %2d %d\n", i, pStats->numDiffBits[i]);
+    }
+
+
+    LOGI("Register Map update position stats (lt16=%d ge16=%d):\n",
+        pStats->updateLT16, pStats->updateGE16);
+    for (i = 0; i < kNumUpdatePosns; i++) {
+        LOGI(" %2d %d\n", i, pStats->updatePosn[i]);
+    }
+#endif
+}
+
+
+/*
+ * ===========================================================================
+ *      Map generation
+ * ===========================================================================
+ */
+
+/*
+ * Generate the register map for a method that has just been verified
+ * (i.e. we're doing this as part of verification).
+ *
+ * For type-precise determination we have all the data we need, so we
+ * just need to encode it in some clever fashion.
+ *
+ * Returns a pointer to a newly-allocated RegisterMap, or NULL on failure.
+ */
+RegisterMap* dvmGenerateRegisterMapV(VerifierData* vdata)
+{
+    static const int kHeaderSize = offsetof(RegisterMap, data);
+    RegisterMap* pMap = NULL;
+    RegisterMap* pResult = NULL;
+    RegisterMapFormat format;
+    u1 regWidth;
+    u1* mapData;
+    int i, bytesForAddr, gcPointCount;
+    int bufSize;
+
+    if (vdata->method->registersSize >= 2048) {
+        LOGE("ERROR: register map can't handle %d registers\n",
+            vdata->method->registersSize);
+        goto bail;
+    }
+    regWidth = (vdata->method->registersSize + 7) / 8;
+
+    /*
+     * Decide if we need 8 or 16 bits to hold the address.  Strictly speaking
+     * we only need 16 bits if we actually encode an address >= 256 -- if
+     * the method has a section at the end without GC points (e.g. array
+     * data) we don't need to count it.  The situation is unusual, and
+     * detecting it requires scanning the entire method, so we don't bother.
+     */
+    if (vdata->insnsSize < 256) {
+        format = kRegMapFormatCompact8;
+        bytesForAddr = 1;
+    } else {
+        format = kRegMapFormatCompact16;
+        bytesForAddr = 2;
+    }
+
+    /*
+     * Count up the number of GC point instructions.
+     *
+     * NOTE: this does not automatically include the first instruction,
+     * since we don't count method entry as a GC point.
+     */
+    gcPointCount = 0;
+    for (i = 0; i < vdata->insnsSize; i++) {
+        if (dvmInsnIsGcPoint(vdata->insnFlags, i))
+            gcPointCount++;
+    }
+    if (gcPointCount >= 65536) {
+        /* we could handle this, but in practice we don't get near this */
+        LOGE("ERROR: register map can't handle %d gc points in one method\n",
+            gcPointCount);
+        goto bail;
+    }
+
+    /*
+     * Allocate a buffer to hold the map data.
+     */
+    bufSize = kHeaderSize + gcPointCount * (bytesForAddr + regWidth);
+
+    LOGV("+++ grm: %s.%s (adr=%d gpc=%d rwd=%d bsz=%d)\n",
+        vdata->method->clazz->descriptor, vdata->method->name,
+        bytesForAddr, gcPointCount, regWidth, bufSize);
+
+    pMap = (RegisterMap*) malloc(bufSize);
+    dvmRegisterMapSetFormat(pMap, format);
+    dvmRegisterMapSetOnHeap(pMap, true);
+    dvmRegisterMapSetRegWidth(pMap, regWidth);
+    dvmRegisterMapSetNumEntries(pMap, gcPointCount);
+
+    /*
+     * Populate it.
+     */
+    mapData = pMap->data;
+    for (i = 0; i < vdata->insnsSize; i++) {
+        if (dvmInsnIsGcPoint(vdata->insnFlags, i)) {
+            assert(vdata->addrRegs[i] != NULL);
+            if (format == kRegMapFormatCompact8) {
+                *mapData++ = i;
+            } else /*kRegMapFormatCompact16*/ {
+                *mapData++ = i & 0xff;
+                *mapData++ = i >> 8;
+            }
+            outputTypeVector(vdata->addrRegs[i], vdata->insnRegCount, mapData);
+            mapData += regWidth;
+        }
+    }
+
+    LOGV("mapData=%p pMap=%p bufSize=%d\n", mapData, pMap, bufSize);
+    assert(mapData - (const u1*) pMap == bufSize);
+
+    if (REGISTER_MAP_VERIFY && !verifyMap(vdata, pMap))
+        goto bail;
+#ifdef REGISTER_MAP_STATS
+    computeMapStats(pMap, vdata->method);
+#endif
+
+    /*
+     * Try to compress the map.
+     */
+    RegisterMap* pCompMap;
+
+    pCompMap = compressMapDifferential(pMap, vdata->method);
+    if (pCompMap != NULL) {
+        if (REGISTER_MAP_VERIFY) {
+            /*
+             * Expand the compressed map we just created, and compare it
+             * to the original.  Abort the VM if it doesn't match up.
+             */
+            RegisterMap* pUncompMap;
+            pUncompMap = uncompressMapDifferential(pCompMap);
+            if (pUncompMap == NULL) {
+                LOGE("Map failed to uncompress - %s.%s\n",
+                    vdata->method->clazz->descriptor,
+                    vdata->method->name);
+                free(pCompMap);
+                /* bad - compression is broken or we're out of memory */
+                dvmAbort();
+            } else {
+                if (compareMaps(pMap, pUncompMap) != 0) {
+                    LOGE("Map comparison failed - %s.%s\n",
+                        vdata->method->clazz->descriptor,
+                        vdata->method->name);
+                    free(pCompMap);
+                    /* bad - compression is broken */
+                    dvmAbort();
+                }
+
+                /* verify succeeded */
+                free(pUncompMap);
+            }
+        }
+
+        if (REGISTER_MAP_VERBOSE) {
+            LOGD("Good compress on %s.%s\n",
+                vdata->method->clazz->descriptor,
+                vdata->method->name);
+        }
+        free(pMap);
+        pMap = pCompMap;
+    } else {
+        if (REGISTER_MAP_VERBOSE) {
+            LOGD("Unable to compress %s.%s (ent=%d rw=%d)\n",
+                vdata->method->clazz->descriptor,
+                vdata->method->name,
+                dvmRegisterMapGetNumEntries(pMap),
+                dvmRegisterMapGetRegWidth(pMap));
+        }
+    }
+
+    pResult = pMap;
+
+bail:
+    return pResult;
+}
+
+/*
+ * Release the storage held by a RegisterMap.
+ */
+void dvmFreeRegisterMap(RegisterMap* pMap)
+{
+    if (pMap == NULL)
+        return;
+
+    assert(dvmRegisterMapGetOnHeap(pMap));
+    free(pMap);
+}
+
+/*
+ * Determine if the RegType value is a reference type.
+ *
+ * Ordinarily we include kRegTypeZero in the "is it a reference"
+ * check.  There's no value in doing so here, because we know
+ * the register can't hold anything but zero.
+ */
+static inline bool isReferenceType(RegType type)
+{
+    return (type > kRegTypeMAX || type == kRegTypeUninit);
+}
+
+/*
+ * Given a line of registers, output a bit vector that indicates whether
+ * or not the register holds a reference type (which could be null).
+ *
+ * We use '1' to indicate it's a reference, '0' for anything else (numeric
+ * value, uninitialized data, merge conflict).  Register 0 will be found
+ * in the low bit of the first byte.
+ */
+static void outputTypeVector(const RegType* regs, int insnRegCount, u1* data)
+{
+    u1 val = 0;
+    int i;
+
+    for (i = 0; i < insnRegCount; i++) {
+        RegType type = *regs++;
+        val >>= 1;
+        if (isReferenceType(type))
+            val |= 0x80;        /* set hi bit */
+
+        if ((i & 0x07) == 7)
+            *data++ = val;
+    }
+    if ((i & 0x07) != 0) {
+        /* flush bits from last byte */
+        val >>= 8 - (i & 0x07);
+        *data++ = val;
+    }
+}
+
+/*
+ * Print the map as a series of binary strings.
+ *
+ * Pass in method->registersSize if known, or -1 if not.
+ */
+static void dumpRegisterMap(const RegisterMap* pMap, int registersSize)
+{
+    const u1* rawMap = pMap->data;
+    const RegisterMapFormat format = dvmRegisterMapGetFormat(pMap);
+    const int numEntries = dvmRegisterMapGetNumEntries(pMap);
+    const int regWidth = dvmRegisterMapGetRegWidth(pMap);
+    int addrWidth;
+
+    switch (format) {
+    case kRegMapFormatCompact8:
+        addrWidth = 1;
+        break;
+    case kRegMapFormatCompact16:
+        addrWidth = 2;
+        break;
+    default:
+        /* can't happen */
+        LOGE("Can only dump Compact8 / Compact16 maps (not %d)\n", format);
+        return;
+    }
+
+    if (registersSize < 0)
+        registersSize = 8 * regWidth;
+    assert(registersSize <= regWidth * 8);
+
+    int ent;
+    for (ent = 0; ent < numEntries; ent++) {
+        int i, addr;
+
+        addr = *rawMap++;
+        if (addrWidth > 1)
+            addr |= (*rawMap++) << 8;
+
+        const u1* dataStart = rawMap;
+        u1 val = 0;
+
+        /* create binary string */
+        char outBuf[registersSize +1];
+        for (i = 0; i < registersSize; i++) {
+            val >>= 1;
+            if ((i & 0x07) == 0)
+                val = *rawMap++;
+
+            outBuf[i] = '0' + (val & 0x01);
+        }
+        outBuf[i] = '\0';
+
+        /* back up and create hex dump */
+        char hexBuf[regWidth * 3 +1];
+        char* cp = hexBuf;
+        rawMap = dataStart;
+        for (i = 0; i < regWidth; i++) {
+            sprintf(cp, " %02x", *rawMap++);
+            cp += 3;
+        }
+        hexBuf[i * 3] = '\0';
+
+        LOGD("  %04x %s %s\n", addr, outBuf, hexBuf);
+    }
+}
+
+/*
+ * Double-check the map.
+ *
+ * We run through all of the data in the map, and compare it to the original.
+ * Only works on uncompressed data.
+ */
+static bool verifyMap(VerifierData* vdata, const RegisterMap* pMap)
+{
+    const u1* rawMap = pMap->data;
+    const RegisterMapFormat format = dvmRegisterMapGetFormat(pMap);
+    const int numEntries = dvmRegisterMapGetNumEntries(pMap);
+    int ent;
+    bool dumpMap = false;
+
+    if (false) {
+        const char* cd = "Landroid/net/http/Request;";
+        const char* mn = "readResponse";
+        const char* sg = "(Landroid/net/http/AndroidHttpClientConnection;)V";
+        if (strcmp(vdata->method->clazz->descriptor, cd) == 0 &&
+            strcmp(vdata->method->name, mn) == 0)
+        {
+            char* desc;
+            desc = dexProtoCopyMethodDescriptor(&vdata->method->prototype);
+            LOGI("Map for %s.%s %s\n", vdata->method->clazz->descriptor,
+                vdata->method->name, desc);
+            free(desc);
+
+            dumpMap = true;
+        }
+    }
+
+    if ((vdata->method->registersSize + 7) / 8 != pMap->regWidth) {
+        LOGE("GLITCH: registersSize=%d, regWidth=%d\n",
+            vdata->method->registersSize, pMap->regWidth);
+        return false;
+    }
+
+    for (ent = 0; ent < numEntries; ent++) {
+        int addr;
+
+        switch (format) {
+        case kRegMapFormatCompact8:
+            addr = *rawMap++;
+            break;
+        case kRegMapFormatCompact16:
+            addr = *rawMap++;
+            addr |= (*rawMap++) << 8;
+            break;
+        default:
+            /* shouldn't happen */
+            LOGE("GLITCH: bad format (%d)", format);
+            dvmAbort();
+        }
+
+        const u1* dataStart = rawMap;
+        const RegType* regs = vdata->addrRegs[addr];
+        if (regs == NULL) {
+            LOGE("GLITCH: addr %d has no data\n", addr);
+            return false;
+        }
+
+        u1 val = 0;
+        int i;
+
+        for (i = 0; i < vdata->method->registersSize; i++) {
+            bool bitIsRef, regIsRef;
+
+            val >>= 1;
+            if ((i & 0x07) == 0) {
+                /* load next byte of data */
+                val = *rawMap++;
+            }
+
+            bitIsRef = val & 0x01;
+
+            RegType type = regs[i];
+            regIsRef = isReferenceType(type);
+
+            if (bitIsRef != regIsRef) {
+                LOGE("GLITCH: addr %d reg %d: bit=%d reg=%d(%d)\n",
+                    addr, i, bitIsRef, regIsRef, type);
+                return false;
+            }
+        }
+
+        /* rawMap now points to the address field of the next entry */
+    }
+
+    if (dumpMap)
+        dumpRegisterMap(pMap, vdata->method->registersSize);
+
+    return true;
+}
+
+
+/*
+ * ===========================================================================
+ *      DEX generation & parsing
+ * ===========================================================================
+ */
+
+/*
+ * Advance "ptr" to ensure 32-bit alignment.
+ */
+static inline u1* align32(u1* ptr)
+{
+    return (u1*) (((int) ptr + 3) & ~0x03);
+}
+
+/*
+ * Compute the size, in bytes, of a register map.
+ */
+static size_t computeRegisterMapSize(const RegisterMap* pMap)
+{
+    static const int kHeaderSize = offsetof(RegisterMap, data);
+    u1 format = dvmRegisterMapGetFormat(pMap);
+    u2 numEntries = dvmRegisterMapGetNumEntries(pMap);
+
+    assert(pMap != NULL);
+
+    switch (format) {
+    case kRegMapFormatNone:
+        return 1;
+    case kRegMapFormatCompact8:
+        return kHeaderSize + (1 + pMap->regWidth) * numEntries;
+    case kRegMapFormatCompact16:
+        return kHeaderSize + (2 + pMap->regWidth) * numEntries;
+    case kRegMapFormatDifferential:
+        {
+            /* kHeaderSize + decoded ULEB128 length */
+            const u1* ptr = pMap->data;
+            int len = readUnsignedLeb128(&ptr);
+            return len + (ptr - (u1*) pMap);
+        }
+    default:
+        LOGE("Bad register map format %d\n", format);
+        dvmAbort();
+        return 0;
+    }
+}
+
+/*
+ * Output the map for a single method, if it has one.
+ *
+ * Abstract and native methods have no map.  All others are expected to
+ * have one, since we know the class verified successfully.
+ *
+ * This strips the "allocated on heap" flag from the format byte, so that
+ * direct-mapped maps are correctly identified as such.
+ */
+static bool writeMapForMethod(const Method* meth, u1** pPtr)
+{
+    if (meth->registerMap == NULL) {
+        if (!dvmIsAbstractMethod(meth) && !dvmIsNativeMethod(meth)) {
+            LOGW("Warning: no map available for %s.%s\n",
+                meth->clazz->descriptor, meth->name);
+            /* weird, but keep going */
+        }
+        *(*pPtr)++ = kRegMapFormatNone;
+        return true;
+    }
+
+    /* serialize map into the buffer */
+    size_t mapSize = computeRegisterMapSize(meth->registerMap);
+    memcpy(*pPtr, meth->registerMap, mapSize);
+
+    /* strip the "on heap" flag out of the format byte, which is always first */
+    assert(**pPtr == meth->registerMap->format);
+    **pPtr &= ~(kRegMapFormatOnHeap);
+
+    *pPtr += mapSize;
+
+    return true;
+}
+
+/*
+ * Write maps for all methods in the specified class to the buffer, which
+ * can hold at most "length" bytes.  "*pPtr" will be advanced past the end
+ * of the data we write.
+ */
+static bool writeMapsAllMethods(DvmDex* pDvmDex, const ClassObject* clazz,
+    u1** pPtr, size_t length)
+{
+    RegisterMapMethodPool* pMethodPool;
+    u1* ptr = *pPtr;
+    int i, methodCount;
+
+    /* artificial limit */
+    if (clazz->virtualMethodCount + clazz->directMethodCount >= 65536) {
+        LOGE("Too many methods in %s\n", clazz->descriptor);
+        return false;
+    }
+
+    pMethodPool = (RegisterMapMethodPool*) ptr;
+    ptr += offsetof(RegisterMapMethodPool, methodData);
+    methodCount = 0;
+
+    /*
+     * Run through all methods, direct then virtual.  The class loader will
+     * traverse them in the same order.  (We could split them into two
+     * distinct pieces, but there doesn't appear to be any value in doing
+     * so other than that it makes class loading slightly less fragile.)
+     *
+     * The class loader won't know about miranda methods at the point
+     * where it parses this, so we omit those.
+     *
+     * TODO: consider omitting all native/abstract definitions.  Should be
+     * safe, though we lose the ability to sanity-check against the
+     * method counts in the DEX file.
+     */
+    for (i = 0; i < clazz->directMethodCount; i++) {
+        const Method* meth = &clazz->directMethods[i];
+        if (dvmIsMirandaMethod(meth))
+            continue;
+        if (!writeMapForMethod(&clazz->directMethods[i], &ptr)) {
+            return false;
+        }
+        methodCount++;
+        //ptr = align32(ptr);
+    }
+
+    for (i = 0; i < clazz->virtualMethodCount; i++) {
+        const Method* meth = &clazz->virtualMethods[i];
+        if (dvmIsMirandaMethod(meth))
+            continue;
+        if (!writeMapForMethod(&clazz->virtualMethods[i], &ptr)) {
+            return false;
+        }
+        methodCount++;
+        //ptr = align32(ptr);
+    }
+
+    pMethodPool->methodCount = methodCount;
+
+    *pPtr = ptr;
+    return true;
+}
+
+/*
+ * Write maps for all classes to the specified buffer, which can hold at
+ * most "length" bytes.
+ *
+ * Returns the actual length used, or 0 on failure.
+ */
+static size_t writeMapsAllClasses(DvmDex* pDvmDex, u1* basePtr, size_t length)
+{
+    DexFile* pDexFile = pDvmDex->pDexFile;
+    u4 count = pDexFile->pHeader->classDefsSize;
+    RegisterMapClassPool* pClassPool;
+    u4* offsetTable;
+    u1* ptr = basePtr;
+    u4 idx;
+
+    assert(gDvm.optimizing);
+
+    pClassPool = (RegisterMapClassPool*) ptr;
+    ptr += offsetof(RegisterMapClassPool, classDataOffset);
+    offsetTable = (u4*) ptr;
+    ptr += count * sizeof(u4);
+
+    pClassPool->numClasses = count;
+
+    /*
+     * We want an entry for every class, loaded or not.
+     */
+    for (idx = 0; idx < count; idx++) {
+        const DexClassDef* pClassDef;
+        const char* classDescriptor;
+        ClassObject* clazz;
+
+        pClassDef = dexGetClassDef(pDexFile, idx);
+        classDescriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx);
+
+        /*
+         * All classes have been loaded into the bootstrap class loader.
+         * If we can find it, and it was successfully pre-verified, we
+         * run through its methods and add the register maps.
+         *
+         * If it wasn't pre-verified then we know it can't have any
+         * register maps.  Classes that can't be loaded or failed
+         * verification get an empty slot in the index.
+         */
+        clazz = NULL;
+        if ((pClassDef->accessFlags & CLASS_ISPREVERIFIED) != 0)
+            clazz = dvmLookupClass(classDescriptor, NULL, false);
+
+        if (clazz != NULL) {
+            offsetTable[idx] = ptr - basePtr;
+            LOGVV("%d -> offset %d (%p-%p)\n",
+                idx, offsetTable[idx], ptr, basePtr);
+
+            if (!writeMapsAllMethods(pDvmDex, clazz, &ptr,
+                    length - (ptr - basePtr)))
+            {
+                return 0;
+            }
+
+            ptr = align32(ptr);
+            LOGVV("Size %s (%d+%d methods): %d\n", clazz->descriptor,
+                clazz->directMethodCount, clazz->virtualMethodCount,
+                (ptr - basePtr) - offsetTable[idx]);
+        } else {
+            LOGV("%4d NOT mapadding '%s'\n", idx, classDescriptor);
+            assert(offsetTable[idx] == 0);
+        }
+    }
+
+    if (ptr - basePtr >= (int)length) {
+        /* a bit late */
+        LOGE("Buffer overrun\n");
+        dvmAbort();
+    }
+
+    return ptr - basePtr;
+}
+
+/*
+ * Generate a register map set for all verified classes in "pDvmDex".
+ */
+RegisterMapBuilder* dvmGenerateRegisterMaps(DvmDex* pDvmDex)
+{
+    RegisterMapBuilder* pBuilder;
+
+    pBuilder = (RegisterMapBuilder*) calloc(1, sizeof(RegisterMapBuilder));
+    if (pBuilder == NULL)
+        return NULL;
+
+    /*
+     * We have a couple of options here:
+     *  (1) Compute the size of the output, and malloc a buffer.
+     *  (2) Create a "large-enough" anonymous mmap region.
+     *
+     * The nice thing about option #2 is that we don't have to traverse
+     * all of the classes and methods twice.  The risk is that we might
+     * not make the region large enough.  Since the pages aren't mapped
+     * until used we can allocate a semi-absurd amount of memory without
+     * worrying about the effect on the rest of the system.
+     *
+     * The basic encoding on the largest jar file requires about 1MB of
+     * storage.  We map out 4MB here.  (TODO: guarantee that the last
+     * page of the mapping is marked invalid, so we reliably fail if
+     * we overrun.)
+     */
+    if (sysCreatePrivateMap(4 * 1024 * 1024, &pBuilder->memMap) != 0) {
+        free(pBuilder);
+        return NULL;
+    }
+
+    /*
+     * Create the maps.
+     */
+    size_t actual = writeMapsAllClasses(pDvmDex, (u1*)pBuilder->memMap.addr,
+                                        pBuilder->memMap.length);
+    if (actual == 0) {
+        dvmFreeRegisterMapBuilder(pBuilder);
+        return NULL;
+    }
+
+    LOGV("TOTAL size of register maps: %d\n", actual);
+
+    pBuilder->data = pBuilder->memMap.addr;
+    pBuilder->size = actual;
+    return pBuilder;
+}
+
+/*
+ * Free the builder.
+ */
+void dvmFreeRegisterMapBuilder(RegisterMapBuilder* pBuilder)
+{
+    if (pBuilder == NULL)
+        return;
+
+    sysReleaseShmem(&pBuilder->memMap);
+    free(pBuilder);
+}
+
+
+/*
+ * Find the data for the specified class.
+ *
+ * If there's no register map data, or none for this class, we return NULL.
+ */
+const void* dvmRegisterMapGetClassData(const DexFile* pDexFile, u4 classIdx,
+    u4* pNumMaps)
+{
+    const RegisterMapClassPool* pClassPool;
+    const RegisterMapMethodPool* pMethodPool;
+
+    pClassPool = (const RegisterMapClassPool*) pDexFile->pRegisterMapPool;
+    if (pClassPool == NULL)
+        return NULL;
+
+    if (classIdx >= pClassPool->numClasses) {
+        LOGE("bad class index (%d vs %d)\n", classIdx, pClassPool->numClasses);
+        dvmAbort();
+    }
+
+    u4 classOffset = pClassPool->classDataOffset[classIdx];
+    if (classOffset == 0) {
+        LOGV("+++ no map for classIdx=%d\n", classIdx);
+        return NULL;
+    }
+
+    pMethodPool =
+        (const RegisterMapMethodPool*) (((u1*) pClassPool) + classOffset);
+    if (pNumMaps != NULL)
+        *pNumMaps = pMethodPool->methodCount;
+    return pMethodPool->methodData;
+}
+
+/*
+ * This advances "*pPtr" and returns its original value.
+ */
+const RegisterMap* dvmRegisterMapGetNext(const void** pPtr)
+{
+    const RegisterMap* pMap = *pPtr;
+
+    *pPtr = /*align32*/(((u1*) pMap) + computeRegisterMapSize(pMap));
+    LOGVV("getNext: %p -> %p (f=0x%x w=%d e=%d)\n",
+        pMap, *pPtr, pMap->format, pMap->regWidth,
+        dvmRegisterMapGetNumEntries(pMap));
+    return pMap;
+}
+
+
+/*
+ * ===========================================================================
+ *      Utility functions
+ * ===========================================================================
+ */
+
+/*
+ * Return the data for the specified address, or NULL if not found.
+ *
+ * The result must be released with dvmReleaseRegisterMapLine().
+ */
+const u1* dvmRegisterMapGetLine(const RegisterMap* pMap, int addr)
+{
+    int addrWidth, lineWidth;
+    u1 format = dvmRegisterMapGetFormat(pMap);
+    u2 numEntries = dvmRegisterMapGetNumEntries(pMap);
+
+    assert(numEntries > 0);
+
+    switch (format) {
+    case kRegMapFormatNone:
+        return NULL;
+    case kRegMapFormatCompact8:
+        addrWidth = 1;
+        break;
+    case kRegMapFormatCompact16:
+        addrWidth = 2;
+        break;
+    default:
+        LOGE("Unknown format %d\n", format);
+        dvmAbort();
+        return NULL;
+    }
+
+    lineWidth = addrWidth + pMap->regWidth;
+
+    /*
+     * Find the appropriate entry.  Many maps are very small, some are very
+     * large.
+     */
+    static const int kSearchThreshold = 8;
+    const u1* data = NULL;
+    int lineAddr;
+
+    if (numEntries < kSearchThreshold) {
+        int i;
+        data = pMap->data;
+        for (i = numEntries; i > 0; i--) {
+            lineAddr = data[0];
+            if (addrWidth > 1)
+                lineAddr |= data[1] << 8;
+            if (lineAddr == addr)
+                return data + addrWidth;
+
+            data += lineWidth;
+        }
+    } else {
+        int hi, lo, mid;
+
+        lo = 0;
+        hi = numEntries -1;
+
+        while (hi >= lo) {
+            mid = (hi + lo) / 2;
+            data = pMap->data + lineWidth * mid;
+
+            lineAddr = data[0];
+            if (addrWidth > 1)
+                lineAddr |= data[1] << 8;
+
+            if (addr > lineAddr) {
+                lo = mid + 1;
+            } else if (addr < lineAddr) {
+                hi = mid - 1;
+            } else {
+                return data + addrWidth;
+            }
+        }
+    }
+
+    assert(data == pMap->data + lineWidth * numEntries);
+    return NULL;
+}
+
+/*
+ * Compare two register maps.
+ *
+ * Returns 0 if they're equal, nonzero if not.
+ */
+static int compareMaps(const RegisterMap* pMap1, const RegisterMap* pMap2)
+{
+    size_t size1, size2;
+
+    size1 = computeRegisterMapSize(pMap1);
+    size2 = computeRegisterMapSize(pMap2);
+    if (size1 != size2) {
+        LOGI("compareMaps: size mismatch (%zd vs %zd)\n", size1, size2);
+        return -1;
+    }
+
+    if (memcmp(pMap1, pMap2, size1) != 0) {
+        LOGI("compareMaps: content mismatch\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+
+/*
+ * Get the expanded form of the register map associated with the method.
+ *
+ * If the map is already in one of the uncompressed formats, we return
+ * immediately.  Otherwise, we expand the map and replace method's register
+ * map pointer, freeing it if it was allocated on the heap.
+ *
+ * NOTE: this function is not synchronized; external locking is mandatory
+ * (unless we're in the zygote, where single-threaded access is guaranteed).
+ */
+const RegisterMap* dvmGetExpandedRegisterMap0(Method* method)
+{
+    const RegisterMap* curMap = method->registerMap;
+    RegisterMap* newMap;
+
+    if (curMap == NULL)
+        return NULL;
+
+    /* sanity check to ensure this isn't called w/o external locking */
+    /* (if we use this at a time other than during GC, fix/remove this test) */
+    if (true) {
+        if (!gDvm.zygote && pthread_mutex_trylock(&gDvm.gcHeapLock) == 0) {
+            LOGE("GLITCH: dvmGetExpandedRegisterMap not called at GC time\n");
+            dvmAbort();
+        }
+    }
+
+    RegisterMapFormat format = dvmRegisterMapGetFormat(curMap);
+    switch (format) {
+    case kRegMapFormatCompact8:
+    case kRegMapFormatCompact16:
+        if (REGISTER_MAP_VERBOSE) {
+            if (dvmRegisterMapGetOnHeap(curMap)) {
+                LOGD("RegMap: already expanded: %s.%s\n",
+                    method->clazz->descriptor, method->name);
+            } else {
+                LOGD("RegMap: stored w/o compression: %s.%s\n",
+                    method->clazz->descriptor, method->name);
+            }
+        }
+        return curMap;
+    case kRegMapFormatDifferential:
+        newMap = uncompressMapDifferential(curMap);
+        break;
+    default:
+        LOGE("Unknown format %d in dvmGetExpandedRegisterMap\n", format);
+        dvmAbort();
+    }
+
+    if (newMap == NULL) {
+        LOGE("Map failed to uncompress (fmt=%d) %s.%s\n",
+            format, method->clazz->descriptor, method->name);
+        return NULL;
+    }
+
+#ifdef REGISTER_MAP_STATS
+    /*
+     * Gather and display some stats.
+     */
+    {
+        MapStats* pStats = (MapStats*) gDvm.registerMapStats;
+        pStats->numExpandedMaps++;
+        pStats->totalExpandedMapSize += computeRegisterMapSize(newMap);
+        LOGD("RMAP: count=%d size=%d\n",
+            pStats->numExpandedMaps, pStats->totalExpandedMapSize);
+    }
+#endif
+
+    IF_LOGV() {
+        char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
+        LOGV("Expanding map -> %s.%s:%s\n",
+            method->clazz->descriptor, method->name, desc);
+        free(desc);
+    }
+
+    /*
+     * Update method, and free compressed map if it was sitting on the heap.
+     */
+    dvmSetRegisterMap(method, newMap);
+
+    if (dvmRegisterMapGetOnHeap(curMap))
+        dvmFreeRegisterMap((RegisterMap*) curMap);
+
+    return newMap;
+}
+
+
+/*
+ * ===========================================================================
+ *      Map compression
+ * ===========================================================================
+ */
+
+/*
+Notes on map compression
+
+The idea is to create a compressed form that will be uncompressed before
+use, with the output possibly saved in a cache.  This means we can use an
+approach that is unsuited for random access if we choose.
+
+In the event that a map simply does not work with our compression scheme,
+it's reasonable to store the map without compression.  In the future we
+may want to have more than one compression scheme, and try each in turn,
+retaining the best.  (We certainly want to keep the uncompressed form if it
+turns out to be smaller or even slightly larger than the compressed form.)
+
+Each entry consists of an address and a bit vector.  Adjacent entries are
+strongly correlated, suggesting differential encoding.
+
+
+Ideally we would avoid outputting adjacent entries with identical
+bit vectors.  However, the register values at a given address do not
+imply anything about the set of valid registers at subsequent addresses.
+We therefore cannot omit an entry.
+
+  If the thread stack has a PC at an address without a corresponding
+  entry in the register map, we must conservatively scan the registers in
+  that thread.  This can happen when single-stepping in the debugger,
+  because the debugger is allowed to invoke arbitrary methods when
+  a thread is stopped at a breakpoint.  If we can guarantee that a GC
+  thread scan will never happen while the debugger has that thread stopped,
+  then we can lift this restriction and simply omit entries that don't
+  change the bit vector from its previous state.
+
+Each entry advances the address value by at least 1 (measured in 16-bit
+"code units").  Looking at the bootclasspath entries, advancing by 2 units
+is most common.  Advances by 1 unit are far less common than advances by
+2 units, but more common than 5, and things fall off rapidly.  Gaps of
+up to 220 code units appear in some computationally intensive bits of code,
+but are exceedingly rare.
+
+If we sum up the number of transitions in a couple of ranges in framework.jar:
+  [1,4]: 188998 of 218922 gaps (86.3%)
+  [1,7]: 211647 of 218922 gaps (96.7%)
+Using a 3-bit delta, with one value reserved as an escape code, should
+yield good results for the address.
+
+These results would change dramatically if we reduced the set of GC
+points by e.g. removing instructions like integer divide that are only
+present because they can throw and cause an allocation.
+
+We also need to include an "initial gap", because the first few instructions
+in a method may not be GC points.
+
+
+By observation, many entries simply repeat the previous bit vector, or
+change only one or two bits.  (This is with type-precise information;
+the rate of change of bits will be different if live-precise information
+is factored in).
+
+Looking again at adjacent entries in framework.jar:
+  0 bits changed: 63.0%
+  1 bit changed: 32.2%
+After that it falls off rapidly, e.g. the number of entries with 2 bits
+changed is usually less than 1/10th of the number of entries with 1 bit
+changed.  A solution that allows us to encode 0- or 1- bit changes
+efficiently will do well.
+
+We still need to handle cases where a large number of bits change.  We
+probably want a way to drop in a full copy of the bit vector when it's
+smaller than the representation of multiple bit changes.
+
+
+The bit-change information can be encoded as an index that tells the
+decoder to toggle the state.  We want to encode the index in as few bits
+as possible, but we need to allow for fairly wide vectors (e.g. we have a
+method with 175 registers).  We can deal with this in a couple of ways:
+(1) use an encoding that assumes few registers and has an escape code
+for larger numbers of registers; or (2) use different encodings based
+on how many total registers the method has.  The choice depends to some
+extent on whether methods with large numbers of registers tend to modify
+the first 16 regs more often than the others.
+
+The last N registers hold method arguments.  If the bytecode is expected
+to be examined in a debugger, "dx" ensures that the contents of these
+registers won't change.  Depending upon the encoding format, we may be
+able to take advantage of this.  We still have to encode the initial
+state, but we know we'll never have to output a bit change for the last
+N registers.
+
+Considering only methods with 16 or more registers, the "target octant"
+for register changes looks like this:
+  [ 43.1%, 16.4%, 6.5%, 6.2%, 7.4%, 8.8%, 9.7%, 1.8% ]
+As expected, there are fewer changes at the end of the list where the
+arguments are kept, and more changes at the start of the list because
+register values smaller than 16 can be used in compact Dalvik instructions
+and hence are favored for frequently-used values.  In general, the first
+octant is considerably more active than later entries, the last octant
+is much less active, and the rest are all about the same.
+
+Looking at all bit changes in all methods, 94% are to registers 0-15.  The
+encoding will benefit greatly by favoring the low-numbered registers.
+
+
+Some of the smaller methods have identical maps, and space could be
+saved by simply including a pointer to an earlier definition.  This would
+be best accomplished by specifying a "pointer" format value, followed by
+a 3-byte (or ULEB128) offset.  Implementing this would probably involve
+generating a hash value for each register map and maintaining a hash table.
+
+In some cases there are repeating patterns in the bit vector that aren't
+adjacent.  These could benefit from a dictionary encoding.  This doesn't
+really become useful until the methods reach a certain size though,
+and managing the dictionary may incur more overhead than we want.
+
+Large maps can be compressed significantly.  The trouble is that, when
+we need to use them, we have to uncompress them onto the heap.  We may
+get a better trade-off between storage size and heap usage by refusing to
+compress large maps, so that they can be memory mapped and used directly.
+(OTOH, only about 2% of the maps will ever actually be used.)
+
+
+----- differential format -----
+
+// common header
++00 1B format
++01 1B regWidth
++02 2B numEntries (little-endian)
++04 nB length in bytes of the data that follows, in ULEB128 format
+       (not strictly necessary; allows determination of size w/o full parse)
++05+ 1B initial address (0-127), high bit set if max addr >= 256
++06+ nB initial value for bit vector
+
+// for each entry
++00: CCCCBAAA
+
+  AAA: address difference.  Values from 0 to 6 indicate an increment of 1
+  to 7.  A value of 7 indicates that the address difference is large,
+  and the next byte is a ULEB128-encoded difference value.
+
+  B: determines the meaning of CCCC.
+
+  CCCC: if B is 0, this is the number of the bit to toggle (0-15).
+  If B is 1, this is a count of the number of changed bits (1-14).  A value
+  of 0 means that no bits were changed, and a value of 15 indicates
+  that enough bits were changed that it required less space to output
+  the entire bit vector.
+
++01: (optional) ULEB128-encoded address difference
+
++01+: (optional) one or more ULEB128-encoded bit numbers, OR the entire
+  bit vector.
+
+The most common situation is an entry whose address has changed by 2-4
+code units, has no changes or just a single bit change, and the changed
+register is less than 16.  We should therefore be able to encode a large
+number of entries with a single byte, which is half the size of the
+Compact8 encoding method.
+*/
+
+/*
+ * Compute some stats on an uncompressed register map.
+ */
+static void computeMapStats(RegisterMap* pMap, const Method* method)
+{
+#ifdef REGISTER_MAP_STATS
+    MapStats* pStats = (MapStats*) gDvm.registerMapStats;
+    const u1 format = dvmRegisterMapGetFormat(pMap);
+    const u2 numEntries = dvmRegisterMapGetNumEntries(pMap);
+    const u1* rawMap = pMap->data;
+    const u1* prevData = NULL;
+    int ent, addr, prevAddr = -1;
+
+    for (ent = 0; ent < numEntries; ent++) {
+        switch (format) {
+        case kRegMapFormatCompact8:
+            addr = *rawMap++;
+            break;
+        case kRegMapFormatCompact16:
+            addr = *rawMap++;
+            addr |= (*rawMap++) << 8;
+            break;
+        default:
+            /* shouldn't happen */
+            LOGE("GLITCH: bad format (%d)", format);
+            dvmAbort();
+        }
+
+        const u1* dataStart = rawMap;
+
+        pStats->totalGcPointCount++;
+
+        /*
+         * Gather "gap size" stats, i.e. the difference in addresses between
+         * successive GC points.
+         */
+        if (prevData != NULL) {
+            assert(prevAddr >= 0);
+            int addrDiff = addr - prevAddr;
+
+            if (addrDiff < 0) {
+                LOGE("GLITCH: address went backward (0x%04x->0x%04x, %s.%s)\n",
+                    prevAddr, addr, method->clazz->descriptor, method->name);
+            } else if (addrDiff > kMaxGcPointGap) {
+                if (REGISTER_MAP_VERBOSE) {
+                    LOGI("HEY: addrDiff is %d, max %d (0x%04x->0x%04x %s.%s)\n",
+                        addrDiff, kMaxGcPointGap, prevAddr, addr,
+                        method->clazz->descriptor, method->name);
+                }
+                /* skip this one */
+            } else {
+                pStats->gcPointGap[addrDiff]++;
+            }
+            pStats->gcGapCount++;
+
+
+            /*
+             * Compare bit vectors in adjacent entries.  We want to count
+             * up the number of bits that differ (to see if we frequently
+             * change 0 or 1 bits) and get a sense for which part of the
+             * vector changes the most often (near the start, middle, end).
+             *
+             * We only do the vector position quantization if we have at
+             * least 16 registers in the method.
+             */
+            int numDiff = 0;
+            float div = (float) kNumUpdatePosns / method->registersSize;
+            int regByte;
+            for (regByte = 0; regByte < pMap->regWidth; regByte++) {
+                int prev, cur, bit;
+
+                prev = prevData[regByte];
+                cur = dataStart[regByte];
+
+                for (bit = 0; bit < 8; bit++) {
+                    if (((prev >> bit) & 1) != ((cur >> bit) & 1)) {
+                        numDiff++;
+
+                        int bitNum = regByte * 8 + bit;
+
+                        if (bitNum < 16)
+                            pStats->updateLT16++;
+                        else
+                            pStats->updateGE16++;
+
+                        if (method->registersSize < 16)
+                            continue;
+
+                        if (bitNum >= method->registersSize) {
+                            /* stuff off the end should be zero in both */
+                            LOGE("WEIRD: bit=%d (%d/%d), prev=%02x cur=%02x\n",
+                                bit, regByte, method->registersSize,
+                                prev, cur);
+                            assert(false);
+                        }
+                        int idx = (int) (bitNum * div);
+                        if (!(idx >= 0 && idx < kNumUpdatePosns)) {
+                            LOGE("FAIL: bitNum=%d (of %d) div=%.3f idx=%d\n",
+                                bitNum, method->registersSize, div, idx);
+                            assert(false);
+                        }
+                        pStats->updatePosn[idx]++;
+                    }
+                }
+            }
+
+            if (numDiff > kMaxDiffBits) {
+                if (REGISTER_MAP_VERBOSE) {
+                    LOGI("WOW: numDiff is %d, max %d\n", numDiff, kMaxDiffBits);
+                }
+            } else {
+                pStats->numDiffBits[numDiff]++;
+            }
+        }
+
+        /* advance to start of next line */
+        rawMap += pMap->regWidth;
+
+        prevAddr = addr;
+        prevData = dataStart;
+    }
+#endif
+}
+
+
+/*
+ * Compute the difference between two bit vectors.
+ *
+ * If "lebOutBuf" is non-NULL, we output the bit indices in ULEB128 format
+ * as we go.  Otherwise, we just generate the various counts.
+ *
+ * The bit vectors are compared byte-by-byte, so any unused bits at the
+ * end must be zero.
+ *
+ * Returns the number of bytes required to hold the ULEB128 output.
+ *
+ * If "pFirstBitChanged" or "pNumBitsChanged" are non-NULL, they will
+ * receive the index of the first changed bit and the number of changed
+ * bits, respectively.
+ */
+static int computeBitDiff(const u1* bits1, const u1* bits2, int byteWidth,
+    int* pFirstBitChanged, int* pNumBitsChanged, u1* lebOutBuf)
+{
+    int numBitsChanged = 0;
+    int firstBitChanged = -1;
+    int lebSize = 0;
+    int byteNum;
+
+    /*
+     * Run through the vectors, first comparing them at the byte level.  This
+     * will yield a fairly quick result if nothing has changed between them.
+     */
+    for (byteNum = 0; byteNum < byteWidth; byteNum++) {
+        u1 byte1 = *bits1++;
+        u1 byte2 = *bits2++;
+        if (byte1 != byte2) {
+            /*
+             * Walk through the byte, identifying the changed bits.
+             */
+            int bitNum;
+            for (bitNum = 0; bitNum < 8; bitNum++) {
+                if (((byte1 >> bitNum) & 0x01) != ((byte2 >> bitNum) & 0x01)) {
+                    int bitOffset = (byteNum << 3) + bitNum;
+
+                    if (firstBitChanged < 0)
+                        firstBitChanged = bitOffset;
+                    numBitsChanged++;
+
+                    if (lebOutBuf == NULL) {
+                        lebSize += unsignedLeb128Size(bitOffset);
+                    } else {
+                        u1* curBuf = lebOutBuf;
+                        lebOutBuf = writeUnsignedLeb128(lebOutBuf, bitOffset);
+                        lebSize += lebOutBuf - curBuf;
+                    }
+                }
+            }
+        }
+    }
+
+    if (numBitsChanged > 0)
+        assert(firstBitChanged >= 0);
+
+    if (pFirstBitChanged != NULL)
+        *pFirstBitChanged = firstBitChanged;
+    if (pNumBitsChanged != NULL)
+        *pNumBitsChanged = numBitsChanged;
+
+    return lebSize;
+}
+
+/*
+ * Compress the register map with differential encoding.
+ *
+ * "meth" is only needed for debug output.
+ *
+ * On success, returns a newly-allocated RegisterMap.  If the map is not
+ * compatible for some reason, or fails to get smaller, this will return NULL.
+ */
+static RegisterMap* compressMapDifferential(const RegisterMap* pMap,
+    const Method* meth)
+{
+    RegisterMap* pNewMap = NULL;
+    int origSize = computeRegisterMapSize(pMap);
+    u1* tmpBuf = NULL;
+    u1* tmpPtr;
+    int addrWidth, regWidth, numEntries;
+    bool debug = false;
+
+    if (false &&
+        strcmp(meth->clazz->descriptor, "Landroid/text/StaticLayout;") == 0 &&
+        strcmp(meth->name, "generate") == 0)
+    {
+        debug = true;
+    }
+
+    u1 format = dvmRegisterMapGetFormat(pMap);
+    switch (format) {
+    case kRegMapFormatCompact8:
+        addrWidth = 1;
+        break;
+    case kRegMapFormatCompact16:
+        addrWidth = 2;
+        break;
+    default:
+        LOGE("ERROR: can't compress map with format=%d\n", format);
+        goto bail;
+    }
+
+    regWidth = dvmRegisterMapGetRegWidth(pMap);
+    numEntries = dvmRegisterMapGetNumEntries(pMap);
+
+    if (debug) {
+        LOGI("COMPRESS: %s.%s aw=%d rw=%d ne=%d\n",
+            meth->clazz->descriptor, meth->name,
+            addrWidth, regWidth, numEntries);
+        dumpRegisterMap(pMap, -1);
+    }
+
+    if (numEntries <= 1) {
+        LOGV("Can't compress map with 0 or 1 entries\n");
+        goto bail;
+    }
+
+    /*
+     * We don't know how large the compressed data will be.  It's possible
+     * for it to expand and become larger than the original.  The header
+     * itself is variable-sized, so we generate everything into a temporary
+     * buffer and then copy it to form-fitting storage once we know how big
+     * it will be (and that it's smaller than the original).
+     *
+     * If we use a size that is equal to the size of the input map plus
+     * a value longer than a single entry can possibly expand to, we need
+     * only check for overflow at the end of each entry.  The worst case
+     * for a single line is (1 + <ULEB8 address> + <full copy of vector>).
+     * Addresses are 16 bits, so that's (1 + 3 + regWidth).
+     *
+     * The initial address offset and bit vector will take up less than
+     * or equal to the amount of space required when uncompressed -- large
+     * initial offsets are rejected.
+     */
+    tmpBuf = (u1*) malloc(origSize + (1 + 3 + regWidth));
+    if (tmpBuf == NULL)
+        goto bail;
+
+    tmpPtr = tmpBuf;
+
+    const u1* mapData = pMap->data;
+    const u1* prevBits;
+    u2 addr, prevAddr;
+
+    addr = *mapData++;
+    if (addrWidth > 1)
+        addr |= (*mapData++) << 8;
+
+    if (addr >= 128) {
+        LOGV("Can't compress map with starting address >= 128\n");
+        goto bail;
+    }
+
+    /*
+     * Start by writing the initial address and bit vector data.  The high
+     * bit of the initial address is used to indicate the required address
+     * width (which the decoder can't otherwise determine without parsing
+     * the compressed data).
+     */
+    *tmpPtr++ = addr | (addrWidth > 1 ? 0x80 : 0x00);
+    memcpy(tmpPtr, mapData, regWidth);
+
+    prevBits = mapData;
+    prevAddr = addr;
+
+    tmpPtr += regWidth;
+    mapData += regWidth;
+
+    /*
+     * Loop over all following entries.
+     */
+    int entry;
+    for (entry = 1; entry < numEntries; entry++) {
+        int addrDiff;
+        u1 key;
+
+        /*
+         * Pull out the address and figure out how to encode it.
+         */
+        addr = *mapData++;
+        if (addrWidth > 1)
+            addr |= (*mapData++) << 8;
+
+        if (debug)
+            LOGI(" addr=0x%04x ent=%d (aw=%d)\n", addr, entry, addrWidth);
+
+        addrDiff = addr - prevAddr;
+        assert(addrDiff > 0);
+        if (addrDiff < 8) {
+            /* small difference, encode in 3 bits */
+            key = addrDiff -1;          /* set 00000AAA */
+            if (debug)
+                LOGI(" : small %d, key=0x%02x\n", addrDiff, key);
+        } else {
+            /* large difference, output escape code */
+            key = 0x07;                 /* escape code for AAA */
+            if (debug)
+                LOGI(" : large %d, key=0x%02x\n", addrDiff, key);
+        }
+
+        int numBitsChanged, firstBitChanged, lebSize;
+
+        lebSize = computeBitDiff(prevBits, mapData, regWidth,
+            &firstBitChanged, &numBitsChanged, NULL);
+
+        if (debug) {
+            LOGI(" : diff fbc=%d nbc=%d ls=%d (rw=%d)\n",
+                firstBitChanged, numBitsChanged, lebSize, regWidth);
+        }
+
+        if (numBitsChanged == 0) {
+            /* set B to 1 and CCCC to zero to indicate no bits were changed */
+            key |= 0x08;
+            if (debug) LOGI(" : no bits changed\n");
+        } else if (numBitsChanged == 1 && firstBitChanged < 16) {
+            /* set B to 0 and CCCC to the index of the changed bit */
+            key |= firstBitChanged << 4;
+            if (debug) LOGI(" : 1 low bit changed\n");
+        } else if (numBitsChanged < 15 && lebSize < regWidth) {
+            /* set B to 1 and CCCC to the number of bits */
+            key |= 0x08 | (numBitsChanged << 4);
+            if (debug) LOGI(" : some bits changed\n");
+        } else {
+            /* set B to 1 and CCCC to 0x0f so we store the entire vector */
+            key |= 0x08 | 0xf0;
+            if (debug) LOGI(" : encode original\n");
+        }
+
+        /*
+         * Encode output.  Start with the key, follow with the address
+         * diff (if it didn't fit in 3 bits), then the changed bit info.
+         */
+        *tmpPtr++ = key;
+        if ((key & 0x07) == 0x07)
+            tmpPtr = writeUnsignedLeb128(tmpPtr, addrDiff);
+
+        if ((key & 0x08) != 0) {
+            int bitCount = key >> 4;
+            if (bitCount == 0) {
+                /* nothing changed, no additional output required */
+            } else if (bitCount == 15) {
+                /* full vector is most compact representation */
+                memcpy(tmpPtr, mapData, regWidth);
+                tmpPtr += regWidth;
+            } else {
+                /* write bit indices in LEB128 format */
+                (void) computeBitDiff(prevBits, mapData, regWidth,
+                    NULL, NULL, tmpPtr);
+                tmpPtr += lebSize;
+            }
+        } else {
+            /* single-bit changed, value encoded in key byte */
+        }
+
+        prevBits = mapData;
+        prevAddr = addr;
+        mapData += regWidth;
+
+        /*
+         * See if we've run past the original size.
+         */
+        if (tmpPtr - tmpBuf >= origSize) {
+            if (debug) {
+                LOGD("Compressed size >= original (%d vs %d): %s.%s\n",
+                    tmpPtr - tmpBuf, origSize,
+                    meth->clazz->descriptor, meth->name);
+            }
+            goto bail;
+        }
+    }
+
+    /*
+     * Create a RegisterMap with the contents.
+     *
+     * TODO: consider using a threshold other than merely ">=".  We would
+     * get poorer compression but potentially use less native heap space.
+     */
+    static const int kHeaderSize = offsetof(RegisterMap, data);
+    int newDataSize = tmpPtr - tmpBuf;
+    int newMapSize;
+
+    newMapSize = kHeaderSize + unsignedLeb128Size(newDataSize) + newDataSize;
+    if (newMapSize >= origSize) {
+        if (debug) {
+            LOGD("Final comp size >= original (%d vs %d): %s.%s\n",
+                newMapSize, origSize, meth->clazz->descriptor, meth->name);
+        }
+        goto bail;
+    }
+
+    pNewMap = (RegisterMap*) malloc(newMapSize);
+    if (pNewMap == NULL)
+        goto bail;
+    dvmRegisterMapSetFormat(pNewMap, kRegMapFormatDifferential);
+    dvmRegisterMapSetOnHeap(pNewMap, true);
+    dvmRegisterMapSetRegWidth(pNewMap, regWidth);
+    dvmRegisterMapSetNumEntries(pNewMap, numEntries);
+
+    tmpPtr = pNewMap->data;
+    tmpPtr = writeUnsignedLeb128(tmpPtr, newDataSize);
+    memcpy(tmpPtr, tmpBuf, newDataSize);
+
+    if (REGISTER_MAP_VERBOSE) {
+        LOGD("Compression successful (%d -> %d) from aw=%d rw=%d ne=%d\n",
+            computeRegisterMapSize(pMap), computeRegisterMapSize(pNewMap),
+            addrWidth, regWidth, numEntries);
+    }
+
+bail:
+    free(tmpBuf);
+    return pNewMap;
+}
+
+/*
+ * Toggle the value of the "idx"th bit in "ptr".
+ */
+static inline void toggleBit(u1* ptr, int idx)
+{
+    ptr[idx >> 3] ^= 1 << (idx & 0x07);
+}
+
+/*
+ * Expand a compressed map to an uncompressed form.
+ *
+ * Returns a newly-allocated RegisterMap on success, or NULL on failure.
+ *
+ * TODO: consider using the linear allocator or a custom allocator with
+ * LRU replacement for these instead of the native heap.
+ */
+static RegisterMap* uncompressMapDifferential(const RegisterMap* pMap)
+{
+    RegisterMap* pNewMap = NULL;
+    static const int kHeaderSize = offsetof(RegisterMap, data);
+    u1 format = dvmRegisterMapGetFormat(pMap);
+    RegisterMapFormat newFormat;
+    int regWidth, numEntries, newAddrWidth, newMapSize;
+
+    if (format != kRegMapFormatDifferential) {
+        LOGE("Not differential (%d)\n", format);
+        goto bail;
+    }
+
+    regWidth = dvmRegisterMapGetRegWidth(pMap);
+    numEntries = dvmRegisterMapGetNumEntries(pMap);
+
+    /* get the data size; we can check this at the end */
+    const u1* srcPtr = pMap->data;
+    int expectedSrcLen = readUnsignedLeb128(&srcPtr);
+    const u1* srcStart = srcPtr;
+
+    /* get the initial address and the 16-bit address flag */
+    int addr = *srcPtr & 0x7f;
+    if ((*srcPtr & 0x80) == 0) {
+        newFormat = kRegMapFormatCompact8;
+        newAddrWidth = 1;
+    } else {
+        newFormat = kRegMapFormatCompact16;
+        newAddrWidth = 2;
+    }
+    srcPtr++;
+
+    /* now we know enough to allocate the new map */
+    if (REGISTER_MAP_VERBOSE) {
+        LOGI("Expanding to map aw=%d rw=%d ne=%d\n",
+            newAddrWidth, regWidth, numEntries);
+    }
+    newMapSize = kHeaderSize + (newAddrWidth + regWidth) * numEntries;
+    pNewMap = (RegisterMap*) malloc(newMapSize);
+    if (pNewMap == NULL)
+        goto bail;
+
+    dvmRegisterMapSetFormat(pNewMap, newFormat);
+    dvmRegisterMapSetOnHeap(pNewMap, true);
+    dvmRegisterMapSetRegWidth(pNewMap, regWidth);
+    dvmRegisterMapSetNumEntries(pNewMap, numEntries);
+
+    /*
+     * Write the start address and initial bits to the new map.
+     */
+    u1* dstPtr = pNewMap->data;
+
+    *dstPtr++ = addr & 0xff;
+    if (newAddrWidth > 1)
+        *dstPtr++ = (u1) (addr >> 8);
+
+    memcpy(dstPtr, srcPtr, regWidth);
+
+    int prevAddr = addr;
+    const u1* prevBits = dstPtr;    /* point at uncompressed data */
+
+    dstPtr += regWidth;
+    srcPtr += regWidth;
+
+    /*
+     * Walk through, uncompressing one line at a time.
+     */
+    int entry;
+    for (entry = 1; entry < numEntries; entry++) {
+        int addrDiff;
+        u1 key;
+
+        key = *srcPtr++;
+
+        /* get the address */
+        if ((key & 0x07) == 7) {
+            /* address diff follows in ULEB128 */
+            addrDiff = readUnsignedLeb128(&srcPtr);
+        } else {
+            addrDiff = (key & 0x07) +1;
+        }
+
+        addr = prevAddr + addrDiff;
+        *dstPtr++ = addr & 0xff;
+        if (newAddrWidth > 1)
+            *dstPtr++ = (u1) (addr >> 8);
+
+        /* unpack the bits */
+        if ((key & 0x08) != 0) {
+            int bitCount = (key >> 4);
+            if (bitCount == 0) {
+                /* no bits changed, just copy previous */
+                memcpy(dstPtr, prevBits, regWidth);
+            } else if (bitCount == 15) {
+                /* full copy of bit vector is present; ignore prevBits */
+                memcpy(dstPtr, srcPtr, regWidth);
+                srcPtr += regWidth;
+            } else {
+                /* copy previous bits and modify listed indices */
+                memcpy(dstPtr, prevBits, regWidth);
+                while (bitCount--) {
+                    int bitIndex = readUnsignedLeb128(&srcPtr);
+                    toggleBit(dstPtr, bitIndex);
+                }
+            }
+        } else {
+            /* copy previous bits and modify the specified one */
+            memcpy(dstPtr, prevBits, regWidth);
+
+            /* one bit, from 0-15 inclusive, was changed */
+            toggleBit(dstPtr, key >> 4);
+        }
+
+        prevAddr = addr;
+        prevBits = dstPtr;
+        dstPtr += regWidth;
+    }
+
+    if (dstPtr - (u1*) pNewMap != newMapSize) {
+        LOGE("ERROR: output %d bytes, expected %d\n",
+            dstPtr - (u1*) pNewMap, newMapSize);
+        goto bail;
+    }
+
+    if (srcPtr - srcStart != expectedSrcLen) {
+        LOGE("ERROR: consumed %d bytes, expected %d\n",
+            srcPtr - srcStart, expectedSrcLen);
+        goto bail;
+    }
+
+    if (REGISTER_MAP_VERBOSE) {
+        LOGD("Expansion successful (%d -> %d)\n",
+            computeRegisterMapSize(pMap), computeRegisterMapSize(pNewMap));
+    }
+
+    return pNewMap;
+
+bail:
+    free(pNewMap);
+    return NULL;
+}
+
+
+/*
+ * ===========================================================================
+ *      Just-in-time generation
+ * ===========================================================================
+ */
+
+#if 0   /* incomplete implementation; may be removed entirely in the future */
 
 /*
 Notes on just-in-time RegisterMap generation
@@ -82,239 +1897,6 @@
 an effort should be made to minimize memory use.
 */
 
-// fwd
-static void outputTypeVector(const RegType* regs, int insnRegCount, u1* data);
-static bool verifyMap(VerifierData* vdata, const RegisterMap* pMap);
-
-/*
- * Generate the register map for a method that has just been verified
- * (i.e. we're doing this as part of verification).
- *
- * For type-precise determination we have all the data we need, so we
- * just need to encode it in some clever fashion.
- *
- * Returns a pointer to a newly-allocated RegisterMap, or NULL on failure.
- */
-RegisterMap* dvmGenerateRegisterMapV(VerifierData* vdata)
-{
-    RegisterMap* pMap = NULL;
-    RegisterMap* pResult = NULL;
-    RegisterMapFormat format;
-    u1 regWidth;
-    u1* mapData;
-    int i, bytesForAddr, gcPointCount;
-    int bufSize;
-
-    regWidth = (vdata->method->registersSize + 7) / 8;
-    if (vdata->insnsSize < 256) {
-        format = kFormatCompact8;
-        bytesForAddr = 1;
-    } else {
-        format = kFormatCompact16;
-        bytesForAddr = 2;
-    }
-
-    /*
-     * Count up the number of GC point instructions.
-     *
-     * NOTE: this does not automatically include the first instruction,
-     * since we don't count method entry as a GC point.
-     */
-    gcPointCount = 0;
-    for (i = 0; i < vdata->insnsSize; i++) {
-        if (dvmInsnIsGcPoint(vdata->insnFlags, i))
-            gcPointCount++;
-    }
-    if (gcPointCount >= 65536) {
-        /* we could handle this, but in practice we don't get near this */
-        LOGE("ERROR: register map can't handle %d gc points in one method\n",
-            gcPointCount);
-        goto bail;
-    }
-
-    /*
-     * Allocate a buffer to hold the map data.
-     */
-    bufSize = offsetof(RegisterMap, data);
-    bufSize += gcPointCount * (bytesForAddr + regWidth);
-
-    LOGD("+++ grm: %s.%s (adr=%d gpc=%d rwd=%d bsz=%d)\n",
-        vdata->method->clazz->descriptor, vdata->method->name,
-        bytesForAddr, gcPointCount, regWidth, bufSize);
-
-    pMap = (RegisterMap*) malloc(bufSize);
-    pMap->format = format;
-    pMap->regWidth = regWidth;
-    pMap->numEntries = gcPointCount;
-
-    /*
-     * Populate it.
-     */
-    mapData = pMap->data;
-    for (i = 0; i < vdata->insnsSize; i++) {
-        if (dvmInsnIsGcPoint(vdata->insnFlags, i)) {
-            assert(vdata->addrRegs[i] != NULL);
-            if (format == kFormatCompact8) {
-                *mapData++ = i;
-            } else /*kFormatCompact16*/ {
-                *mapData++ = i & 0xff;
-                *mapData++ = i >> 8;
-            }
-            outputTypeVector(vdata->addrRegs[i], vdata->insnRegCount, mapData);
-            mapData += regWidth;
-        }
-    }
-
-    LOGI("mapData=%p pMap=%p bufSize=%d\n", mapData, pMap, bufSize);
-    assert(mapData - (const u1*) pMap == bufSize);
-
-#if 1
-    if (!verifyMap(vdata, pMap))
-        goto bail;
-#endif
-
-    pResult = pMap;
-
-bail:
-    return pResult;
-}
-
-/*
- * Release the storage held by a RegisterMap.
- */
-void dvmFreeRegisterMap(RegisterMap* pMap)
-{
-    if (pMap == NULL)
-        return;
-
-    free(pMap);
-}
-
-/*
- * Determine if the RegType value is a reference type.
- *
- * Ordinarily we include kRegTypeZero in the "is it a reference"
- * check.  There's no value in doing so here, because we know
- * the register can't hold anything but zero.
- */
-static inline bool isReferenceType(RegType type)
-{
-    return (type > kRegTypeMAX || type == kRegTypeUninit);
-}
-
-/*
- * Given a line of registers, output a bit vector that indicates whether
- * or not the register holds a reference type (which could be null).
- *
- * We use '1' to indicate it's a reference, '0' for anything else (numeric
- * value, uninitialized data, merge conflict).  Register 0 will be found
- * in the low bit of the first byte.
- */
-static void outputTypeVector(const RegType* regs, int insnRegCount, u1* data)
-{
-    u1 val = 0;
-    int i;
-
-    for (i = 0; i < insnRegCount; i++) {
-        RegType type = *regs++;
-        val >>= 1;
-        if (isReferenceType(type))
-            val |= 0x80;        /* set hi bit */
-
-        if ((i & 0x07) == 7)
-            *data++ = val;
-    }
-    if ((i & 0x07) != 0) {
-        /* flush bits from last byte */
-        val >>= 8 - (i & 0x07);
-        *data++ = val;
-    }
-}
-
-/*
- * Double-check the map.
- *
- * We run through all of the data in the map, and compare it to the original.
- */
-static bool verifyMap(VerifierData* vdata, const RegisterMap* pMap)
-{
-    const u1* data = pMap->data;
-    int ent;
-
-    for (ent = 0; ent < pMap->numEntries; ent++) {
-        int addr;
-
-        switch (pMap->format) {
-        case kFormatCompact8:
-            addr = *data++;
-            break;
-        case kFormatCompact16:
-            addr = *data++;
-            addr |= (*data++) << 8;
-            break;
-        default:
-            /* shouldn't happen */
-            LOGE("GLITCH: bad format (%d)", pMap->format);
-            dvmAbort();
-        }
-
-        const RegType* regs = vdata->addrRegs[addr];
-        if (regs == NULL) {
-            LOGE("GLITCH: addr %d has no data\n", addr);
-            return false;
-        }
-
-        u1 val;
-        int i;
-
-        for (i = 0; i < vdata->method->registersSize; i++) {
-            bool bitIsRef, regIsRef;
-
-            val >>= 1;
-            if ((i & 0x07) == 0) {
-                /* load next byte of data */
-                val = *data++;
-            }
-
-            bitIsRef = val & 0x01;
-
-            RegType type = regs[i];
-            regIsRef = isReferenceType(type);
-
-            if (bitIsRef != regIsRef) {
-                LOGE("GLITCH: addr %d reg %d: bit=%d reg=%d(%d)\n",
-                    addr, i, bitIsRef, regIsRef, type);
-                return false;
-            }
-        }
-
-        /* print the map as a binary string */
-        if (false) {
-            char outBuf[vdata->method->registersSize +1];
-            for (i = 0; i < vdata->method->registersSize; i++) {
-                if (isReferenceType(regs[i])) {
-                    outBuf[i] = '1';
-                } else {
-                    outBuf[i] = '0';
-                }
-            }
-            outBuf[i] = '\0';
-            LOGD("  %04d %s\n", addr, outBuf);
-        }
-    }
-
-    return true;
-}
-
-
-/*
- * ===========================================================================
- *      Just-in-time generation
- * ===========================================================================
- */
-
-#if 0   /* incomplete implementation; may be removed entirely in the future */
-
 /*
  * This is like RegType in the verifier, but simplified.  It holds a value
  * from the reg type enum, or kRegTypeReference.
diff --git a/vm/analysis/RegisterMap.h b/vm/analysis/RegisterMap.h
index 2a890e7..dc17b1d 100644
--- a/vm/analysis/RegisterMap.h
+++ b/vm/analysis/RegisterMap.h
@@ -14,38 +14,221 @@
  * limitations under the License.
  */
 
-// ** UNDER CONSTRUCTION **
-
 /*
  * Declaration of register map data structure and related functions.
+ *
+ * These structures should be treated as opaque through most of the VM.
  */
 #ifndef _DALVIK_REGISTERMAP
 #define _DALVIK_REGISTERMAP
 
+#include "analysis/VerifySubs.h"
+#include "analysis/CodeVerify.h"
+
 /*
  * Format enumeration for RegisterMap data area.
  */
 typedef enum RegisterMapFormat {
-    kFormatUnknown = 0,
-    kFormatCompact8,        /* compact layout, 8-bit addresses */
-    kFormatCompact16,       /* compact layout, 16-bit addresses */
-    // TODO: compressed stream
+    kRegMapFormatUnknown = 0,
+    kRegMapFormatNone,          /* indicates no map data follows */
+    kRegMapFormatCompact8,      /* compact layout, 8-bit addresses */
+    kRegMapFormatCompact16,     /* compact layout, 16-bit addresses */
+    kRegMapFormatDifferential,  /* compressed, differential encoding */
+
+    kRegMapFormatOnHeap = 0x80, /* bit flag, indicates allocation on heap */
 } RegisterMapFormat;
 
 /*
  * This is a single variable-size structure.  It may be allocated on the
  * heap or mapped out of a (post-dexopt) DEX file.
+ *
+ * 32-bit alignment of the structure is NOT guaranteed.  This makes it a
+ * little awkward to deal with as a structure; to avoid accidents we use
+ * only byte types.  Multi-byte values are little-endian.
+ *
+ * Size of (format==FormatNone): 1 byte
+ * Size of (format==FormatCompact8): 4 + (1 + regWidth) * numEntries
+ * Size of (format==FormatCompact16): 4 + (2 + regWidth) * numEntries
  */
 struct RegisterMap {
     /* header */
-    u1      format;         /* enum RegisterMapFormat */
+    u1      format;         /* enum RegisterMapFormat; MUST be first entry */
     u1      regWidth;       /* bytes per register line, 1+ */
-    u2      numEntries;     /* number of entries */
+    u1      numEntries[2];  /* number of entries */
 
-    /* data starts here; no alignment guarantees made */
+    /* raw data starts here; need not be aligned */
     u1      data[1];
 };
 
+bool dvmRegisterMapStartup(void);
+void dvmRegisterMapShutdown(void);
+
+/*
+ * Get the format.
+ */
+INLINE RegisterMapFormat dvmRegisterMapGetFormat(const RegisterMap* pMap) {
+    return pMap->format & ~(kRegMapFormatOnHeap);
+}
+
+/*
+ * Set the format.
+ */
+INLINE void dvmRegisterMapSetFormat(RegisterMap* pMap, RegisterMapFormat format)
+{
+    pMap->format &= kRegMapFormatOnHeap;
+    pMap->format |= format;
+}
+
+/*
+ * Get the "on heap" flag.
+ */
+INLINE bool dvmRegisterMapGetOnHeap(const RegisterMap* pMap) {
+    return (pMap->format & kRegMapFormatOnHeap) != 0;
+}
+
+/*
+ * Get the register bit vector width, in bytes.
+ */
+INLINE u1 dvmRegisterMapGetRegWidth(const RegisterMap* pMap) {
+    return pMap->regWidth;
+}
+
+/*
+ * Set the register bit vector width, in bytes.
+ */
+INLINE void dvmRegisterMapSetRegWidth(RegisterMap* pMap, int regWidth) {
+    pMap->regWidth = regWidth;
+}
+
+/*
+ * Set the "on heap" flag.
+ */
+INLINE void dvmRegisterMapSetOnHeap(RegisterMap* pMap, bool val) {
+    if (val)
+        pMap->format |= kRegMapFormatOnHeap;
+    else
+        pMap->format &= ~(kRegMapFormatOnHeap);
+}
+
+/*
+ * Get the number of entries in this map.
+ */
+INLINE u2 dvmRegisterMapGetNumEntries(const RegisterMap* pMap) {
+    return pMap->numEntries[0] | (pMap->numEntries[1] << 8);
+}
+
+/*
+ * Set the number of entries in this map.
+ */
+INLINE void dvmRegisterMapSetNumEntries(RegisterMap* pMap, u2 numEntries) {
+    pMap->numEntries[0] = (u1) numEntries;
+    pMap->numEntries[1] = numEntries >> 8;
+}
+
+/*
+ * Retrieve the bit vector for the specified address.  This is a pointer
+ * to the bit data from an uncompressed map, or to a temporary copy of
+ * data from a compressed map.
+ *
+ * The caller must call dvmReleaseRegisterMapLine() with the result.
+ *
+ * Returns NULL if not found.
+ */
+const u1* dvmRegisterMapGetLine(const RegisterMap* pMap, int addr);
+
+/*
+ * Release "data".
+ *
+ * If "pMap" points to a compressed map from which we have expanded a
+ * single line onto the heap, this will free "data"; otherwise, it does
+ * nothing.
+ *
+ * TODO: decide if this is still a useful concept.
+ */
+INLINE void dvmReleaseRegisterMapLine(const RegisterMap* pMap, const u1* data)
+{}
+
+
+/*
+ * A pool of register maps for methods associated with a single class.
+ *
+ * Each entry is a 4-byte method index followed by the 32-bit-aligned
+ * RegisterMap.  The size of the RegisterMap is determined by parsing
+ * the map.  The lack of an index reduces random access speed, but we
+ * should be doing that rarely (during class load) and it saves space.
+ *
+ * These structures are 32-bit aligned.
+ */
+typedef struct RegisterMapMethodPool {
+    u2      methodCount;            /* chiefly used as a sanity check */
+
+    /* stream of per-method data starts here */
+    u4      methodData[1];
+} RegisterMapMethodPool;
+
+/*
+ * Header for the memory-mapped RegisterMap pool in the DEX file.
+ *
+ * The classDataOffset table provides offsets from the start of the
+ * RegisterMapPool structure.  There is one entry per class (including
+ * interfaces, which can have static initializers).
+ *
+ * The offset points to a RegisterMapMethodPool.
+ *
+ * These structures are 32-bit aligned.
+ */
+typedef struct RegisterMapClassPool {
+    u4      numClasses;
+
+    /* offset table starts here, 32-bit aligned; offset==0 means no data */
+    u4      classDataOffset[1];
+} RegisterMapClassPool;
+
+/*
+ * Find the register maps for this class.  (Used during class loading.)
+ * If "pNumMaps" is non-NULL, it will return the number of maps in the set.
+ *
+ * Returns NULL if none is available.
+ */
+const void* dvmRegisterMapGetClassData(const DexFile* pDexFile, u4 classIdx,
+    u4* pNumMaps);
+
+/*
+ * Get the register map for the next method.  "*pPtr" will be advanced past
+ * the end of the map.  (Used during class loading.)
+ *
+ * This should initially be called with the result from
+ * dvmRegisterMapGetClassData().
+ */
+const RegisterMap* dvmRegisterMapGetNext(const void** pPtr);
+
+/*
+ * This holds some meta-data while we construct the set of register maps
+ * for a DEX file.
+ *
+ * In particular, it keeps track of our temporary mmap region so we can
+ * free it later.
+ */
+typedef struct RegisterMapBuilder {
+    /* public */
+    void*       data;
+    size_t      size;
+
+    /* private */
+    MemMapping  memMap;
+} RegisterMapBuilder;
+
+/*
+ * Generate a register map set for all verified classes in "pDvmDex".
+ */
+RegisterMapBuilder* dvmGenerateRegisterMaps(DvmDex* pDvmDex);
+
+/*
+ * Free the builder.
+ */
+void dvmFreeRegisterMapBuilder(RegisterMapBuilder* pBuilder);
+
+
 /*
  * Generate the register map for a previously-verified method.
  *
@@ -97,4 +280,31 @@
  */
 RegisterMap* dvmGenerateRegisterMapV(VerifierData* vdata);
 
+/*
+ * Get the expanded form of the register map associated with the specified
+ * method.  May update method->registerMap, possibly freeing the previous
+ * map.
+ *
+ * Returns NULL on failure (e.g. unable to expand map).
+ *
+ * NOTE: this function is not synchronized; external locking is mandatory.
+ * (This is expected to be called at GC time.)
+ */
+const RegisterMap* dvmGetExpandedRegisterMap0(Method* method);
+INLINE const RegisterMap* dvmGetExpandedRegisterMap(Method* method)
+{
+    const RegisterMap* curMap = method->registerMap;
+    if (curMap == NULL)
+        return NULL;
+    RegisterMapFormat format = dvmRegisterMapGetFormat(curMap);
+    if (format == kRegMapFormatCompact8 || format == kRegMapFormatCompact16) {
+        return curMap;
+    } else {
+        return dvmGetExpandedRegisterMap0(method);
+    }
+}
+
+/* dump stats gathered during register map creation process */
+void dvmRegisterMapDumpStats(void);
+
 #endif /*_DALVIK_REGISTERMAP*/
diff --git a/vm/analysis/VerifySubs.c b/vm/analysis/VerifySubs.c
index 8dcc6f8..39d6dc8 100644
--- a/vm/analysis/VerifySubs.c
+++ b/vm/analysis/VerifySubs.c
@@ -65,6 +65,8 @@
             if (width == 0) {
                 LOG_VFY_METH(meth,
                     "VFY: invalid post-opt instruction (0x%x)\n", instr);
+                LOGI("### instr=%d width=%d table=%d\n",
+                    instr, width, dexGetInstrWidthAbs(gDvm.instrWidth, instr));
                 goto bail;
             }
             if (width < 0 || width > 5) {
diff --git a/vm/analysis/VerifySubs.h b/vm/analysis/VerifySubs.h
index 4d5b57c..a87c6f1 100644
--- a/vm/analysis/VerifySubs.h
+++ b/vm/analysis/VerifySubs.h
@@ -57,7 +57,11 @@
 #define LOG_VFY_METH(_meth, ...)    dvmLogVerifyFailure(_meth, __VA_ARGS__)
 
 /* log verification failure with optional method info */
-void dvmLogVerifyFailure(const Method* meth, const char* format, ...);
+void dvmLogVerifyFailure(const Method* meth, const char* format, ...)
+#if defined(__GNUC__)
+    __attribute__ ((format(printf, 2, 3)))
+#endif
+    ;
 
 /* log verification failure due to resolution trouble */
 void dvmLogUnableToResolveClass(const char* missingClassDescr,
diff --git a/vm/arch/arm/CallEABI.S b/vm/arch/arm/CallEABI.S
index a98473f..9717e3b 100644
--- a/vm/arch/arm/CallEABI.S
+++ b/vm/arch/arm/CallEABI.S
@@ -154,7 +154,7 @@
     subeq   r3, r3, #1
 
     @ Do we have arg padding flags in "argInfo"? (just need to check hi bit)
-    teqs    r2, #0
+    teq     r2, #0
     bmi     .Lno_arg_info
 
     /*
@@ -239,7 +239,12 @@
 
     @ call the method
     ldr     ip, [r4, #8]                @ func
+#ifdef __ARM_HAVE_BLX
     blx     ip
+#else
+    mov     lr, pc
+    bx      ip
+#endif
 
     @ We're back, result is in r0 or (for long/double) r0-r1.
     @
diff --git a/vm/arch/sh/CallSH4ABI.S b/vm/arch/sh/CallSH4ABI.S
new file mode 100644
index 0000000..f8b2ddc
--- /dev/null
+++ b/vm/arch/sh/CallSH4ABI.S
@@ -0,0 +1,400 @@
+/*
+ * 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.
+ */
+/*
+ * Invoking JNI native method via SH4 ABI.
+ * This inplementation follows the spec found in following URL.
+ * http://www.ecos.sourceware.org/docs-1.3.1/ref/gnupro-ref/sh/SH_ch01.html#pgfId-461254
+
+ * This version supports SH4A little endian.
+ */
+    .text
+    .align 4
+    .type  dvmPlatformInvoke, #function
+    .globl dvmPlatformInvoke
+
+/*
+ * @param r4 void* pEnv  (used as scrach after invoking method)
+ * @param r5 ClassObject* clazz
+ * @param r6 int argInfo
+ * @param r7 int argc
+ * @param r15[0] const u4 * argv
+ * @param r15[1] const char * shorty
+ * @param r15[2] void * func
+ * @param r15[3] JValue * pReturn
+ *
+ * @remark r0,r1  Scratch before invoking method.
+ *                Return value after invoking method.
+ * @remark r2  shorty pointer
+ * @remark r3  argv pointer before invoking method.
+ *             pReturn after invoking method.
+ * @remark r8-11 Don't touch.
+ * @remark r12 status of r5-7
+ * @remark r13 status of fr4-11
+ * @remark r14 Keep stack pointer.
+ */
+dvmPlatformInvoke:
+    ## save preserved regsiters
+    mov.l   r14, @-r15
+    mov     r15, r14
+    add     #4, r14             /* r14 = original r15 = stack pointer */
+    mov.l   r13, @-r15
+    mov.l   r12, @-r15
+    sts.l   pr, @-r15
+
+    # fetch arguments
+    mov.l   @r14, r3            /* argv */
+    mov.l   @(4,r14), r2        /* shorty for argumnets */
+    mov     #1, r0              /* shorty's 1st byte specify ret value type. */
+    add     r0, r2
+
+### initialize local variables
+
+    ## r12 ... status of r6, and r7
+    ##          bit 1 << 0 : if r6 is available, it contains 1.
+    ##          bit 1 << 1 : if r7 is available, it contains 1.
+    ##  Note : r4 is always used to pass pEnv.
+    ##         r5 is always used for clazz or object
+    mov     #3, r12             /* b0000-0111 : r5-7 avialble. */
+
+    ## r13 ... status of fr4-fr11
+    ##          bit 1 << 0 : if fr4 is available, it contains 1.
+    ##          bit 1 << 1 : if fr5 is available, it contains 1.
+    ##      ...
+    ##          bit 1 << 7 : if fr11 is available, it contains 1.
+    mov     #0xFF, r13          /* b1111-1111 : fr4-11 avialble. */
+
+### put arguments
+
+    ## ... keep pEnv in r4 as is.
+
+    ## check clazz
+    mov     #0, r0
+    cmp/eq  r0, r5
+    bf      arg_loop            /* if r5 has clazz, keep it as is */
+    mov.l   @r3+, r5            /* put object arg in r5 */
+
+    ## other args
+arg_loop:
+one_arg_handled:
+    mov.b   @r2+, r0
+    cmp/eq  #0, r0              /* if (*shorty == '\0) */
+    bf      process_one_arg
+    bra     arg_end             /* no argument left */
+    nop
+
+process_one_arg:
+
+    ## check arg type
+
+    cmp/eq  #'F', r0
+    bt      jfloat_arg
+
+    cmp/eq  #'D', r0
+    bt      jdouble_arg
+
+    cmp/eq  #'J', r0
+    bt      jlong_arg
+
+    ## other 32bit arg types
+    mov     r12, r0
+    cmp/eq  #0, r0
+    bt      put_32bit_on_stack  /* r6-7 not available */
+
+    tst     #1, r0
+    bt      j32_arg_1
+    mov.l   @r3+, r6            /* put one arg in r6 */
+    mov     #1, r0              /* r6 is not available now. */
+    not     r0, r0
+    and     r0, r12
+    bra     one_arg_handled
+    nop
+j32_arg_1:
+    tst     #2, r0
+    bt      j32_arg_fatal_error
+    mov.l   @r3+, r7            /* put one arg in r7 */
+    mov     #2, r0              /* r7 is not available now. */
+    not     r0, r0
+    and     r0, r12
+    bra     one_arg_handled
+    nop
+
+j32_arg_fatal_error:
+    bra     j32_arg_fatal_error
+    nop
+
+jlong_arg:
+    mov     r12, r0
+    cmp/eq  #0, r0
+    bt      put_64bit_on_stack  /* r6-7 not available */
+
+    and     #3, r0
+    cmp/eq  #3, r0
+    bf      put_64bit_on_stack  /* consequent two registers not available. */
+    mov.l   @r3+, r6            /* put one arg in r6 and r7 */
+    mov.l   @r3+, r7
+    mov     #3, r0              /* r6 and r7 are not available now. */
+    not     r0, r0
+    and     r0, r12
+    bra     one_arg_handled
+    nop
+
+    # utility routines are placed here make short range jumps available.
+put_32bit_on_stack:
+    mov.l   @r3+, r0
+    mov.l   r0, @-r15
+    bra     one_arg_handled
+    nop
+
+put_64bit_on_stack:
+    mov.l   @r3+, r0
+    mov.l   r0, @-r15           /* Pay attention that the endianness is */
+    mov.l   @r3+, r0            /* once reversed.  It is corrected when the */
+    mov.l   r0, @-r15           /* arguments on stack are revesred before */
+    bra     one_arg_handled     /* jni call */
+    nop
+
+jdouble_arg:
+    mov     r13, r0
+    cmp/eq  #0, r0
+    bt      put_64bit_on_stack  /* fr4-11 not available */
+
+    and     #3, r0
+    cmp/eq  #3, r0
+    bf      jdouble_arg_1
+
+    fmov.s  @r3+, fr5           /* put one arg to drX */
+    fmov.s  @r3+, fr4
+    mov     #3, r0              /* fr4-frX not available now. */
+    not     r0, r0
+    and     r0, r13
+    bra     one_arg_handled
+    nop
+
+jdouble_arg_1:
+    mov     r13, r0
+    and     #12, r0
+    cmp/eq  #12, r0
+    bf      jdouble_arg_2
+
+    fmov.s  @r3+, fr7           /* put one arg to drX */
+    fmov.s  @r3+, fr6
+    mov     #15, r0             /* fr4-frX not available now. */
+    not     r0, r0
+    and     r0, r13
+    bra     one_arg_handled
+    nop
+
+jdouble_arg_2:
+    mov     r13, r0
+    and     #48, r0
+    cmp/eq  #48, r0
+    bf      jdouble_arg_3
+    fmov.s  @r3+, fr9           /* put one arg to drX */
+    fmov.s  @r3+, fr8
+    mov     #63, r0             /* fr4-frX not available now. */
+    not     r0, r0
+    and     r0, r13
+    bra     one_arg_handled
+    nop
+
+jdouble_arg_3:
+    mov     r13, r0
+    and     #192, r0
+    cmp/eq  #192, r0
+    bf      put_64bit_on_stack
+    fmov.s  @r3+, fr11          /* put one arg to drX */
+    fmov.s  @r3+, fr10
+    mov     #0, r13             /* fr4-fr11 all not available now. */
+    bra     one_arg_handled
+    nop
+
+jfloat_arg:
+    mov     r13, r0
+    cmp/eq  #0, r0
+    bt      put_32bit_on_stack  /* fr4-11 not available */
+
+    tst     #2, r0
+    bt      jfloat_arg_1
+    fmov.s  @r3+, fr5           /* put one arg to frX */
+    mov     #2, r0              /* frX not available now. */
+    not     r0, r0
+    and     r0, r13
+    bra     one_arg_handled
+    nop
+
+jfloat_arg_1:
+    tst     #1, r0
+    bt      jfloat_arg_2
+    fmov.s  @r3+, fr4           /* put one arg to frX */
+    mov     #1, r0              /* frX not available now. */
+    not     r0, r0
+    and     r0, r13
+    bra     one_arg_handled
+    nop
+
+jfloat_arg_2:
+    tst     #8, r0
+    bt      jfloat_arg_3
+    fmov.s  @r3+, fr7           /* put one arg to frX */
+    mov     #8, r0              /* frX not available now. */
+    not     r0, r0
+    and     r0, r13
+    bra     one_arg_handled
+    nop
+
+jfloat_arg_3:
+    tst     #4, r0
+    bt      jfloat_arg_4
+    fmov.s  @r3+, fr6           /* put one arg to frX */
+    mov     #4, r0              /* frX not available now. */
+    not     r0, r0
+    and     r0, r13
+    bra     one_arg_handled
+    nop
+
+jfloat_arg_4:
+    tst     #32, r0
+    bt      jfloat_arg_5
+    fmov.s  @r3+, fr9           /* put one arg to frX */
+    mov     #32, r0             /* frX not available now. */
+    not     r0, r0
+    and     r0, r13
+    bra     one_arg_handled
+    nop
+
+jfloat_arg_5:
+    tst     #16, r0
+    bt      jfloat_arg_6
+    fmov.s  @r3+, fr8           /* put one arg to frX */
+    mov     #16, r0             /* frX not available now. */
+    not     r0, r0
+    and     r0, r13
+    bra     one_arg_handled
+    nop
+
+jfloat_arg_6:
+    tst     #128, r0
+    bt      jfloat_arg_7
+    fmov.s  @r3+, fr11          /* put one arg to frX */
+    mov     #127, r0            /* frX not available now. */
+    not     r0, r0
+    and     r0, r13
+    bra     one_arg_handled
+    nop
+
+jfloat_arg_7:
+    tst     #64, r0
+    bt      jfloat_fatal_error
+    fmov.s  @r3+, fr10          /* put one arg to frX */
+    mov     #64, r0             /* frX not available now. */
+    not     r0, r0
+    and     r0, r13
+    bra     one_arg_handled
+    nop
+
+jfloat_fatal_error:
+    bra     jfloat_fatal_error:
+    nop
+
+arg_end:
+
+
+### reverse the variables on stack
+    mov     r14, r12            /* points to first arg on stack */
+    add     #-20, r12
+    mov     r15, r13            /* points to last arg on stack */
+arg_rev_loop:
+    cmp/hs  r12, r13            /* When r13 >= r12 (unsigned), 1->T */
+    bt      arg_rev_end
+    mov.l   @r12, r0
+    mov.l   @r13, r1
+    mov.l   r0, @r13
+    mov.l   r1, @r12
+    add     #-4, r12
+    add     #4, r13
+    bra     arg_rev_loop
+    nop
+
+arg_rev_end:
+
+### invoke the JNI function.
+
+    mov.l   @(8,r14), r0
+    jsr     @r0
+    nop
+
+### pass the return value
+
+    /*
+     * r0 and r1 keep return value.
+     */
+
+    ## fetch data
+    mov.l   @(4,r14), r2        /* reload shorty */
+    mov.b   @r2, r2             /* first byte specifyes return value type. */
+    mov.l   @(12,r14), r3       /* pReturn */
+
+    ## check return value types
+
+    mov     #'V', r4
+    cmp/eq  r4, r2
+    bt      end
+
+    mov     #'F', r4
+    cmp/eq  r4, r2
+    bt      jfloat_ret
+
+    mov     #'D', r4
+    cmp/eq  r4, r2
+    bt      jdouble_ret
+
+    mov     #'J', r4
+    cmp/eq  r4, r2
+    bt      jlong_ret
+
+    ## fall-through for other 32 bit java types.
+
+    ## load return values
+j32_ret:
+    bra     end
+    mov.l   r0, @r3             /* delay slot */
+
+jfloat_ret:
+    bra     end
+    fmov.s  fr0, @r3            /* delay slot */
+
+jdouble_ret:
+    fmov.s  fr1, @r3
+    mov     #4, r0
+    bra     end
+    fmov.s  fr0, @(r0,r3)       /* delay slot */
+
+jlong_ret:
+    mov.l   r0, @r3
+    bra     end
+    mov.l   r1, @(4,r3)         /* delay slot */
+
+end:
+    ## restore preserved registers
+    mov     r14, r15
+    add     #-16, r15
+    lds.l   @r15+, pr
+    mov.l   @r15+, r12
+    mov.l   @r15+, r13
+    mov.l   @r15+, r14
+
+    rts                         /* dvmPlatformInvoke returns void. */
+    nop
diff --git a/vm/arch/x86/Call386ABI.S b/vm/arch/x86/Call386ABI.S
index 9e32bdd..c98876c 100644
--- a/vm/arch/x86/Call386ABI.S
+++ b/vm/arch/x86/Call386ABI.S
@@ -131,12 +131,32 @@
     /* Is FP? */
     cmpl     $2,%ebx
     jle      isFP
-    /* No need to distinguish between 32/64 - just save both */
+    cmpl     $4,%ebx  /* smaller than 32-bits? */
+    jg       isSmall
+storeRetval:
+    /* Blindly storing 64-bits won't hurt 32-bit case */
     movl     %eax,(%ecx)
     movl     %edx,4(%ecx)
     jmp      cleanUpAndExit
+isSmall:
+    cmpl     $7,%ebx  /* S1? */
+    jne      checkShort
+    movsbl   %al,%eax
+    movl     %eax,(%ecx)
+    jmp      cleanUpAndExit
+checkShort:
+    cmpl     $6,%ebx  /* U2? */
+    jne      isSignedShort
+    movzwl   %ax,%eax
+    movl     %eax,(%ecx)
+    jmp      cleanUpAndExit
+isSignedShort:
+    /* Must be S2 */
+    movswl   %ax,%eax
+    movl     %eax,(%ecx)
+    jmp      cleanUpAndExit
 isFP:
-    /* Is single? */
+    /* Is Float? */
     cmpl    $1,%ebx
     je       saveFloat
     fstpl    (%ecx)
diff --git a/vm/compiler/Compiler.c b/vm/compiler/Compiler.c
new file mode 100644
index 0000000..203a080
--- /dev/null
+++ b/vm/compiler/Compiler.c
@@ -0,0 +1,256 @@
+/*
+ * 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 <sys/mman.h>
+#include <errno.h>
+
+#include "Dalvik.h"
+#include "interp/Jit.h"
+#include "CompilerInternals.h"
+
+
+static inline bool workQueueLength(void)
+{
+    return gDvmJit.compilerQueueLength;
+}
+
+static CompilerWorkOrder workDequeue(void)
+{
+    assert(gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkDequeueIndex].kind
+           != kWorkOrderInvalid);
+    CompilerWorkOrder work =
+        gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkDequeueIndex];
+    gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkDequeueIndex++].kind =
+        kWorkOrderInvalid;
+    if (gDvmJit.compilerWorkDequeueIndex == COMPILER_WORK_QUEUE_SIZE) {
+        gDvmJit.compilerWorkDequeueIndex = 0;
+    }
+    gDvmJit.compilerQueueLength--;
+
+    /* Remember the high water mark of the queue length */
+    if (gDvmJit.compilerQueueLength > gDvmJit.compilerMaxQueued)
+        gDvmJit.compilerMaxQueued = gDvmJit.compilerQueueLength;
+
+    return work;
+}
+
+bool dvmCompilerWorkEnqueue(const u2 *pc, WorkOrderKind kind, void* info)
+{
+    int cc;
+    int i;
+    int numWork;
+
+    dvmLockMutex(&gDvmJit.compilerLock);
+
+    /* Queue full */
+    if (gDvmJit.compilerQueueLength == COMPILER_WORK_QUEUE_SIZE ||
+        gDvmJit.codeCacheFull == true) {
+        dvmUnlockMutex(&gDvmJit.compilerLock);
+        return false;
+    }
+
+    for (numWork = gDvmJit.compilerQueueLength,
+           i = gDvmJit.compilerWorkDequeueIndex;
+         numWork > 0;
+         numWork--) {
+        /* Already enqueued */
+        if (gDvmJit.compilerWorkQueue[i++].pc == pc)
+            goto done;
+        /* Wrap around */
+        if (i == COMPILER_WORK_QUEUE_SIZE)
+            i = 0;
+    }
+
+    gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkEnqueueIndex].pc = pc;
+    gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkEnqueueIndex].kind = kind;
+    gDvmJit.compilerWorkQueue[gDvmJit.compilerWorkEnqueueIndex].info = info;
+    gDvmJit.compilerWorkEnqueueIndex++;
+    if (gDvmJit.compilerWorkEnqueueIndex == COMPILER_WORK_QUEUE_SIZE)
+        gDvmJit.compilerWorkEnqueueIndex = 0;
+    gDvmJit.compilerQueueLength++;
+    cc = pthread_cond_signal(&gDvmJit.compilerQueueActivity);
+    assert(cc == 0);
+
+done:
+    dvmUnlockMutex(&gDvmJit.compilerLock);
+    return true;
+}
+
+/* Block until queue length is 0 */
+void dvmCompilerDrainQueue(void)
+{
+    dvmLockMutex(&gDvmJit.compilerLock);
+    while (workQueueLength() != 0 && !gDvmJit.haltCompilerThread) {
+        pthread_cond_wait(&gDvmJit.compilerQueueEmpty, &gDvmJit.compilerLock);
+    }
+    dvmUnlockMutex(&gDvmJit.compilerLock);
+}
+
+static void *compilerThreadStart(void *arg)
+{
+    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;
+            cc = pthread_cond_signal(&gDvmJit.compilerQueueEmpty);
+            assert(cc == 0);
+            pthread_cond_wait(&gDvmJit.compilerQueueActivity,
+                              &gDvmJit.compilerLock);
+            continue;
+        } else {
+            do {
+                CompilerWorkOrder work = workDequeue();
+                dvmUnlockMutex(&gDvmJit.compilerLock);
+                /* Check whether there is a suspend request on me */
+                dvmCheckSuspendPending(NULL);
+                /* Is JitTable filling up? */
+                if (gDvmJit.jitTableEntriesUsed >
+                    (gDvmJit.jitTableSize - gDvmJit.jitTableSize/4)) {
+                    dvmJitResizeJitTable(gDvmJit.jitTableSize * 2);
+                }
+                if (gDvmJit.haltCompilerThread) {
+                    LOGD("Compiler shutdown in progress - discarding request");
+                } else {
+                    /* Compilation is successful */
+                    if (dvmCompilerDoWork(&work)) {
+                        dvmJitSetCodeAddr(work.pc, work.result.codeAddress,
+                                          work.result.instructionSet);
+                    }
+                }
+                free(work.info);
+                dvmLockMutex(&gDvmJit.compilerLock);
+            } while (workQueueLength() != 0);
+        }
+    }
+    pthread_cond_signal(&gDvmJit.compilerQueueEmpty);
+    dvmUnlockMutex(&gDvmJit.compilerLock);
+
+    LOGD("Compiler thread shutting down\n");
+    return NULL;
+}
+
+bool dvmCompilerSetupCodeCache(void)
+{
+    extern void dvmCompilerTemplateStart(void);
+    extern void dmvCompilerTemplateEnd(void);
+
+    /* Allocate the code cache */
+    gDvmJit.codeCache = mmap(0, CODE_CACHE_SIZE,
+                          PROT_READ | PROT_WRITE | PROT_EXEC,
+                          MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+    if (gDvmJit.codeCache == MAP_FAILED) {
+        LOGE("Failed to create the code cache: %s\n", strerror(errno));
+        return false;
+    }
+
+    /* Copy the template code into the beginning of the code cache */
+    int templateSize = (intptr_t) dmvCompilerTemplateEnd -
+                       (intptr_t) dvmCompilerTemplateStart;
+    memcpy((void *) gDvmJit.codeCache,
+           (void *) dvmCompilerTemplateStart,
+           templateSize);
+
+    gDvmJit.templateSize = templateSize;
+    gDvmJit.codeCacheByteUsed = templateSize;
+
+    /* Flush dcache and invalidate the icache to maintain coherence */
+    cacheflush((intptr_t) gDvmJit.codeCache,
+               (intptr_t) gDvmJit.codeCache + CODE_CACHE_SIZE, 0);
+    return true;
+}
+
+bool dvmCompilerStartup(void)
+{
+    /* Make sure the BBType enum is in sane state */
+    assert(CHAINING_CELL_NORMAL == 0);
+
+    /* Architecture-specific chores to initialize */
+    if (!dvmCompilerArchInit())
+        goto fail;
+
+    /*
+     * Setup the code cache if it is not done so already. For apps it should be
+     * done by the Zygote already, but for command-line dalvikvm invocation we
+     * need to do it here.
+     */
+    if (gDvmJit.codeCache == NULL) {
+        if (!dvmCompilerSetupCodeCache())
+            goto fail;
+    }
+
+    /* Allocate the initial arena block */
+    if (dvmCompilerHeapInit() == false) {
+        goto fail;
+    }
+
+    dvmInitMutex(&gDvmJit.compilerLock);
+    pthread_cond_init(&gDvmJit.compilerQueueActivity, NULL);
+    pthread_cond_init(&gDvmJit.compilerQueueEmpty, NULL);
+
+    dvmLockMutex(&gDvmJit.compilerLock);
+
+    gDvmJit.haltCompilerThread = false;
+
+    /* Reset the work queue */
+    memset(gDvmJit.compilerWorkQueue, 0,
+           sizeof(CompilerWorkOrder) * COMPILER_WORK_QUEUE_SIZE);
+    gDvmJit.compilerWorkEnqueueIndex = gDvmJit.compilerWorkDequeueIndex = 0;
+    gDvmJit.compilerQueueLength = 0;
+    gDvmJit.compilerHighWater =
+        COMPILER_WORK_QUEUE_SIZE - (COMPILER_WORK_QUEUE_SIZE/4);
+
+    assert(gDvmJit.compilerHighWater < COMPILER_WORK_QUEUE_SIZE);
+    if (!dvmCreateInternalThread(&gDvmJit.compilerHandle, "Compiler",
+                                 compilerThreadStart, NULL)) {
+        dvmUnlockMutex(&gDvmJit.compilerLock);
+        goto fail;
+    }
+
+    /* Track method-level compilation statistics */
+    gDvmJit.methodStatsTable =  dvmHashTableCreate(32, NULL);
+
+    dvmUnlockMutex(&gDvmJit.compilerLock);
+
+    return true;
+
+fail:
+    return false;
+}
+
+void dvmCompilerShutdown(void)
+{
+    void *threadReturn;
+
+    if (gDvmJit.compilerHandle) {
+
+        gDvmJit.haltCompilerThread = true;
+
+        dvmLockMutex(&gDvmJit.compilerLock);
+        pthread_cond_signal(&gDvmJit.compilerQueueActivity);
+        dvmUnlockMutex(&gDvmJit.compilerLock);
+
+        if (pthread_join(gDvmJit.compilerHandle, &threadReturn) != 0)
+            LOGW("Compiler thread join failed\n");
+        else
+            LOGD("Compiler thread has shut down\n");
+    }
+}
diff --git a/vm/compiler/Compiler.h b/vm/compiler/Compiler.h
new file mode 100644
index 0000000..3b7ae54
--- /dev/null
+++ b/vm/compiler/Compiler.h
@@ -0,0 +1,125 @@
+/*
+ * 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_COMPILER
+#define _DALVIK_VM_COMPILER
+
+#define CODE_CACHE_SIZE                 1024*1024
+#define MAX_JIT_RUN_LEN                 64
+#define COMPILER_WORK_QUEUE_SIZE        100
+
+#define COMPILER_TRACED(X)
+#define COMPILER_TRACEE(X)
+#define COMPILER_TRACE_CHAINING(X)
+
+typedef enum JitInstructionSetType {
+    DALVIK_JIT_NONE = 0,
+    DALVIK_JIT_ARM,
+    DALVIK_JIT_THUMB,
+    DALVIK_JIT_THUMB2,
+    DALVIK_JIT_THUMB2EE,
+    DALVIK_JIT_X86
+} JitInstructionSetType;
+
+/* Description of a compiled trace. */
+typedef struct JitTranslationInfo {
+    void     *codeAddress;
+    JitInstructionSetType instructionSet;
+} JitTranslationInfo;
+
+typedef enum WorkOrderKind {
+    kWorkOrderInvalid = 0,      // Should never see by the backend
+    kWorkOrderMethod = 1,       // Work is to compile a whole method
+    kWorkOrderTrace = 2,        // Work is to compile code fragment(s)
+} WorkOrderKind;
+
+typedef struct CompilerWorkOrder {
+    const u2* pc;
+    WorkOrderKind kind;
+    void* info;
+    JitTranslationInfo result;
+} CompilerWorkOrder;
+
+typedef enum JitState {
+    kJitOff = 0,
+    kJitNormal = 1,            // Profiling in mterp or running native
+    kJitTSelectRequest = 2,    // Transition state - start trace selection
+    kJitTSelect = 3,           // Actively selecting trace in dbg interp
+    kJitTSelectAbort = 4,      // Something threw during selection - abort
+    kJitTSelectEnd = 5,        // Done with the trace - wrap it up
+    kJitSingleStep = 6,        // Single step interpretation
+    kJitSingleStepEnd = 7,     // Done with single step, return to mterp
+} JitState;
+
+typedef enum JitHint {
+   kJitHintNone = 0,
+   kJitHintTaken = 1,         // Last inst in run was taken branch
+   kJitHintNotTaken = 2,      // Last inst in run was not taken branch
+   kJitHintNoBias = 3,        // Last inst in run was unbiased branch
+} jitHint;
+
+/*
+ * Element of a Jit trace description.  Describes a contiguous
+ * sequence of Dalvik byte codes, the last of which can be
+ * associated with a hint.
+ * Dalvik byte code
+ */
+typedef struct {
+    u2    startOffset;       // Starting offset for trace run
+    unsigned numInsts:8;     // Number of Byte codes in run
+    unsigned runEnd:1;       // Run ends with last byte code
+    jitHint  hint:7;         // Hint to apply to final code of run
+} JitCodeDesc;
+
+typedef union {
+    JitCodeDesc frag;
+    void*       hint;
+} JitTraceRun;
+
+/*
+ * Trace description as will appear in the translation cache.  Note
+ * flexible array at end, as these will be of variable size.  To
+ * conserve space in the translation cache, total length of JitTraceRun
+ * array must be recomputed via seqential scan if needed.
+ */
+typedef struct {
+    const Method* method;
+    JitTraceRun trace[];
+} JitTraceDescription;
+
+typedef struct CompilerMethodStats {
+    const Method *method;       // Used as hash entry signature
+    int dalvikSize;             // # of bytes for dalvik bytecodes
+    int compiledDalvikSize;     // # of compiled dalvik bytecodes
+    int nativeSize;             // # of bytes for produced native code
+} CompilerMethodStats;
+
+bool dvmCompilerSetupCodeCache(void);
+bool dvmCompilerArchInit(void);
+void dvmCompilerArchDump(void);
+bool dvmCompilerStartup(void);
+void dvmCompilerShutdown(void);
+bool dvmCompilerWorkEnqueue(const u2* pc, WorkOrderKind kind, void* info);
+void *dvmCheckCodeCache(void *method);
+bool dvmCompileMethod(const Method *method, JitTranslationInfo *info);
+bool dvmCompileTrace(JitTraceDescription *trace, int numMaxInsts,
+                     JitTranslationInfo *info);
+void dvmCompilerDumpStats(void);
+void dvmCompilerDrainQueue(void);
+void dvmJitUnchainAll(void);
+void dvmCompilerSortAndPrintTraceProfiles(void);
+
+#endif /* _DALVIK_VM_COMPILER */
diff --git a/vm/compiler/CompilerIR.h b/vm/compiler/CompilerIR.h
new file mode 100644
index 0000000..d61d2ee
--- /dev/null
+++ b/vm/compiler/CompilerIR.h
@@ -0,0 +1,108 @@
+/*
+ * 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 "codegen/Optimizer.h"
+
+#ifndef _DALVIK_VM_COMPILER_IR
+#define _DALVIK_VM_COMPILER_IR
+
+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_LAST,
+    DALVIK_BYTECODE,
+    PC_RECONSTRUCTION,
+    EXCEPTION_HANDLING,
+} BBType;
+
+typedef struct ChainCellCounts {
+    union {
+        u1 count[CHAINING_CELL_LAST];
+        u4 dummyForAlignment;
+    } u;
+} ChainCellCounts;
+
+typedef struct LIR {
+    int offset;
+    struct LIR *next;
+    struct LIR *prev;
+    struct LIR *target;
+} LIR;
+
+typedef struct MIR {
+    DecodedInstruction dalvikInsn;
+    unsigned int width;
+    unsigned int offset;
+    struct MIR *prev;
+    struct MIR *next;
+} MIR;
+
+typedef struct BasicBlock {
+    int id;
+    int visited;
+    unsigned int startOffset;
+    const Method *containingMethod;     // For blocks from the callee
+    BBType blockType;
+    bool needFallThroughBranch;         // For blocks ended due to length limit
+    MIR *firstMIRInsn;
+    MIR *lastMIRInsn;
+    struct BasicBlock *fallThrough;
+    struct BasicBlock *taken;
+    struct BasicBlock *next;            // Serial link for book keeping purposes
+} BasicBlock;
+
+typedef struct CompilationUnit {
+    int numInsts;
+    int numBlocks;
+    BasicBlock **blockList;
+    const Method *method;
+    const JitTraceDescription *traceDesc;
+    LIR *firstLIRInsn;
+    LIR *lastLIRInsn;
+    LIR *wordList;
+    LIR *chainCellOffsetLIR;
+    GrowableList pcReconstructionList;
+    int headerSize;                     // bytes before the first code ptr
+    int dataOffset;                     // starting offset of literal pool
+    int totalSize;                      // header + code size
+    unsigned char *codeBuffer;
+    void *baseAddr;
+    bool printMe;
+    bool allSingleStep;
+    bool halveInstCount;
+    bool executionCount;                // Add code to count trace executions
+    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;
+} CompilationUnit;
+
+BasicBlock *dvmCompilerNewBB(BBType blockType);
+
+void dvmCompilerAppendMIR(BasicBlock *bb, MIR *mir);
+
+void dvmCompilerAppendLIR(CompilationUnit *cUnit, LIR *lir);
+
+void dvmCompilerInsertLIRBefore(LIR *currentLIR, LIR *newLIR);
+
+/* Debug Utilities */
+void dvmCompilerDumpCompilationUnit(CompilationUnit *cUnit);
+
+#endif /* _DALVIK_VM_COMPILER_IR */
diff --git a/vm/compiler/CompilerInternals.h b/vm/compiler/CompilerInternals.h
new file mode 100644
index 0000000..410213a
--- /dev/null
+++ b/vm/compiler/CompilerInternals.h
@@ -0,0 +1,26 @@
+/*
+ * 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_COMPILER_INTERNAL
+#define _DALVIK_VM_COMPILER_INTERNAL
+
+#include "Dalvik.h"
+#include "CompilerUtility.h"
+#include "CompilerIR.h"
+#include "codegen/CompilerCodegen.h"
+#include "interp/Jit.h"
+
+#endif /* _DALVIK_VM_COMPILER_INTERNAL */
diff --git a/vm/compiler/CompilerUtility.h b/vm/compiler/CompilerUtility.h
new file mode 100644
index 0000000..7b4de11
--- /dev/null
+++ b/vm/compiler/CompilerUtility.h
@@ -0,0 +1,44 @@
+/*
+ * 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_COMPILER_UTILITY
+#define _DALVIK_VM_COMPILER_UTILITY
+
+#define ARENA_DEFAULT_SIZE 4096
+
+/* Allocate the initial memory block for arena-based allocation */
+bool dvmCompilerHeapInit(void);
+
+typedef struct ArenaMemBlock {
+    size_t bytesAllocated;
+    struct ArenaMemBlock *next;
+    char ptr[0];
+} ArenaMemBlock;
+
+void *dvmCompilerNew(size_t size, bool zero);
+
+void dvmCompilerArenaReset(void);
+
+typedef struct GrowableList {
+    size_t numAllocated;
+    size_t numUsed;
+    void **elemList;
+} GrowableList;
+
+void dvmInitGrowableList(GrowableList *gList, size_t initLength);
+void dvmInsertGrowableList(GrowableList *gList, void *elem);
+
+#endif /* _DALVIK_COMPILER_UTILITY */
diff --git a/vm/compiler/Frontend.c b/vm/compiler/Frontend.c
new file mode 100644
index 0000000..66060a0
--- /dev/null
+++ b/vm/compiler/Frontend.c
@@ -0,0 +1,752 @@
+/*
+ * 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 "libdex/OpCode.h"
+#include "dexdump/OpCodeNames.h"
+#include "interp/Jit.h"
+#include "CompilerInternals.h"
+
+/*
+ * Parse an instruction, return the length of the instruction
+ */
+static inline int parseInsn(const u2 *codePtr, DecodedInstruction *decInsn,
+                            bool printMe)
+{
+    u2 instr = *codePtr;
+    OpCode opcode = instr & 0xff;
+    int insnWidth;
+
+    // Don't parse instruction data
+    if (opcode == OP_NOP && instr != 0) {
+        return 0;
+    } else {
+        insnWidth = gDvm.instrWidth[opcode];
+        if (insnWidth < 0) {
+            insnWidth = -insnWidth;
+        }
+    }
+
+    dexDecodeInstruction(gDvm.instrFormat, codePtr, decInsn);
+    if (printMe) {
+        LOGD("%p: %#06x %s\n", codePtr, opcode, getOpcodeName(opcode));
+    }
+    return insnWidth;
+}
+
+/*
+ * Identify block-ending instructions and collect supplemental information
+ * regarding the following instructions.
+ */
+static inline bool findBlockBoundary(const Method *caller, MIR *insn,
+                                     unsigned int curOffset,
+                                     unsigned int *target, bool *isInvoke,
+                                     const Method **callee)
+{
+    switch (insn->dalvikInsn.opCode) {
+        /* Target is not compile-time constant */
+        case OP_RETURN_VOID:
+        case OP_RETURN:
+        case OP_RETURN_WIDE:
+        case OP_RETURN_OBJECT:
+        case OP_THROW:
+        case OP_INVOKE_VIRTUAL:
+        case OP_INVOKE_VIRTUAL_RANGE:
+        case OP_INVOKE_INTERFACE:
+        case OP_INVOKE_INTERFACE_RANGE:
+        case OP_INVOKE_VIRTUAL_QUICK:
+        case OP_INVOKE_VIRTUAL_QUICK_RANGE:
+            *isInvoke = true;
+            break;
+        case OP_INVOKE_SUPER:
+        case OP_INVOKE_SUPER_RANGE: {
+            int mIndex = caller->clazz->pDvmDex->
+                pResMethods[insn->dalvikInsn.vB]->methodIndex;
+            const Method *calleeMethod =
+                caller->clazz->super->vtable[mIndex];
+
+            if (calleeMethod && !dvmIsNativeMethod(calleeMethod)) {
+                *target = (unsigned int) calleeMethod->insns;
+            }
+            *isInvoke = true;
+            *callee = calleeMethod;
+            break;
+        }
+        case OP_INVOKE_STATIC:
+        case OP_INVOKE_STATIC_RANGE: {
+            const Method *calleeMethod =
+                caller->clazz->pDvmDex->pResMethods[insn->dalvikInsn.vB];
+
+            if (calleeMethod && !dvmIsNativeMethod(calleeMethod)) {
+                *target = (unsigned int) calleeMethod->insns;
+            }
+            *isInvoke = true;
+            *callee = calleeMethod;
+            break;
+        }
+        case OP_INVOKE_SUPER_QUICK:
+        case OP_INVOKE_SUPER_QUICK_RANGE: {
+            const Method *calleeMethod =
+                caller->clazz->super->vtable[insn->dalvikInsn.vB];
+
+            if (calleeMethod && !dvmIsNativeMethod(calleeMethod)) {
+                *target = (unsigned int) calleeMethod->insns;
+            }
+            *isInvoke = true;
+            *callee = calleeMethod;
+            break;
+        }
+        case OP_INVOKE_DIRECT:
+        case OP_INVOKE_DIRECT_RANGE: {
+            const Method *calleeMethod =
+                caller->clazz->pDvmDex->pResMethods[insn->dalvikInsn.vB];
+            if (calleeMethod && !dvmIsNativeMethod(calleeMethod)) {
+                *target = (unsigned int) calleeMethod->insns;
+            }
+            *isInvoke = true;
+            *callee = calleeMethod;
+            break;
+        }
+        case OP_GOTO:
+        case OP_GOTO_16:
+        case OP_GOTO_32:
+            *target = curOffset + (int) insn->dalvikInsn.vA;
+            break;
+
+        case OP_IF_EQ:
+        case OP_IF_NE:
+        case OP_IF_LT:
+        case OP_IF_GE:
+        case OP_IF_GT:
+        case OP_IF_LE:
+            *target = curOffset + (int) insn->dalvikInsn.vC;
+            break;
+
+        case OP_IF_EQZ:
+        case OP_IF_NEZ:
+        case OP_IF_LTZ:
+        case OP_IF_GEZ:
+        case OP_IF_GTZ:
+        case OP_IF_LEZ:
+            *target = curOffset + (int) insn->dalvikInsn.vB;
+            break;
+
+        default:
+            return false;
+    } return true;
+}
+
+/*
+ * Identify conditional branch instructions
+ */
+static inline bool isUnconditionalBranch(MIR *insn)
+{
+    switch (insn->dalvikInsn.opCode) {
+        case OP_RETURN_VOID:
+        case OP_RETURN:
+        case OP_RETURN_WIDE:
+        case OP_RETURN_OBJECT:
+        case OP_GOTO:
+        case OP_GOTO_16:
+        case OP_GOTO_32:
+            return true;
+        default:
+            return false;
+    }
+}
+
+/*
+ * dvmHashTableLookup() callback
+ */
+static int compareMethod(const CompilerMethodStats *m1,
+                         const CompilerMethodStats *m2)
+{
+    return (int) m1->method - (int) m2->method;
+}
+
+/*
+ * Analyze each method whose traces are ever compiled. Collect a variety of
+ * statistics like the ratio of exercised vs overall code and code bloat
+ * ratios.
+ */
+static CompilerMethodStats *analyzeMethodBody(const Method *method)
+{
+    const DexCode *dexCode = dvmGetMethodCode(method);
+    const u2 *codePtr = dexCode->insns;
+    const u2 *codeEnd = dexCode->insns + dexCode->insnsSize;
+    int insnSize = 0;
+    int hashValue = dvmComputeUtf8Hash(method->name);
+
+    CompilerMethodStats dummyMethodEntry; // For hash table lookup
+    CompilerMethodStats *realMethodEntry; // For hash table storage
+
+    /* For lookup only */
+    dummyMethodEntry.method = method;
+    realMethodEntry = dvmHashTableLookup(gDvmJit.methodStatsTable, hashValue,
+                                         &dummyMethodEntry,
+                                         (HashCompareFunc) compareMethod,
+                                         false);
+
+    /* Part of this method has been compiled before - just return the entry */
+    if (realMethodEntry != NULL) {
+        return realMethodEntry;
+    }
+
+    /*
+     * First time to compile this method - set up a new entry in the hash table
+     */
+    realMethodEntry =
+        (CompilerMethodStats *) calloc(1, sizeof(CompilerMethodStats));
+    realMethodEntry->method = method;
+
+    dvmHashTableLookup(gDvmJit.methodStatsTable, hashValue,
+                       realMethodEntry,
+                       (HashCompareFunc) compareMethod,
+                       true);
+
+    /* Count the number of instructions */
+    while (codePtr < codeEnd) {
+        DecodedInstruction dalvikInsn;
+        int width = parseInsn(codePtr, &dalvikInsn, false);
+
+        /* Terminate when the data section is seen */
+        if (width == 0)
+            break;
+
+        insnSize += width;
+        codePtr += width;
+    }
+
+    realMethodEntry->dalvikSize = insnSize * 2;
+    return realMethodEntry;
+}
+
+/*
+ * Main entry point to start trace compilation. Basic blocks are constructed
+ * first and they will be passed to the codegen routines to convert Dalvik
+ * bytecode into machine code.
+ */
+bool dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts,
+                     JitTranslationInfo *info)
+{
+    const DexCode *dexCode = dvmGetMethodCode(desc->method);
+    const JitTraceRun* currRun = &desc->trace[0];
+    unsigned int curOffset = currRun->frag.startOffset;
+    unsigned int numInsts = currRun->frag.numInsts;
+    const u2 *codePtr = dexCode->insns + curOffset;
+    int traceSize = 0;  // # of half-words
+    const u2 *startCodePtr = codePtr;
+    BasicBlock *startBB, *curBB, *lastBB;
+    int numBlocks = 0;
+    static int compilationId;
+    CompilationUnit cUnit;
+    CompilerMethodStats *methodStats;
+
+    compilationId++;
+    memset(&cUnit, 0, sizeof(CompilationUnit));
+
+    /* Locate the entry to store compilation statistics for this method */
+    methodStats = analyzeMethodBody(desc->method);
+
+    cUnit.registerScoreboard.nullCheckedRegs =
+        dvmAllocBitVector(desc->method->registersSize, false);
+
+    /* Initialize the printMe flag */
+    cUnit.printMe = gDvmJit.printMe;
+
+    /* Initialize the profile flag */
+    cUnit.executionCount = gDvmJit.profile;
+
+    /* Identify traces that we don't want to compile */
+    if (gDvmJit.methodTable) {
+        int len = strlen(desc->method->clazz->descriptor) +
+                  strlen(desc->method->name) + 1;
+        char *fullSignature = dvmCompilerNew(len, true);
+        strcpy(fullSignature, desc->method->clazz->descriptor);
+        strcat(fullSignature, desc->method->name);
+
+        int hashValue = dvmComputeUtf8Hash(fullSignature);
+
+        /*
+         * Doing three levels of screening to see whether we want to skip
+         * compiling this method
+         */
+
+        /* First, check the full "class;method" signature */
+        bool methodFound =
+            dvmHashTableLookup(gDvmJit.methodTable, hashValue,
+                               fullSignature, (HashCompareFunc) strcmp,
+                               false) !=
+            NULL;
+
+        /* Full signature not found - check the enclosing class */
+        if (methodFound == false) {
+            int hashValue = dvmComputeUtf8Hash(desc->method->clazz->descriptor);
+            methodFound =
+                dvmHashTableLookup(gDvmJit.methodTable, hashValue,
+                               (char *) desc->method->clazz->descriptor,
+                               (HashCompareFunc) strcmp, false) !=
+                NULL;
+            /* Enclosing class not found - check the method name */
+            if (methodFound == false) {
+                int hashValue = dvmComputeUtf8Hash(desc->method->name);
+                methodFound =
+                    dvmHashTableLookup(gDvmJit.methodTable, hashValue,
+                                   (char *) desc->method->name,
+                                   (HashCompareFunc) strcmp, false) !=
+                    NULL;
+            }
+        }
+
+        /*
+         * Under the following conditions, the trace will be *conservatively*
+         * compiled by only containing single-step instructions to and from the
+         * interpreter.
+         * 1) If includeSelectedMethod == false, the method matches the full or
+         *    partial signature stored in the hash table.
+         *
+         * 2) If includeSelectedMethod == true, the method does not match the
+         *    full and partial signature stored in the hash table.
+         */
+        if (gDvmJit.includeSelectedMethod != methodFound) {
+            cUnit.allSingleStep = true;
+        } else {
+            /* Compile the trace as normal */
+
+            /* Print the method we cherry picked */
+            if (gDvmJit.includeSelectedMethod == true) {
+                cUnit.printMe = true;
+            }
+        }
+    }
+
+    /* Allocate the first basic block */
+    lastBB = startBB = curBB = dvmCompilerNewBB(DALVIK_BYTECODE);
+    curBB->startOffset = curOffset;
+    curBB->id = numBlocks++;
+
+    if (cUnit.printMe) {
+        LOGD("--------\nCompiler: Building trace for %s, offset 0x%x\n",
+             desc->method->name, curOffset);
+    }
+
+    /*
+     * Analyze the trace descriptor and include up to the maximal number
+     * of Dalvik instructions into the IR.
+     */
+    while (1) {
+        MIR *insn;
+        int width;
+        insn = dvmCompilerNew(sizeof(MIR),false);
+        insn->offset = curOffset;
+        width = parseInsn(codePtr, &insn->dalvikInsn, cUnit.printMe);
+
+        /* The trace should never incude instruction data */
+        assert(width);
+        insn->width = width;
+        traceSize += width;
+        dvmCompilerAppendMIR(curBB, insn);
+        cUnit.numInsts++;
+        /* Instruction limit reached - terminate the trace here */
+        if (cUnit.numInsts >= numMaxInsts) {
+            break;
+        }
+        if (--numInsts == 0) {
+            if (currRun->frag.runEnd) {
+                break;
+            } else {
+                curBB = dvmCompilerNewBB(DALVIK_BYTECODE);
+                lastBB->next = curBB;
+                lastBB = curBB;
+                curBB->id = numBlocks++;
+                currRun++;
+                curOffset = currRun->frag.startOffset;
+                numInsts = currRun->frag.numInsts;
+                curBB->startOffset = curOffset;
+                codePtr = dexCode->insns + curOffset;
+            }
+        } else {
+            curOffset += width;
+            codePtr += width;
+        }
+    }
+
+    /* Convert # of half-word to bytes */
+    methodStats->compiledDalvikSize += traceSize * 2;
+
+    /*
+     * Now scan basic blocks containing real code to connect the
+     * taken/fallthrough links. Also create chaining cells for code not included
+     * in the trace.
+     */
+    for (curBB = startBB; curBB; curBB = curBB->next) {
+        MIR *lastInsn = curBB->lastMIRInsn;
+        /* Hit a pseudo block - exit the search now */
+        if (lastInsn == NULL) {
+            break;
+        }
+        curOffset = lastInsn->offset;
+        unsigned int targetOffset = curOffset;
+        unsigned int fallThroughOffset = curOffset + lastInsn->width;
+        bool isInvoke = false;
+        const Method *callee = NULL;
+
+        findBlockBoundary(desc->method, curBB->lastMIRInsn, curOffset,
+                          &targetOffset, &isInvoke, &callee);
+
+        /* Link the taken and fallthrough blocks */
+        BasicBlock *searchBB;
+
+        /* No backward branch in the trace - start searching the next BB */
+        for (searchBB = curBB->next; searchBB; searchBB = searchBB->next) {
+            if (targetOffset == searchBB->startOffset) {
+                curBB->taken = searchBB;
+            }
+            if (fallThroughOffset == searchBB->startOffset) {
+                curBB->fallThrough = searchBB;
+            }
+        }
+
+        int flags = dexGetInstrFlags(gDvm.instrFlags,
+                                     lastInsn->dalvikInsn.opCode);
+
+        /*
+         * Some blocks are ended by non-control-flow-change instructions,
+         * currently only due to trace length constraint. In this case we need
+         * to generate an explicit branch at the end of the block to jump to
+         * the chaining cell.
+         *
+         * NOTE: INVOKE_DIRECT_EMPTY is actually not an invoke but a nop
+         */
+        curBB->needFallThroughBranch =
+            ((flags & (kInstrCanBranch | kInstrCanSwitch | kInstrCanReturn |
+                       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;
+            }
+            newBB->id = numBlocks++;
+            curBB->taken = newBB;
+            lastBB->next = newBB;
+            lastBB = newBB;
+        }
+
+        /* Fallthrough block not included in the trace */
+        if (!isUnconditionalBranch(lastInsn) && curBB->fallThrough == NULL) {
+            /*
+             * If the chaining cell is after an invoke or
+             * instruction that cannot change the control flow, request a hot
+             * chaining cell.
+             */
+            if (isInvoke || curBB->needFallThroughBranch) {
+                lastBB->next = dvmCompilerNewBB(CHAINING_CELL_HOT);
+            } else {
+                lastBB->next = dvmCompilerNewBB(CHAINING_CELL_NORMAL);
+            }
+            lastBB = lastBB->next;
+            lastBB->id = numBlocks++;
+            lastBB->startOffset = fallThroughOffset;
+            curBB->fallThrough = lastBB;
+        }
+    }
+
+    /* Now create a special block to host PC reconstruction code */
+    lastBB->next = dvmCompilerNewBB(PC_RECONSTRUCTION);
+    lastBB = lastBB->next;
+    lastBB->id = numBlocks++;
+
+    /* And one final block that publishes the PC and raise the exception */
+    lastBB->next = dvmCompilerNewBB(EXCEPTION_HANDLING);
+    lastBB = lastBB->next;
+    lastBB->id = numBlocks++;
+
+    if (cUnit.printMe) {
+        LOGD("TRACEINFO (%d): 0x%08x %s%s 0x%x %d of %d, %d blocks",
+            compilationId,
+            (intptr_t) desc->method->insns,
+            desc->method->clazz->descriptor,
+            desc->method->name,
+            desc->trace[0].frag.startOffset,
+            traceSize,
+            dexCode->insnsSize,
+            numBlocks);
+    }
+
+    BasicBlock **blockList;
+
+    cUnit.method = desc->method;
+    cUnit.traceDesc = desc;
+    cUnit.numBlocks = numBlocks;
+    dvmInitGrowableList(&cUnit.pcReconstructionList, 8);
+    blockList = cUnit.blockList =
+        dvmCompilerNew(sizeof(BasicBlock *) * numBlocks, true);
+
+    int i;
+
+    for (i = 0, curBB = startBB; i < numBlocks; i++) {
+        blockList[i] = curBB;
+        curBB = curBB->next;
+    }
+    /* Make sure all blocks are added to the cUnit */
+    assert(curBB == NULL);
+
+    if (cUnit.printMe) {
+        dvmCompilerDumpCompilationUnit(&cUnit);
+    }
+
+    /* Set the instruction set to use (NOTE: later components may change it) */
+    cUnit.instructionSet = dvmCompilerInstructionSet(&cUnit);
+
+    /* Convert MIR to LIR, etc. */
+    dvmCompilerMIR2LIR(&cUnit);
+
+    /* Convert LIR into machine code. */
+    dvmCompilerAssembleLIR(&cUnit, info);
+
+    if (cUnit.printMe) {
+        if (cUnit.halveInstCount) {
+            LOGD("Assembler aborted");
+        } else {
+            dvmCompilerCodegenDump(&cUnit);
+        }
+        LOGD("End %s%s, %d Dalvik instructions",
+             desc->method->clazz->descriptor, desc->method->name,
+             cUnit.numInsts);
+    }
+
+    /* Reset the compiler resource pool */
+    dvmCompilerArenaReset();
+
+    /* Free the bit vector tracking null-checked registers */
+    dvmFreeBitVector(cUnit.registerScoreboard.nullCheckedRegs);
+
+    if (!cUnit.halveInstCount) {
+    /* Success */
+        methodStats->nativeSize += cUnit.totalSize;
+        return info->codeAddress != NULL;
+
+    /* Halve the instruction count and retry again */
+    } else {
+        return dvmCompileTrace(desc, cUnit.numInsts / 2, info);
+    }
+}
+
+/*
+ * Similar to dvmCompileTrace, but the entity processed here is the whole
+ * method.
+ *
+ * TODO: implementation will be revisited when the trace builder can provide
+ * whole-method traces.
+ */
+bool dvmCompileMethod(const Method *method, JitTranslationInfo *info)
+{
+    const DexCode *dexCode = dvmGetMethodCode(method);
+    const u2 *codePtr = dexCode->insns;
+    const u2 *codeEnd = dexCode->insns + dexCode->insnsSize;
+    int blockID = 0;
+    unsigned int curOffset = 0;
+
+    BasicBlock *firstBlock = dvmCompilerNewBB(DALVIK_BYTECODE);
+    firstBlock->id = blockID++;
+
+    /* Allocate the bit-vector to track the beginning of basic blocks */
+    BitVector *bbStartAddr = dvmAllocBitVector(dexCode->insnsSize+1, false);
+    dvmSetBit(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);
+        insn->offset = curOffset;
+        int width = parseInsn(codePtr, &insn->dalvikInsn, false);
+        bool isInvoke = false;
+        const Method *callee;
+        insn->width = width;
+
+        /* Terminate when the data section is seen */
+        if (width == 0)
+            break;
+        dvmCompilerAppendMIR(firstBlock, insn);
+        /*
+         * Check whether this is a block ending instruction and whether it
+         * suggests the start of a new block
+         */
+        unsigned int target = curOffset;
+
+        /*
+         * If findBlockBoundary returns true, it means the current instruction
+         * is terminating the current block. If it is a branch, the target
+         * address will be recorded in target.
+         */
+        if (findBlockBoundary(method, insn, curOffset, &target, &isInvoke,
+                              &callee)) {
+            dvmSetBit(bbStartAddr, curOffset + width);
+            if (target != curOffset) {
+                dvmSetBit(bbStartAddr, target);
+            }
+        }
+
+        codePtr += width;
+        /* each bit represents 16-bit quantity */
+        curOffset += width;
+    }
+
+    /*
+     * The number of blocks will be equal to the number of bits set to 1 in the
+     * bit vector minus 1, because the bit representing the location after the
+     * last instruction is set to one.
+     */
+    int numBlocks = dvmCountSetBits(bbStartAddr);
+    if (dvmIsBitSet(bbStartAddr, dexCode->insnsSize)) {
+        numBlocks--;
+    }
+
+    CompilationUnit cUnit;
+    BasicBlock **blockList;
+
+    memset(&cUnit, 0, sizeof(CompilationUnit));
+    cUnit.method = method;
+    blockList = cUnit.blockList =
+        dvmCompilerNew(sizeof(BasicBlock *) * numBlocks, true);
+
+    /*
+     * Register the first block onto the list and start split it into block
+     * boundaries from there.
+     */
+    blockList[0] = firstBlock;
+    cUnit.numBlocks = 1;
+
+    int i;
+    for (i = 0; i < numBlocks; i++) {
+        MIR *insn;
+        BasicBlock *curBB = blockList[i];
+        curOffset = curBB->lastMIRInsn->offset;
+
+        for (insn = curBB->firstMIRInsn->next; insn; insn = insn->next) {
+            /* Found the beginning of a new block, see if it is created yet */
+            if (dvmIsBitSet(bbStartAddr, insn->offset)) {
+                int j;
+                for (j = 0; j < cUnit.numBlocks; j++) {
+                    if (blockList[j]->firstMIRInsn->offset == insn->offset)
+                        break;
+                }
+
+                /* Block not split yet - do it now */
+                if (j == cUnit.numBlocks) {
+                    BasicBlock *newBB = dvmCompilerNewBB(DALVIK_BYTECODE);
+                    newBB->id = blockID++;
+                    newBB->firstMIRInsn = insn;
+                    newBB->startOffset = insn->offset;
+                    newBB->lastMIRInsn = curBB->lastMIRInsn;
+                    curBB->lastMIRInsn = insn->prev;
+                    insn->prev->next = NULL;
+                    insn->prev = NULL;
+
+                    /*
+                     * If the insn is not an unconditional branch, set up the
+                     * fallthrough link.
+                     */
+                    if (!isUnconditionalBranch(curBB->lastMIRInsn)) {
+                        curBB->fallThrough = newBB;
+                    }
+
+                    /* enqueue the new block */
+                    blockList[cUnit.numBlocks++] = newBB;
+                    break;
+                }
+            }
+        }
+    }
+
+    if (numBlocks != cUnit.numBlocks) {
+        LOGE("Expect %d vs %d basic blocks\n", numBlocks, cUnit.numBlocks);
+        dvmAbort();
+    }
+
+    dvmFreeBitVector(bbStartAddr);
+
+    /* Connect the basic blocks through the taken links */
+    for (i = 0; i < numBlocks; i++) {
+        BasicBlock *curBB = blockList[i];
+        MIR *insn = curBB->lastMIRInsn;
+        unsigned int target = insn->offset;
+        bool isInvoke;
+        const Method *callee;
+
+        findBlockBoundary(method, insn, target, &target, &isInvoke, &callee);
+
+        /* Found a block ended on a branch */
+        if (target != insn->offset) {
+            int j;
+            /* Forward branch */
+            if (target > insn->offset) {
+                j = i + 1;
+            } else {
+                /* Backward branch */
+                j = 0;
+            }
+            for (; j < numBlocks; j++) {
+                if (blockList[j]->firstMIRInsn->offset == target) {
+                    curBB->taken = blockList[j];
+                    break;
+                }
+            }
+
+            /* Don't create dummy block for the callee yet */
+            if (j == numBlocks && !isInvoke) {
+                LOGE("Target not found for insn %x: expect target %x\n",
+                     curBB->lastMIRInsn->offset, target);
+                dvmAbort();
+            }
+        }
+    }
+
+    /* Set the instruction set to use (NOTE: later components may change it) */
+    cUnit.instructionSet = dvmCompilerInstructionSet(&cUnit);
+
+    dvmCompilerMIR2LIR(&cUnit);
+
+    dvmCompilerAssembleLIR(&cUnit, info);
+
+    dvmCompilerDumpCompilationUnit(&cUnit);
+
+    dvmCompilerArenaReset();
+
+    return info->codeAddress != NULL;
+}
diff --git a/vm/compiler/IntermediateRep.c b/vm/compiler/IntermediateRep.c
new file mode 100644
index 0000000..91b7af7
--- /dev/null
+++ b/vm/compiler/IntermediateRep.c
@@ -0,0 +1,77 @@
+/*
+ * 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"
+
+/* Allocate a new basic block */
+BasicBlock *dvmCompilerNewBB(BBType blockType)
+{
+    BasicBlock *bb = dvmCompilerNew(sizeof(BasicBlock), true);
+    bb->blockType = blockType;
+    return bb;
+}
+
+/* Insert an MIR instruction to the end of a basic block */
+void dvmCompilerAppendMIR(BasicBlock *bb, MIR *mir)
+{
+    if (bb->firstMIRInsn == NULL) {
+        assert(bb->firstMIRInsn == NULL);
+        bb->lastMIRInsn = bb->firstMIRInsn = mir;
+        mir->prev = mir->next = NULL;
+    } else {
+        bb->lastMIRInsn->next = mir;
+        mir->prev = bb->lastMIRInsn;
+        mir->next = NULL;
+        bb->lastMIRInsn = mir;
+    }
+}
+
+/*
+ * Append an LIR instruction to the LIR list maintained by a compilation
+ * unit
+ */
+void dvmCompilerAppendLIR(CompilationUnit *cUnit, LIR *lir)
+{
+    if (cUnit->firstLIRInsn == NULL) {
+        assert(cUnit->lastLIRInsn == NULL);
+        cUnit->lastLIRInsn = cUnit->firstLIRInsn = lir;
+        lir->prev = lir->next = NULL;
+    } else {
+        cUnit->lastLIRInsn->next = lir;
+        lir->prev = cUnit->lastLIRInsn;
+        lir->next = NULL;
+        cUnit->lastLIRInsn = lir;
+    }
+}
+
+/*
+ * Insert an LIR instruction before the current instruction, which cannot be the
+ * first instruction.
+ *
+ * prevLIR <-> newLIR <-> currentLIR
+ */
+void dvmCompilerInsertLIRBefore(LIR *currentLIR, LIR *newLIR)
+{
+    if (currentLIR->prev == NULL)
+        dvmAbort();
+    LIR *prevLIR = currentLIR->prev;
+
+    prevLIR->next = newLIR;
+    newLIR->prev = prevLIR;
+    newLIR->next = currentLIR;
+    currentLIR->prev = newLIR;
+}
diff --git a/vm/compiler/Utility.c b/vm/compiler/Utility.c
new file mode 100644
index 0000000..715f750
--- /dev/null
+++ b/vm/compiler/Utility.c
@@ -0,0 +1,212 @@
+/*
+ * 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"
+
+static ArenaMemBlock *arenaHead, *currentArena;
+static int numArenaBlocks;
+
+/* Allocate the initial memory block for arena-based allocation */
+bool dvmCompilerHeapInit(void)
+{
+    assert(arenaHead == NULL);
+    arenaHead =
+        (ArenaMemBlock *) malloc(sizeof(ArenaMemBlock) + ARENA_DEFAULT_SIZE);
+    if (arenaHead == NULL) {
+        LOGE("No memory left to create compiler heap memory\n");
+        return false;
+    }
+    currentArena = arenaHead;
+    currentArena->bytesAllocated = 0;
+    currentArena->next = NULL;
+    numArenaBlocks = 1;
+
+    return true;
+}
+
+/* Arena-based malloc for compilation tasks */
+void * dvmCompilerNew(size_t size, bool zero)
+{
+    size = (size + 3) & ~3;
+retry:
+    /* Normal case - space is available in the current page */
+    if (size + currentArena->bytesAllocated <= ARENA_DEFAULT_SIZE) {
+        void *ptr;
+        ptr = &currentArena->ptr[currentArena->bytesAllocated];
+        currentArena->bytesAllocated += size;
+        if (zero) {
+            memset(ptr, 0, size);
+        }
+        return ptr;
+    } else {
+        /*
+         * See if there are previously allocated arena blocks before the last
+         * reset
+         */
+        if (currentArena->next) {
+            currentArena = currentArena->next;
+            goto retry;
+        }
+        /*
+         * If we allocate really large variable-sized data structures that
+         * could go above the limit we need to enhance the allocation
+         * mechanism.
+         */
+        if (size > ARENA_DEFAULT_SIZE) {
+            LOGE("Requesting %d bytes which exceed the maximal size allowed\n",
+                 size);
+            return NULL;
+        }
+        /* Time to allocate a new arena */
+        ArenaMemBlock *newArena = (ArenaMemBlock *)
+            malloc(sizeof(ArenaMemBlock) + ARENA_DEFAULT_SIZE);
+        newArena->bytesAllocated = 0;
+        newArena->next = NULL;
+        currentArena->next = newArena;
+        currentArena = newArena;
+        numArenaBlocks++;
+        LOGD("Total arena pages for JIT: %d", numArenaBlocks);
+        goto retry;
+    }
+    return NULL;
+}
+
+/* Reclaim all the arena blocks allocated so far */
+void dvmCompilerArenaReset(void)
+{
+    ArenaMemBlock *block;
+
+    for (block = arenaHead; block; block = block->next) {
+        block->bytesAllocated = 0;
+    }
+    currentArena = arenaHead;
+}
+
+/* Growable List initialization */
+void dvmInitGrowableList(GrowableList *gList, size_t initLength)
+{
+    gList->numAllocated = initLength;
+    gList->numUsed = 0;
+    gList->elemList = (void **) dvmCompilerNew(sizeof(void *) * initLength,
+                                               true);
+}
+
+/* Expand the capacity of a growable list */
+static void expandGrowableList(GrowableList *gList)
+{
+    int newLength = gList->numAllocated;
+    if (newLength < 128) {
+        newLength <<= 1;
+    } else {
+        newLength += 128;
+    }
+    void *newArray = dvmCompilerNew(sizeof(void *) * newLength, true);
+    memcpy(newArray, gList->elemList, sizeof(void *) * gList->numAllocated);
+    gList->numAllocated = newLength;
+    gList->elemList = newArray;
+}
+
+/* Insert a new element into the growable list */
+void dvmInsertGrowableList(GrowableList *gList, void *elem)
+{
+    if (gList->numUsed == gList->numAllocated) {
+        expandGrowableList(gList);
+    }
+    gList->elemList[gList->numUsed++] = elem;
+}
+
+/* Debug Utility - dump a compilation unit */
+void dvmCompilerDumpCompilationUnit(CompilationUnit *cUnit)
+{
+    int i;
+    BasicBlock *bb;
+    LOGD("%d blocks in total\n", cUnit->numBlocks);
+
+    for (i = 0; i < cUnit->numBlocks; i++) {
+        bb = cUnit->blockList[i];
+        LOGD("Block %d (insn %04x - %04x%s)\n",
+             bb->id, bb->startOffset,
+             bb->lastMIRInsn ? bb->lastMIRInsn->offset : bb->startOffset,
+             bb->lastMIRInsn ? "" : " empty");
+        if (bb->taken) {
+            LOGD("  Taken branch: block %d (%04x)\n",
+                 bb->taken->id, bb->taken->startOffset);
+        }
+        if (bb->fallThrough) {
+            LOGD("  Fallthrough : block %d (%04x)\n",
+                 bb->fallThrough->id, bb->fallThrough->startOffset);
+        }
+    }
+}
+
+/*
+ * dvmHashForeach callback.
+ */
+static int dumpMethodStats(void *compilerMethodStats, void *totalMethodStats)
+{
+    CompilerMethodStats *methodStats =
+        (CompilerMethodStats *) compilerMethodStats;
+    CompilerMethodStats *totalStats =
+        (CompilerMethodStats *) totalMethodStats;
+    const Method *method = methodStats->method;
+
+    totalStats->dalvikSize += methodStats->dalvikSize;
+    totalStats->compiledDalvikSize += methodStats->compiledDalvikSize;
+    totalStats->nativeSize += methodStats->nativeSize;
+
+    /* Enable the following when fine-tuning the JIT performance */
+#if 0
+    int limit = (methodStats->dalvikSize >> 2) * 3;
+
+    /* If over 3/4 of the Dalvik code is compiled, print something */
+    if (methodStats->compiledDalvikSize >= limit) {
+        LOGD("Method stats: %s%s, %d/%d (compiled/total Dalvik), %d (native)",
+             method->clazz->descriptor, method->name,
+             methodStats->compiledDalvikSize,
+             methodStats->dalvikSize,
+             methodStats->nativeSize);
+    }
+#endif
+    return 0;
+}
+
+/*
+ * Dump the current stats of the compiler, including number of bytes used in
+ * the code cache, arena size, and work queue length, and various JIT stats.
+ */
+void dvmCompilerDumpStats(void)
+{
+    CompilerMethodStats totalMethodStats;
+
+    memset(&totalMethodStats, 0, sizeof(CompilerMethodStats));
+    LOGD("%d compilations using %d + %d bytes",
+         gDvmJit.numCompilations,
+         gDvmJit.templateSize,
+         gDvmJit.codeCacheByteUsed - gDvmJit.templateSize);
+    LOGD("Compiler arena uses %d blocks (%d bytes each)",
+         numArenaBlocks, ARENA_DEFAULT_SIZE);
+    LOGD("Compiler work queue length is %d/%d", gDvmJit.compilerQueueLength,
+         gDvmJit.compilerMaxQueued);
+    dvmJitStats();
+    dvmCompilerArchDump();
+    dvmHashForeach(gDvmJit.methodStatsTable, dumpMethodStats,
+                   &totalMethodStats);
+    LOGD("Code size stats: %d/%d (compiled/total Dalvik), %d (native)",
+         totalMethodStats.compiledDalvikSize,
+         totalMethodStats.dalvikSize,
+         totalMethodStats.nativeSize);
+}
diff --git a/vm/compiler/codegen/CompilerCodegen.h b/vm/compiler/codegen/CompilerCodegen.h
new file mode 100644
index 0000000..c9e6bd6
--- /dev/null
+++ b/vm/compiler/codegen/CompilerCodegen.h
@@ -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.
+ */
+
+#include "../CompilerIR.h"
+
+#ifndef _DALVIK_VM_COMPILERCODEGEN_H_
+#define _DALVIK_VM_COMPILERCODEGEN_H_
+
+/* Work unit is architecture dependent */
+bool dvmCompilerDoWork(CompilerWorkOrder *work);
+
+/* Lower middle-level IR to low-level IR */
+void dvmCompilerMIR2LIR(CompilationUnit *cUnit);
+
+/* Assemble LIR into machine code */
+void dvmCompilerAssembleLIR(CompilationUnit *cUnit, JitTranslationInfo *info);
+
+/* Implemented in the codegen/<target>/ArchUtility.c */
+void dvmCompilerCodegenDump(CompilationUnit *cUnit);
+
+/* Implemented in the codegen/<target>/Assembler.c */
+void* dvmJitChain(void *tgtAddr, u4* branchAddr);
+u4* dvmJitUnchain(void *codeAddr);
+void dvmJitUnchainAll(void);
+
+/* Implemented in codegen/<target>/<target_variant>/ArchVariant.c */
+JitInstructionSetType dvmCompilerInstructionSet(CompilationUnit *cUnit);
+
+#endif /* _DALVIK_VM_COMPILERCODEGEN_H_ */
diff --git a/vm/compiler/codegen/Optimizer.h b/vm/compiler/codegen/Optimizer.h
new file mode 100644
index 0000000..1a891b1
--- /dev/null
+++ b/vm/compiler/codegen/Optimizer.h
@@ -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.
+ */
+
+#include "Dalvik.h"
+#include "compiler/CompilerInternals.h"
+
+#ifndef _DALVIK_VM_COMPILER_OPTIMIZATION_H
+#define _DALVIK_VM_COMPILER_OPTIMIZATION_H
+
+/* Forward declarations */
+struct CompilationUnit;
+struct LIR;
+
+/*
+ * Data structure tracking the mapping between a Dalvik register (pair) and a
+ * native register (pair). The idea is to reuse the previously loaded value
+ * if possible, otherwise to keep the value in a native register as long as
+ * possible.
+ */
+typedef struct RegisterScoreboard {
+    BitVector *nullCheckedRegs; // Track which registers have been null-checked
+    int liveDalvikReg;          // Track which Dalvik register is live
+    int nativeReg;              // And the mapped native register
+    int nativeRegHi;            // And the mapped native register
+    bool isWide;                // Whether a pair of registers are alive
+} RegisterScoreboard;
+
+void dvmCompilerApplyLocalOptimizations(struct CompilationUnit *cUnit,
+                                        struct LIR *head,
+                                        struct LIR *tail);
+
+void dvmCompilerApplyGlobalOptimizations(struct CompilationUnit *cUnit);
+
+#endif /* _DALVIK_VM_COMPILER_OPTIMIZATION_H */
diff --git a/vm/compiler/codegen/arm/ArchUtility.c b/vm/compiler/codegen/arm/ArchUtility.c
new file mode 100644
index 0000000..60c5cdb
--- /dev/null
+++ b/vm/compiler/codegen/arm/ArchUtility.c
@@ -0,0 +1,264 @@
+/*
+ * 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 "../../CompilerInternals.h"
+#include "dexdump/OpCodeNames.h"
+#include "ArmLIR.h"
+
+/* Decode and print a ARM register name */
+static char * decodeRegList(int vector, char *buf)
+{
+    int i;
+    bool printed = false;
+    buf[0] = 0;
+    for (i = 0; i < 8; i++, vector >>= 1) {
+        if (vector & 0x1) {
+            if (printed) {
+                sprintf(buf + strlen(buf), ", r%d", i);
+            } else {
+                printed = true;
+                sprintf(buf, "r%d", i);
+            }
+        }
+    }
+    return buf;
+}
+
+static int expandImmediate(int value)
+{
+    int mode = (value & 0xf00) >> 8;
+    u4 bits = value & 0xff;
+    switch(mode) {
+        case 0:
+            return bits;
+       case 1:
+            return (bits << 16) | bits;
+       case 2:
+            return (bits << 24) | (bits << 8);
+       case 3:
+            return (bits << 24) | (bits << 16) | (bits << 8) | bits;
+      default:
+            break;
+    }
+    bits = (bits | 0x80) << 24;
+    return bits >> (((value & 0xf80) >> 7) - 8);
+}
+
+/*
+ * Interpret a format string and build a string no longer than size
+ * See format key in Assemble.c.
+ */
+static void buildInsnString(char *fmt, ArmLIR *lir, char* buf,
+                            unsigned char *baseAddr, int size)
+{
+    int i;
+    char *bufEnd = &buf[size-1];
+    char *fmtEnd = &fmt[strlen(fmt)];
+    char tbuf[256];
+    char nc;
+    while (fmt < fmtEnd) {
+        int operand;
+        if (*fmt == '!') {
+            fmt++;
+            assert(fmt < fmtEnd);
+            nc = *fmt++;
+            if (nc=='!') {
+                strcpy(tbuf, "!");
+            } else {
+               assert(fmt < fmtEnd);
+               assert((unsigned)(nc-'0') < 3);
+               operand = lir->operands[nc-'0'];
+               switch(*fmt++) {
+                   case 'm':
+                       operand = expandImmediate(operand);
+                       sprintf(tbuf,"%d [0x%x]", operand, operand);
+                       break;
+                   case 's':
+                       sprintf(tbuf,"s%d",operand & FP_REG_MASK);
+                       break;
+                   case 'S':
+                       sprintf(tbuf,"d%d",(operand & FP_REG_MASK) >> 1);
+                       break;
+                   case 'h':
+                       sprintf(tbuf,"%04x", operand);
+                       break;
+                   case 'M':
+                   case 'd':
+                       sprintf(tbuf,"%d", operand);
+                       break;
+                   case 'D':
+                       sprintf(tbuf,"%d", operand+8);
+                       break;
+                   case 'E':
+                       sprintf(tbuf,"%d", operand*4);
+                       break;
+                   case 'F':
+                       sprintf(tbuf,"%d", operand*2);
+                       break;
+                   case 'c':
+                       switch (operand) {
+                           case ARM_COND_EQ:
+                               strcpy(tbuf, "beq");
+                               break;
+                           case ARM_COND_NE:
+                               strcpy(tbuf, "bne");
+                               break;
+                           case ARM_COND_LT:
+                               strcpy(tbuf, "blt");
+                               break;
+                           case ARM_COND_GE:
+                               strcpy(tbuf, "bge");
+                               break;
+                           case ARM_COND_GT:
+                               strcpy(tbuf, "bgt");
+                               break;
+                           case ARM_COND_LE:
+                               strcpy(tbuf, "ble");
+                               break;
+                           case ARM_COND_CS:
+                               strcpy(tbuf, "bcs");
+                               break;
+                           case ARM_COND_MI:
+                               strcpy(tbuf, "bmi");
+                               break;
+                           default:
+                               strcpy(tbuf, "");
+                               break;
+                       }
+                       break;
+                   case 't':
+                       sprintf(tbuf,"0x%08x",
+                               (int) baseAddr + lir->generic.offset + 4 +
+                               (operand << 1));
+                       break;
+                   case 'u': {
+                       int offset_1 = lir->operands[0];
+                       int offset_2 = NEXT_LIR(lir)->operands[0];
+                       intptr_t target =
+                           ((((intptr_t) baseAddr + lir->generic.offset + 4) &
+                            ~3) + (offset_1 << 21 >> 9) + (offset_2 << 1)) &
+                           0xfffffffc;
+                       sprintf(tbuf, "%p", (void *) target);
+                       break;
+                    }
+
+                   /* Nothing to print for BLX_2 */
+                   case 'v':
+                       strcpy(tbuf, "see above");
+                       break;
+                   case 'R':
+                       decodeRegList(operand, tbuf);
+                       break;
+                   default:
+                       strcpy(tbuf,"DecodeError");
+                       break;
+               }
+               if (buf+strlen(tbuf) <= bufEnd) {
+                   strcpy(buf, tbuf);
+                   buf += strlen(tbuf);
+               } else {
+                   break;
+               }
+            }
+        } else {
+           *buf++ = *fmt++;
+        }
+        if (buf == bufEnd)
+            break;
+    }
+    *buf = 0;
+}
+
+/* Pretty-print a LIR instruction */
+static void dumpLIRInsn(LIR *arg, unsigned char *baseAddr)
+{
+    ArmLIR *lir = (ArmLIR *) arg;
+    char buf[256];
+    char opName[256];
+    int offset = lir->generic.offset;
+    int dest = lir->operands[0];
+    u2 *cPtr = (u2*)baseAddr;
+    /* Handle pseudo-ops individually, and all regular insns as a group */
+    switch(lir->opCode) {
+        case ARM_PSEUDO_TARGET_LABEL:
+            break;
+        case ARM_PSEUDO_CHAINING_CELL_NORMAL:
+            LOGD("-------- chaining cell (normal): 0x%04x\n", dest);
+            break;
+        case ARM_PSEUDO_CHAINING_CELL_HOT:
+            LOGD("-------- chaining cell (hot): 0x%04x\n", dest);
+            break;
+        case ARM_PSEUDO_CHAINING_CELL_INVOKE_PREDICTED:
+            LOGD("-------- chaining cell (predicted)\n");
+            break;
+        case ARM_PSEUDO_CHAINING_CELL_INVOKE_SINGLETON:
+            LOGD("-------- chaining cell (invoke singleton): %s/%p\n",
+                 ((Method *)dest)->name,
+                 ((Method *)dest)->insns);
+            break;
+        case ARM_PSEUDO_DALVIK_BYTECODE_BOUNDARY:
+            LOGD("-------- dalvik offset: 0x%04x @ %s\n", dest,
+                   getOpcodeName(lir->operands[1]));
+            break;
+        case ARM_PSEUDO_ALIGN4:
+            LOGD("%p (%04x): .align4\n", baseAddr + offset, offset);
+            break;
+        case ARM_PSEUDO_PC_RECONSTRUCTION_CELL:
+            LOGD("-------- reconstruct dalvik PC : 0x%04x @ +0x%04x\n", dest,
+                 lir->operands[1]);
+            break;
+        case ARM_PSEUDO_PC_RECONSTRUCTION_BLOCK_LABEL:
+            /* Do nothing */
+            break;
+        case ARM_PSEUDO_EH_BLOCK_LABEL:
+            LOGD("Exception_Handling:\n");
+            break;
+        case ARM_PSEUDO_NORMAL_BLOCK_LABEL:
+            LOGD("L%#06x:\n", dest);
+            break;
+        default:
+            if (lir->isNop) {
+                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);
+            break;
+    }
+}
+
+/* Dump instructions and constant pool contents */
+void dvmCompilerCodegenDump(CompilationUnit *cUnit)
+{
+    LOGD("Dumping LIR insns\n");
+    LIR *lirInsn;
+    ArmLIR *armLIR;
+
+    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);
+    }
+    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,
+             armLIR->operands[0]);
+    }
+}
diff --git a/vm/compiler/codegen/arm/ArmLIR.h b/vm/compiler/codegen/arm/ArmLIR.h
new file mode 100644
index 0000000..59c7529
--- /dev/null
+++ b/vm/compiler/codegen/arm/ArmLIR.h
@@ -0,0 +1,395 @@
+/*
+ * 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 "compiler/CompilerInternals.h"
+
+#ifndef _DALVIK_VM_COMPILER_CODEGEN_ARM_ARMLIR_H
+#define _DALVIK_VM_COMPILER_CODEGEN_ARM_ARMLIR_H
+
+/*
+ * r0, r1, r2, r3 are always scratch
+ * r4 (rPC) is scratch for Jit, but most be restored when resuming interp
+ * r5 (rFP) is reserved [holds Dalvik frame pointer]
+ * 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
+ * r10 is always scratch
+ * r11 (fp) used by gcc unless -fomit-frame-pointer set [available for jit?]
+ * r12 is always scratch
+ * r13 (sp) is reserved
+ * r14 (lr) is scratch for Jit
+ * r15 (pc) is reserved
+ *
+ * For Thumb code use:
+ *       r0, r1, r2, r3 to hold operands/results via scoreboard
+ *       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
+ *
+ * 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)
+ */
+
+/* Offset to distingish FP regs */
+#define FP_REG_OFFSET 32
+/* Offset to distinguish DP FP regs */
+#define FP_DOUBLE 64
+/* Reg types */
+#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
+
+
+typedef enum NativeRegisterPool {
+    r0 = 0,
+    r1 = 1,
+    r2 = 2,
+    r3 = 3,
+    r4PC = 4,
+    rFP = 5,
+    rGLUE = 6,
+    r7 = 7,
+    r8 = 8,
+    r9 = 9,
+    r10 = 10,
+    r11 = 11,
+    r12 = 12,
+    r13 = 13,
+    rlr = 14,
+    rpc = 15,
+    fr0  =  0 + FP_REG_OFFSET,
+    fr1  =  1 + FP_REG_OFFSET,
+    fr2  =  2 + FP_REG_OFFSET,
+    fr3  =  3 + FP_REG_OFFSET,
+    fr4  =  4 + FP_REG_OFFSET,
+    fr5  =  5 + FP_REG_OFFSET,
+    fr6  =  6 + FP_REG_OFFSET,
+    fr7  =  7 + FP_REG_OFFSET,
+    fr8  =  8 + FP_REG_OFFSET,
+    fr9  =  9 + FP_REG_OFFSET,
+    fr10 = 10 + FP_REG_OFFSET,
+    fr11 = 11 + FP_REG_OFFSET,
+    fr12 = 12 + FP_REG_OFFSET,
+    fr13 = 13 + FP_REG_OFFSET,
+    fr14 = 14 + FP_REG_OFFSET,
+    fr15 = 15 + FP_REG_OFFSET,
+    fr16 = 16 + FP_REG_OFFSET,
+    fr17 = 17 + FP_REG_OFFSET,
+    fr18 = 18 + FP_REG_OFFSET,
+    fr19 = 19 + FP_REG_OFFSET,
+    fr20 = 20 + FP_REG_OFFSET,
+    fr21 = 21 + FP_REG_OFFSET,
+    fr22 = 22 + FP_REG_OFFSET,
+    fr23 = 23 + FP_REG_OFFSET,
+    fr24 = 24 + FP_REG_OFFSET,
+    fr25 = 25 + FP_REG_OFFSET,
+    fr26 = 26 + FP_REG_OFFSET,
+    fr27 = 27 + FP_REG_OFFSET,
+    fr28 = 28 + FP_REG_OFFSET,
+    fr29 = 29 + FP_REG_OFFSET,
+    fr30 = 30 + FP_REG_OFFSET,
+    fr31 = 31 + FP_REG_OFFSET,
+    dr0 = fr0 + FP_DOUBLE,
+    dr1 = fr2 + FP_DOUBLE,
+    dr2 = fr4 + FP_DOUBLE,
+    dr3 = fr6 + FP_DOUBLE,
+    dr4 = fr8 + FP_DOUBLE,
+    dr5 = fr10 + FP_DOUBLE,
+    dr6 = fr12 + FP_DOUBLE,
+    dr7 = fr14 + FP_DOUBLE,
+    dr8 = fr16 + FP_DOUBLE,
+    dr9 = fr18 + FP_DOUBLE,
+    dr10 = fr20 + FP_DOUBLE,
+    dr11 = fr22 + FP_DOUBLE,
+    dr12 = fr24 + FP_DOUBLE,
+    dr13 = fr26 + FP_DOUBLE,
+    dr14 = fr28 + FP_DOUBLE,
+    dr15 = fr30 + FP_DOUBLE,
+} NativeRegisterPool;
+
+/* Thumb condition encodings */
+typedef enum ArmConditionCode {
+    ARM_COND_EQ = 0x0,    /* 0000 */
+    ARM_COND_NE = 0x1,    /* 0001 */
+    ARM_COND_LT = 0xb,    /* 1011 */
+    ARM_COND_GE = 0xa,    /* 1010 */
+    ARM_COND_GT = 0xc,    /* 1100 */
+    ARM_COND_LE = 0xd,    /* 1101 */
+    ARM_COND_CS = 0x2,    /* 0010 */
+    ARM_COND_MI = 0x4,    /* 0100 */
+} ArmConditionCode;
+
+#define isPseudoOpCode(opCode) ((int)(opCode) < 0)
+
+/*
+ * The following enum defines the list of supported Thumb instructions by the
+ * assembler. Their corresponding snippet positions will be defined in
+ * Assemble.c.
+ */
+typedef enum ArmOpCode {
+    ARM_PSEUDO_TARGET_LABEL = -11,
+    ARM_PSEUDO_CHAINING_CELL_HOT = -10,
+    ARM_PSEUDO_CHAINING_CELL_INVOKE_PREDICTED = -9,
+    ARM_PSEUDO_CHAINING_CELL_INVOKE_SINGLETON = -8,
+    ARM_PSEUDO_CHAINING_CELL_NORMAL = -7,
+    ARM_PSEUDO_DALVIK_BYTECODE_BOUNDARY = -6,
+    ARM_PSEUDO_ALIGN4 = -5,
+    ARM_PSEUDO_PC_RECONSTRUCTION_CELL = -4,
+    ARM_PSEUDO_PC_RECONSTRUCTION_BLOCK_LABEL = -3,
+    ARM_PSEUDO_EH_BLOCK_LABEL = -2,
+    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_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] */
+    THUMB_ADD_RR_LH,      /* add(4)  [01000100] H12[01] rm[5..3] rd[2..0] */
+    THUMB_ADD_RR_HL,      /* add(4)  [01001000] H12[10] rm[5..3] rd[2..0] */
+    THUMB_ADD_RR_HH,      /* add(4)  [01001100] H12[11] rm[5..3] rd[2..0] */
+    THUMB_ADD_PC_REL,     /* add(5)  [10100] rd[10..8] imm_8[7..0] */
+    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_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_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_BX,             /* bx      [010001110] H2[6..6] rm[5..3] SBZ[000] */
+    THUMB_CMN,            /* 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_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] */
+    THUMB_LDR_PC_REL,     /* ldr(3)  [01001] rd[10..8] imm_8[7..0] */
+    THUMB_LDR_SP_REL,     /* ldr(4)  [10011] rd[10..8] imm_8[7..0] */
+    THUMB_LDRB_RRI5,      /* ldrb(1) [01111] imm_5[10..6] rn[5..3] rd[2..0] */
+    THUMB_LDRB_RRR,       /* ldrb(2) [0101110] rm[8..6] rn[5..3] rd[2..0] */
+    THUMB_LDRH_RRI5,      /* ldrh(1) [10001] imm_5[10..6] rn[5..3] rd[2..0] */
+    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_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] */
+    THUMB_MOV_RR_H2L,     /* mov(3)  [01000110] H12[01] rm[5..3] rd[2..0] */
+    THUMB_MOV_RR_L2H,     /* mov(3)  [01000101] H12[10] rm[5..3] rd[2..0] */
+    THUMB_MUL,            /* mul     [0100001101] rm[5..3] rd[2..0] */
+    THUMB_MVN,            /* mvn     [0100001111] rm[5..3] rd[2..0] */
+    THUMB_NEG,            /* neg     [0100001001] rm[5..3] rd[2..0] */
+    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_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] */
+    THUMB_STR_RRR,        /* str(2)  [0101000] rm[8..6] rn[5..3] rd[2..0] */
+    THUMB_STR_SP_REL,     /* str(3)  [10010] rd[10..8] imm_8[7..0] */
+    THUMB_STRB_RRI5,      /* strb(1) [01110] imm_5[10..6] rn[5..3] rd[2..0] */
+    THUMB_STRB_RRR,       /* strb(2) [0101010] rm[8..6] rn[5..3] rd[2..0] */
+    THUMB_STRH_RRI5,      /* strh(1) [10000] imm_5[10..6] rn[5..3] rd[2..0] */
+    THUMB_STRH_RRR,       /* strh(2) [0101001] rm[8..6] rn[5..3] rd[2..0] */
+    THUMB_SUB_RRI3,       /* sub(1)  [0001111] imm_3[8..6] rn[5..3] rd[2..0]*/
+    THUMB_SUB_RI8,        /* sub(2)  [00111] rd[10..8] imm_8[7..0] */
+    THUMB_SUB_RRR,        /* sub(3)  [0001101] rm[8..6] rn[5..3] rd[2..0] */
+    THUMB_SUB_SPI7,       /* sub(4)  [101100001] imm_7[6..0] */
+    THUMB_SWI,            /* swi     [11011111] imm_8[7..0] */
+    THUMB_TST,            /* tst     [0100001000] rm[5..3] rn[2..0] */
+    THUMB2_VLDRS,         /* vldr low  sx [111011011001] rn[19..16] rd[15-12]
+                                       [1010] imm_8[7..0] */
+    THUMB2_VLDRD,         /* vldr low  dx [111011011001] rn[19..16] rd[15-12]
+                                       [1011] imm_8[7..0] */
+    THUMB2_VMULS,         /* vmul vd, vn, vm [111011100010] rn[19..16]
+                                       rd[15-12] [10100000] rm[3..0] */
+    THUMB2_VMULD,         /* vmul vd, vn, vm [111011100010] rn[19..16]
+                                       rd[15-12] [10110000] rm[3..0] */
+    THUMB2_VSTRS,         /* vstr low  sx [111011011000] rn[19..16] rd[15-12]
+                                       [1010] imm_8[7..0] */
+    THUMB2_VSTRD,         /* vstr low  dx [111011011000] rn[19..16] rd[15-12]
+                                       [1011] imm_8[7..0] */
+    THUMB2_VSUBS,         /* vsub vd, vn, vm [111011100011] rn[19..16]
+                                       rd[15-12] [10100040] rm[3..0] */
+    THUMB2_VSUBD,         /* vsub vd, vn, vm [111011100011] rn[19..16]
+                                       rd[15-12] [10110040] rm[3..0] */
+    THUMB2_VADDS,         /* vadd vd, vn, vm [111011100011] rn[19..16]
+                                       rd[15-12] [10100000] rm[3..0] */
+    THUMB2_VADDD,         /* vadd vd, vn, vm [111011100011] rn[19..16]
+                                       rd[15-12] [10110000] rm[3..0] */
+    THUMB2_VDIVS,         /* vdiv vd, vn, vm [111011101000] rn[19..16]
+                                       rd[15-12] [10100000] rm[3..0] */
+    THUMB2_VDIVD,         /* vdiv vd, vn, vm [111011101000] rn[19..16]
+                                       rd[15-12] [10110000] rm[3..0] */
+    THUMB2_VCVTIF,        /* vcvt.F32 vd, vm [1110111010111000] vd[15..12]
+                                       [10101100] vm[3..0] */
+    THUMB2_VCVTID,        /* vcvt.F64 vd, vm [1110111010111000] vd[15..12]
+                                       [10111100] vm[3..0] */
+    THUMB2_VCVTFI,        /* vcvt.S32.F32 vd, vm [1110111010111101] vd[15..12]
+                                       [10101100] vm[3..0] */
+    THUMB2_VCVTDI,        /* vcvt.S32.F32 vd, vm [1110111010111101] vd[15..12]
+                                       [10111100] vm[3..0] */
+    THUMB2_VCVTFD,        /* vcvt.F64.F32 vd, vm [1110111010110111] vd[15..12]
+                                       [10101100] vm[3..0] */
+    THUMB2_VCVTDF,        /* vcvt.F32.F64 vd, vm [1110111010110111] vd[15..12]
+                                       [10111100] vm[3..0] */
+    THUMB2_VSQRTS,        /* vsqrt.f32 vd, vm [1110111010110001] vd[15..12]
+                                       [10101100] vm[3..0] */
+    THUMB2_VSQRTD,        /* vsqrt.f64 vd, vm [1110111010110001] vd[15..12]
+                                       [10111100] vm[3..0] */
+    THUMB2_MOV_IMM_SHIFT, /* mov(T2) rd, #<const> [11110] i [00001001111]
+                                       imm3 rd[11..8] imm8 */
+    THUMB2_MOV_IMM16,     /* mov(T3) rd, #<const> [11110] i [0010100] imm4 [0]
+                                       imm3 rd[11..8] imm8 */
+    THUMB2_STR_RRI12,     /* str(Imm,T3) rd,[rn,#imm12] [111110001100]
+                                       rn[19..16] rt[15..12] imm12[11..0] */
+    THUMB2_LDR_RRI12,     /* str(Imm,T3) rd,[rn,#imm12] [111110001100]
+                                       rn[19..16] rt[15..12] imm12[11..0] */
+    THUMB2_STR_RRI8_PREDEC, /* str(Imm,T4) rd,[rn,#-imm8] [111110000100]
+                                       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]
+                                       rn[2..0] */
+    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]
+                                       [0] imm3[14..12] rd[11..8] imm8[7..0] */
+    THUMB2_MOV_RR,          /* mov rd, rm [11101010010011110000] rd[11..8]
+                                       [0000] rm[3..0] */
+    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]
+                                       vd[15..12] 101101] M [0] 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,
+} ArmOpFeatureFlags;
+
+/* Instruction assembly fieldLoc kind */
+typedef enum ArmEncodingKind {
+    UNUSED,
+    BITBLT,        /* Bit string using end/start */
+    DFP,           /* Double FP reg */
+    SFP,           /* Single FP reg */
+    MODIMM,        /* Shifted 8-bit immediate using [26,14..12,7..0] */
+    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] */
+} ArmEncodingKind;
+
+/* Struct used to define the snippet positions for each Thumb opcode */
+typedef struct ArmEncodingMap {
+    u4 skeleton;
+    struct {
+        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];
+    ArmOpCode opCode;
+    int flags;
+    char *name;
+    char* fmt;
+    int size;
+} ArmEncodingMap;
+
+extern ArmEncodingMap EncodingMap[ARM_LAST];
+
+/*
+ * 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.
+ */
+typedef struct ArmLIR {
+    LIR generic;
+    ArmOpCode opCode;
+    int operands[3];    // [0..2] = [dest, src1, src2]
+    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)
+} ArmLIR;
+
+/* Chain cell for predicted method invocation */
+typedef struct PredictedChainingCell {
+    u4 branch;                  /* Branch to chained destination */
+    const ClassObject *clazz;   /* key #1 for prediction */
+    const Method *method;       /* key #2 to lookup native PC from dalvik PC */
+    u4 counter;                 /* counter to patch the chaining cell */
+} PredictedChainingCell;
+
+/* Init values when a predicted chain is initially assembled */
+#define PREDICTED_CHAIN_BX_PAIR_INIT     0
+#define PREDICTED_CHAIN_CLAZZ_INIT       0
+#define PREDICTED_CHAIN_METHOD_INIT      0
+#define PREDICTED_CHAIN_COUNTER_INIT     0
+
+/* Used when the callee is not compiled yet */
+#define PREDICTED_CHAIN_COUNTER_DELAY    16
+
+/* Rechain after this many mis-predictions have happened */
+#define PREDICTED_CHAIN_COUNTER_RECHAIN  1024
+
+/* Used if the resolved callee is a native method */
+#define PREDICTED_CHAIN_COUNTER_AVOID    0x7fffffff
+
+/* Utility macros to traverse the LIR/ArmLIR list */
+#define NEXT_LIR(lir) ((ArmLIR *) lir->generic.next)
+#define PREV_LIR(lir) ((ArmLIR *) lir->generic.prev)
+
+#define NEXT_LIR_LVALUE(lir) (lir)->generic.next
+#define PREV_LIR_LVALUE(lir) (lir)->generic.prev
+
+#define CHAIN_CELL_OFFSET_TAG   0xcdab
+
+#endif /* _DALVIK_VM_COMPILER_CODEGEN_ARM_ARMLIR_H */
diff --git a/vm/compiler/codegen/arm/Assemble.c b/vm/compiler/codegen/arm/Assemble.c
new file mode 100644
index 0000000..ea133e7
--- /dev/null
+++ b/vm/compiler/codegen/arm/Assemble.c
@@ -0,0 +1,1204 @@
+/*
+ * 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 "libdex/OpCode.h"
+#include "dexdump/OpCodeNames.h"
+
+#include "../../CompilerInternals.h"
+#include "ArmLIR.h"
+#include <unistd.h>             /* for cacheflush */
+
+/*
+ * opcode: ArmOpCode enum
+ * skeleton: pre-designated bit-pattern for this opcode
+ * k0: key to applying ds/de
+ * ds: dest start bit position
+ * de: dest end bit position
+ * k1: key to applying s1s/s1e
+ * s1s: src1 start bit position
+ * s1e: src1 end bit position
+ * k2: key to applying s2s/s2e
+ * s2s: src2 start bit position
+ * s2e: src2 end bit position
+ * operands: number of operands (for sanity check purposes)
+ * name: mnemonic name
+ * 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}
+
+/* Instruction dump string format keys: !pf, where "!" is the start
+ * of the key, "p" is which numeric operand to use and "f" is the
+ * print format.
+ *
+ * [p]ositions:
+ *     0 -> operands[0] (dest)
+ *     1 -> operands[1] (src1)
+ *     2 -> operands[2] (src2)
+ *
+ * [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.)
+ *     t -> pc-relative target
+ *     u -> 1st half of bl[x] target
+ *     v -> 2nd half ob bl[x] target
+ *     R -> register list
+ *     s -> single precision floating point register
+ *     S -> double precision floating point register
+ *     m -> Thumb2 modified immediate
+ *     M -> Thumb2 16-bit zero-extended immediate
+ *
+ *  [!] 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,
+                 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_ADD_RRI3,      0x1c00,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 8, 6,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 "add", "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),
+    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),
+    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),
+    ENCODING_MAP(THUMB_ADD_RR_HL,     0x4480,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST,
+                 "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,
+                 "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,
+                 "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),
+    ENCODING_MAP(THUMB_ADD_SPI7,      0xb000,
+                 BITBLT, 6, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_UNARY_OP | CLOBBER_DEST,
+                 "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),
+    ENCODING_MAP(THUMB_B_COND,        0xd000,
+                 BITBLT, 7, 0, BITBLT, 11, 8, UNUSED, -1, -1,
+                 IS_BINARY_OP | IS_BRANCH,
+                 "!1c", "!0t", 1),
+    ENCODING_MAP(THUMB_B_UNCOND,      0xe000,
+                 BITBLT, 10, 0, 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_BKPT,          0xbe00,
+                 BITBLT, 7, 0, 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,
+                 "blx_1", "!0u", 1),
+    ENCODING_MAP(THUMB_BLX_2,         0xe800,
+                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP | IS_BRANCH,
+                 "blx_2", "!0v", 1),
+    ENCODING_MAP(THUMB_BL_1,          0xf000,
+                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_UNARY_OP | IS_BRANCH,
+                 "bl_1", "!0u", 1),
+    ENCODING_MAP(THUMB_BL_2,          0xf800,
+                 BITBLT, 10, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_UNARY_OP | IS_BRANCH,
+                 "bl_2", "!0v", 1),
+    ENCODING_MAP(THUMB_BLX_R,         0x4780,
+                 BITBLT, 6, 3, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_UNARY_OP | IS_BRANCH,
+                 "blx", "r!0d", 1),
+    ENCODING_MAP(THUMB_BX,            0x4700,
+                 BITBLT, 6, 3, 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,
+                 "cmn", "r!0d, r!1d", 1),
+    ENCODING_MAP(THUMB_CMP_RI8,       0x2800,
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
+                 IS_BINARY_OP,
+                 "cmp", "r!0d, #!1d", 1),
+    ENCODING_MAP(THUMB_CMP_RR,        0x4280,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
+                 IS_BINARY_OP,
+                 "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),
+    ENCODING_MAP(THUMB_CMP_HL,        0x4580,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
+                 IS_BINARY_OP,
+                 "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),
+    ENCODING_MAP(THUMB_LDMIA,         0xc800,
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST | CLOBBER_SRC1,
+                 "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,
+                 "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,
+                 "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,
+                 "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),
+    ENCODING_MAP(THUMB_LDRB_RRI5,     0x7800,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 "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,
+                 "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,
+                 "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,
+                 "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,
+                 "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,
+                 "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_MOV_IMM,       0x2000,
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST,
+                 "mov", "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),
+    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),
+    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),
+    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),
+    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),
+    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),
+    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),
+    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),
+    ENCODING_MAP(THUMB_POP,           0xbc00,
+                 BITBLT, 8, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_UNARY_OP,
+                 "pop", "<!0R>", 1),
+    ENCODING_MAP(THUMB_PUSH,          0xb400,
+                 BITBLT, 8, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_UNARY_OP,
+                 "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_SBC,           0x4180,
+                 BITBLT, 2, 0, BITBLT, 5, 3, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST,
+                 "sbc", "r!0d, r!1d", 1),
+    ENCODING_MAP(THUMB_STMIA,         0xc000,
+                 BITBLT, 10, 8, BITBLT, 7, 0, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_SRC1,
+                 "stmia", "r!0d!!, <!1R>", 1),
+    ENCODING_MAP(THUMB_STR_RRI5,      0x6000,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
+                 IS_TERTIARY_OP,
+                 "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,
+                 "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),
+    ENCODING_MAP(THUMB_STRB_RRI5,     0x7000,
+                 BITBLT, 2, 0, BITBLT, 5, 3, BITBLT, 10, 6,
+                 IS_TERTIARY_OP,
+                 "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,
+                 "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,
+                 "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,
+                 "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),
+    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),
+    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),
+    ENCODING_MAP(THUMB_SUB_SPI7,      0xb080,
+                 BITBLT, 6, 0, UNUSED, -1, -1, UNUSED, -1, -1,
+                 IS_UNARY_OP | CLOBBER_DEST,
+                 "sub", "sp, #!0d", 1),
+    ENCODING_MAP(THUMB_SWI,           0xdf00,
+                 BITBLT, 7, 0, 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,
+                 "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,
+                 "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,
+                 "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,
+                 "vmuls", "!0s, !1s, !2s", 2),
+    ENCODING_MAP(THUMB2_VMULD,        0xee200b00,
+                 DFP, 22, 12, DFP, 7, 16, DFP, 5, 0,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 "vmuld", "!0S, !1S, !2S", 2),
+    ENCODING_MAP(THUMB2_VSTRS,       0xed800a00,
+                 SFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0,
+                 IS_TERTIARY_OP,
+                 "vstr", "!0s, [r!1d, #!2E]", 2),
+    ENCODING_MAP(THUMB2_VSTRD,       0xed800b00,
+                 DFP, 22, 12, BITBLT, 19, 16, BITBLT, 7, 0,
+                 IS_TERTIARY_OP,
+                 "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,
+                 "vsub", "!0s, !1s, !2s", 2),
+    ENCODING_MAP(THUMB2_VSUBD,        0xee300b40,
+                 DFP, 22, 12, DFP, 7, 16, DFP, 5, 0,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 "vsub", "!0S, !1S, !2S", 2),
+    ENCODING_MAP(THUMB2_VADDS,        0xee300a00,
+                 SFP, 22, 12, SFP, 7, 16, SFP, 5, 0,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 "vadd", "!0s, !1s, !2s", 2),
+    ENCODING_MAP(THUMB2_VADDD,        0xee300b00,
+                 DFP, 22, 12, DFP, 7, 16, DFP, 5, 0,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 "vadd", "!0S, !1S, !2S", 2),
+    ENCODING_MAP(THUMB2_VDIVS,        0xee800a00,
+                 SFP, 22, 12, SFP, 7, 16, SFP, 5, 0,
+                 IS_TERTIARY_OP | CLOBBER_DEST,
+                 "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),
+    ENCODING_MAP(THUMB2_VCVTIF,       0xeeb80ac0,
+                 SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST,
+                 "vcvt.f32", "!0s, !1s", 2),
+    ENCODING_MAP(THUMB2_VCVTID,       0xeeb80bc0,
+                 DFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST,
+                 "vcvt.f64", "!0S, !1s", 2),
+    ENCODING_MAP(THUMB2_VCVTFI,       0xeebd0ac0,
+                 SFP, 22, 12, SFP, 5, 0, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST,
+                 "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,
+                 "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,
+                 "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,
+                 "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,
+                 "vsqrt.f32 ", "!0s, !1s", 2),
+    ENCODING_MAP(THUMB2_VSQRTD,       0xeeb10bc0,
+                 DFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST,
+                 "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,
+                 "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,
+                 "mov", "r!0d, #!1M", 2),
+    ENCODING_MAP(THUMB2_STR_RRI12,       0xf8c00000,
+                 BITBLT, 15, 12, BITBLT, 19, 16, BITBLT, 11, 0,
+                 IS_TERTIARY_OP,
+                 "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,
+                 "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,
+                 "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,
+                 "ldr", "r!0d,[r!1d, #-!2d]", 2),
+    ENCODING_MAP(THUMB2_CBNZ,       0xb900,
+                 BITBLT, 2, 0, IMM6, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP,
+                 "cbnz", "r!0d,!1t", 1),
+    ENCODING_MAP(THUMB2_CBZ,       0xb100,
+                 BITBLT, 2, 0, IMM6, -1, -1, UNUSED, -1, -1,
+                 IS_BINARY_OP,
+                 "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,
+                 "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,
+                 "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),
+    ENCODING_MAP(THUMB2_VMOVD,       0xeeb00b40,
+                 DFP, 22, 12, DFP, 5, 0, UNUSED, -1, -1,
+                 IS_BINARY_OP | CLOBBER_DEST,
+                 "vmov.f64 ", "!0s, !1s", 2),
+};
+
+#define PADDING_MOV_R0_R0               0x1C00
+
+/* Write the numbers in the literal pool to the codegen stream */
+static void installDataContent(CompilationUnit *cUnit)
+{
+    int *dataPtr = (int *) ((char *) cUnit->baseAddr + cUnit->dataOffset);
+    ArmLIR *dataLIR = (ArmLIR *) cUnit->wordList;
+    while (dataLIR) {
+        *dataPtr++ = dataLIR->operands[0];
+        dataLIR = NEXT_LIR(dataLIR);
+    }
+}
+
+/* Returns the size of a Jit trace description */
+static int jitTraceDescriptionSize(const JitTraceDescription *desc)
+{
+    int runCount;
+    for (runCount = 0; ; runCount++) {
+        if (desc->trace[runCount].frag.runEnd)
+           break;
+    }
+    return sizeof(JitCodeDesc) + ((runCount+1) * sizeof(JitTraceRun));
+}
+
+/* Return TRUE if error happens */
+static bool assembleInstructions(CompilationUnit *cUnit, intptr_t startAddr)
+{
+    short *bufferAddr = (short *) cUnit->codeBuffer;
+    ArmLIR *lir;
+
+    for (lir = (ArmLIR *) cUnit->firstLIRInsn; lir; lir = NEXT_LIR(lir)) {
+        if (lir->opCode < 0) {
+            if ((lir->opCode == ARM_PSEUDO_ALIGN4) &&
+                /* 1 means padding is needed */
+                (lir->operands[0] == 1)) {
+                *bufferAddr++ = PADDING_MOV_R0_R0;
+            }
+            continue;
+        }
+
+        if (lir->isNop) {
+            continue;
+        }
+
+        if (lir->opCode == THUMB_LDR_PC_REL ||
+            lir->opCode == THUMB_ADD_PC_REL) {
+            ArmLIR *lirTarget = (ArmLIR *) lir->generic.target;
+            intptr_t pc = (lir->generic.offset + 4) & ~3;
+            /*
+             * Allow an offset (stored in operands[2] to be added to the
+             * PC-relative target. Useful to get to a fixed field inside a
+             * chaining cell.
+             */
+            intptr_t target = lirTarget->generic.offset + lir->operands[2];
+            int delta = target - pc;
+            if (delta & 0x3) {
+                LOGE("PC-rel distance is not multiples of 4: %d\n", delta);
+                dvmAbort();
+            }
+            if (delta > 1023) {
+                return true;
+            }
+            lir->operands[1] = 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) {
+                return true;
+            }
+            lir->operands[1] = delta >> 1;
+        } else if (lir->opCode == THUMB_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) {
+                return true;
+            }
+            lir->operands[0] = delta >> 1;
+        } else if (lir->opCode == THUMB_B_UNCOND) {
+            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 > 2046 || delta < -2048) {
+                LOGE("Unconditional branch distance out of range: %d\n", delta);
+                dvmAbort();
+            }
+            lir->operands[0] = delta >> 1;
+        } else if (lir->opCode == THUMB_BLX_1) {
+            assert(NEXT_LIR(lir)->opCode == THUMB_BLX_2);
+            /* curPC is Thumb */
+            intptr_t curPC = (startAddr + lir->generic.offset + 4) & ~3;
+            intptr_t target = lir->operands[1];
+
+            /* Match bit[1] in target with base */
+            if (curPC & 0x2) {
+                target |= 0x2;
+            }
+            int delta = target - curPC;
+            assert((delta >= -(1<<22)) && (delta <= ((1<<22)-2)));
+
+            lir->operands[0] = (delta >> 12) & 0x7ff;
+            NEXT_LIR(lir)->operands[0] = (delta>> 1) & 0x7ff;
+        }
+
+        ArmEncodingMap *encoder = &EncodingMap[lir->opCode];
+        u4 bits = encoder->skeleton;
+        int i;
+        for (i = 0; i < 3; i++) {
+            u4 value;
+            switch(encoder->fieldLoc[i].kind) {
+                case UNUSED:
+                    break;
+                case IMM6:
+                    value = ((lir->operands[i] & 0x20) >> 5) << 9;
+                    value |= (lir->operands[i] & 0x1f) << 3;
+                    bits |= value;
+                    break;
+                case BITBLT:
+                    value = (lir->operands[i] << encoder->fieldLoc[i].start) &
+                            ((1 << (encoder->fieldLoc[i].end + 1)) - 1);
+                    bits |= value;
+                    break;
+                case DFP:
+                    /* Snag the 1-bit slice and position it */
+                    value = ((lir->operands[i] & 0x10) >> 4) <<
+                            encoder->fieldLoc[i].end;
+                    /* Extract and position the 4-bit slice */
+                    value |= (lir->operands[i] & 0x0f) <<
+                            encoder->fieldLoc[i].start;
+                    bits |= value;
+                    break;
+                case SFP:
+                    /* Snag the 1-bit slice and position it */
+                    value = (lir->operands[i] & 0x1) <<
+                            encoder->fieldLoc[i].end;
+                    /* Extract and position the 4-bit slice */
+                    value |= ((lir->operands[i] & 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;
+                    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;
+                    bits |= value;
+                    break;
+                default:
+                    assert(0);
+            }
+        }
+        if (encoder->size == 2) {
+            *bufferAddr++ = (bits >> 16) & 0xffff;
+        }
+        *bufferAddr++ = bits & 0xffff;
+    }
+    return false;
+}
+
+/*
+ * Translation layout in the code cache.  Note that the codeAddress pointer
+ * in JitTable will point directly to the code body (field codeAddress).  The
+ * chain cell offset codeAddress - 2, and (if present) executionCount is at
+ * codeAddress - 6.
+ *
+ *      +----------------------------+
+ *      | Execution count            |  -> [Optional] 4 bytes
+ *      +----------------------------+
+ *   +--| Offset to chain cell counts|  -> 2 bytes
+ *   |  +----------------------------+
+ *   |  | Code body                  |  -> Start address for translation
+ *   |  |                            |     variable in 2-byte chunks
+ *   |  .                            .     (JitTable's codeAddress points here)
+ *   |  .                            .
+ *   |  |                            |
+ *   |  +----------------------------+
+ *   |  | Chaining Cells             |  -> 8 bytes each, must be 4 byte aligned
+ *   |  .                            .
+ *   |  .                            .
+ *   |  |                            |
+ *   |  +----------------------------+
+ *   +->| Chaining cell counts       |  -> 4 bytes, chain cell counts by type
+ *      +----------------------------+
+ *      | Trace description          |  -> variable sized
+ *      .                            .
+ *      |                            |
+ *      +----------------------------+
+ *      | Literal pool               |  -> 4-byte aligned, variable size
+ *      .                            .
+ *      .                            .
+ *      |                            |
+ *      +----------------------------+
+ *
+ * Go over each instruction in the list and calculate the offset from the top
+ * before sending them off to the assembler. If out-of-range branch distance is
+ * seen rearrange the instructions a bit to correct it.
+ */
+void dvmCompilerAssembleLIR(CompilationUnit *cUnit, JitTranslationInfo *info)
+{
+    LIR *lir;
+    ArmLIR *armLIR;
+    int offset = 0;
+    int i;
+    ChainCellCounts chainCellCounts;
+    int descSize = jitTraceDescriptionSize(cUnit->traceDesc);
+
+    info->codeAddress = NULL;
+    info->instructionSet = cUnit->instructionSet;
+
+    /* Beginning offset needs to allow space for chain cell offset */
+    for (armLIR = (ArmLIR *) cUnit->firstLIRInsn;
+         armLIR;
+         armLIR = NEXT_LIR(armLIR)) {
+        armLIR->generic.offset = offset;
+        if (armLIR->opCode >= 0 && !armLIR->isNop) {
+            armLIR->size = EncodingMap[armLIR->opCode].size * 2;
+            offset += armLIR->size;
+        } else if (armLIR->opCode == ARM_PSEUDO_ALIGN4) {
+            if (offset & 0x2) {
+                offset += 2;
+                armLIR->operands[0] = 1;
+            } else {
+                armLIR->operands[0] = 0;
+            }
+        }
+        /* Pseudo opcodes don't consume space */
+    }
+
+    /* Const values have to be word aligned */
+    offset = (offset + 3) & ~3;
+
+    /* Add space for chain cell counts & trace description */
+    u4 chainCellOffset = offset;
+    ArmLIR *chainCellOffsetLIR = (ArmLIR *) cUnit->chainCellOffsetLIR;
+    assert(chainCellOffsetLIR);
+    assert(chainCellOffset < 0x10000);
+    assert(chainCellOffsetLIR->opCode == ARM_16BIT_DATA &&
+           chainCellOffsetLIR->operands[0] == CHAIN_CELL_OFFSET_TAG);
+
+    /*
+     * Replace the CHAIN_CELL_OFFSET_TAG with the real value. If trace
+     * profiling is enabled, subtract 4 (occupied by the counter word) from
+     * the absolute offset as the value stored in chainCellOffsetLIR is the
+     * delta from &chainCellOffsetLIR to &ChainCellCounts.
+     */
+    chainCellOffsetLIR->operands[0] =
+        gDvmJit.profile ? (chainCellOffset - 4) : chainCellOffset;
+
+    offset += sizeof(chainCellCounts) + descSize;
+
+    assert((offset & 0x3) == 0);  /* Should still be word aligned */
+
+    /* Set up offsets for literals */
+    cUnit->dataOffset = offset;
+
+    for (lir = cUnit->wordList; lir; lir = lir->next) {
+        lir->offset = offset;
+        offset += 4;
+    }
+
+    cUnit->totalSize = offset;
+
+    if (gDvmJit.codeCacheByteUsed + cUnit->totalSize > CODE_CACHE_SIZE) {
+        gDvmJit.codeCacheFull = true;
+        cUnit->baseAddr = NULL;
+        return;
+    }
+
+    /* Allocate enough space for the code block */
+    cUnit->codeBuffer = dvmCompilerNew(chainCellOffset, true);
+    if (cUnit->codeBuffer == NULL) {
+        LOGE("Code buffer allocation failure\n");
+        cUnit->baseAddr = NULL;
+        return;
+    }
+
+    bool assemblerFailure = assembleInstructions(
+        cUnit, (intptr_t) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed);
+
+    /*
+     * Currently the only reason that can cause the assembler to fail is due to
+     * trace length - cut it in half and retry.
+     */
+    if (assemblerFailure) {
+        cUnit->halveInstCount = true;
+        return;
+    }
+
+
+    cUnit->baseAddr = (char *) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed;
+    gDvmJit.codeCacheByteUsed += offset;
+
+    /* Install the code block */
+    memcpy((char*)cUnit->baseAddr, cUnit->codeBuffer, chainCellOffset);
+    gDvmJit.numCompilations++;
+
+    /* Install the chaining cell counts */
+    for (i=0; i< CHAINING_CELL_LAST; i++) {
+        chainCellCounts.u.count[i] = cUnit->numChainingCells[i];
+    }
+    memcpy((char*)cUnit->baseAddr + chainCellOffset, &chainCellCounts,
+           sizeof(chainCellCounts));
+
+    /* Install the trace description */
+    memcpy((char*)cUnit->baseAddr + chainCellOffset + sizeof(chainCellCounts),
+           cUnit->traceDesc, descSize);
+
+    /* Write the literals directly into the code cache */
+    installDataContent(cUnit);
+
+    /* Flush dcache and invalidate the icache to maintain coherence */
+    cacheflush((long)cUnit->baseAddr,
+               (long)((char *) cUnit->baseAddr + offset), 0);
+
+    /* Record code entry point and instruction set */
+    info->codeAddress = (char*)cUnit->baseAddr + cUnit->headerSize;
+    info->instructionSet = cUnit->instructionSet;
+    /* If applicable, mark low bit to denote thumb */
+    if (info->instructionSet != DALVIK_JIT_ARM)
+        info->codeAddress = (char*)info->codeAddress + 1;
+}
+
+static u4 assembleBXPair(int branchOffset)
+{
+    u4 thumb1, thumb2;
+
+    if ((branchOffset < -2048) | (branchOffset > 2046)) {
+        thumb1 =  (0xf000 | ((branchOffset>>12) & 0x7ff));
+        thumb2 =  (0xf800 | ((branchOffset>> 1) & 0x7ff));
+    } else {
+        thumb1 =  (0xe000 | ((branchOffset>> 1) & 0x7ff));
+        thumb2 =  0x4300;  /* nop -> or r0, r0 */
+    }
+
+    return thumb2<<16 | thumb1;
+}
+
+/*
+ * Perform translation chain operation.
+ * For ARM, we'll use a pair of thumb instructions to generate
+ * an unconditional chaining branch of up to 4MB in distance.
+ * Use a BL, though we don't really need the link.  The format is
+ *     111HHooooooooooo
+ * Where HH is 10 for the 1st inst, and 11 for the second and
+ * the "o" field is each instruction's 11-bit contribution to the
+ * 22-bit branch offset.
+ * If the target is nearby, use a single-instruction bl.
+ * If one or more threads is suspended, don't chain.
+ */
+void* dvmJitChain(void* tgtAddr, u4* branchAddr)
+{
+    int baseAddr = (u4) branchAddr + 4;
+    int branchOffset = (int) tgtAddr - baseAddr;
+    u4 newInst;
+
+    if (gDvm.sumThreadSuspendCount == 0) {
+        assert((branchOffset >= -(1<<22)) && (branchOffset <= ((1<<22)-2)));
+
+        gDvmJit.translationChains++;
+
+        COMPILER_TRACE_CHAINING(
+            LOGD("Jit Runtime: chaining 0x%x to 0x%x\n",
+                 (int) branchAddr, (int) tgtAddr & -2));
+
+        newInst = assembleBXPair(branchOffset);
+
+        *branchAddr = newInst;
+        cacheflush((long)branchAddr, (long)branchAddr + 4, 0);
+    }
+
+    return tgtAddr;
+}
+
+/*
+ * This method is called from the invoke templates for virtual and interface
+ * methods to speculatively setup a chain to the callee. The templates are
+ * written in assembly and have setup method, cell, and clazz at r0, r2, and
+ * r3 respectively, so there is a unused argument in the list. Upon return one
+ * of the following three results may happen:
+ *   1) Chain is not setup because the callee is native. Reset the rechain
+ *      count to a big number so that it will take a long time before the next
+ *      rechain attempt to happen.
+ *   2) Chain is not setup because the callee has not been created yet. Reset
+ *      the rechain count to a small number and retry in the near future.
+ *   3) Ask all other threads to stop before patching this chaining cell.
+ *      This is required because another thread may have passed the class check
+ *      but hasn't reached the chaining cell yet to follow the chain. If we
+ *      patch the content before halting the other thread, there could be a
+ *      small window for race conditions to happen that it may follow the new
+ *      but wrong chain to invoke a different method.
+ */
+const Method *dvmJitToPatchPredictedChain(const Method *method,
+                                          void *unused,
+                                          PredictedChainingCell *cell,
+                                          const ClassObject *clazz)
+{
+    /* Don't come back here for a long time if the method is native */
+    if (dvmIsNativeMethod(method)) {
+        cell->counter = PREDICTED_CHAIN_COUNTER_AVOID;
+        cacheflush((long) cell, (long) (cell+1), 0);
+        COMPILER_TRACE_CHAINING(
+            LOGD("Jit Runtime: predicted chain %p to native method %s ignored",
+                 cell, method->name));
+        goto done;
+    }
+    int tgtAddr = (int) dvmJitGetCodeAddr(method->insns);
+
+    /*
+     * Compilation not made yet for the callee. Reset the counter to a small
+     * value and come back to check soon.
+     */
+    if (tgtAddr == 0) {
+        /*
+         * Wait for a few invocations (currently set to be 16) before trying
+         * to setup the chain again.
+         */
+        cell->counter = PREDICTED_CHAIN_COUNTER_DELAY;
+        cacheflush((long) cell, (long) (cell+1), 0);
+        COMPILER_TRACE_CHAINING(
+            LOGD("Jit Runtime: predicted chain %p to method %s delayed",
+                 cell, method->name));
+        goto done;
+    }
+
+    /* Stop the world */
+    dvmSuspendAllThreads(SUSPEND_FOR_JIT);
+
+    int baseAddr = (int) cell + 4;   // PC is cur_addr + 4
+    int branchOffset = tgtAddr - baseAddr;
+
+    COMPILER_TRACE_CHAINING(
+        LOGD("Jit Runtime: predicted chain %p from %s to %s (%s) patched",
+             cell, cell->clazz ? cell->clazz->descriptor : "NULL",
+             clazz->descriptor,
+             method->name));
+
+    cell->branch = assembleBXPair(branchOffset);
+    cell->clazz = clazz;
+    cell->method = method;
+    cell->counter = PREDICTED_CHAIN_COUNTER_RECHAIN;
+
+    cacheflush((long) cell, (long) (cell+1), 0);
+
+    /* All done - resume all other threads */
+    dvmResumeAllThreads(SUSPEND_FOR_JIT);
+
+done:
+    return method;
+}
+
+/*
+ * Unchain a trace given the starting address of the translation
+ * in the code cache.  Refer to the diagram in dvmCompilerAssembleLIR.
+ * Returns the address following the last cell unchained.  Note that
+ * the incoming codeAddr is a thumb code address, and therefore has
+ * the low bit set.
+ */
+u4* dvmJitUnchain(void* codeAddr)
+{
+    u2* pChainCellOffset = (u2*)((char*)codeAddr - 3);
+    u2 chainCellOffset = *pChainCellOffset;
+    ChainCellCounts *pChainCellCounts =
+          (ChainCellCounts*)((char*)codeAddr + chainCellOffset - 3);
+    int cellSize;
+    u4* pChainCells;
+    u4* pStart;
+    u4 thumb1;
+    u4 thumb2;
+    u4 newInst;
+    int i,j;
+    PredictedChainingCell *predChainCell;
+
+    /* Get total count of chain cells */
+    for (i = 0, cellSize = 0; i < CHAINING_CELL_LAST; i++) {
+        if (i != CHAINING_CELL_INVOKE_PREDICTED) {
+            cellSize += pChainCellCounts->u.count[i] * 2;
+        } else {
+            cellSize += pChainCellCounts->u.count[i] * 4;
+        }
+    }
+
+    /* Locate the beginning of the chain cell region */
+    pStart = pChainCells = ((u4 *) pChainCellCounts) - cellSize;
+
+    /* The cells are sorted in order - walk through them and reset */
+    for (i = 0; i < CHAINING_CELL_LAST; i++) {
+        int elemSize = 2; /* Most chaining cell has two words */
+        if (i == CHAINING_CELL_INVOKE_PREDICTED) {
+            elemSize = 4;
+        }
+
+        for (j = 0; j < pChainCellCounts->u.count[i]; j++) {
+            int targetOffset;
+            switch(i) {
+                case CHAINING_CELL_NORMAL:
+                    targetOffset = offsetof(InterpState,
+                          jitToInterpEntries.dvmJitToInterpNormal);
+                    break;
+                case CHAINING_CELL_HOT:
+                case CHAINING_CELL_INVOKE_SINGLETON:
+                    targetOffset = offsetof(InterpState,
+                          jitToInterpEntries.dvmJitToTraceSelect);
+                    break;
+                case CHAINING_CELL_INVOKE_PREDICTED:
+                    targetOffset = 0;
+                    predChainCell = (PredictedChainingCell *) pChainCells;
+                    /* Reset the cell to the init state */
+                    predChainCell->branch = PREDICTED_CHAIN_BX_PAIR_INIT;
+                    predChainCell->clazz = PREDICTED_CHAIN_CLAZZ_INIT;
+                    predChainCell->method = PREDICTED_CHAIN_METHOD_INIT;
+                    predChainCell->counter = PREDICTED_CHAIN_COUNTER_INIT;
+                    break;
+                default:
+                    dvmAbort();
+            }
+            COMPILER_TRACE_CHAINING(
+                LOGD("Jit Runtime: unchaining 0x%x", (int)pChainCells));
+            /*
+             * Thumb code sequence for a chaining cell is:
+             *     ldr  r0, rGLUE, #<word offset>
+             *     blx  r0
+             */
+            if (i != CHAINING_CELL_INVOKE_PREDICTED) {
+                targetOffset = targetOffset >> 2;  /* convert to word offset */
+                thumb1 = 0x6800 | (targetOffset << 6) |
+                         (rGLUE << 3) | (r0 << 0);
+                thumb2 = 0x4780 | (r0 << 3);
+                newInst = thumb2<<16 | thumb1;
+                *pChainCells = newInst;
+            }
+            pChainCells += elemSize;  /* Advance by a fixed number of words */
+        }
+    }
+    return pChainCells;
+}
+
+/* Unchain all translation in the cache. */
+void dvmJitUnchainAll()
+{
+    u4* lowAddress = NULL;
+    u4* highAddress = NULL;
+    unsigned int i;
+    if (gDvmJit.pJitEntryTable != NULL) {
+        COMPILER_TRACE_CHAINING(LOGD("Jit Runtime: unchaining all"));
+        dvmLockMutex(&gDvmJit.tableLock);
+        for (i = 0; i < gDvmJit.jitTableSize; i++) {
+            if (gDvmJit.pJitEntryTable[i].dPC &&
+                   gDvmJit.pJitEntryTable[i].codeAddress) {
+                u4* lastAddress;
+                lastAddress =
+                      dvmJitUnchain(gDvmJit.pJitEntryTable[i].codeAddress);
+                if (lowAddress == NULL ||
+                      (u4*)gDvmJit.pJitEntryTable[i].codeAddress < lowAddress)
+                    lowAddress = lastAddress;
+                if (lastAddress > highAddress)
+                    highAddress = lastAddress;
+            }
+        }
+        cacheflush((long)lowAddress, (long)highAddress, 0);
+        dvmUnlockMutex(&gDvmJit.tableLock);
+    }
+}
+
+typedef struct jitProfileAddrToLine {
+    u4 lineNum;
+    u4 bytecodeOffset;
+} jitProfileAddrToLine;
+
+
+/* Callback function to track the bytecode offset/line number relationiship */
+static int addrToLineCb (void *cnxt, u4 bytecodeOffset, u4 lineNum)
+{
+    jitProfileAddrToLine *addrToLine = (jitProfileAddrToLine *) cnxt;
+
+    /* Best match so far for this offset */
+    if (addrToLine->bytecodeOffset >= bytecodeOffset) {
+        addrToLine->lineNum = lineNum;
+    }
+    return 0;
+}
+
+char *getTraceBase(const JitEntry *p)
+{
+    return (char*)p->codeAddress -
+        (6 + (p->u.info.instructionSet == DALVIK_JIT_ARM ? 0 : 1));
+}
+
+/* Dumps profile info for a single trace */
+static int dumpTraceProfile(JitEntry *p)
+{
+    ChainCellCounts* pCellCounts;
+    char* traceBase;
+    u4* pExecutionCount;
+    u2* pCellOffset;
+    JitTraceDescription *desc;
+    const Method* method;
+
+    traceBase = getTraceBase(p);
+
+    if (p->codeAddress == NULL) {
+        LOGD("TRACEPROFILE 0x%08x 0 NULL 0 0", (int)traceBase);
+        return 0;
+    }
+
+    pExecutionCount = (u4*) (traceBase);
+    pCellOffset = (u2*) (traceBase + 4);
+    pCellCounts = (ChainCellCounts*) ((char *)pCellOffset + *pCellOffset);
+    desc = (JitTraceDescription*) ((char*)pCellCounts + sizeof(*pCellCounts));
+    method = desc->method;
+    char *methodDesc = dexProtoCopyMethodDescriptor(&method->prototype);
+    jitProfileAddrToLine addrToLine = {0, desc->trace[0].frag.startOffset};
+
+    /*
+     * We may end up decoding the debug information for the same method
+     * multiple times, but the tradeoff is we don't need to allocate extra
+     * space to store the addr/line mapping. Since this is a debugging feature
+     * and done infrequently so the slower but simpler mechanism should work
+     * just fine.
+     */
+    dexDecodeDebugInfo(method->clazz->pDvmDex->pDexFile,
+                       dvmGetMethodCode(method),
+                       method->clazz->descriptor,
+                       method->prototype.protoIdx,
+                       method->accessFlags,
+                       addrToLineCb, NULL, &addrToLine);
+
+    LOGD("TRACEPROFILE 0x%08x % 10d [%#x(+%d), %d] %s%s;%s",
+         (int)traceBase,
+         *pExecutionCount,
+         desc->trace[0].frag.startOffset,
+         desc->trace[0].frag.numInsts,
+         addrToLine.lineNum,
+         method->clazz->descriptor, method->name, methodDesc);
+    free(methodDesc);
+
+    return *pExecutionCount;
+}
+
+/* Handy function to retrieve the profile count */
+static inline int getProfileCount(const JitEntry *entry)
+{
+    if (entry->dPC == 0 || entry->codeAddress == 0)
+        return 0;
+    u4 *pExecutionCount = (u4 *) getTraceBase(entry);
+
+    return *pExecutionCount;
+}
+
+
+/* qsort callback function */
+static int sortTraceProfileCount(const void *entry1, const void *entry2)
+{
+    const JitEntry *jitEntry1 = entry1;
+    const JitEntry *jitEntry2 = entry2;
+
+    int count1 = getProfileCount(jitEntry1);
+    int count2 = getProfileCount(jitEntry2);
+    return (count1 == count2) ? 0 : ((count1 > count2) ? -1 : 1);
+}
+
+/* Sort the trace profile counts and dump them */
+void dvmCompilerSortAndPrintTraceProfiles()
+{
+    JitEntry *sortedEntries;
+    int numTraces = 0;
+    unsigned long counts = 0;
+    unsigned int i;
+
+    /* Make sure that the table is not changing */
+    dvmLockMutex(&gDvmJit.tableLock);
+
+    /* Sort the entries by descending order */
+    sortedEntries = malloc(sizeof(JitEntry) * gDvmJit.jitTableSize);
+    if (sortedEntries == NULL)
+        goto done;
+    memcpy(sortedEntries, gDvmJit.pJitEntryTable,
+           sizeof(JitEntry) * gDvmJit.jitTableSize);
+    qsort(sortedEntries, gDvmJit.jitTableSize, sizeof(JitEntry),
+          sortTraceProfileCount);
+
+    /* Dump the sorted entries */
+    for (i=0; i < gDvmJit.jitTableSize; i++) {
+        if (sortedEntries[i].dPC != 0) {
+            counts += dumpTraceProfile(&sortedEntries[i]);
+            numTraces++;
+        }
+    }
+    if (numTraces == 0)
+        numTraces = 1;
+    LOGD("JIT: Average execution count -> %d",(int)(counts / numTraces));
+
+    free(sortedEntries);
+done:
+    dvmUnlockMutex(&gDvmJit.tableLock);
+    return;
+}
diff --git a/vm/compiler/codegen/arm/Codegen-armv5te-vfp.c b/vm/compiler/codegen/arm/Codegen-armv5te-vfp.c
new file mode 100644
index 0000000..c3a60e4
--- /dev/null
+++ b/vm/compiler/codegen/arm/Codegen-armv5te-vfp.c
@@ -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.
+ */
+
+#include "Dalvik.h"
+#include "interp/InterpDefs.h"
+#include "libdex/OpCode.h"
+#include "dexdump/OpCodeNames.h"
+#include "vm/compiler/CompilerInternals.h"
+#include "ArmLIR.h"
+#include "vm/mterp/common/FindInterface.h"
+
+#include "armv5te-vfp/ArchVariant.h"
+
+#include "ThumbUtil.c"
+#include "Codegen.c"
+#include "armv5te-vfp/ArchVariant.c"
diff --git a/vm/compiler/codegen/arm/Codegen-armv5te.c b/vm/compiler/codegen/arm/Codegen-armv5te.c
new file mode 100644
index 0000000..baf9dc9
--- /dev/null
+++ b/vm/compiler/codegen/arm/Codegen-armv5te.c
@@ -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.
+ */
+
+#include "Dalvik.h"
+#include "interp/InterpDefs.h"
+#include "libdex/OpCode.h"
+#include "dexdump/OpCodeNames.h"
+#include "vm/compiler/CompilerInternals.h"
+#include "ArmLIR.h"
+#include "vm/mterp/common/FindInterface.h"
+
+#include "armv5te/ArchVariant.h"
+
+#include "ThumbUtil.c"
+#include "Codegen.c"
+#include "armv5te/ArchVariant.c"
diff --git a/vm/compiler/codegen/arm/Codegen-armv7-a.c b/vm/compiler/codegen/arm/Codegen-armv7-a.c
new file mode 100644
index 0000000..a691231
--- /dev/null
+++ b/vm/compiler/codegen/arm/Codegen-armv7-a.c
@@ -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.
+ */
+
+#include "Dalvik.h"
+#include "interp/InterpDefs.h"
+#include "libdex/OpCode.h"
+#include "dexdump/OpCodeNames.h"
+#include "vm/compiler/CompilerInternals.h"
+#include "ArmLIR.h"
+#include "vm/mterp/common/FindInterface.h"
+
+#include "armv7-a/ArchVariant.h"
+
+#include "Thumb2Util.c"
+#include "Codegen.c"
+#include "armv7-a/ArchVariant.c"
diff --git a/vm/compiler/codegen/arm/Codegen.c b/vm/compiler/codegen/arm/Codegen.c
new file mode 100644
index 0000000..7d127f8
--- /dev/null
+++ b/vm/compiler/codegen/arm/Codegen.c
@@ -0,0 +1,3337 @@
+/*
+ * 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 file contains codegen and support common to all supported
+ * ARM variants.  It is included by:
+ *
+ *        Codegen-$(TARGET_ARCH_VARIANT).c
+ *
+ * which combines this common code with specific support found in the
+ * applicable directory below this one.
+ */
+
+
+/* Array holding the entry offset of each template relative to the first one */
+static intptr_t templateEntryOffsets[TEMPLATE_LAST_MARK];
+
+/* Track exercised opcodes */
+static int opcodeCoverage[256];
+
+/*****************************************************************************/
+
+/*
+ * The following are building blocks to construct low-level IRs with 0 - 3
+ * operands.
+ */
+static ArmLIR *newLIR0(CompilationUnit *cUnit, ArmOpCode opCode)
+{
+    ArmLIR *insn = dvmCompilerNew(sizeof(ArmLIR), true);
+    assert(isPseudoOpCode(opCode) || (EncodingMap[opCode].flags & NO_OPERAND));
+    insn->opCode = opCode;
+    dvmCompilerAppendLIR(cUnit, (LIR *) insn);
+    return insn;
+}
+
+static ArmLIR *newLIR1(CompilationUnit *cUnit, ArmOpCode opCode,
+                           int dest)
+{
+    ArmLIR *insn = dvmCompilerNew(sizeof(ArmLIR), true);
+    assert(isPseudoOpCode(opCode) || (EncodingMap[opCode].flags & IS_UNARY_OP));
+    insn->opCode = opCode;
+    insn->operands[0] = dest;
+    dvmCompilerAppendLIR(cUnit, (LIR *) insn);
+    return insn;
+}
+
+static ArmLIR *newLIR2(CompilationUnit *cUnit, ArmOpCode opCode,
+                           int dest, int src1)
+{
+    ArmLIR *insn = dvmCompilerNew(sizeof(ArmLIR), true);
+    assert(isPseudoOpCode(opCode) ||
+           (EncodingMap[opCode].flags & IS_BINARY_OP));
+    insn->opCode = opCode;
+    insn->operands[0] = dest;
+    insn->operands[1] = src1;
+    dvmCompilerAppendLIR(cUnit, (LIR *) insn);
+    return insn;
+}
+
+static ArmLIR *newLIR3(CompilationUnit *cUnit, ArmOpCode opCode,
+                           int dest, int src1, int src2)
+{
+    ArmLIR *insn = dvmCompilerNew(sizeof(ArmLIR), true);
+    assert(isPseudoOpCode(opCode) ||
+           (EncodingMap[opCode].flags & IS_TERTIARY_OP));
+    insn->opCode = opCode;
+    insn->operands[0] = dest;
+    insn->operands[1] = src1;
+    insn->operands[2] = src2;
+    dvmCompilerAppendLIR(cUnit, (LIR *) insn);
+    return insn;
+}
+
+static ArmLIR *newLIR23(CompilationUnit *cUnit, ArmOpCode opCode,
+                            int srcdest, int src2)
+{
+    assert(!isPseudoOpCode(opCode));
+    if (EncodingMap[opCode].flags & IS_BINARY_OP)
+        return newLIR2(cUnit, opCode, srcdest, src2);
+    else
+        return newLIR3(cUnit, opCode, srcdest, srcdest, src2);
+}
+
+/*****************************************************************************/
+
+/*
+ * The following are building blocks to insert constants into the pool or
+ * instruction streams.
+ */
+
+/* Add a 32-bit constant either in the constant pool or mixed with code */
+static ArmLIR *addWordData(CompilationUnit *cUnit, int value, bool inPlace)
+{
+    /* Add the constant to the literal pool */
+    if (!inPlace) {
+        ArmLIR *newValue = dvmCompilerNew(sizeof(ArmLIR), true);
+        newValue->operands[0] = value;
+        newValue->generic.next = cUnit->wordList;
+        cUnit->wordList = (LIR *) newValue;
+        return newValue;
+    } else {
+        /* Add the constant in the middle of code stream */
+        newLIR1(cUnit, ARM_16BIT_DATA, (value & 0xffff));
+        newLIR1(cUnit, ARM_16BIT_DATA, (value >> 16));
+    }
+    return NULL;
+}
+
+/*
+ * Search the existing constants in the literal pool for an exact or close match
+ * within specified delta (greater or equal to 0).
+ */
+static ArmLIR *scanLiteralPool(CompilationUnit *cUnit, int value,
+                                   unsigned int delta)
+{
+    LIR *dataTarget = cUnit->wordList;
+    while (dataTarget) {
+        if (((unsigned) (value - ((ArmLIR *) dataTarget)->operands[0])) <=
+            delta)
+            return (ArmLIR *) dataTarget;
+        dataTarget = dataTarget->next;
+    }
+    return NULL;
+}
+
+/* Perform the actual operation for OP_RETURN_* */
+static void genReturnCommon(CompilationUnit *cUnit, MIR *mir)
+{
+    genDispatchToHandler(cUnit, TEMPLATE_RETURN);
+#if defined(INVOKE_STATS)
+    gDvmJit.returnOp++;
+#endif
+    int dPC = (int) (cUnit->method->insns + mir->offset);
+    /* Insert branch, but defer setting of target */
+    ArmLIR *branch = genUnconditionalBranch(cUnit, NULL);
+    /* 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] = dPC;
+    pcrLabel->operands[1] = mir->offset;
+    /* Insert the place holder to the growable list */
+    dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
+    /* Branch to the PC reconstruction code */
+    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,
+                                         ArmLIR *pcrLabel)
+{
+    /* Set up the place holder to reconstruct this Dalvik PC */
+    if (pcrLabel == NULL) {
+        int dPC = (int) (cUnit->method->insns + dOffset);
+        pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true);
+        pcrLabel->opCode = ARM_PSEUDO_PC_RECONSTRUCTION_CELL;
+        pcrLabel->operands[0] = dPC;
+        pcrLabel->operands[1] = dOffset;
+        /* Insert the place holder to the growable list */
+        dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
+    }
+    /* Branch to the PC reconstruction code */
+    branch->generic.target = (LIR *) pcrLabel;
+    return pcrLabel;
+}
+
+
+/*
+ * 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)
+{
+    newLIR2(cUnit, THUMB_CMP_RR, reg1, reg2);
+    ArmLIR *branch = newLIR2(cUnit, THUMB_B_COND, 0, cond);
+    return genCheckCommon(cUnit, dOffset, branch, pcrLabel);
+}
+
+/*
+ * Perform null-check on a register. vReg is the Dalvik register being checked,
+ * and mReg is the machine register holding the actual value. If internal state
+ * indicates that vReg has been checked before the check request is ignored.
+ */
+static ArmLIR *genNullCheck(CompilationUnit *cUnit, int vReg, int mReg,
+                                int dOffset, ArmLIR *pcrLabel)
+{
+    /* This particular Dalvik register has been null-checked */
+    if (dvmIsBitSet(cUnit->registerScoreboard.nullCheckedRegs, vReg)) {
+        return pcrLabel;
+    }
+    dvmSetBit(cUnit->registerScoreboard.nullCheckedRegs, vReg);
+    return genRegImmCheck(cUnit, ARM_COND_EQ, mReg, 0, dOffset, pcrLabel);
+}
+
+/*
+ * Perform zero-check on a register. Similar to genNullCheck but the value being
+ * checked does not have a corresponding Dalvik register.
+ */
+static ArmLIR *genZeroCheck(CompilationUnit *cUnit, int mReg,
+                                int dOffset, ArmLIR *pcrLabel)
+{
+    return genRegImmCheck(cUnit, ARM_COND_EQ, mReg, 0, dOffset, pcrLabel);
+}
+
+/* Perform bound check on two registers */
+static ArmLIR *genBoundsCheck(CompilationUnit *cUnit, int rIndex,
+                                  int rBound, int dOffset, ArmLIR *pcrLabel)
+{
+    return inertRegRegCheck(cUnit, ARM_COND_CS, rIndex, rBound, dOffset,
+                            pcrLabel);
+}
+
+/* Generate a unconditional branch to go to the interpreter */
+static inline ArmLIR *genTrap(CompilationUnit *cUnit, int dOffset,
+                                  ArmLIR *pcrLabel)
+{
+    ArmLIR *branch = newLIR0(cUnit, THUMB_B_UNCOND);
+    return genCheckCommon(cUnit, dOffset, branch, pcrLabel);
+}
+
+/* Load a wide field from an object instance */
+static void genIGetWide(CompilationUnit *cUnit, MIR *mir, int fieldOffset)
+{
+    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    int reg0, reg1, reg2, reg3;
+
+    /* Allocate reg0..reg3 into physical registers r0..r3 */
+
+    /* See if vB is in a native register. If so, reuse it. */
+    reg2 = selectFirstRegister(cUnit, dInsn->vB, false);
+    /* Ping reg3 to the other register of the same pair containing reg2 */
+    reg3 = reg2 ^ 0x1;
+    /*
+     * Ping reg0 to the first register of the alternate register pair
+     */
+    reg0 = (reg2 + 2) & 0x2;
+    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));
+    storeValuePair(cUnit, reg0, reg1, dInsn->vA, reg3);
+}
+
+/* Store a wide field to an object instance */
+static void genIPutWide(CompilationUnit *cUnit, MIR *mir, int fieldOffset)
+{
+    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    int reg0, reg1, reg2, reg3;
+
+    /* Allocate reg0..reg3 into physical registers r0..r3 */
+
+    /* See if vB is in a native register. If so, reuse it. */
+    reg2 = selectFirstRegister(cUnit, dInsn->vB, false);
+    /* Ping reg3 to the other register of the same pair containing reg2 */
+    reg3 = reg2 ^ 0x1;
+    /*
+     * Ping reg0 to the first register of the alternate register pair
+     */
+    reg0 = (reg2 + 2) & 0x2;
+    reg1 = NEXT_REG(reg0);
+
+
+    loadValue(cUnit, dInsn->vB, reg2);
+    loadValuePair(cUnit, dInsn->vA, reg0, reg1);
+    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));
+}
+
+/*
+ * 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,
+                    int fieldOffset)
+{
+    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    int reg0, reg1;
+
+    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);
+    genNullCheck(cUnit, dInsn->vB, reg0, mir->offset, NULL); /* null object? */
+    newLIR3(cUnit, inst, reg0, reg0, reg1);
+    storeValue(cUnit, reg0, dInsn->vA, reg1);
+}
+
+/*
+ * 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,
+                    int fieldOffset)
+{
+    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    int reg0, reg1, reg2;
+
+    reg0 = selectFirstRegister(cUnit, dInsn->vB, false);
+    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);
+}
+
+
+/* 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,
+                        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);
+    reg1 = NEXT_REG(reg0);
+    reg2 = NEXT_REG(reg1);
+    reg3 = NEXT_REG(reg2);
+
+    loadValue(cUnit, vArray, reg2);
+    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);
+    }
+    if (scale==3) {
+        newLIR3(cUnit, inst, reg0, reg2, reg3);
+        newLIR2(cUnit, THUMB_ADD_RI8, reg2, 4);
+        newLIR3(cUnit, inst, reg1, reg2, reg3);
+        storeValuePair(cUnit, reg0, reg1, vDest, reg3);
+    } else {
+        newLIR3(cUnit, inst, reg0, reg2, reg3);
+        storeValue(cUnit, reg0, vDest, reg3);
+    }
+}
+
+/* TODO: This should probably be done as an out-of-line instruction handler. */
+
+/*
+ * 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,
+                        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);
+    reg1 = NEXT_REG(reg0);
+    reg2 = NEXT_REG(reg1);
+    reg3 = NEXT_REG(reg2);
+
+    loadValue(cUnit, vArray, reg2);
+    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);
+    /* at this point, reg2 points to array, reg3 is unscaled index */
+    if (scale==3) {
+        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);
+    }
+}
+
+static bool genShiftOpLong(CompilationUnit *cUnit, MIR *mir, int vDest,
+                           int vSrc1, int vShift)
+{
+    /*
+     * Don't mess with the regsiters here as there is a particular calling
+     * convention to the out-of-line handler.
+     */
+    loadValue(cUnit, vShift, r2);
+    loadValuePair(cUnit, vSrc1, r0, r1);
+    switch( mir->dalvikInsn.opCode) {
+        case OP_SHL_LONG:
+        case OP_SHL_LONG_2ADDR:
+            genDispatchToHandler(cUnit, TEMPLATE_SHL_LONG);
+            break;
+        case OP_SHR_LONG:
+        case OP_SHR_LONG_2ADDR:
+            genDispatchToHandler(cUnit, TEMPLATE_SHR_LONG);
+            break;
+        case OP_USHR_LONG:
+        case OP_USHR_LONG_2ADDR:
+            genDispatchToHandler(cUnit, TEMPLATE_USHR_LONG);
+            break;
+        default:
+            return true;
+    }
+    storeValuePair(cUnit, r0, r1, vDest, r2);
+    return false;
+}
+bool genArithOpFloatPortable(CompilationUnit *cUnit, MIR *mir,
+                             int vDest, int vSrc1, int vSrc2)
+{
+    /*
+     * Don't optimize the regsiter usage here as they are governed by the EABI
+     * calling convention.
+     */
+    void* funct;
+    int reg0, reg1;
+
+    /* TODO: use a proper include file to define these */
+    float __aeabi_fadd(float a, float b);
+    float __aeabi_fsub(float a, float b);
+    float __aeabi_fdiv(float a, float b);
+    float __aeabi_fmul(float a, float b);
+    float fmodf(float a, float b);
+
+    reg0 = selectFirstRegister(cUnit, vSrc2, false);
+    reg1 = NEXT_REG(reg0);
+
+    switch (mir->dalvikInsn.opCode) {
+        case OP_ADD_FLOAT_2ADDR:
+        case OP_ADD_FLOAT:
+            funct = (void*) __aeabi_fadd;
+            break;
+        case OP_SUB_FLOAT_2ADDR:
+        case OP_SUB_FLOAT:
+            funct = (void*) __aeabi_fsub;
+            break;
+        case OP_DIV_FLOAT_2ADDR:
+        case OP_DIV_FLOAT:
+            funct = (void*) __aeabi_fdiv;
+            break;
+        case OP_MUL_FLOAT_2ADDR:
+        case OP_MUL_FLOAT:
+            funct = (void*) __aeabi_fmul;
+            break;
+        case OP_REM_FLOAT_2ADDR:
+        case OP_REM_FLOAT:
+            funct = (void*) fmodf;
+            break;
+        case OP_NEG_FLOAT: {
+            loadValue(cUnit, vSrc2, reg0);
+            loadConstant(cUnit, reg1, 0x80000000);
+            newLIR3(cUnit, THUMB_ADD_RRR, reg0, reg0, reg1);
+            storeValue(cUnit, reg0, vDest, reg1);
+            return false;
+        }
+        default:
+            return true;
+    }
+    loadConstant(cUnit, r2, (int)funct);
+    loadValue(cUnit, vSrc1, r0);
+    loadValue(cUnit, vSrc2, r1);
+    newLIR1(cUnit, THUMB_BLX_R, r2);
+    storeValue(cUnit, r0, vDest, r1);
+    return false;
+}
+
+bool genArithOpDoublePortable(CompilationUnit *cUnit, MIR *mir,
+                              int vDest, int vSrc1, int vSrc2)
+{
+    void* funct;
+    int reg0, reg1, reg2;
+
+    /* TODO: use a proper include file to define these */
+    double __aeabi_dadd(double a, double b);
+    double __aeabi_dsub(double a, double b);
+    double __aeabi_ddiv(double a, double b);
+    double __aeabi_dmul(double a, double b);
+    double fmod(double a, double b);
+
+    reg0 = selectFirstRegister(cUnit, vSrc2, true);
+    reg1 = NEXT_REG(reg0);
+    reg2 = NEXT_REG(reg1);
+
+    switch (mir->dalvikInsn.opCode) {
+        case OP_ADD_DOUBLE_2ADDR:
+        case OP_ADD_DOUBLE:
+            funct = (void*) __aeabi_dadd;
+            break;
+        case OP_SUB_DOUBLE_2ADDR:
+        case OP_SUB_DOUBLE:
+            funct = (void*) __aeabi_dsub;
+            break;
+        case OP_DIV_DOUBLE_2ADDR:
+        case OP_DIV_DOUBLE:
+            funct = (void*) __aeabi_ddiv;
+            break;
+        case OP_MUL_DOUBLE_2ADDR:
+        case OP_MUL_DOUBLE:
+            funct = (void*) __aeabi_dmul;
+            break;
+        case OP_REM_DOUBLE_2ADDR:
+        case OP_REM_DOUBLE:
+            funct = (void*) fmod;
+            break;
+        case OP_NEG_DOUBLE: {
+            loadValuePair(cUnit, vSrc2, reg0, reg1);
+            loadConstant(cUnit, reg2, 0x80000000);
+            newLIR3(cUnit, THUMB_ADD_RRR, reg1, reg1, reg2);
+            storeValuePair(cUnit, reg0, reg1, vDest, reg2);
+            return false;
+        }
+        default:
+            return true;
+    }
+    /*
+     * Don't optimize the regsiter usage here as they are governed by the EABI
+     * calling convention.
+     */
+    loadConstant(cUnit, r4PC, (int)funct);
+    loadValuePair(cUnit, vSrc1, r0, r1);
+    loadValuePair(cUnit, vSrc2, r2, r3);
+    newLIR1(cUnit, THUMB_BLX_R, r4PC);
+    storeValuePair(cUnit, r0, r1, vDest, r2);
+    return false;
+}
+
+static bool genArithOpLong(CompilationUnit *cUnit, MIR *mir, int vDest,
+                           int vSrc1, int vSrc2)
+{
+    int firstOp = THUMB_BKPT;
+    int secondOp = THUMB_BKPT;
+    bool callOut = false;
+    void *callTgt;
+    int retReg = r0;
+    int reg0, reg1, reg2, reg3;
+    /* TODO - find proper .h file to declare these */
+    long long __aeabi_ldivmod(long long op1, long long op2);
+
+    switch (mir->dalvikInsn.opCode) {
+        case OP_NOT_LONG:
+            firstOp = THUMB_MVN;
+            secondOp = THUMB_MVN;
+            break;
+        case OP_ADD_LONG:
+        case OP_ADD_LONG_2ADDR:
+            firstOp = THUMB_ADD_RRR;
+            secondOp = THUMB_ADC;
+            break;
+        case OP_SUB_LONG:
+        case OP_SUB_LONG_2ADDR:
+            firstOp = THUMB_SUB_RRR;
+            secondOp = THUMB_SBC;
+            break;
+        case OP_MUL_LONG:
+        case OP_MUL_LONG_2ADDR:
+            loadValuePair(cUnit, vSrc1, r0, r1);
+            loadValuePair(cUnit, vSrc2, r2, r3);
+            genDispatchToHandler(cUnit, TEMPLATE_MUL_LONG);
+            storeValuePair(cUnit, r0, r1, vDest, r2);
+            return false;
+            break;
+        case OP_DIV_LONG:
+        case OP_DIV_LONG_2ADDR:
+            callOut = true;
+            retReg = r0;
+            callTgt = (void*)__aeabi_ldivmod;
+            break;
+        /* NOTE - result is in r2/r3 instead of r0/r1 */
+        case OP_REM_LONG:
+        case OP_REM_LONG_2ADDR:
+            callOut = true;
+            callTgt = (void*)__aeabi_ldivmod;
+            retReg = r2;
+            break;
+        case OP_AND_LONG:
+        case OP_AND_LONG_2ADDR:
+            firstOp = THUMB_AND_RR;
+            secondOp = THUMB_AND_RR;
+            break;
+        case OP_OR_LONG:
+        case OP_OR_LONG_2ADDR:
+            firstOp = THUMB_ORR;
+            secondOp = THUMB_ORR;
+            break;
+        case OP_XOR_LONG:
+        case OP_XOR_LONG_2ADDR:
+            firstOp = THUMB_EOR;
+            secondOp = THUMB_EOR;
+            break;
+        case OP_NEG_LONG: {
+            reg0 = selectFirstRegister(cUnit, vSrc2, true);
+            reg1 = NEXT_REG(reg0);
+            reg2 = NEXT_REG(reg1);
+            reg3 = NEXT_REG(reg2);
+
+            loadValuePair(cUnit, vSrc2, reg0, reg1);
+            loadConstant(cUnit, reg3, 0);
+            newLIR3(cUnit, THUMB_SUB_RRR, reg2, reg3, reg0);
+            newLIR2(cUnit, THUMB_SBC, reg3, reg1);
+            storeValuePair(cUnit, reg2, reg3, vDest, reg0);
+            return false;
+        }
+        default:
+            LOGE("Invalid long arith op");
+            dvmAbort();
+    }
+    if (!callOut) {
+        reg0 = selectFirstRegister(cUnit, vSrc1, true);
+        reg1 = NEXT_REG(reg0);
+        reg2 = NEXT_REG(reg1);
+        reg3 = NEXT_REG(reg2);
+
+        loadValuePair(cUnit, vSrc1, reg0, reg1);
+        loadValuePair(cUnit, vSrc2, reg2, reg3);
+        genBinaryOpWide(cUnit, vDest, firstOp, secondOp, reg0, reg2);
+    /*
+     * Don't optimize the regsiter 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);
+        storeValuePair(cUnit, retReg, retReg+1, vDest, r4PC);
+    }
+    return false;
+}
+
+static bool genArithOpInt(CompilationUnit *cUnit, MIR *mir, int vDest,
+                          int vSrc1, int vSrc2)
+{
+    int armOp = THUMB_BKPT;
+    bool callOut = false;
+    bool checkZero = false;
+    int retReg = r0;
+    void *callTgt;
+    int reg0, reg1, regDest;
+
+    /* TODO - find proper .h file to declare these */
+    int __aeabi_idivmod(int op1, int op2);
+    int __aeabi_idiv(int op1, int op2);
+
+    switch (mir->dalvikInsn.opCode) {
+        case OP_NEG_INT:
+            armOp = THUMB_NEG;
+            break;
+        case OP_NOT_INT:
+            armOp = THUMB_MVN;
+            break;
+        case OP_ADD_INT:
+        case OP_ADD_INT_2ADDR:
+            armOp = THUMB_ADD_RRR;
+            break;
+        case OP_SUB_INT:
+        case OP_SUB_INT_2ADDR:
+            armOp = THUMB_SUB_RRR;
+            break;
+        case OP_MUL_INT:
+        case OP_MUL_INT_2ADDR:
+            armOp = THUMB_MUL;
+            break;
+        case OP_DIV_INT:
+        case OP_DIV_INT_2ADDR:
+            callOut = true;
+            checkZero = true;
+            callTgt = __aeabi_idiv;
+            retReg = r0;
+            break;
+        /* NOTE: returns in r1 */
+        case OP_REM_INT:
+        case OP_REM_INT_2ADDR:
+            callOut = true;
+            checkZero = true;
+            callTgt = __aeabi_idivmod;
+            retReg = r1;
+            break;
+        case OP_AND_INT:
+        case OP_AND_INT_2ADDR:
+            armOp = THUMB_AND_RR;
+            break;
+        case OP_OR_INT:
+        case OP_OR_INT_2ADDR:
+            armOp = THUMB_ORR;
+            break;
+        case OP_XOR_INT:
+        case OP_XOR_INT_2ADDR:
+            armOp = THUMB_EOR;
+            break;
+        case OP_SHL_INT:
+        case OP_SHL_INT_2ADDR:
+            armOp = THUMB_LSLV;
+            break;
+        case OP_SHR_INT:
+        case OP_SHR_INT_2ADDR:
+            armOp = THUMB_ASRV;
+            break;
+        case OP_USHR_INT:
+        case OP_USHR_INT_2ADDR:
+            armOp = THUMB_LSRV;
+            break;
+        default:
+            LOGE("Invalid word arith op: 0x%x(%d)",
+                 mir->dalvikInsn.opCode, mir->dalvikInsn.opCode);
+            dvmAbort();
+    }
+    if (!callOut) {
+         /* Try to allocate reg0 to the currently cached source operand  */
+        if (cUnit->registerScoreboard.liveDalvikReg == vSrc1) {
+            reg0 = selectFirstRegister(cUnit, vSrc1, false);
+            reg1 = NEXT_REG(reg0);
+            regDest = NEXT_REG(reg1);
+
+            loadValue(cUnit, vSrc1, reg0); /* Should be optimized away */
+            loadValue(cUnit, vSrc2, reg1);
+            genBinaryOp(cUnit, vDest, armOp, reg0, reg1, regDest);
+        } else {
+            reg0 = selectFirstRegister(cUnit, vSrc2, false);
+            reg1 = NEXT_REG(reg0);
+            regDest = NEXT_REG(reg1);
+
+            loadValue(cUnit, vSrc1, reg1); /* Load this value first */
+            loadValue(cUnit, vSrc2, reg0); /* May be optimized away */
+            genBinaryOp(cUnit, vDest, armOp, reg1, reg0, regDest);
+        }
+    } else {
+        /*
+         * Load the callout target first since it will never be eliminated
+         * and its value will be used first.
+         */
+        loadConstant(cUnit, r2, (int) callTgt);
+        /*
+         * Load vSrc2 first if it is not cached in a native register or it
+         * is in r0 which will be clobbered if vSrc1 is loaded first.
+         */
+        if (cUnit->registerScoreboard.liveDalvikReg != vSrc2 ||
+            cUnit->registerScoreboard.nativeReg == r0) {
+            /* Cannot be optimized and won't clobber r0 */
+            loadValue(cUnit, vSrc2, r1);
+            /* May be optimized if vSrc1 is cached */
+            loadValue(cUnit, vSrc1, r0);
+        } else {
+            loadValue(cUnit, vSrc1, r0);
+            loadValue(cUnit, vSrc2, r1);
+        }
+        if (checkZero) {
+            genNullCheck(cUnit, vSrc2, r1, mir->offset, NULL);
+        }
+        newLIR1(cUnit, THUMB_BLX_R, r2);
+        storeValue(cUnit, retReg, vDest, r2);
+    }
+    return false;
+}
+
+static bool genArithOp(CompilationUnit *cUnit, MIR *mir)
+{
+    OpCode opCode = mir->dalvikInsn.opCode;
+    int vA = mir->dalvikInsn.vA;
+    int vB = mir->dalvikInsn.vB;
+    int vC = mir->dalvikInsn.vC;
+
+    if ((opCode >= OP_ADD_LONG_2ADDR) && (opCode <= OP_XOR_LONG_2ADDR)) {
+        return genArithOpLong(cUnit,mir, vA, vA, vB);
+    }
+    if ((opCode >= OP_ADD_LONG) && (opCode <= OP_XOR_LONG)) {
+        return genArithOpLong(cUnit,mir, vA, vB, vC);
+    }
+    if ((opCode >= OP_SHL_LONG_2ADDR) && (opCode <= OP_USHR_LONG_2ADDR)) {
+        return genShiftOpLong(cUnit,mir, vA, vA, vB);
+    }
+    if ((opCode >= OP_SHL_LONG) && (opCode <= OP_USHR_LONG)) {
+        return genShiftOpLong(cUnit,mir, vA, vB, vC);
+    }
+    if ((opCode >= OP_ADD_INT_2ADDR) && (opCode <= OP_USHR_INT_2ADDR)) {
+        return genArithOpInt(cUnit,mir, vA, vA, vB);
+    }
+    if ((opCode >= OP_ADD_INT) && (opCode <= OP_USHR_INT)) {
+        return genArithOpInt(cUnit,mir, vA, vB, vC);
+    }
+    if ((opCode >= OP_ADD_FLOAT_2ADDR) && (opCode <= OP_REM_FLOAT_2ADDR)) {
+        return genArithOpFloat(cUnit,mir, vA, vA, vB);
+    }
+    if ((opCode >= OP_ADD_FLOAT) && (opCode <= OP_REM_FLOAT)) {
+        return genArithOpFloat(cUnit, mir, vA, vB, vC);
+    }
+    if ((opCode >= OP_ADD_DOUBLE_2ADDR) && (opCode <= OP_REM_DOUBLE_2ADDR)) {
+        return genArithOpDouble(cUnit,mir, vA, vA, vB);
+    }
+    if ((opCode >= OP_ADD_DOUBLE) && (opCode <= OP_REM_DOUBLE)) {
+        return genArithOpDouble(cUnit,mir, vA, vB, vC);
+    }
+    return true;
+}
+
+static bool genConversionCall(CompilationUnit *cUnit, MIR *mir, void *funct,
+                                     int srcSize, int tgtSize)
+{
+    /*
+     * Don't optimize the register usage since it calls out to template
+     * functions
+     */
+    loadConstant(cUnit, r2, (int)funct);
+    if (srcSize == 1) {
+        loadValue(cUnit, mir->dalvikInsn.vB, r0);
+    } else {
+        loadValuePair(cUnit, mir->dalvikInsn.vB, r0, r1);
+    }
+    newLIR1(cUnit, THUMB_BLX_R, r2);
+    if (tgtSize == 1) {
+        storeValue(cUnit, r0, mir->dalvikInsn.vA, r1);
+    } else {
+        storeValuePair(cUnit, r0, r1, mir->dalvikInsn.vA, r2);
+    }
+    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)
+{
+    unsigned int i;
+    unsigned int regMask = 0;
+
+    /* Load arguments to r0..r4 */
+    for (i = 0; i < dInsn->vA; i++) {
+        regMask |= 1 << i;
+        loadValue(cUnit, dInsn->arg[i], i);
+    }
+    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));
+        /* generate null check */
+        if (pcrLabel) {
+            *pcrLabel = genNullCheck(cUnit, dInsn->arg[0], r0, mir->offset,
+                                     NULL);
+        }
+        newLIR2(cUnit, THUMB_STMIA, r7, regMask);
+    }
+}
+
+static void genProcessArgsRange(CompilationUnit *cUnit, MIR *mir,
+                                DecodedInstruction *dInsn,
+                                ArmLIR **pcrLabel)
+{
+    int srcOffset = dInsn->vC << 2;
+    int numArgs = dInsn->vA;
+    int regMask;
+    /*
+     * 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);
+    }
+    /* load [r0 .. min(numArgs,4)] */
+    regMask = (1 << ((numArgs < 4) ? numArgs : 4)) - 1;
+    newLIR2(cUnit, THUMB_LDMIA, r4PC, regMask);
+
+    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);
+    }
+
+    /* generate null check */
+    if (pcrLabel) {
+        *pcrLabel = genNullCheck(cUnit, dInsn->vC, r0, mir->offset, NULL);
+    }
+
+    /*
+     * Handle remaining 4n arguments:
+     * store previously loaded 4 values and load the next 4 values
+     */
+    if (numArgs >= 8) {
+        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.
+         */
+        newLIR1(cUnit, THUMB_PUSH, 1 << r0 | 1 << 5);
+        /* 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);
+        }
+        newLIR2(cUnit, THUMB_STMIA, r7, regMask);
+        newLIR2(cUnit, THUMB_LDMIA, r4PC, regMask);
+        /* No need to generate the loop structure if numArgs <= 11 */
+        if (numArgs > 11) {
+            newLIR2(cUnit, THUMB_SUB_RI8, 5, 4);
+            genConditionalBranch(cUnit, ARM_COND_NE, loopLabel);
+        }
+    }
+
+    /* Save the last batch of loaded values */
+    newLIR2(cUnit, THUMB_STMIA, 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);
+    }
+    if (numArgs >= 8)
+        newLIR1(cUnit, THUMB_POP, 1 << r0 | 1 << 5);
+
+    /* Save the modulo 4 arguments */
+    if ((numArgs > 4) && (numArgs % 4)) {
+        newLIR2(cUnit, THUMB_STMIA, r7, regMask);
+    }
+}
+
+/*
+ * Generate code to setup the call stack then jump to the chaining cell if it
+ * is not a native method.
+ */
+static void genInvokeSingletonCommon(CompilationUnit *cUnit, MIR *mir,
+                                     BasicBlock *bb, ArmLIR *labelList,
+                                     ArmLIR *pcrLabel,
+                                     const Method *calleeMethod)
+{
+    ArmLIR *retChainingCell = &labelList[bb->fallThrough->id];
+
+    /* r1 = &retChainingCell */
+    ArmLIR *addrRetChain = newLIR3(cUnit, THUMB_ADD_PC_REL,
+                                           r1, 0, 0);
+    /* r4PC = dalvikCallsite */
+    loadConstant(cUnit, r4PC,
+                 (int) (cUnit->method->insns + mir->offset));
+    addrRetChain->generic.target = (LIR *) retChainingCell;
+    /*
+     * r0 = calleeMethod (loaded upon calling genInvokeSingletonCommon)
+     * r1 = &ChainingCell
+     * r4PC = callsiteDPC
+     */
+    if (dvmIsNativeMethod(calleeMethod)) {
+        genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_NATIVE);
+#if defined(INVOKE_STATS)
+        gDvmJit.invokeNative++;
+#endif
+    } else {
+        genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_CHAIN);
+#if defined(INVOKE_STATS)
+        gDvmJit.invokeChain++;
+#endif
+        /* Branch to the chaining cell */
+        genUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
+    }
+    /* Handle exceptions using the interpreter */
+    genTrap(cUnit, mir->offset, pcrLabel);
+}
+
+/*
+ * Generate code to check the validity of a predicted chain and take actions
+ * based on the result.
+ *
+ * 0x426a99aa : ldr     r4, [pc, #72] --> r4 <- dalvikPC of this invoke
+ * 0x426a99ac : add     r1, pc, #32   --> r1 <- &retChainingCell
+ * 0x426a99ae : add     r2, pc, #40   --> r2 <- &predictedChainingCell
+ * 0x426a99b0 : blx_1   0x426a918c    --+ TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN
+ * 0x426a99b2 : blx_2   see above     --+
+ * 0x426a99b4 : b       0x426a99d8    --> off to the predicted chain
+ * 0x426a99b6 : b       0x426a99c8    --> punt to the interpreter
+ * 0x426a99b8 : ldr     r0, [r7, #44] --> r0 <- this->class->vtable[methodIdx]
+ * 0x426a99ba : cmp     r1, #0        --> compare r1 (rechain count) against 0
+ * 0x426a99bc : bgt     0x426a99c2    --> >=0? don't rechain
+ * 0x426a99be : ldr     r7, [r6, #96] --+ dvmJitToPatchPredictedChain
+ * 0x426a99c0 : blx     r7            --+
+ * 0x426a99c2 : add     r1, pc, #12   --> r1 <- &retChainingCell
+ * 0x426a99c4 : blx_1   0x426a9098    --+ TEMPLATE_INVOKE_METHOD_NO_OPT
+ * 0x426a99c6 : blx_2   see above     --+
+ */
+static void genInvokeVirtualCommon(CompilationUnit *cUnit, MIR *mir,
+                                   int methodIndex,
+                                   ArmLIR *retChainingCell,
+                                   ArmLIR *predChainingCell,
+                                   ArmLIR *pcrLabel)
+{
+    /* "this" is already left in r0 by genProcessArgs* */
+
+    /* r4PC = dalvikCallsite */
+    loadConstant(cUnit, r4PC,
+                 (int) (cUnit->method->insns + mir->offset));
+
+    /* r1 = &retChainingCell */
+    ArmLIR *addrRetChain = newLIR2(cUnit, THUMB_ADD_PC_REL,
+                                       r1, 0);
+    addrRetChain->generic.target = (LIR *) retChainingCell;
+
+    /* r2 = &predictedChainingCell */
+    ArmLIR *predictedChainingCell =
+        newLIR2(cUnit, THUMB_ADD_PC_REL, r2, 0);
+    predictedChainingCell->generic.target = (LIR *) predChainingCell;
+
+    genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN);
+
+    /* return through lr - jump to the chaining cell */
+    genUnconditionalBranch(cUnit, predChainingCell);
+
+    /*
+     * null-check on "this" may have been eliminated, but we still need a PC-
+     * reconstruction label for stack overflow bailout.
+     */
+    if (pcrLabel == NULL) {
+        int dPC = (int) (cUnit->method->insns + mir->offset);
+        pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true);
+        pcrLabel->opCode = ARM_PSEUDO_PC_RECONSTRUCTION_CELL;
+        pcrLabel->operands[0] = dPC;
+        pcrLabel->operands[1] = mir->offset;
+        /* Insert the place holder to the growable list */
+        dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
+    }
+
+    /* return through lr+2 - punt to the interpreter */
+    genUnconditionalBranch(cUnit, pcrLabel);
+
+    /*
+     * return through lr+4 - fully resolve the callee method.
+     * r1 <- count
+     * r2 <- &predictedChainCell
+     * r3 <- this->class
+     * r4 <- dPC
+     * r7 <- this->class->vtable
+     */
+
+    /* 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);
+    }
+
+    /* Check if rechain limit is reached */
+    newLIR2(cUnit, THUMB_CMP_RI8, r1, 0);
+
+    ArmLIR *bypassRechaining =
+        newLIR2(cUnit, THUMB_B_COND, 0, ARM_COND_GT);
+
+    newLIR3(cUnit, THUMB_LDR_RRI5, r7, rGLUE,
+            offsetof(InterpState,
+                     jitToInterpEntries.dvmJitToPatchPredictedChain)
+            >> 2);
+
+    /*
+     * r0 = calleeMethod
+     * r2 = &predictedChainingCell
+     * r3 = class
+     *
+     * &returnChainingCell has been loaded into r1 but is not needed
+     * when patching the chaining cell and will be clobbered upon
+     * returning so it will be reconstructed again.
+     */
+    newLIR1(cUnit, THUMB_BLX_R, r7);
+
+    /* r1 = &retChainingCell */
+    addrRetChain = newLIR3(cUnit, THUMB_ADD_PC_REL, r1, 0, 0);
+    addrRetChain->generic.target = (LIR *) retChainingCell;
+
+    bypassRechaining->generic.target = (LIR *) addrRetChain;
+    /*
+     * r0 = calleeMethod,
+     * r1 = &ChainingCell,
+     * r4PC = callsiteDPC,
+     */
+    genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_NO_OPT);
+#if defined(INVOKE_STATS)
+    gDvmJit.invokePredictedChain++;
+#endif
+    /* Handle exceptions using the interpreter */
+    genTrap(cUnit, mir->offset, pcrLabel);
+}
+
+/*
+ * Up calling this function, "this" is stored in r0. The actual class will be
+ * chased down off r0 and the predicted one will be retrieved through
+ * predictedChainingCell then a comparison is performed to see whether the
+ * previously established chaining is still valid.
+ *
+ * The return LIR is a branch based on the comparison result. The actual branch
+ * target will be setup in the caller.
+ */
+static ArmLIR *genCheckPredictedChain(CompilationUnit *cUnit,
+                                          ArmLIR *predChainingCell,
+                                          ArmLIR *retChainingCell,
+                                          MIR *mir)
+{
+    /* r3 now contains this->clazz */
+    newLIR3(cUnit, THUMB_LDR_RRI5, r3, r0,
+            offsetof(Object, clazz) >> 2);
+
+    /*
+     * 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));
+    getPredictedClass->generic.target = (LIR *) predChainingCell;
+
+    /*
+     * r0 now contains predicted method. The starting offset of the
+     * cached value is 8 bytes into the chaining cell.
+     */
+    ArmLIR *getPredictedMethod =
+        newLIR3(cUnit, THUMB_LDR_PC_REL, r0, 0,
+                offsetof(PredictedChainingCell, method));
+    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));
+    getRechainingRequestCount->generic.target =
+        (LIR *) predChainingCell;
+
+    /* r4PC = dalvikCallsite */
+    loadConstant(cUnit, r4PC,
+                 (int) (cUnit->method->insns + mir->offset));
+
+    /* r1 = &retChainingCell */
+    ArmLIR *addrRetChain = newLIR3(cUnit, THUMB_ADD_PC_REL,
+                                       r1, 0, 0);
+    addrRetChain->generic.target = (LIR *) retChainingCell;
+
+    /* Check if r2 (predicted class) == r3 (actual class) */
+    newLIR2(cUnit, THUMB_CMP_RR, r2, r3);
+
+    return newLIR2(cUnit, THUMB_B_COND, 0, ARM_COND_EQ);
+}
+
+/* Geneate a branch to go back to the interpreter */
+static void genPuntToInterp(CompilationUnit *cUnit, unsigned int offset)
+{
+    /* 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);
+}
+
+/*
+ * Attempt to single step one instruction using the interpreter and return
+ * to the compiled code for the next Dalvik instruction
+ */
+static void genInterpSingleStep(CompilationUnit *cUnit, MIR *mir)
+{
+    int flags = dexGetInstrFlags(gDvm.instrFlags, mir->dalvikInsn.opCode);
+    int flagsToCheck = kInstrCanBranch | kInstrCanSwitch | kInstrCanReturn |
+                       kInstrCanThrow;
+    if ((mir->next == NULL) || (flags & flagsToCheck)) {
+       genPuntToInterp(cUnit, mir->offset);
+       return;
+    }
+    int entryAddr = offsetof(InterpState,
+                             jitToInterpEntries.dvmJitToInterpSingleStep);
+    newLIR3(cUnit, THUMB_LDR_RRI5, r2, rGLUE, entryAddr >> 2);
+    /* 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);
+}
+
+
+/*****************************************************************************/
+/*
+ * The following are the first-level codegen routines that analyze the format
+ * of each bytecode then either dispatch special purpose codegen routines
+ * or produce corresponding Thumb instructions directly.
+ */
+
+static bool handleFmt10t_Fmt20t_Fmt30t(CompilationUnit *cUnit, MIR *mir,
+                                       BasicBlock *bb, ArmLIR *labelList)
+{
+    /* For OP_GOTO, OP_GOTO_16, and OP_GOTO_32 */
+    genUnconditionalBranch(cUnit, &labelList[bb->taken->id]);
+    return false;
+}
+
+static bool handleFmt10x(CompilationUnit *cUnit, MIR *mir)
+{
+    OpCode dalvikOpCode = mir->dalvikInsn.opCode;
+    if (((dalvikOpCode >= OP_UNUSED_3E) && (dalvikOpCode <= OP_UNUSED_43)) ||
+        ((dalvikOpCode >= OP_UNUSED_E3) && (dalvikOpCode <= OP_UNUSED_EC))) {
+        LOGE("Codegen: got unused opcode 0x%x\n",dalvikOpCode);
+        return true;
+    }
+    switch (dalvikOpCode) {
+        case OP_RETURN_VOID:
+            genReturnCommon(cUnit,mir);
+            break;
+        case OP_UNUSED_73:
+        case OP_UNUSED_79:
+        case OP_UNUSED_7A:
+            LOGE("Codegen: got unused opcode 0x%x\n",dalvikOpCode);
+            return true;
+        case OP_NOP:
+            break;
+        default:
+            return true;
+    }
+    return false;
+}
+
+static bool handleFmt11n_Fmt31i(CompilationUnit *cUnit, MIR *mir)
+{
+    int reg0, reg1, reg2;
+
+    switch (mir->dalvikInsn.opCode) {
+        case OP_CONST:
+        case OP_CONST_4: {
+            /* Avoid using the previously used register */
+            reg0 = selectFirstRegister(cUnit, vNone, false);
+            reg1 = NEXT_REG(reg0);
+            loadConstant(cUnit, reg0, mir->dalvikInsn.vB);
+            storeValue(cUnit, reg0, mir->dalvikInsn.vA, reg1);
+            break;
+        }
+        case OP_CONST_WIDE_32: {
+            /* Avoid using the previously used register */
+            reg0 = selectFirstRegister(cUnit, vNone, true);
+            reg1 = NEXT_REG(reg0);
+            reg2 = NEXT_REG(reg1);
+            loadConstant(cUnit, reg0, mir->dalvikInsn.vB);
+            newLIR3(cUnit, THUMB_ASR, reg1, reg0, 31);
+            storeValuePair(cUnit, reg0, reg1, mir->dalvikInsn.vA, reg2);
+            break;
+        }
+        default:
+            return true;
+    }
+    return false;
+}
+
+static bool handleFmt21h(CompilationUnit *cUnit, MIR *mir)
+{
+    int reg0, reg1, reg2;
+
+    /* Avoid using the previously used register */
+    switch (mir->dalvikInsn.opCode) {
+        case OP_CONST_HIGH16: {
+            reg0 = selectFirstRegister(cUnit, vNone, false);
+            reg1 = NEXT_REG(reg0);
+            loadConstant(cUnit, reg0, mir->dalvikInsn.vB << 16);
+            storeValue(cUnit, reg0, mir->dalvikInsn.vA, reg1);
+            break;
+        }
+        case OP_CONST_WIDE_HIGH16: {
+            reg0 = selectFirstRegister(cUnit, vNone, true);
+            reg1 = NEXT_REG(reg0);
+            reg2 = NEXT_REG(reg1);
+            loadConstant(cUnit, reg1, mir->dalvikInsn.vB << 16);
+            loadConstant(cUnit, reg0, 0);
+            storeValuePair(cUnit, reg0, reg1, mir->dalvikInsn.vA, reg2);
+            break;
+        }
+        default:
+            return true;
+    }
+    return false;
+}
+
+static bool handleFmt20bc(CompilationUnit *cUnit, MIR *mir)
+{
+    /* For OP_THROW_VERIFICATION_ERROR */
+    genInterpSingleStep(cUnit, mir);
+    return false;
+}
+
+static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
+{
+    /* Native register to use if the interested value is vA */
+    int regvA = selectFirstRegister(cUnit, mir->dalvikInsn.vA, false);
+    /* Native register to use if source is not from Dalvik registers */
+    int regvNone = selectFirstRegister(cUnit, vNone, false);
+    /* Similar to regvA but for 64-bit values */
+    int regvAWide = selectFirstRegister(cUnit, mir->dalvikInsn.vA, true);
+    /* Similar to regvNone but for 64-bit values */
+    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*)
+              (cUnit->method->clazz->pDvmDex->pResStrings[mir->dalvikInsn.vB]);
+            assert(strPtr != NULL);
+            loadConstant(cUnit, regvNone, (int) strPtr );
+            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]);
+            assert(classPtr != NULL);
+            loadConstant(cUnit, regvNone, (int) classPtr );
+            storeValue(cUnit, regvNone, mir->dalvikInsn.vA, NEXT_REG(regvNone));
+            break;
+        }
+        case OP_SGET_OBJECT:
+        case OP_SGET_BOOLEAN:
+        case OP_SGET_CHAR:
+        case OP_SGET_BYTE:
+        case OP_SGET_SHORT:
+        case OP_SGET: {
+            int valOffset = offsetof(StaticField, value);
+            void *fieldPtr = (void*)
+              (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);
+            storeValue(cUnit, regvNone, mir->dalvikInsn.vA, NEXT_REG(regvNone));
+            break;
+        }
+        case OP_SGET_WIDE: {
+            int valOffset = offsetof(StaticField, value);
+            void *fieldPtr = (void*)
+              (cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
+            int reg0, reg1, reg2;
+
+            assert(fieldPtr != NULL);
+            reg0 = regvNoneWide;
+            reg1 = NEXT_REG(reg0);
+            reg2 = NEXT_REG(reg1);
+            loadConstant(cUnit, reg2,  (int) fieldPtr + valOffset);
+            newLIR2(cUnit, THUMB_LDMIA, reg2, (1<<reg0 | 1<<reg1));
+            storeValuePair(cUnit, reg0, reg1, mir->dalvikInsn.vA, reg2);
+            break;
+        }
+        case OP_SPUT_OBJECT:
+        case OP_SPUT_BOOLEAN:
+        case OP_SPUT_CHAR:
+        case OP_SPUT_BYTE:
+        case OP_SPUT_SHORT:
+        case OP_SPUT: {
+            int valOffset = offsetof(StaticField, value);
+            void *fieldPtr = (void*)
+              (cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
+
+            assert(fieldPtr != NULL);
+            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);
+            break;
+        }
+        case OP_SPUT_WIDE: {
+            int reg0, reg1, reg2;
+            int valOffset = offsetof(StaticField, value);
+            void *fieldPtr = (void*)
+              (cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
+
+            assert(fieldPtr != NULL);
+            reg0 = regvAWide;
+            reg1 = NEXT_REG(reg0);
+            reg2 = NEXT_REG(reg1);
+            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));
+            break;
+        }
+        case OP_NEW_INSTANCE: {
+            /*
+             * Obey the calling convention and don't mess with the register
+             * usage.
+             */
+            ClassObject *classPtr = (void*)
+              (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;
+            }
+            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);
+            /*
+             * TODO: As coded, we'll bail and reinterpret on alloc failure.
+             * Need a general mechanism to bail to thrown exception code.
+             */
+            genZeroCheck(cUnit, r0, mir->offset, NULL);
+            storeValue(cUnit, r0, mir->dalvikInsn.vA, r1);
+            break;
+        }
+        case OP_CHECK_CAST: {
+            /*
+             * Obey the calling convention and don't mess with the register
+             * usage.
+             */
+            ClassObject *classPtr =
+              (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);
+            /* r0 now contains object->clazz */
+            newLIR3(cUnit, THUMB_LDR_RRI5, r0, r0,
+                    offsetof(Object, clazz) >> 2);
+            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);
+            /* check cast failed - punt to the interpreter */
+            genZeroCheck(cUnit, r0, mir->offset, pcrLabel);
+            /* check cast passed - branch target here */
+            ArmLIR *target = newLIR0(cUnit, ARM_PSEUDO_TARGET_LABEL);
+            branch1->generic.target = (LIR *)target;
+            branch2->generic.target = (LIR *)target;
+            break;
+        }
+        default:
+            return true;
+    }
+    return false;
+}
+
+static bool handleFmt11x(CompilationUnit *cUnit, MIR *mir)
+{
+    OpCode dalvikOpCode = mir->dalvikInsn.opCode;
+    switch (dalvikOpCode) {
+        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);
+            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);
+            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);
+            storeValuePair(cUnit, r0, r1, mir->dalvikInsn.vA, r2);
+            break;
+        }
+        case OP_RETURN_WIDE: {
+            loadValuePair(cUnit, mir->dalvikInsn.vA, r0, r1);
+            int offset = offsetof(InterpState, retval);
+            newLIR3(cUnit, THUMB_STR_RRI5, r0, rGLUE, offset >> 2);
+            newLIR3(cUnit, THUMB_STR_RRI5, r1, rGLUE, (offset >> 2)+1);
+            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);
+            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);
+            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);
+            break;
+        }
+        case OP_THROW: {
+            genInterpSingleStep(cUnit, mir);
+            break;
+        }
+        default:
+            return true;
+    }
+    return false;
+}
+
+static bool genConversionPortable(CompilationUnit *cUnit, MIR *mir)
+{
+    OpCode opCode = mir->dalvikInsn.opCode;
+
+    float  __aeabi_i2f(  int op1 );
+    int    __aeabi_f2iz( float op1 );
+    float  __aeabi_d2f(  double op1 );
+    double __aeabi_f2d(  float op1 );
+    double __aeabi_i2d(  int op1 );
+    int    __aeabi_d2iz( double op1 );
+    float  __aeabi_l2f(  long op1 );
+    double __aeabi_l2d(  long op1 );
+
+    switch (opCode) {
+        case OP_INT_TO_FLOAT:
+            return genConversionCall(cUnit, mir, (void*)__aeabi_i2f, 1, 1);
+        case OP_FLOAT_TO_INT:
+            return genConversionCall(cUnit, mir, (void*)__aeabi_f2iz, 1, 1);
+        case OP_DOUBLE_TO_FLOAT:
+            return genConversionCall(cUnit, mir, (void*)__aeabi_d2f, 2, 1);
+        case OP_FLOAT_TO_DOUBLE:
+            return genConversionCall(cUnit, mir, (void*)__aeabi_f2d, 1, 2);
+        case OP_INT_TO_DOUBLE:
+            return genConversionCall(cUnit, mir, (void*)__aeabi_i2d, 1, 2);
+        case OP_DOUBLE_TO_INT:
+            return genConversionCall(cUnit, mir, (void*)__aeabi_d2iz, 2, 1);
+        case OP_FLOAT_TO_LONG:
+            return genConversionCall(cUnit, mir, (void*)dvmJitf2l, 1, 2);
+        case OP_LONG_TO_FLOAT:
+            return genConversionCall(cUnit, mir, (void*)__aeabi_l2f, 2, 1);
+        case OP_DOUBLE_TO_LONG:
+            return genConversionCall(cUnit, mir, (void*)dvmJitd2l, 2, 2);
+        case OP_LONG_TO_DOUBLE:
+            return genConversionCall(cUnit, mir, (void*)__aeabi_l2d, 2, 2);
+        default:
+            return true;
+    }
+    return false;
+}
+
+static bool handleFmt12x(CompilationUnit *cUnit, MIR *mir)
+{
+    OpCode opCode = mir->dalvikInsn.opCode;
+    int vSrc1Dest = mir->dalvikInsn.vA;
+    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 );
+    }
+
+    /*
+     * If data type is 64-bit, re-calculate the register numbers in the
+     * corresponding cases.
+     */
+    reg0 = selectFirstRegister(cUnit, vSrc2, false);
+    reg1 = NEXT_REG(reg0);
+    reg2 = NEXT_REG(reg1);
+
+    switch (opCode) {
+        case OP_INT_TO_FLOAT:
+        case OP_FLOAT_TO_INT:
+        case OP_DOUBLE_TO_FLOAT:
+        case OP_FLOAT_TO_DOUBLE:
+        case OP_INT_TO_DOUBLE:
+        case OP_DOUBLE_TO_INT:
+        case OP_FLOAT_TO_LONG:
+        case OP_LONG_TO_FLOAT:
+        case OP_DOUBLE_TO_LONG:
+        case OP_LONG_TO_DOUBLE:
+            return genConversion(cUnit, mir);
+        case OP_NEG_INT:
+        case OP_NOT_INT:
+            return genArithOpInt(cUnit, mir, vSrc1Dest, vSrc1Dest, vSrc2);
+        case OP_NEG_LONG:
+        case OP_NOT_LONG:
+            return genArithOpLong(cUnit,mir, vSrc1Dest, vSrc1Dest, vSrc2);
+        case OP_NEG_FLOAT:
+            return genArithOpFloat(cUnit, mir, vSrc1Dest, vSrc1Dest, vSrc2);
+        case OP_NEG_DOUBLE:
+            return genArithOpDouble(cUnit, mir, vSrc1Dest, vSrc1Dest, vSrc2);
+        case OP_MOVE_WIDE: {
+            reg0 = selectFirstRegister(cUnit, vSrc2, true);
+            reg1 = NEXT_REG(reg0);
+            reg2 = NEXT_REG(reg1);
+
+            loadValuePair(cUnit, vSrc2, reg0, reg1);
+            storeValuePair(cUnit, reg0, reg1, vSrc1Dest, reg2);
+            break;
+        }
+        case OP_INT_TO_LONG: {
+            reg0 = selectFirstRegister(cUnit, vSrc2, true);
+            reg1 = NEXT_REG(reg0);
+            reg2 = NEXT_REG(reg1);
+
+            loadValue(cUnit, vSrc2, reg0);
+            newLIR3(cUnit, THUMB_ASR, reg1, reg0, 31);
+            storeValuePair(cUnit, reg0, reg1, vSrc1Dest, reg2);
+            break;
+        }
+        case OP_MOVE:
+        case OP_MOVE_OBJECT:
+        case OP_LONG_TO_INT:
+            loadValue(cUnit, vSrc2, reg0);
+            storeValue(cUnit, reg0, vSrc1Dest, reg1);
+            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);
+            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);
+            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);
+            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);
+            storeValue(cUnit, reg0, vSrc1Dest, reg1);
+            break;
+        }
+        default:
+            return true;
+    }
+    return false;
+}
+
+static bool handleFmt21s(CompilationUnit *cUnit, MIR *mir)
+{
+    OpCode dalvikOpCode = mir->dalvikInsn.opCode;
+    int reg0, reg1, reg2;
+
+    /* It takes few instructions to handle OP_CONST_WIDE_16 inline */
+    if (dalvikOpCode == OP_CONST_WIDE_16) {
+        int vDest = mir->dalvikInsn.vA;
+        int BBBB = mir->dalvikInsn.vB;
+
+        reg0 = selectFirstRegister(cUnit, vNone, true);
+        reg1 = NEXT_REG(reg0);
+        reg2 = NEXT_REG(reg1);
+
+        loadConstant(cUnit, reg0, BBBB);
+        newLIR3(cUnit, THUMB_ASR, reg1, reg0, 31);
+
+        /* Save the long values to the specified Dalvik register pair */
+        storeValuePair(cUnit, reg0, reg1, vDest, reg2);
+    } else if (dalvikOpCode == OP_CONST_16) {
+        int vDest = mir->dalvikInsn.vA;
+        int BBBB = mir->dalvikInsn.vB;
+
+        reg0 = selectFirstRegister(cUnit, vNone, false);
+        reg1 = NEXT_REG(reg0);
+
+        loadConstant(cUnit, reg0, BBBB);
+        storeValue(cUnit, reg0, vDest, reg1);
+    } else {
+        return true;
+    }
+    return false;
+}
+
+/* Compare agaist zero */
+static bool handleFmt21t(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
+                         ArmLIR *labelList)
+{
+    OpCode dalvikOpCode = mir->dalvikInsn.opCode;
+    ArmConditionCode cond;
+    int reg0 = selectFirstRegister(cUnit, mir->dalvikInsn.vA, false);
+
+    loadValue(cUnit, mir->dalvikInsn.vA, reg0);
+    newLIR2(cUnit, THUMB_CMP_RI8, reg0, 0);
+
+    switch (dalvikOpCode) {
+        case OP_IF_EQZ:
+            cond = ARM_COND_EQ;
+            break;
+        case OP_IF_NEZ:
+            cond = ARM_COND_NE;
+            break;
+        case OP_IF_LTZ:
+            cond = ARM_COND_LT;
+            break;
+        case OP_IF_GEZ:
+            cond = ARM_COND_GE;
+            break;
+        case OP_IF_GTZ:
+            cond = ARM_COND_GT;
+            break;
+        case OP_IF_LEZ:
+            cond = ARM_COND_LE;
+            break;
+        default:
+            cond = 0;
+            LOGE("Unexpected opcode (%d) for Fmt21t\n", dalvikOpCode);
+            dvmAbort();
+    }
+    genConditionalBranch(cUnit, cond, &labelList[bb->taken->id]);
+    /* This mostly likely will be optimized away in a later phase */
+    genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
+    return false;
+}
+
+static bool handleFmt22b_Fmt22s(CompilationUnit *cUnit, MIR *mir)
+{
+    OpCode dalvikOpCode = mir->dalvikInsn.opCode;
+    int vSrc = mir->dalvikInsn.vB;
+    int vDest = mir->dalvikInsn.vA;
+    int lit = mir->dalvikInsn.vC;
+    int armOp;
+    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);
+
+    switch (dalvikOpCode) {
+        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);
+            }
+            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);
+            break;
+
+        case OP_MUL_INT_LIT8:
+        case OP_MUL_INT_LIT16:
+        case OP_AND_INT_LIT8:
+        case OP_AND_INT_LIT16:
+        case OP_OR_INT_LIT8:
+        case OP_OR_INT_LIT16:
+        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;
+                    break;
+                case OP_AND_INT_LIT8:
+                case OP_AND_INT_LIT16:
+                    armOp = THUMB_AND_RR;
+                    break;
+                case OP_OR_INT_LIT8:
+                case OP_OR_INT_LIT16:
+                    armOp = THUMB_ORR;
+                    break;
+                case OP_XOR_INT_LIT8:
+                case OP_XOR_INT_LIT16:
+                    armOp = THUMB_EOR;
+                    break;
+                default:
+                    dvmAbort();
+            }
+            genBinaryOp(cUnit, vDest, armOp, reg0, reg1, regDest);
+            break;
+
+        case OP_SHL_INT_LIT8:
+        case OP_SHR_INT_LIT8:
+        case OP_USHR_INT_LIT8:
+            loadValue(cUnit, vSrc, reg0);
+            switch (dalvikOpCode) {
+                case OP_SHL_INT_LIT8:
+                    armOp = THUMB_LSL;
+                    break;
+                case OP_SHR_INT_LIT8:
+                    armOp = THUMB_ASR;
+                    break;
+                case OP_USHR_INT_LIT8:
+                    armOp = THUMB_LSR;
+                    break;
+                default: dvmAbort();
+            }
+            newLIR3(cUnit, armOp, reg0, reg0, lit);
+            storeValue(cUnit, reg0, vDest, reg1);
+            break;
+
+        case OP_DIV_INT_LIT8:
+        case OP_DIV_INT_LIT16:
+            /* Register usage based on the calling convention */
+            if (lit == 0) {
+                /* Let the interpreter deal with div by 0 */
+                genInterpSingleStep(cUnit, mir);
+                return false;
+            }
+            loadConstant(cUnit, r2, (int)__aeabi_idiv);
+            loadConstant(cUnit, r1, lit);
+            loadValue(cUnit, vSrc, r0);
+            newLIR1(cUnit, THUMB_BLX_R, r2);
+            storeValue(cUnit, r0, vDest, r2);
+            break;
+
+        case OP_REM_INT_LIT8:
+        case OP_REM_INT_LIT16:
+            /* Register usage based on the calling convention */
+            if (lit == 0) {
+                /* Let the interpreter deal with div by 0 */
+                genInterpSingleStep(cUnit, mir);
+                return false;
+            }
+            loadConstant(cUnit, r2, (int)__aeabi_idivmod);
+            loadConstant(cUnit, r1, lit);
+            loadValue(cUnit, vSrc, r0);
+            newLIR1(cUnit, THUMB_BLX_R, r2);
+            storeValue(cUnit, r1, vDest, r2);
+            break;
+        default:
+            return true;
+    }
+    return false;
+}
+
+static bool handleFmt22c(CompilationUnit *cUnit, MIR *mir)
+{
+    OpCode dalvikOpCode = mir->dalvikInsn.opCode;
+    int fieldOffset;
+
+    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;
+    }
+    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]);
+            assert(classPtr != NULL);
+            loadValue(cUnit, mir->dalvikInsn.vB, r1);  /* Len */
+            loadConstant(cUnit, r0, (int) classPtr );
+            loadConstant(cUnit, r4PC, (int)dvmAllocArrayByClass);
+            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);
+            /*
+             * TODO: As coded, we'll bail and reinterpret on alloc failure.
+             * Need a general mechanism to bail to thrown exception code.
+             */
+            genZeroCheck(cUnit, r0, mir->offset, pcrLabel);
+            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? */
+            /* When taken r0 has NULL which can be used for store directly */
+            ArmLIR *branch1 = newLIR2(cUnit, THUMB_B_COND, 4,
+                                          ARM_COND_EQ);
+            /* r1 now contains object->clazz */
+            newLIR3(cUnit, THUMB_LDR_RRI5, r1, r0,
+                    offsetof(Object, clazz) >> 2);
+            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);
+            /* branch target here */
+            ArmLIR *target = newLIR0(cUnit, ARM_PSEUDO_TARGET_LABEL);
+            storeValue(cUnit, r0, mir->dalvikInsn.vA, r1);
+            branch1->generic.target = (LIR *)target;
+            branch2->generic.target = (LIR *)target;
+            break;
+        }
+        case OP_IGET_WIDE:
+            genIGetWide(cUnit, mir, fieldOffset);
+            break;
+        case OP_IGET:
+        case OP_IGET_OBJECT:
+            genIGet(cUnit, mir, THUMB_LDR_RRR, fieldOffset);
+            break;
+        case OP_IGET_BOOLEAN:
+            genIGet(cUnit, mir, THUMB_LDRB_RRR, fieldOffset);
+            break;
+        case OP_IGET_BYTE:
+            genIGet(cUnit, mir, THUMB_LDRSB_RRR, fieldOffset);
+            break;
+        case OP_IGET_CHAR:
+            genIGet(cUnit, mir, THUMB_LDRH_RRR, fieldOffset);
+            break;
+        case OP_IGET_SHORT:
+            genIGet(cUnit, mir, THUMB_LDRSH_RRR, 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);
+            break;
+        case OP_IPUT_SHORT:
+        case OP_IPUT_CHAR:
+            genIPut(cUnit, mir, THUMB_STRH_RRR, fieldOffset);
+            break;
+        case OP_IPUT_BYTE:
+        case OP_IPUT_BOOLEAN:
+            genIPut(cUnit, mir, THUMB_STRB_RRR, fieldOffset);
+            break;
+        default:
+            return true;
+    }
+    return false;
+}
+
+static bool handleFmt22cs(CompilationUnit *cUnit, MIR *mir)
+{
+    OpCode dalvikOpCode = mir->dalvikInsn.opCode;
+    int fieldOffset =  mir->dalvikInsn.vC;
+    switch (dalvikOpCode) {
+        case OP_IGET_QUICK:
+        case OP_IGET_OBJECT_QUICK:
+            genIGet(cUnit, mir, THUMB_LDR_RRR, fieldOffset);
+            break;
+        case OP_IPUT_QUICK:
+        case OP_IPUT_OBJECT_QUICK:
+            genIPut(cUnit, mir, THUMB_STR_RRR, fieldOffset);
+            break;
+        case OP_IGET_WIDE_QUICK:
+            genIGetWide(cUnit, mir, fieldOffset);
+            break;
+        case OP_IPUT_WIDE_QUICK:
+            genIPutWide(cUnit, mir, fieldOffset);
+            break;
+        default:
+            return true;
+    }
+    return false;
+
+}
+
+/* Compare agaist zero */
+static bool handleFmt22t(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
+                         ArmLIR *labelList)
+{
+    OpCode dalvikOpCode = mir->dalvikInsn.opCode;
+    ArmConditionCode cond;
+    int reg0, reg1;
+
+    if (cUnit->registerScoreboard.liveDalvikReg == (int) mir->dalvikInsn.vA) {
+        reg0 = selectFirstRegister(cUnit, mir->dalvikInsn.vA, false);
+        reg1 = NEXT_REG(reg0);
+        /* Load vB first since vA can be fetched via a move */
+        loadValue(cUnit, mir->dalvikInsn.vB, reg1);
+        loadValue(cUnit, mir->dalvikInsn.vA, reg0);
+    } else {
+        reg0 = selectFirstRegister(cUnit, mir->dalvikInsn.vB, false);
+        reg1 = NEXT_REG(reg0);
+        /* Load vA first since vB can be fetched via a move */
+        loadValue(cUnit, mir->dalvikInsn.vA, reg0);
+        loadValue(cUnit, mir->dalvikInsn.vB, reg1);
+    }
+    newLIR2(cUnit, THUMB_CMP_RR, reg0, reg1);
+
+    switch (dalvikOpCode) {
+        case OP_IF_EQ:
+            cond = ARM_COND_EQ;
+            break;
+        case OP_IF_NE:
+            cond = ARM_COND_NE;
+            break;
+        case OP_IF_LT:
+            cond = ARM_COND_LT;
+            break;
+        case OP_IF_GE:
+            cond = ARM_COND_GE;
+            break;
+        case OP_IF_GT:
+            cond = ARM_COND_GT;
+            break;
+        case OP_IF_LE:
+            cond = ARM_COND_LE;
+            break;
+        default:
+            cond = 0;
+            LOGE("Unexpected opcode (%d) for Fmt22t\n", dalvikOpCode);
+            dvmAbort();
+    }
+    genConditionalBranch(cUnit, cond, &labelList[bb->taken->id]);
+    /* This mostly likely will be optimized away in a later phase */
+    genUnconditionalBranch(cUnit, &labelList[bb->fallThrough->id]);
+    return false;
+}
+
+static bool handleFmt22x_Fmt32x(CompilationUnit *cUnit, MIR *mir)
+{
+    OpCode opCode = mir->dalvikInsn.opCode;
+    int vSrc1Dest = mir->dalvikInsn.vA;
+    int vSrc2 = mir->dalvikInsn.vB;
+    int reg0, reg1, reg2;
+
+    switch (opCode) {
+        case OP_MOVE_16:
+        case OP_MOVE_OBJECT_16:
+        case OP_MOVE_FROM16:
+        case OP_MOVE_OBJECT_FROM16: {
+            reg0 = selectFirstRegister(cUnit, vSrc2, false);
+            reg1 = NEXT_REG(reg0);
+            loadValue(cUnit, vSrc2, reg0);
+            storeValue(cUnit, reg0, vSrc1Dest, reg1);
+            break;
+        }
+        case OP_MOVE_WIDE_16:
+        case OP_MOVE_WIDE_FROM16: {
+            reg0 = selectFirstRegister(cUnit, vSrc2, true);
+            reg1 = NEXT_REG(reg0);
+            reg2 = NEXT_REG(reg1);
+            loadValuePair(cUnit, vSrc2, reg0, reg1);
+            storeValuePair(cUnit, reg0, reg1, vSrc1Dest, reg2);
+            break;
+        }
+        default:
+            return true;
+    }
+    return false;
+}
+
+static bool handleFmt23x(CompilationUnit *cUnit, MIR *mir)
+{
+    OpCode opCode = mir->dalvikInsn.opCode;
+    int vA = mir->dalvikInsn.vA;
+    int vB = mir->dalvikInsn.vB;
+    int vC = mir->dalvikInsn.vC;
+
+    /* Don't optimize for register usage since out-of-line handlers are used */
+    if ( (opCode >= OP_ADD_INT) && (opCode <= OP_REM_DOUBLE)) {
+        return genArithOp( cUnit, mir );
+    }
+
+    switch (opCode) {
+        case OP_CMPL_FLOAT:
+        case OP_CMPG_FLOAT:
+        case OP_CMPL_DOUBLE:
+        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);
+            break;
+        case OP_AGET_WIDE:
+            genArrayGet(cUnit, mir, THUMB_LDR_RRR, vB, vC, vA, 3);
+            break;
+        case OP_AGET:
+        case OP_AGET_OBJECT:
+            genArrayGet(cUnit, mir, THUMB_LDR_RRR, vB, vC, vA, 2);
+            break;
+        case OP_AGET_BOOLEAN:
+            genArrayGet(cUnit, mir, THUMB_LDRB_RRR, vB, vC, vA, 0);
+            break;
+        case OP_AGET_BYTE:
+            genArrayGet(cUnit, mir, THUMB_LDRSB_RRR, vB, vC, vA, 0);
+            break;
+        case OP_AGET_CHAR:
+            genArrayGet(cUnit, mir, THUMB_LDRH_RRR, vB, vC, vA, 1);
+            break;
+        case OP_AGET_SHORT:
+            genArrayGet(cUnit, mir, THUMB_LDRSH_RRR, vB, vC, vA, 1);
+            break;
+        case OP_APUT_WIDE:
+            genArrayPut(cUnit, mir, THUMB_STR_RRR, vB, vC, vA, 3);
+            break;
+        case OP_APUT:
+        case OP_APUT_OBJECT:
+            genArrayPut(cUnit, mir, THUMB_STR_RRR, vB, vC, vA, 2);
+            break;
+        case OP_APUT_SHORT:
+        case OP_APUT_CHAR:
+            genArrayPut(cUnit, mir, THUMB_STRH_RRR, vB, vC, vA, 1);
+            break;
+        case OP_APUT_BYTE:
+        case OP_APUT_BOOLEAN:
+            genArrayPut(cUnit, mir, THUMB_STRB_RRR, vB, vC, vA, 0);
+            break;
+        default:
+            return true;
+    }
+    return false;
+}
+
+static bool handleFmt31t(CompilationUnit *cUnit, MIR *mir)
+{
+    OpCode dalvikOpCode = mir->dalvikInsn.opCode;
+    switch (dalvikOpCode) {
+        case OP_FILL_ARRAY_DATA: {
+            loadConstant(cUnit, r4PC, (int)dvmInterpHandleFillArrayData);
+            loadValue(cUnit, mir->dalvikInsn.vA, r0);
+            loadConstant(cUnit, r1, (mir->dalvikInsn.vB << 1) +
+                 (int) (cUnit->method->insns + mir->offset));
+            genExportPC(cUnit, mir, r2, r3 );
+            newLIR1(cUnit, THUMB_BLX_R, r4PC);
+            genZeroCheck(cUnit, r0, mir->offset, NULL);
+            break;
+        }
+        /*
+         * TODO
+         * - Add a 1 to 3-entry per-location cache here to completely
+         *   bypass the dvmInterpHandle[Packed/Sparse]Switch call w/ chaining
+         * - Use out-of-line handlers for both of these
+         */
+        case OP_PACKED_SWITCH:
+        case OP_SPARSE_SWITCH: {
+            if (dalvikOpCode == OP_PACKED_SWITCH) {
+                loadConstant(cUnit, r4PC, (int)dvmInterpHandlePackedSwitch);
+            } else {
+                loadConstant(cUnit, r4PC, (int)dvmInterpHandleSparseSwitch);
+            }
+            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);
+            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);
+            break;
+        }
+        default:
+            return true;
+    }
+    return false;
+}
+
+static bool handleFmt35c_3rc(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
+                             ArmLIR *labelList)
+{
+    ArmLIR *retChainingCell = NULL;
+    ArmLIR *pcrLabel = NULL;
+
+    if (bb->fallThrough != NULL)
+        retChainingCell = &labelList[bb->fallThrough->id];
+
+    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    switch (mir->dalvikInsn.opCode) {
+        /*
+         * calleeMethod = this->clazz->vtable[
+         *     method->clazz->pDvmDex->pResMethods[BBBB]->methodIndex
+         * ]
+         */
+        case OP_INVOKE_VIRTUAL:
+        case OP_INVOKE_VIRTUAL_RANGE: {
+            ArmLIR *predChainingCell = &labelList[bb->taken->id];
+            int methodIndex =
+                cUnit->method->clazz->pDvmDex->pResMethods[dInsn->vB]->
+                methodIndex;
+
+            if (mir->dalvikInsn.opCode == OP_INVOKE_VIRTUAL)
+                genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
+            else
+                genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
+
+            genInvokeVirtualCommon(cUnit, mir, methodIndex,
+                                   retChainingCell,
+                                   predChainingCell,
+                                   pcrLabel);
+            break;
+        }
+        /*
+         * calleeMethod = method->clazz->super->vtable[method->clazz->pDvmDex
+         *                ->pResMethods[BBBB]->methodIndex]
+         */
+        /* TODO - not excersized in RunPerf.jar */
+        case OP_INVOKE_SUPER:
+        case OP_INVOKE_SUPER_RANGE: {
+            int mIndex = cUnit->method->clazz->pDvmDex->
+                pResMethods[dInsn->vB]->methodIndex;
+            const Method *calleeMethod =
+                cUnit->method->clazz->super->vtable[mIndex];
+
+            if (mir->dalvikInsn.opCode == OP_INVOKE_SUPER)
+                genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
+            else
+                genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
+
+            /* r0 = calleeMethod */
+            loadConstant(cUnit, r0, (int) calleeMethod);
+
+            genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
+                                     calleeMethod);
+            break;
+        }
+        /* calleeMethod = method->clazz->pDvmDex->pResMethods[BBBB] */
+        case OP_INVOKE_DIRECT:
+        case OP_INVOKE_DIRECT_RANGE: {
+            const Method *calleeMethod =
+                cUnit->method->clazz->pDvmDex->pResMethods[dInsn->vB];
+
+            if (mir->dalvikInsn.opCode == OP_INVOKE_DIRECT)
+                genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
+            else
+                genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
+
+            /* r0 = calleeMethod */
+            loadConstant(cUnit, r0, (int) calleeMethod);
+
+            genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
+                                     calleeMethod);
+            break;
+        }
+        /* calleeMethod = method->clazz->pDvmDex->pResMethods[BBBB] */
+        case OP_INVOKE_STATIC:
+        case OP_INVOKE_STATIC_RANGE: {
+            const Method *calleeMethod =
+                cUnit->method->clazz->pDvmDex->pResMethods[dInsn->vB];
+
+            if (mir->dalvikInsn.opCode == OP_INVOKE_STATIC)
+                genProcessArgsNoRange(cUnit, mir, dInsn,
+                                      NULL /* no null check */);
+            else
+                genProcessArgsRange(cUnit, mir, dInsn,
+                                    NULL /* no null check */);
+
+            /* r0 = calleeMethod */
+            loadConstant(cUnit, r0, (int) calleeMethod);
+
+            genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
+                                     calleeMethod);
+            break;
+        }
+        /*
+         * calleeMethod = dvmFindInterfaceMethodInCache(this->clazz,
+         *                    BBBB, method, method->clazz->pDvmDex)
+         *
+         *  Given "invoke-interface {v0}", the following is the generated code:
+         *
+         * 0x426a9abe : ldr     r0, [r5, #0]   --+
+         * 0x426a9ac0 : mov     r7, r5           |
+         * 0x426a9ac2 : sub     r7, #24          |
+         * 0x426a9ac4 : cmp     r0, #0           | genProcessArgsNoRange
+         * 0x426a9ac6 : beq     0x426a9afe       |
+         * 0x426a9ac8 : stmia   r7, <r0>       --+
+         * 0x426a9aca : ldr     r4, [pc, #104] --> r4 <- dalvikPC of this invoke
+         * 0x426a9acc : add     r1, pc, #52    --> r1 <- &retChainingCell
+         * 0x426a9ace : add     r2, pc, #60    --> r2 <- &predictedChainingCell
+         * 0x426a9ad0 : blx_1   0x426a918c     --+ TEMPLATE_INVOKE_METHOD_
+         * 0x426a9ad2 : blx_2   see above      --+     PREDICTED_CHAIN
+         * 0x426a9ad4 : b       0x426a9b0c     --> off to the predicted chain
+         * 0x426a9ad6 : b       0x426a9afe     --> punt to the interpreter
+         * 0x426a9ad8 : mov     r9, r1         --+
+         * 0x426a9ada : mov     r10, r2          |
+         * 0x426a9adc : mov     r12, r3          |
+         * 0x426a9ade : mov     r0, r3           |
+         * 0x426a9ae0 : mov     r1, #74          | dvmFindInterfaceMethodInCache
+         * 0x426a9ae2 : ldr     r2, [pc, #76]    |
+         * 0x426a9ae4 : ldr     r3, [pc, #68]    |
+         * 0x426a9ae6 : ldr     r7, [pc, #64]    |
+         * 0x426a9ae8 : blx     r7             --+
+         * 0x426a9aea : mov     r1, r9         --> r1 <- rechain count
+         * 0x426a9aec : cmp     r1, #0         --> compare against 0
+         * 0x426a9aee : bgt     0x426a9af8     --> >=0? don't rechain
+         * 0x426a9af0 : ldr     r7, [r6, #96]  --+
+         * 0x426a9af2 : mov     r2, r10          | dvmJitToPatchPredictedChain
+         * 0x426a9af4 : mov     r3, r12          |
+         * 0x426a9af6 : blx     r7             --+
+         * 0x426a9af8 : add     r1, pc, #8     --> r1 <- &retChainingCell
+         * 0x426a9afa : blx_1   0x426a9098     --+ TEMPLATE_INVOKE_METHOD_NO_OPT
+         * 0x426a9afc : blx_2   see above      --+
+         * -------- reconstruct dalvik PC : 0x428b786c @ +0x001e
+         * 0x426a9afe (0042): ldr     r0, [pc, #52]
+         * Exception_Handling:
+         * 0x426a9b00 (0044): ldr     r1, [r6, #84]
+         * 0x426a9b02 (0046): blx     r1
+         * 0x426a9b04 (0048): .align4
+         * -------- chaining cell (hot): 0x0021
+         * 0x426a9b04 (0048): ldr     r0, [r6, #92]
+         * 0x426a9b06 (004a): blx     r0
+         * 0x426a9b08 (004c): data    0x7872(30834)
+         * 0x426a9b0a (004e): data    0x428b(17035)
+         * 0x426a9b0c (0050): .align4
+         * -------- chaining cell (predicted)
+         * 0x426a9b0c (0050): data    0x0000(0) --> will be patched into bx
+         * 0x426a9b0e (0052): data    0x0000(0)
+         * 0x426a9b10 (0054): data    0x0000(0) --> class
+         * 0x426a9b12 (0056): data    0x0000(0)
+         * 0x426a9b14 (0058): data    0x0000(0) --> method
+         * 0x426a9b16 (005a): data    0x0000(0)
+         * 0x426a9b18 (005c): data    0x0000(0) --> reset count
+         * 0x426a9b1a (005e): data    0x0000(0)
+         * 0x426a9b28 (006c): .word (0xad0392a5)
+         * 0x426a9b2c (0070): .word (0x6e750)
+         * 0x426a9b30 (0074): .word (0x4109a618)
+         * 0x426a9b34 (0078): .word (0x428b786c)
+         */
+        case OP_INVOKE_INTERFACE:
+        case OP_INVOKE_INTERFACE_RANGE: {
+            ArmLIR *predChainingCell = &labelList[bb->taken->id];
+            int methodIndex = dInsn->vB;
+
+            if (mir->dalvikInsn.opCode == OP_INVOKE_INTERFACE)
+                genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
+            else
+                genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
+
+            /* "this" is already left in r0 by genProcessArgs* */
+
+            /* r4PC = dalvikCallsite */
+            loadConstant(cUnit, r4PC,
+                         (int) (cUnit->method->insns + mir->offset));
+
+            /* r1 = &retChainingCell */
+            ArmLIR *addrRetChain = newLIR2(cUnit, THUMB_ADD_PC_REL,
+                                               r1, 0);
+            addrRetChain->generic.target = (LIR *) retChainingCell;
+
+            /* r2 = &predictedChainingCell */
+            ArmLIR *predictedChainingCell =
+                newLIR2(cUnit, THUMB_ADD_PC_REL, r2, 0);
+            predictedChainingCell->generic.target = (LIR *) predChainingCell;
+
+            genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN);
+
+            /* return through lr - jump to the chaining cell */
+            genUnconditionalBranch(cUnit, predChainingCell);
+
+            /*
+             * null-check on "this" may have been eliminated, but we still need
+             * a PC-reconstruction label for stack overflow bailout.
+             */
+            if (pcrLabel == NULL) {
+                int dPC = (int) (cUnit->method->insns + mir->offset);
+                pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true);
+                pcrLabel->opCode = ARM_PSEUDO_PC_RECONSTRUCTION_CELL;
+                pcrLabel->operands[0] = dPC;
+                pcrLabel->operands[1] = mir->offset;
+                /* Insert the place holder to the growable list */
+                dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
+            }
+
+            /* return through lr+2 - punt to the interpreter */
+            genUnconditionalBranch(cUnit, pcrLabel);
+
+            /*
+             * return through lr+4 - fully resolve the callee method.
+             * r1 <- count
+             * r2 <- &predictedChainCell
+             * r3 <- this->class
+             * r4 <- dPC
+             * r7 <- this->class->vtable
+             */
+
+            /* 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);
+
+            /* r0 now contains this->clazz */
+            newLIR2(cUnit, THUMB_MOV_RR, r0, r3);
+
+            /* r1 = BBBB */
+            loadConstant(cUnit, r1, dInsn->vB);
+
+            /* r2 = method (caller) */
+            loadConstant(cUnit, r2, (int) cUnit->method);
+
+            /* r3 = pDvmDex */
+            loadConstant(cUnit, r3, (int) cUnit->method->clazz->pDvmDex);
+
+            loadConstant(cUnit, r7,
+                         (intptr_t) dvmFindInterfaceMethodInCache);
+            newLIR1(cUnit, THUMB_BLX_R, r7);
+
+            /* r0 = calleeMethod (returned from dvmFindInterfaceMethodInCache */
+
+            newLIR2(cUnit, THUMB_MOV_RR_H2L, r1, r9 & THUMB_REG_MASK);
+
+            /* Check if rechain limit is reached */
+            newLIR2(cUnit, THUMB_CMP_RI8, r1, 0);
+
+            ArmLIR *bypassRechaining =
+                newLIR2(cUnit, THUMB_B_COND, 0, ARM_COND_GT);
+
+            newLIR3(cUnit, THUMB_LDR_RRI5, r7, rGLUE,
+                    offsetof(InterpState,
+                             jitToInterpEntries.dvmJitToPatchPredictedChain)
+                    >> 2);
+
+            newLIR2(cUnit, THUMB_MOV_RR_H2L, r2, r10 & THUMB_REG_MASK);
+            newLIR2(cUnit, THUMB_MOV_RR_H2L, r3, r12 & THUMB_REG_MASK);
+
+            /*
+             * r0 = calleeMethod
+             * r2 = &predictedChainingCell
+             * r3 = class
+             *
+             * &returnChainingCell has been loaded into r1 but is not needed
+             * when patching the chaining cell and will be clobbered upon
+             * returning so it will be reconstructed again.
+             */
+            newLIR1(cUnit, THUMB_BLX_R, r7);
+
+            /* r1 = &retChainingCell */
+            addrRetChain = newLIR3(cUnit, THUMB_ADD_PC_REL,
+                                               r1, 0, 0);
+            addrRetChain->generic.target = (LIR *) retChainingCell;
+
+            bypassRechaining->generic.target = (LIR *) addrRetChain;
+
+            /*
+             * r0 = this, r1 = calleeMethod,
+             * r1 = &ChainingCell,
+             * r4PC = callsiteDPC,
+             */
+            genDispatchToHandler(cUnit, TEMPLATE_INVOKE_METHOD_NO_OPT);
+#if defined(INVOKE_STATS)
+            gDvmJit.invokePredictedChain++;
+#endif
+            /* Handle exceptions using the interpreter */
+            genTrap(cUnit, mir->offset, pcrLabel);
+            break;
+        }
+        /* NOP */
+        case OP_INVOKE_DIRECT_EMPTY: {
+            return false;
+        }
+        case OP_FILLED_NEW_ARRAY:
+        case OP_FILLED_NEW_ARRAY_RANGE: {
+            /* Just let the interpreter deal with these */
+            genInterpSingleStep(cUnit, mir);
+            break;
+        }
+        default:
+            return true;
+    }
+    return false;
+}
+
+static bool handleFmt35ms_3rms(CompilationUnit *cUnit, MIR *mir,
+                               BasicBlock *bb, ArmLIR *labelList)
+{
+    ArmLIR *retChainingCell = &labelList[bb->fallThrough->id];
+    ArmLIR *predChainingCell = &labelList[bb->taken->id];
+    ArmLIR *pcrLabel = NULL;
+
+    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    switch (mir->dalvikInsn.opCode) {
+        /* calleeMethod = this->clazz->vtable[BBBB] */
+        case OP_INVOKE_VIRTUAL_QUICK_RANGE:
+        case OP_INVOKE_VIRTUAL_QUICK: {
+            int methodIndex = dInsn->vB;
+            if (mir->dalvikInsn.opCode == OP_INVOKE_VIRTUAL_QUICK)
+                genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
+            else
+                genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
+
+            genInvokeVirtualCommon(cUnit, mir, methodIndex,
+                                   retChainingCell,
+                                   predChainingCell,
+                                   pcrLabel);
+            break;
+        }
+        /* calleeMethod = method->clazz->super->vtable[BBBB] */
+        case OP_INVOKE_SUPER_QUICK:
+        case OP_INVOKE_SUPER_QUICK_RANGE: {
+            const Method *calleeMethod =
+                cUnit->method->clazz->super->vtable[dInsn->vB];
+
+            if (mir->dalvikInsn.opCode == OP_INVOKE_SUPER_QUICK)
+                genProcessArgsNoRange(cUnit, mir, dInsn, &pcrLabel);
+            else
+                genProcessArgsRange(cUnit, mir, dInsn, &pcrLabel);
+
+            /* r0 = calleeMethod */
+            loadConstant(cUnit, r0, (int) calleeMethod);
+
+            genInvokeSingletonCommon(cUnit, mir, bb, labelList, pcrLabel,
+                                     calleeMethod);
+            /* Handle exceptions using the interpreter */
+            genTrap(cUnit, mir->offset, pcrLabel);
+            break;
+        }
+        default:
+            return true;
+    }
+    return false;
+}
+
+/*
+ * NOTE: We assume here that the special native inline routines
+ * are side-effect free.  By making this assumption, we can safely
+ * re-execute the routine from the interpreter if it decides it
+ * wants to throw an exception. We still need to EXPORT_PC(), though.
+ */
+static bool handleFmt3inline(CompilationUnit *cUnit, MIR *mir)
+{
+    DecodedInstruction *dInsn = &mir->dalvikInsn;
+    switch( mir->dalvikInsn.opCode) {
+        case OP_EXECUTE_INLINE: {
+            unsigned int i;
+            const InlineOperation* inLineTable = dvmGetInlineOpsTable();
+            int offset = offsetof(InterpState, retval);
+            int operation = dInsn->vB;
+
+            switch (operation) {
+                case INLINE_EMPTYINLINEMETHOD:
+                    return false;  /* Nop */
+                case INLINE_STRING_LENGTH:
+                    return genInlinedStringLength(cUnit, mir);
+                case INLINE_MATH_ABS_INT:
+                    return genInlinedAbsInt(cUnit, mir);
+                case INLINE_MATH_ABS_LONG:
+                    return genInlinedAbsLong(cUnit, mir);
+                case INLINE_MATH_MIN_INT:
+                    return genInlinedMinMaxInt(cUnit, mir, true);
+                case INLINE_MATH_MAX_INT:
+                    return genInlinedMinMaxInt(cUnit, mir, false);
+                case INLINE_STRING_CHARAT:
+                    return genInlinedStringCharAt(cUnit, mir);
+                case INLINE_MATH_SQRT:
+                    if (genInlineSqrt(cUnit, mir))
+                        return false;
+                    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);
+                case INLINE_MATH_ABS_DOUBLE:
+                    return genInlinedAbsDouble(cUnit, mir);
+                case INLINE_STRING_COMPARETO:
+                case INLINE_STRING_EQUALS:
+                    break;
+                default:
+                    dvmAbort();
+            }
+
+            /* Materialize pointer to retval & push */
+            newLIR2(cUnit, THUMB_MOV_RR, r4PC, rGLUE);
+            newLIR2(cUnit, THUMB_ADD_RI8, r4PC, offset);
+            /* Push r4 and (just to take up space) r5) */
+            newLIR1(cUnit, THUMB_PUSH, (1<<r4PC | 1<<rFP));
+
+            /* Get code pointer to inline routine */
+            loadConstant(cUnit, r4PC, (int)inLineTable[operation].func);
+
+            /* Export PC */
+            genExportPC(cUnit, mir, r0, r1 );
+
+            /* Load arguments to r0 through r3 as applicable */
+            for (i=0; i < dInsn->vA; i++) {
+                loadValue(cUnit, dInsn->arg[i], i);
+            }
+            /* Call inline routine */
+            newLIR1(cUnit, THUMB_BLX_R, r4PC);
+
+            /* Strip frame */
+            newLIR1(cUnit, THUMB_ADD_SPI7, 2);
+
+            /* Did we throw? If so, redo under interpreter*/
+            genZeroCheck(cUnit, r0, mir->offset, NULL);
+
+            resetRegisterScoreboard(cUnit);
+            break;
+        }
+        default:
+            return true;
+    }
+    return false;
+}
+
+static bool handleFmt51l(CompilationUnit *cUnit, MIR *mir)
+{
+    loadConstant(cUnit, r0, mir->dalvikInsn.vB_wide & 0xFFFFFFFFUL);
+    loadConstant(cUnit, r1, (mir->dalvikInsn.vB_wide>>32) & 0xFFFFFFFFUL);
+    storeValuePair(cUnit, r0, r1, mir->dalvikInsn.vA, r2);
+    return false;
+}
+
+/*****************************************************************************/
+/*
+ * The following are special processing routines that handle transfer of
+ * controls between compiled code and the interpreter. Certain VM states like
+ * Dalvik PC and special-purpose registers are reconstructed here.
+ */
+
+/* Chaining cell for code that may need warmup. */
+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);
+    addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
+}
+
+/*
+ * Chaining cell for instructions that immediately following already translated
+ * code.
+ */
+static void handleHotChainingCell(CompilationUnit *cUnit,
+                                  unsigned int offset)
+{
+    newLIR3(cUnit, THUMB_LDR_RRI5, r0, rGLUE,
+        offsetof(InterpState, jitToInterpEntries.dvmJitToTraceSelect) >> 2);
+    newLIR1(cUnit, THUMB_BLX_R, r0);
+    addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
+}
+
+/* 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);
+    addWordData(cUnit, (int) (callee->insns), true);
+}
+
+/* Chaining cell for monomorphic method invocations. */
+static void handleInvokePredictedChainingCell(CompilationUnit *cUnit)
+{
+
+    /* Should not be executed in the initial state */
+    addWordData(cUnit, PREDICTED_CHAIN_BX_PAIR_INIT, true);
+    /* To be filled: class */
+    addWordData(cUnit, PREDICTED_CHAIN_CLAZZ_INIT, true);
+    /* To be filled: method */
+    addWordData(cUnit, PREDICTED_CHAIN_METHOD_INIT, true);
+    /*
+     * Rechain count. The initial value of 0 here will trigger chaining upon
+     * the first invocation of this callsite.
+     */
+    addWordData(cUnit, PREDICTED_CHAIN_COUNTER_INIT, true);
+}
+
+/* Load the Dalvik PC into r0 and jump to the specified target */
+static void handlePCReconstruction(CompilationUnit *cUnit,
+                                   ArmLIR *targetLabel)
+{
+    ArmLIR **pcrLabel =
+        (ArmLIR **) cUnit->pcReconstructionList.elemList;
+    int numElems = cUnit->pcReconstructionList.numUsed;
+    int i;
+    for (i = 0; i < numElems; i++) {
+        dvmCompilerAppendLIR(cUnit, (LIR *) pcrLabel[i]);
+        /* r0 = dalvik PC */
+        loadConstant(cUnit, r0, pcrLabel[i]->operands[0]);
+        genUnconditionalBranch(cUnit, targetLabel);
+    }
+}
+
+/* Entry function to invoke the backend of the JIT compiler */
+void dvmCompilerMIR2LIR(CompilationUnit *cUnit)
+{
+    /* Used to hold the labels of each block */
+    ArmLIR *labelList =
+        dvmCompilerNew(sizeof(ArmLIR) * cUnit->numBlocks, true);
+    GrowableList chainingListByType[CHAINING_CELL_LAST];
+    int i;
+
+    /*
+     * Initialize various types chaining lists.
+     */
+    for (i = 0; i < CHAINING_CELL_LAST; i++) {
+        dvmInitGrowableList(&chainingListByType[i], 2);
+    }
+
+    BasicBlock **blockList = cUnit->blockList;
+
+    if (cUnit->executionCount) {
+        /*
+         * Reserve 6 bytes at the beginning of the trace
+         *        +----------------------------+
+         *        | execution count (4 bytes)  |
+         *        +----------------------------+
+         *        | chain cell offset (2 bytes)|
+         *        +----------------------------+
+         * ...and then code to increment the execution
+         * count:
+         *       mov   r0, pc       @ move adr of "mov r0,pc" + 4 to r0
+         *       sub   r0, #10      @ back up to addr of executionCount
+         *       ldr   r1, [r0]
+         *       add   r1, #1
+         *       str   r1, [r0]
+         */
+        newLIR1(cUnit, ARM_16BIT_DATA, 0);
+        newLIR1(cUnit, ARM_16BIT_DATA, 0);
+        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);
+        newLIR2(cUnit, THUMB_SUB_RI8, r0, 10);
+        newLIR3(cUnit, THUMB_LDR_RRI5, r1, r0, 0);
+        newLIR2(cUnit, THUMB_ADD_RI8, r1, 1);
+        newLIR3(cUnit, THUMB_STR_RRI5, r1, r0, 0);
+    } else {
+         /* Just reserve 2 bytes for the chain cell offset */
+        cUnit->chainCellOffsetLIR =
+            (LIR *) newLIR1(cUnit, ARM_16BIT_DATA, CHAIN_CELL_OFFSET_TAG);
+        cUnit->headerSize = 2;
+    }
+
+    /* Handle the content in each basic block */
+    for (i = 0; i < cUnit->numBlocks; i++) {
+        blockList[i]->visited = true;
+        MIR *mir;
+
+        labelList[i].operands[0] = blockList[i]->startOffset;
+
+        if (blockList[i]->blockType >= CHAINING_CELL_LAST) {
+            /*
+             * Append the label pseudo LIR first. Chaining cells will be handled
+             * separately afterwards.
+             */
+            dvmCompilerAppendLIR(cUnit, (LIR *) &labelList[i]);
+        }
+
+        if (blockList[i]->blockType == DALVIK_BYTECODE) {
+            labelList[i].opCode = ARM_PSEUDO_NORMAL_BLOCK_LABEL;
+            /* Reset the register state */
+            resetRegisterScoreboard(cUnit);
+        } else {
+            switch (blockList[i]->blockType) {
+                case CHAINING_CELL_NORMAL:
+                    labelList[i].opCode = ARM_PSEUDO_CHAINING_CELL_NORMAL;
+                    /* handle the codegen later */
+                    dvmInsertGrowableList(
+                        &chainingListByType[CHAINING_CELL_NORMAL], (void *) i);
+                    break;
+                case CHAINING_CELL_INVOKE_SINGLETON:
+                    labelList[i].opCode =
+                        ARM_PSEUDO_CHAINING_CELL_INVOKE_SINGLETON;
+                    labelList[i].operands[0] =
+                        (int) blockList[i]->containingMethod;
+                    /* handle the codegen later */
+                    dvmInsertGrowableList(
+                        &chainingListByType[CHAINING_CELL_INVOKE_SINGLETON],
+                        (void *) i);
+                    break;
+                case CHAINING_CELL_INVOKE_PREDICTED:
+                    labelList[i].opCode =
+                        ARM_PSEUDO_CHAINING_CELL_INVOKE_PREDICTED;
+                    /* handle the codegen later */
+                    dvmInsertGrowableList(
+                        &chainingListByType[CHAINING_CELL_INVOKE_PREDICTED],
+                        (void *) i);
+                    break;
+                case CHAINING_CELL_HOT:
+                    labelList[i].opCode =
+                        ARM_PSEUDO_CHAINING_CELL_HOT;
+                    /* handle the codegen later */
+                    dvmInsertGrowableList(
+                        &chainingListByType[CHAINING_CELL_HOT],
+                        (void *) i);
+                    break;
+                case PC_RECONSTRUCTION:
+                    /* Make sure exception handling block is next */
+                    labelList[i].opCode =
+                        ARM_PSEUDO_PC_RECONSTRUCTION_BLOCK_LABEL;
+                    assert (i == cUnit->numBlocks - 2);
+                    handlePCReconstruction(cUnit, &labelList[i+1]);
+                    break;
+                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);
+                    }
+                    break;
+                default:
+                    break;
+            }
+            continue;
+        }
+
+        ArmLIR *headLIR = NULL;
+
+        for (mir = blockList[i]->firstMIRInsn; mir; mir = mir->next) {
+            OpCode dalvikOpCode = mir->dalvikInsn.opCode;
+            InstructionFormat dalvikFormat =
+                dexGetInstrFormat(gDvm.instrFormat, dalvikOpCode);
+            ArmLIR *boundaryLIR =
+                newLIR2(cUnit, ARM_PSEUDO_DALVIK_BYTECODE_BOUNDARY,
+                        mir->offset,dalvikOpCode);
+            /* Remember the first LIR for this block */
+            if (headLIR == NULL) {
+                headLIR = boundaryLIR;
+            }
+            bool notHandled;
+            /*
+             * Debugging: screen the opcode first to see if it is in the
+             * do[-not]-compile list
+             */
+            bool singleStepMe =
+                gDvmJit.includeSelectedOp !=
+                ((gDvmJit.opList[dalvikOpCode >> 3] &
+                  (1 << (dalvikOpCode & 0x7))) !=
+                 0);
+            if (singleStepMe || cUnit->allSingleStep) {
+                notHandled = false;
+                genInterpSingleStep(cUnit, mir);
+            } else {
+                opcodeCoverage[dalvikOpCode]++;
+                switch (dalvikFormat) {
+                    case kFmt10t:
+                    case kFmt20t:
+                    case kFmt30t:
+                        notHandled = handleFmt10t_Fmt20t_Fmt30t(cUnit,
+                                  mir, blockList[i], labelList);
+                        break;
+                    case kFmt10x:
+                        notHandled = handleFmt10x(cUnit, mir);
+                        break;
+                    case kFmt11n:
+                    case kFmt31i:
+                        notHandled = handleFmt11n_Fmt31i(cUnit, mir);
+                        break;
+                    case kFmt11x:
+                        notHandled = handleFmt11x(cUnit, mir);
+                        break;
+                    case kFmt12x:
+                        notHandled = handleFmt12x(cUnit, mir);
+                        break;
+                    case kFmt20bc:
+                        notHandled = handleFmt20bc(cUnit, mir);
+                        break;
+                    case kFmt21c:
+                    case kFmt31c:
+                        notHandled = handleFmt21c_Fmt31c(cUnit, mir);
+                        break;
+                    case kFmt21h:
+                        notHandled = handleFmt21h(cUnit, mir);
+                        break;
+                    case kFmt21s:
+                        notHandled = handleFmt21s(cUnit, mir);
+                        break;
+                    case kFmt21t:
+                        notHandled = handleFmt21t(cUnit, mir, blockList[i],
+                                                  labelList);
+                        break;
+                    case kFmt22b:
+                    case kFmt22s:
+                        notHandled = handleFmt22b_Fmt22s(cUnit, mir);
+                        break;
+                    case kFmt22c:
+                        notHandled = handleFmt22c(cUnit, mir);
+                        break;
+                    case kFmt22cs:
+                        notHandled = handleFmt22cs(cUnit, mir);
+                        break;
+                    case kFmt22t:
+                        notHandled = handleFmt22t(cUnit, mir, blockList[i],
+                                                  labelList);
+                        break;
+                    case kFmt22x:
+                    case kFmt32x:
+                        notHandled = handleFmt22x_Fmt32x(cUnit, mir);
+                        break;
+                    case kFmt23x:
+                        notHandled = handleFmt23x(cUnit, mir);
+                        break;
+                    case kFmt31t:
+                        notHandled = handleFmt31t(cUnit, mir);
+                        break;
+                    case kFmt3rc:
+                    case kFmt35c:
+                        notHandled = handleFmt35c_3rc(cUnit, mir, blockList[i],
+                                                      labelList);
+                        break;
+                    case kFmt3rms:
+                    case kFmt35ms:
+                        notHandled = handleFmt35ms_3rms(cUnit, mir,blockList[i],
+                                                        labelList);
+                        break;
+                    case kFmt3inline:
+                        notHandled = handleFmt3inline(cUnit, mir);
+                        break;
+                    case kFmt51l:
+                        notHandled = handleFmt51l(cUnit, mir);
+                        break;
+                    default:
+                        notHandled = true;
+                        break;
+                }
+            }
+            if (notHandled) {
+                LOGE("%#06x: Opcode 0x%x (%s) / Fmt %d not handled\n",
+                     mir->offset,
+                     dalvikOpCode, getOpcodeName(dalvikOpCode),
+                     dalvikFormat);
+                dvmAbort();
+                break;
+            }
+        }
+        /* Eliminate redundant loads/stores and delay stores into later slots */
+        dvmCompilerApplyLocalOptimizations(cUnit, (LIR *) headLIR,
+                                           cUnit->lastLIRInsn);
+        /*
+         * Check if the block is terminated due to trace length constraint -
+         * insert an unconditional branch to the chaining cell.
+         */
+        if (blockList[i]->needFallThroughBranch) {
+            genUnconditionalBranch(cUnit,
+                                   &labelList[blockList[i]->fallThrough->id]);
+        }
+
+    }
+
+    /* Handle the chaining cells in predefined order */
+    for (i = 0; i < CHAINING_CELL_LAST; i++) {
+        size_t j;
+        int *blockIdList = (int *) chainingListByType[i].elemList;
+
+        cUnit->numChainingCells[i] = chainingListByType[i].numUsed;
+
+        /* No chaining cells of this type */
+        if (cUnit->numChainingCells[i] == 0)
+            continue;
+
+        /* Record the first LIR for a new type of chaining cell */
+        cUnit->firstChainingLIR[i] = (LIR *) &labelList[blockIdList[0]];
+
+        for (j = 0; j < chainingListByType[i].numUsed; j++) {
+            int blockId = blockIdList[j];
+
+            /* Align this chaining cell first */
+            newLIR0(cUnit, ARM_PSEUDO_ALIGN4);
+
+            /* Insert the pseudo chaining instruction */
+            dvmCompilerAppendLIR(cUnit, (LIR *) &labelList[blockId]);
+
+
+            switch (blockList[blockId]->blockType) {
+                case CHAINING_CELL_NORMAL:
+                    handleNormalChainingCell(cUnit,
+                      blockList[blockId]->startOffset);
+                    break;
+                case CHAINING_CELL_INVOKE_SINGLETON:
+                    handleInvokeSingletonChainingCell(cUnit,
+                        blockList[blockId]->containingMethod);
+                    break;
+                case CHAINING_CELL_INVOKE_PREDICTED:
+                    handleInvokePredictedChainingCell(cUnit);
+                    break;
+                case CHAINING_CELL_HOT:
+                    handleHotChainingCell(cUnit,
+                        blockList[blockId]->startOffset);
+                    break;
+                default:
+                    dvmAbort();
+                    break;
+            }
+        }
+    }
+
+    dvmCompilerApplyGlobalOptimizations(cUnit);
+}
+
+/* Accept the work and start compiling */
+bool dvmCompilerDoWork(CompilerWorkOrder *work)
+{
+   bool res;
+
+   if (gDvmJit.codeCacheFull) {
+       return false;
+   }
+
+   switch (work->kind) {
+       case kWorkOrderMethod:
+           res = dvmCompileMethod(work->info, &work->result);
+           break;
+       case kWorkOrderTrace:
+           /* Start compilation with maximally allowed trace length */
+           res = dvmCompileTrace(work->info, JIT_MAX_TRACE_LEN, &work->result);
+           break;
+       default:
+           res = false;
+           dvmAbort();
+   }
+   return res;
+}
+
+/* Architectural-specific debugging helpers go here */
+void dvmCompilerArchDump(void)
+{
+    /* Print compiled opcode in this VM instance */
+    int i, start, streak;
+    char buf[1024];
+
+    streak = i = 0;
+    buf[0] = 0;
+    while (opcodeCoverage[i] == 0 && i < 256) {
+        i++;
+    }
+    if (i == 256) {
+        return;
+    }
+    for (start = i++, streak = 1; i < 256; i++) {
+        if (opcodeCoverage[i]) {
+            streak++;
+        } else {
+            if (streak == 1) {
+                sprintf(buf+strlen(buf), "%x,", start);
+            } else {
+                sprintf(buf+strlen(buf), "%x-%x,", start, start + streak - 1);
+            }
+            streak = 0;
+            while (opcodeCoverage[i] == 0 && i < 256) {
+                i++;
+            }
+            if (i < 256) {
+                streak = 1;
+                start = i;
+            }
+        }
+    }
+    if (streak) {
+        if (streak == 1) {
+            sprintf(buf+strlen(buf), "%x", start);
+        } else {
+            sprintf(buf+strlen(buf), "%x-%x", start, start + streak - 1);
+        }
+    }
+    if (strlen(buf)) {
+        LOGD("dalvik.vm.jit.op = %s", buf);
+    }
+}
diff --git a/vm/compiler/codegen/arm/Codegen.h b/vm/compiler/codegen/arm/Codegen.h
new file mode 100644
index 0000000..4016075
--- /dev/null
+++ b/vm/compiler/codegen/arm/Codegen.h
@@ -0,0 +1,57 @@
+/*
+ * 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_COMPILER_CODEGEN_ARM_CODEGEN_H
+#define _DALVIK_VM_COMPILER_CODEGEN_ARM_CODEGEN_H
+
+/*
+ * Forward declarations for common routines in Codegen.c used by ISA
+ * variant code such as ThumbUtilty.c
+ */
+
+static ArmLIR *newLIR0(CompilationUnit *cUnit, ArmOpCode opCode);
+static ArmLIR *newLIR1(CompilationUnit *cUnit, ArmOpCode opCode,
+                           int dest);
+static ArmLIR *newLIR2(CompilationUnit *cUnit, ArmOpCode opCode,
+                           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 *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);
+
+/* 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);
+static bool genConversion(CompilationUnit *cUnit, MIR *mir);
+static bool genArithOpFloat(CompilationUnit *cUnit, MIR *mir, int vDest,
+                            int vSrc1, int vSrc2);
+static bool genArithOpDouble(CompilationUnit *cUnit, MIR *mir, int vDest,
+                             int vSrc1, int vSrc2);
+static bool genCmpX(CompilationUnit *cUnit, MIR *mir, int vDest, int vSrc1,
+                    int vSrc2);
+
+
+
+#endif /* _DALVIK_VM_COMPILER_CODEGEN_ARM_CODEGEN_H */
diff --git a/vm/compiler/codegen/arm/GlobalOptimizations.c b/vm/compiler/codegen/arm/GlobalOptimizations.c
new file mode 100644
index 0000000..40e1f07
--- /dev/null
+++ b/vm/compiler/codegen/arm/GlobalOptimizations.c
@@ -0,0 +1,62 @@
+/*
+ * 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 "vm/compiler/CompilerInternals.h"
+#include "ArmLIR.h"
+
+/*
+ * Identify unconditional branches that jump to the immediate successor of the
+ * branch itself.
+ */
+static void applyRedundantBranchElimination(CompilationUnit *cUnit)
+{
+    ArmLIR *thisLIR;
+
+    for (thisLIR = (ArmLIR *) cUnit->firstLIRInsn;
+         thisLIR != (ArmLIR *) cUnit->lastLIRInsn;
+         thisLIR = NEXT_LIR(thisLIR)) {
+
+        /* Branch to the next instruction */
+        if (thisLIR->opCode == THUMB_B_UNCOND) {
+            ArmLIR *nextLIR = thisLIR;
+
+            while (true) {
+                nextLIR = NEXT_LIR(nextLIR);
+
+                /*
+                 * Is the branch target the next instruction?
+                 */
+                if (nextLIR == (ArmLIR *) thisLIR->generic.target) {
+                    thisLIR->isNop = true;
+                    break;
+                }
+
+                /*
+                 * Found real useful stuff between the branch and the target
+                 */
+                if (!isPseudoOpCode(nextLIR->opCode) ||
+                    nextLIR->opCode == ARM_PSEUDO_ALIGN4)
+                    break;
+            }
+        }
+    }
+}
+
+void dvmCompilerApplyGlobalOptimizations(CompilationUnit *cUnit)
+{
+    applyRedundantBranchElimination(cUnit);
+}
diff --git a/vm/compiler/codegen/arm/LocalOptimizations.c b/vm/compiler/codegen/arm/LocalOptimizations.c
new file mode 100644
index 0000000..11aaedd
--- /dev/null
+++ b/vm/compiler/codegen/arm/LocalOptimizations.c
@@ -0,0 +1,166 @@
+/*
+ * 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 "vm/compiler/CompilerInternals.h"
+#include "ArmLIR.h"
+
+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)));
+}
+
+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)));
+}
+
+/*
+ * Perform a pass of top-down walk to
+ * 1) Eliminate redundant loads and stores
+ * 2) Sink stores to latest possible slot
+ */
+static void applyLoadStoreElimination(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) {
+            continue;
+        }
+        if (isDalvikStore(thisLIR)) {
+            int dRegId = thisLIR->operands[2];
+            int nativeRegId = thisLIR->operands[0];
+            ArmLIR *checkLIR;
+            int sinkDistance = 0;
+
+            for (checkLIR = NEXT_LIR(thisLIR);
+                 checkLIR != tailLIR;
+                 checkLIR = NEXT_LIR(checkLIR)) {
+
+                /* 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
+                    }
+                    /* Insert a move to replace the load */
+                    if (checkLIR->operands[0] != nativeRegId) {
+                        ArmLIR *moveLIR;
+                        moveLIR = dvmCompilerRegCopy(cUnit,
+                                                    checkLIR->operands[0],
+                                                    nativeRegId);
+                        /*
+                         * Insertion is guaranteed to succeed since checkLIR
+                         * is never the first LIR on the list
+                         */
+                        dvmCompilerInsertLIRBefore((LIR *) checkLIR,
+                                                   (LIR *) moveLIR);
+                    }
+                    checkLIR->isNop = true;
+                    continue;
+
+                /* Found a true output dependency - nuke the previous store */
+                } else if (isDalvikStore(checkLIR) &&
+                           checkLIR->operands[2] == dRegId) {
+                    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;
+
+                    /*
+                     * 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;
+;
+
+                    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;
+                    }
+
+                    /* Found a new place to put the store - move it here */
+                    if (stopHere == true) {
+
+                        /* The store can be sunk for at least one cycle */
+                        if (sinkDistance != 0) {
+                            ArmLIR *newStoreLIR =
+                                dvmCompilerNew(sizeof(ArmLIR), true);
+                            *newStoreLIR = *thisLIR;
+                            newStoreLIR->age = cUnit->optRound;
+                            /*
+                             * Insertion is guaranteed to succeed since checkLIR
+                             * is never the first LIR on the list
+                             */
+                            dvmCompilerInsertLIRBefore((LIR *) checkLIR,
+                                                       (LIR *) newStoreLIR);
+                            thisLIR->isNop = true;
+                        }
+                        break;
+                    }
+
+                    /*
+                     * Saw a real instruction that the store can be sunk after
+                     */
+                    if (!isPseudoOpCode(checkLIR->opCode)) {
+                        sinkDistance++;
+                    }
+                }
+            }
+        }
+    }
+}
+
+void dvmCompilerApplyLocalOptimizations(CompilationUnit *cUnit, LIR *headLIR,
+                                        LIR *tailLIR)
+{
+    applyLoadStoreElimination(cUnit,
+                              (ArmLIR *) headLIR,
+                              (ArmLIR *) tailLIR);
+}
diff --git a/vm/compiler/codegen/arm/Thumb2Util.c b/vm/compiler/codegen/arm/Thumb2Util.c
new file mode 100644
index 0000000..3a9f1de
--- /dev/null
+++ b/vm/compiler/codegen/arm/Thumb2Util.c
@@ -0,0 +1,488 @@
+/*
+ * 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 file contains codegen for the Thumb ISA and is intended to be
+ * includes by:and support common to all supported
+ *
+ *        Codegen-$(TARGET_ARCH_VARIANT).c
+ *
+ */
+
+#include "Codegen.h"
+
+/* 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 inline ArmLIR *genRegImmCheck(CompilationUnit *cUnit,
+                                         ArmConditionCode cond, int reg,
+                                         int checkValue, int dOffset,
+                                         ArmLIR *pcrLabel);
+ArmLIR* dvmCompilerRegCopy(CompilationUnit *cUnit, int rDest, int rSrc);
+
+/*****************************************************************************/
+
+/*
+ * 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)
+/*
+ * The following are utility routines to help maintain the RegisterScoreboard
+ * state to facilitate register renaming.
+ */
+
+/* Reset the tracker to unknown state */
+static inline void resetRegisterScoreboard(CompilationUnit *cUnit)
+{
+    RegisterScoreboard *registerScoreboard = &cUnit->registerScoreboard;
+
+    dvmClearAllBits(registerScoreboard->nullCheckedRegs);
+    registerScoreboard->liveDalvikReg = vNone;
+    registerScoreboard->nativeReg = vNone;
+    registerScoreboard->nativeRegHi = vNone;
+}
+
+/* Kill the corresponding bit in the null-checked register list */
+static inline void killNullCheckedRegister(CompilationUnit *cUnit, int vReg)
+{
+    dvmClearBit(cUnit->registerScoreboard.nullCheckedRegs, vReg);
+}
+
+/* The Dalvik register pair held in native registers have changed */
+static inline void updateLiveRegisterPair(CompilationUnit *cUnit,
+                                          int vReg, int mRegLo, int mRegHi)
+{
+    cUnit->registerScoreboard.liveDalvikReg = vReg;
+    cUnit->registerScoreboard.nativeReg = mRegLo;
+    cUnit->registerScoreboard.nativeRegHi = mRegHi;
+    cUnit->registerScoreboard.isWide = true;
+}
+
+/* The Dalvik register held in a native register has changed */
+static inline void updateLiveRegister(CompilationUnit *cUnit,
+                                      int vReg, int mReg)
+{
+    cUnit->registerScoreboard.liveDalvikReg = vReg;
+    cUnit->registerScoreboard.nativeReg = mReg;
+    cUnit->registerScoreboard.isWide = false;
+}
+
+/*
+ * Given a Dalvik register id vSrc, use a very simple algorithm to increase
+ * the lifetime of cached Dalvik value in a native register.
+ */
+static inline int selectFirstRegister(CompilationUnit *cUnit, int vSrc,
+                                      bool isWide)
+{
+    RegisterScoreboard *registerScoreboard = &cUnit->registerScoreboard;
+
+    /* No live value - suggest to use r0 */
+    if (registerScoreboard->liveDalvikReg == vNone)
+        return r0;
+
+    /* Reuse the previously used native reg */
+    if (registerScoreboard->liveDalvikReg == vSrc) {
+        if (isWide != true) {
+            return registerScoreboard->nativeReg;
+        } else {
+            /* Return either r0 or r2 */
+            return (registerScoreboard->nativeReg + 1) & 2;
+        }
+    }
+
+    /* No reuse - choose the next one among r0..r3 in the round-robin fashion */
+    if (isWide) {
+        return (registerScoreboard->nativeReg + 2) & 2;
+    } else {
+        return (registerScoreboard->nativeReg + 1) & 3;
+    }
+
+}
+
+/*****************************************************************************/
+
+ArmLIR* dvmCompilerRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
+{
+    ArmLIR* res = dvmCompilerNew(sizeof(ArmLIR), true);
+    res->operands[0] = rDest;
+    res->operands[1] = rSrc;
+    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;
+            }
+        } else {
+            // TODO: support copy between FP and gen regs.
+            assert(!FPREG(rDest));
+            assert(!FPREG(rSrc));
+            res->opCode = THUMB2_MOV_RR;
+        }
+    }
+    return res;
+}
+
+static int leadingZeros(u4 val)
+{
+    u4 alt;
+    int n;
+    int count;
+
+    count = 16;
+    n = 32;
+    do {
+        alt = val >> count;
+        if (alt != 0) {
+            n = n - count;
+            val = alt;
+        }
+        count >>= 1;
+    } while (count);
+    return n - val;
+}
+
+/*
+ * Determine whether value can be encoded as a Thumb modified
+ * immediate.  If not, return -1.  If so, return i:imm3:a:bcdefgh form.
+ */
+static int modifiedImmediate(u4 value)
+{
+   int zLeading;
+   int zTrailing;
+   u4 b0 = value & 0xff;
+
+   /* Note: case of value==0 must use 0:000:0:0000000 encoding */
+   if (value <= 0xFF)
+       return b0;  // 0:000:a:bcdefgh
+   if (value == ((b0 << 16) | b0))
+       return (0x1 << 8) | b0; /* 0:001:a:bcdefgh */
+   if (value == ((b0 << 24) | (b0 << 16) | (b0 << 8) | b0))
+       return (0x3 << 8) | b0; /* 0:011:a:bcdefgh */
+   b0 = (value >> 8) & 0xff;
+   if (value == ((b0 << 24) | (b0 << 8)))
+       return (0x2 << 8) | b0; /* 0:010:a:bcdefgh */
+   /* Can we do it with rotation? */
+   zLeading = leadingZeros(value);
+   zTrailing = 32 - leadingZeros(~value & (value - 1));
+   /* A run of eight or fewer active bits? */
+   if ((zLeading + zTrailing) < 24)
+       return -1;  /* No - bail */
+   /* left-justify the constant, discarding msb (known to be 1) */
+   value <<= zLeading + 1;
+   /* Create bcdefgh */
+   value >>= 25;
+   /* Put it all together */
+   return value | ((0x8 + zLeading) << 7); /* [01000..11111]:bcdefgh */
+}
+
+/*
+ * 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)
+{
+    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;
+    }
+    /* Check Modified immediate special cases */
+    modImm = modifiedImmediate(value);
+    if (modImm >= 0) {
+        newLIR2(cUnit, THUMB2_MOV_IMM_SHIFT, rDest, modImm);
+        return;
+    }
+    /* 16-bit immediate? */
+    if ((value & 0xffff) == value) {
+        newLIR2(cUnit, THUMB2_MOV_IMM16, rDest, value);
+        return;
+    }
+    /* No shortcut - go ahead and use literal pool */
+    ArmLIR *dataTarget = scanLiteralPool(cUnit, value, 255);
+    if (dataTarget == NULL) {
+        dataTarget = addWordData(cUnit, value, false);
+    }
+    ArmLIR *loadPcRel = dvmCompilerNew(sizeof(ArmLIR), true);
+    loadPcRel->opCode = THUMB_LDR_PC_REL;
+    loadPcRel->generic.target = (LIR *) dataTarget;
+    loadPcRel->operands[0] = rDest;
+    dvmCompilerAppendLIR(cUnit, (LIR *) loadPcRel);
+
+    /*
+     * To save space in the constant pool, we use the ADD_RRI8 instruction to
+     * add up to 255 to an existing constant value.
+     */
+    if (dataTarget->operands[0] != value) {
+        newLIR2(cUnit, THUMB_ADD_RI8, rDest, value - dataTarget->operands[0]);
+    }
+}
+
+/* Export the Dalvik PC assicated with an instruction to the StackSave area */
+static void genExportPC(CompilationUnit *cUnit, MIR *mir, int rDPC, int rAddr)
+{
+    int offset = offsetof(StackSaveArea, xtra.currentPc);
+    loadConstant(cUnit, rDPC, (int) (cUnit->method->insns + mir->offset));
+    newLIR3(cUnit, THUMB2_STR_RRI8_PREDEC, rDPC, rFP,
+            sizeof(StackSaveArea) - offset);
+}
+
+/* Generate conditional branch instructions */
+static void genConditionalBranch(CompilationUnit *cUnit,
+                                 ArmConditionCode cond,
+                                 ArmLIR *target)
+{
+    ArmLIR *branch = newLIR2(cUnit, THUMB_B_COND, 0, cond);
+    branch->generic.target = (LIR *) target;
+}
+
+/* Generate unconditional branch instructions */
+static ArmLIR *genUnconditionalBranch(CompilationUnit *cUnit, ArmLIR *target)
+{
+    ArmLIR *branch = newLIR0(cUnit, THUMB_B_UNCOND);
+    branch->generic.target = (LIR *) target;
+    return branch;
+}
+
+/*
+ * Load a pair of values of rFP[src..src+1] and store them into rDestLo and
+ * rDestHi
+ */
+static void loadValuePair(CompilationUnit *cUnit, int vSrc, int rDestLo,
+                          int rDestHi)
+{
+    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);
+    } 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
+        }
+    }
+}
+
+/*
+ * 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)
+{
+    bool allLowRegs = (LOWREG(rSrcLo) && LOWREG(rSrcHi));
+    killNullCheckedRegister(cUnit, vDest);
+    killNullCheckedRegister(cUnit, vDest+1);
+    updateLiveRegisterPair(cUnit, vDest, rSrcLo, rSrcHi);
+
+    /* 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
+        }
+    }
+}
+
+static void addRegisterRegister(CompilationUnit *cUnit, int rDest,
+                                int rSrc1, int rSrc2)
+{
+    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);
+}
+
+/* Store a float to a Dalvik register */
+static void storeFloat(CompilationUnit *cUnit, int rSrc, int vDest,
+                       int rScratch)
+{
+    assert(vSrc <= 255); // FIXME - temp limit to 1st 256
+    assert(SINGLEREG(rSrc));
+    newLIR3(cUnit, THUMB2_VSTRS, rSrc, rFP, vDest);
+}
+
+/* Load a double from a Dalvik register */
+static void 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);
+}
+
+/* Store a double to a Dalvik register */
+static void storeDouble(CompilationUnit *cUnit, int rSrc, int vDest,
+                       int rScratch)
+{
+    assert(vSrc <= 255); // FIXME - temp limit to 1st 256
+    assert(DOUBLEREG(rSrc));
+    newLIR3(cUnit, THUMB2_VSTRD, rSrc, rFP, vDest);
+}
+
+
+/* Load a single value from rFP[src] and store them into rDest */
+static void loadValue(CompilationUnit *cUnit, int vSrc, int rDest)
+{
+    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)
+{
+    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
+        }
+    }
+}
+
+/* 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 (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
+        }
+    }
+}
+
+/*
+ * Perform a "reg cmp imm" operation and jump to the PCR region if condition
+ * satisfies.
+ */
+static ArmLIR *genRegImmCheck(CompilationUnit *cUnit,
+                                         ArmConditionCode cond, int reg,
+                                         int checkValue, int dOffset,
+                                         ArmLIR *pcrLabel)
+{
+    ArmLIR *branch;
+    if ((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);
+        branch = newLIR2(cUnit, THUMB_B_COND, 0, cond);
+    }
+    return genCheckCommon(cUnit, dOffset, branch, pcrLabel);
+}
diff --git a/vm/compiler/codegen/arm/ThumbUtil.c b/vm/compiler/codegen/arm/ThumbUtil.c
new file mode 100644
index 0000000..8be50ad
--- /dev/null
+++ b/vm/compiler/codegen/arm/ThumbUtil.c
@@ -0,0 +1,337 @@
+/*
+ * 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 file contains codegen for the Thumb ISA and is intended to be
+ * includes by:and support common to all supported
+ *
+ *        Codegen-$(TARGET_ARCH_VARIANT).c
+ *
+ */
+
+#include "Codegen.h"
+
+/* 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 inline ArmLIR *genRegImmCheck(CompilationUnit *cUnit,
+                                         ArmConditionCode cond, int reg,
+                                         int checkValue, int dOffset,
+                                         ArmLIR *pcrLabel);
+ArmLIR* dvmCompilerRegCopy(CompilationUnit *cUnit, int rDest, int rSrc);
+
+/*****************************************************************************/
+
+/*
+ * 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)
+/*
+ * The following are utility routines to help maintain the RegisterScoreboard
+ * state to facilitate register renaming.
+ */
+
+/* Reset the tracker to unknown state */
+static inline void resetRegisterScoreboard(CompilationUnit *cUnit)
+{
+    RegisterScoreboard *registerScoreboard = &cUnit->registerScoreboard;
+
+    dvmClearAllBits(registerScoreboard->nullCheckedRegs);
+    registerScoreboard->liveDalvikReg = vNone;
+    registerScoreboard->nativeReg = vNone;
+    registerScoreboard->nativeRegHi = vNone;
+}
+
+/* Kill the corresponding bit in the null-checked register list */
+static inline void killNullCheckedRegister(CompilationUnit *cUnit, int vReg)
+{
+    dvmClearBit(cUnit->registerScoreboard.nullCheckedRegs, vReg);
+}
+
+/* The Dalvik register pair held in native registers have changed */
+static inline void updateLiveRegisterPair(CompilationUnit *cUnit,
+                                          int vReg, int mRegLo, int mRegHi)
+{
+    cUnit->registerScoreboard.liveDalvikReg = vReg;
+    cUnit->registerScoreboard.nativeReg = mRegLo;
+    cUnit->registerScoreboard.nativeRegHi = mRegHi;
+    cUnit->registerScoreboard.isWide = true;
+}
+
+/* The Dalvik register held in a native register has changed */
+static inline void updateLiveRegister(CompilationUnit *cUnit,
+                                      int vReg, int mReg)
+{
+    cUnit->registerScoreboard.liveDalvikReg = vReg;
+    cUnit->registerScoreboard.nativeReg = mReg;
+    cUnit->registerScoreboard.isWide = false;
+}
+
+/*
+ * Given a Dalvik register id vSrc, use a very simple algorithm to increase
+ * the lifetime of cached Dalvik value in a native register.
+ */
+static inline int selectFirstRegister(CompilationUnit *cUnit, int vSrc,
+                                      bool isWide)
+{
+    RegisterScoreboard *registerScoreboard = &cUnit->registerScoreboard;
+
+    /* No live value - suggest to use r0 */
+    if (registerScoreboard->liveDalvikReg == vNone)
+        return r0;
+
+    /* Reuse the previously used native reg */
+    if (registerScoreboard->liveDalvikReg == vSrc) {
+        if (isWide != true) {
+            return registerScoreboard->nativeReg;
+        } else {
+            /* Return either r0 or r2 */
+            return (registerScoreboard->nativeReg + 1) & 2;
+        }
+    }
+
+    /* No reuse - choose the next one among r0..r3 in the round-robin fashion */
+    if (isWide) {
+        return (registerScoreboard->nativeReg + 2) & 2;
+    } else {
+        return (registerScoreboard->nativeReg + 1) & 3;
+    }
+
+}
+
+/*****************************************************************************/
+
+ArmLIR* dvmCompilerRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
+{
+    ArmLIR* res = dvmCompilerNew(sizeof(ArmLIR), true);
+    assert(LOWREG(rDest) && LOWREG(rSrc));
+    res->operands[0] = rDest;
+    res->operands[1] = rSrc;
+    res->opCode = THUMB_MOV_RR;
+    if (rDest == rSrc) {
+        res->isNop = true;
+    }
+    return res;
+}
+
+/*
+ * 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)
+{
+    /* See if the value can be constructed cheaply */
+    if ((value >= 0) && (value <= 255)) {
+        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;
+    }
+    /* No shortcut - go ahead and use literal pool */
+    ArmLIR *dataTarget = scanLiteralPool(cUnit, value, 255);
+    if (dataTarget == NULL) {
+        dataTarget = addWordData(cUnit, value, false);
+    }
+    ArmLIR *loadPcRel = dvmCompilerNew(sizeof(ArmLIR), true);
+    loadPcRel->opCode = THUMB_LDR_PC_REL;
+    loadPcRel->generic.target = (LIR *) dataTarget;
+    loadPcRel->operands[0] = rDest;
+    dvmCompilerAppendLIR(cUnit, (LIR *) loadPcRel);
+
+    /*
+     * To save space in the constant pool, we use the ADD_RRI8 instruction to
+     * add up to 255 to an existing constant value.
+     */
+    if (dataTarget->operands[0] != value) {
+        newLIR2(cUnit, THUMB_ADD_RI8, rDest, value - dataTarget->operands[0]);
+    }
+}
+
+/* Export the Dalvik PC assicated with an instruction to the StackSave area */
+static void genExportPC(CompilationUnit *cUnit, MIR *mir, int rDPC, int rAddr)
+{
+    int offset = offsetof(StackSaveArea, xtra.currentPc);
+    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);
+}
+
+/* Generate conditional branch instructions */
+static void genConditionalBranch(CompilationUnit *cUnit,
+                                 ArmConditionCode cond,
+                                 ArmLIR *target)
+{
+    ArmLIR *branch = newLIR2(cUnit, THUMB_B_COND, 0, cond);
+    branch->generic.target = (LIR *) target;
+}
+
+/* Generate unconditional branch instructions */
+static ArmLIR *genUnconditionalBranch(CompilationUnit *cUnit, ArmLIR *target)
+{
+    ArmLIR *branch = newLIR0(cUnit, THUMB_B_UNCOND);
+    branch->generic.target = (LIR *) target;
+    return branch;
+}
+
+/*
+ * Load a pair of values of rFP[src..src+1] and store them into rDestLo and
+ * rDestHi
+ */
+static void loadValuePair(CompilationUnit *cUnit, int vSrc, int rDestLo,
+                          int rDestHi)
+{
+    /* 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)));
+    }
+}
+
+/*
+ * 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)
+{
+    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) {
+        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)));
+    }
+}
+
+/* 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);
+    } else {
+        loadConstant(cUnit, rDest, vSrc*4);
+        newLIR3(cUnit, THUMB_ADD_RRR, rDest, rFP, rDest);
+    }
+}
+
+/* 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);
+    }
+}
+
+/* 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);
+    }
+}
+
+/*
+ * Perform a "reg cmp imm" operation and jump to the PCR region if condition
+ * satisfies.
+ */
+static inline ArmLIR *genRegImmCheck(CompilationUnit *cUnit,
+                                         ArmConditionCode cond, int reg,
+                                         int checkValue, int dOffset,
+                                         ArmLIR *pcrLabel)
+{
+    newLIR2(cUnit, THUMB_CMP_RI8, reg, checkValue);
+    ArmLIR *branch = newLIR2(cUnit, THUMB_B_COND, 0, cond);
+    return genCheckCommon(cUnit, dOffset, branch, pcrLabel);
+}
diff --git a/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.c b/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.c
new file mode 100644
index 0000000..6c5b010
--- /dev/null
+++ b/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.c
@@ -0,0 +1,291 @@
+/*
+ * 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 file is included by Codegen-armv5te-vfp.c, and implements architecture
+ * variant-specific code.
+ */
+
+#define USE_IN_CACHE_HANDLER 1
+
+/*
+ * Determine the initial instruction set to be used for this trace.
+ * Later components may decide to change this.
+ */
+JitInstructionSetType dvmCompilerInstructionSet(CompilationUnit *cUnit)
+{
+    return DALVIK_JIT_THUMB;
+}
+
+/*
+ * Jump to the out-of-line handler in ARM mode to finish executing the
+ * remaining of more complex instructions.
+ */
+static void genDispatchToHandler(CompilationUnit *cUnit, TemplateOpCode opCode)
+{
+#if USE_IN_CACHE_HANDLER
+    /*
+     * NOTE - In practice BLX only needs one operand, but since the assembler
+     * may abort itself and retry due to other out-of-range conditions we
+     * cannot really use operand[0] to store the absolute target address since
+     * it may get clobbered by the final relative offset. Therefore,
+     * we fake BLX_1 is a two operand instruction and the absolute target
+     * address is stored in operand[1].
+     */
+    newLIR2(cUnit, THUMB_BLX_1,
+            (int) gDvmJit.codeCache + templateEntryOffsets[opCode],
+            (int) gDvmJit.codeCache + templateEntryOffsets[opCode]);
+    newLIR2(cUnit, THUMB_BLX_2,
+            (int) gDvmJit.codeCache + templateEntryOffsets[opCode],
+            (int) gDvmJit.codeCache + templateEntryOffsets[opCode]);
+#else
+    /*
+     * In case we want to access the statically compiled handlers for
+     * debugging purposes, define USE_IN_CACHE_HANDLER to 0
+     */
+    void *templatePtr;
+
+#define JIT_TEMPLATE(X) extern void dvmCompiler_TEMPLATE_##X();
+#include "../../../template/armv5te-vfp/TemplateOpList.h"
+#undef JIT_TEMPLATE
+    switch (opCode) {
+#define JIT_TEMPLATE(X) \
+        case TEMPLATE_##X: { templatePtr = dvmCompiler_TEMPLATE_##X; break; }
+#include "../../../template/armv5te-vfp/TemplateOpList.h"
+#undef JIT_TEMPLATE
+        default: templatePtr = NULL;
+    }
+    loadConstant(cUnit, r7, (int) templatePtr);
+    newLIR1(cUnit, THUMB_BLX_R, r7);
+#endif
+}
+
+/* Architecture-specific initializations and checks go here */
+bool dvmCompilerArchInit(void)
+{
+    /* First, declare dvmCompiler_TEMPLATE_XXX for each template */
+#define JIT_TEMPLATE(X) extern void dvmCompiler_TEMPLATE_##X();
+#include "../../../template/armv5te-vfp/TemplateOpList.h"
+#undef JIT_TEMPLATE
+
+    int i = 0;
+    extern void dvmCompilerTemplateStart(void);
+
+    /*
+     * Then, populate the templateEntryOffsets array with the offsets from the
+     * the dvmCompilerTemplateStart symbol for each template.
+     */
+#define JIT_TEMPLATE(X) templateEntryOffsets[i++] = \
+    (intptr_t) dvmCompiler_TEMPLATE_##X - (intptr_t) dvmCompilerTemplateStart;
+#include "../../../template/armv5te-vfp/TemplateOpList.h"
+#undef JIT_TEMPLATE
+
+    /* Codegen-specific assumptions */
+    assert(offsetof(ClassObject, vtable) < 128 &&
+           (offsetof(ClassObject, vtable) & 0x3) == 0);
+    assert(offsetof(ArrayObject, length) < 128 &&
+           (offsetof(ArrayObject, length) & 0x3) == 0);
+    assert(offsetof(ArrayObject, contents) < 256);
+
+    /* Up to 5 args are pushed on top of FP - sizeofStackSaveArea */
+    assert(sizeof(StackSaveArea) < 236);
+
+    /*
+     * EA is calculated by doing "Rn + imm5 << 2", and there are 5 entry points
+     * that codegen may access, make sure that the offset from the top of the
+     * struct is less than 108.
+     */
+    assert(offsetof(InterpState, jitToInterpEntries) < 108);
+    return true;
+}
+
+static bool genInlineSqrt(CompilationUnit *cUnit, MIR *mir)
+{
+    int offset = offsetof(InterpState, retval);
+    OpCode opCode = mir->dalvikInsn.opCode;
+    int vSrc = mir->dalvikInsn.vA;
+    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)
+{
+    return false;
+}
+
+static bool genArithOpFloat(CompilationUnit *cUnit, MIR *mir, int vDest,
+                                int vSrc1, int vSrc2)
+{
+    TemplateOpCode opCode;
+
+    /*
+     * Don't attempt to optimize register usage since these opcodes call out to
+     * the handlers.
+     */
+    switch (mir->dalvikInsn.opCode) {
+        case OP_ADD_FLOAT_2ADDR:
+        case OP_ADD_FLOAT:
+            opCode = TEMPLATE_ADD_FLOAT_VFP;
+            break;
+        case OP_SUB_FLOAT_2ADDR:
+        case OP_SUB_FLOAT:
+            opCode = TEMPLATE_SUB_FLOAT_VFP;
+            break;
+        case OP_DIV_FLOAT_2ADDR:
+        case OP_DIV_FLOAT:
+            opCode = TEMPLATE_DIV_FLOAT_VFP;
+            break;
+        case OP_MUL_FLOAT_2ADDR:
+        case OP_MUL_FLOAT:
+            opCode = TEMPLATE_MUL_FLOAT_VFP;
+            break;
+        case OP_REM_FLOAT_2ADDR:
+        case OP_REM_FLOAT:
+        case OP_NEG_FLOAT: {
+            return genArithOpFloatPortable(cUnit, mir, vDest,
+                                                      vSrc1, vSrc2);
+        }
+        default:
+            return true;
+    }
+    loadValueAddress(cUnit, vDest, r0);
+    loadValueAddress(cUnit, vSrc1, r1);
+    loadValueAddress(cUnit, vSrc2, r2);
+    genDispatchToHandler(cUnit, opCode);
+    return false;
+}
+
+static bool genArithOpDouble(CompilationUnit *cUnit, MIR *mir, int vDest,
+                             int vSrc1, int vSrc2)
+{
+    TemplateOpCode opCode;
+
+    /*
+     * 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:
+            opCode = TEMPLATE_ADD_DOUBLE_VFP;
+            break;
+        case OP_SUB_DOUBLE_2ADDR:
+        case OP_SUB_DOUBLE:
+            opCode = TEMPLATE_SUB_DOUBLE_VFP;
+            break;
+        case OP_DIV_DOUBLE_2ADDR:
+        case OP_DIV_DOUBLE:
+            opCode = TEMPLATE_DIV_DOUBLE_VFP;
+            break;
+        case OP_MUL_DOUBLE_2ADDR:
+        case OP_MUL_DOUBLE:
+            opCode = TEMPLATE_MUL_DOUBLE_VFP;
+            break;
+        case OP_REM_DOUBLE_2ADDR:
+        case OP_REM_DOUBLE:
+        case OP_NEG_DOUBLE: {
+            return genArithOpDoublePortable(cUnit, mir, vDest,
+                                                       vSrc1, vSrc2);
+        }
+        default:
+            return true;
+    }
+    loadValueAddress(cUnit, vDest, r0);
+    loadValueAddress(cUnit, vSrc1, r1);
+    loadValueAddress(cUnit, vSrc2, r2);
+    genDispatchToHandler(cUnit, opCode);
+    return false;
+}
+
+static bool genConversion(CompilationUnit *cUnit, MIR *mir)
+{
+    OpCode opCode = mir->dalvikInsn.opCode;
+    int vSrc1Dest = mir->dalvikInsn.vA;
+    int vSrc2 = mir->dalvikInsn.vB;
+    TemplateOpCode template;
+
+    switch (opCode) {
+        case OP_INT_TO_FLOAT:
+            template = TEMPLATE_INT_TO_FLOAT_VFP;
+            break;
+        case OP_FLOAT_TO_INT:
+            template = TEMPLATE_FLOAT_TO_INT_VFP;
+            break;
+        case OP_DOUBLE_TO_FLOAT:
+            template = TEMPLATE_DOUBLE_TO_FLOAT_VFP;
+            break;
+        case OP_FLOAT_TO_DOUBLE:
+            template = TEMPLATE_FLOAT_TO_DOUBLE_VFP;
+            break;
+        case OP_INT_TO_DOUBLE:
+            template = TEMPLATE_INT_TO_DOUBLE_VFP;
+            break;
+        case OP_DOUBLE_TO_INT:
+            template = TEMPLATE_DOUBLE_TO_INT_VFP;
+            break;
+        case OP_FLOAT_TO_LONG:
+        case OP_LONG_TO_FLOAT:
+        case OP_DOUBLE_TO_LONG:
+        case OP_LONG_TO_DOUBLE:
+            return genConversionPortable(cUnit, mir);
+        default:
+            return true;
+    }
+    loadValueAddress(cUnit, vSrc1Dest, r0);
+    loadValueAddress(cUnit, vSrc2, r1);
+    genDispatchToHandler(cUnit, template);
+    return false;
+}
+
+static bool genCmpX(CompilationUnit *cUnit, MIR *mir, int vDest, int vSrc1,
+                    int vSrc2)
+{
+    TemplateOpCode template;
+
+    /*
+     * 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;
+            break;
+        case OP_CMPG_FLOAT:
+            template = TEMPLATE_CMPG_FLOAT_VFP;
+            break;
+        case OP_CMPL_DOUBLE:
+            template = TEMPLATE_CMPL_DOUBLE_VFP;
+            break;
+        case OP_CMPG_DOUBLE:
+            template = TEMPLATE_CMPG_DOUBLE_VFP;
+            break;
+        default:
+            return true;
+    }
+    loadValueAddress(cUnit, vSrc1, r0);
+    loadValueAddress(cUnit, vSrc2, r1);
+    genDispatchToHandler(cUnit, template);
+    storeValue(cUnit, r0, vDest, r1);
+    return false;
+}
diff --git a/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.h b/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.h
new file mode 100644
index 0000000..9f862e8
--- /dev/null
+++ b/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.h
@@ -0,0 +1,34 @@
+/*
+ * 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_COMPILER_CODEGEN_ARM_ARMV5TE_VFP_ARCHVARIANT_H
+#define _DALVIK_VM_COMPILER_CODEGEN_ARM_ARMV5TE_VFP_ARCHVARIANT_H
+
+/* Create the TemplateOpcode enum */
+#define JIT_TEMPLATE(X) TEMPLATE_##X,
+typedef enum {
+#include "../../../template/armv5te-vfp/TemplateOpList.h"
+/*
+ * For example,
+ *     TEMPLATE_CMP_LONG,
+ *     TEMPLATE_RETURN,
+ *     ...
+ */
+    TEMPLATE_LAST_MARK,
+} TemplateOpCode;
+#undef JIT_TEMPLATE
+
+#endif /* _DALVIK_VM_COMPILER_CODEGEN_ARM_ARMV5TE_VFP_ARCHVARIANT_H */
diff --git a/vm/compiler/codegen/arm/armv5te/ArchVariant.c b/vm/compiler/codegen/arm/armv5te/ArchVariant.c
new file mode 100644
index 0000000..a1f2b00
--- /dev/null
+++ b/vm/compiler/codegen/arm/armv5te/ArchVariant.c
@@ -0,0 +1,183 @@
+/*
+ * 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 file is included by Codegen-armv5te.c, and implements architecture
+ * variant-specific code.
+ */
+
+#define USE_IN_CACHE_HANDLER 1
+
+/*
+ * Determine the initial instruction set to be used for this trace.
+ * Later components may decide to change this.
+ */
+JitInstructionSetType dvmCompilerInstructionSet(CompilationUnit *cUnit)
+{
+    return DALVIK_JIT_THUMB;
+}
+
+/*
+ * Jump to the out-of-line handler in ARM mode to finish executing the
+ * remaining of more complex instructions.
+ */
+static void genDispatchToHandler(CompilationUnit *cUnit, TemplateOpCode opCode)
+{
+#if USE_IN_CACHE_HANDLER
+    /*
+     * NOTE - In practice BLX only needs one operand, but since the assembler
+     * may abort itself and retry due to other out-of-range conditions we
+     * cannot really use operand[0] to store the absolute target address since
+     * it may get clobbered by the final relative offset. Therefore,
+     * we fake BLX_1 is a two operand instruction and the absolute target
+     * address is stored in operand[1].
+     */
+    newLIR2(cUnit, THUMB_BLX_1,
+            (int) gDvmJit.codeCache + templateEntryOffsets[opCode],
+            (int) gDvmJit.codeCache + templateEntryOffsets[opCode]);
+    newLIR2(cUnit, THUMB_BLX_2,
+            (int) gDvmJit.codeCache + templateEntryOffsets[opCode],
+            (int) gDvmJit.codeCache + templateEntryOffsets[opCode]);
+#else
+    /*
+     * In case we want to access the statically compiled handlers for
+     * debugging purposes, define USE_IN_CACHE_HANDLER to 0
+     */
+    void *templatePtr;
+
+#define JIT_TEMPLATE(X) extern void dvmCompiler_TEMPLATE_##X();
+#include "../../../template/armv5te/TemplateOpList.h"
+#undef JIT_TEMPLATE
+    switch (opCode) {
+#define JIT_TEMPLATE(X) \
+        case TEMPLATE_##X: { templatePtr = dvmCompiler_TEMPLATE_##X; break; }
+#include "../../../template/armv5te/TemplateOpList.h"
+#undef JIT_TEMPLATE
+        default: templatePtr = NULL;
+    }
+    loadConstant(cUnit, r7, (int) templatePtr);
+    newLIR1(cUnit, THUMB_BLX_R, r7);
+#endif
+}
+
+/* Architecture-specific initializations and checks go here */
+bool dvmCompilerArchInit(void)
+{
+    /* First, declare dvmCompiler_TEMPLATE_XXX for each template */
+#define JIT_TEMPLATE(X) extern void dvmCompiler_TEMPLATE_##X();
+#include "../../../template/armv5te/TemplateOpList.h"
+#undef JIT_TEMPLATE
+
+    int i = 0;
+    extern void dvmCompilerTemplateStart(void);
+
+    /*
+     * Then, populate the templateEntryOffsets array with the offsets from the
+     * the dvmCompilerTemplateStart symbol for each template.
+     */
+#define JIT_TEMPLATE(X) templateEntryOffsets[i++] = \
+    (intptr_t) dvmCompiler_TEMPLATE_##X - (intptr_t) dvmCompilerTemplateStart;
+#include "../../../template/armv5te/TemplateOpList.h"
+#undef JIT_TEMPLATE
+
+    /* Codegen-specific assumptions */
+    assert(offsetof(ClassObject, vtable) < 128 &&
+           (offsetof(ClassObject, vtable) & 0x3) == 0);
+    assert(offsetof(ArrayObject, length) < 128 &&
+           (offsetof(ArrayObject, length) & 0x3) == 0);
+    assert(offsetof(ArrayObject, contents) < 256);
+
+    /* Up to 5 args are pushed on top of FP - sizeofStackSaveArea */
+    assert(sizeof(StackSaveArea) < 236);
+
+    /*
+     * EA is calculated by doing "Rn + imm5 << 2", and there are 5 entry points
+     * that codegen may access, make sure that the offset from the top of the
+     * struct is less than 108.
+     */
+    assert(offsetof(InterpState, jitToInterpEntries) < 108);
+    return true;
+}
+
+static bool genInlineSqrt(CompilationUnit *cUnit, MIR *mir)
+{
+    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);
+}
+
+static bool genArithOpFloat(CompilationUnit *cUnit, MIR *mir, int vDest,
+                        int vSrc1, int vSrc2)
+{
+    return genArithOpFloatPortable(cUnit, mir, vDest, vSrc1, vSrc2);
+}
+
+static bool genArithOpDouble(CompilationUnit *cUnit, MIR *mir, int vDest,
+                      int vSrc1, int vSrc2)
+{
+    return genArithOpDoublePortable(cUnit, mir, vDest, vSrc1, vSrc2);
+}
+
+static bool genCmpX(CompilationUnit *cUnit, MIR *mir, int vDest, int vSrc1,
+                    int vSrc2)
+{
+    /*
+     * Don't attempt to optimize register usage since these opcodes call out to
+     * the handlers.
+     */
+    switch (mir->dalvikInsn.opCode) {
+        case OP_CMPL_FLOAT:
+            loadValue(cUnit, vSrc1, r0);
+            loadValue(cUnit, vSrc2, r1);
+            genDispatchToHandler(cUnit, TEMPLATE_CMPL_FLOAT);
+            storeValue(cUnit, r0, vDest, r1);
+            break;
+        case OP_CMPG_FLOAT:
+            loadValue(cUnit, vSrc1, r0);
+            loadValue(cUnit, vSrc2, r1);
+            genDispatchToHandler(cUnit, TEMPLATE_CMPG_FLOAT);
+            storeValue(cUnit, r0, vDest, r1);
+            break;
+        case OP_CMPL_DOUBLE:
+            loadValueAddress(cUnit, vSrc1, r0);
+            loadValueAddress(cUnit, vSrc2, r1);
+            genDispatchToHandler(cUnit, TEMPLATE_CMPL_DOUBLE);
+            storeValue(cUnit, r0, vDest, r1);
+            break;
+        case OP_CMPG_DOUBLE:
+            loadValueAddress(cUnit, vSrc1, r0);
+            loadValueAddress(cUnit, vSrc2, r1);
+            genDispatchToHandler(cUnit, TEMPLATE_CMPG_DOUBLE);
+            storeValue(cUnit, r0, vDest, r1);
+            break;
+        default:
+            return true;
+    }
+    return false;
+}
diff --git a/vm/compiler/codegen/arm/armv5te/ArchVariant.h b/vm/compiler/codegen/arm/armv5te/ArchVariant.h
new file mode 100644
index 0000000..6420df7
--- /dev/null
+++ b/vm/compiler/codegen/arm/armv5te/ArchVariant.h
@@ -0,0 +1,34 @@
+/*
+ * 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_COMPILER_CODEGEN_ARM_ARMV5TE_ARCHVARIANT_H
+#define _DALVIK_VM_COMPILER_CODEGEN_ARM_ARMV5TE_ARCHVARIANT_H
+
+/* Create the TemplateOpcode enum */
+#define JIT_TEMPLATE(X) TEMPLATE_##X,
+typedef enum {
+#include "../../../template/armv5te/TemplateOpList.h"
+/*
+ * For example,
+ *     TEMPLATE_CMP_LONG,
+ *     TEMPLATE_RETURN,
+ *     ...
+ */
+    TEMPLATE_LAST_MARK,
+} TemplateOpCode;
+#undef JIT_TEMPLATE
+
+#endif /* _DALVIK_VM_COMPILER_CODEGEN_ARM_ARMV5TE_ARCHVARIANT_H */
diff --git a/vm/compiler/codegen/arm/armv7-a/ArchVariant.c b/vm/compiler/codegen/arm/armv7-a/ArchVariant.c
new file mode 100644
index 0000000..92097af
--- /dev/null
+++ b/vm/compiler/codegen/arm/armv7-a/ArchVariant.c
@@ -0,0 +1,319 @@
+/*
+ * 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.
+ */
+
+
+static void loadFloat(CompilationUnit *cUnit, int vSrc, int rDest);
+
+/*
+ * This file is included by Codegen-armv5te-vfp.c, and implements architecture
+ * variant-specific code.
+ */
+
+#define USE_IN_CACHE_HANDLER 1
+
+/*
+ * Determine the initial instruction set to be used for this trace.
+ * Later components may decide to change this.
+ */
+JitInstructionSetType dvmCompilerInstructionSet(CompilationUnit *cUnit)
+{
+    return DALVIK_JIT_THUMB2;
+}
+
+/*
+ * Jump to the out-of-line handler in ARM mode to finish executing the
+ * remaining of more complex instructions.
+ */
+static void genDispatchToHandler(CompilationUnit *cUnit, TemplateOpCode opCode)
+{
+#if USE_IN_CACHE_HANDLER
+    /*
+     * NOTE - In practice BLX only needs one operand, but since the assembler
+     * may abort itself and retry due to other out-of-range conditions we
+     * cannot really use operand[0] to store the absolute target address since
+     * it may get clobbered by the final relative offset. Therefore,
+     * we fake BLX_1 is a two operand instruction and the absolute target
+     * address is stored in operand[1].
+     */
+    newLIR2(cUnit, THUMB_BLX_1,
+            (int) gDvmJit.codeCache + templateEntryOffsets[opCode],
+            (int) gDvmJit.codeCache + templateEntryOffsets[opCode]);
+    newLIR2(cUnit, THUMB_BLX_2,
+            (int) gDvmJit.codeCache + templateEntryOffsets[opCode],
+            (int) gDvmJit.codeCache + templateEntryOffsets[opCode]);
+#else
+    /*
+     * In case we want to access the statically compiled handlers for
+     * debugging purposes, define USE_IN_CACHE_HANDLER to 0
+     */
+    void *templatePtr;
+
+#define JIT_TEMPLATE(X) extern void dvmCompiler_TEMPLATE_##X();
+#include "../../../template/armv5te-vfp/TemplateOpList.h"
+#undef JIT_TEMPLATE
+    switch (opCode) {
+#define JIT_TEMPLATE(X) \
+        case TEMPLATE_##X: { templatePtr = dvmCompiler_TEMPLATE_##X; break; }
+#include "../../../template/armv5te-vfp/TemplateOpList.h"
+#undef JIT_TEMPLATE
+        default: templatePtr = NULL;
+    }
+    loadConstant(cUnit, r7, (int) templatePtr);
+    newLIR1(cUnit, THUMB_BLX_R, r7);
+#endif
+}
+
+/* Architecture-specific initializations and checks go here */
+bool dvmCompilerArchInit(void)
+{
+    /* First, declare dvmCompiler_TEMPLATE_XXX for each template */
+#define JIT_TEMPLATE(X) extern void dvmCompiler_TEMPLATE_##X();
+#include "../../../template/armv5te-vfp/TemplateOpList.h"
+#undef JIT_TEMPLATE
+
+    int i = 0;
+    extern void dvmCompilerTemplateStart(void);
+
+    /*
+     * Then, populate the templateEntryOffsets array with the offsets from the
+     * the dvmCompilerTemplateStart symbol for each template.
+     */
+#define JIT_TEMPLATE(X) templateEntryOffsets[i++] = \
+    (intptr_t) dvmCompiler_TEMPLATE_##X - (intptr_t) dvmCompilerTemplateStart;
+#include "../../../template/armv5te-vfp/TemplateOpList.h"
+#undef JIT_TEMPLATE
+
+    /* Codegen-specific assumptions */
+    assert(offsetof(ClassObject, vtable) < 128 &&
+           (offsetof(ClassObject, vtable) & 0x3) == 0);
+    assert(offsetof(ArrayObject, length) < 128 &&
+           (offsetof(ArrayObject, length) & 0x3) == 0);
+    assert(offsetof(ArrayObject, contents) < 256);
+
+    /* Up to 5 args are pushed on top of FP - sizeofStackSaveArea */
+    assert(sizeof(StackSaveArea) < 236);
+
+    /*
+     * EA is calculated by doing "Rn + imm5 << 2", and there are 5 entry points
+     * that codegen may access, make sure that the offset from the top of the
+     * struct is less than 108.
+     */
+    assert(offsetof(InterpState, jitToInterpEntries) < 108);
+    return true;
+}
+
+static bool genInlineSqrt(CompilationUnit *cUnit, MIR *mir)
+{
+    int offset = offsetof(InterpState, retval);
+    int vSrc = mir->dalvikInsn.vA;
+    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);
+    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)
+{
+    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_FLOAT_2ADDR:
+        case OP_ADD_FLOAT:
+            op = THUMB2_VADDS;
+            break;
+        case OP_SUB_FLOAT_2ADDR:
+        case OP_SUB_FLOAT:
+            op = THUMB2_VSUBS;
+            break;
+        case OP_DIV_FLOAT_2ADDR:
+        case OP_DIV_FLOAT:
+            op = THUMB2_VDIVS;
+            break;
+        case OP_MUL_FLOAT_2ADDR:
+        case OP_MUL_FLOAT:
+            op = THUMB2_VMULS;
+            break;
+        case OP_REM_FLOAT_2ADDR:
+        case OP_REM_FLOAT:
+        case OP_NEG_FLOAT: {
+            return genArithOpFloatPortable(cUnit, mir, vDest, vSrc1, vSrc2);
+        }
+        default:
+            return true;
+    }
+    loadFloat(cUnit, vSrc1, fr2);
+    loadFloat(cUnit, vSrc2, fr4);
+    newLIR3(cUnit, op, fr0, fr2, fr4);
+    storeFloat(cUnit, fr0, vDest, 0);
+    return false;
+}
+
+static bool genArithOpDouble(CompilationUnit *cUnit, MIR *mir, int vDest,
+                             int vSrc1, int vSrc2)
+{
+    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:
+            op = THUMB2_VADDD;
+            break;
+        case OP_SUB_DOUBLE_2ADDR:
+        case OP_SUB_DOUBLE:
+            op = THUMB2_VSUBD;
+            break;
+        case OP_DIV_DOUBLE_2ADDR:
+        case OP_DIV_DOUBLE:
+            op = THUMB2_VDIVD;
+            break;
+        case OP_MUL_DOUBLE_2ADDR:
+        case OP_MUL_DOUBLE:
+            op = THUMB2_VMULD;
+            break;
+        case OP_REM_DOUBLE_2ADDR:
+        case OP_REM_DOUBLE:
+        case OP_NEG_DOUBLE: {
+            return genArithOpDoublePortable(cUnit, mir, vDest, vSrc1, vSrc2);
+        }
+        default:
+            return true;
+    }
+    loadDouble(cUnit, vSrc1, dr1);
+    loadDouble(cUnit, vSrc2, dr2);
+    newLIR3(cUnit, op, dr0, dr1, dr2);
+    storeDouble(cUnit, dr0, vDest, 0);
+    return false;
+}
+
+static bool genConversion(CompilationUnit *cUnit, MIR *mir)
+{
+    OpCode opCode = mir->dalvikInsn.opCode;
+    int vSrc1Dest = mir->dalvikInsn.vA;
+    int vSrc2 = mir->dalvikInsn.vB;
+    int op = THUMB_BKPT;
+    bool longSrc = false;
+    bool longDest = false;
+    int srcReg;
+    int tgtReg;
+
+    switch (opCode) {
+        case OP_INT_TO_FLOAT:
+            longSrc = false;
+            longDest = false;
+            op = THUMB2_VCVTIF;
+            break;
+        case OP_FLOAT_TO_INT:
+            longSrc = false;
+            longDest = false;
+            op = THUMB2_VCVTFI;
+            break;
+        case OP_DOUBLE_TO_FLOAT:
+            longSrc = true;
+            longDest = false;
+            op = THUMB2_VCVTDF;
+            break;
+        case OP_FLOAT_TO_DOUBLE:
+            longSrc = false;
+            longDest = true;
+            op = THUMB2_VCVTFD;
+            break;
+        case OP_INT_TO_DOUBLE:
+            longSrc = false;
+            longDest = true;
+            op = THUMB2_VCVTID;
+            break;
+        case OP_DOUBLE_TO_INT:
+            longSrc = true;
+            longDest = false;
+            op = THUMB2_VCVTDI;
+            break;
+        case OP_FLOAT_TO_LONG:
+        case OP_LONG_TO_FLOAT:
+        case OP_DOUBLE_TO_LONG:
+        case OP_LONG_TO_DOUBLE:
+            return genConversionPortable(cUnit, mir);
+        default:
+            return true;
+    }
+    if (longSrc) {
+        srcReg = dr1;
+        loadDouble(cUnit, vSrc2, srcReg);
+    } else {
+        srcReg = fr2;
+        loadFloat(cUnit, vSrc2, srcReg);
+    }
+    if (longDest) {
+        newLIR2(cUnit, op, dr0, srcReg);
+        storeDouble(cUnit, dr0, vSrc1Dest, 0);
+    } else {
+        newLIR2(cUnit, op, fr0, srcReg);
+        storeFloat(cUnit, fr0, vSrc1Dest, 0);
+    }
+    return false;
+}
+
+static bool genCmpX(CompilationUnit *cUnit, MIR *mir, int vDest, int vSrc1,
+                    int vSrc2)
+{
+    TemplateOpCode template;
+
+    /*
+     * 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;
+            break;
+        case OP_CMPG_FLOAT:
+            template = TEMPLATE_CMPG_FLOAT_VFP;
+            break;
+        case OP_CMPL_DOUBLE:
+            template = TEMPLATE_CMPL_DOUBLE_VFP;
+            break;
+        case OP_CMPG_DOUBLE:
+            template = TEMPLATE_CMPG_DOUBLE_VFP;
+            break;
+        default:
+            return true;
+    }
+    loadValueAddress(cUnit, vSrc1, r0);
+    loadValueAddress(cUnit, vSrc2, r1);
+    genDispatchToHandler(cUnit, template);
+    storeValue(cUnit, r0, vDest, r1);
+    return false;
+}
diff --git a/vm/compiler/codegen/arm/armv7-a/ArchVariant.h b/vm/compiler/codegen/arm/armv7-a/ArchVariant.h
new file mode 100644
index 0000000..9f862e8
--- /dev/null
+++ b/vm/compiler/codegen/arm/armv7-a/ArchVariant.h
@@ -0,0 +1,34 @@
+/*
+ * 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_COMPILER_CODEGEN_ARM_ARMV5TE_VFP_ARCHVARIANT_H
+#define _DALVIK_VM_COMPILER_CODEGEN_ARM_ARMV5TE_VFP_ARCHVARIANT_H
+
+/* Create the TemplateOpcode enum */
+#define JIT_TEMPLATE(X) TEMPLATE_##X,
+typedef enum {
+#include "../../../template/armv5te-vfp/TemplateOpList.h"
+/*
+ * For example,
+ *     TEMPLATE_CMP_LONG,
+ *     TEMPLATE_RETURN,
+ *     ...
+ */
+    TEMPLATE_LAST_MARK,
+} TemplateOpCode;
+#undef JIT_TEMPLATE
+
+#endif /* _DALVIK_VM_COMPILER_CODEGEN_ARM_ARMV5TE_VFP_ARCHVARIANT_H */
diff --git a/vm/compiler/template/Makefile-template b/vm/compiler/template/Makefile-template
new file mode 100644
index 0000000..9203183
--- /dev/null
+++ b/vm/compiler/template/Makefile-template
@@ -0,0 +1,49 @@
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Makefile for the Dalvik modular interpreter.  This is not currently
+# integrated into the build system.
+#
+
+SHELL := /bin/sh
+
+# Build system has TARGET_ARCH=arm, but we need the exact architecture.
+# The base assumption for an ARM platform is ARMv5TE, but we may want to
+# support older ARMv4 devices, or use special features from ARMv6 or VFP.
+# The simulator build is "desktop".
+#
+# To generate sources for all targets:
+# for arch in desktop armv5te; do TARGET_ARCH_EXT=$arch make -f Makefile-mterp; done
+#
+#TARGET_ARCH_EXT := armv5te
+
+OUTPUT_DIR := out
+
+# Accumulate all possible dependencies for the generated files in a very
+# conservative fashion.  If it's not one of the generated files in "out",
+# assume it's a dependency.
+SOURCE_DEPS := \
+	$(shell find . -path ./$(OUTPUT_DIR) -prune -o -type f -print)
+
+# Source files generated by the script.  There's always one C and one
+# assembly file, though in practice one or the other could be empty.
+GEN_SOURCES := \
+	$(OUTPUT_DIR)/CompilerTemplateAsm-$(TARGET_ARCH_EXT).S
+
+target: $(GEN_SOURCES)
+
+$(GEN_SOURCES): $(SOURCE_DEPS)
+	@mkdir -p out
+	./gen-template.py $(TARGET_ARCH_EXT) $(OUTPUT_DIR)
diff --git a/vm/compiler/template/README.txt b/vm/compiler/template/README.txt
new file mode 100644
index 0000000..fced412
--- /dev/null
+++ b/vm/compiler/template/README.txt
@@ -0,0 +1 @@
+See README.txt under dalvik/vm/mterp for details.
diff --git a/vm/compiler/template/armv5te-vfp/TEMPLATE_ADD_DOUBLE_VFP.S b/vm/compiler/template/armv5te-vfp/TEMPLATE_ADD_DOUBLE_VFP.S
new file mode 100644
index 0000000..51693fa
--- /dev/null
+++ b/vm/compiler/template/armv5te-vfp/TEMPLATE_ADD_DOUBLE_VFP.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv5te-vfp/fbinopWide.S" {"instr":"faddd   d2, d0, d1"}
diff --git a/vm/compiler/template/armv5te-vfp/TEMPLATE_ADD_FLOAT_VFP.S b/vm/compiler/template/armv5te-vfp/TEMPLATE_ADD_FLOAT_VFP.S
new file mode 100644
index 0000000..ad1e122
--- /dev/null
+++ b/vm/compiler/template/armv5te-vfp/TEMPLATE_ADD_FLOAT_VFP.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv5te-vfp/fbinop.S" {"instr":"fadds   s2, s0, s1"}
diff --git a/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPG_DOUBLE_VFP.S b/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPG_DOUBLE_VFP.S
new file mode 100644
index 0000000..3801f49
--- /dev/null
+++ b/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPG_DOUBLE_VFP.S
@@ -0,0 +1,34 @@
+%verify "executed"
+%verify "basic lt, gt, eq */
+%verify "left arg NaN"
+%verify "right arg NaN"
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else {
+     *         return 1;
+     *     }
+     * }
+     *
+     * On entry:
+     *    r0 = &op1 [vBB]
+     *    r1 = &op2 [vCC]
+     */
+    /* op vAA, vBB, vCC */
+    fldd    d0, [r0]                    @ d0<- vBB
+    fldd    d1, [r1]                    @ d1<- vCC
+    fcmped  d0, d1                      @ compare (vBB, vCC)
+    mov     r0, #1                      @ r0<- 1 (default)
+    fmstat                              @ export status flags
+    mvnmi   r0, #0                      @ (less than) r0<- -1
+    moveq   r0, #0                      @ (equal) r0<- 0
+    bx      lr
+
diff --git a/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPG_FLOAT_VFP.S b/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPG_FLOAT_VFP.S
new file mode 100644
index 0000000..1faafa1
--- /dev/null
+++ b/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPG_FLOAT_VFP.S
@@ -0,0 +1,32 @@
+%verify "executed"
+%verify "basic lt, gt, eq */
+%verify "left arg NaN"
+%verify "right arg NaN"
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else {
+     *         return 1;
+     *     }
+     * }
+     * On entry:
+     *    r0 = &op1 [vBB]
+     *    r1 = &op2 [vCC]
+     */
+    /* op vAA, vBB, vCC */
+    flds    s0, [r0]                    @ d0<- vBB
+    flds    s1, [r1]                    @ d1<- vCC
+    fcmpes  s0, s1                      @ compare (vBB, vCC)
+    mov     r0, #1                      @ r0<- 1 (default)
+    fmstat                              @ export status flags
+    mvnmi   r0, #0                      @ (less than) r0<- -1
+    moveq   r0, #0                      @ (equal) r0<- 0
+    bx      lr
diff --git a/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPL_DOUBLE_VFP.S b/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPL_DOUBLE_VFP.S
new file mode 100644
index 0000000..7241af1
--- /dev/null
+++ b/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPL_DOUBLE_VFP.S
@@ -0,0 +1,32 @@
+%verify "executed"
+%verify "basic lt, gt, eq */
+%verify "left arg NaN"
+%verify "right arg NaN"
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else {
+     *         return -1;
+     *     }
+     * }
+     * On entry:
+     *    r0 = &op1 [vBB]
+     *    r1 = &op2 [vCC]
+     */
+    /* op vAA, vBB, vCC */
+    fldd    d0, [r0]                    @ d0<- vBB
+    fldd    d1, [r1]                    @ d1<- vCC
+    fcmped  d0, d1                      @ compare (vBB, vCC)
+    mvn     r0, #0                      @ r0<- -1 (default)
+    fmstat                              @ export status flags
+    movgt   r0, #1                      @ (greater than) r0<- 1
+    moveq   r0, #0                      @ (equal) r0<- 0
+    bx      lr
diff --git a/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPL_FLOAT_VFP.S b/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPL_FLOAT_VFP.S
new file mode 100644
index 0000000..014f160
--- /dev/null
+++ b/vm/compiler/template/armv5te-vfp/TEMPLATE_CMPL_FLOAT_VFP.S
@@ -0,0 +1,32 @@
+%verify "executed"
+%verify "basic lt, gt, eq */
+%verify "left arg NaN"
+%verify "right arg NaN"
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else {
+     *         return -1;
+     *     }
+     * }
+     * On entry:
+     *    r0 = &op1 [vBB]
+     *    r1 = &op2 [vCC]
+     */
+    /* op vAA, vBB, vCC */
+    flds    s0, [r0]                    @ d0<- vBB
+    flds    s1, [r1]                    @ d1<- vCC
+    fcmpes  s0, s1                      @ compare (vBB, vCC)
+    mvn     r0, #0                      @ r0<- -1 (default)
+    fmstat                              @ export status flags
+    movgt   r0, #1                      @ (greater than) r0<- 1
+    moveq   r0, #0                      @ (equal) r0<- 0
+    bx      lr
diff --git a/vm/compiler/template/armv5te-vfp/TEMPLATE_DIV_DOUBLE_VFP.S b/vm/compiler/template/armv5te-vfp/TEMPLATE_DIV_DOUBLE_VFP.S
new file mode 100644
index 0000000..8fa58b8
--- /dev/null
+++ b/vm/compiler/template/armv5te-vfp/TEMPLATE_DIV_DOUBLE_VFP.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv5te-vfp/fbinopWide.S" {"instr":"fdivd   d2, d0, d1"}
diff --git a/vm/compiler/template/armv5te-vfp/TEMPLATE_DIV_FLOAT_VFP.S b/vm/compiler/template/armv5te-vfp/TEMPLATE_DIV_FLOAT_VFP.S
new file mode 100644
index 0000000..fc125ce
--- /dev/null
+++ b/vm/compiler/template/armv5te-vfp/TEMPLATE_DIV_FLOAT_VFP.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv5te-vfp/fbinop.S" {"instr":"fdivs   s2, s0, s1"}
diff --git a/vm/compiler/template/armv5te-vfp/TEMPLATE_DOUBLE_TO_FLOAT_VFP.S b/vm/compiler/template/armv5te-vfp/TEMPLATE_DOUBLE_TO_FLOAT_VFP.S
new file mode 100644
index 0000000..dba3b08
--- /dev/null
+++ b/vm/compiler/template/armv5te-vfp/TEMPLATE_DOUBLE_TO_FLOAT_VFP.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv5te-vfp/funopNarrower.S" {"instr":"fcvtsd  s0, d0"}
diff --git a/vm/compiler/template/armv5te-vfp/TEMPLATE_DOUBLE_TO_INT_VFP.S b/vm/compiler/template/armv5te-vfp/TEMPLATE_DOUBLE_TO_INT_VFP.S
new file mode 100644
index 0000000..4d910aa
--- /dev/null
+++ b/vm/compiler/template/armv5te-vfp/TEMPLATE_DOUBLE_TO_INT_VFP.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv5te-vfp/funopNarrower.S" {"instr":"ftosizd  s0, d0"}
diff --git a/vm/compiler/template/armv5te-vfp/TEMPLATE_FLOAT_TO_DOUBLE_VFP.S b/vm/compiler/template/armv5te-vfp/TEMPLATE_FLOAT_TO_DOUBLE_VFP.S
new file mode 100644
index 0000000..a5157dd
--- /dev/null
+++ b/vm/compiler/template/armv5te-vfp/TEMPLATE_FLOAT_TO_DOUBLE_VFP.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv5te-vfp/funopWider.S" {"instr":"fcvtds  d0, s0"}
diff --git a/vm/compiler/template/armv5te-vfp/TEMPLATE_FLOAT_TO_INT_VFP.S b/vm/compiler/template/armv5te-vfp/TEMPLATE_FLOAT_TO_INT_VFP.S
new file mode 100644
index 0000000..90900aa
--- /dev/null
+++ b/vm/compiler/template/armv5te-vfp/TEMPLATE_FLOAT_TO_INT_VFP.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv5te-vfp/funop.S" {"instr":"ftosizs s1, s0"}
diff --git a/vm/compiler/template/armv5te-vfp/TEMPLATE_INT_TO_DOUBLE_VFP.S b/vm/compiler/template/armv5te-vfp/TEMPLATE_INT_TO_DOUBLE_VFP.S
new file mode 100644
index 0000000..c9f4fd6
--- /dev/null
+++ b/vm/compiler/template/armv5te-vfp/TEMPLATE_INT_TO_DOUBLE_VFP.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv5te-vfp/funopWider.S" {"instr":"fsitod  d0, s0"}
diff --git a/vm/compiler/template/armv5te-vfp/TEMPLATE_INT_TO_FLOAT_VFP.S b/vm/compiler/template/armv5te-vfp/TEMPLATE_INT_TO_FLOAT_VFP.S
new file mode 100644
index 0000000..a8f57b5
--- /dev/null
+++ b/vm/compiler/template/armv5te-vfp/TEMPLATE_INT_TO_FLOAT_VFP.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv5te-vfp/funop.S" {"instr":"fsitos  s1, s0"}
diff --git a/vm/compiler/template/armv5te-vfp/TEMPLATE_MUL_DOUBLE_VFP.S b/vm/compiler/template/armv5te-vfp/TEMPLATE_MUL_DOUBLE_VFP.S
new file mode 100644
index 0000000..459e796
--- /dev/null
+++ b/vm/compiler/template/armv5te-vfp/TEMPLATE_MUL_DOUBLE_VFP.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv5te-vfp/fbinopWide.S" {"instr":"fmuld   d2, d0, d1"}
diff --git a/vm/compiler/template/armv5te-vfp/TEMPLATE_MUL_FLOAT_VFP.S b/vm/compiler/template/armv5te-vfp/TEMPLATE_MUL_FLOAT_VFP.S
new file mode 100644
index 0000000..301fa84
--- /dev/null
+++ b/vm/compiler/template/armv5te-vfp/TEMPLATE_MUL_FLOAT_VFP.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv5te-vfp/fbinop.S" {"instr":"fmuls   s2, s0, s1"}
diff --git a/vm/compiler/template/armv5te-vfp/TEMPLATE_SQRT_DOUBLE_VFP.S b/vm/compiler/template/armv5te-vfp/TEMPLATE_SQRT_DOUBLE_VFP.S
new file mode 100644
index 0000000..1c6bb46
--- /dev/null
+++ b/vm/compiler/template/armv5te-vfp/TEMPLATE_SQRT_DOUBLE_VFP.S
@@ -0,0 +1,23 @@
+%verify "executed"
+    /*
+     * 64-bit floating point vfp sqrt operation.
+     * If the result is a NaN, bail out to library code to do
+     * the right thing.
+     *
+     * On entry:
+     *     r2 src addr of op1
+     * On exit:
+     *     r0,r1 = res
+     */
+    fldd    d0, [r2]
+    fsqrtd  d1, d0
+    fcmpd   d1, d1
+    fmstat
+    fmrrd   r0, r1, d1
+    bxeq    lr   @ Result OK - return
+    ldr     r2, .Lsqrt
+    fmrrd   r0, r1, d0   @ reload orig operand
+    bx      r2   @ tail call to sqrt library routine
+
+.Lsqrt:
+    .word   sqrt
diff --git a/vm/compiler/template/armv5te-vfp/TEMPLATE_SUB_DOUBLE_VFP.S b/vm/compiler/template/armv5te-vfp/TEMPLATE_SUB_DOUBLE_VFP.S
new file mode 100644
index 0000000..8fa20a0
--- /dev/null
+++ b/vm/compiler/template/armv5te-vfp/TEMPLATE_SUB_DOUBLE_VFP.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv5te-vfp/fbinopWide.S" {"instr":"fsubd   d2, d0, d1"}
diff --git a/vm/compiler/template/armv5te-vfp/TEMPLATE_SUB_FLOAT_VFP.S b/vm/compiler/template/armv5te-vfp/TEMPLATE_SUB_FLOAT_VFP.S
new file mode 100644
index 0000000..5e17e51
--- /dev/null
+++ b/vm/compiler/template/armv5te-vfp/TEMPLATE_SUB_FLOAT_VFP.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv5te-vfp/fbinop.S" {"instr":"fsubs   s2, s0, s1"}
diff --git a/vm/compiler/template/armv5te-vfp/TemplateOpList.h b/vm/compiler/template/armv5te-vfp/TemplateOpList.h
new file mode 100644
index 0000000..c95163c
--- /dev/null
+++ b/vm/compiler/template/armv5te-vfp/TemplateOpList.h
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+/*
+ * Dalvik opcode list that uses additional templates to complete JIT execution.
+ */
+#ifndef JIT_TEMPLATE
+#define JIT_TEMPLATE(X)
+#endif
+
+JIT_TEMPLATE(CMP_LONG)
+JIT_TEMPLATE(RETURN)
+JIT_TEMPLATE(INVOKE_METHOD_NO_OPT)
+JIT_TEMPLATE(INVOKE_METHOD_CHAIN)
+JIT_TEMPLATE(INVOKE_METHOD_PREDICTED_CHAIN)
+JIT_TEMPLATE(INVOKE_METHOD_NATIVE)
+JIT_TEMPLATE(MUL_LONG)
+JIT_TEMPLATE(SHL_LONG)
+JIT_TEMPLATE(SHR_LONG)
+JIT_TEMPLATE(USHR_LONG)
+JIT_TEMPLATE(ADD_FLOAT_VFP)
+JIT_TEMPLATE(SUB_FLOAT_VFP)
+JIT_TEMPLATE(MUL_FLOAT_VFP)
+JIT_TEMPLATE(DIV_FLOAT_VFP)
+JIT_TEMPLATE(ADD_DOUBLE_VFP)
+JIT_TEMPLATE(SUB_DOUBLE_VFP)
+JIT_TEMPLATE(MUL_DOUBLE_VFP)
+JIT_TEMPLATE(DIV_DOUBLE_VFP)
+JIT_TEMPLATE(DOUBLE_TO_FLOAT_VFP)
+JIT_TEMPLATE(DOUBLE_TO_INT_VFP)
+JIT_TEMPLATE(FLOAT_TO_DOUBLE_VFP)
+JIT_TEMPLATE(FLOAT_TO_INT_VFP)
+JIT_TEMPLATE(INT_TO_DOUBLE_VFP)
+JIT_TEMPLATE(INT_TO_FLOAT_VFP)
+JIT_TEMPLATE(CMPG_DOUBLE_VFP)
+JIT_TEMPLATE(CMPL_DOUBLE_VFP)
+JIT_TEMPLATE(CMPG_FLOAT_VFP)
+JIT_TEMPLATE(CMPL_FLOAT_VFP)
+JIT_TEMPLATE(SQRT_DOUBLE_VFP)
diff --git a/vm/compiler/template/armv5te-vfp/fbinop.S b/vm/compiler/template/armv5te-vfp/fbinop.S
new file mode 100644
index 0000000..3bc4b52
--- /dev/null
+++ b/vm/compiler/template/armv5te-vfp/fbinop.S
@@ -0,0 +1,14 @@
+    /*
+     * Generic 32-bit floating point operation.  Provide an "instr" line that
+     * specifies an instruction that performs s2 = s0 op s1.
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = op1 address
+     *     r2 = op2 address
+     */
+     flds    s0,[r1]
+     flds    s1,[r2]
+     $instr
+     fsts    s2,[r0]
+     bx      lr
diff --git a/vm/compiler/template/armv5te-vfp/fbinopWide.S b/vm/compiler/template/armv5te-vfp/fbinopWide.S
new file mode 100644
index 0000000..3774646
--- /dev/null
+++ b/vm/compiler/template/armv5te-vfp/fbinopWide.S
@@ -0,0 +1,14 @@
+    /*
+     * Generic 64-bit floating point operation.  Provide an "instr" line that
+     * specifies an instruction that performs s2 = s0 op s1.
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = op1 address
+     *     r2 = op2 address
+     */
+     fldd    d0,[r1]
+     fldd    d1,[r2]
+     $instr
+     fstd    d2,[r0]
+     bx      lr
diff --git a/vm/compiler/template/armv5te-vfp/funop.S b/vm/compiler/template/armv5te-vfp/funop.S
new file mode 100644
index 0000000..8409c28
--- /dev/null
+++ b/vm/compiler/template/armv5te-vfp/funop.S
@@ -0,0 +1,15 @@
+    /*
+     * Generic 32bit-to-32bit floating point unary operation.  Provide an
+     * "instr" line that specifies an instruction that performs "s1 = op s0".
+     *
+     * For: float-to-int, int-to-float
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = src dalvik register address
+     */
+    /* unop vA, vB */
+    flds    s0, [r1]                    @ s0<- vB
+    $instr                              @ s1<- op s0
+    fsts    s1, [r0]                    @ vA<- s1
+    bx      lr
diff --git a/vm/compiler/template/armv5te-vfp/funopNarrower.S b/vm/compiler/template/armv5te-vfp/funopNarrower.S
new file mode 100644
index 0000000..8566fca
--- /dev/null
+++ b/vm/compiler/template/armv5te-vfp/funopNarrower.S
@@ -0,0 +1,15 @@
+    /*
+     * Generic 64bit-to-32bit floating point unary operation.  Provide an
+     * "instr" line that specifies an instruction that performs "s0 = op d0".
+     *
+     * For: double-to-int, double-to-float
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = src dalvik register address
+     */
+    /* unop vA, vB */
+    fldd    d0, [r1]                    @ d0<- vB
+    $instr                              @ s0<- op d0
+    fsts    s0, [r0]                    @ vA<- s0
+    bx      lr
diff --git a/vm/compiler/template/armv5te-vfp/funopWider.S b/vm/compiler/template/armv5te-vfp/funopWider.S
new file mode 100644
index 0000000..dbe745c
--- /dev/null
+++ b/vm/compiler/template/armv5te-vfp/funopWider.S
@@ -0,0 +1,15 @@
+    /*
+     * Generic 32bit-to-64bit floating point unary operation.  Provide an
+     * "instr" line that specifies an instruction that performs "d0 = op s0".
+     *
+     * For: int-to-double, float-to-double
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = src dalvik register address
+     */
+    /* unop vA, vB */
+    flds    s0, [r1]                    @ s0<- vB
+    $instr                              @ d0<- op s0
+    fstd    d0, [r0]                    @ vA<- d0
+    bx      lr
diff --git a/vm/compiler/template/armv5te/TEMPLATE_CMPG_DOUBLE.S b/vm/compiler/template/armv5te/TEMPLATE_CMPG_DOUBLE.S
new file mode 100644
index 0000000..f18f6d3
--- /dev/null
+++ b/vm/compiler/template/armv5te/TEMPLATE_CMPG_DOUBLE.S
@@ -0,0 +1 @@
+%include "armv5te/TEMPLATE_CMPL_DOUBLE.S" { "naninst":"mov     r0, #1" }
diff --git a/vm/compiler/template/armv5te/TEMPLATE_CMPG_FLOAT.S b/vm/compiler/template/armv5te/TEMPLATE_CMPG_FLOAT.S
new file mode 100644
index 0000000..02887e5
--- /dev/null
+++ b/vm/compiler/template/armv5te/TEMPLATE_CMPG_FLOAT.S
@@ -0,0 +1 @@
+%include "armv5te/TEMPLATE_CMPL_FLOAT.S" { "naninst":"mov     r0, #1" }
diff --git a/vm/compiler/template/armv5te/TEMPLATE_CMPL_DOUBLE.S b/vm/compiler/template/armv5te/TEMPLATE_CMPL_DOUBLE.S
new file mode 100644
index 0000000..dfafd2c
--- /dev/null
+++ b/vm/compiler/template/armv5te/TEMPLATE_CMPL_DOUBLE.S
@@ -0,0 +1,39 @@
+%default { "naninst":"mvn     r0, #0" }
+    /*
+     * For the JIT: incoming arguments are pointers to the arguments in r0/r1
+     *              result in r0
+     *
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
+     * on what value we'd like to return when one of the operands is NaN.
+     *
+     * See OP_CMPL_FLOAT for an explanation.
+     *
+     * For: cmpl-double, cmpg-double
+     */
+    /* op vAA, vBB, vCC */
+    mov     r4, lr                      @ save return address
+    mov     r9, r0                      @ save copy of &arg1
+    mov     r10, r1                     @ save copy of &arg2
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    ldmia   r10, {r2-r3}                @ r2/r3<- vCC/vCC+1
+    LDR_PC_LR ".L__aeabi_cdcmple"       @ PIC way of "bl __aeabi_cdcmple"
+    bhi     .L${opcode}_gt_or_nan       @ C set and Z clear, disambiguate
+    mvncc   r0, #0                      @ (less than) r1<- -1
+    moveq   r0, #0                      @ (equal) r1<- 0, trumps less than
+    bx      r4
+
+    @ Test for NaN with a second comparison.  EABI forbids testing bit
+    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
+    @ make the library call.
+.L${opcode}_gt_or_nan:
+    ldmia   r10, {r0-r1}                @ reverse order
+    ldmia   r9, {r2-r3}
+    LDR_PC_LR ".L__aeabi_cdcmple"       @ r0<- Z set if eq, C clear if <
+    movcc   r0, #1                      @ (greater than) r1<- 1
+    bxcc    r4
+    $naninst                            @ r1<- 1 or -1 for NaN
+    bx      r4
+
diff --git a/vm/compiler/template/armv5te/TEMPLATE_CMPL_FLOAT.S b/vm/compiler/template/armv5te/TEMPLATE_CMPL_FLOAT.S
new file mode 100644
index 0000000..31d4cd8
--- /dev/null
+++ b/vm/compiler/template/armv5te/TEMPLATE_CMPL_FLOAT.S
@@ -0,0 +1,56 @@
+%default { "naninst":"mvn     r0, #0" }
+    /*
+     * For the JIT: incoming arguments in r0, r1
+     *              result in r0
+     *
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
+     * on what value we'd like to return when one of the operands is NaN.
+     *
+     * The operation we're implementing is:
+     *   if (x == y)
+     *     return 0;
+     *   else if (x < y)
+     *     return -1;
+     *   else if (x > y)
+     *     return 1;
+     *   else
+     *     return {-1,1};  // one or both operands was NaN
+     *
+     * The straightforward implementation requires 3 calls to functions
+     * that return a result in r0.  We can do it with two calls if our
+     * EABI library supports __aeabi_cfcmple (only one if we want to check
+     * for NaN directly):
+     *   check x <= y
+     *     if <, return -1
+     *     if ==, return 0
+     *   check y <= x
+     *     if <, return 1
+     *   return {-1,1}
+     *
+     * for: cmpl-float, cmpg-float
+     */
+    /* op vAA, vBB, vCC */
+    mov     r4, lr                      @ save return address
+    mov     r9, r0                      @ Save copies - we may need to redo
+    mov     r10, r1
+    LDR_PC_LR ".L__aeabi_cfcmple"       @ cmp <=: C clear if <, Z set if eq
+    bhi     .L${opcode}_gt_or_nan       @ C set and Z clear, disambiguate
+    mvncc   r0, #0                      @ (less than) r0<- -1
+    moveq   r0, #0                      @ (equal) r0<- 0, trumps less than
+    bx      r4
+    @ Test for NaN with a second comparison.  EABI forbids testing bit
+    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
+    @ make the library call.
+.L${opcode}_gt_or_nan:
+    mov     r1, r9                      @ reverse order
+    mov     r0, r10
+    LDR_PC_LR ".L__aeabi_cfcmple"       @ r0<- Z set if eq, C clear if <
+    movcc   r0, #1                      @ (greater than) r1<- 1
+    bxcc    r4
+    $naninst                            @ r1<- 1 or -1 for NaN
+    bx      r4
+
+
diff --git a/vm/compiler/template/armv5te/TEMPLATE_CMP_LONG.S b/vm/compiler/template/armv5te/TEMPLATE_CMP_LONG.S
new file mode 100644
index 0000000..5f1e16b
--- /dev/null
+++ b/vm/compiler/template/armv5te/TEMPLATE_CMP_LONG.S
@@ -0,0 +1,34 @@
+    /*
+     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
+     * register based on the results of the comparison.
+     *
+     * We load the full values with LDM, but in practice many values could
+     * be resolved by only looking at the high word.  This could be made
+     * faster or slower by splitting the LDM into a pair of LDRs.
+     *
+     * If we just wanted to set condition flags, we could do this:
+     *  subs    ip, r0, r2
+     *  sbcs    ip, r1, r3
+     *  subeqs  ip, r0, r2
+     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
+     * integer value, which we can do with 2 conditional mov/mvn instructions
+     * (set 1, set -1; if they're equal we already have 0 in ip), giving
+     * us a constant 5-cycle path plus a branch at the end to the
+     * instruction epilogue code.  The multi-compare approach below needs
+     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
+     * in the worst case (the 64-bit values are equal).
+     */
+    /* cmp-long vAA, vBB, vCC */
+    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
+    blt     .L${opcode}_less            @ signed compare on high part
+    bgt     .L${opcode}_greater
+    subs    r0, r0, r2                  @ r0<- r0 - r2
+    bxeq     lr
+    bhi     .L${opcode}_greater         @ unsigned compare on low part
+.L${opcode}_less:
+    mvn     r0, #0                      @ r0<- -1
+    bx      lr
+.L${opcode}_greater:
+    mov     r0, #1                      @ r0<- 1
+    bx      lr
+
diff --git a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S
new file mode 100644
index 0000000..20bb3ab
--- /dev/null
+++ b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S
@@ -0,0 +1,47 @@
+    /*
+     * For monomorphic callsite, setup the Dalvik frame and return to the
+     * Thumb code through the link register to transfer control to the callee
+     * method through a dedicated chaining cell.
+     */
+    @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
+    @ methodToCall is guaranteed to be non-native
+.LinvokeChain:
+    ldrh    r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
+    ldrh    r2, [r0, #offMethod_outsSize]  @ r2<- methodToCall->outsSize
+    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
+    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+    add     r3, r1, #1  @ Thumb addr is odd
+    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
+    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
+    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
+    add     r12, lr, #2                 @ setup the punt-to-interp address
+    sub     r10, r10, r2, lsl #2        @ r10<- bottom (newsave - outsSize)
+    ldr     r8, [r8]                    @ r3<- suspendCount (int)
+    cmp     r10, r9                     @ bottom < interpStackEnd?
+    bxlt    r12                         @ return to raise stack overflow excep.
+    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
+    ldr     r9, [r0, #offMethod_clazz]      @ r9<- method->clazz
+    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
+    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- methodToCall->insns
+
+
+    @ set up newSaveArea
+    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
+    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
+    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
+    cmp     r8, #0                      @ suspendCount != 0
+    bxne    r12                         @ bail to the interpreter
+
+    ldr     r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
+    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
+
+    @ Update "glue" values for the new method
+    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
+    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
+    mov     rFP, r1                         @ fp = newFp
+    str     rFP, [r2, #offThread_curFrame]  @ self->curFrame = newFp
+
+    bx      lr                              @ return to the callee-chaining cell
+
+
diff --git a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S
new file mode 100644
index 0000000..b20d564
--- /dev/null
+++ b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S
@@ -0,0 +1,51 @@
+    @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
+    ldrh    r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
+    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
+    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+    add     r3, r1, #1  @ Thumb addr is odd
+    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
+    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
+    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
+    ldr     r8, [r8]                    @ r3<- suspendCount (int)
+    cmp     r10, r9                     @ bottom < interpStackEnd?
+    bxlt    lr                          @ return to raise stack overflow excep.
+    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
+    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
+    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- methodToCall->insns
+
+
+    @ set up newSaveArea
+    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
+    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
+    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
+    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
+    cmp     r8, #0                      @ suspendCount != 0
+    ldr     r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc
+    bxne    lr                          @ bail to the interpreter
+
+    @ go ahead and transfer control to the native code
+    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
+    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
+    str     r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
+                                        @ newFp->localRefCookie=top
+    mov     r9, r3                      @ r9<- glue->self (preserve)
+    SAVEAREA_FROM_FP(r10, r1)           @ r10<- new stack save area
+
+    mov     r2, r0                      @ r2<- methodToCall
+    mov     r0, r1                      @ r0<- newFP
+    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
+
+    blx     r8                          @ off to the native code
+
+    @ native return; r9=self, r10=newSaveArea
+    @ equivalent to dvmPopJniLocals
+    ldr     r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
+    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
+    ldr     r1, [r9, #offThread_exception] @ check for exception
+    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
+    cmp     r1, #0                      @ null?
+    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
+    bne     .LhandleException             @ no, handle exception
+    bx      r2
+
diff --git a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S
new file mode 100644
index 0000000..0ac7cf8
--- /dev/null
+++ b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S
@@ -0,0 +1,47 @@
+    /*
+     * For polymorphic callsites - setup the Dalvik frame and load Dalvik PC
+     * into rPC then jump to dvmJitToInterpNoChain to dispatch the
+     * runtime-resolved callee.
+     */
+    @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
+    ldrh    r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
+    ldrh    r2, [r0, #offMethod_outsSize]  @ r2<- methodToCall->outsSize
+    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
+    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+    add     r3, r1, #1  @ Thumb addr is odd
+    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
+    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
+    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
+    sub     r10, r10, r2, lsl #2        @ r10<- bottom (newsave - outsSize)
+    ldr     r8, [r8]                    @ r3<- suspendCount (int)
+    cmp     r10, r9                     @ bottom < interpStackEnd?
+    bxlt    lr                          @ return to raise stack overflow excep.
+    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
+    ldr     r9, [r0, #offMethod_clazz]      @ r9<- method->clazz
+    ldr     r10, [r0, #offMethod_accessFlags] @ r10<- methodToCall->accessFlags
+    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
+    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- methodToCall->insns
+
+
+    @ set up newSaveArea
+    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
+    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
+    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
+    cmp     r8, #0                      @ suspendCount != 0
+    bxne    lr                          @ bail to the interpreter
+    tst     r10, #ACC_NATIVE
+    bne     .LinvokeNative
+
+    ldr     r10, .LdvmJitToInterpNoChain
+    ldr     r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
+    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
+
+    @ Update "glue" values for the new method
+    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
+    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
+    mov     rFP, r1                         @ fp = newFp
+    str     rFP, [r2, #offThread_curFrame]  @ self->curFrame = newFp
+
+    @ Start executing the callee
+    mov     pc, r10                         @ dvmJitToInterpNoChain
diff --git a/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S
new file mode 100644
index 0000000..9ee49a8
--- /dev/null
+++ b/vm/compiler/template/armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S
@@ -0,0 +1,42 @@
+    /*
+     * For polymorphic callsite, check whether the cached class pointer matches
+     * the current one. If so setup the Dalvik frame and return to the
+     * Thumb code through the link register to transfer control to the callee
+     * method through a dedicated chaining cell.
+     *
+     * The predicted chaining cell is declared in ArmLIR.h with the
+     * following layout:
+     *
+     *  typedef struct PredictedChainingCell {
+     *      u4 branch;
+     *      const ClassObject *clazz;
+     *      const Method *method;
+     *      u4 counter;
+     *  } PredictedChainingCell;
+     *
+     * Upon returning to the callsite:
+     *    - lr  : to branch to the chaining cell
+     *    - lr+2: to punt to the interpreter
+     *    - lr+4: to fully resolve the callee and may rechain.
+     *            r3 <- class
+     *            r9 <- counter
+     */
+    @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite
+    ldr     r3, [r0, #offObject_clazz]  @ r3 <- this->class
+    ldr     r8, [r2, #4]    @ r8 <- predictedChainCell->clazz
+    ldr     r0, [r2, #8]    @ r0 <- predictedChainCell->method
+    ldr     r9, [r2, #12]   @ r9 <- predictedChainCell->counter
+    cmp     r3, r8          @ predicted class == actual class?
+    beq     .LinvokeChain   @ predicted chain is valid
+    ldr     r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable
+    sub     r1, r9, #1      @ count--
+    str     r1, [r2, #12]   @ write back to PredictedChainingCell->counter
+    add     lr, lr, #4      @ return to fully-resolve landing pad
+    /*
+     * r1 <- count
+     * r2 <- &predictedChainCell
+     * r3 <- this->class
+     * r4 <- dPC
+     * r7 <- this->class->vtable
+     */
+    bx      lr
diff --git a/vm/compiler/template/armv5te/TEMPLATE_MUL_LONG.S b/vm/compiler/template/armv5te/TEMPLATE_MUL_LONG.S
new file mode 100644
index 0000000..8a9b115
--- /dev/null
+++ b/vm/compiler/template/armv5te/TEMPLATE_MUL_LONG.S
@@ -0,0 +1,28 @@
+    /*
+     * Signed 64-bit integer multiply.
+     *
+     * For JIT: op1 in r0/r1, op2 in r2/r3, return in r0/r1
+     *
+     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
+     *        WX
+     *      x YZ
+     *  --------
+     *     ZW ZX
+     *  YW YX
+     *
+     * The low word of the result holds ZX, the high word holds
+     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
+     * it doesn't fit in the low 64 bits.
+     *
+     * Unlike most ARM math operations, multiply instructions have
+     * restrictions on using the same register more than once (Rd and Rm
+     * cannot be the same).
+     */
+    /* mul-long vAA, vBB, vCC */
+    mul     ip, r2, r1                  @  ip<- ZxW
+    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
+    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
+    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
+    mov     r0,r9
+    mov     r1,r10
+    bx      lr
diff --git a/vm/compiler/template/armv5te/TEMPLATE_RETURN.S b/vm/compiler/template/armv5te/TEMPLATE_RETURN.S
new file mode 100644
index 0000000..f0a4623
--- /dev/null
+++ b/vm/compiler/template/armv5te/TEMPLATE_RETURN.S
@@ -0,0 +1,38 @@
+    /*
+     * Unwind a frame from the Dalvik stack for compiled OP_RETURN_XXX.
+     * If the stored value in returnAddr
+     * is non-zero, the caller is compiled by the JIT thus return to the
+     * address in the code cache following the invoke instruction. Otherwise
+     * return to the special dvmJitToInterpNoChain entry point.
+     */
+    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
+    ldr     r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame
+    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+    ldr     rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc
+    ldr     r9,  [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
+    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?
+    beq     1f                          @ bail to interpreter
+    ldr     r0, .LdvmJitToInterpNoChain @ defined in footer.S
+    mov     rFP, r10                    @ publish new FP
+    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
+    ldr     r8, [r8]                    @ r8<- suspendCount
+
+    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
+    ldr     r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex
+    str     rFP, [r3, #offThread_curFrame] @ self->curFrame = fp
+    add     rPC, rPC, #6                @ publish new rPC (advance 6 bytes)
+    str     r1, [rGLUE, #offGlue_methodClassDex]
+    cmp     r8, #0                      @ check the suspendCount
+    movne   r9, #0                      @ clear the chaining cell address
+    cmp     r9, #0                      @ chaining cell exists?
+    blxne   r9                          @ jump to the chaining cell
+    mov     pc, r0                      @ callsite is interpreted
+1:
+    stmia   rGLUE, {rPC, rFP}           @ SAVE_PC_FP_TO_GLUE()
+    ldr     r2, .LdvmMterpStdBail       @ defined in footer.S
+    mov     r1, #0                      @ changeInterp = false
+    mov     r0, rGLUE                   @ Expecting rGLUE in r0
+    blx     r2                          @ exit the interpreter
diff --git a/vm/compiler/template/armv5te/TEMPLATE_SHL_LONG.S b/vm/compiler/template/armv5te/TEMPLATE_SHL_LONG.S
new file mode 100644
index 0000000..532f8a4
--- /dev/null
+++ b/vm/compiler/template/armv5te/TEMPLATE_SHL_LONG.S
@@ -0,0 +1,15 @@
+    /*
+     * Long integer shift.  This is different from the generic 32/64-bit
+     * binary operations because vAA/vBB are 64-bit but vCC (the shift
+     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
+     * 6 bits.
+     */
+    /* shl-long vAA, vBB, vCC */
+    and     r2, r2, #63                 @ r2<- r2 & 0x3f
+    mov     r1, r1, asl r2              @  r1<- r1 << r2
+    rsb     r3, r2, #32                 @  r3<- 32 - r2
+    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
+    subs    ip, r2, #32                 @  ip<- r2 - 32
+    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
+    mov     r0, r0, asl r2              @  r0<- r0 << r2
+    bx      lr
diff --git a/vm/compiler/template/armv5te/TEMPLATE_SHR_LONG.S b/vm/compiler/template/armv5te/TEMPLATE_SHR_LONG.S
new file mode 100644
index 0000000..ca7545a
--- /dev/null
+++ b/vm/compiler/template/armv5te/TEMPLATE_SHR_LONG.S
@@ -0,0 +1,16 @@
+    /*
+     * Long integer shift.  This is different from the generic 32/64-bit
+     * binary operations because vAA/vBB are 64-bit but vCC (the shift
+     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
+     * 6 bits.
+     */
+    /* shr-long vAA, vBB, vCC */
+    and     r2, r2, #63                 @ r0<- r0 & 0x3f
+    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
+    rsb     r3, r2, #32                 @  r3<- 32 - r2
+    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
+    subs    ip, r2, #32                 @  ip<- r2 - 32
+    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
+    mov     r1, r1, asr r2              @  r1<- r1 >> r2
+    bx      lr
+
diff --git a/vm/compiler/template/armv5te/TEMPLATE_USHR_LONG.S b/vm/compiler/template/armv5te/TEMPLATE_USHR_LONG.S
new file mode 100644
index 0000000..d7c71d9
--- /dev/null
+++ b/vm/compiler/template/armv5te/TEMPLATE_USHR_LONG.S
@@ -0,0 +1,16 @@
+    /*
+     * Long integer shift.  This is different from the generic 32/64-bit
+     * binary operations because vAA/vBB are 64-bit but vCC (the shift
+     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
+     * 6 bits.
+     */
+    /* ushr-long vAA, vBB, vCC */
+    and     r2, r2, #63                 @ r0<- r0 & 0x3f
+    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
+    rsb     r3, r2, #32                 @  r3<- 32 - r2
+    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
+    subs    ip, r2, #32                 @  ip<- r2 - 32
+    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
+    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
+    bx      lr
+
diff --git a/vm/compiler/template/armv5te/TemplateOpList.h b/vm/compiler/template/armv5te/TemplateOpList.h
new file mode 100644
index 0000000..39cd07a
--- /dev/null
+++ b/vm/compiler/template/armv5te/TemplateOpList.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.
+ */
+
+/*
+ * Dalvik opcode list that uses additional templates to complete JIT execution.
+ */
+#ifndef JIT_TEMPLATE
+#define JIT_TEMPLATE(X)
+#endif
+
+JIT_TEMPLATE(CMP_LONG)
+JIT_TEMPLATE(RETURN)
+JIT_TEMPLATE(INVOKE_METHOD_NO_OPT)
+JIT_TEMPLATE(INVOKE_METHOD_CHAIN)
+JIT_TEMPLATE(INVOKE_METHOD_PREDICTED_CHAIN)
+JIT_TEMPLATE(INVOKE_METHOD_NATIVE)
+JIT_TEMPLATE(CMPG_DOUBLE)
+JIT_TEMPLATE(CMPL_DOUBLE)
+JIT_TEMPLATE(CMPG_FLOAT)
+JIT_TEMPLATE(CMPL_FLOAT)
+JIT_TEMPLATE(MUL_LONG)
+JIT_TEMPLATE(SHL_LONG)
+JIT_TEMPLATE(SHR_LONG)
+JIT_TEMPLATE(USHR_LONG)
diff --git a/vm/compiler/template/armv5te/footer.S b/vm/compiler/template/armv5te/footer.S
new file mode 100644
index 0000000..3b0b149
--- /dev/null
+++ b/vm/compiler/template/armv5te/footer.S
@@ -0,0 +1,61 @@
+/*
+ * ===========================================================================
+ *  Common subroutines and data
+ * ===========================================================================
+ */
+
+    .text
+    .align  2
+.LinvokeNative:
+    @ Prep for the native call
+    @ r1 = newFP, r0 = methodToCall
+    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
+    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
+    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
+    str     r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
+                                        @ newFp->localRefCookie=top
+    mov     r9, r3                      @ r9<- glue->self (preserve)
+    SAVEAREA_FROM_FP(r10, r1)           @ r10<- new stack save area
+
+    mov     r2, r0                      @ r2<- methodToCall
+    mov     r0, r1                      @ r0<- newFP
+    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
+
+    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
+
+    @ native return; r9=self, r10=newSaveArea
+    @ equivalent to dvmPopJniLocals
+    ldr     r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
+    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
+    ldr     r1, [r9, #offThread_exception] @ check for exception
+    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
+    cmp     r1, #0                      @ null?
+    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
+    bne     .LhandleException             @ no, handle exception
+    bx      r2
+
+/* NOTE - this path can be exercised if the JIT threshold is set to 5 */
+.LhandleException:
+    ldr     r0, .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
+
+    .align  2
+.LdvmAsmInstructionStart:
+    .word   dvmAsmInstructionStart
+.LdvmJitToInterpNoChain:
+    .word   dvmJitToInterpNoChain
+.LdvmMterpStdBail:
+    .word   dvmMterpStdBail
+.LdvmMterpCommonExceptionThrown:
+    .word   dvmMterpCommonExceptionThrown
+.L__aeabi_cdcmple:
+    .word   __aeabi_cdcmple
+.L__aeabi_cfcmple:
+    .word   __aeabi_cfcmple
+
+    .global dmvCompilerTemplateEnd
+dmvCompilerTemplateEnd:
+
+#endif /* WITH_JIT */
diff --git a/vm/compiler/template/armv5te/header.S b/vm/compiler/template/armv5te/header.S
new file mode 100644
index 0000000..9651032
--- /dev/null
+++ b/vm/compiler/template/armv5te/header.S
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined(WITH_JIT)
+
+/*
+ * ARMv5 definitions and declarations.
+ */
+
+/*
+ARM EABI general notes:
+
+r0-r3 hold first 4 args to a method; they are not preserved across method calls
+r4-r8 are available for general use
+r9 is given special treatment in some situations, but not for us
+r10 (sl) seems to be generally available
+r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
+r12 (ip) is scratch -- not preserved across method calls
+r13 (sp) should be managed carefully in case a signal arrives
+r14 (lr) must be preserved
+r15 (pc) can be tinkered with directly
+
+r0 holds returns of <= 4 bytes
+r0-r1 hold returns of 8 bytes, low word in r0
+
+Callee must save/restore r4+ (except r12) if it modifies them.
+
+Stack is "full descending".  Only the arguments that don't fit in the first 4
+registers are placed on the stack.  "sp" points at the first stacked argument
+(i.e. the 5th arg).
+
+VFP: single-precision results in s0, double-precision results in d0.
+
+In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
+64-bit quantities (long long, double) must be 64-bit aligned.
+*/
+
+/*
+JIT and ARM notes:
+
+The following registers have fixed assignments:
+
+  reg nick      purpose
+  r5  rFP       interpreted frame pointer, used for accessing locals and args
+  r6  rGLUE     MterpGlue pointer
+
+The following registers have fixed assignments in mterp but are scratch
+registers in compiled code
+
+  reg nick      purpose
+  r4  rPC       interpreted program counter, used for fetching instructions
+  r7  rINST     first 16-bit code unit of current instruction
+  r8  rIBASE    interpreted instruction base pointer, used for computed goto
+
+Macros are provided for common operations.  Each macro MUST emit only
+one instruction to make instruction-counting easier.  They MUST NOT alter
+unspecified registers or condition codes.
+*/
+
+/* single-purpose registers, given names for clarity */
+#define rPC     r4
+#define rFP     r5
+#define rGLUE   r6
+#define rINST   r7
+#define rIBASE  r8
+
+/*
+ * Given a frame pointer, find the stack save area.
+ *
+ * In C this is "((StackSaveArea*)(_fp) -1)".
+ */
+#define SAVEAREA_FROM_FP(_reg, _fpreg) \
+    sub     _reg, _fpreg, #sizeofStackSaveArea
+
+/*
+ * This is a #include, not a %include, because we want the C pre-processor
+ * to expand the macros into assembler assignment statements.
+ */
+#include "../../../mterp/common/asm-constants.h"
+
diff --git a/vm/compiler/template/armv5te/platform.S b/vm/compiler/template/armv5te/platform.S
new file mode 100644
index 0000000..b960a93
--- /dev/null
+++ b/vm/compiler/template/armv5te/platform.S
@@ -0,0 +1,16 @@
+/*
+ * ===========================================================================
+ *  CPU-version-specific defines
+ * ===========================================================================
+ */
+
+/*
+ * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
+ * Jump to subroutine.
+ *
+ * May modify IP and LR.
+ */
+.macro  LDR_PC_LR source
+    mov     lr, pc
+    ldr     pc, \source
+.endm
diff --git a/vm/compiler/template/armv7-a/TemplateOpList.h b/vm/compiler/template/armv7-a/TemplateOpList.h
new file mode 100644
index 0000000..c95163c
--- /dev/null
+++ b/vm/compiler/template/armv7-a/TemplateOpList.h
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+/*
+ * Dalvik opcode list that uses additional templates to complete JIT execution.
+ */
+#ifndef JIT_TEMPLATE
+#define JIT_TEMPLATE(X)
+#endif
+
+JIT_TEMPLATE(CMP_LONG)
+JIT_TEMPLATE(RETURN)
+JIT_TEMPLATE(INVOKE_METHOD_NO_OPT)
+JIT_TEMPLATE(INVOKE_METHOD_CHAIN)
+JIT_TEMPLATE(INVOKE_METHOD_PREDICTED_CHAIN)
+JIT_TEMPLATE(INVOKE_METHOD_NATIVE)
+JIT_TEMPLATE(MUL_LONG)
+JIT_TEMPLATE(SHL_LONG)
+JIT_TEMPLATE(SHR_LONG)
+JIT_TEMPLATE(USHR_LONG)
+JIT_TEMPLATE(ADD_FLOAT_VFP)
+JIT_TEMPLATE(SUB_FLOAT_VFP)
+JIT_TEMPLATE(MUL_FLOAT_VFP)
+JIT_TEMPLATE(DIV_FLOAT_VFP)
+JIT_TEMPLATE(ADD_DOUBLE_VFP)
+JIT_TEMPLATE(SUB_DOUBLE_VFP)
+JIT_TEMPLATE(MUL_DOUBLE_VFP)
+JIT_TEMPLATE(DIV_DOUBLE_VFP)
+JIT_TEMPLATE(DOUBLE_TO_FLOAT_VFP)
+JIT_TEMPLATE(DOUBLE_TO_INT_VFP)
+JIT_TEMPLATE(FLOAT_TO_DOUBLE_VFP)
+JIT_TEMPLATE(FLOAT_TO_INT_VFP)
+JIT_TEMPLATE(INT_TO_DOUBLE_VFP)
+JIT_TEMPLATE(INT_TO_FLOAT_VFP)
+JIT_TEMPLATE(CMPG_DOUBLE_VFP)
+JIT_TEMPLATE(CMPL_DOUBLE_VFP)
+JIT_TEMPLATE(CMPG_FLOAT_VFP)
+JIT_TEMPLATE(CMPL_FLOAT_VFP)
+JIT_TEMPLATE(SQRT_DOUBLE_VFP)
diff --git a/vm/compiler/template/config-armv5te b/vm/compiler/template/config-armv5te
new file mode 100644
index 0000000..668df1b
--- /dev/null
+++ b/vm/compiler/template/config-armv5te
@@ -0,0 +1,45 @@
+# 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.
+
+#
+# Configuration for ARMv5TE architecture targets.
+#
+
+# file header and basic definitions
+#import c/header.c
+import armv5te/header.S
+
+# C pre-processor defines for stub C instructions
+#import cstubs/stubdefs.c
+
+# highly-platform-specific defs
+import armv5te/platform.S
+
+# common defs for the C helpers; include this before the instruction handlers
+#import c/opcommon.c
+
+# opcode list; argument to op-start is default directory
+op-start armv5te
+
+op-end
+
+# "helper" code for C; include if you use any of the C stubs (this generates
+# object code, so it's normally excluded)
+##import c/gotoTargets.c
+
+# end of defs; include this when cstubs/stubdefs.c is included
+#import cstubs/enddefs.c
+
+# common subroutines for asm
+import armv5te/footer.S
diff --git a/vm/compiler/template/config-armv5te-vfp b/vm/compiler/template/config-armv5te-vfp
new file mode 100644
index 0000000..628e75f
--- /dev/null
+++ b/vm/compiler/template/config-armv5te-vfp
@@ -0,0 +1,56 @@
+
+# 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.
+
+#
+# Configuration for ARMv5TE architecture targets.
+#
+
+# file header and basic definitions
+#import c/header.c
+import armv5te/header.S
+
+# C pre-processor defines for stub C instructions
+#import cstubs/stubdefs.c
+
+# highly-platform-specific defs
+import armv5te/platform.S
+
+# common defs for the C helpers; include this before the instruction handlers
+#import c/opcommon.c
+
+# opcode list; argument to op-start is default directory
+op-start armv5te-vfp
+    op TEMPLATE_CMP_LONG armv5te
+    op TEMPLATE_INVOKE_METHOD_CHAIN armv5te
+    op TEMPLATE_INVOKE_METHOD_NATIVE armv5te
+    op TEMPLATE_INVOKE_METHOD_NO_OPT armv5te
+    op TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN armv5te
+    op TEMPLATE_MUL_LONG armv5te
+    op TEMPLATE_RETURN armv5te
+    op TEMPLATE_SHL_LONG armv5te
+    op TEMPLATE_SHR_LONG armv5te
+    op TEMPLATE_USHR_LONG armv5te
+
+op-end
+
+# "helper" code for C; include if you use any of the C stubs (this generates
+# object code, so it's normally excluded)
+##import c/gotoTargets.c
+
+# end of defs; include this when cstubs/stubdefs.c is included
+#import cstubs/enddefs.c
+
+# common subroutines for asm
+import armv5te/footer.S
diff --git a/vm/compiler/template/config-armv7-a b/vm/compiler/template/config-armv7-a
new file mode 100644
index 0000000..ecf0b3a
--- /dev/null
+++ b/vm/compiler/template/config-armv7-a
@@ -0,0 +1,56 @@
+
+# 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.
+
+#
+# Configuration for ARMv7-a architecture targets.
+#
+
+# file header and basic definitions
+#import c/header.c
+import armv5te/header.S
+
+# C pre-processor defines for stub C instructions
+#import cstubs/stubdefs.c
+
+# highly-platform-specific defs
+import armv5te/platform.S
+
+# common defs for the C helpers; include this before the instruction handlers
+#import c/opcommon.c
+
+# opcode list; argument to op-start is default directory
+op-start armv5te-vfp
+    op TEMPLATE_CMP_LONG armv5te
+    op TEMPLATE_INVOKE_METHOD_CHAIN armv5te
+    op TEMPLATE_INVOKE_METHOD_NATIVE armv5te
+    op TEMPLATE_INVOKE_METHOD_NO_OPT armv5te
+    op TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN armv5te
+    op TEMPLATE_MUL_LONG armv5te
+    op TEMPLATE_RETURN armv5te
+    op TEMPLATE_SHL_LONG armv5te
+    op TEMPLATE_SHR_LONG armv5te
+    op TEMPLATE_USHR_LONG armv5te
+
+op-end
+
+# "helper" code for C; include if you use any of the C stubs (this generates
+# object code, so it's normally excluded)
+##import c/gotoTargets.c
+
+# end of defs; include this when cstubs/stubdefs.c is included
+#import cstubs/enddefs.c
+
+# common subroutines for asm
+import armv5te/footer.S
diff --git a/vm/compiler/template/gen-template.py b/vm/compiler/template/gen-template.py
new file mode 100755
index 0000000..8a1ba0c
--- /dev/null
+++ b/vm/compiler/template/gen-template.py
@@ -0,0 +1,422 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2007 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.
+
+#
+# Using instructions from an architecture-specific config file, generate C
+# and assembly source files for the Dalvik JIT.
+#
+
+import sys, string, re, time
+from string import Template
+
+interp_defs_file = "TemplateOpList.h" # need opcode list
+
+handler_size_bits = -1000
+handler_size_bytes = -1000
+in_op_start = 0             # 0=not started, 1=started, 2=ended
+default_op_dir = None
+opcode_locations = {}
+asm_stub_text = []
+label_prefix = ".L"         # use ".L" to hide labels from gdb
+
+
+# Exception class.
+class DataParseError(SyntaxError):
+    "Failure when parsing data file"
+
+#
+# Set any omnipresent substitution values.
+#
+def getGlobalSubDict():
+    return { "handler_size_bits":handler_size_bits,
+             "handler_size_bytes":handler_size_bytes }
+
+#
+# Parse arch config file --
+# Set handler_size_bytes to the value of tokens[1], and handler_size_bits to
+# log2(handler_size_bytes).  Throws an exception if "bytes" is not a power
+# of two.
+#
+def setHandlerSize(tokens):
+    global handler_size_bits, handler_size_bytes
+    if len(tokens) != 2:
+        raise DataParseError("handler-size requires one argument")
+    if handler_size_bits != -1000:
+        raise DataParseError("handler-size may only be set once")
+
+    # compute log2(n), and make sure n is a power of 2
+    handler_size_bytes = bytes = int(tokens[1])
+    bits = -1
+    while bytes > 0:
+        bytes //= 2     # halve with truncating division
+        bits += 1
+
+    if handler_size_bytes == 0 or handler_size_bytes != (1 << bits):
+        raise DataParseError("handler-size (%d) must be power of 2 and > 0" \
+                % orig_bytes)
+    handler_size_bits = bits
+
+#
+# Parse arch config file --
+# Copy a file in to the C or asm output file.
+#
+def importFile(tokens):
+    if len(tokens) != 2:
+        raise DataParseError("import requires one argument")
+    source = tokens[1]
+    if source.endswith(".S"):
+        appendSourceFile(tokens[1], getGlobalSubDict(), asm_fp, None)
+    else:
+        raise DataParseError("don't know how to import %s (expecting .c/.S)"
+                % source)
+
+#
+# Parse arch config file --
+# Copy a file in to the C or asm output file.
+#
+def setAsmStub(tokens):
+    global asm_stub_text
+    if len(tokens) != 2:
+        raise DataParseError("import requires one argument")
+    try:
+        stub_fp = open(tokens[1])
+        asm_stub_text = stub_fp.readlines()
+    except IOError, err:
+        stub_fp.close()
+        raise DataParseError("unable to load asm-stub: %s" % str(err))
+    stub_fp.close()
+
+#
+# Parse arch config file --
+# Start of opcode list.
+#
+def opStart(tokens):
+    global in_op_start
+    global default_op_dir
+    if len(tokens) != 2:
+        raise DataParseError("opStart takes a directory name argument")
+    if in_op_start != 0:
+        raise DataParseError("opStart can only be specified once")
+    default_op_dir = tokens[1]
+    in_op_start = 1
+
+#
+# Parse arch config file --
+# Set location of a single opcode's source file.
+#
+def opEntry(tokens):
+    #global opcode_locations
+    if len(tokens) != 3:
+        raise DataParseError("op requires exactly two arguments")
+    if in_op_start != 1:
+        raise DataParseError("op statements must be between opStart/opEnd")
+    try:
+        index = opcodes.index(tokens[1])
+    except ValueError:
+        raise DataParseError("unknown opcode %s" % tokens[1])
+    opcode_locations[tokens[1]] = tokens[2]
+
+#
+# Parse arch config file --
+# End of opcode list; emit instruction blocks.
+#
+def opEnd(tokens):
+    global in_op_start
+    if len(tokens) != 1:
+        raise DataParseError("opEnd takes no arguments")
+    if in_op_start != 1:
+        raise DataParseError("opEnd must follow opStart, and only appear once")
+    in_op_start = 2
+
+    loadAndEmitOpcodes()
+
+
+#
+# Extract an ordered list of instructions from the VM sources.  We use the
+# "goto table" definition macro, which has exactly 256 entries.
+#
+def getOpcodeList():
+    opcodes = []
+    opcode_fp = open("%s/%s" % (target_arch, interp_defs_file))
+    opcode_re = re.compile(r"^JIT_TEMPLATE\((\w+)\)", re.DOTALL)
+    for line in opcode_fp:
+        match = opcode_re.match(line)
+        if not match:
+            continue
+        opcodes.append("TEMPLATE_" + match.group(1))
+    opcode_fp.close()
+
+    return opcodes
+
+
+#
+# Load and emit opcodes for all 256 instructions.
+#
+def loadAndEmitOpcodes():
+    sister_list = []
+
+    # point dvmAsmInstructionStart at the first handler or stub
+    asm_fp.write("\n    .global dvmCompilerTemplateStart\n")
+    asm_fp.write("    .type   dvmCompilerTemplateStart, %function\n")
+    asm_fp.write("    .text\n\n")
+    asm_fp.write("dvmCompilerTemplateStart:\n\n")
+
+    for i in xrange(len(opcodes)):
+        op = opcodes[i]
+
+        if opcode_locations.has_key(op):
+            location = opcode_locations[op]
+        else:
+            location = default_op_dir
+
+        loadAndEmitAsm(location, i, sister_list)
+
+    # Use variable sized handlers now
+    # asm_fp.write("\n    .balign %d\n" % handler_size_bytes)
+    asm_fp.write("    .size   dvmCompilerTemplateStart, .-dvmCompilerTemplateStart\n")
+
+#
+# Load an assembly fragment and emit it.
+#
+def loadAndEmitAsm(location, opindex, sister_list):
+    op = opcodes[opindex]
+    source = "%s/%s.S" % (location, op)
+    dict = getGlobalSubDict()
+    dict.update({ "opcode":op, "opnum":opindex })
+    print " emit %s --> asm" % source
+
+    emitAsmHeader(asm_fp, dict)
+    appendSourceFile(source, dict, asm_fp, sister_list)
+
+#
+# Output the alignment directive and label for an assembly piece.
+#
+def emitAsmHeader(outfp, dict):
+    outfp.write("/* ------------------------------ */\n")
+    # The alignment directive ensures that the handler occupies
+    # at least the correct amount of space.  We don't try to deal
+    # with overflow here.
+    outfp.write("    .balign 4\n")
+    # Emit a label so that gdb will say the right thing.  We prepend an
+    # underscore so the symbol name doesn't clash with the OpCode enum.
+    template_name = "dvmCompiler_%(opcode)s" % dict
+    outfp.write("    .global %s\n" % template_name);
+    outfp.write("%s:\n" % template_name);
+
+#
+# Output a generic instruction stub that updates the "glue" struct and
+# calls the C implementation.
+#
+def emitAsmStub(outfp, dict):
+    emitAsmHeader(outfp, dict)
+    for line in asm_stub_text:
+        templ = Template(line)
+        outfp.write(templ.substitute(dict))
+
+#
+# Append the file specified by "source" to the open "outfp".  Each line will
+# be template-replaced using the substitution dictionary "dict".
+#
+# If the first line of the file starts with "%" it is taken as a directive.
+# A "%include" line contains a filename and, optionally, a Python-style
+# dictionary declaration with substitution strings.  (This is implemented
+# with recursion.)
+#
+# If "sister_list" is provided, and we find a line that contains only "&",
+# all subsequent lines from the file will be appended to sister_list instead
+# of copied to the output.
+#
+# This may modify "dict".
+#
+def appendSourceFile(source, dict, outfp, sister_list):
+    outfp.write("/* File: %s */\n" % source)
+    infp = open(source, "r")
+    in_sister = False
+    for line in infp:
+        if line.startswith("%include"):
+            # Parse the "include" line
+            tokens = line.strip().split(' ', 2)
+            if len(tokens) < 2:
+                raise DataParseError("malformed %%include in %s" % source)
+
+            alt_source = tokens[1].strip("\"")
+            if alt_source == source:
+                raise DataParseError("self-referential %%include in %s"
+                        % source)
+
+            new_dict = dict.copy()
+            if len(tokens) == 3:
+                new_dict.update(eval(tokens[2]))
+            #print " including src=%s dict=%s" % (alt_source, new_dict)
+            appendSourceFile(alt_source, new_dict, outfp, sister_list)
+            continue
+
+        elif line.startswith("%default"):
+            # copy keywords into dictionary
+            tokens = line.strip().split(' ', 1)
+            if len(tokens) < 2:
+                raise DataParseError("malformed %%default in %s" % source)
+            defaultValues = eval(tokens[1])
+            for entry in defaultValues:
+                dict.setdefault(entry, defaultValues[entry])
+            continue
+
+        elif line.startswith("%verify"):
+            # more to come, someday
+            continue
+
+        elif line.startswith("%break") and sister_list != None:
+            # allow more than one %break, ignoring all following the first
+            if not in_sister:
+                in_sister = True
+                sister_list.append("\n/* continuation for %(opcode)s */\n"%dict)
+            continue
+
+        # perform keyword substitution if a dictionary was provided
+        if dict != None:
+            templ = Template(line)
+            try:
+                subline = templ.substitute(dict)
+            except KeyError, err:
+                raise DataParseError("keyword substitution failed in %s: %s"
+                        % (source, str(err)))
+            except:
+                print "ERROR: substitution failed: " + line
+                raise
+        else:
+            subline = line
+
+        # write output to appropriate file
+        if in_sister:
+            sister_list.append(subline)
+        else:
+            outfp.write(subline)
+    outfp.write("\n")
+    infp.close()
+
+#
+# Emit a C-style section header comment.
+#
+def emitSectionComment(str, fp):
+    equals = "========================================" \
+             "==================================="
+
+    fp.write("\n/*\n * %s\n *  %s\n * %s\n */\n" %
+        (equals, str, equals))
+
+
+#
+# ===========================================================================
+# "main" code
+#
+
+#
+# Check args.
+#
+if len(sys.argv) != 3:
+    print "Usage: %s target-arch output-dir" % sys.argv[0]
+    sys.exit(2)
+
+target_arch = sys.argv[1]
+output_dir = sys.argv[2]
+
+#
+# Extract opcode list.
+#
+opcodes = getOpcodeList()
+#for op in opcodes:
+#    print "  %s" % op
+
+#
+# Open config file.
+#
+try:
+    config_fp = open("config-%s" % target_arch)
+except:
+    print "Unable to open config file 'config-%s'" % target_arch
+    sys.exit(1)
+
+#
+# Open and prepare output files.
+#
+try:
+    asm_fp = open("%s/CompilerTemplateAsm-%s.S" % (output_dir, target_arch), "w")
+except:
+    print "Unable to open output files"
+    print "Make sure directory '%s' exists and existing files are writable" \
+            % output_dir
+    # Ideally we'd remove the files to avoid confusing "make", but if they
+    # failed to open we probably won't be able to remove them either.
+    sys.exit(1)
+
+print "Generating %s" % (asm_fp.name)
+
+file_header = """/*
+ * This file was generated automatically by gen-template.py for '%s'.
+ *
+ * --> DO NOT EDIT <--
+ */
+
+""" % (target_arch)
+
+asm_fp.write(file_header)
+
+#
+# Process the config file.
+#
+failed = False
+try:
+    for line in config_fp:
+        line = line.strip()         # remove CRLF, leading spaces
+        tokens = line.split(' ')    # tokenize
+        #print "%d: %s" % (len(tokens), tokens)
+        if len(tokens[0]) == 0:
+            #print "  blank"
+            pass
+        elif tokens[0][0] == '#':
+            #print "  comment"
+            pass
+        else:
+            if tokens[0] == "handler-size":
+                setHandlerSize(tokens)
+            elif tokens[0] == "import":
+                importFile(tokens)
+            elif tokens[0] == "asm-stub":
+                setAsmStub(tokens)
+            elif tokens[0] == "op-start":
+                opStart(tokens)
+            elif tokens[0] == "op-end":
+                opEnd(tokens)
+            elif tokens[0] == "op":
+                opEntry(tokens)
+            else:
+                raise DataParseError, "unrecognized command '%s'" % tokens[0]
+except DataParseError, err:
+    print "Failed: " + str(err)
+    # TODO: remove output files so "make" doesn't get confused
+    failed = True
+    asm_fp.close()
+    c_fp = asm_fp = None
+
+config_fp.close()
+
+#
+# Done!
+#
+if asm_fp:
+    asm_fp.close()
+
+sys.exit(failed)
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S b/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
new file mode 100644
index 0000000..0c433a1
--- /dev/null
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
@@ -0,0 +1,1064 @@
+/*
+ * This file was generated automatically by gen-template.py for 'armv5te-vfp'.
+ *
+ * --> DO NOT EDIT <--
+ */
+
+/* File: armv5te/header.S */
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined(WITH_JIT)
+
+/*
+ * ARMv5 definitions and declarations.
+ */
+
+/*
+ARM EABI general notes:
+
+r0-r3 hold first 4 args to a method; they are not preserved across method calls
+r4-r8 are available for general use
+r9 is given special treatment in some situations, but not for us
+r10 (sl) seems to be generally available
+r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
+r12 (ip) is scratch -- not preserved across method calls
+r13 (sp) should be managed carefully in case a signal arrives
+r14 (lr) must be preserved
+r15 (pc) can be tinkered with directly
+
+r0 holds returns of <= 4 bytes
+r0-r1 hold returns of 8 bytes, low word in r0
+
+Callee must save/restore r4+ (except r12) if it modifies them.
+
+Stack is "full descending".  Only the arguments that don't fit in the first 4
+registers are placed on the stack.  "sp" points at the first stacked argument
+(i.e. the 5th arg).
+
+VFP: single-precision results in s0, double-precision results in d0.
+
+In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
+64-bit quantities (long long, double) must be 64-bit aligned.
+*/
+
+/*
+JIT and ARM notes:
+
+The following registers have fixed assignments:
+
+  reg nick      purpose
+  r5  rFP       interpreted frame pointer, used for accessing locals and args
+  r6  rGLUE     MterpGlue pointer
+
+The following registers have fixed assignments in mterp but are scratch
+registers in compiled code
+
+  reg nick      purpose
+  r4  rPC       interpreted program counter, used for fetching instructions
+  r7  rINST     first 16-bit code unit of current instruction
+  r8  rIBASE    interpreted instruction base pointer, used for computed goto
+
+Macros are provided for common operations.  Each macro MUST emit only
+one instruction to make instruction-counting easier.  They MUST NOT alter
+unspecified registers or condition codes.
+*/
+
+/* single-purpose registers, given names for clarity */
+#define rPC     r4
+#define rFP     r5
+#define rGLUE   r6
+#define rINST   r7
+#define rIBASE  r8
+
+/*
+ * Given a frame pointer, find the stack save area.
+ *
+ * In C this is "((StackSaveArea*)(_fp) -1)".
+ */
+#define SAVEAREA_FROM_FP(_reg, _fpreg) \
+    sub     _reg, _fpreg, #sizeofStackSaveArea
+
+/*
+ * This is a #include, not a %include, because we want the C pre-processor
+ * to expand the macros into assembler assignment statements.
+ */
+#include "../../../mterp/common/asm-constants.h"
+
+
+/* File: armv5te/platform.S */
+/*
+ * ===========================================================================
+ *  CPU-version-specific defines
+ * ===========================================================================
+ */
+
+/*
+ * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
+ * Jump to subroutine.
+ *
+ * May modify IP and LR.
+ */
+.macro  LDR_PC_LR source
+    mov     lr, pc
+    ldr     pc, \source
+.endm
+
+
+    .global dvmCompilerTemplateStart
+    .type   dvmCompilerTemplateStart, %function
+    .text
+
+dvmCompilerTemplateStart:
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_CMP_LONG
+dvmCompiler_TEMPLATE_CMP_LONG:
+/* File: armv5te/TEMPLATE_CMP_LONG.S */
+    /*
+     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
+     * register based on the results of the comparison.
+     *
+     * We load the full values with LDM, but in practice many values could
+     * be resolved by only looking at the high word.  This could be made
+     * faster or slower by splitting the LDM into a pair of LDRs.
+     *
+     * If we just wanted to set condition flags, we could do this:
+     *  subs    ip, r0, r2
+     *  sbcs    ip, r1, r3
+     *  subeqs  ip, r0, r2
+     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
+     * integer value, which we can do with 2 conditional mov/mvn instructions
+     * (set 1, set -1; if they're equal we already have 0 in ip), giving
+     * us a constant 5-cycle path plus a branch at the end to the
+     * instruction epilogue code.  The multi-compare approach below needs
+     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
+     * in the worst case (the 64-bit values are equal).
+     */
+    /* cmp-long vAA, vBB, vCC */
+    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
+    blt     .LTEMPLATE_CMP_LONG_less            @ signed compare on high part
+    bgt     .LTEMPLATE_CMP_LONG_greater
+    subs    r0, r0, r2                  @ r0<- r0 - r2
+    bxeq     lr
+    bhi     .LTEMPLATE_CMP_LONG_greater         @ unsigned compare on low part
+.LTEMPLATE_CMP_LONG_less:
+    mvn     r0, #0                      @ r0<- -1
+    bx      lr
+.LTEMPLATE_CMP_LONG_greater:
+    mov     r0, #1                      @ r0<- 1
+    bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_RETURN
+dvmCompiler_TEMPLATE_RETURN:
+/* File: armv5te/TEMPLATE_RETURN.S */
+    /*
+     * Unwind a frame from the Dalvik stack for compiled OP_RETURN_XXX.
+     * If the stored value in returnAddr
+     * is non-zero, the caller is compiled by the JIT thus return to the
+     * address in the code cache following the invoke instruction. Otherwise
+     * return to the special dvmJitToInterpNoChain entry point.
+     */
+    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
+    ldr     r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame
+    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+    ldr     rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc
+    ldr     r9,  [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
+    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?
+    beq     1f                          @ bail to interpreter
+    ldr     r0, .LdvmJitToInterpNoChain @ defined in footer.S
+    mov     rFP, r10                    @ publish new FP
+    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
+    ldr     r8, [r8]                    @ r8<- suspendCount
+
+    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
+    ldr     r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex
+    str     rFP, [r3, #offThread_curFrame] @ self->curFrame = fp
+    add     rPC, rPC, #6                @ publish new rPC (advance 6 bytes)
+    str     r1, [rGLUE, #offGlue_methodClassDex]
+    cmp     r8, #0                      @ check the suspendCount
+    movne   r9, #0                      @ clear the chaining cell address
+    cmp     r9, #0                      @ chaining cell exists?
+    blxne   r9                          @ jump to the chaining cell
+    mov     pc, r0                      @ callsite is interpreted
+1:
+    stmia   rGLUE, {rPC, rFP}           @ SAVE_PC_FP_TO_GLUE()
+    ldr     r2, .LdvmMterpStdBail       @ defined in footer.S
+    mov     r1, #0                      @ changeInterp = false
+    mov     r0, rGLUE                   @ Expecting rGLUE in r0
+    blx     r2                          @ exit the interpreter
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT
+dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */
+    /*
+     * For polymorphic callsites - setup the Dalvik frame and load Dalvik PC
+     * into rPC then jump to dvmJitToInterpNoChain to dispatch the
+     * runtime-resolved callee.
+     */
+    @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
+    ldrh    r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
+    ldrh    r2, [r0, #offMethod_outsSize]  @ r2<- methodToCall->outsSize
+    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
+    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+    add     r3, r1, #1  @ Thumb addr is odd
+    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
+    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
+    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
+    sub     r10, r10, r2, lsl #2        @ r10<- bottom (newsave - outsSize)
+    ldr     r8, [r8]                    @ r3<- suspendCount (int)
+    cmp     r10, r9                     @ bottom < interpStackEnd?
+    bxlt    lr                          @ return to raise stack overflow excep.
+    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
+    ldr     r9, [r0, #offMethod_clazz]      @ r9<- method->clazz
+    ldr     r10, [r0, #offMethod_accessFlags] @ r10<- methodToCall->accessFlags
+    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
+    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- methodToCall->insns
+
+
+    @ set up newSaveArea
+    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
+    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
+    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
+    cmp     r8, #0                      @ suspendCount != 0
+    bxne    lr                          @ bail to the interpreter
+    tst     r10, #ACC_NATIVE
+    bne     .LinvokeNative
+
+    ldr     r10, .LdvmJitToInterpNoChain
+    ldr     r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
+    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
+
+    @ Update "glue" values for the new method
+    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
+    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
+    mov     rFP, r1                         @ fp = newFp
+    str     rFP, [r2, #offThread_curFrame]  @ self->curFrame = newFp
+
+    @ Start executing the callee
+    mov     pc, r10                         @ dvmJitToInterpNoChain
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN
+dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S */
+    /*
+     * For monomorphic callsite, setup the Dalvik frame and return to the
+     * Thumb code through the link register to transfer control to the callee
+     * method through a dedicated chaining cell.
+     */
+    @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
+    @ methodToCall is guaranteed to be non-native
+.LinvokeChain:
+    ldrh    r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
+    ldrh    r2, [r0, #offMethod_outsSize]  @ r2<- methodToCall->outsSize
+    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
+    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+    add     r3, r1, #1  @ Thumb addr is odd
+    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
+    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
+    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
+    add     r12, lr, #2                 @ setup the punt-to-interp address
+    sub     r10, r10, r2, lsl #2        @ r10<- bottom (newsave - outsSize)
+    ldr     r8, [r8]                    @ r3<- suspendCount (int)
+    cmp     r10, r9                     @ bottom < interpStackEnd?
+    bxlt    r12                         @ return to raise stack overflow excep.
+    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
+    ldr     r9, [r0, #offMethod_clazz]      @ r9<- method->clazz
+    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
+    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- methodToCall->insns
+
+
+    @ set up newSaveArea
+    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
+    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
+    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
+    cmp     r8, #0                      @ suspendCount != 0
+    bxne    r12                         @ bail to the interpreter
+
+    ldr     r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
+    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
+
+    @ Update "glue" values for the new method
+    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
+    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
+    mov     rFP, r1                         @ fp = newFp
+    str     rFP, [r2, #offThread_curFrame]  @ self->curFrame = newFp
+
+    bx      lr                              @ return to the callee-chaining cell
+
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN
+dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */
+    /*
+     * For polymorphic callsite, check whether the cached class pointer matches
+     * the current one. If so setup the Dalvik frame and return to the
+     * Thumb code through the link register to transfer control to the callee
+     * method through a dedicated chaining cell.
+     *
+     * The predicted chaining cell is declared in ArmLIR.h with the
+     * following layout:
+     *
+     *  typedef struct PredictedChainingCell {
+     *      u4 branch;
+     *      const ClassObject *clazz;
+     *      const Method *method;
+     *      u4 counter;
+     *  } PredictedChainingCell;
+     *
+     * Upon returning to the callsite:
+     *    - lr  : to branch to the chaining cell
+     *    - lr+2: to punt to the interpreter
+     *    - lr+4: to fully resolve the callee and may rechain.
+     *            r3 <- class
+     *            r9 <- counter
+     */
+    @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite
+    ldr     r3, [r0, #offObject_clazz]  @ r3 <- this->class
+    ldr     r8, [r2, #4]    @ r8 <- predictedChainCell->clazz
+    ldr     r0, [r2, #8]    @ r0 <- predictedChainCell->method
+    ldr     r9, [r2, #12]   @ r9 <- predictedChainCell->counter
+    cmp     r3, r8          @ predicted class == actual class?
+    beq     .LinvokeChain   @ predicted chain is valid
+    ldr     r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable
+    sub     r1, r9, #1      @ count--
+    str     r1, [r2, #12]   @ write back to PredictedChainingCell->counter
+    add     lr, lr, #4      @ return to fully-resolve landing pad
+    /*
+     * r1 <- count
+     * r2 <- &predictedChainCell
+     * r3 <- this->class
+     * r4 <- dPC
+     * r7 <- this->class->vtable
+     */
+    bx      lr
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE
+dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S */
+    @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
+    ldrh    r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
+    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
+    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+    add     r3, r1, #1  @ Thumb addr is odd
+    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
+    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
+    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
+    ldr     r8, [r8]                    @ r3<- suspendCount (int)
+    cmp     r10, r9                     @ bottom < interpStackEnd?
+    bxlt    lr                          @ return to raise stack overflow excep.
+    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
+    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
+    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- methodToCall->insns
+
+
+    @ set up newSaveArea
+    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
+    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
+    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
+    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
+    cmp     r8, #0                      @ suspendCount != 0
+    ldr     r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc
+    bxne    lr                          @ bail to the interpreter
+
+    @ go ahead and transfer control to the native code
+    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
+    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
+    str     r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
+                                        @ newFp->localRefCookie=top
+    mov     r9, r3                      @ r9<- glue->self (preserve)
+    SAVEAREA_FROM_FP(r10, r1)           @ r10<- new stack save area
+
+    mov     r2, r0                      @ r2<- methodToCall
+    mov     r0, r1                      @ r0<- newFP
+    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
+
+    blx     r8                          @ off to the native code
+
+    @ native return; r9=self, r10=newSaveArea
+    @ equivalent to dvmPopJniLocals
+    ldr     r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
+    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
+    ldr     r1, [r9, #offThread_exception] @ check for exception
+    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
+    cmp     r1, #0                      @ null?
+    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
+    bne     .LhandleException             @ no, handle exception
+    bx      r2
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_MUL_LONG
+dvmCompiler_TEMPLATE_MUL_LONG:
+/* File: armv5te/TEMPLATE_MUL_LONG.S */
+    /*
+     * Signed 64-bit integer multiply.
+     *
+     * For JIT: op1 in r0/r1, op2 in r2/r3, return in r0/r1
+     *
+     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
+     *        WX
+     *      x YZ
+     *  --------
+     *     ZW ZX
+     *  YW YX
+     *
+     * The low word of the result holds ZX, the high word holds
+     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
+     * it doesn't fit in the low 64 bits.
+     *
+     * Unlike most ARM math operations, multiply instructions have
+     * restrictions on using the same register more than once (Rd and Rm
+     * cannot be the same).
+     */
+    /* mul-long vAA, vBB, vCC */
+    mul     ip, r2, r1                  @  ip<- ZxW
+    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
+    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
+    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
+    mov     r0,r9
+    mov     r1,r10
+    bx      lr
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_SHL_LONG
+dvmCompiler_TEMPLATE_SHL_LONG:
+/* File: armv5te/TEMPLATE_SHL_LONG.S */
+    /*
+     * Long integer shift.  This is different from the generic 32/64-bit
+     * binary operations because vAA/vBB are 64-bit but vCC (the shift
+     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
+     * 6 bits.
+     */
+    /* shl-long vAA, vBB, vCC */
+    and     r2, r2, #63                 @ r2<- r2 & 0x3f
+    mov     r1, r1, asl r2              @  r1<- r1 << r2
+    rsb     r3, r2, #32                 @  r3<- 32 - r2
+    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
+    subs    ip, r2, #32                 @  ip<- r2 - 32
+    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
+    mov     r0, r0, asl r2              @  r0<- r0 << r2
+    bx      lr
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_SHR_LONG
+dvmCompiler_TEMPLATE_SHR_LONG:
+/* File: armv5te/TEMPLATE_SHR_LONG.S */
+    /*
+     * Long integer shift.  This is different from the generic 32/64-bit
+     * binary operations because vAA/vBB are 64-bit but vCC (the shift
+     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
+     * 6 bits.
+     */
+    /* shr-long vAA, vBB, vCC */
+    and     r2, r2, #63                 @ r0<- r0 & 0x3f
+    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
+    rsb     r3, r2, #32                 @  r3<- 32 - r2
+    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
+    subs    ip, r2, #32                 @  ip<- r2 - 32
+    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
+    mov     r1, r1, asr r2              @  r1<- r1 >> r2
+    bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_USHR_LONG
+dvmCompiler_TEMPLATE_USHR_LONG:
+/* File: armv5te/TEMPLATE_USHR_LONG.S */
+    /*
+     * Long integer shift.  This is different from the generic 32/64-bit
+     * binary operations because vAA/vBB are 64-bit but vCC (the shift
+     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
+     * 6 bits.
+     */
+    /* ushr-long vAA, vBB, vCC */
+    and     r2, r2, #63                 @ r0<- r0 & 0x3f
+    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
+    rsb     r3, r2, #32                 @  r3<- 32 - r2
+    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
+    subs    ip, r2, #32                 @  ip<- r2 - 32
+    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
+    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
+    bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_ADD_FLOAT_VFP
+dvmCompiler_TEMPLATE_ADD_FLOAT_VFP:
+/* File: armv5te-vfp/TEMPLATE_ADD_FLOAT_VFP.S */
+/* File: armv5te-vfp/fbinop.S */
+    /*
+     * Generic 32-bit floating point operation.  Provide an "instr" line that
+     * specifies an instruction that performs s2 = s0 op s1.
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = op1 address
+     *     r2 = op2 address
+     */
+     flds    s0,[r1]
+     flds    s1,[r2]
+     fadds   s2, s0, s1
+     fsts    s2,[r0]
+     bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_SUB_FLOAT_VFP
+dvmCompiler_TEMPLATE_SUB_FLOAT_VFP:
+/* File: armv5te-vfp/TEMPLATE_SUB_FLOAT_VFP.S */
+/* File: armv5te-vfp/fbinop.S */
+    /*
+     * Generic 32-bit floating point operation.  Provide an "instr" line that
+     * specifies an instruction that performs s2 = s0 op s1.
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = op1 address
+     *     r2 = op2 address
+     */
+     flds    s0,[r1]
+     flds    s1,[r2]
+     fsubs   s2, s0, s1
+     fsts    s2,[r0]
+     bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_MUL_FLOAT_VFP
+dvmCompiler_TEMPLATE_MUL_FLOAT_VFP:
+/* File: armv5te-vfp/TEMPLATE_MUL_FLOAT_VFP.S */
+/* File: armv5te-vfp/fbinop.S */
+    /*
+     * Generic 32-bit floating point operation.  Provide an "instr" line that
+     * specifies an instruction that performs s2 = s0 op s1.
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = op1 address
+     *     r2 = op2 address
+     */
+     flds    s0,[r1]
+     flds    s1,[r2]
+     fmuls   s2, s0, s1
+     fsts    s2,[r0]
+     bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_DIV_FLOAT_VFP
+dvmCompiler_TEMPLATE_DIV_FLOAT_VFP:
+/* File: armv5te-vfp/TEMPLATE_DIV_FLOAT_VFP.S */
+/* File: armv5te-vfp/fbinop.S */
+    /*
+     * Generic 32-bit floating point operation.  Provide an "instr" line that
+     * specifies an instruction that performs s2 = s0 op s1.
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = op1 address
+     *     r2 = op2 address
+     */
+     flds    s0,[r1]
+     flds    s1,[r2]
+     fdivs   s2, s0, s1
+     fsts    s2,[r0]
+     bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP
+dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP:
+/* File: armv5te-vfp/TEMPLATE_ADD_DOUBLE_VFP.S */
+/* File: armv5te-vfp/fbinopWide.S */
+    /*
+     * Generic 64-bit floating point operation.  Provide an "instr" line that
+     * specifies an instruction that performs s2 = s0 op s1.
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = op1 address
+     *     r2 = op2 address
+     */
+     fldd    d0,[r1]
+     fldd    d1,[r2]
+     faddd   d2, d0, d1
+     fstd    d2,[r0]
+     bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP
+dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP:
+/* File: armv5te-vfp/TEMPLATE_SUB_DOUBLE_VFP.S */
+/* File: armv5te-vfp/fbinopWide.S */
+    /*
+     * Generic 64-bit floating point operation.  Provide an "instr" line that
+     * specifies an instruction that performs s2 = s0 op s1.
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = op1 address
+     *     r2 = op2 address
+     */
+     fldd    d0,[r1]
+     fldd    d1,[r2]
+     fsubd   d2, d0, d1
+     fstd    d2,[r0]
+     bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP
+dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP:
+/* File: armv5te-vfp/TEMPLATE_MUL_DOUBLE_VFP.S */
+/* File: armv5te-vfp/fbinopWide.S */
+    /*
+     * Generic 64-bit floating point operation.  Provide an "instr" line that
+     * specifies an instruction that performs s2 = s0 op s1.
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = op1 address
+     *     r2 = op2 address
+     */
+     fldd    d0,[r1]
+     fldd    d1,[r2]
+     fmuld   d2, d0, d1
+     fstd    d2,[r0]
+     bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP
+dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP:
+/* File: armv5te-vfp/TEMPLATE_DIV_DOUBLE_VFP.S */
+/* File: armv5te-vfp/fbinopWide.S */
+    /*
+     * Generic 64-bit floating point operation.  Provide an "instr" line that
+     * specifies an instruction that performs s2 = s0 op s1.
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = op1 address
+     *     r2 = op2 address
+     */
+     fldd    d0,[r1]
+     fldd    d1,[r2]
+     fdivd   d2, d0, d1
+     fstd    d2,[r0]
+     bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP
+dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP:
+/* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_FLOAT_VFP.S */
+/* File: armv5te-vfp/funopNarrower.S */
+    /*
+     * Generic 64bit-to-32bit floating point unary operation.  Provide an
+     * "instr" line that specifies an instruction that performs "s0 = op d0".
+     *
+     * For: double-to-int, double-to-float
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = src dalvik register address
+     */
+    /* unop vA, vB */
+    fldd    d0, [r1]                    @ d0<- vB
+    fcvtsd  s0, d0                              @ s0<- op d0
+    fsts    s0, [r0]                    @ vA<- s0
+    bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP
+dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP:
+/* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_INT_VFP.S */
+/* File: armv5te-vfp/funopNarrower.S */
+    /*
+     * Generic 64bit-to-32bit floating point unary operation.  Provide an
+     * "instr" line that specifies an instruction that performs "s0 = op d0".
+     *
+     * For: double-to-int, double-to-float
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = src dalvik register address
+     */
+    /* unop vA, vB */
+    fldd    d0, [r1]                    @ d0<- vB
+    ftosizd  s0, d0                              @ s0<- op d0
+    fsts    s0, [r0]                    @ vA<- s0
+    bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP
+dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP:
+/* File: armv5te-vfp/TEMPLATE_FLOAT_TO_DOUBLE_VFP.S */
+/* File: armv5te-vfp/funopWider.S */
+    /*
+     * Generic 32bit-to-64bit floating point unary operation.  Provide an
+     * "instr" line that specifies an instruction that performs "d0 = op s0".
+     *
+     * For: int-to-double, float-to-double
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = src dalvik register address
+     */
+    /* unop vA, vB */
+    flds    s0, [r1]                    @ s0<- vB
+    fcvtds  d0, s0                              @ d0<- op s0
+    fstd    d0, [r0]                    @ vA<- d0
+    bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP
+dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP:
+/* File: armv5te-vfp/TEMPLATE_FLOAT_TO_INT_VFP.S */
+/* File: armv5te-vfp/funop.S */
+    /*
+     * Generic 32bit-to-32bit floating point unary operation.  Provide an
+     * "instr" line that specifies an instruction that performs "s1 = op s0".
+     *
+     * For: float-to-int, int-to-float
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = src dalvik register address
+     */
+    /* unop vA, vB */
+    flds    s0, [r1]                    @ s0<- vB
+    ftosizs s1, s0                              @ s1<- op s0
+    fsts    s1, [r0]                    @ vA<- s1
+    bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP
+dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP:
+/* File: armv5te-vfp/TEMPLATE_INT_TO_DOUBLE_VFP.S */
+/* File: armv5te-vfp/funopWider.S */
+    /*
+     * Generic 32bit-to-64bit floating point unary operation.  Provide an
+     * "instr" line that specifies an instruction that performs "d0 = op s0".
+     *
+     * For: int-to-double, float-to-double
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = src dalvik register address
+     */
+    /* unop vA, vB */
+    flds    s0, [r1]                    @ s0<- vB
+    fsitod  d0, s0                              @ d0<- op s0
+    fstd    d0, [r0]                    @ vA<- d0
+    bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP
+dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP:
+/* File: armv5te-vfp/TEMPLATE_INT_TO_FLOAT_VFP.S */
+/* File: armv5te-vfp/funop.S */
+    /*
+     * Generic 32bit-to-32bit floating point unary operation.  Provide an
+     * "instr" line that specifies an instruction that performs "s1 = op s0".
+     *
+     * For: float-to-int, int-to-float
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = src dalvik register address
+     */
+    /* unop vA, vB */
+    flds    s0, [r1]                    @ s0<- vB
+    fsitos  s1, s0                              @ s1<- op s0
+    fsts    s1, [r0]                    @ vA<- s1
+    bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP
+dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP:
+/* File: armv5te-vfp/TEMPLATE_CMPG_DOUBLE_VFP.S */
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else {
+     *         return 1;
+     *     }
+     * }
+     *
+     * On entry:
+     *    r0 = &op1 [vBB]
+     *    r1 = &op2 [vCC]
+     */
+    /* op vAA, vBB, vCC */
+    fldd    d0, [r0]                    @ d0<- vBB
+    fldd    d1, [r1]                    @ d1<- vCC
+    fcmped  d0, d1                      @ compare (vBB, vCC)
+    mov     r0, #1                      @ r0<- 1 (default)
+    fmstat                              @ export status flags
+    mvnmi   r0, #0                      @ (less than) r0<- -1
+    moveq   r0, #0                      @ (equal) r0<- 0
+    bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP
+dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP:
+/* File: armv5te-vfp/TEMPLATE_CMPL_DOUBLE_VFP.S */
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else {
+     *         return -1;
+     *     }
+     * }
+     * On entry:
+     *    r0 = &op1 [vBB]
+     *    r1 = &op2 [vCC]
+     */
+    /* op vAA, vBB, vCC */
+    fldd    d0, [r0]                    @ d0<- vBB
+    fldd    d1, [r1]                    @ d1<- vCC
+    fcmped  d0, d1                      @ compare (vBB, vCC)
+    mvn     r0, #0                      @ r0<- -1 (default)
+    fmstat                              @ export status flags
+    movgt   r0, #1                      @ (greater than) r0<- 1
+    moveq   r0, #0                      @ (equal) r0<- 0
+    bx      lr
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP
+dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP:
+/* File: armv5te-vfp/TEMPLATE_CMPG_FLOAT_VFP.S */
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else {
+     *         return 1;
+     *     }
+     * }
+     * On entry:
+     *    r0 = &op1 [vBB]
+     *    r1 = &op2 [vCC]
+     */
+    /* op vAA, vBB, vCC */
+    flds    s0, [r0]                    @ d0<- vBB
+    flds    s1, [r1]                    @ d1<- vCC
+    fcmpes  s0, s1                      @ compare (vBB, vCC)
+    mov     r0, #1                      @ r0<- 1 (default)
+    fmstat                              @ export status flags
+    mvnmi   r0, #0                      @ (less than) r0<- -1
+    moveq   r0, #0                      @ (equal) r0<- 0
+    bx      lr
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP
+dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP:
+/* File: armv5te-vfp/TEMPLATE_CMPL_FLOAT_VFP.S */
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else {
+     *         return -1;
+     *     }
+     * }
+     * On entry:
+     *    r0 = &op1 [vBB]
+     *    r1 = &op2 [vCC]
+     */
+    /* op vAA, vBB, vCC */
+    flds    s0, [r0]                    @ d0<- vBB
+    flds    s1, [r1]                    @ d1<- vCC
+    fcmpes  s0, s1                      @ compare (vBB, vCC)
+    mvn     r0, #0                      @ r0<- -1 (default)
+    fmstat                              @ export status flags
+    movgt   r0, #1                      @ (greater than) r0<- 1
+    moveq   r0, #0                      @ (equal) r0<- 0
+    bx      lr
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP
+dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP:
+/* File: armv5te-vfp/TEMPLATE_SQRT_DOUBLE_VFP.S */
+    /*
+     * 64-bit floating point vfp sqrt operation.
+     * If the result is a NaN, bail out to library code to do
+     * the right thing.
+     *
+     * On entry:
+     *     r2 src addr of op1
+     * On exit:
+     *     r0,r1 = res
+     */
+    fldd    d0, [r2]
+    fsqrtd  d1, d0
+    fcmpd   d1, d1
+    fmstat
+    fmrrd   r0, r1, d1
+    bxeq    lr   @ Result OK - return
+    ldr     r2, .Lsqrt
+    fmrrd   r0, r1, d0   @ reload orig operand
+    bx      r2   @ tail call to sqrt library routine
+
+.Lsqrt:
+    .word   sqrt
+
+    .size   dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
+/* File: armv5te/footer.S */
+/*
+ * ===========================================================================
+ *  Common subroutines and data
+ * ===========================================================================
+ */
+
+    .text
+    .align  2
+.LinvokeNative:
+    @ Prep for the native call
+    @ r1 = newFP, r0 = methodToCall
+    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
+    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
+    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
+    str     r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
+                                        @ newFp->localRefCookie=top
+    mov     r9, r3                      @ r9<- glue->self (preserve)
+    SAVEAREA_FROM_FP(r10, r1)           @ r10<- new stack save area
+
+    mov     r2, r0                      @ r2<- methodToCall
+    mov     r0, r1                      @ r0<- newFP
+    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
+
+    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
+
+    @ native return; r9=self, r10=newSaveArea
+    @ equivalent to dvmPopJniLocals
+    ldr     r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
+    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
+    ldr     r1, [r9, #offThread_exception] @ check for exception
+    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
+    cmp     r1, #0                      @ null?
+    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
+    bne     .LhandleException             @ no, handle exception
+    bx      r2
+
+/* NOTE - this path can be exercised if the JIT threshold is set to 5 */
+.LhandleException:
+    ldr     r0, .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
+
+    .align  2
+.LdvmAsmInstructionStart:
+    .word   dvmAsmInstructionStart
+.LdvmJitToInterpNoChain:
+    .word   dvmJitToInterpNoChain
+.LdvmMterpStdBail:
+    .word   dvmMterpStdBail
+.LdvmMterpCommonExceptionThrown:
+    .word   dvmMterpCommonExceptionThrown
+.L__aeabi_cdcmple:
+    .word   __aeabi_cdcmple
+.L__aeabi_cfcmple:
+    .word   __aeabi_cfcmple
+
+    .global dmvCompilerTemplateEnd
+dmvCompilerTemplateEnd:
+
+#endif /* WITH_JIT */
+
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S b/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
new file mode 100644
index 0000000..29dde74
--- /dev/null
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
@@ -0,0 +1,798 @@
+/*
+ * This file was generated automatically by gen-template.py for 'armv5te'.
+ *
+ * --> DO NOT EDIT <--
+ */
+
+/* File: armv5te/header.S */
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined(WITH_JIT)
+
+/*
+ * ARMv5 definitions and declarations.
+ */
+
+/*
+ARM EABI general notes:
+
+r0-r3 hold first 4 args to a method; they are not preserved across method calls
+r4-r8 are available for general use
+r9 is given special treatment in some situations, but not for us
+r10 (sl) seems to be generally available
+r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
+r12 (ip) is scratch -- not preserved across method calls
+r13 (sp) should be managed carefully in case a signal arrives
+r14 (lr) must be preserved
+r15 (pc) can be tinkered with directly
+
+r0 holds returns of <= 4 bytes
+r0-r1 hold returns of 8 bytes, low word in r0
+
+Callee must save/restore r4+ (except r12) if it modifies them.
+
+Stack is "full descending".  Only the arguments that don't fit in the first 4
+registers are placed on the stack.  "sp" points at the first stacked argument
+(i.e. the 5th arg).
+
+VFP: single-precision results in s0, double-precision results in d0.
+
+In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
+64-bit quantities (long long, double) must be 64-bit aligned.
+*/
+
+/*
+JIT and ARM notes:
+
+The following registers have fixed assignments:
+
+  reg nick      purpose
+  r5  rFP       interpreted frame pointer, used for accessing locals and args
+  r6  rGLUE     MterpGlue pointer
+
+The following registers have fixed assignments in mterp but are scratch
+registers in compiled code
+
+  reg nick      purpose
+  r4  rPC       interpreted program counter, used for fetching instructions
+  r7  rINST     first 16-bit code unit of current instruction
+  r8  rIBASE    interpreted instruction base pointer, used for computed goto
+
+Macros are provided for common operations.  Each macro MUST emit only
+one instruction to make instruction-counting easier.  They MUST NOT alter
+unspecified registers or condition codes.
+*/
+
+/* single-purpose registers, given names for clarity */
+#define rPC     r4
+#define rFP     r5
+#define rGLUE   r6
+#define rINST   r7
+#define rIBASE  r8
+
+/*
+ * Given a frame pointer, find the stack save area.
+ *
+ * In C this is "((StackSaveArea*)(_fp) -1)".
+ */
+#define SAVEAREA_FROM_FP(_reg, _fpreg) \
+    sub     _reg, _fpreg, #sizeofStackSaveArea
+
+/*
+ * This is a #include, not a %include, because we want the C pre-processor
+ * to expand the macros into assembler assignment statements.
+ */
+#include "../../../mterp/common/asm-constants.h"
+
+
+/* File: armv5te/platform.S */
+/*
+ * ===========================================================================
+ *  CPU-version-specific defines
+ * ===========================================================================
+ */
+
+/*
+ * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
+ * Jump to subroutine.
+ *
+ * May modify IP and LR.
+ */
+.macro  LDR_PC_LR source
+    mov     lr, pc
+    ldr     pc, \source
+.endm
+
+
+    .global dvmCompilerTemplateStart
+    .type   dvmCompilerTemplateStart, %function
+    .text
+
+dvmCompilerTemplateStart:
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_CMP_LONG
+dvmCompiler_TEMPLATE_CMP_LONG:
+/* File: armv5te/TEMPLATE_CMP_LONG.S */
+    /*
+     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
+     * register based on the results of the comparison.
+     *
+     * We load the full values with LDM, but in practice many values could
+     * be resolved by only looking at the high word.  This could be made
+     * faster or slower by splitting the LDM into a pair of LDRs.
+     *
+     * If we just wanted to set condition flags, we could do this:
+     *  subs    ip, r0, r2
+     *  sbcs    ip, r1, r3
+     *  subeqs  ip, r0, r2
+     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
+     * integer value, which we can do with 2 conditional mov/mvn instructions
+     * (set 1, set -1; if they're equal we already have 0 in ip), giving
+     * us a constant 5-cycle path plus a branch at the end to the
+     * instruction epilogue code.  The multi-compare approach below needs
+     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
+     * in the worst case (the 64-bit values are equal).
+     */
+    /* cmp-long vAA, vBB, vCC */
+    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
+    blt     .LTEMPLATE_CMP_LONG_less            @ signed compare on high part
+    bgt     .LTEMPLATE_CMP_LONG_greater
+    subs    r0, r0, r2                  @ r0<- r0 - r2
+    bxeq     lr
+    bhi     .LTEMPLATE_CMP_LONG_greater         @ unsigned compare on low part
+.LTEMPLATE_CMP_LONG_less:
+    mvn     r0, #0                      @ r0<- -1
+    bx      lr
+.LTEMPLATE_CMP_LONG_greater:
+    mov     r0, #1                      @ r0<- 1
+    bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_RETURN
+dvmCompiler_TEMPLATE_RETURN:
+/* File: armv5te/TEMPLATE_RETURN.S */
+    /*
+     * Unwind a frame from the Dalvik stack for compiled OP_RETURN_XXX.
+     * If the stored value in returnAddr
+     * is non-zero, the caller is compiled by the JIT thus return to the
+     * address in the code cache following the invoke instruction. Otherwise
+     * return to the special dvmJitToInterpNoChain entry point.
+     */
+    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
+    ldr     r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame
+    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+    ldr     rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc
+    ldr     r9,  [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
+    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?
+    beq     1f                          @ bail to interpreter
+    ldr     r0, .LdvmJitToInterpNoChain @ defined in footer.S
+    mov     rFP, r10                    @ publish new FP
+    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
+    ldr     r8, [r8]                    @ r8<- suspendCount
+
+    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
+    ldr     r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex
+    str     rFP, [r3, #offThread_curFrame] @ self->curFrame = fp
+    add     rPC, rPC, #6                @ publish new rPC (advance 6 bytes)
+    str     r1, [rGLUE, #offGlue_methodClassDex]
+    cmp     r8, #0                      @ check the suspendCount
+    movne   r9, #0                      @ clear the chaining cell address
+    cmp     r9, #0                      @ chaining cell exists?
+    blxne   r9                          @ jump to the chaining cell
+    mov     pc, r0                      @ callsite is interpreted
+1:
+    stmia   rGLUE, {rPC, rFP}           @ SAVE_PC_FP_TO_GLUE()
+    ldr     r2, .LdvmMterpStdBail       @ defined in footer.S
+    mov     r1, #0                      @ changeInterp = false
+    mov     r0, rGLUE                   @ Expecting rGLUE in r0
+    blx     r2                          @ exit the interpreter
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT
+dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */
+    /*
+     * For polymorphic callsites - setup the Dalvik frame and load Dalvik PC
+     * into rPC then jump to dvmJitToInterpNoChain to dispatch the
+     * runtime-resolved callee.
+     */
+    @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
+    ldrh    r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
+    ldrh    r2, [r0, #offMethod_outsSize]  @ r2<- methodToCall->outsSize
+    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
+    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+    add     r3, r1, #1  @ Thumb addr is odd
+    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
+    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
+    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
+    sub     r10, r10, r2, lsl #2        @ r10<- bottom (newsave - outsSize)
+    ldr     r8, [r8]                    @ r3<- suspendCount (int)
+    cmp     r10, r9                     @ bottom < interpStackEnd?
+    bxlt    lr                          @ return to raise stack overflow excep.
+    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
+    ldr     r9, [r0, #offMethod_clazz]      @ r9<- method->clazz
+    ldr     r10, [r0, #offMethod_accessFlags] @ r10<- methodToCall->accessFlags
+    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
+    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- methodToCall->insns
+
+
+    @ set up newSaveArea
+    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
+    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
+    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
+    cmp     r8, #0                      @ suspendCount != 0
+    bxne    lr                          @ bail to the interpreter
+    tst     r10, #ACC_NATIVE
+    bne     .LinvokeNative
+
+    ldr     r10, .LdvmJitToInterpNoChain
+    ldr     r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
+    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
+
+    @ Update "glue" values for the new method
+    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
+    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
+    mov     rFP, r1                         @ fp = newFp
+    str     rFP, [r2, #offThread_curFrame]  @ self->curFrame = newFp
+
+    @ Start executing the callee
+    mov     pc, r10                         @ dvmJitToInterpNoChain
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN
+dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S */
+    /*
+     * For monomorphic callsite, setup the Dalvik frame and return to the
+     * Thumb code through the link register to transfer control to the callee
+     * method through a dedicated chaining cell.
+     */
+    @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
+    @ methodToCall is guaranteed to be non-native
+.LinvokeChain:
+    ldrh    r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
+    ldrh    r2, [r0, #offMethod_outsSize]  @ r2<- methodToCall->outsSize
+    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
+    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+    add     r3, r1, #1  @ Thumb addr is odd
+    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
+    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
+    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
+    add     r12, lr, #2                 @ setup the punt-to-interp address
+    sub     r10, r10, r2, lsl #2        @ r10<- bottom (newsave - outsSize)
+    ldr     r8, [r8]                    @ r3<- suspendCount (int)
+    cmp     r10, r9                     @ bottom < interpStackEnd?
+    bxlt    r12                         @ return to raise stack overflow excep.
+    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
+    ldr     r9, [r0, #offMethod_clazz]      @ r9<- method->clazz
+    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
+    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- methodToCall->insns
+
+
+    @ set up newSaveArea
+    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
+    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
+    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
+    cmp     r8, #0                      @ suspendCount != 0
+    bxne    r12                         @ bail to the interpreter
+
+    ldr     r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
+    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
+
+    @ Update "glue" values for the new method
+    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
+    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
+    mov     rFP, r1                         @ fp = newFp
+    str     rFP, [r2, #offThread_curFrame]  @ self->curFrame = newFp
+
+    bx      lr                              @ return to the callee-chaining cell
+
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN
+dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */
+    /*
+     * For polymorphic callsite, check whether the cached class pointer matches
+     * the current one. If so setup the Dalvik frame and return to the
+     * Thumb code through the link register to transfer control to the callee
+     * method through a dedicated chaining cell.
+     *
+     * The predicted chaining cell is declared in ArmLIR.h with the
+     * following layout:
+     *
+     *  typedef struct PredictedChainingCell {
+     *      u4 branch;
+     *      const ClassObject *clazz;
+     *      const Method *method;
+     *      u4 counter;
+     *  } PredictedChainingCell;
+     *
+     * Upon returning to the callsite:
+     *    - lr  : to branch to the chaining cell
+     *    - lr+2: to punt to the interpreter
+     *    - lr+4: to fully resolve the callee and may rechain.
+     *            r3 <- class
+     *            r9 <- counter
+     */
+    @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite
+    ldr     r3, [r0, #offObject_clazz]  @ r3 <- this->class
+    ldr     r8, [r2, #4]    @ r8 <- predictedChainCell->clazz
+    ldr     r0, [r2, #8]    @ r0 <- predictedChainCell->method
+    ldr     r9, [r2, #12]   @ r9 <- predictedChainCell->counter
+    cmp     r3, r8          @ predicted class == actual class?
+    beq     .LinvokeChain   @ predicted chain is valid
+    ldr     r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable
+    sub     r1, r9, #1      @ count--
+    str     r1, [r2, #12]   @ write back to PredictedChainingCell->counter
+    add     lr, lr, #4      @ return to fully-resolve landing pad
+    /*
+     * r1 <- count
+     * r2 <- &predictedChainCell
+     * r3 <- this->class
+     * r4 <- dPC
+     * r7 <- this->class->vtable
+     */
+    bx      lr
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE
+dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S */
+    @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
+    ldrh    r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
+    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
+    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+    add     r3, r1, #1  @ Thumb addr is odd
+    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
+    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
+    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
+    ldr     r8, [r8]                    @ r3<- suspendCount (int)
+    cmp     r10, r9                     @ bottom < interpStackEnd?
+    bxlt    lr                          @ return to raise stack overflow excep.
+    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
+    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
+    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- methodToCall->insns
+
+
+    @ set up newSaveArea
+    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
+    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
+    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
+    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
+    cmp     r8, #0                      @ suspendCount != 0
+    ldr     r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc
+    bxne    lr                          @ bail to the interpreter
+
+    @ go ahead and transfer control to the native code
+    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
+    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
+    str     r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
+                                        @ newFp->localRefCookie=top
+    mov     r9, r3                      @ r9<- glue->self (preserve)
+    SAVEAREA_FROM_FP(r10, r1)           @ r10<- new stack save area
+
+    mov     r2, r0                      @ r2<- methodToCall
+    mov     r0, r1                      @ r0<- newFP
+    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
+
+    blx     r8                          @ off to the native code
+
+    @ native return; r9=self, r10=newSaveArea
+    @ equivalent to dvmPopJniLocals
+    ldr     r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
+    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
+    ldr     r1, [r9, #offThread_exception] @ check for exception
+    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
+    cmp     r1, #0                      @ null?
+    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
+    bne     .LhandleException             @ no, handle exception
+    bx      r2
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_CMPG_DOUBLE
+dvmCompiler_TEMPLATE_CMPG_DOUBLE:
+/* File: armv5te/TEMPLATE_CMPG_DOUBLE.S */
+/* File: armv5te/TEMPLATE_CMPL_DOUBLE.S */
+    /*
+     * For the JIT: incoming arguments are pointers to the arguments in r0/r1
+     *              result in r0
+     *
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
+     * on what value we'd like to return when one of the operands is NaN.
+     *
+     * See OP_CMPL_FLOAT for an explanation.
+     *
+     * For: cmpl-double, cmpg-double
+     */
+    /* op vAA, vBB, vCC */
+    mov     r4, lr                      @ save return address
+    mov     r9, r0                      @ save copy of &arg1
+    mov     r10, r1                     @ save copy of &arg2
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    ldmia   r10, {r2-r3}                @ r2/r3<- vCC/vCC+1
+    LDR_PC_LR ".L__aeabi_cdcmple"       @ PIC way of "bl __aeabi_cdcmple"
+    bhi     .LTEMPLATE_CMPG_DOUBLE_gt_or_nan       @ C set and Z clear, disambiguate
+    mvncc   r0, #0                      @ (less than) r1<- -1
+    moveq   r0, #0                      @ (equal) r1<- 0, trumps less than
+    bx      r4
+
+    @ Test for NaN with a second comparison.  EABI forbids testing bit
+    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
+    @ make the library call.
+.LTEMPLATE_CMPG_DOUBLE_gt_or_nan:
+    ldmia   r10, {r0-r1}                @ reverse order
+    ldmia   r9, {r2-r3}
+    LDR_PC_LR ".L__aeabi_cdcmple"       @ r0<- Z set if eq, C clear if <
+    movcc   r0, #1                      @ (greater than) r1<- 1
+    bxcc    r4
+    mov     r0, #1                            @ r1<- 1 or -1 for NaN
+    bx      r4
+
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_CMPL_DOUBLE
+dvmCompiler_TEMPLATE_CMPL_DOUBLE:
+/* File: armv5te/TEMPLATE_CMPL_DOUBLE.S */
+    /*
+     * For the JIT: incoming arguments are pointers to the arguments in r0/r1
+     *              result in r0
+     *
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
+     * on what value we'd like to return when one of the operands is NaN.
+     *
+     * See OP_CMPL_FLOAT for an explanation.
+     *
+     * For: cmpl-double, cmpg-double
+     */
+    /* op vAA, vBB, vCC */
+    mov     r4, lr                      @ save return address
+    mov     r9, r0                      @ save copy of &arg1
+    mov     r10, r1                     @ save copy of &arg2
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    ldmia   r10, {r2-r3}                @ r2/r3<- vCC/vCC+1
+    LDR_PC_LR ".L__aeabi_cdcmple"       @ PIC way of "bl __aeabi_cdcmple"
+    bhi     .LTEMPLATE_CMPL_DOUBLE_gt_or_nan       @ C set and Z clear, disambiguate
+    mvncc   r0, #0                      @ (less than) r1<- -1
+    moveq   r0, #0                      @ (equal) r1<- 0, trumps less than
+    bx      r4
+
+    @ Test for NaN with a second comparison.  EABI forbids testing bit
+    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
+    @ make the library call.
+.LTEMPLATE_CMPL_DOUBLE_gt_or_nan:
+    ldmia   r10, {r0-r1}                @ reverse order
+    ldmia   r9, {r2-r3}
+    LDR_PC_LR ".L__aeabi_cdcmple"       @ r0<- Z set if eq, C clear if <
+    movcc   r0, #1                      @ (greater than) r1<- 1
+    bxcc    r4
+    mvn     r0, #0                            @ r1<- 1 or -1 for NaN
+    bx      r4
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_CMPG_FLOAT
+dvmCompiler_TEMPLATE_CMPG_FLOAT:
+/* File: armv5te/TEMPLATE_CMPG_FLOAT.S */
+/* File: armv5te/TEMPLATE_CMPL_FLOAT.S */
+    /*
+     * For the JIT: incoming arguments in r0, r1
+     *              result in r0
+     *
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
+     * on what value we'd like to return when one of the operands is NaN.
+     *
+     * The operation we're implementing is:
+     *   if (x == y)
+     *     return 0;
+     *   else if (x < y)
+     *     return -1;
+     *   else if (x > y)
+     *     return 1;
+     *   else
+     *     return {-1,1};  // one or both operands was NaN
+     *
+     * The straightforward implementation requires 3 calls to functions
+     * that return a result in r0.  We can do it with two calls if our
+     * EABI library supports __aeabi_cfcmple (only one if we want to check
+     * for NaN directly):
+     *   check x <= y
+     *     if <, return -1
+     *     if ==, return 0
+     *   check y <= x
+     *     if <, return 1
+     *   return {-1,1}
+     *
+     * for: cmpl-float, cmpg-float
+     */
+    /* op vAA, vBB, vCC */
+    mov     r4, lr                      @ save return address
+    mov     r9, r0                      @ Save copies - we may need to redo
+    mov     r10, r1
+    LDR_PC_LR ".L__aeabi_cfcmple"       @ cmp <=: C clear if <, Z set if eq
+    bhi     .LTEMPLATE_CMPG_FLOAT_gt_or_nan       @ C set and Z clear, disambiguate
+    mvncc   r0, #0                      @ (less than) r0<- -1
+    moveq   r0, #0                      @ (equal) r0<- 0, trumps less than
+    bx      r4
+    @ Test for NaN with a second comparison.  EABI forbids testing bit
+    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
+    @ make the library call.
+.LTEMPLATE_CMPG_FLOAT_gt_or_nan:
+    mov     r1, r9                      @ reverse order
+    mov     r0, r10
+    LDR_PC_LR ".L__aeabi_cfcmple"       @ r0<- Z set if eq, C clear if <
+    movcc   r0, #1                      @ (greater than) r1<- 1
+    bxcc    r4
+    mov     r0, #1                            @ r1<- 1 or -1 for NaN
+    bx      r4
+
+
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_CMPL_FLOAT
+dvmCompiler_TEMPLATE_CMPL_FLOAT:
+/* File: armv5te/TEMPLATE_CMPL_FLOAT.S */
+    /*
+     * For the JIT: incoming arguments in r0, r1
+     *              result in r0
+     *
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
+     * on what value we'd like to return when one of the operands is NaN.
+     *
+     * The operation we're implementing is:
+     *   if (x == y)
+     *     return 0;
+     *   else if (x < y)
+     *     return -1;
+     *   else if (x > y)
+     *     return 1;
+     *   else
+     *     return {-1,1};  // one or both operands was NaN
+     *
+     * The straightforward implementation requires 3 calls to functions
+     * that return a result in r0.  We can do it with two calls if our
+     * EABI library supports __aeabi_cfcmple (only one if we want to check
+     * for NaN directly):
+     *   check x <= y
+     *     if <, return -1
+     *     if ==, return 0
+     *   check y <= x
+     *     if <, return 1
+     *   return {-1,1}
+     *
+     * for: cmpl-float, cmpg-float
+     */
+    /* op vAA, vBB, vCC */
+    mov     r4, lr                      @ save return address
+    mov     r9, r0                      @ Save copies - we may need to redo
+    mov     r10, r1
+    LDR_PC_LR ".L__aeabi_cfcmple"       @ cmp <=: C clear if <, Z set if eq
+    bhi     .LTEMPLATE_CMPL_FLOAT_gt_or_nan       @ C set and Z clear, disambiguate
+    mvncc   r0, #0                      @ (less than) r0<- -1
+    moveq   r0, #0                      @ (equal) r0<- 0, trumps less than
+    bx      r4
+    @ Test for NaN with a second comparison.  EABI forbids testing bit
+    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
+    @ make the library call.
+.LTEMPLATE_CMPL_FLOAT_gt_or_nan:
+    mov     r1, r9                      @ reverse order
+    mov     r0, r10
+    LDR_PC_LR ".L__aeabi_cfcmple"       @ r0<- Z set if eq, C clear if <
+    movcc   r0, #1                      @ (greater than) r1<- 1
+    bxcc    r4
+    mvn     r0, #0                            @ r1<- 1 or -1 for NaN
+    bx      r4
+
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_MUL_LONG
+dvmCompiler_TEMPLATE_MUL_LONG:
+/* File: armv5te/TEMPLATE_MUL_LONG.S */
+    /*
+     * Signed 64-bit integer multiply.
+     *
+     * For JIT: op1 in r0/r1, op2 in r2/r3, return in r0/r1
+     *
+     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
+     *        WX
+     *      x YZ
+     *  --------
+     *     ZW ZX
+     *  YW YX
+     *
+     * The low word of the result holds ZX, the high word holds
+     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
+     * it doesn't fit in the low 64 bits.
+     *
+     * Unlike most ARM math operations, multiply instructions have
+     * restrictions on using the same register more than once (Rd and Rm
+     * cannot be the same).
+     */
+    /* mul-long vAA, vBB, vCC */
+    mul     ip, r2, r1                  @  ip<- ZxW
+    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
+    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
+    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
+    mov     r0,r9
+    mov     r1,r10
+    bx      lr
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_SHL_LONG
+dvmCompiler_TEMPLATE_SHL_LONG:
+/* File: armv5te/TEMPLATE_SHL_LONG.S */
+    /*
+     * Long integer shift.  This is different from the generic 32/64-bit
+     * binary operations because vAA/vBB are 64-bit but vCC (the shift
+     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
+     * 6 bits.
+     */
+    /* shl-long vAA, vBB, vCC */
+    and     r2, r2, #63                 @ r2<- r2 & 0x3f
+    mov     r1, r1, asl r2              @  r1<- r1 << r2
+    rsb     r3, r2, #32                 @  r3<- 32 - r2
+    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
+    subs    ip, r2, #32                 @  ip<- r2 - 32
+    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
+    mov     r0, r0, asl r2              @  r0<- r0 << r2
+    bx      lr
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_SHR_LONG
+dvmCompiler_TEMPLATE_SHR_LONG:
+/* File: armv5te/TEMPLATE_SHR_LONG.S */
+    /*
+     * Long integer shift.  This is different from the generic 32/64-bit
+     * binary operations because vAA/vBB are 64-bit but vCC (the shift
+     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
+     * 6 bits.
+     */
+    /* shr-long vAA, vBB, vCC */
+    and     r2, r2, #63                 @ r0<- r0 & 0x3f
+    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
+    rsb     r3, r2, #32                 @  r3<- 32 - r2
+    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
+    subs    ip, r2, #32                 @  ip<- r2 - 32
+    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
+    mov     r1, r1, asr r2              @  r1<- r1 >> r2
+    bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_USHR_LONG
+dvmCompiler_TEMPLATE_USHR_LONG:
+/* File: armv5te/TEMPLATE_USHR_LONG.S */
+    /*
+     * Long integer shift.  This is different from the generic 32/64-bit
+     * binary operations because vAA/vBB are 64-bit but vCC (the shift
+     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
+     * 6 bits.
+     */
+    /* ushr-long vAA, vBB, vCC */
+    and     r2, r2, #63                 @ r0<- r0 & 0x3f
+    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
+    rsb     r3, r2, #32                 @  r3<- 32 - r2
+    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
+    subs    ip, r2, #32                 @  ip<- r2 - 32
+    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
+    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
+    bx      lr
+
+
+    .size   dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
+/* File: armv5te/footer.S */
+/*
+ * ===========================================================================
+ *  Common subroutines and data
+ * ===========================================================================
+ */
+
+    .text
+    .align  2
+.LinvokeNative:
+    @ Prep for the native call
+    @ r1 = newFP, r0 = methodToCall
+    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
+    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
+    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
+    str     r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
+                                        @ newFp->localRefCookie=top
+    mov     r9, r3                      @ r9<- glue->self (preserve)
+    SAVEAREA_FROM_FP(r10, r1)           @ r10<- new stack save area
+
+    mov     r2, r0                      @ r2<- methodToCall
+    mov     r0, r1                      @ r0<- newFP
+    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
+
+    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
+
+    @ native return; r9=self, r10=newSaveArea
+    @ equivalent to dvmPopJniLocals
+    ldr     r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
+    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
+    ldr     r1, [r9, #offThread_exception] @ check for exception
+    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
+    cmp     r1, #0                      @ null?
+    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
+    bne     .LhandleException             @ no, handle exception
+    bx      r2
+
+/* NOTE - this path can be exercised if the JIT threshold is set to 5 */
+.LhandleException:
+    ldr     r0, .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
+
+    .align  2
+.LdvmAsmInstructionStart:
+    .word   dvmAsmInstructionStart
+.LdvmJitToInterpNoChain:
+    .word   dvmJitToInterpNoChain
+.LdvmMterpStdBail:
+    .word   dvmMterpStdBail
+.LdvmMterpCommonExceptionThrown:
+    .word   dvmMterpCommonExceptionThrown
+.L__aeabi_cdcmple:
+    .word   __aeabi_cdcmple
+.L__aeabi_cfcmple:
+    .word   __aeabi_cfcmple
+
+    .global dmvCompilerTemplateEnd
+dmvCompilerTemplateEnd:
+
+#endif /* WITH_JIT */
+
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
new file mode 100644
index 0000000..9e97b74
--- /dev/null
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
@@ -0,0 +1,1064 @@
+/*
+ * This file was generated automatically by gen-template.py for 'armv7-a'.
+ *
+ * --> DO NOT EDIT <--
+ */
+
+/* File: armv5te/header.S */
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if defined(WITH_JIT)
+
+/*
+ * ARMv5 definitions and declarations.
+ */
+
+/*
+ARM EABI general notes:
+
+r0-r3 hold first 4 args to a method; they are not preserved across method calls
+r4-r8 are available for general use
+r9 is given special treatment in some situations, but not for us
+r10 (sl) seems to be generally available
+r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
+r12 (ip) is scratch -- not preserved across method calls
+r13 (sp) should be managed carefully in case a signal arrives
+r14 (lr) must be preserved
+r15 (pc) can be tinkered with directly
+
+r0 holds returns of <= 4 bytes
+r0-r1 hold returns of 8 bytes, low word in r0
+
+Callee must save/restore r4+ (except r12) if it modifies them.
+
+Stack is "full descending".  Only the arguments that don't fit in the first 4
+registers are placed on the stack.  "sp" points at the first stacked argument
+(i.e. the 5th arg).
+
+VFP: single-precision results in s0, double-precision results in d0.
+
+In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
+64-bit quantities (long long, double) must be 64-bit aligned.
+*/
+
+/*
+JIT and ARM notes:
+
+The following registers have fixed assignments:
+
+  reg nick      purpose
+  r5  rFP       interpreted frame pointer, used for accessing locals and args
+  r6  rGLUE     MterpGlue pointer
+
+The following registers have fixed assignments in mterp but are scratch
+registers in compiled code
+
+  reg nick      purpose
+  r4  rPC       interpreted program counter, used for fetching instructions
+  r7  rINST     first 16-bit code unit of current instruction
+  r8  rIBASE    interpreted instruction base pointer, used for computed goto
+
+Macros are provided for common operations.  Each macro MUST emit only
+one instruction to make instruction-counting easier.  They MUST NOT alter
+unspecified registers or condition codes.
+*/
+
+/* single-purpose registers, given names for clarity */
+#define rPC     r4
+#define rFP     r5
+#define rGLUE   r6
+#define rINST   r7
+#define rIBASE  r8
+
+/*
+ * Given a frame pointer, find the stack save area.
+ *
+ * In C this is "((StackSaveArea*)(_fp) -1)".
+ */
+#define SAVEAREA_FROM_FP(_reg, _fpreg) \
+    sub     _reg, _fpreg, #sizeofStackSaveArea
+
+/*
+ * This is a #include, not a %include, because we want the C pre-processor
+ * to expand the macros into assembler assignment statements.
+ */
+#include "../../../mterp/common/asm-constants.h"
+
+
+/* File: armv5te/platform.S */
+/*
+ * ===========================================================================
+ *  CPU-version-specific defines
+ * ===========================================================================
+ */
+
+/*
+ * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
+ * Jump to subroutine.
+ *
+ * May modify IP and LR.
+ */
+.macro  LDR_PC_LR source
+    mov     lr, pc
+    ldr     pc, \source
+.endm
+
+
+    .global dvmCompilerTemplateStart
+    .type   dvmCompilerTemplateStart, %function
+    .text
+
+dvmCompilerTemplateStart:
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_CMP_LONG
+dvmCompiler_TEMPLATE_CMP_LONG:
+/* File: armv5te/TEMPLATE_CMP_LONG.S */
+    /*
+     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
+     * register based on the results of the comparison.
+     *
+     * We load the full values with LDM, but in practice many values could
+     * be resolved by only looking at the high word.  This could be made
+     * faster or slower by splitting the LDM into a pair of LDRs.
+     *
+     * If we just wanted to set condition flags, we could do this:
+     *  subs    ip, r0, r2
+     *  sbcs    ip, r1, r3
+     *  subeqs  ip, r0, r2
+     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
+     * integer value, which we can do with 2 conditional mov/mvn instructions
+     * (set 1, set -1; if they're equal we already have 0 in ip), giving
+     * us a constant 5-cycle path plus a branch at the end to the
+     * instruction epilogue code.  The multi-compare approach below needs
+     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
+     * in the worst case (the 64-bit values are equal).
+     */
+    /* cmp-long vAA, vBB, vCC */
+    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
+    blt     .LTEMPLATE_CMP_LONG_less            @ signed compare on high part
+    bgt     .LTEMPLATE_CMP_LONG_greater
+    subs    r0, r0, r2                  @ r0<- r0 - r2
+    bxeq     lr
+    bhi     .LTEMPLATE_CMP_LONG_greater         @ unsigned compare on low part
+.LTEMPLATE_CMP_LONG_less:
+    mvn     r0, #0                      @ r0<- -1
+    bx      lr
+.LTEMPLATE_CMP_LONG_greater:
+    mov     r0, #1                      @ r0<- 1
+    bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_RETURN
+dvmCompiler_TEMPLATE_RETURN:
+/* File: armv5te/TEMPLATE_RETURN.S */
+    /*
+     * Unwind a frame from the Dalvik stack for compiled OP_RETURN_XXX.
+     * If the stored value in returnAddr
+     * is non-zero, the caller is compiled by the JIT thus return to the
+     * address in the code cache following the invoke instruction. Otherwise
+     * return to the special dvmJitToInterpNoChain entry point.
+     */
+    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
+    ldr     r10, [r0, #offStackSaveArea_prevFrame] @ r10<- saveArea->prevFrame
+    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+    ldr     rPC, [r0, #offStackSaveArea_savedPc] @ rPC<- saveArea->savedPc
+    ldr     r9,  [r0, #offStackSaveArea_returnAddr] @ r9<- chaining cell ret
+    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?
+    beq     1f                          @ bail to interpreter
+    ldr     r0, .LdvmJitToInterpNoChain @ defined in footer.S
+    mov     rFP, r10                    @ publish new FP
+    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
+    ldr     r8, [r8]                    @ r8<- suspendCount
+
+    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
+    ldr     r1, [r10, #offClassObject_pDvmDex] @ r1<- method->clazz->pDvmDex
+    str     rFP, [r3, #offThread_curFrame] @ self->curFrame = fp
+    add     rPC, rPC, #6                @ publish new rPC (advance 6 bytes)
+    str     r1, [rGLUE, #offGlue_methodClassDex]
+    cmp     r8, #0                      @ check the suspendCount
+    movne   r9, #0                      @ clear the chaining cell address
+    cmp     r9, #0                      @ chaining cell exists?
+    blxne   r9                          @ jump to the chaining cell
+    mov     pc, r0                      @ callsite is interpreted
+1:
+    stmia   rGLUE, {rPC, rFP}           @ SAVE_PC_FP_TO_GLUE()
+    ldr     r2, .LdvmMterpStdBail       @ defined in footer.S
+    mov     r1, #0                      @ changeInterp = false
+    mov     r0, rGLUE                   @ Expecting rGLUE in r0
+    blx     r2                          @ exit the interpreter
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT
+dvmCompiler_TEMPLATE_INVOKE_METHOD_NO_OPT:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_NO_OPT.S */
+    /*
+     * For polymorphic callsites - setup the Dalvik frame and load Dalvik PC
+     * into rPC then jump to dvmJitToInterpNoChain to dispatch the
+     * runtime-resolved callee.
+     */
+    @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
+    ldrh    r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
+    ldrh    r2, [r0, #offMethod_outsSize]  @ r2<- methodToCall->outsSize
+    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
+    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+    add     r3, r1, #1  @ Thumb addr is odd
+    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
+    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
+    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
+    sub     r10, r10, r2, lsl #2        @ r10<- bottom (newsave - outsSize)
+    ldr     r8, [r8]                    @ r3<- suspendCount (int)
+    cmp     r10, r9                     @ bottom < interpStackEnd?
+    bxlt    lr                          @ return to raise stack overflow excep.
+    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
+    ldr     r9, [r0, #offMethod_clazz]      @ r9<- method->clazz
+    ldr     r10, [r0, #offMethod_accessFlags] @ r10<- methodToCall->accessFlags
+    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
+    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- methodToCall->insns
+
+
+    @ set up newSaveArea
+    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
+    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
+    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
+    cmp     r8, #0                      @ suspendCount != 0
+    bxne    lr                          @ bail to the interpreter
+    tst     r10, #ACC_NATIVE
+    bne     .LinvokeNative
+
+    ldr     r10, .LdvmJitToInterpNoChain
+    ldr     r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
+    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
+
+    @ Update "glue" values for the new method
+    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
+    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
+    mov     rFP, r1                         @ fp = newFp
+    str     rFP, [r2, #offThread_curFrame]  @ self->curFrame = newFp
+
+    @ Start executing the callee
+    mov     pc, r10                         @ dvmJitToInterpNoChain
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN
+dvmCompiler_TEMPLATE_INVOKE_METHOD_CHAIN:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_CHAIN.S */
+    /*
+     * For monomorphic callsite, setup the Dalvik frame and return to the
+     * Thumb code through the link register to transfer control to the callee
+     * method through a dedicated chaining cell.
+     */
+    @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
+    @ methodToCall is guaranteed to be non-native
+.LinvokeChain:
+    ldrh    r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
+    ldrh    r2, [r0, #offMethod_outsSize]  @ r2<- methodToCall->outsSize
+    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
+    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+    add     r3, r1, #1  @ Thumb addr is odd
+    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
+    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
+    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
+    add     r12, lr, #2                 @ setup the punt-to-interp address
+    sub     r10, r10, r2, lsl #2        @ r10<- bottom (newsave - outsSize)
+    ldr     r8, [r8]                    @ r3<- suspendCount (int)
+    cmp     r10, r9                     @ bottom < interpStackEnd?
+    bxlt    r12                         @ return to raise stack overflow excep.
+    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
+    ldr     r9, [r0, #offMethod_clazz]      @ r9<- method->clazz
+    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
+    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- methodToCall->insns
+
+
+    @ set up newSaveArea
+    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
+    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
+    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
+    cmp     r8, #0                      @ suspendCount != 0
+    bxne    r12                         @ bail to the interpreter
+
+    ldr     r3, [r9, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
+    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
+
+    @ Update "glue" values for the new method
+    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
+    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
+    mov     rFP, r1                         @ fp = newFp
+    str     rFP, [r2, #offThread_curFrame]  @ self->curFrame = newFp
+
+    bx      lr                              @ return to the callee-chaining cell
+
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN
+dvmCompiler_TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_PREDICTED_CHAIN.S */
+    /*
+     * For polymorphic callsite, check whether the cached class pointer matches
+     * the current one. If so setup the Dalvik frame and return to the
+     * Thumb code through the link register to transfer control to the callee
+     * method through a dedicated chaining cell.
+     *
+     * The predicted chaining cell is declared in ArmLIR.h with the
+     * following layout:
+     *
+     *  typedef struct PredictedChainingCell {
+     *      u4 branch;
+     *      const ClassObject *clazz;
+     *      const Method *method;
+     *      u4 counter;
+     *  } PredictedChainingCell;
+     *
+     * Upon returning to the callsite:
+     *    - lr  : to branch to the chaining cell
+     *    - lr+2: to punt to the interpreter
+     *    - lr+4: to fully resolve the callee and may rechain.
+     *            r3 <- class
+     *            r9 <- counter
+     */
+    @ r0 = this, r1 = returnCell, r2 = predictedChainCell, rPC = dalvikCallsite
+    ldr     r3, [r0, #offObject_clazz]  @ r3 <- this->class
+    ldr     r8, [r2, #4]    @ r8 <- predictedChainCell->clazz
+    ldr     r0, [r2, #8]    @ r0 <- predictedChainCell->method
+    ldr     r9, [r2, #12]   @ r9 <- predictedChainCell->counter
+    cmp     r3, r8          @ predicted class == actual class?
+    beq     .LinvokeChain   @ predicted chain is valid
+    ldr     r7, [r3, #offClassObject_vtable] @ r7 <- this->class->vtable
+    sub     r1, r9, #1      @ count--
+    str     r1, [r2, #12]   @ write back to PredictedChainingCell->counter
+    add     lr, lr, #4      @ return to fully-resolve landing pad
+    /*
+     * r1 <- count
+     * r2 <- &predictedChainCell
+     * r3 <- this->class
+     * r4 <- dPC
+     * r7 <- this->class->vtable
+     */
+    bx      lr
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE
+dvmCompiler_TEMPLATE_INVOKE_METHOD_NATIVE:
+/* File: armv5te/TEMPLATE_INVOKE_METHOD_NATIVE.S */
+    @ r0 = methodToCall, r1 = returnCell, rPC = dalvikCallsite
+    ldrh    r7, [r0, #offMethod_registersSize]  @ r7<- methodToCall->regsSize
+    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
+    ldr     r8, [rGLUE, #offGlue_pSelfSuspendCount] @ r8<- &suspendCount
+    add     r3, r1, #1  @ Thumb addr is odd
+    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
+    sub     r1, r1, r7, lsl #2          @ r1<- newFp (old savearea - regsSize)
+    SAVEAREA_FROM_FP(r10, r1)           @ r10<- stack save area
+    ldr     r8, [r8]                    @ r3<- suspendCount (int)
+    cmp     r10, r9                     @ bottom < interpStackEnd?
+    bxlt    lr                          @ return to raise stack overflow excep.
+    @ r1 = newFP, r0 = methodToCall, r3 = returnCell, rPC = dalvikCallsite
+    str     rPC, [rFP, #(offStackSaveArea_currentPc - sizeofStackSaveArea)]
+    str     rPC, [r1, #(offStackSaveArea_savedPc - sizeofStackSaveArea)]
+    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- methodToCall->insns
+
+
+    @ set up newSaveArea
+    str     rFP, [r1, #(offStackSaveArea_prevFrame - sizeofStackSaveArea)]
+    str     r3, [r1, #(offStackSaveArea_returnAddr - sizeofStackSaveArea)]
+    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
+    str     r0, [r1, #(offStackSaveArea_method - sizeofStackSaveArea)]
+    cmp     r8, #0                      @ suspendCount != 0
+    ldr     r8, [r0, #offMethod_nativeFunc] @ r8<- method->nativeFunc
+    bxne    lr                          @ bail to the interpreter
+
+    @ go ahead and transfer control to the native code
+    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
+    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
+    str     r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
+                                        @ newFp->localRefCookie=top
+    mov     r9, r3                      @ r9<- glue->self (preserve)
+    SAVEAREA_FROM_FP(r10, r1)           @ r10<- new stack save area
+
+    mov     r2, r0                      @ r2<- methodToCall
+    mov     r0, r1                      @ r0<- newFP
+    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
+
+    blx     r8                          @ off to the native code
+
+    @ native return; r9=self, r10=newSaveArea
+    @ equivalent to dvmPopJniLocals
+    ldr     r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
+    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
+    ldr     r1, [r9, #offThread_exception] @ check for exception
+    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
+    cmp     r1, #0                      @ null?
+    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
+    bne     .LhandleException             @ no, handle exception
+    bx      r2
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_MUL_LONG
+dvmCompiler_TEMPLATE_MUL_LONG:
+/* File: armv5te/TEMPLATE_MUL_LONG.S */
+    /*
+     * Signed 64-bit integer multiply.
+     *
+     * For JIT: op1 in r0/r1, op2 in r2/r3, return in r0/r1
+     *
+     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
+     *        WX
+     *      x YZ
+     *  --------
+     *     ZW ZX
+     *  YW YX
+     *
+     * The low word of the result holds ZX, the high word holds
+     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
+     * it doesn't fit in the low 64 bits.
+     *
+     * Unlike most ARM math operations, multiply instructions have
+     * restrictions on using the same register more than once (Rd and Rm
+     * cannot be the same).
+     */
+    /* mul-long vAA, vBB, vCC */
+    mul     ip, r2, r1                  @  ip<- ZxW
+    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
+    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
+    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
+    mov     r0,r9
+    mov     r1,r10
+    bx      lr
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_SHL_LONG
+dvmCompiler_TEMPLATE_SHL_LONG:
+/* File: armv5te/TEMPLATE_SHL_LONG.S */
+    /*
+     * Long integer shift.  This is different from the generic 32/64-bit
+     * binary operations because vAA/vBB are 64-bit but vCC (the shift
+     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
+     * 6 bits.
+     */
+    /* shl-long vAA, vBB, vCC */
+    and     r2, r2, #63                 @ r2<- r2 & 0x3f
+    mov     r1, r1, asl r2              @  r1<- r1 << r2
+    rsb     r3, r2, #32                 @  r3<- 32 - r2
+    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
+    subs    ip, r2, #32                 @  ip<- r2 - 32
+    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
+    mov     r0, r0, asl r2              @  r0<- r0 << r2
+    bx      lr
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_SHR_LONG
+dvmCompiler_TEMPLATE_SHR_LONG:
+/* File: armv5te/TEMPLATE_SHR_LONG.S */
+    /*
+     * Long integer shift.  This is different from the generic 32/64-bit
+     * binary operations because vAA/vBB are 64-bit but vCC (the shift
+     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
+     * 6 bits.
+     */
+    /* shr-long vAA, vBB, vCC */
+    and     r2, r2, #63                 @ r0<- r0 & 0x3f
+    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
+    rsb     r3, r2, #32                 @  r3<- 32 - r2
+    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
+    subs    ip, r2, #32                 @  ip<- r2 - 32
+    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
+    mov     r1, r1, asr r2              @  r1<- r1 >> r2
+    bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_USHR_LONG
+dvmCompiler_TEMPLATE_USHR_LONG:
+/* File: armv5te/TEMPLATE_USHR_LONG.S */
+    /*
+     * Long integer shift.  This is different from the generic 32/64-bit
+     * binary operations because vAA/vBB are 64-bit but vCC (the shift
+     * distance) is 32-bit.  Also, Dalvik requires us to ignore all but the low
+     * 6 bits.
+     */
+    /* ushr-long vAA, vBB, vCC */
+    and     r2, r2, #63                 @ r0<- r0 & 0x3f
+    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
+    rsb     r3, r2, #32                 @  r3<- 32 - r2
+    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
+    subs    ip, r2, #32                 @  ip<- r2 - 32
+    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
+    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
+    bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_ADD_FLOAT_VFP
+dvmCompiler_TEMPLATE_ADD_FLOAT_VFP:
+/* File: armv5te-vfp/TEMPLATE_ADD_FLOAT_VFP.S */
+/* File: armv5te-vfp/fbinop.S */
+    /*
+     * Generic 32-bit floating point operation.  Provide an "instr" line that
+     * specifies an instruction that performs s2 = s0 op s1.
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = op1 address
+     *     r2 = op2 address
+     */
+     flds    s0,[r1]
+     flds    s1,[r2]
+     fadds   s2, s0, s1
+     fsts    s2,[r0]
+     bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_SUB_FLOAT_VFP
+dvmCompiler_TEMPLATE_SUB_FLOAT_VFP:
+/* File: armv5te-vfp/TEMPLATE_SUB_FLOAT_VFP.S */
+/* File: armv5te-vfp/fbinop.S */
+    /*
+     * Generic 32-bit floating point operation.  Provide an "instr" line that
+     * specifies an instruction that performs s2 = s0 op s1.
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = op1 address
+     *     r2 = op2 address
+     */
+     flds    s0,[r1]
+     flds    s1,[r2]
+     fsubs   s2, s0, s1
+     fsts    s2,[r0]
+     bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_MUL_FLOAT_VFP
+dvmCompiler_TEMPLATE_MUL_FLOAT_VFP:
+/* File: armv5te-vfp/TEMPLATE_MUL_FLOAT_VFP.S */
+/* File: armv5te-vfp/fbinop.S */
+    /*
+     * Generic 32-bit floating point operation.  Provide an "instr" line that
+     * specifies an instruction that performs s2 = s0 op s1.
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = op1 address
+     *     r2 = op2 address
+     */
+     flds    s0,[r1]
+     flds    s1,[r2]
+     fmuls   s2, s0, s1
+     fsts    s2,[r0]
+     bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_DIV_FLOAT_VFP
+dvmCompiler_TEMPLATE_DIV_FLOAT_VFP:
+/* File: armv5te-vfp/TEMPLATE_DIV_FLOAT_VFP.S */
+/* File: armv5te-vfp/fbinop.S */
+    /*
+     * Generic 32-bit floating point operation.  Provide an "instr" line that
+     * specifies an instruction that performs s2 = s0 op s1.
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = op1 address
+     *     r2 = op2 address
+     */
+     flds    s0,[r1]
+     flds    s1,[r2]
+     fdivs   s2, s0, s1
+     fsts    s2,[r0]
+     bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP
+dvmCompiler_TEMPLATE_ADD_DOUBLE_VFP:
+/* File: armv5te-vfp/TEMPLATE_ADD_DOUBLE_VFP.S */
+/* File: armv5te-vfp/fbinopWide.S */
+    /*
+     * Generic 64-bit floating point operation.  Provide an "instr" line that
+     * specifies an instruction that performs s2 = s0 op s1.
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = op1 address
+     *     r2 = op2 address
+     */
+     fldd    d0,[r1]
+     fldd    d1,[r2]
+     faddd   d2, d0, d1
+     fstd    d2,[r0]
+     bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP
+dvmCompiler_TEMPLATE_SUB_DOUBLE_VFP:
+/* File: armv5te-vfp/TEMPLATE_SUB_DOUBLE_VFP.S */
+/* File: armv5te-vfp/fbinopWide.S */
+    /*
+     * Generic 64-bit floating point operation.  Provide an "instr" line that
+     * specifies an instruction that performs s2 = s0 op s1.
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = op1 address
+     *     r2 = op2 address
+     */
+     fldd    d0,[r1]
+     fldd    d1,[r2]
+     fsubd   d2, d0, d1
+     fstd    d2,[r0]
+     bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP
+dvmCompiler_TEMPLATE_MUL_DOUBLE_VFP:
+/* File: armv5te-vfp/TEMPLATE_MUL_DOUBLE_VFP.S */
+/* File: armv5te-vfp/fbinopWide.S */
+    /*
+     * Generic 64-bit floating point operation.  Provide an "instr" line that
+     * specifies an instruction that performs s2 = s0 op s1.
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = op1 address
+     *     r2 = op2 address
+     */
+     fldd    d0,[r1]
+     fldd    d1,[r2]
+     fmuld   d2, d0, d1
+     fstd    d2,[r0]
+     bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP
+dvmCompiler_TEMPLATE_DIV_DOUBLE_VFP:
+/* File: armv5te-vfp/TEMPLATE_DIV_DOUBLE_VFP.S */
+/* File: armv5te-vfp/fbinopWide.S */
+    /*
+     * Generic 64-bit floating point operation.  Provide an "instr" line that
+     * specifies an instruction that performs s2 = s0 op s1.
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = op1 address
+     *     r2 = op2 address
+     */
+     fldd    d0,[r1]
+     fldd    d1,[r2]
+     fdivd   d2, d0, d1
+     fstd    d2,[r0]
+     bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP
+dvmCompiler_TEMPLATE_DOUBLE_TO_FLOAT_VFP:
+/* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_FLOAT_VFP.S */
+/* File: armv5te-vfp/funopNarrower.S */
+    /*
+     * Generic 64bit-to-32bit floating point unary operation.  Provide an
+     * "instr" line that specifies an instruction that performs "s0 = op d0".
+     *
+     * For: double-to-int, double-to-float
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = src dalvik register address
+     */
+    /* unop vA, vB */
+    fldd    d0, [r1]                    @ d0<- vB
+    fcvtsd  s0, d0                              @ s0<- op d0
+    fsts    s0, [r0]                    @ vA<- s0
+    bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP
+dvmCompiler_TEMPLATE_DOUBLE_TO_INT_VFP:
+/* File: armv5te-vfp/TEMPLATE_DOUBLE_TO_INT_VFP.S */
+/* File: armv5te-vfp/funopNarrower.S */
+    /*
+     * Generic 64bit-to-32bit floating point unary operation.  Provide an
+     * "instr" line that specifies an instruction that performs "s0 = op d0".
+     *
+     * For: double-to-int, double-to-float
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = src dalvik register address
+     */
+    /* unop vA, vB */
+    fldd    d0, [r1]                    @ d0<- vB
+    ftosizd  s0, d0                              @ s0<- op d0
+    fsts    s0, [r0]                    @ vA<- s0
+    bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP
+dvmCompiler_TEMPLATE_FLOAT_TO_DOUBLE_VFP:
+/* File: armv5te-vfp/TEMPLATE_FLOAT_TO_DOUBLE_VFP.S */
+/* File: armv5te-vfp/funopWider.S */
+    /*
+     * Generic 32bit-to-64bit floating point unary operation.  Provide an
+     * "instr" line that specifies an instruction that performs "d0 = op s0".
+     *
+     * For: int-to-double, float-to-double
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = src dalvik register address
+     */
+    /* unop vA, vB */
+    flds    s0, [r1]                    @ s0<- vB
+    fcvtds  d0, s0                              @ d0<- op s0
+    fstd    d0, [r0]                    @ vA<- d0
+    bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP
+dvmCompiler_TEMPLATE_FLOAT_TO_INT_VFP:
+/* File: armv5te-vfp/TEMPLATE_FLOAT_TO_INT_VFP.S */
+/* File: armv5te-vfp/funop.S */
+    /*
+     * Generic 32bit-to-32bit floating point unary operation.  Provide an
+     * "instr" line that specifies an instruction that performs "s1 = op s0".
+     *
+     * For: float-to-int, int-to-float
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = src dalvik register address
+     */
+    /* unop vA, vB */
+    flds    s0, [r1]                    @ s0<- vB
+    ftosizs s1, s0                              @ s1<- op s0
+    fsts    s1, [r0]                    @ vA<- s1
+    bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP
+dvmCompiler_TEMPLATE_INT_TO_DOUBLE_VFP:
+/* File: armv5te-vfp/TEMPLATE_INT_TO_DOUBLE_VFP.S */
+/* File: armv5te-vfp/funopWider.S */
+    /*
+     * Generic 32bit-to-64bit floating point unary operation.  Provide an
+     * "instr" line that specifies an instruction that performs "d0 = op s0".
+     *
+     * For: int-to-double, float-to-double
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = src dalvik register address
+     */
+    /* unop vA, vB */
+    flds    s0, [r1]                    @ s0<- vB
+    fsitod  d0, s0                              @ d0<- op s0
+    fstd    d0, [r0]                    @ vA<- d0
+    bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP
+dvmCompiler_TEMPLATE_INT_TO_FLOAT_VFP:
+/* File: armv5te-vfp/TEMPLATE_INT_TO_FLOAT_VFP.S */
+/* File: armv5te-vfp/funop.S */
+    /*
+     * Generic 32bit-to-32bit floating point unary operation.  Provide an
+     * "instr" line that specifies an instruction that performs "s1 = op s0".
+     *
+     * For: float-to-int, int-to-float
+     *
+     * On entry:
+     *     r0 = target dalvik register address
+     *     r1 = src dalvik register address
+     */
+    /* unop vA, vB */
+    flds    s0, [r1]                    @ s0<- vB
+    fsitos  s1, s0                              @ s1<- op s0
+    fsts    s1, [r0]                    @ vA<- s1
+    bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP
+dvmCompiler_TEMPLATE_CMPG_DOUBLE_VFP:
+/* File: armv5te-vfp/TEMPLATE_CMPG_DOUBLE_VFP.S */
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else {
+     *         return 1;
+     *     }
+     * }
+     *
+     * On entry:
+     *    r0 = &op1 [vBB]
+     *    r1 = &op2 [vCC]
+     */
+    /* op vAA, vBB, vCC */
+    fldd    d0, [r0]                    @ d0<- vBB
+    fldd    d1, [r1]                    @ d1<- vCC
+    fcmped  d0, d1                      @ compare (vBB, vCC)
+    mov     r0, #1                      @ r0<- 1 (default)
+    fmstat                              @ export status flags
+    mvnmi   r0, #0                      @ (less than) r0<- -1
+    moveq   r0, #0                      @ (equal) r0<- 0
+    bx      lr
+
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP
+dvmCompiler_TEMPLATE_CMPL_DOUBLE_VFP:
+/* File: armv5te-vfp/TEMPLATE_CMPL_DOUBLE_VFP.S */
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else {
+     *         return -1;
+     *     }
+     * }
+     * On entry:
+     *    r0 = &op1 [vBB]
+     *    r1 = &op2 [vCC]
+     */
+    /* op vAA, vBB, vCC */
+    fldd    d0, [r0]                    @ d0<- vBB
+    fldd    d1, [r1]                    @ d1<- vCC
+    fcmped  d0, d1                      @ compare (vBB, vCC)
+    mvn     r0, #0                      @ r0<- -1 (default)
+    fmstat                              @ export status flags
+    movgt   r0, #1                      @ (greater than) r0<- 1
+    moveq   r0, #0                      @ (equal) r0<- 0
+    bx      lr
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP
+dvmCompiler_TEMPLATE_CMPG_FLOAT_VFP:
+/* File: armv5te-vfp/TEMPLATE_CMPG_FLOAT_VFP.S */
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else {
+     *         return 1;
+     *     }
+     * }
+     * On entry:
+     *    r0 = &op1 [vBB]
+     *    r1 = &op2 [vCC]
+     */
+    /* op vAA, vBB, vCC */
+    flds    s0, [r0]                    @ d0<- vBB
+    flds    s1, [r1]                    @ d1<- vCC
+    fcmpes  s0, s1                      @ compare (vBB, vCC)
+    mov     r0, #1                      @ r0<- 1 (default)
+    fmstat                              @ export status flags
+    mvnmi   r0, #0                      @ (less than) r0<- -1
+    moveq   r0, #0                      @ (equal) r0<- 0
+    bx      lr
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP
+dvmCompiler_TEMPLATE_CMPL_FLOAT_VFP:
+/* File: armv5te-vfp/TEMPLATE_CMPL_FLOAT_VFP.S */
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else {
+     *         return -1;
+     *     }
+     * }
+     * On entry:
+     *    r0 = &op1 [vBB]
+     *    r1 = &op2 [vCC]
+     */
+    /* op vAA, vBB, vCC */
+    flds    s0, [r0]                    @ d0<- vBB
+    flds    s1, [r1]                    @ d1<- vCC
+    fcmpes  s0, s1                      @ compare (vBB, vCC)
+    mvn     r0, #0                      @ r0<- -1 (default)
+    fmstat                              @ export status flags
+    movgt   r0, #1                      @ (greater than) r0<- 1
+    moveq   r0, #0                      @ (equal) r0<- 0
+    bx      lr
+
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP
+dvmCompiler_TEMPLATE_SQRT_DOUBLE_VFP:
+/* File: armv5te-vfp/TEMPLATE_SQRT_DOUBLE_VFP.S */
+    /*
+     * 64-bit floating point vfp sqrt operation.
+     * If the result is a NaN, bail out to library code to do
+     * the right thing.
+     *
+     * On entry:
+     *     r2 src addr of op1
+     * On exit:
+     *     r0,r1 = res
+     */
+    fldd    d0, [r2]
+    fsqrtd  d1, d0
+    fcmpd   d1, d1
+    fmstat
+    fmrrd   r0, r1, d1
+    bxeq    lr   @ Result OK - return
+    ldr     r2, .Lsqrt
+    fmrrd   r0, r1, d0   @ reload orig operand
+    bx      r2   @ tail call to sqrt library routine
+
+.Lsqrt:
+    .word   sqrt
+
+    .size   dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
+/* File: armv5te/footer.S */
+/*
+ * ===========================================================================
+ *  Common subroutines and data
+ * ===========================================================================
+ */
+
+    .text
+    .align  2
+.LinvokeNative:
+    @ Prep for the native call
+    @ r1 = newFP, r0 = methodToCall
+    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
+    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
+    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
+    str     r9, [r1, #(offStackSaveArea_localRefCookie - sizeofStackSaveArea)]
+                                        @ newFp->localRefCookie=top
+    mov     r9, r3                      @ r9<- glue->self (preserve)
+    SAVEAREA_FROM_FP(r10, r1)           @ r10<- new stack save area
+
+    mov     r2, r0                      @ r2<- methodToCall
+    mov     r0, r1                      @ r0<- newFP
+    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
+
+    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
+
+    @ native return; r9=self, r10=newSaveArea
+    @ equivalent to dvmPopJniLocals
+    ldr     r2, [r10, #offStackSaveArea_returnAddr] @ r2 = chaining cell ret
+    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved->top
+    ldr     r1, [r9, #offThread_exception] @ check for exception
+    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
+    cmp     r1, #0                      @ null?
+    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
+    bne     .LhandleException             @ no, handle exception
+    bx      r2
+
+/* NOTE - this path can be exercised if the JIT threshold is set to 5 */
+.LhandleException:
+    ldr     r0, .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
+
+    .align  2
+.LdvmAsmInstructionStart:
+    .word   dvmAsmInstructionStart
+.LdvmJitToInterpNoChain:
+    .word   dvmJitToInterpNoChain
+.LdvmMterpStdBail:
+    .word   dvmMterpStdBail
+.LdvmMterpCommonExceptionThrown:
+    .word   dvmMterpCommonExceptionThrown
+.L__aeabi_cdcmple:
+    .word   __aeabi_cdcmple
+.L__aeabi_cfcmple:
+    .word   __aeabi_cfcmple
+
+    .global dmvCompilerTemplateEnd
+dmvCompilerTemplateEnd:
+
+#endif /* WITH_JIT */
+
diff --git a/vm/compiler/template/rebuild.sh b/vm/compiler/template/rebuild.sh
new file mode 100755
index 0000000..8a3861e
--- /dev/null
+++ b/vm/compiler/template/rebuild.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+#
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Rebuild for all known targets.  Necessary until the stuff in "out" gets
+# generated as part of the build.
+#
+set -e
+for arch in armv5te armv5te-vfp armv7-a; do TARGET_ARCH_EXT=$arch make -f Makefile-template; done
+
diff --git a/vm/interp/Interp.c b/vm/interp/Interp.c
index 27b9582..233ee3f 100644
--- a/vm/interp/Interp.c
+++ b/vm/interp/Interp.c
@@ -180,7 +180,7 @@
     const StackSaveArea* saveArea;
     void* fp;
     void* prevFp = NULL;
-    
+
     for (fp = thread->curFrame; fp != NULL; fp = saveArea->prevFrame) {
         const Method* method;
 
@@ -225,7 +225,7 @@
     } else {
         pCtrl->line = dvmLineNumFromPC(saveArea->method,
                         saveArea->xtra.currentPc - saveArea->method->insns);
-        pCtrl->pAddressSet 
+        pCtrl->pAddressSet
                 = dvmAddressSetForLine(saveArea->method, pCtrl->line);
     }
     pCtrl->frameDepth = dvmComputeVagueFrameDepth(thread, thread->curFrame);
@@ -374,7 +374,7 @@
  * ===========================================================================
  */
 
-/* 
+/*
  * Construct an s4 from two consecutive half-words of switch data.
  * This needs to check endianness because the DEX optimizer only swaps
  * half-words in instruction stream.
@@ -389,6 +389,7 @@
 static inline s4 s4FromSwitchData(const void* switchData) {
     u2* data = switchData;
     return data[0] | (((s4) data[1]) << 16);
+}
 #endif
 
 /*
@@ -478,7 +479,7 @@
 
     size = *switchData++;
     assert(size > 0);
-    
+
     /* The keys are guaranteed to be aligned on a 32-bit boundary;
      * we can treat them as a native int array.
      */
@@ -514,6 +515,62 @@
 }
 
 /*
+ * Copy data for a fill-array-data instruction.  On a little-endian machine
+ * we can just do a memcpy(), on a big-endian system we have work to do.
+ *
+ * The trick here is that dexopt has byte-swapped each code unit, which is
+ * exactly what we want for short/char data.  For byte data we need to undo
+ * the swap, and for 4- or 8-byte values we need to swap pieces within
+ * each word.
+ */
+static void copySwappedArrayData(void* dest, const u2* src, u4 size, u2 width)
+{
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+    memcpy(dest, src, size*width);
+#else
+    int i;
+
+    switch (width) {
+    case 1:
+        /* un-swap pairs of bytes as we go */
+        for (i = (size-1) & ~1; i >= 0; i -= 2) {
+            ((u1*)dest)[i] = ((u1*)src)[i+1];
+            ((u1*)dest)[i+1] = ((u1*)src)[i];
+        }
+        /*
+         * "src" is padded to end on a two-byte boundary, but we don't want to
+         * assume "dest" is, so we handle odd length specially.
+         */
+        if ((size & 1) != 0) {
+            ((u1*)dest)[size-1] = ((u1*)src)[size];
+        }
+        break;
+    case 2:
+        /* already swapped correctly */
+        memcpy(dest, src, size*width);
+        break;
+    case 4:
+        /* swap word halves */
+        for (i = 0; i < (int) size; i++) {
+            ((u4*)dest)[i] = (src[(i << 1) + 1] << 16) | src[i << 1];
+        }
+        break;
+    case 8:
+        /* swap word halves and words */
+        for (i = 0; i < (int) (size << 1); i += 2) {
+            ((int*)dest)[i] = (src[(i << 1) + 3] << 16) | src[(i << 1) + 2];
+            ((int*)dest)[i+1] = (src[(i << 1) + 1] << 16) | src[i << 1];
+        }
+        break;
+    default:
+        LOGE("Unexpected width %d in copySwappedArrayData\n", width);
+        dvmAbort();
+        break;
+    }
+#endif
+}
+
+/*
  * Fill the array with predefined constant values.
  *
  * Returns true if job is completed, otherwise false to indicate that
@@ -551,7 +608,7 @@
         dvmThrowException("Ljava/lang/ArrayIndexOutOfBoundsException;", NULL);
         return false;
     }
-    memcpy(arrayObj->contents, &arrayData[4], size*width);
+    copySwappedArrayData(arrayObj->contents, &arrayData[4], size, width);
     return true;
 }
 
@@ -634,6 +691,189 @@
 }
 
 
+
+/*
+ * Helpers for dvmThrowVerificationError().
+ *
+ * Each returns a newly-allocated string.
+ */
+#define kThrowShow_accessFromClass     1
+static char* classNameFromIndex(const Method* method, int ref,
+    VerifyErrorRefType refType, int flags)
+{
+    static const int kBufLen = 256;
+    const DvmDex* pDvmDex = method->clazz->pDvmDex;
+
+    if (refType == VERIFY_ERROR_REF_FIELD) {
+        /* get class ID from field ID */
+        const DexFieldId* pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref);
+        ref = pFieldId->classIdx;
+    } else if (refType == VERIFY_ERROR_REF_METHOD) {
+        /* get class ID from method ID */
+        const DexMethodId* pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref);
+        ref = pMethodId->classIdx;
+    }
+
+    const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, ref);
+    char* dotClassName = dvmDescriptorToDot(className);
+    if (flags == 0)
+        return dotClassName;
+
+    char* result = (char*) malloc(kBufLen);
+
+    if ((flags & kThrowShow_accessFromClass) != 0) {
+        char* dotFromName = dvmDescriptorToDot(method->clazz->descriptor);
+        snprintf(result, kBufLen, "tried to access class %s from class %s",
+            dotClassName, dotFromName);
+        free(dotFromName);
+    } else {
+        assert(false);      // should've been caught above
+        result[0] = '\0';
+    }
+
+    free(dotClassName);
+    return result;
+}
+static char* fieldNameFromIndex(const Method* method, int ref,
+    VerifyErrorRefType refType, int flags)
+{
+    static const int kBufLen = 256;
+    const DvmDex* pDvmDex = method->clazz->pDvmDex;
+    const DexFieldId* pFieldId;
+    const char* className;
+    const char* fieldName;
+
+    if (refType != VERIFY_ERROR_REF_FIELD) {
+        LOGW("Expected ref type %d, got %d\n", VERIFY_ERROR_REF_FIELD, refType);
+        return NULL;    /* no message */
+    }
+
+    pFieldId = dexGetFieldId(pDvmDex->pDexFile, ref);
+    className = dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->classIdx);
+    fieldName = dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx);
+
+    char* dotName = dvmDescriptorToDot(className);
+    char* result = (char*) malloc(kBufLen);
+
+    if ((flags & kThrowShow_accessFromClass) != 0) {
+        char* dotFromName = dvmDescriptorToDot(method->clazz->descriptor);
+        snprintf(result, kBufLen, "tried to access field %s.%s from class %s",
+            dotName, fieldName, dotFromName);
+        free(dotFromName);
+    } else {
+        snprintf(result, kBufLen, "%s.%s", dotName, fieldName);
+    }
+
+    free(dotName);
+    return result;
+}
+static char* methodNameFromIndex(const Method* method, int ref,
+    VerifyErrorRefType refType, int flags)
+{
+    static const int kBufLen = 384;
+    const DvmDex* pDvmDex = method->clazz->pDvmDex;
+    const DexMethodId* pMethodId;
+    const char* className;
+    const char* methodName;
+
+    if (refType != VERIFY_ERROR_REF_METHOD) {
+        LOGW("Expected ref type %d, got %d\n", VERIFY_ERROR_REF_METHOD,refType);
+        return NULL;    /* no message */
+    }
+
+    pMethodId = dexGetMethodId(pDvmDex->pDexFile, ref);
+    className = dexStringByTypeIdx(pDvmDex->pDexFile, pMethodId->classIdx);
+    methodName = dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx);
+
+    char* dotName = dvmDescriptorToDot(className);
+    char* result = (char*) malloc(kBufLen);
+
+    if ((flags & kThrowShow_accessFromClass) != 0) {
+        char* dotFromName = dvmDescriptorToDot(method->clazz->descriptor);
+        char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
+        snprintf(result, kBufLen,
+            "tried to access method %s.%s:%s from class %s",
+            dotName, methodName, desc, dotFromName);
+        free(dotFromName);
+        free(desc);
+    } else {
+        snprintf(result, kBufLen, "%s.%s", dotName, methodName);
+    }
+
+    free(dotName);
+    return result;
+}
+
+/*
+ * Throw an exception for a problem identified by the verifier.
+ *
+ * This is used by the invoke-verification-error instruction.  It always
+ * throws an exception.
+ *
+ * "kind" indicates the kind of failure encountered by the verifier.  It
+ * has two parts, an error code and an indication of the reference type.
+ */
+void dvmThrowVerificationError(const Method* method, int kind, int ref)
+{
+    const int typeMask = 0xff << kVerifyErrorRefTypeShift;
+    VerifyError errorKind = kind & ~typeMask;
+    VerifyErrorRefType refType = kind >> kVerifyErrorRefTypeShift;
+    const char* exceptionName = "Ljava/lang/VerifyError;";
+    char* msg = NULL;
+
+    switch ((VerifyError) errorKind) {
+    case VERIFY_ERROR_NO_CLASS:
+        exceptionName = "Ljava/lang/NoClassDefFoundError;";
+        msg = classNameFromIndex(method, ref, refType, 0);
+        break;
+    case VERIFY_ERROR_NO_FIELD:
+        exceptionName = "Ljava/lang/NoSuchFieldError;";
+        msg = fieldNameFromIndex(method, ref, refType, 0);
+        break;
+    case VERIFY_ERROR_NO_METHOD:
+        exceptionName = "Ljava/lang/NoSuchMethodError;";
+        msg = methodNameFromIndex(method, ref, refType, 0);
+        break;
+    case VERIFY_ERROR_ACCESS_CLASS:
+        exceptionName = "Ljava/lang/IllegalAccessError;";
+        msg = classNameFromIndex(method, ref, refType,
+            kThrowShow_accessFromClass);
+        break;
+    case VERIFY_ERROR_ACCESS_FIELD:
+        exceptionName = "Ljava/lang/IllegalAccessError;";
+        msg = fieldNameFromIndex(method, ref, refType,
+            kThrowShow_accessFromClass);
+        break;
+    case VERIFY_ERROR_ACCESS_METHOD:
+        exceptionName = "Ljava/lang/IllegalAccessError;";
+        msg = methodNameFromIndex(method, ref, refType,
+            kThrowShow_accessFromClass);
+        break;
+    case VERIFY_ERROR_CLASS_CHANGE:
+        exceptionName = "Ljava/lang/IncompatibleClassChangeError;";
+        msg = classNameFromIndex(method, ref, refType, 0);
+        break;
+    case VERIFY_ERROR_INSTANTIATION:
+        exceptionName = "Ljava/lang/InstantiationError;";
+        msg = classNameFromIndex(method, ref, refType, 0);
+        break;
+
+    case VERIFY_ERROR_GENERIC:
+        /* generic VerifyError; use default exception, no message */
+        break;
+    case VERIFY_ERROR_NONE:
+        /* should never happen; use default exception */
+        assert(false);
+        msg = strdup("weird - no error specified");
+        break;
+
+    /* no default clause -- want warning if enum updated */
+    }
+
+    dvmThrowException(exceptionName, msg);
+    free(msg);
+}
+
 /*
  * Main interpreter loop entry point.  Select "standard" or "debug"
  * interpreter and switch between them as required.
@@ -649,6 +889,29 @@
 {
     InterpState interpState;
     bool change;
+#if defined(WITH_JIT)
+    /* Interpreter entry points from compiled code */
+    extern void dvmJitToInterpNormal();
+    extern void dvmJitToInterpNoChain();
+    extern void dvmJitToInterpPunt();
+    extern void dvmJitToInterpSingleStep();
+    extern void dvmJitToTraceSelect();
+    extern void dvmJitToPatchPredictedChain();
+
+    /*
+     * Reserve a static entity here to quickly setup runtime contents as
+     * gcc will issue block copy instructions.
+     */
+    static struct JitToInterpEntries jitToInterpEntries = {
+        dvmJitToInterpNormal,
+        dvmJitToInterpNoChain,
+        dvmJitToInterpPunt,
+        dvmJitToInterpSingleStep,
+        dvmJitToTraceSelect,
+        dvmJitToPatchPredictedChain,
+    };
+#endif
+
 
 #if defined(WITH_TRACKREF_CHECKS)
     interpState.debugTrackedRefStart =
@@ -657,6 +920,19 @@
 #if defined(WITH_PROFILER) || defined(WITH_DEBUGGER)
     interpState.debugIsMethodEntry = true;
 #endif
+#if defined(WITH_JIT)
+    interpState.jitState = gDvmJit.pJitEntryTable ? kJitNormal : kJitOff;
+
+    /* Setup the Jit-to-interpreter entry points */
+    interpState.jitToInterpEntries = jitToInterpEntries;
+
+    /*
+     * Initialize the threshold filter [don't bother to zero out the
+     * actual table.  We're looking for matches, and an occasional
+     * false positive is acceptible.
+     */
+    interpState.lastThreshFilter = 0;
+#endif
 
     /*
      * Initialize working state.
@@ -692,6 +968,14 @@
     Interpreter stdInterp;
     if (gDvm.executionMode == kExecutionModeInterpFast)
         stdInterp = dvmMterpStd;
+#if defined(WITH_JIT)
+    else if (gDvm.executionMode == kExecutionModeJit)
+/* If profiling overhead can be kept low enough, we can use a profiling
+ * mterp fast for both Jit and "fast" modes.  If overhead is too high,
+ * create a specialized profiling interpreter.
+ */
+        stdInterp = dvmMterpStd;
+#endif
     else
         stdInterp = dvmInterpretStd;
 
@@ -702,7 +986,7 @@
             LOGVV("threadid=%d: interp STD\n", self->threadId);
             change = (*stdInterp)(self, &interpState);
             break;
-#if defined(WITH_PROFILER) || defined(WITH_DEBUGGER)
+#if defined(WITH_PROFILER) || defined(WITH_DEBUGGER) || defined(WITH_JIT)
         case INTERP_DBG:
             LOGVV("threadid=%d: interp DBG\n", self->threadId);
             change = dvmInterpretDbg(self, &interpState);
@@ -715,4 +999,3 @@
 
     *pResult = interpState.retval;
 }
-
diff --git a/vm/interp/Interp.h b/vm/interp/Interp.h
index eb36b9f..cd4c7ec 100644
--- a/vm/interp/Interp.h
+++ b/vm/interp/Interp.h
@@ -26,6 +26,14 @@
 void dvmInterpret(Thread* thread, const Method* method, JValue* pResult);
 
 /*
+ * Throw an exception for a problem detected by the verifier.
+ *
+ * This is called from the handler for the throw-verification-error
+ * instruction.  "method" is the method currently being executed.
+ */
+void dvmThrowVerificationError(const Method* method, int kind, int ref);
+
+/*
  * Breakpoint optimization table.
  */
 void dvmInitBreakpoints();
diff --git a/vm/interp/InterpDefs.h b/vm/interp/InterpDefs.h
index 856c2f5..c9c80e3 100644
--- a/vm/interp/InterpDefs.h
+++ b/vm/interp/InterpDefs.h
@@ -32,8 +32,51 @@
     kInterpEntryInstr = 0,      // continue to next instruction
     kInterpEntryReturn = 1,     // jump to method return
     kInterpEntryThrow = 2,      // jump to exception throw
+#if defined(WITH_JIT)
+    kInterpEntryResume = 3,     // Resume after single-step
+#endif
 } InterpEntry;
 
+#if defined(WITH_JIT)
+/*
+ * There are six entry points from the compiled code to the interpreter:
+ * 1) dvmJitToInterpNormal: find if there is a corresponding compilation for
+ *    the new dalvik PC. If so, chain the originating compilation with the
+ *    target then jump to it.
+ * 2) dvmJitToInterpInvokeNoChain: similar to 1) but don't chain. This is
+ *    for handling 1-to-many mappings like virtual method call and
+ *    packed switch.
+ * 3) dvmJitToInterpPunt: use the fast interpreter to execute the next
+ *    instruction(s) and stay there as long as it is appropriate to return
+ *    to the compiled land. This is used when the jit'ed code is about to
+ *    throw an exception.
+ * 4) dvmJitToInterpSingleStep: use the portable interpreter to execute the
+ *    next instruction only and return to pre-specified location in the
+ *    compiled code to resume execution. This is mainly used as debugging
+ *    feature to bypass problematic opcode implementations without
+ *    disturbing the trace formation.
+ * 5) dvmJitToTraceSelect: if there is a single exit from a translation that
+ *    has already gone hot enough to be translated, we should assume that
+ *    the exit point should also be translated (this is a common case for
+ *    invokes).  This trace exit will first check for a chaining
+ *    opportunity, and if none is available will switch to the debug
+ *    interpreter immediately for trace selection (as if threshold had
+ *    just been reached).
+ * 6) dvmJitToPredictedChain: patch the chaining cell for a virtual call site
+ *    to a predicted callee.
+ */
+struct JitToInterpEntries {
+    void *dvmJitToInterpNormal;
+    void *dvmJitToInterpNoChain;
+    void *dvmJitToInterpPunt;
+    void *dvmJitToInterpSingleStep;
+    void *dvmJitToTraceSelect;
+    void *dvmJitToPatchPredictedChain;
+};
+
+#define JIT_TRACE_THRESH_FILTER_SIZE  16
+#endif
+
 /*
  * Interpreter context, used when switching from one interpreter to
  * another.  We also tuck "mterp" state in here.
@@ -66,7 +109,7 @@
     const u1*       interpStackEnd;
     volatile int*   pSelfSuspendCount;
 #if defined(WITH_DEBUGGER)
-    volatile bool*  pDebuggerActive;
+    volatile u1*    pDebuggerActive;
 #endif
 #if defined(WITH_PROFILER)
     volatile int*   pActiveProfilers;
@@ -78,8 +121,17 @@
      * Interpreter switching.
      */
     InterpEntry entryPoint;             // what to do when we start
-    int         nextMode;               // INTERP_STD or INTERP_DBG
+    int         nextMode;               // INTERP_STD, INTERP_DBG
 
+#if defined(WITH_JIT)
+    /*
+     * Local copies of field from gDvm placed here for fast access
+     */
+    unsigned char*     pJitProfTable;
+    JitState           jitState;
+    void*              jitResume;
+    u2*                jitResumePC;
+#endif
 
 #if defined(WITH_PROFILER) || defined(WITH_DEBUGGER)
     bool        debugIsMethodEntry;     // used for method entry event triggers
@@ -88,6 +140,19 @@
     int         debugTrackedRefStart;   // tracked refs from prior invocations
 #endif
 
+#if defined(WITH_JIT)
+    struct JitToInterpEntries jitToInterpEntries;
+
+    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
+    int currRunLen;           // Length of run in 16-bit words
+    int lastThreshFilter;
+    const u2* threshFilter[JIT_TRACE_THRESH_FILTER_SIZE];
+    JitTraceRun trace[MAX_JIT_RUN_LEN];
+#endif
+
 } InterpState;
 
 /*
@@ -123,7 +188,7 @@
 /*
  * Process fill-array-data.
  */
-bool dvmInterpHandleFillArrayData(ArrayObject* arrayObject, 
+bool dvmInterpHandleFillArrayData(ArrayObject* arrayObject,
                                   const u2* arrayData);
 
 /*
@@ -145,4 +210,19 @@
         ;
 }
 
+#if defined(WITH_JIT)
+/*
+ * Determine if the jit, debugger or profiler is currently active.  Used when
+ * selecting which interpreter to switch to.
+ */
+static inline bool dvmJitDebuggerOrProfilerActive(int jitState)
+{
+    return jitState != kJitOff
+#if defined(WITH_PROFILER)
+        || gDvm.activeProfilers != 0
+#endif
+        ||gDvm.debuggerActive;
+}
+#endif
+
 #endif /*_DALVIK_INTERP_DEFS*/
diff --git a/vm/interp/Jit.c b/vm/interp/Jit.c
new file mode 100644
index 0000000..2bcb1f5
--- /dev/null
+++ b/vm/interp/Jit.c
@@ -0,0 +1,701 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifdef WITH_JIT
+
+/*
+ * Target independent portion of Android's Jit
+ */
+
+#include "Dalvik.h"
+#include "Jit.h"
+
+
+#include "dexdump/OpCodeNames.h"
+#include <unistd.h>
+#include <pthread.h>
+#include <sys/time.h>
+#include <signal.h>
+#include "compiler/Compiler.h"
+#include "compiler/CompilerUtility.h"
+#include "compiler/CompilerIR.h"
+#include <errno.h>
+
+int dvmJitStartup(void)
+{
+    unsigned int i;
+    bool res = true;  /* Assume success */
+
+    // Create the compiler thread and setup miscellaneous chores */
+    res &= dvmCompilerStartup();
+
+    dvmInitMutex(&gDvmJit.tableLock);
+    if (res && gDvm.executionMode == kExecutionModeJit) {
+        JitEntry *pJitTable = NULL;
+        unsigned char *pJitProfTable = NULL;
+        assert(gDvm.jitTableSize &&
+            !(gDvm.jitTableSize & (gDvmJit.jitTableSize - 1))); // Power of 2?
+        dvmLockMutex(&gDvmJit.tableLock);
+        pJitTable = (JitEntry*)
+                    calloc(gDvmJit.jitTableSize, sizeof(*pJitTable));
+        if (!pJitTable) {
+            LOGE("jit table allocation failed\n");
+            res = false;
+            goto done;
+        }
+        /*
+         * NOTE: the profile table must only be allocated once, globally.
+         * Profiling is turned on and off by nulling out gDvm.pJitProfTable
+         * and then restoring its original value.  However, this action
+         * is not syncronized for speed so threads may continue to hold
+         * and update the profile table after profiling has been turned
+         * off by null'ng the global pointer.  Be aware.
+         */
+        pJitProfTable = (unsigned char *)malloc(JIT_PROF_SIZE);
+        if (!pJitProfTable) {
+            LOGE("jit prof table allocation failed\n");
+            res = false;
+            goto done;
+        }
+        memset(pJitProfTable,0,JIT_PROF_SIZE);
+        for (i=0; i < gDvmJit.jitTableSize; i++) {
+           pJitTable[i].u.info.chain = gDvmJit.jitTableSize;
+        }
+        /* Is chain field wide enough for termination pattern? */
+        assert(pJitTable[0].u.info.chain == gDvm.maxJitTableEntries);
+
+done:
+        gDvmJit.pJitEntryTable = pJitTable;
+        gDvmJit.jitTableMask = gDvmJit.jitTableSize - 1;
+        gDvmJit.jitTableEntriesUsed = 0;
+        gDvmJit.pProfTableCopy = gDvmJit.pProfTable = pJitProfTable;
+        dvmUnlockMutex(&gDvmJit.tableLock);
+    }
+    return res;
+}
+
+/*
+ * If one of our fixed tables or the translation buffer fills up,
+ * call this routine to avoid wasting cycles on future translation requests.
+ */
+void dvmJitStopTranslationRequests()
+{
+    /*
+     * Note 1: This won't necessarily stop all translation requests, and
+     * operates on a delayed mechanism.  Running threads look to the copy
+     * of this value in their private InterpState structures and won't see
+     * this change until it is refreshed (which happens on interpreter
+     * entry).
+     * Note 2: This is a one-shot memory leak on this table. Because this is a
+     * permanent off switch for Jit profiling, it is a one-time leak of 1K
+     * bytes, and no further attempt will be made to re-allocate it.  Can't
+     * free it because some thread may be holding a reference.
+     */
+    gDvmJit.pProfTable = gDvmJit.pProfTableCopy = NULL;
+}
+
+#if defined(EXIT_STATS)
+/* Convenience function to increment counter from assembly code */
+void dvmBumpNoChain()
+{
+    gDvm.jitNoChainExit++;
+}
+
+/* Convenience function to increment counter from assembly code */
+void dvmBumpNormal()
+{
+    gDvm.jitNormalExit++;
+}
+
+/* Convenience function to increment counter from assembly code */
+void dvmBumpPunt(int from)
+{
+    gDvm.jitPuntExit++;
+}
+#endif
+
+/* Dumps debugging & tuning stats to the log */
+void dvmJitStats()
+{
+    int i;
+    int hit;
+    int not_hit;
+    int chains;
+    if (gDvmJit.pJitEntryTable) {
+        for (i=0, chains=hit=not_hit=0;
+             i < (int) gDvmJit.jitTableSize;
+             i++) {
+            if (gDvmJit.pJitEntryTable[i].dPC != 0)
+                hit++;
+            else
+                not_hit++;
+            if (gDvmJit.pJitEntryTable[i].u.info.chain != gDvmJit.jitTableSize)
+                chains++;
+        }
+        LOGD(
+         "JIT: %d traces, %d slots, %d chains, %d maxQ, %d thresh, %s",
+         hit, not_hit + hit, chains, gDvmJit.compilerMaxQueued,
+         gDvmJit.threshold, gDvmJit.blockingMode ? "Blocking" : "Non-blocking");
+#if defined(EXIT_STATS)
+        LOGD(
+         "JIT: Lookups: %d hits, %d misses; %d NoChain, %d normal, %d punt",
+         gDvmJit.addrLookupsFound, gDvmJit.addrLookupsNotFound,
+         gDvmJit.noChainExit, gDvmJit.normalExit, gDvmJit.puntExit);
+#endif
+        LOGD("JIT: %d Translation chains", gDvmJit.translationChains);
+#if defined(INVOKE_STATS)
+        LOGD("JIT: Invoke: %d chainable, %d pred. chain, %d native, "
+             "%d return",
+             gDvmJit.invokeChain, gDvmJit.invokePredictedChain,
+             gDvmJit.invokeNative, gDvmJit.returnOp);
+#endif
+        if (gDvmJit.profile) {
+            dvmCompilerSortAndPrintTraceProfiles();
+        }
+    }
+}
+
+
+/*
+ * Final JIT shutdown.  Only do this once, and do not attempt to restart
+ * the JIT later.
+ */
+void dvmJitShutdown(void)
+{
+    /* Shutdown the compiler thread */
+    dvmCompilerShutdown();
+
+    dvmCompilerDumpStats();
+
+    dvmDestroyMutex(&gDvmJit.tableLock);
+
+    if (gDvmJit.pJitEntryTable) {
+        free(gDvmJit.pJitEntryTable);
+        gDvmJit.pJitEntryTable = NULL;
+    }
+
+    if (gDvmJit.pProfTable) {
+        free(gDvmJit.pProfTable);
+        gDvmJit.pProfTable = NULL;
+    }
+}
+
+/*
+ * Adds to the current trace request one instruction at a time, just
+ * before that instruction is interpreted.  This is the primary trace
+ * selection function.  NOTE: return instruction are handled a little
+ * differently.  In general, instructions are "proposed" to be added
+ * to the current trace prior to interpretation.  If the interpreter
+ * then successfully completes the instruction, is will be considered
+ * part of the request.  This allows us to examine machine state prior
+ * to interpretation, and also abort the trace request if the instruction
+ * throws or does something unexpected.  However, return instructions
+ * will cause an immediate end to the translation request - which will
+ * be passed to the compiler before the return completes.  This is done
+ * in response to special handling of returns by the interpreter (and
+ * because returns cannot throw in a way that causes problems for the
+ * translated code.
+ */
+int dvmCheckJit(const u2* pc, Thread* self, InterpState* interpState)
+{
+    int flags,i,len;
+    int switchInterp = false;
+    int debugOrProfile = (gDvm.debuggerActive || self->suspendCount
+#if defined(WITH_PROFILER)
+                          || gDvm.activeProfilers
+#endif
+            );
+
+    switch (interpState->jitState) {
+        char* nopStr;
+        int target;
+        int offset;
+        DecodedInstruction decInsn;
+        case kJitTSelect:
+            dexDecodeInstruction(gDvm.instrFormat, pc, &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) {
+                int currTraceRun;
+                /* We need to start a new trace run */
+                currTraceRun = ++interpState->currTraceRun;
+                interpState->currRunLen = 0;
+                interpState->currRunHead = (u2*)pc;
+                interpState->trace[currTraceRun].frag.startOffset = offset;
+                interpState->trace[currTraceRun].frag.numInsts = 0;
+                interpState->trace[currTraceRun].frag.runEnd = false;
+                interpState->trace[currTraceRun].frag.hint = kJitHintNone;
+            }
+            interpState->trace[interpState->currTraceRun].frag.numInsts++;
+            interpState->totalTraceLen++;
+            interpState->currRunLen += len;
+            if (  ((flags & kInstrUnconditional) == 0) &&
+                  /* don't end trace on INVOKE_DIRECT_EMPTY  */
+                  (decInsn.opCode != OP_INVOKE_DIRECT_EMPTY) &&
+                  ((flags & (kInstrCanBranch |
+                             kInstrCanSwitch |
+                             kInstrCanReturn |
+                             kInstrInvoke)) != 0)) {
+                    interpState->jitState = kJitTSelectEnd;
+#if defined(SHOW_TRACE)
+            LOGD("TraceGen: ending on %s, basic block end",
+                 getOpcodeName(decInsn.opCode));
+#endif
+            }
+            if (decInsn.opCode == OP_THROW) {
+                interpState->jitState = kJitTSelectEnd;
+            }
+            if (interpState->totalTraceLen >= JIT_MAX_TRACE_LEN) {
+                interpState->jitState = kJitTSelectEnd;
+            }
+            if (debugOrProfile) {
+                interpState->jitState = kJitTSelectAbort;
+                switchInterp = !debugOrProfile;
+                break;
+            }
+            if ((flags & kInstrCanReturn) != kInstrCanReturn) {
+                break;
+            }
+            /* NOTE: intentional fallthrough for returns */
+        case kJitTSelectEnd:
+            {
+                if (interpState->totalTraceLen == 0) {
+                    switchInterp = !debugOrProfile;
+                    break;
+                }
+                JitTraceDescription* desc =
+                   (JitTraceDescription*)malloc(sizeof(JitTraceDescription) +
+                     sizeof(JitTraceRun) * (interpState->currTraceRun+1));
+                if (desc == NULL) {
+                    LOGE("Out of memory in trace selection");
+                    dvmJitStopTranslationRequests();
+                    interpState->jitState = kJitTSelectAbort;
+                    switchInterp = !debugOrProfile;
+                    break;
+                }
+                interpState->trace[interpState->currTraceRun].frag.runEnd =
+                     true;
+                interpState->jitState = kJitNormal;
+                desc->method = interpState->method;
+                memcpy((char*)&(desc->trace[0]),
+                    (char*)&(interpState->trace[0]),
+                    sizeof(JitTraceRun) * (interpState->currTraceRun+1));
+#if defined(SHOW_TRACE)
+                LOGD("TraceGen:  trace done, adding to queue");
+#endif
+                dvmCompilerWorkEnqueue(
+                       interpState->currTraceHead,kWorkOrderTrace,desc);
+                if (gDvmJit.blockingMode) {
+                    dvmCompilerDrainQueue();
+                }
+                switchInterp = !debugOrProfile;
+            }
+            break;
+        case kJitSingleStep:
+            interpState->jitState = kJitSingleStepEnd;
+            break;
+        case kJitSingleStepEnd:
+            interpState->entryPoint = kInterpEntryResume;
+            switchInterp = !debugOrProfile;
+            break;
+        case kJitTSelectAbort:
+#if defined(SHOW_TRACE)
+            LOGD("TraceGen:  trace abort");
+#endif
+            interpState->jitState = kJitNormal;
+            switchInterp = !debugOrProfile;
+            break;
+        case kJitNormal:
+            switchInterp = !debugOrProfile;
+            break;
+        default:
+            dvmAbort();
+    }
+    return switchInterp;
+}
+
+static inline JitEntry *findJitEntry(const u2* pc)
+{
+    int idx = dvmJitHash(pc);
+
+    /* Expect a high hit rate on 1st shot */
+    if (gDvmJit.pJitEntryTable[idx].dPC == pc)
+        return &gDvmJit.pJitEntryTable[idx];
+    else {
+        int chainEndMarker = gDvmJit.jitTableSize;
+        while (gDvmJit.pJitEntryTable[idx].u.info.chain != chainEndMarker) {
+            idx = gDvmJit.pJitEntryTable[idx].u.info.chain;
+            if (gDvmJit.pJitEntryTable[idx].dPC == pc)
+                return &gDvmJit.pJitEntryTable[idx];
+        }
+    }
+    return NULL;
+}
+
+JitEntry *dvmFindJitEntry(const u2* pc)
+{
+    return findJitEntry(pc);
+}
+
+/*
+ * If a translated code address exists for the davik byte code
+ * pointer return it.  This routine needs to be fast.
+ */
+void* dvmJitGetCodeAddr(const u2* dPC)
+{
+    int idx = dvmJitHash(dPC);
+
+    /* If anything is suspended, don't re-enter the code cache */
+    if (gDvm.sumThreadSuspendCount > 0) {
+        return NULL;
+    }
+
+    /* Expect a high hit rate on 1st shot */
+    if (gDvmJit.pJitEntryTable[idx].dPC == dPC) {
+#if defined(EXIT_STATS)
+        gDvmJit.addrLookupsFound++;
+#endif
+        return gDvmJit.pJitEntryTable[idx].codeAddress;
+    } else {
+        int chainEndMarker = gDvmJit.jitTableSize;
+        while (gDvmJit.pJitEntryTable[idx].u.info.chain != chainEndMarker) {
+            idx = gDvmJit.pJitEntryTable[idx].u.info.chain;
+            if (gDvmJit.pJitEntryTable[idx].dPC == dPC) {
+#if defined(EXIT_STATS)
+                gDvmJit.addrLookupsFound++;
+#endif
+                return gDvmJit.pJitEntryTable[idx].codeAddress;
+            }
+        }
+    }
+#if defined(EXIT_STATS)
+    gDvmJit.addrLookupsNotFound++;
+#endif
+    return NULL;
+}
+
+/*
+ * Find an entry in the JitTable, creating if necessary.
+ * Returns null if table is full.
+ */
+JitEntry *dvmJitLookupAndAdd(const u2* dPC)
+{
+    u4 chainEndMarker = gDvmJit.jitTableSize;
+    u4 idx = dvmJitHash(dPC);
+
+    /* Walk the bucket chain to find an exact match for our PC */
+    while ((gDvmJit.pJitEntryTable[idx].u.info.chain != chainEndMarker) &&
+           (gDvmJit.pJitEntryTable[idx].dPC != dPC)) {
+        idx = gDvmJit.pJitEntryTable[idx].u.info.chain;
+    }
+
+    if (gDvmJit.pJitEntryTable[idx].dPC != dPC) {
+        /*
+         * No match.  Aquire jitTableLock and find the last
+         * slot in the chain. Possibly continue the chain walk in case
+         * some other thread allocated the slot we were looking
+         * at previuosly (perhaps even the dPC we're trying to enter).
+         */
+        dvmLockMutex(&gDvmJit.tableLock);
+        /*
+         * At this point, if .dPC is NULL, then the slot we're
+         * looking at is the target slot from the primary hash
+         * (the simple, and common case).  Otherwise we're going
+         * to have to find a free slot and chain it.
+         */
+        MEM_BARRIER(); /* Make sure we reload [].dPC after lock */
+        if (gDvmJit.pJitEntryTable[idx].dPC != NULL) {
+            u4 prev;
+            while (gDvmJit.pJitEntryTable[idx].u.info.chain != chainEndMarker) {
+                if (gDvmJit.pJitEntryTable[idx].dPC == dPC) {
+                    /* Another thread got there first for this dPC */
+                    dvmUnlockMutex(&gDvmJit.tableLock);
+                    return &gDvmJit.pJitEntryTable[idx];
+                }
+                idx = gDvmJit.pJitEntryTable[idx].u.info.chain;
+            }
+            /* Here, idx should be pointing to the last cell of an
+             * active chain whose last member contains a valid dPC */
+            assert(gDvmJit.pJitEntryTable[idx].dPC != NULL);
+            /* Linear walk to find a free cell and add it to the end */
+            prev = idx;
+            while (true) {
+                idx++;
+                if (idx == chainEndMarker)
+                    idx = 0;  /* Wraparound */
+                if ((gDvmJit.pJitEntryTable[idx].dPC == NULL) ||
+                    (idx == prev))
+                    break;
+            }
+            if (idx != prev) {
+                JitEntryInfoUnion oldValue;
+                JitEntryInfoUnion newValue;
+                /*
+                 * Although we hold the lock so that noone else will
+                 * be trying to update a chain field, the other fields
+                 * packed into the word may be in use by other threads.
+                 */
+                do {
+                    oldValue = gDvmJit.pJitEntryTable[prev].u;
+                    newValue = oldValue;
+                    newValue.info.chain = idx;
+                } while (!ATOMIC_CMP_SWAP(
+                         &gDvmJit.pJitEntryTable[prev].u.infoWord,
+                         oldValue.infoWord, newValue.infoWord));
+            }
+        }
+        if (gDvmJit.pJitEntryTable[idx].dPC == NULL) {
+           /* Allocate the slot */
+            gDvmJit.pJitEntryTable[idx].dPC = dPC;
+            gDvmJit.jitTableEntriesUsed++;
+        } else {
+            /* Table is full */
+            idx = chainEndMarker;
+        }
+        dvmUnlockMutex(&gDvmJit.tableLock);
+    }
+    return (idx == chainEndMarker) ? NULL : &gDvmJit.pJitEntryTable[idx];
+}
+/*
+ * Register the translated code pointer into the JitTable.
+ * NOTE: Once a codeAddress field transitions from NULL to
+ * JIT'd code, it must not be altered without first halting all
+ * threads.  This routine should only be called by the compiler
+ * thread.
+ */
+void dvmJitSetCodeAddr(const u2* dPC, void *nPC, JitInstructionSetType set) {
+    JitEntryInfoUnion oldValue;
+    JitEntryInfoUnion newValue;
+    JitEntry *jitEntry = dvmJitLookupAndAdd(dPC);
+    assert(jitEntry);
+    /* Note: order of update is important */
+    do {
+        oldValue = jitEntry->u;
+        newValue = oldValue;
+        newValue.info.instructionSet = set;
+    } while (!ATOMIC_CMP_SWAP(
+             &jitEntry->u.infoWord,
+             oldValue.infoWord, newValue.infoWord));
+    jitEntry->codeAddress = nPC;
+}
+
+/*
+ * Determine if valid trace-bulding request is active.  Return true
+ * if we need to abort and switch back to the fast interpreter, false
+ * otherwise.  NOTE: may be called even when trace selection is not being
+ * requested
+ */
+
+bool dvmJitCheckTraceRequest(Thread* self, InterpState* interpState)
+{
+    bool res = false;         /* Assume success */
+    int i;
+    if (gDvmJit.pJitEntryTable != NULL) {
+        /* Two-level filtering scheme */
+        for (i=0; i< JIT_TRACE_THRESH_FILTER_SIZE; i++) {
+            if (interpState->pc == interpState->threshFilter[i]) {
+                break;
+            }
+        }
+        if (i == JIT_TRACE_THRESH_FILTER_SIZE) {
+            /*
+             * Use random replacement policy - otherwise we could miss a large
+             * loop that contains more traces than the size of our filter array.
+             */
+            i = rand() % JIT_TRACE_THRESH_FILTER_SIZE;
+            interpState->threshFilter[i] = interpState->pc;
+            res = true;
+        }
+        /*
+         * If the compiler is backlogged, or if a debugger or profiler is
+         * active, cancel any JIT actions
+         */
+        if ( res || (gDvmJit.compilerQueueLength >= gDvmJit.compilerHighWater) ||
+              gDvm.debuggerActive || self->suspendCount
+#if defined(WITH_PROFILER)
+                 || gDvm.activeProfilers
+#endif
+                                             ) {
+            if (interpState->jitState != kJitOff) {
+                interpState->jitState = kJitNormal;
+            }
+        } else if (interpState->jitState == kJitTSelectRequest) {
+            JitEntry *slot = dvmJitLookupAndAdd(interpState->pc);
+            if (slot == NULL) {
+                /*
+                 * Table is full.  This should have been
+                 * detected by the compiler thread and the table
+                 * resized before we run into it here.  Assume bad things
+                 * are afoot and disable profiling.
+                 */
+                interpState->jitState = kJitTSelectAbort;
+                LOGD("JIT: JitTable full, disabling profiling");
+                dvmJitStopTranslationRequests();
+            } else if (slot->u.info.traceRequested) {
+                /* Trace already requested - revert to interpreter */
+                interpState->jitState = kJitTSelectAbort;
+            } else {
+                /* Mark request */
+                JitEntryInfoUnion oldValue;
+                JitEntryInfoUnion newValue;
+                do {
+                    oldValue = slot->u;
+                    newValue = oldValue;
+                    newValue.info.traceRequested = true;
+                } while (!ATOMIC_CMP_SWAP( &slot->u.infoWord,
+                         oldValue.infoWord, newValue.infoWord));
+            }
+        }
+        switch (interpState->jitState) {
+            case kJitTSelectRequest:
+                 interpState->jitState = kJitTSelect;
+                 interpState->currTraceHead = interpState->pc;
+                 interpState->currTraceRun = 0;
+                 interpState->totalTraceLen = 0;
+                 interpState->currRunHead = interpState->pc;
+                 interpState->currRunLen = 0;
+                 interpState->trace[0].frag.startOffset =
+                       interpState->pc - interpState->method->insns;
+                 interpState->trace[0].frag.numInsts = 0;
+                 interpState->trace[0].frag.runEnd = false;
+                 interpState->trace[0].frag.hint = kJitHintNone;
+                 break;
+            case kJitTSelect:
+            case kJitTSelectAbort:
+                 res = true;
+            case kJitSingleStep:
+            case kJitSingleStepEnd:
+            case kJitOff:
+            case kJitNormal:
+                break;
+            default:
+                dvmAbort();
+        }
+    }
+    return res;
+}
+
+/*
+ * Resizes the JitTable.  Must be a power of 2, and returns true on failure.
+ * Stops all threads, and thus is a heavyweight operation.
+ */
+bool dvmJitResizeJitTable( unsigned int size )
+{
+    JitEntry *pNewTable;
+    JitEntry *pOldTable;
+    u4 newMask;
+    unsigned int oldSize;
+    unsigned int i;
+
+    assert(gDvm.pJitEntryTable != NULL);
+    assert(size && !(size & (size - 1)));   /* Is power of 2? */
+
+    LOGD("Jit: resizing JitTable from %d to %d", gDvmJit.jitTableSize, size);
+
+    newMask = size - 1;
+
+    if (size <= gDvmJit.jitTableSize) {
+        return true;
+    }
+
+    pNewTable = (JitEntry*)calloc(size, sizeof(*pNewTable));
+    if (pNewTable == NULL) {
+        return true;
+    }
+    for (i=0; i< size; i++) {
+        pNewTable[i].u.info.chain = size;  /* Initialize chain termination */
+    }
+
+    /* Stop all other interpreting/jit'ng threads */
+    dvmSuspendAllThreads(SUSPEND_FOR_JIT);
+
+    pOldTable = gDvmJit.pJitEntryTable;
+    oldSize = gDvmJit.jitTableSize;
+
+    dvmLockMutex(&gDvmJit.tableLock);
+    gDvmJit.pJitEntryTable = pNewTable;
+    gDvmJit.jitTableSize = size;
+    gDvmJit.jitTableMask = size - 1;
+    gDvmJit.jitTableEntriesUsed = 0;
+    dvmUnlockMutex(&gDvmJit.tableLock);
+
+    for (i=0; i < oldSize; i++) {
+        if (pOldTable[i].dPC) {
+            JitEntry *p;
+            u2 chain;
+            p = dvmJitLookupAndAdd(pOldTable[i].dPC);
+            p->dPC = pOldTable[i].dPC;
+            /*
+             * Compiler thread may have just updated the new entry's
+             * code address field, so don't blindly copy null.
+             */
+            if (pOldTable[i].codeAddress != NULL) {
+                p->codeAddress = pOldTable[i].codeAddress;
+            }
+            /* We need to preserve the new chain field, but copy the rest */
+            dvmLockMutex(&gDvmJit.tableLock);
+            chain = p->u.info.chain;
+            p->u = pOldTable[i].u;
+            p->u.info.chain = chain;
+            dvmUnlockMutex(&gDvmJit.tableLock);
+        }
+    }
+
+    free(pOldTable);
+
+    /* Restart the world */
+    dvmResumeAllThreads(SUSPEND_FOR_JIT);
+
+    return false;
+}
+
+/*
+ * Float/double conversion requires clamping to min and max of integer form.  If
+ * target doesn't support this normally, use these.
+ */
+s8 dvmJitd2l(double d)
+{
+    static const double kMaxLong = (double)(s8)0x7fffffffffffffffULL;
+    static const double kMinLong = (double)(s8)0x8000000000000000ULL;
+    if (d >= kMaxLong)
+        return (s8)0x7fffffffffffffffULL;
+    else if (d <= kMinLong)
+        return (s8)0x8000000000000000ULL;
+    else if (d != d) // NaN case
+        return 0;
+    else
+        return (s8)d;
+}
+
+s8 dvmJitf2l(float f)
+{
+    static const float kMaxLong = (float)(s8)0x7fffffffffffffffULL;
+    static const float kMinLong = (float)(s8)0x8000000000000000ULL;
+    if (f >= kMaxLong)
+        return (s8)0x7fffffffffffffffULL;
+    else if (f <= kMinLong)
+        return (s8)0x8000000000000000ULL;
+    else if (f != f) // NaN case
+        return 0;
+    else
+        return (s8)f;
+}
+
+
+#endif /* WITH_JIT */
diff --git a/vm/interp/Jit.h b/vm/interp/Jit.h
new file mode 100644
index 0000000..660b5ec
--- /dev/null
+++ b/vm/interp/Jit.h
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+/*
+ * Jit control
+ */
+#ifndef _DALVIK_INTERP_JIT
+#define _DALVIK_INTERP_JIT
+
+#include "InterpDefs.h"
+
+#define JIT_PROF_SIZE 512
+
+#define JIT_MAX_TRACE_LEN 100
+
+/*
+ * JitTable hash function.
+ */
+
+static inline u4 dvmJitHashMask( const u2* p, u4 mask ) {
+    return ((((u4)p>>12)^(u4)p)>>1) & (mask);
+}
+
+static inline u4 dvmJitHash( const u2* p ) {
+    return dvmJitHashMask( p, gDvmJit.jitTableMask );
+}
+
+/*
+ * Entries in the JIT's address lookup hash table.
+ * Fields which may be updated by multiple threads packed into a
+ * single 32-bit word to allow use of atomic update.
+ */
+
+typedef struct JitEntryInfo {
+    unsigned int           traceRequested:1;   /* already requested a translation */
+    unsigned int           isMethodEntry:1;
+    unsigned int           inlineCandidate:1;
+    unsigned int           profileEnabled:1;
+    JitInstructionSetType  instructionSet:4;
+    unsigned int           unused:8;
+    u2                     chain;              /* Index of next in chain */
+} JitEntryInfo;
+
+typedef union JitEntryInfoUnion {
+    JitEntryInfo info;
+    volatile int infoWord;
+} JitEntryInfoUnion;
+
+typedef struct JitEntry {
+    JitEntryInfoUnion u;
+    u2                chain;              /* Index of next in chain */
+    const u2*         dPC;                /* Dalvik code address */
+    void*             codeAddress;        /* Code address of native translation */
+} JitEntry;
+
+int dvmJitStartup(void);
+void dvmJitShutdown(void);
+int dvmCheckJit(const u2* pc, Thread* self, InterpState* interpState);
+void* dvmJitGetCodeAddr(const u2* dPC);
+bool dvmJitCheckTraceRequest(Thread* self, InterpState* interpState);
+void dvmJitStopTranslationRequests(void);
+void dvmJitStats(void);
+bool dvmJitResizeJitTable(unsigned int size);
+struct JitEntry *dvmFindJitEntry(const u2* pc);
+s8 dvmJitd2l(double d);
+s8 dvmJitf2l(float f);
+void dvmJitSetCodeAddr(const u2* dPC, void *nPC, JitInstructionSetType set);
+
+
+#endif /*_DALVIK_INTERP_JIT*/
diff --git a/vm/interp/Stack.c b/vm/interp/Stack.c
index 6f418fd..5920cbc 100644
--- a/vm/interp/Stack.c
+++ b/vm/interp/Stack.c
@@ -76,9 +76,10 @@
 
     if (stackPtr - stackReq < self->interpStackEnd) {
         /* not enough space */
-        LOGW("Stack overflow on call to interp (top=%p cur=%p size=%d %s.%s)\n",
-            self->interpStackStart, self->curFrame, self->interpStackSize,
-            method->clazz->descriptor, method->name);
+        LOGW("Stack overflow on call to interp "
+             "(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);
         assert(dvmCheckException(self));
         return false;
@@ -104,7 +105,7 @@
 
     breakSaveBlock->prevFrame = self->curFrame;
     breakSaveBlock->savedPc = NULL;             // not required
-    breakSaveBlock->xtra.localRefTop = NULL;    // not required
+    breakSaveBlock->xtra.localRefCookie = 0;    // not required
     breakSaveBlock->method = NULL;
     saveBlock->prevFrame = FP_FROM_SAVEAREA(breakSaveBlock);
     saveBlock->savedPc = NULL;                  // not required
@@ -148,9 +149,10 @@
 
     if (stackPtr - stackReq < self->interpStackEnd) {
         /* not enough space */
-        LOGW("Stack overflow on call to native (top=%p cur=%p size=%d '%s')\n",
-            self->interpStackStart, self->curFrame, self->interpStackSize,
-            method->name);
+        LOGW("Stack overflow on call to native "
+             "(req=%d top=%p cur=%p size=%d '%s')\n",
+            stackReq, self->interpStackStart, self->curFrame,
+            self->interpStackSize, method->name);
         dvmHandleStackOverflow(self);
         assert(dvmCheckException(self));
         return false;
@@ -180,11 +182,15 @@
 
     breakSaveBlock->prevFrame = self->curFrame;
     breakSaveBlock->savedPc = NULL;             // not required
-    breakSaveBlock->xtra.localRefTop = NULL;    // not required
+    breakSaveBlock->xtra.localRefCookie = 0;    // not required
     breakSaveBlock->method = NULL;
     saveBlock->prevFrame = FP_FROM_SAVEAREA(breakSaveBlock);
     saveBlock->savedPc = NULL;                  // not required
-    saveBlock->xtra.localRefTop = self->jniLocalRefTable.nextEntry;
+#ifdef USE_INDIRECT_REF
+    saveBlock->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
+#else
+    saveBlock->xtra.localRefCookie = self->jniLocalRefTable.nextEntry;
+#endif
     saveBlock->method = method;
 
     LOGVV("PUSH JNI frame: old=%p new=%p (size=%d)\n",
@@ -217,9 +223,10 @@
 
     if (stackPtr - stackReq < self->interpStackEnd) {
         /* not enough space; let JNI throw the exception */
-        LOGW("Stack overflow on PushLocal (top=%p cur=%p size=%d '%s')\n",
-            self->interpStackStart, self->curFrame, self->interpStackSize,
-            method->name);
+        LOGW("Stack overflow on PushLocal "
+             "(req=%d top=%p cur=%p size=%d '%s')\n",
+            stackReq, self->interpStackStart, self->curFrame,
+            self->interpStackSize, method->name);
         dvmHandleStackOverflow(self);
         assert(dvmCheckException(self));
         return false;
@@ -242,7 +249,11 @@
 
     saveBlock->prevFrame = self->curFrame;
     saveBlock->savedPc = NULL;                  // not required
-    saveBlock->xtra.localRefTop = self->jniLocalRefTable.nextEntry;
+#ifdef USE_INDIRECT_REF
+    saveBlock->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
+#else
+    saveBlock->xtra.localRefCookie = self->jniLocalRefTable.nextEntry;
+#endif
     saveBlock->method = method;
 
     LOGVV("PUSH JNI local frame: old=%p new=%p (size=%d)\n",
@@ -317,9 +328,9 @@
                 saveBlock->method->name,
                 (SAVEAREA_FROM_FP(saveBlock->prevFrame)->method == NULL) ?
                 "" : " (JNI local)");
-            assert(saveBlock->xtra.localRefTop != NULL);
-            assert(saveBlock->xtra.localRefTop >=self->jniLocalRefTable.table &&
-                saveBlock->xtra.localRefTop <=self->jniLocalRefTable.nextEntry);
+            assert(saveBlock->xtra.localRefCookie != 0);
+            //assert(saveBlock->xtra.localRefCookie >= self->jniLocalRefTable.table &&
+            //    saveBlock->xtra.localRefCookie <=self->jniLocalRefTable.nextEntry);
 
             dvmPopJniLocals(self, saveBlock);
         }
@@ -421,7 +432,7 @@
 
     va_list args;
     va_start(args, pResult);
-    dvmCallMethodV(self, method, obj, pResult, args);
+    dvmCallMethodV(self, method, obj, false, pResult, args);
     va_end(args);
 }
 
@@ -435,7 +446,7 @@
  * we don't need to worry about static synchronized methods.
  */
 void dvmCallMethodV(Thread* self, const Method* method, Object* obj,
-    JValue* pResult, va_list args)
+    bool fromJni, JValue* pResult, va_list args)
 {
     const char* desc = &(method->shorty[1]); // [0] is the return type.
     int verifyCount = 0;
@@ -460,6 +471,7 @@
         verifyCount++;
     }
 
+    JNIEnv* env = self->jniEnv;
     while (*desc != '\0') {
         switch (*(desc++)) {
             case 'D': case 'J': {
@@ -476,16 +488,18 @@
                 verifyCount++;
                 break;
             }
-#ifdef WITH_EXTRA_OBJECT_VALIDATION
             case 'L': {     /* 'shorty' descr uses L for all refs, incl array */
-                Object* argObj = (Object*) va_arg(args, u4);
+                void* argObj = va_arg(args, void*);
                 assert(obj == NULL || dvmIsValidObject(obj));
-                *ins++ = (u4) argObj;
+                if (fromJni)
+                    *ins++ = (u4) dvmDecodeIndirectRef(env, argObj);
+                else
+                    *ins++ = (u4) argObj;
                 verifyCount++;
                 break;
             }
-#endif
             default: {
+                /* Z B C S I -- all passed as 32-bit integers */
                 *ins++ = va_arg(args, u4);
                 verifyCount++;
                 break;
@@ -505,11 +519,17 @@
     //dvmDumpThreadStack(dvmThreadSelf());
 
     if (dvmIsNativeMethod(method)) {
+#ifdef WITH_PROFILER
+        TRACE_METHOD_ENTER(self, method);
+#endif
         /*
          * Because we leave no space for local variables, "curFrame" points
          * directly at the method arguments.
          */
         (*method->nativeFunc)(self->curFrame, pResult, method, self);
+#ifdef WITH_PROFILER
+        TRACE_METHOD_EXIT(self, method);
+#endif
     } else {
         dvmInterpret(self, method, pResult);
     }
@@ -532,7 +552,7 @@
  * "args" may be NULL if the method has no arguments.
  */
 void dvmCallMethodA(Thread* self, const Method* method, Object* obj,
-    JValue* pResult, const jvalue* args)
+    bool fromJni, JValue* pResult, const jvalue* args)
 {
     const char* desc = &(method->shorty[1]); // [0] is the return type.
     int verifyCount = 0;
@@ -549,56 +569,50 @@
     /* put "this" pointer into in0 if appropriate */
     if (!dvmIsStaticMethod(method)) {
         assert(obj != NULL);
-        *ins++ = (u4) obj;
+        *ins++ = (u4) obj;              /* obj is a "real" ref */
         verifyCount++;
     }
 
+    JNIEnv* env = self->jniEnv;
     while (*desc != '\0') {
-        switch (*(desc++)) {
-            case 'D': case 'J': {
-                memcpy(ins, &args->j, 8);   /* EABI prevents direct store */
-                ins += 2;
-                verifyCount += 2;
-                args++;
-                break;
-            }
-            case 'F': case 'I': case 'L': { /* (no '[' in short signatures) */
-                *ins++ = args->i;           /* get all 32 bits */
-                verifyCount++;
-                args++;
-                break;
-            }
-            case 'S': {
-                *ins++ = args->s;           /* 16 bits, sign-extended */
-                verifyCount++;
-                args++;
-                break;
-            }
-            case 'C': {
-                *ins++ = args->c;           /* 16 bits, unsigned */
-                verifyCount++;
-                args++;
-                break;
-            }
-            case 'B': {
-                *ins++ = args->b;           /* 8 bits, sign-extended */
-                verifyCount++;
-                args++;
-                break;
-            }
-            case 'Z': {
-                *ins++ = args->z;           /* 8 bits, zero or non-zero */
-                verifyCount++;
-                args++;
-                break;
-            }
-            default: {
-                LOGE("Invalid char %c in short signature of %s.%s\n",
-                    *(desc-1), clazz->descriptor, method->name);
-                assert(false);
-                goto bail;
-            }
+        switch (*desc++) {
+        case 'D':                       /* 64-bit quantity; have to use */
+        case 'J':                       /*  memcpy() in case of mis-alignment */
+            memcpy(ins, &args->j, 8);
+            ins += 2;
+            verifyCount++;              /* this needs an extra push */
+            break;
+        case 'L':                       /* includes array refs */
+            if (fromJni)
+                *ins++ = (u4) dvmDecodeIndirectRef(env, args->l);
+            else
+                *ins++ = (u4) args->l;
+            break;
+        case 'F':
+        case 'I':
+            *ins++ = args->i;           /* full 32 bits */
+            break;
+        case 'S':
+            *ins++ = args->s;           /* 16 bits, sign-extended */
+            break;
+        case 'C':
+            *ins++ = args->c;           /* 16 bits, unsigned */
+            break;
+        case 'B':
+            *ins++ = args->b;           /* 8 bits, sign-extended */
+            break;
+        case 'Z':
+            *ins++ = args->z;           /* 8 bits, zero or non-zero */
+            break;
+        default:
+            LOGE("Invalid char %c in short signature of %s.%s\n",
+                *(desc-1), clazz->descriptor, method->name);
+            assert(false);
+            goto bail;
         }
+
+        verifyCount++;
+        args++;
     }
 
 #ifndef NDEBUG
@@ -611,11 +625,17 @@
 #endif
 
     if (dvmIsNativeMethod(method)) {
+#ifdef WITH_PROFILER
+        TRACE_METHOD_ENTER(self, method);
+#endif
         /*
          * Because we leave no space for local variables, "curFrame" points
          * directly at the method arguments.
          */
         (*method->nativeFunc)(self->curFrame, pResult, method, self);
+#ifdef WITH_PROFILER
+        TRACE_METHOD_EXIT(self, method);
+#endif
     } else {
         dvmInterpret(self, method, pResult);
     }
@@ -715,11 +735,17 @@
     //dvmDumpThreadStack(dvmThreadSelf());
 
     if (dvmIsNativeMethod(method)) {
+#ifdef WITH_PROFILER
+        TRACE_METHOD_ENTER(self, method);
+#endif
         /*
          * Because we leave no space for local variables, "curFrame" points
          * directly at the method arguments.
          */
         (*method->nativeFunc)(self->curFrame, &retval, method, self);
+#ifdef WITH_PROFILER
+        TRACE_METHOD_EXIT(self, method);
+#endif
     } else {
         dvmInterpret(self, method, &retval);
     }
@@ -1137,11 +1163,15 @@
 
         first = false;
 
-        assert(framePtr != saveArea->prevFrame);
+        if (saveArea->prevFrame != NULL && saveArea->prevFrame <= framePtr) {
+            LOGW("Warning: loop in stack trace at frame %d (%p -> %p)\n",
+                checkCount, framePtr, saveArea->prevFrame);
+            break;
+        }
         framePtr = saveArea->prevFrame;
 
         checkCount++;
-        if (checkCount > 200) {
+        if (checkCount > 300) {
             dvmPrintDebugMessage(target,
                 "  ***** printed %d frames, not showing any more\n",
                 checkCount);
diff --git a/vm/interp/Stack.h b/vm/interp/Stack.h
index 1b28d49..22f066f 100644
--- a/vm/interp/Stack.h
+++ b/vm/interp/Stack.h
@@ -138,14 +138,20 @@
     const Method* method;
 
     union {
-        /* for JNI native methods: top of local reference storage */
-        Object**    localRefTop;
+        /* for JNI native methods: bottom of local reference segment */
+#ifdef USE_INDIRECT_REF
+        u4          localRefCookie;
+#else
+        Object**    localRefCookie;
+#endif
 
         /* for interpreted methods: saved current PC, for exception stack
          * traces and debugger traces */
         const u2*   currentPc;
     } xtra;
 
+    /* Native return pointer for JIT, or 0 if interpreted */
+    const u2* returnAddr;
 #ifdef PAD_SAVE_AREA
     u4          pad3, pad4, pad5;
 #endif
@@ -189,16 +195,18 @@
 bool dvmPopLocalFrame(Thread* thread);
 
 /*
- * Call an interpreted method from native code.
+ * Call an interpreted method from native code.  If this is being called
+ * from a JNI function, references in the argument list will be converted
+ * back to pointers.
  *
  * "obj" should be NULL for "direct" methods.
  */
-void dvmCallMethodV(Thread* self, const Method* method, Object* obj,
-    JValue* pResult, va_list args);
-void dvmCallMethodA(Thread* self, const Method* method, Object* obj,
-    JValue* pResult, const jvalue* args);
 void dvmCallMethod(Thread* self, const Method* method, Object* obj,
     JValue* pResult, ...);
+void dvmCallMethodV(Thread* self, const Method* method, Object* obj,
+    bool fromJni, JValue* pResult, va_list args);
+void dvmCallMethodA(Thread* self, const Method* method, Object* obj,
+    bool fromJni, JValue* pResult, const jvalue* args);
 
 /*
  * Invoke a method, using the specified arguments and return type, through
diff --git a/vm/jdwp/JdwpAdb.c b/vm/jdwp/JdwpAdb.c
index 317c209..a74f9e1 100644
--- a/vm/jdwp/JdwpAdb.c
+++ b/vm/jdwp/JdwpAdb.c
@@ -49,6 +49,7 @@
     int                 controlSock;
     int                 clientSock;
     bool                awaitingHandshake;
+    bool                shuttingDown;
     int                 wakeFds[2];
 
     int                 inputCount;
@@ -129,6 +130,13 @@
     return true;
 }
 
+/*
+ * Receive a file descriptor from ADB.  The fd can be used to communicate
+ * directly with a debugger or DDMS.
+ *
+ * Returns the file descriptor on success.  On failure, returns -1 and
+ * closes netState->controlSock.
+ */
 static int  receiveClientFd(JdwpNetState*  netState)
 {
     struct msghdr    msg;
@@ -161,9 +169,15 @@
         ret = recvmsg(netState->controlSock, &msg, 0);
     } while (ret < 0 && errno == EINTR);
 
-    if (ret < 0) {
-        LOGE("receiving file descriptor from ADB failed (socket %d): %s\n",
-             netState->controlSock, strerror(errno));
+    if (ret <= 0) {
+        if (ret < 0) {
+            LOGW("receiving file descriptor from ADB failed (socket %d): %s\n",
+                 netState->controlSock, strerror(errno));
+        } else {
+            LOGI("adbd disconnected\n");
+        }
+        close(netState->controlSock);
+        netState->controlSock = -1;
         return -1;
     }
 
@@ -180,11 +194,15 @@
 static bool acceptConnection(struct JdwpState* state)
 {
     JdwpNetState*  netState = state->netState;
+    int retryCount = 0;
 
     /* first, ensure that we get a connection to the ADB daemon */
     
-    if (netState->controlSock < 0)
-    {
+retry:
+    if (netState->shuttingDown)
+        return false;
+
+    if (netState->controlSock < 0) {
         int        sleep_ms     = 500;
         const int  sleep_max_ms = 2*1000;
         char       buff[5];
@@ -205,6 +223,19 @@
         buff[4] = 0;
 
         for (;;) {
+            /*
+             * If adbd isn't running, because USB debugging was disabled or
+             * perhaps the system is restarting it for "adb root", the
+             * connect() will fail.  We loop here forever waiting for it
+             * to come back.
+             *
+             * Waking up and polling every couple of seconds is generally a
+             * bad thing to do, but we only do this if the application is
+             * debuggable *and* adbd isn't running.  Still, for the sake
+             * of battery life, we should consider timing out and giving
+             * up after a few minutes in case somebody ships an app with
+             * the debuggable flag set.
+             */
             int  ret = connect(netState->controlSock,
                                &netState->controlAddr.controlAddrPlain,
                                netState->controlAddrLen);
@@ -237,12 +268,21 @@
     LOGV("trying to receive file descriptor from ADB\n");
     /* now we can receive a client file descriptor */
     netState->clientSock = receiveClientFd(netState);
-    if (netState->clientSock >= 0) {
-        LOGI("received file descriptor %d from ADB\n", netState->clientSock);
+    if (netState->shuttingDown)
+        return false;       // suppress logs and additional activity
+
+    if (netState->clientSock < 0) {
+        if (++retryCount > 5) {
+            LOGE("adb connection max retries exceeded\n");
+            return false;
+        }
+        goto retry;
+    } else {
+        LOGV("received file descriptor %d from ADB\n", netState->clientSock);
         netState->awaitingHandshake = 1;
         netState->inputCount = 0;
+        return true;
     }
-    return (netState->clientSock >= 0);
 }
 
 /*
@@ -287,6 +327,8 @@
     if (netState == NULL)
         return;
 
+    netState->shuttingDown = true;
+
     clientSock = netState->clientSock;
     if (clientSock >= 0) {
         shutdown(clientSock, SHUT_RDWR);
@@ -536,12 +578,18 @@
             if (netState->controlSock >= 0 &&
                 FD_ISSET(netState->controlSock, &readfds))
             {
-                LOGI("Ignoring second debugger -- accepting and dropping\n");
                 int  sock = receiveClientFd(netState);
-                if (sock < 0)
-                    LOGI("Weird -- client fd reception failed\n");
-                else
+                if (sock >= 0) {
+                    LOGI("Ignoring second debugger -- accepting and dropping\n");
                     close(sock);
+                } else {
+                    assert(netState->controlSock < 0);
+                    /*
+                     * Remote side most likely went away, so our next read
+                     * on netState->clientSock will fail and throw us out
+                     * of the loop.
+                     */
+                }
             }
             if (netState->clientSock >= 0 &&
                 FD_ISSET(netState->clientSock, &readfds))
@@ -557,7 +605,7 @@
                     return true;
                 } else if (readCount == 0) {
                     /* EOF hit -- far end went away */
-                    LOGD("+++ peer disconnected\n");
+                    LOGV("+++ peer disconnected\n");
                     goto fail;
                 } else
                     break;
diff --git a/vm/mterp/Mterp.c b/vm/mterp/Mterp.c
index 53ddeb4..053f544 100644
--- a/vm/mterp/Mterp.c
+++ b/vm/mterp/Mterp.c
@@ -27,13 +27,15 @@
  */
 bool dvmCheckAsmConstants(void)
 {
+    bool failed = false;
+
+#ifndef DVM_NO_ASM_INTERP
+
     extern char dvmAsmInstructionStart[];
     extern char dvmAsmInstructionEnd[];
     extern char dvmAsmSisterStart[];
     extern char dvmAsmSisterEnd[];
 
-    bool failed = false;
-
 #define ASM_DEF_VERIFY
 #include "mterp/common/asm-constants.h"
 
@@ -57,6 +59,8 @@
     LOGV("mterp: interp is %d bytes, sisters are %d bytes\n",
         interpSize, sisterSize);
 
+#endif // ndef DVM_NO_ASM_INTERP
+
     return !failed;
 }
 
@@ -77,6 +81,9 @@
 
     glue->interpStackEnd = self->interpStackEnd;
     glue->pSelfSuspendCount = &self->suspendCount;
+#if defined(WITH_JIT)
+    glue->pJitProfTable = gDvmJit.pProfTable;
+#endif
 #if defined(WITH_DEBUGGER)
     glue->pDebuggerActive = &gDvm.debuggerActive;
 #endif
@@ -111,4 +118,3 @@
         return true;
     }
 }
-
diff --git a/vm/mterp/Mterp.h b/vm/mterp/Mterp.h
index ae2d207..8b3f7b4 100644
--- a/vm/mterp/Mterp.h
+++ b/vm/mterp/Mterp.h
@@ -22,6 +22,9 @@
 
 #include "Dalvik.h"
 #include "interp/InterpDefs.h"
+#if defined(WITH_JIT)
+#include "interp/Jit.h"
+#endif
 
 /*
  * Interpreter state, passed into C functions from assembly stubs.  The
diff --git a/vm/mterp/arm-vfp/OP_ADD_DOUBLE.S b/vm/mterp/arm-vfp/OP_ADD_DOUBLE.S
new file mode 100644
index 0000000..5a5ad1d
--- /dev/null
+++ b/vm/mterp/arm-vfp/OP_ADD_DOUBLE.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "arm-vfp/fbinopWide.S" {"instr":"faddd   d2, d0, d1"}
diff --git a/vm/mterp/arm-vfp/OP_ADD_DOUBLE_2ADDR.S b/vm/mterp/arm-vfp/OP_ADD_DOUBLE_2ADDR.S
new file mode 100644
index 0000000..9823765
--- /dev/null
+++ b/vm/mterp/arm-vfp/OP_ADD_DOUBLE_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "arm-vfp/fbinopWide2addr.S" {"instr":"faddd   d2, d0, d1"}
diff --git a/vm/mterp/arm-vfp/OP_ADD_FLOAT.S b/vm/mterp/arm-vfp/OP_ADD_FLOAT.S
new file mode 100644
index 0000000..22023ec
--- /dev/null
+++ b/vm/mterp/arm-vfp/OP_ADD_FLOAT.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "arm-vfp/fbinop.S" {"instr":"fadds   s2, s0, s1"}
diff --git a/vm/mterp/arm-vfp/OP_ADD_FLOAT_2ADDR.S b/vm/mterp/arm-vfp/OP_ADD_FLOAT_2ADDR.S
new file mode 100644
index 0000000..e787589
--- /dev/null
+++ b/vm/mterp/arm-vfp/OP_ADD_FLOAT_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "arm-vfp/fbinop2addr.S" {"instr":"fadds   s2, s0, s1"}
diff --git a/vm/mterp/arm-vfp/OP_CMPG_DOUBLE.S b/vm/mterp/arm-vfp/OP_CMPG_DOUBLE.S
new file mode 100644
index 0000000..a8c3ea4
--- /dev/null
+++ b/vm/mterp/arm-vfp/OP_CMPG_DOUBLE.S
@@ -0,0 +1,43 @@
+%verify "executed"
+%verify "basic lt, gt, eq */
+%verify "left arg NaN"
+%verify "right arg NaN"
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else {
+     *         return 1;
+     *     }
+     * }
+     */
+    /* op vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    fldd    d0, [r2]                    @ d0<- vBB
+    fldd    d1, [r3]                    @ d1<- vCC
+    fcmped  d0, d1                      @ compare (vBB, vCC)
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    mov     r0, #1                      @ r0<- 1 (default)
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fmstat                              @ export status flags
+    mvnmi   r0, #0                      @ (less than) r1<- -1
+    moveq   r0, #0                      @ (equal) r1<- 0
+    b       .L${opcode}_finish          @ argh
+
+%break
+.L${opcode}_finish:
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
diff --git a/vm/mterp/arm-vfp/OP_CMPG_FLOAT.S b/vm/mterp/arm-vfp/OP_CMPG_FLOAT.S
new file mode 100644
index 0000000..4c14fbb
--- /dev/null
+++ b/vm/mterp/arm-vfp/OP_CMPG_FLOAT.S
@@ -0,0 +1,43 @@
+%verify "executed"
+%verify "basic lt, gt, eq */
+%verify "left arg NaN"
+%verify "right arg NaN"
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else {
+     *         return 1;
+     *     }
+     * }
+     */
+    /* op vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    flds    s0, [r2]                    @ s0<- vBB
+    flds    s1, [r3]                    @ s1<- vCC
+    fcmpes  s0, s1                      @ compare (vBB, vCC)
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    mov     r0, #1                      @ r0<- 1 (default)
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fmstat                              @ export status flags
+    mvnmi   r0, #0                      @ (less than) r1<- -1
+    moveq   r0, #0                      @ (equal) r1<- 0
+    b       .L${opcode}_finish          @ argh
+
+%break
+.L${opcode}_finish:
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
diff --git a/vm/mterp/arm-vfp/OP_CMPL_DOUBLE.S b/vm/mterp/arm-vfp/OP_CMPL_DOUBLE.S
new file mode 100644
index 0000000..999faee
--- /dev/null
+++ b/vm/mterp/arm-vfp/OP_CMPL_DOUBLE.S
@@ -0,0 +1,43 @@
+%verify "executed"
+%verify "basic lt, gt, eq */
+%verify "left arg NaN"
+%verify "right arg NaN"
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else {
+     *         return -1;
+     *     }
+     * }
+     */
+    /* op vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    fldd    d0, [r2]                    @ d0<- vBB
+    fldd    d1, [r3]                    @ d1<- vCC
+    fcmped  d0, d1                      @ compare (vBB, vCC)
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    mvn     r0, #0                      @ r0<- -1 (default)
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fmstat                              @ export status flags
+    movgt   r0, #1                      @ (greater than) r1<- 1
+    moveq   r0, #0                      @ (equal) r1<- 0
+    b       .L${opcode}_finish          @ argh
+
+%break
+.L${opcode}_finish:
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
diff --git a/vm/mterp/arm-vfp/OP_CMPL_FLOAT.S b/vm/mterp/arm-vfp/OP_CMPL_FLOAT.S
new file mode 100644
index 0000000..9b2133c
--- /dev/null
+++ b/vm/mterp/arm-vfp/OP_CMPL_FLOAT.S
@@ -0,0 +1,43 @@
+%verify "executed"
+%verify "basic lt, gt, eq */
+%verify "left arg NaN"
+%verify "right arg NaN"
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else {
+     *         return -1;
+     *     }
+     * }
+     */
+    /* op vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    flds    s0, [r2]                    @ s0<- vBB
+    flds    s1, [r3]                    @ s1<- vCC
+    fcmpes  s0, s1                      @ compare (vBB, vCC)
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    mvn     r0, #0                      @ r0<- -1 (default)
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fmstat                              @ export status flags
+    movgt   r0, #1                      @ (greater than) r1<- 1
+    moveq   r0, #0                      @ (equal) r1<- 0
+    b       .L${opcode}_finish          @ argh
+
+%break
+.L${opcode}_finish:
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
diff --git a/vm/mterp/arm-vfp/OP_DIV_DOUBLE.S b/vm/mterp/arm-vfp/OP_DIV_DOUBLE.S
new file mode 100644
index 0000000..11770ad
--- /dev/null
+++ b/vm/mterp/arm-vfp/OP_DIV_DOUBLE.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "arm-vfp/fbinopWide.S" {"instr":"fdivd   d2, d0, d1"}
diff --git a/vm/mterp/arm-vfp/OP_DIV_DOUBLE_2ADDR.S b/vm/mterp/arm-vfp/OP_DIV_DOUBLE_2ADDR.S
new file mode 100644
index 0000000..a52f434
--- /dev/null
+++ b/vm/mterp/arm-vfp/OP_DIV_DOUBLE_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "arm-vfp/fbinopWide2addr.S" {"instr":"fdivd   d2, d0, d1"}
diff --git a/vm/mterp/arm-vfp/OP_DIV_FLOAT.S b/vm/mterp/arm-vfp/OP_DIV_FLOAT.S
new file mode 100644
index 0000000..2e82ada
--- /dev/null
+++ b/vm/mterp/arm-vfp/OP_DIV_FLOAT.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "arm-vfp/fbinop.S" {"instr":"fdivs   s2, s0, s1"}
diff --git a/vm/mterp/arm-vfp/OP_DIV_FLOAT_2ADDR.S b/vm/mterp/arm-vfp/OP_DIV_FLOAT_2ADDR.S
new file mode 100644
index 0000000..2147583
--- /dev/null
+++ b/vm/mterp/arm-vfp/OP_DIV_FLOAT_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "arm-vfp/fbinop2addr.S" {"instr":"fdivs   s2, s0, s1"}
diff --git a/vm/mterp/arm-vfp/OP_DOUBLE_TO_FLOAT.S b/vm/mterp/arm-vfp/OP_DOUBLE_TO_FLOAT.S
new file mode 100644
index 0000000..33d5b61
--- /dev/null
+++ b/vm/mterp/arm-vfp/OP_DOUBLE_TO_FLOAT.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "arm-vfp/funopNarrower.S" {"instr":"fcvtsd  s0, d0"}
diff --git a/vm/mterp/arm-vfp/OP_DOUBLE_TO_INT.S b/vm/mterp/arm-vfp/OP_DOUBLE_TO_INT.S
new file mode 100644
index 0000000..2ef4838
--- /dev/null
+++ b/vm/mterp/arm-vfp/OP_DOUBLE_TO_INT.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "arm-vfp/funopNarrower.S" {"instr":"ftosizd  s0, d0"}
diff --git a/vm/mterp/arm-vfp/OP_FLOAT_TO_DOUBLE.S b/vm/mterp/arm-vfp/OP_FLOAT_TO_DOUBLE.S
new file mode 100644
index 0000000..0acb3d8
--- /dev/null
+++ b/vm/mterp/arm-vfp/OP_FLOAT_TO_DOUBLE.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "arm-vfp/funopWider.S" {"instr":"fcvtds  d0, s0"}
diff --git a/vm/mterp/arm-vfp/OP_FLOAT_TO_INT.S b/vm/mterp/arm-vfp/OP_FLOAT_TO_INT.S
new file mode 100644
index 0000000..d0a9a2e
--- /dev/null
+++ b/vm/mterp/arm-vfp/OP_FLOAT_TO_INT.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "arm-vfp/funop.S" {"instr":"ftosizs s1, s0"}
diff --git a/vm/mterp/arm-vfp/OP_INT_TO_DOUBLE.S b/vm/mterp/arm-vfp/OP_INT_TO_DOUBLE.S
new file mode 100644
index 0000000..6eb430e
--- /dev/null
+++ b/vm/mterp/arm-vfp/OP_INT_TO_DOUBLE.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "arm-vfp/funopWider.S" {"instr":"fsitod  d0, s0"}
diff --git a/vm/mterp/arm-vfp/OP_INT_TO_FLOAT.S b/vm/mterp/arm-vfp/OP_INT_TO_FLOAT.S
new file mode 100644
index 0000000..698bdc7
--- /dev/null
+++ b/vm/mterp/arm-vfp/OP_INT_TO_FLOAT.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "arm-vfp/funop.S" {"instr":"fsitos  s1, s0"}
diff --git a/vm/mterp/arm-vfp/OP_MUL_DOUBLE.S b/vm/mterp/arm-vfp/OP_MUL_DOUBLE.S
new file mode 100644
index 0000000..7563191
--- /dev/null
+++ b/vm/mterp/arm-vfp/OP_MUL_DOUBLE.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "arm-vfp/fbinopWide.S" {"instr":"fmuld   d2, d0, d1"}
diff --git a/vm/mterp/arm-vfp/OP_MUL_DOUBLE_2ADDR.S b/vm/mterp/arm-vfp/OP_MUL_DOUBLE_2ADDR.S
new file mode 100644
index 0000000..eadf101
--- /dev/null
+++ b/vm/mterp/arm-vfp/OP_MUL_DOUBLE_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "arm-vfp/fbinopWide2addr.S" {"instr":"fmuld   d2, d0, d1"}
diff --git a/vm/mterp/arm-vfp/OP_MUL_FLOAT.S b/vm/mterp/arm-vfp/OP_MUL_FLOAT.S
new file mode 100644
index 0000000..bb3ab42
--- /dev/null
+++ b/vm/mterp/arm-vfp/OP_MUL_FLOAT.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "arm-vfp/fbinop.S" {"instr":"fmuls   s2, s0, s1"}
diff --git a/vm/mterp/arm-vfp/OP_MUL_FLOAT_2ADDR.S b/vm/mterp/arm-vfp/OP_MUL_FLOAT_2ADDR.S
new file mode 100644
index 0000000..3918537
--- /dev/null
+++ b/vm/mterp/arm-vfp/OP_MUL_FLOAT_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "arm-vfp/fbinop2addr.S" {"instr":"fmuls   s2, s0, s1"}
diff --git a/vm/mterp/arm-vfp/OP_SUB_DOUBLE.S b/vm/mterp/arm-vfp/OP_SUB_DOUBLE.S
new file mode 100644
index 0000000..d40e083
--- /dev/null
+++ b/vm/mterp/arm-vfp/OP_SUB_DOUBLE.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "arm-vfp/fbinopWide.S" {"instr":"fsubd   d2, d0, d1"}
diff --git a/vm/mterp/arm-vfp/OP_SUB_DOUBLE_2ADDR.S b/vm/mterp/arm-vfp/OP_SUB_DOUBLE_2ADDR.S
new file mode 100644
index 0000000..705124f
--- /dev/null
+++ b/vm/mterp/arm-vfp/OP_SUB_DOUBLE_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "arm-vfp/fbinopWide2addr.S" {"instr":"fsubd   d2, d0, d1"}
diff --git a/vm/mterp/arm-vfp/OP_SUB_FLOAT.S b/vm/mterp/arm-vfp/OP_SUB_FLOAT.S
new file mode 100644
index 0000000..0bf2bc0
--- /dev/null
+++ b/vm/mterp/arm-vfp/OP_SUB_FLOAT.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "arm-vfp/fbinop.S" {"instr":"fsubs   s2, s0, s1"}
diff --git a/vm/mterp/arm-vfp/OP_SUB_FLOAT_2ADDR.S b/vm/mterp/arm-vfp/OP_SUB_FLOAT_2ADDR.S
new file mode 100644
index 0000000..e214068
--- /dev/null
+++ b/vm/mterp/arm-vfp/OP_SUB_FLOAT_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "arm-vfp/fbinop2addr.S" {"instr":"fsubs   s2, s0, s1"}
diff --git a/vm/mterp/arm-vfp/README.txt b/vm/mterp/arm-vfp/README.txt
new file mode 100644
index 0000000..c94e1e8
--- /dev/null
+++ b/vm/mterp/arm-vfp/README.txt
@@ -0,0 +1,7 @@
+Instruction handlers that take advantage of ARM VFP.  These work with VFP
+v2 and v3 (VFPLite).
+
+The ARM code driving the floating-point calculations will run on ARMv5TE
+and later.  It assumes that word alignment is sufficient for double-word
+accesses (which is true for some ARMv5 and all ARMv6/v7), to avoid having
+to transfer double-precision values in two steps.
diff --git a/vm/mterp/arm-vfp/fbinop.S b/vm/mterp/arm-vfp/fbinop.S
new file mode 100644
index 0000000..ff9683e
--- /dev/null
+++ b/vm/mterp/arm-vfp/fbinop.S
@@ -0,0 +1,23 @@
+    /*
+     * Generic 32-bit floating-point operation.  Provide an "instr" line that
+     * specifies an instruction that performs "s2 = s0 op s1".  Because we
+     * use the "softfp" ABI, this must be an instruction, not a function call.
+     *
+     * For: add-float, sub-float, mul-float, div-float
+     */
+    /* floatop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    flds    s1, [r3]                    @ s1<- vCC
+    flds    s0, [r2]                    @ s0<- vBB
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    $instr                              @ s2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
+    fsts    s2, [r9]                    @ vAA<- s2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
diff --git a/vm/mterp/arm-vfp/fbinop2addr.S b/vm/mterp/arm-vfp/fbinop2addr.S
new file mode 100644
index 0000000..85b9fab
--- /dev/null
+++ b/vm/mterp/arm-vfp/fbinop2addr.S
@@ -0,0 +1,21 @@
+    /*
+     * Generic 32-bit floating point "/2addr" binary operation.  Provide
+     * an "instr" line that specifies an instruction that performs
+     * "s2 = s0 op s1".
+     *
+     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    and     r9, r9, #15                 @ r9<- A
+    flds    s1, [r3]                    @ s1<- vB
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    flds    s0, [r9]                    @ s0<- vA
+
+    $instr                              @ s2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fsts    s2, [r9]                    @ vAA<- s2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
diff --git a/vm/mterp/arm-vfp/fbinopWide.S b/vm/mterp/arm-vfp/fbinopWide.S
new file mode 100644
index 0000000..2b9ad69
--- /dev/null
+++ b/vm/mterp/arm-vfp/fbinopWide.S
@@ -0,0 +1,23 @@
+    /*
+     * Generic 64-bit double-precision floating point binary operation.
+     * Provide an "instr" line that specifies an instruction that performs
+     * "d2 = d0 op d1".
+     *
+     * for: add-double, sub-double, mul-double, div-double
+     */
+    /* doubleop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    fldd    d1, [r3]                    @ d1<- vCC
+    fldd    d0, [r2]                    @ d0<- vBB
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    $instr                              @ s2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
+    fstd    d2, [r9]                    @ vAA<- d2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
diff --git a/vm/mterp/arm-vfp/fbinopWide2addr.S b/vm/mterp/arm-vfp/fbinopWide2addr.S
new file mode 100644
index 0000000..15d9424
--- /dev/null
+++ b/vm/mterp/arm-vfp/fbinopWide2addr.S
@@ -0,0 +1,22 @@
+    /*
+     * Generic 64-bit floating point "/2addr" binary operation.  Provide
+     * an "instr" line that specifies an instruction that performs
+     * "d2 = d0 op d1".
+     *
+     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
+     *      div-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    and     r9, r9, #15                 @ r9<- A
+    fldd    d1, [r3]                    @ d1<- vB
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    fldd    d0, [r9]                    @ d0<- vA
+
+    $instr                              @ d2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fstd    d2, [r9]                    @ vAA<- d2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
diff --git a/vm/mterp/arm-vfp/funop.S b/vm/mterp/arm-vfp/funop.S
new file mode 100644
index 0000000..a5846ce
--- /dev/null
+++ b/vm/mterp/arm-vfp/funop.S
@@ -0,0 +1,18 @@
+    /*
+     * Generic 32-bit unary floating-point operation.  Provide an "instr"
+     * line that specifies an instruction that performs "s1 = op s0".
+     *
+     * for: int-to-float, float-to-int
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    flds    s0, [r3]                    @ s0<- vB
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    and     r9, r9, #15                 @ r9<- A
+    $instr                              @ s1<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    fsts    s1, [r9]                    @ vA<- s1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
diff --git a/vm/mterp/arm-vfp/funopNarrower.S b/vm/mterp/arm-vfp/funopNarrower.S
new file mode 100644
index 0000000..7ae1676
--- /dev/null
+++ b/vm/mterp/arm-vfp/funopNarrower.S
@@ -0,0 +1,18 @@
+    /*
+     * Generic 64bit-to-32bit unary floating point operation.  Provide an
+     * "instr" line that specifies an instruction that performs "s0 = op d0".
+     *
+     * For: double-to-int, double-to-float
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    fldd    d0, [r3]                    @ d0<- vB
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    and     r9, r9, #15                 @ r9<- A
+    $instr                              @ s0<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    fsts    s0, [r9]                    @ vA<- s0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
diff --git a/vm/mterp/arm-vfp/funopWider.S b/vm/mterp/arm-vfp/funopWider.S
new file mode 100644
index 0000000..055b851
--- /dev/null
+++ b/vm/mterp/arm-vfp/funopWider.S
@@ -0,0 +1,18 @@
+    /*
+     * Generic 32bit-to-64bit floating point unary operation.  Provide an
+     * "instr" line that specifies an instruction that performs "d0 = op s0".
+     *
+     * For: int-to-double, float-to-double
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    flds    s0, [r3]                    @ s0<- vB
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    and     r9, r9, #15                 @ r9<- A
+    $instr                              @ d0<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    fstd    d0, [r9]                    @ vA<- d0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
diff --git a/vm/mterp/armv5te/OP_DOUBLE_TO_INT.S b/vm/mterp/armv5te/OP_DOUBLE_TO_INT.S
index db5a5d8..2cf88f0 100644
--- a/vm/mterp/armv5te/OP_DOUBLE_TO_INT.S
+++ b/vm/mterp/armv5te/OP_DOUBLE_TO_INT.S
@@ -14,20 +14,23 @@
  */
 d2i_doconv:
     stmfd   sp!, {r4, r5, lr}           @ save regs
-    ldr     r2, .L${opcode}_maxlo       @ (double)maxint, lo
-    ldr     r3, .L${opcode}_maxhi       @ (double)maxint, hi
+    mov     r2, #0x80000000             @ maxint, as a double (low word)
+    mov     r2, r2, asr #9              @  0xffc00000
     sub     sp, sp, #4                  @ align for EABI
-    mov     r4, r0                      @ save r0
+    mvn     r3, #0xbe000000             @ maxint, as a double (high word)
+    sub     r3, r3, #0x00200000         @  0x41dfffff
+    mov     r4, r0                      @ save a copy of r0
     mov     r5, r1                      @  and r1
     bl      __aeabi_dcmpge              @ is arg >= maxint?
     cmp     r0, #0                      @ nonzero == yes
-    mvnne   r0, #0x80000000             @ return maxint (7fffffff)
+    mvnne   r0, #0x80000000             @ return maxint (0x7fffffff)
     bne     1f
 
     mov     r0, r4                      @ recover arg
     mov     r1, r5
-    ldr     r3, .L${opcode}_min         @ (double)minint, hi
-    mov     r2, #0                      @ (double)minint, lo
+    mov     r3, #0xc1000000             @ minint, as a double (high word)
+    add     r3, r3, #0x00e00000         @  0xc1e00000
+    mov     r2, #0                      @ minint, as a double (low word)
     bl      __aeabi_dcmple              @ is arg <= minint?
     cmp     r0, #0                      @ nonzero == yes
     movne   r0, #0x80000000             @ return minint (80000000)
@@ -48,12 +51,5 @@
 1:
     add     sp, sp, #4
     ldmfd   sp!, {r4, r5, pc}
-
-.L${opcode}_maxlo:
-    .word   0xffc00000                  @ maxint, as a double (low word)
-.L${opcode}_maxhi:
-    .word   0x41dfffff                  @ maxint, as a double (high word)
-.L${opcode}_min:
-    .word   0xc1e00000                  @ minint, as a double (high word)
 #endif
 
diff --git a/vm/mterp/armv5te/OP_DOUBLE_TO_LONG.S b/vm/mterp/armv5te/OP_DOUBLE_TO_LONG.S
index 1d274e9..563027d 100644
--- a/vm/mterp/armv5te/OP_DOUBLE_TO_LONG.S
+++ b/vm/mterp/armv5te/OP_DOUBLE_TO_LONG.S
@@ -12,10 +12,11 @@
  */
 d2l_doconv:
     stmfd   sp!, {r4, r5, lr}           @ save regs
-    ldr     r3, .L${opcode}_max         @ (double)maxlong, hi
+    mov     r3, #0x43000000             @ maxlong, as a double (high word)
+    add     r3, #0x00e00000             @  0x43e00000
+    mov     r2, #0                      @ maxlong, as a double (low word)
     sub     sp, sp, #4                  @ align for EABI
-    mov     r2, #0                      @ (double)maxlong, lo
-    mov     r4, r0                      @ save r0
+    mov     r4, r0                      @ save a copy of r0
     mov     r5, r1                      @  and r1
     bl      __aeabi_dcmpge              @ is arg >= maxlong?
     cmp     r0, #0                      @ nonzero == yes
@@ -25,8 +26,9 @@
 
     mov     r0, r4                      @ recover arg
     mov     r1, r5
-    ldr     r3, .L${opcode}_min         @ (double)minlong, hi
-    mov     r2, #0                      @ (double)minlong, lo
+    mov     r3, #0xc3000000             @ minlong, as a double (high word)
+    add     r3, #0x00e00000             @  0xc3e00000
+    mov     r2, #0                      @ minlong, as a double (low word)
     bl      __aeabi_dcmple              @ is arg <= minlong?
     cmp     r0, #0                      @ nonzero == yes
     movne   r0, #0                      @ return minlong (8000000000000000)
@@ -50,8 +52,3 @@
     add     sp, sp, #4
     ldmfd   sp!, {r4, r5, pc}
 
-.L${opcode}_max:
-    .word   0x43e00000                  @ maxlong, as a double (high word)
-.L${opcode}_min:
-    .word   0xc3e00000                  @ minlong, as a double (high word)
-
diff --git a/vm/mterp/armv5te/OP_GOTO.S b/vm/mterp/armv5te/OP_GOTO.S
index 3433a73..26f0c8f 100644
--- a/vm/mterp/armv5te/OP_GOTO.S
+++ b/vm/mterp/armv5te/OP_GOTO.S
@@ -11,7 +11,15 @@
     movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
     mov     r9, r9, lsl #1              @ r9<- byte offset
     bmi     common_backwardBranch       @ backward branch, do periodic checks
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
-
+#endif
diff --git a/vm/mterp/armv5te/OP_GOTO_16.S b/vm/mterp/armv5te/OP_GOTO_16.S
index 479438e..f738a98 100644
--- a/vm/mterp/armv5te/OP_GOTO_16.S
+++ b/vm/mterp/armv5te/OP_GOTO_16.S
@@ -10,7 +10,16 @@
     FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
     movs    r9, r0, asl #1              @ r9<- byte offset, check sign
     bmi     common_backwardBranch       @ backward branch, do periodic checks
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
diff --git a/vm/mterp/armv5te/OP_GOTO_32.S b/vm/mterp/armv5te/OP_GOTO_32.S
index 617b8ba..17780b9 100644
--- a/vm/mterp/armv5te/OP_GOTO_32.S
+++ b/vm/mterp/armv5te/OP_GOTO_32.S
@@ -18,7 +18,15 @@
     orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
     mov     r9, r0, asl #1              @ r9<- byte offset
     ble     common_backwardBranch       @ backward branch, do periodic checks
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
-
+#endif
diff --git a/vm/mterp/armv5te/OP_MONITOR_ENTER.S b/vm/mterp/armv5te/OP_MONITOR_ENTER.S
index 6d4c2d8..524621a 100644
--- a/vm/mterp/armv5te/OP_MONITOR_ENTER.S
+++ b/vm/mterp/armv5te/OP_MONITOR_ENTER.S
@@ -8,9 +8,7 @@
     GET_VREG(r1, r2)                    @ r1<- vAA (object)
     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
     cmp     r1, #0                      @ null object?
-#ifdef WITH_MONITOR_TRACKING
-    EXPORT_PC()                         @ export PC so we can grab stack trace
-#endif
+    EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
     beq     common_errNullObject        @ null object, throw an exception
     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
     bl      dvmLockObject               @ call(self, obj)
diff --git a/vm/mterp/armv5te/OP_MOVE_WIDE_16.S b/vm/mterp/armv5te/OP_MOVE_WIDE_16.S
index 1e0b5f2..88d996f 100644
--- a/vm/mterp/armv5te/OP_MOVE_WIDE_16.S
+++ b/vm/mterp/armv5te/OP_MOVE_WIDE_16.S
@@ -6,7 +6,7 @@
     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
-    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
     GOTO_OPCODE(ip)                     @ jump to next instruction
diff --git a/vm/mterp/armv5te/OP_NEW_INSTANCE.S b/vm/mterp/armv5te/OP_NEW_INSTANCE.S
index d1d2df6..639d9c6 100644
--- a/vm/mterp/armv5te/OP_NEW_INSTANCE.S
+++ b/vm/mterp/armv5te/OP_NEW_INSTANCE.S
@@ -22,16 +22,13 @@
     cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
     bne     .L${opcode}_needinit        @ no, init class now
 .L${opcode}_initialized: @ r0=class
-    ldr     r3, [r0, #offClassObject_accessFlags]   @ r3<- clazz->accessFlags
-    tst     r3, #(ACC_INTERFACE|ACC_ABSTRACT)   @ abstract or interface?
     mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
-    beq     .L${opcode}_finish          @ concrete class, continue
-    b       .L${opcode}_abstract        @ fail
+    bl      dvmAllocObject              @ r0<- new object
+    b       .L${opcode}_finish          @ continue
 %break
 
     .balign 32                          @ minimize cache lines
-.L${opcode}_finish: @ r0=class
-    bl      dvmAllocObject              @ r0<- new object
+.L${opcode}_finish: @ r0=new object
     mov     r3, rINST, lsr #8           @ r3<- AA
     cmp     r0, #0                      @ failed?
     beq     common_exceptionThrown      @ yes, handle the exception
@@ -67,18 +64,6 @@
     bne     .L${opcode}_resolved        @ no, continue
     b       common_exceptionThrown      @ yes, handle exception
 
-    /*
-     * We can't instantiate an abstract class or interface, so throw an
-     * InstantiationError with the class descriptor as the message.
-     *
-     *  r0 holds class object
-     */
-.L${opcode}_abstract:
-    ldr     r1, [r0, #offClassObject_descriptor]
-    ldr     r0, .LstrInstantiationErrorPtr
-    bl      dvmThrowExceptionWithClassMessage
-    b       common_exceptionThrown
-
 .LstrInstantiationErrorPtr:
     .word   .LstrInstantiationError
 
diff --git a/vm/mterp/armv5te/OP_PACKED_SWITCH.S b/vm/mterp/armv5te/OP_PACKED_SWITCH.S
index 6fde05b..72e742a 100644
--- a/vm/mterp/armv5te/OP_PACKED_SWITCH.S
+++ b/vm/mterp/armv5te/OP_PACKED_SWITCH.S
@@ -20,7 +20,16 @@
     movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
     bmi     common_backwardBranch       @ backward branch, do periodic checks
     beq     common_backwardBranch       @ (want to use BLE but V is unknown)
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
diff --git a/vm/mterp/armv5te/OP_THROW_VERIFICATION_ERROR.S b/vm/mterp/armv5te/OP_THROW_VERIFICATION_ERROR.S
new file mode 100644
index 0000000..0ed928b
--- /dev/null
+++ b/vm/mterp/armv5te/OP_THROW_VERIFICATION_ERROR.S
@@ -0,0 +1,14 @@
+%verify executed
+    /*
+     * Handle a throw-verification-error instruction.  This throws an
+     * exception for an error discovered during verification.  The
+     * exception is indicated by AA, with some detail provided by BBBB.
+     */
+    /* op AA, ref@BBBB */
+    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
+    FETCH(r2, 1)                        @ r2<- BBBB
+    EXPORT_PC()                         @ export the PC
+    mov     r1, rINST, lsr #8           @ r1<- AA
+    bl      dvmThrowVerificationError   @ always throws
+    b       common_exceptionThrown      @ handle exception
+
diff --git a/vm/mterp/armv5te/OP_UNUSED_ED.S b/vm/mterp/armv5te/OP_UNUSED_ED.S
deleted file mode 100644
index faa7246..0000000
--- a/vm/mterp/armv5te/OP_UNUSED_ED.S
+++ /dev/null
@@ -1 +0,0 @@
-%include "armv5te/unused.S"
diff --git a/vm/mterp/armv5te/bincmp.S b/vm/mterp/armv5te/bincmp.S
index 9b574a3..1f43918 100644
--- a/vm/mterp/armv5te/bincmp.S
+++ b/vm/mterp/armv5te/bincmp.S
@@ -19,7 +19,14 @@
     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
     movs    r9, r9, asl #1              @ convert to bytes, check sign
     bmi     common_backwardBranch       @ yes, do periodic checks
-1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    b        common_testUpdateProfile
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
diff --git a/vm/mterp/armv5te/binop2addr.S b/vm/mterp/armv5te/binop2addr.S
index fc170a0..27afdda 100644
--- a/vm/mterp/armv5te/binop2addr.S
+++ b/vm/mterp/armv5te/binop2addr.S
@@ -17,8 +17,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if $chkzero
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
diff --git a/vm/mterp/armv5te/debug.c b/vm/mterp/armv5te/debug.c
index 301e27a..9d7413c 100644
--- a/vm/mterp/armv5te/debug.c
+++ b/vm/mterp/armv5te/debug.c
@@ -13,23 +13,23 @@
     register uint32_t rPC       asm("r4");
     register uint32_t rFP       asm("r5");
     register uint32_t rGLUE     asm("r6");
-    register uint32_t rIBASE    asm("r7");
-    register uint32_t rINST     asm("r8");
+    register uint32_t rINST     asm("r7");
+    register uint32_t rIBASE    asm("r8");
     register uint32_t r9        asm("r9");
     register uint32_t r10       asm("r10");
 
     extern char dvmAsmInstructionStart[];
 
     printf("REGS: r0=%08x r1=%08x r2=%08x r3=%08x\n", r0, r1, r2, r3);
-    printf("    : rPC=%08x rFP=%08x rGLUE=%08x rIBASE=%08x\n",
-        rPC, rFP, rGLUE, rIBASE);
-    printf("    : rINST=%08x r9=%08x r10=%08x\n", rINST, r9, r10);
+    printf("    : rPC=%08x rFP=%08x rGLUE=%08x rINST=%08x\n",
+        rPC, rFP, rGLUE, rINST);
+    printf("    : rIBASE=%08x r9=%08x r10=%08x\n", rIBASE, r9, r10);
 
     MterpGlue* glue = (MterpGlue*) rGLUE;
     const Method* method = glue->method;
     printf("    + self is %p\n", dvmThreadSelf());
     //printf("    + currently in %s.%s %s\n",
-    //    method->clazz->descriptor, method->name, method->signature);
+    //    method->clazz->descriptor, method->name, method->shorty);
     //printf("    + dvmAsmInstructionStart = %p\n", dvmAsmInstructionStart);
     //printf("    + next handler for 0x%02x = %p\n",
     //    rINST & 0xff, dvmAsmInstructionStart + (rINST & 0xff) * 64);
@@ -63,12 +63,12 @@
      * It is a direct (non-virtual) method if it is static, private,
      * or a constructor.
      */
-    bool isDirect = 
+    bool isDirect =
         ((method->accessFlags & (ACC_STATIC|ACC_PRIVATE)) != 0) ||
         (method->name[0] == '<');
 
     char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
-        
+
     printf("<%c:%s.%s %s> ",
             isDirect ? 'D' : 'V',
             method->clazz->descriptor,
diff --git a/vm/mterp/armv5te/entry.S b/vm/mterp/armv5te/entry.S
index 5b2cde0..f9e01a3 100644
--- a/vm/mterp/armv5te/entry.S
+++ b/vm/mterp/armv5te/entry.S
@@ -66,10 +66,21 @@
     cmp     r1, #kInterpEntryInstr      @ usual case?
     bne     .Lnot_instr                 @ no, handle it
 
+#if defined(WITH_JIT)
+.Lno_singleStep:
+    /* Entry is always a possible trace start */
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_INST()
+    cmp    r0,#0
+    bne    common_updateProfile
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+#else
     /* start executing the instruction at rPC */
     FETCH_INST()                        @ load rINST from rPC
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 .Lnot_instr:
     cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
@@ -79,6 +90,22 @@
     cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
     beq     common_exceptionThrown
 
+#if defined(WITH_JIT)
+.Lnot_throw:
+    ldr     r0,[rGLUE, #offGlue_jitResume]
+    ldr     r2,[rGLUE, #offGlue_jitResumePC]
+    cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
+    bne     .Lbad_arg
+    cmp     rPC,r2
+    bne     .Lno_singleStep             @ must have branched, don't resume
+    mov     r1, #kInterpEntryInstr
+    strb    r1, [rGLUE, #offGlue_entryPoint]
+    ldr     rINST, .LdvmCompilerTemplate
+    bx      r0                          @ re-enter the translation
+.LdvmCompilerTemplate:
+    .word   dvmCompilerTemplateStart
+#endif
+
 .Lbad_arg:
     ldr     r0, strBadEntryPoint
     @ r1 holds value of entryPoint
diff --git a/vm/mterp/armv5te/footer.S b/vm/mterp/armv5te/footer.S
index 8f7cc41..90e3750 100644
--- a/vm/mterp/armv5te/footer.S
+++ b/vm/mterp/armv5te/footer.S
@@ -1,12 +1,188 @@
+
 /*
  * ===========================================================================
  *  Common subroutines and data
  * ===========================================================================
  */
 
+
+
     .text
     .align  2
 
+#if defined(WITH_JIT)
+/*
+ * Return from the translation cache to the interpreter when the compiler is
+ * having issues translating/executing a Dalvik instruction. We have to skip
+ * the code cache lookup otherwise it is possible to indefinitely bouce
+ * between the interpreter and the code cache if the instruction that fails
+ * to be compiled happens to be at a trace start.
+ */
+    .global dvmJitToInterpPunt
+dvmJitToInterpPunt:
+    mov    rPC, r0
+#ifdef EXIT_STATS
+    mov    r0,lr
+    bl     dvmBumpPunt;
+#endif
+    EXPORT_PC()
+    adrl   rIBASE, dvmAsmInstructionStart
+    FETCH_INST()
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+
+/*
+ * Return to the interpreter to handle a single instruction.
+ * On entry:
+ *    r0 <= PC
+ *    r1 <= PC of resume instruction
+ *    lr <= resume point in translation
+ */
+    .global dvmJitToInterpSingleStep
+dvmJitToInterpSingleStep:
+    str    lr,[rGLUE,#offGlue_jitResume]
+    str    r1,[rGLUE,#offGlue_jitResumePC]
+    mov    r1,#kInterpEntryInstr
+    @ enum is 4 byte in aapcs-EABI
+    str    r1, [rGLUE, #offGlue_entryPoint]
+    mov    rPC,r0
+    EXPORT_PC()
+    adrl   rIBASE, dvmAsmInstructionStart
+    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
+    str    r2,[rGLUE,#offGlue_jitState]
+    mov    r1,#1                  @ set changeInterp to bail to debug interp
+    b      common_gotoBail
+
+
+/*
+ * Return from the translation cache and immediately request
+ * a translation for the exit target.  Commonly used following
+ * invokes.
+ */
+    .global dvmJitToTraceSelect
+dvmJitToTraceSelect:
+    ldr    rPC,[r14, #-1]           @ get our target PC
+    add    rINST,r14,#-5            @ save start of chain branch
+    mov    r0,rPC
+    bl     dvmJitGetCodeAddr        @ Is there a translation?
+    cmp    r0,#0
+    beq    2f
+    mov    r1,rINST
+    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
+    cmp    r0,#0                    @ successful chain?
+    bxne   r0                       @ continue native execution
+    b      toInterpreter            @ didn't chain - resume with interpreter
+
+/* No translation, so request one if profiling isn't disabled*/
+2:
+    adrl   rIBASE, dvmAsmInstructionStart
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_INST()
+    cmp    r0, #0
+    bne    common_selectTrace
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+
+/*
+ * Return from the translation cache to the interpreter.
+ * The return was done with a BLX from thumb mode, and
+ * the following 32-bit word contains the target rPC value.
+ * Note that lr (r14) will have its low-order bit set to denote
+ * its thumb-mode origin.
+ *
+ * We'll need to stash our lr origin away, recover the new
+ * target and then check to see if there is a translation available
+ * for our new target.  If so, we do a translation chain and
+ * go back to native execution.  Otherwise, it's back to the
+ * interpreter (after treating this entry as a potential
+ * trace start).
+ */
+    .global dvmJitToInterpNormal
+dvmJitToInterpNormal:
+    ldr    rPC,[r14, #-1]           @ get our target PC
+    add    rINST,r14,#-5            @ save start of chain branch
+#ifdef EXIT_STATS
+    bl     dvmBumpNormal
+#endif
+    mov    r0,rPC
+    bl     dvmJitGetCodeAddr        @ Is there a translation?
+    cmp    r0,#0
+    beq    toInterpreter            @ go if not, otherwise do chain
+    mov    r1,rINST
+    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
+    cmp    r0,#0                    @ successful chain?
+    bxne   r0                       @ continue native execution
+    b      toInterpreter            @ didn't chain - resume with interpreter
+
+/*
+ * Return from the translation cache to the interpreter to do method invocation.
+ * Check if translation exists for the callee, but don't chain to it.
+ */
+    .global dvmJitToInterpNoChain
+dvmJitToInterpNoChain:
+#ifdef EXIT_STATS
+    bl     dvmBumpNoChain
+#endif
+    mov    r0,rPC
+    bl     dvmJitGetCodeAddr        @ Is there a translation?
+    cmp    r0,#0
+    bxne   r0                       @ continue native execution if so
+
+/*
+ * No translation, restore interpreter regs and start interpreting.
+ * rGLUE & rFP were preserved in the translated code, and rPC has
+ * already been restored by the time we get here.  We'll need to set
+ * up rIBASE & rINST, and load the address of the JitTable into r0.
+ */
+toInterpreter:
+    EXPORT_PC()
+    adrl   rIBASE, dvmAsmInstructionStart
+    FETCH_INST()
+    GET_JIT_PROF_TABLE(r0)
+    @ NOTE: intended fallthrough
+/*
+ * Common code to update potential trace start counter, and initiate
+ * a trace-build if appropriate.  On entry, rPC should point to the
+ * next instruction to execute, and rINST should be already loaded with
+ * the next opcode word, and r0 holds a pointer to the jit profile
+ * table (pJitProfTable).
+ */
+common_testUpdateProfile:
+    cmp     r0,#0
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
+
+common_updateProfile:
+    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
+    lsl     r3,r3,#23          @ shift out excess 511
+    ldrb    r1,[r0,r3,lsr #23] @ get counter
+    GET_INST_OPCODE(ip)
+    subs    r1,r1,#1           @ decrement counter
+    strb    r1,[r0,r3,lsr #23] @ and store it
+    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
+
+/*
+ * Here, we switch to the debug interpreter to request
+ * trace selection.  First, though, check to see if there
+ * is already a native translation in place (and, if so,
+ * jump to it now).
+ */
+    mov     r1,#255
+    strb    r1,[r0,r3,lsr #23] @ reset counter
+    EXPORT_PC()
+    mov     r0,rPC
+    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
+    cmp     r0,#0
+    beq     common_selectTrace
+    bxne    r0                          @ jump to the translation
+common_selectTrace:
+    mov     r2,#kJitTSelectRequest      @ ask for trace selection
+    str     r2,[rGLUE,#offGlue_jitState]
+    mov     r1,#1                       @ set changeInterp
+    b       common_gotoBail
+
+#endif
+
 /*
  * Common code when a backward branch is taken.
  *
@@ -16,9 +192,18 @@
 common_backwardBranch:
     mov     r0, #kInterpEntryInstr
     bl      common_periodicChecks
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+#else
     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 /*
@@ -54,7 +239,7 @@
 #endif
 
     cmp     r3, #0                      @ suspend pending?
-    bne     2f                          @ yes, check suspend
+    bne     2f                          @ yes, do full suspension check
 
 #if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
 # if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
@@ -72,6 +257,7 @@
 
 2:  @ check suspend
     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
+    EXPORT_PC()                         @ need for precise GC
     b       dvmCheckSuspendPending      @ suspend if necessary, then return
 
 3:  @ debugger/profiler enabled, bail out
@@ -119,10 +305,12 @@
     @ (very few methods have > 10 args; could unroll for common cases)
     add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
     sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
+    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
 1:  ldr     r1, [r3], #4                @ val = *fp++
     subs    r2, r2, #1                  @ count--
     str     r1, [r10], #4               @ *outs++ = val
     bne     1b                          @ ...while count != 0
+    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
     b       .LinvokeArgsDone
 
 /*
@@ -136,47 +324,50 @@
     @ prepare to copy args to "outs" area of current frame
     movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
     SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
-    beq     .LinvokeArgsDone            @ if no args, skip the rest
-    FETCH(r1, 2)                        @ r1<- GFED
+    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
+    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
+    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
+    beq     .LinvokeArgsDone
 
-    @ r0=methodToCall, r1=GFED, r2=count, r10=outs
+    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
 .LinvokeNonRange:
     rsb     r2, r2, #5                  @ r2<- 5-r2
     add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
     bl      common_abort                @ (skipped due to ARM prefetch)
 5:  and     ip, rINST, #0x0f00          @ isolate A
-    ldr     r3, [rFP, ip, lsr #6]       @ r3<- vA (shift right 8, left 2)
+    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
     mov     r0, r0                      @ nop
-    str     r3, [r10, #-4]!             @ *--outs = vA
+    str     r2, [r10, #-4]!             @ *--outs = vA
 4:  and     ip, r1, #0xf000             @ isolate G
-    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vG (shift right 12, left 2)
+    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
     mov     r0, r0                      @ nop
-    str     r3, [r10, #-4]!             @ *--outs = vG
+    str     r2, [r10, #-4]!             @ *--outs = vG
 3:  and     ip, r1, #0x0f00             @ isolate F
-    ldr     r3, [rFP, ip, lsr #6]       @ r3<- vF
+    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
     mov     r0, r0                      @ nop
-    str     r3, [r10, #-4]!             @ *--outs = vF
+    str     r2, [r10, #-4]!             @ *--outs = vF
 2:  and     ip, r1, #0x00f0             @ isolate E
-    ldr     r3, [rFP, ip, lsr #2]       @ r3<- vE
+    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
     mov     r0, r0                      @ nop
-    str     r3, [r10, #-4]!             @ *--outs = vE
+    str     r2, [r10, #-4]!             @ *--outs = vE
 1:  and     ip, r1, #0x000f             @ isolate D
-    ldr     r3, [rFP, ip, lsl #2]       @ r3<- vD
+    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
     mov     r0, r0                      @ nop
-    str     r3, [r10, #-4]!             @ *--outs = vD
+    str     r2, [r10, #-4]!             @ *--outs = vD
 0:  @ fall through to .LinvokeArgsDone
 
-.LinvokeArgsDone: @ r0=methodToCall
+.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
+    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
+    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
     @ find space for the new stack frame, check for overflow
     SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
-    ldrh    r2, [r0, #offMethod_registersSize]  @ r2<- methodToCall->regsSize
-    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
-    sub     r1, r1, r2, lsl #2          @ r1<- newFp (old savearea - regsSize)
+    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
     SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
 @    bl      common_dumpRegs
     ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
     sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
     cmp     r3, r9                      @ bottom < interpStackEnd?
+    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
     blt     .LstackOverflow             @ yes, this frame will overflow stack
 
     @ set up newSaveArea
@@ -186,9 +377,11 @@
 #endif
     str     rFP, [r10, #offStackSaveArea_prevFrame]
     str     rPC, [r10, #offStackSaveArea_savedPc]
+#if defined(WITH_JIT)
+    mov     r9, #0
+    str     r9, [r10, #offStackSaveArea_returnAddr]
+#endif
     str     r0, [r10, #offStackSaveArea_method]
-
-    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
     tst     r3, #ACC_NATIVE
     bne     .LinvokeNative
 
@@ -207,27 +400,39 @@
     ldmfd   sp!, {r0-r3}
     */
 
-    @ Update "glue" values for the new method
-    @ r0=methodToCall, r1=newFp
-    ldr     r3, [r0, #offMethod_clazz]      @ r3<- method->clazz
-    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
-    ldr     r3, [r3, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
-    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- method->insns
-    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
+    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
+    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
+    mov     rPC, r2                         @ publish new rPC
     ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
-    FETCH_INST()                            @ load rINST from rPC
+
+    @ Update "glue" values for the new method
+    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
+    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
+    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
     mov     rFP, r1                         @ fp = newFp
-    GET_INST_OPCODE(ip)                     @ extract opcode from rINST
+    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
+    mov     rINST, r9                       @ publish new rINST
+    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
+    cmp     r0,#0
+    bne     common_updateProfile
+    GOTO_OPCODE(ip)                         @ jump to next instruction
+#else
+    mov     rFP, r1                         @ fp = newFp
+    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
+    mov     rINST, r9                       @ publish new rINST
     str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
     GOTO_OPCODE(ip)                         @ jump to next instruction
+#endif
 
 .LinvokeNative:
     @ Prep for the native call
     @ r0=methodToCall, r1=newFp, r10=newSaveArea
     ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
-    ldr     r9, [r3, #offThread_jniLocal_nextEntry] @ r9<- thread->refNext
+    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
     str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
-    str     r9, [r10, #offStackSaveArea_localRefTop] @newFp->localRefTop=refNext
+    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
     mov     r9, r3                      @ r9<- glue->self (preserve)
 
     mov     r2, r0                      @ r2<- methodToCall
@@ -251,11 +456,11 @@
 
     @ native return; r9=self, r10=newSaveArea
     @ equivalent to dvmPopJniLocals
-    ldr     r0, [r10, #offStackSaveArea_localRefTop] @ r0<- newSave->localRefTop
+    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
     ldr     r1, [r9, #offThread_exception] @ check for exception
     str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
     cmp     r1, #0                      @ null?
-    str     r0, [r9, #offThread_jniLocal_nextEntry] @ self->refNext<- r0
+    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
     bne     common_exceptionThrown      @ no, handle exception
 
     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
@@ -312,22 +517,36 @@
 
     SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
     ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
+    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
     ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
                                         @ r2<- method we're returning to
+    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
     cmp     r2, #0                      @ is this a break frame?
+    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
     mov     r1, #0                      @ "want switch" = false
     beq     common_gotoBail             @ break frame, bail out completely
 
-    ldr     rPC, [r0, #offStackSaveArea_savedPc] @ pc = saveArea->savedPc
-    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
-    str     r2, [rGLUE, #offGlue_method]    @ glue->method = newSave->method
+    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
+    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
+    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
     str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
-    ldr     r1, [r2, #offMethod_clazz]      @ r1<- method->clazz
-    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
-    ldr     r1, [r1, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
+#if defined(WITH_JIT)
+    ldr     r3, [r0, #offStackSaveArea_returnAddr] @ r3 = saveArea->returnAddr
+    GET_JIT_PROF_TABLE(r0)
+    mov     rPC, r9                     @ publish new rPC
+    str     r1, [rGLUE, #offGlue_methodClassDex]
+    cmp     r3, #0                      @ caller is compiled code
+    blxne   r3
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    mov     rPC, r9                     @ publish new rPC
     str     r1, [rGLUE, #offGlue_methodClassDex]
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
     /*
      * Return handling, calls through "glue code".
@@ -350,12 +569,19 @@
  *
  * This does not return.
  */
+     .global dvmMterpCommonExceptionThrown
+dvmMterpCommonExceptionThrown:
 common_exceptionThrown:
 .LexceptionNew:
     mov     r0, #kInterpEntryThrow
     mov     r9, #0
     bl      common_periodicChecks
 
+#if defined(WITH_JIT)
+    mov     r2,#kJitTSelectAbort        @ abandon trace selection in progress
+    str     r2,[rGLUE,#offGlue_jitState]
+#endif
+
     ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
     ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
     mov     r1, r10                     @ r1<- self
@@ -637,6 +863,38 @@
     bx      lr
     .endif
 
+#if 0
+/*
+ * Experiment on VFP mode.
+ *
+ * uint32_t setFPSCR(uint32_t val, uint32_t mask)
+ *
+ * Updates the bits specified by "mask", setting them to the values in "val".
+ */
+setFPSCR:
+    and     r0, r0, r1                  @ make sure no stray bits are set
+    fmrx    r2, fpscr                   @ get VFP reg
+    mvn     r1, r1                      @ bit-invert mask
+    and     r2, r2, r1                  @ clear masked bits
+    orr     r2, r2, r0                  @ set specified bits
+    fmxr    fpscr, r2                   @ set VFP reg
+    mov     r0, r2                      @ return new value
+    bx      lr
+
+    .align  2
+    .global dvmConfigureFP
+    .type   dvmConfigureFP, %function
+dvmConfigureFP:
+    stmfd   sp!, {ip, lr}
+    /* 0x03000000 sets DN/FZ */
+    /* 0x00009f00 clears the six exception enable flags */
+    bl      common_squeak0
+    mov     r0, #0x03000000             @ r0<- 0x03000000
+    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
+    bl      setFPSCR
+    ldmfd   sp!, {ip, pc}
+#endif
+
 
 /*
  * String references, must be close to the code that uses them.
diff --git a/vm/mterp/armv5te/header.S b/vm/mterp/armv5te/header.S
index 6f9ba97..e129b15 100644
--- a/vm/mterp/armv5te/header.S
+++ b/vm/mterp/armv5te/header.S
@@ -33,7 +33,9 @@
 r0 holds returns of <= 4 bytes
 r0-r1 hold returns of 8 bytes, low word in r0
 
-Callee must save/restore r4+ (except r12) if it modifies them.
+Callee must save/restore r4+ (except r12) if it modifies them.  If VFP
+is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved,
+s0-s15 (d0-d7, q0-a3) do not need to be.
 
 Stack is "full descending".  Only the arguments that don't fit in the first 4
 registers are placed on the stack.  "sp" points at the first stacked argument
@@ -54,8 +56,8 @@
   r4  rPC       interpreted program counter, used for fetching instructions
   r5  rFP       interpreted frame pointer, used for accessing locals and args
   r6  rGLUE     MterpGlue pointer
-  r7  rIBASE    interpreted instruction base pointer, used for computed goto
-  r8  rINST     first 16-bit code unit of current instruction
+  r7  rINST     first 16-bit code unit of current instruction
+  r8  rIBASE    interpreted instruction base pointer, used for computed goto
 
 Macros are provided for common operations.  Each macro MUST emit only
 one instruction to make instruction-counting easier.  They MUST NOT alter
@@ -66,8 +68,8 @@
 #define rPC     r4
 #define rFP     r5
 #define rGLUE   r6
-#define rIBASE  r7
-#define rINST   r8
+#define rINST   r7
+#define rIBASE  r8
 
 /* save/restore the PC and/or FP from the glue struct */
 #define LOAD_PC_FROM_GLUE()     ldr     rPC, [rGLUE, #offGlue_pc]
@@ -117,6 +119,13 @@
 #define FETCH_ADVANCE_INST(_count) ldrh    rINST, [rPC, #(_count*2)]!
 
 /*
+ * The operation performed here is similar to FETCH_ADVANCE_INST, except the
+ * src and dest registers are parameterized (not hard-wired to rPC and rINST).
+ */
+#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \
+        ldrh    _dreg, [_sreg, #(_count*2)]!
+
+/*
  * Fetch the next instruction from an offset specified by _reg.  Updates
  * rPC to point to the next instruction.  "_reg" must specify the distance
  * in bytes, *not* 16-bit code units, and may be a signed value.
@@ -150,10 +159,17 @@
 #define GET_INST_OPCODE(_reg)   and     _reg, rINST, #255
 
 /*
+ * Put the prefetched instruction's opcode field into the specified register.
+ */
+#define GET_PREFETCHED_OPCODE(_oreg, _ireg)   and     _oreg, _ireg, #255
+
+/*
  * Begin executing the opcode in _reg.  Because this only jumps within the
  * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
  */
 #define GOTO_OPCODE(_reg)       add     pc, rIBASE, _reg, lsl #${handler_size_bits}
+#define GOTO_OPCODE_IFEQ(_reg)  addeq   pc, rIBASE, _reg, lsl #${handler_size_bits}
+#define GOTO_OPCODE_IFNE(_reg)  addne   pc, rIBASE, _reg, lsl #${handler_size_bits}
 
 /*
  * Get/set the 32-bit value from a Dalvik register.
@@ -161,6 +177,17 @@
 #define GET_VREG(_reg, _vreg)   ldr     _reg, [rFP, _vreg, lsl #2]
 #define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
 
+#if defined(WITH_JIT)
+#define GET_JIT_ENABLED(_reg)       ldr     _reg,[rGLUE,#offGlue_jitEnabled]
+#define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
+#endif
+
+/*
+ * Convert a virtual register index into an address.
+ */
+#define VREG_INDEX_TO_ADDR(_reg, _vreg) \
+        add     _reg, rFP, _vreg, lsl #2
+
 /*
  * This is a #include, not a %include, because we want the C pre-processor
  * to expand the macros into assembler assignment statements.
diff --git a/vm/mterp/armv5te/zcmp.S b/vm/mterp/armv5te/zcmp.S
index 7942632..861ca5b 100644
--- a/vm/mterp/armv5te/zcmp.S
+++ b/vm/mterp/armv5te/zcmp.S
@@ -16,7 +16,17 @@
     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
     movs    r9, r9, asl #1              @ convert to bytes, check sign
     bmi     common_backwardBranch       @ backward branch, do periodic checks
-1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
diff --git a/vm/mterp/armv6/OP_INT_TO_BYTE.S b/vm/mterp/armv6/OP_INT_TO_BYTE.S
new file mode 100644
index 0000000..40d8a5c
--- /dev/null
+++ b/vm/mterp/armv6/OP_INT_TO_BYTE.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv5te/unop.S" {"instr":"sxtb    r0, r0"}
diff --git a/vm/mterp/armv6/OP_INT_TO_CHAR.S b/vm/mterp/armv6/OP_INT_TO_CHAR.S
new file mode 100644
index 0000000..3f0fdad
--- /dev/null
+++ b/vm/mterp/armv6/OP_INT_TO_CHAR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv5te/unop.S" {"instr":"uxth    r0, r0"}
diff --git a/vm/mterp/armv6/OP_INT_TO_SHORT.S b/vm/mterp/armv6/OP_INT_TO_SHORT.S
new file mode 100644
index 0000000..82274c4
--- /dev/null
+++ b/vm/mterp/armv6/OP_INT_TO_SHORT.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv5te/unop.S" {"instr":"sxth    r0, r0"}
diff --git a/vm/mterp/armv6t2/OP_ADD_DOUBLE_2ADDR.S b/vm/mterp/armv6t2/OP_ADD_DOUBLE_2ADDR.S
new file mode 100644
index 0000000..d81ece9
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_ADD_DOUBLE_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binopWide2addr.S" {"instr":"bl      __aeabi_dadd"}
diff --git a/vm/mterp/armv6t2/OP_ADD_FLOAT_2ADDR.S b/vm/mterp/armv6t2/OP_ADD_FLOAT_2ADDR.S
new file mode 100644
index 0000000..ec6cdf1
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_ADD_FLOAT_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binop2addr.S" {"instr":"bl      __aeabi_fadd"}
diff --git a/vm/mterp/armv6t2/OP_ADD_INT_2ADDR.S b/vm/mterp/armv6t2/OP_ADD_INT_2ADDR.S
new file mode 100644
index 0000000..af271cb
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_ADD_INT_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binop2addr.S" {"instr":"add     r0, r0, r1"}
diff --git a/vm/mterp/armv6t2/OP_ADD_INT_LIT16.S b/vm/mterp/armv6t2/OP_ADD_INT_LIT16.S
new file mode 100644
index 0000000..f66b1d4
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_ADD_INT_LIT16.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binopLit16.S" {"instr":"add     r0, r0, r1"}
diff --git a/vm/mterp/armv6t2/OP_ADD_LONG_2ADDR.S b/vm/mterp/armv6t2/OP_ADD_LONG_2ADDR.S
new file mode 100644
index 0000000..0e3a901
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_ADD_LONG_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binopWide2addr.S" {"preinstr":"adds    r0, r0, r2", "instr":"adc     r1, r1, r3"}
diff --git a/vm/mterp/armv6t2/OP_AND_INT_2ADDR.S b/vm/mterp/armv6t2/OP_AND_INT_2ADDR.S
new file mode 100644
index 0000000..e7b716d
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_AND_INT_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binop2addr.S" {"instr":"and     r0, r0, r1"}
diff --git a/vm/mterp/armv6t2/OP_AND_INT_LIT16.S b/vm/mterp/armv6t2/OP_AND_INT_LIT16.S
new file mode 100644
index 0000000..77bb06b
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_AND_INT_LIT16.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binopLit16.S" {"instr":"and     r0, r0, r1"}
diff --git a/vm/mterp/armv6t2/OP_AND_LONG_2ADDR.S b/vm/mterp/armv6t2/OP_AND_LONG_2ADDR.S
new file mode 100644
index 0000000..b77fbd2
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_AND_LONG_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binopWide2addr.S" {"preinstr":"and     r0, r0, r2", "instr":"and     r1, r1, r3"}
diff --git a/vm/mterp/armv6t2/OP_ARRAY_LENGTH.S b/vm/mterp/armv6t2/OP_ARRAY_LENGTH.S
new file mode 100644
index 0000000..bb995e2
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_ARRAY_LENGTH.S
@@ -0,0 +1,15 @@
+%verify "executed"
+    /*
+     * Return the length of an array.
+     */
+    mov     r1, rINST, lsr #12          @ r1<- B
+    ubfx    r2, rINST, #8, #4           @ r2<- A
+    GET_VREG(r0, r1)                    @ r0<- vB (object ref)
+    cmp     r0, #0                      @ is object null?
+    beq     common_errNullObject        @ yup, fail
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r3, r2)                    @ vB<- length
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
diff --git a/vm/mterp/armv6t2/OP_CONST_4.S b/vm/mterp/armv6t2/OP_CONST_4.S
new file mode 100644
index 0000000..0d6092c
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_CONST_4.S
@@ -0,0 +1,10 @@
+%verify "executed"
+    /* const/4 vA, #+B */
+    mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
+    ubfx    r0, rINST, #8, #4           @ r0<- A
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
+    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
+    SET_VREG(r1, r0)                    @ fp[A]<- r1
+    GOTO_OPCODE(ip)                     @ execute next instruction
+
diff --git a/vm/mterp/armv6t2/OP_DIV_DOUBLE_2ADDR.S b/vm/mterp/armv6t2/OP_DIV_DOUBLE_2ADDR.S
new file mode 100644
index 0000000..a3b7ffb
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_DIV_DOUBLE_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binopWide2addr.S" {"instr":"bl      __aeabi_ddiv"}
diff --git a/vm/mterp/armv6t2/OP_DIV_FLOAT_2ADDR.S b/vm/mterp/armv6t2/OP_DIV_FLOAT_2ADDR.S
new file mode 100644
index 0000000..125230c
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_DIV_FLOAT_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binop2addr.S" {"instr":"bl      __aeabi_fdiv"}
diff --git a/vm/mterp/armv6t2/OP_DIV_INT_2ADDR.S b/vm/mterp/armv6t2/OP_DIV_INT_2ADDR.S
new file mode 100644
index 0000000..8e58043
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_DIV_INT_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binop2addr.S" {"instr":"bl     __aeabi_idiv","chkzero":"1"}
diff --git a/vm/mterp/armv6t2/OP_DIV_INT_LIT16.S b/vm/mterp/armv6t2/OP_DIV_INT_LIT16.S
new file mode 100644
index 0000000..b4df053
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_DIV_INT_LIT16.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binopLit16.S" {"instr":"bl     __aeabi_idiv","chkzero":"1"}
diff --git a/vm/mterp/armv6t2/OP_DIV_LONG_2ADDR.S b/vm/mterp/armv6t2/OP_DIV_LONG_2ADDR.S
new file mode 100644
index 0000000..cbd9c2d
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_DIV_LONG_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binopWide2addr.S" {"instr":"bl      __aeabi_ldivmod", "chkzero":"1"}
diff --git a/vm/mterp/armv6t2/OP_DOUBLE_TO_FLOAT.S b/vm/mterp/armv6t2/OP_DOUBLE_TO_FLOAT.S
new file mode 100644
index 0000000..bdbb2fb
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_DOUBLE_TO_FLOAT.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/unopNarrower.S" {"instr":"bl      __aeabi_d2f"}
diff --git a/vm/mterp/armv6t2/OP_DOUBLE_TO_INT.S b/vm/mterp/armv6t2/OP_DOUBLE_TO_INT.S
new file mode 100644
index 0000000..d3882f3
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_DOUBLE_TO_INT.S
@@ -0,0 +1,55 @@
+%verify "executed"
+/* EABI appears to have Java-style conversions of +inf/-inf/NaN */
+%include "armv6t2/unopNarrower.S" {"instr":"bl      __aeabi_d2iz"}
+
+#if 0
+@include "armv5te/unopNarrower.S" {"instr":"bl      d2i_doconv"}
+@break
+/*
+ * Convert the double in r0/r1 to an int in r0.
+ *
+ * We have to clip values to int min/max per the specification.  The
+ * expected common case is a "reasonable" value that converts directly
+ * to modest integer.  The EABI convert function isn't doing this for us.
+ */
+d2i_doconv:
+    stmfd   sp!, {r4, r5, lr}           @ save regs
+    mov     r2, #0x80000000             @ maxint, as a double (low word)
+    mov     r2, r2, asr #9              @  0xffc00000
+    sub     sp, sp, #4                  @ align for EABI
+    mvn     r3, #0xbe000000             @ maxint, as a double (high word)
+    sub     r3, r3, #0x00200000         @  0x41dfffff
+    mov     r4, r0                      @ save a copy of r0
+    mov     r5, r1                      @  and r1
+    bl      __aeabi_dcmpge              @ is arg >= maxint?
+    cmp     r0, #0                      @ nonzero == yes
+    mvnne   r0, #0x80000000             @ return maxint (0x7fffffff)
+    bne     1f
+
+    mov     r0, r4                      @ recover arg
+    mov     r1, r5
+    mov     r3, #0xc1000000             @ minint, as a double (high word)
+    add     r3, r3, #0x00e00000         @  0xc1e00000
+    mov     r2, #0                      @ minint, as a double (low word)
+    bl      __aeabi_dcmple              @ is arg <= minint?
+    cmp     r0, #0                      @ nonzero == yes
+    movne   r0, #0x80000000             @ return minint (80000000)
+    bne     1f
+
+    mov     r0, r4                      @ recover arg
+    mov     r1, r5
+    mov     r2, r4                      @ compare against self
+    mov     r3, r5
+    bl      __aeabi_dcmpeq              @ is arg == self?
+    cmp     r0, #0                      @ zero == no
+    beq     1f                          @ return zero for NaN
+
+    mov     r0, r4                      @ recover arg
+    mov     r1, r5
+    bl      __aeabi_d2iz                @ convert double to int
+
+1:
+    add     sp, sp, #4
+    ldmfd   sp!, {r4, r5, pc}
+#endif
+
diff --git a/vm/mterp/armv6t2/OP_DOUBLE_TO_LONG.S b/vm/mterp/armv6t2/OP_DOUBLE_TO_LONG.S
new file mode 100644
index 0000000..a9ecab7
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_DOUBLE_TO_LONG.S
@@ -0,0 +1,54 @@
+%verify "executed"
+@include "armv6t2/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
+%include "armv6t2/unopWide.S" {"instr":"bl      d2l_doconv"}
+
+%break
+/*
+ * Convert the double in r0/r1 to a long in r0/r1.
+ *
+ * We have to clip values to long min/max per the specification.  The
+ * expected common case is a "reasonable" value that converts directly
+ * to modest integer.  The EABI convert function isn't doing this for us.
+ */
+d2l_doconv:
+    stmfd   sp!, {r4, r5, lr}           @ save regs
+    mov     r3, #0x43000000             @ maxlong, as a double (high word)
+    add     r3, #0x00e00000             @  0x43e00000
+    mov     r2, #0                      @ maxlong, as a double (low word)
+    sub     sp, sp, #4                  @ align for EABI
+    mov     r4, r0                      @ save a copy of r0
+    mov     r5, r1                      @  and r1
+    bl      __aeabi_dcmpge              @ is arg >= maxlong?
+    cmp     r0, #0                      @ nonzero == yes
+    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
+    mvnne   r1, #0x80000000
+    bne     1f
+
+    mov     r0, r4                      @ recover arg
+    mov     r1, r5
+    mov     r3, #0xc3000000             @ minlong, as a double (high word)
+    add     r3, #0x00e00000             @  0xc3e00000
+    mov     r2, #0                      @ minlong, as a double (low word)
+    bl      __aeabi_dcmple              @ is arg <= minlong?
+    cmp     r0, #0                      @ nonzero == yes
+    movne   r0, #0                      @ return minlong (8000000000000000)
+    movne   r1, #0x80000000
+    bne     1f
+
+    mov     r0, r4                      @ recover arg
+    mov     r1, r5
+    mov     r2, r4                      @ compare against self
+    mov     r3, r5
+    bl      __aeabi_dcmpeq              @ is arg == self?
+    cmp     r0, #0                      @ zero == no
+    moveq   r1, #0                      @ return zero for NaN
+    beq     1f
+
+    mov     r0, r4                      @ recover arg
+    mov     r1, r5
+    bl      __aeabi_d2lz                @ convert double to long
+
+1:
+    add     sp, sp, #4
+    ldmfd   sp!, {r4, r5, pc}
+
diff --git a/vm/mterp/armv6t2/OP_FLOAT_TO_DOUBLE.S b/vm/mterp/armv6t2/OP_FLOAT_TO_DOUBLE.S
new file mode 100644
index 0000000..64ca64c
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_FLOAT_TO_DOUBLE.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/unopWider.S" {"instr":"bl      __aeabi_f2d"}
diff --git a/vm/mterp/armv6t2/OP_FLOAT_TO_INT.S b/vm/mterp/armv6t2/OP_FLOAT_TO_INT.S
new file mode 100644
index 0000000..444ebae
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_FLOAT_TO_INT.S
@@ -0,0 +1,41 @@
+%verify "executed"
+/* EABI appears to have Java-style conversions of +inf/-inf/NaN */
+%include "armv6t2/unop.S" {"instr":"bl      __aeabi_f2iz"}
+
+#if 0
+@include "armv6t2/unop.S" {"instr":"bl      f2i_doconv"}
+@break
+/*
+ * Convert the float in r0 to an int in r0.
+ *
+ * We have to clip values to int min/max per the specification.  The
+ * expected common case is a "reasonable" value that converts directly
+ * to modest integer.  The EABI convert function isn't doing this for us.
+ */
+f2i_doconv:
+    stmfd   sp!, {r4, lr}
+    mov     r1, #0x4f000000             @ (float)maxint
+    mov     r4, r0
+    bl      __aeabi_fcmpge              @ is arg >= maxint?
+    cmp     r0, #0                      @ nonzero == yes
+    mvnne   r0, #0x80000000             @ return maxint (7fffffff)
+    ldmnefd sp!, {r4, pc}
+
+    mov     r0, r4                      @ recover arg
+    mov     r1, #0xcf000000             @ (float)minint
+    bl      __aeabi_fcmple              @ is arg <= minint?
+    cmp     r0, #0                      @ nonzero == yes
+    movne   r0, #0x80000000             @ return minint (80000000)
+    ldmnefd sp!, {r4, pc}
+
+    mov     r0, r4                      @ recover arg
+    mov     r1, r4
+    bl      __aeabi_fcmpeq              @ is arg == self?
+    cmp     r0, #0                      @ zero == no
+    ldmeqfd sp!, {r4, pc}               @ return zero for NaN
+
+    mov     r0, r4                      @ recover arg
+    bl      __aeabi_f2iz                @ convert float to int
+    ldmfd   sp!, {r4, pc}
+#endif
+
diff --git a/vm/mterp/armv6t2/OP_FLOAT_TO_LONG.S b/vm/mterp/armv6t2/OP_FLOAT_TO_LONG.S
new file mode 100644
index 0000000..5efd04b
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_FLOAT_TO_LONG.S
@@ -0,0 +1,41 @@
+%verify "executed"
+@include "armv6t2/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
+%include "armv6t2/unopWider.S" {"instr":"bl      f2l_doconv"}
+
+%break
+/*
+ * Convert the float in r0 to a long in r0/r1.
+ *
+ * We have to clip values to long min/max per the specification.  The
+ * expected common case is a "reasonable" value that converts directly
+ * to modest integer.  The EABI convert function isn't doing this for us.
+ */
+f2l_doconv:
+    stmfd   sp!, {r4, lr}
+    mov     r1, #0x5f000000             @ (float)maxlong
+    mov     r4, r0
+    bl      __aeabi_fcmpge              @ is arg >= maxlong?
+    cmp     r0, #0                      @ nonzero == yes
+    mvnne   r0, #0                      @ return maxlong (7fffffff)
+    mvnne   r1, #0x80000000
+    ldmnefd sp!, {r4, pc}
+
+    mov     r0, r4                      @ recover arg
+    mov     r1, #0xdf000000             @ (float)minlong
+    bl      __aeabi_fcmple              @ is arg <= minlong?
+    cmp     r0, #0                      @ nonzero == yes
+    movne   r0, #0                      @ return minlong (80000000)
+    movne   r1, #0x80000000
+    ldmnefd sp!, {r4, pc}
+
+    mov     r0, r4                      @ recover arg
+    mov     r1, r4
+    bl      __aeabi_fcmpeq              @ is arg == self?
+    cmp     r0, #0                      @ zero == no
+    moveq   r1, #0                      @ return zero for NaN
+    ldmeqfd sp!, {r4, pc}
+
+    mov     r0, r4                      @ recover arg
+    bl      __aeabi_f2lz                @ convert float to long
+    ldmfd   sp!, {r4, pc}
+
diff --git a/vm/mterp/armv6t2/OP_IF_EQ.S b/vm/mterp/armv6t2/OP_IF_EQ.S
new file mode 100644
index 0000000..d14b10b
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_IF_EQ.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/bincmp.S" { "revcmp":"ne" }
diff --git a/vm/mterp/armv6t2/OP_IF_GE.S b/vm/mterp/armv6t2/OP_IF_GE.S
new file mode 100644
index 0000000..e6c518d
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_IF_GE.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/bincmp.S" { "revcmp":"lt" }
diff --git a/vm/mterp/armv6t2/OP_IF_GT.S b/vm/mterp/armv6t2/OP_IF_GT.S
new file mode 100644
index 0000000..6e89b3c
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_IF_GT.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/bincmp.S" { "revcmp":"le" }
diff --git a/vm/mterp/armv6t2/OP_IF_LE.S b/vm/mterp/armv6t2/OP_IF_LE.S
new file mode 100644
index 0000000..0be9f60
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_IF_LE.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/bincmp.S" { "revcmp":"gt" }
diff --git a/vm/mterp/armv6t2/OP_IF_LT.S b/vm/mterp/armv6t2/OP_IF_LT.S
new file mode 100644
index 0000000..cea79b1
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_IF_LT.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/bincmp.S" { "revcmp":"ge" }
diff --git a/vm/mterp/armv6t2/OP_IF_NE.S b/vm/mterp/armv6t2/OP_IF_NE.S
new file mode 100644
index 0000000..ad1f936
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_IF_NE.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/bincmp.S" { "revcmp":"eq" }
diff --git a/vm/mterp/armv6t2/OP_IGET.S b/vm/mterp/armv6t2/OP_IGET.S
new file mode 100644
index 0000000..537c534
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_IGET.S
@@ -0,0 +1,46 @@
+%default { "load":"ldr", "sqnum":"0" }
+%verify "executed"
+%verify "null object"
+%verify "field already resolved"
+%verify "field not yet resolved"
+%verify "field cannot be resolved"
+    /*
+     * General 32-bit instance field get.
+     *
+     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
+     */
+    /* op vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .L${opcode}_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0
+    bne     .L${opcode}_finish
+    b       common_exceptionThrown
+%break
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.L${opcode}_finish:
+    @bl      common_squeak${sqnum}
+    cmp     r9, #0                      @ check object for null
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    beq     common_errNullObject        @ object was null
+    $load   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
+    ubfx    r2, rINST, #8, #4           @ r2<- A
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r2)                    @ fp[A]<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
diff --git a/vm/mterp/armv6t2/OP_IGET_QUICK.S b/vm/mterp/armv6t2/OP_IGET_QUICK.S
new file mode 100644
index 0000000..83714d5
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_IGET_QUICK.S
@@ -0,0 +1,16 @@
+%verify "executed"
+%verify "null object"
+    /* For: iget-quick, iget-object-quick */
+    /* op vA, vB, offset@CCCC */
+    mov     r2, rINST, lsr #12          @ r2<- B
+    FETCH(r1, 1)                        @ r1<- field byte offset
+    GET_VREG(r3, r2)                    @ r3<- object we're operating on
+    ubfx    r2, rINST, #8, #4           @ r2<- A
+    cmp     r3, #0                      @ check object for null
+    beq     common_errNullObject        @ object was null
+    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r2)                    @ fp[A]<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
diff --git a/vm/mterp/armv6t2/OP_IGET_WIDE.S b/vm/mterp/armv6t2/OP_IGET_WIDE.S
new file mode 100644
index 0000000..948d53d
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_IGET_WIDE.S
@@ -0,0 +1,43 @@
+%verify "executed"
+%verify "null object"
+%verify "field already resolved"
+%verify "field not yet resolved"
+%verify "field cannot be resolved"
+    /*
+     * Wide 32-bit instance field get.
+     */
+    /* iget-wide vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .L${opcode}_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0
+    bne     .L${opcode}_finish
+    b       common_exceptionThrown
+%break
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.L${opcode}_finish:
+    cmp     r9, #0                      @ check object for null
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    beq     common_errNullObject        @ object was null
+    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
+    ubfx    r2, rINST, #8, #4           @ r2<- A
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
diff --git a/vm/mterp/armv6t2/OP_IGET_WIDE_QUICK.S b/vm/mterp/armv6t2/OP_IGET_WIDE_QUICK.S
new file mode 100644
index 0000000..129f424
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_IGET_WIDE_QUICK.S
@@ -0,0 +1,16 @@
+%verify "executed"
+%verify "null object"
+    /* iget-wide-quick vA, vB, offset@CCCC */
+    mov     r2, rINST, lsr #12          @ r2<- B
+    FETCH(r1, 1)                        @ r1<- field byte offset
+    GET_VREG(r3, r2)                    @ r3<- object we're operating on
+    ubfx    r2, rINST, #8, #4           @ r2<- A
+    cmp     r3, #0                      @ check object for null
+    beq     common_errNullObject        @ object was null
+    ldrd    r0, [r3, r1]                @ r0<- obj.field (64 bits, aligned)
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
diff --git a/vm/mterp/armv6t2/OP_INT_TO_BYTE.S b/vm/mterp/armv6t2/OP_INT_TO_BYTE.S
new file mode 100644
index 0000000..27f92e6
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_INT_TO_BYTE.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/unop.S" {"instr":"sxtb    r0, r0"}
diff --git a/vm/mterp/armv6t2/OP_INT_TO_CHAR.S b/vm/mterp/armv6t2/OP_INT_TO_CHAR.S
new file mode 100644
index 0000000..db1eaa3
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_INT_TO_CHAR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/unop.S" {"instr":"uxth    r0, r0"}
diff --git a/vm/mterp/armv6t2/OP_INT_TO_DOUBLE.S b/vm/mterp/armv6t2/OP_INT_TO_DOUBLE.S
new file mode 100644
index 0000000..38a2ef2
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_INT_TO_DOUBLE.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/unopWider.S" {"instr":"bl      __aeabi_i2d"}
diff --git a/vm/mterp/armv6t2/OP_INT_TO_FLOAT.S b/vm/mterp/armv6t2/OP_INT_TO_FLOAT.S
new file mode 100644
index 0000000..7407a73
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_INT_TO_FLOAT.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/unop.S" {"instr":"bl      __aeabi_i2f"}
diff --git a/vm/mterp/armv6t2/OP_INT_TO_LONG.S b/vm/mterp/armv6t2/OP_INT_TO_LONG.S
new file mode 100644
index 0000000..e4d4221
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_INT_TO_LONG.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/unopWider.S" {"instr":"mov     r1, r0, asr #31"}
diff --git a/vm/mterp/armv6t2/OP_INT_TO_SHORT.S b/vm/mterp/armv6t2/OP_INT_TO_SHORT.S
new file mode 100644
index 0000000..6426a9f
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_INT_TO_SHORT.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/unop.S" {"instr":"sxth    r0, r0"}
diff --git a/vm/mterp/armv6t2/OP_IPUT.S b/vm/mterp/armv6t2/OP_IPUT.S
new file mode 100644
index 0000000..10eea24
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_IPUT.S
@@ -0,0 +1,46 @@
+%default { "store":"str", "sqnum":"0" }
+%verify "executed"
+%verify "null object"
+%verify "field already resolved"
+%verify "field not yet resolved"
+%verify "field cannot be resolved"
+    /*
+     * General 32-bit instance field put.
+     *
+     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+     */
+    /* op vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .L${opcode}_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ success?
+    bne     .L${opcode}_finish          @ yes, finish up
+    b       common_exceptionThrown
+%break
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.L${opcode}_finish:
+    @bl      common_squeak${sqnum}
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    ubfx    r1, rINST, #8, #4           @ r1<- A
+    cmp     r9, #0                      @ check object for null
+    GET_VREG(r0, r1)                    @ r0<- fp[A]
+    beq     common_errNullObject        @ object was null
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    $store  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
diff --git a/vm/mterp/armv6t2/OP_IPUT_QUICK.S b/vm/mterp/armv6t2/OP_IPUT_QUICK.S
new file mode 100644
index 0000000..0b6d61c
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_IPUT_QUICK.S
@@ -0,0 +1,16 @@
+%verify "executed"
+%verify "null object"
+    /* For: iput-quick, iput-object-quick */
+    /* op vA, vB, offset@CCCC */
+    mov     r2, rINST, lsr #12          @ r2<- B
+    FETCH(r1, 1)                        @ r1<- field byte offset
+    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
+    ubfx    r2, rINST, #8, #4           @ r2<- A
+    cmp     r3, #0                      @ check object for null
+    beq     common_errNullObject        @ object was null
+    GET_VREG(r0, r2)                    @ r0<- fp[A]
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
diff --git a/vm/mterp/armv6t2/OP_IPUT_WIDE.S b/vm/mterp/armv6t2/OP_IPUT_WIDE.S
new file mode 100644
index 0000000..5c1ab97
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_IPUT_WIDE.S
@@ -0,0 +1,40 @@
+%verify "executed"
+%verify "null object"
+%verify "field already resolved"
+%verify "field not yet resolved"
+%verify "field cannot be resolved"
+    /* iput-wide vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .L${opcode}_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ success?
+    bne     .L${opcode}_finish          @ yes, finish up
+    b       common_exceptionThrown
+%break
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.L${opcode}_finish:
+    ubfx    r2, rINST, #8, #4           @ r2<- A
+    cmp     r9, #0                      @ check object for null
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
+    beq     common_errNullObject        @ object was null
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
diff --git a/vm/mterp/armv6t2/OP_IPUT_WIDE_QUICK.S b/vm/mterp/armv6t2/OP_IPUT_WIDE_QUICK.S
new file mode 100644
index 0000000..5cf4798
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_IPUT_WIDE_QUICK.S
@@ -0,0 +1,16 @@
+%verify "executed"
+%verify "null object"
+    /* iput-wide-quick vA, vB, offset@CCCC */
+    mov     r1, rINST, lsr #12          @ r1<- B
+    ubfx    r0, rINST, #8, #4           @ r0<- A
+    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
+    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
+    cmp     r2, #0                      @ check object for null
+    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
+    beq     common_errNullObject        @ object was null
+    FETCH(r3, 1)                        @ r3<- field byte offset
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
diff --git a/vm/mterp/armv6t2/OP_LONG_TO_DOUBLE.S b/vm/mterp/armv6t2/OP_LONG_TO_DOUBLE.S
new file mode 100644
index 0000000..f04f917
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_LONG_TO_DOUBLE.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/unopWide.S" {"instr":"bl      __aeabi_l2d"}
diff --git a/vm/mterp/armv6t2/OP_LONG_TO_FLOAT.S b/vm/mterp/armv6t2/OP_LONG_TO_FLOAT.S
new file mode 100644
index 0000000..eaf983b
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_LONG_TO_FLOAT.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/unopNarrower.S" {"instr":"bl      __aeabi_l2f"}
diff --git a/vm/mterp/armv6t2/OP_MOVE.S b/vm/mterp/armv6t2/OP_MOVE.S
new file mode 100644
index 0000000..0c11d1a
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_MOVE.S
@@ -0,0 +1,11 @@
+%verify "executed"
+    /* for move, move-object, long-to-int */
+    /* op vA, vB */
+    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
+    ubfx    r0, rINST, #8, #4           @ r0<- A from 11:8
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    GET_VREG(r2, r1)                    @ r2<- fp[B]
+    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
+    SET_VREG(r2, r0)                    @ fp[A]<- r2
+    GOTO_OPCODE(ip)                     @ execute next instruction
+
diff --git a/vm/mterp/armv6t2/OP_MOVE_WIDE.S b/vm/mterp/armv6t2/OP_MOVE_WIDE.S
new file mode 100644
index 0000000..c896e62
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_MOVE_WIDE.S
@@ -0,0 +1,13 @@
+%verify "executed"
+    /* move-wide vA, vB */
+    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r2, rINST, #8, #4           @ r2<- A
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
+    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
diff --git a/vm/mterp/armv6t2/OP_MUL_DOUBLE_2ADDR.S b/vm/mterp/armv6t2/OP_MUL_DOUBLE_2ADDR.S
new file mode 100644
index 0000000..b2b1297
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_MUL_DOUBLE_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binopWide2addr.S" {"instr":"bl      __aeabi_dmul"}
diff --git a/vm/mterp/armv6t2/OP_MUL_FLOAT_2ADDR.S b/vm/mterp/armv6t2/OP_MUL_FLOAT_2ADDR.S
new file mode 100644
index 0000000..a48a3a0
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_MUL_FLOAT_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binop2addr.S" {"instr":"bl      __aeabi_fmul"}
diff --git a/vm/mterp/armv6t2/OP_MUL_INT_2ADDR.S b/vm/mterp/armv6t2/OP_MUL_INT_2ADDR.S
new file mode 100644
index 0000000..e822fce
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_MUL_INT_2ADDR.S
@@ -0,0 +1,3 @@
+%verify "executed"
+/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
+%include "armv6t2/binop2addr.S" {"instr":"mul     r0, r1, r0"}
diff --git a/vm/mterp/armv6t2/OP_MUL_INT_LIT16.S b/vm/mterp/armv6t2/OP_MUL_INT_LIT16.S
new file mode 100644
index 0000000..a07e540
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_MUL_INT_LIT16.S
@@ -0,0 +1,3 @@
+%verify "executed"
+/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
+%include "armv6t2/binopLit16.S" {"instr":"mul     r0, r1, r0"}
diff --git a/vm/mterp/armv6t2/OP_MUL_LONG_2ADDR.S b/vm/mterp/armv6t2/OP_MUL_LONG_2ADDR.S
new file mode 100644
index 0000000..c050ecc
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_MUL_LONG_2ADDR.S
@@ -0,0 +1,26 @@
+%verify "executed"
+    /*
+     * Signed 64-bit integer multiply, "/2addr" version.
+     *
+     * See OP_MUL_LONG for an explanation.
+     *
+     * We get a little tight on registers, so to avoid looking up &fp[A]
+     * again we stuff it into rINST.
+     */
+    /* mul-long/2addr vA, vB */
+    mov     r1, rINST, lsr #12          @ r1<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
+    add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
+    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
+    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
+    mul     ip, r2, r1                  @  ip<- ZxW
+    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
+    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
+    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
diff --git a/vm/mterp/armv6t2/OP_NEG_DOUBLE.S b/vm/mterp/armv6t2/OP_NEG_DOUBLE.S
new file mode 100644
index 0000000..52ef346
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_NEG_DOUBLE.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/unopWide.S" {"instr":"add     r1, r1, #0x80000000"}
diff --git a/vm/mterp/armv6t2/OP_NEG_FLOAT.S b/vm/mterp/armv6t2/OP_NEG_FLOAT.S
new file mode 100644
index 0000000..34672d3
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_NEG_FLOAT.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/unop.S" {"instr":"add     r0, r0, #0x80000000"}
diff --git a/vm/mterp/armv6t2/OP_NEG_INT.S b/vm/mterp/armv6t2/OP_NEG_INT.S
new file mode 100644
index 0000000..98fb1b3
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_NEG_INT.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/unop.S" {"instr":"rsb     r0, r0, #0"}
diff --git a/vm/mterp/armv6t2/OP_NEG_LONG.S b/vm/mterp/armv6t2/OP_NEG_LONG.S
new file mode 100644
index 0000000..22f45fd
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_NEG_LONG.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/unopWide.S" {"preinstr":"rsbs    r0, r0, #0", "instr":"rsc     r1, r1, #0"}
diff --git a/vm/mterp/armv6t2/OP_NOT_INT.S b/vm/mterp/armv6t2/OP_NOT_INT.S
new file mode 100644
index 0000000..5ce758e
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_NOT_INT.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/unop.S" {"instr":"mvn     r0, r0"}
diff --git a/vm/mterp/armv6t2/OP_NOT_LONG.S b/vm/mterp/armv6t2/OP_NOT_LONG.S
new file mode 100644
index 0000000..ac7e875
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_NOT_LONG.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/unopWide.S" {"preinstr":"mvn     r0, r0", "instr":"mvn     r1, r1"}
diff --git a/vm/mterp/armv6t2/OP_OR_INT_2ADDR.S b/vm/mterp/armv6t2/OP_OR_INT_2ADDR.S
new file mode 100644
index 0000000..b13b90c
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_OR_INT_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binop2addr.S" {"instr":"orr     r0, r0, r1"}
diff --git a/vm/mterp/armv6t2/OP_OR_INT_LIT16.S b/vm/mterp/armv6t2/OP_OR_INT_LIT16.S
new file mode 100644
index 0000000..87db288
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_OR_INT_LIT16.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binopLit16.S" {"instr":"orr     r0, r0, r1"}
diff --git a/vm/mterp/armv6t2/OP_OR_LONG_2ADDR.S b/vm/mterp/armv6t2/OP_OR_LONG_2ADDR.S
new file mode 100644
index 0000000..a1891e5
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_OR_LONG_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binopWide2addr.S" {"preinstr":"orr     r0, r0, r2", "instr":"orr     r1, r1, r3"}
diff --git a/vm/mterp/armv6t2/OP_REM_DOUBLE_2ADDR.S b/vm/mterp/armv6t2/OP_REM_DOUBLE_2ADDR.S
new file mode 100644
index 0000000..48e4cc3
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_REM_DOUBLE_2ADDR.S
@@ -0,0 +1,3 @@
+%verify "executed"
+/* EABI doesn't define a double remainder function, but libm does */
+%include "armv6t2/binopWide2addr.S" {"instr":"bl      fmod"}
diff --git a/vm/mterp/armv6t2/OP_REM_FLOAT_2ADDR.S b/vm/mterp/armv6t2/OP_REM_FLOAT_2ADDR.S
new file mode 100644
index 0000000..8273df1
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_REM_FLOAT_2ADDR.S
@@ -0,0 +1,3 @@
+%verify "executed"
+/* EABI doesn't define a float remainder function, but libm does */
+%include "armv6t2/binop2addr.S" {"instr":"bl      fmodf"}
diff --git a/vm/mterp/armv6t2/OP_REM_INT_2ADDR.S b/vm/mterp/armv6t2/OP_REM_INT_2ADDR.S
new file mode 100644
index 0000000..be4951d
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_REM_INT_2ADDR.S
@@ -0,0 +1,3 @@
+%verify "executed"
+/* idivmod returns quotient in r0 and remainder in r1 */
+%include "armv6t2/binop2addr.S" {"instr":"bl      __aeabi_idivmod", "result":"r1", "chkzero":"1"}
diff --git a/vm/mterp/armv6t2/OP_REM_INT_LIT16.S b/vm/mterp/armv6t2/OP_REM_INT_LIT16.S
new file mode 100644
index 0000000..ba66b48
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_REM_INT_LIT16.S
@@ -0,0 +1,3 @@
+%verify "executed"
+/* idivmod returns quotient in r0 and remainder in r1 */
+%include "armv6t2/binopLit16.S" {"instr":"bl      __aeabi_idivmod", "result":"r1", "chkzero":"1"}
diff --git a/vm/mterp/armv6t2/OP_REM_LONG_2ADDR.S b/vm/mterp/armv6t2/OP_REM_LONG_2ADDR.S
new file mode 100644
index 0000000..c663f78
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_REM_LONG_2ADDR.S
@@ -0,0 +1,3 @@
+%verify "executed"
+/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
+%include "armv6t2/binopWide2addr.S" {"instr":"bl      __aeabi_ldivmod", "result0":"r2", "result1":"r3", "chkzero":"1"}
diff --git a/vm/mterp/armv6t2/OP_RSUB_INT.S b/vm/mterp/armv6t2/OP_RSUB_INT.S
new file mode 100644
index 0000000..761259c
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_RSUB_INT.S
@@ -0,0 +1,3 @@
+%verify "executed"
+/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
+%include "armv6t2/binopLit16.S" {"instr":"rsb     r0, r0, r1"}
diff --git a/vm/mterp/armv6t2/OP_SHL_INT_2ADDR.S b/vm/mterp/armv6t2/OP_SHL_INT_2ADDR.S
new file mode 100644
index 0000000..c6959b2
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_SHL_INT_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binop2addr.S" {"preinstr":"and     r1, r1, #31", "instr":"mov     r0, r0, asl r1"}
diff --git a/vm/mterp/armv6t2/OP_SHL_LONG_2ADDR.S b/vm/mterp/armv6t2/OP_SHL_LONG_2ADDR.S
new file mode 100644
index 0000000..bad569a
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_SHL_LONG_2ADDR.S
@@ -0,0 +1,28 @@
+%verify "executed"
+    /*
+     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
+     * 32-bit shift distance.
+     */
+    /* shl-long/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r2, r3)                    @ r2<- vB
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    and     r2, r2, #63                 @ r2<- r2 & 0x3f
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+
+    mov     r1, r1, asl r2              @  r1<- r1 << r2
+    rsb     r3, r2, #32                 @  r3<- 32 - r2
+    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
+    subs    ip, r2, #32                 @  ip<- r2 - 32
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
+    mov     r0, r0, asl r2              @  r0<- r0 << r2
+    b       .L${opcode}_finish
+%break
+
+.L${opcode}_finish:
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
diff --git a/vm/mterp/armv6t2/OP_SHR_INT_2ADDR.S b/vm/mterp/armv6t2/OP_SHR_INT_2ADDR.S
new file mode 100644
index 0000000..ce0a2ce
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_SHR_INT_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binop2addr.S" {"preinstr":"and     r1, r1, #31", "instr":"mov     r0, r0, asr r1"}
diff --git a/vm/mterp/armv6t2/OP_SHR_LONG_2ADDR.S b/vm/mterp/armv6t2/OP_SHR_LONG_2ADDR.S
new file mode 100644
index 0000000..fa77b61
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_SHR_LONG_2ADDR.S
@@ -0,0 +1,28 @@
+%verify "executed"
+    /*
+     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
+     * 32-bit shift distance.
+     */
+    /* shr-long/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r2, r3)                    @ r2<- vB
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    and     r2, r2, #63                 @ r2<- r2 & 0x3f
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+
+    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
+    rsb     r3, r2, #32                 @  r3<- 32 - r2
+    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
+    subs    ip, r2, #32                 @  ip<- r2 - 32
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
+    mov     r1, r1, asr r2              @  r1<- r1 >> r2
+    b       .L${opcode}_finish
+%break
+
+.L${opcode}_finish:
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
diff --git a/vm/mterp/armv6t2/OP_SUB_DOUBLE_2ADDR.S b/vm/mterp/armv6t2/OP_SUB_DOUBLE_2ADDR.S
new file mode 100644
index 0000000..631187b
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_SUB_DOUBLE_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binopWide2addr.S" {"instr":"bl      __aeabi_dsub"}
diff --git a/vm/mterp/armv6t2/OP_SUB_FLOAT_2ADDR.S b/vm/mterp/armv6t2/OP_SUB_FLOAT_2ADDR.S
new file mode 100644
index 0000000..13ee1b4
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_SUB_FLOAT_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binop2addr.S" {"instr":"bl      __aeabi_fsub"}
diff --git a/vm/mterp/armv6t2/OP_SUB_INT_2ADDR.S b/vm/mterp/armv6t2/OP_SUB_INT_2ADDR.S
new file mode 100644
index 0000000..a3bd5e5
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_SUB_INT_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binop2addr.S" {"instr":"sub     r0, r0, r1"}
diff --git a/vm/mterp/armv6t2/OP_SUB_LONG_2ADDR.S b/vm/mterp/armv6t2/OP_SUB_LONG_2ADDR.S
new file mode 100644
index 0000000..46dda45
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_SUB_LONG_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binopWide2addr.S" {"preinstr":"subs    r0, r0, r2", "instr":"sbc     r1, r1, r3"}
diff --git a/vm/mterp/armv6t2/OP_USHR_INT_2ADDR.S b/vm/mterp/armv6t2/OP_USHR_INT_2ADDR.S
new file mode 100644
index 0000000..5d5808e
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_USHR_INT_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binop2addr.S" {"preinstr":"and     r1, r1, #31", "instr":"mov     r0, r0, lsr r1"}
diff --git a/vm/mterp/armv6t2/OP_USHR_LONG_2ADDR.S b/vm/mterp/armv6t2/OP_USHR_LONG_2ADDR.S
new file mode 100644
index 0000000..1183d1f
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_USHR_LONG_2ADDR.S
@@ -0,0 +1,28 @@
+%verify "executed"
+    /*
+     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
+     * 32-bit shift distance.
+     */
+    /* ushr-long/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r2, r3)                    @ r2<- vB
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    and     r2, r2, #63                 @ r2<- r2 & 0x3f
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+
+    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
+    rsb     r3, r2, #32                 @  r3<- 32 - r2
+    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
+    subs    ip, r2, #32                 @  ip<- r2 - 32
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
+    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
+    b       .L${opcode}_finish
+%break
+
+.L${opcode}_finish:
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
diff --git a/vm/mterp/armv6t2/OP_XOR_INT_2ADDR.S b/vm/mterp/armv6t2/OP_XOR_INT_2ADDR.S
new file mode 100644
index 0000000..49c82d6
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_XOR_INT_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binop2addr.S" {"instr":"eor     r0, r0, r1"}
diff --git a/vm/mterp/armv6t2/OP_XOR_INT_LIT16.S b/vm/mterp/armv6t2/OP_XOR_INT_LIT16.S
new file mode 100644
index 0000000..6fe178d
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_XOR_INT_LIT16.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binopLit16.S" {"instr":"eor     r0, r0, r1"}
diff --git a/vm/mterp/armv6t2/OP_XOR_LONG_2ADDR.S b/vm/mterp/armv6t2/OP_XOR_LONG_2ADDR.S
new file mode 100644
index 0000000..8d5ba2b
--- /dev/null
+++ b/vm/mterp/armv6t2/OP_XOR_LONG_2ADDR.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv6t2/binopWide2addr.S" {"preinstr":"eor     r0, r0, r2", "instr":"eor     r1, r1, r3"}
diff --git a/vm/mterp/armv6t2/bincmp.S b/vm/mterp/armv6t2/bincmp.S
new file mode 100644
index 0000000..f3b81b0
--- /dev/null
+++ b/vm/mterp/armv6t2/bincmp.S
@@ -0,0 +1,31 @@
+%verify "branch taken"
+%verify "branch not taken"
+    /*
+     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
+     * fragment that specifies the *reverse* comparison to perform, e.g.
+     * for "if-le" you would use "gt".
+     *
+     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+     */
+    /* if-cmp vA, vB, +CCCC */
+    mov     r1, rINST, lsr #12          @ r1<- B
+    ubfx    r0, rINST, #8, #4           @ r0<- A
+    GET_VREG(r3, r1)                    @ r3<- vB
+    GET_VREG(r2, r0)                    @ r2<- vA
+    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
+    cmp     r2, r3                      @ compare (vA, vB)
+    b${revcmp}  1f                      @ branch to 1 if comparison failed
+    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
+    movs    r9, r9, asl #1              @ convert to bytes, check sign
+    bmi     common_backwardBranch       @ yes, do periodic checks
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    b        common_testUpdateProfile
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
diff --git a/vm/mterp/armv6t2/binop2addr.S b/vm/mterp/armv6t2/binop2addr.S
new file mode 100644
index 0000000..9b421bc
--- /dev/null
+++ b/vm/mterp/armv6t2/binop2addr.S
@@ -0,0 +1,33 @@
+%default {"preinstr":"", "result":"r0", "chkzero":"0"}
+    /*
+     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
+    .if $chkzero
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+    $preinstr                           @ optional op; may set condition codes
+    $instr                              @ $result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG($result, r9)               @ vAA<- $result
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
diff --git a/vm/mterp/armv6t2/binopLit16.S b/vm/mterp/armv6t2/binopLit16.S
new file mode 100644
index 0000000..7bc9902
--- /dev/null
+++ b/vm/mterp/armv6t2/binopLit16.S
@@ -0,0 +1,30 @@
+%default {"result":"r0", "chkzero":"0"}
+    /*
+     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+     */
+    /* binop/lit16 vA, vB, #+CCCC */
+    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
+    mov     r2, rINST, lsr #12          @ r2<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r0, r2)                    @ r0<- vB
+    .if $chkzero
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    $instr                              @ $result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG($result, r9)               @ vAA<- $result
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
diff --git a/vm/mterp/armv6t2/binopWide2addr.S b/vm/mterp/armv6t2/binopWide2addr.S
new file mode 100644
index 0000000..af83c7b
--- /dev/null
+++ b/vm/mterp/armv6t2/binopWide2addr.S
@@ -0,0 +1,35 @@
+%default {"preinstr":"", "result0":"r0", "result1":"r1", "chkzero":"0"}
+    /*
+     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
+     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
+     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
+     *      rem-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r1, rINST, lsr #12          @ r1<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    .if $chkzero
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+    $preinstr                           @ optional op; may set condition codes
+    $instr                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {$result0,$result1}     @ vAA/vAA+1<- $result0/$result1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 12-15 instructions */
+
diff --git a/vm/mterp/armv6t2/unop.S b/vm/mterp/armv6t2/unop.S
new file mode 100644
index 0000000..58465fe
--- /dev/null
+++ b/vm/mterp/armv6t2/unop.S
@@ -0,0 +1,20 @@
+%default {"preinstr":""}
+    /*
+     * Generic 32-bit unary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = op r0".
+     * This could be an ARM instruction or a function call.
+     *
+     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
+     *      int-to-byte, int-to-char, int-to-short
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r0, r3)                    @ r0<- vB
+    $preinstr                           @ optional op; may set condition codes
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    $instr                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 8-9 instructions */
diff --git a/vm/mterp/armv6t2/unopNarrower.S b/vm/mterp/armv6t2/unopNarrower.S
new file mode 100644
index 0000000..224e8e7
--- /dev/null
+++ b/vm/mterp/armv6t2/unopNarrower.S
@@ -0,0 +1,23 @@
+%default {"preinstr":""}
+    /*
+     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = op r0/r1", where
+     * "result" is a 32-bit quantity in r0.
+     *
+     * For: long-to-float, double-to-int, double-to-float
+     *
+     * (This would work for long-to-int, but that instruction is actually
+     * an exact match for OP_MOVE.)
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
+    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    $preinstr                           @ optional op; may set condition codes
+    $instr                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 9-10 instructions */
diff --git a/vm/mterp/armv6t2/unopWide.S b/vm/mterp/armv6t2/unopWide.S
new file mode 100644
index 0000000..62d8645
--- /dev/null
+++ b/vm/mterp/armv6t2/unopWide.S
@@ -0,0 +1,22 @@
+%default {"preinstr":""}
+    /*
+     * Generic 64-bit unary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = op r0/r1".
+     * This could be an ARM instruction or a function call.
+     *
+     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    $preinstr                           @ optional op; may set condition codes
+    $instr                              @ r0/r1<- op, r2-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-11 instructions */
+
diff --git a/vm/mterp/armv6t2/unopWider.S b/vm/mterp/armv6t2/unopWider.S
new file mode 100644
index 0000000..7ec221b
--- /dev/null
+++ b/vm/mterp/armv6t2/unopWider.S
@@ -0,0 +1,20 @@
+%default {"preinstr":""}
+    /*
+     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = op r0", where
+     * "result" is a 64-bit quantity in r0/r1.
+     *
+     * For: int-to-long, int-to-double, float-to-long, float-to-double
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r0, r3)                    @ r0<- vB
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    $preinstr                           @ optional op; may set condition codes
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    $instr                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 9-10 instructions */
diff --git a/vm/mterp/c/OP_MONITOR_ENTER.c b/vm/mterp/c/OP_MONITOR_ENTER.c
index 4d70da7..c9d8999 100644
--- a/vm/mterp/c/OP_MONITOR_ENTER.c
+++ b/vm/mterp/c/OP_MONITOR_ENTER.c
@@ -9,9 +9,7 @@
         if (!checkForNullExportPC(obj, fp, pc))
             GOTO_exceptionThrown();
         ILOGV("+ locking %p %s\n", obj, obj->clazz->descriptor);
-#ifdef WITH_MONITOR_TRACKING
-        EXPORT_PC();        /* need for stack trace */
-#endif
+        EXPORT_PC();    /* need for precise GC, also WITH_MONITOR_TRACKING */
         dvmLockObject(self, obj);
 #ifdef WITH_DEADLOCK_PREDICTION
         if (dvmCheckException(self))
diff --git a/vm/mterp/c/OP_NEW_INSTANCE.c b/vm/mterp/c/OP_NEW_INSTANCE.c
index 8096579..ce04286 100644
--- a/vm/mterp/c/OP_NEW_INSTANCE.c
+++ b/vm/mterp/c/OP_NEW_INSTANCE.c
@@ -19,21 +19,13 @@
             GOTO_exceptionThrown();
 
         /*
-         * Note: the verifier can ensure that this never happens, allowing us
-         * to remove the check.  However, the spec requires we throw the
-         * exception at runtime, not verify time, so the verifier would
-         * need to replace the new-instance call with a magic "throw
-         * InstantiationError" instruction.
-         *
-         * Since this relies on the verifier, which is optional, we would
-         * also need a "new-instance-quick" instruction to identify instances
-         * that don't require the check.
+         * Verifier now tests for interface/abstract class.
          */
-        if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
-            dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationError;",
-                clazz->descriptor);
-            GOTO_exceptionThrown();
-        }
+        //if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
+        //    dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationError;",
+        //        clazz->descriptor);
+        //    GOTO_exceptionThrown();
+        //}
         newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
         if (newObj == NULL)
             GOTO_exceptionThrown();
diff --git a/vm/mterp/c/OP_THROW_VERIFICATION_ERROR.c b/vm/mterp/c/OP_THROW_VERIFICATION_ERROR.c
new file mode 100644
index 0000000..85cc8fb
--- /dev/null
+++ b/vm/mterp/c/OP_THROW_VERIFICATION_ERROR.c
@@ -0,0 +1,7 @@
+HANDLE_OPCODE(OP_THROW_VERIFICATION_ERROR)
+    EXPORT_PC();
+    vsrc1 = INST_AA(inst);
+    ref = FETCH(1);             /* class/field/method ref */
+    dvmThrowVerificationError(curMethod, vsrc1, ref);
+    GOTO_exceptionThrown();
+OP_END
diff --git a/vm/mterp/c/OP_UNUSED_ED.c b/vm/mterp/c/OP_UNUSED_ED.c
deleted file mode 100644
index c11348f..0000000
--- a/vm/mterp/c/OP_UNUSED_ED.c
+++ /dev/null
@@ -1,2 +0,0 @@
-HANDLE_OPCODE(OP_UNUSED_ED)
-OP_END
diff --git a/vm/mterp/c/gotoTargets.c b/vm/mterp/c/gotoTargets.c
index f52e3f0..5b93583 100644
--- a/vm/mterp/c/gotoTargets.c
+++ b/vm/mterp/c/gotoTargets.c
@@ -514,7 +514,7 @@
 
         ILOGV("> retval=0x%llx (leaving %s.%s %s)",
             retval.j, curMethod->clazz->descriptor, curMethod->name,
-            curMethod->signature);
+            curMethod->shorty);
         //DUMP_REGS(curMethod, fp);
 
         saveArea = SAVEAREA_FROM_FP(fp);
@@ -542,7 +542,7 @@
         methodClassDex = curMethod->clazz->pDvmDex;
         pc = saveArea->savedPc;
         ILOGD("> (return to %s.%s %s)", curMethod->clazz->descriptor,
-            curMethod->name, curMethod->signature);
+            curMethod->name, curMethod->shorty);
 
         /* use FINISH on the caller's invoke instruction */
         //u2 invokeInstr = INST_INST(FETCH(0));
@@ -677,7 +677,7 @@
         methodClassDex = curMethod->clazz->pDvmDex;
         pc = curMethod->insns + catchRelPc;
         ILOGV("> pc <-- %s.%s %s", curMethod->clazz->descriptor,
-            curMethod->name, curMethod->signature);
+            curMethod->name, curMethod->shorty);
         DUMP_REGS(curMethod, fp, false);            // show all regs
 
         /*
@@ -726,7 +726,7 @@
         //printf("range=%d call=%p count=%d regs=0x%04x\n",
         //    methodCallRange, methodToCall, count, regs);
         //printf(" --> %s.%s %s\n", methodToCall->clazz->descriptor,
-        //    methodToCall->name, methodToCall->signature);
+        //    methodToCall->name, methodToCall->shorty);
 
         u4* outs;
         int i;
@@ -796,7 +796,7 @@
         ILOGV("> %s%s.%s %s",
             dvmIsNativeMethod(methodToCall) ? "(NATIVE) " : "",
             methodToCall->clazz->descriptor, methodToCall->name,
-            methodToCall->signature);
+            methodToCall->shorty);
 
         newFp = (u4*) SAVEAREA_FROM_FP(fp) - methodToCall->registersSize;
         newSaveArea = SAVEAREA_FROM_FP(newFp);
@@ -836,6 +836,9 @@
 #endif
         newSaveArea->prevFrame = fp;
         newSaveArea->savedPc = pc;
+#if defined(WITH_JIT)
+        newSaveArea->returnAddr = 0;
+#endif
         newSaveArea->method = methodToCall;
 
         if (!dvmIsNativeMethod(methodToCall)) {
@@ -854,12 +857,16 @@
             debugIsMethodEntry = true;              // profiling, debugging
 #endif
             ILOGD("> pc <-- %s.%s %s", curMethod->clazz->descriptor,
-                curMethod->name, curMethod->signature);
+                curMethod->name, curMethod->shorty);
             DUMP_REGS(curMethod, fp, true);         // show input args
             FINISH(0);                              // jump to method start
         } else {
             /* set this up for JNI locals, even if not a JNI native */
-            newSaveArea->xtra.localRefTop = self->jniLocalRefTable.nextEntry;
+#ifdef USE_INDIRECT_REF
+            newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
+#else
+            newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.nextEntry;
+#endif
 
             self->curFrame = newFp;
 
@@ -876,7 +883,7 @@
 #endif
 
             ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
-                methodToCall->name, methodToCall->signature);
+                methodToCall->name, methodToCall->shorty);
 
             /*
              * Jump through native call bridge.  Because we leave no
@@ -913,7 +920,7 @@
             ILOGD("> (return from native %s.%s to %s.%s %s)",
                 methodToCall->clazz->descriptor, methodToCall->name,
                 curMethod->clazz->descriptor, curMethod->name,
-                curMethod->signature);
+                curMethod->shorty);
 
             //u2 invokeInstr = INST_INST(FETCH(0));
             if (true /*invokeInstr >= OP_INVOKE_VIRTUAL &&
@@ -929,4 +936,3 @@
     }
     assert(false);      // should not get here
 GOTO_TARGET_END
-
diff --git a/vm/mterp/c/header.c b/vm/mterp/c/header.c
index e35ded4..174c226 100644
--- a/vm/mterp/c/header.c
+++ b/vm/mterp/c/header.c
@@ -19,6 +19,7 @@
 #include "interp/InterpDefs.h"
 #include "mterp/Mterp.h"
 #include <math.h>                   // needed for fmod, fmodf
+#include "mterp/common/FindInterface.h"
 
 /*
  * Configuration defines.  These affect the C implementations, i.e. the
@@ -46,7 +47,7 @@
  */
 #define THREADED_INTERP             /* threaded vs. while-loop interpreter */
 
-#ifdef WITH_INSTR_CHECKS            /* instruction-level paranoia */
+#ifdef WITH_INSTR_CHECKS            /* instruction-level paranoia (slow!) */
 # define CHECK_BRANCH_OFFSETS
 # define CHECK_REGISTER_INDICES
 #endif
@@ -86,6 +87,18 @@
 #endif
 
 /*
+ * Export another copy of the PC on every instruction; this is largely
+ * redundant with EXPORT_PC and the debugger code.  This value can be
+ * compared against what we have stored on the stack with EXPORT_PC to
+ * help ensure that we aren't missing any export calls.
+ */
+#if WITH_EXTRA_GC_CHECKS > 1
+# define EXPORT_EXTRA_PC() (self->currentPc2 = pc)
+#else
+# define EXPORT_EXTRA_PC()
+#endif
+
+/*
  * Adjust the program counter.  "_offset" is a signed int, in 16-bit units.
  *
  * Assumes the existence of "const u2* pc" and "const u2* curMethod->insns".
@@ -109,9 +122,13 @@
             dvmAbort();                                                     \
         }                                                                   \
         pc += myoff;                                                        \
+        EXPORT_EXTRA_PC();                                                  \
     } while (false)
 #else
-# define ADJUST_PC(_offset) (pc += _offset)
+# define ADJUST_PC(_offset) do {                                            \
+        pc += _offset;                                                      \
+        EXPORT_EXTRA_PC();                                                  \
+    } while (false)
 #endif
 
 /*
@@ -296,6 +313,8 @@
  * within the current method won't be shown correctly.  See the notes
  * in Exception.c.
  *
+ * This is also used to determine the address for precise GC.
+ *
  * Assumes existence of "u4* fp" and "const u2* pc".
  */
 #define EXPORT_PC()         (SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc)
@@ -309,29 +328,21 @@
  * If we're building without debug and profiling support, we never switch.
  */
 #if defined(WITH_PROFILER) || defined(WITH_DEBUGGER)
+#if defined(WITH_JIT)
+# define NEED_INTERP_SWITCH(_current) (                                     \
+    (_current == INTERP_STD) ?                                              \
+        dvmJitDebuggerOrProfilerActive(interpState->jitState) :             \
+        !dvmJitDebuggerOrProfilerActive(interpState->jitState) )
+#else
 # define NEED_INTERP_SWITCH(_current) (                                     \
     (_current == INTERP_STD) ?                                              \
         dvmDebuggerOrProfilerActive() : !dvmDebuggerOrProfilerActive() )
+#endif
 #else
 # define NEED_INTERP_SWITCH(_current) (false)
 #endif
 
 /*
- * Look up an interface on a class using the cache.
- */
-INLINE Method* dvmFindInterfaceMethodInCache(ClassObject* thisClass,
-    u4 methodIdx, const Method* method, DvmDex* methodClassDex)
-{
-#define ATOMIC_CACHE_CALC \
-    dvmInterpFindInterfaceMethod(thisClass, methodIdx, method, methodClassDex)
-
-    return (Method*) ATOMIC_CACHE_LOOKUP(methodClassDex->pInterfaceCache,
-                DEX_INTERFACE_CACHE_SIZE, thisClass, methodIdx);
-
-#undef ATOMIC_CACHE_CALC
-}
-
-/*
  * Check to see if "obj" is NULL.  If so, throw an exception.  Assumes the
  * pc has already been exported to the stack.
  *
@@ -394,4 +405,3 @@
 #endif
     return true;
 }
-
diff --git a/vm/mterp/common/FindInterface.h b/vm/mterp/common/FindInterface.h
new file mode 100644
index 0000000..021ed65
--- /dev/null
+++ b/vm/mterp/common/FindInterface.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.
+ */
+
+/* common includes */
+#include "Dalvik.h"
+
+/*
+ * Look up an interface on a class using the cache.
+ *
+ * This function used to be defined in mterp/c/header.c, but it is now used by
+ * the JIT compiler as well so it is separated into its own header file to
+ * avoid potential out-of-sync changes in the future.
+ */
+INLINE Method* dvmFindInterfaceMethodInCache(ClassObject* thisClass,
+    u4 methodIdx, const Method* method, DvmDex* methodClassDex)
+{
+#define ATOMIC_CACHE_CALC \
+    dvmInterpFindInterfaceMethod(thisClass, methodIdx, method, methodClassDex)
+
+    return (Method*) ATOMIC_CACHE_LOOKUP(methodClassDex->pInterfaceCache,
+                DEX_INTERFACE_CACHE_SIZE, thisClass, methodIdx);
+
+#undef ATOMIC_CACHE_CALC
+}
diff --git a/vm/mterp/common/asm-constants.h b/vm/mterp/common/asm-constants.h
index 73292a9..a69247e 100644
--- a/vm/mterp/common/asm-constants.h
+++ b/vm/mterp/common/asm-constants.h
@@ -82,7 +82,7 @@
  */
 
 /* globals (sanity check for LDR vs LDRB) */
-MTERP_SIZEOF(sizeofGlobal_debuggerActive, gDvm.debuggerActive, MTERP_SMALL_ENUM)
+MTERP_SIZEOF(sizeofGlobal_debuggerActive, gDvm.debuggerActive, 1)
 #if defined(WITH_PROFILER)
 MTERP_SIZEOF(sizeofGlobal_activeProfilers, gDvm.activeProfilers, 4)
 #endif
@@ -101,14 +101,38 @@
 MTERP_OFFSET(offGlue_pDebuggerActive,   MterpGlue, pDebuggerActive, 40)
 MTERP_OFFSET(offGlue_pActiveProfilers,  MterpGlue, pActiveProfilers, 44)
 MTERP_OFFSET(offGlue_entryPoint,        MterpGlue, entryPoint, 48)
+#if defined(WITH_JIT)
+MTERP_OFFSET(offGlue_pJitProfTable,     MterpGlue, pJitProfTable, 56)
+MTERP_OFFSET(offGlue_jitState,          MterpGlue, jitState, 60)
+MTERP_OFFSET(offGlue_jitResume,         MterpGlue, jitResume, 64)
+MTERP_OFFSET(offGlue_jitResumePC,       MterpGlue, jitResumePC, 68)
+#endif
 #elif defined(WITH_DEBUGGER)
 MTERP_OFFSET(offGlue_pDebuggerActive,   MterpGlue, pDebuggerActive, 40)
 MTERP_OFFSET(offGlue_entryPoint,        MterpGlue, entryPoint, 44)
+#if defined(WITH_JIT)
+MTERP_OFFSET(offGlue_pJitProfTable,     MterpGlue, pJitProfTable, 52)
+MTERP_OFFSET(offGlue_jitState,          MterpGlue, jitState, 56)
+MTERP_OFFSET(offGlue_jitResume,         MterpGlue, jitResume, 60)
+MTERP_OFFSET(offGlue_jitResumePC,       MterpGlue, jitResumePC, 64)
+#endif
 #elif defined(WITH_PROFILER)
 MTERP_OFFSET(offGlue_pActiveProfilers,  MterpGlue, pActiveProfilers, 40)
 MTERP_OFFSET(offGlue_entryPoint,        MterpGlue, entryPoint, 44)
+#if defined(WITH_JIT)
+MTERP_OFFSET(offGlue_pJitProfTable,     MterpGlue, pJitProfTable, 52)
+MTERP_OFFSET(offGlue_jitState,          MterpGlue, jitState, 56)
+MTERP_OFFSET(offGlue_jitResume,         MterpGlue, jitResume, 60)
+MTERP_OFFSET(offGlue_jitResumePC,       MterpGlue, jitResumePC, 64)
+#endif
 #else
 MTERP_OFFSET(offGlue_entryPoint,        MterpGlue, entryPoint, 40)
+#if defined(WITH_JIT)
+MTERP_OFFSET(offGlue_pJitProfTable,     MterpGlue, pJitProfTable, 48)
+MTERP_OFFSET(offGlue_jitState,          MterpGlue, jitState, 52)
+MTERP_OFFSET(offGlue_jitResume,         MterpGlue, jitResume, 56)
+MTERP_OFFSET(offGlue_jitResumePC,       MterpGlue, jitResumePC, 60)
+#endif
 #endif
 /* make sure all JValue union members are stored at the same offset */
 MTERP_OFFSET(offGlue_retval_z,          MterpGlue, retval.z, 8)
@@ -130,15 +154,19 @@
 MTERP_OFFSET(offStackSaveArea_savedPc,  StackSaveArea, savedPc, 8)
 MTERP_OFFSET(offStackSaveArea_method,   StackSaveArea, method, 12)
 MTERP_OFFSET(offStackSaveArea_currentPc, StackSaveArea, xtra.currentPc, 16)
-MTERP_OFFSET(offStackSaveArea_localRefTop, StackSaveArea, xtra.localRefTop, 16)
-MTERP_SIZEOF(sizeofStackSaveArea,       StackSaveArea, 20)
+MTERP_OFFSET(offStackSaveArea_localRefCookie, \
+                                        StackSaveArea, xtra.localRefCookie, 16)
+MTERP_OFFSET(offStackSaveArea_returnAddr, StackSaveArea, returnAddr, 20)
+MTERP_SIZEOF(sizeofStackSaveArea,       StackSaveArea, 24)
 #else
 MTERP_OFFSET(offStackSaveArea_prevFrame, StackSaveArea, prevFrame, 0)
 MTERP_OFFSET(offStackSaveArea_savedPc,  StackSaveArea, savedPc, 4)
 MTERP_OFFSET(offStackSaveArea_method,   StackSaveArea, method, 8)
 MTERP_OFFSET(offStackSaveArea_currentPc, StackSaveArea, xtra.currentPc, 12)
-MTERP_OFFSET(offStackSaveArea_localRefTop, StackSaveArea, xtra.localRefTop, 12)
-MTERP_SIZEOF(sizeofStackSaveArea,       StackSaveArea, 16)
+MTERP_OFFSET(offStackSaveArea_localRefCookie, \
+                                        StackSaveArea, xtra.localRefCookie, 12)
+MTERP_OFFSET(offStackSaveArea_returnAddr, StackSaveArea, returnAddr, 16)
+MTERP_SIZEOF(sizeofStackSaveArea,       StackSaveArea, 20)
 #endif
 
 /* InstField fields */
@@ -172,8 +200,13 @@
 MTERP_OFFSET(offThread_stackOverflowed, Thread, stackOverflowed, 40)
 MTERP_OFFSET(offThread_curFrame,        Thread, curFrame, 44)
 MTERP_OFFSET(offThread_exception,       Thread, exception, 48)
-MTERP_OFFSET(offThread_jniLocal_nextEntry, \
-                                        Thread, jniLocalRefTable.nextEntry, 80)
+#ifdef USE_INDIRECT_REF
+MTERP_OFFSET(offThread_jniLocal_topCookie, \
+                                Thread, jniLocalRefTable.segmentState.all, 76)
+#else
+MTERP_OFFSET(offThread_jniLocal_topCookie, \
+                                Thread, jniLocalRefTable.nextEntry, 76)
+#endif
 
 /* Object fields */
 MTERP_OFFSET(offObject_clazz,           Object, clazz, 0)
@@ -200,6 +233,20 @@
 MTERP_CONSTANT(kInterpEntryInstr,   0)
 MTERP_CONSTANT(kInterpEntryReturn,  1)
 MTERP_CONSTANT(kInterpEntryThrow,   2)
+#if defined(WITH_JIT)
+MTERP_CONSTANT(kInterpEntryResume,  3)
+#endif
+
+#if defined(WITH_JIT)
+MTERP_CONSTANT(kJitOff,             0)
+MTERP_CONSTANT(kJitNormal,          1)
+MTERP_CONSTANT(kJitTSelectRequest,  2)
+MTERP_CONSTANT(kJitTSelect,         3)
+MTERP_CONSTANT(kJitTSelectAbort,    4)
+MTERP_CONSTANT(kJitTSelectEnd,      5)
+MTERP_CONSTANT(kJitSingleStep,      6)
+MTERP_CONSTANT(kJitSingleStepEnd,   7)
+#endif
 
 /* ClassStatus enumeration */
 MTERP_SIZEOF(sizeofClassStatus,         ClassStatus, MTERP_SMALL_ENUM)
@@ -224,4 +271,3 @@
 
 /* opcode number */
 MTERP_CONSTANT(OP_MOVE_EXCEPTION,   0x0d)
-
diff --git a/vm/mterp/config-armv5te-vfp b/vm/mterp/config-armv5te-vfp
new file mode 100644
index 0000000..cc77002
--- /dev/null
+++ b/vm/mterp/config-armv5te-vfp
@@ -0,0 +1,105 @@
+# 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.
+
+#
+# Configuration for ARMv5TE targets with VFP support.
+#
+# This is just ARMv5TE with replacements for the handlers that can benefit
+# from floating-point instructions.  Essentially all float/double
+# operations except for "remainder" and conversions to/from 64-bit ints.
+#
+
+handler-size 64
+
+# source for the instruction table stub
+asm-stub armv5te/stub.S
+
+# file header and basic definitions
+import c/header.c
+import armv5te/header.S
+
+# C pre-processor defines for stub C instructions
+import cstubs/stubdefs.c
+
+# highly-platform-specific defs
+import armv5te/platform.S
+
+# common defs for the C helpers; include this before the instruction handlers
+import c/opcommon.c
+
+# arch-specific entry point to interpreter
+import armv5te/entry.S
+
+# opcode list; argument to op-start is default directory
+op-start armv5te
+    op OP_ADD_DOUBLE arm-vfp
+    op OP_ADD_DOUBLE_2ADDR arm-vfp
+    op OP_ADD_FLOAT arm-vfp
+    op OP_ADD_FLOAT_2ADDR arm-vfp
+    op OP_CMPG_DOUBLE arm-vfp
+    op OP_CMPG_FLOAT arm-vfp
+    op OP_CMPL_DOUBLE arm-vfp
+    op OP_CMPL_FLOAT arm-vfp
+    op OP_DIV_DOUBLE arm-vfp
+    op OP_DIV_DOUBLE_2ADDR arm-vfp
+    op OP_DIV_FLOAT arm-vfp
+    op OP_DIV_FLOAT_2ADDR arm-vfp
+    op OP_DOUBLE_TO_FLOAT arm-vfp
+    op OP_DOUBLE_TO_INT arm-vfp
+    op OP_FLOAT_TO_DOUBLE arm-vfp
+    op OP_FLOAT_TO_INT arm-vfp
+    op OP_INT_TO_DOUBLE arm-vfp
+    op OP_INT_TO_FLOAT arm-vfp
+    op OP_MUL_DOUBLE arm-vfp
+    op OP_MUL_DOUBLE_2ADDR arm-vfp
+    op OP_MUL_FLOAT arm-vfp
+    op OP_MUL_FLOAT_2ADDR arm-vfp
+    op OP_SUB_DOUBLE arm-vfp
+    op OP_SUB_DOUBLE_2ADDR arm-vfp
+    op OP_SUB_FLOAT arm-vfp
+    op OP_SUB_FLOAT_2ADDR arm-vfp
+
+    # use trivial integer operation
+    #op OP_NEG_DOUBLE armv5te
+    #op OP_NEG_FLOAT armv5te
+
+    # use __aeabi_* functions
+    #op OP_DOUBLE_TO_LONG armv5te
+    #op OP_FLOAT_TO_LONG armv5te
+    #op OP_LONG_TO_DOUBLE armv5te
+    #op OP_LONG_TO_FLOAT armv5te
+
+    # no "remainder" op in vfp or libgcc.a; use libc function
+    #op OP_REM_DOUBLE armv5te
+    #op OP_REM_DOUBLE_2ADDR armv5te
+    #op OP_REM_FLOAT armv5te
+    #op OP_REM_FLOAT_2ADDR armv5te
+
+    # experiment, unrelated to vfp
+    #op OP_INT_TO_BYTE armv6
+    #op OP_INT_TO_CHAR armv6
+    #op OP_INT_TO_SHORT armv6
+op-end
+
+# "helper" code for C; include if you use any of the C stubs (this generates
+# object code, so it's normally excluded)
+##import c/gotoTargets.c
+
+# end of defs; include this when cstubs/stubdefs.c is included
+import cstubs/enddefs.c
+
+# common subroutines for asm
+import armv5te/footer.S
+import armv5te/debug.c
+
diff --git a/vm/mterp/config-armv7-a b/vm/mterp/config-armv7-a
new file mode 100644
index 0000000..9193632
--- /dev/null
+++ b/vm/mterp/config-armv7-a
@@ -0,0 +1,167 @@
+# 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.
+
+#
+# Configuration for ARMv7-A targets.
+#
+# This target includes Thumb-2 and Thumb2-EE support, as well as VFPLite.
+#
+# The difference in performance between this and ARMv5TE appears to be
+# negligible on a Cortex-A8 CPU, so this is really just an experiment.
+#
+
+handler-size 64
+
+# source for the instruction table stub
+asm-stub armv5te/stub.S
+
+# file header and basic definitions
+import c/header.c
+import armv5te/header.S
+
+# C pre-processor defines for stub C instructions
+import cstubs/stubdefs.c
+
+# highly-platform-specific defs
+import armv5te/platform.S
+
+# common defs for the C helpers; include this before the instruction handlers
+import c/opcommon.c
+
+# arch-specific entry point to interpreter
+import armv5te/entry.S
+
+# opcode list; argument to op-start is default directory
+op-start armv5te
+    # handlers that take advantage of >= ARMv6T2 instructions
+    op OP_ADD_DOUBLE_2ADDR armv6t2
+    op OP_ADD_FLOAT_2ADDR armv6t2
+    op OP_ADD_INT_2ADDR armv6t2
+    op OP_ADD_INT_LIT16 armv6t2
+    op OP_ADD_LONG_2ADDR armv6t2
+    op OP_AND_INT_2ADDR armv6t2
+    op OP_AND_INT_LIT16 armv6t2
+    op OP_AND_LONG_2ADDR armv6t2
+    op OP_ARRAY_LENGTH armv6t2
+    op OP_CONST_4 armv6t2
+    op OP_DIV_DOUBLE_2ADDR armv6t2
+    op OP_DIV_FLOAT_2ADDR armv6t2
+    op OP_DIV_INT_2ADDR armv6t2
+    op OP_DIV_INT_LIT16 armv6t2
+    op OP_DIV_LONG_2ADDR armv6t2
+    op OP_DOUBLE_TO_FLOAT armv6t2
+    op OP_DOUBLE_TO_INT armv6t2
+    op OP_DOUBLE_TO_LONG armv6t2
+    op OP_FLOAT_TO_DOUBLE armv6t2
+    op OP_FLOAT_TO_INT armv6t2
+    op OP_FLOAT_TO_LONG armv6t2
+    op OP_IF_EQ armv6t2
+    op OP_IF_GE armv6t2
+    op OP_IF_GT armv6t2
+    op OP_IF_LE armv6t2
+    op OP_IF_LT armv6t2
+    op OP_IF_NE armv6t2
+    op OP_IGET armv6t2
+    op OP_IGET_QUICK armv6t2
+    op OP_IGET_WIDE armv6t2
+    op OP_IGET_WIDE_QUICK armv6t2
+    op OP_INT_TO_BYTE armv6t2
+    op OP_INT_TO_CHAR armv6t2
+    op OP_INT_TO_DOUBLE armv6t2
+    op OP_INT_TO_FLOAT armv6t2
+    op OP_INT_TO_LONG armv6t2
+    op OP_INT_TO_SHORT armv6t2
+    op OP_IPUT armv6t2
+    op OP_IPUT_QUICK armv6t2
+    op OP_IPUT_WIDE armv6t2
+    op OP_IPUT_WIDE_QUICK armv6t2
+    op OP_LONG_TO_DOUBLE armv6t2
+    op OP_LONG_TO_FLOAT armv6t2
+    op OP_MOVE armv6t2
+    op OP_MOVE_WIDE armv6t2
+    op OP_MUL_DOUBLE_2ADDR armv6t2
+    op OP_MUL_FLOAT_2ADDR armv6t2
+    op OP_MUL_INT_2ADDR armv6t2
+    op OP_MUL_INT_LIT16 armv6t2
+    op OP_MUL_LONG_2ADDR armv6t2
+    op OP_NEG_DOUBLE armv6t2
+    op OP_NEG_FLOAT armv6t2
+    op OP_NEG_INT armv6t2
+    op OP_NEG_LONG armv6t2
+    op OP_NOT_INT armv6t2
+    op OP_NOT_LONG armv6t2
+    op OP_OR_INT_2ADDR armv6t2
+    op OP_OR_INT_LIT16 armv6t2
+    op OP_OR_LONG_2ADDR armv6t2
+    op OP_REM_DOUBLE_2ADDR armv6t2
+    op OP_REM_FLOAT_2ADDR armv6t2
+    op OP_REM_INT_2ADDR armv6t2
+    op OP_REM_INT_LIT16 armv6t2
+    op OP_REM_LONG_2ADDR armv6t2
+    op OP_RSUB_INT armv6t2
+    op OP_SHL_INT_2ADDR armv6t2
+    op OP_SHL_LONG_2ADDR armv6t2
+    op OP_SHR_INT_2ADDR armv6t2
+    op OP_SHR_LONG_2ADDR armv6t2
+    op OP_SUB_DOUBLE_2ADDR armv6t2
+    op OP_SUB_FLOAT_2ADDR armv6t2
+    op OP_SUB_INT_2ADDR armv6t2
+    op OP_SUB_LONG_2ADDR armv6t2
+    op OP_USHR_INT_2ADDR armv6t2
+    op OP_USHR_LONG_2ADDR armv6t2
+    op OP_XOR_INT_2ADDR armv6t2
+    op OP_XOR_INT_LIT16 armv6t2
+    op OP_XOR_LONG_2ADDR armv6t2
+
+    # floating point handlers that use VFP
+    # these override the handlers specified earlier
+    op OP_ADD_DOUBLE arm-vfp
+    op OP_ADD_DOUBLE_2ADDR arm-vfp
+    op OP_ADD_FLOAT arm-vfp
+    op OP_ADD_FLOAT_2ADDR arm-vfp
+    op OP_CMPG_DOUBLE arm-vfp
+    op OP_CMPG_FLOAT arm-vfp
+    op OP_CMPL_DOUBLE arm-vfp
+    op OP_CMPL_FLOAT arm-vfp
+    op OP_DIV_DOUBLE arm-vfp
+    op OP_DIV_DOUBLE_2ADDR arm-vfp
+    op OP_DIV_FLOAT arm-vfp
+    op OP_DIV_FLOAT_2ADDR arm-vfp
+    op OP_DOUBLE_TO_FLOAT arm-vfp
+    op OP_DOUBLE_TO_INT arm-vfp
+    op OP_FLOAT_TO_DOUBLE arm-vfp
+    op OP_FLOAT_TO_INT arm-vfp
+    op OP_INT_TO_DOUBLE arm-vfp
+    op OP_INT_TO_FLOAT arm-vfp
+    op OP_MUL_DOUBLE arm-vfp
+    op OP_MUL_DOUBLE_2ADDR arm-vfp
+    op OP_MUL_FLOAT arm-vfp
+    op OP_MUL_FLOAT_2ADDR arm-vfp
+    op OP_SUB_DOUBLE arm-vfp
+    op OP_SUB_DOUBLE_2ADDR arm-vfp
+    op OP_SUB_FLOAT arm-vfp
+    op OP_SUB_FLOAT_2ADDR arm-vfp
+op-end
+
+# "helper" code for C; include if you use any of the C stubs (this generates
+# object code, so it's normally excluded)
+##import c/gotoTargets.c
+
+# end of defs; include this when cstubs/stubdefs.c is included
+import cstubs/enddefs.c
+
+# common subroutines for asm
+import armv5te/footer.S
+import armv5te/debug.c
+
diff --git a/vm/mterp/cstubs/stubdefs.c b/vm/mterp/cstubs/stubdefs.c
index 1de6f0e..8699f05 100644
--- a/vm/mterp/cstubs/stubdefs.c
+++ b/vm/mterp/cstubs/stubdefs.c
@@ -107,12 +107,15 @@
  * started.  If so, switch to a different "goto" table.
  */
 #define PERIODIC_CHECKS(_entryPoint, _pcadj) {                              \
-        dvmCheckSuspendQuick(self);                                         \
+        if (dvmCheckSuspendQuick(self)) {                                   \
+            EXPORT_PC();  /* need for precise GC */                         \
+            dvmCheckSuspendPending(self);                                   \
+        }                                                                   \
         if (NEED_INTERP_SWITCH(INTERP_TYPE)) {                              \
             ADJUST_PC(_pcadj);                                              \
             glue->entryPoint = _entryPoint;                                 \
             LOGVV("threadid=%d: switch to STD ep=%d adj=%d\n",              \
-                glue->self->threadId, (_entryPoint), (_pcadj));             \
+                self->threadId, (_entryPoint), (_pcadj));                   \
             GOTO_bail_switch();                                             \
         }                                                                   \
     }
diff --git a/vm/mterp/gen-mterp.py b/vm/mterp/gen-mterp.py
index e342266..e685350 100755
--- a/vm/mterp/gen-mterp.py
+++ b/vm/mterp/gen-mterp.py
@@ -24,6 +24,7 @@
 
 interp_defs_file = "../../libdex/OpCode.h" # need opcode list
 
+verbose = False
 handler_size_bits = -1000
 handler_size_bytes = -1000
 in_op_start = 0             # 0=not started, 1=started, 2=ended
@@ -129,6 +130,9 @@
         index = opcodes.index(tokens[1])
     except ValueError:
         raise DataParseError("unknown opcode %s" % tokens[1])
+    if opcode_locations.has_key(tokens[1]):
+        print "Warning: op overrides earlier %s (%s -> %s)" \
+                % (tokens[1], opcode_locations[tokens[1]], tokens[2])
     opcode_locations[tokens[1]] = tokens[2]
 
 #
@@ -228,7 +232,8 @@
 def loadAndEmitC(location, opindex):
     op = opcodes[opindex]
     source = "%s/%s.c" % (location, op)
-    print " emit %s --> C" % source
+    if verbose:
+        print " emit %s --> C" % source
     dict = getGlobalSubDict()
     dict.update({ "opcode":op, "opnum":opindex })
 
@@ -245,7 +250,8 @@
     source = "%s/%s.S" % (location, op)
     dict = getGlobalSubDict()
     dict.update({ "opcode":op, "opnum":opindex })
-    print " emit %s --> asm" % source
+    if verbose:
+        print " emit %s --> asm" % source
 
     emitAsmHeader(asm_fp, dict)
     appendSourceFile(source, dict, asm_fp, sister_list)
diff --git a/vm/mterp/out/InterpAsm-armv4t.S b/vm/mterp/out/InterpAsm-armv4t.S
index d60571b..2df532f 100644
--- a/vm/mterp/out/InterpAsm-armv4t.S
+++ b/vm/mterp/out/InterpAsm-armv4t.S
@@ -40,7 +40,9 @@
 r0 holds returns of <= 4 bytes
 r0-r1 hold returns of 8 bytes, low word in r0
 
-Callee must save/restore r4+ (except r12) if it modifies them.
+Callee must save/restore r4+ (except r12) if it modifies them.  If VFP
+is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved,
+s0-s15 (d0-d7, q0-a3) do not need to be.
 
 Stack is "full descending".  Only the arguments that don't fit in the first 4
 registers are placed on the stack.  "sp" points at the first stacked argument
@@ -61,8 +63,8 @@
   r4  rPC       interpreted program counter, used for fetching instructions
   r5  rFP       interpreted frame pointer, used for accessing locals and args
   r6  rGLUE     MterpGlue pointer
-  r7  rIBASE    interpreted instruction base pointer, used for computed goto
-  r8  rINST     first 16-bit code unit of current instruction
+  r7  rINST     first 16-bit code unit of current instruction
+  r8  rIBASE    interpreted instruction base pointer, used for computed goto
 
 Macros are provided for common operations.  Each macro MUST emit only
 one instruction to make instruction-counting easier.  They MUST NOT alter
@@ -73,8 +75,8 @@
 #define rPC     r4
 #define rFP     r5
 #define rGLUE   r6
-#define rIBASE  r7
-#define rINST   r8
+#define rINST   r7
+#define rIBASE  r8
 
 /* save/restore the PC and/or FP from the glue struct */
 #define LOAD_PC_FROM_GLUE()     ldr     rPC, [rGLUE, #offGlue_pc]
@@ -124,6 +126,13 @@
 #define FETCH_ADVANCE_INST(_count) ldrh    rINST, [rPC, #(_count*2)]!
 
 /*
+ * The operation performed here is similar to FETCH_ADVANCE_INST, except the
+ * src and dest registers are parameterized (not hard-wired to rPC and rINST).
+ */
+#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \
+        ldrh    _dreg, [_sreg, #(_count*2)]!
+
+/*
  * Fetch the next instruction from an offset specified by _reg.  Updates
  * rPC to point to the next instruction.  "_reg" must specify the distance
  * in bytes, *not* 16-bit code units, and may be a signed value.
@@ -157,10 +166,17 @@
 #define GET_INST_OPCODE(_reg)   and     _reg, rINST, #255
 
 /*
+ * Put the prefetched instruction's opcode field into the specified register.
+ */
+#define GET_PREFETCHED_OPCODE(_oreg, _ireg)   and     _oreg, _ireg, #255
+
+/*
  * Begin executing the opcode in _reg.  Because this only jumps within the
  * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
  */
 #define GOTO_OPCODE(_reg)       add     pc, rIBASE, _reg, lsl #6
+#define GOTO_OPCODE_IFEQ(_reg)  addeq   pc, rIBASE, _reg, lsl #6
+#define GOTO_OPCODE_IFNE(_reg)  addne   pc, rIBASE, _reg, lsl #6
 
 /*
  * Get/set the 32-bit value from a Dalvik register.
@@ -168,6 +184,17 @@
 #define GET_VREG(_reg, _vreg)   ldr     _reg, [rFP, _vreg, lsl #2]
 #define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
 
+#if defined(WITH_JIT)
+#define GET_JIT_ENABLED(_reg)       ldr     _reg,[rGLUE,#offGlue_jitEnabled]
+#define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
+#endif
+
+/*
+ * Convert a virtual register index into an address.
+ */
+#define VREG_INDEX_TO_ADDR(_reg, _vreg) \
+        add     _reg, rFP, _vreg, lsl #2
+
 /*
  * This is a #include, not a %include, because we want the C pre-processor
  * to expand the macros into assembler assignment statements.
@@ -282,10 +309,21 @@
     cmp     r1, #kInterpEntryInstr      @ usual case?
     bne     .Lnot_instr                 @ no, handle it
 
+#if defined(WITH_JIT)
+.Lno_singleStep:
+    /* Entry is always a possible trace start */
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_INST()
+    cmp    r0,#0
+    bne    common_updateProfile
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+#else
     /* start executing the instruction at rPC */
     FETCH_INST()                        @ load rINST from rPC
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 .Lnot_instr:
     cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
@@ -295,6 +333,22 @@
     cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
     beq     common_exceptionThrown
 
+#if defined(WITH_JIT)
+.Lnot_throw:
+    ldr     r0,[rGLUE, #offGlue_jitResume]
+    ldr     r2,[rGLUE, #offGlue_jitResumePC]
+    cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
+    bne     .Lbad_arg
+    cmp     rPC,r2
+    bne     .Lno_singleStep             @ must have branched, don't resume
+    mov     r1, #kInterpEntryInstr
+    strb    r1, [rGLUE, #offGlue_entryPoint]
+    ldr     rINST, .LdvmCompilerTemplate
+    bx      r0                          @ re-enter the translation
+.LdvmCompilerTemplate:
+    .word   dvmCompilerTemplateStart
+#endif
+
 .Lbad_arg:
     ldr     r0, strBadEntryPoint
     @ r1 holds value of entryPoint
@@ -450,7 +504,7 @@
     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
-    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
     GOTO_OPCODE(ip)                     @ jump to next instruction
@@ -818,9 +872,7 @@
     GET_VREG(r1, r2)                    @ r1<- vAA (object)
     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
     cmp     r1, #0                      @ null object?
-#ifdef WITH_MONITOR_TRACKING
-    EXPORT_PC()                         @ export PC so we can grab stack trace
-#endif
+    EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
     beq     common_errNullObject        @ null object, throw an exception
     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
     bl      dvmLockObject               @ call(self, obj)
@@ -956,11 +1008,9 @@
     cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
     bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
 .LOP_NEW_INSTANCE_initialized: @ r0=class
-    ldr     r3, [r0, #offClassObject_accessFlags]   @ r3<- clazz->accessFlags
-    tst     r3, #(ACC_INTERFACE|ACC_ABSTRACT)   @ abstract or interface?
     mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
-    beq     .LOP_NEW_INSTANCE_finish          @ concrete class, continue
-    b       .LOP_NEW_INSTANCE_abstract        @ fail
+    bl      dvmAllocObject              @ r0<- new object
+    b       .LOP_NEW_INSTANCE_finish          @ continue
 
 /* ------------------------------ */
     .balign 64
@@ -1095,10 +1145,18 @@
     movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
     mov     r9, r9, lsl #1              @ r9<- byte offset
     bmi     common_backwardBranch       @ backward branch, do periodic checks
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
-
+#endif
 
 /* ------------------------------ */
     .balign 64
@@ -1114,9 +1172,18 @@
     FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
     movs    r9, r0, asl #1              @ r9<- byte offset, check sign
     bmi     common_backwardBranch       @ backward branch, do periodic checks
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 /* ------------------------------ */
@@ -1141,10 +1208,18 @@
     orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
     mov     r9, r0, asl #1              @ r9<- byte offset
     ble     common_backwardBranch       @ backward branch, do periodic checks
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
-
+#endif
 
 /* ------------------------------ */
     .balign 64
@@ -1170,9 +1245,18 @@
     movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
     bmi     common_backwardBranch       @ backward branch, do periodic checks
     beq     common_backwardBranch       @ (want to use BLE but V is unknown)
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 /* ------------------------------ */
@@ -1200,9 +1284,18 @@
     movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
     bmi     common_backwardBranch       @ backward branch, do periodic checks
     beq     common_backwardBranch       @ (want to use BLE but V is unknown)
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 
@@ -1449,9 +1542,16 @@
     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
     movs    r9, r9, asl #1              @ convert to bytes, check sign
     bmi     common_backwardBranch       @ yes, do periodic checks
-1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    b        common_testUpdateProfile
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 
@@ -1479,9 +1579,16 @@
     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
     movs    r9, r9, asl #1              @ convert to bytes, check sign
     bmi     common_backwardBranch       @ yes, do periodic checks
-1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    b        common_testUpdateProfile
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 
@@ -1509,9 +1616,16 @@
     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
     movs    r9, r9, asl #1              @ convert to bytes, check sign
     bmi     common_backwardBranch       @ yes, do periodic checks
-1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    b        common_testUpdateProfile
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 
@@ -1539,9 +1653,16 @@
     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
     movs    r9, r9, asl #1              @ convert to bytes, check sign
     bmi     common_backwardBranch       @ yes, do periodic checks
-1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    b        common_testUpdateProfile
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 
@@ -1569,9 +1690,16 @@
     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
     movs    r9, r9, asl #1              @ convert to bytes, check sign
     bmi     common_backwardBranch       @ yes, do periodic checks
-1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    b        common_testUpdateProfile
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 
@@ -1599,9 +1727,16 @@
     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
     movs    r9, r9, asl #1              @ convert to bytes, check sign
     bmi     common_backwardBranch       @ yes, do periodic checks
-1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    b        common_testUpdateProfile
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 
@@ -1626,9 +1761,19 @@
     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
     movs    r9, r9, asl #1              @ convert to bytes, check sign
     bmi     common_backwardBranch       @ backward branch, do periodic checks
-1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 
@@ -1653,9 +1798,19 @@
     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
     movs    r9, r9, asl #1              @ convert to bytes, check sign
     bmi     common_backwardBranch       @ backward branch, do periodic checks
-1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 
@@ -1680,9 +1835,19 @@
     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
     movs    r9, r9, asl #1              @ convert to bytes, check sign
     bmi     common_backwardBranch       @ backward branch, do periodic checks
-1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 
@@ -1707,9 +1872,19 @@
     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
     movs    r9, r9, asl #1              @ convert to bytes, check sign
     bmi     common_backwardBranch       @ backward branch, do periodic checks
-1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 
@@ -1734,9 +1909,19 @@
     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
     movs    r9, r9, asl #1              @ convert to bytes, check sign
     bmi     common_backwardBranch       @ backward branch, do periodic checks
-1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 
@@ -1761,9 +1946,19 @@
     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
     movs    r9, r9, asl #1              @ convert to bytes, check sign
     bmi     common_backwardBranch       @ backward branch, do periodic checks
-1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 
@@ -3826,20 +4021,23 @@
  */
 d2i_doconv:
     stmfd   sp!, {r4, r5, lr}           @ save regs
-    ldr     r2, .LOP_DOUBLE_TO_INT_maxlo       @ (double)maxint, lo
-    ldr     r3, .LOP_DOUBLE_TO_INT_maxhi       @ (double)maxint, hi
+    mov     r2, #0x80000000             @ maxint, as a double (low word)
+    mov     r2, r2, asr #9              @  0xffc00000
     sub     sp, sp, #4                  @ align for EABI
-    mov     r4, r0                      @ save r0
+    mvn     r3, #0xbe000000             @ maxint, as a double (high word)
+    sub     r3, r3, #0x00200000         @  0x41dfffff
+    mov     r4, r0                      @ save a copy of r0
     mov     r5, r1                      @  and r1
     bl      __aeabi_dcmpge              @ is arg >= maxint?
     cmp     r0, #0                      @ nonzero == yes
-    mvnne   r0, #0x80000000             @ return maxint (7fffffff)
+    mvnne   r0, #0x80000000             @ return maxint (0x7fffffff)
     bne     1f
 
     mov     r0, r4                      @ recover arg
     mov     r1, r5
-    ldr     r3, .LOP_DOUBLE_TO_INT_min         @ (double)minint, hi
-    mov     r2, #0                      @ (double)minint, lo
+    mov     r3, #0xc1000000             @ minint, as a double (high word)
+    add     r3, r3, #0x00e00000         @  0xc1e00000
+    mov     r2, #0                      @ minint, as a double (low word)
     bl      __aeabi_dcmple              @ is arg <= minint?
     cmp     r0, #0                      @ nonzero == yes
     movne   r0, #0x80000000             @ return minint (80000000)
@@ -3860,13 +4058,6 @@
 1:
     add     sp, sp, #4
     ldmfd   sp!, {r4, r5, pc}
-
-.LOP_DOUBLE_TO_INT_maxlo:
-    .word   0xffc00000                  @ maxint, as a double (low word)
-.LOP_DOUBLE_TO_INT_maxhi:
-    .word   0x41dfffff                  @ maxint, as a double (high word)
-.LOP_DOUBLE_TO_INT_min:
-    .word   0xc1e00000                  @ minint, as a double (high word)
 #endif
 
 
@@ -5378,8 +5569,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -5418,8 +5609,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -5459,8 +5650,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -5499,8 +5690,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 1
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -5540,8 +5731,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 1
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -5580,8 +5771,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -5620,8 +5811,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -5660,8 +5851,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -5700,8 +5891,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -5740,8 +5931,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -5780,8 +5971,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -6224,8 +6415,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -6264,8 +6455,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -6304,8 +6495,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -6344,8 +6535,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -6385,8 +6576,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -7435,11 +7626,20 @@
 
 /* ------------------------------ */
     .balign 64
-.L_OP_UNUSED_ED: /* 0xed */
-/* File: armv5te/OP_UNUSED_ED.S */
-/* File: armv5te/unused.S */
-    bl      common_abort
-
+.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
+/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
+    /*
+     * Handle a throw-verification-error instruction.  This throws an
+     * exception for an error discovered during verification.  The
+     * exception is indicated by AA, with some detail provided by BBBB.
+     */
+    /* op AA, ref@BBBB */
+    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
+    FETCH(r2, 1)                        @ r2<- BBBB
+    EXPORT_PC()                         @ export the PC
+    mov     r1, rINST, lsr #8           @ r1<- AA
+    bl      dvmThrowVerificationError   @ always throws
+    b       common_exceptionThrown      @ handle exception
 
 
 /* ------------------------------ */
@@ -7953,8 +8153,7 @@
 /* continuation for OP_NEW_INSTANCE */
 
     .balign 32                          @ minimize cache lines
-.LOP_NEW_INSTANCE_finish: @ r0=class
-    bl      dvmAllocObject              @ r0<- new object
+.LOP_NEW_INSTANCE_finish: @ r0=new object
     mov     r3, rINST, lsr #8           @ r3<- AA
     cmp     r0, #0                      @ failed?
     beq     common_exceptionThrown      @ yes, handle the exception
@@ -7990,18 +8189,6 @@
     bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
     b       common_exceptionThrown      @ yes, handle exception
 
-    /*
-     * We can't instantiate an abstract class or interface, so throw an
-     * InstantiationError with the class descriptor as the message.
-     *
-     *  r0 holds class object
-     */
-.LOP_NEW_INSTANCE_abstract:
-    ldr     r1, [r0, #offClassObject_descriptor]
-    ldr     r0, .LstrInstantiationErrorPtr
-    bl      dvmThrowExceptionWithClassMessage
-    b       common_exceptionThrown
-
 .LstrInstantiationErrorPtr:
     .word   .LstrInstantiationError
 
@@ -9142,10 +9329,11 @@
  */
 d2l_doconv:
     stmfd   sp!, {r4, r5, lr}           @ save regs
-    ldr     r3, .LOP_DOUBLE_TO_LONG_max         @ (double)maxlong, hi
+    mov     r3, #0x43000000             @ maxlong, as a double (high word)
+    add     r3, #0x00e00000             @  0x43e00000
+    mov     r2, #0                      @ maxlong, as a double (low word)
     sub     sp, sp, #4                  @ align for EABI
-    mov     r2, #0                      @ (double)maxlong, lo
-    mov     r4, r0                      @ save r0
+    mov     r4, r0                      @ save a copy of r0
     mov     r5, r1                      @  and r1
     bl      __aeabi_dcmpge              @ is arg >= maxlong?
     cmp     r0, #0                      @ nonzero == yes
@@ -9155,8 +9343,9 @@
 
     mov     r0, r4                      @ recover arg
     mov     r1, r5
-    ldr     r3, .LOP_DOUBLE_TO_LONG_min         @ (double)minlong, hi
-    mov     r2, #0                      @ (double)minlong, lo
+    mov     r3, #0xc3000000             @ minlong, as a double (high word)
+    add     r3, #0x00e00000             @  0xc3e00000
+    mov     r2, #0                      @ minlong, as a double (low word)
     bl      __aeabi_dcmple              @ is arg <= minlong?
     cmp     r0, #0                      @ nonzero == yes
     movne   r0, #0                      @ return minlong (8000000000000000)
@@ -9180,11 +9369,6 @@
     add     sp, sp, #4
     ldmfd   sp!, {r4, r5, pc}
 
-.LOP_DOUBLE_TO_LONG_max:
-    .word   0x43e00000                  @ maxlong, as a double (high word)
-.LOP_DOUBLE_TO_LONG_min:
-    .word   0xc3e00000                  @ minlong, as a double (high word)
-
 
 /* continuation for OP_MUL_LONG */
 
@@ -9286,15 +9470,191 @@
 dvmAsmSisterEnd:
 
 /* File: armv5te/footer.S */
+
 /*
  * ===========================================================================
  *  Common subroutines and data
  * ===========================================================================
  */
 
+
+
     .text
     .align  2
 
+#if defined(WITH_JIT)
+/*
+ * Return from the translation cache to the interpreter when the compiler is
+ * having issues translating/executing a Dalvik instruction. We have to skip
+ * the code cache lookup otherwise it is possible to indefinitely bouce
+ * between the interpreter and the code cache if the instruction that fails
+ * to be compiled happens to be at a trace start.
+ */
+    .global dvmJitToInterpPunt
+dvmJitToInterpPunt:
+    mov    rPC, r0
+#ifdef EXIT_STATS
+    mov    r0,lr
+    bl     dvmBumpPunt;
+#endif
+    EXPORT_PC()
+    adrl   rIBASE, dvmAsmInstructionStart
+    FETCH_INST()
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+
+/*
+ * Return to the interpreter to handle a single instruction.
+ * On entry:
+ *    r0 <= PC
+ *    r1 <= PC of resume instruction
+ *    lr <= resume point in translation
+ */
+    .global dvmJitToInterpSingleStep
+dvmJitToInterpSingleStep:
+    str    lr,[rGLUE,#offGlue_jitResume]
+    str    r1,[rGLUE,#offGlue_jitResumePC]
+    mov    r1,#kInterpEntryInstr
+    @ enum is 4 byte in aapcs-EABI
+    str    r1, [rGLUE, #offGlue_entryPoint]
+    mov    rPC,r0
+    EXPORT_PC()
+    adrl   rIBASE, dvmAsmInstructionStart
+    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
+    str    r2,[rGLUE,#offGlue_jitState]
+    mov    r1,#1                  @ set changeInterp to bail to debug interp
+    b      common_gotoBail
+
+
+/*
+ * Return from the translation cache and immediately request
+ * a translation for the exit target.  Commonly used following
+ * invokes.
+ */
+    .global dvmJitToTraceSelect
+dvmJitToTraceSelect:
+    ldr    rPC,[r14, #-1]           @ get our target PC
+    add    rINST,r14,#-5            @ save start of chain branch
+    mov    r0,rPC
+    bl     dvmJitGetCodeAddr        @ Is there a translation?
+    cmp    r0,#0
+    beq    2f
+    mov    r1,rINST
+    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
+    cmp    r0,#0                    @ successful chain?
+    bxne   r0                       @ continue native execution
+    b      toInterpreter            @ didn't chain - resume with interpreter
+
+/* No translation, so request one if profiling isn't disabled*/
+2:
+    adrl   rIBASE, dvmAsmInstructionStart
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_INST()
+    cmp    r0, #0
+    bne    common_selectTrace
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+
+/*
+ * Return from the translation cache to the interpreter.
+ * The return was done with a BLX from thumb mode, and
+ * the following 32-bit word contains the target rPC value.
+ * Note that lr (r14) will have its low-order bit set to denote
+ * its thumb-mode origin.
+ *
+ * We'll need to stash our lr origin away, recover the new
+ * target and then check to see if there is a translation available
+ * for our new target.  If so, we do a translation chain and
+ * go back to native execution.  Otherwise, it's back to the
+ * interpreter (after treating this entry as a potential
+ * trace start).
+ */
+    .global dvmJitToInterpNormal
+dvmJitToInterpNormal:
+    ldr    rPC,[r14, #-1]           @ get our target PC
+    add    rINST,r14,#-5            @ save start of chain branch
+#ifdef EXIT_STATS
+    bl     dvmBumpNormal
+#endif
+    mov    r0,rPC
+    bl     dvmJitGetCodeAddr        @ Is there a translation?
+    cmp    r0,#0
+    beq    toInterpreter            @ go if not, otherwise do chain
+    mov    r1,rINST
+    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
+    cmp    r0,#0                    @ successful chain?
+    bxne   r0                       @ continue native execution
+    b      toInterpreter            @ didn't chain - resume with interpreter
+
+/*
+ * Return from the translation cache to the interpreter to do method invocation.
+ * Check if translation exists for the callee, but don't chain to it.
+ */
+    .global dvmJitToInterpNoChain
+dvmJitToInterpNoChain:
+#ifdef EXIT_STATS
+    bl     dvmBumpNoChain
+#endif
+    mov    r0,rPC
+    bl     dvmJitGetCodeAddr        @ Is there a translation?
+    cmp    r0,#0
+    bxne   r0                       @ continue native execution if so
+
+/*
+ * No translation, restore interpreter regs and start interpreting.
+ * rGLUE & rFP were preserved in the translated code, and rPC has
+ * already been restored by the time we get here.  We'll need to set
+ * up rIBASE & rINST, and load the address of the JitTable into r0.
+ */
+toInterpreter:
+    EXPORT_PC()
+    adrl   rIBASE, dvmAsmInstructionStart
+    FETCH_INST()
+    GET_JIT_PROF_TABLE(r0)
+    @ NOTE: intended fallthrough
+/*
+ * Common code to update potential trace start counter, and initiate
+ * a trace-build if appropriate.  On entry, rPC should point to the
+ * next instruction to execute, and rINST should be already loaded with
+ * the next opcode word, and r0 holds a pointer to the jit profile
+ * table (pJitProfTable).
+ */
+common_testUpdateProfile:
+    cmp     r0,#0
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
+
+common_updateProfile:
+    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
+    lsl     r3,r3,#23          @ shift out excess 511
+    ldrb    r1,[r0,r3,lsr #23] @ get counter
+    GET_INST_OPCODE(ip)
+    subs    r1,r1,#1           @ decrement counter
+    strb    r1,[r0,r3,lsr #23] @ and store it
+    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
+
+/*
+ * Here, we switch to the debug interpreter to request
+ * trace selection.  First, though, check to see if there
+ * is already a native translation in place (and, if so,
+ * jump to it now).
+ */
+    mov     r1,#255
+    strb    r1,[r0,r3,lsr #23] @ reset counter
+    EXPORT_PC()
+    mov     r0,rPC
+    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
+    cmp     r0,#0
+    beq     common_selectTrace
+    bxne    r0                          @ jump to the translation
+common_selectTrace:
+    mov     r2,#kJitTSelectRequest      @ ask for trace selection
+    str     r2,[rGLUE,#offGlue_jitState]
+    mov     r1,#1                       @ set changeInterp
+    b       common_gotoBail
+
+#endif
+
 /*
  * Common code when a backward branch is taken.
  *
@@ -9304,9 +9664,18 @@
 common_backwardBranch:
     mov     r0, #kInterpEntryInstr
     bl      common_periodicChecks
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+#else
     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 /*
@@ -9342,7 +9711,7 @@
 #endif
 
     cmp     r3, #0                      @ suspend pending?
-    bne     2f                          @ yes, check suspend
+    bne     2f                          @ yes, do full suspension check
 
 #if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
 # if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
@@ -9360,6 +9729,7 @@
 
 2:  @ check suspend
     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
+    EXPORT_PC()                         @ need for precise GC
     b       dvmCheckSuspendPending      @ suspend if necessary, then return
 
 3:  @ debugger/profiler enabled, bail out
@@ -9407,10 +9777,12 @@
     @ (very few methods have > 10 args; could unroll for common cases)
     add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
     sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
+    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
 1:  ldr     r1, [r3], #4                @ val = *fp++
     subs    r2, r2, #1                  @ count--
     str     r1, [r10], #4               @ *outs++ = val
     bne     1b                          @ ...while count != 0
+    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
     b       .LinvokeArgsDone
 
 /*
@@ -9424,47 +9796,50 @@
     @ prepare to copy args to "outs" area of current frame
     movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
     SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
-    beq     .LinvokeArgsDone            @ if no args, skip the rest
-    FETCH(r1, 2)                        @ r1<- GFED
+    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
+    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
+    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
+    beq     .LinvokeArgsDone
 
-    @ r0=methodToCall, r1=GFED, r2=count, r10=outs
+    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
 .LinvokeNonRange:
     rsb     r2, r2, #5                  @ r2<- 5-r2
     add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
     bl      common_abort                @ (skipped due to ARM prefetch)
 5:  and     ip, rINST, #0x0f00          @ isolate A
-    ldr     r3, [rFP, ip, lsr #6]       @ r3<- vA (shift right 8, left 2)
+    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
     mov     r0, r0                      @ nop
-    str     r3, [r10, #-4]!             @ *--outs = vA
+    str     r2, [r10, #-4]!             @ *--outs = vA
 4:  and     ip, r1, #0xf000             @ isolate G
-    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vG (shift right 12, left 2)
+    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
     mov     r0, r0                      @ nop
-    str     r3, [r10, #-4]!             @ *--outs = vG
+    str     r2, [r10, #-4]!             @ *--outs = vG
 3:  and     ip, r1, #0x0f00             @ isolate F
-    ldr     r3, [rFP, ip, lsr #6]       @ r3<- vF
+    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
     mov     r0, r0                      @ nop
-    str     r3, [r10, #-4]!             @ *--outs = vF
+    str     r2, [r10, #-4]!             @ *--outs = vF
 2:  and     ip, r1, #0x00f0             @ isolate E
-    ldr     r3, [rFP, ip, lsr #2]       @ r3<- vE
+    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
     mov     r0, r0                      @ nop
-    str     r3, [r10, #-4]!             @ *--outs = vE
+    str     r2, [r10, #-4]!             @ *--outs = vE
 1:  and     ip, r1, #0x000f             @ isolate D
-    ldr     r3, [rFP, ip, lsl #2]       @ r3<- vD
+    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
     mov     r0, r0                      @ nop
-    str     r3, [r10, #-4]!             @ *--outs = vD
+    str     r2, [r10, #-4]!             @ *--outs = vD
 0:  @ fall through to .LinvokeArgsDone
 
-.LinvokeArgsDone: @ r0=methodToCall
+.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
+    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
+    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
     @ find space for the new stack frame, check for overflow
     SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
-    ldrh    r2, [r0, #offMethod_registersSize]  @ r2<- methodToCall->regsSize
-    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
-    sub     r1, r1, r2, lsl #2          @ r1<- newFp (old savearea - regsSize)
+    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
     SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
 @    bl      common_dumpRegs
     ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
     sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
     cmp     r3, r9                      @ bottom < interpStackEnd?
+    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
     blt     .LstackOverflow             @ yes, this frame will overflow stack
 
     @ set up newSaveArea
@@ -9474,9 +9849,11 @@
 #endif
     str     rFP, [r10, #offStackSaveArea_prevFrame]
     str     rPC, [r10, #offStackSaveArea_savedPc]
+#if defined(WITH_JIT)
+    mov     r9, #0
+    str     r9, [r10, #offStackSaveArea_returnAddr]
+#endif
     str     r0, [r10, #offStackSaveArea_method]
-
-    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
     tst     r3, #ACC_NATIVE
     bne     .LinvokeNative
 
@@ -9495,27 +9872,39 @@
     ldmfd   sp!, {r0-r3}
     */
 
-    @ Update "glue" values for the new method
-    @ r0=methodToCall, r1=newFp
-    ldr     r3, [r0, #offMethod_clazz]      @ r3<- method->clazz
-    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
-    ldr     r3, [r3, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
-    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- method->insns
-    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
+    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
+    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
+    mov     rPC, r2                         @ publish new rPC
     ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
-    FETCH_INST()                            @ load rINST from rPC
+
+    @ Update "glue" values for the new method
+    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
+    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
+    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
     mov     rFP, r1                         @ fp = newFp
-    GET_INST_OPCODE(ip)                     @ extract opcode from rINST
+    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
+    mov     rINST, r9                       @ publish new rINST
+    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
+    cmp     r0,#0
+    bne     common_updateProfile
+    GOTO_OPCODE(ip)                         @ jump to next instruction
+#else
+    mov     rFP, r1                         @ fp = newFp
+    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
+    mov     rINST, r9                       @ publish new rINST
     str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
     GOTO_OPCODE(ip)                         @ jump to next instruction
+#endif
 
 .LinvokeNative:
     @ Prep for the native call
     @ r0=methodToCall, r1=newFp, r10=newSaveArea
     ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
-    ldr     r9, [r3, #offThread_jniLocal_nextEntry] @ r9<- thread->refNext
+    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
     str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
-    str     r9, [r10, #offStackSaveArea_localRefTop] @newFp->localRefTop=refNext
+    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
     mov     r9, r3                      @ r9<- glue->self (preserve)
 
     mov     r2, r0                      @ r2<- methodToCall
@@ -9539,11 +9928,11 @@
 
     @ native return; r9=self, r10=newSaveArea
     @ equivalent to dvmPopJniLocals
-    ldr     r0, [r10, #offStackSaveArea_localRefTop] @ r0<- newSave->localRefTop
+    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
     ldr     r1, [r9, #offThread_exception] @ check for exception
     str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
     cmp     r1, #0                      @ null?
-    str     r0, [r9, #offThread_jniLocal_nextEntry] @ self->refNext<- r0
+    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
     bne     common_exceptionThrown      @ no, handle exception
 
     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
@@ -9600,22 +9989,36 @@
 
     SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
     ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
+    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
     ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
                                         @ r2<- method we're returning to
+    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
     cmp     r2, #0                      @ is this a break frame?
+    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
     mov     r1, #0                      @ "want switch" = false
     beq     common_gotoBail             @ break frame, bail out completely
 
-    ldr     rPC, [r0, #offStackSaveArea_savedPc] @ pc = saveArea->savedPc
-    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
-    str     r2, [rGLUE, #offGlue_method]    @ glue->method = newSave->method
+    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
+    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
+    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
     str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
-    ldr     r1, [r2, #offMethod_clazz]      @ r1<- method->clazz
-    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
-    ldr     r1, [r1, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
+#if defined(WITH_JIT)
+    ldr     r3, [r0, #offStackSaveArea_returnAddr] @ r3 = saveArea->returnAddr
+    GET_JIT_PROF_TABLE(r0)
+    mov     rPC, r9                     @ publish new rPC
+    str     r1, [rGLUE, #offGlue_methodClassDex]
+    cmp     r3, #0                      @ caller is compiled code
+    blxne   r3
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    mov     rPC, r9                     @ publish new rPC
     str     r1, [rGLUE, #offGlue_methodClassDex]
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
     /*
      * Return handling, calls through "glue code".
@@ -9638,12 +10041,19 @@
  *
  * This does not return.
  */
+     .global dvmMterpCommonExceptionThrown
+dvmMterpCommonExceptionThrown:
 common_exceptionThrown:
 .LexceptionNew:
     mov     r0, #kInterpEntryThrow
     mov     r9, #0
     bl      common_periodicChecks
 
+#if defined(WITH_JIT)
+    mov     r2,#kJitTSelectAbort        @ abandon trace selection in progress
+    str     r2,[rGLUE,#offGlue_jitState]
+#endif
+
     ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
     ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
     mov     r1, r10                     @ r1<- self
@@ -9925,6 +10335,38 @@
     bx      lr
     .endif
 
+#if 0
+/*
+ * Experiment on VFP mode.
+ *
+ * uint32_t setFPSCR(uint32_t val, uint32_t mask)
+ *
+ * Updates the bits specified by "mask", setting them to the values in "val".
+ */
+setFPSCR:
+    and     r0, r0, r1                  @ make sure no stray bits are set
+    fmrx    r2, fpscr                   @ get VFP reg
+    mvn     r1, r1                      @ bit-invert mask
+    and     r2, r2, r1                  @ clear masked bits
+    orr     r2, r2, r0                  @ set specified bits
+    fmxr    fpscr, r2                   @ set VFP reg
+    mov     r0, r2                      @ return new value
+    bx      lr
+
+    .align  2
+    .global dvmConfigureFP
+    .type   dvmConfigureFP, %function
+dvmConfigureFP:
+    stmfd   sp!, {ip, lr}
+    /* 0x03000000 sets DN/FZ */
+    /* 0x00009f00 clears the six exception enable flags */
+    bl      common_squeak0
+    mov     r0, #0x03000000             @ r0<- 0x03000000
+    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
+    bl      setFPSCR
+    ldmfd   sp!, {ip, pc}
+#endif
+
 
 /*
  * String references, must be close to the code that uses them.
diff --git a/vm/mterp/out/InterpAsm-armv5te-vfp.S b/vm/mterp/out/InterpAsm-armv5te-vfp.S
new file mode 100644
index 0000000..61b2697
--- /dev/null
+++ b/vm/mterp/out/InterpAsm-armv5te-vfp.S
@@ -0,0 +1,9972 @@
+/*
+ * This file was generated automatically by gen-mterp.py for 'armv5te-vfp'.
+ *
+ * --> DO NOT EDIT <--
+ */
+
+/* File: armv5te/header.S */
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * ARMv5 definitions and declarations.
+ */
+
+/*
+ARM EABI general notes:
+
+r0-r3 hold first 4 args to a method; they are not preserved across method calls
+r4-r8 are available for general use
+r9 is given special treatment in some situations, but not for us
+r10 (sl) seems to be generally available
+r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
+r12 (ip) is scratch -- not preserved across method calls
+r13 (sp) should be managed carefully in case a signal arrives
+r14 (lr) must be preserved
+r15 (pc) can be tinkered with directly
+
+r0 holds returns of <= 4 bytes
+r0-r1 hold returns of 8 bytes, low word in r0
+
+Callee must save/restore r4+ (except r12) if it modifies them.  If VFP
+is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved,
+s0-s15 (d0-d7, q0-a3) do not need to be.
+
+Stack is "full descending".  Only the arguments that don't fit in the first 4
+registers are placed on the stack.  "sp" points at the first stacked argument
+(i.e. the 5th arg).
+
+VFP: single-precision results in s0, double-precision results in d0.
+
+In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
+64-bit quantities (long long, double) must be 64-bit aligned.
+*/
+
+/*
+Mterp and ARM notes:
+
+The following registers have fixed assignments:
+
+  reg nick      purpose
+  r4  rPC       interpreted program counter, used for fetching instructions
+  r5  rFP       interpreted frame pointer, used for accessing locals and args
+  r6  rGLUE     MterpGlue pointer
+  r7  rINST     first 16-bit code unit of current instruction
+  r8  rIBASE    interpreted instruction base pointer, used for computed goto
+
+Macros are provided for common operations.  Each macro MUST emit only
+one instruction to make instruction-counting easier.  They MUST NOT alter
+unspecified registers or condition codes.
+*/
+
+/* single-purpose registers, given names for clarity */
+#define rPC     r4
+#define rFP     r5
+#define rGLUE   r6
+#define rINST   r7
+#define rIBASE  r8
+
+/* save/restore the PC and/or FP from the glue struct */
+#define LOAD_PC_FROM_GLUE()     ldr     rPC, [rGLUE, #offGlue_pc]
+#define SAVE_PC_TO_GLUE()       str     rPC, [rGLUE, #offGlue_pc]
+#define LOAD_FP_FROM_GLUE()     ldr     rFP, [rGLUE, #offGlue_fp]
+#define SAVE_FP_TO_GLUE()       str     rFP, [rGLUE, #offGlue_fp]
+#define LOAD_PC_FP_FROM_GLUE()  ldmia   rGLUE, {rPC, rFP}
+#define SAVE_PC_FP_TO_GLUE()    stmia   rGLUE, {rPC, rFP}
+
+/*
+ * "export" the PC to the stack frame, f/b/o future exception objects.  Must
+ * be done *before* something calls dvmThrowException.
+ *
+ * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
+ * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
+ *
+ * It's okay to do this more than once.
+ */
+#define EXPORT_PC() \
+    str     rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
+
+/*
+ * Given a frame pointer, find the stack save area.
+ *
+ * In C this is "((StackSaveArea*)(_fp) -1)".
+ */
+#define SAVEAREA_FROM_FP(_reg, _fpreg) \
+    sub     _reg, _fpreg, #sizeofStackSaveArea
+
+/*
+ * Fetch the next instruction from rPC into rINST.  Does not advance rPC.
+ */
+#define FETCH_INST()            ldrh    rINST, [rPC]
+
+/*
+ * Fetch the next instruction from the specified offset.  Advances rPC
+ * to point to the next instruction.  "_count" is in 16-bit code units.
+ *
+ * Because of the limited size of immediate constants on ARM, this is only
+ * suitable for small forward movements (i.e. don't try to implement "goto"
+ * with this).
+ *
+ * This must come AFTER anything that can throw an exception, or the
+ * exception catch may miss.  (This also implies that it must come after
+ * EXPORT_PC().)
+ */
+#define FETCH_ADVANCE_INST(_count) ldrh    rINST, [rPC, #(_count*2)]!
+
+/*
+ * The operation performed here is similar to FETCH_ADVANCE_INST, except the
+ * src and dest registers are parameterized (not hard-wired to rPC and rINST).
+ */
+#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \
+        ldrh    _dreg, [_sreg, #(_count*2)]!
+
+/*
+ * Fetch the next instruction from an offset specified by _reg.  Updates
+ * rPC to point to the next instruction.  "_reg" must specify the distance
+ * in bytes, *not* 16-bit code units, and may be a signed value.
+ *
+ * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the
+ * bits that hold the shift distance are used for the half/byte/sign flags.
+ * In some cases we can pre-double _reg for free, so we require a byte offset
+ * here.
+ */
+#define FETCH_ADVANCE_INST_RB(_reg) ldrh    rINST, [rPC, _reg]!
+
+/*
+ * Fetch a half-word code unit from an offset past the current PC.  The
+ * "_count" value is in 16-bit code units.  Does not advance rPC.
+ *
+ * The "_S" variant works the same but treats the value as signed.
+ */
+#define FETCH(_reg, _count)     ldrh    _reg, [rPC, #(_count*2)]
+#define FETCH_S(_reg, _count)   ldrsh   _reg, [rPC, #(_count*2)]
+
+/*
+ * Fetch one byte from an offset past the current PC.  Pass in the same
+ * "_count" as you would for FETCH, and an additional 0/1 indicating which
+ * byte of the halfword you want (lo/hi).
+ */
+#define FETCH_B(_reg, _count, _byte) ldrb     _reg, [rPC, #(_count*2+_byte)]
+
+/*
+ * Put the instruction's opcode field into the specified register.
+ */
+#define GET_INST_OPCODE(_reg)   and     _reg, rINST, #255
+
+/*
+ * Put the prefetched instruction's opcode field into the specified register.
+ */
+#define GET_PREFETCHED_OPCODE(_oreg, _ireg)   and     _oreg, _ireg, #255
+
+/*
+ * Begin executing the opcode in _reg.  Because this only jumps within the
+ * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
+ */
+#define GOTO_OPCODE(_reg)       add     pc, rIBASE, _reg, lsl #6
+#define GOTO_OPCODE_IFEQ(_reg)  addeq   pc, rIBASE, _reg, lsl #6
+#define GOTO_OPCODE_IFNE(_reg)  addne   pc, rIBASE, _reg, lsl #6
+
+/*
+ * Get/set the 32-bit value from a Dalvik register.
+ */
+#define GET_VREG(_reg, _vreg)   ldr     _reg, [rFP, _vreg, lsl #2]
+#define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
+
+#if defined(WITH_JIT)
+#define GET_JIT_ENABLED(_reg)       ldr     _reg,[rGLUE,#offGlue_jitEnabled]
+#define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
+#endif
+
+/*
+ * Convert a virtual register index into an address.
+ */
+#define VREG_INDEX_TO_ADDR(_reg, _vreg) \
+        add     _reg, rFP, _vreg, lsl #2
+
+/*
+ * This is a #include, not a %include, because we want the C pre-processor
+ * to expand the macros into assembler assignment statements.
+ */
+#include "../common/asm-constants.h"
+
+
+/* File: armv5te/platform.S */
+/*
+ * ===========================================================================
+ *  CPU-version-specific defines
+ * ===========================================================================
+ */
+
+/*
+ * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5.  Essentially a
+ * one-way branch.
+ *
+ * May modify IP.  Does not modify LR.
+ */
+.macro  LDR_PC source
+    ldr     pc, \source
+.endm
+
+/*
+ * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
+ * Jump to subroutine.
+ *
+ * May modify IP and LR.
+ */
+.macro  LDR_PC_LR source
+    mov     lr, pc
+    ldr     pc, \source
+.endm
+
+/*
+ * Macro for "LDMFD SP!, {...regs...,PC}".
+ *
+ * May modify IP and LR.
+ */
+.macro  LDMFD_PC regs
+    ldmfd   sp!, {\regs,pc}
+.endm
+
+
+/* File: armv5te/entry.S */
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Interpreter entry point.
+ */
+
+/*
+ * We don't have formal stack frames, so gdb scans upward in the code
+ * to find the start of the function (a label with the %function type),
+ * and then looks at the next few instructions to figure out what
+ * got pushed onto the stack.  From this it figures out how to restore
+ * the registers, including PC, for the previous stack frame.  If gdb
+ * sees a non-function label, it stops scanning, so either we need to
+ * have nothing but assembler-local labels between the entry point and
+ * the break, or we need to fake it out.
+ *
+ * When this is defined, we add some stuff to make gdb less confused.
+ */
+#define ASSIST_DEBUGGER 1
+
+    .text
+    .align  2
+    .global dvmMterpStdRun
+    .type   dvmMterpStdRun, %function
+
+/*
+ * On entry:
+ *  r0  MterpGlue* glue
+ *
+ * This function returns a boolean "changeInterp" value.  The return comes
+ * via a call to dvmMterpStdBail().
+ */
+dvmMterpStdRun:
+#define MTERP_ENTRY1 \
+    .save {r4-r10,fp,lr}; \
+    stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
+#define MTERP_ENTRY2 \
+    .pad    #4; \
+    sub     sp, sp, #4                  @ align 64
+
+    .fnstart
+    MTERP_ENTRY1
+    MTERP_ENTRY2
+
+    /* save stack pointer, add magic word for debuggerd */
+    str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
+
+    /* set up "named" registers, figure out entry point */
+    mov     rGLUE, r0                   @ set rGLUE
+    ldrb    r1, [r0, #offGlue_entryPoint]   @ InterpEntry enum is char
+    LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
+    adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
+    cmp     r1, #kInterpEntryInstr      @ usual case?
+    bne     .Lnot_instr                 @ no, handle it
+
+#if defined(WITH_JIT)
+.Lno_singleStep:
+    /* Entry is always a possible trace start */
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_INST()
+    cmp    r0,#0
+    bne    common_updateProfile
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+#else
+    /* start executing the instruction at rPC */
+    FETCH_INST()                        @ load rINST from rPC
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+.Lnot_instr:
+    cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
+    beq     common_returnFromMethod
+
+.Lnot_return:
+    cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
+    beq     common_exceptionThrown
+
+#if defined(WITH_JIT)
+.Lnot_throw:
+    ldr     r0,[rGLUE, #offGlue_jitResume]
+    ldr     r2,[rGLUE, #offGlue_jitResumePC]
+    cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
+    bne     .Lbad_arg
+    cmp     rPC,r2
+    bne     .Lno_singleStep             @ must have branched, don't resume
+    mov     r1, #kInterpEntryInstr
+    strb    r1, [rGLUE, #offGlue_entryPoint]
+    ldr     rINST, .LdvmCompilerTemplate
+    bx      r0                          @ re-enter the translation
+.LdvmCompilerTemplate:
+    .word   dvmCompilerTemplateStart
+#endif
+
+.Lbad_arg:
+    ldr     r0, strBadEntryPoint
+    @ r1 holds value of entryPoint
+    bl      printf
+    bl      dvmAbort
+    .fnend
+
+
+    .global dvmMterpStdBail
+    .type   dvmMterpStdBail, %function
+
+/*
+ * Restore the stack pointer and PC from the save point established on entry.
+ * This is essentially the same as a longjmp, but should be cheaper.  The
+ * last instruction causes us to return to whoever called dvmMterpStdRun.
+ *
+ * We pushed some registers on the stack in dvmMterpStdRun, then saved
+ * SP and LR.  Here we restore SP, restore the registers, and then restore
+ * LR to PC.
+ *
+ * On entry:
+ *  r0  MterpGlue* glue
+ *  r1  bool changeInterp
+ */
+dvmMterpStdBail:
+    ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
+    mov     r0, r1                          @ return the changeInterp value
+    add     sp, sp, #4                      @ un-align 64
+    LDMFD_PC "r4-r10,fp"                    @ restore 9 regs and return
+
+
+/*
+ * String references.
+ */
+strBadEntryPoint:
+    .word   .LstrBadEntryPoint
+
+
+
+    .global dvmAsmInstructionStart
+    .type   dvmAsmInstructionStart, %function
+dvmAsmInstructionStart = .L_OP_NOP
+    .text
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_NOP: /* 0x00 */
+/* File: armv5te/OP_NOP.S */
+    FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
+    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
+    GOTO_OPCODE(ip)                     @ execute it
+
+#ifdef ASSIST_DEBUGGER
+    /* insert fake function header to help gdb find the stack frame */
+    .type   dalvik_inst, %function
+dalvik_inst:
+    .fnstart
+    MTERP_ENTRY1
+    MTERP_ENTRY2
+    .fnend
+#endif
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MOVE: /* 0x01 */
+/* File: armv5te/OP_MOVE.S */
+    /* for move, move-object, long-to-int */
+    /* op vA, vB */
+    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
+    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    GET_VREG(r2, r1)                    @ r2<- fp[B]
+    and     r0, r0, #15
+    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
+    SET_VREG(r2, r0)                    @ fp[A]<- r2
+    GOTO_OPCODE(ip)                     @ execute next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MOVE_FROM16: /* 0x02 */
+/* File: armv5te/OP_MOVE_FROM16.S */
+    /* for: move/from16, move-object/from16 */
+    /* op vAA, vBBBB */
+    FETCH(r1, 1)                        @ r1<- BBBB
+    mov     r0, rINST, lsr #8           @ r0<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r2, r0)                    @ fp[AA]<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MOVE_16: /* 0x03 */
+/* File: armv5te/OP_MOVE_16.S */
+    /* for: move/16, move-object/16 */
+    /* op vAAAA, vBBBB */
+    FETCH(r1, 2)                        @ r1<- BBBB
+    FETCH(r0, 1)                        @ r0<- AAAA
+    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
+    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MOVE_WIDE: /* 0x04 */
+/* File: armv5te/OP_MOVE_WIDE.S */
+    /* move-wide vA, vB */
+    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
+    mov     r2, rINST, lsr #8           @ r2<- A(+)
+    mov     r3, rINST, lsr #12          @ r3<- B
+    and     r2, r2, #15
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
+    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
+/* File: armv5te/OP_MOVE_WIDE_FROM16.S */
+    /* move-wide/from16 vAA, vBBBB */
+    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
+    FETCH(r3, 1)                        @ r3<- BBBB
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
+    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MOVE_WIDE_16: /* 0x06 */
+/* File: armv5te/OP_MOVE_WIDE_16.S */
+    /* move-wide/16 vAAAA, vBBBB */
+    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
+    FETCH(r3, 2)                        @ r3<- BBBB
+    FETCH(r2, 1)                        @ r2<- AAAA
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
+    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
+    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MOVE_OBJECT: /* 0x07 */
+/* File: armv5te/OP_MOVE_OBJECT.S */
+/* File: armv5te/OP_MOVE.S */
+    /* for move, move-object, long-to-int */
+    /* op vA, vB */
+    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
+    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    GET_VREG(r2, r1)                    @ r2<- fp[B]
+    and     r0, r0, #15
+    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
+    SET_VREG(r2, r0)                    @ fp[A]<- r2
+    GOTO_OPCODE(ip)                     @ execute next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
+/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
+/* File: armv5te/OP_MOVE_FROM16.S */
+    /* for: move/from16, move-object/from16 */
+    /* op vAA, vBBBB */
+    FETCH(r1, 1)                        @ r1<- BBBB
+    mov     r0, rINST, lsr #8           @ r0<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r2, r0)                    @ fp[AA]<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MOVE_OBJECT_16: /* 0x09 */
+/* File: armv5te/OP_MOVE_OBJECT_16.S */
+/* File: armv5te/OP_MOVE_16.S */
+    /* for: move/16, move-object/16 */
+    /* op vAAAA, vBBBB */
+    FETCH(r1, 2)                        @ r1<- BBBB
+    FETCH(r0, 1)                        @ r0<- AAAA
+    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
+    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MOVE_RESULT: /* 0x0a */
+/* File: armv5te/OP_MOVE_RESULT.S */
+    /* for: move-result, move-result-object */
+    /* op vAA */
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r2)                    @ fp[AA]<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
+/* File: armv5te/OP_MOVE_RESULT_WIDE.S */
+    /* move-result-wide vAA */
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
+    ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
+/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
+/* File: armv5te/OP_MOVE_RESULT.S */
+    /* for: move-result, move-result-object */
+    /* op vAA */
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r2)                    @ fp[AA]<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MOVE_EXCEPTION: /* 0x0d */
+/* File: armv5te/OP_MOVE_EXCEPTION.S */
+    /* move-exception vAA */
+    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
+    mov     r1, #0                      @ r1<- 0
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_RETURN_VOID: /* 0x0e */
+/* File: armv5te/OP_RETURN_VOID.S */
+    b       common_returnFromMethod
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_RETURN: /* 0x0f */
+/* File: armv5te/OP_RETURN.S */
+    /*
+     * Return a 32-bit value.  Copies the return value into the "glue"
+     * structure, then jumps to the return handler.
+     *
+     * for: return, return-object
+     */
+    /* op vAA */
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    GET_VREG(r0, r2)                    @ r0<- vAA
+    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
+    b       common_returnFromMethod
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_RETURN_WIDE: /* 0x10 */
+/* File: armv5te/OP_RETURN_WIDE.S */
+    /*
+     * Return a 64-bit value.  Copies the return value into the "glue"
+     * structure, then jumps to the return handler.
+     */
+    /* return-wide vAA */
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
+    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
+    ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
+    stmia   r3, {r0-r1}                 @ retval<- r0/r1
+    b       common_returnFromMethod
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_RETURN_OBJECT: /* 0x11 */
+/* File: armv5te/OP_RETURN_OBJECT.S */
+/* File: armv5te/OP_RETURN.S */
+    /*
+     * Return a 32-bit value.  Copies the return value into the "glue"
+     * structure, then jumps to the return handler.
+     *
+     * for: return, return-object
+     */
+    /* op vAA */
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    GET_VREG(r0, r2)                    @ r0<- vAA
+    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
+    b       common_returnFromMethod
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CONST_4: /* 0x12 */
+/* File: armv5te/OP_CONST_4.S */
+    /* const/4 vA, #+B */
+    mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
+    mov     r0, rINST, lsr #8           @ r0<- A+
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
+    and     r0, r0, #15
+    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
+    SET_VREG(r1, r0)                    @ fp[A]<- r1
+    GOTO_OPCODE(ip)                     @ execute next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CONST_16: /* 0x13 */
+/* File: armv5te/OP_CONST_16.S */
+    /* const/16 vAA, #+BBBB */
+    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    SET_VREG(r0, r3)                    @ vAA<- r0
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CONST: /* 0x14 */
+/* File: armv5te/OP_CONST.S */
+    /* const vAA, #+BBBBbbbb */
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    FETCH(r0, 1)                        @ r0<- bbbb (low)
+    FETCH(r1, 2)                        @ r1<- BBBB (high)
+    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
+    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r3)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CONST_HIGH16: /* 0x15 */
+/* File: armv5te/OP_CONST_HIGH16.S */
+    /* const/high16 vAA, #+BBBB0000 */
+    FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    mov     r0, r0, lsl #16             @ r0<- BBBB0000
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    SET_VREG(r0, r3)                    @ vAA<- r0
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CONST_WIDE_16: /* 0x16 */
+/* File: armv5te/OP_CONST_WIDE_16.S */
+    /* const-wide/16 vAA, #+BBBB */
+    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    mov     r1, r0, asr #31             @ r1<- ssssssss
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CONST_WIDE_32: /* 0x17 */
+/* File: armv5te/OP_CONST_WIDE_32.S */
+    /* const-wide/32 vAA, #+BBBBbbbb */
+    FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
+    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
+    orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
+    mov     r1, r0, asr #31             @ r1<- ssssssss
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CONST_WIDE: /* 0x18 */
+/* File: armv5te/OP_CONST_WIDE.S */
+    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
+    FETCH(r0, 1)                        @ r0<- bbbb (low)
+    FETCH(r1, 2)                        @ r1<- BBBB (low middle)
+    FETCH(r2, 3)                        @ r2<- hhhh (high middle)
+    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
+    FETCH(r3, 4)                        @ r3<- HHHH (high)
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
+    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
+/* File: armv5te/OP_CONST_WIDE_HIGH16.S */
+    /* const-wide/high16 vAA, #+BBBB000000000000 */
+    FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    mov     r0, #0                      @ r0<- 00000000
+    mov     r1, r1, lsl #16             @ r1<- BBBB0000
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CONST_STRING: /* 0x1a */
+/* File: armv5te/OP_CONST_STRING.S */
+    /* const/string vAA, String@BBBB */
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
+    cmp     r0, #0                      @ not yet resolved?
+    beq     .LOP_CONST_STRING_resolve
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CONST_STRING_JUMBO: /* 0x1b */
+/* File: armv5te/OP_CONST_STRING_JUMBO.S */
+    /* const/string vAA, String@BBBBBBBB */
+    FETCH(r0, 1)                        @ r0<- bbbb (low)
+    FETCH(r1, 2)                        @ r1<- BBBB (high)
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
+    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
+    cmp     r0, #0
+    beq     .LOP_CONST_STRING_JUMBO_resolve
+    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CONST_CLASS: /* 0x1c */
+/* File: armv5te/OP_CONST_CLASS.S */
+    /* const/class vAA, Class@BBBB */
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
+    cmp     r0, #0                      @ not yet resolved?
+    beq     .LOP_CONST_CLASS_resolve
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MONITOR_ENTER: /* 0x1d */
+/* File: armv5te/OP_MONITOR_ENTER.S */
+    /*
+     * Synchronize on an object.
+     */
+    /* monitor-enter vAA */
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    GET_VREG(r1, r2)                    @ r1<- vAA (object)
+    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
+    cmp     r1, #0                      @ null object?
+    EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
+    beq     common_errNullObject        @ null object, throw an exception
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    bl      dvmLockObject               @ call(self, obj)
+#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
+    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
+    ldr     r1, [r0, #offThread_exception] @ check for exception
+    cmp     r1, #0
+    bne     common_exceptionThrown      @ exception raised, bail out
+#endif
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MONITOR_EXIT: /* 0x1e */
+/* File: armv5te/OP_MONITOR_EXIT.S */
+    /*
+     * Unlock an object.
+     *
+     * Exceptions that occur when unlocking a monitor need to appear as
+     * if they happened at the following instruction.  See the Dalvik
+     * instruction spec.
+     */
+    /* monitor-exit vAA */
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    EXPORT_PC()                         @ before fetch: export the PC
+    GET_VREG(r1, r2)                    @ r1<- vAA (object)
+    cmp     r1, #0                      @ null object?
+    beq     common_errNullObject        @ yes
+    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
+    bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
+    cmp     r0, #0                      @ failed?
+    beq     common_exceptionThrown      @ yes, exception is pending
+    FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CHECK_CAST: /* 0x1f */
+/* File: armv5te/OP_CHECK_CAST.S */
+    /*
+     * Check to see if a cast from one class to another is allowed.
+     */
+    /* check-cast vAA, class@BBBB */
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    FETCH(r2, 1)                        @ r2<- BBBB
+    GET_VREG(r9, r3)                    @ r9<- object
+    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
+    cmp     r9, #0                      @ is object null?
+    ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
+    beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
+    ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
+    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
+    cmp     r1, #0                      @ have we resolved this before?
+    beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
+.LOP_CHECK_CAST_resolved:
+    cmp     r0, r1                      @ same class (trivial success)?
+    bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
+.LOP_CHECK_CAST_okay:
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INSTANCE_OF: /* 0x20 */
+/* File: armv5te/OP_INSTANCE_OF.S */
+    /*
+     * Check to see if an object reference is an instance of a class.
+     *
+     * Most common situation is a non-null object, being compared against
+     * an already-resolved class.
+     */
+    /* instance-of vA, vB, class@CCCC */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    GET_VREG(r0, r3)                    @ r0<- vB (object)
+    and     r9, r9, #15                 @ r9<- A
+    cmp     r0, #0                      @ is object null?
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
+    beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
+    FETCH(r3, 1)                        @ r3<- CCCC
+    ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
+    ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
+    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
+    cmp     r1, #0                      @ have we resolved this before?
+    beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
+.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
+    cmp     r0, r1                      @ same class (trivial success)?
+    beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
+    b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_ARRAY_LENGTH: /* 0x21 */
+/* File: armv5te/OP_ARRAY_LENGTH.S */
+    /*
+     * Return the length of an array.
+     */
+    mov     r1, rINST, lsr #12          @ r1<- B
+    mov     r2, rINST, lsr #8           @ r2<- A+
+    GET_VREG(r0, r1)                    @ r0<- vB (object ref)
+    and     r2, r2, #15                 @ r2<- A
+    cmp     r0, #0                      @ is object null?
+    beq     common_errNullObject        @ yup, fail
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r3, r2)                    @ vB<- length
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_NEW_INSTANCE: /* 0x22 */
+/* File: armv5te/OP_NEW_INSTANCE.S */
+    /*
+     * Create a new instance of a class.
+     */
+    /* new-instance vAA, class@BBBB */
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
+    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
+    EXPORT_PC()                         @ req'd for init, resolve, alloc
+    cmp     r0, #0                      @ already resolved?
+    beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
+.LOP_NEW_INSTANCE_resolved:   @ r0=class
+    ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
+    cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
+    bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
+.LOP_NEW_INSTANCE_initialized: @ r0=class
+    mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
+    bl      dvmAllocObject              @ r0<- new object
+    b       .LOP_NEW_INSTANCE_finish          @ continue
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_NEW_ARRAY: /* 0x23 */
+/* File: armv5te/OP_NEW_ARRAY.S */
+    /*
+     * Allocate an array of objects, specified with the array class
+     * and a count.
+     *
+     * The verifier guarantees that this is an array class, so we don't
+     * check for it here.
+     */
+    /* new-array vA, vB, class@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    FETCH(r2, 1)                        @ r2<- CCCC
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
+    GET_VREG(r1, r0)                    @ r1<- vB (array length)
+    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
+    cmp     r1, #0                      @ check length
+    ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
+    bmi     common_errNegativeArraySize @ negative length, bail
+    cmp     r0, #0                      @ already resolved?
+    EXPORT_PC()                         @ req'd for resolve, alloc
+    bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
+    b       .LOP_NEW_ARRAY_resolve         @ do resolve now
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
+/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
+    /*
+     * Create a new array with elements filled from registers.
+     *
+     * for: filled-new-array, filled-new-array/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
+    EXPORT_PC()                         @ need for resolve and alloc
+    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
+    mov     r10, rINST, lsr #8          @ r10<- AA or BA
+    cmp     r0, #0                      @ already resolved?
+    bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
+8:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
+    mov     r2, #0                      @ r2<- false
+    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveClass             @ r0<- call(clazz, ref)
+    cmp     r0, #0                      @ got null?
+    beq     common_exceptionThrown      @ yes, handle exception
+    b       .LOP_FILLED_NEW_ARRAY_continue
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
+/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
+/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
+    /*
+     * Create a new array with elements filled from registers.
+     *
+     * for: filled-new-array, filled-new-array/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
+    EXPORT_PC()                         @ need for resolve and alloc
+    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
+    mov     r10, rINST, lsr #8          @ r10<- AA or BA
+    cmp     r0, #0                      @ already resolved?
+    bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
+8:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
+    mov     r2, #0                      @ r2<- false
+    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveClass             @ r0<- call(clazz, ref)
+    cmp     r0, #0                      @ got null?
+    beq     common_exceptionThrown      @ yes, handle exception
+    b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_FILL_ARRAY_DATA: /* 0x26 */
+/* File: armv5te/OP_FILL_ARRAY_DATA.S */
+    /* fill-array-data vAA, +BBBBBBBB */
+    FETCH(r0, 1)                        @ r0<- bbbb (lo)
+    FETCH(r1, 2)                        @ r1<- BBBB (hi)
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
+    GET_VREG(r0, r3)                    @ r0<- vAA (array object)
+    add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
+    EXPORT_PC();
+    bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
+    cmp     r0, #0                      @ 0 means an exception is thrown
+    beq     common_exceptionThrown      @ has exception
+    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_THROW: /* 0x27 */
+/* File: armv5te/OP_THROW.S */
+    /*
+     * Throw an exception object in the current thread.
+     */
+    /* throw vAA */
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
+    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
+    cmp     r1, #0                      @ null object?
+    beq     common_errNullObject        @ yes, throw an NPE instead
+    @ bypass dvmSetException, just store it
+    str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
+    b       common_exceptionThrown
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_GOTO: /* 0x28 */
+/* File: armv5te/OP_GOTO.S */
+    /*
+     * Unconditional branch, 8-bit offset.
+     *
+     * The branch distance is a signed code-unit offset, which we need to
+     * double to get a byte offset.
+     */
+    /* goto +AA */
+    mov     r0, rINST, lsl #16          @ r0<- AAxx0000
+    movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
+    mov     r9, r9, lsl #1              @ r9<- byte offset
+    bmi     common_backwardBranch       @ backward branch, do periodic checks
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_GOTO_16: /* 0x29 */
+/* File: armv5te/OP_GOTO_16.S */
+    /*
+     * Unconditional branch, 16-bit offset.
+     *
+     * The branch distance is a signed code-unit offset, which we need to
+     * double to get a byte offset.
+     */
+    /* goto/16 +AAAA */
+    FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
+    movs    r9, r0, asl #1              @ r9<- byte offset, check sign
+    bmi     common_backwardBranch       @ backward branch, do periodic checks
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_GOTO_32: /* 0x2a */
+/* File: armv5te/OP_GOTO_32.S */
+    /*
+     * Unconditional branch, 32-bit offset.
+     *
+     * The branch distance is a signed code-unit offset, which we need to
+     * double to get a byte offset.
+     *
+     * Unlike most opcodes, this one is allowed to branch to itself, so
+     * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
+     * instruction doesn't affect the V flag, so we need to clear it
+     * explicitly.
+     */
+    /* goto/32 +AAAAAAAA */
+    FETCH(r0, 1)                        @ r0<- aaaa (lo)
+    FETCH(r1, 2)                        @ r1<- AAAA (hi)
+    cmp     ip, ip                      @ (clear V flag during stall)
+    orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
+    mov     r9, r0, asl #1              @ r9<- byte offset
+    ble     common_backwardBranch       @ backward branch, do periodic checks
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_PACKED_SWITCH: /* 0x2b */
+/* File: armv5te/OP_PACKED_SWITCH.S */
+    /*
+     * Handle a packed-switch or sparse-switch instruction.  In both cases
+     * we decode it and hand it off to a helper function.
+     *
+     * We don't really expect backward branches in a switch statement, but
+     * they're perfectly legal, so we check for them here.
+     *
+     * for: packed-switch, sparse-switch
+     */
+    /* op vAA, +BBBB */
+    FETCH(r0, 1)                        @ r0<- bbbb (lo)
+    FETCH(r1, 2)                        @ r1<- BBBB (hi)
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
+    GET_VREG(r1, r3)                    @ r1<- vAA
+    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
+    bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
+    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
+    bmi     common_backwardBranch       @ backward branch, do periodic checks
+    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SPARSE_SWITCH: /* 0x2c */
+/* File: armv5te/OP_SPARSE_SWITCH.S */
+/* File: armv5te/OP_PACKED_SWITCH.S */
+    /*
+     * Handle a packed-switch or sparse-switch instruction.  In both cases
+     * we decode it and hand it off to a helper function.
+     *
+     * We don't really expect backward branches in a switch statement, but
+     * they're perfectly legal, so we check for them here.
+     *
+     * for: packed-switch, sparse-switch
+     */
+    /* op vAA, +BBBB */
+    FETCH(r0, 1)                        @ r0<- bbbb (lo)
+    FETCH(r1, 2)                        @ r1<- BBBB (hi)
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
+    GET_VREG(r1, r3)                    @ r1<- vAA
+    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
+    bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
+    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
+    bmi     common_backwardBranch       @ backward branch, do periodic checks
+    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CMPL_FLOAT: /* 0x2d */
+/* File: arm-vfp/OP_CMPL_FLOAT.S */
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else {
+     *         return -1;
+     *     }
+     * }
+     */
+    /* op vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    flds    s0, [r2]                    @ s0<- vBB
+    flds    s1, [r3]                    @ s1<- vCC
+    fcmpes  s0, s1                      @ compare (vBB, vCC)
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    mvn     r0, #0                      @ r0<- -1 (default)
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fmstat                              @ export status flags
+    movgt   r0, #1                      @ (greater than) r1<- 1
+    moveq   r0, #0                      @ (equal) r1<- 0
+    b       .LOP_CMPL_FLOAT_finish          @ argh
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CMPG_FLOAT: /* 0x2e */
+/* File: arm-vfp/OP_CMPG_FLOAT.S */
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else {
+     *         return 1;
+     *     }
+     * }
+     */
+    /* op vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    flds    s0, [r2]                    @ s0<- vBB
+    flds    s1, [r3]                    @ s1<- vCC
+    fcmpes  s0, s1                      @ compare (vBB, vCC)
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    mov     r0, #1                      @ r0<- 1 (default)
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fmstat                              @ export status flags
+    mvnmi   r0, #0                      @ (less than) r1<- -1
+    moveq   r0, #0                      @ (equal) r1<- 0
+    b       .LOP_CMPG_FLOAT_finish          @ argh
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CMPL_DOUBLE: /* 0x2f */
+/* File: arm-vfp/OP_CMPL_DOUBLE.S */
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else {
+     *         return -1;
+     *     }
+     * }
+     */
+    /* op vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    fldd    d0, [r2]                    @ d0<- vBB
+    fldd    d1, [r3]                    @ d1<- vCC
+    fcmped  d0, d1                      @ compare (vBB, vCC)
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    mvn     r0, #0                      @ r0<- -1 (default)
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fmstat                              @ export status flags
+    movgt   r0, #1                      @ (greater than) r1<- 1
+    moveq   r0, #0                      @ (equal) r1<- 0
+    b       .LOP_CMPL_DOUBLE_finish          @ argh
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CMPG_DOUBLE: /* 0x30 */
+/* File: arm-vfp/OP_CMPG_DOUBLE.S */
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else {
+     *         return 1;
+     *     }
+     * }
+     */
+    /* op vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    fldd    d0, [r2]                    @ d0<- vBB
+    fldd    d1, [r3]                    @ d1<- vCC
+    fcmped  d0, d1                      @ compare (vBB, vCC)
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    mov     r0, #1                      @ r0<- 1 (default)
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fmstat                              @ export status flags
+    mvnmi   r0, #0                      @ (less than) r1<- -1
+    moveq   r0, #0                      @ (equal) r1<- 0
+    b       .LOP_CMPG_DOUBLE_finish          @ argh
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CMP_LONG: /* 0x31 */
+/* File: armv5te/OP_CMP_LONG.S */
+    /*
+     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
+     * register based on the results of the comparison.
+     *
+     * We load the full values with LDM, but in practice many values could
+     * be resolved by only looking at the high word.  This could be made
+     * faster or slower by splitting the LDM into a pair of LDRs.
+     *
+     * If we just wanted to set condition flags, we could do this:
+     *  subs    ip, r0, r2
+     *  sbcs    ip, r1, r3
+     *  subeqs  ip, r0, r2
+     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
+     * integer value, which we can do with 2 conditional mov/mvn instructions
+     * (set 1, set -1; if they're equal we already have 0 in ip), giving
+     * us a constant 5-cycle path plus a branch at the end to the
+     * instruction epilogue code.  The multi-compare approach below needs
+     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
+     * in the worst case (the 64-bit values are equal).
+     */
+    /* cmp-long vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
+    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
+    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
+    blt     .LOP_CMP_LONG_less            @ signed compare on high part
+    bgt     .LOP_CMP_LONG_greater
+    subs    r1, r0, r2                  @ r1<- r0 - r2
+    bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
+    bne     .LOP_CMP_LONG_less
+    b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IF_EQ: /* 0x32 */
+/* File: armv5te/OP_IF_EQ.S */
+/* File: armv5te/bincmp.S */
+    /*
+     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
+     * fragment that specifies the *reverse* comparison to perform, e.g.
+     * for "if-le" you would use "gt".
+     *
+     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+     */
+    /* if-cmp vA, vB, +CCCC */
+    mov     r0, rINST, lsr #8           @ r0<- A+
+    mov     r1, rINST, lsr #12          @ r1<- B
+    and     r0, r0, #15
+    GET_VREG(r3, r1)                    @ r3<- vB
+    GET_VREG(r2, r0)                    @ r2<- vA
+    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
+    cmp     r2, r3                      @ compare (vA, vB)
+    bne  1f                      @ branch to 1 if comparison failed
+    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
+    movs    r9, r9, asl #1              @ convert to bytes, check sign
+    bmi     common_backwardBranch       @ yes, do periodic checks
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    b        common_testUpdateProfile
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IF_NE: /* 0x33 */
+/* File: armv5te/OP_IF_NE.S */
+/* File: armv5te/bincmp.S */
+    /*
+     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
+     * fragment that specifies the *reverse* comparison to perform, e.g.
+     * for "if-le" you would use "gt".
+     *
+     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+     */
+    /* if-cmp vA, vB, +CCCC */
+    mov     r0, rINST, lsr #8           @ r0<- A+
+    mov     r1, rINST, lsr #12          @ r1<- B
+    and     r0, r0, #15
+    GET_VREG(r3, r1)                    @ r3<- vB
+    GET_VREG(r2, r0)                    @ r2<- vA
+    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
+    cmp     r2, r3                      @ compare (vA, vB)
+    beq  1f                      @ branch to 1 if comparison failed
+    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
+    movs    r9, r9, asl #1              @ convert to bytes, check sign
+    bmi     common_backwardBranch       @ yes, do periodic checks
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    b        common_testUpdateProfile
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IF_LT: /* 0x34 */
+/* File: armv5te/OP_IF_LT.S */
+/* File: armv5te/bincmp.S */
+    /*
+     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
+     * fragment that specifies the *reverse* comparison to perform, e.g.
+     * for "if-le" you would use "gt".
+     *
+     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+     */
+    /* if-cmp vA, vB, +CCCC */
+    mov     r0, rINST, lsr #8           @ r0<- A+
+    mov     r1, rINST, lsr #12          @ r1<- B
+    and     r0, r0, #15
+    GET_VREG(r3, r1)                    @ r3<- vB
+    GET_VREG(r2, r0)                    @ r2<- vA
+    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
+    cmp     r2, r3                      @ compare (vA, vB)
+    bge  1f                      @ branch to 1 if comparison failed
+    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
+    movs    r9, r9, asl #1              @ convert to bytes, check sign
+    bmi     common_backwardBranch       @ yes, do periodic checks
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    b        common_testUpdateProfile
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IF_GE: /* 0x35 */
+/* File: armv5te/OP_IF_GE.S */
+/* File: armv5te/bincmp.S */
+    /*
+     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
+     * fragment that specifies the *reverse* comparison to perform, e.g.
+     * for "if-le" you would use "gt".
+     *
+     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+     */
+    /* if-cmp vA, vB, +CCCC */
+    mov     r0, rINST, lsr #8           @ r0<- A+
+    mov     r1, rINST, lsr #12          @ r1<- B
+    and     r0, r0, #15
+    GET_VREG(r3, r1)                    @ r3<- vB
+    GET_VREG(r2, r0)                    @ r2<- vA
+    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
+    cmp     r2, r3                      @ compare (vA, vB)
+    blt  1f                      @ branch to 1 if comparison failed
+    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
+    movs    r9, r9, asl #1              @ convert to bytes, check sign
+    bmi     common_backwardBranch       @ yes, do periodic checks
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    b        common_testUpdateProfile
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IF_GT: /* 0x36 */
+/* File: armv5te/OP_IF_GT.S */
+/* File: armv5te/bincmp.S */
+    /*
+     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
+     * fragment that specifies the *reverse* comparison to perform, e.g.
+     * for "if-le" you would use "gt".
+     *
+     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+     */
+    /* if-cmp vA, vB, +CCCC */
+    mov     r0, rINST, lsr #8           @ r0<- A+
+    mov     r1, rINST, lsr #12          @ r1<- B
+    and     r0, r0, #15
+    GET_VREG(r3, r1)                    @ r3<- vB
+    GET_VREG(r2, r0)                    @ r2<- vA
+    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
+    cmp     r2, r3                      @ compare (vA, vB)
+    ble  1f                      @ branch to 1 if comparison failed
+    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
+    movs    r9, r9, asl #1              @ convert to bytes, check sign
+    bmi     common_backwardBranch       @ yes, do periodic checks
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    b        common_testUpdateProfile
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IF_LE: /* 0x37 */
+/* File: armv5te/OP_IF_LE.S */
+/* File: armv5te/bincmp.S */
+    /*
+     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
+     * fragment that specifies the *reverse* comparison to perform, e.g.
+     * for "if-le" you would use "gt".
+     *
+     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+     */
+    /* if-cmp vA, vB, +CCCC */
+    mov     r0, rINST, lsr #8           @ r0<- A+
+    mov     r1, rINST, lsr #12          @ r1<- B
+    and     r0, r0, #15
+    GET_VREG(r3, r1)                    @ r3<- vB
+    GET_VREG(r2, r0)                    @ r2<- vA
+    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
+    cmp     r2, r3                      @ compare (vA, vB)
+    bgt  1f                      @ branch to 1 if comparison failed
+    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
+    movs    r9, r9, asl #1              @ convert to bytes, check sign
+    bmi     common_backwardBranch       @ yes, do periodic checks
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    b        common_testUpdateProfile
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IF_EQZ: /* 0x38 */
+/* File: armv5te/OP_IF_EQZ.S */
+/* File: armv5te/zcmp.S */
+    /*
+     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
+     * fragment that specifies the *reverse* comparison to perform, e.g.
+     * for "if-le" you would use "gt".
+     *
+     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+     */
+    /* if-cmp vAA, +BBBB */
+    mov     r0, rINST, lsr #8           @ r0<- AA
+    GET_VREG(r2, r0)                    @ r2<- vAA
+    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
+    cmp     r2, #0                      @ compare (vA, 0)
+    bne  1f                      @ branch to 1 if comparison failed
+    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
+    movs    r9, r9, asl #1              @ convert to bytes, check sign
+    bmi     common_backwardBranch       @ backward branch, do periodic checks
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IF_NEZ: /* 0x39 */
+/* File: armv5te/OP_IF_NEZ.S */
+/* File: armv5te/zcmp.S */
+    /*
+     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
+     * fragment that specifies the *reverse* comparison to perform, e.g.
+     * for "if-le" you would use "gt".
+     *
+     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+     */
+    /* if-cmp vAA, +BBBB */
+    mov     r0, rINST, lsr #8           @ r0<- AA
+    GET_VREG(r2, r0)                    @ r2<- vAA
+    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
+    cmp     r2, #0                      @ compare (vA, 0)
+    beq  1f                      @ branch to 1 if comparison failed
+    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
+    movs    r9, r9, asl #1              @ convert to bytes, check sign
+    bmi     common_backwardBranch       @ backward branch, do periodic checks
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IF_LTZ: /* 0x3a */
+/* File: armv5te/OP_IF_LTZ.S */
+/* File: armv5te/zcmp.S */
+    /*
+     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
+     * fragment that specifies the *reverse* comparison to perform, e.g.
+     * for "if-le" you would use "gt".
+     *
+     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+     */
+    /* if-cmp vAA, +BBBB */
+    mov     r0, rINST, lsr #8           @ r0<- AA
+    GET_VREG(r2, r0)                    @ r2<- vAA
+    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
+    cmp     r2, #0                      @ compare (vA, 0)
+    bge  1f                      @ branch to 1 if comparison failed
+    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
+    movs    r9, r9, asl #1              @ convert to bytes, check sign
+    bmi     common_backwardBranch       @ backward branch, do periodic checks
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IF_GEZ: /* 0x3b */
+/* File: armv5te/OP_IF_GEZ.S */
+/* File: armv5te/zcmp.S */
+    /*
+     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
+     * fragment that specifies the *reverse* comparison to perform, e.g.
+     * for "if-le" you would use "gt".
+     *
+     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+     */
+    /* if-cmp vAA, +BBBB */
+    mov     r0, rINST, lsr #8           @ r0<- AA
+    GET_VREG(r2, r0)                    @ r2<- vAA
+    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
+    cmp     r2, #0                      @ compare (vA, 0)
+    blt  1f                      @ branch to 1 if comparison failed
+    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
+    movs    r9, r9, asl #1              @ convert to bytes, check sign
+    bmi     common_backwardBranch       @ backward branch, do periodic checks
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IF_GTZ: /* 0x3c */
+/* File: armv5te/OP_IF_GTZ.S */
+/* File: armv5te/zcmp.S */
+    /*
+     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
+     * fragment that specifies the *reverse* comparison to perform, e.g.
+     * for "if-le" you would use "gt".
+     *
+     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+     */
+    /* if-cmp vAA, +BBBB */
+    mov     r0, rINST, lsr #8           @ r0<- AA
+    GET_VREG(r2, r0)                    @ r2<- vAA
+    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
+    cmp     r2, #0                      @ compare (vA, 0)
+    ble  1f                      @ branch to 1 if comparison failed
+    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
+    movs    r9, r9, asl #1              @ convert to bytes, check sign
+    bmi     common_backwardBranch       @ backward branch, do periodic checks
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IF_LEZ: /* 0x3d */
+/* File: armv5te/OP_IF_LEZ.S */
+/* File: armv5te/zcmp.S */
+    /*
+     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
+     * fragment that specifies the *reverse* comparison to perform, e.g.
+     * for "if-le" you would use "gt".
+     *
+     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+     */
+    /* if-cmp vAA, +BBBB */
+    mov     r0, rINST, lsr #8           @ r0<- AA
+    GET_VREG(r2, r0)                    @ r2<- vAA
+    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
+    cmp     r2, #0                      @ compare (vA, 0)
+    bgt  1f                      @ branch to 1 if comparison failed
+    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
+    movs    r9, r9, asl #1              @ convert to bytes, check sign
+    bmi     common_backwardBranch       @ backward branch, do periodic checks
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_3E: /* 0x3e */
+/* File: armv5te/OP_UNUSED_3E.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_3F: /* 0x3f */
+/* File: armv5te/OP_UNUSED_3F.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_40: /* 0x40 */
+/* File: armv5te/OP_UNUSED_40.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_41: /* 0x41 */
+/* File: armv5te/OP_UNUSED_41.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_42: /* 0x42 */
+/* File: armv5te/OP_UNUSED_42.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_43: /* 0x43 */
+/* File: armv5te/OP_UNUSED_43.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_AGET: /* 0x44 */
+/* File: armv5te/OP_AGET.S */
+    /*
+     * Array get, 32 bits or less.  vAA <- vBB[vCC].
+     *
+     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+     * instructions.  We use a pair of FETCH_Bs instead.
+     *
+     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
+     */
+    /* op vAA, vBB, vCC */
+    FETCH_B(r2, 1, 0)                   @ r2<- BB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    FETCH_B(r3, 1, 1)                   @ r3<- CC
+    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
+    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
+    cmp     r1, r3                      @ compare unsigned index, length
+    bcs     common_errArrayIndex        @ index >= length, bail
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r2, r9)                    @ vAA<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_AGET_WIDE: /* 0x45 */
+/* File: armv5te/OP_AGET_WIDE.S */
+    /*
+     * Array get, 64 bits.  vAA <- vBB[vCC].
+     *
+     * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
+     */
+    /* aget-wide vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
+    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
+    cmp     r1, r3                      @ compare unsigned index, length
+    bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
+    b       common_errArrayIndex        @ index >= length, bail
+    @ May want to swap the order of these two branches depending on how the
+    @ branch prediction (if any) handles conditional forward branches vs.
+    @ unconditional forward branches.
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_AGET_OBJECT: /* 0x46 */
+/* File: armv5te/OP_AGET_OBJECT.S */
+/* File: armv5te/OP_AGET.S */
+    /*
+     * Array get, 32 bits or less.  vAA <- vBB[vCC].
+     *
+     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+     * instructions.  We use a pair of FETCH_Bs instead.
+     *
+     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
+     */
+    /* op vAA, vBB, vCC */
+    FETCH_B(r2, 1, 0)                   @ r2<- BB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    FETCH_B(r3, 1, 1)                   @ r3<- CC
+    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
+    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
+    cmp     r1, r3                      @ compare unsigned index, length
+    bcs     common_errArrayIndex        @ index >= length, bail
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r2, r9)                    @ vAA<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_AGET_BOOLEAN: /* 0x47 */
+/* File: armv5te/OP_AGET_BOOLEAN.S */
+/* File: armv5te/OP_AGET.S */
+    /*
+     * Array get, 32 bits or less.  vAA <- vBB[vCC].
+     *
+     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+     * instructions.  We use a pair of FETCH_Bs instead.
+     *
+     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
+     */
+    /* op vAA, vBB, vCC */
+    FETCH_B(r2, 1, 0)                   @ r2<- BB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    FETCH_B(r3, 1, 1)                   @ r3<- CC
+    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
+    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
+    cmp     r1, r3                      @ compare unsigned index, length
+    bcs     common_errArrayIndex        @ index >= length, bail
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r2, r9)                    @ vAA<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_AGET_BYTE: /* 0x48 */
+/* File: armv5te/OP_AGET_BYTE.S */
+/* File: armv5te/OP_AGET.S */
+    /*
+     * Array get, 32 bits or less.  vAA <- vBB[vCC].
+     *
+     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+     * instructions.  We use a pair of FETCH_Bs instead.
+     *
+     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
+     */
+    /* op vAA, vBB, vCC */
+    FETCH_B(r2, 1, 0)                   @ r2<- BB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    FETCH_B(r3, 1, 1)                   @ r3<- CC
+    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
+    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
+    cmp     r1, r3                      @ compare unsigned index, length
+    bcs     common_errArrayIndex        @ index >= length, bail
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r2, r9)                    @ vAA<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_AGET_CHAR: /* 0x49 */
+/* File: armv5te/OP_AGET_CHAR.S */
+/* File: armv5te/OP_AGET.S */
+    /*
+     * Array get, 32 bits or less.  vAA <- vBB[vCC].
+     *
+     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+     * instructions.  We use a pair of FETCH_Bs instead.
+     *
+     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
+     */
+    /* op vAA, vBB, vCC */
+    FETCH_B(r2, 1, 0)                   @ r2<- BB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    FETCH_B(r3, 1, 1)                   @ r3<- CC
+    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
+    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
+    cmp     r1, r3                      @ compare unsigned index, length
+    bcs     common_errArrayIndex        @ index >= length, bail
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r2, r9)                    @ vAA<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_AGET_SHORT: /* 0x4a */
+/* File: armv5te/OP_AGET_SHORT.S */
+/* File: armv5te/OP_AGET.S */
+    /*
+     * Array get, 32 bits or less.  vAA <- vBB[vCC].
+     *
+     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+     * instructions.  We use a pair of FETCH_Bs instead.
+     *
+     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
+     */
+    /* op vAA, vBB, vCC */
+    FETCH_B(r2, 1, 0)                   @ r2<- BB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    FETCH_B(r3, 1, 1)                   @ r3<- CC
+    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
+    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
+    cmp     r1, r3                      @ compare unsigned index, length
+    bcs     common_errArrayIndex        @ index >= length, bail
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r2, r9)                    @ vAA<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_APUT: /* 0x4b */
+/* File: armv5te/OP_APUT.S */
+    /*
+     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
+     *
+     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+     * instructions.  We use a pair of FETCH_Bs instead.
+     *
+     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
+     */
+    /* op vAA, vBB, vCC */
+    FETCH_B(r2, 1, 0)                   @ r2<- BB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    FETCH_B(r3, 1, 1)                   @ r3<- CC
+    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
+    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
+    cmp     r1, r3                      @ compare unsigned index, length
+    bcs     common_errArrayIndex        @ index >= length, bail
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_VREG(r2, r9)                    @ r2<- vAA
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_APUT_WIDE: /* 0x4c */
+/* File: armv5te/OP_APUT_WIDE.S */
+    /*
+     * Array put, 64 bits.  vBB[vCC] <- vAA.
+     *
+     * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
+     */
+    /* aput-wide vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
+    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
+    cmp     r1, r3                      @ compare unsigned index, length
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+    bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
+    b       common_errArrayIndex        @ index >= length, bail
+    @ May want to swap the order of these two branches depending on how the
+    @ branch prediction (if any) handles conditional forward branches vs.
+    @ unconditional forward branches.
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_APUT_OBJECT: /* 0x4d */
+/* File: armv5te/OP_APUT_OBJECT.S */
+    /*
+     * Store an object into an array.  vBB[vCC] <- vAA.
+     *
+     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+     * instructions.  We use a pair of FETCH_Bs instead.
+     */
+    /* op vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    GET_VREG(r1, r2)                    @ r1<- vBB (array object)
+    GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
+    cmp     r1, #0                      @ null array object?
+    GET_VREG(r9, r9)                    @ r9<- vAA
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
+    cmp     r0, r3                      @ compare unsigned index, length
+    bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
+    b       common_errArrayIndex        @ index >= length, bail
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_APUT_BOOLEAN: /* 0x4e */
+/* File: armv5te/OP_APUT_BOOLEAN.S */
+/* File: armv5te/OP_APUT.S */
+    /*
+     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
+     *
+     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+     * instructions.  We use a pair of FETCH_Bs instead.
+     *
+     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
+     */
+    /* op vAA, vBB, vCC */
+    FETCH_B(r2, 1, 0)                   @ r2<- BB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    FETCH_B(r3, 1, 1)                   @ r3<- CC
+    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
+    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
+    cmp     r1, r3                      @ compare unsigned index, length
+    bcs     common_errArrayIndex        @ index >= length, bail
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_VREG(r2, r9)                    @ r2<- vAA
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_APUT_BYTE: /* 0x4f */
+/* File: armv5te/OP_APUT_BYTE.S */
+/* File: armv5te/OP_APUT.S */
+    /*
+     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
+     *
+     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+     * instructions.  We use a pair of FETCH_Bs instead.
+     *
+     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
+     */
+    /* op vAA, vBB, vCC */
+    FETCH_B(r2, 1, 0)                   @ r2<- BB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    FETCH_B(r3, 1, 1)                   @ r3<- CC
+    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
+    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
+    cmp     r1, r3                      @ compare unsigned index, length
+    bcs     common_errArrayIndex        @ index >= length, bail
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_VREG(r2, r9)                    @ r2<- vAA
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_APUT_CHAR: /* 0x50 */
+/* File: armv5te/OP_APUT_CHAR.S */
+/* File: armv5te/OP_APUT.S */
+    /*
+     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
+     *
+     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+     * instructions.  We use a pair of FETCH_Bs instead.
+     *
+     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
+     */
+    /* op vAA, vBB, vCC */
+    FETCH_B(r2, 1, 0)                   @ r2<- BB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    FETCH_B(r3, 1, 1)                   @ r3<- CC
+    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
+    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
+    cmp     r1, r3                      @ compare unsigned index, length
+    bcs     common_errArrayIndex        @ index >= length, bail
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_VREG(r2, r9)                    @ r2<- vAA
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_APUT_SHORT: /* 0x51 */
+/* File: armv5te/OP_APUT_SHORT.S */
+/* File: armv5te/OP_APUT.S */
+    /*
+     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
+     *
+     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+     * instructions.  We use a pair of FETCH_Bs instead.
+     *
+     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
+     */
+    /* op vAA, vBB, vCC */
+    FETCH_B(r2, 1, 0)                   @ r2<- BB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    FETCH_B(r3, 1, 1)                   @ r3<- CC
+    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
+    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
+    cmp     r1, r3                      @ compare unsigned index, length
+    bcs     common_errArrayIndex        @ index >= length, bail
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_VREG(r2, r9)                    @ r2<- vAA
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IGET: /* 0x52 */
+/* File: armv5te/OP_IGET.S */
+    /*
+     * General 32-bit instance field get.
+     *
+     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
+     */
+    /* op vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IGET_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0
+    bne     .LOP_IGET_finish
+    b       common_exceptionThrown
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IGET_WIDE: /* 0x53 */
+/* File: armv5te/OP_IGET_WIDE.S */
+    /*
+     * Wide 32-bit instance field get.
+     */
+    /* iget-wide vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IGET_WIDE_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0
+    bne     .LOP_IGET_WIDE_finish
+    b       common_exceptionThrown
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IGET_OBJECT: /* 0x54 */
+/* File: armv5te/OP_IGET_OBJECT.S */
+/* File: armv5te/OP_IGET.S */
+    /*
+     * General 32-bit instance field get.
+     *
+     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
+     */
+    /* op vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0
+    bne     .LOP_IGET_OBJECT_finish
+    b       common_exceptionThrown
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IGET_BOOLEAN: /* 0x55 */
+/* File: armv5te/OP_IGET_BOOLEAN.S */
+@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
+/* File: armv5te/OP_IGET.S */
+    /*
+     * General 32-bit instance field get.
+     *
+     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
+     */
+    /* op vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0
+    bne     .LOP_IGET_BOOLEAN_finish
+    b       common_exceptionThrown
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IGET_BYTE: /* 0x56 */
+/* File: armv5te/OP_IGET_BYTE.S */
+@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
+/* File: armv5te/OP_IGET.S */
+    /*
+     * General 32-bit instance field get.
+     *
+     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
+     */
+    /* op vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IGET_BYTE_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0
+    bne     .LOP_IGET_BYTE_finish
+    b       common_exceptionThrown
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IGET_CHAR: /* 0x57 */
+/* File: armv5te/OP_IGET_CHAR.S */
+@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
+/* File: armv5te/OP_IGET.S */
+    /*
+     * General 32-bit instance field get.
+     *
+     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
+     */
+    /* op vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IGET_CHAR_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0
+    bne     .LOP_IGET_CHAR_finish
+    b       common_exceptionThrown
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IGET_SHORT: /* 0x58 */
+/* File: armv5te/OP_IGET_SHORT.S */
+@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
+/* File: armv5te/OP_IGET.S */
+    /*
+     * General 32-bit instance field get.
+     *
+     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
+     */
+    /* op vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IGET_SHORT_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0
+    bne     .LOP_IGET_SHORT_finish
+    b       common_exceptionThrown
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IPUT: /* 0x59 */
+/* File: armv5te/OP_IPUT.S */
+    /*
+     * General 32-bit instance field put.
+     *
+     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+     */
+    /* op vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IPUT_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_IPUT_finish          @ yes, finish up
+    b       common_exceptionThrown
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IPUT_WIDE: /* 0x5a */
+/* File: armv5te/OP_IPUT_WIDE.S */
+    /* iput-wide vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
+    b       common_exceptionThrown
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IPUT_OBJECT: /* 0x5b */
+/* File: armv5te/OP_IPUT_OBJECT.S */
+/* File: armv5te/OP_IPUT.S */
+    /*
+     * General 32-bit instance field put.
+     *
+     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+     */
+    /* op vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
+    b       common_exceptionThrown
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IPUT_BOOLEAN: /* 0x5c */
+/* File: armv5te/OP_IPUT_BOOLEAN.S */
+@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
+/* File: armv5te/OP_IPUT.S */
+    /*
+     * General 32-bit instance field put.
+     *
+     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+     */
+    /* op vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
+    b       common_exceptionThrown
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IPUT_BYTE: /* 0x5d */
+/* File: armv5te/OP_IPUT_BYTE.S */
+@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
+/* File: armv5te/OP_IPUT.S */
+    /*
+     * General 32-bit instance field put.
+     *
+     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+     */
+    /* op vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
+    b       common_exceptionThrown
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IPUT_CHAR: /* 0x5e */
+/* File: armv5te/OP_IPUT_CHAR.S */
+@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
+/* File: armv5te/OP_IPUT.S */
+    /*
+     * General 32-bit instance field put.
+     *
+     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+     */
+    /* op vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
+    b       common_exceptionThrown
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IPUT_SHORT: /* 0x5f */
+/* File: armv5te/OP_IPUT_SHORT.S */
+@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
+/* File: armv5te/OP_IPUT.S */
+    /*
+     * General 32-bit instance field put.
+     *
+     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+     */
+    /* op vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
+    b       common_exceptionThrown
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SGET: /* 0x60 */
+/* File: armv5te/OP_SGET.S */
+    /*
+     * General 32-bit SGET handler.
+     *
+     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
+     */
+    /* op vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SGET_resolve         @ yes, do resolve
+.LOP_SGET_finish: @ field ptr in r0
+    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    SET_VREG(r1, r2)                    @ fp[AA]<- r1
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SGET_WIDE: /* 0x61 */
+/* File: armv5te/OP_SGET_WIDE.S */
+    /*
+     * 64-bit SGET handler.
+     */
+    /* sget-wide vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
+.LOP_SGET_WIDE_finish:
+    mov     r1, rINST, lsr #8           @ r1<- AA
+    ldrd    r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
+    add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SGET_OBJECT: /* 0x62 */
+/* File: armv5te/OP_SGET_OBJECT.S */
+/* File: armv5te/OP_SGET.S */
+    /*
+     * General 32-bit SGET handler.
+     *
+     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
+     */
+    /* op vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
+.LOP_SGET_OBJECT_finish: @ field ptr in r0
+    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    SET_VREG(r1, r2)                    @ fp[AA]<- r1
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SGET_BOOLEAN: /* 0x63 */
+/* File: armv5te/OP_SGET_BOOLEAN.S */
+/* File: armv5te/OP_SGET.S */
+    /*
+     * General 32-bit SGET handler.
+     *
+     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
+     */
+    /* op vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
+.LOP_SGET_BOOLEAN_finish: @ field ptr in r0
+    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    SET_VREG(r1, r2)                    @ fp[AA]<- r1
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SGET_BYTE: /* 0x64 */
+/* File: armv5te/OP_SGET_BYTE.S */
+/* File: armv5te/OP_SGET.S */
+    /*
+     * General 32-bit SGET handler.
+     *
+     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
+     */
+    /* op vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
+.LOP_SGET_BYTE_finish: @ field ptr in r0
+    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    SET_VREG(r1, r2)                    @ fp[AA]<- r1
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SGET_CHAR: /* 0x65 */
+/* File: armv5te/OP_SGET_CHAR.S */
+/* File: armv5te/OP_SGET.S */
+    /*
+     * General 32-bit SGET handler.
+     *
+     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
+     */
+    /* op vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
+.LOP_SGET_CHAR_finish: @ field ptr in r0
+    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    SET_VREG(r1, r2)                    @ fp[AA]<- r1
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SGET_SHORT: /* 0x66 */
+/* File: armv5te/OP_SGET_SHORT.S */
+/* File: armv5te/OP_SGET.S */
+    /*
+     * General 32-bit SGET handler.
+     *
+     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
+     */
+    /* op vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
+.LOP_SGET_SHORT_finish: @ field ptr in r0
+    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    SET_VREG(r1, r2)                    @ fp[AA]<- r1
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SPUT: /* 0x67 */
+/* File: armv5te/OP_SPUT.S */
+    /*
+     * General 32-bit SPUT handler.
+     *
+     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
+     */
+    /* op vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SPUT_resolve         @ yes, do resolve
+.LOP_SPUT_finish:   @ field ptr in r0
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_VREG(r1, r2)                    @ r1<- fp[AA]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str     r1, [r0, #offStaticField_value] @ field<- vAA
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SPUT_WIDE: /* 0x68 */
+/* File: armv5te/OP_SPUT_WIDE.S */
+    /*
+     * 64-bit SPUT handler.
+     */
+    /* sput-wide vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
+.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    strd    r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SPUT_OBJECT: /* 0x69 */
+/* File: armv5te/OP_SPUT_OBJECT.S */
+/* File: armv5te/OP_SPUT.S */
+    /*
+     * General 32-bit SPUT handler.
+     *
+     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
+     */
+    /* op vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SPUT_OBJECT_resolve         @ yes, do resolve
+.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_VREG(r1, r2)                    @ r1<- fp[AA]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str     r1, [r0, #offStaticField_value] @ field<- vAA
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SPUT_BOOLEAN: /* 0x6a */
+/* File: armv5te/OP_SPUT_BOOLEAN.S */
+/* File: armv5te/OP_SPUT.S */
+    /*
+     * General 32-bit SPUT handler.
+     *
+     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
+     */
+    /* op vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
+.LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_VREG(r1, r2)                    @ r1<- fp[AA]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str     r1, [r0, #offStaticField_value] @ field<- vAA
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SPUT_BYTE: /* 0x6b */
+/* File: armv5te/OP_SPUT_BYTE.S */
+/* File: armv5te/OP_SPUT.S */
+    /*
+     * General 32-bit SPUT handler.
+     *
+     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
+     */
+    /* op vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
+.LOP_SPUT_BYTE_finish:   @ field ptr in r0
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_VREG(r1, r2)                    @ r1<- fp[AA]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str     r1, [r0, #offStaticField_value] @ field<- vAA
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SPUT_CHAR: /* 0x6c */
+/* File: armv5te/OP_SPUT_CHAR.S */
+/* File: armv5te/OP_SPUT.S */
+    /*
+     * General 32-bit SPUT handler.
+     *
+     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
+     */
+    /* op vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
+.LOP_SPUT_CHAR_finish:   @ field ptr in r0
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_VREG(r1, r2)                    @ r1<- fp[AA]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str     r1, [r0, #offStaticField_value] @ field<- vAA
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SPUT_SHORT: /* 0x6d */
+/* File: armv5te/OP_SPUT_SHORT.S */
+/* File: armv5te/OP_SPUT.S */
+    /*
+     * General 32-bit SPUT handler.
+     *
+     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
+     */
+    /* op vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
+.LOP_SPUT_SHORT_finish:   @ field ptr in r0
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_VREG(r1, r2)                    @ r1<- fp[AA]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str     r1, [r0, #offStaticField_value] @ field<- vAA
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_VIRTUAL: /* 0x6e */
+/* File: armv5te/OP_INVOKE_VIRTUAL.S */
+    /*
+     * Handle a virtual method call.
+     *
+     * for: invoke-virtual, invoke-virtual/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
+    FETCH(r10, 2)                       @ r10<- GFED or CCCC
+    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
+    .if     (!0)
+    and     r10, r10, #15               @ r10<- D (or stays CCCC)
+    .endif
+    cmp     r0, #0                      @ already resolved?
+    EXPORT_PC()                         @ must export for invoke
+    bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
+    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
+    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
+    mov     r2, #METHOD_VIRTUAL         @ resolver method type
+    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
+    cmp     r0, #0                      @ got null?
+    bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
+    b       common_exceptionThrown      @ yes, handle exception
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_SUPER: /* 0x6f */
+/* File: armv5te/OP_INVOKE_SUPER.S */
+    /*
+     * Handle a "super" method call.
+     *
+     * for: invoke-super, invoke-super/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    FETCH(r10, 2)                       @ r10<- GFED or CCCC
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
+    .if     (!0)
+    and     r10, r10, #15               @ r10<- D (or stays CCCC)
+    .endif
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
+    GET_VREG(r2, r10)                   @ r2<- "this" ptr
+    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
+    cmp     r2, #0                      @ null "this"?
+    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
+    beq     common_errNullObject        @ null "this", throw exception
+    cmp     r0, #0                      @ already resolved?
+    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
+    EXPORT_PC()                         @ must export for invoke
+    bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
+    b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_DIRECT: /* 0x70 */
+/* File: armv5te/OP_INVOKE_DIRECT.S */
+    /*
+     * Handle a direct method call.
+     *
+     * (We could defer the "is 'this' pointer null" test to the common
+     * method invocation code, and use a flag to indicate that static
+     * calls don't count.  If we do this as part of copying the arguments
+     * out we could avoiding loading the first arg twice.)
+     *
+     * for: invoke-direct, invoke-direct/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
+    FETCH(r10, 2)                       @ r10<- GFED or CCCC
+    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
+    .if     (!0)
+    and     r10, r10, #15               @ r10<- D (or stays CCCC)
+    .endif
+    cmp     r0, #0                      @ already resolved?
+    EXPORT_PC()                         @ must export for invoke
+    GET_VREG(r2, r10)                   @ r2<- "this" ptr
+    beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
+.LOP_INVOKE_DIRECT_finish:
+    cmp     r2, #0                      @ null "this" ref?
+    bne     common_invokeMethodNoRange   @ no, continue on
+    b       common_errNullObject        @ yes, throw exception
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_STATIC: /* 0x71 */
+/* File: armv5te/OP_INVOKE_STATIC.S */
+    /*
+     * Handle a static method call.
+     *
+     * for: invoke-static, invoke-static/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
+    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
+    cmp     r0, #0                      @ already resolved?
+    EXPORT_PC()                         @ must export for invoke
+    bne     common_invokeMethodNoRange @ yes, continue on
+0:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
+    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
+    mov     r2, #METHOD_STATIC          @ resolver method type
+    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
+    cmp     r0, #0                      @ got null?
+    bne     common_invokeMethodNoRange @ no, continue
+    b       common_exceptionThrown      @ yes, handle exception
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_INTERFACE: /* 0x72 */
+/* File: armv5te/OP_INVOKE_INTERFACE.S */
+    /*
+     * Handle an interface method call.
+     *
+     * for: invoke-interface, invoke-interface/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
+    FETCH(r1, 1)                        @ r1<- BBBB
+    .if     (!0)
+    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
+    .endif
+    EXPORT_PC()                         @ must export for invoke
+    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
+    cmp     r0, #0                      @ null obj?
+    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
+    beq     common_errNullObject        @ yes, fail
+    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
+    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
+    cmp     r0, #0                      @ failed?
+    beq     common_exceptionThrown      @ yes, handle exception
+    b       common_invokeMethodNoRange @ jump to common handler 
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_73: /* 0x73 */
+/* File: armv5te/OP_UNUSED_73.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
+/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
+/* File: armv5te/OP_INVOKE_VIRTUAL.S */
+    /*
+     * Handle a virtual method call.
+     *
+     * for: invoke-virtual, invoke-virtual/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
+    FETCH(r10, 2)                       @ r10<- GFED or CCCC
+    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
+    .if     (!1)
+    and     r10, r10, #15               @ r10<- D (or stays CCCC)
+    .endif
+    cmp     r0, #0                      @ already resolved?
+    EXPORT_PC()                         @ must export for invoke
+    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
+    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
+    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
+    mov     r2, #METHOD_VIRTUAL         @ resolver method type
+    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
+    cmp     r0, #0                      @ got null?
+    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
+    b       common_exceptionThrown      @ yes, handle exception
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
+/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
+/* File: armv5te/OP_INVOKE_SUPER.S */
+    /*
+     * Handle a "super" method call.
+     *
+     * for: invoke-super, invoke-super/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    FETCH(r10, 2)                       @ r10<- GFED or CCCC
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
+    .if     (!1)
+    and     r10, r10, #15               @ r10<- D (or stays CCCC)
+    .endif
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
+    GET_VREG(r2, r10)                   @ r2<- "this" ptr
+    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
+    cmp     r2, #0                      @ null "this"?
+    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
+    beq     common_errNullObject        @ null "this", throw exception
+    cmp     r0, #0                      @ already resolved?
+    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
+    EXPORT_PC()                         @ must export for invoke
+    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
+    b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
+/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
+/* File: armv5te/OP_INVOKE_DIRECT.S */
+    /*
+     * Handle a direct method call.
+     *
+     * (We could defer the "is 'this' pointer null" test to the common
+     * method invocation code, and use a flag to indicate that static
+     * calls don't count.  If we do this as part of copying the arguments
+     * out we could avoiding loading the first arg twice.)
+     *
+     * for: invoke-direct, invoke-direct/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
+    FETCH(r10, 2)                       @ r10<- GFED or CCCC
+    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
+    .if     (!1)
+    and     r10, r10, #15               @ r10<- D (or stays CCCC)
+    .endif
+    cmp     r0, #0                      @ already resolved?
+    EXPORT_PC()                         @ must export for invoke
+    GET_VREG(r2, r10)                   @ r2<- "this" ptr
+    beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
+.LOP_INVOKE_DIRECT_RANGE_finish:
+    cmp     r2, #0                      @ null "this" ref?
+    bne     common_invokeMethodRange   @ no, continue on
+    b       common_errNullObject        @ yes, throw exception
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
+/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
+/* File: armv5te/OP_INVOKE_STATIC.S */
+    /*
+     * Handle a static method call.
+     *
+     * for: invoke-static, invoke-static/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
+    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
+    cmp     r0, #0                      @ already resolved?
+    EXPORT_PC()                         @ must export for invoke
+    bne     common_invokeMethodRange @ yes, continue on
+0:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
+    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
+    mov     r2, #METHOD_STATIC          @ resolver method type
+    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
+    cmp     r0, #0                      @ got null?
+    bne     common_invokeMethodRange @ no, continue
+    b       common_exceptionThrown      @ yes, handle exception
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
+/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
+/* File: armv5te/OP_INVOKE_INTERFACE.S */
+    /*
+     * Handle an interface method call.
+     *
+     * for: invoke-interface, invoke-interface/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
+    FETCH(r1, 1)                        @ r1<- BBBB
+    .if     (!1)
+    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
+    .endif
+    EXPORT_PC()                         @ must export for invoke
+    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
+    cmp     r0, #0                      @ null obj?
+    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
+    beq     common_errNullObject        @ yes, fail
+    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
+    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
+    cmp     r0, #0                      @ failed?
+    beq     common_exceptionThrown      @ yes, handle exception
+    b       common_invokeMethodRange @ jump to common handler 
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_79: /* 0x79 */
+/* File: armv5te/OP_UNUSED_79.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_7A: /* 0x7a */
+/* File: armv5te/OP_UNUSED_7A.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_NEG_INT: /* 0x7b */
+/* File: armv5te/OP_NEG_INT.S */
+/* File: armv5te/unop.S */
+    /*
+     * Generic 32-bit unary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = op r0".
+     * This could be an ARM instruction or a function call.
+     *
+     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
+     *      int-to-byte, int-to-char, int-to-short
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    GET_VREG(r0, r3)                    @ r0<- vB
+    and     r9, r9, #15
+                               @ optional op; may set condition codes
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 9-10 instructions */
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_NOT_INT: /* 0x7c */
+/* File: armv5te/OP_NOT_INT.S */
+/* File: armv5te/unop.S */
+    /*
+     * Generic 32-bit unary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = op r0".
+     * This could be an ARM instruction or a function call.
+     *
+     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
+     *      int-to-byte, int-to-char, int-to-short
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    GET_VREG(r0, r3)                    @ r0<- vB
+    and     r9, r9, #15
+                               @ optional op; may set condition codes
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    mvn     r0, r0                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 9-10 instructions */
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_NEG_LONG: /* 0x7d */
+/* File: armv5te/OP_NEG_LONG.S */
+/* File: armv5te/unopWide.S */
+    /*
+     * Generic 64-bit unary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = op r0/r1".
+     * This could be an ARM instruction or a function call.
+     *
+     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
+     */
+    /* unop vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r3, rINST, lsr #12          @ r3<- B
+    and     r9, r9, #15
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    rsbs    r0, r0, #0                           @ optional op; may set condition codes
+    rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 12-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_NOT_LONG: /* 0x7e */
+/* File: armv5te/OP_NOT_LONG.S */
+/* File: armv5te/unopWide.S */
+    /*
+     * Generic 64-bit unary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = op r0/r1".
+     * This could be an ARM instruction or a function call.
+     *
+     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
+     */
+    /* unop vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r3, rINST, lsr #12          @ r3<- B
+    and     r9, r9, #15
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    mvn     r0, r0                           @ optional op; may set condition codes
+    mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 12-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_NEG_FLOAT: /* 0x7f */
+/* File: armv5te/OP_NEG_FLOAT.S */
+/* File: armv5te/unop.S */
+    /*
+     * Generic 32-bit unary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = op r0".
+     * This could be an ARM instruction or a function call.
+     *
+     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
+     *      int-to-byte, int-to-char, int-to-short
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    GET_VREG(r0, r3)                    @ r0<- vB
+    and     r9, r9, #15
+                               @ optional op; may set condition codes
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 9-10 instructions */
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_NEG_DOUBLE: /* 0x80 */
+/* File: armv5te/OP_NEG_DOUBLE.S */
+/* File: armv5te/unopWide.S */
+    /*
+     * Generic 64-bit unary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = op r0/r1".
+     * This could be an ARM instruction or a function call.
+     *
+     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
+     */
+    /* unop vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r3, rINST, lsr #12          @ r3<- B
+    and     r9, r9, #15
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+                               @ optional op; may set condition codes
+    add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 12-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INT_TO_LONG: /* 0x81 */
+/* File: armv5te/OP_INT_TO_LONG.S */
+/* File: armv5te/unopWider.S */
+    /*
+     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = op r0", where
+     * "result" is a 64-bit quantity in r0/r1.
+     *
+     * For: int-to-long, int-to-double, float-to-long, float-to-double
+     */
+    /* unop vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r3, rINST, lsr #12          @ r3<- B
+    and     r9, r9, #15
+    GET_VREG(r0, r3)                    @ r0<- vB
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+                               @ optional op; may set condition codes
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-11 instructions */
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INT_TO_FLOAT: /* 0x82 */
+/* File: arm-vfp/OP_INT_TO_FLOAT.S */
+/* File: arm-vfp/funop.S */
+    /*
+     * Generic 32-bit unary floating-point operation.  Provide an "instr"
+     * line that specifies an instruction that performs "s1 = op s0".
+     *
+     * for: int-to-float, float-to-int
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    flds    s0, [r3]                    @ s0<- vB
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    and     r9, r9, #15                 @ r9<- A
+    fsitos  s1, s0                              @ s1<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    fsts    s1, [r9]                    @ vA<- s1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INT_TO_DOUBLE: /* 0x83 */
+/* File: arm-vfp/OP_INT_TO_DOUBLE.S */
+/* File: arm-vfp/funopWider.S */
+    /*
+     * Generic 32bit-to-64bit floating point unary operation.  Provide an
+     * "instr" line that specifies an instruction that performs "d0 = op s0".
+     *
+     * For: int-to-double, float-to-double
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    flds    s0, [r3]                    @ s0<- vB
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    and     r9, r9, #15                 @ r9<- A
+    fsitod  d0, s0                              @ d0<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    fstd    d0, [r9]                    @ vA<- d0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_LONG_TO_INT: /* 0x84 */
+/* File: armv5te/OP_LONG_TO_INT.S */
+/* we ignore the high word, making this equivalent to a 32-bit reg move */
+/* File: armv5te/OP_MOVE.S */
+    /* for move, move-object, long-to-int */
+    /* op vA, vB */
+    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
+    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    GET_VREG(r2, r1)                    @ r2<- fp[B]
+    and     r0, r0, #15
+    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
+    SET_VREG(r2, r0)                    @ fp[A]<- r2
+    GOTO_OPCODE(ip)                     @ execute next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_LONG_TO_FLOAT: /* 0x85 */
+/* File: armv5te/OP_LONG_TO_FLOAT.S */
+/* File: armv5te/unopNarrower.S */
+    /*
+     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = op r0/r1", where
+     * "result" is a 32-bit quantity in r0.
+     *
+     * For: long-to-float, double-to-int, double-to-float
+     *
+     * (This would work for long-to-int, but that instruction is actually
+     * an exact match for OP_MOVE.)
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
+    and     r9, r9, #15
+    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+                               @ optional op; may set condition codes
+    bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-11 instructions */
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_LONG_TO_DOUBLE: /* 0x86 */
+/* File: armv5te/OP_LONG_TO_DOUBLE.S */
+/* File: armv5te/unopWide.S */
+    /*
+     * Generic 64-bit unary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = op r0/r1".
+     * This could be an ARM instruction or a function call.
+     *
+     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
+     */
+    /* unop vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r3, rINST, lsr #12          @ r3<- B
+    and     r9, r9, #15
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+                               @ optional op; may set condition codes
+    bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 12-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_FLOAT_TO_INT: /* 0x87 */
+/* File: arm-vfp/OP_FLOAT_TO_INT.S */
+/* File: arm-vfp/funop.S */
+    /*
+     * Generic 32-bit unary floating-point operation.  Provide an "instr"
+     * line that specifies an instruction that performs "s1 = op s0".
+     *
+     * for: int-to-float, float-to-int
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    flds    s0, [r3]                    @ s0<- vB
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    and     r9, r9, #15                 @ r9<- A
+    ftosizs s1, s0                              @ s1<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    fsts    s1, [r9]                    @ vA<- s1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_FLOAT_TO_LONG: /* 0x88 */
+/* File: armv5te/OP_FLOAT_TO_LONG.S */
+@include "armv5te/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
+/* File: armv5te/unopWider.S */
+    /*
+     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = op r0", where
+     * "result" is a 64-bit quantity in r0/r1.
+     *
+     * For: int-to-long, int-to-double, float-to-long, float-to-double
+     */
+    /* unop vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r3, rINST, lsr #12          @ r3<- B
+    and     r9, r9, #15
+    GET_VREG(r0, r3)                    @ r0<- vB
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+                               @ optional op; may set condition codes
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    bl      f2l_doconv                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-11 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
+/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
+/* File: arm-vfp/funopWider.S */
+    /*
+     * Generic 32bit-to-64bit floating point unary operation.  Provide an
+     * "instr" line that specifies an instruction that performs "d0 = op s0".
+     *
+     * For: int-to-double, float-to-double
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    flds    s0, [r3]                    @ s0<- vB
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    and     r9, r9, #15                 @ r9<- A
+    fcvtds  d0, s0                              @ d0<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    fstd    d0, [r9]                    @ vA<- d0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_DOUBLE_TO_INT: /* 0x8a */
+/* File: arm-vfp/OP_DOUBLE_TO_INT.S */
+/* File: arm-vfp/funopNarrower.S */
+    /*
+     * Generic 64bit-to-32bit unary floating point operation.  Provide an
+     * "instr" line that specifies an instruction that performs "s0 = op d0".
+     *
+     * For: double-to-int, double-to-float
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    fldd    d0, [r3]                    @ d0<- vB
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    and     r9, r9, #15                 @ r9<- A
+    ftosizd  s0, d0                              @ s0<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    fsts    s0, [r9]                    @ vA<- s0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_DOUBLE_TO_LONG: /* 0x8b */
+/* File: armv5te/OP_DOUBLE_TO_LONG.S */
+@include "armv5te/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
+/* File: armv5te/unopWide.S */
+    /*
+     * Generic 64-bit unary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = op r0/r1".
+     * This could be an ARM instruction or a function call.
+     *
+     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
+     */
+    /* unop vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r3, rINST, lsr #12          @ r3<- B
+    and     r9, r9, #15
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+                               @ optional op; may set condition codes
+    bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 12-13 instructions */
+
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
+/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
+/* File: arm-vfp/funopNarrower.S */
+    /*
+     * Generic 64bit-to-32bit unary floating point operation.  Provide an
+     * "instr" line that specifies an instruction that performs "s0 = op d0".
+     *
+     * For: double-to-int, double-to-float
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    fldd    d0, [r3]                    @ d0<- vB
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    and     r9, r9, #15                 @ r9<- A
+    fcvtsd  s0, d0                              @ s0<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    fsts    s0, [r9]                    @ vA<- s0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INT_TO_BYTE: /* 0x8d */
+/* File: armv5te/OP_INT_TO_BYTE.S */
+/* File: armv5te/unop.S */
+    /*
+     * Generic 32-bit unary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = op r0".
+     * This could be an ARM instruction or a function call.
+     *
+     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
+     *      int-to-byte, int-to-char, int-to-short
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    GET_VREG(r0, r3)                    @ r0<- vB
+    and     r9, r9, #15
+    mov     r0, r0, asl #24                           @ optional op; may set condition codes
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    mov     r0, r0, asr #24                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 9-10 instructions */
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INT_TO_CHAR: /* 0x8e */
+/* File: armv5te/OP_INT_TO_CHAR.S */
+/* File: armv5te/unop.S */
+    /*
+     * Generic 32-bit unary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = op r0".
+     * This could be an ARM instruction or a function call.
+     *
+     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
+     *      int-to-byte, int-to-char, int-to-short
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    GET_VREG(r0, r3)                    @ r0<- vB
+    and     r9, r9, #15
+    mov     r0, r0, asl #16                           @ optional op; may set condition codes
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    mov     r0, r0, lsr #16                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 9-10 instructions */
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INT_TO_SHORT: /* 0x8f */
+/* File: armv5te/OP_INT_TO_SHORT.S */
+/* File: armv5te/unop.S */
+    /*
+     * Generic 32-bit unary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = op r0".
+     * This could be an ARM instruction or a function call.
+     *
+     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
+     *      int-to-byte, int-to-char, int-to-short
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    GET_VREG(r0, r3)                    @ r0<- vB
+    and     r9, r9, #15
+    mov     r0, r0, asl #16                           @ optional op; may set condition codes
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    mov     r0, r0, asr #16                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 9-10 instructions */
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_ADD_INT: /* 0x90 */
+/* File: armv5te/OP_ADD_INT.S */
+/* File: armv5te/binop.S */
+    /*
+     * Generic 32-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.  Note that we
+     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+     * handles it correctly.
+     *
+     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
+     *      mul-float, div-float, rem-float
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    GET_VREG(r1, r3)                    @ r1<- vCC
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+                               @ optional op; may set condition codes
+    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 11-14 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SUB_INT: /* 0x91 */
+/* File: armv5te/OP_SUB_INT.S */
+/* File: armv5te/binop.S */
+    /*
+     * Generic 32-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.  Note that we
+     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+     * handles it correctly.
+     *
+     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
+     *      mul-float, div-float, rem-float
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    GET_VREG(r1, r3)                    @ r1<- vCC
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+                               @ optional op; may set condition codes
+    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 11-14 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MUL_INT: /* 0x92 */
+/* File: armv5te/OP_MUL_INT.S */
+/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
+/* File: armv5te/binop.S */
+    /*
+     * Generic 32-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.  Note that we
+     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+     * handles it correctly.
+     *
+     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
+     *      mul-float, div-float, rem-float
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    GET_VREG(r1, r3)                    @ r1<- vCC
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+                               @ optional op; may set condition codes
+    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 11-14 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_DIV_INT: /* 0x93 */
+/* File: armv5te/OP_DIV_INT.S */
+/* File: armv5te/binop.S */
+    /*
+     * Generic 32-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.  Note that we
+     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+     * handles it correctly.
+     *
+     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
+     *      mul-float, div-float, rem-float
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    GET_VREG(r1, r3)                    @ r1<- vCC
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    .if 1
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+                               @ optional op; may set condition codes
+    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 11-14 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_REM_INT: /* 0x94 */
+/* File: armv5te/OP_REM_INT.S */
+/* idivmod returns quotient in r0 and remainder in r1 */
+/* File: armv5te/binop.S */
+    /*
+     * Generic 32-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.  Note that we
+     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+     * handles it correctly.
+     *
+     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
+     *      mul-float, div-float, rem-float
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    GET_VREG(r1, r3)                    @ r1<- vCC
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    .if 1
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+                               @ optional op; may set condition codes
+    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r1, r9)               @ vAA<- r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 11-14 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_AND_INT: /* 0x95 */
+/* File: armv5te/OP_AND_INT.S */
+/* File: armv5te/binop.S */
+    /*
+     * Generic 32-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.  Note that we
+     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+     * handles it correctly.
+     *
+     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
+     *      mul-float, div-float, rem-float
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    GET_VREG(r1, r3)                    @ r1<- vCC
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+                               @ optional op; may set condition codes
+    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 11-14 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_OR_INT: /* 0x96 */
+/* File: armv5te/OP_OR_INT.S */
+/* File: armv5te/binop.S */
+    /*
+     * Generic 32-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.  Note that we
+     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+     * handles it correctly.
+     *
+     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
+     *      mul-float, div-float, rem-float
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    GET_VREG(r1, r3)                    @ r1<- vCC
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+                               @ optional op; may set condition codes
+    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 11-14 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_XOR_INT: /* 0x97 */
+/* File: armv5te/OP_XOR_INT.S */
+/* File: armv5te/binop.S */
+    /*
+     * Generic 32-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.  Note that we
+     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+     * handles it correctly.
+     *
+     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
+     *      mul-float, div-float, rem-float
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    GET_VREG(r1, r3)                    @ r1<- vCC
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+                               @ optional op; may set condition codes
+    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 11-14 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SHL_INT: /* 0x98 */
+/* File: armv5te/OP_SHL_INT.S */
+/* File: armv5te/binop.S */
+    /*
+     * Generic 32-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.  Note that we
+     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+     * handles it correctly.
+     *
+     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
+     *      mul-float, div-float, rem-float
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    GET_VREG(r1, r3)                    @ r1<- vCC
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r1, r1, #31                           @ optional op; may set condition codes
+    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 11-14 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SHR_INT: /* 0x99 */
+/* File: armv5te/OP_SHR_INT.S */
+/* File: armv5te/binop.S */
+    /*
+     * Generic 32-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.  Note that we
+     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+     * handles it correctly.
+     *
+     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
+     *      mul-float, div-float, rem-float
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    GET_VREG(r1, r3)                    @ r1<- vCC
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r1, r1, #31                           @ optional op; may set condition codes
+    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 11-14 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_USHR_INT: /* 0x9a */
+/* File: armv5te/OP_USHR_INT.S */
+/* File: armv5te/binop.S */
+    /*
+     * Generic 32-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.  Note that we
+     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+     * handles it correctly.
+     *
+     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
+     *      mul-float, div-float, rem-float
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    GET_VREG(r1, r3)                    @ r1<- vCC
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r1, r1, #31                           @ optional op; may set condition codes
+    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 11-14 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_ADD_LONG: /* 0x9b */
+/* File: armv5te/OP_ADD_LONG.S */
+/* File: armv5te/binopWide.S */
+    /*
+     * Generic 64-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
+     *      xor-long, add-double, sub-double, mul-double, div-double,
+     *      rem-double
+     *
+     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
+    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
+    .if 0
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    adds    r0, r0, r2                           @ optional op; may set condition codes
+    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 14-17 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SUB_LONG: /* 0x9c */
+/* File: armv5te/OP_SUB_LONG.S */
+/* File: armv5te/binopWide.S */
+    /*
+     * Generic 64-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
+     *      xor-long, add-double, sub-double, mul-double, div-double,
+     *      rem-double
+     *
+     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
+    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
+    .if 0
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    subs    r0, r0, r2                           @ optional op; may set condition codes
+    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 14-17 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MUL_LONG: /* 0x9d */
+/* File: armv5te/OP_MUL_LONG.S */
+    /*
+     * Signed 64-bit integer multiply.
+     *
+     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
+     *        WX
+     *      x YZ
+     *  --------
+     *     ZW ZX
+     *  YW YX
+     *
+     * The low word of the result holds ZX, the high word holds
+     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
+     * it doesn't fit in the low 64 bits.
+     *
+     * Unlike most ARM math operations, multiply instructions have
+     * restrictions on using the same register more than once (Rd and Rm
+     * cannot be the same).
+     */
+    /* mul-long vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
+    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
+    mul     ip, r2, r1                  @  ip<- ZxW
+    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
+    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
+    mov     r0, rINST, lsr #8           @ r0<- AA
+    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
+    add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    b       .LOP_MUL_LONG_finish
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_DIV_LONG: /* 0x9e */
+/* File: armv5te/OP_DIV_LONG.S */
+/* File: armv5te/binopWide.S */
+    /*
+     * Generic 64-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
+     *      xor-long, add-double, sub-double, mul-double, div-double,
+     *      rem-double
+     *
+     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
+    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
+    .if 1
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 14-17 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_REM_LONG: /* 0x9f */
+/* File: armv5te/OP_REM_LONG.S */
+/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
+/* File: armv5te/binopWide.S */
+    /*
+     * Generic 64-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
+     *      xor-long, add-double, sub-double, mul-double, div-double,
+     *      rem-double
+     *
+     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
+    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
+    .if 1
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 14-17 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_AND_LONG: /* 0xa0 */
+/* File: armv5te/OP_AND_LONG.S */
+/* File: armv5te/binopWide.S */
+    /*
+     * Generic 64-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
+     *      xor-long, add-double, sub-double, mul-double, div-double,
+     *      rem-double
+     *
+     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
+    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
+    .if 0
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    and     r0, r0, r2                           @ optional op; may set condition codes
+    and     r1, r1, r3                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 14-17 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_OR_LONG: /* 0xa1 */
+/* File: armv5te/OP_OR_LONG.S */
+/* File: armv5te/binopWide.S */
+    /*
+     * Generic 64-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
+     *      xor-long, add-double, sub-double, mul-double, div-double,
+     *      rem-double
+     *
+     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
+    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
+    .if 0
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    orr     r0, r0, r2                           @ optional op; may set condition codes
+    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 14-17 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_XOR_LONG: /* 0xa2 */
+/* File: armv5te/OP_XOR_LONG.S */
+/* File: armv5te/binopWide.S */
+    /*
+     * Generic 64-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
+     *      xor-long, add-double, sub-double, mul-double, div-double,
+     *      rem-double
+     *
+     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
+    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
+    .if 0
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    eor     r0, r0, r2                           @ optional op; may set condition codes
+    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 14-17 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SHL_LONG: /* 0xa3 */
+/* File: armv5te/OP_SHL_LONG.S */
+    /*
+     * Long integer shift.  This is different from the generic 32/64-bit
+     * binary operations because vAA/vBB are 64-bit but vCC (the shift
+     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
+     * 6 bits of the shift distance.
+     */
+    /* shl-long vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r3, r0, #255                @ r3<- BB
+    mov     r0, r0, lsr #8              @ r0<- CC
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
+    GET_VREG(r2, r0)                    @ r2<- vCC
+    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    and     r2, r2, #63                 @ r2<- r2 & 0x3f
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+
+    mov     r1, r1, asl r2              @  r1<- r1 << r2
+    rsb     r3, r2, #32                 @  r3<- 32 - r2
+    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
+    subs    ip, r2, #32                 @  ip<- r2 - 32
+    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    b       .LOP_SHL_LONG_finish
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SHR_LONG: /* 0xa4 */
+/* File: armv5te/OP_SHR_LONG.S */
+    /*
+     * Long integer shift.  This is different from the generic 32/64-bit
+     * binary operations because vAA/vBB are 64-bit but vCC (the shift
+     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
+     * 6 bits of the shift distance.
+     */
+    /* shr-long vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r3, r0, #255                @ r3<- BB
+    mov     r0, r0, lsr #8              @ r0<- CC
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
+    GET_VREG(r2, r0)                    @ r2<- vCC
+    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    and     r2, r2, #63                 @ r0<- r0 & 0x3f
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+
+    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
+    rsb     r3, r2, #32                 @  r3<- 32 - r2
+    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
+    subs    ip, r2, #32                 @  ip<- r2 - 32
+    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    b       .LOP_SHR_LONG_finish
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_USHR_LONG: /* 0xa5 */
+/* File: armv5te/OP_USHR_LONG.S */
+    /*
+     * Long integer shift.  This is different from the generic 32/64-bit
+     * binary operations because vAA/vBB are 64-bit but vCC (the shift
+     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
+     * 6 bits of the shift distance.
+     */
+    /* ushr-long vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r3, r0, #255                @ r3<- BB
+    mov     r0, r0, lsr #8              @ r0<- CC
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
+    GET_VREG(r2, r0)                    @ r2<- vCC
+    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    and     r2, r2, #63                 @ r0<- r0 & 0x3f
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+
+    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
+    rsb     r3, r2, #32                 @  r3<- 32 - r2
+    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
+    subs    ip, r2, #32                 @  ip<- r2 - 32
+    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    b       .LOP_USHR_LONG_finish
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_ADD_FLOAT: /* 0xa6 */
+/* File: arm-vfp/OP_ADD_FLOAT.S */
+/* File: arm-vfp/fbinop.S */
+    /*
+     * Generic 32-bit floating-point operation.  Provide an "instr" line that
+     * specifies an instruction that performs "s2 = s0 op s1".  Because we
+     * use the "softfp" ABI, this must be an instruction, not a function call.
+     *
+     * For: add-float, sub-float, mul-float, div-float
+     */
+    /* floatop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    flds    s1, [r3]                    @ s1<- vCC
+    flds    s0, [r2]                    @ s0<- vBB
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    fadds   s2, s0, s1                              @ s2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
+    fsts    s2, [r9]                    @ vAA<- s2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SUB_FLOAT: /* 0xa7 */
+/* File: arm-vfp/OP_SUB_FLOAT.S */
+/* File: arm-vfp/fbinop.S */
+    /*
+     * Generic 32-bit floating-point operation.  Provide an "instr" line that
+     * specifies an instruction that performs "s2 = s0 op s1".  Because we
+     * use the "softfp" ABI, this must be an instruction, not a function call.
+     *
+     * For: add-float, sub-float, mul-float, div-float
+     */
+    /* floatop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    flds    s1, [r3]                    @ s1<- vCC
+    flds    s0, [r2]                    @ s0<- vBB
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    fsubs   s2, s0, s1                              @ s2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
+    fsts    s2, [r9]                    @ vAA<- s2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MUL_FLOAT: /* 0xa8 */
+/* File: arm-vfp/OP_MUL_FLOAT.S */
+/* File: arm-vfp/fbinop.S */
+    /*
+     * Generic 32-bit floating-point operation.  Provide an "instr" line that
+     * specifies an instruction that performs "s2 = s0 op s1".  Because we
+     * use the "softfp" ABI, this must be an instruction, not a function call.
+     *
+     * For: add-float, sub-float, mul-float, div-float
+     */
+    /* floatop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    flds    s1, [r3]                    @ s1<- vCC
+    flds    s0, [r2]                    @ s0<- vBB
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    fmuls   s2, s0, s1                              @ s2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
+    fsts    s2, [r9]                    @ vAA<- s2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_DIV_FLOAT: /* 0xa9 */
+/* File: arm-vfp/OP_DIV_FLOAT.S */
+/* File: arm-vfp/fbinop.S */
+    /*
+     * Generic 32-bit floating-point operation.  Provide an "instr" line that
+     * specifies an instruction that performs "s2 = s0 op s1".  Because we
+     * use the "softfp" ABI, this must be an instruction, not a function call.
+     *
+     * For: add-float, sub-float, mul-float, div-float
+     */
+    /* floatop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    flds    s1, [r3]                    @ s1<- vCC
+    flds    s0, [r2]                    @ s0<- vBB
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    fdivs   s2, s0, s1                              @ s2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
+    fsts    s2, [r9]                    @ vAA<- s2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_REM_FLOAT: /* 0xaa */
+/* File: armv5te/OP_REM_FLOAT.S */
+/* EABI doesn't define a float remainder function, but libm does */
+/* File: armv5te/binop.S */
+    /*
+     * Generic 32-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.  Note that we
+     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+     * handles it correctly.
+     *
+     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
+     *      mul-float, div-float, rem-float
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    GET_VREG(r1, r3)                    @ r1<- vCC
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+                               @ optional op; may set condition codes
+    bl      fmodf                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 11-14 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_ADD_DOUBLE: /* 0xab */
+/* File: arm-vfp/OP_ADD_DOUBLE.S */
+/* File: arm-vfp/fbinopWide.S */
+    /*
+     * Generic 64-bit double-precision floating point binary operation.
+     * Provide an "instr" line that specifies an instruction that performs
+     * "d2 = d0 op d1".
+     *
+     * for: add-double, sub-double, mul-double, div-double
+     */
+    /* doubleop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    fldd    d1, [r3]                    @ d1<- vCC
+    fldd    d0, [r2]                    @ d0<- vBB
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    faddd   d2, d0, d1                              @ s2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
+    fstd    d2, [r9]                    @ vAA<- d2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SUB_DOUBLE: /* 0xac */
+/* File: arm-vfp/OP_SUB_DOUBLE.S */
+/* File: arm-vfp/fbinopWide.S */
+    /*
+     * Generic 64-bit double-precision floating point binary operation.
+     * Provide an "instr" line that specifies an instruction that performs
+     * "d2 = d0 op d1".
+     *
+     * for: add-double, sub-double, mul-double, div-double
+     */
+    /* doubleop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    fldd    d1, [r3]                    @ d1<- vCC
+    fldd    d0, [r2]                    @ d0<- vBB
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    fsubd   d2, d0, d1                              @ s2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
+    fstd    d2, [r9]                    @ vAA<- d2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MUL_DOUBLE: /* 0xad */
+/* File: arm-vfp/OP_MUL_DOUBLE.S */
+/* File: arm-vfp/fbinopWide.S */
+    /*
+     * Generic 64-bit double-precision floating point binary operation.
+     * Provide an "instr" line that specifies an instruction that performs
+     * "d2 = d0 op d1".
+     *
+     * for: add-double, sub-double, mul-double, div-double
+     */
+    /* doubleop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    fldd    d1, [r3]                    @ d1<- vCC
+    fldd    d0, [r2]                    @ d0<- vBB
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    fmuld   d2, d0, d1                              @ s2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
+    fstd    d2, [r9]                    @ vAA<- d2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_DIV_DOUBLE: /* 0xae */
+/* File: arm-vfp/OP_DIV_DOUBLE.S */
+/* File: arm-vfp/fbinopWide.S */
+    /*
+     * Generic 64-bit double-precision floating point binary operation.
+     * Provide an "instr" line that specifies an instruction that performs
+     * "d2 = d0 op d1".
+     *
+     * for: add-double, sub-double, mul-double, div-double
+     */
+    /* doubleop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    fldd    d1, [r3]                    @ d1<- vCC
+    fldd    d0, [r2]                    @ d0<- vBB
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    fdivd   d2, d0, d1                              @ s2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
+    fstd    d2, [r9]                    @ vAA<- d2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_REM_DOUBLE: /* 0xaf */
+/* File: armv5te/OP_REM_DOUBLE.S */
+/* EABI doesn't define a double remainder function, but libm does */
+/* File: armv5te/binopWide.S */
+    /*
+     * Generic 64-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
+     *      xor-long, add-double, sub-double, mul-double, div-double,
+     *      rem-double
+     *
+     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
+    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
+    .if 0
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    bl      fmod                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 14-17 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_ADD_INT_2ADDR: /* 0xb0 */
+/* File: armv5te/OP_ADD_INT_2ADDR.S */
+/* File: armv5te/binop2addr.S */
+    /*
+     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r3, rINST, lsr #12          @ r3<- B
+    and     r9, r9, #15
+    GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SUB_INT_2ADDR: /* 0xb1 */
+/* File: armv5te/OP_SUB_INT_2ADDR.S */
+/* File: armv5te/binop2addr.S */
+    /*
+     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r3, rINST, lsr #12          @ r3<- B
+    and     r9, r9, #15
+    GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MUL_INT_2ADDR: /* 0xb2 */
+/* File: armv5te/OP_MUL_INT_2ADDR.S */
+/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
+/* File: armv5te/binop2addr.S */
+    /*
+     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r3, rINST, lsr #12          @ r3<- B
+    and     r9, r9, #15
+    GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_DIV_INT_2ADDR: /* 0xb3 */
+/* File: armv5te/OP_DIV_INT_2ADDR.S */
+/* File: armv5te/binop2addr.S */
+    /*
+     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r3, rINST, lsr #12          @ r3<- B
+    and     r9, r9, #15
+    GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
+    .if 1
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_REM_INT_2ADDR: /* 0xb4 */
+/* File: armv5te/OP_REM_INT_2ADDR.S */
+/* idivmod returns quotient in r0 and remainder in r1 */
+/* File: armv5te/binop2addr.S */
+    /*
+     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r3, rINST, lsr #12          @ r3<- B
+    and     r9, r9, #15
+    GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
+    .if 1
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r1, r9)               @ vAA<- r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_AND_INT_2ADDR: /* 0xb5 */
+/* File: armv5te/OP_AND_INT_2ADDR.S */
+/* File: armv5te/binop2addr.S */
+    /*
+     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r3, rINST, lsr #12          @ r3<- B
+    and     r9, r9, #15
+    GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_OR_INT_2ADDR: /* 0xb6 */
+/* File: armv5te/OP_OR_INT_2ADDR.S */
+/* File: armv5te/binop2addr.S */
+    /*
+     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r3, rINST, lsr #12          @ r3<- B
+    and     r9, r9, #15
+    GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_XOR_INT_2ADDR: /* 0xb7 */
+/* File: armv5te/OP_XOR_INT_2ADDR.S */
+/* File: armv5te/binop2addr.S */
+    /*
+     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r3, rINST, lsr #12          @ r3<- B
+    and     r9, r9, #15
+    GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SHL_INT_2ADDR: /* 0xb8 */
+/* File: armv5te/OP_SHL_INT_2ADDR.S */
+/* File: armv5te/binop2addr.S */
+    /*
+     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r3, rINST, lsr #12          @ r3<- B
+    and     r9, r9, #15
+    GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+    and     r1, r1, #31                           @ optional op; may set condition codes
+    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SHR_INT_2ADDR: /* 0xb9 */
+/* File: armv5te/OP_SHR_INT_2ADDR.S */
+/* File: armv5te/binop2addr.S */
+    /*
+     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r3, rINST, lsr #12          @ r3<- B
+    and     r9, r9, #15
+    GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+    and     r1, r1, #31                           @ optional op; may set condition codes
+    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_USHR_INT_2ADDR: /* 0xba */
+/* File: armv5te/OP_USHR_INT_2ADDR.S */
+/* File: armv5te/binop2addr.S */
+    /*
+     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r3, rINST, lsr #12          @ r3<- B
+    and     r9, r9, #15
+    GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+    and     r1, r1, #31                           @ optional op; may set condition codes
+    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_ADD_LONG_2ADDR: /* 0xbb */
+/* File: armv5te/OP_ADD_LONG_2ADDR.S */
+/* File: armv5te/binopWide2addr.S */
+    /*
+     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
+     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
+     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
+     *      rem-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r1, rINST, lsr #12          @ r1<- B
+    and     r9, r9, #15
+    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    .if 0
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+    adds    r0, r0, r2                           @ optional op; may set condition codes
+    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 12-15 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SUB_LONG_2ADDR: /* 0xbc */
+/* File: armv5te/OP_SUB_LONG_2ADDR.S */
+/* File: armv5te/binopWide2addr.S */
+    /*
+     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
+     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
+     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
+     *      rem-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r1, rINST, lsr #12          @ r1<- B
+    and     r9, r9, #15
+    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    .if 0
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+    subs    r0, r0, r2                           @ optional op; may set condition codes
+    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 12-15 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MUL_LONG_2ADDR: /* 0xbd */
+/* File: armv5te/OP_MUL_LONG_2ADDR.S */
+    /*
+     * Signed 64-bit integer multiply, "/2addr" version.
+     *
+     * See OP_MUL_LONG for an explanation.
+     *
+     * We get a little tight on registers, so to avoid looking up &fp[A]
+     * again we stuff it into rINST.
+     */
+    /* mul-long/2addr vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r1, rINST, lsr #12          @ r1<- B
+    and     r9, r9, #15
+    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
+    add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
+    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
+    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
+    mul     ip, r2, r1                  @  ip<- ZxW
+    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
+    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
+    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_DIV_LONG_2ADDR: /* 0xbe */
+/* File: armv5te/OP_DIV_LONG_2ADDR.S */
+/* File: armv5te/binopWide2addr.S */
+    /*
+     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
+     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
+     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
+     *      rem-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r1, rINST, lsr #12          @ r1<- B
+    and     r9, r9, #15
+    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    .if 1
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 12-15 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_REM_LONG_2ADDR: /* 0xbf */
+/* File: armv5te/OP_REM_LONG_2ADDR.S */
+/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
+/* File: armv5te/binopWide2addr.S */
+    /*
+     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
+     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
+     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
+     *      rem-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r1, rINST, lsr #12          @ r1<- B
+    and     r9, r9, #15
+    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    .if 1
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 12-15 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_AND_LONG_2ADDR: /* 0xc0 */
+/* File: armv5te/OP_AND_LONG_2ADDR.S */
+/* File: armv5te/binopWide2addr.S */
+    /*
+     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
+     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
+     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
+     *      rem-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r1, rINST, lsr #12          @ r1<- B
+    and     r9, r9, #15
+    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    .if 0
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+    and     r0, r0, r2                           @ optional op; may set condition codes
+    and     r1, r1, r3                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 12-15 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_OR_LONG_2ADDR: /* 0xc1 */
+/* File: armv5te/OP_OR_LONG_2ADDR.S */
+/* File: armv5te/binopWide2addr.S */
+    /*
+     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
+     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
+     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
+     *      rem-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r1, rINST, lsr #12          @ r1<- B
+    and     r9, r9, #15
+    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    .if 0
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+    orr     r0, r0, r2                           @ optional op; may set condition codes
+    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 12-15 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
+/* File: armv5te/OP_XOR_LONG_2ADDR.S */
+/* File: armv5te/binopWide2addr.S */
+    /*
+     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
+     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
+     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
+     *      rem-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r1, rINST, lsr #12          @ r1<- B
+    and     r9, r9, #15
+    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    .if 0
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+    eor     r0, r0, r2                           @ optional op; may set condition codes
+    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 12-15 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
+/* File: armv5te/OP_SHL_LONG_2ADDR.S */
+    /*
+     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
+     * 32-bit shift distance.
+     */
+    /* shl-long/2addr vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r3, rINST, lsr #12          @ r3<- B
+    and     r9, r9, #15
+    GET_VREG(r2, r3)                    @ r2<- vB
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    and     r2, r2, #63                 @ r2<- r2 & 0x3f
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+
+    mov     r1, r1, asl r2              @  r1<- r1 << r2
+    rsb     r3, r2, #32                 @  r3<- 32 - r2
+    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
+    subs    ip, r2, #32                 @  ip<- r2 - 32
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
+    mov     r0, r0, asl r2              @  r0<- r0 << r2
+    b       .LOP_SHL_LONG_2ADDR_finish
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
+/* File: armv5te/OP_SHR_LONG_2ADDR.S */
+    /*
+     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
+     * 32-bit shift distance.
+     */
+    /* shr-long/2addr vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r3, rINST, lsr #12          @ r3<- B
+    and     r9, r9, #15
+    GET_VREG(r2, r3)                    @ r2<- vB
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    and     r2, r2, #63                 @ r2<- r2 & 0x3f
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+
+    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
+    rsb     r3, r2, #32                 @  r3<- 32 - r2
+    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
+    subs    ip, r2, #32                 @  ip<- r2 - 32
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
+    mov     r1, r1, asr r2              @  r1<- r1 >> r2
+    b       .LOP_SHR_LONG_2ADDR_finish
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
+/* File: armv5te/OP_USHR_LONG_2ADDR.S */
+    /*
+     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
+     * 32-bit shift distance.
+     */
+    /* ushr-long/2addr vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r3, rINST, lsr #12          @ r3<- B
+    and     r9, r9, #15
+    GET_VREG(r2, r3)                    @ r2<- vB
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    and     r2, r2, #63                 @ r2<- r2 & 0x3f
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+
+    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
+    rsb     r3, r2, #32                 @  r3<- 32 - r2
+    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
+    subs    ip, r2, #32                 @  ip<- r2 - 32
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
+    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
+    b       .LOP_USHR_LONG_2ADDR_finish
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
+/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
+/* File: arm-vfp/fbinop2addr.S */
+    /*
+     * Generic 32-bit floating point "/2addr" binary operation.  Provide
+     * an "instr" line that specifies an instruction that performs
+     * "s2 = s0 op s1".
+     *
+     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    and     r9, r9, #15                 @ r9<- A
+    flds    s1, [r3]                    @ s1<- vB
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    flds    s0, [r9]                    @ s0<- vA
+
+    fadds   s2, s0, s1                              @ s2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fsts    s2, [r9]                    @ vAA<- s2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
+/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
+/* File: arm-vfp/fbinop2addr.S */
+    /*
+     * Generic 32-bit floating point "/2addr" binary operation.  Provide
+     * an "instr" line that specifies an instruction that performs
+     * "s2 = s0 op s1".
+     *
+     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    and     r9, r9, #15                 @ r9<- A
+    flds    s1, [r3]                    @ s1<- vB
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    flds    s0, [r9]                    @ s0<- vA
+
+    fsubs   s2, s0, s1                              @ s2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fsts    s2, [r9]                    @ vAA<- s2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
+/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
+/* File: arm-vfp/fbinop2addr.S */
+    /*
+     * Generic 32-bit floating point "/2addr" binary operation.  Provide
+     * an "instr" line that specifies an instruction that performs
+     * "s2 = s0 op s1".
+     *
+     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    and     r9, r9, #15                 @ r9<- A
+    flds    s1, [r3]                    @ s1<- vB
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    flds    s0, [r9]                    @ s0<- vA
+
+    fmuls   s2, s0, s1                              @ s2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fsts    s2, [r9]                    @ vAA<- s2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
+/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
+/* File: arm-vfp/fbinop2addr.S */
+    /*
+     * Generic 32-bit floating point "/2addr" binary operation.  Provide
+     * an "instr" line that specifies an instruction that performs
+     * "s2 = s0 op s1".
+     *
+     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    and     r9, r9, #15                 @ r9<- A
+    flds    s1, [r3]                    @ s1<- vB
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    flds    s0, [r9]                    @ s0<- vA
+
+    fdivs   s2, s0, s1                              @ s2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fsts    s2, [r9]                    @ vAA<- s2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_REM_FLOAT_2ADDR: /* 0xca */
+/* File: armv5te/OP_REM_FLOAT_2ADDR.S */
+/* EABI doesn't define a float remainder function, but libm does */
+/* File: armv5te/binop2addr.S */
+    /*
+     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r3, rINST, lsr #12          @ r3<- B
+    and     r9, r9, #15
+    GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    bl      fmodf                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
+/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
+/* File: arm-vfp/fbinopWide2addr.S */
+    /*
+     * Generic 64-bit floating point "/2addr" binary operation.  Provide
+     * an "instr" line that specifies an instruction that performs
+     * "d2 = d0 op d1".
+     *
+     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
+     *      div-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    and     r9, r9, #15                 @ r9<- A
+    fldd    d1, [r3]                    @ d1<- vB
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    fldd    d0, [r9]                    @ d0<- vA
+
+    faddd   d2, d0, d1                              @ d2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fstd    d2, [r9]                    @ vAA<- d2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
+/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
+/* File: arm-vfp/fbinopWide2addr.S */
+    /*
+     * Generic 64-bit floating point "/2addr" binary operation.  Provide
+     * an "instr" line that specifies an instruction that performs
+     * "d2 = d0 op d1".
+     *
+     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
+     *      div-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    and     r9, r9, #15                 @ r9<- A
+    fldd    d1, [r3]                    @ d1<- vB
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    fldd    d0, [r9]                    @ d0<- vA
+
+    fsubd   d2, d0, d1                              @ d2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fstd    d2, [r9]                    @ vAA<- d2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
+/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
+/* File: arm-vfp/fbinopWide2addr.S */
+    /*
+     * Generic 64-bit floating point "/2addr" binary operation.  Provide
+     * an "instr" line that specifies an instruction that performs
+     * "d2 = d0 op d1".
+     *
+     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
+     *      div-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    and     r9, r9, #15                 @ r9<- A
+    fldd    d1, [r3]                    @ d1<- vB
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    fldd    d0, [r9]                    @ d0<- vA
+
+    fmuld   d2, d0, d1                              @ d2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fstd    d2, [r9]                    @ vAA<- d2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
+/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
+/* File: arm-vfp/fbinopWide2addr.S */
+    /*
+     * Generic 64-bit floating point "/2addr" binary operation.  Provide
+     * an "instr" line that specifies an instruction that performs
+     * "d2 = d0 op d1".
+     *
+     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
+     *      div-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    and     r9, r9, #15                 @ r9<- A
+    fldd    d1, [r3]                    @ d1<- vB
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    fldd    d0, [r9]                    @ d0<- vA
+
+    fdivd   d2, d0, d1                              @ d2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fstd    d2, [r9]                    @ vAA<- d2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
+/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */
+/* EABI doesn't define a double remainder function, but libm does */
+/* File: armv5te/binopWide2addr.S */
+    /*
+     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
+     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
+     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
+     *      rem-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    mov     r1, rINST, lsr #12          @ r1<- B
+    and     r9, r9, #15
+    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    .if 0
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    bl      fmod                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 12-15 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_ADD_INT_LIT16: /* 0xd0 */
+/* File: armv5te/OP_ADD_INT_LIT16.S */
+/* File: armv5te/binopLit16.S */
+    /*
+     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+     */
+    /* binop/lit16 vA, vB, #+CCCC */
+    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
+    mov     r2, rINST, lsr #12          @ r2<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    GET_VREG(r0, r2)                    @ r0<- vB
+    and     r9, r9, #15
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_RSUB_INT: /* 0xd1 */
+/* File: armv5te/OP_RSUB_INT.S */
+/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
+/* File: armv5te/binopLit16.S */
+    /*
+     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+     */
+    /* binop/lit16 vA, vB, #+CCCC */
+    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
+    mov     r2, rINST, lsr #12          @ r2<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    GET_VREG(r0, r2)                    @ r0<- vB
+    and     r9, r9, #15
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MUL_INT_LIT16: /* 0xd2 */
+/* File: armv5te/OP_MUL_INT_LIT16.S */
+/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
+/* File: armv5te/binopLit16.S */
+    /*
+     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+     */
+    /* binop/lit16 vA, vB, #+CCCC */
+    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
+    mov     r2, rINST, lsr #12          @ r2<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    GET_VREG(r0, r2)                    @ r0<- vB
+    and     r9, r9, #15
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_DIV_INT_LIT16: /* 0xd3 */
+/* File: armv5te/OP_DIV_INT_LIT16.S */
+/* File: armv5te/binopLit16.S */
+    /*
+     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+     */
+    /* binop/lit16 vA, vB, #+CCCC */
+    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
+    mov     r2, rINST, lsr #12          @ r2<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    GET_VREG(r0, r2)                    @ r0<- vB
+    and     r9, r9, #15
+    .if 1
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_REM_INT_LIT16: /* 0xd4 */
+/* File: armv5te/OP_REM_INT_LIT16.S */
+/* idivmod returns quotient in r0 and remainder in r1 */
+/* File: armv5te/binopLit16.S */
+    /*
+     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+     */
+    /* binop/lit16 vA, vB, #+CCCC */
+    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
+    mov     r2, rINST, lsr #12          @ r2<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    GET_VREG(r0, r2)                    @ r0<- vB
+    and     r9, r9, #15
+    .if 1
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r1, r9)               @ vAA<- r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_AND_INT_LIT16: /* 0xd5 */
+/* File: armv5te/OP_AND_INT_LIT16.S */
+/* File: armv5te/binopLit16.S */
+    /*
+     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+     */
+    /* binop/lit16 vA, vB, #+CCCC */
+    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
+    mov     r2, rINST, lsr #12          @ r2<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    GET_VREG(r0, r2)                    @ r0<- vB
+    and     r9, r9, #15
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_OR_INT_LIT16: /* 0xd6 */
+/* File: armv5te/OP_OR_INT_LIT16.S */
+/* File: armv5te/binopLit16.S */
+    /*
+     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+     */
+    /* binop/lit16 vA, vB, #+CCCC */
+    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
+    mov     r2, rINST, lsr #12          @ r2<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    GET_VREG(r0, r2)                    @ r0<- vB
+    and     r9, r9, #15
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_XOR_INT_LIT16: /* 0xd7 */
+/* File: armv5te/OP_XOR_INT_LIT16.S */
+/* File: armv5te/binopLit16.S */
+    /*
+     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+     */
+    /* binop/lit16 vA, vB, #+CCCC */
+    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
+    mov     r2, rINST, lsr #12          @ r2<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    GET_VREG(r0, r2)                    @ r0<- vB
+    and     r9, r9, #15
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_ADD_INT_LIT8: /* 0xd8 */
+/* File: armv5te/OP_ADD_INT_LIT8.S */
+/* File: armv5te/binopLit8.S */
+    /*
+     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
+     */
+    /* binop/lit8 vAA, vBB, #+CC */
+    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r3, #255                @ r2<- BB
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
+    .if 0
+    @cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-12 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_RSUB_INT_LIT8: /* 0xd9 */
+/* File: armv5te/OP_RSUB_INT_LIT8.S */
+/* File: armv5te/binopLit8.S */
+    /*
+     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
+     */
+    /* binop/lit8 vAA, vBB, #+CC */
+    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r3, #255                @ r2<- BB
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
+    .if 0
+    @cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-12 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MUL_INT_LIT8: /* 0xda */
+/* File: armv5te/OP_MUL_INT_LIT8.S */
+/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
+/* File: armv5te/binopLit8.S */
+    /*
+     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
+     */
+    /* binop/lit8 vAA, vBB, #+CC */
+    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r3, #255                @ r2<- BB
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
+    .if 0
+    @cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-12 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_DIV_INT_LIT8: /* 0xdb */
+/* File: armv5te/OP_DIV_INT_LIT8.S */
+/* File: armv5te/binopLit8.S */
+    /*
+     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
+     */
+    /* binop/lit8 vAA, vBB, #+CC */
+    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r3, #255                @ r2<- BB
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
+    .if 1
+    @cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-12 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_REM_INT_LIT8: /* 0xdc */
+/* File: armv5te/OP_REM_INT_LIT8.S */
+/* idivmod returns quotient in r0 and remainder in r1 */
+/* File: armv5te/binopLit8.S */
+    /*
+     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
+     */
+    /* binop/lit8 vAA, vBB, #+CC */
+    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r3, #255                @ r2<- BB
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
+    .if 1
+    @cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r1, r9)               @ vAA<- r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-12 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_AND_INT_LIT8: /* 0xdd */
+/* File: armv5te/OP_AND_INT_LIT8.S */
+/* File: armv5te/binopLit8.S */
+    /*
+     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
+     */
+    /* binop/lit8 vAA, vBB, #+CC */
+    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r3, #255                @ r2<- BB
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
+    .if 0
+    @cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-12 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_OR_INT_LIT8: /* 0xde */
+/* File: armv5te/OP_OR_INT_LIT8.S */
+/* File: armv5te/binopLit8.S */
+    /*
+     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
+     */
+    /* binop/lit8 vAA, vBB, #+CC */
+    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r3, #255                @ r2<- BB
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
+    .if 0
+    @cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-12 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_XOR_INT_LIT8: /* 0xdf */
+/* File: armv5te/OP_XOR_INT_LIT8.S */
+/* File: armv5te/binopLit8.S */
+    /*
+     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
+     */
+    /* binop/lit8 vAA, vBB, #+CC */
+    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r3, #255                @ r2<- BB
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
+    .if 0
+    @cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-12 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SHL_INT_LIT8: /* 0xe0 */
+/* File: armv5te/OP_SHL_INT_LIT8.S */
+/* File: armv5te/binopLit8.S */
+    /*
+     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
+     */
+    /* binop/lit8 vAA, vBB, #+CC */
+    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r3, #255                @ r2<- BB
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
+    .if 0
+    @cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    and     r1, r1, #31                           @ optional op; may set condition codes
+    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-12 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SHR_INT_LIT8: /* 0xe1 */
+/* File: armv5te/OP_SHR_INT_LIT8.S */
+/* File: armv5te/binopLit8.S */
+    /*
+     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
+     */
+    /* binop/lit8 vAA, vBB, #+CC */
+    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r3, #255                @ r2<- BB
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
+    .if 0
+    @cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    and     r1, r1, #31                           @ optional op; may set condition codes
+    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-12 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_USHR_INT_LIT8: /* 0xe2 */
+/* File: armv5te/OP_USHR_INT_LIT8.S */
+/* File: armv5te/binopLit8.S */
+    /*
+     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
+     */
+    /* binop/lit8 vAA, vBB, #+CC */
+    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r3, #255                @ r2<- BB
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
+    .if 0
+    @cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    and     r1, r1, #31                           @ optional op; may set condition codes
+    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-12 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_E3: /* 0xe3 */
+/* File: armv5te/OP_UNUSED_E3.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_E4: /* 0xe4 */
+/* File: armv5te/OP_UNUSED_E4.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_E5: /* 0xe5 */
+/* File: armv5te/OP_UNUSED_E5.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_E6: /* 0xe6 */
+/* File: armv5te/OP_UNUSED_E6.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_E7: /* 0xe7 */
+/* File: armv5te/OP_UNUSED_E7.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_E8: /* 0xe8 */
+/* File: armv5te/OP_UNUSED_E8.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_E9: /* 0xe9 */
+/* File: armv5te/OP_UNUSED_E9.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_EA: /* 0xea */
+/* File: armv5te/OP_UNUSED_EA.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_EB: /* 0xeb */
+/* File: armv5te/OP_UNUSED_EB.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_EC: /* 0xec */
+/* File: armv5te/OP_UNUSED_EC.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
+/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
+    /*
+     * Handle a throw-verification-error instruction.  This throws an
+     * exception for an error discovered during verification.  The
+     * exception is indicated by AA, with some detail provided by BBBB.
+     */
+    /* op AA, ref@BBBB */
+    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
+    FETCH(r2, 1)                        @ r2<- BBBB
+    EXPORT_PC()                         @ export the PC
+    mov     r1, rINST, lsr #8           @ r1<- AA
+    bl      dvmThrowVerificationError   @ always throws
+    b       common_exceptionThrown      @ handle exception
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_EXECUTE_INLINE: /* 0xee */
+/* File: armv5te/OP_EXECUTE_INLINE.S */
+    /*
+     * Execute a "native inline" instruction.
+     *
+     * We need to call:
+     *  dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref)
+     *
+     * The first four args are in r0-r3, but the last two must be pushed
+     * onto the stack.
+     */
+    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
+    FETCH(r10, 1)                       @ r10<- BBBB
+    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
+    EXPORT_PC()                         @ can throw
+    sub     sp, sp, #8                  @ make room for arg(s)
+    mov     r0, rINST, lsr #12          @ r0<- B
+    str     r1, [sp]                    @ push &glue->retval
+    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
+    add     sp, sp, #8                  @ pop stack
+    cmp     r0, #0                      @ test boolean result of inline
+    beq     common_exceptionThrown      @ returned false, handle exception
+    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_EF: /* 0xef */
+/* File: armv5te/OP_UNUSED_EF.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
+/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
+    /*
+     * invoke-direct-empty is a no-op in a "standard" interpreter.
+     */
+    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
+    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
+    GOTO_OPCODE(ip)                     @ execute it
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_F1: /* 0xf1 */
+/* File: armv5te/OP_UNUSED_F1.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IGET_QUICK: /* 0xf2 */
+/* File: armv5te/OP_IGET_QUICK.S */
+    /* For: iget-quick, iget-object-quick */
+    /* op vA, vB, offset@CCCC */
+    mov     r2, rINST, lsr #12          @ r2<- B
+    GET_VREG(r3, r2)                    @ r3<- object we're operating on
+    FETCH(r1, 1)                        @ r1<- field byte offset
+    cmp     r3, #0                      @ check object for null
+    mov     r2, rINST, lsr #8           @ r2<- A(+)
+    beq     common_errNullObject        @ object was null
+    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r2, r2, #15
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r2)                    @ fp[A]<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
+/* File: armv5te/OP_IGET_WIDE_QUICK.S */
+    /* iget-wide-quick vA, vB, offset@CCCC */
+    mov     r2, rINST, lsr #12          @ r2<- B
+    GET_VREG(r3, r2)                    @ r3<- object we're operating on
+    FETCH(r1, 1)                        @ r1<- field byte offset
+    cmp     r3, #0                      @ check object for null
+    mov     r2, rINST, lsr #8           @ r2<- A(+)
+    beq     common_errNullObject        @ object was null
+    ldrd    r0, [r3, r1]                @ r0<- obj.field (64 bits, aligned)
+    and     r2, r2, #15
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
+/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
+/* File: armv5te/OP_IGET_QUICK.S */
+    /* For: iget-quick, iget-object-quick */
+    /* op vA, vB, offset@CCCC */
+    mov     r2, rINST, lsr #12          @ r2<- B
+    GET_VREG(r3, r2)                    @ r3<- object we're operating on
+    FETCH(r1, 1)                        @ r1<- field byte offset
+    cmp     r3, #0                      @ check object for null
+    mov     r2, rINST, lsr #8           @ r2<- A(+)
+    beq     common_errNullObject        @ object was null
+    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r2, r2, #15
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r2)                    @ fp[A]<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IPUT_QUICK: /* 0xf5 */
+/* File: armv5te/OP_IPUT_QUICK.S */
+    /* For: iput-quick, iput-object-quick */
+    /* op vA, vB, offset@CCCC */
+    mov     r2, rINST, lsr #12          @ r2<- B
+    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
+    FETCH(r1, 1)                        @ r1<- field byte offset
+    cmp     r3, #0                      @ check object for null
+    mov     r2, rINST, lsr #8           @ r2<- A(+)
+    beq     common_errNullObject        @ object was null
+    and     r2, r2, #15
+    GET_VREG(r0, r2)                    @ r0<- fp[A]
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
+/* File: armv5te/OP_IPUT_WIDE_QUICK.S */
+    /* iput-wide-quick vA, vB, offset@CCCC */
+    mov     r0, rINST, lsr #8           @ r0<- A(+)
+    mov     r1, rINST, lsr #12          @ r1<- B
+    and     r0, r0, #15
+    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
+    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
+    cmp     r2, #0                      @ check object for null
+    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
+    beq     common_errNullObject        @ object was null
+    FETCH(r3, 1)                        @ r3<- field byte offset
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
+/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
+/* File: armv5te/OP_IPUT_QUICK.S */
+    /* For: iput-quick, iput-object-quick */
+    /* op vA, vB, offset@CCCC */
+    mov     r2, rINST, lsr #12          @ r2<- B
+    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
+    FETCH(r1, 1)                        @ r1<- field byte offset
+    cmp     r3, #0                      @ check object for null
+    mov     r2, rINST, lsr #8           @ r2<- A(+)
+    beq     common_errNullObject        @ object was null
+    and     r2, r2, #15
+    GET_VREG(r0, r2)                    @ r0<- fp[A]
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
+/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
+    /*
+     * Handle an optimized virtual method call.
+     *
+     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
+    FETCH(r1, 1)                        @ r1<- BBBB
+    .if     (!0)
+    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
+    .endif
+    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
+    cmp     r2, #0                      @ is "this" null?
+    beq     common_errNullObject        @ null "this", throw exception
+    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
+    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
+    EXPORT_PC()                         @ invoke must export
+    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
+    bl      common_invokeMethodNoRange @ continue on
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
+/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
+/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
+    /*
+     * Handle an optimized virtual method call.
+     *
+     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
+    FETCH(r1, 1)                        @ r1<- BBBB
+    .if     (!1)
+    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
+    .endif
+    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
+    cmp     r2, #0                      @ is "this" null?
+    beq     common_errNullObject        @ null "this", throw exception
+    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
+    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
+    EXPORT_PC()                         @ invoke must export
+    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
+    bl      common_invokeMethodRange @ continue on
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
+/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
+    /*
+     * Handle an optimized "super" method call.
+     *
+     * for: [opt] invoke-super-quick, invoke-super-quick/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    FETCH(r10, 2)                       @ r10<- GFED or CCCC
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    .if     (!0)
+    and     r10, r10, #15               @ r10<- D (or stays CCCC)
+    .endif
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
+    EXPORT_PC()                         @ must export for invoke
+    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
+    GET_VREG(r3, r10)                   @ r3<- "this"
+    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
+    cmp     r3, #0                      @ null "this" ref?
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
+    beq     common_errNullObject        @ "this" is null, throw exception
+    bl      common_invokeMethodNoRange @ continue on
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
+/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
+/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
+    /*
+     * Handle an optimized "super" method call.
+     *
+     * for: [opt] invoke-super-quick, invoke-super-quick/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    FETCH(r10, 2)                       @ r10<- GFED or CCCC
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    .if     (!1)
+    and     r10, r10, #15               @ r10<- D (or stays CCCC)
+    .endif
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
+    EXPORT_PC()                         @ must export for invoke
+    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
+    GET_VREG(r3, r10)                   @ r3<- "this"
+    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
+    cmp     r3, #0                      @ null "this" ref?
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
+    beq     common_errNullObject        @ "this" is null, throw exception
+    bl      common_invokeMethodRange @ continue on
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_FC: /* 0xfc */
+/* File: armv5te/OP_UNUSED_FC.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_FD: /* 0xfd */
+/* File: armv5te/OP_UNUSED_FD.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_FE: /* 0xfe */
+/* File: armv5te/OP_UNUSED_FE.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_FF: /* 0xff */
+/* File: armv5te/OP_UNUSED_FF.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+
+    .balign 64
+    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
+    .global dvmAsmInstructionEnd
+dvmAsmInstructionEnd:
+
+/*
+ * ===========================================================================
+ *  Sister implementations
+ * ===========================================================================
+ */
+    .global dvmAsmSisterStart
+    .type   dvmAsmSisterStart, %function
+    .text
+    .balign 4
+dvmAsmSisterStart:
+
+/* continuation for OP_CONST_STRING */
+
+    /*
+     * Continuation if the String has not yet been resolved.
+     *  r1: BBBB (String ref)
+     *  r9: target register
+     */
+.LOP_CONST_STRING_resolve:
+    EXPORT_PC()
+    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
+    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveString            @ r0<- String reference
+    cmp     r0, #0                      @ failed?
+    beq     common_exceptionThrown      @ yup, handle the exception
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_CONST_STRING_JUMBO */
+
+    /*
+     * Continuation if the String has not yet been resolved.
+     *  r1: BBBBBBBB (String ref)
+     *  r9: target register
+     */
+.LOP_CONST_STRING_JUMBO_resolve:
+    EXPORT_PC()
+    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
+    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveString            @ r0<- String reference
+    cmp     r0, #0                      @ failed?
+    beq     common_exceptionThrown      @ yup, handle the exception
+    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_CONST_CLASS */
+
+    /*
+     * Continuation if the Class has not yet been resolved.
+     *  r1: BBBB (Class ref)
+     *  r9: target register
+     */
+.LOP_CONST_CLASS_resolve:
+    EXPORT_PC()
+    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
+    mov     r2, #1                      @ r2<- true
+    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveClass             @ r0<- Class reference
+    cmp     r0, #0                      @ failed?
+    beq     common_exceptionThrown      @ yup, handle the exception
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_CHECK_CAST */
+
+    /*
+     * Trivial test failed, need to perform full check.  This is common.
+     *  r0 holds obj->clazz
+     *  r1 holds class resolved from BBBB
+     *  r9 holds object
+     */
+.LOP_CHECK_CAST_fullcheck:
+    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
+    cmp     r0, #0                      @ failed?
+    bne     .LOP_CHECK_CAST_okay            @ no, success
+
+    @ A cast has failed.  We need to throw a ClassCastException with the
+    @ class of the object that failed to be cast.
+    EXPORT_PC()                         @ about to throw
+    ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
+    ldr     r0, .LstrClassCastExceptionPtr
+    ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
+    bl      dvmThrowExceptionWithClassMessage
+    b       common_exceptionThrown
+
+    /*
+     * Resolution required.  This is the least-likely path.
+     *
+     *  r2 holds BBBB
+     *  r9 holds object
+     */
+.LOP_CHECK_CAST_resolve:
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
+    mov     r1, r2                      @ r1<- BBBB
+    mov     r2, #0                      @ r2<- false
+    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
+    cmp     r0, #0                      @ got null?
+    beq     common_exceptionThrown      @ yes, handle exception
+    mov     r1, r0                      @ r1<- class resolved from BBB
+    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
+    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
+
+.LstrClassCastExceptionPtr:
+    .word   .LstrClassCastException
+
+
+/* continuation for OP_INSTANCE_OF */
+
+    /*
+     * Trivial test failed, need to perform full check.  This is common.
+     *  r0 holds obj->clazz
+     *  r1 holds class resolved from BBBB
+     *  r9 holds A
+     */
+.LOP_INSTANCE_OF_fullcheck:
+    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
+    @ fall through to OP_INSTANCE_OF_store
+
+    /*
+     * r0 holds boolean result
+     * r9 holds A
+     */
+.LOP_INSTANCE_OF_store:
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    SET_VREG(r0, r9)                    @ vA<- r0
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+    /*
+     * Trivial test succeeded, save and bail.
+     *  r9 holds A
+     */
+.LOP_INSTANCE_OF_trivial:
+    mov     r0, #1                      @ indicate success
+    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    SET_VREG(r0, r9)                    @ vA<- r0
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+    /*
+     * Resolution required.  This is the least-likely path.
+     *
+     *  r3 holds BBBB
+     *  r9 holds A
+     */
+.LOP_INSTANCE_OF_resolve:
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
+    mov     r1, r3                      @ r1<- BBBB
+    mov     r2, #1                      @ r2<- true
+    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
+    cmp     r0, #0                      @ got null?
+    beq     common_exceptionThrown      @ yes, handle exception
+    mov     r1, r0                      @ r1<- class resolved from BBB
+    mov     r3, rINST, lsr #12          @ r3<- B
+    GET_VREG(r0, r3)                    @ r0<- vB (object)
+    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
+    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
+
+
+/* continuation for OP_NEW_INSTANCE */
+
+    .balign 32                          @ minimize cache lines
+.LOP_NEW_INSTANCE_finish: @ r0=new object
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    cmp     r0, #0                      @ failed?
+    beq     common_exceptionThrown      @ yes, handle the exception
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r3)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+    /*
+     * Class initialization required.
+     *
+     *  r0 holds class object
+     */
+.LOP_NEW_INSTANCE_needinit:
+    mov     r9, r0                      @ save r0
+    bl      dvmInitClass                @ initialize class
+    cmp     r0, #0                      @ check boolean result
+    mov     r0, r9                      @ restore r0
+    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
+    b       common_exceptionThrown      @ failed, deal with init exception
+
+    /*
+     * Resolution required.  This is the least-likely path.
+     *
+     *  r1 holds BBBB
+     */
+.LOP_NEW_INSTANCE_resolve:
+    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
+    mov     r2, #0                      @ r2<- false
+    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
+    cmp     r0, #0                      @ got null?
+    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
+    b       common_exceptionThrown      @ yes, handle exception
+
+.LstrInstantiationErrorPtr:
+    .word   .LstrInstantiationError
+
+
+/* continuation for OP_NEW_ARRAY */
+
+
+    /*
+     * Resolve class.  (This is an uncommon case.)
+     *
+     *  r1 holds array length
+     *  r2 holds class ref CCCC
+     */
+.LOP_NEW_ARRAY_resolve:
+    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
+    mov     r9, r1                      @ r9<- length (save)
+    mov     r1, r2                      @ r1<- CCCC
+    mov     r2, #0                      @ r2<- false
+    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveClass             @ r0<- call(clazz, ref)
+    cmp     r0, #0                      @ got null?
+    mov     r1, r9                      @ r1<- length (restore)
+    beq     common_exceptionThrown      @ yes, handle exception
+    @ fall through to OP_NEW_ARRAY_finish
+
+    /*
+     * Finish allocation.
+     *
+     *  r0 holds class
+     *  r1 holds array length
+     */
+.LOP_NEW_ARRAY_finish:
+    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
+    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
+    cmp     r0, #0                      @ failed?
+    mov     r2, rINST, lsr #8           @ r2<- A+
+    beq     common_exceptionThrown      @ yes, handle the exception
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r2, r2, #15                 @ r2<- A
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r2)                    @ vA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_FILLED_NEW_ARRAY */
+
+    /*
+     * On entry:
+     *  r0 holds array class
+     *  r10 holds AA or BA
+     */
+.LOP_FILLED_NEW_ARRAY_continue:
+    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
+    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
+    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
+    .if     0
+    mov     r1, r10                     @ r1<- AA (length)
+    .else
+    mov     r1, r10, lsr #4             @ r1<- B (length)
+    .endif
+    cmp     r3, #'I'                    @ array of ints?
+    cmpne   r3, #'L'                    @ array of objects?
+    cmpne   r3, #'['                    @ array of arrays?
+    mov     r9, r1                      @ save length in r9
+    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
+    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
+    cmp     r0, #0                      @ null return?
+    beq     common_exceptionThrown      @ alloc failed, handle exception
+
+    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
+    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
+    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
+    subs    r9, r9, #1                  @ length--, check for neg
+    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
+    bmi     2f                          @ was zero, bail
+
+    @ copy values from registers into the array
+    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
+    .if     0
+    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
+1:  ldr     r3, [r2], #4                @ r3<- *r2++
+    subs    r9, r9, #1                  @ count--
+    str     r3, [r0], #4                @ *contents++ = vX
+    bpl     1b
+    @ continue at 2
+    .else
+    cmp     r9, #4                      @ length was initially 5?
+    and     r2, r10, #15                @ r2<- A
+    bne     1f                          @ <= 4 args, branch
+    GET_VREG(r3, r2)                    @ r3<- vA
+    sub     r9, r9, #1                  @ count--
+    str     r3, [r0, #16]               @ contents[4] = vA
+1:  and     r2, r1, #15                 @ r2<- F/E/D/C
+    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
+    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
+    subs    r9, r9, #1                  @ count--
+    str     r3, [r0], #4                @ *contents++ = vX
+    bpl     1b
+    @ continue at 2
+    .endif
+
+2:
+    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
+    GOTO_OPCODE(ip)                     @ execute it
+
+    /*
+     * Throw an exception indicating that we have not implemented this
+     * mode of filled-new-array.
+     */
+.LOP_FILLED_NEW_ARRAY_notimpl:
+    ldr     r0, .L_strInternalError
+    ldr     r1, .L_strFilledNewArrayNotImpl
+    bl      dvmThrowException
+    b       common_exceptionThrown
+
+    .if     (!0)                 @ define in one or the other, not both
+.L_strFilledNewArrayNotImpl:
+    .word   .LstrFilledNewArrayNotImpl
+.L_strInternalError:
+    .word   .LstrInternalError
+    .endif
+
+
+/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
+
+    /*
+     * On entry:
+     *  r0 holds array class
+     *  r10 holds AA or BA
+     */
+.LOP_FILLED_NEW_ARRAY_RANGE_continue:
+    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
+    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
+    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
+    .if     1
+    mov     r1, r10                     @ r1<- AA (length)
+    .else
+    mov     r1, r10, lsr #4             @ r1<- B (length)
+    .endif
+    cmp     r3, #'I'                    @ array of ints?
+    cmpne   r3, #'L'                    @ array of objects?
+    cmpne   r3, #'['                    @ array of arrays?
+    mov     r9, r1                      @ save length in r9
+    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
+    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
+    cmp     r0, #0                      @ null return?
+    beq     common_exceptionThrown      @ alloc failed, handle exception
+
+    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
+    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
+    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
+    subs    r9, r9, #1                  @ length--, check for neg
+    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
+    bmi     2f                          @ was zero, bail
+
+    @ copy values from registers into the array
+    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
+    .if     1
+    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
+1:  ldr     r3, [r2], #4                @ r3<- *r2++
+    subs    r9, r9, #1                  @ count--
+    str     r3, [r0], #4                @ *contents++ = vX
+    bpl     1b
+    @ continue at 2
+    .else
+    cmp     r9, #4                      @ length was initially 5?
+    and     r2, r10, #15                @ r2<- A
+    bne     1f                          @ <= 4 args, branch
+    GET_VREG(r3, r2)                    @ r3<- vA
+    sub     r9, r9, #1                  @ count--
+    str     r3, [r0, #16]               @ contents[4] = vA
+1:  and     r2, r1, #15                 @ r2<- F/E/D/C
+    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
+    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
+    subs    r9, r9, #1                  @ count--
+    str     r3, [r0], #4                @ *contents++ = vX
+    bpl     1b
+    @ continue at 2
+    .endif
+
+2:
+    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
+    GOTO_OPCODE(ip)                     @ execute it
+
+    /*
+     * Throw an exception indicating that we have not implemented this
+     * mode of filled-new-array.
+     */
+.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
+    ldr     r0, .L_strInternalError
+    ldr     r1, .L_strFilledNewArrayNotImpl
+    bl      dvmThrowException
+    b       common_exceptionThrown
+
+    .if     (!1)                 @ define in one or the other, not both
+.L_strFilledNewArrayNotImpl:
+    .word   .LstrFilledNewArrayNotImpl
+.L_strInternalError:
+    .word   .LstrInternalError
+    .endif
+
+
+/* continuation for OP_CMPL_FLOAT */
+.LOP_CMPL_FLOAT_finish:
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_CMPG_FLOAT */
+.LOP_CMPG_FLOAT_finish:
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_CMPL_DOUBLE */
+.LOP_CMPL_DOUBLE_finish:
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_CMPG_DOUBLE */
+.LOP_CMPG_DOUBLE_finish:
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_CMP_LONG */
+
+.LOP_CMP_LONG_less:
+    mvn     r1, #0                      @ r1<- -1
+    @ Want to cond code the next mov so we can avoid branch, but don't see it;
+    @ instead, we just replicate the tail end.
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    SET_VREG(r1, r9)                    @ vAA<- r1
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+.LOP_CMP_LONG_greater:
+    mov     r1, #1                      @ r1<- 1
+    @ fall through to _finish
+
+.LOP_CMP_LONG_finish:
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    SET_VREG(r1, r9)                    @ vAA<- r1
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_AGET_WIDE */
+
+.LOP_AGET_WIDE_finish:
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_APUT_WIDE */
+
+.LOP_APUT_WIDE_finish:
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_APUT_OBJECT */
+    /*
+     * On entry:
+     *  r1 = vBB (arrayObj)
+     *  r9 = vAA (obj)
+     *  r10 = offset into array (vBB + vCC * width)
+     */
+.LOP_APUT_OBJECT_finish:
+    cmp     r9, #0                      @ storing null reference?
+    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
+    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
+    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
+    bl      dvmCanPutArrayElement       @ test object type vs. array type
+    cmp     r0, #0                      @ okay?
+    beq     common_errArrayStore        @ no
+.LOP_APUT_OBJECT_skip_check:
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IGET */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IGET_finish:
+    @bl      common_squeak0
+    cmp     r9, #0                      @ check object for null
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    beq     common_errNullObject        @ object was null
+    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
+    mov     r2, rINST, lsr #8           @ r2<- A+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r2, r2, #15                 @ r2<- A
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r2)                    @ fp[A]<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IGET_WIDE */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IGET_WIDE_finish:
+    cmp     r9, #0                      @ check object for null
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    beq     common_errNullObject        @ object was null
+    mov     r2, rINST, lsr #8           @ r2<- A+
+    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
+    and     r2, r2, #15                 @ r2<- A
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IGET_OBJECT */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IGET_OBJECT_finish:
+    @bl      common_squeak0
+    cmp     r9, #0                      @ check object for null
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    beq     common_errNullObject        @ object was null
+    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
+    mov     r2, rINST, lsr #8           @ r2<- A+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r2, r2, #15                 @ r2<- A
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r2)                    @ fp[A]<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IGET_BOOLEAN */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IGET_BOOLEAN_finish:
+    @bl      common_squeak1
+    cmp     r9, #0                      @ check object for null
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    beq     common_errNullObject        @ object was null
+    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
+    mov     r2, rINST, lsr #8           @ r2<- A+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r2, r2, #15                 @ r2<- A
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r2)                    @ fp[A]<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IGET_BYTE */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IGET_BYTE_finish:
+    @bl      common_squeak2
+    cmp     r9, #0                      @ check object for null
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    beq     common_errNullObject        @ object was null
+    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
+    mov     r2, rINST, lsr #8           @ r2<- A+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r2, r2, #15                 @ r2<- A
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r2)                    @ fp[A]<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IGET_CHAR */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IGET_CHAR_finish:
+    @bl      common_squeak3
+    cmp     r9, #0                      @ check object for null
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    beq     common_errNullObject        @ object was null
+    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
+    mov     r2, rINST, lsr #8           @ r2<- A+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r2, r2, #15                 @ r2<- A
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r2)                    @ fp[A]<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IGET_SHORT */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IGET_SHORT_finish:
+    @bl      common_squeak4
+    cmp     r9, #0                      @ check object for null
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    beq     common_errNullObject        @ object was null
+    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
+    mov     r2, rINST, lsr #8           @ r2<- A+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r2, r2, #15                 @ r2<- A
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r2)                    @ fp[A]<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IPUT */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IPUT_finish:
+    @bl      common_squeak0
+    mov     r1, rINST, lsr #8           @ r1<- A+
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    and     r1, r1, #15                 @ r1<- A
+    cmp     r9, #0                      @ check object for null
+    GET_VREG(r0, r1)                    @ r0<- fp[A]
+    beq     common_errNullObject        @ object was null
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IPUT_WIDE */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IPUT_WIDE_finish:
+    mov     r2, rINST, lsr #8           @ r2<- A+
+    cmp     r9, #0                      @ check object for null
+    and     r2, r2, #15                 @ r2<- A
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
+    beq     common_errNullObject        @ object was null
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IPUT_OBJECT */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IPUT_OBJECT_finish:
+    @bl      common_squeak0
+    mov     r1, rINST, lsr #8           @ r1<- A+
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    and     r1, r1, #15                 @ r1<- A
+    cmp     r9, #0                      @ check object for null
+    GET_VREG(r0, r1)                    @ r0<- fp[A]
+    beq     common_errNullObject        @ object was null
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IPUT_BOOLEAN */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IPUT_BOOLEAN_finish:
+    @bl      common_squeak1
+    mov     r1, rINST, lsr #8           @ r1<- A+
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    and     r1, r1, #15                 @ r1<- A
+    cmp     r9, #0                      @ check object for null
+    GET_VREG(r0, r1)                    @ r0<- fp[A]
+    beq     common_errNullObject        @ object was null
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IPUT_BYTE */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IPUT_BYTE_finish:
+    @bl      common_squeak2
+    mov     r1, rINST, lsr #8           @ r1<- A+
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    and     r1, r1, #15                 @ r1<- A
+    cmp     r9, #0                      @ check object for null
+    GET_VREG(r0, r1)                    @ r0<- fp[A]
+    beq     common_errNullObject        @ object was null
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IPUT_CHAR */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IPUT_CHAR_finish:
+    @bl      common_squeak3
+    mov     r1, rINST, lsr #8           @ r1<- A+
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    and     r1, r1, #15                 @ r1<- A
+    cmp     r9, #0                      @ check object for null
+    GET_VREG(r0, r1)                    @ r0<- fp[A]
+    beq     common_errNullObject        @ object was null
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IPUT_SHORT */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IPUT_SHORT_finish:
+    @bl      common_squeak4
+    mov     r1, rINST, lsr #8           @ r1<- A+
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    and     r1, r1, #15                 @ r1<- A
+    cmp     r9, #0                      @ check object for null
+    GET_VREG(r0, r1)                    @ r0<- fp[A]
+    beq     common_errNullObject        @ object was null
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_SGET */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     */
+.LOP_SGET_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SGET_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_SGET_WIDE */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     */
+.LOP_SGET_WIDE_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SGET_WIDE_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_SGET_OBJECT */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     */
+.LOP_SGET_OBJECT_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_SGET_BOOLEAN */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     */
+.LOP_SGET_BOOLEAN_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_SGET_BYTE */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     */
+.LOP_SGET_BYTE_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SGET_BYTE_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_SGET_CHAR */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     */
+.LOP_SGET_CHAR_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SGET_CHAR_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_SGET_SHORT */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     */
+.LOP_SGET_SHORT_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SGET_SHORT_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_SPUT */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     */
+.LOP_SPUT_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SPUT_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_SPUT_WIDE */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     *  r9: &fp[AA]
+     */
+.LOP_SPUT_WIDE_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_SPUT_OBJECT */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     */
+.LOP_SPUT_OBJECT_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_SPUT_BOOLEAN */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     */
+.LOP_SPUT_BOOLEAN_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_SPUT_BYTE */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     */
+.LOP_SPUT_BYTE_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_SPUT_CHAR */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     */
+.LOP_SPUT_CHAR_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_SPUT_SHORT */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     */
+.LOP_SPUT_SHORT_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_INVOKE_VIRTUAL */
+
+    /*
+     * At this point:
+     *  r0 = resolved base method
+     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
+     */
+.LOP_INVOKE_VIRTUAL_continue:
+    GET_VREG(r1, r10)                   @ r1<- "this" ptr
+    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
+    cmp     r1, #0                      @ is "this" null?
+    beq     common_errNullObject        @ null "this", throw exception
+    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
+    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
+    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
+    bl      common_invokeMethodNoRange @ continue on
+
+
+/* continuation for OP_INVOKE_SUPER */
+
+    /*
+     * At this point:
+     *  r0 = resolved base method
+     *  r9 = method->clazz
+     */
+.LOP_INVOKE_SUPER_continue:
+    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
+    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
+    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
+    EXPORT_PC()                         @ must export for invoke
+    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
+    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
+    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
+    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
+    bl      common_invokeMethodNoRange @ continue on
+
+.LOP_INVOKE_SUPER_resolve:
+    mov     r0, r9                      @ r0<- method->clazz
+    mov     r2, #METHOD_VIRTUAL         @ resolver method type
+    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
+    cmp     r0, #0                      @ got null?
+    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
+    b       common_exceptionThrown      @ yes, handle exception
+
+    /*
+     * Throw a NoSuchMethodError with the method name as the message.
+     *  r0 = resolved base method
+     */
+.LOP_INVOKE_SUPER_nsm:
+    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
+    b       common_errNoSuchMethod
+
+
+/* continuation for OP_INVOKE_DIRECT */
+
+    /*
+     * On entry:
+     *  r1 = reference (BBBB or CCCC)
+     *  r10 = "this" register
+     */
+.LOP_INVOKE_DIRECT_resolve:
+    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
+    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
+    mov     r2, #METHOD_DIRECT          @ resolver method type
+    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
+    cmp     r0, #0                      @ got null?
+    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
+    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
+    b       common_exceptionThrown      @ yes, handle exception
+
+
+/* continuation for OP_INVOKE_VIRTUAL_RANGE */
+
+    /*
+     * At this point:
+     *  r0 = resolved base method
+     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
+     */
+.LOP_INVOKE_VIRTUAL_RANGE_continue:
+    GET_VREG(r1, r10)                   @ r1<- "this" ptr
+    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
+    cmp     r1, #0                      @ is "this" null?
+    beq     common_errNullObject        @ null "this", throw exception
+    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
+    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
+    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
+    bl      common_invokeMethodRange @ continue on
+
+
+/* continuation for OP_INVOKE_SUPER_RANGE */
+
+    /*
+     * At this point:
+     *  r0 = resolved base method
+     *  r9 = method->clazz
+     */
+.LOP_INVOKE_SUPER_RANGE_continue:
+    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
+    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
+    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
+    EXPORT_PC()                         @ must export for invoke
+    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
+    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
+    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
+    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
+    bl      common_invokeMethodRange @ continue on
+
+.LOP_INVOKE_SUPER_RANGE_resolve:
+    mov     r0, r9                      @ r0<- method->clazz
+    mov     r2, #METHOD_VIRTUAL         @ resolver method type
+    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
+    cmp     r0, #0                      @ got null?
+    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
+    b       common_exceptionThrown      @ yes, handle exception
+
+    /*
+     * Throw a NoSuchMethodError with the method name as the message.
+     *  r0 = resolved base method
+     */
+.LOP_INVOKE_SUPER_RANGE_nsm:
+    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
+    b       common_errNoSuchMethod
+
+
+/* continuation for OP_INVOKE_DIRECT_RANGE */
+
+    /*
+     * On entry:
+     *  r1 = reference (BBBB or CCCC)
+     *  r10 = "this" register
+     */
+.LOP_INVOKE_DIRECT_RANGE_resolve:
+    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
+    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
+    mov     r2, #METHOD_DIRECT          @ resolver method type
+    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
+    cmp     r0, #0                      @ got null?
+    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
+    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
+    b       common_exceptionThrown      @ yes, handle exception
+
+
+/* continuation for OP_FLOAT_TO_LONG */
+/*
+ * Convert the float in r0 to a long in r0/r1.
+ *
+ * We have to clip values to long min/max per the specification.  The
+ * expected common case is a "reasonable" value that converts directly
+ * to modest integer.  The EABI convert function isn't doing this for us.
+ */
+f2l_doconv:
+    stmfd   sp!, {r4, lr}
+    mov     r1, #0x5f000000             @ (float)maxlong
+    mov     r4, r0
+    bl      __aeabi_fcmpge              @ is arg >= maxlong?
+    cmp     r0, #0                      @ nonzero == yes
+    mvnne   r0, #0                      @ return maxlong (7fffffff)
+    mvnne   r1, #0x80000000
+    ldmnefd sp!, {r4, pc}
+
+    mov     r0, r4                      @ recover arg
+    mov     r1, #0xdf000000             @ (float)minlong
+    bl      __aeabi_fcmple              @ is arg <= minlong?
+    cmp     r0, #0                      @ nonzero == yes
+    movne   r0, #0                      @ return minlong (80000000)
+    movne   r1, #0x80000000
+    ldmnefd sp!, {r4, pc}
+
+    mov     r0, r4                      @ recover arg
+    mov     r1, r4
+    bl      __aeabi_fcmpeq              @ is arg == self?
+    cmp     r0, #0                      @ zero == no
+    moveq   r1, #0                      @ return zero for NaN
+    ldmeqfd sp!, {r4, pc}
+
+    mov     r0, r4                      @ recover arg
+    bl      __aeabi_f2lz                @ convert float to long
+    ldmfd   sp!, {r4, pc}
+
+
+/* continuation for OP_DOUBLE_TO_LONG */
+/*
+ * Convert the double in r0/r1 to a long in r0/r1.
+ *
+ * We have to clip values to long min/max per the specification.  The
+ * expected common case is a "reasonable" value that converts directly
+ * to modest integer.  The EABI convert function isn't doing this for us.
+ */
+d2l_doconv:
+    stmfd   sp!, {r4, r5, lr}           @ save regs
+    mov     r3, #0x43000000             @ maxlong, as a double (high word)
+    add     r3, #0x00e00000             @  0x43e00000
+    mov     r2, #0                      @ maxlong, as a double (low word)
+    sub     sp, sp, #4                  @ align for EABI
+    mov     r4, r0                      @ save a copy of r0
+    mov     r5, r1                      @  and r1
+    bl      __aeabi_dcmpge              @ is arg >= maxlong?
+    cmp     r0, #0                      @ nonzero == yes
+    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
+    mvnne   r1, #0x80000000
+    bne     1f
+
+    mov     r0, r4                      @ recover arg
+    mov     r1, r5
+    mov     r3, #0xc3000000             @ minlong, as a double (high word)
+    add     r3, #0x00e00000             @  0xc3e00000
+    mov     r2, #0                      @ minlong, as a double (low word)
+    bl      __aeabi_dcmple              @ is arg <= minlong?
+    cmp     r0, #0                      @ nonzero == yes
+    movne   r0, #0                      @ return minlong (8000000000000000)
+    movne   r1, #0x80000000
+    bne     1f
+
+    mov     r0, r4                      @ recover arg
+    mov     r1, r5
+    mov     r2, r4                      @ compare against self
+    mov     r3, r5
+    bl      __aeabi_dcmpeq              @ is arg == self?
+    cmp     r0, #0                      @ zero == no
+    moveq   r1, #0                      @ return zero for NaN
+    beq     1f
+
+    mov     r0, r4                      @ recover arg
+    mov     r1, r5
+    bl      __aeabi_d2lz                @ convert double to long
+
+1:
+    add     sp, sp, #4
+    ldmfd   sp!, {r4, r5, pc}
+
+
+/* continuation for OP_MUL_LONG */
+
+.LOP_MUL_LONG_finish:
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_SHL_LONG */
+
+.LOP_SHL_LONG_finish:
+    mov     r0, r0, asl r2              @  r0<- r0 << r2
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_SHR_LONG */
+
+.LOP_SHR_LONG_finish:
+    mov     r1, r1, asr r2              @  r1<- r1 >> r2
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_USHR_LONG */
+
+.LOP_USHR_LONG_finish:
+    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_SHL_LONG_2ADDR */
+
+.LOP_SHL_LONG_2ADDR_finish:
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_SHR_LONG_2ADDR */
+
+.LOP_SHR_LONG_2ADDR_finish:
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_USHR_LONG_2ADDR */
+
+.LOP_USHR_LONG_2ADDR_finish:
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_EXECUTE_INLINE */
+
+    /*
+     * Extract args, call function.
+     *  r0 = #of args (0-4)
+     *  r10 = call index
+     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
+     *
+     * Other ideas:
+     * - Use a jump table from the main piece to jump directly into the
+     *   AND/LDR pairs.  Costs a data load, saves a branch.
+     * - Have five separate pieces that do the loading, so we can work the
+     *   interleave a little better.  Increases code size.
+     */
+.LOP_EXECUTE_INLINE_continue:
+    rsb     r0, r0, #4                  @ r0<- 4-r0
+    FETCH(r9, 2)                        @ r9<- FEDC
+    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
+    bl      common_abort                @ (skipped due to ARM prefetch)
+4:  and     ip, r9, #0xf000             @ isolate F
+    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
+3:  and     ip, r9, #0x0f00             @ isolate E
+    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
+2:  and     ip, r9, #0x00f0             @ isolate D
+    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
+1:  and     ip, r9, #0x000f             @ isolate C
+    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
+0:
+    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
+    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
+    @ (not reached)
+
+.LOP_EXECUTE_INLINE_table:
+    .word   gDvmInlineOpsTable
+
+
+    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
+    .global dvmAsmSisterEnd
+dvmAsmSisterEnd:
+
+/* File: armv5te/footer.S */
+
+/*
+ * ===========================================================================
+ *  Common subroutines and data
+ * ===========================================================================
+ */
+
+
+
+    .text
+    .align  2
+
+#if defined(WITH_JIT)
+/*
+ * Return from the translation cache to the interpreter when the compiler is
+ * having issues translating/executing a Dalvik instruction. We have to skip
+ * the code cache lookup otherwise it is possible to indefinitely bouce
+ * between the interpreter and the code cache if the instruction that fails
+ * to be compiled happens to be at a trace start.
+ */
+    .global dvmJitToInterpPunt
+dvmJitToInterpPunt:
+    mov    rPC, r0
+#ifdef EXIT_STATS
+    mov    r0,lr
+    bl     dvmBumpPunt;
+#endif
+    EXPORT_PC()
+    adrl   rIBASE, dvmAsmInstructionStart
+    FETCH_INST()
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+
+/*
+ * Return to the interpreter to handle a single instruction.
+ * On entry:
+ *    r0 <= PC
+ *    r1 <= PC of resume instruction
+ *    lr <= resume point in translation
+ */
+    .global dvmJitToInterpSingleStep
+dvmJitToInterpSingleStep:
+    str    lr,[rGLUE,#offGlue_jitResume]
+    str    r1,[rGLUE,#offGlue_jitResumePC]
+    mov    r1,#kInterpEntryInstr
+    @ enum is 4 byte in aapcs-EABI
+    str    r1, [rGLUE, #offGlue_entryPoint]
+    mov    rPC,r0
+    EXPORT_PC()
+    adrl   rIBASE, dvmAsmInstructionStart
+    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
+    str    r2,[rGLUE,#offGlue_jitState]
+    mov    r1,#1                  @ set changeInterp to bail to debug interp
+    b      common_gotoBail
+
+
+/*
+ * Return from the translation cache and immediately request
+ * a translation for the exit target.  Commonly used following
+ * invokes.
+ */
+    .global dvmJitToTraceSelect
+dvmJitToTraceSelect:
+    ldr    rPC,[r14, #-1]           @ get our target PC
+    add    rINST,r14,#-5            @ save start of chain branch
+    mov    r0,rPC
+    bl     dvmJitGetCodeAddr        @ Is there a translation?
+    cmp    r0,#0
+    beq    2f
+    mov    r1,rINST
+    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
+    cmp    r0,#0                    @ successful chain?
+    bxne   r0                       @ continue native execution
+    b      toInterpreter            @ didn't chain - resume with interpreter
+
+/* No translation, so request one if profiling isn't disabled*/
+2:
+    adrl   rIBASE, dvmAsmInstructionStart
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_INST()
+    cmp    r0, #0
+    bne    common_selectTrace
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+
+/*
+ * Return from the translation cache to the interpreter.
+ * The return was done with a BLX from thumb mode, and
+ * the following 32-bit word contains the target rPC value.
+ * Note that lr (r14) will have its low-order bit set to denote
+ * its thumb-mode origin.
+ *
+ * We'll need to stash our lr origin away, recover the new
+ * target and then check to see if there is a translation available
+ * for our new target.  If so, we do a translation chain and
+ * go back to native execution.  Otherwise, it's back to the
+ * interpreter (after treating this entry as a potential
+ * trace start).
+ */
+    .global dvmJitToInterpNormal
+dvmJitToInterpNormal:
+    ldr    rPC,[r14, #-1]           @ get our target PC
+    add    rINST,r14,#-5            @ save start of chain branch
+#ifdef EXIT_STATS
+    bl     dvmBumpNormal
+#endif
+    mov    r0,rPC
+    bl     dvmJitGetCodeAddr        @ Is there a translation?
+    cmp    r0,#0
+    beq    toInterpreter            @ go if not, otherwise do chain
+    mov    r1,rINST
+    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
+    cmp    r0,#0                    @ successful chain?
+    bxne   r0                       @ continue native execution
+    b      toInterpreter            @ didn't chain - resume with interpreter
+
+/*
+ * Return from the translation cache to the interpreter to do method invocation.
+ * Check if translation exists for the callee, but don't chain to it.
+ */
+    .global dvmJitToInterpNoChain
+dvmJitToInterpNoChain:
+#ifdef EXIT_STATS
+    bl     dvmBumpNoChain
+#endif
+    mov    r0,rPC
+    bl     dvmJitGetCodeAddr        @ Is there a translation?
+    cmp    r0,#0
+    bxne   r0                       @ continue native execution if so
+
+/*
+ * No translation, restore interpreter regs and start interpreting.
+ * rGLUE & rFP were preserved in the translated code, and rPC has
+ * already been restored by the time we get here.  We'll need to set
+ * up rIBASE & rINST, and load the address of the JitTable into r0.
+ */
+toInterpreter:
+    EXPORT_PC()
+    adrl   rIBASE, dvmAsmInstructionStart
+    FETCH_INST()
+    GET_JIT_PROF_TABLE(r0)
+    @ NOTE: intended fallthrough
+/*
+ * Common code to update potential trace start counter, and initiate
+ * a trace-build if appropriate.  On entry, rPC should point to the
+ * next instruction to execute, and rINST should be already loaded with
+ * the next opcode word, and r0 holds a pointer to the jit profile
+ * table (pJitProfTable).
+ */
+common_testUpdateProfile:
+    cmp     r0,#0
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
+
+common_updateProfile:
+    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
+    lsl     r3,r3,#23          @ shift out excess 511
+    ldrb    r1,[r0,r3,lsr #23] @ get counter
+    GET_INST_OPCODE(ip)
+    subs    r1,r1,#1           @ decrement counter
+    strb    r1,[r0,r3,lsr #23] @ and store it
+    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
+
+/*
+ * Here, we switch to the debug interpreter to request
+ * trace selection.  First, though, check to see if there
+ * is already a native translation in place (and, if so,
+ * jump to it now).
+ */
+    mov     r1,#255
+    strb    r1,[r0,r3,lsr #23] @ reset counter
+    EXPORT_PC()
+    mov     r0,rPC
+    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
+    cmp     r0,#0
+    beq     common_selectTrace
+    bxne    r0                          @ jump to the translation
+common_selectTrace:
+    mov     r2,#kJitTSelectRequest      @ ask for trace selection
+    str     r2,[rGLUE,#offGlue_jitState]
+    mov     r1,#1                       @ set changeInterp
+    b       common_gotoBail
+
+#endif
+
+/*
+ * Common code when a backward branch is taken.
+ *
+ * On entry:
+ *  r9 is PC adjustment *in bytes*
+ */
+common_backwardBranch:
+    mov     r0, #kInterpEntryInstr
+    bl      common_periodicChecks
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+/*
+ * Need to see if the thread needs to be suspended or debugger/profiler
+ * activity has begun.
+ *
+ * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't
+ * have to do the second ldr.
+ *
+ * TODO: reduce this so we're just checking a single location.
+ *
+ * On entry:
+ *  r0 is reentry type, e.g. kInterpEntryInstr
+ *  r9 is trampoline PC adjustment *in bytes*
+ */
+common_periodicChecks:
+    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
+
+#if defined(WITH_DEBUGGER)
+    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
+#endif
+#if defined(WITH_PROFILER)
+    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
+#endif
+
+    ldr     r3, [r3]                    @ r3<- suspendCount (int)
+
+#if defined(WITH_DEBUGGER)
+    ldrb    r1, [r1]                    @ r1<- debuggerActive (boolean)
+#endif
+#if defined (WITH_PROFILER)
+    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
+#endif
+
+    cmp     r3, #0                      @ suspend pending?
+    bne     2f                          @ yes, do full suspension check
+
+#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
+# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
+    orrs    r1, r1, r2                  @ r1<- r1 | r2
+    cmp     r1, #0                      @ debugger attached or profiler started?
+# elif defined(WITH_DEBUGGER)
+    cmp     r1, #0                      @ debugger attached?
+# elif defined(WITH_PROFILER)
+    cmp     r2, #0                      @ profiler started?
+# endif
+    bne     3f                          @ debugger/profiler, switch interp
+#endif
+
+    bx      lr                          @ nothing to do, return
+
+2:  @ check suspend
+    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
+    EXPORT_PC()                         @ need for precise GC
+    b       dvmCheckSuspendPending      @ suspend if necessary, then return
+
+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
+
+
+/*
+ * The equivalent of "goto bail", this calls through the "bail handler".
+ *
+ * State registers will be saved to the "glue" area before bailing.
+ *
+ * On entry:
+ *  r1 is "bool changeInterp", indicating if we want to switch to the
+ *     other interpreter or just bail all the way out
+ */
+common_gotoBail:
+    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
+    mov     r0, rGLUE                   @ r0<- glue ptr
+    b       dvmMterpStdBail             @ call(glue, changeInterp)
+
+    @add     r1, r1, #1                  @ using (boolean+1)
+    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
+    @bl      _longjmp                    @ does not return
+    @bl      common_abort
+
+
+/*
+ * Common code for method invocation with range.
+ *
+ * On entry:
+ *  r0 is "Method* methodToCall", the method we're trying to call
+ */
+common_invokeMethodRange:
+.LinvokeNewRange:
+    @ prepare to copy args to "outs" area of current frame
+    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
+    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
+    beq     .LinvokeArgsDone            @ if no args, skip the rest
+    FETCH(r1, 2)                        @ r1<- CCCC
+
+    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
+    @ (very few methods have > 10 args; could unroll for common cases)
+    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
+    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
+    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
+1:  ldr     r1, [r3], #4                @ val = *fp++
+    subs    r2, r2, #1                  @ count--
+    str     r1, [r10], #4               @ *outs++ = val
+    bne     1b                          @ ...while count != 0
+    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
+    b       .LinvokeArgsDone
+
+/*
+ * Common code for method invocation without range.
+ *
+ * On entry:
+ *  r0 is "Method* methodToCall", the method we're trying to call
+ */
+common_invokeMethodNoRange:
+.LinvokeNewNoRange:
+    @ prepare to copy args to "outs" area of current frame
+    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
+    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
+    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
+    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
+    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
+    beq     .LinvokeArgsDone
+
+    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
+.LinvokeNonRange:
+    rsb     r2, r2, #5                  @ r2<- 5-r2
+    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
+    bl      common_abort                @ (skipped due to ARM prefetch)
+5:  and     ip, rINST, #0x0f00          @ isolate A
+    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
+    mov     r0, r0                      @ nop
+    str     r2, [r10, #-4]!             @ *--outs = vA
+4:  and     ip, r1, #0xf000             @ isolate G
+    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
+    mov     r0, r0                      @ nop
+    str     r2, [r10, #-4]!             @ *--outs = vG
+3:  and     ip, r1, #0x0f00             @ isolate F
+    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
+    mov     r0, r0                      @ nop
+    str     r2, [r10, #-4]!             @ *--outs = vF
+2:  and     ip, r1, #0x00f0             @ isolate E
+    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
+    mov     r0, r0                      @ nop
+    str     r2, [r10, #-4]!             @ *--outs = vE
+1:  and     ip, r1, #0x000f             @ isolate D
+    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
+    mov     r0, r0                      @ nop
+    str     r2, [r10, #-4]!             @ *--outs = vD
+0:  @ fall through to .LinvokeArgsDone
+
+.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
+    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
+    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
+    @ find space for the new stack frame, check for overflow
+    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
+    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
+    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
+@    bl      common_dumpRegs
+    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
+    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
+    cmp     r3, r9                      @ bottom < interpStackEnd?
+    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
+    blt     .LstackOverflow             @ yes, this frame will overflow stack
+
+    @ set up newSaveArea
+#ifdef EASY_GDB
+    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
+    str     ip, [r10, #offStackSaveArea_prevSave]
+#endif
+    str     rFP, [r10, #offStackSaveArea_prevFrame]
+    str     rPC, [r10, #offStackSaveArea_savedPc]
+#if defined(WITH_JIT)
+    mov     r9, #0
+    str     r9, [r10, #offStackSaveArea_returnAddr]
+#endif
+    str     r0, [r10, #offStackSaveArea_method]
+    tst     r3, #ACC_NATIVE
+    bne     .LinvokeNative
+
+    /*
+    stmfd   sp!, {r0-r3}
+    bl      common_printNewline
+    mov     r0, rFP
+    mov     r1, #0
+    bl      dvmDumpFp
+    ldmfd   sp!, {r0-r3}
+    stmfd   sp!, {r0-r3}
+    mov     r0, r1
+    mov     r1, r10
+    bl      dvmDumpFp
+    bl      common_printNewline
+    ldmfd   sp!, {r0-r3}
+    */
+
+    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
+    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
+    mov     rPC, r2                         @ publish new rPC
+    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
+
+    @ Update "glue" values for the new method
+    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
+    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
+    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    mov     rFP, r1                         @ fp = newFp
+    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
+    mov     rINST, r9                       @ publish new rINST
+    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
+    cmp     r0,#0
+    bne     common_updateProfile
+    GOTO_OPCODE(ip)                         @ jump to next instruction
+#else
+    mov     rFP, r1                         @ fp = newFp
+    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
+    mov     rINST, r9                       @ publish new rINST
+    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
+    GOTO_OPCODE(ip)                         @ jump to next instruction
+#endif
+
+.LinvokeNative:
+    @ Prep for the native call
+    @ r0=methodToCall, r1=newFp, r10=newSaveArea
+    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
+    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
+    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
+    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
+    mov     r9, r3                      @ r9<- glue->self (preserve)
+
+    mov     r2, r0                      @ r2<- methodToCall
+    mov     r0, r1                      @ r0<- newFp (points to args)
+    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
+
+#ifdef ASSIST_DEBUGGER
+    /* insert fake function header to help gdb find the stack frame */
+    b       .Lskip
+    .type   dalvik_mterp, %function
+dalvik_mterp:
+    .fnstart
+    MTERP_ENTRY1
+    MTERP_ENTRY2
+.Lskip:
+#endif
+
+    @mov     lr, pc                      @ set return addr
+    @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
+    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
+
+    @ native return; r9=self, r10=newSaveArea
+    @ equivalent to dvmPopJniLocals
+    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
+    ldr     r1, [r9, #offThread_exception] @ check for exception
+    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
+    cmp     r1, #0                      @ null?
+    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
+    bne     common_exceptionThrown      @ no, handle exception
+
+    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+.LstackOverflow:
+    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
+    bl      dvmHandleStackOverflow
+    b       common_exceptionThrown
+#ifdef ASSIST_DEBUGGER
+    .fnend
+#endif
+
+
+    /*
+     * Common code for method invocation, calling through "glue code".
+     *
+     * TODO: now that we have range and non-range invoke handlers, this
+     *       needs to be split into two.  Maybe just create entry points
+     *       that set r9 and jump here?
+     *
+     * On entry:
+     *  r0 is "Method* methodToCall", the method we're trying to call
+     *  r9 is "bool methodCallRange", indicating if this is a /range variant
+     */
+     .if    0
+.LinvokeOld:
+    sub     sp, sp, #8                  @ space for args + pad
+    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
+    mov     r2, r0                      @ A2<- methodToCall
+    mov     r0, rGLUE                   @ A0<- glue
+    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
+    mov     r1, r9                      @ A1<- methodCallRange
+    mov     r3, rINST, lsr #8           @ A3<- AA
+    str     ip, [sp, #0]                @ A4<- ip
+    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
+    add     sp, sp, #8                  @ remove arg area
+    b       common_resumeAfterGlueCall  @ continue to next instruction
+    .endif
+
+
+
+/*
+ * Common code for handling a return instruction.
+ *
+ * This does not return.
+ */
+common_returnFromMethod:
+.LreturnNew:
+    mov     r0, #kInterpEntryReturn
+    mov     r9, #0
+    bl      common_periodicChecks
+
+    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
+    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
+    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
+    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
+                                        @ r2<- method we're returning to
+    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
+    cmp     r2, #0                      @ is this a break frame?
+    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
+    mov     r1, #0                      @ "want switch" = false
+    beq     common_gotoBail             @ break frame, bail out completely
+
+    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
+    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
+    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
+    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
+#if defined(WITH_JIT)
+    ldr     r3, [r0, #offStackSaveArea_returnAddr] @ r3 = saveArea->returnAddr
+    GET_JIT_PROF_TABLE(r0)
+    mov     rPC, r9                     @ publish new rPC
+    str     r1, [rGLUE, #offGlue_methodClassDex]
+    cmp     r3, #0                      @ caller is compiled code
+    blxne   r3
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    mov     rPC, r9                     @ publish new rPC
+    str     r1, [rGLUE, #offGlue_methodClassDex]
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+    /*
+     * Return handling, calls through "glue code".
+     */
+     .if    0
+.LreturnOld:
+    SAVE_PC_FP_TO_GLUE()                @ export state
+    mov     r0, rGLUE                   @ arg to function
+    bl      dvmMterp_returnFromMethod
+    b       common_resumeAfterGlueCall
+    .endif
+
+
+/*
+ * Somebody has thrown an exception.  Handle it.
+ *
+ * If the exception processing code returns to us (instead of falling
+ * out of the interpreter), continue with whatever the next instruction
+ * now happens to be.
+ *
+ * This does not return.
+ */
+     .global dvmMterpCommonExceptionThrown
+dvmMterpCommonExceptionThrown:
+common_exceptionThrown:
+.LexceptionNew:
+    mov     r0, #kInterpEntryThrow
+    mov     r9, #0
+    bl      common_periodicChecks
+
+#if defined(WITH_JIT)
+    mov     r2,#kJitTSelectAbort        @ abandon trace selection in progress
+    str     r2,[rGLUE,#offGlue_jitState]
+#endif
+
+    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
+    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
+    mov     r1, r10                     @ r1<- self
+    mov     r0, r9                      @ r0<- exception
+    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
+    mov     r3, #0                      @ r3<- NULL
+    str     r3, [r10, #offThread_exception] @ self->exception = NULL
+
+    /* set up args and a local for "&fp" */
+    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
+    str     rFP, [sp, #-4]!             @ *--sp = fp
+    mov     ip, sp                      @ ip<- &fp
+    mov     r3, #0                      @ r3<- false
+    str     ip, [sp, #-4]!              @ *--sp = &fp
+    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
+    mov     r0, r10                     @ r0<- self
+    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
+    mov     r2, r9                      @ r2<- exception
+    sub     r1, rPC, r1                 @ r1<- pc - method->insns
+    mov     r1, r1, asr #1              @ r1<- offset in code units
+
+    /* call, r0 gets catchRelPc (a code-unit offset) */
+    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
+
+    /* fix earlier stack overflow if necessary; may trash rFP */
+    ldrb    r1, [r10, #offThread_stackOverflowed]
+    cmp     r1, #0                      @ did we overflow earlier?
+    beq     1f                          @ no, skip ahead
+    mov     rFP, r0                     @ save relPc result in rFP
+    mov     r0, r10                     @ r0<- self
+    bl      dvmCleanupStackOverflow     @ call(self)
+    mov     r0, rFP                     @ restore result
+1:
+
+    /* update frame pointer and check result from dvmFindCatchBlock */
+    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
+    cmp     r0, #0                      @ is catchRelPc < 0?
+    add     sp, sp, #8                  @ restore stack
+    bmi     .LnotCaughtLocally
+
+    /* adjust locals to match self->curFrame and updated PC */
+    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
+    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
+    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
+    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
+    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
+    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
+    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
+    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
+
+    /* release the tracked alloc on the exception */
+    mov     r0, r9                      @ r0<- exception
+    mov     r1, r10                     @ r1<- self
+    bl      dvmReleaseTrackedAlloc      @ release the exception
+
+    /* restore the exception if the handler wants it */
+    FETCH_INST()                        @ load rINST from rPC
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
+    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+.LnotCaughtLocally: @ r9=exception, r10=self
+    /* fix stack overflow if necessary */
+    ldrb    r1, [r10, #offThread_stackOverflowed]
+    cmp     r1, #0                      @ did we overflow earlier?
+    movne   r0, r10                     @ if yes: r0<- self
+    blne    dvmCleanupStackOverflow     @ if yes: call(self)
+
+    @ may want to show "not caught locally" debug messages here
+#if DVM_SHOW_EXCEPTION >= 2
+    /* call __android_log_print(prio, tag, format, ...) */
+    /* "Exception %s from %s:%d not caught locally" */
+    @ dvmLineNumFromPC(method, pc - method->insns)
+    ldr     r0, [rGLUE, #offGlue_method]
+    ldr     r1, [r0, #offMethod_insns]
+    sub     r1, rPC, r1
+    asr     r1, r1, #1
+    bl      dvmLineNumFromPC
+    str     r0, [sp, #-4]!
+    @ dvmGetMethodSourceFile(method)
+    ldr     r0, [rGLUE, #offGlue_method]
+    bl      dvmGetMethodSourceFile
+    str     r0, [sp, #-4]!
+    @ exception->clazz->descriptor
+    ldr     r3, [r9, #offObject_clazz]
+    ldr     r3, [r3, #offClassObject_descriptor]
+    @
+    ldr     r2, strExceptionNotCaughtLocally
+    ldr     r1, strLogTag
+    mov     r0, #3                      @ LOG_DEBUG
+    bl      __android_log_print
+#endif
+    str     r9, [r10, #offThread_exception] @ restore exception
+    mov     r0, r9                      @ r0<- exception
+    mov     r1, r10                     @ r1<- self
+    bl      dvmReleaseTrackedAlloc      @ release the exception
+    mov     r1, #0                      @ "want switch" = false
+    b       common_gotoBail             @ bail out
+
+
+    /*
+     * Exception handling, calls through "glue code".
+     */
+    .if     0
+.LexceptionOld:
+    SAVE_PC_FP_TO_GLUE()                @ export state
+    mov     r0, rGLUE                   @ arg to function
+    bl      dvmMterp_exceptionThrown
+    b       common_resumeAfterGlueCall
+    .endif
+
+
+/*
+ * After returning from a "glued" function, pull out the updated
+ * values and start executing at the next instruction.
+ */
+common_resumeAfterGlueCall:
+    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
+    FETCH_INST()                        @ load rINST from rPC
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+/*
+ * Invalid array index.
+ */
+common_errArrayIndex:
+    EXPORT_PC()
+    ldr     r0, strArrayIndexException
+    mov     r1, #0
+    bl      dvmThrowException
+    b       common_exceptionThrown
+
+/*
+ * Invalid array value.
+ */
+common_errArrayStore:
+    EXPORT_PC()
+    ldr     r0, strArrayStoreException
+    mov     r1, #0
+    bl      dvmThrowException
+    b       common_exceptionThrown
+
+/*
+ * Integer divide or mod by zero.
+ */
+common_errDivideByZero:
+    EXPORT_PC()
+    ldr     r0, strArithmeticException
+    ldr     r1, strDivideByZero
+    bl      dvmThrowException
+    b       common_exceptionThrown
+
+/*
+ * Attempt to allocate an array with a negative size.
+ */
+common_errNegativeArraySize:
+    EXPORT_PC()
+    ldr     r0, strNegativeArraySizeException
+    mov     r1, #0
+    bl      dvmThrowException
+    b       common_exceptionThrown
+
+/*
+ * Invocation of a non-existent method.
+ */
+common_errNoSuchMethod:
+    EXPORT_PC()
+    ldr     r0, strNoSuchMethodError
+    mov     r1, #0
+    bl      dvmThrowException
+    b       common_exceptionThrown
+
+/*
+ * We encountered a null object when we weren't expecting one.  We
+ * export the PC, throw a NullPointerException, and goto the exception
+ * processing code.
+ */
+common_errNullObject:
+    EXPORT_PC()
+    ldr     r0, strNullPointerException
+    mov     r1, #0
+    bl      dvmThrowException
+    b       common_exceptionThrown
+
+/*
+ * For debugging, cause an immediate fault.  The source address will
+ * be in lr (use a bl instruction to jump here).
+ */
+common_abort:
+    ldr     pc, .LdeadFood
+.LdeadFood:
+    .word   0xdeadf00d
+
+/*
+ * Spit out a "we were here", preserving all registers.  (The attempt
+ * to save ip won't work, but we need to save an even number of
+ * registers for EABI 64-bit stack alignment.)
+ */
+    .macro  SQUEAK num
+common_squeak\num:
+    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    ldr     r0, strSqueak
+    mov     r1, #\num
+    bl      printf
+    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    bx      lr
+    .endm
+
+    SQUEAK  0
+    SQUEAK  1
+    SQUEAK  2
+    SQUEAK  3
+    SQUEAK  4
+    SQUEAK  5
+
+/*
+ * Spit out the number in r0, preserving registers.
+ */
+common_printNum:
+    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    mov     r1, r0
+    ldr     r0, strSqueak
+    bl      printf
+    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    bx      lr
+
+/*
+ * Print a newline, preserving registers.
+ */
+common_printNewline:
+    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    ldr     r0, strNewline
+    bl      printf
+    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    bx      lr
+
+    /*
+     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
+     */
+common_printHex:
+    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    mov     r1, r0
+    ldr     r0, strPrintHex
+    bl      printf
+    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    bx      lr
+
+/*
+ * Print the 64-bit quantity in r0-r1, preserving registers.
+ */
+common_printLong:
+    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    mov     r3, r1
+    mov     r2, r0
+    ldr     r0, strPrintLong
+    bl      printf
+    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    bx      lr
+
+/*
+ * Print full method info.  Pass the Method* in r0.  Preserves regs.
+ */
+common_printMethod:
+    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    bl      dvmMterpPrintMethod
+    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    bx      lr
+
+/*
+ * Call a C helper function that dumps regs and possibly some
+ * additional info.  Requires the C function to be compiled in.
+ */
+    .if     0
+common_dumpRegs:
+    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    bl      dvmMterpDumpArmRegs
+    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    bx      lr
+    .endif
+
+#if 0
+/*
+ * Experiment on VFP mode.
+ *
+ * uint32_t setFPSCR(uint32_t val, uint32_t mask)
+ *
+ * Updates the bits specified by "mask", setting them to the values in "val".
+ */
+setFPSCR:
+    and     r0, r0, r1                  @ make sure no stray bits are set
+    fmrx    r2, fpscr                   @ get VFP reg
+    mvn     r1, r1                      @ bit-invert mask
+    and     r2, r2, r1                  @ clear masked bits
+    orr     r2, r2, r0                  @ set specified bits
+    fmxr    fpscr, r2                   @ set VFP reg
+    mov     r0, r2                      @ return new value
+    bx      lr
+
+    .align  2
+    .global dvmConfigureFP
+    .type   dvmConfigureFP, %function
+dvmConfigureFP:
+    stmfd   sp!, {ip, lr}
+    /* 0x03000000 sets DN/FZ */
+    /* 0x00009f00 clears the six exception enable flags */
+    bl      common_squeak0
+    mov     r0, #0x03000000             @ r0<- 0x03000000
+    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
+    bl      setFPSCR
+    ldmfd   sp!, {ip, pc}
+#endif
+
+
+/*
+ * String references, must be close to the code that uses them.
+ */
+    .align  2
+strArithmeticException:
+    .word   .LstrArithmeticException
+strArrayIndexException:
+    .word   .LstrArrayIndexException
+strArrayStoreException:
+    .word   .LstrArrayStoreException
+strDivideByZero:
+    .word   .LstrDivideByZero
+strNegativeArraySizeException:
+    .word   .LstrNegativeArraySizeException
+strNoSuchMethodError:
+    .word   .LstrNoSuchMethodError
+strNullPointerException:
+    .word   .LstrNullPointerException
+
+strLogTag:
+    .word   .LstrLogTag
+strExceptionNotCaughtLocally:
+    .word   .LstrExceptionNotCaughtLocally
+
+strNewline:
+    .word   .LstrNewline
+strSqueak:
+    .word   .LstrSqueak
+strPrintHex:
+    .word   .LstrPrintHex
+strPrintLong:
+    .word   .LstrPrintLong
+
+/*
+ * Zero-terminated ASCII string data.
+ *
+ * On ARM we have two choices: do like gcc does, and LDR from a .word
+ * with the address, or use an ADR pseudo-op to get the address
+ * directly.  ADR saves 4 bytes and an indirection, but it's using a
+ * PC-relative addressing mode and hence has a limited range, which
+ * makes it not work well with mergeable string sections.
+ */
+    .section .rodata.str1.4,"aMS",%progbits,1
+
+.LstrBadEntryPoint:
+    .asciz  "Bad entry point %d\n"
+.LstrArithmeticException:
+    .asciz  "Ljava/lang/ArithmeticException;"
+.LstrArrayIndexException:
+    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
+.LstrArrayStoreException:
+    .asciz  "Ljava/lang/ArrayStoreException;"
+.LstrClassCastException:
+    .asciz  "Ljava/lang/ClassCastException;"
+.LstrDivideByZero:
+    .asciz  "divide by zero"
+.LstrFilledNewArrayNotImpl:
+    .asciz  "filled-new-array only implemented for objects and 'int'"
+.LstrInternalError:
+    .asciz  "Ljava/lang/InternalError;"
+.LstrInstantiationError:
+    .asciz  "Ljava/lang/InstantiationError;"
+.LstrNegativeArraySizeException:
+    .asciz  "Ljava/lang/NegativeArraySizeException;"
+.LstrNoSuchMethodError:
+    .asciz  "Ljava/lang/NoSuchMethodError;"
+.LstrNullPointerException:
+    .asciz  "Ljava/lang/NullPointerException;"
+
+.LstrLogTag:
+    .asciz  "mterp"
+.LstrExceptionNotCaughtLocally:
+    .asciz  "Exception %s from %s:%d not caught locally\n"
+
+.LstrNewline:
+    .asciz  "\n"
+.LstrSqueak:
+    .asciz  "<%d>"
+.LstrPrintHex:
+    .asciz  "<0x%x>"
+.LstrPrintLong:
+    .asciz  "<%lld>"
+
+
diff --git a/vm/mterp/out/InterpAsm-armv5te.S b/vm/mterp/out/InterpAsm-armv5te.S
index 9987ff5..bafd442 100644
--- a/vm/mterp/out/InterpAsm-armv5te.S
+++ b/vm/mterp/out/InterpAsm-armv5te.S
@@ -40,7 +40,9 @@
 r0 holds returns of <= 4 bytes
 r0-r1 hold returns of 8 bytes, low word in r0
 
-Callee must save/restore r4+ (except r12) if it modifies them.
+Callee must save/restore r4+ (except r12) if it modifies them.  If VFP
+is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved,
+s0-s15 (d0-d7, q0-a3) do not need to be.
 
 Stack is "full descending".  Only the arguments that don't fit in the first 4
 registers are placed on the stack.  "sp" points at the first stacked argument
@@ -61,8 +63,8 @@
   r4  rPC       interpreted program counter, used for fetching instructions
   r5  rFP       interpreted frame pointer, used for accessing locals and args
   r6  rGLUE     MterpGlue pointer
-  r7  rIBASE    interpreted instruction base pointer, used for computed goto
-  r8  rINST     first 16-bit code unit of current instruction
+  r7  rINST     first 16-bit code unit of current instruction
+  r8  rIBASE    interpreted instruction base pointer, used for computed goto
 
 Macros are provided for common operations.  Each macro MUST emit only
 one instruction to make instruction-counting easier.  They MUST NOT alter
@@ -73,8 +75,8 @@
 #define rPC     r4
 #define rFP     r5
 #define rGLUE   r6
-#define rIBASE  r7
-#define rINST   r8
+#define rINST   r7
+#define rIBASE  r8
 
 /* save/restore the PC and/or FP from the glue struct */
 #define LOAD_PC_FROM_GLUE()     ldr     rPC, [rGLUE, #offGlue_pc]
@@ -124,6 +126,13 @@
 #define FETCH_ADVANCE_INST(_count) ldrh    rINST, [rPC, #(_count*2)]!
 
 /*
+ * The operation performed here is similar to FETCH_ADVANCE_INST, except the
+ * src and dest registers are parameterized (not hard-wired to rPC and rINST).
+ */
+#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \
+        ldrh    _dreg, [_sreg, #(_count*2)]!
+
+/*
  * Fetch the next instruction from an offset specified by _reg.  Updates
  * rPC to point to the next instruction.  "_reg" must specify the distance
  * in bytes, *not* 16-bit code units, and may be a signed value.
@@ -157,10 +166,17 @@
 #define GET_INST_OPCODE(_reg)   and     _reg, rINST, #255
 
 /*
+ * Put the prefetched instruction's opcode field into the specified register.
+ */
+#define GET_PREFETCHED_OPCODE(_oreg, _ireg)   and     _oreg, _ireg, #255
+
+/*
  * Begin executing the opcode in _reg.  Because this only jumps within the
  * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
  */
 #define GOTO_OPCODE(_reg)       add     pc, rIBASE, _reg, lsl #6
+#define GOTO_OPCODE_IFEQ(_reg)  addeq   pc, rIBASE, _reg, lsl #6
+#define GOTO_OPCODE_IFNE(_reg)  addne   pc, rIBASE, _reg, lsl #6
 
 /*
  * Get/set the 32-bit value from a Dalvik register.
@@ -168,6 +184,17 @@
 #define GET_VREG(_reg, _vreg)   ldr     _reg, [rFP, _vreg, lsl #2]
 #define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
 
+#if defined(WITH_JIT)
+#define GET_JIT_ENABLED(_reg)       ldr     _reg,[rGLUE,#offGlue_jitEnabled]
+#define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
+#endif
+
+/*
+ * Convert a virtual register index into an address.
+ */
+#define VREG_INDEX_TO_ADDR(_reg, _vreg) \
+        add     _reg, rFP, _vreg, lsl #2
+
 /*
  * This is a #include, not a %include, because we want the C pre-processor
  * to expand the macros into assembler assignment statements.
@@ -282,10 +309,21 @@
     cmp     r1, #kInterpEntryInstr      @ usual case?
     bne     .Lnot_instr                 @ no, handle it
 
+#if defined(WITH_JIT)
+.Lno_singleStep:
+    /* Entry is always a possible trace start */
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_INST()
+    cmp    r0,#0
+    bne    common_updateProfile
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+#else
     /* start executing the instruction at rPC */
     FETCH_INST()                        @ load rINST from rPC
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 .Lnot_instr:
     cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
@@ -295,6 +333,22 @@
     cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
     beq     common_exceptionThrown
 
+#if defined(WITH_JIT)
+.Lnot_throw:
+    ldr     r0,[rGLUE, #offGlue_jitResume]
+    ldr     r2,[rGLUE, #offGlue_jitResumePC]
+    cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
+    bne     .Lbad_arg
+    cmp     rPC,r2
+    bne     .Lno_singleStep             @ must have branched, don't resume
+    mov     r1, #kInterpEntryInstr
+    strb    r1, [rGLUE, #offGlue_entryPoint]
+    ldr     rINST, .LdvmCompilerTemplate
+    bx      r0                          @ re-enter the translation
+.LdvmCompilerTemplate:
+    .word   dvmCompilerTemplateStart
+#endif
+
 .Lbad_arg:
     ldr     r0, strBadEntryPoint
     @ r1 holds value of entryPoint
@@ -450,7 +504,7 @@
     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
-    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
     GOTO_OPCODE(ip)                     @ jump to next instruction
@@ -818,9 +872,7 @@
     GET_VREG(r1, r2)                    @ r1<- vAA (object)
     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
     cmp     r1, #0                      @ null object?
-#ifdef WITH_MONITOR_TRACKING
-    EXPORT_PC()                         @ export PC so we can grab stack trace
-#endif
+    EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
     beq     common_errNullObject        @ null object, throw an exception
     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
     bl      dvmLockObject               @ call(self, obj)
@@ -956,11 +1008,9 @@
     cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
     bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
 .LOP_NEW_INSTANCE_initialized: @ r0=class
-    ldr     r3, [r0, #offClassObject_accessFlags]   @ r3<- clazz->accessFlags
-    tst     r3, #(ACC_INTERFACE|ACC_ABSTRACT)   @ abstract or interface?
     mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
-    beq     .LOP_NEW_INSTANCE_finish          @ concrete class, continue
-    b       .LOP_NEW_INSTANCE_abstract        @ fail
+    bl      dvmAllocObject              @ r0<- new object
+    b       .LOP_NEW_INSTANCE_finish          @ continue
 
 /* ------------------------------ */
     .balign 64
@@ -1095,10 +1145,18 @@
     movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
     mov     r9, r9, lsl #1              @ r9<- byte offset
     bmi     common_backwardBranch       @ backward branch, do periodic checks
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
-
+#endif
 
 /* ------------------------------ */
     .balign 64
@@ -1114,9 +1172,18 @@
     FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
     movs    r9, r0, asl #1              @ r9<- byte offset, check sign
     bmi     common_backwardBranch       @ backward branch, do periodic checks
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 /* ------------------------------ */
@@ -1141,10 +1208,18 @@
     orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
     mov     r9, r0, asl #1              @ r9<- byte offset
     ble     common_backwardBranch       @ backward branch, do periodic checks
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
-
+#endif
 
 /* ------------------------------ */
     .balign 64
@@ -1170,9 +1245,18 @@
     movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
     bmi     common_backwardBranch       @ backward branch, do periodic checks
     beq     common_backwardBranch       @ (want to use BLE but V is unknown)
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 /* ------------------------------ */
@@ -1200,9 +1284,18 @@
     movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
     bmi     common_backwardBranch       @ backward branch, do periodic checks
     beq     common_backwardBranch       @ (want to use BLE but V is unknown)
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 
@@ -1449,9 +1542,16 @@
     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
     movs    r9, r9, asl #1              @ convert to bytes, check sign
     bmi     common_backwardBranch       @ yes, do periodic checks
-1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    b        common_testUpdateProfile
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 
@@ -1479,9 +1579,16 @@
     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
     movs    r9, r9, asl #1              @ convert to bytes, check sign
     bmi     common_backwardBranch       @ yes, do periodic checks
-1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    b        common_testUpdateProfile
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 
@@ -1509,9 +1616,16 @@
     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
     movs    r9, r9, asl #1              @ convert to bytes, check sign
     bmi     common_backwardBranch       @ yes, do periodic checks
-1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    b        common_testUpdateProfile
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 
@@ -1539,9 +1653,16 @@
     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
     movs    r9, r9, asl #1              @ convert to bytes, check sign
     bmi     common_backwardBranch       @ yes, do periodic checks
-1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    b        common_testUpdateProfile
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 
@@ -1569,9 +1690,16 @@
     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
     movs    r9, r9, asl #1              @ convert to bytes, check sign
     bmi     common_backwardBranch       @ yes, do periodic checks
-1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    b        common_testUpdateProfile
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 
@@ -1599,9 +1727,16 @@
     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
     movs    r9, r9, asl #1              @ convert to bytes, check sign
     bmi     common_backwardBranch       @ yes, do periodic checks
-1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    b        common_testUpdateProfile
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 
@@ -1626,9 +1761,19 @@
     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
     movs    r9, r9, asl #1              @ convert to bytes, check sign
     bmi     common_backwardBranch       @ backward branch, do periodic checks
-1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 
@@ -1653,9 +1798,19 @@
     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
     movs    r9, r9, asl #1              @ convert to bytes, check sign
     bmi     common_backwardBranch       @ backward branch, do periodic checks
-1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 
@@ -1680,9 +1835,19 @@
     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
     movs    r9, r9, asl #1              @ convert to bytes, check sign
     bmi     common_backwardBranch       @ backward branch, do periodic checks
-1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 
@@ -1707,9 +1872,19 @@
     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
     movs    r9, r9, asl #1              @ convert to bytes, check sign
     bmi     common_backwardBranch       @ backward branch, do periodic checks
-1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 
@@ -1734,9 +1909,19 @@
     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
     movs    r9, r9, asl #1              @ convert to bytes, check sign
     bmi     common_backwardBranch       @ backward branch, do periodic checks
-1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 
@@ -1761,9 +1946,19 @@
     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
     movs    r9, r9, asl #1              @ convert to bytes, check sign
     bmi     common_backwardBranch       @ backward branch, do periodic checks
-1:  FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 
@@ -3826,20 +4021,23 @@
  */
 d2i_doconv:
     stmfd   sp!, {r4, r5, lr}           @ save regs
-    ldr     r2, .LOP_DOUBLE_TO_INT_maxlo       @ (double)maxint, lo
-    ldr     r3, .LOP_DOUBLE_TO_INT_maxhi       @ (double)maxint, hi
+    mov     r2, #0x80000000             @ maxint, as a double (low word)
+    mov     r2, r2, asr #9              @  0xffc00000
     sub     sp, sp, #4                  @ align for EABI
-    mov     r4, r0                      @ save r0
+    mvn     r3, #0xbe000000             @ maxint, as a double (high word)
+    sub     r3, r3, #0x00200000         @  0x41dfffff
+    mov     r4, r0                      @ save a copy of r0
     mov     r5, r1                      @  and r1
     bl      __aeabi_dcmpge              @ is arg >= maxint?
     cmp     r0, #0                      @ nonzero == yes
-    mvnne   r0, #0x80000000             @ return maxint (7fffffff)
+    mvnne   r0, #0x80000000             @ return maxint (0x7fffffff)
     bne     1f
 
     mov     r0, r4                      @ recover arg
     mov     r1, r5
-    ldr     r3, .LOP_DOUBLE_TO_INT_min         @ (double)minint, hi
-    mov     r2, #0                      @ (double)minint, lo
+    mov     r3, #0xc1000000             @ minint, as a double (high word)
+    add     r3, r3, #0x00e00000         @  0xc1e00000
+    mov     r2, #0                      @ minint, as a double (low word)
     bl      __aeabi_dcmple              @ is arg <= minint?
     cmp     r0, #0                      @ nonzero == yes
     movne   r0, #0x80000000             @ return minint (80000000)
@@ -3860,13 +4058,6 @@
 1:
     add     sp, sp, #4
     ldmfd   sp!, {r4, r5, pc}
-
-.LOP_DOUBLE_TO_INT_maxlo:
-    .word   0xffc00000                  @ maxint, as a double (low word)
-.LOP_DOUBLE_TO_INT_maxhi:
-    .word   0x41dfffff                  @ maxint, as a double (high word)
-.LOP_DOUBLE_TO_INT_min:
-    .word   0xc1e00000                  @ minint, as a double (high word)
 #endif
 
 
@@ -5378,8 +5569,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -5418,8 +5609,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -5459,8 +5650,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -5499,8 +5690,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 1
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -5540,8 +5731,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 1
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -5580,8 +5771,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -5620,8 +5811,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -5660,8 +5851,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -5700,8 +5891,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -5740,8 +5931,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -5780,8 +5971,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -6224,8 +6415,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -6264,8 +6455,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -6304,8 +6495,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -6344,8 +6535,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -6385,8 +6576,8 @@
     mov     r9, rINST, lsr #8           @ r9<- A+
     mov     r3, rINST, lsr #12          @ r3<- B
     and     r9, r9, #15
-    GET_VREG(r0, r9)                    @ r0<- vA
     GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
     .if 0
     cmp     r1, #0                      @ is second operand zero?
     beq     common_errDivideByZero
@@ -7435,11 +7626,20 @@
 
 /* ------------------------------ */
     .balign 64
-.L_OP_UNUSED_ED: /* 0xed */
-/* File: armv5te/OP_UNUSED_ED.S */
-/* File: armv5te/unused.S */
-    bl      common_abort
-
+.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
+/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
+    /*
+     * Handle a throw-verification-error instruction.  This throws an
+     * exception for an error discovered during verification.  The
+     * exception is indicated by AA, with some detail provided by BBBB.
+     */
+    /* op AA, ref@BBBB */
+    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
+    FETCH(r2, 1)                        @ r2<- BBBB
+    EXPORT_PC()                         @ export the PC
+    mov     r1, rINST, lsr #8           @ r1<- AA
+    bl      dvmThrowVerificationError   @ always throws
+    b       common_exceptionThrown      @ handle exception
 
 
 /* ------------------------------ */
@@ -7951,8 +8151,7 @@
 /* continuation for OP_NEW_INSTANCE */
 
     .balign 32                          @ minimize cache lines
-.LOP_NEW_INSTANCE_finish: @ r0=class
-    bl      dvmAllocObject              @ r0<- new object
+.LOP_NEW_INSTANCE_finish: @ r0=new object
     mov     r3, rINST, lsr #8           @ r3<- AA
     cmp     r0, #0                      @ failed?
     beq     common_exceptionThrown      @ yes, handle the exception
@@ -7988,18 +8187,6 @@
     bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
     b       common_exceptionThrown      @ yes, handle exception
 
-    /*
-     * We can't instantiate an abstract class or interface, so throw an
-     * InstantiationError with the class descriptor as the message.
-     *
-     *  r0 holds class object
-     */
-.LOP_NEW_INSTANCE_abstract:
-    ldr     r1, [r0, #offClassObject_descriptor]
-    ldr     r0, .LstrInstantiationErrorPtr
-    bl      dvmThrowExceptionWithClassMessage
-    b       common_exceptionThrown
-
 .LstrInstantiationErrorPtr:
     .word   .LstrInstantiationError
 
@@ -9136,10 +9323,11 @@
  */
 d2l_doconv:
     stmfd   sp!, {r4, r5, lr}           @ save regs
-    ldr     r3, .LOP_DOUBLE_TO_LONG_max         @ (double)maxlong, hi
+    mov     r3, #0x43000000             @ maxlong, as a double (high word)
+    add     r3, #0x00e00000             @  0x43e00000
+    mov     r2, #0                      @ maxlong, as a double (low word)
     sub     sp, sp, #4                  @ align for EABI
-    mov     r2, #0                      @ (double)maxlong, lo
-    mov     r4, r0                      @ save r0
+    mov     r4, r0                      @ save a copy of r0
     mov     r5, r1                      @  and r1
     bl      __aeabi_dcmpge              @ is arg >= maxlong?
     cmp     r0, #0                      @ nonzero == yes
@@ -9149,8 +9337,9 @@
 
     mov     r0, r4                      @ recover arg
     mov     r1, r5
-    ldr     r3, .LOP_DOUBLE_TO_LONG_min         @ (double)minlong, hi
-    mov     r2, #0                      @ (double)minlong, lo
+    mov     r3, #0xc3000000             @ minlong, as a double (high word)
+    add     r3, #0x00e00000             @  0xc3e00000
+    mov     r2, #0                      @ minlong, as a double (low word)
     bl      __aeabi_dcmple              @ is arg <= minlong?
     cmp     r0, #0                      @ nonzero == yes
     movne   r0, #0                      @ return minlong (8000000000000000)
@@ -9174,11 +9363,6 @@
     add     sp, sp, #4
     ldmfd   sp!, {r4, r5, pc}
 
-.LOP_DOUBLE_TO_LONG_max:
-    .word   0x43e00000                  @ maxlong, as a double (high word)
-.LOP_DOUBLE_TO_LONG_min:
-    .word   0xc3e00000                  @ minlong, as a double (high word)
-
 
 /* continuation for OP_MUL_LONG */
 
@@ -9280,15 +9464,191 @@
 dvmAsmSisterEnd:
 
 /* File: armv5te/footer.S */
+
 /*
  * ===========================================================================
  *  Common subroutines and data
  * ===========================================================================
  */
 
+
+
     .text
     .align  2
 
+#if defined(WITH_JIT)
+/*
+ * Return from the translation cache to the interpreter when the compiler is
+ * having issues translating/executing a Dalvik instruction. We have to skip
+ * the code cache lookup otherwise it is possible to indefinitely bouce
+ * between the interpreter and the code cache if the instruction that fails
+ * to be compiled happens to be at a trace start.
+ */
+    .global dvmJitToInterpPunt
+dvmJitToInterpPunt:
+    mov    rPC, r0
+#ifdef EXIT_STATS
+    mov    r0,lr
+    bl     dvmBumpPunt;
+#endif
+    EXPORT_PC()
+    adrl   rIBASE, dvmAsmInstructionStart
+    FETCH_INST()
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+
+/*
+ * Return to the interpreter to handle a single instruction.
+ * On entry:
+ *    r0 <= PC
+ *    r1 <= PC of resume instruction
+ *    lr <= resume point in translation
+ */
+    .global dvmJitToInterpSingleStep
+dvmJitToInterpSingleStep:
+    str    lr,[rGLUE,#offGlue_jitResume]
+    str    r1,[rGLUE,#offGlue_jitResumePC]
+    mov    r1,#kInterpEntryInstr
+    @ enum is 4 byte in aapcs-EABI
+    str    r1, [rGLUE, #offGlue_entryPoint]
+    mov    rPC,r0
+    EXPORT_PC()
+    adrl   rIBASE, dvmAsmInstructionStart
+    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
+    str    r2,[rGLUE,#offGlue_jitState]
+    mov    r1,#1                  @ set changeInterp to bail to debug interp
+    b      common_gotoBail
+
+
+/*
+ * Return from the translation cache and immediately request
+ * a translation for the exit target.  Commonly used following
+ * invokes.
+ */
+    .global dvmJitToTraceSelect
+dvmJitToTraceSelect:
+    ldr    rPC,[r14, #-1]           @ get our target PC
+    add    rINST,r14,#-5            @ save start of chain branch
+    mov    r0,rPC
+    bl     dvmJitGetCodeAddr        @ Is there a translation?
+    cmp    r0,#0
+    beq    2f
+    mov    r1,rINST
+    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
+    cmp    r0,#0                    @ successful chain?
+    bxne   r0                       @ continue native execution
+    b      toInterpreter            @ didn't chain - resume with interpreter
+
+/* No translation, so request one if profiling isn't disabled*/
+2:
+    adrl   rIBASE, dvmAsmInstructionStart
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_INST()
+    cmp    r0, #0
+    bne    common_selectTrace
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+
+/*
+ * Return from the translation cache to the interpreter.
+ * The return was done with a BLX from thumb mode, and
+ * the following 32-bit word contains the target rPC value.
+ * Note that lr (r14) will have its low-order bit set to denote
+ * its thumb-mode origin.
+ *
+ * We'll need to stash our lr origin away, recover the new
+ * target and then check to see if there is a translation available
+ * for our new target.  If so, we do a translation chain and
+ * go back to native execution.  Otherwise, it's back to the
+ * interpreter (after treating this entry as a potential
+ * trace start).
+ */
+    .global dvmJitToInterpNormal
+dvmJitToInterpNormal:
+    ldr    rPC,[r14, #-1]           @ get our target PC
+    add    rINST,r14,#-5            @ save start of chain branch
+#ifdef EXIT_STATS
+    bl     dvmBumpNormal
+#endif
+    mov    r0,rPC
+    bl     dvmJitGetCodeAddr        @ Is there a translation?
+    cmp    r0,#0
+    beq    toInterpreter            @ go if not, otherwise do chain
+    mov    r1,rINST
+    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
+    cmp    r0,#0                    @ successful chain?
+    bxne   r0                       @ continue native execution
+    b      toInterpreter            @ didn't chain - resume with interpreter
+
+/*
+ * Return from the translation cache to the interpreter to do method invocation.
+ * Check if translation exists for the callee, but don't chain to it.
+ */
+    .global dvmJitToInterpNoChain
+dvmJitToInterpNoChain:
+#ifdef EXIT_STATS
+    bl     dvmBumpNoChain
+#endif
+    mov    r0,rPC
+    bl     dvmJitGetCodeAddr        @ Is there a translation?
+    cmp    r0,#0
+    bxne   r0                       @ continue native execution if so
+
+/*
+ * No translation, restore interpreter regs and start interpreting.
+ * rGLUE & rFP were preserved in the translated code, and rPC has
+ * already been restored by the time we get here.  We'll need to set
+ * up rIBASE & rINST, and load the address of the JitTable into r0.
+ */
+toInterpreter:
+    EXPORT_PC()
+    adrl   rIBASE, dvmAsmInstructionStart
+    FETCH_INST()
+    GET_JIT_PROF_TABLE(r0)
+    @ NOTE: intended fallthrough
+/*
+ * Common code to update potential trace start counter, and initiate
+ * a trace-build if appropriate.  On entry, rPC should point to the
+ * next instruction to execute, and rINST should be already loaded with
+ * the next opcode word, and r0 holds a pointer to the jit profile
+ * table (pJitProfTable).
+ */
+common_testUpdateProfile:
+    cmp     r0,#0
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
+
+common_updateProfile:
+    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
+    lsl     r3,r3,#23          @ shift out excess 511
+    ldrb    r1,[r0,r3,lsr #23] @ get counter
+    GET_INST_OPCODE(ip)
+    subs    r1,r1,#1           @ decrement counter
+    strb    r1,[r0,r3,lsr #23] @ and store it
+    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
+
+/*
+ * Here, we switch to the debug interpreter to request
+ * trace selection.  First, though, check to see if there
+ * is already a native translation in place (and, if so,
+ * jump to it now).
+ */
+    mov     r1,#255
+    strb    r1,[r0,r3,lsr #23] @ reset counter
+    EXPORT_PC()
+    mov     r0,rPC
+    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
+    cmp     r0,#0
+    beq     common_selectTrace
+    bxne    r0                          @ jump to the translation
+common_selectTrace:
+    mov     r2,#kJitTSelectRequest      @ ask for trace selection
+    str     r2,[rGLUE,#offGlue_jitState]
+    mov     r1,#1                       @ set changeInterp
+    b       common_gotoBail
+
+#endif
+
 /*
  * Common code when a backward branch is taken.
  *
@@ -9298,9 +9658,18 @@
 common_backwardBranch:
     mov     r0, #kInterpEntryInstr
     bl      common_periodicChecks
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+#else
     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
 
 /*
@@ -9336,7 +9705,7 @@
 #endif
 
     cmp     r3, #0                      @ suspend pending?
-    bne     2f                          @ yes, check suspend
+    bne     2f                          @ yes, do full suspension check
 
 #if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
 # if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
@@ -9354,6 +9723,7 @@
 
 2:  @ check suspend
     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
+    EXPORT_PC()                         @ need for precise GC
     b       dvmCheckSuspendPending      @ suspend if necessary, then return
 
 3:  @ debugger/profiler enabled, bail out
@@ -9401,10 +9771,12 @@
     @ (very few methods have > 10 args; could unroll for common cases)
     add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
     sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
+    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
 1:  ldr     r1, [r3], #4                @ val = *fp++
     subs    r2, r2, #1                  @ count--
     str     r1, [r10], #4               @ *outs++ = val
     bne     1b                          @ ...while count != 0
+    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
     b       .LinvokeArgsDone
 
 /*
@@ -9418,47 +9790,50 @@
     @ prepare to copy args to "outs" area of current frame
     movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
     SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
-    beq     .LinvokeArgsDone            @ if no args, skip the rest
-    FETCH(r1, 2)                        @ r1<- GFED
+    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
+    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
+    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
+    beq     .LinvokeArgsDone
 
-    @ r0=methodToCall, r1=GFED, r2=count, r10=outs
+    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
 .LinvokeNonRange:
     rsb     r2, r2, #5                  @ r2<- 5-r2
     add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
     bl      common_abort                @ (skipped due to ARM prefetch)
 5:  and     ip, rINST, #0x0f00          @ isolate A
-    ldr     r3, [rFP, ip, lsr #6]       @ r3<- vA (shift right 8, left 2)
+    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
     mov     r0, r0                      @ nop
-    str     r3, [r10, #-4]!             @ *--outs = vA
+    str     r2, [r10, #-4]!             @ *--outs = vA
 4:  and     ip, r1, #0xf000             @ isolate G
-    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vG (shift right 12, left 2)
+    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
     mov     r0, r0                      @ nop
-    str     r3, [r10, #-4]!             @ *--outs = vG
+    str     r2, [r10, #-4]!             @ *--outs = vG
 3:  and     ip, r1, #0x0f00             @ isolate F
-    ldr     r3, [rFP, ip, lsr #6]       @ r3<- vF
+    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
     mov     r0, r0                      @ nop
-    str     r3, [r10, #-4]!             @ *--outs = vF
+    str     r2, [r10, #-4]!             @ *--outs = vF
 2:  and     ip, r1, #0x00f0             @ isolate E
-    ldr     r3, [rFP, ip, lsr #2]       @ r3<- vE
+    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
     mov     r0, r0                      @ nop
-    str     r3, [r10, #-4]!             @ *--outs = vE
+    str     r2, [r10, #-4]!             @ *--outs = vE
 1:  and     ip, r1, #0x000f             @ isolate D
-    ldr     r3, [rFP, ip, lsl #2]       @ r3<- vD
+    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
     mov     r0, r0                      @ nop
-    str     r3, [r10, #-4]!             @ *--outs = vD
+    str     r2, [r10, #-4]!             @ *--outs = vD
 0:  @ fall through to .LinvokeArgsDone
 
-.LinvokeArgsDone: @ r0=methodToCall
+.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
+    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
+    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
     @ find space for the new stack frame, check for overflow
     SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
-    ldrh    r2, [r0, #offMethod_registersSize]  @ r2<- methodToCall->regsSize
-    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
-    sub     r1, r1, r2, lsl #2          @ r1<- newFp (old savearea - regsSize)
+    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
     SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
 @    bl      common_dumpRegs
     ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
     sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
     cmp     r3, r9                      @ bottom < interpStackEnd?
+    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
     blt     .LstackOverflow             @ yes, this frame will overflow stack
 
     @ set up newSaveArea
@@ -9468,9 +9843,11 @@
 #endif
     str     rFP, [r10, #offStackSaveArea_prevFrame]
     str     rPC, [r10, #offStackSaveArea_savedPc]
+#if defined(WITH_JIT)
+    mov     r9, #0
+    str     r9, [r10, #offStackSaveArea_returnAddr]
+#endif
     str     r0, [r10, #offStackSaveArea_method]
-
-    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
     tst     r3, #ACC_NATIVE
     bne     .LinvokeNative
 
@@ -9489,27 +9866,39 @@
     ldmfd   sp!, {r0-r3}
     */
 
-    @ Update "glue" values for the new method
-    @ r0=methodToCall, r1=newFp
-    ldr     r3, [r0, #offMethod_clazz]      @ r3<- method->clazz
-    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
-    ldr     r3, [r3, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
-    ldr     rPC, [r0, #offMethod_insns]     @ rPC<- method->insns
-    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
+    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
+    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
+    mov     rPC, r2                         @ publish new rPC
     ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
-    FETCH_INST()                            @ load rINST from rPC
+
+    @ Update "glue" values for the new method
+    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
+    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
+    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
     mov     rFP, r1                         @ fp = newFp
-    GET_INST_OPCODE(ip)                     @ extract opcode from rINST
+    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
+    mov     rINST, r9                       @ publish new rINST
+    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
+    cmp     r0,#0
+    bne     common_updateProfile
+    GOTO_OPCODE(ip)                         @ jump to next instruction
+#else
+    mov     rFP, r1                         @ fp = newFp
+    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
+    mov     rINST, r9                       @ publish new rINST
     str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
     GOTO_OPCODE(ip)                         @ jump to next instruction
+#endif
 
 .LinvokeNative:
     @ Prep for the native call
     @ r0=methodToCall, r1=newFp, r10=newSaveArea
     ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
-    ldr     r9, [r3, #offThread_jniLocal_nextEntry] @ r9<- thread->refNext
+    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
     str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
-    str     r9, [r10, #offStackSaveArea_localRefTop] @newFp->localRefTop=refNext
+    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
     mov     r9, r3                      @ r9<- glue->self (preserve)
 
     mov     r2, r0                      @ r2<- methodToCall
@@ -9533,11 +9922,11 @@
 
     @ native return; r9=self, r10=newSaveArea
     @ equivalent to dvmPopJniLocals
-    ldr     r0, [r10, #offStackSaveArea_localRefTop] @ r0<- newSave->localRefTop
+    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
     ldr     r1, [r9, #offThread_exception] @ check for exception
     str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
     cmp     r1, #0                      @ null?
-    str     r0, [r9, #offThread_jniLocal_nextEntry] @ self->refNext<- r0
+    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
     bne     common_exceptionThrown      @ no, handle exception
 
     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
@@ -9594,22 +9983,36 @@
 
     SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
     ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
+    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
     ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
                                         @ r2<- method we're returning to
+    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
     cmp     r2, #0                      @ is this a break frame?
+    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
     mov     r1, #0                      @ "want switch" = false
     beq     common_gotoBail             @ break frame, bail out completely
 
-    ldr     rPC, [r0, #offStackSaveArea_savedPc] @ pc = saveArea->savedPc
-    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
-    str     r2, [rGLUE, #offGlue_method]    @ glue->method = newSave->method
+    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
+    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
+    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
     str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
-    ldr     r1, [r2, #offMethod_clazz]      @ r1<- method->clazz
-    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
-    ldr     r1, [r1, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
+#if defined(WITH_JIT)
+    ldr     r3, [r0, #offStackSaveArea_returnAddr] @ r3 = saveArea->returnAddr
+    GET_JIT_PROF_TABLE(r0)
+    mov     rPC, r9                     @ publish new rPC
+    str     r1, [rGLUE, #offGlue_methodClassDex]
+    cmp     r3, #0                      @ caller is compiled code
+    blxne   r3
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    mov     rPC, r9                     @ publish new rPC
     str     r1, [rGLUE, #offGlue_methodClassDex]
     GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
 
     /*
      * Return handling, calls through "glue code".
@@ -9632,12 +10035,19 @@
  *
  * This does not return.
  */
+     .global dvmMterpCommonExceptionThrown
+dvmMterpCommonExceptionThrown:
 common_exceptionThrown:
 .LexceptionNew:
     mov     r0, #kInterpEntryThrow
     mov     r9, #0
     bl      common_periodicChecks
 
+#if defined(WITH_JIT)
+    mov     r2,#kJitTSelectAbort        @ abandon trace selection in progress
+    str     r2,[rGLUE,#offGlue_jitState]
+#endif
+
     ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
     ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
     mov     r1, r10                     @ r1<- self
@@ -9919,6 +10329,38 @@
     bx      lr
     .endif
 
+#if 0
+/*
+ * Experiment on VFP mode.
+ *
+ * uint32_t setFPSCR(uint32_t val, uint32_t mask)
+ *
+ * Updates the bits specified by "mask", setting them to the values in "val".
+ */
+setFPSCR:
+    and     r0, r0, r1                  @ make sure no stray bits are set
+    fmrx    r2, fpscr                   @ get VFP reg
+    mvn     r1, r1                      @ bit-invert mask
+    and     r2, r2, r1                  @ clear masked bits
+    orr     r2, r2, r0                  @ set specified bits
+    fmxr    fpscr, r2                   @ set VFP reg
+    mov     r0, r2                      @ return new value
+    bx      lr
+
+    .align  2
+    .global dvmConfigureFP
+    .type   dvmConfigureFP, %function
+dvmConfigureFP:
+    stmfd   sp!, {ip, lr}
+    /* 0x03000000 sets DN/FZ */
+    /* 0x00009f00 clears the six exception enable flags */
+    bl      common_squeak0
+    mov     r0, #0x03000000             @ r0<- 0x03000000
+    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
+    bl      setFPSCR
+    ldmfd   sp!, {ip, pc}
+#endif
+
 
 /*
  * String references, must be close to the code that uses them.
diff --git a/vm/mterp/out/InterpAsm-armv7-a.S b/vm/mterp/out/InterpAsm-armv7-a.S
new file mode 100644
index 0000000..8d018c1
--- /dev/null
+++ b/vm/mterp/out/InterpAsm-armv7-a.S
@@ -0,0 +1,9908 @@
+/*
+ * This file was generated automatically by gen-mterp.py for 'armv7-a'.
+ *
+ * --> DO NOT EDIT <--
+ */
+
+/* File: armv5te/header.S */
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * ARMv5 definitions and declarations.
+ */
+
+/*
+ARM EABI general notes:
+
+r0-r3 hold first 4 args to a method; they are not preserved across method calls
+r4-r8 are available for general use
+r9 is given special treatment in some situations, but not for us
+r10 (sl) seems to be generally available
+r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
+r12 (ip) is scratch -- not preserved across method calls
+r13 (sp) should be managed carefully in case a signal arrives
+r14 (lr) must be preserved
+r15 (pc) can be tinkered with directly
+
+r0 holds returns of <= 4 bytes
+r0-r1 hold returns of 8 bytes, low word in r0
+
+Callee must save/restore r4+ (except r12) if it modifies them.  If VFP
+is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved,
+s0-s15 (d0-d7, q0-a3) do not need to be.
+
+Stack is "full descending".  Only the arguments that don't fit in the first 4
+registers are placed on the stack.  "sp" points at the first stacked argument
+(i.e. the 5th arg).
+
+VFP: single-precision results in s0, double-precision results in d0.
+
+In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
+64-bit quantities (long long, double) must be 64-bit aligned.
+*/
+
+/*
+Mterp and ARM notes:
+
+The following registers have fixed assignments:
+
+  reg nick      purpose
+  r4  rPC       interpreted program counter, used for fetching instructions
+  r5  rFP       interpreted frame pointer, used for accessing locals and args
+  r6  rGLUE     MterpGlue pointer
+  r7  rINST     first 16-bit code unit of current instruction
+  r8  rIBASE    interpreted instruction base pointer, used for computed goto
+
+Macros are provided for common operations.  Each macro MUST emit only
+one instruction to make instruction-counting easier.  They MUST NOT alter
+unspecified registers or condition codes.
+*/
+
+/* single-purpose registers, given names for clarity */
+#define rPC     r4
+#define rFP     r5
+#define rGLUE   r6
+#define rINST   r7
+#define rIBASE  r8
+
+/* save/restore the PC and/or FP from the glue struct */
+#define LOAD_PC_FROM_GLUE()     ldr     rPC, [rGLUE, #offGlue_pc]
+#define SAVE_PC_TO_GLUE()       str     rPC, [rGLUE, #offGlue_pc]
+#define LOAD_FP_FROM_GLUE()     ldr     rFP, [rGLUE, #offGlue_fp]
+#define SAVE_FP_TO_GLUE()       str     rFP, [rGLUE, #offGlue_fp]
+#define LOAD_PC_FP_FROM_GLUE()  ldmia   rGLUE, {rPC, rFP}
+#define SAVE_PC_FP_TO_GLUE()    stmia   rGLUE, {rPC, rFP}
+
+/*
+ * "export" the PC to the stack frame, f/b/o future exception objects.  Must
+ * be done *before* something calls dvmThrowException.
+ *
+ * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
+ * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
+ *
+ * It's okay to do this more than once.
+ */
+#define EXPORT_PC() \
+    str     rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
+
+/*
+ * Given a frame pointer, find the stack save area.
+ *
+ * In C this is "((StackSaveArea*)(_fp) -1)".
+ */
+#define SAVEAREA_FROM_FP(_reg, _fpreg) \
+    sub     _reg, _fpreg, #sizeofStackSaveArea
+
+/*
+ * Fetch the next instruction from rPC into rINST.  Does not advance rPC.
+ */
+#define FETCH_INST()            ldrh    rINST, [rPC]
+
+/*
+ * Fetch the next instruction from the specified offset.  Advances rPC
+ * to point to the next instruction.  "_count" is in 16-bit code units.
+ *
+ * Because of the limited size of immediate constants on ARM, this is only
+ * suitable for small forward movements (i.e. don't try to implement "goto"
+ * with this).
+ *
+ * This must come AFTER anything that can throw an exception, or the
+ * exception catch may miss.  (This also implies that it must come after
+ * EXPORT_PC().)
+ */
+#define FETCH_ADVANCE_INST(_count) ldrh    rINST, [rPC, #(_count*2)]!
+
+/*
+ * The operation performed here is similar to FETCH_ADVANCE_INST, except the
+ * src and dest registers are parameterized (not hard-wired to rPC and rINST).
+ */
+#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \
+        ldrh    _dreg, [_sreg, #(_count*2)]!
+
+/*
+ * Fetch the next instruction from an offset specified by _reg.  Updates
+ * rPC to point to the next instruction.  "_reg" must specify the distance
+ * in bytes, *not* 16-bit code units, and may be a signed value.
+ *
+ * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the
+ * bits that hold the shift distance are used for the half/byte/sign flags.
+ * In some cases we can pre-double _reg for free, so we require a byte offset
+ * here.
+ */
+#define FETCH_ADVANCE_INST_RB(_reg) ldrh    rINST, [rPC, _reg]!
+
+/*
+ * Fetch a half-word code unit from an offset past the current PC.  The
+ * "_count" value is in 16-bit code units.  Does not advance rPC.
+ *
+ * The "_S" variant works the same but treats the value as signed.
+ */
+#define FETCH(_reg, _count)     ldrh    _reg, [rPC, #(_count*2)]
+#define FETCH_S(_reg, _count)   ldrsh   _reg, [rPC, #(_count*2)]
+
+/*
+ * Fetch one byte from an offset past the current PC.  Pass in the same
+ * "_count" as you would for FETCH, and an additional 0/1 indicating which
+ * byte of the halfword you want (lo/hi).
+ */
+#define FETCH_B(_reg, _count, _byte) ldrb     _reg, [rPC, #(_count*2+_byte)]
+
+/*
+ * Put the instruction's opcode field into the specified register.
+ */
+#define GET_INST_OPCODE(_reg)   and     _reg, rINST, #255
+
+/*
+ * Put the prefetched instruction's opcode field into the specified register.
+ */
+#define GET_PREFETCHED_OPCODE(_oreg, _ireg)   and     _oreg, _ireg, #255
+
+/*
+ * Begin executing the opcode in _reg.  Because this only jumps within the
+ * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
+ */
+#define GOTO_OPCODE(_reg)       add     pc, rIBASE, _reg, lsl #6
+#define GOTO_OPCODE_IFEQ(_reg)  addeq   pc, rIBASE, _reg, lsl #6
+#define GOTO_OPCODE_IFNE(_reg)  addne   pc, rIBASE, _reg, lsl #6
+
+/*
+ * Get/set the 32-bit value from a Dalvik register.
+ */
+#define GET_VREG(_reg, _vreg)   ldr     _reg, [rFP, _vreg, lsl #2]
+#define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
+
+#if defined(WITH_JIT)
+#define GET_JIT_ENABLED(_reg)       ldr     _reg,[rGLUE,#offGlue_jitEnabled]
+#define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
+#endif
+
+/*
+ * Convert a virtual register index into an address.
+ */
+#define VREG_INDEX_TO_ADDR(_reg, _vreg) \
+        add     _reg, rFP, _vreg, lsl #2
+
+/*
+ * This is a #include, not a %include, because we want the C pre-processor
+ * to expand the macros into assembler assignment statements.
+ */
+#include "../common/asm-constants.h"
+
+
+/* File: armv5te/platform.S */
+/*
+ * ===========================================================================
+ *  CPU-version-specific defines
+ * ===========================================================================
+ */
+
+/*
+ * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5.  Essentially a
+ * one-way branch.
+ *
+ * May modify IP.  Does not modify LR.
+ */
+.macro  LDR_PC source
+    ldr     pc, \source
+.endm
+
+/*
+ * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
+ * Jump to subroutine.
+ *
+ * May modify IP and LR.
+ */
+.macro  LDR_PC_LR source
+    mov     lr, pc
+    ldr     pc, \source
+.endm
+
+/*
+ * Macro for "LDMFD SP!, {...regs...,PC}".
+ *
+ * May modify IP and LR.
+ */
+.macro  LDMFD_PC regs
+    ldmfd   sp!, {\regs,pc}
+.endm
+
+
+/* File: armv5te/entry.S */
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Interpreter entry point.
+ */
+
+/*
+ * We don't have formal stack frames, so gdb scans upward in the code
+ * to find the start of the function (a label with the %function type),
+ * and then looks at the next few instructions to figure out what
+ * got pushed onto the stack.  From this it figures out how to restore
+ * the registers, including PC, for the previous stack frame.  If gdb
+ * sees a non-function label, it stops scanning, so either we need to
+ * have nothing but assembler-local labels between the entry point and
+ * the break, or we need to fake it out.
+ *
+ * When this is defined, we add some stuff to make gdb less confused.
+ */
+#define ASSIST_DEBUGGER 1
+
+    .text
+    .align  2
+    .global dvmMterpStdRun
+    .type   dvmMterpStdRun, %function
+
+/*
+ * On entry:
+ *  r0  MterpGlue* glue
+ *
+ * This function returns a boolean "changeInterp" value.  The return comes
+ * via a call to dvmMterpStdBail().
+ */
+dvmMterpStdRun:
+#define MTERP_ENTRY1 \
+    .save {r4-r10,fp,lr}; \
+    stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
+#define MTERP_ENTRY2 \
+    .pad    #4; \
+    sub     sp, sp, #4                  @ align 64
+
+    .fnstart
+    MTERP_ENTRY1
+    MTERP_ENTRY2
+
+    /* save stack pointer, add magic word for debuggerd */
+    str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
+
+    /* set up "named" registers, figure out entry point */
+    mov     rGLUE, r0                   @ set rGLUE
+    ldrb    r1, [r0, #offGlue_entryPoint]   @ InterpEntry enum is char
+    LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
+    adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
+    cmp     r1, #kInterpEntryInstr      @ usual case?
+    bne     .Lnot_instr                 @ no, handle it
+
+#if defined(WITH_JIT)
+.Lno_singleStep:
+    /* Entry is always a possible trace start */
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_INST()
+    cmp    r0,#0
+    bne    common_updateProfile
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+#else
+    /* start executing the instruction at rPC */
+    FETCH_INST()                        @ load rINST from rPC
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+.Lnot_instr:
+    cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
+    beq     common_returnFromMethod
+
+.Lnot_return:
+    cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
+    beq     common_exceptionThrown
+
+#if defined(WITH_JIT)
+.Lnot_throw:
+    ldr     r0,[rGLUE, #offGlue_jitResume]
+    ldr     r2,[rGLUE, #offGlue_jitResumePC]
+    cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
+    bne     .Lbad_arg
+    cmp     rPC,r2
+    bne     .Lno_singleStep             @ must have branched, don't resume
+    mov     r1, #kInterpEntryInstr
+    strb    r1, [rGLUE, #offGlue_entryPoint]
+    ldr     rINST, .LdvmCompilerTemplate
+    bx      r0                          @ re-enter the translation
+.LdvmCompilerTemplate:
+    .word   dvmCompilerTemplateStart
+#endif
+
+.Lbad_arg:
+    ldr     r0, strBadEntryPoint
+    @ r1 holds value of entryPoint
+    bl      printf
+    bl      dvmAbort
+    .fnend
+
+
+    .global dvmMterpStdBail
+    .type   dvmMterpStdBail, %function
+
+/*
+ * Restore the stack pointer and PC from the save point established on entry.
+ * This is essentially the same as a longjmp, but should be cheaper.  The
+ * last instruction causes us to return to whoever called dvmMterpStdRun.
+ *
+ * We pushed some registers on the stack in dvmMterpStdRun, then saved
+ * SP and LR.  Here we restore SP, restore the registers, and then restore
+ * LR to PC.
+ *
+ * On entry:
+ *  r0  MterpGlue* glue
+ *  r1  bool changeInterp
+ */
+dvmMterpStdBail:
+    ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
+    mov     r0, r1                          @ return the changeInterp value
+    add     sp, sp, #4                      @ un-align 64
+    LDMFD_PC "r4-r10,fp"                    @ restore 9 regs and return
+
+
+/*
+ * String references.
+ */
+strBadEntryPoint:
+    .word   .LstrBadEntryPoint
+
+
+
+    .global dvmAsmInstructionStart
+    .type   dvmAsmInstructionStart, %function
+dvmAsmInstructionStart = .L_OP_NOP
+    .text
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_NOP: /* 0x00 */
+/* File: armv5te/OP_NOP.S */
+    FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
+    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
+    GOTO_OPCODE(ip)                     @ execute it
+
+#ifdef ASSIST_DEBUGGER
+    /* insert fake function header to help gdb find the stack frame */
+    .type   dalvik_inst, %function
+dalvik_inst:
+    .fnstart
+    MTERP_ENTRY1
+    MTERP_ENTRY2
+    .fnend
+#endif
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MOVE: /* 0x01 */
+/* File: armv6t2/OP_MOVE.S */
+    /* for move, move-object, long-to-int */
+    /* op vA, vB */
+    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
+    ubfx    r0, rINST, #8, #4           @ r0<- A from 11:8
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    GET_VREG(r2, r1)                    @ r2<- fp[B]
+    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
+    SET_VREG(r2, r0)                    @ fp[A]<- r2
+    GOTO_OPCODE(ip)                     @ execute next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MOVE_FROM16: /* 0x02 */
+/* File: armv5te/OP_MOVE_FROM16.S */
+    /* for: move/from16, move-object/from16 */
+    /* op vAA, vBBBB */
+    FETCH(r1, 1)                        @ r1<- BBBB
+    mov     r0, rINST, lsr #8           @ r0<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r2, r0)                    @ fp[AA]<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MOVE_16: /* 0x03 */
+/* File: armv5te/OP_MOVE_16.S */
+    /* for: move/16, move-object/16 */
+    /* op vAAAA, vBBBB */
+    FETCH(r1, 2)                        @ r1<- BBBB
+    FETCH(r0, 1)                        @ r0<- AAAA
+    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
+    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MOVE_WIDE: /* 0x04 */
+/* File: armv6t2/OP_MOVE_WIDE.S */
+    /* move-wide vA, vB */
+    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r2, rINST, #8, #4           @ r2<- A
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
+    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
+/* File: armv5te/OP_MOVE_WIDE_FROM16.S */
+    /* move-wide/from16 vAA, vBBBB */
+    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
+    FETCH(r3, 1)                        @ r3<- BBBB
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
+    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MOVE_WIDE_16: /* 0x06 */
+/* File: armv5te/OP_MOVE_WIDE_16.S */
+    /* move-wide/16 vAAAA, vBBBB */
+    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
+    FETCH(r3, 2)                        @ r3<- BBBB
+    FETCH(r2, 1)                        @ r2<- AAAA
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
+    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
+    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MOVE_OBJECT: /* 0x07 */
+/* File: armv5te/OP_MOVE_OBJECT.S */
+/* File: armv5te/OP_MOVE.S */
+    /* for move, move-object, long-to-int */
+    /* op vA, vB */
+    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
+    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    GET_VREG(r2, r1)                    @ r2<- fp[B]
+    and     r0, r0, #15
+    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
+    SET_VREG(r2, r0)                    @ fp[A]<- r2
+    GOTO_OPCODE(ip)                     @ execute next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
+/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
+/* File: armv5te/OP_MOVE_FROM16.S */
+    /* for: move/from16, move-object/from16 */
+    /* op vAA, vBBBB */
+    FETCH(r1, 1)                        @ r1<- BBBB
+    mov     r0, rINST, lsr #8           @ r0<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r2, r0)                    @ fp[AA]<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MOVE_OBJECT_16: /* 0x09 */
+/* File: armv5te/OP_MOVE_OBJECT_16.S */
+/* File: armv5te/OP_MOVE_16.S */
+    /* for: move/16, move-object/16 */
+    /* op vAAAA, vBBBB */
+    FETCH(r1, 2)                        @ r1<- BBBB
+    FETCH(r0, 1)                        @ r0<- AAAA
+    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
+    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MOVE_RESULT: /* 0x0a */
+/* File: armv5te/OP_MOVE_RESULT.S */
+    /* for: move-result, move-result-object */
+    /* op vAA */
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r2)                    @ fp[AA]<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
+/* File: armv5te/OP_MOVE_RESULT_WIDE.S */
+    /* move-result-wide vAA */
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
+    ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
+/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
+/* File: armv5te/OP_MOVE_RESULT.S */
+    /* for: move-result, move-result-object */
+    /* op vAA */
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r2)                    @ fp[AA]<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MOVE_EXCEPTION: /* 0x0d */
+/* File: armv5te/OP_MOVE_EXCEPTION.S */
+    /* move-exception vAA */
+    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
+    mov     r1, #0                      @ r1<- 0
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_RETURN_VOID: /* 0x0e */
+/* File: armv5te/OP_RETURN_VOID.S */
+    b       common_returnFromMethod
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_RETURN: /* 0x0f */
+/* File: armv5te/OP_RETURN.S */
+    /*
+     * Return a 32-bit value.  Copies the return value into the "glue"
+     * structure, then jumps to the return handler.
+     *
+     * for: return, return-object
+     */
+    /* op vAA */
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    GET_VREG(r0, r2)                    @ r0<- vAA
+    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
+    b       common_returnFromMethod
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_RETURN_WIDE: /* 0x10 */
+/* File: armv5te/OP_RETURN_WIDE.S */
+    /*
+     * Return a 64-bit value.  Copies the return value into the "glue"
+     * structure, then jumps to the return handler.
+     */
+    /* return-wide vAA */
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
+    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
+    ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
+    stmia   r3, {r0-r1}                 @ retval<- r0/r1
+    b       common_returnFromMethod
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_RETURN_OBJECT: /* 0x11 */
+/* File: armv5te/OP_RETURN_OBJECT.S */
+/* File: armv5te/OP_RETURN.S */
+    /*
+     * Return a 32-bit value.  Copies the return value into the "glue"
+     * structure, then jumps to the return handler.
+     *
+     * for: return, return-object
+     */
+    /* op vAA */
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    GET_VREG(r0, r2)                    @ r0<- vAA
+    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
+    b       common_returnFromMethod
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CONST_4: /* 0x12 */
+/* File: armv6t2/OP_CONST_4.S */
+    /* const/4 vA, #+B */
+    mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
+    ubfx    r0, rINST, #8, #4           @ r0<- A
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
+    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
+    SET_VREG(r1, r0)                    @ fp[A]<- r1
+    GOTO_OPCODE(ip)                     @ execute next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CONST_16: /* 0x13 */
+/* File: armv5te/OP_CONST_16.S */
+    /* const/16 vAA, #+BBBB */
+    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    SET_VREG(r0, r3)                    @ vAA<- r0
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CONST: /* 0x14 */
+/* File: armv5te/OP_CONST.S */
+    /* const vAA, #+BBBBbbbb */
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    FETCH(r0, 1)                        @ r0<- bbbb (low)
+    FETCH(r1, 2)                        @ r1<- BBBB (high)
+    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
+    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r3)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CONST_HIGH16: /* 0x15 */
+/* File: armv5te/OP_CONST_HIGH16.S */
+    /* const/high16 vAA, #+BBBB0000 */
+    FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    mov     r0, r0, lsl #16             @ r0<- BBBB0000
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    SET_VREG(r0, r3)                    @ vAA<- r0
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CONST_WIDE_16: /* 0x16 */
+/* File: armv5te/OP_CONST_WIDE_16.S */
+    /* const-wide/16 vAA, #+BBBB */
+    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    mov     r1, r0, asr #31             @ r1<- ssssssss
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CONST_WIDE_32: /* 0x17 */
+/* File: armv5te/OP_CONST_WIDE_32.S */
+    /* const-wide/32 vAA, #+BBBBbbbb */
+    FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
+    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
+    orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
+    mov     r1, r0, asr #31             @ r1<- ssssssss
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CONST_WIDE: /* 0x18 */
+/* File: armv5te/OP_CONST_WIDE.S */
+    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
+    FETCH(r0, 1)                        @ r0<- bbbb (low)
+    FETCH(r1, 2)                        @ r1<- BBBB (low middle)
+    FETCH(r2, 3)                        @ r2<- hhhh (high middle)
+    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
+    FETCH(r3, 4)                        @ r3<- HHHH (high)
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
+    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
+/* File: armv5te/OP_CONST_WIDE_HIGH16.S */
+    /* const-wide/high16 vAA, #+BBBB000000000000 */
+    FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    mov     r0, #0                      @ r0<- 00000000
+    mov     r1, r1, lsl #16             @ r1<- BBBB0000
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CONST_STRING: /* 0x1a */
+/* File: armv5te/OP_CONST_STRING.S */
+    /* const/string vAA, String@BBBB */
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
+    cmp     r0, #0                      @ not yet resolved?
+    beq     .LOP_CONST_STRING_resolve
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CONST_STRING_JUMBO: /* 0x1b */
+/* File: armv5te/OP_CONST_STRING_JUMBO.S */
+    /* const/string vAA, String@BBBBBBBB */
+    FETCH(r0, 1)                        @ r0<- bbbb (low)
+    FETCH(r1, 2)                        @ r1<- BBBB (high)
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
+    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
+    cmp     r0, #0
+    beq     .LOP_CONST_STRING_JUMBO_resolve
+    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CONST_CLASS: /* 0x1c */
+/* File: armv5te/OP_CONST_CLASS.S */
+    /* const/class vAA, Class@BBBB */
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
+    cmp     r0, #0                      @ not yet resolved?
+    beq     .LOP_CONST_CLASS_resolve
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MONITOR_ENTER: /* 0x1d */
+/* File: armv5te/OP_MONITOR_ENTER.S */
+    /*
+     * Synchronize on an object.
+     */
+    /* monitor-enter vAA */
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    GET_VREG(r1, r2)                    @ r1<- vAA (object)
+    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
+    cmp     r1, #0                      @ null object?
+    EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
+    beq     common_errNullObject        @ null object, throw an exception
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    bl      dvmLockObject               @ call(self, obj)
+#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
+    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
+    ldr     r1, [r0, #offThread_exception] @ check for exception
+    cmp     r1, #0
+    bne     common_exceptionThrown      @ exception raised, bail out
+#endif
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MONITOR_EXIT: /* 0x1e */
+/* File: armv5te/OP_MONITOR_EXIT.S */
+    /*
+     * Unlock an object.
+     *
+     * Exceptions that occur when unlocking a monitor need to appear as
+     * if they happened at the following instruction.  See the Dalvik
+     * instruction spec.
+     */
+    /* monitor-exit vAA */
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    EXPORT_PC()                         @ before fetch: export the PC
+    GET_VREG(r1, r2)                    @ r1<- vAA (object)
+    cmp     r1, #0                      @ null object?
+    beq     common_errNullObject        @ yes
+    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
+    bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
+    cmp     r0, #0                      @ failed?
+    beq     common_exceptionThrown      @ yes, exception is pending
+    FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CHECK_CAST: /* 0x1f */
+/* File: armv5te/OP_CHECK_CAST.S */
+    /*
+     * Check to see if a cast from one class to another is allowed.
+     */
+    /* check-cast vAA, class@BBBB */
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    FETCH(r2, 1)                        @ r2<- BBBB
+    GET_VREG(r9, r3)                    @ r9<- object
+    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
+    cmp     r9, #0                      @ is object null?
+    ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
+    beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
+    ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
+    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
+    cmp     r1, #0                      @ have we resolved this before?
+    beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
+.LOP_CHECK_CAST_resolved:
+    cmp     r0, r1                      @ same class (trivial success)?
+    bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
+.LOP_CHECK_CAST_okay:
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INSTANCE_OF: /* 0x20 */
+/* File: armv5te/OP_INSTANCE_OF.S */
+    /*
+     * Check to see if an object reference is an instance of a class.
+     *
+     * Most common situation is a non-null object, being compared against
+     * an already-resolved class.
+     */
+    /* instance-of vA, vB, class@CCCC */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    GET_VREG(r0, r3)                    @ r0<- vB (object)
+    and     r9, r9, #15                 @ r9<- A
+    cmp     r0, #0                      @ is object null?
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
+    beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
+    FETCH(r3, 1)                        @ r3<- CCCC
+    ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
+    ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
+    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
+    cmp     r1, #0                      @ have we resolved this before?
+    beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
+.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
+    cmp     r0, r1                      @ same class (trivial success)?
+    beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
+    b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_ARRAY_LENGTH: /* 0x21 */
+/* File: armv6t2/OP_ARRAY_LENGTH.S */
+    /*
+     * Return the length of an array.
+     */
+    mov     r1, rINST, lsr #12          @ r1<- B
+    ubfx    r2, rINST, #8, #4           @ r2<- A
+    GET_VREG(r0, r1)                    @ r0<- vB (object ref)
+    cmp     r0, #0                      @ is object null?
+    beq     common_errNullObject        @ yup, fail
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r3, r2)                    @ vB<- length
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_NEW_INSTANCE: /* 0x22 */
+/* File: armv5te/OP_NEW_INSTANCE.S */
+    /*
+     * Create a new instance of a class.
+     */
+    /* new-instance vAA, class@BBBB */
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
+    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
+    EXPORT_PC()                         @ req'd for init, resolve, alloc
+    cmp     r0, #0                      @ already resolved?
+    beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
+.LOP_NEW_INSTANCE_resolved:   @ r0=class
+    ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
+    cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
+    bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
+.LOP_NEW_INSTANCE_initialized: @ r0=class
+    mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
+    bl      dvmAllocObject              @ r0<- new object
+    b       .LOP_NEW_INSTANCE_finish          @ continue
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_NEW_ARRAY: /* 0x23 */
+/* File: armv5te/OP_NEW_ARRAY.S */
+    /*
+     * Allocate an array of objects, specified with the array class
+     * and a count.
+     *
+     * The verifier guarantees that this is an array class, so we don't
+     * check for it here.
+     */
+    /* new-array vA, vB, class@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    FETCH(r2, 1)                        @ r2<- CCCC
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
+    GET_VREG(r1, r0)                    @ r1<- vB (array length)
+    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
+    cmp     r1, #0                      @ check length
+    ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
+    bmi     common_errNegativeArraySize @ negative length, bail
+    cmp     r0, #0                      @ already resolved?
+    EXPORT_PC()                         @ req'd for resolve, alloc
+    bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
+    b       .LOP_NEW_ARRAY_resolve         @ do resolve now
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
+/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
+    /*
+     * Create a new array with elements filled from registers.
+     *
+     * for: filled-new-array, filled-new-array/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
+    EXPORT_PC()                         @ need for resolve and alloc
+    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
+    mov     r10, rINST, lsr #8          @ r10<- AA or BA
+    cmp     r0, #0                      @ already resolved?
+    bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
+8:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
+    mov     r2, #0                      @ r2<- false
+    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveClass             @ r0<- call(clazz, ref)
+    cmp     r0, #0                      @ got null?
+    beq     common_exceptionThrown      @ yes, handle exception
+    b       .LOP_FILLED_NEW_ARRAY_continue
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
+/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
+/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
+    /*
+     * Create a new array with elements filled from registers.
+     *
+     * for: filled-new-array, filled-new-array/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
+    EXPORT_PC()                         @ need for resolve and alloc
+    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
+    mov     r10, rINST, lsr #8          @ r10<- AA or BA
+    cmp     r0, #0                      @ already resolved?
+    bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
+8:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
+    mov     r2, #0                      @ r2<- false
+    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveClass             @ r0<- call(clazz, ref)
+    cmp     r0, #0                      @ got null?
+    beq     common_exceptionThrown      @ yes, handle exception
+    b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_FILL_ARRAY_DATA: /* 0x26 */
+/* File: armv5te/OP_FILL_ARRAY_DATA.S */
+    /* fill-array-data vAA, +BBBBBBBB */
+    FETCH(r0, 1)                        @ r0<- bbbb (lo)
+    FETCH(r1, 2)                        @ r1<- BBBB (hi)
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
+    GET_VREG(r0, r3)                    @ r0<- vAA (array object)
+    add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
+    EXPORT_PC();
+    bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
+    cmp     r0, #0                      @ 0 means an exception is thrown
+    beq     common_exceptionThrown      @ has exception
+    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_THROW: /* 0x27 */
+/* File: armv5te/OP_THROW.S */
+    /*
+     * Throw an exception object in the current thread.
+     */
+    /* throw vAA */
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
+    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
+    cmp     r1, #0                      @ null object?
+    beq     common_errNullObject        @ yes, throw an NPE instead
+    @ bypass dvmSetException, just store it
+    str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
+    b       common_exceptionThrown
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_GOTO: /* 0x28 */
+/* File: armv5te/OP_GOTO.S */
+    /*
+     * Unconditional branch, 8-bit offset.
+     *
+     * The branch distance is a signed code-unit offset, which we need to
+     * double to get a byte offset.
+     */
+    /* goto +AA */
+    mov     r0, rINST, lsl #16          @ r0<- AAxx0000
+    movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
+    mov     r9, r9, lsl #1              @ r9<- byte offset
+    bmi     common_backwardBranch       @ backward branch, do periodic checks
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_GOTO_16: /* 0x29 */
+/* File: armv5te/OP_GOTO_16.S */
+    /*
+     * Unconditional branch, 16-bit offset.
+     *
+     * The branch distance is a signed code-unit offset, which we need to
+     * double to get a byte offset.
+     */
+    /* goto/16 +AAAA */
+    FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
+    movs    r9, r0, asl #1              @ r9<- byte offset, check sign
+    bmi     common_backwardBranch       @ backward branch, do periodic checks
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_GOTO_32: /* 0x2a */
+/* File: armv5te/OP_GOTO_32.S */
+    /*
+     * Unconditional branch, 32-bit offset.
+     *
+     * The branch distance is a signed code-unit offset, which we need to
+     * double to get a byte offset.
+     *
+     * Unlike most opcodes, this one is allowed to branch to itself, so
+     * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
+     * instruction doesn't affect the V flag, so we need to clear it
+     * explicitly.
+     */
+    /* goto/32 +AAAAAAAA */
+    FETCH(r0, 1)                        @ r0<- aaaa (lo)
+    FETCH(r1, 2)                        @ r1<- AAAA (hi)
+    cmp     ip, ip                      @ (clear V flag during stall)
+    orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
+    mov     r9, r0, asl #1              @ r9<- byte offset
+    ble     common_backwardBranch       @ backward branch, do periodic checks
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_PACKED_SWITCH: /* 0x2b */
+/* File: armv5te/OP_PACKED_SWITCH.S */
+    /*
+     * Handle a packed-switch or sparse-switch instruction.  In both cases
+     * we decode it and hand it off to a helper function.
+     *
+     * We don't really expect backward branches in a switch statement, but
+     * they're perfectly legal, so we check for them here.
+     *
+     * for: packed-switch, sparse-switch
+     */
+    /* op vAA, +BBBB */
+    FETCH(r0, 1)                        @ r0<- bbbb (lo)
+    FETCH(r1, 2)                        @ r1<- BBBB (hi)
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
+    GET_VREG(r1, r3)                    @ r1<- vAA
+    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
+    bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
+    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
+    bmi     common_backwardBranch       @ backward branch, do periodic checks
+    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SPARSE_SWITCH: /* 0x2c */
+/* File: armv5te/OP_SPARSE_SWITCH.S */
+/* File: armv5te/OP_PACKED_SWITCH.S */
+    /*
+     * Handle a packed-switch or sparse-switch instruction.  In both cases
+     * we decode it and hand it off to a helper function.
+     *
+     * We don't really expect backward branches in a switch statement, but
+     * they're perfectly legal, so we check for them here.
+     *
+     * for: packed-switch, sparse-switch
+     */
+    /* op vAA, +BBBB */
+    FETCH(r0, 1)                        @ r0<- bbbb (lo)
+    FETCH(r1, 2)                        @ r1<- BBBB (hi)
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
+    GET_VREG(r1, r3)                    @ r1<- vAA
+    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
+    bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
+    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
+    bmi     common_backwardBranch       @ backward branch, do periodic checks
+    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CMPL_FLOAT: /* 0x2d */
+/* File: arm-vfp/OP_CMPL_FLOAT.S */
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else {
+     *         return -1;
+     *     }
+     * }
+     */
+    /* op vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    flds    s0, [r2]                    @ s0<- vBB
+    flds    s1, [r3]                    @ s1<- vCC
+    fcmpes  s0, s1                      @ compare (vBB, vCC)
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    mvn     r0, #0                      @ r0<- -1 (default)
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fmstat                              @ export status flags
+    movgt   r0, #1                      @ (greater than) r1<- 1
+    moveq   r0, #0                      @ (equal) r1<- 0
+    b       .LOP_CMPL_FLOAT_finish          @ argh
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CMPG_FLOAT: /* 0x2e */
+/* File: arm-vfp/OP_CMPG_FLOAT.S */
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else {
+     *         return 1;
+     *     }
+     * }
+     */
+    /* op vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    flds    s0, [r2]                    @ s0<- vBB
+    flds    s1, [r3]                    @ s1<- vCC
+    fcmpes  s0, s1                      @ compare (vBB, vCC)
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    mov     r0, #1                      @ r0<- 1 (default)
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fmstat                              @ export status flags
+    mvnmi   r0, #0                      @ (less than) r1<- -1
+    moveq   r0, #0                      @ (equal) r1<- 0
+    b       .LOP_CMPG_FLOAT_finish          @ argh
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CMPL_DOUBLE: /* 0x2f */
+/* File: arm-vfp/OP_CMPL_DOUBLE.S */
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else {
+     *         return -1;
+     *     }
+     * }
+     */
+    /* op vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    fldd    d0, [r2]                    @ d0<- vBB
+    fldd    d1, [r3]                    @ d1<- vCC
+    fcmped  d0, d1                      @ compare (vBB, vCC)
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    mvn     r0, #0                      @ r0<- -1 (default)
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fmstat                              @ export status flags
+    movgt   r0, #1                      @ (greater than) r1<- 1
+    moveq   r0, #0                      @ (equal) r1<- 0
+    b       .LOP_CMPL_DOUBLE_finish          @ argh
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CMPG_DOUBLE: /* 0x30 */
+/* File: arm-vfp/OP_CMPG_DOUBLE.S */
+    /*
+     * Compare two floating-point values.  Puts 0, 1, or -1 into the
+     * destination register based on the results of the comparison.
+     *
+     * int compare(x, y) {
+     *     if (x == y) {
+     *         return 0;
+     *     } else if (x < y) {
+     *         return -1;
+     *     } else if (x > y) {
+     *         return 1;
+     *     } else {
+     *         return 1;
+     *     }
+     * }
+     */
+    /* op vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    fldd    d0, [r2]                    @ d0<- vBB
+    fldd    d1, [r3]                    @ d1<- vCC
+    fcmped  d0, d1                      @ compare (vBB, vCC)
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    mov     r0, #1                      @ r0<- 1 (default)
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fmstat                              @ export status flags
+    mvnmi   r0, #0                      @ (less than) r1<- -1
+    moveq   r0, #0                      @ (equal) r1<- 0
+    b       .LOP_CMPG_DOUBLE_finish          @ argh
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_CMP_LONG: /* 0x31 */
+/* File: armv5te/OP_CMP_LONG.S */
+    /*
+     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
+     * register based on the results of the comparison.
+     *
+     * We load the full values with LDM, but in practice many values could
+     * be resolved by only looking at the high word.  This could be made
+     * faster or slower by splitting the LDM into a pair of LDRs.
+     *
+     * If we just wanted to set condition flags, we could do this:
+     *  subs    ip, r0, r2
+     *  sbcs    ip, r1, r3
+     *  subeqs  ip, r0, r2
+     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
+     * integer value, which we can do with 2 conditional mov/mvn instructions
+     * (set 1, set -1; if they're equal we already have 0 in ip), giving
+     * us a constant 5-cycle path plus a branch at the end to the
+     * instruction epilogue code.  The multi-compare approach below needs
+     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
+     * in the worst case (the 64-bit values are equal).
+     */
+    /* cmp-long vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
+    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
+    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
+    blt     .LOP_CMP_LONG_less            @ signed compare on high part
+    bgt     .LOP_CMP_LONG_greater
+    subs    r1, r0, r2                  @ r1<- r0 - r2
+    bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
+    bne     .LOP_CMP_LONG_less
+    b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IF_EQ: /* 0x32 */
+/* File: armv6t2/OP_IF_EQ.S */
+/* File: armv6t2/bincmp.S */
+    /*
+     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
+     * fragment that specifies the *reverse* comparison to perform, e.g.
+     * for "if-le" you would use "gt".
+     *
+     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+     */
+    /* if-cmp vA, vB, +CCCC */
+    mov     r1, rINST, lsr #12          @ r1<- B
+    ubfx    r0, rINST, #8, #4           @ r0<- A
+    GET_VREG(r3, r1)                    @ r3<- vB
+    GET_VREG(r2, r0)                    @ r2<- vA
+    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
+    cmp     r2, r3                      @ compare (vA, vB)
+    bne  1f                      @ branch to 1 if comparison failed
+    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
+    movs    r9, r9, asl #1              @ convert to bytes, check sign
+    bmi     common_backwardBranch       @ yes, do periodic checks
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    b        common_testUpdateProfile
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IF_NE: /* 0x33 */
+/* File: armv6t2/OP_IF_NE.S */
+/* File: armv6t2/bincmp.S */
+    /*
+     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
+     * fragment that specifies the *reverse* comparison to perform, e.g.
+     * for "if-le" you would use "gt".
+     *
+     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+     */
+    /* if-cmp vA, vB, +CCCC */
+    mov     r1, rINST, lsr #12          @ r1<- B
+    ubfx    r0, rINST, #8, #4           @ r0<- A
+    GET_VREG(r3, r1)                    @ r3<- vB
+    GET_VREG(r2, r0)                    @ r2<- vA
+    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
+    cmp     r2, r3                      @ compare (vA, vB)
+    beq  1f                      @ branch to 1 if comparison failed
+    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
+    movs    r9, r9, asl #1              @ convert to bytes, check sign
+    bmi     common_backwardBranch       @ yes, do periodic checks
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    b        common_testUpdateProfile
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IF_LT: /* 0x34 */
+/* File: armv6t2/OP_IF_LT.S */
+/* File: armv6t2/bincmp.S */
+    /*
+     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
+     * fragment that specifies the *reverse* comparison to perform, e.g.
+     * for "if-le" you would use "gt".
+     *
+     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+     */
+    /* if-cmp vA, vB, +CCCC */
+    mov     r1, rINST, lsr #12          @ r1<- B
+    ubfx    r0, rINST, #8, #4           @ r0<- A
+    GET_VREG(r3, r1)                    @ r3<- vB
+    GET_VREG(r2, r0)                    @ r2<- vA
+    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
+    cmp     r2, r3                      @ compare (vA, vB)
+    bge  1f                      @ branch to 1 if comparison failed
+    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
+    movs    r9, r9, asl #1              @ convert to bytes, check sign
+    bmi     common_backwardBranch       @ yes, do periodic checks
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    b        common_testUpdateProfile
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IF_GE: /* 0x35 */
+/* File: armv6t2/OP_IF_GE.S */
+/* File: armv6t2/bincmp.S */
+    /*
+     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
+     * fragment that specifies the *reverse* comparison to perform, e.g.
+     * for "if-le" you would use "gt".
+     *
+     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+     */
+    /* if-cmp vA, vB, +CCCC */
+    mov     r1, rINST, lsr #12          @ r1<- B
+    ubfx    r0, rINST, #8, #4           @ r0<- A
+    GET_VREG(r3, r1)                    @ r3<- vB
+    GET_VREG(r2, r0)                    @ r2<- vA
+    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
+    cmp     r2, r3                      @ compare (vA, vB)
+    blt  1f                      @ branch to 1 if comparison failed
+    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
+    movs    r9, r9, asl #1              @ convert to bytes, check sign
+    bmi     common_backwardBranch       @ yes, do periodic checks
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    b        common_testUpdateProfile
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IF_GT: /* 0x36 */
+/* File: armv6t2/OP_IF_GT.S */
+/* File: armv6t2/bincmp.S */
+    /*
+     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
+     * fragment that specifies the *reverse* comparison to perform, e.g.
+     * for "if-le" you would use "gt".
+     *
+     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+     */
+    /* if-cmp vA, vB, +CCCC */
+    mov     r1, rINST, lsr #12          @ r1<- B
+    ubfx    r0, rINST, #8, #4           @ r0<- A
+    GET_VREG(r3, r1)                    @ r3<- vB
+    GET_VREG(r2, r0)                    @ r2<- vA
+    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
+    cmp     r2, r3                      @ compare (vA, vB)
+    ble  1f                      @ branch to 1 if comparison failed
+    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
+    movs    r9, r9, asl #1              @ convert to bytes, check sign
+    bmi     common_backwardBranch       @ yes, do periodic checks
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    b        common_testUpdateProfile
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IF_LE: /* 0x37 */
+/* File: armv6t2/OP_IF_LE.S */
+/* File: armv6t2/bincmp.S */
+    /*
+     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
+     * fragment that specifies the *reverse* comparison to perform, e.g.
+     * for "if-le" you would use "gt".
+     *
+     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
+     */
+    /* if-cmp vA, vB, +CCCC */
+    mov     r1, rINST, lsr #12          @ r1<- B
+    ubfx    r0, rINST, #8, #4           @ r0<- A
+    GET_VREG(r3, r1)                    @ r3<- vB
+    GET_VREG(r2, r0)                    @ r2<- vA
+    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
+    cmp     r2, r3                      @ compare (vA, vB)
+    bgt  1f                      @ branch to 1 if comparison failed
+    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
+    movs    r9, r9, asl #1              @ convert to bytes, check sign
+    bmi     common_backwardBranch       @ yes, do periodic checks
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    b        common_testUpdateProfile
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IF_EQZ: /* 0x38 */
+/* File: armv5te/OP_IF_EQZ.S */
+/* File: armv5te/zcmp.S */
+    /*
+     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
+     * fragment that specifies the *reverse* comparison to perform, e.g.
+     * for "if-le" you would use "gt".
+     *
+     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+     */
+    /* if-cmp vAA, +BBBB */
+    mov     r0, rINST, lsr #8           @ r0<- AA
+    GET_VREG(r2, r0)                    @ r2<- vAA
+    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
+    cmp     r2, #0                      @ compare (vA, 0)
+    bne  1f                      @ branch to 1 if comparison failed
+    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
+    movs    r9, r9, asl #1              @ convert to bytes, check sign
+    bmi     common_backwardBranch       @ backward branch, do periodic checks
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IF_NEZ: /* 0x39 */
+/* File: armv5te/OP_IF_NEZ.S */
+/* File: armv5te/zcmp.S */
+    /*
+     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
+     * fragment that specifies the *reverse* comparison to perform, e.g.
+     * for "if-le" you would use "gt".
+     *
+     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+     */
+    /* if-cmp vAA, +BBBB */
+    mov     r0, rINST, lsr #8           @ r0<- AA
+    GET_VREG(r2, r0)                    @ r2<- vAA
+    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
+    cmp     r2, #0                      @ compare (vA, 0)
+    beq  1f                      @ branch to 1 if comparison failed
+    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
+    movs    r9, r9, asl #1              @ convert to bytes, check sign
+    bmi     common_backwardBranch       @ backward branch, do periodic checks
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IF_LTZ: /* 0x3a */
+/* File: armv5te/OP_IF_LTZ.S */
+/* File: armv5te/zcmp.S */
+    /*
+     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
+     * fragment that specifies the *reverse* comparison to perform, e.g.
+     * for "if-le" you would use "gt".
+     *
+     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+     */
+    /* if-cmp vAA, +BBBB */
+    mov     r0, rINST, lsr #8           @ r0<- AA
+    GET_VREG(r2, r0)                    @ r2<- vAA
+    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
+    cmp     r2, #0                      @ compare (vA, 0)
+    bge  1f                      @ branch to 1 if comparison failed
+    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
+    movs    r9, r9, asl #1              @ convert to bytes, check sign
+    bmi     common_backwardBranch       @ backward branch, do periodic checks
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IF_GEZ: /* 0x3b */
+/* File: armv5te/OP_IF_GEZ.S */
+/* File: armv5te/zcmp.S */
+    /*
+     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
+     * fragment that specifies the *reverse* comparison to perform, e.g.
+     * for "if-le" you would use "gt".
+     *
+     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+     */
+    /* if-cmp vAA, +BBBB */
+    mov     r0, rINST, lsr #8           @ r0<- AA
+    GET_VREG(r2, r0)                    @ r2<- vAA
+    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
+    cmp     r2, #0                      @ compare (vA, 0)
+    blt  1f                      @ branch to 1 if comparison failed
+    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
+    movs    r9, r9, asl #1              @ convert to bytes, check sign
+    bmi     common_backwardBranch       @ backward branch, do periodic checks
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IF_GTZ: /* 0x3c */
+/* File: armv5te/OP_IF_GTZ.S */
+/* File: armv5te/zcmp.S */
+    /*
+     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
+     * fragment that specifies the *reverse* comparison to perform, e.g.
+     * for "if-le" you would use "gt".
+     *
+     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+     */
+    /* if-cmp vAA, +BBBB */
+    mov     r0, rINST, lsr #8           @ r0<- AA
+    GET_VREG(r2, r0)                    @ r2<- vAA
+    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
+    cmp     r2, #0                      @ compare (vA, 0)
+    ble  1f                      @ branch to 1 if comparison failed
+    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
+    movs    r9, r9, asl #1              @ convert to bytes, check sign
+    bmi     common_backwardBranch       @ backward branch, do periodic checks
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IF_LEZ: /* 0x3d */
+/* File: armv5te/OP_IF_LEZ.S */
+/* File: armv5te/zcmp.S */
+    /*
+     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
+     * fragment that specifies the *reverse* comparison to perform, e.g.
+     * for "if-le" you would use "gt".
+     *
+     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
+     */
+    /* if-cmp vAA, +BBBB */
+    mov     r0, rINST, lsr #8           @ r0<- AA
+    GET_VREG(r2, r0)                    @ r2<- vAA
+    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
+    cmp     r2, #0                      @ compare (vA, 0)
+    bgt  1f                      @ branch to 1 if comparison failed
+    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
+    movs    r9, r9, asl #1              @ convert to bytes, check sign
+    bmi     common_backwardBranch       @ backward branch, do periodic checks
+1:
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_3E: /* 0x3e */
+/* File: armv5te/OP_UNUSED_3E.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_3F: /* 0x3f */
+/* File: armv5te/OP_UNUSED_3F.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_40: /* 0x40 */
+/* File: armv5te/OP_UNUSED_40.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_41: /* 0x41 */
+/* File: armv5te/OP_UNUSED_41.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_42: /* 0x42 */
+/* File: armv5te/OP_UNUSED_42.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_43: /* 0x43 */
+/* File: armv5te/OP_UNUSED_43.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_AGET: /* 0x44 */
+/* File: armv5te/OP_AGET.S */
+    /*
+     * Array get, 32 bits or less.  vAA <- vBB[vCC].
+     *
+     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+     * instructions.  We use a pair of FETCH_Bs instead.
+     *
+     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
+     */
+    /* op vAA, vBB, vCC */
+    FETCH_B(r2, 1, 0)                   @ r2<- BB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    FETCH_B(r3, 1, 1)                   @ r3<- CC
+    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
+    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
+    cmp     r1, r3                      @ compare unsigned index, length
+    bcs     common_errArrayIndex        @ index >= length, bail
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r2, r9)                    @ vAA<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_AGET_WIDE: /* 0x45 */
+/* File: armv5te/OP_AGET_WIDE.S */
+    /*
+     * Array get, 64 bits.  vAA <- vBB[vCC].
+     *
+     * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
+     */
+    /* aget-wide vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
+    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
+    cmp     r1, r3                      @ compare unsigned index, length
+    bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
+    b       common_errArrayIndex        @ index >= length, bail
+    @ May want to swap the order of these two branches depending on how the
+    @ branch prediction (if any) handles conditional forward branches vs.
+    @ unconditional forward branches.
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_AGET_OBJECT: /* 0x46 */
+/* File: armv5te/OP_AGET_OBJECT.S */
+/* File: armv5te/OP_AGET.S */
+    /*
+     * Array get, 32 bits or less.  vAA <- vBB[vCC].
+     *
+     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+     * instructions.  We use a pair of FETCH_Bs instead.
+     *
+     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
+     */
+    /* op vAA, vBB, vCC */
+    FETCH_B(r2, 1, 0)                   @ r2<- BB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    FETCH_B(r3, 1, 1)                   @ r3<- CC
+    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
+    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
+    cmp     r1, r3                      @ compare unsigned index, length
+    bcs     common_errArrayIndex        @ index >= length, bail
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r2, r9)                    @ vAA<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_AGET_BOOLEAN: /* 0x47 */
+/* File: armv5te/OP_AGET_BOOLEAN.S */
+/* File: armv5te/OP_AGET.S */
+    /*
+     * Array get, 32 bits or less.  vAA <- vBB[vCC].
+     *
+     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+     * instructions.  We use a pair of FETCH_Bs instead.
+     *
+     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
+     */
+    /* op vAA, vBB, vCC */
+    FETCH_B(r2, 1, 0)                   @ r2<- BB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    FETCH_B(r3, 1, 1)                   @ r3<- CC
+    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
+    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
+    cmp     r1, r3                      @ compare unsigned index, length
+    bcs     common_errArrayIndex        @ index >= length, bail
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r2, r9)                    @ vAA<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_AGET_BYTE: /* 0x48 */
+/* File: armv5te/OP_AGET_BYTE.S */
+/* File: armv5te/OP_AGET.S */
+    /*
+     * Array get, 32 bits or less.  vAA <- vBB[vCC].
+     *
+     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+     * instructions.  We use a pair of FETCH_Bs instead.
+     *
+     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
+     */
+    /* op vAA, vBB, vCC */
+    FETCH_B(r2, 1, 0)                   @ r2<- BB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    FETCH_B(r3, 1, 1)                   @ r3<- CC
+    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
+    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
+    cmp     r1, r3                      @ compare unsigned index, length
+    bcs     common_errArrayIndex        @ index >= length, bail
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r2, r9)                    @ vAA<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_AGET_CHAR: /* 0x49 */
+/* File: armv5te/OP_AGET_CHAR.S */
+/* File: armv5te/OP_AGET.S */
+    /*
+     * Array get, 32 bits or less.  vAA <- vBB[vCC].
+     *
+     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+     * instructions.  We use a pair of FETCH_Bs instead.
+     *
+     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
+     */
+    /* op vAA, vBB, vCC */
+    FETCH_B(r2, 1, 0)                   @ r2<- BB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    FETCH_B(r3, 1, 1)                   @ r3<- CC
+    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
+    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
+    cmp     r1, r3                      @ compare unsigned index, length
+    bcs     common_errArrayIndex        @ index >= length, bail
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r2, r9)                    @ vAA<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_AGET_SHORT: /* 0x4a */
+/* File: armv5te/OP_AGET_SHORT.S */
+/* File: armv5te/OP_AGET.S */
+    /*
+     * Array get, 32 bits or less.  vAA <- vBB[vCC].
+     *
+     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+     * instructions.  We use a pair of FETCH_Bs instead.
+     *
+     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
+     */
+    /* op vAA, vBB, vCC */
+    FETCH_B(r2, 1, 0)                   @ r2<- BB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    FETCH_B(r3, 1, 1)                   @ r3<- CC
+    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
+    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
+    cmp     r1, r3                      @ compare unsigned index, length
+    bcs     common_errArrayIndex        @ index >= length, bail
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r2, r9)                    @ vAA<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_APUT: /* 0x4b */
+/* File: armv5te/OP_APUT.S */
+    /*
+     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
+     *
+     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+     * instructions.  We use a pair of FETCH_Bs instead.
+     *
+     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
+     */
+    /* op vAA, vBB, vCC */
+    FETCH_B(r2, 1, 0)                   @ r2<- BB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    FETCH_B(r3, 1, 1)                   @ r3<- CC
+    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
+    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
+    cmp     r1, r3                      @ compare unsigned index, length
+    bcs     common_errArrayIndex        @ index >= length, bail
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_VREG(r2, r9)                    @ r2<- vAA
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_APUT_WIDE: /* 0x4c */
+/* File: armv5te/OP_APUT_WIDE.S */
+    /*
+     * Array put, 64 bits.  vBB[vCC] <- vAA.
+     *
+     * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
+     */
+    /* aput-wide vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
+    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
+    cmp     r1, r3                      @ compare unsigned index, length
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+    bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
+    b       common_errArrayIndex        @ index >= length, bail
+    @ May want to swap the order of these two branches depending on how the
+    @ branch prediction (if any) handles conditional forward branches vs.
+    @ unconditional forward branches.
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_APUT_OBJECT: /* 0x4d */
+/* File: armv5te/OP_APUT_OBJECT.S */
+    /*
+     * Store an object into an array.  vBB[vCC] <- vAA.
+     *
+     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+     * instructions.  We use a pair of FETCH_Bs instead.
+     */
+    /* op vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    GET_VREG(r1, r2)                    @ r1<- vBB (array object)
+    GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
+    cmp     r1, #0                      @ null array object?
+    GET_VREG(r9, r9)                    @ r9<- vAA
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
+    cmp     r0, r3                      @ compare unsigned index, length
+    bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
+    b       common_errArrayIndex        @ index >= length, bail
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_APUT_BOOLEAN: /* 0x4e */
+/* File: armv5te/OP_APUT_BOOLEAN.S */
+/* File: armv5te/OP_APUT.S */
+    /*
+     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
+     *
+     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+     * instructions.  We use a pair of FETCH_Bs instead.
+     *
+     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
+     */
+    /* op vAA, vBB, vCC */
+    FETCH_B(r2, 1, 0)                   @ r2<- BB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    FETCH_B(r3, 1, 1)                   @ r3<- CC
+    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
+    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
+    cmp     r1, r3                      @ compare unsigned index, length
+    bcs     common_errArrayIndex        @ index >= length, bail
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_VREG(r2, r9)                    @ r2<- vAA
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_APUT_BYTE: /* 0x4f */
+/* File: armv5te/OP_APUT_BYTE.S */
+/* File: armv5te/OP_APUT.S */
+    /*
+     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
+     *
+     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+     * instructions.  We use a pair of FETCH_Bs instead.
+     *
+     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
+     */
+    /* op vAA, vBB, vCC */
+    FETCH_B(r2, 1, 0)                   @ r2<- BB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    FETCH_B(r3, 1, 1)                   @ r3<- CC
+    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
+    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
+    cmp     r1, r3                      @ compare unsigned index, length
+    bcs     common_errArrayIndex        @ index >= length, bail
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_VREG(r2, r9)                    @ r2<- vAA
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_APUT_CHAR: /* 0x50 */
+/* File: armv5te/OP_APUT_CHAR.S */
+/* File: armv5te/OP_APUT.S */
+    /*
+     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
+     *
+     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+     * instructions.  We use a pair of FETCH_Bs instead.
+     *
+     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
+     */
+    /* op vAA, vBB, vCC */
+    FETCH_B(r2, 1, 0)                   @ r2<- BB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    FETCH_B(r3, 1, 1)                   @ r3<- CC
+    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
+    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
+    cmp     r1, r3                      @ compare unsigned index, length
+    bcs     common_errArrayIndex        @ index >= length, bail
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_VREG(r2, r9)                    @ r2<- vAA
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_APUT_SHORT: /* 0x51 */
+/* File: armv5te/OP_APUT_SHORT.S */
+/* File: armv5te/OP_APUT.S */
+    /*
+     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
+     *
+     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
+     * instructions.  We use a pair of FETCH_Bs instead.
+     *
+     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
+     */
+    /* op vAA, vBB, vCC */
+    FETCH_B(r2, 1, 0)                   @ r2<- BB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    FETCH_B(r3, 1, 1)                   @ r3<- CC
+    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
+    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
+    cmp     r0, #0                      @ null array object?
+    beq     common_errNullObject        @ yes, bail
+    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
+    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
+    cmp     r1, r3                      @ compare unsigned index, length
+    bcs     common_errArrayIndex        @ index >= length, bail
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_VREG(r2, r9)                    @ r2<- vAA
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IGET: /* 0x52 */
+/* File: armv6t2/OP_IGET.S */
+    /*
+     * General 32-bit instance field get.
+     *
+     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
+     */
+    /* op vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IGET_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0
+    bne     .LOP_IGET_finish
+    b       common_exceptionThrown
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IGET_WIDE: /* 0x53 */
+/* File: armv6t2/OP_IGET_WIDE.S */
+    /*
+     * Wide 32-bit instance field get.
+     */
+    /* iget-wide vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IGET_WIDE_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0
+    bne     .LOP_IGET_WIDE_finish
+    b       common_exceptionThrown
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IGET_OBJECT: /* 0x54 */
+/* File: armv5te/OP_IGET_OBJECT.S */
+/* File: armv5te/OP_IGET.S */
+    /*
+     * General 32-bit instance field get.
+     *
+     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
+     */
+    /* op vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0
+    bne     .LOP_IGET_OBJECT_finish
+    b       common_exceptionThrown
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IGET_BOOLEAN: /* 0x55 */
+/* File: armv5te/OP_IGET_BOOLEAN.S */
+@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
+/* File: armv5te/OP_IGET.S */
+    /*
+     * General 32-bit instance field get.
+     *
+     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
+     */
+    /* op vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0
+    bne     .LOP_IGET_BOOLEAN_finish
+    b       common_exceptionThrown
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IGET_BYTE: /* 0x56 */
+/* File: armv5te/OP_IGET_BYTE.S */
+@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
+/* File: armv5te/OP_IGET.S */
+    /*
+     * General 32-bit instance field get.
+     *
+     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
+     */
+    /* op vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IGET_BYTE_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0
+    bne     .LOP_IGET_BYTE_finish
+    b       common_exceptionThrown
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IGET_CHAR: /* 0x57 */
+/* File: armv5te/OP_IGET_CHAR.S */
+@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
+/* File: armv5te/OP_IGET.S */
+    /*
+     * General 32-bit instance field get.
+     *
+     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
+     */
+    /* op vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IGET_CHAR_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0
+    bne     .LOP_IGET_CHAR_finish
+    b       common_exceptionThrown
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IGET_SHORT: /* 0x58 */
+/* File: armv5te/OP_IGET_SHORT.S */
+@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
+/* File: armv5te/OP_IGET.S */
+    /*
+     * General 32-bit instance field get.
+     *
+     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
+     */
+    /* op vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IGET_SHORT_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0
+    bne     .LOP_IGET_SHORT_finish
+    b       common_exceptionThrown
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IPUT: /* 0x59 */
+/* File: armv6t2/OP_IPUT.S */
+    /*
+     * General 32-bit instance field put.
+     *
+     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+     */
+    /* op vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IPUT_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_IPUT_finish          @ yes, finish up
+    b       common_exceptionThrown
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IPUT_WIDE: /* 0x5a */
+/* File: armv6t2/OP_IPUT_WIDE.S */
+    /* iput-wide vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
+    b       common_exceptionThrown
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IPUT_OBJECT: /* 0x5b */
+/* File: armv5te/OP_IPUT_OBJECT.S */
+/* File: armv5te/OP_IPUT.S */
+    /*
+     * General 32-bit instance field put.
+     *
+     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+     */
+    /* op vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
+    b       common_exceptionThrown
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IPUT_BOOLEAN: /* 0x5c */
+/* File: armv5te/OP_IPUT_BOOLEAN.S */
+@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
+/* File: armv5te/OP_IPUT.S */
+    /*
+     * General 32-bit instance field put.
+     *
+     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+     */
+    /* op vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
+    b       common_exceptionThrown
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IPUT_BYTE: /* 0x5d */
+/* File: armv5te/OP_IPUT_BYTE.S */
+@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
+/* File: armv5te/OP_IPUT.S */
+    /*
+     * General 32-bit instance field put.
+     *
+     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+     */
+    /* op vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
+    b       common_exceptionThrown
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IPUT_CHAR: /* 0x5e */
+/* File: armv5te/OP_IPUT_CHAR.S */
+@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
+/* File: armv5te/OP_IPUT.S */
+    /*
+     * General 32-bit instance field put.
+     *
+     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+     */
+    /* op vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
+    b       common_exceptionThrown
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IPUT_SHORT: /* 0x5f */
+/* File: armv5te/OP_IPUT_SHORT.S */
+@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
+/* File: armv5te/OP_IPUT.S */
+    /*
+     * General 32-bit instance field put.
+     *
+     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
+     */
+    /* op vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
+    b       common_exceptionThrown
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SGET: /* 0x60 */
+/* File: armv5te/OP_SGET.S */
+    /*
+     * General 32-bit SGET handler.
+     *
+     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
+     */
+    /* op vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SGET_resolve         @ yes, do resolve
+.LOP_SGET_finish: @ field ptr in r0
+    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    SET_VREG(r1, r2)                    @ fp[AA]<- r1
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SGET_WIDE: /* 0x61 */
+/* File: armv5te/OP_SGET_WIDE.S */
+    /*
+     * 64-bit SGET handler.
+     */
+    /* sget-wide vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
+.LOP_SGET_WIDE_finish:
+    mov     r1, rINST, lsr #8           @ r1<- AA
+    ldrd    r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
+    add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SGET_OBJECT: /* 0x62 */
+/* File: armv5te/OP_SGET_OBJECT.S */
+/* File: armv5te/OP_SGET.S */
+    /*
+     * General 32-bit SGET handler.
+     *
+     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
+     */
+    /* op vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
+.LOP_SGET_OBJECT_finish: @ field ptr in r0
+    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    SET_VREG(r1, r2)                    @ fp[AA]<- r1
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SGET_BOOLEAN: /* 0x63 */
+/* File: armv5te/OP_SGET_BOOLEAN.S */
+/* File: armv5te/OP_SGET.S */
+    /*
+     * General 32-bit SGET handler.
+     *
+     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
+     */
+    /* op vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
+.LOP_SGET_BOOLEAN_finish: @ field ptr in r0
+    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    SET_VREG(r1, r2)                    @ fp[AA]<- r1
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SGET_BYTE: /* 0x64 */
+/* File: armv5te/OP_SGET_BYTE.S */
+/* File: armv5te/OP_SGET.S */
+    /*
+     * General 32-bit SGET handler.
+     *
+     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
+     */
+    /* op vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
+.LOP_SGET_BYTE_finish: @ field ptr in r0
+    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    SET_VREG(r1, r2)                    @ fp[AA]<- r1
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SGET_CHAR: /* 0x65 */
+/* File: armv5te/OP_SGET_CHAR.S */
+/* File: armv5te/OP_SGET.S */
+    /*
+     * General 32-bit SGET handler.
+     *
+     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
+     */
+    /* op vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
+.LOP_SGET_CHAR_finish: @ field ptr in r0
+    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    SET_VREG(r1, r2)                    @ fp[AA]<- r1
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SGET_SHORT: /* 0x66 */
+/* File: armv5te/OP_SGET_SHORT.S */
+/* File: armv5te/OP_SGET.S */
+    /*
+     * General 32-bit SGET handler.
+     *
+     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
+     */
+    /* op vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
+.LOP_SGET_SHORT_finish: @ field ptr in r0
+    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    SET_VREG(r1, r2)                    @ fp[AA]<- r1
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SPUT: /* 0x67 */
+/* File: armv5te/OP_SPUT.S */
+    /*
+     * General 32-bit SPUT handler.
+     *
+     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
+     */
+    /* op vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SPUT_resolve         @ yes, do resolve
+.LOP_SPUT_finish:   @ field ptr in r0
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_VREG(r1, r2)                    @ r1<- fp[AA]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str     r1, [r0, #offStaticField_value] @ field<- vAA
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SPUT_WIDE: /* 0x68 */
+/* File: armv5te/OP_SPUT_WIDE.S */
+    /*
+     * 64-bit SPUT handler.
+     */
+    /* sput-wide vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
+.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    strd    r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SPUT_OBJECT: /* 0x69 */
+/* File: armv5te/OP_SPUT_OBJECT.S */
+/* File: armv5te/OP_SPUT.S */
+    /*
+     * General 32-bit SPUT handler.
+     *
+     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
+     */
+    /* op vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SPUT_OBJECT_resolve         @ yes, do resolve
+.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_VREG(r1, r2)                    @ r1<- fp[AA]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str     r1, [r0, #offStaticField_value] @ field<- vAA
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SPUT_BOOLEAN: /* 0x6a */
+/* File: armv5te/OP_SPUT_BOOLEAN.S */
+/* File: armv5te/OP_SPUT.S */
+    /*
+     * General 32-bit SPUT handler.
+     *
+     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
+     */
+    /* op vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
+.LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_VREG(r1, r2)                    @ r1<- fp[AA]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str     r1, [r0, #offStaticField_value] @ field<- vAA
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SPUT_BYTE: /* 0x6b */
+/* File: armv5te/OP_SPUT_BYTE.S */
+/* File: armv5te/OP_SPUT.S */
+    /*
+     * General 32-bit SPUT handler.
+     *
+     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
+     */
+    /* op vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
+.LOP_SPUT_BYTE_finish:   @ field ptr in r0
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_VREG(r1, r2)                    @ r1<- fp[AA]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str     r1, [r0, #offStaticField_value] @ field<- vAA
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SPUT_CHAR: /* 0x6c */
+/* File: armv5te/OP_SPUT_CHAR.S */
+/* File: armv5te/OP_SPUT.S */
+    /*
+     * General 32-bit SPUT handler.
+     *
+     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
+     */
+    /* op vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
+.LOP_SPUT_CHAR_finish:   @ field ptr in r0
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_VREG(r1, r2)                    @ r1<- fp[AA]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str     r1, [r0, #offStaticField_value] @ field<- vAA
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SPUT_SHORT: /* 0x6d */
+/* File: armv5te/OP_SPUT_SHORT.S */
+/* File: armv5te/OP_SPUT.S */
+    /*
+     * General 32-bit SPUT handler.
+     *
+     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
+     */
+    /* op vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
+.LOP_SPUT_SHORT_finish:   @ field ptr in r0
+    mov     r2, rINST, lsr #8           @ r2<- AA
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_VREG(r1, r2)                    @ r1<- fp[AA]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str     r1, [r0, #offStaticField_value] @ field<- vAA
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_VIRTUAL: /* 0x6e */
+/* File: armv5te/OP_INVOKE_VIRTUAL.S */
+    /*
+     * Handle a virtual method call.
+     *
+     * for: invoke-virtual, invoke-virtual/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
+    FETCH(r10, 2)                       @ r10<- GFED or CCCC
+    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
+    .if     (!0)
+    and     r10, r10, #15               @ r10<- D (or stays CCCC)
+    .endif
+    cmp     r0, #0                      @ already resolved?
+    EXPORT_PC()                         @ must export for invoke
+    bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
+    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
+    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
+    mov     r2, #METHOD_VIRTUAL         @ resolver method type
+    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
+    cmp     r0, #0                      @ got null?
+    bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
+    b       common_exceptionThrown      @ yes, handle exception
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_SUPER: /* 0x6f */
+/* File: armv5te/OP_INVOKE_SUPER.S */
+    /*
+     * Handle a "super" method call.
+     *
+     * for: invoke-super, invoke-super/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    FETCH(r10, 2)                       @ r10<- GFED or CCCC
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
+    .if     (!0)
+    and     r10, r10, #15               @ r10<- D (or stays CCCC)
+    .endif
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
+    GET_VREG(r2, r10)                   @ r2<- "this" ptr
+    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
+    cmp     r2, #0                      @ null "this"?
+    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
+    beq     common_errNullObject        @ null "this", throw exception
+    cmp     r0, #0                      @ already resolved?
+    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
+    EXPORT_PC()                         @ must export for invoke
+    bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
+    b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_DIRECT: /* 0x70 */
+/* File: armv5te/OP_INVOKE_DIRECT.S */
+    /*
+     * Handle a direct method call.
+     *
+     * (We could defer the "is 'this' pointer null" test to the common
+     * method invocation code, and use a flag to indicate that static
+     * calls don't count.  If we do this as part of copying the arguments
+     * out we could avoiding loading the first arg twice.)
+     *
+     * for: invoke-direct, invoke-direct/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
+    FETCH(r10, 2)                       @ r10<- GFED or CCCC
+    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
+    .if     (!0)
+    and     r10, r10, #15               @ r10<- D (or stays CCCC)
+    .endif
+    cmp     r0, #0                      @ already resolved?
+    EXPORT_PC()                         @ must export for invoke
+    GET_VREG(r2, r10)                   @ r2<- "this" ptr
+    beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
+.LOP_INVOKE_DIRECT_finish:
+    cmp     r2, #0                      @ null "this" ref?
+    bne     common_invokeMethodNoRange   @ no, continue on
+    b       common_errNullObject        @ yes, throw exception
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_STATIC: /* 0x71 */
+/* File: armv5te/OP_INVOKE_STATIC.S */
+    /*
+     * Handle a static method call.
+     *
+     * for: invoke-static, invoke-static/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
+    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
+    cmp     r0, #0                      @ already resolved?
+    EXPORT_PC()                         @ must export for invoke
+    bne     common_invokeMethodNoRange @ yes, continue on
+0:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
+    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
+    mov     r2, #METHOD_STATIC          @ resolver method type
+    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
+    cmp     r0, #0                      @ got null?
+    bne     common_invokeMethodNoRange @ no, continue
+    b       common_exceptionThrown      @ yes, handle exception
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_INTERFACE: /* 0x72 */
+/* File: armv5te/OP_INVOKE_INTERFACE.S */
+    /*
+     * Handle an interface method call.
+     *
+     * for: invoke-interface, invoke-interface/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
+    FETCH(r1, 1)                        @ r1<- BBBB
+    .if     (!0)
+    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
+    .endif
+    EXPORT_PC()                         @ must export for invoke
+    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
+    cmp     r0, #0                      @ null obj?
+    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
+    beq     common_errNullObject        @ yes, fail
+    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
+    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
+    cmp     r0, #0                      @ failed?
+    beq     common_exceptionThrown      @ yes, handle exception
+    b       common_invokeMethodNoRange @ jump to common handler 
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_73: /* 0x73 */
+/* File: armv5te/OP_UNUSED_73.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
+/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
+/* File: armv5te/OP_INVOKE_VIRTUAL.S */
+    /*
+     * Handle a virtual method call.
+     *
+     * for: invoke-virtual, invoke-virtual/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
+    FETCH(r10, 2)                       @ r10<- GFED or CCCC
+    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
+    .if     (!1)
+    and     r10, r10, #15               @ r10<- D (or stays CCCC)
+    .endif
+    cmp     r0, #0                      @ already resolved?
+    EXPORT_PC()                         @ must export for invoke
+    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
+    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
+    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
+    mov     r2, #METHOD_VIRTUAL         @ resolver method type
+    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
+    cmp     r0, #0                      @ got null?
+    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
+    b       common_exceptionThrown      @ yes, handle exception
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
+/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
+/* File: armv5te/OP_INVOKE_SUPER.S */
+    /*
+     * Handle a "super" method call.
+     *
+     * for: invoke-super, invoke-super/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    FETCH(r10, 2)                       @ r10<- GFED or CCCC
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
+    .if     (!1)
+    and     r10, r10, #15               @ r10<- D (or stays CCCC)
+    .endif
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
+    GET_VREG(r2, r10)                   @ r2<- "this" ptr
+    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
+    cmp     r2, #0                      @ null "this"?
+    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
+    beq     common_errNullObject        @ null "this", throw exception
+    cmp     r0, #0                      @ already resolved?
+    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
+    EXPORT_PC()                         @ must export for invoke
+    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
+    b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
+/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
+/* File: armv5te/OP_INVOKE_DIRECT.S */
+    /*
+     * Handle a direct method call.
+     *
+     * (We could defer the "is 'this' pointer null" test to the common
+     * method invocation code, and use a flag to indicate that static
+     * calls don't count.  If we do this as part of copying the arguments
+     * out we could avoiding loading the first arg twice.)
+     *
+     * for: invoke-direct, invoke-direct/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
+    FETCH(r10, 2)                       @ r10<- GFED or CCCC
+    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
+    .if     (!1)
+    and     r10, r10, #15               @ r10<- D (or stays CCCC)
+    .endif
+    cmp     r0, #0                      @ already resolved?
+    EXPORT_PC()                         @ must export for invoke
+    GET_VREG(r2, r10)                   @ r2<- "this" ptr
+    beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
+.LOP_INVOKE_DIRECT_RANGE_finish:
+    cmp     r2, #0                      @ null "this" ref?
+    bne     common_invokeMethodRange   @ no, continue on
+    b       common_errNullObject        @ yes, throw exception
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
+/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
+/* File: armv5te/OP_INVOKE_STATIC.S */
+    /*
+     * Handle a static method call.
+     *
+     * for: invoke-static, invoke-static/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
+    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
+    cmp     r0, #0                      @ already resolved?
+    EXPORT_PC()                         @ must export for invoke
+    bne     common_invokeMethodRange @ yes, continue on
+0:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
+    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
+    mov     r2, #METHOD_STATIC          @ resolver method type
+    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
+    cmp     r0, #0                      @ got null?
+    bne     common_invokeMethodRange @ no, continue
+    b       common_exceptionThrown      @ yes, handle exception
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
+/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
+/* File: armv5te/OP_INVOKE_INTERFACE.S */
+    /*
+     * Handle an interface method call.
+     *
+     * for: invoke-interface, invoke-interface/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
+    FETCH(r1, 1)                        @ r1<- BBBB
+    .if     (!1)
+    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
+    .endif
+    EXPORT_PC()                         @ must export for invoke
+    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
+    cmp     r0, #0                      @ null obj?
+    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
+    beq     common_errNullObject        @ yes, fail
+    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
+    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
+    cmp     r0, #0                      @ failed?
+    beq     common_exceptionThrown      @ yes, handle exception
+    b       common_invokeMethodRange @ jump to common handler 
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_79: /* 0x79 */
+/* File: armv5te/OP_UNUSED_79.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_7A: /* 0x7a */
+/* File: armv5te/OP_UNUSED_7A.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_NEG_INT: /* 0x7b */
+/* File: armv6t2/OP_NEG_INT.S */
+/* File: armv6t2/unop.S */
+    /*
+     * Generic 32-bit unary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = op r0".
+     * This could be an ARM instruction or a function call.
+     *
+     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
+     *      int-to-byte, int-to-char, int-to-short
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r0, r3)                    @ r0<- vB
+                               @ optional op; may set condition codes
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 8-9 instructions */
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_NOT_INT: /* 0x7c */
+/* File: armv6t2/OP_NOT_INT.S */
+/* File: armv6t2/unop.S */
+    /*
+     * Generic 32-bit unary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = op r0".
+     * This could be an ARM instruction or a function call.
+     *
+     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
+     *      int-to-byte, int-to-char, int-to-short
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r0, r3)                    @ r0<- vB
+                               @ optional op; may set condition codes
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    mvn     r0, r0                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 8-9 instructions */
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_NEG_LONG: /* 0x7d */
+/* File: armv6t2/OP_NEG_LONG.S */
+/* File: armv6t2/unopWide.S */
+    /*
+     * Generic 64-bit unary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = op r0/r1".
+     * This could be an ARM instruction or a function call.
+     *
+     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    rsbs    r0, r0, #0                           @ optional op; may set condition codes
+    rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-11 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_NOT_LONG: /* 0x7e */
+/* File: armv6t2/OP_NOT_LONG.S */
+/* File: armv6t2/unopWide.S */
+    /*
+     * Generic 64-bit unary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = op r0/r1".
+     * This could be an ARM instruction or a function call.
+     *
+     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    mvn     r0, r0                           @ optional op; may set condition codes
+    mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-11 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_NEG_FLOAT: /* 0x7f */
+/* File: armv6t2/OP_NEG_FLOAT.S */
+/* File: armv6t2/unop.S */
+    /*
+     * Generic 32-bit unary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = op r0".
+     * This could be an ARM instruction or a function call.
+     *
+     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
+     *      int-to-byte, int-to-char, int-to-short
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r0, r3)                    @ r0<- vB
+                               @ optional op; may set condition codes
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 8-9 instructions */
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_NEG_DOUBLE: /* 0x80 */
+/* File: armv6t2/OP_NEG_DOUBLE.S */
+/* File: armv6t2/unopWide.S */
+    /*
+     * Generic 64-bit unary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = op r0/r1".
+     * This could be an ARM instruction or a function call.
+     *
+     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+                               @ optional op; may set condition codes
+    add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-11 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INT_TO_LONG: /* 0x81 */
+/* File: armv6t2/OP_INT_TO_LONG.S */
+/* File: armv6t2/unopWider.S */
+    /*
+     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = op r0", where
+     * "result" is a 64-bit quantity in r0/r1.
+     *
+     * For: int-to-long, int-to-double, float-to-long, float-to-double
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r0, r3)                    @ r0<- vB
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+                               @ optional op; may set condition codes
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 9-10 instructions */
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INT_TO_FLOAT: /* 0x82 */
+/* File: arm-vfp/OP_INT_TO_FLOAT.S */
+/* File: arm-vfp/funop.S */
+    /*
+     * Generic 32-bit unary floating-point operation.  Provide an "instr"
+     * line that specifies an instruction that performs "s1 = op s0".
+     *
+     * for: int-to-float, float-to-int
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    flds    s0, [r3]                    @ s0<- vB
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    and     r9, r9, #15                 @ r9<- A
+    fsitos  s1, s0                              @ s1<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    fsts    s1, [r9]                    @ vA<- s1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INT_TO_DOUBLE: /* 0x83 */
+/* File: arm-vfp/OP_INT_TO_DOUBLE.S */
+/* File: arm-vfp/funopWider.S */
+    /*
+     * Generic 32bit-to-64bit floating point unary operation.  Provide an
+     * "instr" line that specifies an instruction that performs "d0 = op s0".
+     *
+     * For: int-to-double, float-to-double
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    flds    s0, [r3]                    @ s0<- vB
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    and     r9, r9, #15                 @ r9<- A
+    fsitod  d0, s0                              @ d0<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    fstd    d0, [r9]                    @ vA<- d0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_LONG_TO_INT: /* 0x84 */
+/* File: armv5te/OP_LONG_TO_INT.S */
+/* we ignore the high word, making this equivalent to a 32-bit reg move */
+/* File: armv5te/OP_MOVE.S */
+    /* for move, move-object, long-to-int */
+    /* op vA, vB */
+    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
+    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    GET_VREG(r2, r1)                    @ r2<- fp[B]
+    and     r0, r0, #15
+    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
+    SET_VREG(r2, r0)                    @ fp[A]<- r2
+    GOTO_OPCODE(ip)                     @ execute next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_LONG_TO_FLOAT: /* 0x85 */
+/* File: armv6t2/OP_LONG_TO_FLOAT.S */
+/* File: armv6t2/unopNarrower.S */
+    /*
+     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = op r0/r1", where
+     * "result" is a 32-bit quantity in r0.
+     *
+     * For: long-to-float, double-to-int, double-to-float
+     *
+     * (This would work for long-to-int, but that instruction is actually
+     * an exact match for OP_MOVE.)
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
+    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+                               @ optional op; may set condition codes
+    bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 9-10 instructions */
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_LONG_TO_DOUBLE: /* 0x86 */
+/* File: armv6t2/OP_LONG_TO_DOUBLE.S */
+/* File: armv6t2/unopWide.S */
+    /*
+     * Generic 64-bit unary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = op r0/r1".
+     * This could be an ARM instruction or a function call.
+     *
+     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+                               @ optional op; may set condition codes
+    bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-11 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_FLOAT_TO_INT: /* 0x87 */
+/* File: arm-vfp/OP_FLOAT_TO_INT.S */
+/* File: arm-vfp/funop.S */
+    /*
+     * Generic 32-bit unary floating-point operation.  Provide an "instr"
+     * line that specifies an instruction that performs "s1 = op s0".
+     *
+     * for: int-to-float, float-to-int
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    flds    s0, [r3]                    @ s0<- vB
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    and     r9, r9, #15                 @ r9<- A
+    ftosizs s1, s0                              @ s1<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    fsts    s1, [r9]                    @ vA<- s1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_FLOAT_TO_LONG: /* 0x88 */
+/* File: armv6t2/OP_FLOAT_TO_LONG.S */
+@include "armv6t2/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
+/* File: armv6t2/unopWider.S */
+    /*
+     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = op r0", where
+     * "result" is a 64-bit quantity in r0/r1.
+     *
+     * For: int-to-long, int-to-double, float-to-long, float-to-double
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r0, r3)                    @ r0<- vB
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+                               @ optional op; may set condition codes
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    bl      f2l_doconv                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 9-10 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
+/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
+/* File: arm-vfp/funopWider.S */
+    /*
+     * Generic 32bit-to-64bit floating point unary operation.  Provide an
+     * "instr" line that specifies an instruction that performs "d0 = op s0".
+     *
+     * For: int-to-double, float-to-double
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    flds    s0, [r3]                    @ s0<- vB
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    and     r9, r9, #15                 @ r9<- A
+    fcvtds  d0, s0                              @ d0<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    fstd    d0, [r9]                    @ vA<- d0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_DOUBLE_TO_INT: /* 0x8a */
+/* File: arm-vfp/OP_DOUBLE_TO_INT.S */
+/* File: arm-vfp/funopNarrower.S */
+    /*
+     * Generic 64bit-to-32bit unary floating point operation.  Provide an
+     * "instr" line that specifies an instruction that performs "s0 = op d0".
+     *
+     * For: double-to-int, double-to-float
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    fldd    d0, [r3]                    @ d0<- vB
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    and     r9, r9, #15                 @ r9<- A
+    ftosizd  s0, d0                              @ s0<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    fsts    s0, [r9]                    @ vA<- s0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_DOUBLE_TO_LONG: /* 0x8b */
+/* File: armv6t2/OP_DOUBLE_TO_LONG.S */
+@include "armv6t2/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
+/* File: armv6t2/unopWide.S */
+    /*
+     * Generic 64-bit unary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = op r0/r1".
+     * This could be an ARM instruction or a function call.
+     *
+     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+                               @ optional op; may set condition codes
+    bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-11 instructions */
+
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
+/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
+/* File: arm-vfp/funopNarrower.S */
+    /*
+     * Generic 64bit-to-32bit unary floating point operation.  Provide an
+     * "instr" line that specifies an instruction that performs "s0 = op d0".
+     *
+     * For: double-to-int, double-to-float
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    fldd    d0, [r3]                    @ d0<- vB
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    and     r9, r9, #15                 @ r9<- A
+    fcvtsd  s0, d0                              @ s0<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    fsts    s0, [r9]                    @ vA<- s0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INT_TO_BYTE: /* 0x8d */
+/* File: armv6t2/OP_INT_TO_BYTE.S */
+/* File: armv6t2/unop.S */
+    /*
+     * Generic 32-bit unary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = op r0".
+     * This could be an ARM instruction or a function call.
+     *
+     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
+     *      int-to-byte, int-to-char, int-to-short
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r0, r3)                    @ r0<- vB
+                               @ optional op; may set condition codes
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    sxtb    r0, r0                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 8-9 instructions */
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INT_TO_CHAR: /* 0x8e */
+/* File: armv6t2/OP_INT_TO_CHAR.S */
+/* File: armv6t2/unop.S */
+    /*
+     * Generic 32-bit unary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = op r0".
+     * This could be an ARM instruction or a function call.
+     *
+     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
+     *      int-to-byte, int-to-char, int-to-short
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r0, r3)                    @ r0<- vB
+                               @ optional op; may set condition codes
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    uxth    r0, r0                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 8-9 instructions */
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INT_TO_SHORT: /* 0x8f */
+/* File: armv6t2/OP_INT_TO_SHORT.S */
+/* File: armv6t2/unop.S */
+    /*
+     * Generic 32-bit unary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = op r0".
+     * This could be an ARM instruction or a function call.
+     *
+     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
+     *      int-to-byte, int-to-char, int-to-short
+     */
+    /* unop vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r0, r3)                    @ r0<- vB
+                               @ optional op; may set condition codes
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    sxth    r0, r0                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 8-9 instructions */
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_ADD_INT: /* 0x90 */
+/* File: armv5te/OP_ADD_INT.S */
+/* File: armv5te/binop.S */
+    /*
+     * Generic 32-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.  Note that we
+     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+     * handles it correctly.
+     *
+     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
+     *      mul-float, div-float, rem-float
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    GET_VREG(r1, r3)                    @ r1<- vCC
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+                               @ optional op; may set condition codes
+    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 11-14 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SUB_INT: /* 0x91 */
+/* File: armv5te/OP_SUB_INT.S */
+/* File: armv5te/binop.S */
+    /*
+     * Generic 32-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.  Note that we
+     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+     * handles it correctly.
+     *
+     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
+     *      mul-float, div-float, rem-float
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    GET_VREG(r1, r3)                    @ r1<- vCC
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+                               @ optional op; may set condition codes
+    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 11-14 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MUL_INT: /* 0x92 */
+/* File: armv5te/OP_MUL_INT.S */
+/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
+/* File: armv5te/binop.S */
+    /*
+     * Generic 32-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.  Note that we
+     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+     * handles it correctly.
+     *
+     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
+     *      mul-float, div-float, rem-float
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    GET_VREG(r1, r3)                    @ r1<- vCC
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+                               @ optional op; may set condition codes
+    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 11-14 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_DIV_INT: /* 0x93 */
+/* File: armv5te/OP_DIV_INT.S */
+/* File: armv5te/binop.S */
+    /*
+     * Generic 32-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.  Note that we
+     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+     * handles it correctly.
+     *
+     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
+     *      mul-float, div-float, rem-float
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    GET_VREG(r1, r3)                    @ r1<- vCC
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    .if 1
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+                               @ optional op; may set condition codes
+    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 11-14 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_REM_INT: /* 0x94 */
+/* File: armv5te/OP_REM_INT.S */
+/* idivmod returns quotient in r0 and remainder in r1 */
+/* File: armv5te/binop.S */
+    /*
+     * Generic 32-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.  Note that we
+     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+     * handles it correctly.
+     *
+     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
+     *      mul-float, div-float, rem-float
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    GET_VREG(r1, r3)                    @ r1<- vCC
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    .if 1
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+                               @ optional op; may set condition codes
+    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r1, r9)               @ vAA<- r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 11-14 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_AND_INT: /* 0x95 */
+/* File: armv5te/OP_AND_INT.S */
+/* File: armv5te/binop.S */
+    /*
+     * Generic 32-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.  Note that we
+     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+     * handles it correctly.
+     *
+     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
+     *      mul-float, div-float, rem-float
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    GET_VREG(r1, r3)                    @ r1<- vCC
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+                               @ optional op; may set condition codes
+    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 11-14 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_OR_INT: /* 0x96 */
+/* File: armv5te/OP_OR_INT.S */
+/* File: armv5te/binop.S */
+    /*
+     * Generic 32-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.  Note that we
+     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+     * handles it correctly.
+     *
+     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
+     *      mul-float, div-float, rem-float
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    GET_VREG(r1, r3)                    @ r1<- vCC
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+                               @ optional op; may set condition codes
+    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 11-14 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_XOR_INT: /* 0x97 */
+/* File: armv5te/OP_XOR_INT.S */
+/* File: armv5te/binop.S */
+    /*
+     * Generic 32-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.  Note that we
+     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+     * handles it correctly.
+     *
+     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
+     *      mul-float, div-float, rem-float
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    GET_VREG(r1, r3)                    @ r1<- vCC
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+                               @ optional op; may set condition codes
+    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 11-14 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SHL_INT: /* 0x98 */
+/* File: armv5te/OP_SHL_INT.S */
+/* File: armv5te/binop.S */
+    /*
+     * Generic 32-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.  Note that we
+     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+     * handles it correctly.
+     *
+     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
+     *      mul-float, div-float, rem-float
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    GET_VREG(r1, r3)                    @ r1<- vCC
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r1, r1, #31                           @ optional op; may set condition codes
+    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 11-14 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SHR_INT: /* 0x99 */
+/* File: armv5te/OP_SHR_INT.S */
+/* File: armv5te/binop.S */
+    /*
+     * Generic 32-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.  Note that we
+     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+     * handles it correctly.
+     *
+     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
+     *      mul-float, div-float, rem-float
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    GET_VREG(r1, r3)                    @ r1<- vCC
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r1, r1, #31                           @ optional op; may set condition codes
+    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 11-14 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_USHR_INT: /* 0x9a */
+/* File: armv5te/OP_USHR_INT.S */
+/* File: armv5te/binop.S */
+    /*
+     * Generic 32-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.  Note that we
+     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+     * handles it correctly.
+     *
+     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
+     *      mul-float, div-float, rem-float
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    GET_VREG(r1, r3)                    @ r1<- vCC
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r1, r1, #31                           @ optional op; may set condition codes
+    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 11-14 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_ADD_LONG: /* 0x9b */
+/* File: armv5te/OP_ADD_LONG.S */
+/* File: armv5te/binopWide.S */
+    /*
+     * Generic 64-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
+     *      xor-long, add-double, sub-double, mul-double, div-double,
+     *      rem-double
+     *
+     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
+    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
+    .if 0
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    adds    r0, r0, r2                           @ optional op; may set condition codes
+    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 14-17 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SUB_LONG: /* 0x9c */
+/* File: armv5te/OP_SUB_LONG.S */
+/* File: armv5te/binopWide.S */
+    /*
+     * Generic 64-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
+     *      xor-long, add-double, sub-double, mul-double, div-double,
+     *      rem-double
+     *
+     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
+    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
+    .if 0
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    subs    r0, r0, r2                           @ optional op; may set condition codes
+    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 14-17 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MUL_LONG: /* 0x9d */
+/* File: armv5te/OP_MUL_LONG.S */
+    /*
+     * Signed 64-bit integer multiply.
+     *
+     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
+     *        WX
+     *      x YZ
+     *  --------
+     *     ZW ZX
+     *  YW YX
+     *
+     * The low word of the result holds ZX, the high word holds
+     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
+     * it doesn't fit in the low 64 bits.
+     *
+     * Unlike most ARM math operations, multiply instructions have
+     * restrictions on using the same register more than once (Rd and Rm
+     * cannot be the same).
+     */
+    /* mul-long vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
+    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
+    mul     ip, r2, r1                  @  ip<- ZxW
+    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
+    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
+    mov     r0, rINST, lsr #8           @ r0<- AA
+    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
+    add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    b       .LOP_MUL_LONG_finish
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_DIV_LONG: /* 0x9e */
+/* File: armv5te/OP_DIV_LONG.S */
+/* File: armv5te/binopWide.S */
+    /*
+     * Generic 64-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
+     *      xor-long, add-double, sub-double, mul-double, div-double,
+     *      rem-double
+     *
+     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
+    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
+    .if 1
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 14-17 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_REM_LONG: /* 0x9f */
+/* File: armv5te/OP_REM_LONG.S */
+/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
+/* File: armv5te/binopWide.S */
+    /*
+     * Generic 64-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
+     *      xor-long, add-double, sub-double, mul-double, div-double,
+     *      rem-double
+     *
+     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
+    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
+    .if 1
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 14-17 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_AND_LONG: /* 0xa0 */
+/* File: armv5te/OP_AND_LONG.S */
+/* File: armv5te/binopWide.S */
+    /*
+     * Generic 64-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
+     *      xor-long, add-double, sub-double, mul-double, div-double,
+     *      rem-double
+     *
+     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
+    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
+    .if 0
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    and     r0, r0, r2                           @ optional op; may set condition codes
+    and     r1, r1, r3                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 14-17 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_OR_LONG: /* 0xa1 */
+/* File: armv5te/OP_OR_LONG.S */
+/* File: armv5te/binopWide.S */
+    /*
+     * Generic 64-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
+     *      xor-long, add-double, sub-double, mul-double, div-double,
+     *      rem-double
+     *
+     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
+    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
+    .if 0
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    orr     r0, r0, r2                           @ optional op; may set condition codes
+    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 14-17 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_XOR_LONG: /* 0xa2 */
+/* File: armv5te/OP_XOR_LONG.S */
+/* File: armv5te/binopWide.S */
+    /*
+     * Generic 64-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
+     *      xor-long, add-double, sub-double, mul-double, div-double,
+     *      rem-double
+     *
+     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
+    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
+    .if 0
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    eor     r0, r0, r2                           @ optional op; may set condition codes
+    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 14-17 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SHL_LONG: /* 0xa3 */
+/* File: armv5te/OP_SHL_LONG.S */
+    /*
+     * Long integer shift.  This is different from the generic 32/64-bit
+     * binary operations because vAA/vBB are 64-bit but vCC (the shift
+     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
+     * 6 bits of the shift distance.
+     */
+    /* shl-long vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r3, r0, #255                @ r3<- BB
+    mov     r0, r0, lsr #8              @ r0<- CC
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
+    GET_VREG(r2, r0)                    @ r2<- vCC
+    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    and     r2, r2, #63                 @ r2<- r2 & 0x3f
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+
+    mov     r1, r1, asl r2              @  r1<- r1 << r2
+    rsb     r3, r2, #32                 @  r3<- 32 - r2
+    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
+    subs    ip, r2, #32                 @  ip<- r2 - 32
+    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    b       .LOP_SHL_LONG_finish
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SHR_LONG: /* 0xa4 */
+/* File: armv5te/OP_SHR_LONG.S */
+    /*
+     * Long integer shift.  This is different from the generic 32/64-bit
+     * binary operations because vAA/vBB are 64-bit but vCC (the shift
+     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
+     * 6 bits of the shift distance.
+     */
+    /* shr-long vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r3, r0, #255                @ r3<- BB
+    mov     r0, r0, lsr #8              @ r0<- CC
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
+    GET_VREG(r2, r0)                    @ r2<- vCC
+    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    and     r2, r2, #63                 @ r0<- r0 & 0x3f
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+
+    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
+    rsb     r3, r2, #32                 @  r3<- 32 - r2
+    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
+    subs    ip, r2, #32                 @  ip<- r2 - 32
+    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    b       .LOP_SHR_LONG_finish
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_USHR_LONG: /* 0xa5 */
+/* File: armv5te/OP_USHR_LONG.S */
+    /*
+     * Long integer shift.  This is different from the generic 32/64-bit
+     * binary operations because vAA/vBB are 64-bit but vCC (the shift
+     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
+     * 6 bits of the shift distance.
+     */
+    /* ushr-long vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r3, r0, #255                @ r3<- BB
+    mov     r0, r0, lsr #8              @ r0<- CC
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
+    GET_VREG(r2, r0)                    @ r2<- vCC
+    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    and     r2, r2, #63                 @ r0<- r0 & 0x3f
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+
+    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
+    rsb     r3, r2, #32                 @  r3<- 32 - r2
+    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
+    subs    ip, r2, #32                 @  ip<- r2 - 32
+    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    b       .LOP_USHR_LONG_finish
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_ADD_FLOAT: /* 0xa6 */
+/* File: arm-vfp/OP_ADD_FLOAT.S */
+/* File: arm-vfp/fbinop.S */
+    /*
+     * Generic 32-bit floating-point operation.  Provide an "instr" line that
+     * specifies an instruction that performs "s2 = s0 op s1".  Because we
+     * use the "softfp" ABI, this must be an instruction, not a function call.
+     *
+     * For: add-float, sub-float, mul-float, div-float
+     */
+    /* floatop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    flds    s1, [r3]                    @ s1<- vCC
+    flds    s0, [r2]                    @ s0<- vBB
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    fadds   s2, s0, s1                              @ s2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
+    fsts    s2, [r9]                    @ vAA<- s2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SUB_FLOAT: /* 0xa7 */
+/* File: arm-vfp/OP_SUB_FLOAT.S */
+/* File: arm-vfp/fbinop.S */
+    /*
+     * Generic 32-bit floating-point operation.  Provide an "instr" line that
+     * specifies an instruction that performs "s2 = s0 op s1".  Because we
+     * use the "softfp" ABI, this must be an instruction, not a function call.
+     *
+     * For: add-float, sub-float, mul-float, div-float
+     */
+    /* floatop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    flds    s1, [r3]                    @ s1<- vCC
+    flds    s0, [r2]                    @ s0<- vBB
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    fsubs   s2, s0, s1                              @ s2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
+    fsts    s2, [r9]                    @ vAA<- s2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MUL_FLOAT: /* 0xa8 */
+/* File: arm-vfp/OP_MUL_FLOAT.S */
+/* File: arm-vfp/fbinop.S */
+    /*
+     * Generic 32-bit floating-point operation.  Provide an "instr" line that
+     * specifies an instruction that performs "s2 = s0 op s1".  Because we
+     * use the "softfp" ABI, this must be an instruction, not a function call.
+     *
+     * For: add-float, sub-float, mul-float, div-float
+     */
+    /* floatop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    flds    s1, [r3]                    @ s1<- vCC
+    flds    s0, [r2]                    @ s0<- vBB
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    fmuls   s2, s0, s1                              @ s2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
+    fsts    s2, [r9]                    @ vAA<- s2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_DIV_FLOAT: /* 0xa9 */
+/* File: arm-vfp/OP_DIV_FLOAT.S */
+/* File: arm-vfp/fbinop.S */
+    /*
+     * Generic 32-bit floating-point operation.  Provide an "instr" line that
+     * specifies an instruction that performs "s2 = s0 op s1".  Because we
+     * use the "softfp" ABI, this must be an instruction, not a function call.
+     *
+     * For: add-float, sub-float, mul-float, div-float
+     */
+    /* floatop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    flds    s1, [r3]                    @ s1<- vCC
+    flds    s0, [r2]                    @ s0<- vBB
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    fdivs   s2, s0, s1                              @ s2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
+    fsts    s2, [r9]                    @ vAA<- s2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_REM_FLOAT: /* 0xaa */
+/* File: armv5te/OP_REM_FLOAT.S */
+/* EABI doesn't define a float remainder function, but libm does */
+/* File: armv5te/binop.S */
+    /*
+     * Generic 32-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.  Note that we
+     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
+     * handles it correctly.
+     *
+     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
+     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
+     *      mul-float, div-float, rem-float
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    GET_VREG(r1, r3)                    @ r1<- vCC
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+                               @ optional op; may set condition codes
+    bl      fmodf                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 11-14 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_ADD_DOUBLE: /* 0xab */
+/* File: arm-vfp/OP_ADD_DOUBLE.S */
+/* File: arm-vfp/fbinopWide.S */
+    /*
+     * Generic 64-bit double-precision floating point binary operation.
+     * Provide an "instr" line that specifies an instruction that performs
+     * "d2 = d0 op d1".
+     *
+     * for: add-double, sub-double, mul-double, div-double
+     */
+    /* doubleop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    fldd    d1, [r3]                    @ d1<- vCC
+    fldd    d0, [r2]                    @ d0<- vBB
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    faddd   d2, d0, d1                              @ s2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
+    fstd    d2, [r9]                    @ vAA<- d2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SUB_DOUBLE: /* 0xac */
+/* File: arm-vfp/OP_SUB_DOUBLE.S */
+/* File: arm-vfp/fbinopWide.S */
+    /*
+     * Generic 64-bit double-precision floating point binary operation.
+     * Provide an "instr" line that specifies an instruction that performs
+     * "d2 = d0 op d1".
+     *
+     * for: add-double, sub-double, mul-double, div-double
+     */
+    /* doubleop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    fldd    d1, [r3]                    @ d1<- vCC
+    fldd    d0, [r2]                    @ d0<- vBB
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    fsubd   d2, d0, d1                              @ s2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
+    fstd    d2, [r9]                    @ vAA<- d2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MUL_DOUBLE: /* 0xad */
+/* File: arm-vfp/OP_MUL_DOUBLE.S */
+/* File: arm-vfp/fbinopWide.S */
+    /*
+     * Generic 64-bit double-precision floating point binary operation.
+     * Provide an "instr" line that specifies an instruction that performs
+     * "d2 = d0 op d1".
+     *
+     * for: add-double, sub-double, mul-double, div-double
+     */
+    /* doubleop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    fldd    d1, [r3]                    @ d1<- vCC
+    fldd    d0, [r2]                    @ d0<- vBB
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    fmuld   d2, d0, d1                              @ s2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
+    fstd    d2, [r9]                    @ vAA<- d2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_DIV_DOUBLE: /* 0xae */
+/* File: arm-vfp/OP_DIV_DOUBLE.S */
+/* File: arm-vfp/fbinopWide.S */
+    /*
+     * Generic 64-bit double-precision floating point binary operation.
+     * Provide an "instr" line that specifies an instruction that performs
+     * "d2 = d0 op d1".
+     *
+     * for: add-double, sub-double, mul-double, div-double
+     */
+    /* doubleop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    mov     r3, r0, lsr #8              @ r3<- CC
+    and     r2, r0, #255                @ r2<- BB
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
+    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
+    fldd    d1, [r3]                    @ d1<- vCC
+    fldd    d0, [r2]                    @ d0<- vBB
+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    fdivd   d2, d0, d1                              @ s2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
+    fstd    d2, [r9]                    @ vAA<- d2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_REM_DOUBLE: /* 0xaf */
+/* File: armv5te/OP_REM_DOUBLE.S */
+/* EABI doesn't define a double remainder function, but libm does */
+/* File: armv5te/binopWide.S */
+    /*
+     * Generic 64-bit binary operation.  Provide an "instr" line that
+     * specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
+     *      xor-long, add-double, sub-double, mul-double, div-double,
+     *      rem-double
+     *
+     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
+     */
+    /* binop vAA, vBB, vCC */
+    FETCH(r0, 1)                        @ r0<- CCBB
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r0, #255                @ r2<- BB
+    mov     r3, r0, lsr #8              @ r3<- CC
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
+    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
+    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
+    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
+    .if 0
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    bl      fmod                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 14-17 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_ADD_INT_2ADDR: /* 0xb0 */
+/* File: armv6t2/OP_ADD_INT_2ADDR.S */
+/* File: armv6t2/binop2addr.S */
+    /*
+     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SUB_INT_2ADDR: /* 0xb1 */
+/* File: armv6t2/OP_SUB_INT_2ADDR.S */
+/* File: armv6t2/binop2addr.S */
+    /*
+     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MUL_INT_2ADDR: /* 0xb2 */
+/* File: armv6t2/OP_MUL_INT_2ADDR.S */
+/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
+/* File: armv6t2/binop2addr.S */
+    /*
+     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_DIV_INT_2ADDR: /* 0xb3 */
+/* File: armv6t2/OP_DIV_INT_2ADDR.S */
+/* File: armv6t2/binop2addr.S */
+    /*
+     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
+    .if 1
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_REM_INT_2ADDR: /* 0xb4 */
+/* File: armv6t2/OP_REM_INT_2ADDR.S */
+/* idivmod returns quotient in r0 and remainder in r1 */
+/* File: armv6t2/binop2addr.S */
+    /*
+     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
+    .if 1
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r1, r9)               @ vAA<- r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_AND_INT_2ADDR: /* 0xb5 */
+/* File: armv6t2/OP_AND_INT_2ADDR.S */
+/* File: armv6t2/binop2addr.S */
+    /*
+     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_OR_INT_2ADDR: /* 0xb6 */
+/* File: armv6t2/OP_OR_INT_2ADDR.S */
+/* File: armv6t2/binop2addr.S */
+    /*
+     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_XOR_INT_2ADDR: /* 0xb7 */
+/* File: armv6t2/OP_XOR_INT_2ADDR.S */
+/* File: armv6t2/binop2addr.S */
+    /*
+     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SHL_INT_2ADDR: /* 0xb8 */
+/* File: armv6t2/OP_SHL_INT_2ADDR.S */
+/* File: armv6t2/binop2addr.S */
+    /*
+     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+    and     r1, r1, #31                           @ optional op; may set condition codes
+    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SHR_INT_2ADDR: /* 0xb9 */
+/* File: armv6t2/OP_SHR_INT_2ADDR.S */
+/* File: armv6t2/binop2addr.S */
+    /*
+     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+    and     r1, r1, #31                           @ optional op; may set condition codes
+    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_USHR_INT_2ADDR: /* 0xba */
+/* File: armv6t2/OP_USHR_INT_2ADDR.S */
+/* File: armv6t2/binop2addr.S */
+    /*
+     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+    and     r1, r1, #31                           @ optional op; may set condition codes
+    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_ADD_LONG_2ADDR: /* 0xbb */
+/* File: armv6t2/OP_ADD_LONG_2ADDR.S */
+/* File: armv6t2/binopWide2addr.S */
+    /*
+     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
+     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
+     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
+     *      rem-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r1, rINST, lsr #12          @ r1<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    .if 0
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+    adds    r0, r0, r2                           @ optional op; may set condition codes
+    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 12-15 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SUB_LONG_2ADDR: /* 0xbc */
+/* File: armv6t2/OP_SUB_LONG_2ADDR.S */
+/* File: armv6t2/binopWide2addr.S */
+    /*
+     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
+     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
+     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
+     *      rem-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r1, rINST, lsr #12          @ r1<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    .if 0
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+    subs    r0, r0, r2                           @ optional op; may set condition codes
+    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 12-15 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MUL_LONG_2ADDR: /* 0xbd */
+/* File: armv6t2/OP_MUL_LONG_2ADDR.S */
+    /*
+     * Signed 64-bit integer multiply, "/2addr" version.
+     *
+     * See OP_MUL_LONG for an explanation.
+     *
+     * We get a little tight on registers, so to avoid looking up &fp[A]
+     * again we stuff it into rINST.
+     */
+    /* mul-long/2addr vA, vB */
+    mov     r1, rINST, lsr #12          @ r1<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
+    add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
+    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
+    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
+    mul     ip, r2, r1                  @  ip<- ZxW
+    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
+    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
+    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_DIV_LONG_2ADDR: /* 0xbe */
+/* File: armv6t2/OP_DIV_LONG_2ADDR.S */
+/* File: armv6t2/binopWide2addr.S */
+    /*
+     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
+     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
+     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
+     *      rem-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r1, rINST, lsr #12          @ r1<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    .if 1
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 12-15 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_REM_LONG_2ADDR: /* 0xbf */
+/* File: armv6t2/OP_REM_LONG_2ADDR.S */
+/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
+/* File: armv6t2/binopWide2addr.S */
+    /*
+     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
+     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
+     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
+     *      rem-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r1, rINST, lsr #12          @ r1<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    .if 1
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 12-15 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_AND_LONG_2ADDR: /* 0xc0 */
+/* File: armv6t2/OP_AND_LONG_2ADDR.S */
+/* File: armv6t2/binopWide2addr.S */
+    /*
+     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
+     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
+     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
+     *      rem-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r1, rINST, lsr #12          @ r1<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    .if 0
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+    and     r0, r0, r2                           @ optional op; may set condition codes
+    and     r1, r1, r3                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 12-15 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_OR_LONG_2ADDR: /* 0xc1 */
+/* File: armv6t2/OP_OR_LONG_2ADDR.S */
+/* File: armv6t2/binopWide2addr.S */
+    /*
+     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
+     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
+     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
+     *      rem-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r1, rINST, lsr #12          @ r1<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    .if 0
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+    orr     r0, r0, r2                           @ optional op; may set condition codes
+    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 12-15 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
+/* File: armv6t2/OP_XOR_LONG_2ADDR.S */
+/* File: armv6t2/binopWide2addr.S */
+    /*
+     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
+     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
+     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
+     *      rem-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r1, rINST, lsr #12          @ r1<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    .if 0
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+    eor     r0, r0, r2                           @ optional op; may set condition codes
+    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 12-15 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
+/* File: armv6t2/OP_SHL_LONG_2ADDR.S */
+    /*
+     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
+     * 32-bit shift distance.
+     */
+    /* shl-long/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r2, r3)                    @ r2<- vB
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    and     r2, r2, #63                 @ r2<- r2 & 0x3f
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+
+    mov     r1, r1, asl r2              @  r1<- r1 << r2
+    rsb     r3, r2, #32                 @  r3<- 32 - r2
+    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
+    subs    ip, r2, #32                 @  ip<- r2 - 32
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
+    mov     r0, r0, asl r2              @  r0<- r0 << r2
+    b       .LOP_SHL_LONG_2ADDR_finish
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
+/* File: armv6t2/OP_SHR_LONG_2ADDR.S */
+    /*
+     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
+     * 32-bit shift distance.
+     */
+    /* shr-long/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r2, r3)                    @ r2<- vB
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    and     r2, r2, #63                 @ r2<- r2 & 0x3f
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+
+    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
+    rsb     r3, r2, #32                 @  r3<- 32 - r2
+    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
+    subs    ip, r2, #32                 @  ip<- r2 - 32
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
+    mov     r1, r1, asr r2              @  r1<- r1 >> r2
+    b       .LOP_SHR_LONG_2ADDR_finish
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
+/* File: armv6t2/OP_USHR_LONG_2ADDR.S */
+    /*
+     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
+     * 32-bit shift distance.
+     */
+    /* ushr-long/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r2, r3)                    @ r2<- vB
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    and     r2, r2, #63                 @ r2<- r2 & 0x3f
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+
+    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
+    rsb     r3, r2, #32                 @  r3<- 32 - r2
+    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
+    subs    ip, r2, #32                 @  ip<- r2 - 32
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
+    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
+    b       .LOP_USHR_LONG_2ADDR_finish
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
+/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
+/* File: arm-vfp/fbinop2addr.S */
+    /*
+     * Generic 32-bit floating point "/2addr" binary operation.  Provide
+     * an "instr" line that specifies an instruction that performs
+     * "s2 = s0 op s1".
+     *
+     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    and     r9, r9, #15                 @ r9<- A
+    flds    s1, [r3]                    @ s1<- vB
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    flds    s0, [r9]                    @ s0<- vA
+
+    fadds   s2, s0, s1                              @ s2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fsts    s2, [r9]                    @ vAA<- s2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
+/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
+/* File: arm-vfp/fbinop2addr.S */
+    /*
+     * Generic 32-bit floating point "/2addr" binary operation.  Provide
+     * an "instr" line that specifies an instruction that performs
+     * "s2 = s0 op s1".
+     *
+     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    and     r9, r9, #15                 @ r9<- A
+    flds    s1, [r3]                    @ s1<- vB
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    flds    s0, [r9]                    @ s0<- vA
+
+    fsubs   s2, s0, s1                              @ s2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fsts    s2, [r9]                    @ vAA<- s2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
+/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
+/* File: arm-vfp/fbinop2addr.S */
+    /*
+     * Generic 32-bit floating point "/2addr" binary operation.  Provide
+     * an "instr" line that specifies an instruction that performs
+     * "s2 = s0 op s1".
+     *
+     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    and     r9, r9, #15                 @ r9<- A
+    flds    s1, [r3]                    @ s1<- vB
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    flds    s0, [r9]                    @ s0<- vA
+
+    fmuls   s2, s0, s1                              @ s2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fsts    s2, [r9]                    @ vAA<- s2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
+/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
+/* File: arm-vfp/fbinop2addr.S */
+    /*
+     * Generic 32-bit floating point "/2addr" binary operation.  Provide
+     * an "instr" line that specifies an instruction that performs
+     * "s2 = s0 op s1".
+     *
+     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    and     r9, r9, #15                 @ r9<- A
+    flds    s1, [r3]                    @ s1<- vB
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    flds    s0, [r9]                    @ s0<- vA
+
+    fdivs   s2, s0, s1                              @ s2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fsts    s2, [r9]                    @ vAA<- s2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_REM_FLOAT_2ADDR: /* 0xca */
+/* File: armv6t2/OP_REM_FLOAT_2ADDR.S */
+/* EABI doesn't define a float remainder function, but libm does */
+/* File: armv6t2/binop2addr.S */
+    /*
+     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
+     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
+     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
+     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r1, r3)                    @ r1<- vB
+    GET_VREG(r0, r9)                    @ r0<- vA
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    bl      fmodf                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
+/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
+/* File: arm-vfp/fbinopWide2addr.S */
+    /*
+     * Generic 64-bit floating point "/2addr" binary operation.  Provide
+     * an "instr" line that specifies an instruction that performs
+     * "d2 = d0 op d1".
+     *
+     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
+     *      div-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    and     r9, r9, #15                 @ r9<- A
+    fldd    d1, [r3]                    @ d1<- vB
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    fldd    d0, [r9]                    @ d0<- vA
+
+    faddd   d2, d0, d1                              @ d2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fstd    d2, [r9]                    @ vAA<- d2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
+/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
+/* File: arm-vfp/fbinopWide2addr.S */
+    /*
+     * Generic 64-bit floating point "/2addr" binary operation.  Provide
+     * an "instr" line that specifies an instruction that performs
+     * "d2 = d0 op d1".
+     *
+     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
+     *      div-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    and     r9, r9, #15                 @ r9<- A
+    fldd    d1, [r3]                    @ d1<- vB
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    fldd    d0, [r9]                    @ d0<- vA
+
+    fsubd   d2, d0, d1                              @ d2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fstd    d2, [r9]                    @ vAA<- d2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
+/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
+/* File: arm-vfp/fbinopWide2addr.S */
+    /*
+     * Generic 64-bit floating point "/2addr" binary operation.  Provide
+     * an "instr" line that specifies an instruction that performs
+     * "d2 = d0 op d1".
+     *
+     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
+     *      div-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    and     r9, r9, #15                 @ r9<- A
+    fldd    d1, [r3]                    @ d1<- vB
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    fldd    d0, [r9]                    @ d0<- vA
+
+    fmuld   d2, d0, d1                              @ d2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fstd    d2, [r9]                    @ vAA<- d2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
+/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
+/* File: arm-vfp/fbinopWide2addr.S */
+    /*
+     * Generic 64-bit floating point "/2addr" binary operation.  Provide
+     * an "instr" line that specifies an instruction that performs
+     * "d2 = d0 op d1".
+     *
+     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
+     *      div-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r3, rINST, lsr #12          @ r3<- B
+    mov     r9, rINST, lsr #8           @ r9<- A+
+    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
+    and     r9, r9, #15                 @ r9<- A
+    fldd    d1, [r3]                    @ d1<- vB
+    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+    fldd    d0, [r9]                    @ d0<- vA
+
+    fdivd   d2, d0, d1                              @ d2<- op
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    fstd    d2, [r9]                    @ vAA<- d2
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
+/* File: armv6t2/OP_REM_DOUBLE_2ADDR.S */
+/* EABI doesn't define a double remainder function, but libm does */
+/* File: armv6t2/binopWide2addr.S */
+    /*
+     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
+     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
+     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
+     *      rem-double/2addr
+     */
+    /* binop/2addr vA, vB */
+    mov     r1, rINST, lsr #12          @ r1<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
+    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    .if 0
+    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    bl      fmod                              @ result<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 12-15 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_ADD_INT_LIT16: /* 0xd0 */
+/* File: armv6t2/OP_ADD_INT_LIT16.S */
+/* File: armv6t2/binopLit16.S */
+    /*
+     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+     */
+    /* binop/lit16 vA, vB, #+CCCC */
+    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
+    mov     r2, rINST, lsr #12          @ r2<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r0, r2)                    @ r0<- vB
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_RSUB_INT: /* 0xd1 */
+/* File: armv6t2/OP_RSUB_INT.S */
+/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
+/* File: armv6t2/binopLit16.S */
+    /*
+     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+     */
+    /* binop/lit16 vA, vB, #+CCCC */
+    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
+    mov     r2, rINST, lsr #12          @ r2<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r0, r2)                    @ r0<- vB
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MUL_INT_LIT16: /* 0xd2 */
+/* File: armv6t2/OP_MUL_INT_LIT16.S */
+/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
+/* File: armv6t2/binopLit16.S */
+    /*
+     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+     */
+    /* binop/lit16 vA, vB, #+CCCC */
+    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
+    mov     r2, rINST, lsr #12          @ r2<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r0, r2)                    @ r0<- vB
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_DIV_INT_LIT16: /* 0xd3 */
+/* File: armv6t2/OP_DIV_INT_LIT16.S */
+/* File: armv6t2/binopLit16.S */
+    /*
+     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+     */
+    /* binop/lit16 vA, vB, #+CCCC */
+    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
+    mov     r2, rINST, lsr #12          @ r2<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r0, r2)                    @ r0<- vB
+    .if 1
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_REM_INT_LIT16: /* 0xd4 */
+/* File: armv6t2/OP_REM_INT_LIT16.S */
+/* idivmod returns quotient in r0 and remainder in r1 */
+/* File: armv6t2/binopLit16.S */
+    /*
+     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+     */
+    /* binop/lit16 vA, vB, #+CCCC */
+    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
+    mov     r2, rINST, lsr #12          @ r2<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r0, r2)                    @ r0<- vB
+    .if 1
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r1, r9)               @ vAA<- r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_AND_INT_LIT16: /* 0xd5 */
+/* File: armv6t2/OP_AND_INT_LIT16.S */
+/* File: armv6t2/binopLit16.S */
+    /*
+     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+     */
+    /* binop/lit16 vA, vB, #+CCCC */
+    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
+    mov     r2, rINST, lsr #12          @ r2<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r0, r2)                    @ r0<- vB
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_OR_INT_LIT16: /* 0xd6 */
+/* File: armv6t2/OP_OR_INT_LIT16.S */
+/* File: armv6t2/binopLit16.S */
+    /*
+     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+     */
+    /* binop/lit16 vA, vB, #+CCCC */
+    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
+    mov     r2, rINST, lsr #12          @ r2<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r0, r2)                    @ r0<- vB
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_XOR_INT_LIT16: /* 0xd7 */
+/* File: armv6t2/OP_XOR_INT_LIT16.S */
+/* File: armv6t2/binopLit16.S */
+    /*
+     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
+     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
+     */
+    /* binop/lit16 vA, vB, #+CCCC */
+    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
+    mov     r2, rINST, lsr #12          @ r2<- B
+    ubfx    r9, rINST, #8, #4           @ r9<- A
+    GET_VREG(r0, r2)                    @ r0<- vB
+    .if 0
+    cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-13 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_ADD_INT_LIT8: /* 0xd8 */
+/* File: armv5te/OP_ADD_INT_LIT8.S */
+/* File: armv5te/binopLit8.S */
+    /*
+     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
+     */
+    /* binop/lit8 vAA, vBB, #+CC */
+    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r3, #255                @ r2<- BB
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
+    .if 0
+    @cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-12 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_RSUB_INT_LIT8: /* 0xd9 */
+/* File: armv5te/OP_RSUB_INT_LIT8.S */
+/* File: armv5te/binopLit8.S */
+    /*
+     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
+     */
+    /* binop/lit8 vAA, vBB, #+CC */
+    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r3, #255                @ r2<- BB
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
+    .if 0
+    @cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-12 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_MUL_INT_LIT8: /* 0xda */
+/* File: armv5te/OP_MUL_INT_LIT8.S */
+/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
+/* File: armv5te/binopLit8.S */
+    /*
+     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
+     */
+    /* binop/lit8 vAA, vBB, #+CC */
+    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r3, #255                @ r2<- BB
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
+    .if 0
+    @cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-12 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_DIV_INT_LIT8: /* 0xdb */
+/* File: armv5te/OP_DIV_INT_LIT8.S */
+/* File: armv5te/binopLit8.S */
+    /*
+     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
+     */
+    /* binop/lit8 vAA, vBB, #+CC */
+    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r3, #255                @ r2<- BB
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
+    .if 1
+    @cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-12 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_REM_INT_LIT8: /* 0xdc */
+/* File: armv5te/OP_REM_INT_LIT8.S */
+/* idivmod returns quotient in r0 and remainder in r1 */
+/* File: armv5te/binopLit8.S */
+    /*
+     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
+     */
+    /* binop/lit8 vAA, vBB, #+CC */
+    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r3, #255                @ r2<- BB
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
+    .if 1
+    @cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r1, r9)               @ vAA<- r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-12 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_AND_INT_LIT8: /* 0xdd */
+/* File: armv5te/OP_AND_INT_LIT8.S */
+/* File: armv5te/binopLit8.S */
+    /*
+     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
+     */
+    /* binop/lit8 vAA, vBB, #+CC */
+    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r3, #255                @ r2<- BB
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
+    .if 0
+    @cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-12 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_OR_INT_LIT8: /* 0xde */
+/* File: armv5te/OP_OR_INT_LIT8.S */
+/* File: armv5te/binopLit8.S */
+    /*
+     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
+     */
+    /* binop/lit8 vAA, vBB, #+CC */
+    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r3, #255                @ r2<- BB
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
+    .if 0
+    @cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-12 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_XOR_INT_LIT8: /* 0xdf */
+/* File: armv5te/OP_XOR_INT_LIT8.S */
+/* File: armv5te/binopLit8.S */
+    /*
+     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
+     */
+    /* binop/lit8 vAA, vBB, #+CC */
+    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r3, #255                @ r2<- BB
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
+    .if 0
+    @cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+                               @ optional op; may set condition codes
+    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-12 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SHL_INT_LIT8: /* 0xe0 */
+/* File: armv5te/OP_SHL_INT_LIT8.S */
+/* File: armv5te/binopLit8.S */
+    /*
+     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
+     */
+    /* binop/lit8 vAA, vBB, #+CC */
+    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r3, #255                @ r2<- BB
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
+    .if 0
+    @cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    and     r1, r1, #31                           @ optional op; may set condition codes
+    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-12 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_SHR_INT_LIT8: /* 0xe1 */
+/* File: armv5te/OP_SHR_INT_LIT8.S */
+/* File: armv5te/binopLit8.S */
+    /*
+     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
+     */
+    /* binop/lit8 vAA, vBB, #+CC */
+    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r3, #255                @ r2<- BB
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
+    .if 0
+    @cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    and     r1, r1, #31                           @ optional op; may set condition codes
+    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-12 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_USHR_INT_LIT8: /* 0xe2 */
+/* File: armv5te/OP_USHR_INT_LIT8.S */
+/* File: armv5te/binopLit8.S */
+    /*
+     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
+     * that specifies an instruction that performs "result = r0 op r1".
+     * This could be an ARM instruction or a function call.  (If the result
+     * comes back in a register other than r0, you can override "result".)
+     *
+     * If "chkzero" is set to 1, we perform a divide-by-zero check on
+     * vCC (r1).  Useful for integer division and modulus.
+     *
+     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
+     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
+     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
+     */
+    /* binop/lit8 vAA, vBB, #+CC */
+    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    and     r2, r3, #255                @ r2<- BB
+    GET_VREG(r0, r2)                    @ r0<- vBB
+    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
+    .if 0
+    @cmp     r1, #0                      @ is second operand zero?
+    beq     common_errDivideByZero
+    .endif
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+
+    and     r1, r1, #31                           @ optional op; may set condition codes
+    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)               @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+    /* 10-12 instructions */
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_E3: /* 0xe3 */
+/* File: armv5te/OP_UNUSED_E3.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_E4: /* 0xe4 */
+/* File: armv5te/OP_UNUSED_E4.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_E5: /* 0xe5 */
+/* File: armv5te/OP_UNUSED_E5.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_E6: /* 0xe6 */
+/* File: armv5te/OP_UNUSED_E6.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_E7: /* 0xe7 */
+/* File: armv5te/OP_UNUSED_E7.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_E8: /* 0xe8 */
+/* File: armv5te/OP_UNUSED_E8.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_E9: /* 0xe9 */
+/* File: armv5te/OP_UNUSED_E9.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_EA: /* 0xea */
+/* File: armv5te/OP_UNUSED_EA.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_EB: /* 0xeb */
+/* File: armv5te/OP_UNUSED_EB.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_EC: /* 0xec */
+/* File: armv5te/OP_UNUSED_EC.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
+/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
+    /*
+     * Handle a throw-verification-error instruction.  This throws an
+     * exception for an error discovered during verification.  The
+     * exception is indicated by AA, with some detail provided by BBBB.
+     */
+    /* op AA, ref@BBBB */
+    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
+    FETCH(r2, 1)                        @ r2<- BBBB
+    EXPORT_PC()                         @ export the PC
+    mov     r1, rINST, lsr #8           @ r1<- AA
+    bl      dvmThrowVerificationError   @ always throws
+    b       common_exceptionThrown      @ handle exception
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_EXECUTE_INLINE: /* 0xee */
+/* File: armv5te/OP_EXECUTE_INLINE.S */
+    /*
+     * Execute a "native inline" instruction.
+     *
+     * We need to call:
+     *  dvmPerformInlineOp4Std(arg0, arg1, arg2, arg3, &retval, ref)
+     *
+     * The first four args are in r0-r3, but the last two must be pushed
+     * onto the stack.
+     */
+    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
+    FETCH(r10, 1)                       @ r10<- BBBB
+    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
+    EXPORT_PC()                         @ can throw
+    sub     sp, sp, #8                  @ make room for arg(s)
+    mov     r0, rINST, lsr #12          @ r0<- B
+    str     r1, [sp]                    @ push &glue->retval
+    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
+    add     sp, sp, #8                  @ pop stack
+    cmp     r0, #0                      @ test boolean result of inline
+    beq     common_exceptionThrown      @ returned false, handle exception
+    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_EF: /* 0xef */
+/* File: armv5te/OP_UNUSED_EF.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
+/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
+    /*
+     * invoke-direct-empty is a no-op in a "standard" interpreter.
+     */
+    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
+    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
+    GOTO_OPCODE(ip)                     @ execute it
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_F1: /* 0xf1 */
+/* File: armv5te/OP_UNUSED_F1.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IGET_QUICK: /* 0xf2 */
+/* File: armv6t2/OP_IGET_QUICK.S */
+    /* For: iget-quick, iget-object-quick */
+    /* op vA, vB, offset@CCCC */
+    mov     r2, rINST, lsr #12          @ r2<- B
+    FETCH(r1, 1)                        @ r1<- field byte offset
+    GET_VREG(r3, r2)                    @ r3<- object we're operating on
+    ubfx    r2, rINST, #8, #4           @ r2<- A
+    cmp     r3, #0                      @ check object for null
+    beq     common_errNullObject        @ object was null
+    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r2)                    @ fp[A]<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
+/* File: armv6t2/OP_IGET_WIDE_QUICK.S */
+    /* iget-wide-quick vA, vB, offset@CCCC */
+    mov     r2, rINST, lsr #12          @ r2<- B
+    FETCH(r1, 1)                        @ r1<- field byte offset
+    GET_VREG(r3, r2)                    @ r3<- object we're operating on
+    ubfx    r2, rINST, #8, #4           @ r2<- A
+    cmp     r3, #0                      @ check object for null
+    beq     common_errNullObject        @ object was null
+    ldrd    r0, [r3, r1]                @ r0<- obj.field (64 bits, aligned)
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
+/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
+/* File: armv5te/OP_IGET_QUICK.S */
+    /* For: iget-quick, iget-object-quick */
+    /* op vA, vB, offset@CCCC */
+    mov     r2, rINST, lsr #12          @ r2<- B
+    GET_VREG(r3, r2)                    @ r3<- object we're operating on
+    FETCH(r1, 1)                        @ r1<- field byte offset
+    cmp     r3, #0                      @ check object for null
+    mov     r2, rINST, lsr #8           @ r2<- A(+)
+    beq     common_errNullObject        @ object was null
+    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r2, r2, #15
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r2)                    @ fp[A]<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IPUT_QUICK: /* 0xf5 */
+/* File: armv6t2/OP_IPUT_QUICK.S */
+    /* For: iput-quick, iput-object-quick */
+    /* op vA, vB, offset@CCCC */
+    mov     r2, rINST, lsr #12          @ r2<- B
+    FETCH(r1, 1)                        @ r1<- field byte offset
+    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
+    ubfx    r2, rINST, #8, #4           @ r2<- A
+    cmp     r3, #0                      @ check object for null
+    beq     common_errNullObject        @ object was null
+    GET_VREG(r0, r2)                    @ r0<- fp[A]
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
+/* File: armv6t2/OP_IPUT_WIDE_QUICK.S */
+    /* iput-wide-quick vA, vB, offset@CCCC */
+    mov     r1, rINST, lsr #12          @ r1<- B
+    ubfx    r0, rINST, #8, #4           @ r0<- A
+    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
+    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
+    cmp     r2, #0                      @ check object for null
+    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
+    beq     common_errNullObject        @ object was null
+    FETCH(r3, 1)                        @ r3<- field byte offset
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
+/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
+/* File: armv5te/OP_IPUT_QUICK.S */
+    /* For: iput-quick, iput-object-quick */
+    /* op vA, vB, offset@CCCC */
+    mov     r2, rINST, lsr #12          @ r2<- B
+    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
+    FETCH(r1, 1)                        @ r1<- field byte offset
+    cmp     r3, #0                      @ check object for null
+    mov     r2, rINST, lsr #8           @ r2<- A(+)
+    beq     common_errNullObject        @ object was null
+    and     r2, r2, #15
+    GET_VREG(r0, r2)                    @ r0<- fp[A]
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
+/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
+    /*
+     * Handle an optimized virtual method call.
+     *
+     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
+    FETCH(r1, 1)                        @ r1<- BBBB
+    .if     (!0)
+    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
+    .endif
+    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
+    cmp     r2, #0                      @ is "this" null?
+    beq     common_errNullObject        @ null "this", throw exception
+    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
+    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
+    EXPORT_PC()                         @ invoke must export
+    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
+    bl      common_invokeMethodNoRange @ continue on
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
+/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
+/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
+    /*
+     * Handle an optimized virtual method call.
+     *
+     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
+    FETCH(r1, 1)                        @ r1<- BBBB
+    .if     (!1)
+    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
+    .endif
+    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
+    cmp     r2, #0                      @ is "this" null?
+    beq     common_errNullObject        @ null "this", throw exception
+    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
+    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
+    EXPORT_PC()                         @ invoke must export
+    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
+    bl      common_invokeMethodRange @ continue on
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
+/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
+    /*
+     * Handle an optimized "super" method call.
+     *
+     * for: [opt] invoke-super-quick, invoke-super-quick/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    FETCH(r10, 2)                       @ r10<- GFED or CCCC
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    .if     (!0)
+    and     r10, r10, #15               @ r10<- D (or stays CCCC)
+    .endif
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
+    EXPORT_PC()                         @ must export for invoke
+    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
+    GET_VREG(r3, r10)                   @ r3<- "this"
+    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
+    cmp     r3, #0                      @ null "this" ref?
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
+    beq     common_errNullObject        @ "this" is null, throw exception
+    bl      common_invokeMethodNoRange @ continue on
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
+/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
+/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
+    /*
+     * Handle an optimized "super" method call.
+     *
+     * for: [opt] invoke-super-quick, invoke-super-quick/range
+     */
+    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
+    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
+    FETCH(r10, 2)                       @ r10<- GFED or CCCC
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    .if     (!1)
+    and     r10, r10, #15               @ r10<- D (or stays CCCC)
+    .endif
+    FETCH(r1, 1)                        @ r1<- BBBB
+    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
+    EXPORT_PC()                         @ must export for invoke
+    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
+    GET_VREG(r3, r10)                   @ r3<- "this"
+    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
+    cmp     r3, #0                      @ null "this" ref?
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
+    beq     common_errNullObject        @ "this" is null, throw exception
+    bl      common_invokeMethodRange @ continue on
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_FC: /* 0xfc */
+/* File: armv5te/OP_UNUSED_FC.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_FD: /* 0xfd */
+/* File: armv5te/OP_UNUSED_FD.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_FE: /* 0xfe */
+/* File: armv5te/OP_UNUSED_FE.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+/* ------------------------------ */
+    .balign 64
+.L_OP_UNUSED_FF: /* 0xff */
+/* File: armv5te/OP_UNUSED_FF.S */
+/* File: armv5te/unused.S */
+    bl      common_abort
+
+
+
+
+    .balign 64
+    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
+    .global dvmAsmInstructionEnd
+dvmAsmInstructionEnd:
+
+/*
+ * ===========================================================================
+ *  Sister implementations
+ * ===========================================================================
+ */
+    .global dvmAsmSisterStart
+    .type   dvmAsmSisterStart, %function
+    .text
+    .balign 4
+dvmAsmSisterStart:
+
+/* continuation for OP_CONST_STRING */
+
+    /*
+     * Continuation if the String has not yet been resolved.
+     *  r1: BBBB (String ref)
+     *  r9: target register
+     */
+.LOP_CONST_STRING_resolve:
+    EXPORT_PC()
+    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
+    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveString            @ r0<- String reference
+    cmp     r0, #0                      @ failed?
+    beq     common_exceptionThrown      @ yup, handle the exception
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_CONST_STRING_JUMBO */
+
+    /*
+     * Continuation if the String has not yet been resolved.
+     *  r1: BBBBBBBB (String ref)
+     *  r9: target register
+     */
+.LOP_CONST_STRING_JUMBO_resolve:
+    EXPORT_PC()
+    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
+    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveString            @ r0<- String reference
+    cmp     r0, #0                      @ failed?
+    beq     common_exceptionThrown      @ yup, handle the exception
+    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_CONST_CLASS */
+
+    /*
+     * Continuation if the Class has not yet been resolved.
+     *  r1: BBBB (Class ref)
+     *  r9: target register
+     */
+.LOP_CONST_CLASS_resolve:
+    EXPORT_PC()
+    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
+    mov     r2, #1                      @ r2<- true
+    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveClass             @ r0<- Class reference
+    cmp     r0, #0                      @ failed?
+    beq     common_exceptionThrown      @ yup, handle the exception
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_CHECK_CAST */
+
+    /*
+     * Trivial test failed, need to perform full check.  This is common.
+     *  r0 holds obj->clazz
+     *  r1 holds class resolved from BBBB
+     *  r9 holds object
+     */
+.LOP_CHECK_CAST_fullcheck:
+    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
+    cmp     r0, #0                      @ failed?
+    bne     .LOP_CHECK_CAST_okay            @ no, success
+
+    @ A cast has failed.  We need to throw a ClassCastException with the
+    @ class of the object that failed to be cast.
+    EXPORT_PC()                         @ about to throw
+    ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
+    ldr     r0, .LstrClassCastExceptionPtr
+    ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
+    bl      dvmThrowExceptionWithClassMessage
+    b       common_exceptionThrown
+
+    /*
+     * Resolution required.  This is the least-likely path.
+     *
+     *  r2 holds BBBB
+     *  r9 holds object
+     */
+.LOP_CHECK_CAST_resolve:
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
+    mov     r1, r2                      @ r1<- BBBB
+    mov     r2, #0                      @ r2<- false
+    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
+    cmp     r0, #0                      @ got null?
+    beq     common_exceptionThrown      @ yes, handle exception
+    mov     r1, r0                      @ r1<- class resolved from BBB
+    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
+    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
+
+.LstrClassCastExceptionPtr:
+    .word   .LstrClassCastException
+
+
+/* continuation for OP_INSTANCE_OF */
+
+    /*
+     * Trivial test failed, need to perform full check.  This is common.
+     *  r0 holds obj->clazz
+     *  r1 holds class resolved from BBBB
+     *  r9 holds A
+     */
+.LOP_INSTANCE_OF_fullcheck:
+    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
+    @ fall through to OP_INSTANCE_OF_store
+
+    /*
+     * r0 holds boolean result
+     * r9 holds A
+     */
+.LOP_INSTANCE_OF_store:
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    SET_VREG(r0, r9)                    @ vA<- r0
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+    /*
+     * Trivial test succeeded, save and bail.
+     *  r9 holds A
+     */
+.LOP_INSTANCE_OF_trivial:
+    mov     r0, #1                      @ indicate success
+    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    SET_VREG(r0, r9)                    @ vA<- r0
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+    /*
+     * Resolution required.  This is the least-likely path.
+     *
+     *  r3 holds BBBB
+     *  r9 holds A
+     */
+.LOP_INSTANCE_OF_resolve:
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
+    mov     r1, r3                      @ r1<- BBBB
+    mov     r2, #1                      @ r2<- true
+    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
+    cmp     r0, #0                      @ got null?
+    beq     common_exceptionThrown      @ yes, handle exception
+    mov     r1, r0                      @ r1<- class resolved from BBB
+    mov     r3, rINST, lsr #12          @ r3<- B
+    GET_VREG(r0, r3)                    @ r0<- vB (object)
+    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
+    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
+
+
+/* continuation for OP_NEW_INSTANCE */
+
+    .balign 32                          @ minimize cache lines
+.LOP_NEW_INSTANCE_finish: @ r0=new object
+    mov     r3, rINST, lsr #8           @ r3<- AA
+    cmp     r0, #0                      @ failed?
+    beq     common_exceptionThrown      @ yes, handle the exception
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r3)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+    /*
+     * Class initialization required.
+     *
+     *  r0 holds class object
+     */
+.LOP_NEW_INSTANCE_needinit:
+    mov     r9, r0                      @ save r0
+    bl      dvmInitClass                @ initialize class
+    cmp     r0, #0                      @ check boolean result
+    mov     r0, r9                      @ restore r0
+    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
+    b       common_exceptionThrown      @ failed, deal with init exception
+
+    /*
+     * Resolution required.  This is the least-likely path.
+     *
+     *  r1 holds BBBB
+     */
+.LOP_NEW_INSTANCE_resolve:
+    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
+    mov     r2, #0                      @ r2<- false
+    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
+    cmp     r0, #0                      @ got null?
+    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
+    b       common_exceptionThrown      @ yes, handle exception
+
+.LstrInstantiationErrorPtr:
+    .word   .LstrInstantiationError
+
+
+/* continuation for OP_NEW_ARRAY */
+
+
+    /*
+     * Resolve class.  (This is an uncommon case.)
+     *
+     *  r1 holds array length
+     *  r2 holds class ref CCCC
+     */
+.LOP_NEW_ARRAY_resolve:
+    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
+    mov     r9, r1                      @ r9<- length (save)
+    mov     r1, r2                      @ r1<- CCCC
+    mov     r2, #0                      @ r2<- false
+    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveClass             @ r0<- call(clazz, ref)
+    cmp     r0, #0                      @ got null?
+    mov     r1, r9                      @ r1<- length (restore)
+    beq     common_exceptionThrown      @ yes, handle exception
+    @ fall through to OP_NEW_ARRAY_finish
+
+    /*
+     * Finish allocation.
+     *
+     *  r0 holds class
+     *  r1 holds array length
+     */
+.LOP_NEW_ARRAY_finish:
+    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
+    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
+    cmp     r0, #0                      @ failed?
+    mov     r2, rINST, lsr #8           @ r2<- A+
+    beq     common_exceptionThrown      @ yes, handle the exception
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r2, r2, #15                 @ r2<- A
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r2)                    @ vA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_FILLED_NEW_ARRAY */
+
+    /*
+     * On entry:
+     *  r0 holds array class
+     *  r10 holds AA or BA
+     */
+.LOP_FILLED_NEW_ARRAY_continue:
+    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
+    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
+    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
+    .if     0
+    mov     r1, r10                     @ r1<- AA (length)
+    .else
+    mov     r1, r10, lsr #4             @ r1<- B (length)
+    .endif
+    cmp     r3, #'I'                    @ array of ints?
+    cmpne   r3, #'L'                    @ array of objects?
+    cmpne   r3, #'['                    @ array of arrays?
+    mov     r9, r1                      @ save length in r9
+    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
+    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
+    cmp     r0, #0                      @ null return?
+    beq     common_exceptionThrown      @ alloc failed, handle exception
+
+    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
+    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
+    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
+    subs    r9, r9, #1                  @ length--, check for neg
+    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
+    bmi     2f                          @ was zero, bail
+
+    @ copy values from registers into the array
+    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
+    .if     0
+    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
+1:  ldr     r3, [r2], #4                @ r3<- *r2++
+    subs    r9, r9, #1                  @ count--
+    str     r3, [r0], #4                @ *contents++ = vX
+    bpl     1b
+    @ continue at 2
+    .else
+    cmp     r9, #4                      @ length was initially 5?
+    and     r2, r10, #15                @ r2<- A
+    bne     1f                          @ <= 4 args, branch
+    GET_VREG(r3, r2)                    @ r3<- vA
+    sub     r9, r9, #1                  @ count--
+    str     r3, [r0, #16]               @ contents[4] = vA
+1:  and     r2, r1, #15                 @ r2<- F/E/D/C
+    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
+    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
+    subs    r9, r9, #1                  @ count--
+    str     r3, [r0], #4                @ *contents++ = vX
+    bpl     1b
+    @ continue at 2
+    .endif
+
+2:
+    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
+    GOTO_OPCODE(ip)                     @ execute it
+
+    /*
+     * Throw an exception indicating that we have not implemented this
+     * mode of filled-new-array.
+     */
+.LOP_FILLED_NEW_ARRAY_notimpl:
+    ldr     r0, .L_strInternalError
+    ldr     r1, .L_strFilledNewArrayNotImpl
+    bl      dvmThrowException
+    b       common_exceptionThrown
+
+    .if     (!0)                 @ define in one or the other, not both
+.L_strFilledNewArrayNotImpl:
+    .word   .LstrFilledNewArrayNotImpl
+.L_strInternalError:
+    .word   .LstrInternalError
+    .endif
+
+
+/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
+
+    /*
+     * On entry:
+     *  r0 holds array class
+     *  r10 holds AA or BA
+     */
+.LOP_FILLED_NEW_ARRAY_RANGE_continue:
+    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
+    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
+    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
+    .if     1
+    mov     r1, r10                     @ r1<- AA (length)
+    .else
+    mov     r1, r10, lsr #4             @ r1<- B (length)
+    .endif
+    cmp     r3, #'I'                    @ array of ints?
+    cmpne   r3, #'L'                    @ array of objects?
+    cmpne   r3, #'['                    @ array of arrays?
+    mov     r9, r1                      @ save length in r9
+    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
+    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
+    cmp     r0, #0                      @ null return?
+    beq     common_exceptionThrown      @ alloc failed, handle exception
+
+    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
+    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
+    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
+    subs    r9, r9, #1                  @ length--, check for neg
+    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
+    bmi     2f                          @ was zero, bail
+
+    @ copy values from registers into the array
+    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
+    .if     1
+    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
+1:  ldr     r3, [r2], #4                @ r3<- *r2++
+    subs    r9, r9, #1                  @ count--
+    str     r3, [r0], #4                @ *contents++ = vX
+    bpl     1b
+    @ continue at 2
+    .else
+    cmp     r9, #4                      @ length was initially 5?
+    and     r2, r10, #15                @ r2<- A
+    bne     1f                          @ <= 4 args, branch
+    GET_VREG(r3, r2)                    @ r3<- vA
+    sub     r9, r9, #1                  @ count--
+    str     r3, [r0, #16]               @ contents[4] = vA
+1:  and     r2, r1, #15                 @ r2<- F/E/D/C
+    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
+    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
+    subs    r9, r9, #1                  @ count--
+    str     r3, [r0], #4                @ *contents++ = vX
+    bpl     1b
+    @ continue at 2
+    .endif
+
+2:
+    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
+    GOTO_OPCODE(ip)                     @ execute it
+
+    /*
+     * Throw an exception indicating that we have not implemented this
+     * mode of filled-new-array.
+     */
+.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
+    ldr     r0, .L_strInternalError
+    ldr     r1, .L_strFilledNewArrayNotImpl
+    bl      dvmThrowException
+    b       common_exceptionThrown
+
+    .if     (!1)                 @ define in one or the other, not both
+.L_strFilledNewArrayNotImpl:
+    .word   .LstrFilledNewArrayNotImpl
+.L_strInternalError:
+    .word   .LstrInternalError
+    .endif
+
+
+/* continuation for OP_CMPL_FLOAT */
+.LOP_CMPL_FLOAT_finish:
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_CMPG_FLOAT */
+.LOP_CMPG_FLOAT_finish:
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_CMPL_DOUBLE */
+.LOP_CMPL_DOUBLE_finish:
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_CMPG_DOUBLE */
+.LOP_CMPG_DOUBLE_finish:
+    SET_VREG(r0, r9)                    @ vAA<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_CMP_LONG */
+
+.LOP_CMP_LONG_less:
+    mvn     r1, #0                      @ r1<- -1
+    @ Want to cond code the next mov so we can avoid branch, but don't see it;
+    @ instead, we just replicate the tail end.
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    SET_VREG(r1, r9)                    @ vAA<- r1
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+.LOP_CMP_LONG_greater:
+    mov     r1, #1                      @ r1<- 1
+    @ fall through to _finish
+
+.LOP_CMP_LONG_finish:
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    SET_VREG(r1, r9)                    @ vAA<- r1
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_AGET_WIDE */
+
+.LOP_AGET_WIDE_finish:
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_APUT_WIDE */
+
+.LOP_APUT_WIDE_finish:
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_APUT_OBJECT */
+    /*
+     * On entry:
+     *  r1 = vBB (arrayObj)
+     *  r9 = vAA (obj)
+     *  r10 = offset into array (vBB + vCC * width)
+     */
+.LOP_APUT_OBJECT_finish:
+    cmp     r9, #0                      @ storing null reference?
+    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
+    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
+    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
+    bl      dvmCanPutArrayElement       @ test object type vs. array type
+    cmp     r0, #0                      @ okay?
+    beq     common_errArrayStore        @ no
+.LOP_APUT_OBJECT_skip_check:
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IGET */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IGET_finish:
+    @bl      common_squeak0
+    cmp     r9, #0                      @ check object for null
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    beq     common_errNullObject        @ object was null
+    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
+    ubfx    r2, rINST, #8, #4           @ r2<- A
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r2)                    @ fp[A]<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IGET_WIDE */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IGET_WIDE_finish:
+    cmp     r9, #0                      @ check object for null
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    beq     common_errNullObject        @ object was null
+    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
+    ubfx    r2, rINST, #8, #4           @ r2<- A
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IGET_OBJECT */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IGET_OBJECT_finish:
+    @bl      common_squeak0
+    cmp     r9, #0                      @ check object for null
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    beq     common_errNullObject        @ object was null
+    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
+    mov     r2, rINST, lsr #8           @ r2<- A+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r2, r2, #15                 @ r2<- A
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r2)                    @ fp[A]<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IGET_BOOLEAN */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IGET_BOOLEAN_finish:
+    @bl      common_squeak1
+    cmp     r9, #0                      @ check object for null
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    beq     common_errNullObject        @ object was null
+    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
+    mov     r2, rINST, lsr #8           @ r2<- A+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r2, r2, #15                 @ r2<- A
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r2)                    @ fp[A]<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IGET_BYTE */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IGET_BYTE_finish:
+    @bl      common_squeak2
+    cmp     r9, #0                      @ check object for null
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    beq     common_errNullObject        @ object was null
+    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
+    mov     r2, rINST, lsr #8           @ r2<- A+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r2, r2, #15                 @ r2<- A
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r2)                    @ fp[A]<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IGET_CHAR */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IGET_CHAR_finish:
+    @bl      common_squeak3
+    cmp     r9, #0                      @ check object for null
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    beq     common_errNullObject        @ object was null
+    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
+    mov     r2, rINST, lsr #8           @ r2<- A+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r2, r2, #15                 @ r2<- A
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r2)                    @ fp[A]<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IGET_SHORT */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IGET_SHORT_finish:
+    @bl      common_squeak4
+    cmp     r9, #0                      @ check object for null
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    beq     common_errNullObject        @ object was null
+    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
+    mov     r2, rINST, lsr #8           @ r2<- A+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r2, r2, #15                 @ r2<- A
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    SET_VREG(r0, r2)                    @ fp[A]<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IPUT */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IPUT_finish:
+    @bl      common_squeak0
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    ubfx    r1, rINST, #8, #4           @ r1<- A
+    cmp     r9, #0                      @ check object for null
+    GET_VREG(r0, r1)                    @ r0<- fp[A]
+    beq     common_errNullObject        @ object was null
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IPUT_WIDE */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IPUT_WIDE_finish:
+    ubfx    r2, rINST, #8, #4           @ r2<- A
+    cmp     r9, #0                      @ check object for null
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
+    beq     common_errNullObject        @ object was null
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IPUT_OBJECT */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IPUT_OBJECT_finish:
+    @bl      common_squeak0
+    mov     r1, rINST, lsr #8           @ r1<- A+
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    and     r1, r1, #15                 @ r1<- A
+    cmp     r9, #0                      @ check object for null
+    GET_VREG(r0, r1)                    @ r0<- fp[A]
+    beq     common_errNullObject        @ object was null
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IPUT_BOOLEAN */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IPUT_BOOLEAN_finish:
+    @bl      common_squeak1
+    mov     r1, rINST, lsr #8           @ r1<- A+
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    and     r1, r1, #15                 @ r1<- A
+    cmp     r9, #0                      @ check object for null
+    GET_VREG(r0, r1)                    @ r0<- fp[A]
+    beq     common_errNullObject        @ object was null
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IPUT_BYTE */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IPUT_BYTE_finish:
+    @bl      common_squeak2
+    mov     r1, rINST, lsr #8           @ r1<- A+
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    and     r1, r1, #15                 @ r1<- A
+    cmp     r9, #0                      @ check object for null
+    GET_VREG(r0, r1)                    @ r0<- fp[A]
+    beq     common_errNullObject        @ object was null
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IPUT_CHAR */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IPUT_CHAR_finish:
+    @bl      common_squeak3
+    mov     r1, rINST, lsr #8           @ r1<- A+
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    and     r1, r1, #15                 @ r1<- A
+    cmp     r9, #0                      @ check object for null
+    GET_VREG(r0, r1)                    @ r0<- fp[A]
+    beq     common_errNullObject        @ object was null
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IPUT_SHORT */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IPUT_SHORT_finish:
+    @bl      common_squeak4
+    mov     r1, rINST, lsr #8           @ r1<- A+
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    and     r1, r1, #15                 @ r1<- A
+    cmp     r9, #0                      @ check object for null
+    GET_VREG(r0, r1)                    @ r0<- fp[A]
+    beq     common_errNullObject        @ object was null
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_SGET */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     */
+.LOP_SGET_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SGET_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_SGET_WIDE */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     */
+.LOP_SGET_WIDE_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SGET_WIDE_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_SGET_OBJECT */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     */
+.LOP_SGET_OBJECT_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_SGET_BOOLEAN */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     */
+.LOP_SGET_BOOLEAN_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_SGET_BYTE */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     */
+.LOP_SGET_BYTE_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SGET_BYTE_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_SGET_CHAR */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     */
+.LOP_SGET_CHAR_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SGET_CHAR_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_SGET_SHORT */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     */
+.LOP_SGET_SHORT_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SGET_SHORT_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_SPUT */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     */
+.LOP_SPUT_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SPUT_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_SPUT_WIDE */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     *  r9: &fp[AA]
+     */
+.LOP_SPUT_WIDE_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_SPUT_OBJECT */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     */
+.LOP_SPUT_OBJECT_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_SPUT_BOOLEAN */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     */
+.LOP_SPUT_BOOLEAN_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_SPUT_BYTE */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     */
+.LOP_SPUT_BYTE_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_SPUT_CHAR */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     */
+.LOP_SPUT_CHAR_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_SPUT_SHORT */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     */
+.LOP_SPUT_SHORT_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_INVOKE_VIRTUAL */
+
+    /*
+     * At this point:
+     *  r0 = resolved base method
+     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
+     */
+.LOP_INVOKE_VIRTUAL_continue:
+    GET_VREG(r1, r10)                   @ r1<- "this" ptr
+    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
+    cmp     r1, #0                      @ is "this" null?
+    beq     common_errNullObject        @ null "this", throw exception
+    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
+    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
+    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
+    bl      common_invokeMethodNoRange @ continue on
+
+
+/* continuation for OP_INVOKE_SUPER */
+
+    /*
+     * At this point:
+     *  r0 = resolved base method
+     *  r9 = method->clazz
+     */
+.LOP_INVOKE_SUPER_continue:
+    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
+    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
+    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
+    EXPORT_PC()                         @ must export for invoke
+    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
+    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
+    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
+    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
+    bl      common_invokeMethodNoRange @ continue on
+
+.LOP_INVOKE_SUPER_resolve:
+    mov     r0, r9                      @ r0<- method->clazz
+    mov     r2, #METHOD_VIRTUAL         @ resolver method type
+    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
+    cmp     r0, #0                      @ got null?
+    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
+    b       common_exceptionThrown      @ yes, handle exception
+
+    /*
+     * Throw a NoSuchMethodError with the method name as the message.
+     *  r0 = resolved base method
+     */
+.LOP_INVOKE_SUPER_nsm:
+    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
+    b       common_errNoSuchMethod
+
+
+/* continuation for OP_INVOKE_DIRECT */
+
+    /*
+     * On entry:
+     *  r1 = reference (BBBB or CCCC)
+     *  r10 = "this" register
+     */
+.LOP_INVOKE_DIRECT_resolve:
+    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
+    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
+    mov     r2, #METHOD_DIRECT          @ resolver method type
+    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
+    cmp     r0, #0                      @ got null?
+    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
+    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
+    b       common_exceptionThrown      @ yes, handle exception
+
+
+/* continuation for OP_INVOKE_VIRTUAL_RANGE */
+
+    /*
+     * At this point:
+     *  r0 = resolved base method
+     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
+     */
+.LOP_INVOKE_VIRTUAL_RANGE_continue:
+    GET_VREG(r1, r10)                   @ r1<- "this" ptr
+    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
+    cmp     r1, #0                      @ is "this" null?
+    beq     common_errNullObject        @ null "this", throw exception
+    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
+    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
+    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
+    bl      common_invokeMethodRange @ continue on
+
+
+/* continuation for OP_INVOKE_SUPER_RANGE */
+
+    /*
+     * At this point:
+     *  r0 = resolved base method
+     *  r9 = method->clazz
+     */
+.LOP_INVOKE_SUPER_RANGE_continue:
+    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
+    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
+    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
+    EXPORT_PC()                         @ must export for invoke
+    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
+    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
+    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
+    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
+    bl      common_invokeMethodRange @ continue on
+
+.LOP_INVOKE_SUPER_RANGE_resolve:
+    mov     r0, r9                      @ r0<- method->clazz
+    mov     r2, #METHOD_VIRTUAL         @ resolver method type
+    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
+    cmp     r0, #0                      @ got null?
+    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
+    b       common_exceptionThrown      @ yes, handle exception
+
+    /*
+     * Throw a NoSuchMethodError with the method name as the message.
+     *  r0 = resolved base method
+     */
+.LOP_INVOKE_SUPER_RANGE_nsm:
+    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
+    b       common_errNoSuchMethod
+
+
+/* continuation for OP_INVOKE_DIRECT_RANGE */
+
+    /*
+     * On entry:
+     *  r1 = reference (BBBB or CCCC)
+     *  r10 = "this" register
+     */
+.LOP_INVOKE_DIRECT_RANGE_resolve:
+    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
+    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
+    mov     r2, #METHOD_DIRECT          @ resolver method type
+    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
+    cmp     r0, #0                      @ got null?
+    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
+    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
+    b       common_exceptionThrown      @ yes, handle exception
+
+
+/* continuation for OP_FLOAT_TO_LONG */
+/*
+ * Convert the float in r0 to a long in r0/r1.
+ *
+ * We have to clip values to long min/max per the specification.  The
+ * expected common case is a "reasonable" value that converts directly
+ * to modest integer.  The EABI convert function isn't doing this for us.
+ */
+f2l_doconv:
+    stmfd   sp!, {r4, lr}
+    mov     r1, #0x5f000000             @ (float)maxlong
+    mov     r4, r0
+    bl      __aeabi_fcmpge              @ is arg >= maxlong?
+    cmp     r0, #0                      @ nonzero == yes
+    mvnne   r0, #0                      @ return maxlong (7fffffff)
+    mvnne   r1, #0x80000000
+    ldmnefd sp!, {r4, pc}
+
+    mov     r0, r4                      @ recover arg
+    mov     r1, #0xdf000000             @ (float)minlong
+    bl      __aeabi_fcmple              @ is arg <= minlong?
+    cmp     r0, #0                      @ nonzero == yes
+    movne   r0, #0                      @ return minlong (80000000)
+    movne   r1, #0x80000000
+    ldmnefd sp!, {r4, pc}
+
+    mov     r0, r4                      @ recover arg
+    mov     r1, r4
+    bl      __aeabi_fcmpeq              @ is arg == self?
+    cmp     r0, #0                      @ zero == no
+    moveq   r1, #0                      @ return zero for NaN
+    ldmeqfd sp!, {r4, pc}
+
+    mov     r0, r4                      @ recover arg
+    bl      __aeabi_f2lz                @ convert float to long
+    ldmfd   sp!, {r4, pc}
+
+
+/* continuation for OP_DOUBLE_TO_LONG */
+/*
+ * Convert the double in r0/r1 to a long in r0/r1.
+ *
+ * We have to clip values to long min/max per the specification.  The
+ * expected common case is a "reasonable" value that converts directly
+ * to modest integer.  The EABI convert function isn't doing this for us.
+ */
+d2l_doconv:
+    stmfd   sp!, {r4, r5, lr}           @ save regs
+    mov     r3, #0x43000000             @ maxlong, as a double (high word)
+    add     r3, #0x00e00000             @  0x43e00000
+    mov     r2, #0                      @ maxlong, as a double (low word)
+    sub     sp, sp, #4                  @ align for EABI
+    mov     r4, r0                      @ save a copy of r0
+    mov     r5, r1                      @  and r1
+    bl      __aeabi_dcmpge              @ is arg >= maxlong?
+    cmp     r0, #0                      @ nonzero == yes
+    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
+    mvnne   r1, #0x80000000
+    bne     1f
+
+    mov     r0, r4                      @ recover arg
+    mov     r1, r5
+    mov     r3, #0xc3000000             @ minlong, as a double (high word)
+    add     r3, #0x00e00000             @  0xc3e00000
+    mov     r2, #0                      @ minlong, as a double (low word)
+    bl      __aeabi_dcmple              @ is arg <= minlong?
+    cmp     r0, #0                      @ nonzero == yes
+    movne   r0, #0                      @ return minlong (8000000000000000)
+    movne   r1, #0x80000000
+    bne     1f
+
+    mov     r0, r4                      @ recover arg
+    mov     r1, r5
+    mov     r2, r4                      @ compare against self
+    mov     r3, r5
+    bl      __aeabi_dcmpeq              @ is arg == self?
+    cmp     r0, #0                      @ zero == no
+    moveq   r1, #0                      @ return zero for NaN
+    beq     1f
+
+    mov     r0, r4                      @ recover arg
+    mov     r1, r5
+    bl      __aeabi_d2lz                @ convert double to long
+
+1:
+    add     sp, sp, #4
+    ldmfd   sp!, {r4, r5, pc}
+
+
+/* continuation for OP_MUL_LONG */
+
+.LOP_MUL_LONG_finish:
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_SHL_LONG */
+
+.LOP_SHL_LONG_finish:
+    mov     r0, r0, asl r2              @  r0<- r0 << r2
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_SHR_LONG */
+
+.LOP_SHR_LONG_finish:
+    mov     r1, r1, asr r2              @  r1<- r1 >> r2
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_USHR_LONG */
+
+.LOP_USHR_LONG_finish:
+    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_SHL_LONG_2ADDR */
+
+.LOP_SHL_LONG_2ADDR_finish:
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_SHR_LONG_2ADDR */
+
+.LOP_SHR_LONG_2ADDR_finish:
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_USHR_LONG_2ADDR */
+
+.LOP_USHR_LONG_2ADDR_finish:
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_EXECUTE_INLINE */
+
+    /*
+     * Extract args, call function.
+     *  r0 = #of args (0-4)
+     *  r10 = call index
+     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
+     *
+     * Other ideas:
+     * - Use a jump table from the main piece to jump directly into the
+     *   AND/LDR pairs.  Costs a data load, saves a branch.
+     * - Have five separate pieces that do the loading, so we can work the
+     *   interleave a little better.  Increases code size.
+     */
+.LOP_EXECUTE_INLINE_continue:
+    rsb     r0, r0, #4                  @ r0<- 4-r0
+    FETCH(r9, 2)                        @ r9<- FEDC
+    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
+    bl      common_abort                @ (skipped due to ARM prefetch)
+4:  and     ip, r9, #0xf000             @ isolate F
+    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
+3:  and     ip, r9, #0x0f00             @ isolate E
+    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
+2:  and     ip, r9, #0x00f0             @ isolate D
+    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
+1:  and     ip, r9, #0x000f             @ isolate C
+    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
+0:
+    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
+    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
+    @ (not reached)
+
+.LOP_EXECUTE_INLINE_table:
+    .word   gDvmInlineOpsTable
+
+
+    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
+    .global dvmAsmSisterEnd
+dvmAsmSisterEnd:
+
+/* File: armv5te/footer.S */
+
+/*
+ * ===========================================================================
+ *  Common subroutines and data
+ * ===========================================================================
+ */
+
+
+
+    .text
+    .align  2
+
+#if defined(WITH_JIT)
+/*
+ * Return from the translation cache to the interpreter when the compiler is
+ * having issues translating/executing a Dalvik instruction. We have to skip
+ * the code cache lookup otherwise it is possible to indefinitely bouce
+ * between the interpreter and the code cache if the instruction that fails
+ * to be compiled happens to be at a trace start.
+ */
+    .global dvmJitToInterpPunt
+dvmJitToInterpPunt:
+    mov    rPC, r0
+#ifdef EXIT_STATS
+    mov    r0,lr
+    bl     dvmBumpPunt;
+#endif
+    EXPORT_PC()
+    adrl   rIBASE, dvmAsmInstructionStart
+    FETCH_INST()
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+
+/*
+ * Return to the interpreter to handle a single instruction.
+ * On entry:
+ *    r0 <= PC
+ *    r1 <= PC of resume instruction
+ *    lr <= resume point in translation
+ */
+    .global dvmJitToInterpSingleStep
+dvmJitToInterpSingleStep:
+    str    lr,[rGLUE,#offGlue_jitResume]
+    str    r1,[rGLUE,#offGlue_jitResumePC]
+    mov    r1,#kInterpEntryInstr
+    @ enum is 4 byte in aapcs-EABI
+    str    r1, [rGLUE, #offGlue_entryPoint]
+    mov    rPC,r0
+    EXPORT_PC()
+    adrl   rIBASE, dvmAsmInstructionStart
+    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
+    str    r2,[rGLUE,#offGlue_jitState]
+    mov    r1,#1                  @ set changeInterp to bail to debug interp
+    b      common_gotoBail
+
+
+/*
+ * Return from the translation cache and immediately request
+ * a translation for the exit target.  Commonly used following
+ * invokes.
+ */
+    .global dvmJitToTraceSelect
+dvmJitToTraceSelect:
+    ldr    rPC,[r14, #-1]           @ get our target PC
+    add    rINST,r14,#-5            @ save start of chain branch
+    mov    r0,rPC
+    bl     dvmJitGetCodeAddr        @ Is there a translation?
+    cmp    r0,#0
+    beq    2f
+    mov    r1,rINST
+    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
+    cmp    r0,#0                    @ successful chain?
+    bxne   r0                       @ continue native execution
+    b      toInterpreter            @ didn't chain - resume with interpreter
+
+/* No translation, so request one if profiling isn't disabled*/
+2:
+    adrl   rIBASE, dvmAsmInstructionStart
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_INST()
+    cmp    r0, #0
+    bne    common_selectTrace
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+
+/*
+ * Return from the translation cache to the interpreter.
+ * The return was done with a BLX from thumb mode, and
+ * the following 32-bit word contains the target rPC value.
+ * Note that lr (r14) will have its low-order bit set to denote
+ * its thumb-mode origin.
+ *
+ * We'll need to stash our lr origin away, recover the new
+ * target and then check to see if there is a translation available
+ * for our new target.  If so, we do a translation chain and
+ * go back to native execution.  Otherwise, it's back to the
+ * interpreter (after treating this entry as a potential
+ * trace start).
+ */
+    .global dvmJitToInterpNormal
+dvmJitToInterpNormal:
+    ldr    rPC,[r14, #-1]           @ get our target PC
+    add    rINST,r14,#-5            @ save start of chain branch
+#ifdef EXIT_STATS
+    bl     dvmBumpNormal
+#endif
+    mov    r0,rPC
+    bl     dvmJitGetCodeAddr        @ Is there a translation?
+    cmp    r0,#0
+    beq    toInterpreter            @ go if not, otherwise do chain
+    mov    r1,rINST
+    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
+    cmp    r0,#0                    @ successful chain?
+    bxne   r0                       @ continue native execution
+    b      toInterpreter            @ didn't chain - resume with interpreter
+
+/*
+ * Return from the translation cache to the interpreter to do method invocation.
+ * Check if translation exists for the callee, but don't chain to it.
+ */
+    .global dvmJitToInterpNoChain
+dvmJitToInterpNoChain:
+#ifdef EXIT_STATS
+    bl     dvmBumpNoChain
+#endif
+    mov    r0,rPC
+    bl     dvmJitGetCodeAddr        @ Is there a translation?
+    cmp    r0,#0
+    bxne   r0                       @ continue native execution if so
+
+/*
+ * No translation, restore interpreter regs and start interpreting.
+ * rGLUE & rFP were preserved in the translated code, and rPC has
+ * already been restored by the time we get here.  We'll need to set
+ * up rIBASE & rINST, and load the address of the JitTable into r0.
+ */
+toInterpreter:
+    EXPORT_PC()
+    adrl   rIBASE, dvmAsmInstructionStart
+    FETCH_INST()
+    GET_JIT_PROF_TABLE(r0)
+    @ NOTE: intended fallthrough
+/*
+ * Common code to update potential trace start counter, and initiate
+ * a trace-build if appropriate.  On entry, rPC should point to the
+ * next instruction to execute, and rINST should be already loaded with
+ * the next opcode word, and r0 holds a pointer to the jit profile
+ * table (pJitProfTable).
+ */
+common_testUpdateProfile:
+    cmp     r0,#0
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
+
+common_updateProfile:
+    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
+    lsl     r3,r3,#23          @ shift out excess 511
+    ldrb    r1,[r0,r3,lsr #23] @ get counter
+    GET_INST_OPCODE(ip)
+    subs    r1,r1,#1           @ decrement counter
+    strb    r1,[r0,r3,lsr #23] @ and store it
+    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
+
+/*
+ * Here, we switch to the debug interpreter to request
+ * trace selection.  First, though, check to see if there
+ * is already a native translation in place (and, if so,
+ * jump to it now).
+ */
+    mov     r1,#255
+    strb    r1,[r0,r3,lsr #23] @ reset counter
+    EXPORT_PC()
+    mov     r0,rPC
+    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
+    cmp     r0,#0
+    beq     common_selectTrace
+    bxne    r0                          @ jump to the translation
+common_selectTrace:
+    mov     r2,#kJitTSelectRequest      @ ask for trace selection
+    str     r2,[rGLUE,#offGlue_jitState]
+    mov     r1,#1                       @ set changeInterp
+    b       common_gotoBail
+
+#endif
+
+/*
+ * Common code when a backward branch is taken.
+ *
+ * On entry:
+ *  r9 is PC adjustment *in bytes*
+ */
+common_backwardBranch:
+    mov     r0, #kInterpEntryInstr
+    bl      common_periodicChecks
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GET_INST_OPCODE(ip)
+    GOTO_OPCODE(ip)
+#else
+    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+
+/*
+ * Need to see if the thread needs to be suspended or debugger/profiler
+ * activity has begun.
+ *
+ * TODO: if JDWP isn't running, zero out pDebuggerActive pointer so we don't
+ * have to do the second ldr.
+ *
+ * TODO: reduce this so we're just checking a single location.
+ *
+ * On entry:
+ *  r0 is reentry type, e.g. kInterpEntryInstr
+ *  r9 is trampoline PC adjustment *in bytes*
+ */
+common_periodicChecks:
+    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
+
+#if defined(WITH_DEBUGGER)
+    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
+#endif
+#if defined(WITH_PROFILER)
+    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
+#endif
+
+    ldr     r3, [r3]                    @ r3<- suspendCount (int)
+
+#if defined(WITH_DEBUGGER)
+    ldrb    r1, [r1]                    @ r1<- debuggerActive (boolean)
+#endif
+#if defined (WITH_PROFILER)
+    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
+#endif
+
+    cmp     r3, #0                      @ suspend pending?
+    bne     2f                          @ yes, do full suspension check
+
+#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
+# if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
+    orrs    r1, r1, r2                  @ r1<- r1 | r2
+    cmp     r1, #0                      @ debugger attached or profiler started?
+# elif defined(WITH_DEBUGGER)
+    cmp     r1, #0                      @ debugger attached?
+# elif defined(WITH_PROFILER)
+    cmp     r2, #0                      @ profiler started?
+# endif
+    bne     3f                          @ debugger/profiler, switch interp
+#endif
+
+    bx      lr                          @ nothing to do, return
+
+2:  @ check suspend
+    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
+    EXPORT_PC()                         @ need for precise GC
+    b       dvmCheckSuspendPending      @ suspend if necessary, then return
+
+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
+
+
+/*
+ * The equivalent of "goto bail", this calls through the "bail handler".
+ *
+ * State registers will be saved to the "glue" area before bailing.
+ *
+ * On entry:
+ *  r1 is "bool changeInterp", indicating if we want to switch to the
+ *     other interpreter or just bail all the way out
+ */
+common_gotoBail:
+    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
+    mov     r0, rGLUE                   @ r0<- glue ptr
+    b       dvmMterpStdBail             @ call(glue, changeInterp)
+
+    @add     r1, r1, #1                  @ using (boolean+1)
+    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
+    @bl      _longjmp                    @ does not return
+    @bl      common_abort
+
+
+/*
+ * Common code for method invocation with range.
+ *
+ * On entry:
+ *  r0 is "Method* methodToCall", the method we're trying to call
+ */
+common_invokeMethodRange:
+.LinvokeNewRange:
+    @ prepare to copy args to "outs" area of current frame
+    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
+    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
+    beq     .LinvokeArgsDone            @ if no args, skip the rest
+    FETCH(r1, 2)                        @ r1<- CCCC
+
+    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
+    @ (very few methods have > 10 args; could unroll for common cases)
+    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
+    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
+    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
+1:  ldr     r1, [r3], #4                @ val = *fp++
+    subs    r2, r2, #1                  @ count--
+    str     r1, [r10], #4               @ *outs++ = val
+    bne     1b                          @ ...while count != 0
+    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
+    b       .LinvokeArgsDone
+
+/*
+ * Common code for method invocation without range.
+ *
+ * On entry:
+ *  r0 is "Method* methodToCall", the method we're trying to call
+ */
+common_invokeMethodNoRange:
+.LinvokeNewNoRange:
+    @ prepare to copy args to "outs" area of current frame
+    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
+    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
+    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
+    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
+    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
+    beq     .LinvokeArgsDone
+
+    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
+.LinvokeNonRange:
+    rsb     r2, r2, #5                  @ r2<- 5-r2
+    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
+    bl      common_abort                @ (skipped due to ARM prefetch)
+5:  and     ip, rINST, #0x0f00          @ isolate A
+    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
+    mov     r0, r0                      @ nop
+    str     r2, [r10, #-4]!             @ *--outs = vA
+4:  and     ip, r1, #0xf000             @ isolate G
+    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
+    mov     r0, r0                      @ nop
+    str     r2, [r10, #-4]!             @ *--outs = vG
+3:  and     ip, r1, #0x0f00             @ isolate F
+    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
+    mov     r0, r0                      @ nop
+    str     r2, [r10, #-4]!             @ *--outs = vF
+2:  and     ip, r1, #0x00f0             @ isolate E
+    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
+    mov     r0, r0                      @ nop
+    str     r2, [r10, #-4]!             @ *--outs = vE
+1:  and     ip, r1, #0x000f             @ isolate D
+    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
+    mov     r0, r0                      @ nop
+    str     r2, [r10, #-4]!             @ *--outs = vD
+0:  @ fall through to .LinvokeArgsDone
+
+.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
+    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
+    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
+    @ find space for the new stack frame, check for overflow
+    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
+    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
+    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
+@    bl      common_dumpRegs
+    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
+    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
+    cmp     r3, r9                      @ bottom < interpStackEnd?
+    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
+    blt     .LstackOverflow             @ yes, this frame will overflow stack
+
+    @ set up newSaveArea
+#ifdef EASY_GDB
+    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
+    str     ip, [r10, #offStackSaveArea_prevSave]
+#endif
+    str     rFP, [r10, #offStackSaveArea_prevFrame]
+    str     rPC, [r10, #offStackSaveArea_savedPc]
+#if defined(WITH_JIT)
+    mov     r9, #0
+    str     r9, [r10, #offStackSaveArea_returnAddr]
+#endif
+    str     r0, [r10, #offStackSaveArea_method]
+    tst     r3, #ACC_NATIVE
+    bne     .LinvokeNative
+
+    /*
+    stmfd   sp!, {r0-r3}
+    bl      common_printNewline
+    mov     r0, rFP
+    mov     r1, #0
+    bl      dvmDumpFp
+    ldmfd   sp!, {r0-r3}
+    stmfd   sp!, {r0-r3}
+    mov     r0, r1
+    mov     r1, r10
+    bl      dvmDumpFp
+    bl      common_printNewline
+    ldmfd   sp!, {r0-r3}
+    */
+
+    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
+    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
+    mov     rPC, r2                         @ publish new rPC
+    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
+
+    @ Update "glue" values for the new method
+    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
+    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
+    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
+#if defined(WITH_JIT)
+    GET_JIT_PROF_TABLE(r0)
+    mov     rFP, r1                         @ fp = newFp
+    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
+    mov     rINST, r9                       @ publish new rINST
+    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
+    cmp     r0,#0
+    bne     common_updateProfile
+    GOTO_OPCODE(ip)                         @ jump to next instruction
+#else
+    mov     rFP, r1                         @ fp = newFp
+    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
+    mov     rINST, r9                       @ publish new rINST
+    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
+    GOTO_OPCODE(ip)                         @ jump to next instruction
+#endif
+
+.LinvokeNative:
+    @ Prep for the native call
+    @ r0=methodToCall, r1=newFp, r10=newSaveArea
+    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
+    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
+    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
+    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
+    mov     r9, r3                      @ r9<- glue->self (preserve)
+
+    mov     r2, r0                      @ r2<- methodToCall
+    mov     r0, r1                      @ r0<- newFp (points to args)
+    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
+
+#ifdef ASSIST_DEBUGGER
+    /* insert fake function header to help gdb find the stack frame */
+    b       .Lskip
+    .type   dalvik_mterp, %function
+dalvik_mterp:
+    .fnstart
+    MTERP_ENTRY1
+    MTERP_ENTRY2
+.Lskip:
+#endif
+
+    @mov     lr, pc                      @ set return addr
+    @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
+    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
+
+    @ native return; r9=self, r10=newSaveArea
+    @ equivalent to dvmPopJniLocals
+    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
+    ldr     r1, [r9, #offThread_exception] @ check for exception
+    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
+    cmp     r1, #0                      @ null?
+    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
+    bne     common_exceptionThrown      @ no, handle exception
+
+    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+.LstackOverflow:
+    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
+    bl      dvmHandleStackOverflow
+    b       common_exceptionThrown
+#ifdef ASSIST_DEBUGGER
+    .fnend
+#endif
+
+
+    /*
+     * Common code for method invocation, calling through "glue code".
+     *
+     * TODO: now that we have range and non-range invoke handlers, this
+     *       needs to be split into two.  Maybe just create entry points
+     *       that set r9 and jump here?
+     *
+     * On entry:
+     *  r0 is "Method* methodToCall", the method we're trying to call
+     *  r9 is "bool methodCallRange", indicating if this is a /range variant
+     */
+     .if    0
+.LinvokeOld:
+    sub     sp, sp, #8                  @ space for args + pad
+    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
+    mov     r2, r0                      @ A2<- methodToCall
+    mov     r0, rGLUE                   @ A0<- glue
+    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
+    mov     r1, r9                      @ A1<- methodCallRange
+    mov     r3, rINST, lsr #8           @ A3<- AA
+    str     ip, [sp, #0]                @ A4<- ip
+    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
+    add     sp, sp, #8                  @ remove arg area
+    b       common_resumeAfterGlueCall  @ continue to next instruction
+    .endif
+
+
+
+/*
+ * Common code for handling a return instruction.
+ *
+ * This does not return.
+ */
+common_returnFromMethod:
+.LreturnNew:
+    mov     r0, #kInterpEntryReturn
+    mov     r9, #0
+    bl      common_periodicChecks
+
+    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
+    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
+    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
+    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
+                                        @ r2<- method we're returning to
+    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
+    cmp     r2, #0                      @ is this a break frame?
+    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
+    mov     r1, #0                      @ "want switch" = false
+    beq     common_gotoBail             @ break frame, bail out completely
+
+    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
+    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
+    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
+    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
+#if defined(WITH_JIT)
+    ldr     r3, [r0, #offStackSaveArea_returnAddr] @ r3 = saveArea->returnAddr
+    GET_JIT_PROF_TABLE(r0)
+    mov     rPC, r9                     @ publish new rPC
+    str     r1, [rGLUE, #offGlue_methodClassDex]
+    cmp     r3, #0                      @ caller is compiled code
+    blxne   r3
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    cmp     r0,#0
+    bne     common_updateProfile
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#else
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    mov     rPC, r9                     @ publish new rPC
+    str     r1, [rGLUE, #offGlue_methodClassDex]
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+#endif
+
+    /*
+     * Return handling, calls through "glue code".
+     */
+     .if    0
+.LreturnOld:
+    SAVE_PC_FP_TO_GLUE()                @ export state
+    mov     r0, rGLUE                   @ arg to function
+    bl      dvmMterp_returnFromMethod
+    b       common_resumeAfterGlueCall
+    .endif
+
+
+/*
+ * Somebody has thrown an exception.  Handle it.
+ *
+ * If the exception processing code returns to us (instead of falling
+ * out of the interpreter), continue with whatever the next instruction
+ * now happens to be.
+ *
+ * This does not return.
+ */
+     .global dvmMterpCommonExceptionThrown
+dvmMterpCommonExceptionThrown:
+common_exceptionThrown:
+.LexceptionNew:
+    mov     r0, #kInterpEntryThrow
+    mov     r9, #0
+    bl      common_periodicChecks
+
+#if defined(WITH_JIT)
+    mov     r2,#kJitTSelectAbort        @ abandon trace selection in progress
+    str     r2,[rGLUE,#offGlue_jitState]
+#endif
+
+    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
+    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
+    mov     r1, r10                     @ r1<- self
+    mov     r0, r9                      @ r0<- exception
+    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
+    mov     r3, #0                      @ r3<- NULL
+    str     r3, [r10, #offThread_exception] @ self->exception = NULL
+
+    /* set up args and a local for "&fp" */
+    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
+    str     rFP, [sp, #-4]!             @ *--sp = fp
+    mov     ip, sp                      @ ip<- &fp
+    mov     r3, #0                      @ r3<- false
+    str     ip, [sp, #-4]!              @ *--sp = &fp
+    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
+    mov     r0, r10                     @ r0<- self
+    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
+    mov     r2, r9                      @ r2<- exception
+    sub     r1, rPC, r1                 @ r1<- pc - method->insns
+    mov     r1, r1, asr #1              @ r1<- offset in code units
+
+    /* call, r0 gets catchRelPc (a code-unit offset) */
+    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
+
+    /* fix earlier stack overflow if necessary; may trash rFP */
+    ldrb    r1, [r10, #offThread_stackOverflowed]
+    cmp     r1, #0                      @ did we overflow earlier?
+    beq     1f                          @ no, skip ahead
+    mov     rFP, r0                     @ save relPc result in rFP
+    mov     r0, r10                     @ r0<- self
+    bl      dvmCleanupStackOverflow     @ call(self)
+    mov     r0, rFP                     @ restore result
+1:
+
+    /* update frame pointer and check result from dvmFindCatchBlock */
+    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
+    cmp     r0, #0                      @ is catchRelPc < 0?
+    add     sp, sp, #8                  @ restore stack
+    bmi     .LnotCaughtLocally
+
+    /* adjust locals to match self->curFrame and updated PC */
+    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
+    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
+    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
+    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
+    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
+    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
+    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
+    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
+
+    /* release the tracked alloc on the exception */
+    mov     r0, r9                      @ r0<- exception
+    mov     r1, r10                     @ r1<- self
+    bl      dvmReleaseTrackedAlloc      @ release the exception
+
+    /* restore the exception if the handler wants it */
+    FETCH_INST()                        @ load rINST from rPC
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
+    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+.LnotCaughtLocally: @ r9=exception, r10=self
+    /* fix stack overflow if necessary */
+    ldrb    r1, [r10, #offThread_stackOverflowed]
+    cmp     r1, #0                      @ did we overflow earlier?
+    movne   r0, r10                     @ if yes: r0<- self
+    blne    dvmCleanupStackOverflow     @ if yes: call(self)
+
+    @ may want to show "not caught locally" debug messages here
+#if DVM_SHOW_EXCEPTION >= 2
+    /* call __android_log_print(prio, tag, format, ...) */
+    /* "Exception %s from %s:%d not caught locally" */
+    @ dvmLineNumFromPC(method, pc - method->insns)
+    ldr     r0, [rGLUE, #offGlue_method]
+    ldr     r1, [r0, #offMethod_insns]
+    sub     r1, rPC, r1
+    asr     r1, r1, #1
+    bl      dvmLineNumFromPC
+    str     r0, [sp, #-4]!
+    @ dvmGetMethodSourceFile(method)
+    ldr     r0, [rGLUE, #offGlue_method]
+    bl      dvmGetMethodSourceFile
+    str     r0, [sp, #-4]!
+    @ exception->clazz->descriptor
+    ldr     r3, [r9, #offObject_clazz]
+    ldr     r3, [r3, #offClassObject_descriptor]
+    @
+    ldr     r2, strExceptionNotCaughtLocally
+    ldr     r1, strLogTag
+    mov     r0, #3                      @ LOG_DEBUG
+    bl      __android_log_print
+#endif
+    str     r9, [r10, #offThread_exception] @ restore exception
+    mov     r0, r9                      @ r0<- exception
+    mov     r1, r10                     @ r1<- self
+    bl      dvmReleaseTrackedAlloc      @ release the exception
+    mov     r1, #0                      @ "want switch" = false
+    b       common_gotoBail             @ bail out
+
+
+    /*
+     * Exception handling, calls through "glue code".
+     */
+    .if     0
+.LexceptionOld:
+    SAVE_PC_FP_TO_GLUE()                @ export state
+    mov     r0, rGLUE                   @ arg to function
+    bl      dvmMterp_exceptionThrown
+    b       common_resumeAfterGlueCall
+    .endif
+
+
+/*
+ * After returning from a "glued" function, pull out the updated
+ * values and start executing at the next instruction.
+ */
+common_resumeAfterGlueCall:
+    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
+    FETCH_INST()                        @ load rINST from rPC
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+/*
+ * Invalid array index.
+ */
+common_errArrayIndex:
+    EXPORT_PC()
+    ldr     r0, strArrayIndexException
+    mov     r1, #0
+    bl      dvmThrowException
+    b       common_exceptionThrown
+
+/*
+ * Invalid array value.
+ */
+common_errArrayStore:
+    EXPORT_PC()
+    ldr     r0, strArrayStoreException
+    mov     r1, #0
+    bl      dvmThrowException
+    b       common_exceptionThrown
+
+/*
+ * Integer divide or mod by zero.
+ */
+common_errDivideByZero:
+    EXPORT_PC()
+    ldr     r0, strArithmeticException
+    ldr     r1, strDivideByZero
+    bl      dvmThrowException
+    b       common_exceptionThrown
+
+/*
+ * Attempt to allocate an array with a negative size.
+ */
+common_errNegativeArraySize:
+    EXPORT_PC()
+    ldr     r0, strNegativeArraySizeException
+    mov     r1, #0
+    bl      dvmThrowException
+    b       common_exceptionThrown
+
+/*
+ * Invocation of a non-existent method.
+ */
+common_errNoSuchMethod:
+    EXPORT_PC()
+    ldr     r0, strNoSuchMethodError
+    mov     r1, #0
+    bl      dvmThrowException
+    b       common_exceptionThrown
+
+/*
+ * We encountered a null object when we weren't expecting one.  We
+ * export the PC, throw a NullPointerException, and goto the exception
+ * processing code.
+ */
+common_errNullObject:
+    EXPORT_PC()
+    ldr     r0, strNullPointerException
+    mov     r1, #0
+    bl      dvmThrowException
+    b       common_exceptionThrown
+
+/*
+ * For debugging, cause an immediate fault.  The source address will
+ * be in lr (use a bl instruction to jump here).
+ */
+common_abort:
+    ldr     pc, .LdeadFood
+.LdeadFood:
+    .word   0xdeadf00d
+
+/*
+ * Spit out a "we were here", preserving all registers.  (The attempt
+ * to save ip won't work, but we need to save an even number of
+ * registers for EABI 64-bit stack alignment.)
+ */
+    .macro  SQUEAK num
+common_squeak\num:
+    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    ldr     r0, strSqueak
+    mov     r1, #\num
+    bl      printf
+    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    bx      lr
+    .endm
+
+    SQUEAK  0
+    SQUEAK  1
+    SQUEAK  2
+    SQUEAK  3
+    SQUEAK  4
+    SQUEAK  5
+
+/*
+ * Spit out the number in r0, preserving registers.
+ */
+common_printNum:
+    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    mov     r1, r0
+    ldr     r0, strSqueak
+    bl      printf
+    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    bx      lr
+
+/*
+ * Print a newline, preserving registers.
+ */
+common_printNewline:
+    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    ldr     r0, strNewline
+    bl      printf
+    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    bx      lr
+
+    /*
+     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
+     */
+common_printHex:
+    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    mov     r1, r0
+    ldr     r0, strPrintHex
+    bl      printf
+    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    bx      lr
+
+/*
+ * Print the 64-bit quantity in r0-r1, preserving registers.
+ */
+common_printLong:
+    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    mov     r3, r1
+    mov     r2, r0
+    ldr     r0, strPrintLong
+    bl      printf
+    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    bx      lr
+
+/*
+ * Print full method info.  Pass the Method* in r0.  Preserves regs.
+ */
+common_printMethod:
+    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    bl      dvmMterpPrintMethod
+    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    bx      lr
+
+/*
+ * Call a C helper function that dumps regs and possibly some
+ * additional info.  Requires the C function to be compiled in.
+ */
+    .if     0
+common_dumpRegs:
+    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    bl      dvmMterpDumpArmRegs
+    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
+    bx      lr
+    .endif
+
+#if 0
+/*
+ * Experiment on VFP mode.
+ *
+ * uint32_t setFPSCR(uint32_t val, uint32_t mask)
+ *
+ * Updates the bits specified by "mask", setting them to the values in "val".
+ */
+setFPSCR:
+    and     r0, r0, r1                  @ make sure no stray bits are set
+    fmrx    r2, fpscr                   @ get VFP reg
+    mvn     r1, r1                      @ bit-invert mask
+    and     r2, r2, r1                  @ clear masked bits
+    orr     r2, r2, r0                  @ set specified bits
+    fmxr    fpscr, r2                   @ set VFP reg
+    mov     r0, r2                      @ return new value
+    bx      lr
+
+    .align  2
+    .global dvmConfigureFP
+    .type   dvmConfigureFP, %function
+dvmConfigureFP:
+    stmfd   sp!, {ip, lr}
+    /* 0x03000000 sets DN/FZ */
+    /* 0x00009f00 clears the six exception enable flags */
+    bl      common_squeak0
+    mov     r0, #0x03000000             @ r0<- 0x03000000
+    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
+    bl      setFPSCR
+    ldmfd   sp!, {ip, pc}
+#endif
+
+
+/*
+ * String references, must be close to the code that uses them.
+ */
+    .align  2
+strArithmeticException:
+    .word   .LstrArithmeticException
+strArrayIndexException:
+    .word   .LstrArrayIndexException
+strArrayStoreException:
+    .word   .LstrArrayStoreException
+strDivideByZero:
+    .word   .LstrDivideByZero
+strNegativeArraySizeException:
+    .word   .LstrNegativeArraySizeException
+strNoSuchMethodError:
+    .word   .LstrNoSuchMethodError
+strNullPointerException:
+    .word   .LstrNullPointerException
+
+strLogTag:
+    .word   .LstrLogTag
+strExceptionNotCaughtLocally:
+    .word   .LstrExceptionNotCaughtLocally
+
+strNewline:
+    .word   .LstrNewline
+strSqueak:
+    .word   .LstrSqueak
+strPrintHex:
+    .word   .LstrPrintHex
+strPrintLong:
+    .word   .LstrPrintLong
+
+/*
+ * Zero-terminated ASCII string data.
+ *
+ * On ARM we have two choices: do like gcc does, and LDR from a .word
+ * with the address, or use an ADR pseudo-op to get the address
+ * directly.  ADR saves 4 bytes and an indirection, but it's using a
+ * PC-relative addressing mode and hence has a limited range, which
+ * makes it not work well with mergeable string sections.
+ */
+    .section .rodata.str1.4,"aMS",%progbits,1
+
+.LstrBadEntryPoint:
+    .asciz  "Bad entry point %d\n"
+.LstrArithmeticException:
+    .asciz  "Ljava/lang/ArithmeticException;"
+.LstrArrayIndexException:
+    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
+.LstrArrayStoreException:
+    .asciz  "Ljava/lang/ArrayStoreException;"
+.LstrClassCastException:
+    .asciz  "Ljava/lang/ClassCastException;"
+.LstrDivideByZero:
+    .asciz  "divide by zero"
+.LstrFilledNewArrayNotImpl:
+    .asciz  "filled-new-array only implemented for objects and 'int'"
+.LstrInternalError:
+    .asciz  "Ljava/lang/InternalError;"
+.LstrInstantiationError:
+    .asciz  "Ljava/lang/InstantiationError;"
+.LstrNegativeArraySizeException:
+    .asciz  "Ljava/lang/NegativeArraySizeException;"
+.LstrNoSuchMethodError:
+    .asciz  "Ljava/lang/NoSuchMethodError;"
+.LstrNullPointerException:
+    .asciz  "Ljava/lang/NullPointerException;"
+
+.LstrLogTag:
+    .asciz  "mterp"
+.LstrExceptionNotCaughtLocally:
+    .asciz  "Exception %s from %s:%d not caught locally\n"
+
+.LstrNewline:
+    .asciz  "\n"
+.LstrSqueak:
+    .asciz  "<%d>"
+.LstrPrintHex:
+    .asciz  "<0x%x>"
+.LstrPrintLong:
+    .asciz  "<%lld>"
+
+
diff --git a/vm/mterp/out/InterpAsm-x86.S b/vm/mterp/out/InterpAsm-x86.S
index a80e59e..79c98f6 100644
--- a/vm/mterp/out/InterpAsm-x86.S
+++ b/vm/mterp/out/InterpAsm-x86.S
@@ -682,9 +682,7 @@
     movl    offGlue_self(%ecx),%ecx     # ecx<- glue->self
     FETCH_INST_WORD(1)
     testl   %eax,%eax                   # null object?
-#ifdef WITH_MONITOR_TRACKING
-    EXPORT_PC()
-#endif
+    EXPORT_PC()                         # need for precise GC, MONITOR_TRACKING
     jne     .LOP_MONITOR_ENTER_continue
     jmp     common_errNullObject
 
@@ -2854,9 +2852,7 @@
 .LOP_INVOKE_DIRECT_finish:
     UNSPILL(rPC)
     testl     %ecx,%ecx                # null "this"?
-    movl      $0,%ecx
-    #jne       common_invokeMethodNoRange  # no, continue on
-    jne       common_invokeOld          # no, continue on, eax<- method, ecx<- methodCallRange
+    jne       common_invokeMethodNoRange  # no, continue on
     jmp       common_errNullObject
 
 /* ------------------------------ */
@@ -2876,10 +2872,8 @@
     EXPORT_PC()
     movl      offDvmDex_pResMethods(%ecx),%ecx  # ecx<- pDvmDex->pResMethods
     movl      (%ecx,%eax,4),%eax        # eax<- resolved methodToCall
-    movl      $0,%ecx           # needed by common_invokeOld - revisit
     testl     %eax,%eax
-    #jne       common_invokeMethodNoRange
-    jne       common_invokeOld
+    jne       common_invokeMethodNoRange
     GET_GLUE(%ecx)
     movl      offGlue_method(%ecx),%ecx # ecx<- glue->method
     movzwl    2(rPC),%eax
@@ -3021,9 +3015,7 @@
 .LOP_INVOKE_DIRECT_RANGE_finish:
     UNSPILL(rPC)
     testl     %ecx,%ecx                # null "this"?
-    movl      $1,%ecx
-    #jne       common_invokeMethodRange  # no, continue on
-    jne       common_invokeOld          # no, continue on, eax<- method, ecx<- methodCallRange
+    jne       common_invokeMethodRange  # no, continue on
     jmp       common_errNullObject
 
 
@@ -3045,10 +3037,8 @@
     EXPORT_PC()
     movl      offDvmDex_pResMethods(%ecx),%ecx  # ecx<- pDvmDex->pResMethods
     movl      (%ecx,%eax,4),%eax        # eax<- resolved methodToCall
-    movl      $1,%ecx           # needed by common_invokeOld - revisit
     testl     %eax,%eax
-    #jne       common_invokeMethodRange
-    jne       common_invokeOld
+    jne       common_invokeMethodRange
     GET_GLUE(%ecx)
     movl      offGlue_method(%ecx),%ecx # ecx<- glue->method
     movzwl    2(rPC),%eax
@@ -5815,10 +5805,26 @@
 
 /* ------------------------------ */
     .balign 64
-.L_OP_UNUSED_ED: /* 0xed */
-/* File: x86/OP_UNUSED_ED.S */
-/* File: x86/unused.S */
-    jmp     common_abort
+.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
+/* File: x86/OP_THROW_VERIFICATION_ERROR.S */
+    /*
+     * Handle a throw-verification-error instruction.  This throws an
+     * exception for an error discovered during verification.  The
+     * exception is indicated by AA, with some detail provided by BBBB.
+     */
+    /* op AA, ref@BBBB */
+    GET_GLUE(%ecx)
+    movzwl   2(rPC),%eax                     # eax<- BBBB
+    movl     offGlue_method(%ecx),%ecx       # ecx<- glue->method
+    EXPORT_PC()
+    movzbl   rINST_HI,rINST_FULL             # rINST_FULL<- AA
+    movl     %eax,OUT_ARG2(%esp)             # arg2<- BBBB
+    movl     rINST_FULL,OUT_ARG1(%esp)       # arg1<- AA
+    movl     %ecx,OUT_ARG0(%esp)             # arg0<- method
+    SPILL(rPC)
+    call     dvmThrowVerificationError       # call(method, kind, ref)
+    UNSPILL(rPC)
+    jmp      common_exceptionThrown          # handle exception
 
 
 /* ------------------------------ */
@@ -6029,9 +6035,8 @@
     movl      offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable
     EXPORT_PC()                         # might throw later - get ready
     movl      (%eax,%ecx,4),%eax        # eax<- vtable[BBBB]
-    movl      $0,%ecx           # pass range flag
-    #jmp       common_invokeMethodNoRange
-    jmp       common_invokeOld
+    jmp       common_invokeMethodNoRange
+
 
 
 /* ------------------------------ */
@@ -6058,9 +6063,8 @@
     movl      offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable
     EXPORT_PC()                         # might throw later - get ready
     movl      (%eax,%ecx,4),%eax        # eax<- vtable[BBBB]
-    movl      $1,%ecx           # pass range flag
-    #jmp       common_invokeMethodRange
-    jmp       common_invokeOld
+    jmp       common_invokeMethodRange
+
 
 
 
@@ -6090,9 +6094,7 @@
     movl      offClassObject_vtable(%ecx),%ecx # ecx<- vtable
     EXPORT_PC()
     movl      (%ecx,%eax,4),%eax        # eax<- super->vtable[BBBB]
-    movl      $0,%ecx           # ecx<- range flag
-    #jmp       common_invokeMethodNoRange
-    jmp       common_invokeOld
+    jmp       common_invokeMethodNoRange
 
 
 /* ------------------------------ */
@@ -6122,9 +6124,7 @@
     movl      offClassObject_vtable(%ecx),%ecx # ecx<- vtable
     EXPORT_PC()
     movl      (%ecx,%eax,4),%eax        # eax<- super->vtable[BBBB]
-    movl      $1,%ecx           # ecx<- range flag
-    #jmp       common_invokeMethodRange
-    jmp       common_invokeOld
+    jmp       common_invokeMethodRange
 
 
 
@@ -6407,6 +6407,7 @@
 /* continuation for OP_NEW_INSTANCE */
 
 .LOP_NEW_INSTANCE_initialized:  # on entry, ecx<- class
+    /* TODO: remove test for interface/abstract, now done in verifier */
     testl     $(ACC_INTERFACE|ACC_ABSTRACT),offClassObject_accessFlags(%ecx)
     movl      $ALLOC_DONT_TRACK,OUT_ARG1(%esp)
     jne       .LOP_NEW_INSTANCE_abstract
@@ -6457,6 +6458,7 @@
     jmp     common_exceptionThrown      # no, handle exception
 
     /*
+     * TODO: remove this
      * We can't instantiate an abstract class or interface, so throw an
      * InstantiationError with the class descriptor as the message.
      *
@@ -7671,9 +7673,7 @@
     movl      offObject_clazz(%ecx),%ecx  # ecx<- thisPtr->clazz
     movl      offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable
     movl      (%ecx,%eax,4),%eax        # eax<- vtable[methodIndex]
-    movl      $0,%ecx           # needed for common_invokeOld
-    #jmp       common_invokeMethodNoRange
-    jmp       common_invokeOld
+    jmp       common_invokeMethodNoRange
 
 
 /* continuation for OP_INVOKE_SUPER */
@@ -7690,9 +7690,8 @@
     jae     .LOP_INVOKE_SUPER_nsm           # method not present in superclass
     movl    offClassObject_vtable(%eax),%eax   # eax<- ...clazz->super->vtable
     movl    (%eax,%ecx,4),%eax        # eax<- vtable[methodIndex]
-    movl    $0,%ecx
-    #jmp     common_invokeMethodNoRange
-    jmp     common_invokeOld
+    jmp     common_invokeMethodNoRange
+
 
     /* At this point:
      * ecx = null (needs to be resolved base method)
@@ -7755,10 +7754,8 @@
     SPILL(rPC)
     call      dvmResolveMethod          # call(clazz,ref,flags)
     UNSPILL(rPC)
-    movl      $0,%ecx
     testl     %eax,%eax                 # got null?
-    #jne       common_invokeMethodNoRange
-    jne       common_invokeOld
+    jne       common_invokeMethodNoRange
     jmp       common_exceptionThrown
 
 
@@ -7769,9 +7766,7 @@
     UNSPILL(rPC)
     testl      %eax,%eax
     je         common_exceptionThrown
-    movl       $0,%ecx
-    #jmp        common_invokeMethodNoRange
-    jmp        common_invokeOld
+    jmp        common_invokeMethodNoRange
 
 
 /* continuation for OP_INVOKE_VIRTUAL_RANGE */
@@ -7803,9 +7798,7 @@
     movl      offObject_clazz(%ecx),%ecx  # ecx<- thisPtr->clazz
     movl      offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable
     movl      (%ecx,%eax,4),%eax        # eax<- vtable[methodIndex]
-    movl      $1,%ecx           # needed for common_invokeOld
-    #jmp       common_invokeMethodRange
-    jmp       common_invokeOld
+    jmp       common_invokeMethodRange
 
 
 /* continuation for OP_INVOKE_SUPER_RANGE */
@@ -7822,9 +7815,8 @@
     jae     .LOP_INVOKE_SUPER_RANGE_nsm           # method not present in superclass
     movl    offClassObject_vtable(%eax),%eax   # eax<- ...clazz->super->vtable
     movl    (%eax,%ecx,4),%eax        # eax<- vtable[methodIndex]
-    movl    $1,%ecx
-    #jmp     common_invokeMethodRange
-    jmp     common_invokeOld
+    jmp     common_invokeMethodRange
+
 
     /* At this point:
      * ecx = null (needs to be resolved base method)
@@ -7887,10 +7879,8 @@
     SPILL(rPC)
     call      dvmResolveMethod          # call(clazz,ref,flags)
     UNSPILL(rPC)
-    movl      $1,%ecx
     testl     %eax,%eax                 # got null?
-    #jne       common_invokeMethodRange
-    jne       common_invokeOld
+    jne       common_invokeMethodRange
     jmp       common_exceptionThrown
 
 
@@ -7901,9 +7891,7 @@
     UNSPILL(rPC)
     testl      %eax,%eax
     je         common_exceptionThrown
-    movl       $1,%ecx
-    #jmp        common_invokeMethodRange
-    jmp        common_invokeOld
+    jmp        common_invokeMethodRange
 
 
 /* continuation for OP_FLOAT_TO_INT */
@@ -8537,11 +8525,217 @@
  */
 common_backwardBranch:
     GET_GLUE(%ecx)
-    call   common_periodicChecks      # Note: expects rPC to be preserved
+    call   common_periodicChecks  # Note: expects rPC to be preserved
     ADVANCE_PC_INDEXED(rINST_FULL)
     FETCH_INST()
     GOTO_NEXT
 
+
+
+/*
+ * Common code for method invocation with range.
+ *
+ * On entry:
+ *   eax = Method* methodToCall
+ *   rINST trashed, must reload
+ */
+
+common_invokeMethodRange:
+.LinvokeNewRange:
+
+   /*
+    * prepare to copy args to "outs" area of current frame
+    */
+
+    movzbl      1(rPC),rINST_FULL       # rINST_FULL<- AA
+    movzwl      4(rPC), %ecx            # %ecx<- CCCC
+    SPILL(rPC)
+    SAVEAREA_FROM_FP(%edx,rFP)          # %edx<- &StackSaveArea
+    test        rINST_FULL, rINST_FULL
+    movl        rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- AA
+    jz          .LinvokeArgsDone        # no args; jump to args done
+
+
+   /*
+    * %eax=methodToCall, %ecx=CCCC, LOCAL0_OFFSET(%ebp)=count, %edx=&outs (&stackSaveArea)
+    * (very few methods have > 10 args; could unroll for common cases)
+    */
+
+    movl        %ebx, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- save %ebx
+    lea         (rFP, %ecx, 4), %ecx    # %ecx<- &vCCCC
+    shll        $2, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- offset
+    subl        LOCAL0_OFFSET(%ebp), %edx       # %edx<- update &outs
+    shrl        $2, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- offset
+1:
+    movl        (%ecx), %ebx            # %ebx<- vCCCC
+    lea         4(%ecx), %ecx           # %ecx<- &vCCCC++
+    subl        $1, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET<- LOCAL0_OFFSET--
+    movl        %ebx, (%edx)            # *outs<- vCCCC
+    lea         4(%edx), %edx           # outs++
+    jne         1b                      # loop if count (LOCAL0_OFFSET(%ebp)) not zero
+    movl        LOCAL1_OFFSET(%ebp), %ebx       # %ebx<- restore %ebx
+    jmp         .LinvokeArgsDone        # continue
+
+   /*
+    * %eax is "Method* methodToCall", the method we're trying to call
+    * prepare to copy args to "outs" area of current frame
+    */
+
+common_invokeMethodNoRange:
+.LinvokeNewNoRange:
+    movzbl      1(rPC),rINST_FULL       # rINST_FULL<- BA
+    SPILL(rPC)
+    movl        rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- BA
+    shrl        $4, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- B
+    je          .LinvokeArgsDone        # no args; jump to args done
+    movzwl      4(rPC), %ecx            # %ecx<- GFED
+    SAVEAREA_FROM_FP(%edx,rFP)          # %edx<- &StackSaveArea
+
+   /*
+    * %eax=methodToCall, %ecx=GFED, LOCAL0_OFFSET(%ebp)=count, %edx=outs
+    */
+
+.LinvokeNonRange:
+    cmp         $2, LOCAL0_OFFSET(%ebp)        # compare LOCAL0_OFFSET(%ebp) to 2
+    movl        %ecx, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- GFED
+    jl          1f                      # handle 1 arg
+    je          2f                      # handle 2 args
+    cmp         $4, LOCAL0_OFFSET(%ebp)        # compare LOCAL0_OFFSET(%ebp) to 4
+    jl          3f                      # handle 3 args
+    je          4f                      # handle 4 args
+5:
+    andl        $15, rINST_FULL        # rINST<- A
+    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
+    movl        (rFP, rINST_FULL, 4), %ecx # %ecx<- vA
+    movl        %ecx, (%edx)            # *outs<- vA
+    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
+4:
+    shr         $12, %ecx              # %ecx<- G
+    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
+    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vG
+    movl        %ecx, (%edx)            # *outs<- vG
+    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
+3:
+    and         $0x0f00, %ecx          # %ecx<- 0F00
+    shr         $8, %ecx               # %ecx<- F
+    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
+    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vF
+    movl        %ecx, (%edx)            # *outs<- vF
+    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
+2:
+    and         $0x00f0, %ecx          # %ecx<- 00E0
+    shr         $4, %ecx               # %ecx<- E
+    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
+    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vE
+    movl        %ecx, (%edx)            # *outs<- vE
+    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
+1:
+    and         $0x000f, %ecx          # %ecx<- 000D
+    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vD
+    movl        %ecx, -4(%edx)          # *--outs<- vD
+0:
+
+   /*
+    * %eax is "Method* methodToCall", the method we're trying to call
+    * find space for the new stack frame, check for overflow
+    */
+
+.LinvokeArgsDone:
+    movzwl      offMethod_registersSize(%eax), %edx # %edx<- methodToCall->regsSize
+    movzwl      offMethod_outsSize(%eax), %ecx # %ecx<- methodToCall->outsSize
+    movl        %eax, LOCAL0_OFFSET(%ebp)       # LOCAL0_OFFSET<- methodToCall
+    shl         $2, %edx               # %edx<- update offset
+    SAVEAREA_FROM_FP(%eax,rFP)          # %eax<- &StackSaveArea
+    subl        %edx, %eax              # %eax<- newFP; (old savearea - regsSize)
+    GET_GLUE(%edx)                      # %edx<- pMterpGlue
+    movl        %eax, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- &outs
+    subl        $sizeofStackSaveArea, %eax # %eax<- newSaveArea (stack save area using newFP)
+    movl        offGlue_interpStackEnd(%edx), %edx # %edx<- glue->interpStackEnd
+    movl        %edx, LOCAL2_OFFSET(%ebp)       # LOCAL2_OFFSET<- glue->interpStackEnd
+    shl         $2, %ecx               # %ecx<- update offset for outsSize
+    movl        %eax, %edx              # %edx<- newSaveArea
+    sub         %ecx, %eax              # %eax<- bottom; (newSaveArea - outsSize)
+    cmp         LOCAL2_OFFSET(%ebp), %eax       # compare interpStackEnd and bottom
+    movl        LOCAL0_OFFSET(%ebp), %eax       # %eax<- restore methodToCall
+    jl          .LstackOverflow         # handle frame overflow
+
+   /*
+    * set up newSaveArea
+    */
+
+#ifdef EASY_GDB
+    SAVEAREA_FROM_FP(%ecx,rFP)          # %ecx<- &StackSaveArea
+    movl        %ecx, offStackSaveArea_prevSave(%edx) # newSaveArea->prevSave<- &outs
+#endif
+    movl        rFP, offStackSaveArea_prevFrame(%edx) # newSaveArea->prevFrame<- rFP
+    movl        rPC_SPILL(%ebp), %ecx
+    movl        %ecx, offStackSaveArea_savedPc(%edx) # newSaveArea->savedPc<- rPC
+    testl       $ACC_NATIVE, offMethod_accessFlags(%eax) # check for native call
+    movl        %eax, offStackSaveArea_method(%edx) # newSaveArea->method<- method to call
+    jne         .LinvokeNative          # handle native call
+
+   /*
+    * Update "glue" values for the new method
+    * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFp
+    */
+
+    movl        offMethod_clazz(%eax), %edx # %edx<- method->clazz
+    GET_GLUE(%ecx)                      # %ecx<- pMterpGlue
+    movl        offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex
+    movl        %eax, offGlue_method(%ecx) # glue->method<- methodToCall
+    movl        %edx, offGlue_methodClassDex(%ecx) # glue->methodClassDex<- method->clazz->pDvmDex
+    movl        offMethod_insns(%eax), rPC # rPC<- methodToCall->insns
+    movl        offGlue_self(%ecx), %eax # %eax<- glue->self
+    movl        LOCAL1_OFFSET(%ebp), rFP # rFP<- newFP
+    movl        rFP, offThread_curFrame(%eax) # glue->self->curFrame<- newFP
+    FETCH_INST()
+    GOTO_NEXT                           # jump to methodToCall->insns
+
+   /*
+    * Prep for the native call
+    * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFP, %edx=newSaveArea
+    */
+
+.LinvokeNative:
+    GET_GLUE(%ecx)                      # %ecx<- pMterpGlue
+    movl        %eax, OUT_ARG1(%esp)    # push parameter methodToCall
+    movl        offGlue_self(%ecx), %ecx        # %ecx<- glue->self
+    movl        offThread_jniLocal_topCookie(%ecx), %eax # %eax<- self->localRef->...
+    movl        %eax, offStackSaveArea_localRefCookie(%edx) # newSaveArea->localRefCookie<- top
+    movl        %edx, OUT_ARG4(%esp)    # save newSaveArea
+    movl        LOCAL1_OFFSET(%ebp), %edx # %edx<- newFP
+    movl        %edx, offThread_curFrame(%ecx)  # glue->self->curFrame<- newFP
+    movl        %ecx, OUT_ARG3(%esp)    # save glue->self
+    movl        %ecx, OUT_ARG2(%esp)    # push parameter glue->self
+    GET_GLUE(%ecx)                      # %ecx<- pMterpGlue
+    movl        OUT_ARG1(%esp), %eax    # %eax<- methodToCall
+    lea         offGlue_retval(%ecx), %ecx # %ecx<- &retval
+    movl        %ecx, OUT_ARG0(%esp)    # push parameter pMterpGlue
+    push        %edx                    # push parameter newFP
+
+    call        *offMethod_nativeFunc(%eax) # call methodToCall->nativeFunc
+    lea         4(%esp), %esp
+    movl        OUT_ARG4(%esp), %ecx    # %ecx<- newSaveArea
+    movl        OUT_ARG3(%esp), %eax    # %eax<- glue->self
+    movl        offStackSaveArea_localRefCookie(%ecx), %edx # %edx<- old top
+    cmp         $0, offThread_exception(%eax) # check for exception
+    movl        rFP, offThread_curFrame(%eax) # glue->self->curFrame<- rFP
+    movl        %edx, offThread_jniLocal_topCookie(%eax) # new top <- old top
+    UNSPILL(rPC)
+    jne         common_exceptionThrown  # handle exception
+    FETCH_INST_WORD(3)
+    ADVANCE_PC(3)
+    GOTO_NEXT                           # jump to next instruction
+
+.LstackOverflow:
+    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)
+    UNSPILL(rPC)                        # return: void
+    jmp         common_exceptionThrown  # handle exception
+
+
 /*
  * Common invoke code (old-style).
  * TUNING:  Rewrite along lines of new armv5 code?
@@ -8618,6 +8812,7 @@
      *      bool dvmCheckSuspendPending(Thread* self)
      *  Because we reached here via a call, go ahead and build a new frame.
      */
+    EXPORT_PC()                         # need for precise GC
     movl    offGlue_self(%ecx),%eax      # eax<- glue->self
     SPILL(rPC)                      # save edx
     push    %ebp
diff --git a/vm/mterp/out/InterpC-allstubs.c b/vm/mterp/out/InterpC-allstubs.c
index 635a873..4e832d8 100644
--- a/vm/mterp/out/InterpC-allstubs.c
+++ b/vm/mterp/out/InterpC-allstubs.c
@@ -26,6 +26,7 @@
 #include "interp/InterpDefs.h"
 #include "mterp/Mterp.h"
 #include <math.h>                   // needed for fmod, fmodf
+#include "mterp/common/FindInterface.h"
 
 /*
  * Configuration defines.  These affect the C implementations, i.e. the
@@ -53,7 +54,7 @@
  */
 #define THREADED_INTERP             /* threaded vs. while-loop interpreter */
 
-#ifdef WITH_INSTR_CHECKS            /* instruction-level paranoia */
+#ifdef WITH_INSTR_CHECKS            /* instruction-level paranoia (slow!) */
 # define CHECK_BRANCH_OFFSETS
 # define CHECK_REGISTER_INDICES
 #endif
@@ -93,6 +94,18 @@
 #endif
 
 /*
+ * Export another copy of the PC on every instruction; this is largely
+ * redundant with EXPORT_PC and the debugger code.  This value can be
+ * compared against what we have stored on the stack with EXPORT_PC to
+ * help ensure that we aren't missing any export calls.
+ */
+#if WITH_EXTRA_GC_CHECKS > 1
+# define EXPORT_EXTRA_PC() (self->currentPc2 = pc)
+#else
+# define EXPORT_EXTRA_PC()
+#endif
+
+/*
  * Adjust the program counter.  "_offset" is a signed int, in 16-bit units.
  *
  * Assumes the existence of "const u2* pc" and "const u2* curMethod->insns".
@@ -116,9 +129,13 @@
             dvmAbort();                                                     \
         }                                                                   \
         pc += myoff;                                                        \
+        EXPORT_EXTRA_PC();                                                  \
     } while (false)
 #else
-# define ADJUST_PC(_offset) (pc += _offset)
+# define ADJUST_PC(_offset) do {                                            \
+        pc += _offset;                                                      \
+        EXPORT_EXTRA_PC();                                                  \
+    } while (false)
 #endif
 
 /*
@@ -303,6 +320,8 @@
  * within the current method won't be shown correctly.  See the notes
  * in Exception.c.
  *
+ * This is also used to determine the address for precise GC.
+ *
  * Assumes existence of "u4* fp" and "const u2* pc".
  */
 #define EXPORT_PC()         (SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc)
@@ -316,29 +335,21 @@
  * If we're building without debug and profiling support, we never switch.
  */
 #if defined(WITH_PROFILER) || defined(WITH_DEBUGGER)
+#if defined(WITH_JIT)
+# define NEED_INTERP_SWITCH(_current) (                                     \
+    (_current == INTERP_STD) ?                                              \
+        dvmJitDebuggerOrProfilerActive(interpState->jitState) :             \
+        !dvmJitDebuggerOrProfilerActive(interpState->jitState) )
+#else
 # define NEED_INTERP_SWITCH(_current) (                                     \
     (_current == INTERP_STD) ?                                              \
         dvmDebuggerOrProfilerActive() : !dvmDebuggerOrProfilerActive() )
+#endif
 #else
 # define NEED_INTERP_SWITCH(_current) (false)
 #endif
 
 /*
- * Look up an interface on a class using the cache.
- */
-INLINE Method* dvmFindInterfaceMethodInCache(ClassObject* thisClass,
-    u4 methodIdx, const Method* method, DvmDex* methodClassDex)
-{
-#define ATOMIC_CACHE_CALC \
-    dvmInterpFindInterfaceMethod(thisClass, methodIdx, method, methodClassDex)
-
-    return (Method*) ATOMIC_CACHE_LOOKUP(methodClassDex->pInterfaceCache,
-                DEX_INTERFACE_CACHE_SIZE, thisClass, methodIdx);
-
-#undef ATOMIC_CACHE_CALC
-}
-
-/*
  * Check to see if "obj" is NULL.  If so, throw an exception.  Assumes the
  * pc has already been exported to the stack.
  *
@@ -402,7 +413,6 @@
     return true;
 }
 
-
 /* File: cstubs/stubdefs.c */
 /* this is a standard (no debug support) interpreter */
 #define INTERP_TYPE INTERP_STD
@@ -513,12 +523,15 @@
  * started.  If so, switch to a different "goto" table.
  */
 #define PERIODIC_CHECKS(_entryPoint, _pcadj) {                              \
-        dvmCheckSuspendQuick(self);                                         \
+        if (dvmCheckSuspendQuick(self)) {                                   \
+            EXPORT_PC();  /* need for precise GC */                         \
+            dvmCheckSuspendPending(self);                                   \
+        }                                                                   \
         if (NEED_INTERP_SWITCH(INTERP_TYPE)) {                              \
             ADJUST_PC(_pcadj);                                              \
             glue->entryPoint = _entryPoint;                                 \
             LOGVV("threadid=%d: switch to STD ep=%d adj=%d\n",              \
-                glue->self->threadId, (_entryPoint), (_pcadj));             \
+                self->threadId, (_entryPoint), (_pcadj));                   \
             GOTO_bail_switch();                                             \
         }                                                                   \
     }
@@ -1525,9 +1538,7 @@
         if (!checkForNullExportPC(obj, fp, pc))
             GOTO_exceptionThrown();
         ILOGV("+ locking %p %s\n", obj, obj->clazz->descriptor);
-#ifdef WITH_MONITOR_TRACKING
-        EXPORT_PC();        /* need for stack trace */
-#endif
+        EXPORT_PC();    /* need for precise GC, also WITH_MONITOR_TRACKING */
         dvmLockObject(self, obj);
 #ifdef WITH_DEADLOCK_PREDICTION
         if (dvmCheckException(self))
@@ -1674,21 +1685,13 @@
             GOTO_exceptionThrown();
 
         /*
-         * Note: the verifier can ensure that this never happens, allowing us
-         * to remove the check.  However, the spec requires we throw the
-         * exception at runtime, not verify time, so the verifier would
-         * need to replace the new-instance call with a magic "throw
-         * InstantiationError" instruction.
-         *
-         * Since this relies on the verifier, which is optional, we would
-         * also need a "new-instance-quick" instruction to identify instances
-         * that don't require the check.
+         * Verifier now tests for interface/abstract class.
          */
-        if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
-            dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationError;",
-                clazz->descriptor);
-            GOTO_exceptionThrown();
-        }
+        //if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
+        //    dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationError;",
+        //        clazz->descriptor);
+        //    GOTO_exceptionThrown();
+        //}
         newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
         if (newObj == NULL)
             GOTO_exceptionThrown();
@@ -2784,8 +2787,13 @@
 HANDLE_OPCODE(OP_UNUSED_EC)
 OP_END
 
-/* File: c/OP_UNUSED_ED.c */
-HANDLE_OPCODE(OP_UNUSED_ED)
+/* File: c/OP_THROW_VERIFICATION_ERROR.c */
+HANDLE_OPCODE(OP_THROW_VERIFICATION_ERROR)
+    EXPORT_PC();
+    vsrc1 = INST_AA(inst);
+    ref = FETCH(1);             /* class/field/method ref */
+    dvmThrowVerificationError(curMethod, vsrc1, ref);
+    GOTO_exceptionThrown();
 OP_END
 
 /* File: c/OP_EXECUTE_INLINE.c */
@@ -3539,7 +3547,7 @@
 
         ILOGV("> retval=0x%llx (leaving %s.%s %s)",
             retval.j, curMethod->clazz->descriptor, curMethod->name,
-            curMethod->signature);
+            curMethod->shorty);
         //DUMP_REGS(curMethod, fp);
 
         saveArea = SAVEAREA_FROM_FP(fp);
@@ -3567,7 +3575,7 @@
         methodClassDex = curMethod->clazz->pDvmDex;
         pc = saveArea->savedPc;
         ILOGD("> (return to %s.%s %s)", curMethod->clazz->descriptor,
-            curMethod->name, curMethod->signature);
+            curMethod->name, curMethod->shorty);
 
         /* use FINISH on the caller's invoke instruction */
         //u2 invokeInstr = INST_INST(FETCH(0));
@@ -3702,7 +3710,7 @@
         methodClassDex = curMethod->clazz->pDvmDex;
         pc = curMethod->insns + catchRelPc;
         ILOGV("> pc <-- %s.%s %s", curMethod->clazz->descriptor,
-            curMethod->name, curMethod->signature);
+            curMethod->name, curMethod->shorty);
         DUMP_REGS(curMethod, fp, false);            // show all regs
 
         /*
@@ -3751,7 +3759,7 @@
         //printf("range=%d call=%p count=%d regs=0x%04x\n",
         //    methodCallRange, methodToCall, count, regs);
         //printf(" --> %s.%s %s\n", methodToCall->clazz->descriptor,
-        //    methodToCall->name, methodToCall->signature);
+        //    methodToCall->name, methodToCall->shorty);
 
         u4* outs;
         int i;
@@ -3821,7 +3829,7 @@
         ILOGV("> %s%s.%s %s",
             dvmIsNativeMethod(methodToCall) ? "(NATIVE) " : "",
             methodToCall->clazz->descriptor, methodToCall->name,
-            methodToCall->signature);
+            methodToCall->shorty);
 
         newFp = (u4*) SAVEAREA_FROM_FP(fp) - methodToCall->registersSize;
         newSaveArea = SAVEAREA_FROM_FP(newFp);
@@ -3861,6 +3869,9 @@
 #endif
         newSaveArea->prevFrame = fp;
         newSaveArea->savedPc = pc;
+#if defined(WITH_JIT)
+        newSaveArea->returnAddr = 0;
+#endif
         newSaveArea->method = methodToCall;
 
         if (!dvmIsNativeMethod(methodToCall)) {
@@ -3879,12 +3890,16 @@
             debugIsMethodEntry = true;              // profiling, debugging
 #endif
             ILOGD("> pc <-- %s.%s %s", curMethod->clazz->descriptor,
-                curMethod->name, curMethod->signature);
+                curMethod->name, curMethod->shorty);
             DUMP_REGS(curMethod, fp, true);         // show input args
             FINISH(0);                              // jump to method start
         } else {
             /* set this up for JNI locals, even if not a JNI native */
-            newSaveArea->xtra.localRefTop = self->jniLocalRefTable.nextEntry;
+#ifdef USE_INDIRECT_REF
+            newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
+#else
+            newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.nextEntry;
+#endif
 
             self->curFrame = newFp;
 
@@ -3901,7 +3916,7 @@
 #endif
 
             ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
-                methodToCall->name, methodToCall->signature);
+                methodToCall->name, methodToCall->shorty);
 
             /*
              * Jump through native call bridge.  Because we leave no
@@ -3938,7 +3953,7 @@
             ILOGD("> (return from native %s.%s to %s.%s %s)",
                 methodToCall->clazz->descriptor, methodToCall->name,
                 curMethod->clazz->descriptor, curMethod->name,
-                curMethod->signature);
+                curMethod->shorty);
 
             //u2 invokeInstr = INST_INST(FETCH(0));
             if (true /*invokeInstr >= OP_INVOKE_VIRTUAL &&
@@ -3955,7 +3970,6 @@
     assert(false);      // should not get here
 GOTO_TARGET_END
 
-
 /* File: cstubs/enddefs.c */
 
 /* undefine "magic" name remapping */
diff --git a/vm/mterp/out/InterpC-armv4t.c b/vm/mterp/out/InterpC-armv4t.c
index 7f101a9..6b82bc8 100644
--- a/vm/mterp/out/InterpC-armv4t.c
+++ b/vm/mterp/out/InterpC-armv4t.c
@@ -26,6 +26,7 @@
 #include "interp/InterpDefs.h"
 #include "mterp/Mterp.h"
 #include <math.h>                   // needed for fmod, fmodf
+#include "mterp/common/FindInterface.h"
 
 /*
  * Configuration defines.  These affect the C implementations, i.e. the
@@ -53,7 +54,7 @@
  */
 #define THREADED_INTERP             /* threaded vs. while-loop interpreter */
 
-#ifdef WITH_INSTR_CHECKS            /* instruction-level paranoia */
+#ifdef WITH_INSTR_CHECKS            /* instruction-level paranoia (slow!) */
 # define CHECK_BRANCH_OFFSETS
 # define CHECK_REGISTER_INDICES
 #endif
@@ -93,6 +94,18 @@
 #endif
 
 /*
+ * Export another copy of the PC on every instruction; this is largely
+ * redundant with EXPORT_PC and the debugger code.  This value can be
+ * compared against what we have stored on the stack with EXPORT_PC to
+ * help ensure that we aren't missing any export calls.
+ */
+#if WITH_EXTRA_GC_CHECKS > 1
+# define EXPORT_EXTRA_PC() (self->currentPc2 = pc)
+#else
+# define EXPORT_EXTRA_PC()
+#endif
+
+/*
  * Adjust the program counter.  "_offset" is a signed int, in 16-bit units.
  *
  * Assumes the existence of "const u2* pc" and "const u2* curMethod->insns".
@@ -116,9 +129,13 @@
             dvmAbort();                                                     \
         }                                                                   \
         pc += myoff;                                                        \
+        EXPORT_EXTRA_PC();                                                  \
     } while (false)
 #else
-# define ADJUST_PC(_offset) (pc += _offset)
+# define ADJUST_PC(_offset) do {                                            \
+        pc += _offset;                                                      \
+        EXPORT_EXTRA_PC();                                                  \
+    } while (false)
 #endif
 
 /*
@@ -303,6 +320,8 @@
  * within the current method won't be shown correctly.  See the notes
  * in Exception.c.
  *
+ * This is also used to determine the address for precise GC.
+ *
  * Assumes existence of "u4* fp" and "const u2* pc".
  */
 #define EXPORT_PC()         (SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc)
@@ -316,29 +335,21 @@
  * If we're building without debug and profiling support, we never switch.
  */
 #if defined(WITH_PROFILER) || defined(WITH_DEBUGGER)
+#if defined(WITH_JIT)
+# define NEED_INTERP_SWITCH(_current) (                                     \
+    (_current == INTERP_STD) ?                                              \
+        dvmJitDebuggerOrProfilerActive(interpState->jitState) :             \
+        !dvmJitDebuggerOrProfilerActive(interpState->jitState) )
+#else
 # define NEED_INTERP_SWITCH(_current) (                                     \
     (_current == INTERP_STD) ?                                              \
         dvmDebuggerOrProfilerActive() : !dvmDebuggerOrProfilerActive() )
+#endif
 #else
 # define NEED_INTERP_SWITCH(_current) (false)
 #endif
 
 /*
- * Look up an interface on a class using the cache.
- */
-INLINE Method* dvmFindInterfaceMethodInCache(ClassObject* thisClass,
-    u4 methodIdx, const Method* method, DvmDex* methodClassDex)
-{
-#define ATOMIC_CACHE_CALC \
-    dvmInterpFindInterfaceMethod(thisClass, methodIdx, method, methodClassDex)
-
-    return (Method*) ATOMIC_CACHE_LOOKUP(methodClassDex->pInterfaceCache,
-                DEX_INTERFACE_CACHE_SIZE, thisClass, methodIdx);
-
-#undef ATOMIC_CACHE_CALC
-}
-
-/*
  * Check to see if "obj" is NULL.  If so, throw an exception.  Assumes the
  * pc has already been exported to the stack.
  *
@@ -402,7 +413,6 @@
     return true;
 }
 
-
 /* File: cstubs/stubdefs.c */
 /* this is a standard (no debug support) interpreter */
 #define INTERP_TYPE INTERP_STD
@@ -513,12 +523,15 @@
  * started.  If so, switch to a different "goto" table.
  */
 #define PERIODIC_CHECKS(_entryPoint, _pcadj) {                              \
-        dvmCheckSuspendQuick(self);                                         \
+        if (dvmCheckSuspendQuick(self)) {                                   \
+            EXPORT_PC();  /* need for precise GC */                         \
+            dvmCheckSuspendPending(self);                                   \
+        }                                                                   \
         if (NEED_INTERP_SWITCH(INTERP_TYPE)) {                              \
             ADJUST_PC(_pcadj);                                              \
             glue->entryPoint = _entryPoint;                                 \
             LOGVV("threadid=%d: switch to STD ep=%d adj=%d\n",              \
-                glue->self->threadId, (_entryPoint), (_pcadj));             \
+                self->threadId, (_entryPoint), (_pcadj));                   \
             GOTO_bail_switch();                                             \
         }                                                                   \
     }
@@ -1199,23 +1212,23 @@
     register uint32_t rPC       asm("r4");
     register uint32_t rFP       asm("r5");
     register uint32_t rGLUE     asm("r6");
-    register uint32_t rIBASE    asm("r7");
-    register uint32_t rINST     asm("r8");
+    register uint32_t rINST     asm("r7");
+    register uint32_t rIBASE    asm("r8");
     register uint32_t r9        asm("r9");
     register uint32_t r10       asm("r10");
 
     extern char dvmAsmInstructionStart[];
 
     printf("REGS: r0=%08x r1=%08x r2=%08x r3=%08x\n", r0, r1, r2, r3);
-    printf("    : rPC=%08x rFP=%08x rGLUE=%08x rIBASE=%08x\n",
-        rPC, rFP, rGLUE, rIBASE);
-    printf("    : rINST=%08x r9=%08x r10=%08x\n", rINST, r9, r10);
+    printf("    : rPC=%08x rFP=%08x rGLUE=%08x rINST=%08x\n",
+        rPC, rFP, rGLUE, rINST);
+    printf("    : rIBASE=%08x r9=%08x r10=%08x\n", rIBASE, r9, r10);
 
     MterpGlue* glue = (MterpGlue*) rGLUE;
     const Method* method = glue->method;
     printf("    + self is %p\n", dvmThreadSelf());
     //printf("    + currently in %s.%s %s\n",
-    //    method->clazz->descriptor, method->name, method->signature);
+    //    method->clazz->descriptor, method->name, method->shorty);
     //printf("    + dvmAsmInstructionStart = %p\n", dvmAsmInstructionStart);
     //printf("    + next handler for 0x%02x = %p\n",
     //    rINST & 0xff, dvmAsmInstructionStart + (rINST & 0xff) * 64);
@@ -1249,12 +1262,12 @@
      * It is a direct (non-virtual) method if it is static, private,
      * or a constructor.
      */
-    bool isDirect = 
+    bool isDirect =
         ((method->accessFlags & (ACC_STATIC|ACC_PRIVATE)) != 0) ||
         (method->name[0] == '<');
 
     char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
-        
+
     printf("<%c:%s.%s %s> ",
             isDirect ? 'D' : 'V',
             method->clazz->descriptor,
diff --git a/vm/mterp/out/InterpC-armv5te-vfp.c b/vm/mterp/out/InterpC-armv5te-vfp.c
new file mode 100644
index 0000000..7312700
--- /dev/null
+++ b/vm/mterp/out/InterpC-armv5te-vfp.c
@@ -0,0 +1,1279 @@
+/*
+ * This file was generated automatically by gen-mterp.py for 'armv5te-vfp'.
+ *
+ * --> DO NOT EDIT <--
+ */
+
+/* File: c/header.c */
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* common includes */
+#include "Dalvik.h"
+#include "interp/InterpDefs.h"
+#include "mterp/Mterp.h"
+#include <math.h>                   // needed for fmod, fmodf
+#include "mterp/common/FindInterface.h"
+
+/*
+ * Configuration defines.  These affect the C implementations, i.e. the
+ * portable interpreter(s) and C stubs.
+ *
+ * Some defines are controlled by the Makefile, e.g.:
+ *   WITH_PROFILER
+ *   WITH_DEBUGGER
+ *   WITH_INSTR_CHECKS
+ *   WITH_TRACKREF_CHECKS
+ *   EASY_GDB
+ *   NDEBUG
+ *
+ * If THREADED_INTERP is not defined, we use a classic "while true / switch"
+ * interpreter.  If it is defined, then the tail end of each instruction
+ * handler fetches the next instruction and jumps directly to the handler.
+ * This increases the size of the "Std" interpreter by about 10%, but
+ * provides a speedup of about the same magnitude.
+ *
+ * There's a "hybrid" approach that uses a goto table instead of a switch
+ * statement, avoiding the "is the opcode in range" tests required for switch.
+ * The performance is close to the threaded version, and without the 10%
+ * size increase, but the benchmark results are off enough that it's not
+ * worth adding as a third option.
+ */
+#define THREADED_INTERP             /* threaded vs. while-loop interpreter */
+
+#ifdef WITH_INSTR_CHECKS            /* instruction-level paranoia (slow!) */
+# define CHECK_BRANCH_OFFSETS
+# define CHECK_REGISTER_INDICES
+#endif
+
+/*
+ * ARM EABI requires 64-bit alignment for access to 64-bit data types.  We
+ * can't just use pointers to copy 64-bit values out of our interpreted
+ * register set, because gcc will generate ldrd/strd.
+ *
+ * The __UNION version copies data in and out of a union.  The __MEMCPY
+ * version uses a memcpy() call to do the transfer; gcc is smart enough to
+ * not actually call memcpy().  The __UNION version is very bad on ARM;
+ * it only uses one more instruction than __MEMCPY, but for some reason
+ * gcc thinks it needs separate storage for every instance of the union.
+ * On top of that, it feels the need to zero them out at the start of the
+ * method.  Net result is we zero out ~700 bytes of stack space at the top
+ * of the interpreter using ARM STM instructions.
+ */
+#if defined(__ARM_EABI__)
+//# define NO_UNALIGN_64__UNION
+# define NO_UNALIGN_64__MEMCPY
+#endif
+
+//#define LOG_INSTR                   /* verbose debugging */
+/* set and adjust ANDROID_LOG_TAGS='*:i jdwp:i dalvikvm:i dalvikvmi:i' */
+
+/*
+ * Keep a tally of accesses to fields.  Currently only works if full DEX
+ * optimization is disabled.
+ */
+#ifdef PROFILE_FIELD_ACCESS
+# define UPDATE_FIELD_GET(_field) { (_field)->gets++; }
+# define UPDATE_FIELD_PUT(_field) { (_field)->puts++; }
+#else
+# define UPDATE_FIELD_GET(_field) ((void)0)
+# define UPDATE_FIELD_PUT(_field) ((void)0)
+#endif
+
+/*
+ * Export another copy of the PC on every instruction; this is largely
+ * redundant with EXPORT_PC and the debugger code.  This value can be
+ * compared against what we have stored on the stack with EXPORT_PC to
+ * help ensure that we aren't missing any export calls.
+ */
+#if WITH_EXTRA_GC_CHECKS > 1
+# define EXPORT_EXTRA_PC() (self->currentPc2 = pc)
+#else
+# define EXPORT_EXTRA_PC()
+#endif
+
+/*
+ * Adjust the program counter.  "_offset" is a signed int, in 16-bit units.
+ *
+ * Assumes the existence of "const u2* pc" and "const u2* curMethod->insns".
+ *
+ * We don't advance the program counter until we finish an instruction or
+ * branch, because we do want to have to unroll the PC if there's an
+ * exception.
+ */
+#ifdef CHECK_BRANCH_OFFSETS
+# define ADJUST_PC(_offset) do {                                            \
+        int myoff = _offset;        /* deref only once */                   \
+        if (pc + myoff < curMethod->insns ||                                \
+            pc + myoff >= curMethod->insns + dvmGetMethodInsnsSize(curMethod)) \
+        {                                                                   \
+            char* desc;                                                     \
+            desc = dexProtoCopyMethodDescriptor(&curMethod->prototype);     \
+            LOGE("Invalid branch %d at 0x%04x in %s.%s %s\n",               \
+                myoff, (int) (pc - curMethod->insns),                       \
+                curMethod->clazz->descriptor, curMethod->name, desc);       \
+            free(desc);                                                     \
+            dvmAbort();                                                     \
+        }                                                                   \
+        pc += myoff;                                                        \
+        EXPORT_EXTRA_PC();                                                  \
+    } while (false)
+#else
+# define ADJUST_PC(_offset) do {                                            \
+        pc += _offset;                                                      \
+        EXPORT_EXTRA_PC();                                                  \
+    } while (false)
+#endif
+
+/*
+ * If enabled, log instructions as we execute them.
+ */
+#ifdef LOG_INSTR
+# define ILOGD(...) ILOG(LOG_DEBUG, __VA_ARGS__)
+# define ILOGV(...) ILOG(LOG_VERBOSE, __VA_ARGS__)
+# define ILOG(_level, ...) do {                                             \
+        char debugStrBuf[128];                                              \
+        snprintf(debugStrBuf, sizeof(debugStrBuf), __VA_ARGS__);            \
+        if (curMethod != NULL)                                                 \
+            LOG(_level, LOG_TAG"i", "%-2d|%04x%s\n",                        \
+                self->threadId, (int)(pc - curMethod->insns), debugStrBuf); \
+        else                                                                \
+            LOG(_level, LOG_TAG"i", "%-2d|####%s\n",                        \
+                self->threadId, debugStrBuf);                               \
+    } while(false)
+void dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly);
+# define DUMP_REGS(_meth, _frame, _inOnly) dvmDumpRegs(_meth, _frame, _inOnly)
+static const char kSpacing[] = "            ";
+#else
+# define ILOGD(...) ((void)0)
+# define ILOGV(...) ((void)0)
+# define DUMP_REGS(_meth, _frame, _inOnly) ((void)0)
+#endif
+
+/* get a long from an array of u4 */
+static inline s8 getLongFromArray(const u4* ptr, int idx)
+{
+#if defined(NO_UNALIGN_64__UNION)
+    union { s8 ll; u4 parts[2]; } conv;
+
+    ptr += idx;
+    conv.parts[0] = ptr[0];
+    conv.parts[1] = ptr[1];
+    return conv.ll;
+#elif defined(NO_UNALIGN_64__MEMCPY)
+    s8 val;
+    memcpy(&val, &ptr[idx], 8);
+    return val;
+#else
+    return *((s8*) &ptr[idx]);
+#endif
+}
+
+/* store a long into an array of u4 */
+static inline void putLongToArray(u4* ptr, int idx, s8 val)
+{
+#if defined(NO_UNALIGN_64__UNION)
+    union { s8 ll; u4 parts[2]; } conv;
+
+    ptr += idx;
+    conv.ll = val;
+    ptr[0] = conv.parts[0];
+    ptr[1] = conv.parts[1];
+#elif defined(NO_UNALIGN_64__MEMCPY)
+    memcpy(&ptr[idx], &val, 8);
+#else
+    *((s8*) &ptr[idx]) = val;
+#endif
+}
+
+/* get a double from an array of u4 */
+static inline double getDoubleFromArray(const u4* ptr, int idx)
+{
+#if defined(NO_UNALIGN_64__UNION)
+    union { double d; u4 parts[2]; } conv;
+
+    ptr += idx;
+    conv.parts[0] = ptr[0];
+    conv.parts[1] = ptr[1];
+    return conv.d;
+#elif defined(NO_UNALIGN_64__MEMCPY)
+    double dval;
+    memcpy(&dval, &ptr[idx], 8);
+    return dval;
+#else
+    return *((double*) &ptr[idx]);
+#endif
+}
+
+/* store a double into an array of u4 */
+static inline void putDoubleToArray(u4* ptr, int idx, double dval)
+{
+#if defined(NO_UNALIGN_64__UNION)
+    union { double d; u4 parts[2]; } conv;
+
+    ptr += idx;
+    conv.d = dval;
+    ptr[0] = conv.parts[0];
+    ptr[1] = conv.parts[1];
+#elif defined(NO_UNALIGN_64__MEMCPY)
+    memcpy(&ptr[idx], &dval, 8);
+#else
+    *((double*) &ptr[idx]) = dval;
+#endif
+}
+
+/*
+ * If enabled, validate the register number on every access.  Otherwise,
+ * just do an array access.
+ *
+ * Assumes the existence of "u4* fp".
+ *
+ * "_idx" may be referenced more than once.
+ */
+#ifdef CHECK_REGISTER_INDICES
+# define GET_REGISTER(_idx) \
+    ( (_idx) < curMethod->registersSize ? \
+        (fp[(_idx)]) : (assert(!"bad reg"),1969) )
+# define SET_REGISTER(_idx, _val) \
+    ( (_idx) < curMethod->registersSize ? \
+        (fp[(_idx)] = (u4)(_val)) : (assert(!"bad reg"),1969) )
+# define GET_REGISTER_AS_OBJECT(_idx)       ((Object *)GET_REGISTER(_idx))
+# define SET_REGISTER_AS_OBJECT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
+# define GET_REGISTER_INT(_idx) ((s4) GET_REGISTER(_idx))
+# define SET_REGISTER_INT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
+# define GET_REGISTER_WIDE(_idx) \
+    ( (_idx) < curMethod->registersSize-1 ? \
+        getLongFromArray(fp, (_idx)) : (assert(!"bad reg"),1969) )
+# define SET_REGISTER_WIDE(_idx, _val) \
+    ( (_idx) < curMethod->registersSize-1 ? \
+        putLongToArray(fp, (_idx), (_val)) : (assert(!"bad reg"),1969) )
+# define GET_REGISTER_FLOAT(_idx) \
+    ( (_idx) < curMethod->registersSize ? \
+        (*((float*) &fp[(_idx)])) : (assert(!"bad reg"),1969.0f) )
+# define SET_REGISTER_FLOAT(_idx, _val) \
+    ( (_idx) < curMethod->registersSize ? \
+        (*((float*) &fp[(_idx)]) = (_val)) : (assert(!"bad reg"),1969.0f) )
+# define GET_REGISTER_DOUBLE(_idx) \
+    ( (_idx) < curMethod->registersSize-1 ? \
+        getDoubleFromArray(fp, (_idx)) : (assert(!"bad reg"),1969.0) )
+# define SET_REGISTER_DOUBLE(_idx, _val) \
+    ( (_idx) < curMethod->registersSize-1 ? \
+        putDoubleToArray(fp, (_idx), (_val)) : (assert(!"bad reg"),1969.0) )
+#else
+# define GET_REGISTER(_idx)                 (fp[(_idx)])
+# define SET_REGISTER(_idx, _val)           (fp[(_idx)] = (_val))
+# define GET_REGISTER_AS_OBJECT(_idx)       ((Object*) fp[(_idx)])
+# define SET_REGISTER_AS_OBJECT(_idx, _val) (fp[(_idx)] = (u4)(_val))
+# define GET_REGISTER_INT(_idx)             ((s4)GET_REGISTER(_idx))
+# define SET_REGISTER_INT(_idx, _val)       SET_REGISTER(_idx, (s4)_val)
+# define GET_REGISTER_WIDE(_idx)            getLongFromArray(fp, (_idx))
+# define SET_REGISTER_WIDE(_idx, _val)      putLongToArray(fp, (_idx), (_val))
+# define GET_REGISTER_FLOAT(_idx)           (*((float*) &fp[(_idx)]))
+# define SET_REGISTER_FLOAT(_idx, _val)     (*((float*) &fp[(_idx)]) = (_val))
+# define GET_REGISTER_DOUBLE(_idx)          getDoubleFromArray(fp, (_idx))
+# define SET_REGISTER_DOUBLE(_idx, _val)    putDoubleToArray(fp, (_idx), (_val))
+#endif
+
+/*
+ * Get 16 bits from the specified offset of the program counter.  We always
+ * want to load 16 bits at a time from the instruction stream -- it's more
+ * efficient than 8 and won't have the alignment problems that 32 might.
+ *
+ * Assumes existence of "const u2* pc".
+ */
+#define FETCH(_offset)     (pc[(_offset)])
+
+/*
+ * Extract instruction byte from 16-bit fetch (_inst is a u2).
+ */
+#define INST_INST(_inst)    ((_inst) & 0xff)
+
+/*
+ * Extract the "vA, vB" 4-bit registers from the instruction word (_inst is u2).
+ */
+#define INST_A(_inst)       (((_inst) >> 8) & 0x0f)
+#define INST_B(_inst)       ((_inst) >> 12)
+
+/*
+ * Get the 8-bit "vAA" 8-bit register index from the instruction word.
+ * (_inst is u2)
+ */
+#define INST_AA(_inst)      ((_inst) >> 8)
+
+/*
+ * The current PC must be available to Throwable constructors, e.g.
+ * those created by dvmThrowException(), so that the exception stack
+ * trace can be generated correctly.  If we don't do this, the offset
+ * within the current method won't be shown correctly.  See the notes
+ * in Exception.c.
+ *
+ * This is also used to determine the address for precise GC.
+ *
+ * Assumes existence of "u4* fp" and "const u2* pc".
+ */
+#define EXPORT_PC()         (SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc)
+
+/*
+ * Determine if we need to switch to a different interpreter.  "_current"
+ * is either INTERP_STD or INTERP_DBG.  It should be fixed for a given
+ * interpreter generation file, which should remove the outer conditional
+ * from the following.
+ *
+ * If we're building without debug and profiling support, we never switch.
+ */
+#if defined(WITH_PROFILER) || defined(WITH_DEBUGGER)
+#if defined(WITH_JIT)
+# define NEED_INTERP_SWITCH(_current) (                                     \
+    (_current == INTERP_STD) ?                                              \
+        dvmJitDebuggerOrProfilerActive(interpState->jitState) :             \
+        !dvmJitDebuggerOrProfilerActive(interpState->jitState) )
+#else
+# define NEED_INTERP_SWITCH(_current) (                                     \
+    (_current == INTERP_STD) ?                                              \
+        dvmDebuggerOrProfilerActive() : !dvmDebuggerOrProfilerActive() )
+#endif
+#else
+# define NEED_INTERP_SWITCH(_current) (false)
+#endif
+
+/*
+ * Check to see if "obj" is NULL.  If so, throw an exception.  Assumes the
+ * pc has already been exported to the stack.
+ *
+ * Perform additional checks on debug builds.
+ *
+ * Use this to check for NULL when the instruction handler calls into
+ * something that could throw an exception (so we have already called
+ * EXPORT_PC at the top).
+ */
+static inline bool checkForNull(Object* obj)
+{
+    if (obj == NULL) {
+        dvmThrowException("Ljava/lang/NullPointerException;", NULL);
+        return false;
+    }
+#ifdef WITH_EXTRA_OBJECT_VALIDATION
+    if (!dvmIsValidObject(obj)) {
+        LOGE("Invalid object %p\n", obj);
+        dvmAbort();
+    }
+#endif
+#ifndef NDEBUG
+    if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) {
+        /* probable heap corruption */
+        LOGE("Invalid object class %p (in %p)\n", obj->clazz, obj);
+        dvmAbort();
+    }
+#endif
+    return true;
+}
+
+/*
+ * Check to see if "obj" is NULL.  If so, export the PC into the stack
+ * frame and throw an exception.
+ *
+ * Perform additional checks on debug builds.
+ *
+ * Use this to check for NULL when the instruction handler doesn't do
+ * anything else that can throw an exception.
+ */
+static inline bool checkForNullExportPC(Object* obj, u4* fp, const u2* pc)
+{
+    if (obj == NULL) {
+        EXPORT_PC();
+        dvmThrowException("Ljava/lang/NullPointerException;", NULL);
+        return false;
+    }
+#ifdef WITH_EXTRA_OBJECT_VALIDATION
+    if (!dvmIsValidObject(obj)) {
+        LOGE("Invalid object %p\n", obj);
+        dvmAbort();
+    }
+#endif
+#ifndef NDEBUG
+    if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) {
+        /* probable heap corruption */
+        LOGE("Invalid object class %p (in %p)\n", obj->clazz, obj);
+        dvmAbort();
+    }
+#endif
+    return true;
+}
+
+/* File: cstubs/stubdefs.c */
+/* this is a standard (no debug support) interpreter */
+#define INTERP_TYPE INTERP_STD
+#define CHECK_DEBUG_AND_PROF() ((void)0)
+# define CHECK_TRACKED_REFS() ((void)0)
+
+/*
+ * In the C mterp stubs, "goto" is a function call followed immediately
+ * by a return.
+ */
+
+#define GOTO_TARGET_DECL(_target, ...)                                      \
+    void dvmMterp_##_target(MterpGlue* glue, ## __VA_ARGS__);
+
+#define GOTO_TARGET(_target, ...)                                           \
+    void dvmMterp_##_target(MterpGlue* glue, ## __VA_ARGS__) {              \
+        u2 ref, vsrc1, vsrc2, vdst;                                         \
+        u2 inst = FETCH(0);                                                 \
+        const Method* methodToCall;                                         \
+        StackSaveArea* debugSaveArea;
+
+#define GOTO_TARGET_END }
+
+/*
+ * Redefine what used to be local variable accesses into MterpGlue struct
+ * references.  (These are undefined down in "footer.c".)
+ */
+#define retval                  glue->retval
+#define pc                      glue->pc
+#define fp                      glue->fp
+#define curMethod               glue->method
+#define methodClassDex          glue->methodClassDex
+#define self                    glue->self
+#define debugTrackedRefStart    glue->debugTrackedRefStart
+
+/* ugh */
+#define STUB_HACK(x) x
+
+
+/*
+ * Opcode handler framing macros.  Here, each opcode is a separate function
+ * that takes a "glue" argument and returns void.  We can't declare
+ * these "static" because they may be called from an assembly stub.
+ */
+#define HANDLE_OPCODE(_op)                                                  \
+    void dvmMterp_##_op(MterpGlue* glue) {                                  \
+        u2 ref, vsrc1, vsrc2, vdst;                                         \
+        u2 inst = FETCH(0);
+
+#define OP_END }
+
+/*
+ * Like the "portable" FINISH, but don't reload "inst", and return to caller
+ * when done.
+ */
+#define FINISH(_offset) {                                                   \
+        ADJUST_PC(_offset);                                                 \
+        CHECK_DEBUG_AND_PROF();                                             \
+        CHECK_TRACKED_REFS();                                               \
+        return;                                                             \
+    }
+
+
+/*
+ * The "goto label" statements turn into function calls followed by
+ * return statements.  Some of the functions take arguments, which in the
+ * portable interpreter are handled by assigning values to globals.
+ */
+
+#define GOTO_exceptionThrown()                                              \
+    do {                                                                    \
+        dvmMterp_exceptionThrown(glue);                                     \
+        return;                                                             \
+    } while(false)
+
+#define GOTO_returnFromMethod()                                             \
+    do {                                                                    \
+        dvmMterp_returnFromMethod(glue);                                    \
+        return;                                                             \
+    } while(false)
+
+#define GOTO_invoke(_target, _methodCallRange)                              \
+    do {                                                                    \
+        dvmMterp_##_target(glue, _methodCallRange);                         \
+        return;                                                             \
+    } while(false)
+
+#define GOTO_invokeMethod(_methodCallRange, _methodToCall, _vsrc1, _vdst)   \
+    do {                                                                    \
+        dvmMterp_invokeMethod(glue, _methodCallRange, _methodToCall,        \
+            _vsrc1, _vdst);                                                 \
+        return;                                                             \
+    } while(false)
+
+/*
+ * As a special case, "goto bail" turns into a longjmp.  Use "bail_switch"
+ * if we need to switch to the other interpreter upon our return.
+ */
+#define GOTO_bail()                                                         \
+    dvmMterpStdBail(glue, false);
+#define GOTO_bail_switch()                                                  \
+    dvmMterpStdBail(glue, true);
+
+/*
+ * Periodically check for thread suspension.
+ *
+ * While we're at it, see if a debugger has attached or the profiler has
+ * started.  If so, switch to a different "goto" table.
+ */
+#define PERIODIC_CHECKS(_entryPoint, _pcadj) {                              \
+        if (dvmCheckSuspendQuick(self)) {                                   \
+            EXPORT_PC();  /* need for precise GC */                         \
+            dvmCheckSuspendPending(self);                                   \
+        }                                                                   \
+        if (NEED_INTERP_SWITCH(INTERP_TYPE)) {                              \
+            ADJUST_PC(_pcadj);                                              \
+            glue->entryPoint = _entryPoint;                                 \
+            LOGVV("threadid=%d: switch to STD ep=%d adj=%d\n",              \
+                self->threadId, (_entryPoint), (_pcadj));                   \
+            GOTO_bail_switch();                                             \
+        }                                                                   \
+    }
+
+
+/* File: c/opcommon.c */
+/* forward declarations of goto targets */
+GOTO_TARGET_DECL(filledNewArray, bool methodCallRange);
+GOTO_TARGET_DECL(invokeVirtual, bool methodCallRange);
+GOTO_TARGET_DECL(invokeSuper, bool methodCallRange);
+GOTO_TARGET_DECL(invokeInterface, bool methodCallRange);
+GOTO_TARGET_DECL(invokeDirect, bool methodCallRange);
+GOTO_TARGET_DECL(invokeStatic, bool methodCallRange);
+GOTO_TARGET_DECL(invokeVirtualQuick, bool methodCallRange);
+GOTO_TARGET_DECL(invokeSuperQuick, bool methodCallRange);
+GOTO_TARGET_DECL(invokeMethod, bool methodCallRange, const Method* methodToCall,
+    u2 count, u2 regs);
+GOTO_TARGET_DECL(returnFromMethod);
+GOTO_TARGET_DECL(exceptionThrown);
+
+/*
+ * ===========================================================================
+ *
+ * What follows are opcode definitions shared between multiple opcodes with
+ * minor substitutions handled by the C pre-processor.  These should probably
+ * use the mterp substitution mechanism instead, with the code here moved
+ * into common fragment files (like the asm "binop.S"), although it's hard
+ * to give up the C preprocessor in favor of the much simpler text subst.
+ *
+ * ===========================================================================
+ */
+
+#define HANDLE_NUMCONV(_opcode, _opname, _fromtype, _totype)                \
+    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);                                               \
+        ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1);                       \
+        SET_REGISTER##_totype(vdst,                                         \
+            GET_REGISTER##_fromtype(vsrc1));                                \
+        FINISH(1);
+
+#define HANDLE_FLOAT_TO_INT(_opcode, _opname, _fromvtype, _fromrtype,       \
+        _tovtype, _tortype)                                                 \
+    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
+    {                                                                       \
+        /* spec defines specific handling for +/- inf and NaN values */     \
+        _fromvtype val;                                                     \
+        _tovtype intMin, intMax, result;                                    \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);                                               \
+        ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1);                       \
+        val = GET_REGISTER##_fromrtype(vsrc1);                              \
+        intMin = (_tovtype) 1 << (sizeof(_tovtype) * 8 -1);                 \
+        intMax = ~intMin;                                                   \
+        result = (_tovtype) val;                                            \
+        if (val >= intMax)          /* +inf */                              \
+            result = intMax;                                                \
+        else if (val <= intMin)     /* -inf */                              \
+            result = intMin;                                                \
+        else if (val != val)        /* NaN */                               \
+            result = 0;                                                     \
+        else                                                                \
+            result = (_tovtype) val;                                        \
+        SET_REGISTER##_tortype(vdst, result);                               \
+    }                                                                       \
+    FINISH(1);
+
+#define HANDLE_INT_TO_SMALL(_opcode, _opname, _type)                        \
+    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);                                               \
+        ILOGV("|int-to-%s v%d,v%d", (_opname), vdst, vsrc1);                \
+        SET_REGISTER(vdst, (_type) GET_REGISTER(vsrc1));                    \
+        FINISH(1);
+
+/* NOTE: the comparison result is always a signed 4-byte integer */
+#define HANDLE_OP_CMPX(_opcode, _opname, _varType, _type, _nanVal)          \
+    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
+    {                                                                       \
+        int result;                                                         \
+        u2 regs;                                                            \
+        _varType val1, val2;                                                \
+        vdst = INST_AA(inst);                                               \
+        regs = FETCH(1);                                                    \
+        vsrc1 = regs & 0xff;                                                \
+        vsrc2 = regs >> 8;                                                  \
+        ILOGV("|cmp%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);         \
+        val1 = GET_REGISTER##_type(vsrc1);                                  \
+        val2 = GET_REGISTER##_type(vsrc2);                                  \
+        if (val1 == val2)                                                   \
+            result = 0;                                                     \
+        else if (val1 < val2)                                               \
+            result = -1;                                                    \
+        else if (val1 > val2)                                               \
+            result = 1;                                                     \
+        else                                                                \
+            result = (_nanVal);                                             \
+        ILOGV("+ result=%d\n", result);                                     \
+        SET_REGISTER(vdst, result);                                         \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_OP_IF_XX(_opcode, _opname, _cmp)                             \
+    HANDLE_OPCODE(_opcode /*vA, vB, +CCCC*/)                                \
+        vsrc1 = INST_A(inst);                                               \
+        vsrc2 = INST_B(inst);                                               \
+        if ((s4) GET_REGISTER(vsrc1) _cmp (s4) GET_REGISTER(vsrc2)) {       \
+            int branchOffset = (s2)FETCH(1);    /* sign-extended */         \
+            ILOGV("|if-%s v%d,v%d,+0x%04x", (_opname), vsrc1, vsrc2,        \
+                branchOffset);                                              \
+            ILOGV("> branch taken");                                        \
+            if (branchOffset < 0)                                           \
+                PERIODIC_CHECKS(kInterpEntryInstr, branchOffset);           \
+            FINISH(branchOffset);                                           \
+        } else {                                                            \
+            ILOGV("|if-%s v%d,v%d,-", (_opname), vsrc1, vsrc2);             \
+            FINISH(2);                                                      \
+        }
+
+#define HANDLE_OP_IF_XXZ(_opcode, _opname, _cmp)                            \
+    HANDLE_OPCODE(_opcode /*vAA, +BBBB*/)                                   \
+        vsrc1 = INST_AA(inst);                                              \
+        if ((s4) GET_REGISTER(vsrc1) _cmp 0) {                              \
+            int branchOffset = (s2)FETCH(1);    /* sign-extended */         \
+            ILOGV("|if-%s v%d,+0x%04x", (_opname), vsrc1, branchOffset);    \
+            ILOGV("> branch taken");                                        \
+            if (branchOffset < 0)                                           \
+                PERIODIC_CHECKS(kInterpEntryInstr, branchOffset);           \
+            FINISH(branchOffset);                                           \
+        } else {                                                            \
+            ILOGV("|if-%s v%d,-", (_opname), vsrc1);                        \
+            FINISH(2);                                                      \
+        }
+
+#define HANDLE_UNOP(_opcode, _opname, _pfx, _sfx, _type)                    \
+    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);                                               \
+        ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1);                       \
+        SET_REGISTER##_type(vdst, _pfx GET_REGISTER##_type(vsrc1) _sfx);    \
+        FINISH(1);
+
+#define HANDLE_OP_X_INT(_opcode, _opname, _op, _chkdiv)                     \
+    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
+    {                                                                       \
+        u2 srcRegs;                                                         \
+        vdst = INST_AA(inst);                                               \
+        srcRegs = FETCH(1);                                                 \
+        vsrc1 = srcRegs & 0xff;                                             \
+        vsrc2 = srcRegs >> 8;                                               \
+        ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1);                   \
+        if (_chkdiv != 0) {                                                 \
+            s4 firstVal, secondVal, result;                                 \
+            firstVal = GET_REGISTER(vsrc1);                                 \
+            secondVal = GET_REGISTER(vsrc2);                                \
+            if (secondVal == 0) {                                           \
+                EXPORT_PC();                                                \
+                dvmThrowException("Ljava/lang/ArithmeticException;",        \
+                    "divide by zero");                                      \
+                GOTO_exceptionThrown();                                     \
+            }                                                               \
+            if ((u4)firstVal == 0x80000000 && secondVal == -1) {            \
+                if (_chkdiv == 1)                                           \
+                    result = firstVal;  /* division */                      \
+                else                                                        \
+                    result = 0;         /* remainder */                     \
+            } else {                                                        \
+                result = firstVal _op secondVal;                            \
+            }                                                               \
+            SET_REGISTER(vdst, result);                                     \
+        } else {                                                            \
+            /* non-div/rem case */                                          \
+            SET_REGISTER(vdst,                                              \
+                (s4) GET_REGISTER(vsrc1) _op (s4) GET_REGISTER(vsrc2));     \
+        }                                                                   \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_OP_SHX_INT(_opcode, _opname, _cast, _op)                     \
+    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
+    {                                                                       \
+        u2 srcRegs;                                                         \
+        vdst = INST_AA(inst);                                               \
+        srcRegs = FETCH(1);                                                 \
+        vsrc1 = srcRegs & 0xff;                                             \
+        vsrc2 = srcRegs >> 8;                                               \
+        ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1);                   \
+        SET_REGISTER(vdst,                                                  \
+            _cast GET_REGISTER(vsrc1) _op (GET_REGISTER(vsrc2) & 0x1f));    \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_OP_X_INT_LIT16(_opcode, _opname, _op, _chkdiv)               \
+    HANDLE_OPCODE(_opcode /*vA, vB, #+CCCC*/)                               \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);                                               \
+        vsrc2 = FETCH(1);                                                   \
+        ILOGV("|%s-int/lit16 v%d,v%d,#+0x%04x",                             \
+            (_opname), vdst, vsrc1, vsrc2);                                 \
+        if (_chkdiv != 0) {                                                 \
+            s4 firstVal, result;                                            \
+            firstVal = GET_REGISTER(vsrc1);                                 \
+            if ((s2) vsrc2 == 0) {                                          \
+                EXPORT_PC();                                                \
+                dvmThrowException("Ljava/lang/ArithmeticException;",        \
+                    "divide by zero");                                      \
+                GOTO_exceptionThrown();                                      \
+            }                                                               \
+            if ((u4)firstVal == 0x80000000 && ((s2) vsrc2) == -1) {         \
+                /* won't generate /lit16 instr for this; check anyway */    \
+                if (_chkdiv == 1)                                           \
+                    result = firstVal;  /* division */                      \
+                else                                                        \
+                    result = 0;         /* remainder */                     \
+            } else {                                                        \
+                result = firstVal _op (s2) vsrc2;                           \
+            }                                                               \
+            SET_REGISTER(vdst, result);                                     \
+        } else {                                                            \
+            /* non-div/rem case */                                          \
+            SET_REGISTER(vdst, GET_REGISTER(vsrc1) _op (s2) vsrc2);         \
+        }                                                                   \
+        FINISH(2);
+
+#define HANDLE_OP_X_INT_LIT8(_opcode, _opname, _op, _chkdiv)                \
+    HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/)                               \
+    {                                                                       \
+        u2 litInfo;                                                         \
+        vdst = INST_AA(inst);                                               \
+        litInfo = FETCH(1);                                                 \
+        vsrc1 = litInfo & 0xff;                                             \
+        vsrc2 = litInfo >> 8;       /* constant */                          \
+        ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x",                              \
+            (_opname), vdst, vsrc1, vsrc2);                                 \
+        if (_chkdiv != 0) {                                                 \
+            s4 firstVal, result;                                            \
+            firstVal = GET_REGISTER(vsrc1);                                 \
+            if ((s1) vsrc2 == 0) {                                          \
+                EXPORT_PC();                                                \
+                dvmThrowException("Ljava/lang/ArithmeticException;",        \
+                    "divide by zero");                                      \
+                GOTO_exceptionThrown();                                     \
+            }                                                               \
+            if ((u4)firstVal == 0x80000000 && ((s1) vsrc2) == -1) {         \
+                if (_chkdiv == 1)                                           \
+                    result = firstVal;  /* division */                      \
+                else                                                        \
+                    result = 0;         /* remainder */                     \
+            } else {                                                        \
+                result = firstVal _op ((s1) vsrc2);                         \
+            }                                                               \
+            SET_REGISTER(vdst, result);                                     \
+        } else {                                                            \
+            SET_REGISTER(vdst,                                              \
+                (s4) GET_REGISTER(vsrc1) _op (s1) vsrc2);                   \
+        }                                                                   \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_OP_SHX_INT_LIT8(_opcode, _opname, _cast, _op)                \
+    HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/)                               \
+    {                                                                       \
+        u2 litInfo;                                                         \
+        vdst = INST_AA(inst);                                               \
+        litInfo = FETCH(1);                                                 \
+        vsrc1 = litInfo & 0xff;                                             \
+        vsrc2 = litInfo >> 8;       /* constant */                          \
+        ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x",                              \
+            (_opname), vdst, vsrc1, vsrc2);                                 \
+        SET_REGISTER(vdst,                                                  \
+            _cast GET_REGISTER(vsrc1) _op (vsrc2 & 0x1f));                  \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_OP_X_INT_2ADDR(_opcode, _opname, _op, _chkdiv)               \
+    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);                                               \
+        ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1);             \
+        if (_chkdiv != 0) {                                                 \
+            s4 firstVal, secondVal, result;                                 \
+            firstVal = GET_REGISTER(vdst);                                  \
+            secondVal = GET_REGISTER(vsrc1);                                \
+            if (secondVal == 0) {                                           \
+                EXPORT_PC();                                                \
+                dvmThrowException("Ljava/lang/ArithmeticException;",        \
+                    "divide by zero");                                      \
+                GOTO_exceptionThrown();                                     \
+            }                                                               \
+            if ((u4)firstVal == 0x80000000 && secondVal == -1) {            \
+                if (_chkdiv == 1)                                           \
+                    result = firstVal;  /* division */                      \
+                else                                                        \
+                    result = 0;         /* remainder */                     \
+            } else {                                                        \
+                result = firstVal _op secondVal;                            \
+            }                                                               \
+            SET_REGISTER(vdst, result);                                     \
+        } else {                                                            \
+            SET_REGISTER(vdst,                                              \
+                (s4) GET_REGISTER(vdst) _op (s4) GET_REGISTER(vsrc1));      \
+        }                                                                   \
+        FINISH(1);
+
+#define HANDLE_OP_SHX_INT_2ADDR(_opcode, _opname, _cast, _op)               \
+    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);                                               \
+        ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1);             \
+        SET_REGISTER(vdst,                                                  \
+            _cast GET_REGISTER(vdst) _op (GET_REGISTER(vsrc1) & 0x1f));     \
+        FINISH(1);
+
+#define HANDLE_OP_X_LONG(_opcode, _opname, _op, _chkdiv)                    \
+    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
+    {                                                                       \
+        u2 srcRegs;                                                         \
+        vdst = INST_AA(inst);                                               \
+        srcRegs = FETCH(1);                                                 \
+        vsrc1 = srcRegs & 0xff;                                             \
+        vsrc2 = srcRegs >> 8;                                               \
+        ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);       \
+        if (_chkdiv != 0) {                                                 \
+            s8 firstVal, secondVal, result;                                 \
+            firstVal = GET_REGISTER_WIDE(vsrc1);                            \
+            secondVal = GET_REGISTER_WIDE(vsrc2);                           \
+            if (secondVal == 0LL) {                                         \
+                EXPORT_PC();                                                \
+                dvmThrowException("Ljava/lang/ArithmeticException;",        \
+                    "divide by zero");                                      \
+                GOTO_exceptionThrown();                                     \
+            }                                                               \
+            if ((u8)firstVal == 0x8000000000000000ULL &&                    \
+                secondVal == -1LL)                                          \
+            {                                                               \
+                if (_chkdiv == 1)                                           \
+                    result = firstVal;  /* division */                      \
+                else                                                        \
+                    result = 0;         /* remainder */                     \
+            } else {                                                        \
+                result = firstVal _op secondVal;                            \
+            }                                                               \
+            SET_REGISTER_WIDE(vdst, result);                                \
+        } else {                                                            \
+            SET_REGISTER_WIDE(vdst,                                         \
+                (s8) GET_REGISTER_WIDE(vsrc1) _op (s8) GET_REGISTER_WIDE(vsrc2)); \
+        }                                                                   \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_OP_SHX_LONG(_opcode, _opname, _cast, _op)                    \
+    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
+    {                                                                       \
+        u2 srcRegs;                                                         \
+        vdst = INST_AA(inst);                                               \
+        srcRegs = FETCH(1);                                                 \
+        vsrc1 = srcRegs & 0xff;                                             \
+        vsrc2 = srcRegs >> 8;                                               \
+        ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);       \
+        SET_REGISTER_WIDE(vdst,                                             \
+            _cast GET_REGISTER_WIDE(vsrc1) _op (GET_REGISTER(vsrc2) & 0x3f)); \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_OP_X_LONG_2ADDR(_opcode, _opname, _op, _chkdiv)              \
+    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);                                               \
+        ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1);            \
+        if (_chkdiv != 0) {                                                 \
+            s8 firstVal, secondVal, result;                                 \
+            firstVal = GET_REGISTER_WIDE(vdst);                             \
+            secondVal = GET_REGISTER_WIDE(vsrc1);                           \
+            if (secondVal == 0LL) {                                         \
+                EXPORT_PC();                                                \
+                dvmThrowException("Ljava/lang/ArithmeticException;",        \
+                    "divide by zero");                                      \
+                GOTO_exceptionThrown();                                     \
+            }                                                               \
+            if ((u8)firstVal == 0x8000000000000000ULL &&                    \
+                secondVal == -1LL)                                          \
+            {                                                               \
+                if (_chkdiv == 1)                                           \
+                    result = firstVal;  /* division */                      \
+                else                                                        \
+                    result = 0;         /* remainder */                     \
+            } else {                                                        \
+                result = firstVal _op secondVal;                            \
+            }                                                               \
+            SET_REGISTER_WIDE(vdst, result);                                \
+        } else {                                                            \
+            SET_REGISTER_WIDE(vdst,                                         \
+                (s8) GET_REGISTER_WIDE(vdst) _op (s8)GET_REGISTER_WIDE(vsrc1));\
+        }                                                                   \
+        FINISH(1);
+
+#define HANDLE_OP_SHX_LONG_2ADDR(_opcode, _opname, _cast, _op)              \
+    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);                                               \
+        ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1);            \
+        SET_REGISTER_WIDE(vdst,                                             \
+            _cast GET_REGISTER_WIDE(vdst) _op (GET_REGISTER(vsrc1) & 0x3f)); \
+        FINISH(1);
+
+#define HANDLE_OP_X_FLOAT(_opcode, _opname, _op)                            \
+    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
+    {                                                                       \
+        u2 srcRegs;                                                         \
+        vdst = INST_AA(inst);                                               \
+        srcRegs = FETCH(1);                                                 \
+        vsrc1 = srcRegs & 0xff;                                             \
+        vsrc2 = srcRegs >> 8;                                               \
+        ILOGV("|%s-float v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);      \
+        SET_REGISTER_FLOAT(vdst,                                            \
+            GET_REGISTER_FLOAT(vsrc1) _op GET_REGISTER_FLOAT(vsrc2));       \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_OP_X_DOUBLE(_opcode, _opname, _op)                           \
+    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
+    {                                                                       \
+        u2 srcRegs;                                                         \
+        vdst = INST_AA(inst);                                               \
+        srcRegs = FETCH(1);                                                 \
+        vsrc1 = srcRegs & 0xff;                                             \
+        vsrc2 = srcRegs >> 8;                                               \
+        ILOGV("|%s-double v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);     \
+        SET_REGISTER_DOUBLE(vdst,                                           \
+            GET_REGISTER_DOUBLE(vsrc1) _op GET_REGISTER_DOUBLE(vsrc2));     \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_OP_X_FLOAT_2ADDR(_opcode, _opname, _op)                      \
+    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);                                               \
+        ILOGV("|%s-float-2addr v%d,v%d", (_opname), vdst, vsrc1);           \
+        SET_REGISTER_FLOAT(vdst,                                            \
+            GET_REGISTER_FLOAT(vdst) _op GET_REGISTER_FLOAT(vsrc1));        \
+        FINISH(1);
+
+#define HANDLE_OP_X_DOUBLE_2ADDR(_opcode, _opname, _op)                     \
+    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);                                               \
+        ILOGV("|%s-double-2addr v%d,v%d", (_opname), vdst, vsrc1);          \
+        SET_REGISTER_DOUBLE(vdst,                                           \
+            GET_REGISTER_DOUBLE(vdst) _op GET_REGISTER_DOUBLE(vsrc1));      \
+        FINISH(1);
+
+#define HANDLE_OP_AGET(_opcode, _opname, _type, _regsize)                   \
+    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
+    {                                                                       \
+        ArrayObject* arrayObj;                                              \
+        u2 arrayInfo;                                                       \
+        EXPORT_PC();                                                        \
+        vdst = INST_AA(inst);                                               \
+        arrayInfo = FETCH(1);                                               \
+        vsrc1 = arrayInfo & 0xff;    /* array ptr */                        \
+        vsrc2 = arrayInfo >> 8;      /* index */                            \
+        ILOGV("|aget%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);        \
+        arrayObj = (ArrayObject*) GET_REGISTER(vsrc1);                      \
+        if (!checkForNull((Object*) arrayObj))                              \
+            GOTO_exceptionThrown();                                         \
+        if (GET_REGISTER(vsrc2) >= arrayObj->length) {                      \
+            LOGV("Invalid array access: %p %d (len=%d)\n",                  \
+                arrayObj, vsrc2, arrayObj->length);                         \
+            dvmThrowException("Ljava/lang/ArrayIndexOutOfBoundsException;", \
+                NULL);                                                      \
+            GOTO_exceptionThrown();                                         \
+        }                                                                   \
+        SET_REGISTER##_regsize(vdst,                                        \
+            ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)]);            \
+        ILOGV("+ AGET[%d]=0x%x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));  \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_OP_APUT(_opcode, _opname, _type, _regsize)                   \
+    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
+    {                                                                       \
+        ArrayObject* arrayObj;                                              \
+        u2 arrayInfo;                                                       \
+        EXPORT_PC();                                                        \
+        vdst = INST_AA(inst);       /* AA: source value */                  \
+        arrayInfo = FETCH(1);                                               \
+        vsrc1 = arrayInfo & 0xff;   /* BB: array ptr */                     \
+        vsrc2 = arrayInfo >> 8;     /* CC: index */                         \
+        ILOGV("|aput%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);        \
+        arrayObj = (ArrayObject*) GET_REGISTER(vsrc1);                      \
+        if (!checkForNull((Object*) arrayObj))                              \
+            GOTO_exceptionThrown();                                         \
+        if (GET_REGISTER(vsrc2) >= arrayObj->length) {                      \
+            dvmThrowException("Ljava/lang/ArrayIndexOutOfBoundsException;", \
+                NULL);                                                      \
+            GOTO_exceptionThrown();                                         \
+        }                                                                   \
+        ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
+        ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)] =                \
+            GET_REGISTER##_regsize(vdst);                                   \
+    }                                                                       \
+    FINISH(2);
+
+/*
+ * It's possible to get a bad value out of a field with sub-32-bit stores
+ * because the -quick versions always operate on 32 bits.  Consider:
+ *   short foo = -1  (sets a 32-bit register to 0xffffffff)
+ *   iput-quick foo  (writes all 32 bits to the field)
+ *   short bar = 1   (sets a 32-bit register to 0x00000001)
+ *   iput-short      (writes the low 16 bits to the field)
+ *   iget-quick foo  (reads all 32 bits from the field, yielding 0xffff0001)
+ * This can only happen when optimized and non-optimized code has interleaved
+ * access to the same field.  This is unlikely but possible.
+ *
+ * The easiest way to fix this is to always read/write 32 bits at a time.  On
+ * a device with a 16-bit data bus this is sub-optimal.  (The alternative
+ * approach is to have sub-int versions of iget-quick, but now we're wasting
+ * Dalvik instruction space and making it less likely that handler code will
+ * already be in the CPU i-cache.)
+ */
+#define HANDLE_IGET_X(_opcode, _opname, _ftype, _regsize)                   \
+    HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \
+    {                                                                       \
+        InstField* ifield;                                                  \
+        Object* obj;                                                        \
+        EXPORT_PC();                                                        \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);   /* object ptr */                            \
+        ref = FETCH(1);         /* field ref */                             \
+        ILOGV("|iget%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \
+        obj = (Object*) GET_REGISTER(vsrc1);                                \
+        if (!checkForNull(obj))                                             \
+            GOTO_exceptionThrown();                                         \
+        ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref);  \
+        if (ifield == NULL) {                                               \
+            ifield = dvmResolveInstField(curMethod->clazz, ref);            \
+            if (ifield == NULL)                                             \
+                GOTO_exceptionThrown();                                     \
+        }                                                                   \
+        SET_REGISTER##_regsize(vdst,                                        \
+            dvmGetField##_ftype(obj, ifield->byteOffset));                  \
+        ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name,                   \
+            (u8) GET_REGISTER##_regsize(vdst));                             \
+        UPDATE_FIELD_GET(&ifield->field);                                   \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_IGET_X_QUICK(_opcode, _opname, _ftype, _regsize)             \
+    HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \
+    {                                                                       \
+        Object* obj;                                                        \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);   /* object ptr */                            \
+        ref = FETCH(1);         /* field offset */                          \
+        ILOGV("|iget%s-quick v%d,v%d,field@+%u",                            \
+            (_opname), vdst, vsrc1, ref);                                   \
+        obj = (Object*) GET_REGISTER(vsrc1);                                \
+        if (!checkForNullExportPC(obj, fp, pc))                             \
+            GOTO_exceptionThrown();                                         \
+        SET_REGISTER##_regsize(vdst, dvmGetField##_ftype(obj, ref));        \
+        ILOGV("+ IGETQ %d=0x%08llx", ref,                                   \
+            (u8) GET_REGISTER##_regsize(vdst));                             \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_IPUT_X(_opcode, _opname, _ftype, _regsize)                   \
+    HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \
+    {                                                                       \
+        InstField* ifield;                                                  \
+        Object* obj;                                                        \
+        EXPORT_PC();                                                        \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);   /* object ptr */                            \
+        ref = FETCH(1);         /* field ref */                             \
+        ILOGV("|iput%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \
+        obj = (Object*) GET_REGISTER(vsrc1);                                \
+        if (!checkForNull(obj))                                             \
+            GOTO_exceptionThrown();                                         \
+        ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref);  \
+        if (ifield == NULL) {                                               \
+            ifield = dvmResolveInstField(curMethod->clazz, ref);            \
+            if (ifield == NULL)                                             \
+                GOTO_exceptionThrown();                                     \
+        }                                                                   \
+        dvmSetField##_ftype(obj, ifield->byteOffset,                        \
+            GET_REGISTER##_regsize(vdst));                                  \
+        ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name,                   \
+            (u8) GET_REGISTER##_regsize(vdst));                             \
+        UPDATE_FIELD_PUT(&ifield->field);                                   \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_IPUT_X_QUICK(_opcode, _opname, _ftype, _regsize)             \
+    HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \
+    {                                                                       \
+        Object* obj;                                                        \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);   /* object ptr */                            \
+        ref = FETCH(1);         /* field offset */                          \
+        ILOGV("|iput%s-quick v%d,v%d,field@0x%04x",                         \
+            (_opname), vdst, vsrc1, ref);                                   \
+        obj = (Object*) GET_REGISTER(vsrc1);                                \
+        if (!checkForNullExportPC(obj, fp, pc))                             \
+            GOTO_exceptionThrown();                                         \
+        dvmSetField##_ftype(obj, ref, GET_REGISTER##_regsize(vdst));        \
+        ILOGV("+ IPUTQ %d=0x%08llx", ref,                                   \
+            (u8) GET_REGISTER##_regsize(vdst));                             \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_SGET_X(_opcode, _opname, _ftype, _regsize)                   \
+    HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/)                              \
+    {                                                                       \
+        StaticField* sfield;                                                \
+        vdst = INST_AA(inst);                                               \
+        ref = FETCH(1);         /* field ref */                             \
+        ILOGV("|sget%s v%d,sfield@0x%04x", (_opname), vdst, ref);           \
+        sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
+        if (sfield == NULL) {                                               \
+            EXPORT_PC();                                                    \
+            sfield = dvmResolveStaticField(curMethod->clazz, ref);          \
+            if (sfield == NULL)                                             \
+                GOTO_exceptionThrown();                                     \
+        }                                                                   \
+        SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield));    \
+        ILOGV("+ SGET '%s'=0x%08llx",                                       \
+            sfield->field.name, (u8)GET_REGISTER##_regsize(vdst));          \
+        UPDATE_FIELD_GET(&sfield->field);                                   \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_SPUT_X(_opcode, _opname, _ftype, _regsize)                   \
+    HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/)                              \
+    {                                                                       \
+        StaticField* sfield;                                                \
+        vdst = INST_AA(inst);                                               \
+        ref = FETCH(1);         /* field ref */                             \
+        ILOGV("|sput%s v%d,sfield@0x%04x", (_opname), vdst, ref);           \
+        sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
+        if (sfield == NULL) {                                               \
+            EXPORT_PC();                                                    \
+            sfield = dvmResolveStaticField(curMethod->clazz, ref);          \
+            if (sfield == NULL)                                             \
+                GOTO_exceptionThrown();                                     \
+        }                                                                   \
+        dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst));    \
+        ILOGV("+ SPUT '%s'=0x%08llx",                                       \
+            sfield->field.name, (u8)GET_REGISTER##_regsize(vdst));          \
+        UPDATE_FIELD_PUT(&sfield->field);                                   \
+    }                                                                       \
+    FINISH(2);
+
+
+/* File: cstubs/enddefs.c */
+
+/* undefine "magic" name remapping */
+#undef retval
+#undef pc
+#undef fp
+#undef curMethod
+#undef methodClassDex
+#undef self
+#undef debugTrackedRefStart
+
+/* File: armv5te/debug.c */
+#include <inttypes.h>
+
+/*
+ * Dump the fixed-purpose ARM registers, along with some other info.
+ *
+ * This function MUST be compiled in ARM mode -- THUMB will yield bogus
+ * results.
+ *
+ * This will NOT preserve r0-r3/ip.
+ */
+void dvmMterpDumpArmRegs(uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3)
+{
+    register uint32_t rPC       asm("r4");
+    register uint32_t rFP       asm("r5");
+    register uint32_t rGLUE     asm("r6");
+    register uint32_t rINST     asm("r7");
+    register uint32_t rIBASE    asm("r8");
+    register uint32_t r9        asm("r9");
+    register uint32_t r10       asm("r10");
+
+    extern char dvmAsmInstructionStart[];
+
+    printf("REGS: r0=%08x r1=%08x r2=%08x r3=%08x\n", r0, r1, r2, r3);
+    printf("    : rPC=%08x rFP=%08x rGLUE=%08x rINST=%08x\n",
+        rPC, rFP, rGLUE, rINST);
+    printf("    : rIBASE=%08x r9=%08x r10=%08x\n", rIBASE, r9, r10);
+
+    MterpGlue* glue = (MterpGlue*) rGLUE;
+    const Method* method = glue->method;
+    printf("    + self is %p\n", dvmThreadSelf());
+    //printf("    + currently in %s.%s %s\n",
+    //    method->clazz->descriptor, method->name, method->shorty);
+    //printf("    + dvmAsmInstructionStart = %p\n", dvmAsmInstructionStart);
+    //printf("    + next handler for 0x%02x = %p\n",
+    //    rINST & 0xff, dvmAsmInstructionStart + (rINST & 0xff) * 64);
+}
+
+/*
+ * Dump the StackSaveArea for the specified frame pointer.
+ */
+void dvmDumpFp(void* fp, StackSaveArea* otherSaveArea)
+{
+    StackSaveArea* saveArea = SAVEAREA_FROM_FP(fp);
+    printf("StackSaveArea for fp %p [%p/%p]:\n", fp, saveArea, otherSaveArea);
+#ifdef EASY_GDB
+    printf("  prevSave=%p, prevFrame=%p savedPc=%p meth=%p curPc=%p\n",
+        saveArea->prevSave, saveArea->prevFrame, saveArea->savedPc,
+        saveArea->method, saveArea->xtra.currentPc);
+#else
+    printf("  prevFrame=%p savedPc=%p meth=%p curPc=%p fp[0]=0x%08x\n",
+        saveArea->prevFrame, saveArea->savedPc,
+        saveArea->method, saveArea->xtra.currentPc,
+        *(u4*)fp);
+#endif
+}
+
+/*
+ * Does the bulk of the work for common_printMethod().
+ */
+void dvmMterpPrintMethod(Method* method)
+{
+    /*
+     * It is a direct (non-virtual) method if it is static, private,
+     * or a constructor.
+     */
+    bool isDirect =
+        ((method->accessFlags & (ACC_STATIC|ACC_PRIVATE)) != 0) ||
+        (method->name[0] == '<');
+
+    char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
+
+    printf("<%c:%s.%s %s> ",
+            isDirect ? 'D' : 'V',
+            method->clazz->descriptor,
+            method->name,
+            desc);
+
+    free(desc);
+}
+
diff --git a/vm/mterp/out/InterpC-armv5te.c b/vm/mterp/out/InterpC-armv5te.c
index 47c8709..ea11551 100644
--- a/vm/mterp/out/InterpC-armv5te.c
+++ b/vm/mterp/out/InterpC-armv5te.c
@@ -26,6 +26,7 @@
 #include "interp/InterpDefs.h"
 #include "mterp/Mterp.h"
 #include <math.h>                   // needed for fmod, fmodf
+#include "mterp/common/FindInterface.h"
 
 /*
  * Configuration defines.  These affect the C implementations, i.e. the
@@ -53,7 +54,7 @@
  */
 #define THREADED_INTERP             /* threaded vs. while-loop interpreter */
 
-#ifdef WITH_INSTR_CHECKS            /* instruction-level paranoia */
+#ifdef WITH_INSTR_CHECKS            /* instruction-level paranoia (slow!) */
 # define CHECK_BRANCH_OFFSETS
 # define CHECK_REGISTER_INDICES
 #endif
@@ -93,6 +94,18 @@
 #endif
 
 /*
+ * Export another copy of the PC on every instruction; this is largely
+ * redundant with EXPORT_PC and the debugger code.  This value can be
+ * compared against what we have stored on the stack with EXPORT_PC to
+ * help ensure that we aren't missing any export calls.
+ */
+#if WITH_EXTRA_GC_CHECKS > 1
+# define EXPORT_EXTRA_PC() (self->currentPc2 = pc)
+#else
+# define EXPORT_EXTRA_PC()
+#endif
+
+/*
  * Adjust the program counter.  "_offset" is a signed int, in 16-bit units.
  *
  * Assumes the existence of "const u2* pc" and "const u2* curMethod->insns".
@@ -116,9 +129,13 @@
             dvmAbort();                                                     \
         }                                                                   \
         pc += myoff;                                                        \
+        EXPORT_EXTRA_PC();                                                  \
     } while (false)
 #else
-# define ADJUST_PC(_offset) (pc += _offset)
+# define ADJUST_PC(_offset) do {                                            \
+        pc += _offset;                                                      \
+        EXPORT_EXTRA_PC();                                                  \
+    } while (false)
 #endif
 
 /*
@@ -303,6 +320,8 @@
  * within the current method won't be shown correctly.  See the notes
  * in Exception.c.
  *
+ * This is also used to determine the address for precise GC.
+ *
  * Assumes existence of "u4* fp" and "const u2* pc".
  */
 #define EXPORT_PC()         (SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc)
@@ -316,29 +335,21 @@
  * If we're building without debug and profiling support, we never switch.
  */
 #if defined(WITH_PROFILER) || defined(WITH_DEBUGGER)
+#if defined(WITH_JIT)
+# define NEED_INTERP_SWITCH(_current) (                                     \
+    (_current == INTERP_STD) ?                                              \
+        dvmJitDebuggerOrProfilerActive(interpState->jitState) :             \
+        !dvmJitDebuggerOrProfilerActive(interpState->jitState) )
+#else
 # define NEED_INTERP_SWITCH(_current) (                                     \
     (_current == INTERP_STD) ?                                              \
         dvmDebuggerOrProfilerActive() : !dvmDebuggerOrProfilerActive() )
+#endif
 #else
 # define NEED_INTERP_SWITCH(_current) (false)
 #endif
 
 /*
- * Look up an interface on a class using the cache.
- */
-INLINE Method* dvmFindInterfaceMethodInCache(ClassObject* thisClass,
-    u4 methodIdx, const Method* method, DvmDex* methodClassDex)
-{
-#define ATOMIC_CACHE_CALC \
-    dvmInterpFindInterfaceMethod(thisClass, methodIdx, method, methodClassDex)
-
-    return (Method*) ATOMIC_CACHE_LOOKUP(methodClassDex->pInterfaceCache,
-                DEX_INTERFACE_CACHE_SIZE, thisClass, methodIdx);
-
-#undef ATOMIC_CACHE_CALC
-}
-
-/*
  * Check to see if "obj" is NULL.  If so, throw an exception.  Assumes the
  * pc has already been exported to the stack.
  *
@@ -402,7 +413,6 @@
     return true;
 }
 
-
 /* File: cstubs/stubdefs.c */
 /* this is a standard (no debug support) interpreter */
 #define INTERP_TYPE INTERP_STD
@@ -513,12 +523,15 @@
  * started.  If so, switch to a different "goto" table.
  */
 #define PERIODIC_CHECKS(_entryPoint, _pcadj) {                              \
-        dvmCheckSuspendQuick(self);                                         \
+        if (dvmCheckSuspendQuick(self)) {                                   \
+            EXPORT_PC();  /* need for precise GC */                         \
+            dvmCheckSuspendPending(self);                                   \
+        }                                                                   \
         if (NEED_INTERP_SWITCH(INTERP_TYPE)) {                              \
             ADJUST_PC(_pcadj);                                              \
             glue->entryPoint = _entryPoint;                                 \
             LOGVV("threadid=%d: switch to STD ep=%d adj=%d\n",              \
-                glue->self->threadId, (_entryPoint), (_pcadj));             \
+                self->threadId, (_entryPoint), (_pcadj));                   \
             GOTO_bail_switch();                                             \
         }                                                                   \
     }
@@ -1199,23 +1212,23 @@
     register uint32_t rPC       asm("r4");
     register uint32_t rFP       asm("r5");
     register uint32_t rGLUE     asm("r6");
-    register uint32_t rIBASE    asm("r7");
-    register uint32_t rINST     asm("r8");
+    register uint32_t rINST     asm("r7");
+    register uint32_t rIBASE    asm("r8");
     register uint32_t r9        asm("r9");
     register uint32_t r10       asm("r10");
 
     extern char dvmAsmInstructionStart[];
 
     printf("REGS: r0=%08x r1=%08x r2=%08x r3=%08x\n", r0, r1, r2, r3);
-    printf("    : rPC=%08x rFP=%08x rGLUE=%08x rIBASE=%08x\n",
-        rPC, rFP, rGLUE, rIBASE);
-    printf("    : rINST=%08x r9=%08x r10=%08x\n", rINST, r9, r10);
+    printf("    : rPC=%08x rFP=%08x rGLUE=%08x rINST=%08x\n",
+        rPC, rFP, rGLUE, rINST);
+    printf("    : rIBASE=%08x r9=%08x r10=%08x\n", rIBASE, r9, r10);
 
     MterpGlue* glue = (MterpGlue*) rGLUE;
     const Method* method = glue->method;
     printf("    + self is %p\n", dvmThreadSelf());
     //printf("    + currently in %s.%s %s\n",
-    //    method->clazz->descriptor, method->name, method->signature);
+    //    method->clazz->descriptor, method->name, method->shorty);
     //printf("    + dvmAsmInstructionStart = %p\n", dvmAsmInstructionStart);
     //printf("    + next handler for 0x%02x = %p\n",
     //    rINST & 0xff, dvmAsmInstructionStart + (rINST & 0xff) * 64);
@@ -1249,12 +1262,12 @@
      * It is a direct (non-virtual) method if it is static, private,
      * or a constructor.
      */
-    bool isDirect = 
+    bool isDirect =
         ((method->accessFlags & (ACC_STATIC|ACC_PRIVATE)) != 0) ||
         (method->name[0] == '<');
 
     char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
-        
+
     printf("<%c:%s.%s %s> ",
             isDirect ? 'D' : 'V',
             method->clazz->descriptor,
diff --git a/vm/mterp/out/InterpC-armv7-a.c b/vm/mterp/out/InterpC-armv7-a.c
new file mode 100644
index 0000000..97799ec
--- /dev/null
+++ b/vm/mterp/out/InterpC-armv7-a.c
@@ -0,0 +1,1279 @@
+/*
+ * This file was generated automatically by gen-mterp.py for 'armv7-a'.
+ *
+ * --> DO NOT EDIT <--
+ */
+
+/* File: c/header.c */
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* common includes */
+#include "Dalvik.h"
+#include "interp/InterpDefs.h"
+#include "mterp/Mterp.h"
+#include <math.h>                   // needed for fmod, fmodf
+#include "mterp/common/FindInterface.h"
+
+/*
+ * Configuration defines.  These affect the C implementations, i.e. the
+ * portable interpreter(s) and C stubs.
+ *
+ * Some defines are controlled by the Makefile, e.g.:
+ *   WITH_PROFILER
+ *   WITH_DEBUGGER
+ *   WITH_INSTR_CHECKS
+ *   WITH_TRACKREF_CHECKS
+ *   EASY_GDB
+ *   NDEBUG
+ *
+ * If THREADED_INTERP is not defined, we use a classic "while true / switch"
+ * interpreter.  If it is defined, then the tail end of each instruction
+ * handler fetches the next instruction and jumps directly to the handler.
+ * This increases the size of the "Std" interpreter by about 10%, but
+ * provides a speedup of about the same magnitude.
+ *
+ * There's a "hybrid" approach that uses a goto table instead of a switch
+ * statement, avoiding the "is the opcode in range" tests required for switch.
+ * The performance is close to the threaded version, and without the 10%
+ * size increase, but the benchmark results are off enough that it's not
+ * worth adding as a third option.
+ */
+#define THREADED_INTERP             /* threaded vs. while-loop interpreter */
+
+#ifdef WITH_INSTR_CHECKS            /* instruction-level paranoia (slow!) */
+# define CHECK_BRANCH_OFFSETS
+# define CHECK_REGISTER_INDICES
+#endif
+
+/*
+ * ARM EABI requires 64-bit alignment for access to 64-bit data types.  We
+ * can't just use pointers to copy 64-bit values out of our interpreted
+ * register set, because gcc will generate ldrd/strd.
+ *
+ * The __UNION version copies data in and out of a union.  The __MEMCPY
+ * version uses a memcpy() call to do the transfer; gcc is smart enough to
+ * not actually call memcpy().  The __UNION version is very bad on ARM;
+ * it only uses one more instruction than __MEMCPY, but for some reason
+ * gcc thinks it needs separate storage for every instance of the union.
+ * On top of that, it feels the need to zero them out at the start of the
+ * method.  Net result is we zero out ~700 bytes of stack space at the top
+ * of the interpreter using ARM STM instructions.
+ */
+#if defined(__ARM_EABI__)
+//# define NO_UNALIGN_64__UNION
+# define NO_UNALIGN_64__MEMCPY
+#endif
+
+//#define LOG_INSTR                   /* verbose debugging */
+/* set and adjust ANDROID_LOG_TAGS='*:i jdwp:i dalvikvm:i dalvikvmi:i' */
+
+/*
+ * Keep a tally of accesses to fields.  Currently only works if full DEX
+ * optimization is disabled.
+ */
+#ifdef PROFILE_FIELD_ACCESS
+# define UPDATE_FIELD_GET(_field) { (_field)->gets++; }
+# define UPDATE_FIELD_PUT(_field) { (_field)->puts++; }
+#else
+# define UPDATE_FIELD_GET(_field) ((void)0)
+# define UPDATE_FIELD_PUT(_field) ((void)0)
+#endif
+
+/*
+ * Export another copy of the PC on every instruction; this is largely
+ * redundant with EXPORT_PC and the debugger code.  This value can be
+ * compared against what we have stored on the stack with EXPORT_PC to
+ * help ensure that we aren't missing any export calls.
+ */
+#if WITH_EXTRA_GC_CHECKS > 1
+# define EXPORT_EXTRA_PC() (self->currentPc2 = pc)
+#else
+# define EXPORT_EXTRA_PC()
+#endif
+
+/*
+ * Adjust the program counter.  "_offset" is a signed int, in 16-bit units.
+ *
+ * Assumes the existence of "const u2* pc" and "const u2* curMethod->insns".
+ *
+ * We don't advance the program counter until we finish an instruction or
+ * branch, because we do want to have to unroll the PC if there's an
+ * exception.
+ */
+#ifdef CHECK_BRANCH_OFFSETS
+# define ADJUST_PC(_offset) do {                                            \
+        int myoff = _offset;        /* deref only once */                   \
+        if (pc + myoff < curMethod->insns ||                                \
+            pc + myoff >= curMethod->insns + dvmGetMethodInsnsSize(curMethod)) \
+        {                                                                   \
+            char* desc;                                                     \
+            desc = dexProtoCopyMethodDescriptor(&curMethod->prototype);     \
+            LOGE("Invalid branch %d at 0x%04x in %s.%s %s\n",               \
+                myoff, (int) (pc - curMethod->insns),                       \
+                curMethod->clazz->descriptor, curMethod->name, desc);       \
+            free(desc);                                                     \
+            dvmAbort();                                                     \
+        }                                                                   \
+        pc += myoff;                                                        \
+        EXPORT_EXTRA_PC();                                                  \
+    } while (false)
+#else
+# define ADJUST_PC(_offset) do {                                            \
+        pc += _offset;                                                      \
+        EXPORT_EXTRA_PC();                                                  \
+    } while (false)
+#endif
+
+/*
+ * If enabled, log instructions as we execute them.
+ */
+#ifdef LOG_INSTR
+# define ILOGD(...) ILOG(LOG_DEBUG, __VA_ARGS__)
+# define ILOGV(...) ILOG(LOG_VERBOSE, __VA_ARGS__)
+# define ILOG(_level, ...) do {                                             \
+        char debugStrBuf[128];                                              \
+        snprintf(debugStrBuf, sizeof(debugStrBuf), __VA_ARGS__);            \
+        if (curMethod != NULL)                                                 \
+            LOG(_level, LOG_TAG"i", "%-2d|%04x%s\n",                        \
+                self->threadId, (int)(pc - curMethod->insns), debugStrBuf); \
+        else                                                                \
+            LOG(_level, LOG_TAG"i", "%-2d|####%s\n",                        \
+                self->threadId, debugStrBuf);                               \
+    } while(false)
+void dvmDumpRegs(const Method* method, const u4* framePtr, bool inOnly);
+# define DUMP_REGS(_meth, _frame, _inOnly) dvmDumpRegs(_meth, _frame, _inOnly)
+static const char kSpacing[] = "            ";
+#else
+# define ILOGD(...) ((void)0)
+# define ILOGV(...) ((void)0)
+# define DUMP_REGS(_meth, _frame, _inOnly) ((void)0)
+#endif
+
+/* get a long from an array of u4 */
+static inline s8 getLongFromArray(const u4* ptr, int idx)
+{
+#if defined(NO_UNALIGN_64__UNION)
+    union { s8 ll; u4 parts[2]; } conv;
+
+    ptr += idx;
+    conv.parts[0] = ptr[0];
+    conv.parts[1] = ptr[1];
+    return conv.ll;
+#elif defined(NO_UNALIGN_64__MEMCPY)
+    s8 val;
+    memcpy(&val, &ptr[idx], 8);
+    return val;
+#else
+    return *((s8*) &ptr[idx]);
+#endif
+}
+
+/* store a long into an array of u4 */
+static inline void putLongToArray(u4* ptr, int idx, s8 val)
+{
+#if defined(NO_UNALIGN_64__UNION)
+    union { s8 ll; u4 parts[2]; } conv;
+
+    ptr += idx;
+    conv.ll = val;
+    ptr[0] = conv.parts[0];
+    ptr[1] = conv.parts[1];
+#elif defined(NO_UNALIGN_64__MEMCPY)
+    memcpy(&ptr[idx], &val, 8);
+#else
+    *((s8*) &ptr[idx]) = val;
+#endif
+}
+
+/* get a double from an array of u4 */
+static inline double getDoubleFromArray(const u4* ptr, int idx)
+{
+#if defined(NO_UNALIGN_64__UNION)
+    union { double d; u4 parts[2]; } conv;
+
+    ptr += idx;
+    conv.parts[0] = ptr[0];
+    conv.parts[1] = ptr[1];
+    return conv.d;
+#elif defined(NO_UNALIGN_64__MEMCPY)
+    double dval;
+    memcpy(&dval, &ptr[idx], 8);
+    return dval;
+#else
+    return *((double*) &ptr[idx]);
+#endif
+}
+
+/* store a double into an array of u4 */
+static inline void putDoubleToArray(u4* ptr, int idx, double dval)
+{
+#if defined(NO_UNALIGN_64__UNION)
+    union { double d; u4 parts[2]; } conv;
+
+    ptr += idx;
+    conv.d = dval;
+    ptr[0] = conv.parts[0];
+    ptr[1] = conv.parts[1];
+#elif defined(NO_UNALIGN_64__MEMCPY)
+    memcpy(&ptr[idx], &dval, 8);
+#else
+    *((double*) &ptr[idx]) = dval;
+#endif
+}
+
+/*
+ * If enabled, validate the register number on every access.  Otherwise,
+ * just do an array access.
+ *
+ * Assumes the existence of "u4* fp".
+ *
+ * "_idx" may be referenced more than once.
+ */
+#ifdef CHECK_REGISTER_INDICES
+# define GET_REGISTER(_idx) \
+    ( (_idx) < curMethod->registersSize ? \
+        (fp[(_idx)]) : (assert(!"bad reg"),1969) )
+# define SET_REGISTER(_idx, _val) \
+    ( (_idx) < curMethod->registersSize ? \
+        (fp[(_idx)] = (u4)(_val)) : (assert(!"bad reg"),1969) )
+# define GET_REGISTER_AS_OBJECT(_idx)       ((Object *)GET_REGISTER(_idx))
+# define SET_REGISTER_AS_OBJECT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
+# define GET_REGISTER_INT(_idx) ((s4) GET_REGISTER(_idx))
+# define SET_REGISTER_INT(_idx, _val) SET_REGISTER(_idx, (s4)_val)
+# define GET_REGISTER_WIDE(_idx) \
+    ( (_idx) < curMethod->registersSize-1 ? \
+        getLongFromArray(fp, (_idx)) : (assert(!"bad reg"),1969) )
+# define SET_REGISTER_WIDE(_idx, _val) \
+    ( (_idx) < curMethod->registersSize-1 ? \
+        putLongToArray(fp, (_idx), (_val)) : (assert(!"bad reg"),1969) )
+# define GET_REGISTER_FLOAT(_idx) \
+    ( (_idx) < curMethod->registersSize ? \
+        (*((float*) &fp[(_idx)])) : (assert(!"bad reg"),1969.0f) )
+# define SET_REGISTER_FLOAT(_idx, _val) \
+    ( (_idx) < curMethod->registersSize ? \
+        (*((float*) &fp[(_idx)]) = (_val)) : (assert(!"bad reg"),1969.0f) )
+# define GET_REGISTER_DOUBLE(_idx) \
+    ( (_idx) < curMethod->registersSize-1 ? \
+        getDoubleFromArray(fp, (_idx)) : (assert(!"bad reg"),1969.0) )
+# define SET_REGISTER_DOUBLE(_idx, _val) \
+    ( (_idx) < curMethod->registersSize-1 ? \
+        putDoubleToArray(fp, (_idx), (_val)) : (assert(!"bad reg"),1969.0) )
+#else
+# define GET_REGISTER(_idx)                 (fp[(_idx)])
+# define SET_REGISTER(_idx, _val)           (fp[(_idx)] = (_val))
+# define GET_REGISTER_AS_OBJECT(_idx)       ((Object*) fp[(_idx)])
+# define SET_REGISTER_AS_OBJECT(_idx, _val) (fp[(_idx)] = (u4)(_val))
+# define GET_REGISTER_INT(_idx)             ((s4)GET_REGISTER(_idx))
+# define SET_REGISTER_INT(_idx, _val)       SET_REGISTER(_idx, (s4)_val)
+# define GET_REGISTER_WIDE(_idx)            getLongFromArray(fp, (_idx))
+# define SET_REGISTER_WIDE(_idx, _val)      putLongToArray(fp, (_idx), (_val))
+# define GET_REGISTER_FLOAT(_idx)           (*((float*) &fp[(_idx)]))
+# define SET_REGISTER_FLOAT(_idx, _val)     (*((float*) &fp[(_idx)]) = (_val))
+# define GET_REGISTER_DOUBLE(_idx)          getDoubleFromArray(fp, (_idx))
+# define SET_REGISTER_DOUBLE(_idx, _val)    putDoubleToArray(fp, (_idx), (_val))
+#endif
+
+/*
+ * Get 16 bits from the specified offset of the program counter.  We always
+ * want to load 16 bits at a time from the instruction stream -- it's more
+ * efficient than 8 and won't have the alignment problems that 32 might.
+ *
+ * Assumes existence of "const u2* pc".
+ */
+#define FETCH(_offset)     (pc[(_offset)])
+
+/*
+ * Extract instruction byte from 16-bit fetch (_inst is a u2).
+ */
+#define INST_INST(_inst)    ((_inst) & 0xff)
+
+/*
+ * Extract the "vA, vB" 4-bit registers from the instruction word (_inst is u2).
+ */
+#define INST_A(_inst)       (((_inst) >> 8) & 0x0f)
+#define INST_B(_inst)       ((_inst) >> 12)
+
+/*
+ * Get the 8-bit "vAA" 8-bit register index from the instruction word.
+ * (_inst is u2)
+ */
+#define INST_AA(_inst)      ((_inst) >> 8)
+
+/*
+ * The current PC must be available to Throwable constructors, e.g.
+ * those created by dvmThrowException(), so that the exception stack
+ * trace can be generated correctly.  If we don't do this, the offset
+ * within the current method won't be shown correctly.  See the notes
+ * in Exception.c.
+ *
+ * This is also used to determine the address for precise GC.
+ *
+ * Assumes existence of "u4* fp" and "const u2* pc".
+ */
+#define EXPORT_PC()         (SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc)
+
+/*
+ * Determine if we need to switch to a different interpreter.  "_current"
+ * is either INTERP_STD or INTERP_DBG.  It should be fixed for a given
+ * interpreter generation file, which should remove the outer conditional
+ * from the following.
+ *
+ * If we're building without debug and profiling support, we never switch.
+ */
+#if defined(WITH_PROFILER) || defined(WITH_DEBUGGER)
+#if defined(WITH_JIT)
+# define NEED_INTERP_SWITCH(_current) (                                     \
+    (_current == INTERP_STD) ?                                              \
+        dvmJitDebuggerOrProfilerActive(interpState->jitState) :             \
+        !dvmJitDebuggerOrProfilerActive(interpState->jitState) )
+#else
+# define NEED_INTERP_SWITCH(_current) (                                     \
+    (_current == INTERP_STD) ?                                              \
+        dvmDebuggerOrProfilerActive() : !dvmDebuggerOrProfilerActive() )
+#endif
+#else
+# define NEED_INTERP_SWITCH(_current) (false)
+#endif
+
+/*
+ * Check to see if "obj" is NULL.  If so, throw an exception.  Assumes the
+ * pc has already been exported to the stack.
+ *
+ * Perform additional checks on debug builds.
+ *
+ * Use this to check for NULL when the instruction handler calls into
+ * something that could throw an exception (so we have already called
+ * EXPORT_PC at the top).
+ */
+static inline bool checkForNull(Object* obj)
+{
+    if (obj == NULL) {
+        dvmThrowException("Ljava/lang/NullPointerException;", NULL);
+        return false;
+    }
+#ifdef WITH_EXTRA_OBJECT_VALIDATION
+    if (!dvmIsValidObject(obj)) {
+        LOGE("Invalid object %p\n", obj);
+        dvmAbort();
+    }
+#endif
+#ifndef NDEBUG
+    if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) {
+        /* probable heap corruption */
+        LOGE("Invalid object class %p (in %p)\n", obj->clazz, obj);
+        dvmAbort();
+    }
+#endif
+    return true;
+}
+
+/*
+ * Check to see if "obj" is NULL.  If so, export the PC into the stack
+ * frame and throw an exception.
+ *
+ * Perform additional checks on debug builds.
+ *
+ * Use this to check for NULL when the instruction handler doesn't do
+ * anything else that can throw an exception.
+ */
+static inline bool checkForNullExportPC(Object* obj, u4* fp, const u2* pc)
+{
+    if (obj == NULL) {
+        EXPORT_PC();
+        dvmThrowException("Ljava/lang/NullPointerException;", NULL);
+        return false;
+    }
+#ifdef WITH_EXTRA_OBJECT_VALIDATION
+    if (!dvmIsValidObject(obj)) {
+        LOGE("Invalid object %p\n", obj);
+        dvmAbort();
+    }
+#endif
+#ifndef NDEBUG
+    if (obj->clazz == NULL || ((u4) obj->clazz) <= 65536) {
+        /* probable heap corruption */
+        LOGE("Invalid object class %p (in %p)\n", obj->clazz, obj);
+        dvmAbort();
+    }
+#endif
+    return true;
+}
+
+/* File: cstubs/stubdefs.c */
+/* this is a standard (no debug support) interpreter */
+#define INTERP_TYPE INTERP_STD
+#define CHECK_DEBUG_AND_PROF() ((void)0)
+# define CHECK_TRACKED_REFS() ((void)0)
+
+/*
+ * In the C mterp stubs, "goto" is a function call followed immediately
+ * by a return.
+ */
+
+#define GOTO_TARGET_DECL(_target, ...)                                      \
+    void dvmMterp_##_target(MterpGlue* glue, ## __VA_ARGS__);
+
+#define GOTO_TARGET(_target, ...)                                           \
+    void dvmMterp_##_target(MterpGlue* glue, ## __VA_ARGS__) {              \
+        u2 ref, vsrc1, vsrc2, vdst;                                         \
+        u2 inst = FETCH(0);                                                 \
+        const Method* methodToCall;                                         \
+        StackSaveArea* debugSaveArea;
+
+#define GOTO_TARGET_END }
+
+/*
+ * Redefine what used to be local variable accesses into MterpGlue struct
+ * references.  (These are undefined down in "footer.c".)
+ */
+#define retval                  glue->retval
+#define pc                      glue->pc
+#define fp                      glue->fp
+#define curMethod               glue->method
+#define methodClassDex          glue->methodClassDex
+#define self                    glue->self
+#define debugTrackedRefStart    glue->debugTrackedRefStart
+
+/* ugh */
+#define STUB_HACK(x) x
+
+
+/*
+ * Opcode handler framing macros.  Here, each opcode is a separate function
+ * that takes a "glue" argument and returns void.  We can't declare
+ * these "static" because they may be called from an assembly stub.
+ */
+#define HANDLE_OPCODE(_op)                                                  \
+    void dvmMterp_##_op(MterpGlue* glue) {                                  \
+        u2 ref, vsrc1, vsrc2, vdst;                                         \
+        u2 inst = FETCH(0);
+
+#define OP_END }
+
+/*
+ * Like the "portable" FINISH, but don't reload "inst", and return to caller
+ * when done.
+ */
+#define FINISH(_offset) {                                                   \
+        ADJUST_PC(_offset);                                                 \
+        CHECK_DEBUG_AND_PROF();                                             \
+        CHECK_TRACKED_REFS();                                               \
+        return;                                                             \
+    }
+
+
+/*
+ * The "goto label" statements turn into function calls followed by
+ * return statements.  Some of the functions take arguments, which in the
+ * portable interpreter are handled by assigning values to globals.
+ */
+
+#define GOTO_exceptionThrown()                                              \
+    do {                                                                    \
+        dvmMterp_exceptionThrown(glue);                                     \
+        return;                                                             \
+    } while(false)
+
+#define GOTO_returnFromMethod()                                             \
+    do {                                                                    \
+        dvmMterp_returnFromMethod(glue);                                    \
+        return;                                                             \
+    } while(false)
+
+#define GOTO_invoke(_target, _methodCallRange)                              \
+    do {                                                                    \
+        dvmMterp_##_target(glue, _methodCallRange);                         \
+        return;                                                             \
+    } while(false)
+
+#define GOTO_invokeMethod(_methodCallRange, _methodToCall, _vsrc1, _vdst)   \
+    do {                                                                    \
+        dvmMterp_invokeMethod(glue, _methodCallRange, _methodToCall,        \
+            _vsrc1, _vdst);                                                 \
+        return;                                                             \
+    } while(false)
+
+/*
+ * As a special case, "goto bail" turns into a longjmp.  Use "bail_switch"
+ * if we need to switch to the other interpreter upon our return.
+ */
+#define GOTO_bail()                                                         \
+    dvmMterpStdBail(glue, false);
+#define GOTO_bail_switch()                                                  \
+    dvmMterpStdBail(glue, true);
+
+/*
+ * Periodically check for thread suspension.
+ *
+ * While we're at it, see if a debugger has attached or the profiler has
+ * started.  If so, switch to a different "goto" table.
+ */
+#define PERIODIC_CHECKS(_entryPoint, _pcadj) {                              \
+        if (dvmCheckSuspendQuick(self)) {                                   \
+            EXPORT_PC();  /* need for precise GC */                         \
+            dvmCheckSuspendPending(self);                                   \
+        }                                                                   \
+        if (NEED_INTERP_SWITCH(INTERP_TYPE)) {                              \
+            ADJUST_PC(_pcadj);                                              \
+            glue->entryPoint = _entryPoint;                                 \
+            LOGVV("threadid=%d: switch to STD ep=%d adj=%d\n",              \
+                self->threadId, (_entryPoint), (_pcadj));                   \
+            GOTO_bail_switch();                                             \
+        }                                                                   \
+    }
+
+
+/* File: c/opcommon.c */
+/* forward declarations of goto targets */
+GOTO_TARGET_DECL(filledNewArray, bool methodCallRange);
+GOTO_TARGET_DECL(invokeVirtual, bool methodCallRange);
+GOTO_TARGET_DECL(invokeSuper, bool methodCallRange);
+GOTO_TARGET_DECL(invokeInterface, bool methodCallRange);
+GOTO_TARGET_DECL(invokeDirect, bool methodCallRange);
+GOTO_TARGET_DECL(invokeStatic, bool methodCallRange);
+GOTO_TARGET_DECL(invokeVirtualQuick, bool methodCallRange);
+GOTO_TARGET_DECL(invokeSuperQuick, bool methodCallRange);
+GOTO_TARGET_DECL(invokeMethod, bool methodCallRange, const Method* methodToCall,
+    u2 count, u2 regs);
+GOTO_TARGET_DECL(returnFromMethod);
+GOTO_TARGET_DECL(exceptionThrown);
+
+/*
+ * ===========================================================================
+ *
+ * What follows are opcode definitions shared between multiple opcodes with
+ * minor substitutions handled by the C pre-processor.  These should probably
+ * use the mterp substitution mechanism instead, with the code here moved
+ * into common fragment files (like the asm "binop.S"), although it's hard
+ * to give up the C preprocessor in favor of the much simpler text subst.
+ *
+ * ===========================================================================
+ */
+
+#define HANDLE_NUMCONV(_opcode, _opname, _fromtype, _totype)                \
+    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);                                               \
+        ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1);                       \
+        SET_REGISTER##_totype(vdst,                                         \
+            GET_REGISTER##_fromtype(vsrc1));                                \
+        FINISH(1);
+
+#define HANDLE_FLOAT_TO_INT(_opcode, _opname, _fromvtype, _fromrtype,       \
+        _tovtype, _tortype)                                                 \
+    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
+    {                                                                       \
+        /* spec defines specific handling for +/- inf and NaN values */     \
+        _fromvtype val;                                                     \
+        _tovtype intMin, intMax, result;                                    \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);                                               \
+        ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1);                       \
+        val = GET_REGISTER##_fromrtype(vsrc1);                              \
+        intMin = (_tovtype) 1 << (sizeof(_tovtype) * 8 -1);                 \
+        intMax = ~intMin;                                                   \
+        result = (_tovtype) val;                                            \
+        if (val >= intMax)          /* +inf */                              \
+            result = intMax;                                                \
+        else if (val <= intMin)     /* -inf */                              \
+            result = intMin;                                                \
+        else if (val != val)        /* NaN */                               \
+            result = 0;                                                     \
+        else                                                                \
+            result = (_tovtype) val;                                        \
+        SET_REGISTER##_tortype(vdst, result);                               \
+    }                                                                       \
+    FINISH(1);
+
+#define HANDLE_INT_TO_SMALL(_opcode, _opname, _type)                        \
+    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);                                               \
+        ILOGV("|int-to-%s v%d,v%d", (_opname), vdst, vsrc1);                \
+        SET_REGISTER(vdst, (_type) GET_REGISTER(vsrc1));                    \
+        FINISH(1);
+
+/* NOTE: the comparison result is always a signed 4-byte integer */
+#define HANDLE_OP_CMPX(_opcode, _opname, _varType, _type, _nanVal)          \
+    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
+    {                                                                       \
+        int result;                                                         \
+        u2 regs;                                                            \
+        _varType val1, val2;                                                \
+        vdst = INST_AA(inst);                                               \
+        regs = FETCH(1);                                                    \
+        vsrc1 = regs & 0xff;                                                \
+        vsrc2 = regs >> 8;                                                  \
+        ILOGV("|cmp%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);         \
+        val1 = GET_REGISTER##_type(vsrc1);                                  \
+        val2 = GET_REGISTER##_type(vsrc2);                                  \
+        if (val1 == val2)                                                   \
+            result = 0;                                                     \
+        else if (val1 < val2)                                               \
+            result = -1;                                                    \
+        else if (val1 > val2)                                               \
+            result = 1;                                                     \
+        else                                                                \
+            result = (_nanVal);                                             \
+        ILOGV("+ result=%d\n", result);                                     \
+        SET_REGISTER(vdst, result);                                         \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_OP_IF_XX(_opcode, _opname, _cmp)                             \
+    HANDLE_OPCODE(_opcode /*vA, vB, +CCCC*/)                                \
+        vsrc1 = INST_A(inst);                                               \
+        vsrc2 = INST_B(inst);                                               \
+        if ((s4) GET_REGISTER(vsrc1) _cmp (s4) GET_REGISTER(vsrc2)) {       \
+            int branchOffset = (s2)FETCH(1);    /* sign-extended */         \
+            ILOGV("|if-%s v%d,v%d,+0x%04x", (_opname), vsrc1, vsrc2,        \
+                branchOffset);                                              \
+            ILOGV("> branch taken");                                        \
+            if (branchOffset < 0)                                           \
+                PERIODIC_CHECKS(kInterpEntryInstr, branchOffset);           \
+            FINISH(branchOffset);                                           \
+        } else {                                                            \
+            ILOGV("|if-%s v%d,v%d,-", (_opname), vsrc1, vsrc2);             \
+            FINISH(2);                                                      \
+        }
+
+#define HANDLE_OP_IF_XXZ(_opcode, _opname, _cmp)                            \
+    HANDLE_OPCODE(_opcode /*vAA, +BBBB*/)                                   \
+        vsrc1 = INST_AA(inst);                                              \
+        if ((s4) GET_REGISTER(vsrc1) _cmp 0) {                              \
+            int branchOffset = (s2)FETCH(1);    /* sign-extended */         \
+            ILOGV("|if-%s v%d,+0x%04x", (_opname), vsrc1, branchOffset);    \
+            ILOGV("> branch taken");                                        \
+            if (branchOffset < 0)                                           \
+                PERIODIC_CHECKS(kInterpEntryInstr, branchOffset);           \
+            FINISH(branchOffset);                                           \
+        } else {                                                            \
+            ILOGV("|if-%s v%d,-", (_opname), vsrc1);                        \
+            FINISH(2);                                                      \
+        }
+
+#define HANDLE_UNOP(_opcode, _opname, _pfx, _sfx, _type)                    \
+    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);                                               \
+        ILOGV("|%s v%d,v%d", (_opname), vdst, vsrc1);                       \
+        SET_REGISTER##_type(vdst, _pfx GET_REGISTER##_type(vsrc1) _sfx);    \
+        FINISH(1);
+
+#define HANDLE_OP_X_INT(_opcode, _opname, _op, _chkdiv)                     \
+    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
+    {                                                                       \
+        u2 srcRegs;                                                         \
+        vdst = INST_AA(inst);                                               \
+        srcRegs = FETCH(1);                                                 \
+        vsrc1 = srcRegs & 0xff;                                             \
+        vsrc2 = srcRegs >> 8;                                               \
+        ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1);                   \
+        if (_chkdiv != 0) {                                                 \
+            s4 firstVal, secondVal, result;                                 \
+            firstVal = GET_REGISTER(vsrc1);                                 \
+            secondVal = GET_REGISTER(vsrc2);                                \
+            if (secondVal == 0) {                                           \
+                EXPORT_PC();                                                \
+                dvmThrowException("Ljava/lang/ArithmeticException;",        \
+                    "divide by zero");                                      \
+                GOTO_exceptionThrown();                                     \
+            }                                                               \
+            if ((u4)firstVal == 0x80000000 && secondVal == -1) {            \
+                if (_chkdiv == 1)                                           \
+                    result = firstVal;  /* division */                      \
+                else                                                        \
+                    result = 0;         /* remainder */                     \
+            } else {                                                        \
+                result = firstVal _op secondVal;                            \
+            }                                                               \
+            SET_REGISTER(vdst, result);                                     \
+        } else {                                                            \
+            /* non-div/rem case */                                          \
+            SET_REGISTER(vdst,                                              \
+                (s4) GET_REGISTER(vsrc1) _op (s4) GET_REGISTER(vsrc2));     \
+        }                                                                   \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_OP_SHX_INT(_opcode, _opname, _cast, _op)                     \
+    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
+    {                                                                       \
+        u2 srcRegs;                                                         \
+        vdst = INST_AA(inst);                                               \
+        srcRegs = FETCH(1);                                                 \
+        vsrc1 = srcRegs & 0xff;                                             \
+        vsrc2 = srcRegs >> 8;                                               \
+        ILOGV("|%s-int v%d,v%d", (_opname), vdst, vsrc1);                   \
+        SET_REGISTER(vdst,                                                  \
+            _cast GET_REGISTER(vsrc1) _op (GET_REGISTER(vsrc2) & 0x1f));    \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_OP_X_INT_LIT16(_opcode, _opname, _op, _chkdiv)               \
+    HANDLE_OPCODE(_opcode /*vA, vB, #+CCCC*/)                               \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);                                               \
+        vsrc2 = FETCH(1);                                                   \
+        ILOGV("|%s-int/lit16 v%d,v%d,#+0x%04x",                             \
+            (_opname), vdst, vsrc1, vsrc2);                                 \
+        if (_chkdiv != 0) {                                                 \
+            s4 firstVal, result;                                            \
+            firstVal = GET_REGISTER(vsrc1);                                 \
+            if ((s2) vsrc2 == 0) {                                          \
+                EXPORT_PC();                                                \
+                dvmThrowException("Ljava/lang/ArithmeticException;",        \
+                    "divide by zero");                                      \
+                GOTO_exceptionThrown();                                      \
+            }                                                               \
+            if ((u4)firstVal == 0x80000000 && ((s2) vsrc2) == -1) {         \
+                /* won't generate /lit16 instr for this; check anyway */    \
+                if (_chkdiv == 1)                                           \
+                    result = firstVal;  /* division */                      \
+                else                                                        \
+                    result = 0;         /* remainder */                     \
+            } else {                                                        \
+                result = firstVal _op (s2) vsrc2;                           \
+            }                                                               \
+            SET_REGISTER(vdst, result);                                     \
+        } else {                                                            \
+            /* non-div/rem case */                                          \
+            SET_REGISTER(vdst, GET_REGISTER(vsrc1) _op (s2) vsrc2);         \
+        }                                                                   \
+        FINISH(2);
+
+#define HANDLE_OP_X_INT_LIT8(_opcode, _opname, _op, _chkdiv)                \
+    HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/)                               \
+    {                                                                       \
+        u2 litInfo;                                                         \
+        vdst = INST_AA(inst);                                               \
+        litInfo = FETCH(1);                                                 \
+        vsrc1 = litInfo & 0xff;                                             \
+        vsrc2 = litInfo >> 8;       /* constant */                          \
+        ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x",                              \
+            (_opname), vdst, vsrc1, vsrc2);                                 \
+        if (_chkdiv != 0) {                                                 \
+            s4 firstVal, result;                                            \
+            firstVal = GET_REGISTER(vsrc1);                                 \
+            if ((s1) vsrc2 == 0) {                                          \
+                EXPORT_PC();                                                \
+                dvmThrowException("Ljava/lang/ArithmeticException;",        \
+                    "divide by zero");                                      \
+                GOTO_exceptionThrown();                                     \
+            }                                                               \
+            if ((u4)firstVal == 0x80000000 && ((s1) vsrc2) == -1) {         \
+                if (_chkdiv == 1)                                           \
+                    result = firstVal;  /* division */                      \
+                else                                                        \
+                    result = 0;         /* remainder */                     \
+            } else {                                                        \
+                result = firstVal _op ((s1) vsrc2);                         \
+            }                                                               \
+            SET_REGISTER(vdst, result);                                     \
+        } else {                                                            \
+            SET_REGISTER(vdst,                                              \
+                (s4) GET_REGISTER(vsrc1) _op (s1) vsrc2);                   \
+        }                                                                   \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_OP_SHX_INT_LIT8(_opcode, _opname, _cast, _op)                \
+    HANDLE_OPCODE(_opcode /*vAA, vBB, #+CC*/)                               \
+    {                                                                       \
+        u2 litInfo;                                                         \
+        vdst = INST_AA(inst);                                               \
+        litInfo = FETCH(1);                                                 \
+        vsrc1 = litInfo & 0xff;                                             \
+        vsrc2 = litInfo >> 8;       /* constant */                          \
+        ILOGV("|%s-int/lit8 v%d,v%d,#+0x%02x",                              \
+            (_opname), vdst, vsrc1, vsrc2);                                 \
+        SET_REGISTER(vdst,                                                  \
+            _cast GET_REGISTER(vsrc1) _op (vsrc2 & 0x1f));                  \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_OP_X_INT_2ADDR(_opcode, _opname, _op, _chkdiv)               \
+    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);                                               \
+        ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1);             \
+        if (_chkdiv != 0) {                                                 \
+            s4 firstVal, secondVal, result;                                 \
+            firstVal = GET_REGISTER(vdst);                                  \
+            secondVal = GET_REGISTER(vsrc1);                                \
+            if (secondVal == 0) {                                           \
+                EXPORT_PC();                                                \
+                dvmThrowException("Ljava/lang/ArithmeticException;",        \
+                    "divide by zero");                                      \
+                GOTO_exceptionThrown();                                     \
+            }                                                               \
+            if ((u4)firstVal == 0x80000000 && secondVal == -1) {            \
+                if (_chkdiv == 1)                                           \
+                    result = firstVal;  /* division */                      \
+                else                                                        \
+                    result = 0;         /* remainder */                     \
+            } else {                                                        \
+                result = firstVal _op secondVal;                            \
+            }                                                               \
+            SET_REGISTER(vdst, result);                                     \
+        } else {                                                            \
+            SET_REGISTER(vdst,                                              \
+                (s4) GET_REGISTER(vdst) _op (s4) GET_REGISTER(vsrc1));      \
+        }                                                                   \
+        FINISH(1);
+
+#define HANDLE_OP_SHX_INT_2ADDR(_opcode, _opname, _cast, _op)               \
+    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);                                               \
+        ILOGV("|%s-int-2addr v%d,v%d", (_opname), vdst, vsrc1);             \
+        SET_REGISTER(vdst,                                                  \
+            _cast GET_REGISTER(vdst) _op (GET_REGISTER(vsrc1) & 0x1f));     \
+        FINISH(1);
+
+#define HANDLE_OP_X_LONG(_opcode, _opname, _op, _chkdiv)                    \
+    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
+    {                                                                       \
+        u2 srcRegs;                                                         \
+        vdst = INST_AA(inst);                                               \
+        srcRegs = FETCH(1);                                                 \
+        vsrc1 = srcRegs & 0xff;                                             \
+        vsrc2 = srcRegs >> 8;                                               \
+        ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);       \
+        if (_chkdiv != 0) {                                                 \
+            s8 firstVal, secondVal, result;                                 \
+            firstVal = GET_REGISTER_WIDE(vsrc1);                            \
+            secondVal = GET_REGISTER_WIDE(vsrc2);                           \
+            if (secondVal == 0LL) {                                         \
+                EXPORT_PC();                                                \
+                dvmThrowException("Ljava/lang/ArithmeticException;",        \
+                    "divide by zero");                                      \
+                GOTO_exceptionThrown();                                     \
+            }                                                               \
+            if ((u8)firstVal == 0x8000000000000000ULL &&                    \
+                secondVal == -1LL)                                          \
+            {                                                               \
+                if (_chkdiv == 1)                                           \
+                    result = firstVal;  /* division */                      \
+                else                                                        \
+                    result = 0;         /* remainder */                     \
+            } else {                                                        \
+                result = firstVal _op secondVal;                            \
+            }                                                               \
+            SET_REGISTER_WIDE(vdst, result);                                \
+        } else {                                                            \
+            SET_REGISTER_WIDE(vdst,                                         \
+                (s8) GET_REGISTER_WIDE(vsrc1) _op (s8) GET_REGISTER_WIDE(vsrc2)); \
+        }                                                                   \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_OP_SHX_LONG(_opcode, _opname, _cast, _op)                    \
+    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
+    {                                                                       \
+        u2 srcRegs;                                                         \
+        vdst = INST_AA(inst);                                               \
+        srcRegs = FETCH(1);                                                 \
+        vsrc1 = srcRegs & 0xff;                                             \
+        vsrc2 = srcRegs >> 8;                                               \
+        ILOGV("|%s-long v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);       \
+        SET_REGISTER_WIDE(vdst,                                             \
+            _cast GET_REGISTER_WIDE(vsrc1) _op (GET_REGISTER(vsrc2) & 0x3f)); \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_OP_X_LONG_2ADDR(_opcode, _opname, _op, _chkdiv)              \
+    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);                                               \
+        ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1);            \
+        if (_chkdiv != 0) {                                                 \
+            s8 firstVal, secondVal, result;                                 \
+            firstVal = GET_REGISTER_WIDE(vdst);                             \
+            secondVal = GET_REGISTER_WIDE(vsrc1);                           \
+            if (secondVal == 0LL) {                                         \
+                EXPORT_PC();                                                \
+                dvmThrowException("Ljava/lang/ArithmeticException;",        \
+                    "divide by zero");                                      \
+                GOTO_exceptionThrown();                                     \
+            }                                                               \
+            if ((u8)firstVal == 0x8000000000000000ULL &&                    \
+                secondVal == -1LL)                                          \
+            {                                                               \
+                if (_chkdiv == 1)                                           \
+                    result = firstVal;  /* division */                      \
+                else                                                        \
+                    result = 0;         /* remainder */                     \
+            } else {                                                        \
+                result = firstVal _op secondVal;                            \
+            }                                                               \
+            SET_REGISTER_WIDE(vdst, result);                                \
+        } else {                                                            \
+            SET_REGISTER_WIDE(vdst,                                         \
+                (s8) GET_REGISTER_WIDE(vdst) _op (s8)GET_REGISTER_WIDE(vsrc1));\
+        }                                                                   \
+        FINISH(1);
+
+#define HANDLE_OP_SHX_LONG_2ADDR(_opcode, _opname, _cast, _op)              \
+    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);                                               \
+        ILOGV("|%s-long-2addr v%d,v%d", (_opname), vdst, vsrc1);            \
+        SET_REGISTER_WIDE(vdst,                                             \
+            _cast GET_REGISTER_WIDE(vdst) _op (GET_REGISTER(vsrc1) & 0x3f)); \
+        FINISH(1);
+
+#define HANDLE_OP_X_FLOAT(_opcode, _opname, _op)                            \
+    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
+    {                                                                       \
+        u2 srcRegs;                                                         \
+        vdst = INST_AA(inst);                                               \
+        srcRegs = FETCH(1);                                                 \
+        vsrc1 = srcRegs & 0xff;                                             \
+        vsrc2 = srcRegs >> 8;                                               \
+        ILOGV("|%s-float v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);      \
+        SET_REGISTER_FLOAT(vdst,                                            \
+            GET_REGISTER_FLOAT(vsrc1) _op GET_REGISTER_FLOAT(vsrc2));       \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_OP_X_DOUBLE(_opcode, _opname, _op)                           \
+    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
+    {                                                                       \
+        u2 srcRegs;                                                         \
+        vdst = INST_AA(inst);                                               \
+        srcRegs = FETCH(1);                                                 \
+        vsrc1 = srcRegs & 0xff;                                             \
+        vsrc2 = srcRegs >> 8;                                               \
+        ILOGV("|%s-double v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);     \
+        SET_REGISTER_DOUBLE(vdst,                                           \
+            GET_REGISTER_DOUBLE(vsrc1) _op GET_REGISTER_DOUBLE(vsrc2));     \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_OP_X_FLOAT_2ADDR(_opcode, _opname, _op)                      \
+    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);                                               \
+        ILOGV("|%s-float-2addr v%d,v%d", (_opname), vdst, vsrc1);           \
+        SET_REGISTER_FLOAT(vdst,                                            \
+            GET_REGISTER_FLOAT(vdst) _op GET_REGISTER_FLOAT(vsrc1));        \
+        FINISH(1);
+
+#define HANDLE_OP_X_DOUBLE_2ADDR(_opcode, _opname, _op)                     \
+    HANDLE_OPCODE(_opcode /*vA, vB*/)                                       \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);                                               \
+        ILOGV("|%s-double-2addr v%d,v%d", (_opname), vdst, vsrc1);          \
+        SET_REGISTER_DOUBLE(vdst,                                           \
+            GET_REGISTER_DOUBLE(vdst) _op GET_REGISTER_DOUBLE(vsrc1));      \
+        FINISH(1);
+
+#define HANDLE_OP_AGET(_opcode, _opname, _type, _regsize)                   \
+    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
+    {                                                                       \
+        ArrayObject* arrayObj;                                              \
+        u2 arrayInfo;                                                       \
+        EXPORT_PC();                                                        \
+        vdst = INST_AA(inst);                                               \
+        arrayInfo = FETCH(1);                                               \
+        vsrc1 = arrayInfo & 0xff;    /* array ptr */                        \
+        vsrc2 = arrayInfo >> 8;      /* index */                            \
+        ILOGV("|aget%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);        \
+        arrayObj = (ArrayObject*) GET_REGISTER(vsrc1);                      \
+        if (!checkForNull((Object*) arrayObj))                              \
+            GOTO_exceptionThrown();                                         \
+        if (GET_REGISTER(vsrc2) >= arrayObj->length) {                      \
+            LOGV("Invalid array access: %p %d (len=%d)\n",                  \
+                arrayObj, vsrc2, arrayObj->length);                         \
+            dvmThrowException("Ljava/lang/ArrayIndexOutOfBoundsException;", \
+                NULL);                                                      \
+            GOTO_exceptionThrown();                                         \
+        }                                                                   \
+        SET_REGISTER##_regsize(vdst,                                        \
+            ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)]);            \
+        ILOGV("+ AGET[%d]=0x%x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));  \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_OP_APUT(_opcode, _opname, _type, _regsize)                   \
+    HANDLE_OPCODE(_opcode /*vAA, vBB, vCC*/)                                \
+    {                                                                       \
+        ArrayObject* arrayObj;                                              \
+        u2 arrayInfo;                                                       \
+        EXPORT_PC();                                                        \
+        vdst = INST_AA(inst);       /* AA: source value */                  \
+        arrayInfo = FETCH(1);                                               \
+        vsrc1 = arrayInfo & 0xff;   /* BB: array ptr */                     \
+        vsrc2 = arrayInfo >> 8;     /* CC: index */                         \
+        ILOGV("|aput%s v%d,v%d,v%d", (_opname), vdst, vsrc1, vsrc2);        \
+        arrayObj = (ArrayObject*) GET_REGISTER(vsrc1);                      \
+        if (!checkForNull((Object*) arrayObj))                              \
+            GOTO_exceptionThrown();                                         \
+        if (GET_REGISTER(vsrc2) >= arrayObj->length) {                      \
+            dvmThrowException("Ljava/lang/ArrayIndexOutOfBoundsException;", \
+                NULL);                                                      \
+            GOTO_exceptionThrown();                                         \
+        }                                                                   \
+        ILOGV("+ APUT[%d]=0x%08x", GET_REGISTER(vsrc2), GET_REGISTER(vdst));\
+        ((_type*) arrayObj->contents)[GET_REGISTER(vsrc2)] =                \
+            GET_REGISTER##_regsize(vdst);                                   \
+    }                                                                       \
+    FINISH(2);
+
+/*
+ * It's possible to get a bad value out of a field with sub-32-bit stores
+ * because the -quick versions always operate on 32 bits.  Consider:
+ *   short foo = -1  (sets a 32-bit register to 0xffffffff)
+ *   iput-quick foo  (writes all 32 bits to the field)
+ *   short bar = 1   (sets a 32-bit register to 0x00000001)
+ *   iput-short      (writes the low 16 bits to the field)
+ *   iget-quick foo  (reads all 32 bits from the field, yielding 0xffff0001)
+ * This can only happen when optimized and non-optimized code has interleaved
+ * access to the same field.  This is unlikely but possible.
+ *
+ * The easiest way to fix this is to always read/write 32 bits at a time.  On
+ * a device with a 16-bit data bus this is sub-optimal.  (The alternative
+ * approach is to have sub-int versions of iget-quick, but now we're wasting
+ * Dalvik instruction space and making it less likely that handler code will
+ * already be in the CPU i-cache.)
+ */
+#define HANDLE_IGET_X(_opcode, _opname, _ftype, _regsize)                   \
+    HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \
+    {                                                                       \
+        InstField* ifield;                                                  \
+        Object* obj;                                                        \
+        EXPORT_PC();                                                        \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);   /* object ptr */                            \
+        ref = FETCH(1);         /* field ref */                             \
+        ILOGV("|iget%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \
+        obj = (Object*) GET_REGISTER(vsrc1);                                \
+        if (!checkForNull(obj))                                             \
+            GOTO_exceptionThrown();                                         \
+        ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref);  \
+        if (ifield == NULL) {                                               \
+            ifield = dvmResolveInstField(curMethod->clazz, ref);            \
+            if (ifield == NULL)                                             \
+                GOTO_exceptionThrown();                                     \
+        }                                                                   \
+        SET_REGISTER##_regsize(vdst,                                        \
+            dvmGetField##_ftype(obj, ifield->byteOffset));                  \
+        ILOGV("+ IGET '%s'=0x%08llx", ifield->field.name,                   \
+            (u8) GET_REGISTER##_regsize(vdst));                             \
+        UPDATE_FIELD_GET(&ifield->field);                                   \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_IGET_X_QUICK(_opcode, _opname, _ftype, _regsize)             \
+    HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \
+    {                                                                       \
+        Object* obj;                                                        \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);   /* object ptr */                            \
+        ref = FETCH(1);         /* field offset */                          \
+        ILOGV("|iget%s-quick v%d,v%d,field@+%u",                            \
+            (_opname), vdst, vsrc1, ref);                                   \
+        obj = (Object*) GET_REGISTER(vsrc1);                                \
+        if (!checkForNullExportPC(obj, fp, pc))                             \
+            GOTO_exceptionThrown();                                         \
+        SET_REGISTER##_regsize(vdst, dvmGetField##_ftype(obj, ref));        \
+        ILOGV("+ IGETQ %d=0x%08llx", ref,                                   \
+            (u8) GET_REGISTER##_regsize(vdst));                             \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_IPUT_X(_opcode, _opname, _ftype, _regsize)                   \
+    HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \
+    {                                                                       \
+        InstField* ifield;                                                  \
+        Object* obj;                                                        \
+        EXPORT_PC();                                                        \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);   /* object ptr */                            \
+        ref = FETCH(1);         /* field ref */                             \
+        ILOGV("|iput%s v%d,v%d,field@0x%04x", (_opname), vdst, vsrc1, ref); \
+        obj = (Object*) GET_REGISTER(vsrc1);                                \
+        if (!checkForNull(obj))                                             \
+            GOTO_exceptionThrown();                                         \
+        ifield = (InstField*) dvmDexGetResolvedField(methodClassDex, ref);  \
+        if (ifield == NULL) {                                               \
+            ifield = dvmResolveInstField(curMethod->clazz, ref);            \
+            if (ifield == NULL)                                             \
+                GOTO_exceptionThrown();                                     \
+        }                                                                   \
+        dvmSetField##_ftype(obj, ifield->byteOffset,                        \
+            GET_REGISTER##_regsize(vdst));                                  \
+        ILOGV("+ IPUT '%s'=0x%08llx", ifield->field.name,                   \
+            (u8) GET_REGISTER##_regsize(vdst));                             \
+        UPDATE_FIELD_PUT(&ifield->field);                                   \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_IPUT_X_QUICK(_opcode, _opname, _ftype, _regsize)             \
+    HANDLE_OPCODE(_opcode /*vA, vB, field@CCCC*/)                           \
+    {                                                                       \
+        Object* obj;                                                        \
+        vdst = INST_A(inst);                                                \
+        vsrc1 = INST_B(inst);   /* object ptr */                            \
+        ref = FETCH(1);         /* field offset */                          \
+        ILOGV("|iput%s-quick v%d,v%d,field@0x%04x",                         \
+            (_opname), vdst, vsrc1, ref);                                   \
+        obj = (Object*) GET_REGISTER(vsrc1);                                \
+        if (!checkForNullExportPC(obj, fp, pc))                             \
+            GOTO_exceptionThrown();                                         \
+        dvmSetField##_ftype(obj, ref, GET_REGISTER##_regsize(vdst));        \
+        ILOGV("+ IPUTQ %d=0x%08llx", ref,                                   \
+            (u8) GET_REGISTER##_regsize(vdst));                             \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_SGET_X(_opcode, _opname, _ftype, _regsize)                   \
+    HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/)                              \
+    {                                                                       \
+        StaticField* sfield;                                                \
+        vdst = INST_AA(inst);                                               \
+        ref = FETCH(1);         /* field ref */                             \
+        ILOGV("|sget%s v%d,sfield@0x%04x", (_opname), vdst, ref);           \
+        sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
+        if (sfield == NULL) {                                               \
+            EXPORT_PC();                                                    \
+            sfield = dvmResolveStaticField(curMethod->clazz, ref);          \
+            if (sfield == NULL)                                             \
+                GOTO_exceptionThrown();                                     \
+        }                                                                   \
+        SET_REGISTER##_regsize(vdst, dvmGetStaticField##_ftype(sfield));    \
+        ILOGV("+ SGET '%s'=0x%08llx",                                       \
+            sfield->field.name, (u8)GET_REGISTER##_regsize(vdst));          \
+        UPDATE_FIELD_GET(&sfield->field);                                   \
+    }                                                                       \
+    FINISH(2);
+
+#define HANDLE_SPUT_X(_opcode, _opname, _ftype, _regsize)                   \
+    HANDLE_OPCODE(_opcode /*vAA, field@BBBB*/)                              \
+    {                                                                       \
+        StaticField* sfield;                                                \
+        vdst = INST_AA(inst);                                               \
+        ref = FETCH(1);         /* field ref */                             \
+        ILOGV("|sput%s v%d,sfield@0x%04x", (_opname), vdst, ref);           \
+        sfield = (StaticField*)dvmDexGetResolvedField(methodClassDex, ref); \
+        if (sfield == NULL) {                                               \
+            EXPORT_PC();                                                    \
+            sfield = dvmResolveStaticField(curMethod->clazz, ref);          \
+            if (sfield == NULL)                                             \
+                GOTO_exceptionThrown();                                     \
+        }                                                                   \
+        dvmSetStaticField##_ftype(sfield, GET_REGISTER##_regsize(vdst));    \
+        ILOGV("+ SPUT '%s'=0x%08llx",                                       \
+            sfield->field.name, (u8)GET_REGISTER##_regsize(vdst));          \
+        UPDATE_FIELD_PUT(&sfield->field);                                   \
+    }                                                                       \
+    FINISH(2);
+
+
+/* File: cstubs/enddefs.c */
+
+/* undefine "magic" name remapping */
+#undef retval
+#undef pc
+#undef fp
+#undef curMethod
+#undef methodClassDex
+#undef self
+#undef debugTrackedRefStart
+
+/* File: armv5te/debug.c */
+#include <inttypes.h>
+
+/*
+ * Dump the fixed-purpose ARM registers, along with some other info.
+ *
+ * This function MUST be compiled in ARM mode -- THUMB will yield bogus
+ * results.
+ *
+ * This will NOT preserve r0-r3/ip.
+ */
+void dvmMterpDumpArmRegs(uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3)
+{
+    register uint32_t rPC       asm("r4");
+    register uint32_t rFP       asm("r5");
+    register uint32_t rGLUE     asm("r6");
+    register uint32_t rINST     asm("r7");
+    register uint32_t rIBASE    asm("r8");
+    register uint32_t r9        asm("r9");
+    register uint32_t r10       asm("r10");
+
+    extern char dvmAsmInstructionStart[];
+
+    printf("REGS: r0=%08x r1=%08x r2=%08x r3=%08x\n", r0, r1, r2, r3);
+    printf("    : rPC=%08x rFP=%08x rGLUE=%08x rINST=%08x\n",
+        rPC, rFP, rGLUE, rINST);
+    printf("    : rIBASE=%08x r9=%08x r10=%08x\n", rIBASE, r9, r10);
+
+    MterpGlue* glue = (MterpGlue*) rGLUE;
+    const Method* method = glue->method;
+    printf("    + self is %p\n", dvmThreadSelf());
+    //printf("    + currently in %s.%s %s\n",
+    //    method->clazz->descriptor, method->name, method->shorty);
+    //printf("    + dvmAsmInstructionStart = %p\n", dvmAsmInstructionStart);
+    //printf("    + next handler for 0x%02x = %p\n",
+    //    rINST & 0xff, dvmAsmInstructionStart + (rINST & 0xff) * 64);
+}
+
+/*
+ * Dump the StackSaveArea for the specified frame pointer.
+ */
+void dvmDumpFp(void* fp, StackSaveArea* otherSaveArea)
+{
+    StackSaveArea* saveArea = SAVEAREA_FROM_FP(fp);
+    printf("StackSaveArea for fp %p [%p/%p]:\n", fp, saveArea, otherSaveArea);
+#ifdef EASY_GDB
+    printf("  prevSave=%p, prevFrame=%p savedPc=%p meth=%p curPc=%p\n",
+        saveArea->prevSave, saveArea->prevFrame, saveArea->savedPc,
+        saveArea->method, saveArea->xtra.currentPc);
+#else
+    printf("  prevFrame=%p savedPc=%p meth=%p curPc=%p fp[0]=0x%08x\n",
+        saveArea->prevFrame, saveArea->savedPc,
+        saveArea->method, saveArea->xtra.currentPc,
+        *(u4*)fp);
+#endif
+}
+
+/*
+ * Does the bulk of the work for common_printMethod().
+ */
+void dvmMterpPrintMethod(Method* method)
+{
+    /*
+     * It is a direct (non-virtual) method if it is static, private,
+     * or a constructor.
+     */
+    bool isDirect =
+        ((method->accessFlags & (ACC_STATIC|ACC_PRIVATE)) != 0) ||
+        (method->name[0] == '<');
+
+    char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
+
+    printf("<%c:%s.%s %s> ",
+            isDirect ? 'D' : 'V',
+            method->clazz->descriptor,
+            method->name,
+            desc);
+
+    free(desc);
+}
+
diff --git a/vm/mterp/out/InterpC-portdbg.c b/vm/mterp/out/InterpC-portdbg.c
index d527cc0..4b92639 100644
--- a/vm/mterp/out/InterpC-portdbg.c
+++ b/vm/mterp/out/InterpC-portdbg.c
@@ -26,6 +26,7 @@
 #include "interp/InterpDefs.h"
 #include "mterp/Mterp.h"
 #include <math.h>                   // needed for fmod, fmodf
+#include "mterp/common/FindInterface.h"
 
 /*
  * Configuration defines.  These affect the C implementations, i.e. the
@@ -53,7 +54,7 @@
  */
 #define THREADED_INTERP             /* threaded vs. while-loop interpreter */
 
-#ifdef WITH_INSTR_CHECKS            /* instruction-level paranoia */
+#ifdef WITH_INSTR_CHECKS            /* instruction-level paranoia (slow!) */
 # define CHECK_BRANCH_OFFSETS
 # define CHECK_REGISTER_INDICES
 #endif
@@ -93,6 +94,18 @@
 #endif
 
 /*
+ * Export another copy of the PC on every instruction; this is largely
+ * redundant with EXPORT_PC and the debugger code.  This value can be
+ * compared against what we have stored on the stack with EXPORT_PC to
+ * help ensure that we aren't missing any export calls.
+ */
+#if WITH_EXTRA_GC_CHECKS > 1
+# define EXPORT_EXTRA_PC() (self->currentPc2 = pc)
+#else
+# define EXPORT_EXTRA_PC()
+#endif
+
+/*
  * Adjust the program counter.  "_offset" is a signed int, in 16-bit units.
  *
  * Assumes the existence of "const u2* pc" and "const u2* curMethod->insns".
@@ -116,9 +129,13 @@
             dvmAbort();                                                     \
         }                                                                   \
         pc += myoff;                                                        \
+        EXPORT_EXTRA_PC();                                                  \
     } while (false)
 #else
-# define ADJUST_PC(_offset) (pc += _offset)
+# define ADJUST_PC(_offset) do {                                            \
+        pc += _offset;                                                      \
+        EXPORT_EXTRA_PC();                                                  \
+    } while (false)
 #endif
 
 /*
@@ -303,6 +320,8 @@
  * within the current method won't be shown correctly.  See the notes
  * in Exception.c.
  *
+ * This is also used to determine the address for precise GC.
+ *
  * Assumes existence of "u4* fp" and "const u2* pc".
  */
 #define EXPORT_PC()         (SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc)
@@ -316,29 +335,21 @@
  * If we're building without debug and profiling support, we never switch.
  */
 #if defined(WITH_PROFILER) || defined(WITH_DEBUGGER)
+#if defined(WITH_JIT)
+# define NEED_INTERP_SWITCH(_current) (                                     \
+    (_current == INTERP_STD) ?                                              \
+        dvmJitDebuggerOrProfilerActive(interpState->jitState) :             \
+        !dvmJitDebuggerOrProfilerActive(interpState->jitState) )
+#else
 # define NEED_INTERP_SWITCH(_current) (                                     \
     (_current == INTERP_STD) ?                                              \
         dvmDebuggerOrProfilerActive() : !dvmDebuggerOrProfilerActive() )
+#endif
 #else
 # define NEED_INTERP_SWITCH(_current) (false)
 #endif
 
 /*
- * Look up an interface on a class using the cache.
- */
-INLINE Method* dvmFindInterfaceMethodInCache(ClassObject* thisClass,
-    u4 methodIdx, const Method* method, DvmDex* methodClassDex)
-{
-#define ATOMIC_CACHE_CALC \
-    dvmInterpFindInterfaceMethod(thisClass, methodIdx, method, methodClassDex)
-
-    return (Method*) ATOMIC_CACHE_LOOKUP(methodClassDex->pInterfaceCache,
-                DEX_INTERFACE_CACHE_SIZE, thisClass, methodIdx);
-
-#undef ATOMIC_CACHE_CALC
-}
-
-/*
  * Check to see if "obj" is NULL.  If so, throw an exception.  Assumes the
  * pc has already been exported to the stack.
  *
@@ -402,7 +413,6 @@
     return true;
 }
 
-
 /* File: portable/portdbg.c */
 #define INTERP_FUNC_NAME dvmInterpretDbg
 #define INTERP_TYPE INTERP_DBG
@@ -410,6 +420,14 @@
 #define CHECK_DEBUG_AND_PROF() \
     checkDebugAndProf(pc, fp, self, curMethod, &debugIsMethodEntry)
 
+#if defined(WITH_JIT)
+#define CHECK_JIT() \
+    if (dvmCheckJit(pc, self, interpState)) GOTO_bail_switch()
+#else
+#define CHECK_JIT() \
+    ((void)0)
+#endif
+
 /* File: portable/stubdefs.c */
 /*
  * In the C mterp stubs, "goto" is a function call followed immediately
@@ -441,6 +459,7 @@
         inst = FETCH(0);                                                    \
         CHECK_DEBUG_AND_PROF();                                             \
         CHECK_TRACKED_REFS();                                               \
+        CHECK_JIT();                                                        \
         goto *handlerTable[INST_INST(inst)];                                \
     }
 #else
@@ -486,7 +505,10 @@
  * started.  If so, switch to a different "goto" table.
  */
 #define PERIODIC_CHECKS(_entryPoint, _pcadj) {                              \
-        dvmCheckSuspendQuick(self);                                         \
+        if (dvmCheckSuspendQuick(self)) {                                   \
+            EXPORT_PC();  /* need for precise GC */                         \
+            dvmCheckSuspendPending(self);                                   \
+        }                                                                   \
         if (NEED_INTERP_SWITCH(INTERP_TYPE)) {                              \
             ADJUST_PC(_pcadj);                                              \
             interpState->entryPoint = _entryPoint;                          \
@@ -1373,7 +1395,7 @@
         if (/*gDvm.debuggerActive &&*/
             strcmp(method->clazz->descriptor, cd) == 0 &&
             strcmp(method->name, mn) == 0 &&
-            strcmp(method->signature, sg) == 0)
+            strcmp(method->shorty, sg) == 0)
         {
             LOGW("Reached %s.%s, enabling verbose mode\n",
                 method->clazz->descriptor, method->name);
@@ -1458,11 +1480,32 @@
     const Method* methodToCall;
     bool methodCallRange;
 
+
 #if defined(THREADED_INTERP)
     /* static computed goto table */
     DEFINE_GOTO_TABLE(handlerTable);
 #endif
 
+#if defined(WITH_JIT)
+#if 0
+    LOGD("*DebugInterp - entrypoint is %d, tgt is 0x%x, %s\n",
+         interpState->entryPoint,
+         interpState->pc,
+         interpState->method->name);
+#endif
+
+#if INTERP_TYPE == INTERP_DBG
+    /* Check to see if we've got a trace selection request.  If we do,
+     * but something is amiss, revert to the fast interpreter.
+     */
+    if (dvmJitCheckTraceRequest(self,interpState)) {
+        interpState->nextMode = INTERP_STD;
+        //LOGD("** something wrong, exiting\n");
+        return true;
+    }
+#endif
+#endif
+
     /* copy state in */
     curMethod = interpState->method;
     pc = interpState->pc;
@@ -1869,9 +1912,7 @@
         if (!checkForNullExportPC(obj, fp, pc))
             GOTO_exceptionThrown();
         ILOGV("+ locking %p %s\n", obj, obj->clazz->descriptor);
-#ifdef WITH_MONITOR_TRACKING
-        EXPORT_PC();        /* need for stack trace */
-#endif
+        EXPORT_PC();    /* need for precise GC, also WITH_MONITOR_TRACKING */
         dvmLockObject(self, obj);
 #ifdef WITH_DEADLOCK_PREDICTION
         if (dvmCheckException(self))
@@ -2018,21 +2059,13 @@
             GOTO_exceptionThrown();
 
         /*
-         * Note: the verifier can ensure that this never happens, allowing us
-         * to remove the check.  However, the spec requires we throw the
-         * exception at runtime, not verify time, so the verifier would
-         * need to replace the new-instance call with a magic "throw
-         * InstantiationError" instruction.
-         *
-         * Since this relies on the verifier, which is optional, we would
-         * also need a "new-instance-quick" instruction to identify instances
-         * that don't require the check.
+         * Verifier now tests for interface/abstract class.
          */
-        if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
-            dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationError;",
-                clazz->descriptor);
-            GOTO_exceptionThrown();
-        }
+        //if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
+        //    dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationError;",
+        //        clazz->descriptor);
+        //    GOTO_exceptionThrown();
+        //}
         newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
         if (newObj == NULL)
             GOTO_exceptionThrown();
@@ -3128,8 +3161,13 @@
 HANDLE_OPCODE(OP_UNUSED_EC)
 OP_END
 
-/* File: c/OP_UNUSED_ED.c */
-HANDLE_OPCODE(OP_UNUSED_ED)
+/* File: c/OP_THROW_VERIFICATION_ERROR.c */
+HANDLE_OPCODE(OP_THROW_VERIFICATION_ERROR)
+    EXPORT_PC();
+    vsrc1 = INST_AA(inst);
+    ref = FETCH(1);             /* class/field/method ref */
+    dvmThrowVerificationError(curMethod, vsrc1, ref);
+    GOTO_exceptionThrown();
 OP_END
 
 /* File: c/OP_EXECUTE_INLINE.c */
@@ -3800,7 +3838,7 @@
 
         ILOGV("> retval=0x%llx (leaving %s.%s %s)",
             retval.j, curMethod->clazz->descriptor, curMethod->name,
-            curMethod->signature);
+            curMethod->shorty);
         //DUMP_REGS(curMethod, fp);
 
         saveArea = SAVEAREA_FROM_FP(fp);
@@ -3828,7 +3866,7 @@
         methodClassDex = curMethod->clazz->pDvmDex;
         pc = saveArea->savedPc;
         ILOGD("> (return to %s.%s %s)", curMethod->clazz->descriptor,
-            curMethod->name, curMethod->signature);
+            curMethod->name, curMethod->shorty);
 
         /* use FINISH on the caller's invoke instruction */
         //u2 invokeInstr = INST_INST(FETCH(0));
@@ -3963,7 +4001,7 @@
         methodClassDex = curMethod->clazz->pDvmDex;
         pc = curMethod->insns + catchRelPc;
         ILOGV("> pc <-- %s.%s %s", curMethod->clazz->descriptor,
-            curMethod->name, curMethod->signature);
+            curMethod->name, curMethod->shorty);
         DUMP_REGS(curMethod, fp, false);            // show all regs
 
         /*
@@ -4012,7 +4050,7 @@
         //printf("range=%d call=%p count=%d regs=0x%04x\n",
         //    methodCallRange, methodToCall, count, regs);
         //printf(" --> %s.%s %s\n", methodToCall->clazz->descriptor,
-        //    methodToCall->name, methodToCall->signature);
+        //    methodToCall->name, methodToCall->shorty);
 
         u4* outs;
         int i;
@@ -4082,7 +4120,7 @@
         ILOGV("> %s%s.%s %s",
             dvmIsNativeMethod(methodToCall) ? "(NATIVE) " : "",
             methodToCall->clazz->descriptor, methodToCall->name,
-            methodToCall->signature);
+            methodToCall->shorty);
 
         newFp = (u4*) SAVEAREA_FROM_FP(fp) - methodToCall->registersSize;
         newSaveArea = SAVEAREA_FROM_FP(newFp);
@@ -4122,6 +4160,9 @@
 #endif
         newSaveArea->prevFrame = fp;
         newSaveArea->savedPc = pc;
+#if defined(WITH_JIT)
+        newSaveArea->returnAddr = 0;
+#endif
         newSaveArea->method = methodToCall;
 
         if (!dvmIsNativeMethod(methodToCall)) {
@@ -4140,12 +4181,16 @@
             debugIsMethodEntry = true;              // profiling, debugging
 #endif
             ILOGD("> pc <-- %s.%s %s", curMethod->clazz->descriptor,
-                curMethod->name, curMethod->signature);
+                curMethod->name, curMethod->shorty);
             DUMP_REGS(curMethod, fp, true);         // show input args
             FINISH(0);                              // jump to method start
         } else {
             /* set this up for JNI locals, even if not a JNI native */
-            newSaveArea->xtra.localRefTop = self->jniLocalRefTable.nextEntry;
+#ifdef USE_INDIRECT_REF
+            newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
+#else
+            newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.nextEntry;
+#endif
 
             self->curFrame = newFp;
 
@@ -4162,7 +4207,7 @@
 #endif
 
             ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
-                methodToCall->name, methodToCall->signature);
+                methodToCall->name, methodToCall->shorty);
 
             /*
              * Jump through native call bridge.  Because we leave no
@@ -4199,7 +4244,7 @@
             ILOGD("> (return from native %s.%s to %s.%s %s)",
                 methodToCall->clazz->descriptor, methodToCall->name,
                 curMethod->clazz->descriptor, curMethod->name,
-                curMethod->signature);
+                curMethod->shorty);
 
             //u2 invokeInstr = INST_INST(FETCH(0));
             if (true /*invokeInstr >= OP_INVOKE_VIRTUAL &&
@@ -4216,7 +4261,6 @@
     assert(false);      // should not get here
 GOTO_TARGET_END
 
-
 /* File: portable/enddefs.c */
 /*--- end of opcodes ---*/
 
diff --git a/vm/mterp/out/InterpC-portstd.c b/vm/mterp/out/InterpC-portstd.c
index 64e5ccd..1db6e87 100644
--- a/vm/mterp/out/InterpC-portstd.c
+++ b/vm/mterp/out/InterpC-portstd.c
@@ -26,6 +26,7 @@
 #include "interp/InterpDefs.h"
 #include "mterp/Mterp.h"
 #include <math.h>                   // needed for fmod, fmodf
+#include "mterp/common/FindInterface.h"
 
 /*
  * Configuration defines.  These affect the C implementations, i.e. the
@@ -53,7 +54,7 @@
  */
 #define THREADED_INTERP             /* threaded vs. while-loop interpreter */
 
-#ifdef WITH_INSTR_CHECKS            /* instruction-level paranoia */
+#ifdef WITH_INSTR_CHECKS            /* instruction-level paranoia (slow!) */
 # define CHECK_BRANCH_OFFSETS
 # define CHECK_REGISTER_INDICES
 #endif
@@ -93,6 +94,18 @@
 #endif
 
 /*
+ * Export another copy of the PC on every instruction; this is largely
+ * redundant with EXPORT_PC and the debugger code.  This value can be
+ * compared against what we have stored on the stack with EXPORT_PC to
+ * help ensure that we aren't missing any export calls.
+ */
+#if WITH_EXTRA_GC_CHECKS > 1
+# define EXPORT_EXTRA_PC() (self->currentPc2 = pc)
+#else
+# define EXPORT_EXTRA_PC()
+#endif
+
+/*
  * Adjust the program counter.  "_offset" is a signed int, in 16-bit units.
  *
  * Assumes the existence of "const u2* pc" and "const u2* curMethod->insns".
@@ -116,9 +129,13 @@
             dvmAbort();                                                     \
         }                                                                   \
         pc += myoff;                                                        \
+        EXPORT_EXTRA_PC();                                                  \
     } while (false)
 #else
-# define ADJUST_PC(_offset) (pc += _offset)
+# define ADJUST_PC(_offset) do {                                            \
+        pc += _offset;                                                      \
+        EXPORT_EXTRA_PC();                                                  \
+    } while (false)
 #endif
 
 /*
@@ -303,6 +320,8 @@
  * within the current method won't be shown correctly.  See the notes
  * in Exception.c.
  *
+ * This is also used to determine the address for precise GC.
+ *
  * Assumes existence of "u4* fp" and "const u2* pc".
  */
 #define EXPORT_PC()         (SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc)
@@ -316,29 +335,21 @@
  * If we're building without debug and profiling support, we never switch.
  */
 #if defined(WITH_PROFILER) || defined(WITH_DEBUGGER)
+#if defined(WITH_JIT)
+# define NEED_INTERP_SWITCH(_current) (                                     \
+    (_current == INTERP_STD) ?                                              \
+        dvmJitDebuggerOrProfilerActive(interpState->jitState) :             \
+        !dvmJitDebuggerOrProfilerActive(interpState->jitState) )
+#else
 # define NEED_INTERP_SWITCH(_current) (                                     \
     (_current == INTERP_STD) ?                                              \
         dvmDebuggerOrProfilerActive() : !dvmDebuggerOrProfilerActive() )
+#endif
 #else
 # define NEED_INTERP_SWITCH(_current) (false)
 #endif
 
 /*
- * Look up an interface on a class using the cache.
- */
-INLINE Method* dvmFindInterfaceMethodInCache(ClassObject* thisClass,
-    u4 methodIdx, const Method* method, DvmDex* methodClassDex)
-{
-#define ATOMIC_CACHE_CALC \
-    dvmInterpFindInterfaceMethod(thisClass, methodIdx, method, methodClassDex)
-
-    return (Method*) ATOMIC_CACHE_LOOKUP(methodClassDex->pInterfaceCache,
-                DEX_INTERFACE_CACHE_SIZE, thisClass, methodIdx);
-
-#undef ATOMIC_CACHE_CALC
-}
-
-/*
  * Check to see if "obj" is NULL.  If so, throw an exception.  Assumes the
  * pc has already been exported to the stack.
  *
@@ -402,13 +413,14 @@
     return true;
 }
 
-
 /* File: portable/portstd.c */
 #define INTERP_FUNC_NAME dvmInterpretStd
 #define INTERP_TYPE INTERP_STD
 
 #define CHECK_DEBUG_AND_PROF() ((void)0)
 
+#define CHECK_JIT() ((void)0)
+
 /* File: portable/stubdefs.c */
 /*
  * In the C mterp stubs, "goto" is a function call followed immediately
@@ -440,6 +452,7 @@
         inst = FETCH(0);                                                    \
         CHECK_DEBUG_AND_PROF();                                             \
         CHECK_TRACKED_REFS();                                               \
+        CHECK_JIT();                                                        \
         goto *handlerTable[INST_INST(inst)];                                \
     }
 #else
@@ -485,7 +498,10 @@
  * started.  If so, switch to a different "goto" table.
  */
 #define PERIODIC_CHECKS(_entryPoint, _pcadj) {                              \
-        dvmCheckSuspendQuick(self);                                         \
+        if (dvmCheckSuspendQuick(self)) {                                   \
+            EXPORT_PC();  /* need for precise GC */                         \
+            dvmCheckSuspendPending(self);                                   \
+        }                                                                   \
         if (NEED_INTERP_SWITCH(INTERP_TYPE)) {                              \
             ADJUST_PC(_pcadj);                                              \
             interpState->entryPoint = _entryPoint;                          \
@@ -1178,11 +1194,32 @@
     const Method* methodToCall;
     bool methodCallRange;
 
+
 #if defined(THREADED_INTERP)
     /* static computed goto table */
     DEFINE_GOTO_TABLE(handlerTable);
 #endif
 
+#if defined(WITH_JIT)
+#if 0
+    LOGD("*DebugInterp - entrypoint is %d, tgt is 0x%x, %s\n",
+         interpState->entryPoint,
+         interpState->pc,
+         interpState->method->name);
+#endif
+
+#if INTERP_TYPE == INTERP_DBG
+    /* Check to see if we've got a trace selection request.  If we do,
+     * but something is amiss, revert to the fast interpreter.
+     */
+    if (dvmJitCheckTraceRequest(self,interpState)) {
+        interpState->nextMode = INTERP_STD;
+        //LOGD("** something wrong, exiting\n");
+        return true;
+    }
+#endif
+#endif
+
     /* copy state in */
     curMethod = interpState->method;
     pc = interpState->pc;
@@ -1589,9 +1626,7 @@
         if (!checkForNullExportPC(obj, fp, pc))
             GOTO_exceptionThrown();
         ILOGV("+ locking %p %s\n", obj, obj->clazz->descriptor);
-#ifdef WITH_MONITOR_TRACKING
-        EXPORT_PC();        /* need for stack trace */
-#endif
+        EXPORT_PC();    /* need for precise GC, also WITH_MONITOR_TRACKING */
         dvmLockObject(self, obj);
 #ifdef WITH_DEADLOCK_PREDICTION
         if (dvmCheckException(self))
@@ -1738,21 +1773,13 @@
             GOTO_exceptionThrown();
 
         /*
-         * Note: the verifier can ensure that this never happens, allowing us
-         * to remove the check.  However, the spec requires we throw the
-         * exception at runtime, not verify time, so the verifier would
-         * need to replace the new-instance call with a magic "throw
-         * InstantiationError" instruction.
-         *
-         * Since this relies on the verifier, which is optional, we would
-         * also need a "new-instance-quick" instruction to identify instances
-         * that don't require the check.
+         * Verifier now tests for interface/abstract class.
          */
-        if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
-            dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationError;",
-                clazz->descriptor);
-            GOTO_exceptionThrown();
-        }
+        //if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
+        //    dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationError;",
+        //        clazz->descriptor);
+        //    GOTO_exceptionThrown();
+        //}
         newObj = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
         if (newObj == NULL)
             GOTO_exceptionThrown();
@@ -2848,8 +2875,13 @@
 HANDLE_OPCODE(OP_UNUSED_EC)
 OP_END
 
-/* File: c/OP_UNUSED_ED.c */
-HANDLE_OPCODE(OP_UNUSED_ED)
+/* File: c/OP_THROW_VERIFICATION_ERROR.c */
+HANDLE_OPCODE(OP_THROW_VERIFICATION_ERROR)
+    EXPORT_PC();
+    vsrc1 = INST_AA(inst);
+    ref = FETCH(1);             /* class/field/method ref */
+    dvmThrowVerificationError(curMethod, vsrc1, ref);
+    GOTO_exceptionThrown();
 OP_END
 
 /* File: c/OP_EXECUTE_INLINE.c */
@@ -3520,7 +3552,7 @@
 
         ILOGV("> retval=0x%llx (leaving %s.%s %s)",
             retval.j, curMethod->clazz->descriptor, curMethod->name,
-            curMethod->signature);
+            curMethod->shorty);
         //DUMP_REGS(curMethod, fp);
 
         saveArea = SAVEAREA_FROM_FP(fp);
@@ -3548,7 +3580,7 @@
         methodClassDex = curMethod->clazz->pDvmDex;
         pc = saveArea->savedPc;
         ILOGD("> (return to %s.%s %s)", curMethod->clazz->descriptor,
-            curMethod->name, curMethod->signature);
+            curMethod->name, curMethod->shorty);
 
         /* use FINISH on the caller's invoke instruction */
         //u2 invokeInstr = INST_INST(FETCH(0));
@@ -3683,7 +3715,7 @@
         methodClassDex = curMethod->clazz->pDvmDex;
         pc = curMethod->insns + catchRelPc;
         ILOGV("> pc <-- %s.%s %s", curMethod->clazz->descriptor,
-            curMethod->name, curMethod->signature);
+            curMethod->name, curMethod->shorty);
         DUMP_REGS(curMethod, fp, false);            // show all regs
 
         /*
@@ -3732,7 +3764,7 @@
         //printf("range=%d call=%p count=%d regs=0x%04x\n",
         //    methodCallRange, methodToCall, count, regs);
         //printf(" --> %s.%s %s\n", methodToCall->clazz->descriptor,
-        //    methodToCall->name, methodToCall->signature);
+        //    methodToCall->name, methodToCall->shorty);
 
         u4* outs;
         int i;
@@ -3802,7 +3834,7 @@
         ILOGV("> %s%s.%s %s",
             dvmIsNativeMethod(methodToCall) ? "(NATIVE) " : "",
             methodToCall->clazz->descriptor, methodToCall->name,
-            methodToCall->signature);
+            methodToCall->shorty);
 
         newFp = (u4*) SAVEAREA_FROM_FP(fp) - methodToCall->registersSize;
         newSaveArea = SAVEAREA_FROM_FP(newFp);
@@ -3842,6 +3874,9 @@
 #endif
         newSaveArea->prevFrame = fp;
         newSaveArea->savedPc = pc;
+#if defined(WITH_JIT)
+        newSaveArea->returnAddr = 0;
+#endif
         newSaveArea->method = methodToCall;
 
         if (!dvmIsNativeMethod(methodToCall)) {
@@ -3860,12 +3895,16 @@
             debugIsMethodEntry = true;              // profiling, debugging
 #endif
             ILOGD("> pc <-- %s.%s %s", curMethod->clazz->descriptor,
-                curMethod->name, curMethod->signature);
+                curMethod->name, curMethod->shorty);
             DUMP_REGS(curMethod, fp, true);         // show input args
             FINISH(0);                              // jump to method start
         } else {
             /* set this up for JNI locals, even if not a JNI native */
-            newSaveArea->xtra.localRefTop = self->jniLocalRefTable.nextEntry;
+#ifdef USE_INDIRECT_REF
+            newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
+#else
+            newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.nextEntry;
+#endif
 
             self->curFrame = newFp;
 
@@ -3882,7 +3921,7 @@
 #endif
 
             ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
-                methodToCall->name, methodToCall->signature);
+                methodToCall->name, methodToCall->shorty);
 
             /*
              * Jump through native call bridge.  Because we leave no
@@ -3919,7 +3958,7 @@
             ILOGD("> (return from native %s.%s to %s.%s %s)",
                 methodToCall->clazz->descriptor, methodToCall->name,
                 curMethod->clazz->descriptor, curMethod->name,
-                curMethod->signature);
+                curMethod->shorty);
 
             //u2 invokeInstr = INST_INST(FETCH(0));
             if (true /*invokeInstr >= OP_INVOKE_VIRTUAL &&
@@ -3936,7 +3975,6 @@
     assert(false);      // should not get here
 GOTO_TARGET_END
 
-
 /* File: portable/enddefs.c */
 /*--- end of opcodes ---*/
 
diff --git a/vm/mterp/out/InterpC-x86.c b/vm/mterp/out/InterpC-x86.c
index cd5fe95..07536c4 100644
--- a/vm/mterp/out/InterpC-x86.c
+++ b/vm/mterp/out/InterpC-x86.c
@@ -26,6 +26,7 @@
 #include "interp/InterpDefs.h"
 #include "mterp/Mterp.h"
 #include <math.h>                   // needed for fmod, fmodf
+#include "mterp/common/FindInterface.h"
 
 /*
  * Configuration defines.  These affect the C implementations, i.e. the
@@ -53,7 +54,7 @@
  */
 #define THREADED_INTERP             /* threaded vs. while-loop interpreter */
 
-#ifdef WITH_INSTR_CHECKS            /* instruction-level paranoia */
+#ifdef WITH_INSTR_CHECKS            /* instruction-level paranoia (slow!) */
 # define CHECK_BRANCH_OFFSETS
 # define CHECK_REGISTER_INDICES
 #endif
@@ -93,6 +94,18 @@
 #endif
 
 /*
+ * Export another copy of the PC on every instruction; this is largely
+ * redundant with EXPORT_PC and the debugger code.  This value can be
+ * compared against what we have stored on the stack with EXPORT_PC to
+ * help ensure that we aren't missing any export calls.
+ */
+#if WITH_EXTRA_GC_CHECKS > 1
+# define EXPORT_EXTRA_PC() (self->currentPc2 = pc)
+#else
+# define EXPORT_EXTRA_PC()
+#endif
+
+/*
  * Adjust the program counter.  "_offset" is a signed int, in 16-bit units.
  *
  * Assumes the existence of "const u2* pc" and "const u2* curMethod->insns".
@@ -116,9 +129,13 @@
             dvmAbort();                                                     \
         }                                                                   \
         pc += myoff;                                                        \
+        EXPORT_EXTRA_PC();                                                  \
     } while (false)
 #else
-# define ADJUST_PC(_offset) (pc += _offset)
+# define ADJUST_PC(_offset) do {                                            \
+        pc += _offset;                                                      \
+        EXPORT_EXTRA_PC();                                                  \
+    } while (false)
 #endif
 
 /*
@@ -303,6 +320,8 @@
  * within the current method won't be shown correctly.  See the notes
  * in Exception.c.
  *
+ * This is also used to determine the address for precise GC.
+ *
  * Assumes existence of "u4* fp" and "const u2* pc".
  */
 #define EXPORT_PC()         (SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc)
@@ -316,29 +335,21 @@
  * If we're building without debug and profiling support, we never switch.
  */
 #if defined(WITH_PROFILER) || defined(WITH_DEBUGGER)
+#if defined(WITH_JIT)
+# define NEED_INTERP_SWITCH(_current) (                                     \
+    (_current == INTERP_STD) ?                                              \
+        dvmJitDebuggerOrProfilerActive(interpState->jitState) :             \
+        !dvmJitDebuggerOrProfilerActive(interpState->jitState) )
+#else
 # define NEED_INTERP_SWITCH(_current) (                                     \
     (_current == INTERP_STD) ?                                              \
         dvmDebuggerOrProfilerActive() : !dvmDebuggerOrProfilerActive() )
+#endif
 #else
 # define NEED_INTERP_SWITCH(_current) (false)
 #endif
 
 /*
- * Look up an interface on a class using the cache.
- */
-INLINE Method* dvmFindInterfaceMethodInCache(ClassObject* thisClass,
-    u4 methodIdx, const Method* method, DvmDex* methodClassDex)
-{
-#define ATOMIC_CACHE_CALC \
-    dvmInterpFindInterfaceMethod(thisClass, methodIdx, method, methodClassDex)
-
-    return (Method*) ATOMIC_CACHE_LOOKUP(methodClassDex->pInterfaceCache,
-                DEX_INTERFACE_CACHE_SIZE, thisClass, methodIdx);
-
-#undef ATOMIC_CACHE_CALC
-}
-
-/*
  * Check to see if "obj" is NULL.  If so, throw an exception.  Assumes the
  * pc has already been exported to the stack.
  *
@@ -402,7 +413,6 @@
     return true;
 }
 
-
 /* File: cstubs/stubdefs.c */
 /* this is a standard (no debug support) interpreter */
 #define INTERP_TYPE INTERP_STD
@@ -513,12 +523,15 @@
  * started.  If so, switch to a different "goto" table.
  */
 #define PERIODIC_CHECKS(_entryPoint, _pcadj) {                              \
-        dvmCheckSuspendQuick(self);                                         \
+        if (dvmCheckSuspendQuick(self)) {                                   \
+            EXPORT_PC();  /* need for precise GC */                         \
+            dvmCheckSuspendPending(self);                                   \
+        }                                                                   \
         if (NEED_INTERP_SWITCH(INTERP_TYPE)) {                              \
             ADJUST_PC(_pcadj);                                              \
             glue->entryPoint = _entryPoint;                                 \
             LOGVV("threadid=%d: switch to STD ep=%d adj=%d\n",              \
-                glue->self->threadId, (_entryPoint), (_pcadj));             \
+                self->threadId, (_entryPoint), (_pcadj));                   \
             GOTO_bail_switch();                                             \
         }                                                                   \
     }
@@ -1689,7 +1702,7 @@
 
         ILOGV("> retval=0x%llx (leaving %s.%s %s)",
             retval.j, curMethod->clazz->descriptor, curMethod->name,
-            curMethod->signature);
+            curMethod->shorty);
         //DUMP_REGS(curMethod, fp);
 
         saveArea = SAVEAREA_FROM_FP(fp);
@@ -1717,7 +1730,7 @@
         methodClassDex = curMethod->clazz->pDvmDex;
         pc = saveArea->savedPc;
         ILOGD("> (return to %s.%s %s)", curMethod->clazz->descriptor,
-            curMethod->name, curMethod->signature);
+            curMethod->name, curMethod->shorty);
 
         /* use FINISH on the caller's invoke instruction */
         //u2 invokeInstr = INST_INST(FETCH(0));
@@ -1852,7 +1865,7 @@
         methodClassDex = curMethod->clazz->pDvmDex;
         pc = curMethod->insns + catchRelPc;
         ILOGV("> pc <-- %s.%s %s", curMethod->clazz->descriptor,
-            curMethod->name, curMethod->signature);
+            curMethod->name, curMethod->shorty);
         DUMP_REGS(curMethod, fp, false);            // show all regs
 
         /*
@@ -1901,7 +1914,7 @@
         //printf("range=%d call=%p count=%d regs=0x%04x\n",
         //    methodCallRange, methodToCall, count, regs);
         //printf(" --> %s.%s %s\n", methodToCall->clazz->descriptor,
-        //    methodToCall->name, methodToCall->signature);
+        //    methodToCall->name, methodToCall->shorty);
 
         u4* outs;
         int i;
@@ -1971,7 +1984,7 @@
         ILOGV("> %s%s.%s %s",
             dvmIsNativeMethod(methodToCall) ? "(NATIVE) " : "",
             methodToCall->clazz->descriptor, methodToCall->name,
-            methodToCall->signature);
+            methodToCall->shorty);
 
         newFp = (u4*) SAVEAREA_FROM_FP(fp) - methodToCall->registersSize;
         newSaveArea = SAVEAREA_FROM_FP(newFp);
@@ -2011,6 +2024,9 @@
 #endif
         newSaveArea->prevFrame = fp;
         newSaveArea->savedPc = pc;
+#if defined(WITH_JIT)
+        newSaveArea->returnAddr = 0;
+#endif
         newSaveArea->method = methodToCall;
 
         if (!dvmIsNativeMethod(methodToCall)) {
@@ -2029,12 +2045,16 @@
             debugIsMethodEntry = true;              // profiling, debugging
 #endif
             ILOGD("> pc <-- %s.%s %s", curMethod->clazz->descriptor,
-                curMethod->name, curMethod->signature);
+                curMethod->name, curMethod->shorty);
             DUMP_REGS(curMethod, fp, true);         // show input args
             FINISH(0);                              // jump to method start
         } else {
             /* set this up for JNI locals, even if not a JNI native */
-            newSaveArea->xtra.localRefTop = self->jniLocalRefTable.nextEntry;
+#ifdef USE_INDIRECT_REF
+            newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.segmentState.all;
+#else
+            newSaveArea->xtra.localRefCookie = self->jniLocalRefTable.nextEntry;
+#endif
 
             self->curFrame = newFp;
 
@@ -2051,7 +2071,7 @@
 #endif
 
             ILOGD("> native <-- %s.%s %s", methodToCall->clazz->descriptor,
-                methodToCall->name, methodToCall->signature);
+                methodToCall->name, methodToCall->shorty);
 
             /*
              * Jump through native call bridge.  Because we leave no
@@ -2088,7 +2108,7 @@
             ILOGD("> (return from native %s.%s to %s.%s %s)",
                 methodToCall->clazz->descriptor, methodToCall->name,
                 curMethod->clazz->descriptor, curMethod->name,
-                curMethod->signature);
+                curMethod->shorty);
 
             //u2 invokeInstr = INST_INST(FETCH(0));
             if (true /*invokeInstr >= OP_INVOKE_VIRTUAL &&
@@ -2105,7 +2125,6 @@
     assert(false);      // should not get here
 GOTO_TARGET_END
 
-
 /* File: cstubs/enddefs.c */
 
 /* undefine "magic" name remapping */
diff --git a/vm/mterp/portable/debug.c b/vm/mterp/portable/debug.c
index 38b55ae..449d49b 100644
--- a/vm/mterp/portable/debug.c
+++ b/vm/mterp/portable/debug.c
@@ -223,7 +223,7 @@
         if (/*gDvm.debuggerActive &&*/
             strcmp(method->clazz->descriptor, cd) == 0 &&
             strcmp(method->name, mn) == 0 &&
-            strcmp(method->signature, sg) == 0)
+            strcmp(method->shorty, sg) == 0)
         {
             LOGW("Reached %s.%s, enabling verbose mode\n",
                 method->clazz->descriptor, method->name);
diff --git a/vm/mterp/portable/entry.c b/vm/mterp/portable/entry.c
index 6698959..9c7c2d6 100644
--- a/vm/mterp/portable/entry.c
+++ b/vm/mterp/portable/entry.c
@@ -29,11 +29,32 @@
     const Method* methodToCall;
     bool methodCallRange;
 
+
 #if defined(THREADED_INTERP)
     /* static computed goto table */
     DEFINE_GOTO_TABLE(handlerTable);
 #endif
 
+#if defined(WITH_JIT)
+#if 0
+    LOGD("*DebugInterp - entrypoint is %d, tgt is 0x%x, %s\n",
+         interpState->entryPoint,
+         interpState->pc,
+         interpState->method->name);
+#endif
+
+#if INTERP_TYPE == INTERP_DBG
+    /* Check to see if we've got a trace selection request.  If we do,
+     * but something is amiss, revert to the fast interpreter.
+     */
+    if (dvmJitCheckTraceRequest(self,interpState)) {
+        interpState->nextMode = INTERP_STD;
+        //LOGD("** something wrong, exiting\n");
+        return true;
+    }
+#endif
+#endif
+
     /* copy state in */
     curMethod = interpState->method;
     pc = interpState->pc;
diff --git a/vm/mterp/portable/portdbg.c b/vm/mterp/portable/portdbg.c
index a657f09..04132cb 100644
--- a/vm/mterp/portable/portdbg.c
+++ b/vm/mterp/portable/portdbg.c
@@ -3,3 +3,11 @@
 
 #define CHECK_DEBUG_AND_PROF() \
     checkDebugAndProf(pc, fp, self, curMethod, &debugIsMethodEntry)
+
+#if defined(WITH_JIT)
+#define CHECK_JIT() \
+    if (dvmCheckJit(pc, self, interpState)) GOTO_bail_switch()
+#else
+#define CHECK_JIT() \
+    ((void)0)
+#endif
diff --git a/vm/mterp/portable/portstd.c b/vm/mterp/portable/portstd.c
index 01fbda1..f55e8e7 100644
--- a/vm/mterp/portable/portstd.c
+++ b/vm/mterp/portable/portstd.c
@@ -2,3 +2,5 @@
 #define INTERP_TYPE INTERP_STD
 
 #define CHECK_DEBUG_AND_PROF() ((void)0)
+
+#define CHECK_JIT() ((void)0)
diff --git a/vm/mterp/portable/stubdefs.c b/vm/mterp/portable/stubdefs.c
index 0ea563c..305aebb 100644
--- a/vm/mterp/portable/stubdefs.c
+++ b/vm/mterp/portable/stubdefs.c
@@ -28,6 +28,7 @@
         inst = FETCH(0);                                                    \
         CHECK_DEBUG_AND_PROF();                                             \
         CHECK_TRACKED_REFS();                                               \
+        CHECK_JIT();                                                        \
         goto *handlerTable[INST_INST(inst)];                                \
     }
 #else
@@ -73,7 +74,10 @@
  * started.  If so, switch to a different "goto" table.
  */
 #define PERIODIC_CHECKS(_entryPoint, _pcadj) {                              \
-        dvmCheckSuspendQuick(self);                                         \
+        if (dvmCheckSuspendQuick(self)) {                                   \
+            EXPORT_PC();  /* need for precise GC */                         \
+            dvmCheckSuspendPending(self);                                   \
+        }                                                                   \
         if (NEED_INTERP_SWITCH(INTERP_TYPE)) {                              \
             ADJUST_PC(_pcadj);                                              \
             interpState->entryPoint = _entryPoint;                          \
diff --git a/vm/mterp/rebuild.sh b/vm/mterp/rebuild.sh
index 1380f69..32c9007 100755
--- a/vm/mterp/rebuild.sh
+++ b/vm/mterp/rebuild.sh
@@ -19,7 +19,7 @@
 # generated as part of the build.
 #
 set -e
-for arch in portstd portdbg allstubs armv4t armv5te x86; do TARGET_ARCH_EXT=$arch make -f Makefile-mterp; done
+for arch in portstd portdbg allstubs armv4t armv5te armv5te-vfp armv7-a x86; do TARGET_ARCH_EXT=$arch make -f Makefile-mterp; done
 
 # These aren't actually used, so just go ahead and remove them.  The correct
 # approach is to prevent them from being generated in the first place, but
diff --git a/vm/mterp/x86/OP_INVOKE_DIRECT.S b/vm/mterp/x86/OP_INVOKE_DIRECT.S
index a772540..f423dc3 100644
--- a/vm/mterp/x86/OP_INVOKE_DIRECT.S
+++ b/vm/mterp/x86/OP_INVOKE_DIRECT.S
@@ -30,9 +30,7 @@
 .L${opcode}_finish:
     UNSPILL(rPC)
     testl     %ecx,%ecx                # null "this"?
-    movl      $$$isrange,%ecx
-    #jne       common_invokeMethod${routine}  # no, continue on
-    jne       common_invokeOld          # no, continue on, eax<- method, ecx<- methodCallRange
+    jne       common_invokeMethod${routine}  # no, continue on
     jmp       common_errNullObject
 %break
 
diff --git a/vm/mterp/x86/OP_INVOKE_INTERFACE.S b/vm/mterp/x86/OP_INVOKE_INTERFACE.S
index 02dc76f..1631177 100644
--- a/vm/mterp/x86/OP_INVOKE_INTERFACE.S
+++ b/vm/mterp/x86/OP_INVOKE_INTERFACE.S
@@ -35,7 +35,5 @@
     UNSPILL(rPC)
     testl      %eax,%eax
     je         common_exceptionThrown
-    movl       $$$isrange,%ecx
-    #jmp        common_invokeMethod${routine}
-    jmp        common_invokeOld
+    jmp        common_invokeMethod${routine}
 
diff --git a/vm/mterp/x86/OP_INVOKE_STATIC.S b/vm/mterp/x86/OP_INVOKE_STATIC.S
index c65fc1f..40dac06 100644
--- a/vm/mterp/x86/OP_INVOKE_STATIC.S
+++ b/vm/mterp/x86/OP_INVOKE_STATIC.S
@@ -14,10 +14,8 @@
     EXPORT_PC()
     movl      offDvmDex_pResMethods(%ecx),%ecx  # ecx<- pDvmDex->pResMethods
     movl      (%ecx,%eax,4),%eax        # eax<- resolved methodToCall
-    movl      $$$isrange,%ecx           # needed by common_invokeOld - revisit
     testl     %eax,%eax
-    #jne       common_invokeMethod${routine}
-    jne       common_invokeOld
+    jne       common_invokeMethod${routine}
     GET_GLUE(%ecx)
     movl      offGlue_method(%ecx),%ecx # ecx<- glue->method
     movzwl    2(rPC),%eax
@@ -33,9 +31,7 @@
     SPILL(rPC)
     call      dvmResolveMethod          # call(clazz,ref,flags)
     UNSPILL(rPC)
-    movl      $$$isrange,%ecx
     testl     %eax,%eax                 # got null?
-    #jne       common_invokeMethod${routine}
-    jne       common_invokeOld
+    jne       common_invokeMethod${routine}
     jmp       common_exceptionThrown
 
diff --git a/vm/mterp/x86/OP_INVOKE_SUPER.S b/vm/mterp/x86/OP_INVOKE_SUPER.S
index d0a6ad6..013fc01 100644
--- a/vm/mterp/x86/OP_INVOKE_SUPER.S
+++ b/vm/mterp/x86/OP_INVOKE_SUPER.S
@@ -40,9 +40,8 @@
     jae     .L${opcode}_nsm           # method not present in superclass
     movl    offClassObject_vtable(%eax),%eax   # eax<- ...clazz->super->vtable
     movl    (%eax,%ecx,4),%eax        # eax<- vtable[methodIndex]
-    movl    $$$isrange,%ecx
-    #jmp     common_invokeMethod${routine}
-    jmp     common_invokeOld
+    jmp     common_invokeMethod${routine}
+
 
     /* At this point:
      * ecx = null (needs to be resolved base method)
diff --git a/vm/mterp/x86/OP_INVOKE_SUPER_QUICK.S b/vm/mterp/x86/OP_INVOKE_SUPER_QUICK.S
index b050c82..7545eb0 100644
--- a/vm/mterp/x86/OP_INVOKE_SUPER_QUICK.S
+++ b/vm/mterp/x86/OP_INVOKE_SUPER_QUICK.S
@@ -23,7 +23,5 @@
     movl      offClassObject_vtable(%ecx),%ecx # ecx<- vtable
     EXPORT_PC()
     movl      (%ecx,%eax,4),%eax        # eax<- super->vtable[BBBB]
-    movl      $$$isrange,%ecx           # ecx<- range flag
-    #jmp       common_invokeMethod${routine}
-    jmp       common_invokeOld
+    jmp       common_invokeMethod${routine}
 
diff --git a/vm/mterp/x86/OP_INVOKE_VIRTUAL.S b/vm/mterp/x86/OP_INVOKE_VIRTUAL.S
index 6d32a81..20d9120 100644
--- a/vm/mterp/x86/OP_INVOKE_VIRTUAL.S
+++ b/vm/mterp/x86/OP_INVOKE_VIRTUAL.S
@@ -52,7 +52,5 @@
     movl      offObject_clazz(%ecx),%ecx  # ecx<- thisPtr->clazz
     movl      offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable
     movl      (%ecx,%eax,4),%eax        # eax<- vtable[methodIndex]
-    movl      $$$isrange,%ecx           # needed for common_invokeOld
-    #jmp       common_invokeMethod${routine}
-    jmp       common_invokeOld
+    jmp       common_invokeMethod${routine}
 
diff --git a/vm/mterp/x86/OP_INVOKE_VIRTUAL_QUICK.S b/vm/mterp/x86/OP_INVOKE_VIRTUAL_QUICK.S
index d197f29..f36ed2d 100644
--- a/vm/mterp/x86/OP_INVOKE_VIRTUAL_QUICK.S
+++ b/vm/mterp/x86/OP_INVOKE_VIRTUAL_QUICK.S
@@ -20,7 +20,6 @@
     movl      offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable
     EXPORT_PC()                         # might throw later - get ready
     movl      (%eax,%ecx,4),%eax        # eax<- vtable[BBBB]
-    movl      $$$isrange,%ecx           # pass range flag
-    #jmp       common_invokeMethod${routine}
-    jmp       common_invokeOld
+    jmp       common_invokeMethod${routine}
+
 
diff --git a/vm/mterp/x86/OP_MONITOR_ENTER.S b/vm/mterp/x86/OP_MONITOR_ENTER.S
index 18425f4..548f71f 100644
--- a/vm/mterp/x86/OP_MONITOR_ENTER.S
+++ b/vm/mterp/x86/OP_MONITOR_ENTER.S
@@ -10,9 +10,7 @@
     movl    offGlue_self(%ecx),%ecx     # ecx<- glue->self
     FETCH_INST_WORD(1)
     testl   %eax,%eax                   # null object?
-#ifdef WITH_MONITOR_TRACKING
-    EXPORT_PC()
-#endif
+    EXPORT_PC()                         # need for precise GC, MONITOR_TRACKING
     jne     .L${opcode}_continue
     jmp     common_errNullObject
 %break
diff --git a/vm/mterp/x86/OP_NEW_INSTANCE.S b/vm/mterp/x86/OP_NEW_INSTANCE.S
index da951f7..d56d55c 100644
--- a/vm/mterp/x86/OP_NEW_INSTANCE.S
+++ b/vm/mterp/x86/OP_NEW_INSTANCE.S
@@ -27,6 +27,7 @@
 %break
 
 .L${opcode}_initialized:  # on entry, ecx<- class
+    /* TODO: remove test for interface/abstract, now done in verifier */
     testl     $$(ACC_INTERFACE|ACC_ABSTRACT),offClassObject_accessFlags(%ecx)
     movl      $$ALLOC_DONT_TRACK,OUT_ARG1(%esp)
     jne       .L${opcode}_abstract
@@ -77,6 +78,7 @@
     jmp     common_exceptionThrown      # no, handle exception
 
     /*
+     * TODO: remove this
      * We can't instantiate an abstract class or interface, so throw an
      * InstantiationError with the class descriptor as the message.
      *
diff --git a/vm/mterp/x86/OP_THROW_VERIFICATION_ERROR.S b/vm/mterp/x86/OP_THROW_VERIFICATION_ERROR.S
new file mode 100644
index 0000000..c3b5063
--- /dev/null
+++ b/vm/mterp/x86/OP_THROW_VERIFICATION_ERROR.S
@@ -0,0 +1,20 @@
+%verify executed
+    /*
+     * Handle a throw-verification-error instruction.  This throws an
+     * exception for an error discovered during verification.  The
+     * exception is indicated by AA, with some detail provided by BBBB.
+     */
+    /* op AA, ref@BBBB */
+    GET_GLUE(%ecx)
+    movzwl   2(rPC),%eax                     # eax<- BBBB
+    movl     offGlue_method(%ecx),%ecx       # ecx<- glue->method
+    EXPORT_PC()
+    movzbl   rINST_HI,rINST_FULL             # rINST_FULL<- AA
+    movl     %eax,OUT_ARG2(%esp)             # arg2<- BBBB
+    movl     rINST_FULL,OUT_ARG1(%esp)       # arg1<- AA
+    movl     %ecx,OUT_ARG0(%esp)             # arg0<- method
+    SPILL(rPC)
+    call     dvmThrowVerificationError       # call(method, kind, ref)
+    UNSPILL(rPC)
+    jmp      common_exceptionThrown          # handle exception
+
diff --git a/vm/mterp/x86/OP_UNUSED_ED.S b/vm/mterp/x86/OP_UNUSED_ED.S
deleted file mode 100644
index 31d98c1..0000000
--- a/vm/mterp/x86/OP_UNUSED_ED.S
+++ /dev/null
@@ -1 +0,0 @@
-%include "x86/unused.S"
diff --git a/vm/mterp/x86/footer.S b/vm/mterp/x86/footer.S
index 50634dd..c39fa16 100644
--- a/vm/mterp/x86/footer.S
+++ b/vm/mterp/x86/footer.S
@@ -25,11 +25,217 @@
  */
 common_backwardBranch:
     GET_GLUE(%ecx)
-    call   common_periodicChecks      # Note: expects rPC to be preserved
+    call   common_periodicChecks  # Note: expects rPC to be preserved
     ADVANCE_PC_INDEXED(rINST_FULL)
     FETCH_INST()
     GOTO_NEXT
 
+
+
+/*
+ * Common code for method invocation with range.
+ *
+ * On entry:
+ *   eax = Method* methodToCall
+ *   rINST trashed, must reload
+ */
+
+common_invokeMethodRange:
+.LinvokeNewRange:
+
+   /*
+    * prepare to copy args to "outs" area of current frame
+    */
+
+    movzbl      1(rPC),rINST_FULL       # rINST_FULL<- AA
+    movzwl      4(rPC), %ecx            # %ecx<- CCCC
+    SPILL(rPC)
+    SAVEAREA_FROM_FP(%edx,rFP)          # %edx<- &StackSaveArea
+    test        rINST_FULL, rINST_FULL
+    movl        rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- AA
+    jz          .LinvokeArgsDone        # no args; jump to args done
+
+
+   /*
+    * %eax=methodToCall, %ecx=CCCC, LOCAL0_OFFSET(%ebp)=count, %edx=&outs (&stackSaveArea)
+    * (very few methods have > 10 args; could unroll for common cases)
+    */
+
+    movl        %ebx, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- save %ebx
+    lea         (rFP, %ecx, 4), %ecx    # %ecx<- &vCCCC
+    shll        $$2, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- offset
+    subl        LOCAL0_OFFSET(%ebp), %edx       # %edx<- update &outs
+    shrl        $$2, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- offset
+1:
+    movl        (%ecx), %ebx            # %ebx<- vCCCC
+    lea         4(%ecx), %ecx           # %ecx<- &vCCCC++
+    subl        $$1, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET<- LOCAL0_OFFSET--
+    movl        %ebx, (%edx)            # *outs<- vCCCC
+    lea         4(%edx), %edx           # outs++
+    jne         1b                      # loop if count (LOCAL0_OFFSET(%ebp)) not zero
+    movl        LOCAL1_OFFSET(%ebp), %ebx       # %ebx<- restore %ebx
+    jmp         .LinvokeArgsDone        # continue
+
+   /*
+    * %eax is "Method* methodToCall", the method we're trying to call
+    * prepare to copy args to "outs" area of current frame
+    */
+
+common_invokeMethodNoRange:
+.LinvokeNewNoRange:
+    movzbl      1(rPC),rINST_FULL       # rINST_FULL<- BA
+    SPILL(rPC)
+    movl        rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- BA
+    shrl        $$4, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- B
+    je          .LinvokeArgsDone        # no args; jump to args done
+    movzwl      4(rPC), %ecx            # %ecx<- GFED
+    SAVEAREA_FROM_FP(%edx,rFP)          # %edx<- &StackSaveArea
+
+   /*
+    * %eax=methodToCall, %ecx=GFED, LOCAL0_OFFSET(%ebp)=count, %edx=outs
+    */
+
+.LinvokeNonRange:
+    cmp         $$2, LOCAL0_OFFSET(%ebp)        # compare LOCAL0_OFFSET(%ebp) to 2
+    movl        %ecx, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- GFED
+    jl          1f                      # handle 1 arg
+    je          2f                      # handle 2 args
+    cmp         $$4, LOCAL0_OFFSET(%ebp)        # compare LOCAL0_OFFSET(%ebp) to 4
+    jl          3f                      # handle 3 args
+    je          4f                      # handle 4 args
+5:
+    andl        $$15, rINST_FULL        # rINST<- A
+    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
+    movl        (rFP, rINST_FULL, 4), %ecx # %ecx<- vA
+    movl        %ecx, (%edx)            # *outs<- vA
+    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
+4:
+    shr         $$12, %ecx              # %ecx<- G
+    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
+    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vG
+    movl        %ecx, (%edx)            # *outs<- vG
+    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
+3:
+    and         $$0x0f00, %ecx          # %ecx<- 0F00
+    shr         $$8, %ecx               # %ecx<- F
+    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
+    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vF
+    movl        %ecx, (%edx)            # *outs<- vF
+    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
+2:
+    and         $$0x00f0, %ecx          # %ecx<- 00E0
+    shr         $$4, %ecx               # %ecx<- E
+    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
+    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vE
+    movl        %ecx, (%edx)            # *outs<- vE
+    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
+1:
+    and         $$0x000f, %ecx          # %ecx<- 000D
+    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vD
+    movl        %ecx, -4(%edx)          # *--outs<- vD
+0:
+
+   /*
+    * %eax is "Method* methodToCall", the method we're trying to call
+    * find space for the new stack frame, check for overflow
+    */
+
+.LinvokeArgsDone:
+    movzwl      offMethod_registersSize(%eax), %edx # %edx<- methodToCall->regsSize
+    movzwl      offMethod_outsSize(%eax), %ecx # %ecx<- methodToCall->outsSize
+    movl        %eax, LOCAL0_OFFSET(%ebp)       # LOCAL0_OFFSET<- methodToCall
+    shl         $$2, %edx               # %edx<- update offset
+    SAVEAREA_FROM_FP(%eax,rFP)          # %eax<- &StackSaveArea
+    subl        %edx, %eax              # %eax<- newFP; (old savearea - regsSize)
+    GET_GLUE(%edx)                      # %edx<- pMterpGlue
+    movl        %eax, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- &outs
+    subl        $$sizeofStackSaveArea, %eax # %eax<- newSaveArea (stack save area using newFP)
+    movl        offGlue_interpStackEnd(%edx), %edx # %edx<- glue->interpStackEnd
+    movl        %edx, LOCAL2_OFFSET(%ebp)       # LOCAL2_OFFSET<- glue->interpStackEnd
+    shl         $$2, %ecx               # %ecx<- update offset for outsSize
+    movl        %eax, %edx              # %edx<- newSaveArea
+    sub         %ecx, %eax              # %eax<- bottom; (newSaveArea - outsSize)
+    cmp         LOCAL2_OFFSET(%ebp), %eax       # compare interpStackEnd and bottom
+    movl        LOCAL0_OFFSET(%ebp), %eax       # %eax<- restore methodToCall
+    jl          .LstackOverflow         # handle frame overflow
+
+   /*
+    * set up newSaveArea
+    */
+
+#ifdef EASY_GDB
+    SAVEAREA_FROM_FP(%ecx,rFP)          # %ecx<- &StackSaveArea
+    movl        %ecx, offStackSaveArea_prevSave(%edx) # newSaveArea->prevSave<- &outs
+#endif
+    movl        rFP, offStackSaveArea_prevFrame(%edx) # newSaveArea->prevFrame<- rFP
+    movl        rPC_SPILL(%ebp), %ecx
+    movl        %ecx, offStackSaveArea_savedPc(%edx) # newSaveArea->savedPc<- rPC
+    testl       $$ACC_NATIVE, offMethod_accessFlags(%eax) # check for native call
+    movl        %eax, offStackSaveArea_method(%edx) # newSaveArea->method<- method to call
+    jne         .LinvokeNative          # handle native call
+
+   /*
+    * Update "glue" values for the new method
+    * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFp
+    */
+
+    movl        offMethod_clazz(%eax), %edx # %edx<- method->clazz
+    GET_GLUE(%ecx)                      # %ecx<- pMterpGlue
+    movl        offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex
+    movl        %eax, offGlue_method(%ecx) # glue->method<- methodToCall
+    movl        %edx, offGlue_methodClassDex(%ecx) # glue->methodClassDex<- method->clazz->pDvmDex
+    movl        offMethod_insns(%eax), rPC # rPC<- methodToCall->insns
+    movl        offGlue_self(%ecx), %eax # %eax<- glue->self
+    movl        LOCAL1_OFFSET(%ebp), rFP # rFP<- newFP
+    movl        rFP, offThread_curFrame(%eax) # glue->self->curFrame<- newFP
+    FETCH_INST()
+    GOTO_NEXT                           # jump to methodToCall->insns
+
+   /*
+    * Prep for the native call
+    * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFP, %edx=newSaveArea
+    */
+
+.LinvokeNative:
+    GET_GLUE(%ecx)                      # %ecx<- pMterpGlue
+    movl        %eax, OUT_ARG1(%esp)    # push parameter methodToCall
+    movl        offGlue_self(%ecx), %ecx        # %ecx<- glue->self
+    movl        offThread_jniLocal_topCookie(%ecx), %eax # %eax<- self->localRef->...
+    movl        %eax, offStackSaveArea_localRefCookie(%edx) # newSaveArea->localRefCookie<- top
+    movl        %edx, OUT_ARG4(%esp)    # save newSaveArea
+    movl        LOCAL1_OFFSET(%ebp), %edx # %edx<- newFP
+    movl        %edx, offThread_curFrame(%ecx)  # glue->self->curFrame<- newFP
+    movl        %ecx, OUT_ARG3(%esp)    # save glue->self
+    movl        %ecx, OUT_ARG2(%esp)    # push parameter glue->self
+    GET_GLUE(%ecx)                      # %ecx<- pMterpGlue
+    movl        OUT_ARG1(%esp), %eax    # %eax<- methodToCall
+    lea         offGlue_retval(%ecx), %ecx # %ecx<- &retval
+    movl        %ecx, OUT_ARG0(%esp)    # push parameter pMterpGlue
+    push        %edx                    # push parameter newFP
+
+    call        *offMethod_nativeFunc(%eax) # call methodToCall->nativeFunc
+    lea         4(%esp), %esp
+    movl        OUT_ARG4(%esp), %ecx    # %ecx<- newSaveArea
+    movl        OUT_ARG3(%esp), %eax    # %eax<- glue->self
+    movl        offStackSaveArea_localRefCookie(%ecx), %edx # %edx<- old top
+    cmp         $$0, offThread_exception(%eax) # check for exception
+    movl        rFP, offThread_curFrame(%eax) # glue->self->curFrame<- rFP
+    movl        %edx, offThread_jniLocal_topCookie(%eax) # new top <- old top
+    UNSPILL(rPC)
+    jne         common_exceptionThrown  # handle exception
+    FETCH_INST_WORD(3)
+    ADVANCE_PC(3)
+    GOTO_NEXT                           # jump to next instruction
+
+.LstackOverflow:
+    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)
+    UNSPILL(rPC)                        # return: void
+    jmp         common_exceptionThrown  # handle exception
+
+
 /*
  * Common invoke code (old-style).
  * TUNING:  Rewrite along lines of new armv5 code?
@@ -106,6 +312,7 @@
      *      bool dvmCheckSuspendPending(Thread* self)
      *  Because we reached here via a call, go ahead and build a new frame.
      */
+    EXPORT_PC()                         # need for precise GC
     movl    offGlue_self(%ecx),%eax      # eax<- glue->self
     SPILL(rPC)                      # save edx
     push    %ebp
diff --git a/vm/native/InternalNative.c b/vm/native/InternalNative.c
index 2cad260..735cf96 100644
--- a/vm/native/InternalNative.c
+++ b/vm/native/InternalNative.c
@@ -47,6 +47,8 @@
             dvm_java_security_AccessController, 0 },
     { "Ljava/util/concurrent/atomic/AtomicLong;",
             dvm_java_util_concurrent_atomic_AtomicLong, 0 },
+    { "Ldalvik/system/SamplingProfiler;",
+            dvm_dalvik_system_SamplingProfiler, 0 },
     { "Ldalvik/system/VMDebug;",          dvm_dalvik_system_VMDebug, 0 },
     { "Ldalvik/system/DexFile;",          dvm_dalvik_system_DexFile, 0 },
     { "Ldalvik/system/VMRuntime;",        dvm_dalvik_system_VMRuntime, 0 },
diff --git a/vm/native/InternalNativePriv.h b/vm/native/InternalNativePriv.h
index 5e08bf9..abfda6c 100644
--- a/vm/native/InternalNativePriv.h
+++ b/vm/native/InternalNativePriv.h
@@ -103,6 +103,7 @@
 extern const DalvikNativeMethod dvm_java_lang_reflect_Proxy[];
 extern const DalvikNativeMethod dvm_java_security_AccessController[];
 extern const DalvikNativeMethod dvm_java_util_concurrent_atomic_AtomicLong[];
+extern const DalvikNativeMethod dvm_dalvik_system_SamplingProfiler[];
 extern const DalvikNativeMethod dvm_dalvik_system_VMDebug[];
 extern const DalvikNativeMethod dvm_dalvik_system_DexFile[];
 extern const DalvikNativeMethod dvm_dalvik_system_VMRuntime[];
diff --git a/vm/native/SystemThread.c b/vm/native/SystemThread.c
new file mode 100644
index 0000000..bd2be03
--- /dev/null
+++ b/vm/native/SystemThread.c
@@ -0,0 +1,169 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "SystemThread"
+
+/*
+ * System thread support.
+ */
+#include "Dalvik.h"
+#include "native/SystemThread.h"
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+struct SystemThread {
+    /*
+     * /proc/PID/task/TID/stat. -1 if not opened yet. -2 indicates an error
+     * occurred while opening the file.
+     */
+    int statFile;
+
+    /* Offset of state char in stat file, last we checked. */
+    int stateOffset;
+};
+
+void dvmDetachSystemThread(Thread* thread) {
+    if (thread->systemThread != NULL) {
+        if (thread->systemThread->statFile > -1) {
+            close(thread->systemThread->statFile);
+        }
+        free(thread->systemThread);
+        thread->systemThread = NULL;
+    }
+}
+
+/* Converts a Linux thread state to a ThreadStatus. */
+static ThreadStatus stateToStatus(char state) {
+    switch (state) {
+        case 'R': return THREAD_RUNNING;    // running
+        case 'S': return THREAD_WAIT;       // sleeping in interruptible wait
+        case 'D': return THREAD_WAIT;       // uninterruptible disk sleep
+        case 'Z': return THREAD_ZOMBIE;     // zombie
+        case 'T': return THREAD_WAIT;       // traced or stopped on a signal
+        case 'W': return THREAD_WAIT;  // paging memory
+        default:
+            LOGE("Unexpected state: %c", state);
+            return THREAD_NATIVE;
+    }
+}
+
+/* Reads the state char starting from the beginning of the file. */
+static char readStateFromBeginning(SystemThread* thread) {
+    char buffer[256];
+    int size = read(thread->statFile, buffer, sizeof(buffer) - 1);
+    if (size <= 0) {
+        LOGE("read() returned %d: %s", size, strerror(errno));
+        return 0;
+    }
+    char* endOfName = (char*) memchr(buffer, ')', size);
+    if (endOfName == NULL) {
+        LOGE("End of executable name not found.");
+        return 0;
+    }
+    char* state = endOfName + 2;
+    if ((state - buffer) + 1 > size) {
+        LOGE("Unexpected EOF while trying to read stat file.");
+        return 0;
+    }
+    thread->stateOffset = state - buffer;
+    return *state;
+}
+
+/*
+ * Looks for the state char at the last place we found it. Read from the
+ * beginning if necessary.
+ */
+static char readStateRelatively(SystemThread* thread) {
+    char buffer[3];
+    // Position file offset at end of executable name.
+    int result = lseek(thread->statFile, thread->stateOffset - 2, SEEK_SET);
+    if (result < 0) {
+        LOGE("lseek() error.");
+        return 0;
+    }
+    int size = read(thread->statFile, buffer, sizeof(buffer));
+    if (size < (int) sizeof(buffer)) {
+        LOGE("Unexpected EOF while trying to read stat file.");
+        return 0;
+    }
+    if (buffer[0] != ')') {
+        // The executable name must have changed.
+        result = lseek(thread->statFile, 0, SEEK_SET);
+        if (result < 0) {
+            LOGE("lseek() error.");
+            return 0;
+        }
+        return readStateFromBeginning(thread);
+    }
+    return buffer[2];
+}
+
+ThreadStatus dvmGetSystemThreadStatus(Thread* thread) {
+    ThreadStatus status = thread->status;
+    if (status != THREAD_NATIVE) {
+        // Return cached status so we don't accidentally return THREAD_NATIVE.
+        return status;
+    }
+
+    if (thread->systemThread == NULL) {
+        thread->systemThread = (SystemThread*) malloc(sizeof(SystemThread));
+        if (thread->systemThread == NULL) {
+            LOGE("Couldn't allocate a SystemThread.");
+            return THREAD_NATIVE;
+        }
+        thread->systemThread->statFile = -1;
+    }
+
+    SystemThread* systemThread = thread->systemThread;
+    if (systemThread->statFile == -2) {
+        // We tried and failed to open the file earlier. Return current status.
+        return thread->status;
+    }
+
+    // Note: see "man proc" for the format of stat.
+    // The format is "PID (EXECUTABLE NAME) STATE_CHAR ...".
+    // Example: "15 (/foo/bar) R ..."
+    char state;
+    if (systemThread->statFile == -1) {
+        // We haven't tried to open the file yet. Do so.
+        char fileName[256];
+        sprintf(fileName, "/proc/self/task/%d/stat", thread->systemTid);
+        systemThread->statFile = open(fileName, O_RDONLY);
+        if (systemThread->statFile == -1) {
+            LOGE("Error opening %s: %s", fileName, strerror(errno));
+            systemThread->statFile = -2;
+            return thread->status;
+        }
+        state = readStateFromBeginning(systemThread);
+    } else {
+        state = readStateRelatively(systemThread);
+    }
+
+    if (state == 0) {
+        close(systemThread->statFile);
+        systemThread->statFile = -2;
+        return thread->status;
+    }
+    ThreadStatus nativeStatus = stateToStatus(state);
+
+    // The thread status could have changed from NATIVE.
+    status = thread->status;
+    return status == THREAD_NATIVE ? nativeStatus : status;
+}
diff --git a/vm/native/SystemThread.h b/vm/native/SystemThread.h
new file mode 100644
index 0000000..fb41b04
--- /dev/null
+++ b/vm/native/SystemThread.h
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+/*
+ * System thread support.
+ */
+#ifndef _DALVIK_SYSTEM_THREAD
+#define _DALVIK_SYSTEM_THREAD
+
+#include "Thread.h"
+
+/*
+ * Queries the system thread status for the given thread. If the thread is in
+ * native code, this function queries the system thread state and converts it
+ * to an equivalent ThreadStatus. If the system thread state is "paging",
+ * this function returns THREAD_WAIT. If the native status can't be read,
+ * this function returns THREAD_NATIVE. The thread list lock should be held
+ * when calling this function.
+ */
+ThreadStatus dvmGetSystemThreadStatus(Thread* thread);
+
+/*
+ * Frees system thread-specific state in the given thread. The thread list
+ * lock is *not* held when this function is invoked.
+ */
+void dvmDetachSystemThread(Thread* thread);
+
+#endif /*_DALVIK_SYSTEM_THREAD*/
diff --git a/vm/native/dalvik_system_DexFile.c b/vm/native/dalvik_system_DexFile.c
index f4e576c..95e01aa 100644
--- a/vm/native/dalvik_system_DexFile.c
+++ b/vm/native/dalvik_system_DexFile.c
@@ -63,6 +63,8 @@
  * Verify that the "cookie" is a DEX file we opened.
  *
  * Expects that the hash table will be *unlocked* here.
+ *
+ * If the cookie is invalid, we throw an exception and return "false".
  */
 static bool validateCookie(int cookie)
 {
@@ -78,8 +80,11 @@
     void* result = dvmHashTableLookup(gDvm.userDexFiles, hash, pDexOrJar,
                 hashcmpDexOrJar, false);
     dvmHashTableUnlock(gDvm.userDexFiles);
-    if (result == NULL)
+    if (result == NULL) {
+        dvmThrowException("Ljava/lang/RuntimeException;",
+            "invalid DexFile cookie");
         return false;
+    }
 
     return true;
 }
@@ -213,7 +218,7 @@
     LOGV("Closing DEX file %p (%s)\n", pDexOrJar, pDexOrJar->fileName);
 
     if (!validateCookie(cookie))
-        dvmAbort();
+        RETURN_VOID();
 
     /*
      * We can't just free arbitrary DEX files because they have bits and
@@ -249,6 +254,8 @@
  * creation of a specific class.  The difference is that the search for and
  * reading of the bytes is done within the VM.
  *
+ * The class name is a "binary name", e.g. "java.lang.String".
+ *
  * Returns a null pointer with no exception if the class was not found.
  * Throws an exception on other failures.
  */
@@ -266,12 +273,12 @@
     char* descriptor;
 
     name = dvmCreateCstrFromString(nameObj);
-    descriptor = dvmNameToDescriptor(name);
-    LOGV("--- Explicit class load '%s' 0x%08x\n", name, cookie);
+    descriptor = dvmDotToDescriptor(name);
+    LOGV("--- Explicit class load '%s' 0x%08x\n", descriptor, cookie);
     free(name);
 
     if (!validateCookie(cookie))
-        dvmAbort();
+        RETURN_VOID();
 
     if (pDexOrJar->isDex)
         pDvmDex = dvmGetRawDexFileDex(pDexOrJar->pRawDexFile);
@@ -331,7 +338,7 @@
     ArrayObject* stringArray;
 
     if (!validateCookie(cookie))
-        dvmAbort();
+        RETURN_VOID();
 
     if (pDexOrJar->isDex)
         pDvmDex = dvmGetRawDexFileDex(pDexOrJar->pRawDexFile);
diff --git a/vm/native/dalvik_system_SamplingProfiler.c b/vm/native/dalvik_system_SamplingProfiler.c
new file mode 100644
index 0000000..5642bde
--- /dev/null
+++ b/vm/native/dalvik_system_SamplingProfiler.c
@@ -0,0 +1,647 @@
+/*
+ * 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.
+ */
+
+/**
+ * Native support for dalvik.system.SamplingProfiler
+ */
+
+#define LOG_TAG "SamplingProfiler"
+
+#include <cutils/log.h>
+
+#include "Dalvik.h"
+#include "native/InternalNativePriv.h"
+#include "native/SystemThread.h"
+
+// ~20k
+#define INITIAL_CAPACITY 1024
+
+// ~80k
+#define MAX_CAPACITY 4096
+
+typedef enum {
+    /** The "event thread". */
+    EVENT_THREAD,
+    /** Not the "event thread". */
+    OTHER_THREAD
+} ThreadType;
+
+#define THREAD_TYPE_SIZE (OTHER_THREAD + 1)
+
+typedef enum {
+    /** Executing bytecode. */
+    RUNNING_THREAD,
+    /** Waiting on a lock or VM resource. */
+    SUSPENDED_THREAD
+} ThreadState;
+
+#define THREAD_STATE_SIZE (SUSPENDED_THREAD + 1)
+
+typedef enum {
+    /** This method is in the call stack. */
+    CALLING_METHOD,
+    /** VM is in this method. */
+    LEAF_METHOD
+} MethodState;
+
+#define METHOD_STATE_SIZE (LEAF_METHOD + 1)
+
+/** SampleSet entry. */
+typedef struct {
+    /** Entry key. */
+    const Method* method; // 4 bytes
+    /** Sample counts for method divided by thread type and state. */
+    u2 counts[THREAD_TYPE_SIZE][THREAD_STATE_SIZE][METHOD_STATE_SIZE]; // 16B
+} MethodCount;
+
+/**
+ * Set of MethodCount entries.
+ *
+ * Note: If we ever support class unloading, we'll need to make this a GC root
+ * so the methods don't get reclaimed.
+ */
+typedef struct {
+    /** Hash collisions. */
+    int collisions;
+    /** Number of entries in set. */
+    int size;
+    /** Number of slots. */
+    int capacity;
+    /** Maximum number of entries this set can hold. 3/4 capacity. */
+    int maxSize;
+    /** Used to convert a hash to an entry index. */
+    int mask;
+    /** Entry table. */
+    MethodCount* entries;
+    /** The event thread. */
+    Thread* eventThread;
+} SampleSet;
+
+/**
+ * Initializes an empty set with the given capacity (which must be a power of
+ * two). Allocates memory for the entry array which must be freed.
+ */
+static SampleSet newSampleSet(int capacity) {
+    SampleSet set;
+    set.collisions = 0;
+    set.size = 0;
+    set.capacity = capacity;
+    set.maxSize = (capacity >> 2) * 3; // 3/4 capacity
+    set.mask = capacity - 1;
+    set.entries = (MethodCount*) calloc(sizeof(MethodCount), capacity);
+    set.eventThread = NULL;
+    return set;
+}
+
+/** Hashes the given pointer. */
+static u4 hash(const void* p) {
+    u4 h = (u4) p;
+
+    // This function treats its argument as seed for a Marsaglia
+    // xorshift random number generator, and produces the next
+    // value. The particular xorshift parameters used here tend to
+    // spread bits downward, to better cope with keys that differ
+    // only in upper bits, which otherwise excessively collide in
+    // small tables.
+    h ^= h >> 11;
+    h ^= h << 7;
+    return h ^ (h >> 16);
+}
+
+/** Doubles capacity of SampleSet. */
+static void expand(SampleSet* oldSet) {
+    // TODO: Handle newSet.entries == NULL
+    SampleSet newSet = newSampleSet(oldSet->capacity << 1);
+    LOGI("Expanding sample set capacity to %d.", newSet.capacity);
+    int oldIndex;
+    MethodCount* oldEntries = oldSet->entries;
+    for (oldIndex = 0; oldIndex < oldSet->size; oldIndex++) {
+        MethodCount oldEntry = oldEntries[oldIndex];
+        if (oldEntry.method != NULL) {
+            // Find the first empty slot.
+            int start = hash(oldEntry.method) & newSet.mask;
+            int i = start;
+            while (newSet.entries[i].method != NULL) {
+                i = (i + 1) & newSet.mask;
+            }
+
+            // Copy the entry into the empty slot.
+            newSet.entries[i] = oldEntry;
+            newSet.collisions += (i != start);
+        }
+    }
+    free(oldEntries);
+    newSet.size = oldSet->size;
+    newSet.eventThread = oldSet->eventThread;
+    *oldSet = newSet;
+}
+
+/** Increments counter for method in set. */
+static void countMethod(SampleSet* set, const Method* method,
+        ThreadType threadType, ThreadState threadState,
+        MethodState methodState) {
+    MethodCount* entries = set->entries;
+    int start = hash(method) & set->mask;
+    int i;
+    for (i = start;; i = (i + 1) & set->mask) {
+        MethodCount* entry = &entries[i];
+
+        if (entry->method == method) {
+            // We found an existing entry.
+            entry->counts[threadType][threadState][methodState]++;
+            return;
+        }
+
+        if (entry->method == NULL) {
+            // Add a new entry.
+            if (set->size < set->maxSize) {
+                entry->method = method;
+                entry->counts[threadType][threadState][methodState] = 1;
+                set->collisions += (i != start);
+                set->size++;
+            } else {
+                if (set->capacity < MAX_CAPACITY) {
+                    // The set is 3/4 full. Expand it, and then add the entry.
+                    expand(set);
+                    countMethod(set, method, threadType, threadState,
+                            methodState);
+                } else {
+                    // Don't add any more entries.
+                    // TODO: Should we replace the LRU entry?
+                }
+            }
+            return;
+        }
+    }
+}
+
+/** Clears all entries from sample set. */
+static void clearSampleSet(SampleSet* set) {
+    set->collisions = 0;
+    set->size = 0;
+    memset(set->entries, 0, set->capacity * sizeof(MethodCount));
+}
+
+/**
+ * Collects a sample from a single, possibly running thread.
+ */
+static void sample(SampleSet* set, Thread* thread) {
+    ThreadType threadType = thread == set->eventThread
+        ? EVENT_THREAD : OTHER_THREAD;
+
+    ThreadState threadState;
+    switch (dvmGetSystemThreadStatus(thread)) {
+        case THREAD_RUNNING: threadState = RUNNING_THREAD; break;
+        case THREAD_NATIVE: return; // Something went wrong. Skip this thread.
+        default: threadState = SUSPENDED_THREAD; // includes PAGING
+    }
+
+    /*
+     * This code reads the stack concurrently, so it needs to defend against
+     * garbage data that will certainly result from the stack changing out
+     * from under us.
+     */
+
+    // Top of the stack.
+    void* stackTop = thread->interpStackStart;
+
+    void* currentFrame = thread->curFrame;
+    if (currentFrame == NULL) {
+        return;
+    }
+
+    MethodState methodState = LEAF_METHOD;
+    while (true) {
+        StackSaveArea* saveArea = SAVEAREA_FROM_FP(currentFrame);
+
+        const Method* method = saveArea->method;
+        // Count the method now. We'll validate later that it's a real Method*.
+        if (method != NULL) {
+            countMethod(set, method, threadType, threadState, methodState);
+            methodState = CALLING_METHOD;
+        }
+
+        void* callerFrame = saveArea->prevFrame;
+        if (callerFrame == NULL // No more callers.
+                || callerFrame > stackTop // Stack underflow!
+                || callerFrame < currentFrame // Wrong way!
+            ) {
+            break;
+        }
+
+        currentFrame = callerFrame;
+    }
+}
+
+/**
+ * Collects samples.
+ */
+static void Dalvik_dalvik_system_SamplingProfiler_sample(const u4* args,
+        JValue* pResult) {
+    SampleSet* set = (SampleSet*) args[0];
+    dvmLockThreadList(dvmThreadSelf());
+    Thread* thread = gDvm.threadList;
+    int sampledThreads = 0;
+    Thread* self = dvmThreadSelf();
+    while (thread != NULL) {
+        if (thread != self) {
+            sample(set, thread);
+            sampledThreads++;
+        }
+        thread = thread->next;
+    }
+    dvmUnlockThreadList();
+    RETURN_INT(sampledThreads);
+}
+
+/**
+ * Gets the number of methods in the sample set.
+ */
+static void Dalvik_dalvik_system_SamplingProfiler_size(const u4* args,
+        JValue* pResult) {
+    SampleSet* set = (SampleSet*) args[0];
+    RETURN_INT(set->size);
+}
+
+/**
+ * Gets the number of collisions in the sample set.
+ */
+static void Dalvik_dalvik_system_SamplingProfiler_collisions(const u4* args,
+        JValue* pResult) {
+    SampleSet* set = (SampleSet*) args[0];
+    RETURN_INT(set->collisions);
+}
+
+/**
+ * Returns true if the method is in the given table.
+ */
+static bool inTable(const Method* method, const Method* table,
+        int tableLength) {
+    if (tableLength < 1) {
+        return false;
+    }
+
+    const Method* last = table + (tableLength - 1);
+
+    // Cast to char* to handle misaligned pointers.
+    return (char*) method >= (char*) table
+        && (char*) method <= (char*) last;
+}
+
+/** Entry in a hash of method counts by class. */
+typedef struct mcw {
+    /** Decorated method count. */
+    MethodCount* methodCount;
+
+    /** Shortcut to methodCount->method->clazz. */
+    ClassObject* clazz;
+    /** Pointer to class name that enables us to chop off the first char. */
+    const char* className;
+    /** Cached string lengths. */
+    u2 classNameLength;
+    u2 methodNameLength;
+
+    /** Next method in the same class. */
+    struct mcw* next;
+} MethodCountWrapper;
+
+/** Returns true if we can trim the first and last chars in the class name. */
+static bool isNormalClassName(const char* clazzName, int length) {
+    return (length >= 2) && (clazzName[0] == 'L')
+        && (clazzName[length - 1] == ';');
+}
+
+/**
+ * Heurtistically guesses whether or not 'method' actually points to a Method
+ * struct.
+ */
+static bool isValidMethod(const Method* method) {
+    if (!dvmLinearAllocContains(method, sizeof(Method))) {
+        LOGW("Method* is not in linear allocation table.");
+        return false;
+    }
+    ClassObject* clazz = method->clazz;
+    if (!dvmIsValidObject((Object*) clazz)) {
+        LOGW("method->clazz doesn't point to an object at all.");
+        return false;
+    }
+    if (clazz->obj.clazz != gDvm.classJavaLangClass) {
+        LOGW("method->clazz doesn't point to a ClassObject.");
+        return false;
+    }
+
+    // No need to validate the tables because we don't actually read them.
+    if (!inTable(method, clazz->directMethods, clazz->directMethodCount)
+            && !inTable(method, clazz->virtualMethods,
+                    clazz->virtualMethodCount)) {
+        LOGW("Method not found in associated ClassObject.");
+        return false;
+    }
+
+    // We're pretty sure at this point that we're looking at a real Method*.
+    // The only alternative is that 'method' points to the middle of a Method
+    // struct and whatever ->clazz resolves to relative to that random
+    // address happens to point to the right ClassObject*. We could mod
+    // the address to ensure that the Method* is aligned as expected, but it's
+    // probably not worth the overhead.
+    return true;
+}
+
+/** Converts slashes to dots in the given class name. */
+static void slashesToDots(char* s, int length) {
+    int i;
+    for (i = 0; i < length; i++) {
+        if (s[i] == '/') {
+            s[i] = '.';
+        }
+    }
+}
+
+/**
+ * Compares class pointers from two method count wrappers. Used in the by-class
+ * hash table.
+ */
+static int compareMethodCountClasses(const void* tableItem,
+        const void* looseItem) {
+    const MethodCountWrapper* a = (MethodCountWrapper*) tableItem;
+    const MethodCountWrapper* b = (MethodCountWrapper*) looseItem;
+    u4 serialA = a->clazz->serialNumber;
+    u4 serialB = b->clazz->serialNumber;
+    return serialA == serialB ? 0 : (serialA < serialB ? -1 : 1);
+}
+
+/**
+ * Calculates amount of memory needed for the given class in the final
+ * snapshot and adds the result to arg.
+ */
+static int calculateSnapshotEntrySize(void* data, void* arg) {
+    MethodCountWrapper* wrapper = (MethodCountWrapper*) data;
+
+    const char* className = wrapper->clazz->descriptor;
+    wrapper->classNameLength = strlen(className);
+    if (isNormalClassName(className, wrapper->classNameLength)) {
+        // Trim first & last chars.
+        wrapper->className = className + 1;
+        wrapper->classNameLength -= 2;
+    } else {
+        wrapper->className = className;
+    }
+
+    // Size of this class entry.
+    int size = 2; // class name size
+    size += wrapper->classNameLength;
+    size += 2; // number of methods in this class
+    do {
+        wrapper->methodNameLength
+                = strlen(wrapper->methodCount->method->name);
+
+        size += 2; // method name size
+        size += wrapper->methodNameLength;
+        // sample counts
+        size += THREAD_TYPE_SIZE * THREAD_STATE_SIZE * METHOD_STATE_SIZE * 2;
+        wrapper = wrapper->next;
+    } while (wrapper != NULL);
+
+    int* total = (int*) arg;
+    *total += size;
+
+    return 0;
+}
+
+/** Writes 2 bytes and increments dest pointer. */
+#define writeShort(dest, value)     \
+do {                                \
+    u2 _value = (value);            \
+    *dest++ = (char) (_value >> 8); \
+    *dest++ = (char) _value;        \
+} while (0);
+
+/** Writes length in 2 bytes and then string, increments dest. */
+#define writeString(dest, s, length)    \
+do {                                    \
+    u2 _length = (length);              \
+    writeShort(dest, _length);          \
+    memcpy(dest, s, _length);           \
+    dest += _length;                    \
+} while (0);
+
+/**
+ * Writes the entry data and advances the pointer (in arg).
+ */
+static int writeSnapshotEntry(void* data, void* arg) {
+    MethodCountWrapper* wrapper = (MethodCountWrapper*) data;
+
+    // We'll copy offset back into offsetPointer at the end.
+    char** offsetPointer = (char**) arg;
+    char* offset = *offsetPointer;
+
+    // Class name.
+    writeString(offset, wrapper->className, wrapper->classNameLength);
+    slashesToDots(offset - wrapper->classNameLength, wrapper->classNameLength);
+
+    // Method count.
+    char* methodCountPointer = offset;
+    u2 methodCount = 0;
+    offset += 2;
+
+    // Method entries.
+    do {
+        // Method name.
+        writeString(offset, wrapper->methodCount->method->name,
+                wrapper->methodNameLength);
+
+        // Sample counts.
+        u2 (*counts)[THREAD_STATE_SIZE][METHOD_STATE_SIZE]
+                = wrapper->methodCount->counts;
+        int type, threadState, methodState;
+        for (type = 0; type < THREAD_TYPE_SIZE; type++)
+            for (threadState = 0; threadState < THREAD_STATE_SIZE;
+                    threadState++)
+                for (methodState = 0; methodState < METHOD_STATE_SIZE;
+                        methodState++)
+                    writeShort(offset, counts[type][threadState][methodState]);
+
+        methodCount++;
+        wrapper = wrapper->next;
+    } while (wrapper != NULL);
+
+    // Go back and write method count.
+    writeShort(methodCountPointer, methodCount);
+
+    // Increment original pointer.
+    *offsetPointer = offset;
+    return 0;
+}
+
+/**
+ * Captures the collected samples and clears the sample set.
+ */
+static void Dalvik_dalvik_system_SamplingProfiler_snapshot(const u4* args,
+        JValue* pResult) {
+    /*
+     * Format:
+     *   version # (2 bytes)
+     *   # of class entries (2 bytes)
+     *   ClassEntry...
+     *
+     * ClassEntry:
+     *   class name length (2 bytes)
+     *   UTF-8 class name
+     *   # of method entries (2 bytes)
+     *   MethodEntry...
+     *
+     *  MethodEntry:
+     *    method name length (2 bytes)
+     *    UTF-8 method name
+     *    CountsByThreadState (for event thread)
+     *    CountsByThreadState (for other threads)
+     *
+     *  CountsByThreadState:
+     *    CountsByMethodState (for running threads)
+     *    CountsByMethodState (for suspended threads)
+     *
+     *  CountsByMethodState:
+     *    as calling method (2 bytes)
+     *    as leaf method (2 bytes)
+     */
+
+    SampleSet* set = (SampleSet*) args[0];
+    if (set->size == 0) {
+        // No data has been captured.
+        RETURN_PTR(NULL);
+    }
+
+    MethodCountWrapper* wrappers = (MethodCountWrapper*) calloc(set->size,
+            sizeof(MethodCountWrapper));
+    if (wrappers == NULL) {
+        LOGW("Out of memory.");
+        RETURN_PTR(NULL);
+    }
+
+    // Method count wrappers by class.
+    HashTable* byClass = dvmHashTableCreate(set->size, NULL);
+    if (byClass == NULL) {
+        free(wrappers);
+        LOGW("Out of memory.");
+        RETURN_PTR(NULL);
+    }
+
+    // Validate method pointers and index by class.
+    int setIndex;
+    int wrapperIndex;
+    for (setIndex = set->capacity - 1, wrapperIndex = 0;
+            setIndex >= 0 && wrapperIndex < set->size;
+            setIndex--) {
+        MethodCount* mc = &set->entries[setIndex];
+        const Method* method = mc->method;
+        if (method != NULL && isValidMethod(method)) {
+            MethodCountWrapper* wrapper = &wrappers[wrapperIndex];
+            wrapper->methodCount = mc;
+            wrapper->clazz = mc->method->clazz;
+            u4 h = hash(wrapper->clazz);
+            MethodCountWrapper* fromTable = dvmHashTableLookup(byClass, h,
+                    wrapper, compareMethodCountClasses, true);
+            if (fromTable != wrapper) {
+                // We already have an entry for this class. Link the new entry.
+                wrapper->next = fromTable->next;
+                fromTable->next = wrapper;
+            }
+            wrapperIndex++;
+        }
+    }
+
+    // Calculate size of snapshot in bytes.
+    int totalSize = 4; // version, # of classes
+    dvmHashForeach(byClass, calculateSnapshotEntrySize, &totalSize);
+
+    // Write snapshot.
+    ArrayObject* snapshot
+            = dvmAllocPrimitiveArray('B', totalSize, ALLOC_DEFAULT);
+    if (snapshot == NULL) {
+        // Not enough memory to hold snapshot.
+        // TODO: Still clear the set or leave it to try again later?
+        LOGW("Out of memory.");
+        free(wrappers);
+        dvmHashTableFree(byClass);
+        RETURN_PTR(NULL);
+    }
+
+    char* offset = (char*) snapshot->contents;
+    writeShort(offset, 1); // version
+    writeShort(offset, dvmHashTableNumEntries(byClass)); // class count
+    dvmHashForeach(byClass, writeSnapshotEntry, &offset);
+
+    // Verify that our size calculation was correct.
+    int actualSize = offset - (char*) snapshot->contents;
+    if (actualSize != totalSize) {
+        LOGE("expected: %d, actual: %d", totalSize, actualSize);
+        abort();
+    }
+
+    dvmHashTableFree(byClass);
+    free(wrappers);
+
+    clearSampleSet(set);
+
+    dvmReleaseTrackedAlloc((Object*) snapshot, NULL);
+    RETURN_PTR(snapshot);
+}
+
+/**
+ * Allocates native memory.
+ */
+static void Dalvik_dalvik_system_SamplingProfiler_allocate(const u4* args,
+        JValue* pResult) {
+    SampleSet* set = (SampleSet*) malloc(sizeof(SampleSet));
+    *set = newSampleSet(INITIAL_CAPACITY);
+    RETURN_INT((jint) set);
+}
+
+/**
+ * Frees native memory.
+ */
+static void Dalvik_dalvik_system_SamplingProfiler_free(const u4* args,
+        JValue* pResult) {
+    SampleSet* set = (SampleSet*) args[0];
+    free(set->entries);
+    free(set);
+    RETURN_VOID();
+}
+
+/**
+ * Identifies the event thread.
+ */
+static void Dalvik_dalvik_system_SamplingProfiler_setEventThread(const u4* args,
+        JValue* pResult) {
+    SampleSet* set = (SampleSet*) args[0];
+    Object* eventThread = (Object*) args[1];  // java.lang.Thread
+    Object* vmThread = dvmGetFieldObject(eventThread,
+            gDvm.offJavaLangThread_vmThread); // java.lang.VMThread
+    set->eventThread = dvmGetThreadFromThreadObject(vmThread);
+    RETURN_VOID();
+}
+
+const DalvikNativeMethod dvm_dalvik_system_SamplingProfiler[] = {
+    { "collisions", "(I)I", Dalvik_dalvik_system_SamplingProfiler_collisions },
+    { "size", "(I)I", Dalvik_dalvik_system_SamplingProfiler_size },
+    { "sample", "(I)I", Dalvik_dalvik_system_SamplingProfiler_sample },
+    { "snapshot", "(I)[B", Dalvik_dalvik_system_SamplingProfiler_snapshot },
+    { "free", "(I)V", Dalvik_dalvik_system_SamplingProfiler_free },
+    { "allocate", "()I", Dalvik_dalvik_system_SamplingProfiler_allocate },
+    { "setEventThread", "(ILjava/lang/Thread;)V",
+            Dalvik_dalvik_system_SamplingProfiler_setEventThread },
+    { NULL, NULL, NULL },
+};
diff --git a/vm/native/dalvik_system_VMDebug.c b/vm/native/dalvik_system_VMDebug.c
index bf7ce61..8aa371d 100644
--- a/vm/native/dalvik_system_VMDebug.c
+++ b/vm/native/dalvik_system_VMDebug.c
@@ -586,13 +586,143 @@
     RETURN_VOID();
 }
 
+/*
+ * static boolean cacheRegisterMap(String classAndMethodDescr)
+ *
+ * If the specified class is loaded, and the named method exists, ensure
+ * that the method's register map is ready for use.  If the class/method
+ * cannot be found, nothing happens.
+ *
+ * This can improve the zygote's sharing of compressed register maps.  Do
+ * this after class preloading.
+ *
+ * Returns true if the register map is cached and ready, either as a result
+ * of this call or earlier activity.  Returns false if the class isn't loaded,
+ * if the method couldn't be found, or if the method has no register map.
+ *
+ * (Uncomment logs in dvmGetExpandedRegisterMap0() to gather stats.)
+ */
+static void Dalvik_dalvik_system_VMDebug_cacheRegisterMap(const u4* args,
+    JValue* pResult)
+{
+    StringObject* classAndMethodDescStr = (StringObject*) args[0];
+    ClassObject* clazz;
+    bool result = false;
+
+    if (classAndMethodDescStr == NULL) {
+        dvmThrowException("Ljava/lang/NullPointerException;", NULL);
+        RETURN_VOID();
+    }
+
+    char* classAndMethodDesc = NULL;
+
+    /*
+     * Pick the string apart.  We have a local copy, so just modify it
+     * in place.
+     */
+    classAndMethodDesc = dvmCreateCstrFromString(classAndMethodDescStr);
+
+    char* methodName = strchr(classAndMethodDesc, '.');
+    if (methodName == NULL) {
+        dvmThrowException("Ljava/lang/RuntimeException;",
+            "method name not found in string");
+        RETURN_VOID();
+    }
+    *methodName++ = '\0';
+
+    char* methodDescr = strchr(methodName, ':');
+    if (methodDescr == NULL) {
+        dvmThrowException("Ljava/lang/RuntimeException;",
+            "method descriptor not found in string");
+        RETURN_VOID();
+    }
+    *methodDescr++ = '\0';
+
+    //LOGD("GOT: %s %s %s\n", classAndMethodDesc, methodName, methodDescr);
+
+    /*
+     * Find the class, but only if it's already loaded.
+     */
+    clazz = dvmLookupClass(classAndMethodDesc, NULL, false);
+    if (clazz == NULL) {
+        LOGD("Class %s not found in bootstrap loader\n", classAndMethodDesc);
+        goto bail;
+    }
+
+    Method* method;
+
+    /*
+     * Find the method, which could be virtual or direct, defined directly
+     * or inherited.
+     */
+    if (methodName[0] == '<') {
+        /*
+         * Constructor or class initializer.  Only need to examine the
+         * "direct" list, and don't need to search up the class hierarchy.
+         */
+        method = dvmFindDirectMethodByDescriptor(clazz, methodName,
+                    methodDescr);
+    } else {
+        /*
+         * Try both lists, and scan up the tree.
+         */
+        method = dvmFindVirtualMethodHierByDescriptor(clazz, methodName,
+                    methodDescr);
+        if (method == NULL) {
+            method = dvmFindDirectMethodHierByDescriptor(clazz, methodName,
+                        methodDescr);
+        }
+    }
+
+    if (method != NULL) {
+        /*
+         * Got it.  See if there's a register map here.
+         */
+        const RegisterMap* pMap;
+        pMap = dvmGetExpandedRegisterMap(method);
+        if (pMap == NULL) {
+            LOGV("No map for %s.%s %s\n",
+                classAndMethodDesc, methodName, methodDescr);
+        } else {
+            LOGV("Found map %s.%s %s\n",
+                classAndMethodDesc, methodName, methodDescr);
+            result = true;
+        }
+    } else {
+        LOGV("Unable to find %s.%s %s\n",
+            classAndMethodDesc, methodName, methodDescr);
+    }
+
+bail:
+    free(classAndMethodDesc);
+    RETURN_BOOLEAN(result);
+}
+
+/*
+ * static void crash()
+ *
+ * Dump the current thread's interpreted stack and abort the VM.  Useful
+ * for seeing both interpreted and native stack traces.
+ *
+ * (Might want to restrict this to debuggable processes as a security
+ * measure, or check SecurityManager.checkExit().)
+ */
+static void Dalvik_dalvik_system_VMDebug_crash(const u4* args,
+    JValue* pResult)
+{
+    UNUSED_PARAMETER(args);
+    UNUSED_PARAMETER(pResult);
+
+    LOGW("Crashing VM on request\n");
+    dvmDumpThread(dvmThreadSelf(), false);
+    dvmAbort();
+}
+
 const DalvikNativeMethod dvm_dalvik_system_VMDebug[] = {
     { "getAllocCount",              "(I)I",
         Dalvik_dalvik_system_VMDebug_getAllocCount },
     { "resetAllocCount",            "(I)V",
         Dalvik_dalvik_system_VMDebug_resetAllocCount },
-    //{ "print",              "(Ljava/lang/String;)V",
-    //    Dalvik_dalvik_system_VMDebug_print },
     { "startAllocCounting",         "()V",
         Dalvik_dalvik_system_VMDebug_startAllocCounting },
     { "stopAllocCounting",          "()V",
@@ -633,6 +763,10 @@
         Dalvik_dalvik_system_VMDebug_threadCpuTimeNanos },
     { "dumpHprofData",              "(Ljava/lang/String;)V",
         Dalvik_dalvik_system_VMDebug_dumpHprofData },
+    { "cacheRegisterMap",           "(Ljava/lang/String;)Z",
+        Dalvik_dalvik_system_VMDebug_cacheRegisterMap },
+    { "crash",                      "()V",
+        Dalvik_dalvik_system_VMDebug_crash },
     { NULL, NULL, NULL },
 };
 
diff --git a/vm/native/dalvik_system_VMStack.c b/vm/native/dalvik_system_VMStack.c
index cb771dc..d62fea9 100644
--- a/vm/native/dalvik_system_VMStack.c
+++ b/vm/native/dalvik_system_VMStack.c
@@ -56,6 +56,21 @@
 }
 
 /*
+ * public static Class<?> getStackClass2()
+ *
+ * Returns the class of the caller's caller's caller.
+ */
+static void Dalvik_dalvik_system_VMStack_getStackClass2(const u4* args,
+    JValue* pResult)
+{
+    ClassObject* clazz = dvmGetCaller3Class(dvmThreadSelf()->curFrame);
+
+    UNUSED_PARAMETER(args);
+
+    RETURN_PTR(clazz);
+}
+
+/*
  * public static Class<?>[] getClasses(int maxDepth, boolean stopAtPrivileged)
  *
  * Create an array of classes for the methods on the stack, skipping the
@@ -212,6 +227,8 @@
         Dalvik_dalvik_system_VMStack_getCallingClassLoader },
     { "getCallingClassLoader2", "()Ljava/lang/ClassLoader;",
         Dalvik_dalvik_system_VMStack_getCallingClassLoader2 },
+    { "getStackClass2", "()Ljava/lang/Class;",
+        Dalvik_dalvik_system_VMStack_getStackClass2 },
     { "getClasses",             "(IZ)[Ljava/lang/Class;",
         Dalvik_dalvik_system_VMStack_getClasses },
     { "getThreadStackTrace",    "(Ljava/lang/Thread;)[Ljava/lang/StackTraceElement;",
diff --git a/vm/oo/Class.c b/vm/oo/Class.c
index 00f5683..1bde718 100644
--- a/vm/oo/Class.c
+++ b/vm/oo/Class.c
@@ -271,6 +271,12 @@
     char* str = dvmLinearStrdup(NULL, "This is a test!");
     LOGI("GOT: '%s'\n", str);
 
+    /* try to check the bounds; allocator may round allocation size up */
+    fiddle = dvmLinearAlloc(NULL, 12);
+    LOGI("Should be 1: %d\n", dvmLinearAllocContains(fiddle, 12));
+    LOGI("Should be 0: %d\n", dvmLinearAllocContains(fiddle, 13));
+    LOGI("Should be 0: %d\n", dvmLinearAllocContains(fiddle - 128*1024, 1));
+
     dvmLinearAllocDump(NULL);
     dvmLinearFree(NULL, str);
 }
@@ -478,7 +484,7 @@
 
     cc = stat(cpe->fileName, &sb);
     if (cc < 0) {
-        LOGW("Unable to stat classpath element '%s'\n", cpe->fileName);
+        LOGD("Unable to stat classpath element '%s'\n", cpe->fileName);
         return false;
     }
     if (S_ISDIR(sb.st_mode)) {
@@ -510,6 +516,7 @@
         return true;
     }
 
+    LOGD("Unable to process classpath element '%s'\n", cpe->fileName);
     return false;
 }
 
@@ -517,13 +524,13 @@
  * Convert a colon-separated list of directories, Zip files, and DEX files
  * into an array of ClassPathEntry structs.
  *
- * If we're unable to load a bootstrap class path entry, we fail.  This
- * is necessary to preserve the dependencies implied by optimized DEX files
- * (e.g. if the same class appears in multiple places).
- *
  * During normal startup we fail if there are no entries, because we won't
  * get very far without the basic language support classes, but if we're
  * optimizing a DEX file we allow it.
+ *
+ * If entries are added or removed from the bootstrap class path, the
+ * dependencies in the DEX files will break, and everything except the
+ * very first entry will need to be regenerated.
  */
 static ClassPathEntry* processClassPath(const char* pathStr, bool isBootstrap)
 {
@@ -583,16 +590,8 @@
             cpe[idx].ptr = NULL;
 
             if (!prepareCpe(&tmp, isBootstrap)) {
-                LOGD("Failed on '%s' (boot=%d)\n", tmp.fileName, isBootstrap);
                 /* drop from list and continue on */
                 free(tmp.fileName);
-
-                if (isBootstrap || gDvm.optimizing) {
-                    /* if boot path entry or we're optimizing, this is fatal */
-                    free(cpe);
-                    cpe = NULL;
-                    goto bail;
-                }
             } else {
                 /* copy over, pointers and all */
                 if (tmp.fileName[0] != '/')
@@ -1421,8 +1420,14 @@
         }
 
         if (pDvmDex == NULL || pClassDef == NULL) {
-            dvmThrowExceptionWithClassMessage(
-                "Ljava/lang/NoClassDefFoundError;", descriptor);
+            if (gDvm.noClassDefFoundErrorObj != NULL) {
+                /* usual case -- use prefabricated object */
+                dvmSetException(self, gDvm.noClassDefFoundErrorObj);
+            } else {
+                /* dexopt case -- can't guarantee prefab (core.jar) */
+                dvmThrowExceptionWithClassMessage(
+                    "Ljava/lang/NoClassDefFoundError;", descriptor);
+            }
             goto bail;
         }
 
@@ -1760,7 +1765,39 @@
         dvmLinearReadOnly(classLoader, newClass->ifields);
     }
 
-    /* load method definitions */
+    /*
+     * Load method definitions.  We do this in two batches, direct then
+     * virtual.
+     *
+     * If register maps have already been generated for this class, and
+     * precise GC is enabled, we pull out pointers to them.  We know that
+     * they were streamed to the DEX file in the same order in which the
+     * methods appear.
+     *
+     * If the class wasn't pre-verified, the maps will be generated when
+     * the class is verified during class initialization.
+     */
+    u4 classDefIdx = dexGetIndexForClassDef(pDexFile, pClassDef);
+    const void* classMapData;
+    u4 numMethods;
+
+    if (gDvm.preciseGc) {
+        classMapData =
+            dvmRegisterMapGetClassData(pDexFile, classDefIdx, &numMethods);
+
+        /* sanity check */
+        if (classMapData != NULL &&
+            pHeader->directMethodsSize + pHeader->virtualMethodsSize != numMethods)
+        {
+            LOGE("ERROR: in %s, direct=%d virtual=%d, maps have %d\n",
+                newClass->descriptor, pHeader->directMethodsSize,
+                pHeader->virtualMethodsSize, numMethods);
+            assert(false);
+            classMapData = NULL;        /* abandon */
+        }
+    } else {
+        classMapData = NULL;
+    }
 
     if (pHeader->directMethodsSize != 0) {
         int count = (int) pHeader->directMethodsSize;
@@ -1773,6 +1810,15 @@
         for (i = 0; i < count; i++) {
             dexReadClassDataMethod(&pEncodedData, &method, &lastIndex);
             loadMethodFromDex(newClass, &method, &newClass->directMethods[i]);
+            if (classMapData != NULL) {
+                const RegisterMap* pMap = dvmRegisterMapGetNext(&classMapData);
+                if (dvmRegisterMapGetFormat(pMap) != kRegMapFormatNone) {
+                    newClass->directMethods[i].registerMap = pMap;
+                    /* TODO: add rigorous checks */
+                    assert((newClass->directMethods[i].registersSize+7) / 8 ==
+                        newClass->directMethods[i].registerMap->regWidth);
+                }
+            }
         }
         dvmLinearReadOnly(classLoader, newClass->directMethods);
     }
@@ -1788,6 +1834,15 @@
         for (i = 0; i < count; i++) {
             dexReadClassDataMethod(&pEncodedData, &method, &lastIndex);
             loadMethodFromDex(newClass, &method, &newClass->virtualMethods[i]);
+            if (classMapData != NULL) {
+                const RegisterMap* pMap = dvmRegisterMapGetNext(&classMapData);
+                if (dvmRegisterMapGetFormat(pMap) != kRegMapFormatNone) {
+                    newClass->virtualMethods[i].registerMap = pMap;
+                    /* TODO: add rigorous checks */
+                    assert((newClass->virtualMethods[i].registersSize+7) / 8 ==
+                        newClass->virtualMethods[i].registerMap->regWidth);
+                }
+            }
         }
         dvmLinearReadOnly(classLoader, newClass->virtualMethods);
     }
@@ -1912,9 +1967,11 @@
         int directMethodCount = clazz->directMethodCount;
         clazz->directMethods = NULL;
         clazz->directMethodCount = -1;
+        dvmLinearReadWrite(clazz->classLoader, directMethods);
         for (i = 0; i < directMethodCount; i++) {
             freeMethodInnards(&directMethods[i]);
         }
+        dvmLinearReadOnly(clazz->classLoader, directMethods);
         dvmLinearFree(clazz->classLoader, directMethods);
     }
     if (clazz->virtualMethods != NULL) {
@@ -1922,9 +1979,11 @@
         int virtualMethodCount = clazz->virtualMethodCount;
         clazz->virtualMethodCount = -1;
         clazz->virtualMethods = NULL;
+        dvmLinearReadWrite(clazz->classLoader, virtualMethods);
         for (i = 0; i < virtualMethodCount; i++) {
             freeMethodInnards(&virtualMethods[i]);
         }
+        dvmLinearReadOnly(clazz->classLoader, virtualMethods);
         dvmLinearFree(clazz->classLoader, virtualMethods);
     }
 
@@ -1953,6 +2012,8 @@
 
 /*
  * Free anything in a Method that was allocated on the system heap.
+ *
+ * The containing class is largely torn down by this point.
  */
 static void freeMethodInnards(Method* meth)
 {
@@ -1960,26 +2021,39 @@
     free(meth->exceptions);
     free(meth->lines);
     free(meth->locals);
-#else
-    // TODO: call dvmFreeRegisterMap() if meth->registerMap was allocated
-    //       on the system heap
-    UNUSED_PARAMETER(meth);
 #endif
+
+    /*
+     * Some register maps are allocated on the heap, either because of late
+     * verification or because we're caching an uncompressed form.
+     */
+    const RegisterMap* pMap = meth->registerMap;
+    if (pMap != NULL && dvmRegisterMapGetOnHeap(pMap)) {
+        dvmFreeRegisterMap((RegisterMap*) pMap);
+        meth->registerMap = NULL;
+    }
+
+    /*
+     * We may have copied the instructions.
+     */
+    if (IS_METHOD_FLAG_SET(meth, METHOD_ISWRITABLE)) {
+        DexCode* methodDexCode = (DexCode*) dvmGetMethodCode(meth);
+        dvmLinearFree(meth->clazz->classLoader, methodDexCode);
+    }
 }
 
 /*
  * Clone a Method, making new copies of anything that will be freed up
- * by freeMethodInnards().
+ * by freeMethodInnards().  This is used for "miranda" methods.
  */
 static void cloneMethod(Method* dst, const Method* src)
 {
+    if (src->registerMap != NULL) {
+        LOGE("GLITCH: only expected abstract methods here\n");
+        LOGE("        cloning %s.%s\n", src->clazz->descriptor, src->name);
+        dvmAbort();
+    }
     memcpy(dst, src, sizeof(Method));
-#if 0
-    /* for current usage, these are never set, so no need to implement copy */
-    assert(dst->exceptions == NULL);
-    assert(dst->lines == NULL);
-    assert(dst->locals == NULL);
-#endif
 }
 
 /*
@@ -2042,6 +2116,55 @@
 }
 
 /*
+ * We usually map bytecode directly out of the DEX file, which is mapped
+ * shared read-only.  If we want to be able to modify it, we have to make
+ * a new copy.
+ *
+ * Once copied, the code will be in the LinearAlloc region, which may be
+ * marked read-only.
+ *
+ * The bytecode instructions are embedded inside a DexCode structure, so we
+ * need to copy all of that.  (The dvmGetMethodCode function backs up the
+ * instruction pointer to find the start of the DexCode.)
+ */
+void dvmMakeCodeReadWrite(Method* meth)
+{
+    DexCode* methodDexCode = (DexCode*) dvmGetMethodCode(meth);
+
+    if (IS_METHOD_FLAG_SET(meth, METHOD_ISWRITABLE)) {
+        dvmLinearReadWrite(meth->clazz->classLoader, methodDexCode);
+        return;
+    }
+
+    assert(!dvmIsNativeMethod(meth) && !dvmIsAbstractMethod(meth));
+
+    size_t dexCodeSize = dexGetDexCodeSize(methodDexCode);
+    LOGD("Making a copy of %s.%s code (%d bytes)\n",
+        meth->clazz->descriptor, meth->name, dexCodeSize);
+
+    DexCode* newCode =
+        (DexCode*) dvmLinearAlloc(meth->clazz->classLoader, dexCodeSize);
+    memcpy(newCode, methodDexCode, dexCodeSize);
+
+    meth->insns = newCode->insns;
+    SET_METHOD_FLAG(meth, METHOD_ISWRITABLE);
+}
+
+/*
+ * Mark the bytecode read-only.
+ *
+ * If the contents of the DexCode haven't actually changed, we could revert
+ * to the original shared page.
+ */
+void dvmMakeCodeReadOnly(Method* meth)
+{
+    DexCode* methodDexCode = (DexCode*) dvmGetMethodCode(meth);
+    LOGV("+++ marking %p read-only\n", methodDexCode);
+    dvmLinearReadOnly(meth->clazz->classLoader, methodDexCode);
+}
+
+
+/*
  * jniArgInfo (32-bit int) layout:
  *   SRRRHHHH HHHHHHHH HHHHHHHH HHHHHHHH
  *
@@ -2078,6 +2201,16 @@
     case 'J':
         returnType = DALVIK_JNI_RETURN_S8;
         break;
+    case 'Z':
+    case 'B':
+        returnType = DALVIK_JNI_RETURN_S1;
+        break;
+    case 'C':
+        returnType = DALVIK_JNI_RETURN_U2;
+        break;
+    case 'S':
+        returnType = DALVIK_JNI_RETURN_S2;
+        break;
     default:
         returnType = DALVIK_JNI_RETURN_S4;
         break;
@@ -3116,6 +3249,7 @@
     }
 
     if (mirandaCount != 0) {
+        static const int kManyMirandas = 150;   /* arbitrary */
         Method* newVirtualMethods;
         Method* meth;
         int oldMethodCount, oldVtableCount;
@@ -3124,6 +3258,17 @@
             LOGVV("MIRANDA %d: %s.%s\n", i,
                 mirandaList[i]->clazz->descriptor, mirandaList[i]->name);
         }
+        if (mirandaCount > kManyMirandas) {
+            /*
+             * Some obfuscators like to create an interface with a huge
+             * pile of methods, declare classes as implementing it, and then
+             * only define a couple of methods.  This leads to a rather
+             * massive collection of Miranda methods and a lot of wasted
+             * space, sometimes enough to blow out the LinearAlloc cap.
+             */
+            LOGD("Note: class %s has %d unimplemented (abstract) methods\n",
+                clazz->descriptor, mirandaCount);
+        }
 
         /*
          * We found methods in one or more interfaces for which we do not
@@ -3190,6 +3335,9 @@
          * Now we need to create the fake methods.  We clone the abstract
          * method definition from the interface and then replace a few
          * things.
+         *
+         * The Method will be an "abstract native", with nativeFunc set to
+         * dvmAbstractMethodStub().
          */
         meth = clazz->virtualMethods + oldMethodCount;
         for (i = 0; i < mirandaCount; i++, meth++) {
@@ -3875,17 +4023,32 @@
  *
  * What we need to do is ensure that the classes named in the method
  * descriptors in our ancestors and ourselves resolve to the same class
- * objects.  The only time this matters is when the classes come from
- * different class loaders, and the resolver might come up with a
- * different answer for the same class name depending on context.
+ * objects.  We can get conflicts when the classes come from different
+ * class loaders, and the resolver comes up with different results for
+ * the same class name in different contexts.
  *
- * We don't need to check to see if an interface's methods match with
- * its superinterface's methods, because you can't instantiate an
- * interface and do something inappropriate with it.  If interface I1
- * extends I2 and is implemented by C, and I1 and I2 are in separate
- * class loaders and have conflicting views of other classes, we will
- * catch the conflict when we process C.  Anything that implements I1 is
- * doomed to failure, but we don't need to catch that while processing I1.
+ * An easy way to cause the problem is to declare a base class that uses
+ * class Foo in a method signature (e.g. as the return type).  Then,
+ * define a subclass and a different version of Foo, and load them from a
+ * different class loader.  If the subclass overrides the method, it will
+ * have a different concept of what Foo is than its parent does, so even
+ * though the method signature strings are identical, they actually mean
+ * different things.
+ *
+ * A call to the method through a base-class reference would be treated
+ * differently than a call to the method through a subclass reference, which
+ * isn't the way polymorphism works, so we have to reject the subclass.
+ * If the subclass doesn't override the base method, then there's no
+ * problem, because calls through base-class references and subclass
+ * references end up in the same place.
+ *
+ * We don't need to check to see if an interface's methods match with its
+ * superinterface's methods, because you can't instantiate an interface
+ * and do something inappropriate with it.  If interface I1 extends I2
+ * and is implemented by C, and I1 and I2 are in separate class loaders
+ * and have conflicting views of other classes, we will catch the conflict
+ * when we process C.  Anything that implements I1 is doomed to failure,
+ * but we don't need to catch that while processing I1.
  *
  * On failure, throws an exception and returns "false".
  */
@@ -3903,15 +4066,18 @@
         clazz->classLoader != clazz->super->classLoader)
     {
         /*
-         * Walk through every method declared in the superclass, and
-         * compare resolved descriptor components.  We pull the Method
-         * structs out of the vtable.  It doesn't matter whether we get
-         * the struct from the parent or child, since we just need the
-         * UTF-8 descriptor, which must match.
+         * Walk through every overridden method and compare resolved
+         * descriptor components.  We pull the Method structs out of
+         * the vtable.  It doesn't matter whether we get the struct from
+         * the parent or child, since we just need the UTF-8 descriptor,
+         * which must match.
          *
          * We need to do this even for the stuff inherited from Object,
          * because it's possible that the new class loader has redefined
          * a basic class like String.
+         *
+         * We don't need to check stuff defined in a superclass because
+         * it was checked when the superclass was loaded.
          */
         const Method* meth;
 
@@ -3920,7 +4086,9 @@
         //    clazz->super->descriptor, clazz->super->classLoader);
         for (i = clazz->super->vtableCount - 1; i >= 0; i--) {
             meth = clazz->vtable[i];
-            if (!checkMethodDescriptorClasses(meth, clazz->super, clazz)) {
+            if (meth != clazz->super->vtable[i] &&
+                !checkMethodDescriptorClasses(meth, clazz->super, clazz))
+            {
                 LOGW("Method mismatch: %s in %s (cl=%p) and super %s (cl=%p)\n",
                     meth->name, clazz->descriptor, clazz->classLoader,
                     clazz->super->descriptor, clazz->super->classLoader);
@@ -3932,7 +4100,12 @@
     }
 
     /*
-     * Check all interfaces we implement.
+     * Check the methods defined by this class against the interfaces it
+     * implements.  If we inherited the implementation from a superclass,
+     * we have to check it against the superclass (which might be in a
+     * different class loader).  If the superclass also implements the
+     * interface, we could skip the check since by definition it was
+     * performed when the class was loaded.
      */
     for (i = 0; i < clazz->iftableCount; i++) {
         const InterfaceEntry* iftable = &clazz->iftable[i];
@@ -3948,7 +4121,7 @@
                 vtableIndex = iftable->methodIndexArray[j];
                 meth = clazz->vtable[vtableIndex];
 
-                if (!checkMethodDescriptorClasses(meth, iface, clazz)) {
+                if (!checkMethodDescriptorClasses(meth, iface, meth->clazz)) {
                     LOGW("Method mismatch: %s in %s (cl=%p) and "
                             "iface %s (cl=%p)\n",
                         meth->name, clazz->descriptor, clazz->classLoader,
@@ -4248,6 +4421,44 @@
         dvmCallMethod(self, method, NULL, &unused);
     }
 
+    /* Set the bitmap of reference offsets. Except for class Object,
+     * start with the superclass offsets.
+     */
+    if (clazz->super != NULL) {
+        clazz->refOffsets = clazz->super->refOffsets;
+    } else {
+        clazz->refOffsets = 0;
+    }
+    /*
+     * If our superclass overflowed, we don't stand a chance.
+     */
+    if (clazz->refOffsets != CLASS_WALK_SUPER) {
+        InstField *f;
+        int i;
+
+        /* All of the fields that contain object references
+         * are guaranteed to be at the beginning of the ifields list.
+         */
+        f = clazz->ifields;
+        for (i = 0; i < clazz->ifieldRefCount; i++) {
+            /*
+             * Note that, per the comment on struct InstField,
+             * f->byteOffset is the offset from the beginning of
+             * obj, not the offset into obj->instanceData.
+             */
+            assert(f->byteOffset >= (int) CLASS_SMALLEST_OFFSET);
+            assert((f->byteOffset & (CLASS_OFFSET_ALIGNMENT - 1)) == 0);
+            u4 newBit = CLASS_BIT_FROM_OFFSET(f->byteOffset);
+            if (newBit != 0) {
+                clazz->refOffsets |= newBit;
+            } else {
+                clazz->refOffsets = CLASS_WALK_SUPER;
+                break;
+            }
+            f++;
+        }
+    }
+
     if (dvmCheckException(self)) {
         /*
          * We've had an exception thrown during static initialization.  We
@@ -4310,19 +4521,21 @@
 
 /*
  * Add a RegisterMap to a Method.  This is done when we verify the class
- * and compute the register maps at class initialization time, which means
- * that "pMap" is on the heap and should be freed when the Method is
- * discarded.
+ * and compute the register maps at class initialization time (i.e. when
+ * we don't have a pre-generated map).  This means "pMap" is on the heap
+ * and should be freed when the Method is discarded.
  */
 void dvmSetRegisterMap(Method* method, const RegisterMap* pMap)
 {
     ClassObject* clazz = method->clazz;
 
     if (method->registerMap != NULL) {
-        LOGW("WARNING: registerMap already set for %s.%s\n",
+        /* unexpected during class loading, okay on first use (uncompress) */
+        LOGV("NOTE: registerMap already set for %s.%s\n",
             method->clazz->descriptor, method->name);
         /* keep going */
     }
+    assert(!dvmIsNativeMethod(method) && !dvmIsAbstractMethod(method));
 
     /* might be virtual or direct */
     dvmLinearReadWrite(clazz->classLoader, clazz->virtualMethods);
diff --git a/vm/oo/Class.h b/vm/oo/Class.h
index 349df3f..59e0da4 100644
--- a/vm/oo/Class.h
+++ b/vm/oo/Class.h
@@ -149,8 +149,19 @@
  */
 void dvmSetRegisterMap(Method* method, const RegisterMap* pMap);
 
-/* during DEX optimizing, add an extra DEX to the bootstrap class path */
-INLINE void dvmSetBootPathExtraDex(DvmDex* pDvmDex);
+/*
+ * Make a method's DexCode (which includes the bytecode) read-write or
+ * read-only.  The conversion to read-write may involve making a new copy
+ * of the DexCode, and in normal operation the read-only state is not
+ * actually enforced.
+ */
+void dvmMakeCodeReadWrite(Method* meth);
+void dvmMakeCodeReadOnly(Method* meth);
+
+/*
+ * During DEX optimizing, add an extra DEX to the bootstrap class path.
+ */
+void dvmSetBootPathExtraDex(DvmDex* pDvmDex);
 
 /*
  * Debugging.
diff --git a/vm/oo/Object.c b/vm/oo/Object.c
index 189ad09..eff0983 100644
--- a/vm/oo/Object.c
+++ b/vm/oo/Object.c
@@ -90,18 +90,16 @@
 
     assert(clazz != NULL);
 
+    /*
+     * Find a field with a matching name and signature.  As with instance
+     * fields, the VM allows you to have two fields with the same name so
+     * long as they have different types.
+     */
     pField = clazz->sfields;
     for (i = 0; i < clazz->sfieldCount; i++, pField++) {
-        if (strcmp(fieldName, pField->field.name) == 0) {
-            /*
-             * The name matches.  Unlike methods, we can't have two fields
-             * with the same names but differing types.
-             */
-            if (strcmp(signature, pField->field.signature) != 0) {
-                LOGW("Found field '%s', but sig is '%s' not '%s'\n",
-                    fieldName, pField->field.signature, signature);
-                return NULL;
-            }
+        if (strcmp(fieldName, pField->field.name) == 0 &&
+            strcmp(signature, pField->field.signature) == 0)
+        {
             return pField;
         }
     }
@@ -152,6 +150,58 @@
 }
 
 /*
+ * Find a matching field, in this class or a superclass.
+ *
+ * We scan both the static and instance field lists in the class.  If it's
+ * not found there, we check the direct interfaces, and then recursively
+ * scan the superclasses.  This is the order prescribed in the VM spec
+ * (v2 5.4.3.2).
+ *
+ * In most cases we know that we're looking for either a static or an
+ * instance field and there's no value in searching through both types.
+ * During verification we need to recognize and reject certain unusual
+ * situations, and we won't see them unless we walk the lists this way.
+ */
+Field* dvmFindFieldHier(const ClassObject* clazz, const char* fieldName,
+    const char* signature)
+{
+    Field* pField;
+
+    /*
+     * Search for a match in the current class.  Which set we scan first
+     * doesn't really matter.
+     */
+    pField = (Field*) dvmFindStaticField(clazz, fieldName, signature);
+    if (pField != NULL)
+        return pField;
+    pField = (Field*) dvmFindInstanceField(clazz, fieldName, signature);
+    if (pField != NULL)
+        return pField;
+
+    /*
+     * See if it's in any of our interfaces.  We don't check interfaces
+     * inherited from the superclass yet.
+     */
+    int i = 0;
+    if (clazz->super != NULL) {
+        assert(clazz->iftableCount >= clazz->super->iftableCount);
+        i = clazz->super->iftableCount;
+    }
+    for ( ; i < clazz->iftableCount; i++) {
+        ClassObject* iface = clazz->iftable[i].clazz;
+        pField = (Field*) dvmFindStaticField(iface, fieldName, signature);
+        if (pField != NULL)
+            return pField;
+    }
+
+    if (clazz->super != NULL)
+        return dvmFindFieldHier(clazz->super, fieldName, signature);
+    else
+        return NULL;
+}
+
+
+/*
  * Compare the given name, return type, and argument types with the contents
  * of the given method. This returns 0 if they are equal and non-zero if not.
  */
@@ -367,27 +417,34 @@
 /*
  * Look for a match in the given clazz. Returns the match if found
  * or NULL if not.
+ *
+ * "wantedType" should be METHOD_VIRTUAL or METHOD_DIRECT to indicate the
+ * list to search through.  If the match can come from either list, use
+ * MATCH_UNKNOWN to scan both.
  */
 static Method* findMethodInListByProto(const ClassObject* clazz,
-    bool findVirtual, bool isHier, const char* name, const DexProto* proto)
+    MethodType wantedType, bool isHier, const char* name, const DexProto* proto)
 {    
     while (clazz != NULL) {
-        Method* methods;
-        size_t methodCount;
-        size_t i;
+        int i;
 
-        if (findVirtual) {
-            methods = clazz->virtualMethods;
-            methodCount = clazz->virtualMethodCount;
-        } else {
-            methods = clazz->directMethods;
-            methodCount = clazz->directMethodCount;
+        /*
+         * Check the virtual and/or direct method lists.
+         */
+        if (wantedType == METHOD_VIRTUAL || wantedType == METHOD_UNKNOWN) {
+            for (i = 0; i < clazz->virtualMethodCount; i++) {
+                Method* method = &clazz->virtualMethods[i];
+                if (dvmCompareNameProtoAndMethod(name, proto, method) == 0) {
+                    return method;
+                }
+            }
         }
-
-        for (i = 0; i < methodCount; i++) {
-            Method* method = &methods[i];
-            if (dvmCompareNameProtoAndMethod(name, proto, method) == 0) {
-                return method;
+        if (wantedType == METHOD_DIRECT || wantedType == METHOD_UNKNOWN) {
+            for (i = 0; i < clazz->directMethodCount; i++) {
+                Method* method = &clazz->directMethods[i];
+                if (dvmCompareNameProtoAndMethod(name, proto, method) == 0) {
+                    return method;
+                }
             }
         }
 
@@ -454,7 +511,8 @@
 Method* dvmFindVirtualMethod(const ClassObject* clazz, const char* methodName,
     const DexProto* proto)
 {
-    return findMethodInListByProto(clazz, true, false, methodName, proto);
+    return findMethodInListByProto(clazz, METHOD_VIRTUAL, false, methodName,
+            proto);
 }
 
 /*
@@ -479,7 +537,8 @@
 Method* dvmFindVirtualMethodHier(const ClassObject* clazz,
     const char* methodName, const DexProto* proto)
 {
-    return findMethodInListByProto(clazz, true, true, methodName, proto);
+    return findMethodInListByProto(clazz, METHOD_VIRTUAL, true, methodName,
+            proto);
 }
 
 /*
@@ -516,7 +575,8 @@
 Method* dvmFindDirectMethod(const ClassObject* clazz, const char* methodName,
     const DexProto* proto)
 {
-    return findMethodInListByProto(clazz, false, false, methodName, proto);
+    return findMethodInListByProto(clazz, METHOD_DIRECT, false, methodName,
+            proto);
 }
 
 /*
@@ -528,10 +588,32 @@
 Method* dvmFindDirectMethodHier(const ClassObject* clazz,
     const char* methodName, const DexProto* proto)
 {
-    return findMethodInListByProto(clazz, false, true, methodName, proto);
+    return findMethodInListByProto(clazz, METHOD_DIRECT, true, methodName,
+            proto);
 }
 
 /*
+ * Find a virtual or static method in a class.  If we don't find it, try the
+ * superclass.  This is compatible with the VM spec (v2 5.4.3.3) method
+ * search order, but it stops short of scanning through interfaces (which
+ * should be done after this function completes).
+ *
+ * In most cases we know that we're looking for either a static or an
+ * instance field and there's no value in searching through both types.
+ * During verification we need to recognize and reject certain unusual
+ * situations, and we won't see them unless we walk the lists this way.
+ *
+ * Returns NULL if the method can't be found.  (Does not throw an exception.)
+ */
+Method* dvmFindMethodHier(const ClassObject* clazz, const char* methodName,
+    const DexProto* proto)
+{
+    return findMethodInListByProto(clazz, METHOD_UNKNOWN, true, methodName,
+            proto);
+}
+
+
+/*
  * We have a method pointer for a method in "clazz", but it might be
  * pointing to a method in a derived class.  We want to find the actual entry
  * from the class' vtable.  If "clazz" is an interface, we have to do a
@@ -617,37 +699,44 @@
     }
 
     clazz = obj->clazz;
-    LOGV("----- Object dump: %p (%s, %d bytes) -----\n",
+    LOGD("----- Object dump: %p (%s, %d bytes) -----\n",
         obj, clazz->descriptor, (int) clazz->objectSize);
     //printHexDump(obj, clazz->objectSize);
-    LOGV("  Fields:\n");
-    for (i = 0; i < clazz->ifieldCount; i++) {
-        const InstField* pField = &clazz->ifields[i];
-        char type = pField->field.signature[0];
+    LOGD("  Fields:\n");
+    while (clazz != NULL) {
+        LOGD("    -- %s\n", clazz->descriptor);
+        for (i = 0; i < clazz->ifieldCount; i++) {
+            const InstField* pField = &clazz->ifields[i];
+            char type = pField->field.signature[0];
 
-        if (type == 'F' || type == 'D') {
-            double dval;
+            if (type == 'F' || type == 'D') {
+                double dval;
 
-            if (type == 'F')
-                dval = dvmGetFieldFloat(obj, pField->byteOffset);
-            else
-                dval = dvmGetFieldDouble(obj, pField->byteOffset);
+                if (type == 'F')
+                    dval = dvmGetFieldFloat(obj, pField->byteOffset);
+                else
+                    dval = dvmGetFieldDouble(obj, pField->byteOffset);
 
-            LOGV("  %2d: '%s' '%s' flg=%04x %.3f\n", i, pField->field.name,
-                pField->field.signature, pField->field.accessFlags, dval);
-        } else {
-            long long lval;
+                LOGD("    %2d: '%s' '%s' af=%04x off=%d %.3f\n", i,
+                    pField->field.name, pField->field.signature,
+                    pField->field.accessFlags, pField->byteOffset, dval);
+            } else {
+                u8 lval;
 
-            if (pField->field.signature[0] == 'J')
-                lval = dvmGetFieldLong(obj, pField->byteOffset);
-            else if (pField->field.signature[0] == 'Z')
-                lval = dvmGetFieldBoolean(obj, pField->byteOffset);
-            else
-                lval = dvmGetFieldInt(obj, pField->byteOffset);
+                if (type == 'J')
+                    lval = dvmGetFieldLong(obj, pField->byteOffset);
+                else if (type == 'Z')
+                    lval = dvmGetFieldBoolean(obj, pField->byteOffset);
+                else
+                    lval = dvmGetFieldInt(obj, pField->byteOffset);
 
-            LOGV("  %2d: '%s' '%s' af=%04x 0x%llx\n", i, pField->field.name,
-                pField->field.signature, pField->field.accessFlags, lval);
+                LOGD("    %2d: '%s' '%s' af=%04x off=%d 0x%08llx\n", i,
+                    pField->field.name, pField->field.signature,
+                    pField->field.accessFlags, pField->byteOffset, lval);
+            }
         }
+
+        clazz = clazz->super;
     }
 }
 
diff --git a/vm/oo/Object.h b/vm/oo/Object.h
index 18fbb36..3e724f4 100644
--- a/vm/oo/Object.h
+++ b/vm/oo/Object.h
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 /*
  * Declaration of the fundamental Object type and refinements thereof, plus
  * some functions for manipulating them.
@@ -93,6 +94,44 @@
 #define EXPECTED_FILE_FLAGS \
     (ACC_CLASS_MASK | CLASS_ISPREVERIFIED | CLASS_ISOPTIMIZED)
 
+/*
+ * Get/set class flags.
+ */
+#define SET_CLASS_FLAG(clazz, flag) \
+    do { (clazz)->accessFlags |= (flag); } while (0)
+
+#define CLEAR_CLASS_FLAG(clazz, flag) \
+    do { (clazz)->accessFlags &= ~(flag); } while (0)
+
+#define IS_CLASS_FLAG_SET(clazz, flag) \
+    (((clazz)->accessFlags & (flag)) != 0)
+
+#define GET_CLASS_FLAG_GROUP(clazz, flags) \
+    ((u4)((clazz)->accessFlags & (flags)))
+
+/*
+ * Use the top 16 bits of the access flags field for other method flags.
+ * Code should use the *METHOD_FLAG*() macros to set/get these flags.
+ */
+typedef enum MethodFlags {
+    METHOD_ISWRITABLE       = (1<<31),  // the method's code is writable
+} MethodFlags;
+
+/*
+ * Get/set method flags.
+ */
+#define SET_METHOD_FLAG(method, flag) \
+    do { (method)->accessFlags |= (flag); } while (0)
+
+#define CLEAR_METHOD_FLAG(method, flag) \
+    do { (method)->accessFlags &= ~(flag); } while (0)
+
+#define IS_METHOD_FLAG_SET(method, flag) \
+    (((method)->accessFlags & (flag)) != 0)
+
+#define GET_METHOD_FLAG_GROUP(method, flags) \
+    ((u4)((method)->accessFlags & (flags)))
+
 /* current state of the class, increasing as we progress */
 typedef enum ClassStatus {
     CLASS_ERROR         = -1,
@@ -134,11 +173,31 @@
 #define PRIM_TYPE_TO_LETTER "ZCFDBSIJV"     /* must match order in enum */
 
 /*
- * This defines the amount of space we leave for field slots in the
- * java.lang.Class definition.  If we alter the class to have more than
- * this many fields, the VM will abort at startup.
+ * Definitions for packing refOffsets in ClassObject.
  */
-#define CLASS_FIELD_SLOTS   4
+/*
+ * A magic value for refOffsets. Ignore the bits and walk the super
+ * chain when this is the value.
+ * [This is an unlikely "natural" value, since it would be 30 non-ref instance
+ * fields followed by 2 ref instance fields.]
+ */
+#define CLASS_WALK_SUPER ((unsigned int)(3))
+#define CLASS_SMALLEST_OFFSET (sizeof(struct Object))
+#define CLASS_BITS_PER_WORD (sizeof(unsigned long int) * 8)
+#define CLASS_OFFSET_ALIGNMENT 4
+#define CLASS_HIGH_BIT ((unsigned int)1 << (CLASS_BITS_PER_WORD - 1))
+/*
+ * Return a single bit, or zero if the encoding can't encode the offset.
+ */
+#define CLASS_BIT_FROM_OFFSET(byteOffset) \
+    (CLASS_HIGH_BIT >> \
+      (((unsigned int)(byteOffset) - CLASS_SMALLEST_OFFSET) / \
+       CLASS_OFFSET_ALIGNMENT))
+/*
+ * Return an offset, given a bit number as returned from CLZ.
+ */
+#define CLASS_OFFSET_FROM_CLZ(rshift) \
+    (((int)(rshift) * CLASS_OFFSET_ALIGNMENT) + CLASS_SMALLEST_OFFSET)
 
 
 /*
@@ -185,21 +244,6 @@
     do { (obj)->clazz = (clazz_); DVM_LOCK_INIT(&(obj)->lock); } while (0)
 
 /*
- * Get/set class flags.
- */
-#define SET_CLASS_FLAG(clazz, flag) \
-    do { (clazz)->accessFlags |= (flag); } while (0)
-
-#define CLEAR_CLASS_FLAG(clazz, flag) \
-    do { (clazz)->accessFlags &= ~(flag); } while (0)
-
-#define IS_CLASS_FLAG_SET(clazz, flag) \
-    (((clazz)->accessFlags & (flag)) != 0)
-
-#define GET_CLASS_FLAG_GROUP(clazz, flags) \
-    ((u4)((clazz)->accessFlags & (flags)))
-
-/*
  * Data objects have an Object header followed by their instance data.
  */
 struct DataObject {
@@ -262,6 +306,13 @@
 };
 
 /*
+ * This defines the amount of space we leave for field slots in the
+ * java.lang.Class definition.  If we alter the class to have more than
+ * this many fields, the VM will abort at startup.
+ */
+#define CLASS_FIELD_SLOTS   4
+
+/*
  * Class objects have many additional fields.  This is used for both
  * classes and interfaces, including synthesized classes (arrays and
  * primitive types).
@@ -400,6 +451,9 @@
     int             ifieldRefCount; // number of fields that are object refs
     InstField*      ifields;
 
+    /* bitmap of offsets of ifields */
+    u4 refOffsets;
+
     /* source file name, if known */
     const char*     sourceFile;
 };
@@ -559,6 +613,8 @@
     const char* methodName, const DexProto* proto);
 Method* dvmFindVirtualMethodHier(const ClassObject* clazz,
     const char* methodName, const DexProto* proto);
+Method* dvmFindMethodHier(const ClassObject* clazz, const char* methodName,
+    const DexProto* proto);
 
 /*
  * Find the implementation of "meth" in "clazz".
@@ -588,6 +644,8 @@
     const char* fieldName, const char* signature);
 StaticField* dvmFindStaticFieldHier(const ClassObject* clazz,
     const char* fieldName, const char* signature);
+Field* dvmFindFieldHier(const ClassObject* clazz, const char* fieldName,
+    const char* signature);
 
 /*
  * Find a field and return the byte offset from the object pointer.  Only
diff --git a/vm/oo/Resolve.c b/vm/oo/Resolve.c
index 52eeee0..68fdd51 100644
--- a/vm/oo/Resolve.c
+++ b/vm/oo/Resolve.c
@@ -130,8 +130,11 @@
                     referrer->pDvmDex,
                     resClass->descriptor, resClassCheck->descriptor,
                     resClassCheck->classLoader, resClassCheck->pDvmDex);
+                LOGW("(%s had used a different %s during pre-verification)\n",
+                    referrer->descriptor, resClass->descriptor);
                 dvmThrowException("Ljava/lang/IllegalAccessError;",
-                    "cross-loader access from pre-verified class");
+                    "Class ref in pre-verified class resolved to unexpected "
+                    "implementation");
                 return NULL;
             }
         }
diff --git a/vm/reflect/Annotation.c b/vm/reflect/Annotation.c
index c07c602..109c7fb 100644
--- a/vm/reflect/Annotation.c
+++ b/vm/reflect/Annotation.c
@@ -330,11 +330,12 @@
         resMethod = dvmFindDirectMethod(resClass, name, &proto);
     } else {
         /*
-         * Try both lists, and scan up the tree.
+         * Do a hierarchical scan for direct and virtual methods.
+         *
+         * This uses the search order from the VM spec (v2 5.4.3.3), which
+         * seems appropriate here.
          */
-        resMethod = dvmFindVirtualMethodHier(resClass, name, &proto);
-        if (resMethod == NULL)
-            resMethod = dvmFindDirectMethodHier(resClass, name, &proto);
+        resMethod = dvmFindMethodHier(resClass, name, &proto);
     }
 
     return resMethod;
diff --git a/vm/test/AtomicSpeed.c b/vm/test/AtomicSpeed.c
new file mode 100644
index 0000000..e2ffbef
--- /dev/null
+++ b/vm/test/AtomicSpeed.c
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+
+/*
+ * Atomic operation performance test.
+ */
+#include "Dalvik.h"
+
+//#define TRIVIAL_COMPARE     /* do something simple instead of an atomic op */
+
+/*
+ * Perform operation.  Returns elapsed time.
+ */
+u8 dvmTestAtomicSpeedSub(int repeatCount)
+{
+    static int value = 7;
+    int* valuePtr = &value;
+    u8 start, end;
+    int i;
+    
+#ifdef TRIVIAL_COMPARE
+    /* init to arg value so compiler can't pre-determine result */
+    int j = repeatCount;
+#endif
+
+    assert((repeatCount % 10) == 0);
+
+    start = dvmGetRelativeTimeNsec();
+
+    for (i = repeatCount / 10; i != 0; i--) {
+#ifdef TRIVIAL_COMPARE
+        // integer add (Dream: 3.4ns -- THUMB has 10 adds, ARM condenses)
+        j += i; j += i; j += i; j += i; j += i;
+        j += i; j += i; j += i; j += i; j += i;
+#else
+        // succeed 10x (Dream: 155.9ns)
+        ATOMIC_CMP_SWAP(valuePtr, 7, 7);
+        ATOMIC_CMP_SWAP(valuePtr, 7, 7);
+        ATOMIC_CMP_SWAP(valuePtr, 7, 7);
+        ATOMIC_CMP_SWAP(valuePtr, 7, 7);
+        ATOMIC_CMP_SWAP(valuePtr, 7, 7);
+        ATOMIC_CMP_SWAP(valuePtr, 7, 7);
+        ATOMIC_CMP_SWAP(valuePtr, 7, 7);
+        ATOMIC_CMP_SWAP(valuePtr, 7, 7);
+        ATOMIC_CMP_SWAP(valuePtr, 7, 7);
+        ATOMIC_CMP_SWAP(valuePtr, 7, 7);
+
+        // fail 10x (Dream: 158.5ns)
+        /*
+        ATOMIC_CMP_SWAP(valuePtr, 6, 7);
+        ATOMIC_CMP_SWAP(valuePtr, 6, 7);
+        ATOMIC_CMP_SWAP(valuePtr, 6, 7);
+        ATOMIC_CMP_SWAP(valuePtr, 6, 7);
+        ATOMIC_CMP_SWAP(valuePtr, 6, 7);
+        ATOMIC_CMP_SWAP(valuePtr, 6, 7);
+        ATOMIC_CMP_SWAP(valuePtr, 6, 7);
+        ATOMIC_CMP_SWAP(valuePtr, 6, 7);
+        ATOMIC_CMP_SWAP(valuePtr, 6, 7);
+        ATOMIC_CMP_SWAP(valuePtr, 6, 7);
+        */
+#endif
+    }
+
+    end = dvmGetRelativeTimeNsec();
+
+#ifdef TRIVIAL_COMPARE
+    /* use value so compiler can't eliminate it */
+    dvmFprintf(stdout, "%d\n", j);
+#else
+    dvmFprintf(stdout, ".");
+    fflush(stdout);     // not quite right if they intercepted fprintf
+#endif
+    return end - start;
+}
+
+/*
+ * Control loop.
+ */
+bool dvmTestAtomicSpeed(void)
+{
+    static const int kIterations = 10;
+    static const int kRepeatCount = 5 * 1000 * 1000;
+    static const int kDelay = 500 * 1000;
+    u8 results[kIterations];
+    int i;
+
+    for (i = 0; i < kIterations; i++) {
+        results[i] = dvmTestAtomicSpeedSub(kRepeatCount);
+        usleep(kDelay);
+    }
+
+    dvmFprintf(stdout, "\n");
+    dvmFprintf(stdout, "Atomic speed test results (%d per iteration):\n",
+        kRepeatCount);
+    for (i = 0; i < kIterations; i++) {
+        dvmFprintf(stdout,
+            " %2d: %.3fns\n", i, (double) results[i] / kRepeatCount);
+    }
+
+    return true;
+}
+
diff --git a/vm/test/Test.h b/vm/test/Test.h
index a6b54a5..f17526f 100644
--- a/vm/test/Test.h
+++ b/vm/test/Test.h
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 /*
  * Internal unit tests.
  */
@@ -20,5 +21,7 @@
 #define _DALVIK_TEST_TEST
 
 bool dvmTestHash(void);
+bool dvmTestAtomicSpeed(void);
+bool dvmTestIndirectRefTable(void);
 
 #endif /*_DALVIK_TEST_TEST*/
diff --git a/vm/test/TestHash.c b/vm/test/TestHash.c
index 42fe014..7233b15 100644
--- a/vm/test/TestHash.c
+++ b/vm/test/TestHash.c
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 /*
  * Test the hash table functions.
  */
@@ -20,6 +21,8 @@
 
 #include <stdlib.h>
 
+#ifndef NDEBUG
+
 #define kNumTestEntries 14
 
 /*
@@ -185,3 +188,4 @@
     return true;
 }
 
+#endif /*NDEBUG*/
diff --git a/vm/test/TestIndirectRefTable.c b/vm/test/TestIndirectRefTable.c
new file mode 100644
index 0000000..64d843c
--- /dev/null
+++ b/vm/test/TestIndirectRefTable.c
@@ -0,0 +1,485 @@
+/*
+ * 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.
+ */
+
+/*
+ * Test the indirect reference table implementation.
+ */
+#include "Dalvik.h"
+
+#include <stdlib.h>
+
+#ifndef NDEBUG
+
+#define DBUG_MSG    LOGV
+
+/*
+ * Basic add/get/delete tests in an unsegmented table.
+ */
+static bool basicTest(void)
+{
+    static const int kTableMax = 20;
+    IndirectRefTable irt;
+    IndirectRef iref0, iref1, iref2, iref3;
+    IndirectRef manyRefs[kTableMax];
+    ClassObject* clazz = dvmFindClass("Ljava/lang/Object;", NULL);
+    Object* obj0 = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
+    Object* obj1 = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
+    Object* obj2 = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
+    Object* obj3 = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
+    const u4 cookie = IRT_FIRST_SEGMENT;
+    bool result = false;
+
+    if (!dvmInitIndirectRefTable(&irt, kTableMax/2, kTableMax,
+            kIndirectKindGlobal))
+    {
+        return false;
+    }
+
+    iref0 = (IndirectRef) 0x11110;
+    if (dvmRemoveFromIndirectRefTable(&irt, cookie, iref0)) {
+        LOGE("unexpectedly successful removal\n");
+        goto bail;
+    }
+
+    /*
+     * Add three, check, remove in the order in which they were added.
+     */
+    DBUG_MSG("+++ START fifo\n");
+    iref0 = dvmAddToIndirectRefTable(&irt, cookie, obj0);
+    iref1 = dvmAddToIndirectRefTable(&irt, cookie, obj1);
+    iref2 = dvmAddToIndirectRefTable(&irt, cookie, obj2);
+    if (iref0 == NULL || iref1 == NULL || iref2 == NULL) {
+        LOGE("trivial add1 failed\n");
+        goto bail;
+    }
+
+    if (dvmGetFromIndirectRefTable(&irt, iref0) != obj0 ||
+        dvmGetFromIndirectRefTable(&irt, iref1) != obj1 ||
+        dvmGetFromIndirectRefTable(&irt, iref2) != obj2)
+    {
+        LOGE("objects don't match expected values %p %p %p vs. %p %p %p\n",
+            dvmGetFromIndirectRefTable(&irt, iref0),
+            dvmGetFromIndirectRefTable(&irt, iref1),
+            dvmGetFromIndirectRefTable(&irt, iref2),
+            obj0, obj1, obj2);
+        goto bail;
+    } else {
+        DBUG_MSG("+++ obj1=%p --> iref1=%p\n", obj1, iref1);
+    }
+
+    if (!dvmRemoveFromIndirectRefTable(&irt, cookie, iref0) ||
+        !dvmRemoveFromIndirectRefTable(&irt, cookie, iref1) ||
+        !dvmRemoveFromIndirectRefTable(&irt, cookie, iref2))
+    {
+        LOGE("fifo deletion failed\n");
+        goto bail;
+    }
+
+    /* table should be empty now */
+    if (dvmIndirectRefTableEntries(&irt) != 0) {
+        LOGE("fifo del not empty\n");
+        goto bail;
+    }
+
+    /* get invalid entry (off the end of the list) */
+    if (dvmGetFromIndirectRefTable(&irt, iref0) != NULL) {
+        LOGE("stale entry get succeeded unexpectedly\n");
+        goto bail;
+    }
+
+    /*
+     * Add three, remove in the opposite order.
+     */
+    DBUG_MSG("+++ START lifo\n");
+    iref0 = dvmAddToIndirectRefTable(&irt, cookie, obj0);
+    iref1 = dvmAddToIndirectRefTable(&irt, cookie, obj1);
+    iref2 = dvmAddToIndirectRefTable(&irt, cookie, obj2);
+    if (iref0 == NULL || iref1 == NULL || iref2 == NULL) {
+        LOGE("trivial add2 failed\n");
+        goto bail;
+    }
+
+    if (!dvmRemoveFromIndirectRefTable(&irt, cookie, iref2) ||
+        !dvmRemoveFromIndirectRefTable(&irt, cookie, iref1) ||
+        !dvmRemoveFromIndirectRefTable(&irt, cookie, iref0))
+    {
+        LOGE("lifo deletion failed\n");
+        goto bail;
+    }
+
+    /* table should be empty now */
+    if (dvmIndirectRefTableEntries(&irt) != 0) {
+        LOGE("lifo del not empty\n");
+        goto bail;
+    }
+
+    /*
+     * Add three, remove middle / middle / bottom / top.  (Second attempt
+     * to remove middle should fail.)
+     */
+    DBUG_MSG("+++ START unorder\n");
+    iref0 = dvmAddToIndirectRefTable(&irt, cookie, obj0);
+    iref1 = dvmAddToIndirectRefTable(&irt, cookie, obj1);
+    iref2 = dvmAddToIndirectRefTable(&irt, cookie, obj2);
+    if (iref0 == NULL || iref1 == NULL || iref2 == NULL) {
+        LOGE("trivial add3 failed\n");
+        goto bail;
+    }
+
+    if (dvmIndirectRefTableEntries(&irt) != 3) {
+        LOGE("expected 3 entries, found %d\n",
+            dvmIndirectRefTableEntries(&irt));
+        goto bail;
+    }
+
+    if (!dvmRemoveFromIndirectRefTable(&irt, cookie, iref1) ||
+        dvmRemoveFromIndirectRefTable(&irt, cookie, iref1))
+    {
+        LOGE("unorder deletion1 failed\n");
+        goto bail;
+    }
+
+    /* get invalid entry (from hole) */
+    if (dvmGetFromIndirectRefTable(&irt, iref1) != NULL) {
+        LOGE("hole get succeeded unexpectedly\n");
+        goto bail;
+    }
+
+    if (!dvmRemoveFromIndirectRefTable(&irt, cookie, iref2) ||
+        !dvmRemoveFromIndirectRefTable(&irt, cookie, iref0))
+    {
+        LOGE("unorder deletion2 failed\n");
+        goto bail;
+    }
+
+    /* table should be empty now */
+    if (dvmIndirectRefTableEntries(&irt) != 0) {
+        LOGE("unorder del not empty\n");
+        goto bail;
+    }
+
+    /*
+     * Add four entries.  Remove #1, add new entry, verify that table size
+     * is still 4 (i.e. holes are getting filled).  Remove #1 and #3, verify
+     * that we delete one and don't hole-compact the other.
+     */
+    DBUG_MSG("+++ START hole fill\n");
+    iref0 = dvmAddToIndirectRefTable(&irt, cookie, obj0);
+    iref1 = dvmAddToIndirectRefTable(&irt, cookie, obj1);
+    iref2 = dvmAddToIndirectRefTable(&irt, cookie, obj2);
+    iref3 = dvmAddToIndirectRefTable(&irt, cookie, obj3);
+    if (iref0 == NULL || iref1 == NULL || iref2 == NULL || iref3 == NULL) {
+        LOGE("trivial add4 failed\n");
+        goto bail;
+    }
+    if (!dvmRemoveFromIndirectRefTable(&irt, cookie, iref1)) {
+        LOGE("remove 1 of 4 failed\n");
+        goto bail;
+    }
+    iref1 = dvmAddToIndirectRefTable(&irt, cookie, obj1);
+    if (dvmIndirectRefTableEntries(&irt) != 4) {
+        LOGE("hole not filled\n");
+        goto bail;
+    }
+    if (!dvmRemoveFromIndirectRefTable(&irt, cookie, iref1) ||
+        !dvmRemoveFromIndirectRefTable(&irt, cookie, iref3))
+    {
+        LOGE("remove 1/3 failed\n");
+        goto bail;
+    }
+    if (dvmIndirectRefTableEntries(&irt) != 3) {
+        LOGE("should be 3 after two deletions\n");
+        goto bail;
+    }
+    if (!dvmRemoveFromIndirectRefTable(&irt, cookie, iref2) ||
+        !dvmRemoveFromIndirectRefTable(&irt, cookie, iref0))
+    {
+        LOGE("remove 2/0 failed\n");
+        goto bail;
+    }
+    if (dvmIndirectRefTableEntries(&irt) != 0) {
+        LOGE("not empty after split remove\n");
+        goto bail;
+    }
+
+    /*
+     * Add an entry, remove it, add a new entry, and try to use the original
+     * iref.  They have the same slot number but are for different objects.
+     * With the extended checks in place, this should fail.
+     */
+    DBUG_MSG("+++ START switched\n");
+    iref0 = dvmAddToIndirectRefTable(&irt, cookie, obj0);
+    dvmRemoveFromIndirectRefTable(&irt, cookie, iref0);
+    iref1 = dvmAddToIndirectRefTable(&irt, cookie, obj1);
+    if (dvmRemoveFromIndirectRefTable(&irt, cookie, iref0)) {
+        LOGE("mismatched del succeeded (%p vs %p)\n", iref0, iref1);
+        goto bail;
+    }
+    if (!dvmRemoveFromIndirectRefTable(&irt, cookie, iref1)) {
+        LOGE("switched del failed\n");
+        goto bail;
+    }
+    if (dvmIndirectRefTableEntries(&irt) != 0) {
+        LOGE("switching del not empty\n");
+        goto bail;
+    }
+
+    /*
+     * Same as above, but with the same object.  A more rigorous checker
+     * (e.g. with slot serialization) will catch this.
+     */
+    iref0 = dvmAddToIndirectRefTable(&irt, cookie, obj0);
+    dvmRemoveFromIndirectRefTable(&irt, cookie, iref0);
+    iref1 = dvmAddToIndirectRefTable(&irt, cookie, obj0);
+    if (iref0 != iref1) {
+        if (dvmRemoveFromIndirectRefTable(&irt, cookie, iref0)) {
+            LOGE("temporal del succeeded (%p vs %p)\n", iref0, iref1);
+            goto bail;
+        }
+    } else {
+        dvmRemoveFromIndirectRefTable(&irt, cookie, iref1);
+    }
+    if (dvmIndirectRefTableEntries(&irt) != 0) {
+        LOGE("temporal del not empty\n");
+        goto bail;
+    }
+
+    /*
+     * Test table overflow.
+     */
+    DBUG_MSG("+++ START overflow\n");
+    int i;
+    for (i = 0; i < kTableMax; i++) {
+        manyRefs[i] = dvmAddToIndirectRefTable(&irt, cookie, obj0);
+        if (manyRefs[i] == NULL) {
+            LOGE("Failed adding %d of %d\n", i, kTableMax);
+            goto bail;
+        }
+    }
+    if (dvmAddToIndirectRefTable(&irt, cookie, obj0) != NULL) {
+        LOGE("Table overflow succeeded\n");
+        goto bail;
+    }
+    if (dvmIndirectRefTableEntries(&irt) != (size_t)kTableMax) {
+        LOGE("Expected %d entries, found %d\n",
+            kTableMax, dvmIndirectRefTableEntries(&irt));
+        goto bail;
+    }
+    for (i = 0; i < kTableMax-1; i++) {
+        if (!dvmRemoveFromIndirectRefTable(&irt, cookie, manyRefs[i])) {
+            LOGE("multi-remove failed at %d\n", i);
+            goto bail;
+        }
+    }
+    /* because of removal order, should have 20 entries, 19 of them holes */
+    if (dvmIndirectRefTableEntries(&irt) != (size_t)kTableMax) {
+        LOGE("Expected %d entries (with holes), found %d\n",
+            kTableMax, dvmIndirectRefTableEntries(&irt));
+        goto bail;
+    }
+    if (!dvmRemoveFromIndirectRefTable(&irt, cookie, manyRefs[kTableMax-1])) {
+        LOGE("multi-remove final failed\n");
+        goto bail;
+    }
+    if (dvmIndirectRefTableEntries(&irt) != 0) {
+        LOGE("multi-del not empty\n");
+        goto bail;
+    }
+
+    DBUG_MSG("+++ basic test complete\n");
+    result = true;
+
+bail:
+    dvmClearIndirectRefTable(&irt);
+    return result;
+}
+
+/*
+ * Test operations on a segmented table.
+ */
+static bool segmentTest(void)
+{
+    static const int kTableMax = 20;
+    IndirectRefTable irt;
+    IndirectRef iref0, iref1, iref2, iref3;
+    ClassObject* clazz = dvmFindClass("Ljava/lang/Object;", NULL);
+    Object* obj0 = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
+    Object* obj1 = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
+    Object* obj2 = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
+    Object* obj3 = dvmAllocObject(clazz, ALLOC_DONT_TRACK);
+    u4 cookie;
+    u4 segmentState[4];
+    bool result = false;
+
+    if (!dvmInitIndirectRefTable(&irt, kTableMax, kTableMax,
+            kIndirectKindLocal))
+    {
+        return false;
+    }
+    cookie = segmentState[0] = IRT_FIRST_SEGMENT;
+    DBUG_MSG("+++ objs %p %p %p %p\n", obj0, obj1, obj2, obj3);
+
+    /*
+     * Push two, create new segment, push two more, try to get all four,
+     * try to delete all 4.  All four should be accessible, but only the
+     * last two should be deletable.
+     */
+    DBUG_MSG("+++ START basic segment\n");
+    iref0 = dvmAddToIndirectRefTable(&irt, cookie, obj0);
+    iref1 = dvmAddToIndirectRefTable(&irt, cookie, obj1);
+    cookie = segmentState[1] = dvmPushIndirectRefTableSegment(&irt);
+    DBUG_MSG("+++ pushed, cookie is 0x%08x\n", cookie);
+    iref2 = dvmAddToIndirectRefTable(&irt, cookie, obj2);
+    iref3 = dvmAddToIndirectRefTable(&irt, cookie, obj3);
+
+    if (dvmRemoveFromIndirectRefTable(&irt, cookie, iref0) ||
+        dvmRemoveFromIndirectRefTable(&irt, cookie, iref1))
+    {
+        LOGE("removed values from earlier segment\n");
+        goto bail;
+    }
+    if (!dvmRemoveFromIndirectRefTable(&irt, cookie, iref2) ||
+        !dvmRemoveFromIndirectRefTable(&irt, cookie, iref3))
+    {
+        LOGE("unable to remove values from current segment\n");
+        goto bail;
+    }
+    if (dvmIndirectRefTableEntries(&irt) != 2) {
+        LOGE("wrong total entries\n");
+        goto bail;
+    }
+    dvmPopIndirectRefTableSegment(&irt, segmentState[1]);
+    cookie = segmentState[0];
+    if (!dvmRemoveFromIndirectRefTable(&irt, cookie, iref0) ||
+        !dvmRemoveFromIndirectRefTable(&irt, cookie, iref1))
+    {
+        LOGE("unable to remove values from first segment\n");
+        goto bail;
+    }
+    if (dvmIndirectRefTableEntries(&irt) != 0) {
+        LOGE("basic push/pop not empty\n");
+        goto bail;
+    }
+
+    /*
+     * Push two, delete first, segment, push two more, pop segment, verify
+     * the last two are no longer present and hole count is right.  The
+     * adds after the segment pop should not be filling in the hole.
+     */
+    DBUG_MSG("+++ START segment pop\n");
+    iref0 = dvmAddToIndirectRefTable(&irt, cookie, obj0);
+    iref1 = dvmAddToIndirectRefTable(&irt, cookie, obj1);
+    dvmRemoveFromIndirectRefTable(&irt, cookie, iref0);
+    cookie = segmentState[1] = dvmPushIndirectRefTableSegment(&irt);
+    iref2 = dvmAddToIndirectRefTable(&irt, cookie, obj2);
+    iref3 = dvmAddToIndirectRefTable(&irt, cookie, obj3);
+    dvmPopIndirectRefTableSegment(&irt, segmentState[1]);
+    cookie = segmentState[0];
+    if (dvmIndirectRefTableEntries(&irt) != 2) {
+        LOGE("wrong total entries after pop\n");
+        goto bail;
+    }
+    dvmRemoveFromIndirectRefTable(&irt, cookie, iref1);
+    if (dvmIndirectRefTableEntries(&irt) != 0) {
+        LOGE("not back to zero after pop + del\n");
+        goto bail;
+    }
+
+    /*
+     * Multiple segments, some empty.
+     */
+    DBUG_MSG("+++ START multiseg\n");
+    iref0 = dvmAppendToIndirectRefTable(&irt, cookie, obj0);
+    iref1 = dvmAppendToIndirectRefTable(&irt, cookie, obj1);
+    cookie = segmentState[1] = dvmPushIndirectRefTableSegment(&irt);
+    cookie = segmentState[2] = dvmPushIndirectRefTableSegment(&irt);
+    iref3 = dvmAppendToIndirectRefTable(&irt, cookie, obj3);
+    iref2 = dvmAppendToIndirectRefTable(&irt, cookie, obj2);
+    dvmRemoveFromIndirectRefTable(&irt, cookie, iref3);
+    cookie = segmentState[3] = dvmPushIndirectRefTableSegment(&irt);
+    iref3 = dvmAppendToIndirectRefTable(&irt, cookie, obj3);
+
+    if (dvmGetFromIndirectRefTable(&irt, iref0) != obj0 ||
+        dvmGetFromIndirectRefTable(&irt, iref1) != obj1 ||
+        dvmGetFromIndirectRefTable(&irt, iref2) != obj2 ||
+        dvmGetFromIndirectRefTable(&irt, iref3) != obj3)
+    {
+        LOGE("Unable to retrieve all multiseg objects\n");
+        goto bail;
+    }
+
+    dvmDumpIndirectRefTable(&irt, "test");
+
+    //int i;
+    //for (i = 0; i < sizeof(segmentState) / sizeof(segmentState[0]); i++) {
+    //    DBUG_MSG("+++  segment %d = 0x%08x\n", i, segmentState[i]);
+    //}
+
+    dvmRemoveFromIndirectRefTable(&irt, cookie, iref3);
+    if (dvmRemoveFromIndirectRefTable(&irt, cookie, iref2)) {
+        LOGE("multiseg del2 worked\n");
+        goto bail;
+    }
+    dvmPopIndirectRefTableSegment(&irt, segmentState[3]);
+    cookie = segmentState[2];
+    if (!dvmRemoveFromIndirectRefTable(&irt, cookie, iref2)) {
+        LOGE("multiseg del2b failed (cookie=0x%08x ref=%p)\n", cookie, iref2);
+        goto bail;
+    }
+    iref2 = dvmAddToIndirectRefTable(&irt, cookie, obj2);
+
+    /* pop two off at once */
+    dvmPopIndirectRefTableSegment(&irt, segmentState[1]);
+    cookie = segmentState[0];
+
+    if (dvmIndirectRefTableEntries(&irt) != 2) {
+        LOGE("Unexpected entry count in multiseg\n");
+        goto bail;
+    }
+    dvmRemoveFromIndirectRefTable(&irt, cookie, iref0);
+    dvmRemoveFromIndirectRefTable(&irt, cookie, iref1);
+    if (dvmIndirectRefTableEntries(&irt) != 0) {
+        LOGE("Unexpected entry count at multiseg end\n");
+        goto bail;
+    }
+
+    DBUG_MSG("+++ segment test complete\n");
+    result = true;
+
+bail:
+    dvmClearIndirectRefTable(&irt);
+    return result;
+}
+
+
+/*
+ * Some quick tests.
+ */
+bool dvmTestIndirectRefTable(void)
+{
+    if (!basicTest()) {
+        LOGE("IRT basic test failed\n");
+        return false;
+    }
+    if (!segmentTest()) {
+        LOGE("IRT segment test failed\n");
+        return false;
+    }
+
+    return true;
+}
+
+#endif /*NDEBUG*/